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 и построение собсвенных виджетов и их работа.

Please wait...
0
3 Комментарий
Сначала Новые
Сначала Старые Популярные
guest

Межтекстовые Отзывы
Посмотреть все комментарии
Eugenius
Eugenius
9 лет назад

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

Please wait...
soulseekah
soulseekah
9 лет назад

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

Please wait...
Игорь Красман
Игорь Красман
9 лет назад

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

Please wait...
Наверх

Повідомити про помилку

Текст, який буде надіслано нашим редакторам: