JsTree — деревья это так просто

  • Tutorial
Привет!

О плагине JsTree на хабре упоминалось лишь в далеком 2009 году. С тех времен все довольно сильно поменялось. Плагин активно развивается. Страница проекта на гитхабе.

Учитывая специфику проекта, над которым сейчас работаю(справочная система), этот плагин оказался просто незаменимым, и я использую 90% его функционала с превеликим удовольствием. И я до сих пор не видел такой же мощной альтернативы.



Если вам нужно отрисовать в брауезере просто дерево, то, конечно можно использовать и другие плагины, или вовсе написать это самому и лаконично, но для более широкого функционала — JsTree — просто отличный вариант.

Что мы имеем?


  • Построение дерева на основе html разметки, json и xml формата
  • Drag & drop с тонкой настройкой возможности перемещения нодов по дереву
  • Динамическое добавление/удаление/изменение нодов
  • Возможность построения нескольких деревьев на одной странице и манипуляция нодами между этими деревьями
  • Возможность присвоения нодам произвольных типов (file, folder, drive, да какой угодно), и указать отдельное поведения для каждого
  • Поддержка тем оформления (на скрине в начале статьи пример того, как это реализовал я)
  • Управление с клавиатуры
  • Использование нативных и кастомных чекбоксов
  • AJAX подгрузка нодов, запоминание состояния дерева
  • Плагин красиво и читабельно написан, позволяет писать дополнительные плагины к нему и без проблем кастомизировать.
  • Удобная система байндингов для обработки событий
  • Мультиязычность
  • Управление анимацией раскрытия
  • Поиск по дереву
  • Кастомное контекстное меню
  • Поддержка браузеров: IE 6+, Firefox 2+, Safari 3+, Opera 9+, Chrome
  • Мини-фича, которая меня особенно порадовала — плагин wholerow — выделения нода во всю ширину. А-ля mac style


Как оно работает?


Отличные и понятные примеры можно найти на официальном сайте. Подробная документация так же присутствует.

Чтобы начать работу, нам нужно подключить jquery.js, jstree.js(180КБ в несжатом виде) и папку с темами(подключается плагином сама, достаточно положить ее рядом)

Приведу пример использования дерева на основе JSON.

HTML:
<div id="tree"></div>

JQuery:
$("#tree")
	.bind("before.jstree", function (e, data) {
		// байндинг на событие перед загрузкой дерева
	})
	.jstree({ 
		// Подключаем плагины
		"plugins" : [ 
			"themes","json_data"
		],
		"json_data" : { 
			"ajax" : {
				"url" : "tree.php", // получаем наш JSON
				"data" : function (n) { 
					// необходиый коллбэк
				}
			}
		},
	})
	.bind("select_node.jstree", function(e, data){
		// байндинг на выделение нода
                // укажем ему открытие документа на основе якорей
                window.location.hash = "view_" + data.rslt.obj.attr("id").replace("node_","");
	})
});

Получаем простое дерево в духе примеров

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

