Dojo Toolkit для начинающих

Dojo Toolkit

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

В данной статье я постараюсь описать базовые возможности Dojo, так же буду проводить параллели с jQuery, так что не пугайтесь возникшему дежавю…

Как я уже когда-то говорил – учиться лучше на примерах, так что приступим…

Подключение

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

Используя локальный файл:

<script type="text/javascript" src="js/dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script>

Данная запись аналогична предыдущей:

<script type="text/javascript">
    var djConfig = {
        isDebug:true,
        parseOnLoad:true
    };
</script>
<script type="text/javascript" src="js/dojo/dojo.js"></script>

Dojo так же доступен на следующих хостах:

<!-- AOL -->
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.3/dojo/dojo.xd.js"></script>
<!-- Google -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"></script>

Селекторы

Перейдем к поиску элементов, для этой цели есть следующие функции:

// самый простой вариант - получить елемент по его 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 event to 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. Всего несколько строк кода заставят квадраты двигаться, изменять размер и прозрачность. (см. пример):

Dojo Chainable Effects

// когда прогрузилась страница (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,'opacity')-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,'opacity')+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 Accordion

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

// подключаем 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();
                }
            });

        // получаем необходимый нам <p>
        var p = dojo.query("p", this.parentNode);

        // проверяем наличие класса active
        if (dojo.hasClass(this,'active')) {
            dojo.removeClass(this,'active'); // удаляем класс active
            p.wipeOut().play(); // прячем  <p>
        } else {
            dojo.addClass(this,'active'); // добавляем класс active
            p.wipeIn().play(); // показываем  <p>
        }
    });

});

Приведу сразу код HTML, чтобы далеко не ходить:

<div class="accordion">
<div>
    <h3>Question One Sample Text</h3>
    <p>Lorem ipsum dolor sit amet...</p>
</div>
<div>
    <h3>This is Question Two</h3>
    <p>Lorem ipsum dolor sit amet...</p>
</div>
<div>
    <h3>Another Questio here</h3>
    <p>Lorem ipsum dolor sit amet...</p>
</div>
</div>

Примечание: наткнулся на различное поведение селектора :first-child в Dojo и jQuery в приведенном примере. Dojo не находит элемент <p>, т.к. он не является first-child’ом относительно парента, jQuery же находит, т.к. он является первым потомком <p>. Кто прав я не могу сказать точно, но браузеры считают, что таки 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(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.accordion div:nth-child(3) h3&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).addClass(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;active&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);
    // работает лишь с webkit'ом
    // dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.accordion div:not(:nth-child(3)) p&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).style({ display:'none' });
    var els = dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.accordion div p&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);  // выбираем все параграфы
         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 (надеюсь, Вы знаете что это?), (см. пример):

Dojo Hover

Когда Вы наводите мышкой на элемент меню (mouseover), происходит поиск следующего элемента <em> и анимируются его прозрачность и расположение:

dojo.addOnLoad(function(){
    // вешаемся на событие onmouseover
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.menu a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;onmouseover&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,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:&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;px&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;  }  // располложение
            },
            beforeBegin:function() {  // перед началом анимации надо выставить правильно св-во display
                em.style({display:'block'});
            }
        }).play();
    });
    // вешаемся на событие onmouseout
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.menu a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;onmouseout&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,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:&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;px&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;  }
            },
            onEnd:function() {
                em.style({display:'none'});
            }
        }).play();
    });

});

Анимация для события hover #2

Данный пример чуть-чуть посложней предыдущего примера: для формирования подсказки используется атрибут title (см. пример)

Dojo Hover 2

Первым делом добавим тэг <em> в каждый элемент <a>. Когда произойдет событие mouseover, мы возьмем текст из атрибута “title” и вставим его в тэг <em>:

dojo.addOnLoad(function(){
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.menu2 a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;onmouseover&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,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:&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;px&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;  }
            },
            beforeBegin:function() {
                em.style({display:'block'});
            }
        }).play();
    });

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.menu2 a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;onmouseout&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,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:&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;px&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;  }
            },
            onEnd:function() {
                // удаляем элемент из DOM'a
                em.orphan();
            }
        }).play();
    });

});

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

Этот пример демонстрирует, как сделать кликабельным блок с текстом, а не только ссылку (см. пример):

Создадим список <ul> с классом class=”pane-list” и мы хотим сделать элементы <li> кликабельными. Для начала привяжемся к событию click для элемента “.pane-list li”; когда пользователь будет кликать по элементу списка, наша функция произведет поиск тэга <a> и сделает редирект на страницу указанную в атрибуте href.

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

Складывающиеся панельки

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

  • скрываем все элементы <div class="message_body"> после первого.
  • скрываем все элементы <li> после пятого
  • клик по <p class=”message_head”> – вызывает метод wipeOut/wipeIn для следующего элемента <div class=”message_body”>
  • клик по <a class=”collpase_all_message”> – вызывает метод wipeOut для всех <div class=”message_body”>
  • клик по <a class=”show_all_message”> – скрывает элемент, и отображает <a class=”show_recent_only”>, так же вызывается метод wipeIn для всех <li> после пятого
  • клик по <a class=”show_recent_only”> – скрывает элемент, и отображает <a class=”show_all_message”>, так же вызывается метод wipeOut для всех <li> после пятого
dojo.require(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;dojo.fx&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);
dojo.require(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;dojo.NodeList-fx&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);
dojo.addOnLoad(function(){
// hide message_body after the first one
dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_list li:not(:first-child) .message_body&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).style({ display:'none' });

// hide message li after the 5th
// dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_list li&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).splice(4).style({ display:'none' }); // not equal for FF and IE
dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_list li:nth-child(1n+4)&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).style({ display:'none' });

// event on header click
dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_head&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(){
    var body = dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_body&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,this.parentNode)
    if (dojo.style(body[0], 'display') != 'none') {
        body.wipeOut().play();
    } else {
        body.wipeIn().play();
    }
    return false;
});

// collapse all messages
dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.collpase_all_message&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(e){
    e.preventDefault();
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_body&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).wipeOut().play();
});

// show all messages
dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.show_all_message&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(e){
    e.preventDefault();
    dojo.query(this).fadeOut().play();
    dojo.style(this,'display','none');
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.show_recent_only&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).style('display','block').fadeIn().play();
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_list li:nth-child(1n+4)&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).wipeIn().play();
});

// hide old messages
dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.show_recent_only&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(e){
    e.preventDefault();
    dojo.query(this).fadeOut().play();
    dojo.style(this,'display','none');
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.show_all_message&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).style('display','block').fadeIn().play();
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.message_list li:nth-child(1n+4)&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).wipeOut().play();
});
});

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

Имитация Backend’a WordPress’a

Я думаю многие из читателей сталкивались с админской частью wordpress’a, точнее с редактирование комментариев. Попробуем сделать что-то подобное (см. пример):

  • добавим класс “alt” к каждому чётному элементу <div class="pane"> (данный класс изменяет цвет фона элемента)
  • клик по <a class=”btn-delete”> инициирует появление сообщения (alert), так же происходит анимация фонового цвета и прозрачности (backgroundColor и opacity) для <div class=”pane”>
  • клик по <a class=”btn-unapprove”> – вызывает анимацию фона у <div class=”pane”> (цвет изменяется на желтый и обратно) и добавляет класс “spam”
  • клик по <a class=”btn-approve”> – вызывает анимацию фона у <div class=”pane”> (цвет изменяется на зеленый и обратно) и удаляет класс “spam”
  • клик по <a class=”btn-spam”> – вызывает анимацию фона у <div class=”pane”> (цвет изменяется на красный), затем вызываем FadeOut(), по завершению анимации элемент удаляем из DOM’а
