Обработка событий в Додзё - PullRequest
1 голос
/ 01 сентября 2008

Прислушиваясь к совету Джеффа Этвуда , я решил использовать библиотеку JavaScript для самого простого приложения со списком дел, который я пишу. Я выбрал Dojo toolkit , версия 1.1.1. Сначала все было хорошо: код перетаскивания, который я написал, работал впервые, вы можете перетаскивать задачи на экран, чтобы изменить их порядок приоритета, и каждая операция перетаскивания вызывает обработчик событий, который отправляет AJAX. позвоните на сервер, чтобы сообщить, что заказ был изменен.

Затем я добавил функцию отслеживания электронной почты. Стандартный материал: к новым входящим электронным письмам присваивается уникальный идентификационный номер, прикрепленный к их строке темы, все последующие электронные письма об этой проблеме можно отслеживать, просто оставив этот идентификационный номер в теме при ответе. Итак, у нас есть список открытых задач, каждая из которых имеет свой идентификационный номер, и у каждой из этих задач есть упорядоченный по времени список связанных писем. Я хотел, чтобы текст этих электронных писем был доступен пользователю, когда он просматривал свой список задач, поэтому я сделал каждый блок задач элементом управления Dijit «Дерево» - верхний уровень содержит описание задачи, ветви содержат даты электронной почты и один «листок» каждой из этих веток содержит текст электронного письма.

Первая проблема: я хотел, чтобы представление дерева было полностью свернуто по умолчанию. После тщательного поиска в Google я нашел несколько решений, которые, как мне показалось, действительны для предыдущих версий Dojo, но не те, которые я использовал. В конце концов я понял, что наилучшим решением, по-видимому, было бы вызывать обработчик событий при загрузке элемента управления Tree, который просто сворачивал каждую ветвь / лист. К сожалению, хотя элемент управления Tree был создан и вызван его обработчик события запуска, ветви и листья все еще не были загружены (данные все еще загружались с помощью вызова AJAX). Итак, я изменил систему так, чтобы весь текст электронной почты и древовидная структура добавлялись на стороне сервера. Это означает, что весь полностью заполненный элемент управления Tree доступен, когда вызывается его обработчик события запуска.

Итак, обработчик событий запуска полностью сворачивает дерево. Затем я не смог найти «правильный» способ иметь хороший форматированный текст для электронных писем. Я могу просто поместить текст письма в лист, но любой HTML-код выходит и отображается на веб-странице. Более подробно рассмотрите документацию Dojo (как правило, устаревшую, с кодом и примерами для версий до 1.0) и Google. В конце концов я нашел решение заставить JavaScript идти и читать элемент SPAN, который находится внутри каждого конечного узла, и не использовать экранированный код HTML в его innerHTML. Я решил поместить код, чтобы сделать это в коде полного коллапса дерева, в обработчике событий запуска элемента управления Tree.

Однако ... оказывается, что элемент SPAN фактически не создается до тех пор, пока пользователь не щелкнет по кнопке expando (маленький символ «+» в древовидном представлении, который вы щелкаете, чтобы развернуть узел). Хорошо, достаточно справедливо - я добавлю код переформатирования в обработчик события onExpand (), или как он там называется. Которого, кажется, не существует. Я искал в документации, я искал в Google ... Я, возможно, неправильно понимаю систему обработки событий "публиковать / подписаться" в Dojo, но я думаю, что в основном потому, что, кажется, нет какой-либо исчерпывающей документации для где угодно (например, где я могу узнать, на какие события я могу подписаться?).

Итак, в конечном итоге, лучшее решение, которое я могу предложить, - это добавить обработчик события onClick (не событие «Dojo», а обычное событие JavaScript, о котором Dojo ничего не знает) в узел расширения каждого дерева. ветвь, которая переформатирует HTML внутри элемента SPAN каждого листа. За исключением ... когда это вызывается, элемент SPAN все еще не существует (иногда - иногда он кэшируется, просто чтобы еще больше сбить вас с толку). Поэтому у меня есть обработчик событий, устанавливающий таймер, который периодически вызывает функцию, которая проверяет, не появился ли соответствующий элемент SPAN, прежде чем затем переформатировать его.

// An event handler called whenever a "email title" tree node is expanded.
function formatTreeNode(nodeID) {
    if (dijit.byId(nodeID).getChildren().length != 0) {
        clearInterval(nodeUpdateIntervalID);
        messageBody = dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML
        if (messageBody.indexOf("<b>Message text:</b>") == -1) {
            messageBody = messageBody.replace(/&gt;/g, ">");
            messageBody = messageBody.replace(/&lt;/g, "<");
            messageBody = messageBody.replace(/&amp;/g, "&");
            dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML = "<b>Message text:</b><div style=\"font-family:courier\">"+messageBody+"</div>";
        }
    }
}

// An event handler called when a tree node has been set up - we changed the default fully-expanded to fully-collapsed.
function setupTree(theTree) {
    dijit.byId("tree-"+theTree).rootNode.collapse();

    messageNode = dijit.byId("tree-"+theTree).rootNode.getChildren();
    for (pl = 0; pl < messageNode.length; pl++) {
        messageNode[pl].collapse();
        messageNode[pl].expandoNode.onclick = eval("nodeUpdateIntervalID = setInterval(\"formatTreeNode('"+messageNode[pl].id+"')\",200); formatTreeNode('"+messageNode[pl].id+"');");
    }
}

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

  • Правильный способ размещения красиво отформатированного текста в элементе управления Dojo / Dijit Tree.
  • Правильный способ обработки событий Dojo, например, где я могу выяснить, на какие события я могу подписаться.
  • Лучшая библиотека JavaScript для использования (могу ли я делать то, что я хочу с JQuery, и избегать универсального подхода, описанного выше?).

PS: Если вы называете программный проект, подумайте об уникальности его имени в Google - я уверен, что поиск документации по «Dojo» в Google будет проще, если не будут мешать все результаты боевых искусств.

PPS: Проверка орфографии Firefox знает, как писать «Atwood», исправляя меня, когда я ставлю две буквы T вместо одной. Джефф сейчас так знаменит?

1 Ответ

3 голосов
/ 01 сентября 2008

Я предполагаю, что вы следовали учебнику по dijit.Tree и dojo.data в Dojo 1.1 , который велел вам передавать данные в древовидный элемент управления с использованием хранилища данных. Это заставило меня долго биться головой о кирпичную стену.

Это не очень хороший подход, и альтернатива не очень хорошо документирована. Вам нужно создать модель использования вместо этого. Ниже приведен пример древовидной модели, созданной для отображения структуры каталога LDAP.

Вы найдете реализацию модели по умолчанию в вашем дистрибутиве dojo по адресу ./dijit/_tree/model.js. Комментарии должны помочь вам понять функции, поддерживаемые моделью.

Класс IDirectoryService, код которого приведен ниже, является заглушками для серверных Java POJO, сгенерированных Direct Web Remoting (DWR). Я настоятельно рекомендую DWR, если вы собираетесь активно взаимодействовать клиент-сервер.

dojo.declare("LDAPDirectoryTreeModel", [ dijit.tree.model ], {
    getRoot : function(onItem) {
        IDirectoryService.getRoots( function(roots) {
            onItem(roots[0])
        });
    },

    mayHaveChildren : function(item) {
        return true;
    },

    getChildren : function(parentItem, onComplete) {
        IDirectoryService.getChildrenImpl(parentItem, onComplete);
    },

    getIdentity : function(item) {
        return item.dn;
    },

    getLabel : function(item) {
        return item.rdn;
    }
});

А вот выдержка из моей страницы JSP, где я создал модель и использовал ее для заполнения элемента управления деревом.

<div
  dojoType="LDAPDirectoryTreeModel"
  jsid="treeModel"
  id="treeModel">
</div>
<div
  jsid="tree"
  id="tree"
  dojoType="dijit.Tree" model="treeModel"
  labelAttr="name"
  label="${directory.host}:${directory.port}">
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...