Подробнее
Реклама
Комментарии 47
  • +5
    JsTree очень хороший плагин, тоже использовал его.
    Мне последнее время больше нравится dynatree, с производительностью там намного лучше.
    • +1
      Да, я знакомился с этим плагином когда начинал проект. Мне он показался менее «интуитивным». По скорости работы не жалуюсь на JsTree. 10к нодов отрисосывается не более пары секунд.
      • +1
        Прекрасно, надо будет поглядеть, что там нового. Раньше всё было хуже…
        • 0
          А как 10к по памяти? B есть ли примерчик с большими числами?
          • 0
            Завтра набросаю пример.
            • +1
              Память не мерял, со скоростью немного преувеличил. На 10к узлах браузеру становится чутка плохо. 5к узлов строит 5 секунд. Пример на 5к узлов
          • +1
            да, dynatree классный плагин!
          • +1
            Плагин отличный, но есть несколько «но». При выпуске последних версий (тех, что на гитхабе) автор очень сильно перелопатил все ядро. В результате на и так не богатую документацию на официальном сайте наложилось еще и то, что она просто не соответствует последней версии. Многие описанные ф-ии не работают или работают совершенно не очевидным образом. Иногда мне приходилось лазить по исходникам, чтобы понять как сделать ту или иную операцию, а иногда даже их править. Как вариант, можно использовать последнюю версию с официального сайта. В целом же плагин отличный, других аналогов ему так и не нашел.
            • 0
              Автора не хило шпигуют репортами и по помему мнению он достаточно оперативно с ними разбирается. Документацию обещает выложить в скором времени.
              • 0
                *по моему
                • 0
                  Не знаю как сейчас, но год-полтора назад, все двигалось очень медленно. Об этом свидетельствует то, что на оф.сайте как висела «pre1.0 fixed», так и висит (более года). Один разработчик все-таки.

                  Но я искренне надеюсь, что все идет в лучшую сторону. Проект хороший и полезный. [Скрестил пальцы.]
              • 0
                в одном проекте долго мучался,
                очень нужно было скрестить JsTree и JGrid
                былоб здорово если б кто написал такой плагин
                • 0
                  В чем проблема? JsTree спокойно инициализируется «на лету» в нужный блок. Или есть что-то особенно ужасное?
                • 0
                  Не знаю требований вашего проекта… Могу предложить глянуть на jqGrid.
                  Там есть группировка строк (со сверткой списков) и иерархические таблицы.

                  Демо можно глянуть тут (см. раздел «Grouping» и «Hierarchy»).
                  Оф.сайт: www.trirand.com/blog/
                  • 0
                    суть функционала, который мне пришлось реализовать в следующем:
                    есть правое окно — дерево и левое окно таблица, по навигации в дереве отображается соответствующие элементы таблицы, на разных уровнях ветвей может быть разная структура таблицы.

                    естественно можно сделать используя JsTree & JqFrid, именно я этим и занимался… и потратил много сил и времени, так как не специалист в JS.

                    Вот если бы была бы нормальная единая компонента, то многим разработчикам облегчилась бы жизнь.

                    Вот только и всё, что я хотел подчеркнуть своим предыдущем постом.
                • +1
                  в одном проекте долго мучался,
                  очень нужно было скрестить JsTree и JGrid
                  былоб здорово если б кто написал такой плагин
                  • 0
                    Сегодня день дублирующихся комментариев, Чип и Дейл кого-то спасают поди…

                    По делу — жаль, что нет (или я не нашел) из коробки возможность на разных уровнях ставить разные иконки (на первом одну, на втором вторую, на третьем и далее — третью).
                    • +1
                      При построении дерева достаточно передать нодам параметр rel и указать в нем тип иконки (folder, file, etc). А при инициализации описать эти типы

                      Пример инициализации
                      $(function () {
                      
                      $("#reference-view")
                      	.jstree({ 
                      		"plugins" : [ 
                      			"themes","json_data","ui","core","types","wholerow"
                      		],
                      		"json_data" : { 
                      			"ajax" : {
                      				"url" : "/alpha/tree.json",
                      				"data" : function (n) { 
                      					
                      				}
                      			}
                      		},
                              "types" : {
                      			"types" : {
                      				"file" : {
                      					"icon" : {
                      						"image" : "file.png"
                      					}
                      				},
                      				"folder" : {
                      					"icon" : {
                      						"image" : "folder.png"
                      					}
                      				},
                      				"drive" : {
                      					"icon" : {
                      						"image" : "drive.png"
                      					},
                      					"start_drag" : false,
                      					"move_node" : false,
                      					"delete_node" : false,
                      					"remove" : false
                      				}
                      			}
                      		},
                      	});
                      });
                      
                  • 0
                    мне тоже этот плагин нравится,
                    но не нравится что совершенно не понятно как к нему написать плагин (у меня не получилось) — и доки по этому поводу нет.

                    Нужен был функционал постраничной разбивки. т.е. если узле 1000 вложенных нодов, то получается не уютное дерево, хотелось бы внутри узла большое количество нодов разбивать постранично
                    • 0
                      С докой есть задержки, согласен. Напишите issue на гитхабе. Автор оперативно отвечает. Меня функционал из коробки пока что полностью устраивает.

                      Я попытался представить постраничную выдачу нодов в дереве. Не вышло :)
                      • +1
                        Если к узлу крепится 1000 нодов (даже 100) уже что-то не так с идеологией и UI. Я не могу представить себе такую реальную задачу :(
                        • –1
                          реальная задача: есть дерево сайта, есть нода «новости», в которой есть новости за последние три-четыре года в количестве около 1000 штук
                          • +2
                            Так зачем их вешать в дереве, если можно отображать в главном блоке? А в дереве хранить лишь структуру разделов.
                            Ну или вполне логичное решение — группировать новости по папкам, которые являются месяцами определенного года, например.
                            • 0
                              Ну да. 1000 явно проблема с продуманностью UI и структурирования.

                              з.ы. Спасибо вам за 'большой' пример. 5К реально туговато крутится и открывается заметно тормознуто.
                              Ну тут сам и объем приличный в dom загонять, да и задач таких реально вряд ли найдешь.
                              Нужно (под)ветки динамически грузить-выгружать
                              • 0
                                Замечу, что на открытии мы получаем те же 5к. То есть если бы я прогружал изначальные 5к в древовидном формате, то прогруженные узлы открывались бы сразу.
                      • 0
                        А я вот пользовался и был крайне разочарован производительностью. 2-3 секунды отрисовки при паре тысяч нод на относительно современном компе и мучительное ожидание по 15 секунд на стареньких селерончиках поставило для меня крест на этой библиотеке. Переписал дерево на flash — меньше секунды отрисовки на любом железе.
                        • 0
                          Давно тестили производительность плагина? Я таких ужасов не наблюдал. Да и подгружать столько нодов это достаточно сурово. Использую ajax подгрузку нодов при открытии узла.
                          • 0
                            2 месяца назад. Загружать сразу всё было необходимо так как использовался плагин checkbox, а он чисто логически не дружит с постапенной загрузкой. Он же не может поставить галку или снять её не зная всех своих детей. Это можно было обойти переносом этого функционала на сервер, но сервер и так нагружен. А флешёвое дерево оказалось очень просто в реализации.
                            • 0
                              Да, можно перенести это на сервер, но так же можно при щелчке по чекбоксу прогрузить детей и чекнуть их. Так и делаю в своем проекте.
                        • 0
                          Активно использовал год назад. В дополнение к отмеченной бедности документации и не соответствия оной актуальному коду, добавлю, что тогда я испытал большие проблемы с настройкой внешнего вида.

                          Проблема произрастала из того, что часть стилей была жестко «зашита» в код, причем в разных местах, и при отрисовке элементов использовались инлайн определения стилей.

                          [Подробнее:
                          Задача тогда стояла, сделать полноценное управление деревом с клавиатуры. Т.е. курсором бегаем по списку, раскрываем/сворачиваем, удаляем/добавляем, выделяем и т.п.
                          Собственно с управлением проблем не было, а вот нормально отрисовать выделение элемента цветом фона было проблемой. Исходя из задания курсор должен был быть во всю ширину элемента дерева. Но при таком подходе у него постоянно «прыгала» высота от элемента к элементу. Победить так и не смог.
                          ]

                          Надуюсь в последней версии это исправили, или хотя бы исправят. Нельзя стили и определения размеров элементов запихивать в код.
                          • 0
                            *надеюсь
                            • 0
                              Небольшая демка. Выделение нода во всю ширину дерева. Плагин называется wholerow
                              • 0
                                В этом выделении, правда. есть небольшой баг. При изменении размера блока с деревом(resize) это выделение не пересчитывается по ширине. Хотя если после открыть еще какой нибудь нод, то пересчет происходит. Отправил это автору. Нов принципе и самому вылечить не проблематично.
                                • 0
                                  Вспоминаю…
                                  Этот плагин в каком-то виде был и год назад. Он мне не подошел тогда, т.к. у меня некоторые пункты списка были длинные (читай многострочные). И для этого случая он совсем не годился.

                                  Пытался как-то исправить это изменением стилей и разметки самого элемента. Тогда и столкнулся с тем, что многие параметры жестко забиты в основной код.


                                  • 0
                                    Оставил заявку на ГитХабе.
                              • 0
                                «столько нодов», «выделения нода» — откуда такое написание?
                                Я бы написал, столько нод, выделение ноды и тп.
                                • –1
                                  Node => Nodes, Нод => Ноды
                                  Не вижу ничего ужасного.
                                  • +1
                                    Node => Нода — мне в такой интерпретации всегда попадался перевод.
                                    • 0
                                      Дело привычки, не более. Мне в мужском роде привычнее. Меня понимают.
                                • 0
                                  Когда то в админке хотел использовать этот плагин (JsTree), но чем-то не устроило.
                                  тем более он тогда еще свежий был совсем.
                                  Сейчас посмотрел и вспомнил.
                                  Невозможно было автоматически превращать простую ноду в папку. Т.е. невозможно перенести ноду в ноду чтобы родительская нода автоматом превращалась в папку.
                                  Тогда пришлось писать килобайты своего tree.
                                  Ради интереса посмотрел демки. эта возможность либо не появилась либо ее нет в демо. Глубже не копал.
                                  • 0
                                    Это возможно и работает нормально. В примерах автор придерживается логики, что нельзя файл сделать родителем(блокирует перенос в него). Но не отсекает эту реализацию.
                                  • 0
                                    Спасибо. Копну глубже
                                    • 0
                                      Исправьте:
                                      Динамическо добавление/удаление/изменение нодов
                                    • 0
                                      Копнул глубже
                                      Jstree показалась тяжелой по сравнению с dynatree.
                                      В конце концов решил оставить свое решение, написанное под конкретную задачу.
                                      Но был бы тогда знаком с dynatree, остановился бы на нем. Это личное мнение.

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