Шаблоны jquery. Официальные плагины jQuery: Templates plugin. Приступаем к работе

Лучший способ начать изучение шаблонов данных – это сразу же приступить к работе с ними. В показаны базовые возможности шаблонов. В этот листинг я включил полный HTML документ из-за способа, которым мы устанавливаем шаблоны, используя элемент script , но я покажу вам релевантные элементы в дальнейших примерах.

Листинг 12-3: Первый пример шаблона данных Example $(document).ready(function () { var data = [ { name: "Astor", product: "astor", stocklevel: "10", price: 2.99 }, { name: "Daffodil", product: "daffodil", stocklevel: "12", price: 1.99 }, { name: "Rose", product: "rose", stocklevel: "2", price: 4.99 }, { name: "Peony", product: "peony", stocklevel: "0", price: 1.50 }, { name: "Primula", product: "primula", stocklevel: "1", price: 3.12 }, { name: "Snowdrop", product: "snowdrop", stocklevel: "15", price: 0.99 }, ]; }); ${name}: Jacqui"s Flower Shop Place Order

В следующих разделах я разделю пример и объясню каждую часть. Если данные являются частью документа, они известны как встроенные данные . Альтернативой являются удаленные данные , это когда вы получаете данные от сервера отдельно от документа. Удаленных данных мы коснемся далее в этой главе, но это затрагивает поддержку jQuery для Ajax, что является темой глав 14 и 15.

Определение данных

Начальной точкой примера являются данные, которые в данном случае представляют собой массив объектов, каждый из которых описывает отдельную единицу цветочной продукции. В показаны соответствующие выражения из документа.

Листинг 12-4: Определение данных по цветам var data = [ { name: "Astor", product: "astor", stocklevel: "10", price: 2.99 }, { name: "Daffodil", product: "daffodil", stocklevel: "12", price: 1.99 }, { name: "Rose", product: "rose", stocklevel: "2", price: 4.99 }, { name: "Peony", product: "peony", stocklevel: "0", price: 1.50 }, { name: "Primula", product: "primula", stocklevel: "1", price: 3.12 }, { name: "Snowdrop", product: "snowdrop", stocklevel: "15", price: 0.99 }, ];

Вы выражаете ваши данные как один или более JavaScript объектов. Библиотека шаблонов jQuery очень гибка, когда речь идет о виде объектов, которые могут быть использованы в качестве данных, но формат, показанный в шаблоне, используется наиболее часто, потому что он соответствует формату данных JSON, о чем я расскажу в главе 14.

Совет

JSON важен, потому что он часто используется с Ajax, о чем я расскажу в главах 14 и 15.

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

Определение шаблона

Как вы можете себе представить, в сердце библиотеки шаблонов данных находится шаблон данных. Это набор HTML элементов, содержащих метки-заполнители (placeholders), которые соответствуют аспектам объектов данных. В показан шаблон для этого примера.

Листинг 12-5: Определение шаблона данных ${product} .png" /> ${name} :

Первая вещь, касаемо шаблона, на которую стоит обратить внимание, – это то, что он содержится внутри элемента script со значением атрибута type равном text/x-jquery-tmpl . Мы делаем это для того, чтобы браузер не интерпретировал содержание шаблона как обычный HTML. Это не совсем обязательно, но это хорошая практика, которая поможет избежать многих потенциальных проблем.

Вторым моментом, на который стоит обратить внимание, является то, что когда вы определяете шаблон в элементе script , вы назначите имя шаблона, используя атрибут id . В нашем случае шаблон называется flowerTmpl . Вам нужно знать имя шаблона, когда вы его применяете к вашим данным.

Содержание шаблона будет применяться к объектам в массиве данных, чтобы создать набор HTML элементов для каждого объекта в отдельности. Вы видите, что структура шаблона соответствует набору элементов, который я использовал для цветочной продукции в предыдущих главах. Ключевое различие, естественно, заключается в кусках кода, которые я выделил в листинге. Это и есть метки-заполнители для данных .

Когда библиотека шаблонов обрабатывает шаблон, она замещает любые метки-заполнители данных значениями свойств объекта, с которым работает. Так, например, первый объект в массиве библиотека шаблонов свяжет с меткой ${product} и заменит ее значением свойства единицы продукции, то есть в данном случае astor . Вот эта часть шаблона:

${product} .png"/>

трансформированная в это:

astor .png"/>

Вставка значений данных – это только одна из вещей, которые вы можете делать с шаблоном. Далее в этой главе я объясню другие возможности.

Применение шаблона

Мы сводим шаблон, используя метод tmpl . Это позволяет указать данные, которые мы хотим использовать, и шаблон, который должен быть к ним применен. В показано использование этого метода.

Листинг 12-6: $("#flowerTmpl").tmpl(data).appendTo("#row1");

Я использую jQuery $ функцию, чтобы выбрать элемент, который содержит шаблон, а затем для результата вызываю метод tmpl , передавая в качестве аргумента данные, которые вы хотите обработать.

Метод tmpl возвращает стандартный jQuery объект, который содержит элементы, полученные из шаблона. В нашем случае я завершаю это набором элементов div , каждый из которых содержит элемент img , label и input , которые были обработаны для одного из объектов в моем массиве данных. Я использую метод appendTo , что вставить полный набор дочерних элементов для row1 . Результат можно увидеть на .

Рисунок 12-2: Использование шаблона данных Настройка результата

Мы не получили полностью того результата, который ожидали, потому что вся продукция расположена на одной линии. Но поскольку мы работаем с объектом jQuery , мы можем делать с элементами все, что мы и делали раньше. В показано, как это можно сделать, оперируя результатом метода tmpl .

Листинг 12-7: Обработка результатов, полученных из шаблона $("#flowerTmpl").tmpl(data) .slice(0, 3).appendTo("#row1").end().end().slice(3).appendTo("#row2"); }); ${name}:

В этом примере я использую методы slice и end , чтобы сузить и расширить выборку, и метод appendTo , чтобы добавить подмножества элементов, сгенерированных из шаблона, в разные ряды.

Обратите внимание, что мне пришлось вызвать метод end два раза подряд, чтобы проработать сужение выборки, вызванное методами slice и appendTo . Это очень функционально, и я вообще люблю использовать метод end , чтобы создавать команды в одно выражение, но мне не очень нравится последовательность end().end() . Вместо этого я обычно разделяю такие последовательности на отдельные команды, как показано в .

Листинг 12-8: Разделение элементов с использованием нескольких выражений var templResult = $("#flowerTmpl").tmpl(data); templResult.slice(0, 3).appendTo("#row1"); templResult.slice(3).appendTo("#row2");

В любом случае вы получаете тот же результат, то есть продукция поделена по двум рядам, в каждом содержится три цветка, как показано на.

Рисунок 12-3: Настройка результатов для того, чтобы они подходили верстке
Корректировка ввода данных

Можно использовать и другой способ, чтобы скорректировать данные, переданные методу tmpl . В показано, как это можно сделать.

Листинг 12-9: Использование данных для корректировки результатов из шаблона $(document).ready(function () { var data = [ { name: "Astor", product: "astor", stocklevel: "10", price: 2.99 }, { name: "Daffodil", product: "daffodil", stocklevel: "12", price: 1.99 }, { name: "Rose", product: "rose", stocklevel: "2", price: 4.99 }, { name: "Peony", product: "peony", stocklevel: "0", price: 1.50 }, { name: "Primula", product: "primula", stocklevel: "1", price: 3.12 }, { name: "Snowdrop", product: "snowdrop", stocklevel: "15", price: 0.99 }, ]; var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }); ${name}:

