Можливо, багато хто вже читали статті з серії jQuery для початківців, так ось з деяких пір мене зацікавив ще один JavaScript фреймворк, і зветься він Dojo Toolkit.

У цій статті я постараюся описати базові можливості Dojo, так само буду проводити паралелі з jQuery, так що не лякайтеся виникло дежавю…

Як я вже колись казав – краще вчитися на прикладах, так що приступимо…

Підключення

Ну, для початку Вам знадобиться сам фреймворк, його ви зможете завантажити з домашньої сторінки проекту, потім підключаємо його одним з наступних способів:

Використовуючи локальний файл:

Дана запис аналогічна попередньої:

var djConfig = {
isDebug:true,
parseOnLoad:true
};

Dojo так само доступний на наступних машин:

Селектори

Перейдемо до пошуку елементів, для цієї мети є наступні функції:

// найпростіший варіант – отримати елемент за його Id
var element = dojo.byId(‘elementId’);
// так само можемо виділити кілька елементів, використовуючи селектори з CSS3, – повертається об’єкт NodeList
var elements = dojo.query(‘.elementsClass’)

Список підтримуваних CSS селекторів можна знайти у документації функції dojo.query (docs.dojocampus.org).

Події

Для роботи з подіями в Dojo використовуються функції dojo.connect і dojo.disconnect – для додавання і видалення обробників відповідно, наведу простий приклад:

// якась функція
function update() {
console.log(‘click!’);
}
// і певний елемент
var obj = dojo.byId(‘someId’);
// вішаємо обробник
var link = dojo.connect(obj, “onclick”, null, “update”);
// або
dojo.connect(obj, “onclick”, “update”);
// або використовуючи анонімну функцію
dojo.connect(obj, “onclick”, function update() { console.log(‘click!’); });
// прибираємо наш обробник
dojo.disconnect(link);

Функція connect так само підтримується NodeList’ом:

// переробимо трохи попередній приклад
dojo.query(‘.someClass’).connect(“onclick”, function update() { console.log(‘click!’); });

Примітка: dojo однаково розуміє події click і onclick

Прості приклади

Тепер перейдемо безпосередньо до роботи, почнемо з події, яка сповістить нас про завершення будівництва DOM’а:

// створюємо функцію init і вызваем її за події OnLoad
var init = function(){
console.log(“DOM побудований…”);
};
dojo.addOnLoad(init);
// та/або використовуємо анонімну функцію
dojo.addOnLoad(function(){
console.log(“…спасибі”);
});

Тривіальна задача – організація “зебри” з якоїсь таблиці:

