Удобное дерево с 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).
Вы также можете:
|
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
Thanks for sharing FLUX Canny
Thanks for sharing FLUX Canny
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
Thanks for sharing https://fluxcanny.online/
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
This blog should be shared, as the information I discovered here holds value that transcends monetary worth FLUX Tools .
May I quote some of the information found in your web site to my local people? kitchen remodeling jacksonville
May I quote some of the information found in your web site to my local people? kitchen remodeling jacksonville
Hope you will not get tired on making posts as informative as this.
bathroom remodeling jacksonville
Models flux canny designed to provide structural guidance using canny edges taken from an input image along with a text prompt.
FLUX.1 AI Tools is a set of models that enhances our main text-to-image model, FLUX.1. It flux tools allows users to control and adjust images, whether they are real or generated.
Great blog! I found some interesting things in here that I might use for future references. kitchen remodeling nashville