Javascript.RU

Удобное дерево с AJAX-подгрузкой

Эта статья показывает, как написать простое и удобное дерево с AJAX-подгрузкой узлов.

Она основана на материалах грамотное javascript-дерево и интеграция AJAX в интерфейс.

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

Для начала оформим дерево в виде компоненты интерфейса. Инициализацию будет осуществлять функция tree, которая получает два параметра:

id
ID узла DOM, который служит контейнером для дерева
url
Адрес, с которого подгружать узлы при помощи AJAX-запроса

Код ниже полностью описывает дерево, за исключением функции AJAX-подгрузки узлов load, которая будет разобрана ниже. Он полностью соответствует оригинальной статье, только чуть реорганизован.

Все, что он делает - это отслеживает клик на элементе element.onclick, содержащем дерево, получает узел по event.target и, если узел не содержит элементов и еще не было попыток загрузки - то получает его с сервера вызовом load. Саму функцию загрузки load разберем дальше в статье.

Функции hasClass и toggleNode - вспомогательные, для индикации скрытия-открытия ветки дерева через CSS-класс.

function tree(id, url) {
	var element = document.getElementById(id)

	/* вспомогательная функция */
	function hasClass(elem, className) {
		return new RegExp("(^|\\s)"+className+"(\\s|$)").test(elem.className)
	}

	function toggleNode(node) {
		// определить новый класс для узла
		var newClass = hasClass(node, 'ExpandOpen') ? 'ExpandClosed' : 'ExpandOpen'
		// заменить текущий класс на newClass
		// регексп находит отдельно стоящий open|close и меняет на newClass
		var re =  /(^|\s)(ExpandOpen|ExpandClosed)(\s|$)/
		node.className = node.className.replace(re, '$1'+newClass+'$3')
	}

	function load(node) {/* ... загрузить узел с сервера, код далее ... */}

	element.onclick = function(event) {
		event = event || window.event
		var clickedElem = event.target || event.srcElement

		if (!hasClass(clickedElem, 'Expand')) {
			return // клик не там
		}

		// Node, на который кликнули
		var node = clickedElem.parentNode
		if (hasClass(node, 'ExpandLeaf')) {
			return // клик на листе
		}

		if (node.isLoaded || node.getElementsByTagName('LI').length) {
			// Узел уже загружен через AJAX(возможно он пуст)
			toggleNode(node)
			return
		}


		if (node.getElementsByTagName('LI').length) {
			// Узел не был загружен при помощи AJAX, но у него почему-то есть потомки
			// Например, эти узлы были в DOM дерева до вызова tree()
			// Как правило, это "структурные" узлы
			// ничего подгружать не надо
			toggleNode(node)
			return
		}

		// загрузить узел
		load(node)
	}
}

Чтобы инициализовать дерево - достаточно запустить функцию tree на DOM-контейнере для дерева.

Вспомним, что согласно структуре дерева - для этого служит элемент UL.

Можно взять дерево с уже готовыми узлами, а можно и пустое дерево с единственным корневым узлом "Каталог", вот такого вида (просто картинка, рабочий вариант далее):

Наше дерево:
  • Каталог

HTML-код:

Наше дерево:
<ul class="Container" id="tree">
  <li class="Node IsRoot IsLast ExpandClosed">
    <div class="Expand"></div>
    <div class="Content">Каталог</div>
    <ul class="Container">
    </ul>
  </li>
</ul>

Яваскрипт-вызов для инициализации дерева:

tree('id', '/ajax/data.php')

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

Для этого нужно реализовать метод load и необходимые вспомогательные функции.

При описании дерева была предусмотрена AJAX-индикация, а в статье по интеграции AJAX в интерфейс - стандартные методы и последовательность вызовов. Остается применить их для дерева.

...

function load(node) {

	/*
	  код этих трех функций - 
      как в статье по интеграции AJAX в интерфейсы 
    */ 
	function onSuccess(data) {... }
	function onAjaxError(xhr, status) {... }
	function onLoadError(error) { ...}

    /*
	  функция showLoading использует способ 
      AJAX-индикации через CSS из этой же статьи.
    */
	function showLoading(on) {
		var expand = node.getElementsByTagName('DIV')[0]
		expand.className = on ? 'ExpandLoading' : 'Expand'
	}

	function onLoaded(data) {

		for(var i=0; i<data.length; i++) {
			var child = data[i]
			var li = document.createElement('LI')
			li.id = child.id

			li.className = "Node Expand" + (child.isFolder ? 'Closed' : 'Leaf')
			if (i == data.length-1) li.className += ' IsLast'

			li.innerHTML = '<div class="Expand"></div><div class="Content">'+child.title+'</div>'
			if (child.isFolder) {
				li.innerHTML += '<ul class="Container"></ul>'
			}
			node.getElementsByTagName('UL')[0].appendChild(li)
		}

		node.isLoaded = true
		toggleNode(node)
	}


	showLoading(true)


	$.ajax({
		url: url,
		data: node.id,
		dataType: "json",
		success: onSuccess,
		error: onAjaxError,
		cache: false
	})
}
...

Для начала заметим, что все вспомогательные функции объявлены внутри load. Это удобно, т.к. автоматически дает им доступ к узлу node.

Можно вызвать новую загрузку load, не дожидаясь окончания текущей - конфликта доступа не произойдет, т.к обработчики через замыкание привязаны к загружаемому узлу.

Оригинальная функция здесь, пожалуй, всего одна - это onLoaded. Она принимает данные с сервера в виде массива объектов-детей:

[
  { id: 1, title: 'Node 1', isFolder: 1},
  { id: 2, title: 'Node 2', isFolder: 1},
  { id: 3, title: 'Node 3', isFolder: 0}
]

Из этих объектов создается DOM-структура дерева.

Никаких новых обработчиков событий при создании узлов на них не навешивается, т.к структура дерева использует один единый обработчик на контейнере.

Жмите на +, чтобы загрузить детей с сервера.

На стороне сервера используется скрипт, который сначала полсекунды спит (чтобы продемонстрировать индикацию загрузки), а затем возвращает 3 узла с последовательными номерами и примерно 33%-ным шансом того, что узел является листовым (isFolder=0).

Наше дерево:
  • Каталог

Вы также можете:


Автор: igor (не зарегистрирован), дата: 30 апреля, 2009 - 20:25
#permalink

А как изменить этот скрипт, чтобы в скрытом фрейме отправлял запрос вместо аякс, а то в ИЕ6 по умолчанию отключен activeX и не отсылается или запрашивает подтверждение для включенияактивного содержимого?


Автор: Kosty, дата: 8 мая, 2009 - 19:54
#permalink

Осталось еще добавить фунуцию перетаскивания узлов в дереве и между несколькими деревьями и будет перфект контрол


Автор: Илья Кантор, дата: 8 мая, 2009 - 20:43
#permalink

Да, я это когда-то все делал. В принципе, никаких проблем - статья про drag'n'drop на сайте есть. Все что надо - замечательно реализуется.


Автор: TT (не зарегистрирован), дата: 19 мая, 2009 - 20:54
#permalink

Статья очень классная, спасибо за неё!
Но у меня есть один вопрос - как в php'шном скрипте здесь узнать значение узла по которому кликнули? (т.е. то что значится как Node 1,2,3)?


Автор: Илья Кантор, дата: 19 мая, 2009 - 22:56
#permalink

Эта информация содержится в ajax-запросе:

.ajax(
...
data: node.id
...
)

Автор: ТТ (не зарегистрирован), дата: 20 мая, 2009 - 00:21
#permalink

