Аргументы «функции в виде строк»

Библиотека Base предоставляет возможность передавать функциям forEach, map, filter, every и some сокращенные аргументы «функции в виде строк». Вообще такой подход выглядит проще, чем создание функцийоберток, и особенно удобен в действительно простых случа ях, когда выполняется быстрое преобразование. Суть заключается в том, что вместо целой функции вы передаете в виде строки только тело функции. Три ключевых слова имеют специальное значение при использовании в таких строках:

item

Представляет ссылку на текущий обрабатываемый элемент.
array

Представляет ссылку на весь обрабатываемый массив.
index

Представляет ссылку на индекс текущего обрабатываемого элемента.

Взгляните на следующий пример, где для достижения одного и того же результата используются два разных подхода:
var a = new Array(1,2,3,...);
//Вариант, требующий много ввода для достижения простой цели
a.forEach(function(x) {console.log(x);}); //первый подход
//Вариант, требующий меньшего объема ввода,
//поэтому вы выполните свою работу быстрее
a.forEach("console.log(item)"); //второй подход

Добавлено: 24 Июля 2018 08:28:33 Добавил: Андрей Ковальчук

Преобразование элементов

Функции map и filter имеют точно такую же сигнатуру, что и forEach, но они принципиально отличаются от последней тем, что, применяя некоторую логику к каждому элементу массива, они возвращают другой массив, оставляя оригинальный массив без изменений.

Программисты, использующие функциональные языки программирования (или даже языки программирования с функциональными расширениями, такие как Python), хорошо знают, что функции map и filter очень быстро приобретают высокую значимость, потому что они обеспечивают очень широкие возможности при таком кратком синтаксисе. Тем, кто не сталкивался с функцией map прежде, она может показаться загадочной. В действительности же ее имя говорит само за себя, потому что она создает отображение (mapping) массива, получаемое с помощью функции преобразования. Следующий пример иллюстрирует применение функции map:

var z = dojo.map([2,3,4], function(x) {
return x + 1
}); //вернет [3,4,5]

Для сравнения ниже приводится версия, которая создает аналогич
ный массив z, но без использования функции map:
var a = [2,3,4];
var z = [];
for (var i=0; i < a.length; i++) {
z.push(a[i] +1);
}


Одно из преимуществ использования функции map, как и функции forEach, заключается в более высокой выразительности программного кода, что в свою очередь упрощает его сопровождение. Кроме того, вы получаете те же преимущества от создания замыканий с помощью анонимных функций, когда использование переменных, полученных в результате промежуточных вычислений, при отказе от замыканий могло бы привести к загромождению контекста.

Имя функции filter тоже говорит само за себя, так как эта функция фильтрует массив согласно некоторому функциональному критерию. Ниже показано, как она используется:
dojo.filter([2,3,4], function(x) {
return x % 2 == 0
}); //вернет [2,4]


Реализация эквивалентного фрагмента программного кода не сложна, но требует большего внимания и дополнительных инструкций и, как следствие, увеличивает вероятность допустить опечатку или ошибку:
var a = [2,3,4];
var z = [];
for (var i=0; i < a.length; i++) {
if (a[i] % 2 == 0)
z.push(a[i]);
}


Как и в случае с другими функциями для работы с массивами, присутствующими в библиотеке Base, вы можете передавать функциям map и filter дополнительный параметр, определяющий контекст, если в этом есть необходимость:
function someContext() { this.y = 2; }
var context = new someContext;
dojo.filter([2,3,4], function(x) {return x % this.y==0}, context);
//вернет [2,4]

Добавлено: 24 Июля 2018 08:28:02 Добавил: Андрей Ковальчук

Обход элементов

Функция forEach передает каждый элемент массива функции, принимающей до трех параметров и не возвращающей никакого значения. Первый параметр – текущий элемент массива, обход которого выполняется, второй параметр (необязательный) – индекс текущего элемента массива и третий параметр – сам массив. Вообще функция forEachиспользуется для обхода всех элементов массива, как если бы это был обычный цикл for. Ниже приводится сигнатура этой функции:
dojo.forEach(/*Array*/ array, /*Function*/ function) // Не возвращает ничего

В простейшем случае функция forEach применяется, как показано ниже:

dojo.forEach([1,2,3], function(x) {
console.log(x);
});


Функция forEach обладает следующими очевидными преимуществами: она меньше загромождает программный код, чем цикл for, для работы которого необходимо еще предусмотреть переменную цикла, и, кроме того, позволяет использовать литералы массивов. Однако самое важное преимущество состоит в том, что на основе функции, определяемой вторым параметром, она позволяет реализовать замыкания, защищая тем самым свой контекст от влияния переменной цикла и любых других переменных, которые могут использоваться в теле цикла. Как и другие вспомогательные функции, forEach способна принимать дополнительный параметр, определяющий контекст для встроенной функции.

Чтобы продемонстрировать, как функция forEach может обезопасить вас от неожиданностей, рассмотрим следующий фрагмент программ ного кода:
var nodes = getSomeNodes();
for(var x=0; x<nodes.length; x++){
nodes[x].onclick = function(){
console.debug("clicked:", x);
}
}


Как вы думаете, какое значение переменной x будет здесь полученоПоскольку замыкание выполняется по лексической переменной x, а не по ее значению, во все вызовы функции будет передано последнее значение. Функция forEach предохраняет нас от такого поведения, создавая новую лексическую область видимости. Следующая версия программного кода демонстрирует, как выполнить обход массива и вывести ожидаемое значение:
var nodes = getSomeNodes();
var idx = 0;
dojo.forEach(nodes, function(node, idx){
node.onclick = function(){
console.debug("clicked:", idx);
}
});

Добавлено: 24 Июля 2018 08:27:27 Добавил: Андрей Ковальчук

Проверка элементов на соответствие условию

Очень часто бывает необходимо определить, соответствуют ли все элементы массива некоторому условию или существуют ли в массиве элементы, соответствующие некоторому условию. Для выполнения такого рода проверок библиотека Base предоставляет функции every и some.

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

dojo.every([2,4,6], function (x) { return x % 2 == 0 }); //true
dojo.every([2,4,6,7], function (x) { return x % 2 == 0 }); //false
dojo.some([3,5,7], function f(x) { return x % 2 == 0 }); //false
dojo.some([3,5,7,8], function f(x) { return x % 2 == 0 }); //true

Добавлено: 24 Июля 2018 08:27:00 Добавил: Андрей Ковальчук

Поиск местоположения элементов

Две самые распространенные операции при работе с массивами включают в себя определение индекса элемента, причем обе они, по сути, проверяют наличие элемента в массиве. Библиотека Base упрощает поиск двумя функциями с говорящими именами: dojo.indexOf и dojo.lastIndexOf. Каждая из этих функций возвращает целое число, представляющее собой индекс элемента в массиве, если он существует. Если заданный элемент в массиве отсутствует, функции возвращают значение -1. В сигнатурах этих функций имеется дополнительный параметр, определяющий начальный или конечный индекс, откуда следует начинать поиск. Обе функции имеют одинаковые сигнатуры:

dojo.indexOf(/*Array*/ array, /*Any*/ value, /*Integer?*/ fromIndex)
//возвращает Integer
dojo.lastIndexOf(/*Array*/ array, /*Any*/ value, /*Integer?*/ fromIndex)
//возвращает Integer


Следующий фрагмент программного кода иллюстрирует некоторые основные приемы использования этих методов:
var foo = [1,2,3];
var bar = [4,5,6,5,6];
var baz = [1,2,3];
dojo.indexOf([foo, bar], baz); // -1
dojo.indexOf(foo, 3); // 2
dojo.indexOf(bar, 6, 2); // 2
dojo.indexOf(bar, 6, 3); // 4
dojo.lastIndexOf(bar, 6); // 4


Кроме того, следует отметить, что эти методы выполняют поверхностное сравнение. Для таких сложных структур данных, как Array, это означает, что сравниваются ссылки на объекты. Следующий фрагмент поясняет это утверждение на конкретном примере:
bop = [4,5,6,5,6, foo]; // bop содержит вложенный массив
dojo.indexOf(bop, foo); //5, потому что (ссылка на) foo содержится в bop
dojo.indexOf(bop, [1,2,3]); //-1, потому что foo - это не тот же самый объект
//что и [1,2,3]

Добавлено: 24 Июля 2018 08:26:36 Добавил: Андрей Ковальчук

Утилиты для работы со строками

Усечение начальных и завершающих пробельных символов в строках является чрезвычайно часто используемой операцией. В следующий раз, когда вам потребуется выполнить эту операцию, вместо того, что бы создавать свою функцию, воспользуйтесь функцией trim из библиотеки Base.

Ниже приводится пример использования функции trim:

var s = " this is a value with whitespace padding each side ";
s = dojo.trim(s); //"this is a value with whitespace padding each side"


В состав модуля string библиотеки Core входят еще несколько функций для работы со строками. Каждый из следующих примеров предполагает, что загрузка модуля dojo.string уже была выполнена с помощью инструкции dojo.require.
dojo.string.pad


Дополняет строку, гарантируя, что ее длина будет точно соответствовать указанному числу символов. По умолчанию дополнение производится слева. С помощью дополнительного параметра можно организовать дополнение справа:
dojo.string.pad("", 5); // "00000"
dojo.string.pad("", 5, " "); // " "
dojo.string.pad("0", 5, "1"); // "11110"
dojo.string.pad("0", 5, "1", true); // "01111"
dojo.string.substitute