// таблиця c “id=tabular_data” беремо її “tbody”
// (використовуємо селектор “>”, щоб вибрати лише потрібні елементи, крім підтаблиці)
// і кожному непарному елементу “tr” додаємо клас “odd”
dojo.query(“#tabular_data > tbody > tr:nth-child(odd)”).addClass(“odd”);

Зміна атрибутів, класів і стилів об’єктів:

// отримуємо атрибут title
dojo.attr(“Id/Node”, “title”); // title=”bar”
// встановлюємо атрибут title
dojo.attr(“Id/Node”, “title”, “A new Title”);
// встановлюємо кілька атрибутів
dojo.attr(“Id/Node”, {
“tabindex”: 2, // add to tab order
“onclick”: function(e) {
// add a click to event this node
}
});
// додаємо клас anewClass
dojo.addClass(“Id/Node”, “anewClass”);
// видаляємо клас anewClass
dojo.removeClass(“Id/Node”, “anewClass”);
// перемикач класу (ні – додасть, є – видалить)
dojo.toggleClass(“Id/Node”, “anewClass”);
// працює так само і з NodeList (тобто масивом елементів)
dojo.query(“.selector”).toggleClass(“anewClass”);
// поверне об’єкт стилю
dojo.style(“Id/Node”);
// поверне значення opacity
dojo.style(“Id/Node”, “opacity”);
// встановить значення opacity=0.5
dojo.style(“Id/Node”, “opacity”, 0.5);
// змінюємо кілька властивостей
dojo.style(“Id/Node”, {
“opacity”: 0.5,
“border”: “3px solid black”,
“height”: “300px”
});
// працює так само і з NodeList (тобто масивом елементів)
dojo.query(“.selector”).style({
“opacity”: 0.5,
“border”: “3px solid black”,
“height”: “300px”
});

Примітка: якщо яка-небудь функція вимагає вказівки node в якості параметра об’єкта (див. dojo.animateProperty), значить вона не зможе переварити NodeList, навіть якщо там міститься лише один об’єкт, звичайно, це логічно, але після jQuery – трохи напружує

Висувна панель

Почнемо з найпростішого прикладу – слайд-панель, вона у нас буде рухатися вгору/вниз по кліку на посилання (див. приклад)

Реалізуємо це наступним чином, по кліку на посилання, у нас буде перемикатися її клас (між “active” і “btn-slide”), а панелька з id=”panel” буде висуватися/ховатися. (клас “active” змінює позицію фонового зображення, див. CSS код).

dojo.addOnLoad(function(){
dojo.query(“.btn-slide”).connect(“onclick”,function(e){
dojo.stopEvent(e);
var panel = dojo.byId(‘panel’);
if (dojo.style(panel, ‘height’) != 0) {
dojo.anim(panel, {height:0}).play();
} else {
dojo.anim(panel, {height:200}).play();
}
dojo.toggleClass(this, “active”);
});
});

 

Магічні зникнення

Цей приклад покаже, як можна красиво і легко прибирати розчиняти елементи (див. приклад):

Коли ми клікаємо по картинці , буде знайдено батьківський елемент

і його прозорість буде повільно змінюватися від opacity= 1.0 до opacity=0 – для цього скористаємося функцією dojo.fadeOut:

dojo.addOnLoad(function(){
dojo.query(“.pane .delete”).connect(“onclick”,function(){
dojo.fadeOut({node:this.parentNode, duration:1000, onEnd: dojo.partial(dojo.style, this.parentNode, “display”, “none”)}).play();
// по завершенню – ховаємо елемент display:none
});
});

Пов’язана анімація #1

Тепер приклад складніше, але він допоможе Вам краще зрозуміти Dojo. Усього кілька рядків коду змусять квадрати рухатися, змінювати розмір і прозорість. (див. приклад):

// коли прогрузилась сторінка (DOM готовий до маніпуляцій)
dojo.addOnLoad(function(){
// прив’язуємося до події click для елемента з class=”down”
dojo.query(“.down”).connect(“onclick”,function(e){
e.preventDefault(); // видаляємо подія
// біжимо по всьому найденым елементів class=”box”
dojo.query(‘.box’).forEach(function(el){
dojo.anim(el,{ top: dojo.style(el,’top’)+160 // нарощуємо позицію top на 160px
, left: dojo.style(el,’left’)+160 // нарощуємо позицію left на 160px
, width: dojo.style(el,’width’)+10 // нарощуємо ширину на 10px
, height: dojo.style(el,’height’)+10 // нарощуємо висоту на 10px
, opacity: dojo.style(el,’непрозорість’)-0.2 // зменшуємо opacity на 0.2
}, 1000).play(); // запускаємо анімацію, вказуючи час в 1000ms = 1s
});
});
});
// прив’язуємося до події click для елемента з class=”up”, далі все аналогічно
dojo.query(“.up”).connect(“onclick”,function(e){
e.preventDefault();
dojo.query(‘.box’).forEach(function(el){
dojo.anim(el,{ top: dojo.style(el,’top’)-160
, left: dojo.style(el,’left’)-160
, width: dojo.style(el,’width’)-10
, height: dojo.style(el,’height’)-10
, opacity: dojo.style(el,’непрозорість’)+0.2}, 1000).play();
});
});
});
});

Примітка: в Opera 9.63 неправильно визначається початкове положення елементів

Пов’язана анімація #2

А тепер будемо анімувати кожен box окремо. Для руху вниз будемо використовувати dojo.fx.chain – і вся анімація буде виконуватися послідовно. Для руху вгору будемо використовувати dojo.fx.combine – анімація буде відбуватися паралельно (див. приклад):

dojo.require(“dojo.fx”);
dojo.addOnLoad(function(){
// обираємо кожен елемент окремо
var box1 = dojo.query(‘.box:nth-child(1)’)[0];
var box2 = dojo.query(‘.box:nth-child(2)’)[0];
var box3 = dojo.query(‘.box:nth-child(3)’)[0];
// вішаємо обробник на “down”
dojo.query(“.down”).connect(“onclick”,function(e){
e.preventDefault();
dojo.fx.chain(
[
dojo.animateProperty({node:box1,properties:{top: dojo.style(box1,’top’)+160,duration:1000}}) // змінюємо позицію першого квадрата
,dojo.animateProperty({node:box1,properties:{left: dojo.style(box1,’left’)+160,duration:1000}})
,dojo.animateProperty({node:box2,properties:{top: dojo.style(box2,’top’)+160,duration:1000}}) // змінюємо позицію другого квадрата
,dojo.animateProperty({node:box2,properties:{left: dojo.style(box2,’left’)+160,duration:1000}})
,dojo.animateProperty({node:box3,properties:{top: dojo.style(box3,’top’)+160,duration:1000}}) // змінюємо позицію третього квадрату
,dojo.animateProperty({node:box3,properties:{left: dojo.style(box3,’left’)+160,duration:1000}})
]
).play();
});
// вішаємо обробник на “up”
dojo.query(“.up”).connect(“onclick”,function(e){
e.preventDefault();
dojo.fx.combine(
[
dojo.animateProperty({node:box1,properties:{top: dojo.style(box1,’top’)-160,duration:1000}})
,dojo.animateProperty({node:box1,properties:{left: dojo.style(box1,’left’)-160,duration:1000}})
,dojo.animateProperty({node:box2,properties:{top: dojo.style(box2,’top’)-160,duration:1000}})
,dojo.animateProperty({node:box2,properties:{left: dojo.style(box2,’left’)-160,duration:1000}})
,dojo.animateProperty({node:box3,properties:{top: dojo.style(box3,’top’)-160,duration:1000}})
,dojo.animateProperty({node:box3,properties:{left: dojo.style(box3,’left’)-160,duration:1000}})
]
).play();
});
});

Примітка: функції dojo.fx.chain і dojo.fx.combine – працюють з dojo.animateProperty і не розуміють dojo.anim

Гармошка #1

Приклад реалізації “гармошки”. (див. приклад)

Тепер приступимо до розбору польотів:

// підключаємо dojo.fx і dojo.NodeList-fx
dojo.require(“dojo.fx”);
dojo.require(“dojo.NodeList-fx”);
dojo.addOnLoad(function(){
// ховаємо всі параграфи (можете використовувати CSS, але буде не так цікаво)
dojo.query(“.accordion div p”).style({ display:’none’ });
// вешаемся на подію onclick
dojo.query(“.accordion h3”).connect(“onclick”,function(){
// отримуємо індекс поточного елемента в предка
var index = dojo.query(“.accordion h3”).indexOf(this);
// ховаємо всі параграфи крім поточного
dojo.forEach(dojo.query(“.accordion div”).query(“p”), function(item, idx){
if (idx != index && dojo.style(item, ‘display’) != ‘none’) {
dojo.query(item).wipeOut().play();
}
});
// отримуємо необхідний нам

var p = dojo.query(“p”, this.parentNode);
// перевіряємо наявність класу active
if (dojo.hasClass(this,’active’)) {
dojo.removeClass(this,’active’); // видаляємо клас active
p.wipeOut().play(); // ховаємо

} else {
dojo.addClass(this,’active’); // додаємо клас active
p.wipeIn().play(); // показуємо

}
});
});

Наведу відразу код HTML, щоб далеко не ходити:

Question One Sample Text

Lorem ipsum dolor sit amet…

This Question is Two

Lorem ipsum dolor sit amet…

Another Questio here

Lorem ipsum dolor sit amet…

Примітка: натрапив на різну поведінку селектора :first-child в Додзьо і jQuery у наведеному прикладі. Dojo не знаходить елемент

, т. к. він не є first-child’ом щодо парента, jQuery ж знаходить, оскільки він є першим нащадком

. Хто правий я не можу сказати точно, але браузери вважають, що таки Dojo… (селектор :nth-child в Dojo так само вважає входження нащадків інакше).

Ще кину камінь в город Dojo – коду в jQuery значно менше, і структура документа простіше (хоча, можливо, я просто не знаю, як отримати в Dojo наступний елемент в будинку, маючи лише поточний node).

Так само не зовсім зрозуміло, чому при переборі dojo.query(“.accordion div p”).forEach(…) елементи йдуть у зворотному порядку (лише в webkit’е правильно), при цьому dojo.query(“.accordion div”).query(“p”).forEach(…) працює правильно у всіх браузерах.

Гармошка #2

Цей приклад схожий з попереднім, лише відрізняється тим, що ми вказуємо відкриту за замовчуванням панельку. (див. приклад)

В CSS у нас вказано для всіх елементів

display:none. Тепер нам необхідно відкрити третю панель. Для цього ми можемо написати наступний код:

dojo.addOnLoad(function(){
// обираємо третій div і додаємо до заголовка клас active
dojo.query(“.accordion div:nth-child(3) h3”).addClass(“active”);
// працює лише з webkit’ом
// dojo.query(“.accordion div:not(:nth-child(3)) p”).style({ display:’none’ });
var els = dojo.query(“.accordion div p”); // вибираємо всі параграфи
els.splice(2,1); // вирізаємо третій (тут відлік з нуля йде)
els.style({ display:’none’ }); // всі інші приховуємо
/* … */
});

Примітка: Селектор виду div:not(:nth-child(2)) заробив лише в Safari і Chrome. До речі, я реалізував анімацію в даному прикладі інакше – використовував dojo.fx.Toggler – досить кумедна річ, правда я так і не зрозумів як правильно перемикатися між show() і hide() (наприклад, якщо мені хочеться створити функцію аля slideToggle в jQuery)

Анімація для події hover #1

Даний приклад допоможе створити Вам дуже красиву анімацію для події hover (сподіваюся, Ви знаєте що це?), (див. приклад):

Коли Ви наводите мишкою на елемент меню (mouseover), відбувається пошук наступного елемента і анімуються його прозорість і розташування:

dojo.addOnLoad(function(){
// вешаемся на подія onmouseover
dojo.query(“.menu a”).connect(“onmouseover”,function(){
// шукаємо em елемент і його анимируем
var em = dojo.query(’em’, this.parentNode);
dojo.animateProperty({ node: em[0], duration:500,
properties: {
opacity: { start: 0, end: 1 }, // прозорість
top: { start:-85, end:-70, unit:”px” } // располложение
},
beforeBegin:function() { // перед початком анімації треба виставити правильно св-во display
em.style({display:’block’});
}
}).play();
});
// вешаемся на подію onmouseout
dojo.query(“.menu a”).connect(“onmouseout”,function(){
var em = dojo.query(’em’, this.parentNode);
dojo.animateProperty({ node: em[0], duration:300,
properties: {
opacity: { start: 1, end: 0 },
top: { start:-70, end: -85, unit:”px” }
},
onEnd:function() {
em.style({display:’none’});
}
}).play();
});
});

Анімація для події hover #2

Даний приклад трохи складніше попереднього прикладу: для формування підказки використовується атрибут title (див. приклад)

Першим ділом додамо тег в кожен елемент . Коли відбудеться подія mouseover, ми візьмемо текст з атрибуту “title” та вставити його в тег :

dojo.addOnLoad(function(){
dojo.query(“.menu2 a”).connect(“onmouseover”,function(){
// створюємо елемент em і закидаємо його в DOM
var em = dojo.query(dojo.create(’em’, {innerHTML:dojo.attr(this, ‘title’)})).place(this.parentNode);
// анімація
dojo.animateProperty({ node: em[0], duration:500,
properties: {
opacity: { start: 0, end: 1 },
top: { start:-85, end:-70, unit:”px” }
},
beforeBegin:function() {
em.style({display:’block’});
}
}).play();
});
dojo.query(“.menu2 a”).connect(“onmouseout”,function(){
var em = dojo.query(’em’, this.parentNode);
dojo.animateProperty({ node: em[0], duration:300,
properties: {
opacity: { start: 1, end: 0 },
top: { start:-70, end: -85, unit:”px” }
},
onEnd:function() {
// видаляємо елемент з DOM’a
em.orphan();
}
}).play();
});
});

Клікабельні блоки

Цей приклад демонструє, як зробити кликабельним блок з текстом, а не тільки посилання (див. приклад):

Створимо список

    з класом class=”pane-list” і ми хочемо зробити елементи

  • клікабельними. Для початку прикуємося до події click для елемента “.pane-list li”; коли користувач буде клікати по елементу списку, наша функція зробить пошук тега і зробить редирект на сторінку зазначену в атрибуті href.

    dojo.addOnLoad(function(){
    dojo.query(“.pane-list li”).connect(“click”,function(){
    window.location=dojo.query(“a”, this).attr(“href”);return false;
    });
    });

    Складаються панельки

    Ну, а тепер трохи комбінуємо попередні приклади і створимо ряд складаються панельок (на зразок як в Gmail організований inbox). (див. приклад)
     

    • покриваємо всі елементи
      після першого.
    • покриваємо всі елементи
    • після п’ятого
    • клік по

      – викликає метод wipeOut/wipeIn для наступного елемента

    • клік по – викликає метод wipeOut для всіх
    • клік по – приховує елемент, і відображає , так само викликається метод wipeIn для всіх
    • після п’ятого
    • клік по – приховує елемент, і відображає , так само викликається метод wipeOut для всіх
    • після п’ятого

    dojo.require(“dojo.fx”);
    dojo.require(“dojo.NodeList-fx”);
    dojo.addOnLoad(function(){
    // hide message_body after the first one
    dojo.query(“.message_list li:not(:first-child) .message_body”).style({ display:’none’ });
    // hide message li after the 5th
    // dojo.query(“.message_list li”).splice(4).style({ display:’none’ }); // not equal for FF and IE
    dojo.query(“.message_list li:nth-child(1n+4)”).style({ display:’none’ });
    // event header on click
    dojo.query(“.message_head”).connect(‘onclick’,function(){
    var body = dojo.query(“.message_body”,this.parentNode)
    if (dojo.style(body[0], ‘display’) != ‘none’) {
    body.wipeOut().play();
    } else {
    body.wipeIn().play();
    }
    return false;
    });
    // collapse all messages
    dojo.query(“.collpase_all_message”).connect(‘onclick’,function(e){
    e.preventDefault();
    dojo.query(“.message_body”).wipeOut().play();
    });
    // show all messages
    dojo.query(“.show_all_message”).connect(‘onclick’,function(e){
    e.preventDefault();
    dojo.query(this).fadeOut().play();
    dojo.style(this,’display’,’none’);
    dojo.query(“.show_recent_only”).style(‘display’,’block’).fadeIn().play();
    dojo.query(“.message_list li:nth-child(1n+4)”).wipeIn().play();
    });
    // hide old messages
    dojo.query(“.show_recent_only”).connect(‘onclick’,function(e){
    e.preventDefault();
    dojo.query(this).fadeOut().play();
    dojo.style(this,’display’,’none’);
    dojo.query(“.show_all_message”).style(‘display’,’block’).fadeIn().play();
    dojo.query(“.message_list li:nth-child(1n+4)”).wipeOut().play();
    });
    });

    Примітка: помітив різну поведінку функції dojo.NodeList.splice в різних браузерах

    Імітація Backend’a wordpress’a

    Я думаю багато хто з читачів стикалися з адмінської частиною wordpress’a, точніше з редагування коментарів. Спробуємо зробити щось подібне (див. приклад):

    • додамо клас “alt” до кожного елементу парним
      (даний клас змінює колір фону елемента)
    • клік по ініціює появу повідомлення (alert), так само відбувається анімація фонового кольору і прозорості (backgroundColor і opacity) для
    • клік по – викликає анімацію фону у
      (колір змінюється на жовтий і назад) і додає клас “spam”
    • клік по – викликає анімацію фону у
      (колір змінюється на зелений і назад) і видаляє клас “spam”
    • клік по – викликає анімацію фону у
      (колір змінюється на червоний), потім викликаємо FadeOut(), по завершенню анімації елемент видаляємо з DOM’а

    dojo.require(‘dojo.fx’);
    dojo.addOnLoad(function(){
    // знаходимо парні елементи
    dojo.query(“.pane:nth-child(even)”).addClass(“alt”);
    dojo.query(“.pane .btn-delete”).connect(‘onclick’,function(e){
    // видаляємо стандартний обробник події – щоб не було переходу за посиланням
    e.preventDefault();
    alert(“This comment will be deleted!”);
    // вибираємо необхідний нам блок
    var block = this.parentNode.parentNode;
    // вся анімація буде відбуватися послідовно
    var anim = dojo.fx.chain([
    dojo.animateProperty({ node: block, properties: { backgroundColor: “#fbc7c7” }}),
    dojo.fadeOut({ node: block})
    ]);
    // по завершенню анімації блок захований
    dojo.connect(анім, “onEnd”, function(){
    dojo.style(block, {‘display’:’none’});
    });
    anim.play();
    });
    dojo.query(“.pane .btn-unapprove”).connect(‘onclick’,function(e){
    e.preventDefault();
    var block = this.parentNode.parentNode;
    dojo.fx.chain([
    dojo.animateProperty({ node: block, properties: { backgroundColor: “#fff568” }}),
    dojo.animateProperty({ node: block, properties: { backgroundColor: “#ffffff” }, onEnd:function() {
    dojo.addClass(block, ‘spam’);
    }})
    ]).play();
    });
    dojo.query(“.pane .btn-approve”).connect(‘onclick’,function(e){
    e.preventDefault();
    dojo.fx.chain([
    dojo.animateProperty({ node: this.parentNode.parentNode, properties: { backgroundColor: “#dafda5” }}),
    dojo.animateProperty({ node: this.parentNode.parentNode, properties: { backgroundColor: “#ffffff” }, onEnd:function() {
    dojo.removeClass(this.node, ‘spam’);
    }})
    ]).play();
    });
    dojo.query(“.pane .btn-spam”).connect(‘onclick’,function(e){
    e.preventDefault();
    dojo.fx.chain([
    dojo.animateProperty({ node: this.parentNode.parentNode, properties: { backgroundColor: “#fbc7c7” }}),
    dojo.fadeOut({ node: this.parentNode.parentNode, properties: { backgroundColor: “#ffffff” }, onEnd:function() {
    dojo.query(this.node).orphan();
    }})
    ]).play();
    });
    });

    Примітка: код кожної функції трохи різниться, так – для різноманітності

    Галерея зображень

    Найпростіший приклад реалізації галереї, без перезавантаження сторінки. (див. приклад)

    Для початку додамо тег в заголовки

    По кліку на зображення

    виконуємо наступні дії:

    • скасовуємо подія (це перехід за посиланням)
    • зберігаємо значення атрибута href у змінній “largePath”
    • зберігаємо значення атрибута “title” змінної “largeAlt”
    • замінюємо в елементі значення атрибута “scr” і “alt” значеннями змінних “largePath” і “largeAlt”
    • так само присвоюємо елементу “h2 em” значення “largeAlt”

    dojo.addOnLoad(function(){
    dojo.query(dojo.create(’em’)).place(dojo.query(‘h2’));
    dojo.query(“.thumbs a”).connect(“onclick”,function(e){
    e.preventDefault();
    // отримуємо необхідні нам дані
    var largePath = dojo.attr(this, “href”);
    var largeAlt = dojo.attr(this, “title”);
    // замінюємо картинку і alt-текст
    dojo.attr(“largeImg”, {src:largePath,alt:largeAlt});
    em = dojo.query(“h2 em”)[0];
    // змінюємо опис
    em.innerHTML = ” (” + largeAlt + “)”;
    });
    });

    Стилизируем посилання

    Більшість нормальних браузерів легко розуміють коли ми хочемо домогтися від них стилізації посилань для різного типу файлів, для цього можна використовувати наступне правило CSS: a[href $=’.pdf’] { … }. Але як зазвичай IE6 відрізняється розумом і кмітливістю, з цієї причини будемо ставити йому милиці використовуючи Dojo. (див. приклад)

    Для початку додамо клас для кожного посилання, у відповідності з типом файлу.
    Потім виберемо всі елементи які не містять посилання на “http://anton.shevchuk.name” і не починаються на ” # ” “href”, потім додамо їм клас “external” і встановлюємо target= “_blank”.

    dojo.addOnLoad(function(){
    dojo.query(“a[href$=pdf]”).addClass (pdf);
    dojo.query(“a[href$=zip]”).addClass(“zip”);
    dojo.query(“a[href$=psd]”).addClass(“psd”);
    dojo.query(“a:not([href*=http://anton.shevchuk.name])”).filter(“:not([href^=#])”)
    .addClass(“external”)
    .attr({ target: “_blank” });
    });

    Так само Ви можете подивитися усі приклади або завантажити Dojo для початківців.

    Корисні посилання

    Наведу посилання на корисні ресурси по темі:

    • Загальний погляд на Dojo Toolkit
    • Два приклади створення data – таблиці на Dojo Toolkit і JQuery. Частина 1
    • Dojo Campus – багато корисної інформації, так само є свій Quick Start
    • Dojo Quick Start Guide – SitePen, Inc.
    • Introducing The Dojo Toolkit