dojo.require('dojo.fx');
dojo.addOnLoad(function(){
    // находим четные элементы
    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.pane:nth-child(even)&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).addClass(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;alt&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.pane .btn-delete&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(e){
        // удаляем стандартный обработчик события - чтобы не было перехода по ссылке
        e.preventDefault();
        alert(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;This comment will be deleted!&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);

        // выбираем необходимый нам блок
        var block = this.parentNode.parentNode;
        
        // вся анимация будет происходить последовательно
        var anim = dojo.fx.chain([
            dojo.animateProperty({ node: block, properties: { backgroundColor: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;#fbc7c7&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; }}),
            dojo.fadeOut({ node: block})
        ]);

        // по завершению анимации блок будет спрятан
        dojo.connect(anim, &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;onEnd&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;, function(){
            dojo.style(block, {'display':'none'});
        });

        anim.play();
    });

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.pane .btn-unapprove&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(e){
        e.preventDefault();
        var block = this.parentNode.parentNode;

        dojo.fx.chain([
            dojo.animateProperty({ node: block, properties: { backgroundColor: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;#fff568&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; }}),
            dojo.animateProperty({ node: block, properties: { backgroundColor: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;#ffffff&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; }, onEnd:function() {
                    dojo.addClass(block, 'spam');
                }})

        ]).play();
    });

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.pane .btn-approve&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(e){
        e.preventDefault();

        dojo.fx.chain([
            dojo.animateProperty({ node: this.parentNode.parentNode, properties: { backgroundColor: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;#dafda5&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; }}),
            dojo.animateProperty({ node: this.parentNode.parentNode, properties: { backgroundColor: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;#ffffff&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; }, onEnd:function() {
                    dojo.removeClass(this.node, 'spam');
                }})

        ]).play();
    });

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.pane .btn-spam&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect('onclick',function(e){
        e.preventDefault();

        dojo.fx.chain([
            dojo.animateProperty({ node: this.parentNode.parentNode, properties: { backgroundColor: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;#fbc7c7&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; }}),
            dojo.fadeOut({ node: this.parentNode.parentNode, properties: { backgroundColor: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;#ffffff&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; }, onEnd:function() {
                    dojo.query(this.node).orphan();
                }})

        ]).play();
    });

});

Примечение: код каждой функции немного различается, так – для разнообразия

Галерея изображений

Простейший пример реализации галереи, без перезагрузки страницы. (см. пример)

Для начала добавим тэг <em> в заголовки <h2>
По клику на изображения в <p class=thumbs> выполняем следующие действия:

  • отменяем событие по умолчанию (это переход по ссылке)
  • сохраняем значение атрибута “href” в переменной “largePath”
  • сохраняем значение атрибута “title” в переменной “largeAlt”
  • заменяем в элементе <img id=”largeImg”> значение атрибута “scr” и “alt” значениями из переменных “largePath” и “largeAlt”
  • так же присваиваем элементу “h2 em” значение из “largeAlt”
dojo.addOnLoad(function(){
   dojo.query(dojo.create('em')).place(dojo.query('h2'));
   dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;.thumbs a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).connect(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;onclick&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,function(e){
        e.preventDefault();

        // получаем необходимые нам данные
        var largePath = dojo.attr(this, &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;href&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);
        var largeAlt  = dojo.attr(this, &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;title&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);

        // заменяем картинку и alt-текст
        dojo.attr(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;largeImg&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;, {src:largePath,alt:largeAlt});
        em = dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;h2 em&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;)[0];

        // изменяем описание
        em.innerHTML = &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; (&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; + largeAlt + &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;)&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;
    });
});

Стилизируем ссылки

Большинство нормальных браузеров легко понимают когда мы хотим добиться от них стилизации ссылок для различного типа файлов, для это цели можно использовать следующее CSS правило: a[href $='.pdf'] { ... }. Но как обычно IE6 отличается умом и сообразительностью, по этой причине будем ставить ему костыли используя Dojo. (см. пример

Для начала добавим класс для каждой ссылки, в соответствии с типом файла.
Затем выберем все элементы <a> которые не содержат ссылки на “http://anton.shevchuk.name” и не начинающиеся на “#” в “href”, затем добавим им класс "external" и устанавливаем target= "_blank".

dojo.addOnLoad(function(){

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;a[href$=pdf]&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).addClass(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;pdf&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;a[href$=zip]&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).addClass(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;zip&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;a[href$=psd]&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).addClass(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;psd&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);

    dojo.query(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;a:not([href*=http://anton.shevchuk.name])&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;).filter(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;:not([href^=#])&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;)
        .addClass(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;external&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;)
        .attr({ target: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;_blank&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; });

});

Так же Вы можете посмотреть все примеры или скачать Dojo для начинающих.

Полезные ссылки

Приведу ссылки на полезные ресурсы по теме:

59 thoughts on “Dojo Toolkit для начинающих”

  1. Спасибо. Хорошая запись.

    Только вот лично я не думаю, что с jQuery можно конкурировать…

    1. У Dojo немного другая ниша, да он проигрывает по удобству использования в приведенных примерах – но это лишь вершина айсберга – есть еще Dijit и Dojox…

  2. Это скорее для … ммм… профессионалов, я же оценивал все это со стороны продвинутого пользователя.

    1. Думаю, что это для тех, кто не умеет верстать. Как и ExtJs. Или для админок, где достаточно стандартных стилей dojo.

  3. Антон, что случилось с RSS-лентой.
    Весь анонс-текст статьи в единое «месиво» без единого переноса строки и т.п. (

    1. Проверил в Опере – вроде все ок…
      Правда Google Reader все еще не подхватил обновление :(

      1. Странно, на работе FeedDemon нормально отобразил, дома, он же нет, ладно наверно дома глюкнул )

  4. Куда интереснее было бы прочитать строк десять: обоснованную экспертную оценку, в каких ситуациях стоит использовать jQuery, а в каких – Dojo. А уж после этого решать – читать все эти буквы или нет.

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

  5. Как по мне, так jQuery проще и понятней.
    А для какой “ниши” этот фреймворк?

    1. В Dojo включает в себя Dijit – это набор виджетов – помогает быстро и красиво создавать формы и элементы страниц, чем-то схож с ExtJs – jQuery тут пока не конкурент…

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

  7. Есть книга даже на русском языке
    Мэтью А. Расселл. Dojo Подробное руководство.Символ- O’Reilly. Санкт-Петерубрг-Москва, 2009

  8. Что-то у меня при переходе по “jQuery для начинающих” в конце URL точка с запятой добавляется и, соответственно, – 404…
    А статья полезная, спасибо!

  9. Ну как минимум dojo во всех тестах на скорость показывает очень хорошие результаты, чем не могут похвастаться ни JQuery, ни Prototype.

  10. Pingback: progg.ru
  11. Спасибо, воспользовался,
    Я ищу как поймать событие при изменении ссылки после знака #
    Это чтоб исполнять js по смене якоря.
    Я пока придумал так

    previousUrl='#754828723$';
    function initUrl(url) {
    	if (url == previousUrl) return;
    	previousUrl = url;
    	var parts = url.split("#");
    	navigate_func(parts[1]);
    };
    
    function urlCheckDaemon() {
        initUrl(window.location.hash);
        setTimeout("CFLoader.checkUrlThread()", 250);
    }
    
    dojo.addOnLoad(function() {
        setTimeout("urlCheckDaemon()", 250);
    });
    

    Но это мне не очень нравится и я думаю это отразится на скорости приложения проверять каждые четверть секунды не изменился ли anchor name

  12. спасибо за статью.
    dojo понравился намного больше, чем jquery, только вот с оперой у него проблемы..
    есть какой-то выход?

  13. проблемы с тем, что мне понравилось в нем больше всего – dijit (до dojox дойти не успел)
    например:
    dijit.form.ValidationTextBox – сообщения об ошибках не исчезают
    dijit.Dialog – диалог не закрывается
    dijit.form.FilteringSelect – тоже глючит
    проверял на 9.26

    1. Точно! dojox.image.Gallery тоже глючит, правда терпимо..

  14. Добавляем в DIV innerHTML (например, кнопку)
    New BUTTON
    кнопка не применила никакой стиль dojo!
    Тупо обыкновенная HTML кнопка без украшательств

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
    	"http://www.w3.org/TR/html4/strict.dtd">
    <html>
     <head>
        	<title>Dijit Test Page</title>    
    	<link rel="stylesheet"
    			href="js/dojotoolkit/dijit/themes/soria/soria.css" />
    	<!-- load the dojo toolkit base -->
    	<script type="text/javascript" src="js/dojotoolkit/dojo/dojo.js"
    	    djConfig="parseOnLoad:true, isDebug:false"></script>
    	<script type="text/javascript">	
    		// our code, and dojo.requires() 
    		dojo.require("dijit.Dialog");
    		dojo.require("dijit.form.Button");
    		function Test()
    		{
    			dojo.byId("testcontent").innerHTML = "<button dojoType=\"dijit.form.Button\" id=\"myButton2\" onClick=\"alert(123)\"> New BUTTON </button>";
    		}
    	</script>
        
     </head>
     <body class="soria"><!-- this is a Typical WebPage starting point ... -->
    	<div id="testcontent">
    		<p>I am the Content of div id="testcontent".</p>
    	</div>
    	<button dojoType="dijit.form.Button" id="myButton"
    		onClick="Test()">
    		Add New Button
    	</button> 	
     </body>
    </html>
    
      1. теперь еще одна проблемка – не могу динамически изменить

        title у Dialog, у объекта то он меняется, а вот отображается тот, который в коде HTML

        [html entities=’1′]<div dojoType="dijit.Dialog" id="dialog1" title="Ð

      2. dijit.byId('dialog1').attr('title', 'YOUR TITLE');

        Вот бы мне кто ответил про отлавливание события изменения hash в адрексной строке браузера…

      3. У меня висит функция которая проверяет hash, вызывается она по setInterval раз в 200ms

      4. тоже у меня. Не хочется верить, что это единственный способ.

  15. Спасибо, теперь я могу использовать всё могущество innerHTML!

  16. У меня проблема Опере 10.10белая полоса в начале страницы, и у меня при разработке и на ваших примерах. В FF/IE всё отлично.
    Если кто-то сталкивался – подскажите, что я пропустил. Похожих проблем через google ни у кого не нахожу.

  17. Tp phplive: проверьте кодировку исходных файлов. Если файлы имеют различную кодировку то в Opere появлялась белая полоса вверху страницы (встречалось)

  18. Спасибо, вообще ваш ресурс просто рулит, супер.

  19. Приличную часть примеров реализовать можно несколькими строчками js
    Подозреваю, я не дошёл ещё до того большого потока сайтов и огномного функционала, когда библиотеки могут пригодиться.

    План есть познакомиться с jQ, когда-нибудь, очень интересно с селекторами работает (начал читать)

    Но дело оправдывает себя? ..ведь сперва одну изучишь, потом новая, ещё лучше.. если всё это время заниматься чистым js, профессионалом уже был бы или нет?

  20. Антон, спасибо за статью! Как раз заинтересовался dojo но не знал где почтиать, до этого прочел твои статьи про jquery.

    Хотел сказать про пример “гормошка”, кажется там ошибка в логикей, если разворачиваешь один пункт, а потом другой, то предыдущий не меняет статус, как будто он остался развернутым(хотя сам спрятался) и при нажатии на него повторно он не разворачивается, а пытается еще раз свернуться =)

    За статьи еще раз спасибо! Очень просто и доходчиво

  21. Лично для меня Dojo не конкурент для jQuery. Хотя Dijit в нем является огромным плюсом, но тут на помощь jQuery приходят такие “помошники” как http://flowplayer.org/tools/demos/

    jQuery по простоте написания и кол-ву кода гораздо превосходит Dojo.

  22. Смотрю на различные javascript фреймворки для выбора альтернатив jquery. И как это не прискорбно, но, похоже, jquery действительно по удобству использования превосходит остальные.
    проблема в том, что я люблю, когда код хорошо организован. а в jquery этому внимания уделяется слишком мало. сторонние плагины зачастую ужасны и, чтоб изменить в них что-либо на свой вкус бывает, что нужно пилить их целиком.
    однако просмотрел я ваши примеры. jquery код такой интуитивно понятный, а dojo.. действительно разбираться надо.. да и ваши примечания по поводу того, что dojo зачастую себя ведет не так, как хотелось бы…

    prototype умер; mochikit, похоже, тоже умер (так и не развившись); mootools, как я понимает имеет популярность только благодаря RoR и любителям ООП; extJS страшный слишком; а dojo странно себя ведет и код больше и сложнее, чем в jquery..

    видимо jquery – наше спасение

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

    1. на счет mootools я не то написал. хотел написать, что он жив за счет joomla :)

      1. Да ладно… Его от туда всячески выкуривают, у меня, например, ни в одном проекте нет его… разве что в админе…

      2. А dojo действительно заинтересовал, я просто мыкаюсь между ExtJS (который просто бесит своей ограниченностью, как минимум в плане темизации, ну знаете ли… “это кнопочка должна быть красненькой с зелененькой полупрозрачной тенью, с фиолетовым 2-х пиксельным бордюром…” типа того), т.е. показалось, что он катит для админок, собственно для админов (ну или для корпоративной внутренней веб системы), да и нужно сказать, что ХТМЛ он сам генерит, что тоже не хорошо (я же в Codeigniter-e или в Joomla не генерю js или css).

        2.Указанных недостатков нет в Dojo, “зерна можно отделить от плевел” (типа MVC, или его производные), есть некая централизованная организация, (те же require), но есть какое-то необъяснимое отвращение (извините, но чувства есть чувства, так что не судите строго, у каждого есть свои предпочтения), т.е. я привык к “палочке-выручалочке” Jquery и все тут.

        Так вот 3-й выбор написать некое подручное подобие такого фреймворка на JQ… но… собсно – лисапед…

        Мучительно, однако, стоять на распутье, при чем опятьже, ExtJS и Dojo рассматривал поверхностно, что-то реализовывать не пытался, но нужн подобный фреймворк для систем со сложным UI и в простом виде JQ просто не подходит (нет системности, один хаос)… мож вразумите меня?

  23. Привет Антон, подскажи пожалуйста:
    Отправляю форму на сервер через ajax запрос, в форме несколько кнопок.
    function doneForm(url) {
    var form = dojo.byId(“system_form_8”);
    dojo.connect(form, “onsubmit”,function(event) {
    dojo.stopEvent(event);
    var xhrArgs = {
    url: url,
    form: dojo.byId(“system_form_8”),
    handleAs: “text”,
    load: function(data) {
    dojo.byId(“content”).innerHTML = data;
    },
    error: function(error) {
    dojo.byId(“content”).innerHTML = error;
    }
    }
    var deferred = dojo.xhrPost(xhrArgs);
    });
    return false;
    }

    как передать значение кнопки на сервер?

    к примеру
    <form class="uniForm askOnLeave showErrors" id="system_form_8" enctype="multipart/form-data" method="post" onsubmit="return doneForm('/process/done/company/company[‘company_id’];?>/’)”>
    <input type="checkbox" class="inline input_checkbox" value="1" id="completeParent" name="form[is_propose]" company[‘project’][‘is_propose’]) echo ‘checked=”checked”‘;?>>
    <button type = "submit" id="error" onclick="return doneForm('/process/done/company/company[‘company_id’];?>/status/error’)”>translate(“P_ERROR”); ?>
    translate(“P_DONE”); ?>

    1. Привет Антон, подскажи пожалуйста:
      Отправляю форму на сервер через ajax запрос, в форме несколько кнопок.

      function doneForm(url) {
      	var form = dojo.byId("system_form_8");
      	dojo.connect(form, "onsubmit",function(event) {
               		dojo.stopEvent(event);
      	         var xhrArgs = {
      	       		url: url,
                      		form: dojo.byId("system_form_8"),
                      		handleAs: "text",
                      		load: function(data) {
                          	dojo.byId("content").innerHTML = data;
                      	},
                      	error: function(error) {
                         	dojo.byId("content").innerHTML = error;
                      	}
                  }
                  var deferred = dojo.xhrPost(xhrArgs);
           });
      return false;
      }
      

      как передать значение кнопки на сервер?

      к примеру

      <form class="uniForm askOnLeave showErrors" id="system_form_8" enctype="multipart/form-data" method="post"  onsubmit="return doneForm('/process/done/company/<?=$this->company['company_id'];?>/')">
      <input type="checkbox" class="inline input_checkbox" value="1" id="completeParent" name="form[is_propose]" <?php if ($this->company['project']['is_propose']) echo 'checked="checked"';?>>
      <button type = "submit" id="error" onclick="return doneForm('/process/done/company/<?=$this->company['company_id'];?>/status/error')"><span><span><?php echo $this->translate("P_ERROR"); ?></span></span></button>            
      <button type="submit" name="form[status]" value="done"><span><span><?php echo $this->translate("P_DONE"); ?></span></span></button>              
      </form>
      1. Проще всего преобразовать данные формы в JSON и передать на сервер.
        Но имейте ввиду, что есть и “подводные камни”: если не выставить заголовки. то post насильно (и неправильно) сконвертирует данные и вы получите JSON-строку в качестве ключа анонимного словаря. У меня, с Dojo 1.7, работает так:

        dojo.rawXhrPost({
         url: '/api/stock/shipment/in/',
         postData: dojo.toJson(data),
         headers: { "Content-Type": "application/json; charset=utf-8"},
         handleAs: "json",
         load: function(result){
           alert('Операция успешно выполнена');
           return result;
         },
         error: function(result){
           alert('Операция провалена');
           return result;
                                        }
           });
        
  24. Dojo хорош, хотя судя по примерам, сложность работы с его синтаксисом подталкивает использовать Jquery или чистый JS. Но думаю, что осилю. Спасибо за хорошую вводную статью.

  25. Почитал комменты… Мне Доджо нравится!!!
    Я уже частично адаптировал его для Джумлы, теперь на очереди Престашоп. Приходится обучать Смарта работать с Доджо (более 20 плагинов написал для Смарти) — справляется. Зато какое удобство в программировании визуальных компонентов!
    Вот, в примеру, смарти-код, создающий titlepane:
    {titlepane id=”new-products_block_right” title=”New products” mod=”blocknewproducts” open=$open_title style=”width:190px;font-size: 14px;font-weight:bold;color:#000;”}

  26. Привет! Я попробовала сделать пример магические исчезновения на dojo 1.7. Вот код моего примера. Помоги разобраться

    Disappear

    var dojoConfig = { async: true, tlmSiblingOfDojo: false, parseOnLoad: true, isDebug: true,
    packages: [
    { location: “../dijit”, name: “dijit” },
    { location: “../dojox”, name: “dojox” },
    { location: “.”, name: “dojo” },
    { location: “/dojo/js/sample”, name: “sample” } ]};

    require([“dojo/_base/lang”, “dojo/dom-style”, “dojo/_base/fx”, “dojo/query”, “dojo/domReady!”],
    function(lang, domStyle, fx, query) {
    query(“.pane .delete”).on(“click”, function(){
    var animation = fx.fadeOut({
    node:this.parentNode,
    duration:1000,
    onEnd:lang.partial(domStyle.set, this.parentNode, “display”, “none” )
    });
    animation.play();
    });
    });

    body {
    margin: 10px auto;
    width: 470px;
    }
    h3 {
    margin: 0;
    padding: 0 0 .3em;
    }
    p {
    margin: 0;
    padding: 0 0 .5em;
    }
    .pane {
    background: #edf5e1;
    padding: 10px 20px 10px;
    position: relative;
    border-top: solid 2px #c4df9b;
    }
    .pane .delete {
    position: absolute;
    top: 10px;
    right: 10px;
    cursor: pointer;
    }

    Sample heading
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi malesuada, ante at feugiat tincidunt, enim massa gravida metus, commodo lacinia massa diam vel eros. Proin eget urna. Nunc fringilla neque vitae odio. Vivamus vitae ligula.

    Sample heading
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi malesuada, ante at feugiat tincidunt, enim massa gravida metus, commodo lacinia massa diam vel eros. Proin eget urna. Nunc fringilla neque vitae odio. Vivamus vitae ligula.

    Sample heading
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi malesuada, ante at feugiat tincidunt, enim massa gravida metus, commodo lacinia massa diam vel eros. Proin eget urna. Nunc fringilla neque vitae odio. Vivamus vitae ligula.

    Sample heading
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi malesuada, ante at feugiat tincidunt, enim massa gravida metus, commodo lacinia massa diam vel eros. Proin eget urna. Nunc fringilla neque vitae odio. Vivamus vitae ligula.

    Sample heading
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi malesuada, ante at feugiat tincidunt, enim massa gravida metus, commodo lacinia massa diam vel eros. Proin eget urna. Nunc fringilla neque vitae odio. Vivamus vitae ligula.

  27. К моему предыдущему посту. К сожалению, html разметка была “сьета”, поэтому сейчас привожу только мой неработающий скрипт.
    Это попытка реализации магических исчезновений с помощью dojo 1.7. Скажи, пожалуйста в чем проблема? Спасибо.
    require([“dojo/_base/lang”, “dojo/dom-style”, “dojo/_base/fx”, “dojo/query”, “dojo/domReady!”],
    function(lang, domStyle, fx, query) {
    query(“.pane .delete”).on(“click”, function(){
    var animation = fx.fadeOut({
    node:this.parentNode,
    duration:1000,
    onEnd:lang.partial(domStyle.set, this.parentNode, “display”, “none” )
    });
    animation.play();
    });
    });

    1. Мне кажется ваша сттрока: query(“.pane .delete”).on(“click”, function(){…
      должна выглядеть вот так:
      query(“.pane .delete”).connect(“onclick”, function(){…});
      Могу ошибаться, ибо думаю так исходя из примеров выше, так как с DOJO ознакомился прочитав примеры автора этой страницы :)

  28. Честно говоря, — еще не проверял семерку. Но насчет шестерки скажу так: офигенный фрейм!!!
    Кстати, адаптировал Доджо к Джумле (pingv.in.ua, esculap.in) и Престашоп (ra-shop.us). Написал нормальный плуг, совмещающий fetchscript(компрессия всех стилей и скриптов) и подключающий ядро доджо. Для DLE тоже пробовал, только на все времени не хватает.
    Но семерку собираюсь опробовать в ближайшее время…

  29. Кстати, нарисовался вопрос, мо знаешь в чем суть…
    Тут, намедни, ваял мод для Джумлы, скрывающий реф-ссылки на банерах. В принципе, от доджо пришлось пока отказаться. И вот почему: доджевский base64.decode выдает не исходную ссылку (кодированную в пэхпке), а набор числовых значений. Решил, чтоб без геморроя, просто включить маленький скриптик-декодер.
    Ясно дело — не проблема сделать преобразование битов в чары, только нафиг этот гемор? Тема ведь и так рулит!

  30. Добрый день!
    Спасибо за статью !
    Подскажите возможно ли отключить полностью всю анимацию dojo на странице?
    Как например для jquery
    jQuery.fx.off = true;

  31. dojo.js.uncompressed.js это ВОСЕМНАДЦАТЬ С ПОЛОВИНОЙ ТЫСЯЧ строк !!!
    А не проще ли составить самому маленький скриптик, чтобы получить те или иные функции что есть сейчас в dojo ? И не надо заморачиваться с изучением этого dojo.
    Фреймворк не только имеет большой размер, но много функций, которые не будут использованы не то что на какой то одной странице, но и на сайте в целом.
    Универсализм и избыточность присущи всем без исключения фреймворкам, и написаны они на всякий случай, а вдруг кому то лень написать свой скрипт. Избыточный код оказался очень популярен.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.