Выполняет замену параметров в строке и при необходимости позволяет указывать функцию преобразования и/или другой объект, являющийся источником информации:
//Вернет "Jack and Jill went up a hill."
dojo.string.substitute("${0} and ${1} went up a hill.", ["Jack", "Jill"]);
//Вернет "Jack and Jill went up a hill."
dojo.string.substitute("${person1} and ${person2} went up a hill.",
{person1 :
"Jack", person2: "Jill"});
//Вернет "*Jack* and *Jill* went up a hill."
dojo.string.substitute("${0} and ${1} went up a hill.", ["Jack", "Jill"],
function(x) {
return "*"+x+"*";
});
dojo.string.trim


За счет несколько большего размера по сравнению с реализацией одноименной функции в библиотеке Base, функция из модуля string библиотеки Core обеспечивает немного более высокую производительность и может использоваться в случаях, когда быстродействие имеет большое значение:
dojo.string.trim( /* строковое значение */);

Добавлено: 24 Июля 2018 08:25:59 Добавил: Андрей Ковальчук

Определение типа

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

isString(/*Any*/ value)

Возвращает true, если значение имеет тип String.
isArray(/*Any*/ value)

Возвращает true, если значение имеет тип Array.
isFunction(/*Any*/ value)

Возвращает true, если значение имеет тип Function.
isObject(/*Any*/ value)

Возвращает true, если значение имеет тип Object (включая Array
и Function) или null.
isArrayLike(/*Any*/ value)


Возвращает true, если значение имеет тип Array, но при этом относит к массивам некоторые другие типы. Например, встроенное свойство arguments, к которому можно обращаться внутри объекта Function, принадлежит одному из таких типов. Этот тип не поддерживает встроенные методы, такие как push, однако он напоминает массив в том смысле, что представляет список значений, к которым можно обращаться через индексы.
isAlien(/*Any*/ value)

Возвращает true, если значение является встроенной функцией или «родной» функцией таких компонентов, как ActiveX, но не опознается таким методом, как применение функции instanceof.

Добавлено: 24 Июля 2018 08:24:30 Добавил: Андрей Ковальчук

Поиск узлов DOM

В предыдущей главе была представлена функция dojo.byId – специализированный механизм поиска узлов DOM более переносимым и предсказуемым способом, чем метод document.getElementById. Функция dojo.byId является самой часто используемой функцией при разработке с использованием Dojo, поэтому есть смысл еще раз вернуться к дискуссии из главы 1, где были обозначены некоторые проблемы функции document.getElementById и говорилось о том, как dojo.byId помогает их решать. В качестве напоминания ниже приводится полная сигнатура функции dojo.byId:

dojo.byId(/*String*/ id | /*DomNode*/ node, /*DomNode*/doc) // Возвращает// узел DOM

В примере 2.1 приводится ряд других типичных случаев использования этой функции.

Пример 2.1. Краткое напоминание о функции dojo.byId
var foo = dojo.byId("foo"); //вернет узел с id=foo, если он существует
dojo.byId(foo).innerHTML="bar"; //поиск не выполняется, так как foo –
//это узел; затем в свойство innerHTML
//записывается значение "bar"
var bar = dojo.byId("bar", baz); //вернет узел с id=bar в документе, на
//который ссылается baz, если он существует

Добавлено: 24 Июля 2018 08:23:47 Добавил: Андрей Ковальчук

Исследование Dijit

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

Пример 1.4. Пример примитивной формы

<html>
<head>
<title>Fun with Dijit!</title>
</head>
(body)
Just Use the form below to sign-up for our great offers:(br /)(br /)
<form id="registration_form">
First Name: <input type="text" maxlength=25 name="first"/>(br /)
Last Name: <input type="text" maxlength=25 name="last"/>(br /)
Your Email: <input type="text" maxlength=25 name="email"/>
(br /)(br /)
(button onclick="alert('Boo!')")Sign Up!(/button)
</form>
(/body)
</html>


Возможно, в 92 году такая форма вполне сгодилась бы, но она совершенно неприемлема для наших дней. Остановимся на минутку и посмотрим, что вы обычно делаете в таких случаях: определяете несколько классов, применяете классы, пишете программный код JavaScript с целью обеспечить проверку правильности вводимых данных и т. д.

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

Пример 1.5. Форма, которая (благодаря Dojo) перестала быть примитивной
<html>
<head>
<title>Fun with Dijit!</title>
<!-- Некоторые стили взяты из встроенной темы tundra, которая предлагается инструментальным набором Dojo для стилизации страниц, что дает вам возможность использовать профессиональный стиль без приложения дополнительных усилий. -->
<link rel="stylesheet" type="text/css"
href="http://o.aolcdn.com/dojo/1.1/dijit/themes/tundra/tundra.css" />
<link rel="stylesheet" type="text/css"
href="http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css" />
<!-- Дополнительные стили CSS для выравнивания элементов формы -->
<style type="text/css">
h3 {
margin : 10px;
}
label,input {
display: block;
float: left;
margin-bottom: 5px;
}
label {
text-align: right;
width: 70px;
padding-right: 20px;
}
br {
clear: left;
}
.grouping {
width:300px;
border:solid 1px rgb(230,230,230);
padding:5px;
margin:10px;
}
</style>
<!-- Загрузить Base и указать, что после загрузки страницы требуется
выполнить парсинг диджитов -->
<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
djConfig="parseOnLoad: true" >
</script>
<!-- Загрузить некоторые диджиты с помощью dojo.require так же, как если бы вы подключали с помощью директивы #include файлы в языке C или выполняли импортирование модулей в языке Java -->
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.form.Button");
</script>
</head>
<!-- Указать, что встроенная тема tundra должна применяться ко всему, что находится в теле страницы. (Библиотека Dijit в значительной степени опирается на CSS, поэтому включение соответствующей темы имеет очень важное значение.)-->
(body class="tundra")
<h3>Sign-up for our great offers:</h3>
<form id="registration_form">
<!-- Мы внедрили несколько виджетов в страницу, вставив теги и включив в них атрибут dojoType, чтобы парсер мог обнаружить и загрузить их -->
<div class="grouping">
<label>First Name:</label>
<input type="text"
maxlength=25
name="first"
dojoType="dijit.form.TextBox"
trim="true"
propercase="true"/>(br)
<label>Last Name:</label>
<input type="text"
maxlength=25
name="last"
dojoType="dijit.form.TextBox"
trim="true"
propercase="true"/>(br)
<label>Your Email:</label>
<input type="text"
maxlength=25
name="email"
dojoType="dijit.form.ValidationTextBox"
trim="true"
lowercase="true"
regExp="[a-z0-9._%+-]+@[a-z0-9-]+\.[a-z]{2,4}"
required="true"
invalidMessage="Please enter a valid e-mail address"/>(br)
(button dojoType="dijit.form.Button"
onClick="alert('Boo!')")Sign Up!(/button)
</div>
</form>
(/body)
</html>

Добавлено: 24 Июля 2018 08:23:15 Добавил: Андрей Ковальчук

dojo.connect

Получение ссылки на узел дерева DOM, несомненно, ничем не интерес но, поэтому давайте рассмотрим чтонибудь более интересное, например подключение события пользовательского интерфейса, такого как перемещение указателя мыши, к узлу с помощью функции dojo.con-
nect – механизма инструментального набора для динамического добавления и удаления этих типов событий. Сигнатура функции может показаться сложной на первый взгляд, но функцией в действительности совсем просто пользоваться. Взгляните:

connect(/*Object|null*/ obj,
/*String*/ event,
/*Object|null*/ context,
/*String|Function*/ method) // Возвращает дескриптор соединения


Чтобы опробовать действие функции connect, выполните приведенный далее программный код в консоли Firebug, а затем переместите указатель мыши на текст предложения, содержащегося в теге SPAN, чтобы убедиться, что обработка события mouseover настроена должным образом. (Возможно, вам придется щелкнуть на ярлыке с крышечкой в правом нижнем углу, чтобы переключить командную строку в многострочный режим ввода.)
var handle = dojo.connect(
dojo.byId("s1"), //контекст
"onmouseover", //событие
null, //контекст
function(evt) {console.log("mouseover event", evt);} //обработчик события
);


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

Как оказывается, функция dojo.connect, как и dojo.byId, проверяет многие вещи, для того чтобы работа с ней была проще, чем это могло сначала показаться. Фактически любые аргументы, которые допускают значение null, вообще могут быть опущены. Вследствие этого предыдущий фрагмент можно переписать, как показано ниже, сделав его немного более удобочитаемым:
var handle = dojo.connect(
dojo.byId("s1"), //контекст
"onmouseover", //событие
function(evt) {console.log("mouseover event",evt);} //обработчик события
);


Операция отключения функции, предназначенной для обработки события DOM, выполняется еще проще, и она имеет большое значение для предотвращения утечек памяти, если в странице приходится делать большое число подключений и отключений. Для этого достаточно вызвать функцию dojo.disconnect, передав ей дескриптор соединения, который был сохранен ранее, а инструментарий Dojo сам позаботится обо всем остальном:
dojo.disconnect(handle);


Несмотря на всю простоту примера, функция dojo.connect демонстрирует ключевой принцип философии Dojo: перемещение из пункта A в пункт B всегда должно быть максимально простым. Уверен, если вы близко знакомы с языком JavaScript, вы могли бы и сами пройти все этапы установки, поддержания и отсоединения обработчика события. Однако при этом вам пришлось бы использовать шаблон, загромождающий программный код, и давайте не будем забывать: каждую строку программного кода, которую вы напишете, вам же и придется сопровождать. Опытные вебразработчики, которых немало и среди нас, предпочитающие не усложнять задачу, оценят преимущества использования функций dojo.connect и dojo.disconnect.

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

Другой интересной особенностью, которая демонстрирует огромную мощь, заключенную в маленьком пакете, является функция dojo.que-ry – механизм, позволяющий быстро выполнять запросы к странице с использованием синтаксиса CSS3.

Например, поиск всех элементов DIV в странице выполняется очень просто, как показано ниже:
dojo.query("div") //отыскивает все элементы div в дереве DOM


Если вы попробуете выполнить эту инструкцию в консоли Firebug, то вы увидите, что она действительно возвращает список элементов DIV. Поиск конкретного элемента DIV с определенным именем также выполняется очень просто:
dojo.query("div#d2") //проверяет наличие элемента div с атрибутом id=d2


А вот так выполняется поиск элементов определенного класса:
dojo.query(".blue") //возвращает список элементов с классом blue.


Заговорив о классах, следует заметить, что существует возможность отбирать элементы определенного типа, но, так как в нашем документе класс CSS применяется только к одному элементу DIV, нам необходимо применить класс blue еще к какомунибудь элементу. Но, вместо того чтобы редактировать страницу HTML, почему бы не воспользоваться еще одной встроенной функцией из библиотеки Base – dojo.addClass, чтобы применить класс к выбранному элементу, как показано ниже:
dojo.addClass("s1", "blue"); //добавляет класс blue в элемент SPAN


После применения класса blue к элементу s1, можно продемонстрировать другой вариант запроса с помощью функции dojo.query:
dojo.query("span.blue") //возвращает только элементы span с классом blue


Уловили суть? Уверен, вы смогли бы реализовать все это с использованием своих собственных обходных приемов, но разве не проще знать, что инструментальный набор изолирует вас от всего этой чехарды и вместо этого предоставляет единственную и простую в использовании функцию?

Добавлено: 24 Июля 2018 08:22:32 Добавил: Андрей Ковальчук

dojo.byId

В наборе инструментальных средств Dojo имеется функция dojo.byId, которая служит заменой методу document.getElementById. То есть, если передать функции строковое значение, например, dojo.byId("s1"), она вернет ссылку, которую можно было бы сохранить в переменной, как и в случае использования метода document.getElementById. Однако, кроме того, что она отыскивает элемент по значению атрибута id, функция dojo.byId может также играть роль пустой операции, если ей передать ссылку на узел дерева DOM. Функция анализирует полученный аргумент, поэтому при разработке приложения вам даже не придется вспоминать, как она действует. Полная сигнатура этой функции выглядит, как показано ниже:

dojo.byId(/*String*/ id | /*DomNode*/ node) // Возвращает ссылку на узел DOM


Может показаться, что функция dojo.byId выполняет те же действия, что и метод document.getElementById, и у вас вполне может возникнуть желание просто забыть о dojo.byId, но не торопитесь! Как оказывается, эта функция устраняет некоторые несовместимости между броузера ми, которые могут приводить к появлению ошибок, когда вы меньше всего ожидаете этого. Одна из хорошо известных ошибок, связанных с применением метода document.getElementById, проявляется в IE6 и IE7.

Для демонстрации сказанного введите следующую строку в консоли Firebug Lite после открытия документа с последним представленным
примером:
document.getElementById("foo") // Разве результат не очевиден?!?


Хмм. Вероятно, вы не ожидали, что в качестве результата получите элемент FORM, не так ли? Оказывается, если бы этот элемент не стоял первым в документе, в качестве результата вы получили бы элемент div. Эта специфическая ошибка возникает изза того, что в IE атрибуты name и id расцениваются как одно и то же. Поэтому так важно помнить о совместимости броузеров даже в самых обычных вещах!

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

Кроме того что dojo.byId ликвидирует конкретную несовместимость между броузерами, она также возвращает первый элемент, если в документе имеется несколько элементов с одинаковым значением атрибута id, тем самым нормализуя неоднозначность выбора. Убедиться в том, что dojo.byId всегда возвращает первый встретившийся элемент, можно, попробовав применить к нашему документу следующую инструкцию:
dojo.byId("d2").innerHTML


Самый главный вывод из этого короткого урока заключается в том, что если в разработке вы применяете инструментальный набор JavaScript, – используйте его прикладной интерфейс, вместо того чтобы искать обходные пути на простом JavaScript. Иногда вам могут встречаться вызовы API, которые на первый взгляд не несут никаких дополнительных преимуществ, и может появиться искушение вернуться к старым, испытанным способам, но не поддавайтесь искушению! Хорошо продуманный прикладной интерфейс не содержит бесполезных функций.

Добавлено: 24 Июля 2018 08:21:27 Добавил: Андрей Ковальчук

Исследование библиотеки Base

Для иллюстрации сначала сохраним страницу HTML, представленную в примере 1.3, в локальном файле. Единственный нюанс в этом сценарии заключен в теге, выполняющем загрузку версии XDomain. Мы еще не рассматривали массив djConfig, определение которого присутствует в теге SCRIPT, однако это всего лишь способ передачи конфигурационной информации в Dojo на этапе самонастройки. В данном случае мы явно указываем, что средства отладки, такие как консоль Firebug, должны быть доступны для нас. Даже если вы используете другой броузер, такой как IE, параметр djConfig="isDebug:true" обеспечит загрузку Firebird Lite.
Пример 1.3. Очень простая страница HTML для демонстрации
некоторых особенностей библиотеки Base