Если что - извиняюсь за глупые вопросы ><
то что оно в этой строке содержится я разобралась. А вот как этот node.id в php вытащить?... перечитала учебника 3 и что-то не разобралась( статьи про jquery тож не помогли(
дай хотябы ссылку на то где это объясняется


Автор: Гарик (не зарегистрирован), дата: 30 мая, 2009 - 16:43
#permalink

Илья, огромное спасибо за статью!
Не подскажите, как сделать подгрузку узлов для бесконечного дерева из БД.


Автор: Илья Кантор, дата: 30 мая, 2009 - 22:52
#permalink

Модифицируйте PHP-скрипт, чтобы вместо генерации узлов он брал их из базы.


Автор: Илья Кантор, дата: 12 июня, 2009 - 11:03
#permalink

Если у вас возникают проблемы с node.id - убедитесь, что у каждого DOM-узла дерева есть ID. Это и есть node.id.


Автор: Гарик (не зарегистрирован), дата: 22 июня, 2009 - 20:18
#permalink
function onLoaded(data) {
    for(var i=0; i<data.length; i++) {
    var child = data[i]
               
    var li = document.createElement('LI')
    li.className = "Node Expand" + (child.isFolder ? 'Closed' : 'Leaf')
    if (i == data.length-1) li.className += ' IsLast'
// через здесь узлам добавил id
    li.id = child.id
//
    li.innerHTML = '<div class="Expand"></div><div class="Content">'+child.title+'</div>'
    if (child.isFolder) {
    li.innerHTML += '<ul class="Container"></ul>'
    }
 node.getElementsByTagName('UL')[0].appendChild(li)
                
  }
 node.isLoaded = true
 toggleNode(node)
}

Ещё раз респект и уважуха Илья! Уже присоветовал сайт пацанам на работе.


Автор: Илья Кантор, дата: 22 июня, 2009 - 22:13
#permalink

Оо! Большое спасибо за багрепорт.

Как я понял - все дело было в том, что загружаемым узлам не ставился id, да ?

Исправил в тексте статьи, обновил скрипты и архив.


Автор: Гарик (не зарегистрирован), дата: 26 июня, 2009 - 03:07
#permalink

Да, и ещё такой вот запрос:

$.ajax({

//через эту вот строку id узла передаётся в data.php
url: url + '?id=' + node.id,
//без неё в data.php ничего не передаётся

data: node.id, // а что это за "беда" и с чем её едят?
dataType: "json",
success: onSuccess,
error: onAjaxError,
cache: false
})

Автор: Гость (не зарегистрирован), дата: 5 февраля, 2010 - 08:05
#permalink

Добавила, что-то не заработало Sad


Автор: MikhailGirshberg (не зарегистрирован), дата: 27 июля, 2010 - 09:10
#permalink
$.ajax({
      url: url,
// правильнее так:
      data: {id: node.id},
      dataType: "json",
      success: onSuccess,
      error: onAjaxError,
      cache: false
    })

источник:http://api.jquery.com/jQuery.ajax/


Автор: Гость (не зарегистрирован), дата: 27 июня, 2009 - 20:36
#permalink

Как исправить функцию onLoaded, что бы это дерево не было бесконечным?


Автор: Илья Кантор, дата: 20 июля, 2009 - 09:14
#permalink

Дерево бесконечное только потому, что ПХП-скрипт на сервере возвращает все новые узлы.
В реальной жизни все будет конечное.. Обычно


Автор: Гость (не зарегистрирован), дата: 27 июня, 2009 - 22:38
#permalink

разобрался как работает... алгоритм тут хитрый


Автор: thunder2, дата: 19 июля, 2009 - 12:53
#permalink

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


Автор: thunder2, дата: 20 июля, 2009 - 10:33
#permalink

Со html структорой разобрался, тепер надо поразбираться с функциями


Автор: Антонн (не зарегистрирован), дата: 31 августа, 2009 - 10:27
#permalink

Спасибо за дерево, отличная штука!

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


Автор: Антонн (не зарегистрирован), дата: 31 августа, 2009 - 10:47
#permalink

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

function onLoaded(data) {

Это примерно 60 строка tree.js


Автор: Илья Кантор, дата: 31 августа, 2009 - 11:28
#permalink

В том-то и дело, что ничего не надо добавлять.
onclick один на все дерево.

Просто вставляете узел и оно будет работать.


Автор: 4vanger, дата: 13 октября, 2009 - 11:19
#permalink

Реализовывал свой аналогичный компонент. Во многом применял похожие приёмы.
Единственное чем недоволен - тем что использовал таблицы вместо списков. Но было требование, что новое дерево должно быть совместимо по формату с предыдущей версией.
Очень полезная функция - инициализация узлов дерева on demand - демка (из JSON очень быстро строится дерево с 500.000.000 узлами). Как показала практика - существует очень много пользователей, которым очень нужна эта функция.


Автор: Zorro2 (не зарегистрирован), дата: 24 ноября, 2009 - 14:04
#permalink

Я кликнул мышкой по надписи Node 2, как определить, описание какой ветки нужно вывести рядом? Я так понял Node 2 - это DIV, значить при создании нового узла, надо присваевать второму диву который является классом content, идентификатор (например "div_"+child.id), потом вешать на него обработчик onclick, и дальше обрабатывать аяксом элемент в котором должно появиться описание данного узла, можно и с пхп, но прийдеться перегружать страницу, а отсюда проблема сохранения состояния дерева!

Если я не прав, то поправьте меня, просто не вижу смысла в этом дереве, если оно просто открывает и закрывает ветки, а просмотреть информацию по данной ветки, у него, как я понял мозгов нет!

Далее--------------


Автор: TT (не зарегистрирован), дата: вт., 19/05/2009 - 20:54
#permalink

Статья очень классная, спасибо за неё!
Но у меня есть один вопрос - как в php'шном скрипте здесь узнать значение узла по которому кликнули? (т.е. то что значится как Node 1,2,3)?

* Ответить

Автор: Илья Кантор, дата: вт., 19/05/2009 - 22:56
#permalink

Эта информация содержится в ajax-запросе:
Выделить все

.ajax(
...
data: node.id
...
)

это про то что я писал выше, человек спрашивал, как отловить нажатие на надписе, и узнать по какой именно был клик! Вопрос автору: описанный мною вариант имеет смысл, или я что-накрутил? Второй день копаюсь в коде, с некоторыми приколами так и не разобрался!
Вопрос номер 2: как сохранить состояние дерева, при перезагрузке страницы! Все открытые ветки пересылать по сессии, а потом циклом выводить, и присваивать каждой открытой function() { tree("tree", "data.php") }, это, мне кажеться, и вам понятно что полная чуш!

Есть какие нить предложения?

Заранее благодарен!


Автор: snick (не зарегистрирован), дата: 9 декабря, 2009 - 10:19
#permalink

Спасибо за отличный скрипт!
Но не магу разобраться с одним моментом
Как можно скриптом скрыть и загрузить заново список детей в одной из папок?
В моем приложение это дерево ещё и редактируеться


Автор: snick (не зарегистрирован), дата: 9 декабря, 2009 - 10:21
#permalink

И ещё как можно средствами javascript открыть одну из папок


Автор: Надежда_ (не зарегистрирован), дата: 4 февраля, 2010 - 13:20
#permalink

Спасибо большое за деревко!

Подскажите, пожалуйста, почему у меня $id не передаётся? Подставляю в запрос циферку - работает, только, конечно же, один и тот же уровень всё время.
ЗЫ Если записываю его в имя нода, то в названии появляется.

$id = $_GET['id'];
...
$sql = "SELECT reg_id, region, pid, lvl FROM vision.`vision_region` WHERE pid = ".$id." ORDER BY region";

$result = mysql_query($sql);

if (mysql_num_rows($result) > 0){

while ($row = mysql_fetch_array($result)) {
$id_node = $row['reg_id'];
$nam_nod = $row['region'];
if (!$row['lvl'] = '0') {$isFolder = 1;} else {$isFolder = 0;}
$node[] = "{id: '$id_node', title: '$nam_nod', isFolder: $isFolder}";

Автор: AlexBigHorn (не зарегистрирован), дата: 24 февраля, 2010 - 17:00
#permalink

Вызов $.ajax автоматически интерпретирует ответ сервера как JSON - и если с этим проблемы, то хотя XmlHttpRequest выполнился успешно, но $.ajax вызывает коллбэк для ошибки и ставит status="parsererror".

как раз такая ситуация.
консоль firebug'a показывает

xhr.status 200
из data.php возвращается
[{ id: 1, title: 'Node 1', isFolder: 1},{ id: 2, title: 'Node 2', isFolder: 1},{ id: 3, title: 'Node 3', isFolder: 0}]

но парсер говорит что некорректные данные с сервера...
в чем может быть затык?


Автор: Денис_ (не зарегистрирован), дата: 20 мая, 2010 - 19:50
#permalink

Ошибки не будет, если в ответе и ключи и их значения будут взяты в двойные кавычки.

{"id" : "1", "title": "Node 1", "isFolder": "1"}


Автор: AlexBigHorn (не зарегистрирован), дата: 24 февраля, 2010 - 18:32
#permalink

Нашлась затыка.
С новой библиотекой jquery 1.4.2 не работает пример.
Работает с 1.3.2

не смотрел, но видимо onAjaxError по другому работает..


Автор: Алексей Гость (не зарегистрирован), дата: 31 марта, 2010 - 18:33
#permalink

При выполнении примера вываливается ошибка $ is not defined в tree.js строка 81 $.ajax({
....

Что у меня не так? Куда копать?


Автор: Денис_ (не зарегистрирован), дата: 20 мая, 2010 - 19:59
#permalink

Подключите jquery в тот же файл, куда подключили tree.js


Автор: THERE (не зарегистрирован), дата: 3 июня, 2010 - 18:19
#permalink

Илья, спасибо большое за сайт и статьи.

Мелкий баг:

Вы также можете:
* Посмотреть дерево на отдельной страничке
* Скачать архив со всеми исходниками и картинками

На слове "Скачать " ссылка не та.


Автор: MikhailGirshberg (не зарегистрирован), дата: 27 июля, 2010 - 09:16
#permalink

Как заметили некоторые коллеги, в формировании запроса есть ошибка...

$.ajax({
      url: url,
// правильно так:
      data: {id: node.id},
      dataType: "json",
      success: onSuccess,
      error: onAjaxError,
      cache: false
    })

источник:http://api.jquery.com/jQuery.ajax/


Автор: anon (не зарегистрирован), дата: 14 ноября, 2010 - 16:44
#permalink

После манипуляций с библиотекой jQuery (пример работает с версией 1.3.2), в эксплорере пример заработал, а в опере по прежнему пишет: Ошибка parsererror :Некорректные данные с сервера.
В чем может быть проблема?Разве этот скрипт не кроссбраузерный?


Автор: Гость (не зарегистрирован), дата: 14 ноября, 2010 - 22:57
#permalink

Та же беда что у Надежда_ (не зарегистрирован), не хочет работать с id из базы


Автор: Гость (не зарегистрирован), дата: 14 ноября, 2010 - 23:15
#permalink

Никак не пойму, почему если id генериться автоматически - скрип работает, если id берем из базы, то получаем "Ошибка parsererror: Некорректные данные с сервера"


Автор: Гость (не зарегистрирован), дата: 15 ноября, 2010 - 00:57
#permalink

Ключи взятые в двойные кавычки не помагают Sad
На сколько я понял, дело в типе данных, когда берем id из базы, переменная строковая, а должна быть int, исправляется с помощью settype().


Автор: Гость (не зарегистрирован), дата: 15 ноября, 2010 - 01:01
#permalink

И внесите, пожалуйста, в архив эти изменения:

$.ajax({
	 
	//через эту вот строку id узла передаётся в data.php
	url: url + '?id=' + node.id,
	//без неё в data.php ничего не передаётся

Автор: Антон_83 (не зарегистрирован), дата: 19 ноября, 2010 - 10:02
#permalink

Для корректной работы с библиотекой jquery 1.4.2, нужно
ключи и их значения взять в двойные кавычки
{"id" : "1", "title": "Node 1", "isFolder": 1}, но значение ключа "isFolder" не нужно
брать в "", а то всегда будут узлы.


Автор: Pirks (не зарегистрирован), дата: 28 января, 2011 - 20:21
#permalink

Для jquery-1.4.4., у меня заработало так:

как правильно заметил MikhailGirshberg

$.ajax({
      url: url,
// правильно так:
      data: {id: node.id},
      dataType: "json",
      success: onSuccess,
      error: onAjaxError,
      cache: false
    })

и в data.php

$node[] = '{"id":"'.$id.'", "title": "Node '.$id.'", "isFolder":'.$isFolder.'}';

Автор: Гость (не зарегистрирован), дата: 21 марта, 2011 - 14:38
#permalink

Отличный скрипт! Автору респект.
Попытался разобраться при использовании его в форме. Что-то не выходит у меня каменный цветок.
Добавляю

input type="checkbox"

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


Автор: Гость (не зарегистрирован), дата: 25 апреля, 2011 - 23:23
#permalink

сбор данных из формы

var data = '';

	f = document.getElementById(form_id);

	if (f == null)
	{
		alert ('Ошибка работы с формой id=' + fname);
	}

	var len = f.elements.length;

	for(var i=0;i<len;i++)
	{
		var key = f.elements[i].name;
		var val = f.elements[i].value;
		var t = f.elements[i].type;

		if (!key || t == 'button')
		{
			continue;
		}

		// обработка нестандартных значений полей
		if (t == 'checkbox' || t == 'radio')
		{
			if (f.elements[i].checked != true)
			{
				continue;
			}
		}
		// EOL


		if (data && data.length > 0)
		{
			data += '&';
		}

		data += key + '=' + encodeURIComponent(val);
	}

Автор: Гость (не зарегистрирован), дата: 29 апреля, 2011 - 10:29
#permalink

Данные то собрались, а как их в POST кинуть?


Автор: hamster (не зарегистрирован), дата: 2 июня, 2011 - 06:28
#permalink

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


Автор: kravru, дата: 16 июня, 2011 - 04:25
#permalink

Подскажите где найти простой пример кода на AJAX:
есть таблица групп с подгруппами
в форме 2 селекта, в 1-м выбирается группа, а во 2-й подгружаются подгруппы выбранной группы.


Автор: Гость, дата: 4 июля, 2011 - 12:25
#permalink

День добрый.
Хелп!!!

Сделал первый вывод дерева из базы.
Какой вариант есть чтобы сделать вывод последующих веток был уже зависим от содержания родительской???


Автор: Владимир_ (не зарегистрирован), дата: 1 декабря, 2011 - 22:24
#permalink

Здравствуйте!!!

Очень интересная статья, пытаюсь сделать, чтобы скрипт заработал на моем виртуальном сервере, но при нажатии на "плюсик" отображается картинка загрузки и всё. Прочитал все комментарии, вносил соответствующие исправления в разных комбинациях.

У меня такой вопрос, думаю что не у меня одного, подскажите пожалуйста:
в файле tree.html есть ссылка на /misc/jquery.js, однако такого файла в архиве с исходниками нет. Может быть в этом проблема? И что должно быть в этом файле?


Автор: maxtrime (не зарегистрирован), дата: 17 мая, 2012 - 19:52
#permalink

была та же проблема. с добавлением файла всё наладилось


Автор: GreyDog, дата: 9 октября, 2012 - 11:00
#permalink

МОжно ли в узлах (паротив) дерева добавить пару кнопок?


Автор: Maxsim-v (не зарегистрирован), дата: 17 августа, 2014 - 12:42
#permalink

Здравствуйте, а как сделать, чтобы вот только обновил, страницу, а оно само выдвигалось, тоесть что бы не надо было на плюсик жать.!


Автор: Слайдер (не зарегистрирован), дата: 17 апреля, 2015 - 23:34
#permalink

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


Автор: Андрей Кузьменко (не зарегистрирован), дата: 11 октября, 2016 - 16:59
#permalink

Здравствуйте, простите за тупой может вопрос, не могу понять как считываеться id для GET запроса. Подскажите пожалуйста как передать ид в php


Автор: Андрей Кузьменко (не зарегистрирован), дата: 11 октября, 2016 - 17:01
#permalink
$.ajax({
			url: url,
                        type:"GET",
			data: ({id:node.id}),
			dataType: "json",
			success: onSuccess,
			error: onAjaxError,
			cache: false
		})

Сделал так но ошибку выводит.


Автор: Гость (не зарегистрирован), дата: 24 января, 2017 - 22:06
#permalink

Добрый день.
Есть база:
id parent title note
1 0 Заголовок1 описание
2 0 Заголовок2 описание
3 1 Заголовок3 описание
4 2 Заголовок1 описание

У корневых элементов parent = 0
Далее идут элементы уже с parent корневых и так далее. Получается древовидная структура.

Как будет выглядеть код php , который мне сформирует сначала корневые
элементы с parent 0 (верхний уровень) и код php, который по ID будет подгружать иp этой базы дочерние элементы ?

Если не трудно дайте плиз листинг


Автор: Гость (не зарегистрирован), дата: 26 января, 2017 - 11:04
#permalink

Подскажите пожалуйста как раскрывать элементы дерева по клику на название title, а не на +


Автор: Гость (не зарегистрирован), дата: 18 февраля, 2019 - 09:00
#permalink

Ребята, я новичок, поэтому учусь на подобных сайтах.

Из вышеуказанных скриптов, я скопировал код HTML и создал файл html, а код для CSS скопировал и создал отдельный файл .css, но ничего не работает Sad


Автор: Гость2 (не зарегистрирован), дата: 21 февраля, 2019 - 09:33
#permalink

Ребята помогите со скриптом. Суть в том, что я хочу написать в поле для поиска какое нибудь слово, которое находится в списке меню. Из обычного списка выходить слово, но когда слово находится внутри ("tree" - дерево - этот скрипт для меню под дерево я взял прямо с данной темы) скрипт не находит это слово.

==

.searchinput {
xbackground-image: url('/css/searchicon.png');
xbackground-position: 8px 6px;
xbackground-repeat: no-repeat;
width: 91%;
font-size: 14px;
padding: 6px 6px 6px 40px;
padding: 6px;
border: 1px solid #ddd;
margin: 0 0 20px 10px;
}

function filterContent(elmnt) {
var x, i, val, show, showh2, showbr;
val = elmnt.value;
x = document.getElementById("leftmenuinnerinner").getElementsByTagName("*");
for (i = 1; i < x.length; i++) {
if (x[i].tagName == "H2") {
if (showh2) {
if (show == false) {
showh2.style.display = "none";
} else {
showh2.style.display = "block";
}
}
show = false;
showh2 = x[i];
}
if (x[i].tagName == "BR") {
if (showbr) {
if (show == false) {
showbr.style.display = "none";
} else {
showbr.style.display = "block";
}
}
showbr = x[i];
}
if (x[i].tagName == "A") {
if (x[i].innerHTML.toUpperCase().indexOf(val.toUpperCase()) == -1) {
x[i].style.display = "none";
} else {
x[i].style.display = "block";
show = true;
}
}
if (showh2) {
if (show == false) {
showh2.style.display = "none";
} else {
showh2.style.display = "block";
}
}
}
}


Автор: Гость (не зарегистрирован), дата: 21 февраля, 2019 - 09:40
#permalink

function tree_toggle(event) {
event = event || window.event
var clickedElem = event.target || event.srcElement

if (!hasClass(clickedElem, 'Expand')) {
return // клик не там
}

// Node, на который кликнули
var node = clickedElem.parentNode
if (hasClass(node, 'ExpandLeaf')) {
return // клик на листе
}

// определить новый класс для узла
var newClass = hasClass(node, 'ExpandOpen') ? 'ExpandClosed' : 'ExpandOpen'
// заменить текущий класс на newClass
// регексп находит отдельно стоящий open|close и меняет на newClass
var re = /(^|\s)(ExpandOpen|ExpandClosed)(\s|$)/
node.className = node.className.replace(re, '$1'+newClass+'$3')
}

function hasClass(elem, className) {
return new RegExp("(^|\\s)"+className+"(\\s|$)").test(elem.className)
}

.Container {
padding: 10px;
margin: 0;
}

.Container li {
list-style-type: none;
}

/* indent for all tree children excepts root */
.Node {
background-image : url(img/i.gif);
background-position : top left;
background-repeat : repeat-y;
margin-left: 18px;
zoom: 1;

}

.IsRoot {
margin-left: 0;
margin-top: -15px;
}

/* left vertical line (grid) for all nodes */
.IsLast {
background-image: url(img/i_half.gif);
background-repeat : no-repeat;
}

.ExpandOpen .Expand {
background-image: url(img/expand_minus.gif);
}

/* closed is higher priority than open */
.ExpandClosed .Expand {
background-image: url(img/expand_plus.gif);
}

/* highest priority */
.ExpandLeaf .Expand {
background-image: url(img/expand_leaf.gif);
}

.Content {
min-height: 18px;
margin-left:18px;

}

* html .Content {
height: 18px;
}

.Expand {
width: 18px;
height: 18px;
float: left;
}

.ExpandOpen .Container {
display: block;
}

.ExpandClosed .Container {
display: none;
}

.ExpandOpen .Expand, .ExpandClosed .Expand {
cursor: pointer;
}
.ExpandLeaf .Expand {
cursor: auto;
}


Автор: basketbros (не зарегистрирован), дата: 6 апреля, 2022 - 09:48
#permalink

огромное спасибо
Я думаю, что это будет полезно для моего проекта


Автор: Irene Buck (не зарегистрирован), дата: 20 июля, 2022 - 05:47
#permalink

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


Автор: Alice12 (не зарегистрирован), дата: 10 мая, 2024 - 05:32
#permalink

Удобное дерево с AJAX-подгрузкой можно реализовать с использованием JavaScript-библиотеки, Friday Night Funkin такой как jQuery или Vue.js, в зависимости от ваших предпочтений и требований проекта.


 
Текущий раздел
Поиск по сайту
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Последние темы на форуме
Forum