Объекты ExtJs в админке. Часть 2
В первой части мы познакомились с методом Ext.getCmp()
, который позволяет взаимодействовать с виджетами ExtJs — панелями, таблицами, формами, окнами, запрашивать и обрабатывать данные с сервера и т.д. Но иногда требуется просто поработать с обычными HTML элементами. А для этого метод Ext.getCmp()
совсем не подходит. Можно, конечно, пользоваться обычным javascript. Но уж очень хочется иметь такой же удобный инструмент как jQuery. И ExtJs предоставляет нам такой функционал. Для работы с элементами DOM у него есть несколько методов.
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.
Комментарии ()
Вы должны авторизоваться, чтобы оставлять комментарии.
На сайте реализован импорт ресурсов из xml ссылок, которые прописаны в категориях, в общей сложности по всем категориям собирается порядка 100 тыс. При добавлении/ обновлении ссылок, чтобы не запускать целиком весь импорт, который может затянуться на несколько часов, а то и суток, придумали следующее:
Что если добавить виджет в панель управления MODX, в котором будут перечислены категории со ссылками, и чекбоксы (чтобы отметить нужные категории) После того, как отмечу все необходимые категории, нажимаю – ИМПОРТ, и запускается консольный импорт ресурсов из xml только отмеченных категорий. Причем всё в цикле (как, например, при запуске индексации mSearch2 из админки).
Пытался найти что-то похожее на просторах интернета, и не нашел. Может не так искал.
Так вот вопрос, с высоты вашего опыта, что можете посоветовать почитать или может подскажете, куда копать, чтобы реализовать подобное (а может и что-то более удобное сможете подсказать)
Спасибо!:)
В данном вопросе я совсем не помощник. Ни одного виджета в жизни не сделал и ни одного импорта/экспорта. По циклическому выполнению скрипта видел в сообществе инфу. Так что можно поискать. Из последнего вот. И тот же вариант mSearch2.
Так что сорри, помочь нечем.