Pro jQuery

Pro jQuery

Адам Фриман

Использование методов для определенного типа данных

jQuery предлагает три удобных метода, которые делают работу с конкретным типом данных более простой. Эти методы описаны и представлены в следующих разделах.

Получение HTML фрагмента

Метод load будет получать только HTML данные, что позволяет вам в один этап запросить HTML фрагмент, обработать ответ, чтобы создать набор элементов, и вставить эти элементы в документ. В листинге 14-15 показано, как можно использовать метод load.

Листинг 14-15: Использование сокращенного метода load
<script type="text/javascript">
	$(document).ready(function () {
		$('<button>Ajax</button>').appendTo('#buttonDiv').click(function (e) {
			$('#row1').load("flowers.html");
			e.preventDefault();
		});
	});
</script>

Вы вызываете метод load для элемента в документе, в который вы хотите вставить новые элементы, и передаете URL методу в качестве аргумента. Если запрос прошел удачно и ответ с сервера содержит валидный HTML, тогда элементы будут вставлены в указанное место, как показано на рисунке 14-6.

Рисунок 14-6: Добавление элементов в документ с использованием метода load

Вы видите, что элементы с файла flower.html были добавлены в документ, но поскольку у них нет атрибута class, они некорректно добавлены к CSS верстке, которую использует основной документ. По этой причине метод load наиболее полезен, если все элементы должны быть вставлены в один район, и вам не нужно их модифицировать, прежде чем они будут добавлены.

Получение и выполнение скриптов

Метод getScript загружает JavaScript файл и затем выполняет содержащиеся в нем выражения. Чтобы продемонстрировать это метод, я создал файл с именем myscript.js и сохранил его на моем сервере вместе с example.html. В листинге 14-16 показано содержание этого файла.

Листинг 14-16: Содержание файла myscript.js
var flowers = [
	["Astor", "Daffodil", "Rose"],
	["Peony", "Primula", "Snowdrop"],
	["Carnation", "Lily", "Orchid"]
]
$('<div id=row3 class=drow/>').appendTo('div.dtable');
var fTemplate = $('<div class=dcell><img/><label/><input/></div>');
for (var row = 0; row < flowers.length; row++) {
	var fNames = flowers[row];
	for (var i = 0; i < fNames.length; i++) {
		fTemplate.clone().appendTo("#row" + (row + 1)).children()
			.filter('img').attr('src', fNames[i] + ".png").end()
			.filter('label').attr('for', fNames[i]).text(fNames[i]).end()
			.filter('input').attr({ name: fNames[i], value: 0 })
	}
}

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

Наиболее важной вещью, на которую стоит обратить внимание при работе со скриптами, наподобие этого, является то, что статус документа может меняться между тем, когда вы инициируете Ajax запрос и выполнением script выражений. В листинге 14-17 содержится скрипт из основного документа, который использует метод getScript, но также меняет DOM, прежде чем может быть завершен Ajax запрос.

Листинг 14-17: Запрос и выполнение скриптов методом getScript
<script type="text/javascript">
	$(document).ready(function () {
		$('<button>Ajax</button>').appendTo('#buttonDiv').click(function (e) {
			$.getScript("myscript.js");
			$('#row2').remove();

			e.preventDefault();
		});
	});
</script>

Вы вызываете метод getScript для основной $ функции и просто передаете в качестве аргумента URL JavaScript файла, который вы хотите использовать. Если сервер может предоставить файл и если это файл содержит валидные JavaScript выражения, тогда код будет выполнен.

Совет

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

В этом примере после того, как я начал Ajax запрос при помощи метода getScript, я использую метод remove, чтобы удалить из документа элемент row2. Этот элемент используется файлом myscript.js для добавления некоторых новых элементов. Эти элементы спокойно отбрасываются, потому что селектор для ID row2 не соответствует ничему в документе. Результат можно увидеть на рисунке 14-7. В зависимости от обстоятельств, вы можете посчитать это понятным дизайном, который проявляет себя лучшим образом в свете изменений в документе, или обычным действием, которое просто располагает элементы. В любом случае, не стоит делать слишком много предположений о статусе документа в ваших внешних JavaScript файлах.

Рисунок 14-7: Результат изменения документа во время Ajax запроса

Получение данных JSON

Метод getJSON получает с сервера объект JSON. Наверное, это наименее полезный из всех трех названных методов, потому что он не делает с данными ничего более, чем базовый метод get. В листинге 14-18 показано использование метода getJSON.

Листинг 14-18: Использование метода getJSON
<script type="text/javascript">
	$(document).ready(function () {
		$('<button>Ajax</button>').appendTo('#buttonDiv').click(function (e) {
			$.getJSON("mydata.json", function (data) {
				var template = $('#flowerTmpl');
				template.tmpl(data.slice(0, 3)).appendTo("#row1");
				template.tmpl(data.slice(3)).appendTo("#row2");
			});
			e.preventDefault();
		});
	});
</script>
<script id="flowerTmpl" type="text/x-jquery-tmpl">
	<div class="dcell">
		<img src="${product}.png" />
		<label for="${product}">${name}:</label>
		<input name="${product}" data-price="${price}" data-stock="${stocklevel}" value="0" required />
	</div>
</script>

В этом примере в ответ на нажатие кнопки (элемента button) я запрашиваю файл с данными JSON. Данные, полученные с сервера, передаются функции, так же как и при помощи метода get, который я показал вам ранее в этой главе. Я использовал плагин шаблона данных (описанный в главе 12) для обработки данных и генерирования из них HTML элементов, а затем методы slice и appendTo, чтобы вставить элементы в документ. Обратите внимание, что в качестве аргумента функции передается объект JavaScript. Вам ничего не нужно делать, чтобы конвертировать формат JSON в объект, потому что jQuery сделает это за вас.

Работа с JSONP

JSONP – это альтернатива CORS, которая работает с ограничением Ajax запросов для одного и того же абсолютного интернет адреса. JSONP полагается на тот факт, что браузер разрешит вам подгружать JavaScript код с любого сервера, так же как работает элемент script, если определен атрибут src. Для начала, определим в документе функцию, которая будет обрабатывать данные, например, вот так:

function processJSONP(data) {
	//...do something with the data...
}

Затем выделаете запрос на сервер, где строка запроса включает ваши данные из формы и свойство callback, установленное имени функции, которую вы только что определили, вот так:

http://node.jacquisflowershop.com/order?callback=processJSONP&astor=1
	&daffodil=2&rose=2&peony=0&primula=0&snowdrop=0

Сервер, который должен определить, как работает JSONP, генерирует данные JSON, а затем создает выражение JavaScript, которое вызывает созданную вами функцию, и передает ей данные в качестве аргумента:

processJSONP({"astor":"1","daffodil":"2","rose":"2","total":5})

Также сервер устанавливает тип содержания (content type) ответа text/javascript, который говорит браузеру, что он получил выражения JavaScript и должен их выполнить. В результате этого вызывается метод, который вы определили ранее, и ему передаются данные, отправленные сервером. Таким образом, вы аккуратно обходите запреты по абсолютному интернет адресу (origin) без использования CORS.

Внимание

Кросс-доменные запросы запрещены по разумной причине. Не используйте JSONP слишком часто. Это может создать некоторые серьезные проблемы безопасности.

В jQuery есть очень хорошая поддержка для JSONP. Все, что вам нужно сделать, это использовать метод getJSON и указать URL, который содержит callback=? в строке запроса. jQuery создает функцию с произвольным именем и использует ее для взаимодействия с сервером, подразумевая, что вам вообще не нужно менять ваш код. В листинге 14-19 показано, как сделать JSONP запрос.

Листинг 14-19: Создание JSONP запроса при помощи метода getJSON
<script type="text/javascript">
	$(document).ready(function () {
		$('button').get(0).disabled = true;
		$.getJSON("mydata.json", function (data) {
			var template = $('#flowerTmpl');
			template.tmpl(data.slice(0, 3)).appendTo("#row1");
			template.tmpl(data.slice(3)).appendTo("#row2");
			$('button').get(0).disabled = false;
		});
		$('button').click(function (e) {
			var formData = $('form').serialize();
			$.getJSON("http://node.jacquisflowershop.com/order?callback=?",
				formData, processServerResponse)
			e.preventDefault();
		})
		function processServerResponse(data) {
			var inputElems = $('div.dcell').hide();
			for (var prop in data) {
				var filtered = inputElems.has('input[name=' + prop + ']')
					.appendTo("#row1").show();
			}
			$('#buttonDiv, #totalDiv').remove();
			$('#totalTmpl').tmpl(data).appendTo('body');
		}
	});
</script>
или RSS канал: Что новенького на smarly.net