Объекты страницы: описание одной техники

от автора

Здравствуйте, хабровчане.

Хочу поделиться с вами одной техникой организации кода при массивной работе с DOM-элементами. Несколько лет назад, когда еще вовсе не было бэкбона и MVVC, мы писали старый добрый джаваскрипт без фреймворков: создавали объекты и заставляли их плясать на странице в общем танце. Такая практика, без сомнения, до сих пор оправдывает себя, и техника, о которой пойдет речь, применима именно к ней.

Мой рассказ — о маленькой библиотечке PageObject.js (текущая версия v0.14, 2.6K) и о том, как с ее помощью можно упростить себе жизнь.

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

Суть техники

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

function Calculator() {   if (this.constructor.name !== 'Calculator') { throw “No way, buddy!”; }   // 1. отрендерить шаблон   // 2. разобрать на части   // 3. повесить обработчики   // 4. остальная логика } 

PageObject.js помогает с первыми двумя шагами.

function Calculator() {   if (this.constructor.name !== 'Calculator') { throw “No way, buddy!”; }   var calc = this;   $.turnToPageObject(calc, {     template: $('#tmplCalculator').html(),     containerClass: 'calc',     context: {       caption: "Calculator"     },     selectors: {       buttons: [ ':button', Calculator.getButtonName ],       led: 'p'     }   });   // 3. повесить обработчики   // 4. другая логика } var calc = new Calculator; $('body').append(calc.DOM.container); 

После того, как отработает функция $.turnToPageObject (“превратить в объект страницы”), у объекта calc появится свойство calc.DOM — неймспейс, заполненый DOM-элементами, которые будут соответствовать указанным селекторам, и еще появится calc.DOM.container — именно та легко встраиваемая в приложение часть объекта — контейнер всего-всего.

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

$.turnToPageObject

Первый аргумент должен быть объектом, у которого в последствии появится заполненый составными HTML-елементами неймспейс DOM. Второй аргумент — опции.

Если НЕ указать опцию container, то контейнер будет создан (без него никак), и это будет такой же элемент, как и containerElement (по умолчанию — DIV).

Если указать containerClass, то контейнеру будет присвоен класс.

Если указать template, то будет отрендерен шаблон и его результат будет помещен внутрь контейнера.

Если НЕ указать context, то шаблон будет отрендерен с пустым контекстом {}.

template может быть либо строкой, либо функцией (интеграция с Jammit JST).

Когда template — функция, он принимает только контекст и должен возвратить строку.

Когда template — строка, шаблон рендерится при помощи templateEngine, которая автоматически настроится по умолчанию на использование шаблонизатора _.template, если underscore присутствует.

Если в вашем проекте нет underscore, вам нужно сконфигурировать templateEngine.

// вот так меняются умолчания: $.turnToPageObject.configure({   templateEngine: window.tmpl, // http://ejohn.org/blog/javascript-micro-templating   containerElement: 'strong' }); 

templateEngine принимает два аргумента — строку шаблона и контекст — и также должен возвратить строку.

Если указана опция hide, то контейнер будет спрятан, что часто бывало удобно.

И главное — селекторы. Если указать опцию selectors (объект), то соответствующие селекторам найденые в содержимом контейнера HTML-элементы будут по аналогичным ключам помещены в неймспейс DOM. Если опция template была указана, то селекторы будут искать в уже отрендеренном шаблоне.

Если по селектору не будет найдено ни одного элемента — будет крик.
Если по селектору будет найдено более одного элемента — также будет исключение.
Если все же нужно, чтобы по селектору были найдены и помещены в массив более одного элемента, нужно к значению селектора дописать [] (пустые квадратные скобки) — такое выделение себя оправдывает.

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

Стоит отметить, что дополнительные неймспейсы в селекторах образуют неймспейсы с теми же именами внутри свойства DOM.

Пожалуй, на этом все.

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

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

ссылка на оригинал статьи http://habrahabr.ru/post/179983/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *