ExtJs для новичков. Админка загрузилась. ч.2
В первой части познакомились с методом Ext.getCmp() для работы с компонентами ExtJs. Он позволяет взаимодействовать с виджетами ExtJs — панелями, таблицами, формами, окнами, запрашивать и обрабатывать данные с сервера и т.д. Но иногда требуется просто поработать с обычными HTML элементами. А для этого метод Ext.getCmp() совсем не подходит. Можно, конечно, пользоваться обычным javascript. Но уж очень хочется иметь такой же удобный инструмент как jQuery. И ExtJs предоставляет нам такой функционал. Для работы с элементами DOM у него есть несколько методов.
Ext.get(el) — метод-обертка, возвращающий объект класа Ext.Element (элемент ExtJs), который инкапсулирует в себе и сам DOM элемент и методы для работы с ним. Очень похоже на jQuery с его $('div.class'). В качестве параметра передаются или id узла DOM, или сам узел или элемент ExtJs.
Ext.select(selector) — возвращает коллекцию элементов ExtJs. Этот метод позволяет использовать селекторы CSS.
Ext.query(selector) — возвращает массив HTML элементов. Этот метод позволяет использовать селекторы CSS. В отличие от Ext.select, этот метод не создает объекты-обертки ExtJs для найденных элементов.
Ext.getDom(el) — также как и Ext.query возвращает чистый узел DOM, но всего один. Параметр — id узла DOM, узел DOM или объект Ext.Element.
Подробную информацию по этим и другим методам можно посмотреть в официальной документации.
Давайте сделаем так, чтобы пункты меню открывались и закрывались только по клику.
Создадим файл clickmenu.js.
Подключаем js файл и стиль в плагине
В этом примере использовались методы для работы с элементами DOM. Немного похоже на jQuery, правда? Можно было бы сделать тоже самое на javascript. Но получилось бы сложнее. А в ExtJs мы видим уже знакомые по jQuery методы — addClass(), show(), hide(), on().
Как мы видим, этот пункт меню имеет id=«limenu-components». А описания лежат в теге span.
Задача выполнена.
Другие методы, описанные выше, также могут быть использованы в элементах ExtJs.
На этом со статьями по ExtJs всё. Судя по предыдущей заметке особого интереса эта тема не вызвала. Надеюсь, кому-нибудь это поможет в начинании.
Ext.get(el) — метод-обертка, возвращающий объект класа Ext.Element (элемент ExtJs), который инкапсулирует в себе и сам DOM элемент и методы для работы с ним. Очень похоже на jQuery с его $('div.class'). В качестве параметра передаются или id узла DOM, или сам узел или элемент ExtJs.
// Получаем элемент ExtJs из div с id="title"
var title = Ext.get('title');
// Обновляем текст
title.update('Новый заголовок');
Ext.select(selector) — возвращает коллекцию элементов ExtJs. Этот метод позволяет использовать селекторы CSS.
// Получаем все див узлы с классом "text" и скрываем их
var divs= Ext.select('div.text');
divs.hide();
Ext.query(selector) — возвращает массив HTML элементов. Этот метод позволяет использовать селекторы CSS. В отличие от Ext.select, этот метод не создает объекты-обертки ExtJs для найденных элементов.
Ext.getDom(el) — также как и Ext.query возвращает чистый узел DOM, но всего один. Параметр — id узла DOM, узел DOM или объект Ext.Element.
Подробную информацию по этим и другим методам можно посмотреть в официальной документации.
Упражнение 1
Для понимания принципов работы этих методов давайте попробуем поработать с главным меню, которое не является виджетом (компонентом) ExtJs. Поэтому для него нельзя использовать Ext.getCmp(). Вот его HTML структура<ul id="modx-topnav">
<li id="modx-home-dashboard">
<li id="modx-site-info">
<li id="modx-manager-search-icon">
<li id="limenu-site" class="top">
<li id="limenu-media" class="top">
<li id="limenu-components" class="top">
<li id="limenu-manage" class="top">
</ul>
Давайте сделаем так, чтобы пункты меню открывались и закрывались только по клику.
Создадим файл clickmenu.js.
// DOM построен
Ext.onReady(function () {
// Получаем все li элементы главного меню
var menuli = Ext.select('#modx-topnav > li');
// Скрываем все подменю, чтобы они не открывались на hover
Ext.select('ul.modx-subnav').hide();
// Закрываем открытое подменю (если есть) при клике на любое место
Ext.get(document.body).on('click', function(e){
var li = Ext.select('#modx-topnav > li.active');
if (li.elements.length) {
li.removeClass('active');
// Скрываем подменю (ul), являющееся дочерним элементом li элемента
li.el.child('ul').hide();
}
});
// Каждому элементу главного меню навешиваем обработчик события клика
Ext.each(menuli.elements, function(d,i){
// Получаем элемент ExtJs для d узла DOM
var li = Ext.get(l);
li.on('click',function(){
// Закрываем открытое подменю
var active = Ext.select('#modx-topnav > li.active');
// Массив active.elements содержит элементы DOM из предыдущего запроса (если есть)
if (active.elements.length > 0) {
active.removeClass('active');
// Скрываем подменю (ul), являющееся дочерним элементом li элемента
active.el.child('ul').hide();
}
// Если мы кликнули на уже открытом меню, то просто закрываем его. Если на другое
//или нет других открытых меню, то открываем кликнутый пункт меню и прописываем класс.
if (active.elements.length == 0 || active.elements.length && active.el.id != li.id) {
var ul = li.child('ul');
if (ul) {
li.addClass('active');
li.child('ul').show();
}
}
},this, {stopPropagation: true})
});
});
Тут мы используем CSS класс «active» для обозначения открытого подменю. #modx-navbar li.active ul.modx-subnav {
opacity: 1 !important;
visibility: visible !important;
}
Подключаем js файл и стиль в плагине
switch ($modx->event->name) {
case 'OnManagerPageBeforeRender':
$modx->controller->addHtml('<style type="text/css">#modx-navbar li.active ul.modx-subnav {opacity: 1 !important;visibility: visible !important;} </style>');
$modx->controller->addJavascript('/inc/clickmenu.js');
break;
}
перезагружаем админку и вуаля. Всего несколько строчек кода и наше меню работает как мы ему приказали — по клику. В этом примере использовались методы для работы с элементами DOM. Немного похоже на jQuery, правда? Можно было бы сделать тоже самое на javascript. Но получилось бы сложнее. А в ExtJs мы видим уже знакомые по jQuery методы — addClass(), show(), hide(), on().
Упражнение 2
В предыдущем упражнении мы использовали метод Ext.select(), который выбирал все записи документа с указанными параметрами. Но этот метод select() есть у всех элементов ExtJs. Что это дает? Это позволяет задавать ограничения поиска. Так мы можем выбрать всех потомков определенного контейнера. Давайте используем эту возможность в примере — скроем описание пунктов меню «Приложения», чтобы укоротить меню. Частая задача, когда компонентов слишком много. У остальных пунктов меню описание оставим.Как мы видим, этот пункт меню имеет id=«limenu-components». А описания лежат в теге span.
// Получаем объект пункта меню компонентов
var liComponents = Ext.get('limenu-components');
// И у него ищем потомков - элементы span с описанием. И скрываем их.
// По-умолчанию, у элементов за отображение отвечает свойство visibility. А в этом случае, хоть элемент и скрыт,
// но место, где он расположен, остается. Поэтому нам нужно скрывать элемент через display: none.
// Вариант 1. Устанавливаем всем элементам метод отображения DISPLAY, а затем скрываем методом hide().
liComponents.select('span.description').setVisibilityMode(Ext.Element.DISPLAY).hide();
// Вариант 2. Просто меняем стиль display
liComponents.select('span.description').setStyle({display: 'none'});
Задача выполнена.
Другие методы, описанные выше, также могут быть использованы в элементах ExtJs.
Итог
ExtJs предлагает 2 вида методов для работы. Один — это работа с компонентами на уровнях Controller и View с точки зрения стандарта MCV. Второй — для работы с узлами DOM.
Поблагодарить автора
Отправить деньги
Комментарии: 19
Очень зря, Сергей. Не знаю, как кому, но мне было очень интересно!
Да, интереса сейчас мало. Вот позже, когда у людей появится необходимость разобраться, они через Яндекс или Google найдут эти статьи, в комментариях начнутся и вопросы, и благодарности)
Мне, например, интересно, я про этот ExtJS все еще как про магию думаю)
Мне, например, интересно, я про этот ExtJS все еще как про магию думаю)
Аналогично..)
Может, стоит дублировать такие статьи напрямую в docs.modx.pro?
Может, стоит дублировать такие статьи напрямую в docs.modx.pro?
Честно говоря, мои статьи рассчитаны на новичков MODX. Но уж если такого уровня людям интересно, готов продолжить.
П.С. Дело не в благодарностях. Просто я поддерживаю хорошую традицию, начатую Василием, делится опытом. Пусть этот опыт пока не большой, но все же может кому-то пригодится. А если это не интересно никому, то какой смысл тратить время.
Мою степень знаний ExtJs можно отследить по моим дополнениям. Начинал с elementNote, а сейчас дошел до adminTools с панелью задач, чтобы можно было переключаться между окнами. Мне пока самому интересно. :)
П.С. Дело не в благодарностях. Просто я поддерживаю хорошую традицию, начатую Василием, делится опытом. Пусть этот опыт пока не большой, но все же может кому-то пригодится. А если это не интересно никому, то какой смысл тратить время.
Мою степень знаний ExtJs можно отследить по моим дополнениям. Начинал с elementNote, а сейчас дошел до adminTools с панелью задач, чтобы можно было переключаться между окнами. Мне пока самому интересно. :)
ДелитЬся опытом :)
А в остальном просто замечательно, как и Илья, смотрю пока на ExtJS как чудо, хоть и не новичок в MODX. Продолжай обязательно!
А в остальном просто замечательно, как и Илья, смотрю пока на ExtJS как чудо, хоть и не новичок в MODX. Продолжай обязательно!
как НА чудо :)
Странно, что ни одного вопроса нет.
Странно, что ни одного вопроса нет.
Гы, 1:1 :)
Вопросы будут, но позже. У меня основная работа теперь связана теперь немного с другим.
Вопросы будут, но позже. У меня основная работа теперь связана теперь немного с другим.
Странно, что ни одного вопроса нет.Потому-что на изучение время нужно, а время надо выбрать, чтобы заняться вплотную, тем более тема довольно обширная. Вот тогда и вопросы появятся :)
По ExtJs для Modx весьма мало материалов. Есть конечно офф документация sencha но интересна именно свзязка с Modx. Поэтому хотелось бы чтобы серия статей не умерла.
Есть официальная документация на modx.com
Я знаю про эту документацию. Однако она весьма поверхностна
Добавил упражнение 2.
Начну с вопроса) Как сделать свою вкладку около вкладок Ресурсы, Элементы, Файлы и в ней выводить в древовидной форме записи из таблицы компонента?)
Все компоненты ExtJs выводятся в контейнерах. Основные контейнеры — это панели и окна. В данном случае, контейнер с вкладками Ресурсы, Элементы, Файлы — это tabPanel. Если посмотреть исходный код, то можно увидеть, что у этого контейнера есть id — 'modx-leftbar-tabpanel'. Получая компонент через метод Ext.getCmp(), можно использовать все его методы, в том числе и add(), который добавляет дочерние элементы — табы. Но можно воспользоваться альтернативным способом. В MODX есть метод addTab(), который также добавляет вкладку указанной панели.
В ближайшее время выйдет статья, где поподробнее поговорим о компонентах ExtJs.
MODx.addTab('modx-leftbar-tabpanel',{
id: "id нового таба",
title: "Заголовок таба",
items: [{
xtype: "x-type элемента, который будет показан на вкладке (в данном случае это дерево)"
//, другие параметры
}]
})
П.С. Начинать изучать ExtJs с дерева — не очень хорошая идея. Это сложный компонент. Лучше начинать разбираться с чего-то попроще. В ближайшее время выйдет статья, где поподробнее поговорим о компонентах ExtJs.
Жду статью, Сергей. Побольше бы информации об ExtJS, побольше. :)
А как подключить к окну редактирования ресурса таб с функционалом своего компонента? Как только указываю не родной xtype выдает ошибку:
TypeError: b[(intermediate value)] is not a constructorПри этом в плагине подкобчил файлы:
$modx->controller->addJavascript($modx->modCOM->config['jsUrl'] . 'mgr/modcom.js');
$modx->controller->addJavascript($modx->modCOM->config['jsUrl'] . 'mgr/widgets/items.grid.js');
$modx->controller->addLastJavascript($modx->modCOM->config['jsUrl'] . 'mgr/tab.js');
$modx->controller->addHtml('<script type="text/javascript">modCOM.config = ' . $modx->toJSON($modx->modCOM->config) . ';</script>');
Вот пример из AdminTools.
Сергей, а можно суть подробнее рассказать. Сам таб я создаю, кнопки, поля и т.д. в нем также могу сделать, но все это получается оторванным от самого компонента и не функциональным. Если же я в плагине подключаю файл items.grid.js и задаю xtype modcom-grid-items (тот, что на странице компонента выводит табличку), то все перестает работать.
Может мне нужно сам компонент инициализировать как-то?
Может мне нужно сам компонент инициализировать как-то?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.