<html>
<head>
<title>Fun with Dojo!</title>
<link rel="stylesheet" type="text/css"
href="http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css" />
<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
djConfig="isDebug:true">
</script>
<style type="text/css">
.blue {color: blue;}
</style>
</head>
(body)
<div id="d1" class="blue">A div with id=d1 and class=blue</div>
<div id="d2">A div with id=d2</div>
<div id="d2">Another div with id=d2</div>
<div id="d4">A div with id=d4.
<span id="s1">
This sentence is in a span that's contained in d4.
The span's id is s1.
</span>
</div>
<form name="foo" action="">
A form with name="foo"
</form>
<div id="foo">
A div with id=foo
</div>
(/body)
</html>


Сохранив страницу в файле, откройте его в Firefox и щелкните на маленьком зеленом кружочке с галочкой в нем, чтобы открыть консоль Firebug. Затем щелкните на ярлыке с изображением крышечки, рядом с полем ввода для поиска, чтобы открыть Firebug в новом окне. (Если вы еще не прочитали учебное руководство по Firebug в приложении A, тогда самое время, чтобы сделать это прямо сейчас.) Щелкнув на вкладке «Net» (Сеть), вы сможете убедиться, что файл dojo.xd.js, содержащий библиотеку Base версии XDomain, действительно был загружен с сайта CDN.

Если теперь опять щелкнуть на вкладке «Console» (Консоль), ввести dojo в строке приглашения к вводу >>> и нажать клавишу Enter, вы должны увидеть в консоли Firebug сообщение примерно с таким текстом: Object _scopeName=dojo _scopeMap=Object, который говорит о том, что глобальный объект dojo действительно жив и здоров. Введя команду console.dir(dojo), вы получите исчерпывающий древовидный список всего, что содержится в Dojo. В этом списке вы увидите большое количество внутренних элементов, имена которых начинаются с символа подчеркивания, но пусть это вас не останавливает. Просмотрите весь список, это позволит вам получить некоторое представление о том, что находится в библиотеке Base.

Добавлено: 24 Июля 2018 08:20:45 Добавил: Андрей Ковальчук

Настройка с помощью djConfig

Чаще всего определение массива djConfig находится в том же теге SCRIPT, где выполняется загрузка инструментального набора, как показано в примере ниже:

<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
djConfig="parseOnLoad:true,isDebug:true">
</script>


Однако при желании, например, когда необходимо указать большое число параметров или такой способ просто удобнее для вас в данной конкретной ситуации, массив можно определить в другом теге SCRIPT, предшествующем тегу, выполняющему загрузку инструментария. Ниже приводится переделанный программный код предыдущего примера, который имеет тот же эффект:
<script type="text/javascript">
djConfig = {
parseOnLoad : true,
isDebug : true
};
</script>
<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js ">
</script>

Добавлено: 24 Июля 2018 08:19:00 Добавил: Андрей Ковальчук

Обзор архитектуры Dojo

Как вы увидите дальше, использование термина инструментальный набор применительно к Dojo далеко не случайно. В дополнение к тому, что он содержит своего рода стандартную библиотеку языка Java Script, в состав Dojo также входят: коллекция готовых к употреблению графических компонентов (виджетов), для использования которых если и требуется писать программный код, то только минимального объема; инструменты сборки; платформа тестирования и многое другое. В этом разделе вашему вниманию предлагается обзор архитек туры Dojo с общих позиций. Как вы убедитесь в этом позднее, организация остальной части книги в значительной степени определяется архитектурой нструментария. Хотя библиотека DojoX представлена отдельно от Dijit, тем не менее ресурсы DojoX можно построить на основе ресурсов Dijit, так же как вы можете создавать свои собственные виджеты на любых комбинациях ресурсов из Dijit и DojoX.

Base
Ядром Dojo является Base – чрезвычайно компактная, высоко оптимизированная библиотека, образующая основу для всего остального инструментария. Кроме всего прочего библиотека Base содержит удобные языковые конструкции и утилиты AJAX, систему пакетов, позволяющую добавлять ресурсы из Dojo прямо во время выполнения, а не во время загрузки страницы. Эта библиотека также предоставляет инструменты для создания и управления иерархиями наследования, средства для выполнения практически универсальных запросов к дереву DOM с использованием селекторов CSS3 и конструкцию, нормализующую модели событий DOM, имеющиеся в разных броузерах. Все, что находится в библиотеке Base, доступно как функции или атрибуты пространства имен верхнего уровня dojo.*. Библиотека Base представлена единственным файлом dojo.js, который при передаче по сети занимает порядка 30 Кбайт. Если вы задумаетесь над тем, что раз мер большинства рекламных Flashроликов, наводнивших Всемирную паутину, составляет значительно больше 30 Кбайт, то это число покажется вам удивительно маленьким.

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

Библиотека Base предоставляет великое множество вспомогательных функций для реализации многих стандартных операций, которые часто бывает необходимо выполнить для достижения поставленных целей. Даже если вы ничего больше не будете использовать из набора инструментальных средств, библиотека Base наверняка станет для вас ценным ресурсом, от которого уже не захочется отказаться, стоит только почувствовать, как она позволяет повысить производитель ность труда. Без библиотеки Base не будет и Dojo – все, что имеется в комплекте инструментальных средств Dojo, так или иначе, зависит или построено на основе этой библиотеки.

Core
Библиотека Core основана на библиотеке Base и предлагает дополнительные средства для парсинга виджетов, улучшенные анимационные эффекты, средства реализации механизма «перетащил и бросил», интернационализации (i18n), обработки кнопки «Назад», управления cookie и многого другого. Ресурсы, доступные в Core, используются довольно часто и обеспечивают фундаментальную поддержку для выполнения наиболее распространенных операций, но они не считаются достаточно универсальными, чтобы включить их в состав библиотеки Base. Хотя критерии внесения ресурсов в состав библиотеки Core можно считать несовершенными, но система управления пакетами в инструментальном наборе Dojo упрощает подключение дополнительных модулей и ресурсов по мере необходимости с помощью простого механизма, который работает на манер директивы #include из языка C или инструкции import из языка Java.

Вообще, различия между Base и Core определяются просто: если явно импортируемый ресурс, внешний по отношению к dojo.js, принадлежит к пространству имен dojo, значит, он является частью библиотеки Core. Обычно средства из библиотеки Core не входят непосредственно в пространство имен библиотеки Base, а составляют пространства имен более низкого уровня, такие как dojo.fx или dojo.data.

Dijit
Сказать, что Dojo – это всего лишь стандартная библиотека языка JavaScript, значит ничего не сказать. Кроме всего прочего в состав инструментального набора Dojo входит Dijit (сокращенно от «Dojo widget») – фантастическая библиотека виджетов, готовых к использованию, для работы с которыми часто вообще не требуется писать программный код JavaScript. Диджиты соответствуют общепринятым стандартам доступности, таким как ARIA1, и поставляются с предварительными интернациональными настройками для большинства распространенных языковых настроек. Библиотека Dijit построена непосредственно на базе Core (и тем самым полностью зависит от целостности Core), по этому, когда вам потребуется создать свой собственный виджет, вы будете использовать те же самые стандартные блоки, которые использовались для всего, что имеется в Dijit. Виджеты, которые создаются средствами Dojo, обладают высокой степенью переносимости и легко могут разворачиваться на любом вебсервере или даже запускаться локально, вообще без участия вебсервера, с помощью протокола file://.

Включение диджитов в вебстраницу выполняется простым определением специального атрибута dojoType внутри обычного тега HTML – во плотившаяся в реальность мечта дизайнеров и пользователей, которых мало интересует (если вообще интересует) программирование на языке JavaScript. Основное преимущество от использования библиотеки Dijit состоит в том, что она фактически позволяет получать богатые функциональные возможности без необходимости погружаться в детали реализации. Даже если вы занимаетесь созданием библиотек или разработкой собственных виджетов, следование стилю и соглашениям, принятым в Dijit, обеспечит вашим виджетам высокую переносимость и простоту в использовании, составляющим основу любого программного компонента многократного использования.

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

DojoX
DojoX – это коллекция проектов, название которой происходит от «Dojo Extensions» (расширения для Dojo), хотя ее часто называют «Extensions and Experimental» (расширения и экспериментальные реализации). Проекты «расширений» в DojoX – это стабильные виджеты и ресурсы, которые представляют собой ценные дополнения, назначение которых просто не соответствует тому, чтобы поместить их в библиотеку Core или в библиотеку Dijit. К «экспериментальным» проектам относят виджеты, которые подвержены частым изменениям и находятся на начальной стадии разработки.

В составе каждого проекта, входящего в коллекцию DojoX, должен присутствовать файл README, где описывается состояние проекта. Проекты в DojoX обычно стремятся соответствовать инициативам по интернационализации и обеспечению доступности совместимым с Dijit способом, но вообще это редкий случай, когда такое соответствие находится на достаточно высоком уровне. Как бы то ни было, реализация значительного числа механизмов, используемых в действующих приложениях, находится именно в коллекции DojoX, включая виджет табличного представления данных, процедуры преобразования данных для наиболее типичных разновидностей вебслужб и т. д. Кроме того, в состав коллекции DojoX входят испытательный полигон и инкубатор для новых идей, что гарантирует отсутствие угрозы стандартному и стабильному прикладному интерфейсу ресурсов в Core и Dijit.

В этом смысле DojoX обеспечивает тонкий баланс в решении критических проблем, занимающих центральное место в любом проекте, под держиваемом сообществом.

