Комментарии comment-bg 3
Dojo и построение интерфейсов

Dojo — это модульная библиотека JavaScript. Разработана для простоты и ускорения в построении сайтов с использованием интерактивных систем и AJAX технологий. Разработка данной библиотеки берет свое начало с 2004 года. С версии 1.0. С выходом версии 1.6 dojo начало использоваться в Zend Framework.

Внутренние классы Dojo

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

В версиях 1.10 была выпущенна поддержка работы с мобильными устройствами.
Также библиотека Dojo поддерживает работу с браузерами:

  • Internet Explorer 9-11
  • FireFox 3.6+
  • Safari 5+
  • Opera 10.5+
  • Chrome 13+

Поддержка в операционных системах

  • IOS 5+
  • Android 2.2+
  • Windows Phone 8+
  • BlackBerry 6+
  • А также работа с Node.js в версиях 0.6.11+, 0.8.6+, 0.10+

Dojo и Dijit UI Framework.
Без сомнения, самым большим преимуществом Dojo Toolkit перед другими JavaScript фреймворками является его Dijit UI фреймворк.

Это беспрецедентный набор лэйаутов, форм и других инструментов:

  • полная локализация из коробки;
  • расширенный макет виджетов для облегчения 100% высоты элементов, cоздания пользовательских разделителей, изменения лэйаута и т.д.;
  • виджеты формы с улучшенным удобством и встроенной поддержкой валидации;
    много тем оформления;
  • поддержка LESS в пользовательских темах;
  • модульный код, что позволяет полную пользовательскую настройку любых виджетов, а также расширение их возможностей.

По мимо выше перечисленных пунктов dojo  предлагают пользователям прямо из коробки  5 тем для начальной разработки  и построения интерфейсов. Имена шаблонов стиля:

  • ally
  • claro
  • nihilo
  • soria
  • tundra

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

Модульность и расширяемость

Клиентский JavaScript код, как и любой код, склонен расти в размерах. Модульность является тем ключем, который делает наш код легко поддерживаемым и производительным. Dojo Toolkit является ярким примером фреймворка, использующего модули. Он использует dojo.require для того, чтобы динамически подтягивать только те ресурсы, которые нужны странице в данный момент.
Dojo использует асинхронный загрузчик, который мастерски загружает все ресурсы асинхронно и намного быстрее, чем в начальных версиях 1.0 — 1.3.

Пример кода:
// Функция require сообщает загрузчику, что необходимы модули из первого массива
// Если модуль из списка уже был загружен, то он будет взят из кэша
require(
// Массив модулей требующих загрузки [«dojo/on», «dojo/touch», «dijit/form/Button», «dojo/domReady!»],
// Функция, которая будет вызвана после загрузки всех модулей,
// с объектами модулей переданными ей в качестве аргументов.
// Модули должны быть перечислены в том же порядке, что и в массиве требований
function(on, touch, Button) {
// Здесь выполняем нужные нам действия с загруженными модулями.
});

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

В то время, как JavaScript не предоставляет настоящей системы классов, Dojo Toolkit предоставляет классоподобный паттерн наследования, основанный на использовании dojo/declare. Declare реализован во фреймворке так, что позволяет разработчикам:

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

Одной из самых негативных сторон в разработке модулей есть непонимание проблем в возникающих ошибках при удалениях и созданиях новых объектов, так как система оповещения об ошибках с описанием в dojo  отсутствует.

Система классов Dojo использует прототипное наследование. Использование dojo/declare невероятно просто:

Пример кода:

define([
«dojo/_base/declare», // базовые классы для расширения
«dijit/_WidgetBase»,
«dijit/_TemplatedMixin»,
‘dijit/_AttachMixin’,
‘dijit/_WidgetsInTemplateMixin’,
«dojo/_base/fx»,
«dojo/_base/lang»,

«dojo/text!./templates/template1.html», // путь к используемому шаблону

«dojo/dom-style», // внутренние классы для работы с структурой DOM
«dojo/on»,
«dojo/mouse»,
«dojo/dom-construct»,
//подключаемые классы из предоставленых библиотекой dojo компонентов.
«dijit/form/Button»
], function(declare, _WidgetBase, _TemplatedMixin, _AttachMixin, _WidgetsInTemplateMixin, baseFx, lang, template, domStyle,  on, mouse, require, domConstruct,  Button){
return declare([_WidgetBase, _TemplatedMixin, _AttachMixin, _WidgetsInTemplateMixin], {
templateString: template,
description: «»,
alertType: «»,
baseClass: «systemAlert»,
answer: null,
}
});
});

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

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

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

<div>
<h3 data-dojo-attach-point=»Nodetitle» class=»${baseClass}title» ></h3>
<div class=»${baseClass}description»>
<img class=»${baseClass}image» src=»» data-dojo-attach-point=»Nodemessageimage»>
<p data-dojo-attach-point=»Nodedescription» class=»alertdescription»>${description}</p>
<div class=»${baseClass}buttonpanel»>
<button data-dojo-type=»dijit.form.Button» data-dojo-attach-point=»buttonOk» label=»Ок» data-dojo-attach-event=»click:ok» ></button>
<button data-dojo-type=»dijit.form.Button» data-dojo-attach-point=»Cancel» label=»Відмінити» data-dojo-attach-event=»click: cancel»></button>
</div>
</div>
</div>

Главным и решающим моментом в создание шаблона является нахождения всего тела шаблона в одном теге. Все внутренные переменные в шаблоне объявляються в формате ${baseClass}. Доступ к определенным узлам в шаблоне фиксинуеться внутринными переменными типа  data-dojo-attach-point = «имя переменной». Для того, чтобы прикрепить к определенному тегу событие, используют внутреннюю переменную data-dojo-attach-event=» «название события»:  «Имя функции» «. Где имя функции описываеться в теле класса:
data-dojo-attach-event=»click: cancel»

Использование стандартных модулей, а также модулей, написанных в ходе разработки, возможна двумя разными способами. Первый из них является инициализацией объекта через JavaScript:

<script>
require([«mywidjet/systemAlert»,
function(systemAlert){
dojo.byId(«IdName»).appendChild(new  systemAlert({}).domNode);
});
</script>

и другой способ, который возможен в виде описания модуля HTML разметкой. Но при этом следует иницализировать стандартный объект dojo.parser, которой распознает в структуре HTML ключевые слова, по которым может создать готовый объект dojo.

<div id=»IdName» data-dojo-type=»mywidjet/systemAlert»></div>

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

Пример описание инпута с валидацией и текстовым сообщением при не коректном вводе данных.

<script>
require([«dojo/parser», «dijit/form/ValidationTextBox»]);
</script>
<label for=»phone»>Phone number, no spaces:</label>
<input type=»text» name=»phone» id=»phone» value=»someTestString» required=»true»
data-dojo-type=»dijit/form/ValidationTextBox»
data-dojo-props=»regExp:'[\\w]+’, invalidMessage:’Invalid Non-Space Text.'» />

От теории к практике

Данный пример заключается в написании собственного виджета, расширяемого элементами dijit Ui framework`a, с использованием call-back функций, привязкой событий к виджету и работу с внутренними переменными, а также доступ к ним.

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

Тематика нашего виджета будет предельно простой, это будет окно уведомления пользователя, которое будет в себе вмещать изображение, описание, название (шапку).

Функциональность виджета будет реагировать на нажатия кнопок. Их будет две: для окна, которое будет опрашивать пользователя, и одна кнопка для простого окна уведомления, после которого системное окно будет удаляться.

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

Пример кода виджета «systemAlert»:
define([
«dojo/_base/declare»,
«dijit/_WidgetBase»,
«dijit/_TemplatedMixin»,
«dojo/text!./templates/template1.html»,
«dojo/dom-style»,
«dojo/_base/fx»,
«dojo/_base/lang»,
«dojo/on»,
«dojo/mouse»,
«require»,
«dojo/dom-construct»,
‘dijit/_AttachMixin’,
‘dijit/_WidgetsInTemplateMixin’,
«dijit/form/Button»
], function(declare, _WidgetBase, _TemplatedMixin, template, domStyle, baseFx, lang, on, mouse, require, domConstruct, _AttachMixin, _WidgetsInTemplateMixin, Button){
return declare(«mywidjet/systemAlert», [_WidgetBase, _TemplatedMixin, _AttachMixin, _WidgetsInTemplateMixin], {
templateString: template
}
});
});

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

Шаблон, который привязан к виджету:

<div>
<h3 data-dojo-attach-point=»Nodetitle» class=»${baseClass}title» ></h3>
<div class=»${baseClass}description»>
<img class=»${baseClass}image» src=»» data-dojo-attach-point=»Nodemessageimage»>
<p data-dojo-attach-point=»Nodedescription» class=»alertdescription»>${description}</p>
<div class=»${baseClass}buttonpanel»>
<button data-dojo-type=»dijit.form.Button» data-dojo-attach-point=»buttonOk» label=»Ок» data-dojo-attach-event=»click:ok» ></button>
<button data-dojo-type=»dijit.form.Button» data-dojo-attach-point=»Cancel» label=»Відмінити» data-dojo-attach-event=»click: cancel»></button>
</div>
</div>
</div>

Данная конструкция может быть уже инициализирована и работать. Но без всякой функциональности.

Для примера я приведу следущий код, который заставит виджет показаться на экран =)
<!DOCTYPE HTML>
<html>
<head>
<meta charset=»utf-8″>
<title>Тег DIV</title>

<script type=»text/javascript» src=»js/dojo-release/dojo/dojo.js» djConfig=»parseOnLoad:true, isDebug:true»></script>
<link rel=»StyleSheet» type=»text/css» href=»/js/dojo-release/dijit/themes/claro/claro.css»>
<link rel=»StyleSheet» type=»text/css» href=»/js/dojo-release/mywidjet/css/systemAlert.css»>

</head>
<body class=»claro»>
<div data-dojo-type=»mywidjet/systemAlert» alertType=»question» description=»Тут написаное описание вопроса?»></div>
</body></html>
<script>
require([«dojo/parser»], function(parser){    parser.parse(); });</script>

И получаем картинку нашего уже полуработающего виджета.

2

И для того, чтобы показать еще второй способ вызвать виджет, опишу кусочек куда:

<script>
require([«mywidjet/systemAlert»],
function(systemAlert){
dojo.byId(«1234»).appendChild(new systemAlert({
‘alertType’ : ‘question’,
‘description’: «Тут написаное описание вопроса?»
}).domNode);
});
});
</script>

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

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

Пример кода функционала виджета:

templateString: template, // данная переменная является базовой она отвечает за привязку шаблона к виджету и расширяет параметры виджета, объявленными переменными в шаблоне.
Description: «»,  // переменная, которая отвечает на описание, которое будет находиться в виджете.
AlertType: «», // Отвечает за тип увидомления. Типы виджета описаны в функции PostCreate.
baseClass: «systemAlert», // базовый класс виджета для применения стиля
answer: null, // call-back функция для получения ответа от пользователя

ok: function() // функция, которая вызывается при нажатии на кнопку «OK»
{
if(typeof(this.answer) == «function») //call-back функция, которая отвечает за ответ пользователя.
this.answer(true);
},

cancel: function(){ // функция, которая вызывается при нажатии на кнопку «Відміна»
if(typeof(this.answer) == «function»)
this.answer(false);
},
constructor: function (args){ // базовая  функция. Являеться точкой начала создания виджета
if(args){
lang.mixin(this,args);
}
},

// базовая функция, которая выполняется после функции констракт и выводит инициализированый объект в HTML разметку.
postCreate: function() {
switch(this.alertType) // обращение к переменой в теле виджета.
{
case «informing»: {
this.Nodetitle.innerHTML = «Інформування»; // переменная, которая     подтягивается с шаблона виджета.
this.Nodemessageimage.src = require.toUrl(«./image/informing.png»);
domStyle.set(this._startupWidgets[1].domNode, «display», «none»); /* this._startupWidgets[1] this is button cancel*/
break;
}
case «error»: {
this.Nodetitle.innerHTML = «Помилка»;
this.Nodemessageimage.src = require.toUrl(«./image/error.png»);
domStyle.set(this._startupWidgets[1].domNode, «display», «none»); /* this._startupWidgets[1] this is button cancel*/
break;
}

case «success»: {
this.Nodetitle.innerHTML = «Успішно»;
this.Nodemessageimage.src = require.toUrl(«./image/success.png»);
domStyle.set(this._startupWidgets[1].domNode, «display», «none»); /* this._startupWidgets[1] this is button cancel*/
break;
}
case «question»: {
this.Nodetitle.innerHTML = «Видійсно хочете виконати данну операцію?»;
this.Nodemessageimage.src = require.toUrl(«./image/question.png»);
break;
}
case «warning»: {
this.Nodetitle.innerHTML = «Попередження»;
this.Nodemessageimage.src = require.toUrl(«./image/warning.png»);
domStyle.set(this._startupWidgets[1].domNode, «display», «none»); /* this._startupWidgets[1] this is button cancel*/
break;
}
default: break;

}
Данный пример направлен на поверхносное ознакомление с структурой работы dojo library и построение собсвенных виджетов и их работа.

Комменты

3 комментария

сначала новые
по рейтингу сначала новые по хронологии
1
Игорь Красман

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

2

Неужели сложно было код засунуть в code?!

3

Крутанская статья, но советую всю массу кода отформатировать, а то ведь совсем не читается, в оберните.

Новый комментарий

Такой e-mail уже зарегистрирован. Воспользуйтесь формой входа или введите другой.

Вы ввели некорректные логин или пароль

Извините, для комментирования необходимо войти.