11 сентября 2012 в 13:01

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_","");
	})
});

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

Пожалуй не буду описывать простыню из других примеров. Вы можете ознакомится с ними на официальном сайте, а вот если есть какие либо конкретные вопросы по теме, с удовольствием отвечу.
Артур Кох @dudeonthehorse
карма
72,7
рейтинг 0,0
Email developer
Самое читаемое Разработка

Комментарии (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
        см ниже
    • 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
        спасибо!
  • 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, остановился бы на нем. Это личное мнение.

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