В этом скрипте я решил задачу размещения цветов по рядам, используя шаблон дважды: по одному разу для каждого ряда. Я использовал метод slice , таким образом я смог передавать определенный набор объектов данных каждый раз шаблону. Техника отличается, но результат такой же, как и на .

Вычисление выражений

Мы не ограничены исключительно значениями свойств объектов данных. Между фигурными скобками можно разместить выражение JavaScript, а движок шаблона произведет вычисления и вставит результат, сделанный шаблоном, в HTML. В содержится пример.

Листинг 12-10: ${name}:

В этом шаблоне я использую тройной оператор JavaScript, чтобы установить атрибут value элемента input , основываясь на свойстве stocklevel . Я размещаю это выражение между фигурными скобками, так же как я делал, когда напрямую вставлял значения свойств. Если свойство stocklevel больше нуля, тогда атрибут value будет установлено на 1 , иначе оно будет равно 0 . Результат можно увидеть на . Для всех цветов, кроме пиона, значение stocklevel больше нуля.

Рисунок 12-4: Вычисление выражения в шаблоне

Этот пример вкратце демонстрирует основной функционал шаблона: вы комбинируете данные с шаблоном, чтобы получить объекты DOM, которые вы потом добавляете в документ, используя основной jQuery. Затем напрямую или косвенно можно использовать в выражениях значения данных, чтобы сгенерировать содержание.

Он обеспечивает возможность использования шаблонов, упрощающих генерацию HTML-элементов из объектов данных JavaScript.

Чтобы не возникало недопонимания, хочу предупредить, что данный модуль не относится к числу активно разрабатываемых или поддерживаемых в настоящее время, и команда разработчиков jQuery не рекомендует его применять. Это не означает, что вы не должны его использовать, однако я счел своим долгом сказать вам об этом, прежде чем вы будете включать его в свои проекты. Я был бы рад порекомендовать вам какой-нибудь другой активно разрабатываемый вариант, однако найти хотя бы близкую по своим возможностям замену jQuery Templates мне пока что не удалось. Но даже при упомянутом отношении к нему разработчиков этот модуль все еще остается наилучшим.

История модуля jQuery Templates довольно необычна. В свое время Microsoft и команда разработчиков jQuery объявили, что трем подключаемым модулям, разработанным компанией Microsoft, присвоен статус "официальных", чего до того не удостаивался ни один из подключаемых модулей.

Спустя какое-то время команда jQuery объявила об отказе от использования этих модулей и лишении их статуса официальных, а также о своих планах относительно замены их другой функциональностью. Предполагаемая замена должна была войти в состав библиотеки jQuery UI. Прискорбно, но факт: ничего из того, что было обещано, пока еще не предоставлено, а отвергнутые плагины по-прежнему доступны и широко используются (особенно это относится к подключаемому модулю для работы с шаблонами).

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

Настройка библиотеки jQuery Templates

Прежде чем использовать шаблоны jQuery, нужно загрузить библиотеку jQuery Templates и подключить ее к своему документу.

Распакуйте архив и скопируйте файл jQuery.tmpl.js (версия для разработки) или jQuery.tmpl.min.js (версия для развертывания) на свой веб-сервер. Следующее, что необходимо сделать - добавить в образец документа элемент script, подключающий библиотеку шаблонов, как показано в примере ниже:

Библиотека jQuery $(function() { // Сюда будет помещаться код примеров }); h1 { min-width: 70px; border: thick double black; margin-left: auto; margin-right: auto; text-align: center; font-size: x-large; padding: ..png"); background-size: contain; margin-top: 0; } .dtable {display: table;} .drow {display: table-row;} .dcell {display: table-cell; padding: 10px;} .dcell > * {vertical-align: middle} input {width: 2em; text-align: right; border: thin solid black; padding: 2px;} label {width: 6em; padding-left: .5em; display: inline-block;} #buttonDiv {text-align: center;} button {padding: 12px;} #oblock {display: block; margin-left: auto; margin-right: auto; min-width: 700px; } Цветочный магазин Заказать

Мы будем использовать этот код в качестве образца документа в этой статье. Наверное, вы заметили, что от первоначального варианта, рассмотренного ранее, он отличается не только тем, что в него добавлена библиотека шаблонов, но и тем, что из него удалены элементы, соответствующие различным видам цветочной продукции. Это сделано специально для того, чтобы мы могли восстанавливать эти элементы в документе различными способами с помощью библиотеки шаблонов.

Внешний вид исходного документа в окне браузера на данном этапе представлен на рисунке:

Простой пример шаблона данных

Наилучший способ изучения шаблонов данных - сразу же взяться за дело. Для демонстрации основных возможностей шаблонов мы используем код из примера ниже:

... $(function() { var data = [ { name: "Астра", product: "astor", stocklevel: "10", price: 2.99}, { name: "Нарцисс", product: "daffodil", stocklevel: "12", price: 1.99}, { name: "Роза", product: "rose", stocklevel: "2", price: 4.99}, { name: "Пион", product: "peony", stocklevel: "0", price: 1.50}, { name: "Примула", product: "primula", stocklevel: "1", price: 3.12}, { name: "Подснежник", product: "snowdrop", stocklevel: "15", price: 0.99}, ]; $("#flowerTmpl").tmpl(data).appendTo("#row1"); }); .png"/> ${name}: ...

В последующих разделах мы разобьем пример на отдельные части и проанализируем код каждой из них по отдельности. Когда данные являются частью документа, они называются встроенными данными (inline data) . Альтернативой им являются дистанционные данные (remote data) , хранящиеся на сервере отдельно от документа. Мы рассмотрим дистанционные данные несколько позже, а пока что можно заметить, что этот вопрос тесно связан с поддержкой Ajax, которую предоставляет библиотека jQuery.

Определение данных

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

Var data = [ { name: "Астра", product: "astor", stocklevel: "10", price: 2.99}, { name: "Нарцисс", product: "daffodil", stocklevel: "12", price: 1.99}, { name: "Роза", product: "rose", stocklevel: "2", price: 4.99}, { name: "Пион", product: "peony", stocklevel: "0", price: 1.50}, { name: "Примула", product: "primula", stocklevel: "1", price: 3.12}, { name: "Подснежник", product: "snowdrop", stocklevel: "15", price: 0.99}, ];

Данные выражаются в виде одного или нескольких объектов JavaScript. Библиотека шаблонов jQuery предоставляет значительную гибкость в выборе объектов, которые могут быть использованы в качестве данных, но представленный выше формат, соответствующий формату данных JSON , является наиболее распространенным. Формат JS0N играет очень важную роль, поскольку его часто используют при работе с Ajax.

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

Определение шаблона

Как вы, наверное, и сами догадываетесь, центральным элементом библиотеки шаблонов является шаблон данных (data template) . Он представляет собой набор HTML-элементов, содержащих заполнители, которые соответствуют различным свойствам объектов данных. Шаблон для этого примера показан ниже:

.png"/> ${name}:

Первое, на что следует обратить внимание, - это то, что шаблон помещается в элемент script, атрибуту type которого присваивается значение несуществующего типа - text/x-jquery-tmpl . Это сделано для того, чтобы браузер не пытался интерпретировать содержимое шаблона как обычную HTML-разметку. Хотя это и несущественно, но такой практики следует придерживаться, поскольку она чрезвычайно полезна и позволит вам избежать множества потенциальных проблем в будущем.

Второй момент, на котором я хочу заострить ваше внимание, - это то, что для присвоения имени шаблону, определенному в элементе script, используется атрибут id. В данном случае именем шаблона служит flowerTmpl. Чтобы применить к данным шаблон, необходимо знать его имя.

Содержимое шаблона будет применено ко всем объектам в массиве данных, что приведет к созданию набора HTML-элементов для каждого объекта. Вы видите, что структура шаблона в целом соответствует набору элементов, которые использовались в предыдущих статьях для представления различных видов цветочной продукции. Главное, чем они отличаются - это элементы кода выполняющие функции заполнителей (data placeholders) .

В процессе обработки шаблона вместо каждого заполнителя подставляется значение свойства, взятое из текущего объекта. Например, для первого объекта массива вместо заполнителя ${product} будет подставлено значение свойства product, т.е. "astor". Таким образом, часть шаблона

${name}:

преобразуется в следующий HTML-фрагмент:

Астра:

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

Применение шаблона

Для объединения шаблона с данными используется метод tmpl() . При этом вы указываете данные, которые должны использоваться, и применяемый к ним шаблон. Пример использования этого метода приведен ниже:

$("#flowerTmpl").tmpl(data).appendTo("#row1");

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

Метод tmpl() возвращает стандартный объект jQuery, который содержит элементы, полученные из шаблона. В данном случае это приводит к набору элементов div, каждый из которых содержит элементы img, label и input, сконфигурированные для одного из объектов, содержащихся в массиве данных. Для вставки всего набора в качестве дочернего элемента в элемент row1 используется метод appendTo(). Результат представлен на рисунке:

Модификация результата

Полученный результат не совсем нас устраивает, поскольку все элементы, соответствующие различным цветам, отображаются в одном ряду. Но поскольку мы имеем дело с объектом jQuery, расположить элементы так, как нам надо, не составит большого труда. В примере ниже показано, как это можно сделать, воздействуя на результат работы метода tmpl():

... $("#flowerTmpl").tmpl(data) .slice(0, 3).appendTo("#row1").end().end() .slice(3).appendTo("#row2");

В этом примере методы slice() и end() используются для сужения и расширения набора выбранных элементов, а метод appendTo() - для добавления поднаборов элементов, сгенерированных с помощью шаблона, в различные ряды.

Обратите внимание: для возврата набора в исходное состояние, в котором он находился до применения методов slice() и appendTo(), метод end() пришлось вызывать два раза подряд. Ничего противозаконного в этом нет, и я охотно использую метод end(), чтобы выполнить необходимые действия в рамках одной инструкции, но последовательность end().end() не вызывает у меня восторга. В подобных случаях я предпочитаю разбивать всю последовательность действий на ряд отдельных операций, как показано в примере ниже:

Var templResult = $("#flowerTmpl").tmpl(data); templResult.slice(0, 3).appendTo("#row1"); templResult.slice(3).appendTo("#row2");

В обоих случаях результат будет одним и тем же: представление совокупности продуктов двумя рядами, в каждом из которых отображается по три вида цветов, как показано на рисунке:

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

Другой возможный подход заключается в изменении способа передачи данных методу tmpl(). Соответствующий пример приведен ниже:

Var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2");

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

Вычисление выражений

Объекты данных можно использовать не только для получения значений свойств. Если поместить между двумя фигурными скобками выражение JavaScript, то движок шаблонов вычислит его и вставит в сгенерированную шаблоном HTML-разметку. Соответствующий пример приведен ниже:

${name}:

В этом шаблоне значение атрибута value элемента input устанавливается на основании значения свойства stocklevel с помощью тернарного условного оператора. Выражение, заключенное в фигурные скобки, играет ту же роль, какую играло бы записанное вместо него непосредственное значение свойства. Если значение свойства stocklevel больше нуля, то значение value устанавливается равным 1, в противном случае - 0.

Вид полученной страницы в окне браузера представлен на рисунке ниже. Значение stocklevel, большее нуля, установлено для всех цветов, кроме пионов:

Рассмотренный пример иллюстрирует основную схему работы с шаблонами: данные объединяются с шаблоном для получения DOM-объектов, которые затем добавляются в документ с использованием основной функциональности jQuery. Для генерации содержимого можно использовать как непосредственно заданные значения, так и вычисляемые выражения.

Использование переменных шаблона

Шаблоны не являются сценариями JavaScript. Любое содержимое, которое вы добавляете в элемент script, считается частью шаблона и будет включаться в выходной результат. Чтобы сделать шаблоны более гибкими, вам предоставляется небольшое количество контекстных переменных, которые можно использовать в дескрипторах заполнителей. Краткое описание этих переменных содержится в таблице ниже:

Использование переменной $data

Переменная $data возвращает текущий элемент данных, к которому применяется шаблон. Например, используемая переменная $data будет поочередно ссылаться на каждый из объектов, соответствующих отдельным видам цветов. Для получения данных в предыдущем примере в шаблоне использовался тернарный условный оператор. Такой подход вполне допустим, однако чтение получаемых при этом шаблонов часто вызывает затруднения, чего, разумеется, желательно не допускать.

Я всегда стараюсь уменьшить объем кода шаблона до необходимого минимума и поэтому предпочитаю использовать переменную $data внутри функций JavaScript, которые затем вызываю из шаблона. Соответствующий демонстрационный пример приведен ниже:

$(function() { var data = [ { name: "Астра", product: "astor", stocklevel: "10", price: 2.99}, { name: "Нарцисс", product: "daffodil", stocklevel: "12", price: 1.99}, { name: "Роза", product: "rose", stocklevel: "2", price: 4.99}, { name: "Пион", product: "peony", stocklevel: "0", price: 1.50}, { name: "Примула", product: "primula", stocklevel: "1", price: 3.12}, { name: "Подснежник", product: "snowdrop", stocklevel: "15", price: 0.99}, ]; var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }); function stockDisplay(product) { return product.stocklevel > 0 ? 1: 0; } .png"/> ${name}:

В этом примере определяется функция stockDisplay(), возвращающая значение, которое должно отображаться в элементе input. Аргументом этой функции является объект данных, который мы получаем внутри шаблона с использованием переменной $data. Учитывая, что речь идет всего лишь о простом тернарном операторе, разница в удобочитаемости кода по сравнению с предыдущим вариантом не очень значительна, но в случае более сложных выражений или в случае многократного использования выражения в пределах одного шаблона она будет гораздо более ощутимой.

Определяя функции, которые будут вызываться из шаблона, будьте внимательны. Дело в том, что такие функции должны определяться до вызова метода tmpl(). Я всегда стараюсь помещать их в конце элемента script, но если функция должна находиться внутри обработчика события ready, то непременно следует убеждаться в том, что она была ранее определена. Другой распространенной ошибкой является то, что функцию часто определяют внутри шаблона.

Использование функции $() внутри шаблона

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

Использование переменной $item

Объект, возвращаемый переменной $item, решает несколько задач. Первая из них - обеспечение возможности обмена дополнительными данными между сценарием JavaScript и шаблоном. Соответствующий пример приведен ниже:

$(function() { var data = [ { name: "Астра", product: "astor", stocklevel: "10", price: 2.99}, { name: "Нарцисс", product: "daffodil", stocklevel: "12", price: 1.99}, { name: "Роза", product: "rose", stocklevel: "2", price: 4.99}, { name: "Пион", product: "peony", stocklevel: "0", price: 1.50}, { name: "Примула", product: "primula", stocklevel: "1", price: 3.12}, { name: "Подснежник", product: "snowdrop", stocklevel: "15", price: 0.99}, ]; $("Специальное предложение на сегодняшний день: " + "скидка 50 центов") .insertAfter("h1") .css({ color: "red", fontSize: "14pt", textAlign: "center" }); var options = { discount: $("#offer").data("discount"), stockDisplay: function(product) { return product.stocklevel > 0 ? 1: 0; } }; var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3), options).appendTo("#row1"); template.tmpl(data.slice(3), options).appendTo("#row2"); }); .png"/> ${name}:

В этом примере мы создаем объект options, для которого определяются свойство (discount) и метод (stockDisplay()). Затем этот объект передается методу tmpl() в качестве второго аргумента. Доступ к свойствам и методам объекта из шаблона обеспечивает переменная $item. Как видите, для обработки скидки в цене, здесь используется свойство discount объекта options.

Хочу обратить ваше внимание на необходимость включения префикса $ в имена контекстных переменных: $item и $data. Такой же префикс обязателен и в конструкции дескриптора шаблона ${...}, используемой для подстановки значений в шаблон. Пропуск любого из этих префиксов является одной из наиболее распространенных ошибок.

О других применениях этого объекта мы поговорим далее.

Использование вложенных шаблонов

При создании сложных приложений иногда имеет смысл разбить большой шаблон на несколько частей, объединение которых происходит уже на стадии выполнения приложения. Как будет показано далее, такой способ объединения шаблонов обеспечивает более гибкое управление выводом. Мы начнем с самого элементарного. В примере ниже показано, каким образом один шаблон может ссылаться на другой:

... .png"/> ${name}: {{tmpl($data, $item) "#inputTmpl"}}

В этом примере шаблон разбит на две части. Первая из них, шаблон flowerTmpl, вызывается для каждого элемента массива данных. В свою очередь, этот шаблон вызывает шаблон inputTmpl для создания элементов input. Вызов второго шаблона осуществляется с помощью дескриптора {{tmpl}} . В этом вызове используются три аргумента. Первые два - это текущий элемент данных и объект options; эти аргументы заключаются в круглые скобки. Третий аргумент - это вызываемый шаблон. Его можно задавать либо jQuery-селектором (что и сделано выше), либо переменной или функцией, определенной в сценарии.

Использование условных шаблонов

Механизм шаблонов обеспечивает возможность динамического принятия решений относительно использования различных частей шаблона в зависимости от выполнения определенных условий. Для этого существуют дескрипторы {{if}} и {{/if}} , пример использования которых представлен в ниже:

... {{if stocklevel > 0}} .png"/> ${name}: {{/if}}

Условие указывается в дескрипторе {{if}}, и часть шаблона, заключенная между этим дескриптором и дескриптором {{/if}}, будет использоваться, только если результат вычисления условного выражения окажется равным true. Если же этот результат равен false, то указанная часть шаблона игнорируется. В данном случае проверяется значение свойства stocklevel, и если оно равно нулю, то игнорируется весь шаблон flowerTmpl. Это означает, что отображаться будут лишь те продукты, которые имеются в наличии на складе, как показано на рисунке:

Более сложные условия можно задавать с помощью дескриптора {{else}} , позволяющего определить часть шаблона, которая должна использоваться в тех случаях, когда результатом вычисления выражения в дескрипторе {{if}} является false. Соответствующий пример приведен ниже:

... {{if stocklevel > 5}} .png"/> ${name}: {{else stocklevel > 0}} .png"/> ${name}: (Небольшое количество) {{else}} .png" style="opacity:0.5"/> ${name} (Нет в наличии) {{/if}}

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

Результат работы приведенного выше сценария представлен на рисунке:

4 октября 2010 года была опубликована об анонсе трёх плагинов jQuery, созданных при поддержке команды Microsoft. Эти плагины – плагин шаблонов (the jQuery Templates plugin) , плагин привязки данных (the jQuery Data Link plugin) и плагин глобализации (the jQuery Globalization plugin) – получили статус “Официальные плагины проекта jQuery” (officially supported plugins of the jQuery project).

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

Следует отметить, что команда Microsoft использовала свои немалые наработки в этих направлениях, как и команда проекта jQuery, и при хорошо сложившемся взаимодействии получились, на мой взгляд, отличные инструменты для разработчиков. В подтверждение моего мнения могу добавить, что разработчики jQuery анонсировали включение плагинов шаблонов и привязки данных в ядро библиотеки jQuery уже версии 1.5, а плагина глобализации – в соответствующую версию jQuery UI. Плагины пока ещё не получили статус релиза, но уже активно ведется написание документации на сайте. К слову, команда Microsoft последовала традициям разработки jQuery и разместила материалы по разработке плагинов на github.com, где доступны описание и исходники плагинов.

В этой статье я расскажу немного о плагине шаблонов.

jQuery Templates plugin

