Pull to refresh

Работаем с jQuery Templates. Часть третья, jQuery Templates Plus

Reading time7 min
Views7K
Две недели назад я рассказал об основных возможностях плагина jQuery Templates и обещал на этом не останавливаться. Обещания надо выполнять, поэтому сегодня я расскажу о дополнительных функциях, не вошедших в основной код плагина.

Дополнительные функции плагина включают:
  1. Набор команд, существенно упрощающих изменение отрендеренных шаблонов при изменении связанных с ними данных;
  2. Событие rendered, которое вызывается после того, как отрендеренный шаблон добавляется в структуру документа.

Код дополнительных функций вынесен в файл jquery.tmplPlus.js, поэтому для их использования вы должны добавить ссылку на этот файл:

<script src="Scripts/jquery-1.5.js" type="text/javascript"></script>
<script src="Scripts/jquery.tmpl.js" type="text/javascript"></script>
<script src="Scripts/jquery.tmplPlus.js" type="text/javascript"></script>



Команды для изменения отрендеренных шаблонов


Вызов команд


Для вызова всех команд используется метод jQuery.tmplCmd().

Этот метод имеет три формы вызова:
  1. jQuery.tmplCmd(command, tmplItem)
  2. jQuery.tmplCmd(command, tmplItems)
  3. jQuery.tmplCmd(command, data, tmplItems)

Параметр command используется для указания имени команды (update, remove, replace или find).

Параметр tmlItem используется для передачи ссылки на экземпляр шаблона, с которым будет работать команда. Соответственно, параметр tmplItems используется для передачи массива ссылок на экземпляры шаблонов.

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



Какие из этих трех форм вызова применимы для каждой команды, я укажу в описании этих команд.

Команда replace


Команда replace, пожалуй, самая интересная из всех, она меняет порядок отрендеренных шаблонов в структуре документа в соответствии с порядком, заданным ее аргументами, причем без повторного рендеринга шаблонов.

Эта команда допускает три формы вызова, но практическое применение имеет только одна из них:
  1. jQuery.tmplCmd('replace', data, tmplItems)

После вызова replace отрендеренные шаблоны будут переставлены в порядке, в котором в массиве data следуют ссылки на элементы данных. Идеальное решение для сортировки!

Давайте теперь посмотрим, как это работает. Данные, с которыми я буду работать в этом и в других примерах из этого раздела, находятся в массиве dataItems (полный код примера – в файле Samples.htm):

var dataItems = [
    { firstName: 'Брюс', lastName: 'Уиллис' },
    { firstName: 'Билли Боб', lastName: 'Торнтон' },
    ...
];

Для показа этих данных я использую следующий шаблон:

<script id="item_tmpl" type="text/x-jquery-tmpl">
    <tr class="item">
        <td>${firstName}</td>
        <td>${lastName}</td>
        <td>
            <img src="Images/item-edit.png" class="item-edit" title="Edit" />
            <img src="Images/item-delete.png" class="item-delete" title="Delete" >
        </td>
    </tr>
</script>

После рендеринга я сохраняю ссылки на все экземпляры шаблона в массиве tmplItems:

$('#item_tmpl').tmpl(dataItems, options).appendTo('#items_bag');

tmplItems = $('#items_bag .item').map(function () {
    return $.tmplItem(this);
}).get();

Обработчики событий я прикрепляю к картинкам, помеченным классами sort-asc и sort-desc в заголовке таблицы. Дополнительный атрибут x-field-name содержит имя поля, по которому будет проводиться сортировка:

<table id="items_bag">
    <tr>
        <th>First Name
            <img src="Images/sort-asc.png" class="sort-asc" x-field-name="firstName" alt="" />
            <img src="Images/sort-desc.png" class="sort-desc" x-field-name="firstName" alt="" />
        </th>
        <th>Last Name
            <img src="Images/sort-asc.png" class="sort-asc" x-field-name="lastName" alt="" />
            <img src="Images/sort-desc.png" class="sort-desc" x-field-name="lastName" alt="" />
        </th>
        <th></th>
    </tr>
</table>

Код для сортировки по возрастанию показан ниже:

$('#items_bag').delegate('.sort-asc', 'click', function () {
    var fieldName = $(this).attr('x-field-name');

    dataItems.sort(function (a, b) {
        return compareStrings(a[fieldName], b[fieldName]);
    });

    tmplItems = $.tmplCmd('replace', dataItems, tmplItems);
});

Здесь я сначала получаю имя поля, по которому производится сортировка:

var fieldName = $(this).attr('x-field-name');

Затем сортирую массив с элементами данных:

dataItems.sort(function (a, b) {
    return compareStrings(a[fieldName], b[fieldName]);
});

И, наконец, вызываю команду replace, чтобы отобразить в документе измененные данные:

tmplItems = $.tmplCmd('replace', dataItems, tmplItems);

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

Код для сортировки по убыванию выглядит аналогично:

$('#items_bag').delegate('.sort-desc', 'click', function () {
    var fieldName = $(this).attr('x-field-name');

    dataItems.sort(function (a, b) {
        return compareStrings(a[fieldName], b[fieldName]);
    }).reverse();

    tmplItems = $.tmplCmd('replace', dataItems, tmplItems);
});

Как это работает, показано на видео ниже:



Команда update


Команда update инициирует повторный рендеринг шаблонов. Фактически, это эквивалент метода update() экземпляра шаблона с дополнительными опциями. Самое ее логичное применение – обновить документ после изменения данных.

Эта команда допускает три формы вызова, и, в отличие от команды replace, все эти формы имеют практическое применение:
  1. jQuery.tmplCmd('update', tmplItem)
  2. jQuery.tmplCmd('update', tmplItems)
  3. jQuery.tmplCmd('update', data, tmplItems)

Давайте посмотрим, как она работает на примере редактора таблицы (полный код примера – в файле Samples.htm). Код для редактирования элемента показан ниже:

$('#items_bag').delegate('.item-edit', 'click', function () {
    var tmplItem = $.tmplItem(this);
    var dataItem = tmplItem.data;

    editDialog.show(dataItem, function () {
        $.tmplCmd('update', tmplItem);
    });
});

Здесь я сначала получаю ссылку на экземпляр шаблона и ссылку на элемент данных:

var tmplItem = $.tmplItem(this);
var dataItem = tmplItem.data;

Затем вызываю диалоговое окно, которому передаю ссылку на элемент данных и callback-функцию, которая будет вызвана, если пользователь нажал OK, и данные были изменены:

editDialog.show(dataItem, function () {
    $.tmplCmd('update', tmplItem);
});

А в callback-функции я вызываю команду update, указав ей ссылку на экземпляр шаблона, что вызывает его повторный рендеринг:

$.tmplCmd('update', tmplItem);

Как это работает, показано на видео ниже:



Команда remove


Команда remove, как несложно догадаться, удаляет отрендеренные шаблоны из структуры документа. Так же как и команда update, она имеет три формы вызова:
  1. jQuery.tmplCmd('remove', tmplItem)
  2. jQuery.tmplCmd('remove', tmplItems)
  3. jQuery.tmplCmd('remove', data, tmplItems)

Особенностью этой команды являет то, что она не только удаляет отрендеренные шаблоны из структуры документа, но еще и удаляет из массива tmplItems ссылки на соответствующие экземпляры шаблонов!

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

Код для удаления элемента таблицы показан ниже:

$('#items_bag').delegate('.item-delete', 'click', function () {
    var tmplItem = $.tmplItem(this);
    var dataItem = tmplItem.data;

    if (confirm('Do you really want to delete "' + dataItem.firstName + ' ' + dataItem.lastName + '"?')) {
        dataItems.splice(jQuery.inArray(dataItem, dataItems), 1);

        $.tmplCmd('remove', dataItem, tmplItems);

        updateDebugInfo();
    }
});

Здесь я сначала получаю ссылку на экземпляр шаблона и ссылку на элемент данных:

var tmplItem = $.tmplItem(this);
var dataItem = tmplItem.data;

А после получения подтверждения от пользователя сначала удаляю соответствующий элемент из массива dataItems:

dataItems.splice(jQuery.inArray(dataItem, dataItems), 1);

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

$.tmplCmd('remove', dataItem, tmplItems);

Код функции updateDebugInfo() показан ниже:

function updateDebugInfo() {
    $('#data_items_length').text(dataItems.length);
    $('#tmpl_items_length').text(tmplItems.length);
}

Эта функция как раз предназначена для демонстрации побочного эффекта команды remove.

Как это работает, показано на видео ниже:



Команда find


Команда find предназначена для поиска экземпляров шаблона, связанных с определенными данными. Вместе с командами update и remove она может использоваться для «точечного» обновления документа, когда повторный рендеринг всех шаблонов занимает слишком много времени.

Эта команда допускает только одну форму вызова:
  1. jQuery.tmplCmd('find', data, tmplItems)

Результат выполнения этой команды – массив ссылок на экземпляры шаблонов, связанных с данными, переданными через аргумент data.

Пример использования команды find приведен ниже (полный код примера – в файле Samples.htm):

$('#item_rnd').click(function () {
    var dataItem = dataItems[Math.round(Math.random() * (dataItems.length - 1))];

    var tmplItem = $.tmplCmd('find', dataItem, tmplItems)[0];

    $(tmplItem.nodes).css('background-color', '#ff0000');
    $(tmplItem.nodes).animate({ 'background-color': '#ffffff' }, 1500);
});

В этом примере я случайным образом выбираю элемент данных:

var dataItem = dataItems[Math.round(Math.random() * (dataItems.length - 1))];

Затем с помощью команды find нахожу экземпляр шаблона, с которым связан этот элемент данных:

var tmplItem = $.tmplCmd('find', dataItem, tmplItems)[0];

И, наконец, подсвечиваю соответствующую строку таблицы:

$(tmplItem.nodes).css('background-color', '#ff0000');
$(tmplItem.nodes).animate({ 'background-color': '#ffffff' }, 1500);

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

Как это работает, показано на видео ниже:



Событие rendered


Событие rendered определено для экземпляра шаблона и вызывается после того, как отрендеренный шаблон помещается в структуру документа.

Для задания обработчика события используется параметр options вызова .tmpl():

var options = {
    rendered: function (tmplItem) {
        if (window.console) {
            console.log("rendered: %s %s", tmplItem.data.firstName, tmplItem.data.lastName);
        }
    }
};

$('#item_tmpl').tmpl(dataItems, options).appendTo('#items_bag');

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

Как это работает, показано на видео ниже:



Заключение


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

Напоминаю так же, что загрузить jQuery Templates можно с web-сайта ASP.NET CDN или напрямую из репозитария GitHub:

Документация по jQuery Templates доступна на сайте документации jQuery.
Tags:
Hubs:
+46
Comments5

Articles