Асинхронная отправка файлов при помощи YUI

29 февраля 2008

Ранее я написал о том, как асинхронно отправлять файлы на сервер используя простой скрипт. Теперь я покажу, как то же самое можно сделать при помощи библиотеки YUI, которая предоставляет гораздо более удобный интерфейс.

В YUI, отправка асинхронных запросов на сервер осуществляет функция asyncRequest() модуля Connection Manager. Функции необходимо передать тип (GET или POST), URL запроса и объект callback, который будет обрабатывать полученные от сервера данные. Если нужно отправить на сервер данные формы, то необходимо указать объекту Connect вашу форму. Делается это при помощи функции setForm():

YAHOO.util.Connect.setForm(formObject, true);

Первый параметр - formObject - это указатель на форму. Однако, первым параметром может быть и ID формы. В этом случае Connection Manager сам получит указатель на форму при помощи getElementById. Второй параметр - это собственно то, что нам и нужно - это значение указывает на то, что нам необходимо отправлять файлы на сервер.

Далее нужно создать объект callback (если вам конечно нужно обрабатывать данные, которые возвращает сервер). Все члены объекта callback являются не обязательными, но желательно указать по крайней мере success и failure - функции, которые будут вызываться при успешной отправке (success) или ошибке (failure). Помимо этого, при отправке файлов, нужно также объявить функцию upload, которая будет вызываться при успешной отправке файла. Еще один очень важный параметр объекта callback это массив argument, в который нужно добавлять значения, необходимые для последующей обработки данных. Итак, пример:

var callback_obj = {
	argument : ['targetPre'],
	success: function(o) { alert('Файл успешно отправлен.'); },
	failure: function(o) { alert('Ошибка!!!'); },

	upload : function(response){
		var target = document.getElementById(response.argument[0]);
		target.innerHTML = response.responseText;
	}
}

В этом примере ответ от сервера (responseText) будет добавлен как содержимое в элемент с ID = targetPre (параметр, указанный в argument). После этого можно выполнять запрос:

var cObj = YAHOO.util.Connect.asyncRequest('POST', 'http://www.example.com', callback_obj);

Теперь пример простого web приложения, которое асинхронно отправляет файл на сервер и полученные от сервера данные помещает в элемент pre:

<html>
<head>
<script src="http://yui.yahooapis.com/2.5.0/build/yahoo/yahoo-min.js"></script>
<script src="http://yui.yahooapis.com/2.5.0/build/event/event-min.js"></script>
<script src="http://yui.yahooapis.com/2.5.0/build/connection/connection-min.js"></script>
<script type="text/javascript">

function upload(){
	var formObject = document.getElementById('aForm'); 

	// аргумент true указывает на то, что нам нужно отправлять файлы
	YAHOO.util.Connect.setForm(formObject, true);
	// отправка формы
	var cObj = YAHOO.util.Connect.asyncRequest('POST', formObject.getAttribute('action'), callback_obj);
}

var callback_obj = {
	argument : ['targetPre'],
	success: function(o) { alert('Файл успешно отправлен.'); },
	failure: function(o) { alert('Ошибка!!!'); },

	upload : function(response){
		var target = document.getElementById(response.argument[0]);
		target.innerHTML = response.responseText;
	}
}
</script>
</head>
<body>
<form id="aForm" name="my_form" action="upload.php" onsubmit="upload(); return false;">
<input type="file" name="my_file" />
<input type="submit" name="submit_btn" value="Send" />
</form>
<pre id="targetPre"></pre>
</body>
</html>

Здесь указатель на форму получается при помощи getElementById(), аттрибут action которого используется как URL запроса. Функция upload() вызывается из хендлера onsubmit, а для того, чтобы форма не выполняла действие по умолчанию (чтобы не перезагружалась страница) возвращаем из onsubmit значение false.

Подробнее о модуле Connection Manager можно узнать из официальной документации библиотеки.

Асинхронная отправка файлов на сервер

20 февраля 2008

Не так давно, при разработке чата, я столкнулся с проблемой асинхронной отправки файлов на сервер. Мне нужно было добавить возможность добавлять аватару к профилю пользователя без перезагрузки страницы. После продолжительных поисков я наткнулся на очень хороший по моему мнению скрипт, осуществляющий отправку файла через скрытый iframe, который создается динамически:

var AIM = {
	frame : function(c) {

		var n = 'f' + Math.floor(Math.random() * 99999);
		var d = document.createElement('DIV');
		d.innerHTML = '<iframe style="display:none" src="about:blank" id="'+n+'" name="'+n+'" onload="AIM.loaded(\''+n+'\')"></iframe>';
		document.body.appendChild(d);

		var i = document.getElementById(n);
		if (c && typeof(c.onComplete) == 'function') {
			i.onComplete = c.onComplete;
		}

		return n;
	},

	form : function(f, name) {
		f.setAttribute('target', name);
	},

	submit : function(f, c) {
		AIM.form(f, AIM.frame(c));
		if (c && typeof(c.onStart) == 'function') {
			return c.onStart();
		} else {
			return true;
		}
	},

	loaded : function(id) {
		var i = document.getElementById(id);
		if (i.contentDocument) {
			var d = i.contentDocument;
		} else if (i.contentWindow) {
			var d = i.contentWindow.document;
		} else {
			var d = window.frames[id].document;
		}
		if (d.location.href == "about:blank") {
			return;
		}

		if (typeof(i.onComplete) == 'function') {
			i.onComplete(d.body.innerHTML);
		}
	}
}

Функция submit() является основной в объекте AIM. Она создаёт скрытый iframe при помощи функции frame(), добавляет атрибут target для формы и при необходимости выполняет callback onStart при начале отправки формы. В целом, принцип действия скрипта основывается на применении атрибута target, который указывает, где будет отображаться новый документ. Поскольку здесь target указывает на скрытый iframe, то страница не будет перезагружаться при оправке формы, а ответ от сервера будет помещен как его содержимое.

Пример применения объекта AIM приведен в следующем листинге:

<form action="index.php" method="post" onsubmit="return AIM.submit(this, {'onStart' : null, 'onComplete' : completeCallback})">
....
</form>

В этом примере будет происходить отправка данных формы (в том числе и файлов, если таковые указаны) на сервер. Возвращаемые сервером данные передаются в функцию completeCallback, которую целесообразно использовать для оповещения пользователя о результатах отправки формы и возможных ошибках.

Если вы предпочитаете использовать библиотеку YUI, то отправку файлов можно осуществлять при помощи connection manager. Подробнее об этом я расскажу в следующий раз.

Добавление поддержки объекта History в AJAX приложения.

20 января 2008

Одной из основных проблем при использовании AJAX является невозможность навигации при помощи кнопок BACK и FORWARD, а также функций history.back(), history.go() и др., потому что изменения в веб странице, которые осуществляются через AJAX никак не отображаются на объекте History. Кроме того, страницы, полученные с использованием AJAX, невозможно добавлять в закладки.

Эти проблемы можно решить при помощи утилиты Browser History Manager, входящей в состав библиотеки YUI. Она позволяет создавать веб приложения с полностью функциональным объектом History, а также возможностью сохранять другие параметры состояния приложения, например, информацию о том, какие панели или кнопки на странице активны.

Читать дальше »