Наверх
Это запись из блога автора Владимир Назаренко
Мнение редакции сайта Keddr.com может не совпадать с мнением данной публикации.
Читать правила написания блогов
3 комментария 04/01/2015

Dojo и построение интерфейсов

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

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

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

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

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

2

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

3

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

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

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

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

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

Modal box

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: