LINUX.ORG.RU

Эмуляция иерархичного списка с помощью стороннего виджета

 , ,


0

1

Здравствуй, ЛОР!

Осваиваю веб-программирование на небольшом проекте. Имеется таблица с иерархией (т.е. поле parent_id в таблице БД), возникла необходимость представить эту информацию в наглядном виде, с отображением этой иерархии и возможностью сворачивать/разворачивать отдельные ее ветви, т.е. наподобие TreeView-виджетов различных GUI-тулкитов.

Нагуглил такую библиотеку на основе jQuery, предоставляющую необходимый виджет (посмотреть на него можно на странице примеров), почитал примеры, разобрался с отдачей данных в формате JSON. Все хорошо, все отображается, но возникла небольшая проблема с тем, чтобы заставить этот виджет работать как элемент формы (наподобие select). Проблема также усугубляется тем, что раньше с Javascript я не работал, и приходится осваивать его так сказать «по пути».

Я пока пришел к алгоритму, который хочу представить на ваш суд. В паре с каждым TreeView-виджетом будет идти hidden-поле, которое и будет определять значение (id в таблице БД) выбранного элемента, а при обработке события выбора элемента дерева (select) будет меняться значение этого поля. Но у меня возникли трудности с тем, как хранить id-шники (id не как html атрибут, а как идентификатор поля в БД) элементов вместе с названиями при генерации дерева, чтобы впоследствии использовать эти значения в обработчике. Единственный способ, который я придумал, использует поле template, которое определяет шаблон, по которому генерируются узлы дерева.

Суть в том, чтобы обернуть выводимый текст в некоторый тег TAG (кстати, какой тег можно использовать для этой цели?) с аттрибутом VALUE (соответствующий шаблон: «<TAG class='node-value' VALUE='#= item.id #'>#= item.text #</TAG>»), затем в обработчике искать ближайший к текущему узлу (параметр события, тип HTMLLIElement) элемент TAG с классом «node-value» и использовать значение его атрибута VALUE, на которое и будет меняться значение hidden-поля. Но это похоже на костыль.

Собственно, теперь сам вопрос: есть ли более правильный способ решить данную проблему?

Заранее спасибо.

★★★★★

Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от VirRaa

А в исходном сообщении разве не это написано? Да и главный вопрос в том, как это value в обработчике получить.

theNamelessOne ★★★★★
() автор топика
Последнее исправление: theNamelessOne (всего исправлений: 1)

Можно посмотреть на zTree, хорошее дерево с вменяемым API и документацией.

При инициализации дерева установить обработчик:

callback: {
beforeClick: onNodeSelect
} 
в сам обработчик будет передан узел дерева:
function onNodeSelect(treeId, treeNode) {
   // treeId - имя дерева
   // treeNode - выбранный узел
} 

ollowtf ★★★
()
Последнее исправление: ollowtf (всего исправлений: 1)
Ответ на: комментарий от ollowtf

Спасибо за ссылку, посмотрю. Вообще, я хотел бы разобраться с Kendo UI, т.к. планирую использовать и некоторые другие виджеты из этой библиотеки, но на крайний случай пусть будет запасной вариант.

theNamelessOne ★★★★★
() автор топика

Вот немного (псевдо-)кода для иллюстрации идеи:

<div id="my-tree"></div>

<input id="my-value" type=hidden value="">

<script type="text/javascript">
$(document).ready(function() {

  function onSelect(e) {
    // Псевдокод обработчика нажатия на элемент дерева
    var TAG = GetClosestTAGByClass(e.node, "node-value");
    var VALUE = TAG.GetVALUE();
    ChangeHiddenInput("my-value", VALUE);
  }

  /*
   * Данные в следующем формате:
   * [{"id": 1, "title": "foo", "children": false},
   *  {"id": 2, "title": "bar", "children": true}
   * ]
   * Поле id используется при запросе к серверу,
   * также я хочу использовать его в качестве значения
   * для input hidden. Поле title определяет выводимый текст,
   * children — есть ли у текущего узла потомки
   *
   * Названия полей определяются ниже (см. model и dataTextField)
   */
  var data = new kendo.data.HierarchicalDataSource({
    transport: {
      read: {
        url: "/path/to/my/data.json",
        dataType: "json"
      }
    },
    schema: {
      model: {
        id: "id",  // Название поля для id
        hasChildren: "has_children" // Название поля, определяющего, есть ли узла потомки
      }
    }
  });

  $("#my-tree").kendoTreeView({
    dataSource: data,
    dataTextField: "title", // Название поля, данные из которого будут выводиться
    select: onSelect,
    // С помощью шаблона "внедряем" значение id в генерируемый узел
    template: "<TAG class='node-value' VALUE='#= item.id #'>#= item.title #</TAG>"
  });
});
</script>
theNamelessOne ★★★★★
() автор топика
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

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

function onSelect(e) {
  var id = this.dataItem(e.node).id;
  $("input#hidden-value").val(id);
}

Всем спасибо за участие.

theNamelessOne ★★★★★
() автор топика
Последнее исправление: theNamelessOne (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.