Util
Util – это коллекция вспомогательных инструментов Dojo, включая платформу модульного тестирования и инструменты сборки, позволяющие создавать свои версии библиотеки инструментальных средств Dojo для собственных нужд. Платформа модульного тестирования, DOH1, не имеет прямого отношения к Dojo и представляет собой простой набор конструкций, которые могут использоваться для автоматизации проверки качества любого программного кода JavaScript. В конце концов, вы ведь хотите реализовать четкое и систематическое тестирование своего программного кода JavaScript, разве не так? Основное назначение инструментов сборки состоит в том, чтобы сократить размер вашего программного кода и объединить его в несколько слоев, где каждый слой не что иное, как набор других файлов JavaScript. Сжатие производится посредством инструмента ShrinkSafe – адаптированной проектом Mozilla версии механизма из Rhino JavaScript, который сжимает программный код JavaScript, не повреждая общедоступный программный интерфейс, а объединение выполняется с помощью коллекции сценариев, которые также были разработаны для Rhino. Другие вспомогательные компоненты в библиотеке Util вы полняют такие операции, как встраивание строк шаблонов HTML в файлы JavaScript – еще один прием, позволяющий уменьшить задержки.

Подобно DOH механизм ShrinkSafe может применяться независимо от Dojo, и нет никаких причин, чтобы не использовать его при подготовке рабочей версии программного кода JavaScript, особенно если учесть, что он позволяет сократить объем кода JavaScript до 50% и больше.

Разница во времени между загрузкой множества крупных файлов JavaScript посредством серии синхронных запросов и получением одного или двух сжатых файлов JavaScript может оказаться весьма существенной.

Добавлено: 24 Июля 2018 08:06:02 Добавил: Андрей Ковальчук

Примеры применения функций XHR

Как минимум, в числе аргументов для выполнения запросов XHR должны быть определены адрес URL и функция load. Однако обычно, и это очень правильно, в число аргументов включается еще и обработчик ошибок – не опускайте его, если вы действительно не уверены, что можете обойтись без него. Например:

//...обрезано...
dojo.addOnLoad(function() {
dojo.xhrGet({
url : "someText.html", //относительный URL
// Вызвать эту функцию в случае успеха
load : function(response, ioArgs) {
console.log("successful xhrGet", response, ioArgs);
//Заполнить некоторый элемент содержимым...
dojo.byId("foo").innerHTML= response;
return response; //всегда возвращайте аргумент response
},
// Вызвать эту функцию в случае неудачи
error : function(response, ioArgs) {
console.log("failed xhrGet", response, ioArgs);
/* обработка ошибки... */
return response; //всегда возвращайте аргумент response
}
});
});
//...обрезано...


Совсем необязательно, что вам всегда будет нужен текст в качестве ответа. Иногда может появиться потребность ограничить время ожидания ответа или передать дополнительную информацию в виде строки запроса. К счастью, это не сильно усложнит вашу жизнь. Просто добавьте несколько параметров, как показано ниже:
dojo.xhrGet({
url : "someJSON.html", //Нечто такое: {’bar’:’baz’}
handleAs : "json", //Преобразовать в объект JavaScript
timeout: 5000, //Вызвать обработчик ошибок через 5 секунд,
//если за это время ответ не будет получен
content: {foo:’bar’}, //Добавить foo=bar в строку запроса
// Вызвать эту функцию в случае успеха
load : function(response, ioArgs) {
console.log("successful xhrGet", request, ioArgs);
console.log(response);
//Значение свойства handleAs предписывает Dojo
//преобразовать данные в объект
dojo.byId("foo").innerHTML= response.bar;
//Отобразит обновленные данные, например 'baz'
return response; //всегда возвращайте аргумент response
},
// Вызвать эту функцию в случае неудачи
error : function(response, ioArgs) {
console.log("failed xhrGet");
return response; //всегда возвращайте аргумент response
}
});


Обратите внимание, что отсутствие правильного определения значения для свойства handleAs может приводить к появлению ошибок, поиск которых может оказаться непростым делом. Например, если случайно забыть определить параметр handleAs и попытаться в функции load обратиться к значению ответа как к объекту JavaScript, вы наверняка получите ошибку, которая может увести вас далеко, прежде чем вы заметите, что пытаетесь интерпретировать значение типа String как значение типа Object, потому что в тексте сообщения об ошибке значения строк и объектов могут выглядеть практически идентично.

В большинстве приложений выполняются запросы GET, однако у вас могут сложиться обстоятельства, обязывающие использовать запрос типа PUT, POST или DELETE. Процедура выполнения таких запросов остается прежней, только при этом необходимо включить требуемые данные в свойство putData или postData и вызвать функцию rawXhrPut или rawXhrPost, соответственно, как средство передачи данных серверу. Ниже приводится пример использования функции rawXhrPost:
dojo.rawXhrPost({
url : "/place/to/post/some/raw/data",
postData : "{foo : 'bar'}", //литерал JSON
handleAs : "json",
load : function(response, ioArgs) {
/* Здесь выполняются всякие интересные действия */
return response;
},
error : function(response, ioArgs) {
/* Получше обрабатывайте ошибки */
return response;
}
});

Добавлено: 17 Июля 2018 20:02:47 Добавил: Андрей Ковальчук