Начнём с простенького примера:

  • ${Name} (${ReleaseYear})
  • var movies = [ { Name: "The Red Violin", ReleaseYear: "1998" }, { Name: "Eyes Wide Shut", ReleaseYear: "1999" }, { Name: "The Inheritance", ReleaseYear: "1976" } ]; $("#movieTemplate").tmpl(movies) .appendTo("#movieList");

    Итак, в примере разработчик страницы описал шаблон для вывода объектов в виде разметки (первый элемент script ), потом получил откуда-то массив объектов movies и вызвал инструкцию сгенерировать нужную разметку по шаблону, взяв данные из предоставленного массива объектов, а результат добавить в конец списка #movieList .
    В результате работы плагина мы получим такую разметку:

    • The Red Violin (1998)
    • Eyes Wide Shut (1999)
    • The Inheritance (1976)

    А теперь по сути вопроса.
    Что делает плагин?
    Плагин получает на вход строку шаблона и множество объектов (или один объект), которые нужно вывести в строку (или разметку) с форматированием.
    Где это применяется?
    В основном этот плагин полезен при динамическом выводе объектов JS на страницу, объекты могут быть получены самыми разными способами, например, при разчётах или по результатам каких-то действий пользователя и, конечно самый часто приводимый пример, в виде JSON в ответе сервера на AJAX запрос.

    Методы плагина

    .tmpl([ data ], [ options ])
    Получает содержимое первого выбранного элемента и использует его в качестве шаблона для форматированного вывода указанных данных.
    data – данные для вывода в шаблон (объект или массив объектов).
    options – опционально, определённое пользователем расширение в виде пар ключ-значение для объекта вывода в шаблон.
    jQuery.tmpl(template, [ data ], [ options ])
    Использует указанный шаблон для форматированного вывода указанных данных.
    template – шаблон для форматирования данных, может быть одного из следующих типов: строка с разметкой, HTML-элемент (в том числе и в jQuery-обёртке), строка, соответствующая имени ранее скомпилированного шаблона.
    data, options – имеют то же значение, что и выше
    .tmplItem()
    Возвращает для первого выбранного элемента структуру (объект) с результатами работы шаблонизатора. Возвращаемый методом объект обеспечивает доступ к:

    • HTML-частям, из которых состоит шаблон
    • ассоциированной единице переданных данных
    • родительскому шаблону, если текущий шаблон является вложенным
    • текущему шаблону, использованному для вывода
    • определённому пользователем расширению (полям и методам), переданным в параметр options метода tmpl()

    Этот метод используется, напрмер, когда после проведенного форматирования данных требуется узнать, а какие же данные были использованы при формировании некоторого куска разметки, или для обновления куска разметки с использованием новых данных.
    jQuery.tmplItem(element)
    Аналогичен методу.tmplItem, только структура с результатами работы шаблонизатора ищется для элемента element (HTML-элемент, в том числе и в jQuery-обёртке).
    .template([ name ])
    Метод делает из содержимого первого выбранного элемента скомпилированную версию шаблона форматирования.
    name – необязательно имя шаблона, если имя указано, то потом можно использовать его для обращения к этому шаблону в методе jQuery.tmpl(name, data, options)
    jQuery.template([ name, ] template)
    Метод аналогичен описанному выше, только здесь шаблон передаётся в качестве параметра template – это может быть строка, строка с разметкой, HTML-элемент (в том числе и в jQuery-обёртке).

    Синтаксис шаблона

    Я вкратце приведу описание нескольких самых основных элементов шаблона, остальное надеюсь более подробно описать в следующей статье (если будет положительный отклик на эту статью)
    ${fieldNameOrExpression} и {{= fieldNameOrExpression}}
    Позволяет вставить в шаблон значение поля (свойства) объекта данных, может быть также использовано для вставки результата метода или js-выражения. Напрмер, «${Name}» – вставит в шаблон значение поля obj.Name, а при том, что Languages – это поле объекта, которому присвоен массив, «${Languages.length}» – вставит в шаблон длину этого массива, и наконец, если у объекта есть метод getLanguages с двумя параметрами, то «${getLanguages(Languages, ‘ – ‘)}» – вставит в шаблон результат работы этого метода.
    {{html fieldNameOrExpression}}
    Элемент шаблона ${field} (или {{= field}}) вставляет в результат значение указанного поля в виде текста, т.е. если в строке будут HTML-теги, то они будут закодированы, а не преобразованы в разметку. Если вам требуется вставить данные в шаблон именно в виде HTML-разметки, то надо использовать синтаксис {{html }} .
    Для начала работы с плагином уже достаточно рассказано, могу лишь добавить, что синтаксис шаблонов позволяет вставлять вложенные шаблоны, условные инструкции, обращаться к некоторым объектам JS и jQuery и ещё кое-что… Остальное – материал будущей статьи.

    Источники

    Статья написана по материалам, найденным во всемирной паутине. В основном это перевод официальной документации. Оригиналы можно посмотреть по следующим ссылкам:

    • (примеры взяты оттуда)
    Об авторе

    Зовут меня Зайцев Андрей, профиль на форуме zandroid

    Это моя первая статья в этом блоге, надеюсь, и не последняя Большое спасибо Геннадию за возможность публикации и за полезные советы по написанию и оформлению материала.

    Примеры

    Пример 1: Динамическое переключение применяемого шаблона

    table { cursor:pointer; border-collapse:collapse; border:2px solid blue; width:300px; margin:8px; } table tr { border:1px solid blue; color:blue; background-color:#f8f8f8; } table td { padding:3px; } table tr:hover { color:red; } .movieDetail { background-color:yellow; } .movieDetail.row1 { border-bottom:none; } .movieDetail.row2 { border-top:none; } ${Name} ${Name}${ReleaseYear}Director: ${Director} Click for details:

    var movies = [ { Name: "The Red Violin", ReleaseYear: "1998", Director: "François Girard" }, { Name: "Eyes Wide Shut", ReleaseYear: "1999", Director: "Stanley Kubrick" }, { Name: "The Inheritance", ReleaseYear: "1976", Director: "Mauro Bolognini" } ]; var selectedItem = null; /* Render the summaryTemplate with the "movies" data */ $("#summaryTemplate").tmpl(movies).appendTo("#movieList"); /* Add onclick handlers for movie template items using the summary or details template */ $("#movieList") .delegate(".movieSummary", "click", function () { if (selectedItem) { // Set the template on the previously selected item // back to the summary template selectedItem.tmpl = $("#summaryTemplate").template(); selectedItem.update(); } /* Get the data structure for the template item which this clicked element belongs to, and make it the selected item */ selectedItem = $.tmplItem(this); /* Set the template on this item to the detail template */ selectedItem.tmpl = $("#detailTemplate").template(); selectedItem.update(); }) .delegate(".movieDetail", "click", function () { /* Set the template on this item to the summary template */ selectedItem.tmpl = $("#summaryTemplate").template(); selectedItem.update(); selectedItem = null; });

    Довольно сложный и объемный, в нём используются сразу несколько методов плагина, взят с.

    Пример 2: Вставка данных с разметкой в шаблон

    .role {font-weight:bold;font-style: italic;} #movieContainer {padding-left: 8px;} ${Name}

    {{html Synopsis}}

    /* The Synopsis data field contains HTML markup. */ var movie = { Name: "Meet Joe Black", Synopsis: "The grim reaper (Brad Pitt) visits Bill Parrish (Anthony Hopkins)..." }; /* Render the template with the movie data. The template uses the {{html}} template tag to insert the Synopsis HTML markup data. */ $("#movieTemplate").tmpl(movie) .appendTo("#movieContainer");

    В этом примере в шаблон добавляются как простые строковые значения полей, так и значения с разметкой, взято вот с.

    P.S.

    Примеры не стал расписывать, если аудитория поддержит мои начинания, то можно пошагово расписать что, как и почему, и привести ещё несколько примерчиков.

    Вопросы по плагину прошу задавать на форуме , если есть комменты именно по статье – то комментируйте ниже.

    Плагин для реализации сменяющихся слов с различными анимированными эффектами. CSS эффект подойдет для реализации промо-сайтов и анимированных баннеров.

    Реализация разбиения содержимого страницы на вкладки (табы) с использованием анимированных CSS3 эффектов. Четыре варианта исполнения: горизонтальные и вертикальные табы с различными анимированными эффектами.

    3. Адаптивный jQuery слайдер на основе плагина IMPRESS.JS

    Классный слайдер с имитацией 3D эффекта при пролистывании слайдов. При увеличении/уменьшении размера экрана - изменяется размер шрифта, изображений и всех элементов на слайде, что гарантирует корректное отображение при любом расширении экрана. Предусмотрена автоматическая прокрутка.

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

    Реализация навигации по содержимому в виде Список категорий → Список разделов → Содержимое раздела. Навигация сопровождается различными JS эффектами.

    Пролистывание слайдов осуществляется с Parallax эффектом (движение слоев с различной скоростью, в совокупности создают 3D эффект). Размер слайдера изменяется пропорционально изменению размера окна браузера.

    Слайд-шоу с музыкальным сопровождением. Есть возможность ставить на паузу или проматывать музыкальную композицию.

    11. Своеобразное меню на jQuery и CSS

    При выборе пункта меню область с его содержимым раскрывается поверх.

    Выпадающее горизонтальное меню с интересным jQuery эффектом появления вложенных пунктов.

    Обалденный jQuery CSS плагин, будет очень полезным дополнением для сайта любой веб-студии или фрилансера. С его помощью можно наглядно отобразить примеры выполненных работ с разбивкой по времени. Внизу отображается сама временная шкала, а сверху выполненные работы. Для перехода между работами можно использовать как шкалу, так и стрелки влево/вправо.

    14. Галерея «TouchTouch», оптимизированная для просмотра с мобильных устройств 15. CSS3 слайдер изображений «Cycle Slider»

    При клике на название выезжает изображение с описанием. Используется только CSS3.
    Урок по созданию галереи .

    17. Классные яркие всплывающие подсказки jQuery и CSS3

    Всплывающие jQuery подсказки в 7 стилевых оформлениях. Легко подключить и использовать в своих проектах.

    Если изображений в галерее больше 5, то появляются стрелки влево/вправо для навигации по фотографиям.

    Слайдами могут быть не только изображения, но и другой HTML контент.

    Плагин для создания фотореалистичных теней.

    Свежая реализация слайдера.

    26. Перенос текста «Bacon»

    Необычный эффект переноса текста на странице на новую строчку по кривой или заданной линии с определенным шагом смещения.

    Плагин автоматически рассчитывает размер шрифта для каждого слова таким образом, чтобы весь текст занимал одинаковую область по ширине, вне зависимости от количества слов в строке.

    28. Выбор вида отображения блоков с использованием CSS3

    Четыре вида отображения блоков: изображение с описанием в три колонки, изображение с описанием в одну колонку, только изображения, только текстовое описание. Для переключения вида отображения блоков необходимо воспользоваться пиктограммами сверху.

    Приступаем к работе Давайте начнем. Приведенный ниже пример показывает список фильмов, заданный в массиве (полный код примера - в файле BasicSample1.htm ):

    Простой пример (1) ${title}

    Режиссер: ${director}
    В ролях: ${actors}
    Год: ${year}

    $(function () { $("#movieTmpl").tmpl(dataItems).appendTo("#movieListBag"); }); Простой пример (1)
    А вот что вы увидите в браузере:

    Давайте разберем этот пример подробно.

    Итак, первое, что я делаю, это подключаю jQuery Core Library и jQuery Templates :


    Ранее неоднократно говорилось о том, что jQuery Templates будут включены в jQuery Core Library - но в jQuery 1.5 RC1, вышедшем 24 января, шаблоны по прежнему отсутствуют.

    Затем я загружаю список фильмов:


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

    Внутри файл DataItems.js выглядит следующим образом:

    Var dataItems = [ { title: "Бандиты", thumbnail: "Bandits.jpg", director: "Барри Левинсон", actors: ["Брюс Уиллис", "Билли Боб Торнтон", "Кейт Бланшетт"], year: 2001, budget: 95000000, grossRevenue: 67631903, rating: 0, frames: ["Bandits-1.jpg", "Bandits-2.jpg", "Bandits-3.jpg", "Bandits-4.jpg", "Bandits-5.jpg"] }, ...
    Следующим шагом я создаю шаблон:

    ${title}

    Режиссер: ${director}
    В ролях: ${actors}
    Год: ${year}


    Обратите внимание, что шаблон размещается в теге SCRIPT , а в качестве MIME-типа я указываю text/x-jquery-tmpl . Встретив при разборе документа незнакомый MIME-тип, браузер не пытается интерпретировать содержимое тега SCRIPT , что мне и требуется.

    Вообще говоря, шаблон можно разместить в любом теге, например, в теге DIV :

    ${title}

    Режиссер: ${director}
    В ролях: ${actors}
    Год: ${year}


    Однако в этом случае не избежать побочных эффектов, т.к. браузер обязательно попытается интерпретировать код шаблона.

    Например, для приведенного выше примера будет сделана попытка загрузить несуществующую картинку:

    А вот случае с таблицей все может быть гораздо интереснее (большое спасибо TEHEK за этот пример!):

    {{each dataItems}} {{/each}}
    ${title} ${director} ${year}

    Internet Explorer и Opera обработают этот код корректно:

    А вот Chrome и Fire Fox «вытолкнут» лишний код за пределы таблицы, в результате чего таблица окажется пустой… Happy debugging! ;-)

    Для тега SELECT будет наблюдаться аналогичная картина.

    И, наконец, я инстанцирую шаблон с помощью следующего вызова:

    $("#movieTmpl").tmpl(dataItems).appendTo("#movieListBag");
    Что при этом происходит, я изобразил на приведенной ниже диаграмме:

  • Метод .tmpl() получает текст шаблона - т.е. inner text элемента, полученного с помощью вызова $("#movieTmpl") .
  • Текст шаблона компилируется - на его основе создается функция JavaScript.
  • Создается «экземпляр шаблона» - объект, который содержит ссылку на элемент данных (поле data ), переданный как аргумент метода .tmpl() . Методу .tmpl() можно передать массив, объект, null или вызвать его без аргументов. Если передать массив, то для каждого элемента массива будет создан свой экземпляр шаблона, ссылающийся на этот элемент, во всех остальных случаях будет создан только один экземпляр.
  • Вызывается скомпилированная функция-шаблон, которой передается объект-экземпляр. Функция возвращает текст шаблона, в котором сделаны все подстановки.
  • Полученный на предыдущем шаге текст преобразуется в коллекцию HTML-элементов. Ссылки на эти элементы также сохраняются в объекте-экземпляре (поле nodes ), что позволяет в дальнейшем легко обновить «выход» шаблона при изменении исходных данных (см. раздел «Динамическое обновление»).
  • И, наконец, метод .tmpl() возвращает jQuery -коллекцию HTML-элементов, которые добавляются в документ с помощью вызова appendTo("#movieListBag") .
  • Выражения Для подстановки в шаблон значений используется тег ${...} . Внутри этого тега можно указать как наименование свойства объекта, переданного методу .tmpl() , так и любое корректное выражение JavaScript, в том числе вызов функции.

    Использование свойств объекта (элемента массива):

    ${title}
    Использование выражений JavaScript:

    Бюджет: $${(budget / 1000000).toFixed(0)} млн.
    Сборы: $${(grossRevenue / 1000000).toFixed(1)} млн.

    Поля и методы экземпляра шаблона Внутри выражений вы можете обращаться к текущему экземпляру шаблона через переменную $item , а для обращения к текущему элементу данных - переменную $data .

    Каждый экземпляр шаблона содержит следующие поля:

  • data - содержит ссылку на элемент данных, связанный с экземпляром шаблона;
  • tmpl - содержит ссылку на скомпилированный шаблон, используемый для рендеринга;
  • parent - если шаблон был вызван из другого шаблона с помощью тега {{tmpl}} , содержит ссылку на «родительcкий» экземпляр шаблона;
  • nodes - после рендеринга содержит ссылки на HTML-элементы, порожденные в результате применения шаблона.
  • Кроме того, метод .tmpl() принимает два аргумента - data и options . С аргументом data вы уже познакомились, через него передается ссылка на элемент данных. А используя аргумент options , можно передать ссылку на объект, все поля и методы которого будут перенесены в каждый экземпляр шаблона, созданный в методе .tmpl() .

    Ниже приведен пример использования этого параметра:

    ${title}

    Режиссер: ${director}
    В ролях: ${actors}
    Год: ${year}
    Бюджет: $${$item.formatBudget(budget)} млн.
    Сборы: $${$item.formatGrossRevenue(grossRevenue)} млн.


    $(function () { $("#movieTmpl") .tmpl(dataItems, { formatBudget: function (value) { return (value / 1000000).toFixed(0); }, formatGrossRevenue: function (value) { return (value / 1000000).toFixed(1); } }) .appendTo("#movieListBag"); });
    В этом примере я использую для форматирования значений бюджета и сборов вызовы функций, но чтобы не «захламлять» глобальное пространство имен, я передал их через параметр options , после чего эти функции стали доступны как методы текущего экземпляра шаблона.

    И, наконец, экземпляр шаблона содержит методы update() и html() , использование которых я покажу далее.

    Как выглядит скомпилированный шаблон? Как выглядит скомпилированный шаблон, можно увидеть, воспользовавшись методом .template() , который как раз и осуществляет компиляцию шаблонов. Этот метод возвращает объект-функцию, содержимое которой легко посмотреть:

    $("#compiledTemplateBag").text("" + $("#movieTmpl").template());
    Шаблон, использованный в примере выше, после компиляции выглядит следующим образом (текст отформатирован для лучшей читаемости):

    Function anonymous(jQuery, $item) { var $ = jQuery, call, _ = , $data = $item.data; with ($data) { _.push(" "); if (typeof (title) !== "undefined" && (title) != null) { _.push($.encode((typeof (title) === "function" ? (title).call($item) : (title)))); } _.push("

    Режиссер: "); if (typeof (director) !== "undefined" && (director) != null) { _.push($.encode((typeof (director) === "function" ? (director).call($item) : (director)))); } _.push("
    В ролях: "); if (typeof (actors) !== "undefined" && (actors) != null) { _.push($.encode((typeof (actors) === "function" ? (actors).call($item) : (actors)))); } _.push("
    Год: "); if (typeof (year) !== "undefined" && (year) != null) { _.push($.encode((typeof (year) === "function" ? (year).call($item) : (year)))); } _.push("

    "); } return _; }
    Думаю, что теперь вам должно быть понятно, как обрабатываются выражения, указанные в теге ${...} - и это понимание может существенно помочь вам при отладке! Дело в том, что jQuery Templates выполняет относительно простое преобразование текста шаблона, поэтому если вы допустите ошибку в выражении, то сообщение об ошибке будет относиться к тексту полученной в результате преобразования функции и часто может быть крайне невразумительным.

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

    Что ж, пожалуй, на этом рассказ о работе jQuery Templates стоит завершить и перейти к его практическому применению.

    Часть вторая, практическаяУсловия Для того чтобы применять части шаблона в зависимости от некоторых условий, в jQuery Templates используются теги {{if}}...{{else}}...{{/if}} .

    Приведенный ниже пример показывает использование этих тегов (полный код примера - в файле IfElseTag.htm ):

    Носитель: {{if $item.data.media == "dvd"}} {{else $item.data.media == "blue-ray"}} {{else}} {{/if}}


    Как несложно догадаться, этот код предназначен для вывода значка носителя, на котором находится фильм. Вот как это выглядит в браузере:

    В качестве условия в тегах {{if}} и {{else}} можно использовать любое корректное JavaScript-выражение.

    Обработка коллекций Для обработки коллекций в шаблонах используется тег {{each}}...{{/each}} . Приведенный ниже пример показывает использование тега {{each}} для вывода списка актеров (полный код примера - в файле EachTag1.htm ):

    В ролях: {{each actors}} ${$value} {{if $index < $data.actors.length - 1}} , {{/if}} {{/each}}

    В качестве аргумента тегу {{each}} можно передать массив, объект, или jQuery -коллекцию. Внутри тег {{each}} использует вызов jQuery.each() , поэтому все, что сказано в документации о поведении jQuery.each() справедливо и для тега {{each}} . Пример ниже демонстрирует использование тега {{each}} для показа всех свойств объекта (полный код примера - в файле EachTag2.htm ):

    {{each $data}} ${$index} ${$value} {{/each}}
    Внутри тега {{each}} доступно две переменные: $value , которая содержит ссылку на текущий элемент массива, и $index , которая содержит индекс текущего элемента массива или имя свойства.

    Разумеется, внутри тега {{each}} можно использовать другие теги, а кроме того, вам по-прежнему будут доступны переменные $item и $data . В приведенном примере переменные $index и $data вместе с тегом {{if}} используются, чтобы вывести запятую между именами актеров - к сожалению, переменная $last не предусмотрена, хотя она была бы очень полезна!

    Наконец, если у вас вдруг возникнет такая необходимость, вы можете изменить имена переменных по умолчанию. В примере, приведенном ниже, эти имена изменены на myIndex и myValue (полный код примера - в файле EachTag3.htm ):

    В ролях: {{each(myIndex, myValue) actors}} ${myValue} {{if myIndex < $data.actors.length - 1}} , {{/if}} {{/each}}
    Кстати, попытка изменить имя только для переменной $index ни к чему хорошему не приведет - ошибки не будет, но и доступа к текущему значению вы тоже не сможете получить!

    Вложенные шаблоны Шаблоны могут быть очень большими - и тогда имеет смысл разделить их на несколько частей меньшего объема или включать повторяющиеся части, которые логично выделить в отдельный шаблон. В jQuery Templates это осуществляется с помощью вложенных шаблонов, для вызова которых используется тег {{tmpl}} .

    Пример ниже иллюстрирует, как вынести часть кода шаблона в другой шаблон (полный код примера - в файле NestedTemplates1.htm ):

    ...

    Режиссер: ${director}
    В ролях: {{tmpl "#actorsTmpl"}}
    Год: ${year}

    ... {{each actors}} ${$value} {{if $index < $data.actors.length - 1}} , {{/if}} {{/each}}
    В теге {{tmpl}} обязательно указывается jQuery -селектор вызываемого шаблона или имя шаблона, ранее сохраненного в кэше. Т.к. в этом примере других аргументов у тега {{tmpl}} нет, вложенный шаблон получит тот же самый элемент данных, что и родительский - но экземпляр шаблона у него будет свой, причем поле parent в нем будет ссылаться на родительский экземпляр шаблона.

    Следующий пример демонстрирует передачу во вложенный шаблон нового элемента данных и использование ссылки на родительский экземпляр шаблона. Как и в случае использования метода .tmpl() , если при вызове вложенного шаблона указать массив, то шаблон будет применен для каждого элемента массива (полный код примера - в файле NestedTemplates2.htm ):

    ...

    Режиссер: ${director}
    В ролях: {{tmpl(actors) "#actors_template"}}
    Год: ${year}

    ... ${$data} {{if $data !== $item.parent.data.actors[$item.parent.data.actors.length - 1]}} , {{/if}}
    И, наконец, последний пример в этом разделе показывает, как передать во вложенный шаблон аргумент options , а заодно демонстрирует, как аргумент options можно использовать для определения последнего элемента в обрабатываемом массиве (полный код примера - в файле NestedTemplates3.htm ):

    ...

    Режиссер: ${director}
    В ролях: {{tmpl(actors, { last: actors }) "#actors_template"}}
    Год: ${year}

    ... ${$data} {{if $data !== $item.last}} , {{/if}}

    Трансформация Еще одна интересная возможность jQuery Templates связана с трансформацией HTML-разметки, для чего используется тег {{wrap}} (вообще говоря, wrap - это «обертывание», но мне кажется что термин «трансформация» лучше отражает суть происходящего).

    Классический пример использования тега {{wrap}} - это создание закладок:

    Вот как это выглядит внутри (полный код примера - в файле Transformation1.htm ):

    {{wrap(null, { viewState: $item.viewState }) "#tabsTmpl"}} English The Ballad of East and West Rudyard Kipling

    OH, East is East, and West is West...

    {{/wrap}}
    Исходные данные для трансформации размещаются в шаблоне tabContent - именно этот шаблон я дальше будут инстанцировать.

    HTML-разметка, которую я буду трансформировать, помещается в теге {{wrap}} . Для тега {{wrap}} используется точно такая же нотация вызова, что и для тега {}}
    В браузере этот пример будет выглядеть так:

    Кэширование шаблонов В каждом вызове $("#...").tmpl(...) происходит компиляция шаблона, что, несмотря на резко возросшую скорость работы JavaScript в современных браузерах, может крайне негативно сказаться на производительности. Разработчики jQuery Templates никак не могли обойти своим вниманием этот очевидный факт, поэтому в jQuery Templates предусмотрен механизм для предварительной компиляции и кэширования шаблонов.

    Компиляция и кэширование шаблона производится следующим образом:

    $("#movieTmpl").template("movieTmpl");
    Скомпилированный шаблон сохраняется во внутреннем кэше jQuery Templates под именем movieTmpl . Для обращения к кэшированному шаблону используется метод jQuery.tmpl() , и первым параметром ему передается имя кэшированного шаблона:

    $.tmpl("movieTmpl", dataItems).appendTo("#movieListBag");
    В примере, приведенном ниже, осуществляется навигация по списку фильмов, причем для показа информации о фильме используется кэшированный шаблон.

    Код шаблона практически не отличается от тех, что я использовал ранее, единственное его отличие - под описанием фильма дополнительно размещаются ссылки для навигации (полный код примера - в файле CachedTemplates.htm ):

    ${title}

    Режиссер: ${director}
    В ролях: ${actors}
    Год: ${year}

    {{if $item.canMoveBack}} [Назад] {{/if}} {{if $item.canMoveFwd}} [Вперед] {{/if}}
    Сопутствующий скрипт так же несложен:

    Var movieIndex = 0; $(function () { $("#movieTmpl").template("movieTmpl"); updateMovie(); $("#movieBag").delegate(".nav-link", "click", function () { movieIndex += parseInt($(this).attr("x-inc")); updateMovie(); }); }); function updateMovie() { $("#movieBag").empty(); $("#movieBag").append($.tmpl("movieTmpl", dataItems, { canMoveBack: movieIndex > 0, canMoveFwd: movieIndex < dataItems.length - 1 })); }
    Обработчик нажатия на навигационную ссылку меняет индекс выбранного фильма, а затем вызывает функцию updateMovie() , которая сначала очищает контейнер с описанием фильма, а затем заполняет его новыми данными.

    Вот как этот пример выглядит в браузере:


    Браузер, конечно, загрузит соответствующий файл - но вот получить доступ к его содержимому у вас все равно не получится.

    Но шаблон все-таки можно разместить в отдельном файле, и для этого потребуется буквально одна дополнительная строчка кода (полный код примера - в файле ):

    $(function () { $.get("Templates/DynamicLoading.htm", {}, function (templateBody) { $.tmpl(templateBody, dataItems).appendTo("#movieListBag"); }); });
    Т.к. в данном случае мы получаем шаблон в виде текста, для его инстанцирования применяется метод jQuery.tmpl() , первым аргументом которому передается полученный текст шаблона.

    Да, метод jQuery.tmpl() используется для инстанцирования как кэшированных шаблонов по имени, так и шаблонов, заданных в виде текста (традиция!..) - впрочем, он достаточно «умен», чтобы отличить их друг от друга.

    Если вам нужно загрузить несколько связанных шаблонов, вы можете воспользоваться библиотекой WaitSync (см. «Синхронизация асинхронных вызовов. WaitSync ») или написать свой синхронизатор (полный код примера - в файле ):

    $(function () { var ws = new WaitSync(function () { $.tmpl("movieTmpl", dataItems).appendTo("#movieListBag"); }); $.ajax({ cache: false, url: "Templates/MovieTmpl.htm", success: ws.wrap("MovieTmpl", function (templateBody) { $.template("movieTmpl", templateBody); }), error: ws.wrap("MovieTmpl", function () { alert("Error loading MovieTmpl.htm!"); }) }); $.ajax({ cache: false, url: "Templates/ActorsTmpl.htm", success: ws.wrap("ActorsTmpl", function (templateBody) { $.template("actorsTmpl", templateBody); }), error: ws.wrap("ActorsTmpl", function () { alert("Error loading ActorsTmpl.htm!"); }) }); });
    Обратите внимание, что в данном случае шаблон actorsTmpl вызывается по имени (файл Templates\MovieTmpl.htm ):

    Режиссер: ${director}
    В ролях: {{tmpl(actors, { last: actors }) "actorsTmpl"}}
    Год: ${year}

    Динамическое обновление В последнем разделе практической части я покажу еще два сценария работы jQuery Templates - изменение связанных данных и подмену связанного шаблона.

    В приведенном ниже примере для каждого фильма добавлена возможность изменить его рейтинг (полный код примера - в файле DynamicUpdate1.htm ):

    ...
    Сопутствующий код:

    $(function () { $("#movieTmpl").tmpl(dataItems).appendTo("#movieListBag"); $("#movieListBag").delegate(".rating-button", "click", function () { var item = $.tmplItem(this); item.data.rating += parseInt($(this).attr("x-inc")); item.update(); }); });
    Как видно, этот код очень похож на код закладок из раздела «Трансформация», только при работе с закладками я обращался к разделяемому объекту viewState , а здесь я работаю с данными, связанными с экземпляром шаблона.

    В браузере этот пример выглядит так:

    Следующий пример демонстрирует подмену связанного шаблона (полный код примера - в файле DynamicUpdate2.htm ):

    {{tmpl "#movieMainTmpl"}}

    [Больше...]

    {{tmpl "#movieMainTmpl"}}

    Кадры из фильма:

    {{each frames}} {{/each}}

    [Меньше...]


    Здесь я использую два шаблона, movieShortTmpl и movieFullTmpl , общая часть которых вынесена в шаблон movieMainTmpl .

    Сопутствующий код:

    $(function () { var shortTemplate = $("#movieShortTmpl").template("shortTemplate"); var fullTemplate = $("#movieFullTmpl").template(); $.tmpl("shortTemplate", dataItems).appendTo("#movieListBag"); $("#movieListBag").delegate(".more-details", "click", function () { var item = $.tmplItem(this); item.tmpl = item.tmpl === shortTemplate ? fullTemplate: shortTemplate; item.update(); }); });
    Думаю, этот код требует дополнительных пояснений.

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

    В браузере этот пример выглядит следующим образом:

    Заключение Код примеров, использованных в статье, вы можете загрузить по этой ссылке .

    Загрузить jQuery Templates можно с web-сайта ASP.NET CDN или напрямую из репозитария GitHub:
    Brian Landau «Benchmarking Javascript Templating Libraries ».

    И в заключение я хочу выразить благодарность Виталию Дильмухаметову и Денису Гладких за ценные замечания, сделанные в процессе работы над статьей.

    Теги: Добавить метки



    Понравилась статья? Поделиться с друзьями: