OpenXE/www/js/aciTree/js/jquery.aciTree.dom.js
2021-05-21 08:49:41 +02:00

661 lines
23 KiB
JavaScript

/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* The aciTree low-level DOM functions.
*
* A collection of functions optimised for aciTree DOM structure.
*
* Need to be included before the aciTree core and after aciPlugin.
*/
aciPluginClass.plugins.aciTree_dom = {
// get the UL container from a LI
// `node` must be valid LI DOM node
// can return NULL
container: function(node) {
var container = node.lastChild;
if (container && (container.nodeName == 'UL')) {
return container;
}
return null;
},
// get the first children from a LI (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
firstChild: function(node, callback) {
var container = this.container(node);
if (container) {
var firstChild = container.firstChild;
if (callback) {
while (firstChild && !callback.call(this, firstChild)) {
firstChild = firstChild.nextSibling;
}
}
return firstChild;
}
return null;
},
// get the last children from a LI (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
lastChild: function(node, callback) {
var container = this.container(node);
if (container) {
var lastChild = container.lastChild;
if (callback) {
while (lastChild && !callback.call(this, lastChild)) {
lastChild = lastChild.previousSibling;
}
}
return lastChild;
}
return null;
},
// get the previous LI sibling (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
prev: function(node, callback) {
var previous = node.previousSibling;
if (callback) {
while (previous && !callback.call(this, previous)) {
previous = previous.previousSibling;
}
}
return previous;
},
// get the next LI sibling (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
next: function(node, callback) {
var next = node.nextSibling;
if (callback) {
while (next && !callback.call(this, next)) {
next = next.nextSibling;
}
}
return next;
},
// get the previous LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
prevAll: function(node, callback) {
var previous, lastChild, drillDown, match, prev, parent;
while (true) {
previous = this.prev(node);
if (previous) {
if (callback) {
match = callback.call(this, previous);
if (match === null) {
node = previous;
continue;
}
}
lastChild = this.lastChild(previous);
if (lastChild) {
if (callback && (callback.call(this, lastChild) === null)) {
node = lastChild;
continue;
}
prev = false;
while (drillDown = this.lastChild(lastChild)) {
lastChild = drillDown;
if (callback) {
match = callback.call(this, lastChild);
if (match === null) {
node = lastChild;
prev = true;
break;
}
}
}
if (prev) {
continue;
}
if (callback) {
match = callback.call(this, lastChild);
if (match) {
return lastChild;
} else if (match !== null) {
node = lastChild;
continue;
}
} else {
return lastChild;
}
} else {
if (!callback || match) {
return previous;
} else {
node = previous;
continue;
}
}
}
parent = this.parent(node);
if (parent) {
if (callback) {
match = callback.call(this, parent);
if (match) {
return parent;
} else {
node = parent;
}
} else {
return parent;
}
} else {
return null;
}
}
return null;
},
// get the next LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
nextAll: function(node, callback) {
var firstChild, match, next, parent, child;
while (true) {
firstChild = this.firstChild(node);
if (firstChild) {
if (callback) {
match = callback.call(this, firstChild);
if (match) {
return firstChild;
} else {
node = firstChild;
if (match !== null) {
continue;
}
}
} else {
return firstChild;
}
}
while (true) {
next = this.next(node);
if (next) {
if (callback) {
match = callback.call(this, next);
if (match) {
return next;
} else {
node = next;
if (match !== null) {
break;
} else {
continue;
}
}
} else {
return next;
}
} else {
parent = node;
child = null;
while (parent = this.parent(parent)) {
next = this.next(parent);
if (next) {
if (callback) {
match = callback.call(this, next);
if (match) {
return next;
} else {
node = next;
if (match !== null) {
child = true;
} else {
child = false;
}
break;
}
} else {
return next;
}
}
}
if (child !== null) {
if (child) {
break;
} else {
continue;
}
}
return null;
}
}
}
return null;
},
// get the first LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
first: function(node, callback) {
var container = this.container(node);
if (container) {
var firstChild = container.firstChild;
if (firstChild) {
if (callback && !callback.call(this, firstChild)) {
return this.nextAll(firstChild, callback);
}
return firstChild;
}
}
return null;
},
// get the last LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
last: function(node, callback) {
var container = this.container(node);
if (container) {
var lastChild = container.lastChild;
if (lastChild) {
if (callback && (callback.call(this, lastChild) === null)) {
return this.prevAll(lastChild, callback);
} else {
var drillDown;
while (drillDown = this.lastChild(lastChild)) {
lastChild = drillDown;
}
if (callback && !callback.call(this, lastChild)) {
return this.prevAll(lastChild, callback);
}
return lastChild;
}
}
}
return null;
},
// get the children LI from the node
// `node` must be valid LI DOM node
// `drillDown` if TRUE all children are returned
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
children: function(node, drillDown, callback) {
var children = [], levels = [], match, next, skip;
var firstChild = this.firstChild(node);
if (firstChild) {
while (true) {
skip = false;
do {
if (callback) {
match = callback.call(this, firstChild);
if (match) {
children.push(firstChild);
}
if (drillDown && (match !== null)) {
next = this.firstChild(firstChild);
if (next) {
levels.push(firstChild);
firstChild = next;
skip = true;
break;
}
}
} else {
children.push(firstChild);
if (drillDown) {
next = this.firstChild(firstChild);
if (next) {
levels.push(firstChild);
firstChild = next;
skip = true;
break;
}
}
}
} while (firstChild = firstChild.nextSibling);
if (!skip) {
while (firstChild = levels.pop()) {
firstChild = firstChild.nextSibling;
if (firstChild) {
break;
}
}
if (!firstChild) {
break;
}
}
}
}
return children;
},
// get a children from the node
// `node` must be valid DOM node
// `callback` can return FALSE to skip a node or NULL to stop the search
// can return NULL
childrenTill: function(node, callback) {
var levels = [], match, next, skip;
var firstChild = node.firstChild;
if (firstChild) {
while (true) {
skip = false;
do {
match = callback.call(this, firstChild);
if (match) {
return firstChild;
} else if (match === null) {
return null;
}
next = firstChild.firstChild;
if (next) {
levels.push(firstChild);
firstChild = next;
skip = true;
break;
}
} while (firstChild = firstChild.nextSibling);
if (!skip) {
while (firstChild = levels.pop()) {
firstChild = firstChild.nextSibling;
if (firstChild) {
break;
}
}
if (!firstChild) {
break;
}
}
}
}
return null;
},
// get a children from the node having a class
// `node` must be valid DOM node
// `className` String or Array to check for
// can return NULL
childrenByClass: function(node, className) {
if (node.getElementsByClassName) {
var list = node.getElementsByClassName(className instanceof Array ? className.join(' ') : className);
return list ? list[0] : null;
} else {
return this.childrenTill(node, function(node) {
return this.hasClass(node, className);
});
}
},
// get the parent LI from the children LI
// `node` must be valid LI DOM node
// can return NULL
parent: function(node) {
var parent = node.parentNode.parentNode;
if (parent && (parent.nodeName == 'LI')) {
return parent;
}
return null;
},
// get the parent LI from any children
// `node` must be valid children of a LI DOM node
// can return NULL
parentFrom: function(node) {
while (node.nodeName != 'LI') {
node = node.parentNode;
if (!node) {
return null;
}
}
return node;
},
// get a parent from the node
// `node` must be valid DOM node
// `callback` can return FALSE to skip a node or NULL to stop the search
// can return NULL
parentTill: function(node, callback) {
var match;
while (node = node.parentNode) {
match = callback.call(this, node);
if (match) {
return node;
} else if (match === null) {
return null;
}
}
return null;
},
// get a parent from the node having a class
// `node` must be valid DOM node
// `className` String or Array to check for
// can return NULL
parentByClass: function(node, className) {
return this.parentTill(node, function(node) {
return this.hasClass(node, className);
});
},
// test if node has class(es)
// `className` String or Array to check for
// `withOut` String or Array to exclude with
hasClass: function(node, className, withOut) {
var oldClass = ' ' + node.className + ' ';
if (withOut instanceof Array) {
for (var i = 0; i < withOut.length; i++) {
if (oldClass.indexOf(' ' + withOut[i] + ' ') != -1) {
return false;
}
}
} else {
if (withOut && oldClass.indexOf(' ' + withOut + ' ') != -1) {
return false;
}
}
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
if (oldClass.indexOf(' ' + className[i] + ' ') == -1) {
return false;
}
}
} else {
if (className && oldClass.indexOf(' ' + className + ' ') == -1) {
return false;
}
}
return true;
},
// filter nodes with class(es)
// `nodes` Array of DOM nodes
// @see `hasClass`
withClass: function(nodes, className, withOut) {
var filter = [];
for (var i = 0; i < nodes.length; i++) {
if (this.hasClass(nodes[i], className, withOut)) {
filter.push(nodes[i]);
}
}
return filter;
},
// test if node has any class(es)
// `className` String or Array to check for (any class)
// `withOut` String or Array to exclude with
hasAnyClass: function(node, className, withOut) {
var oldClass = ' ' + node.className + ' ';
if (withOut instanceof Array) {
for (var i = 0; i < withOut.length; i++) {
if (oldClass.indexOf(' ' + withOut[i] + ' ') != -1) {
return false;
}
}
} else {
if (withOut && oldClass.indexOf(' ' + withOut + ' ') != -1) {
return false;
}
}
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
if (oldClass.indexOf(' ' + className[i] + ' ') != -1) {
return true;
}
}
} else {
if (className && oldClass.indexOf(' ' + className + ' ') != -1) {
return true;
}
}
return false;
},
// filter nodes with any class(es)
// `nodes` Array of DOM nodes
// @see `hasAnyClass`
withAnyClass: function(nodes, className, withOut) {
var filter = [];
for (var i = 0; i < nodes.length; i++) {
if (this.hasAnyClass(nodes[i], className, withOut)) {
filter.push(nodes[i]);
}
}
return filter;
},
// add class(es) to node
// `node` must be valid DOM node
// `className` String or Array to add
// return TRUE if className changed
addClass: function(node, className) {
var oldClass = ' ' + node.className + ' ', append = '';
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
if (oldClass.indexOf(' ' + className[i] + ' ') == -1) {
append += ' ' + className[i];
}
}
} else {
if (oldClass.indexOf(' ' + className + ' ') == -1) {
append += ' ' + className;
}
}
if (append) {
node.className = node.className + append;
return true;
}
return false;
},
// add class(es) to nodes
// `nodes` Array of DOM nodes
// @see `addClass`
addListClass: function(nodes, className, callback) {
for (var i = 0; i < nodes.length; i++) {
this.addClass(nodes[i], className);
if (callback) {
callback.call(this, nodes[i]);
}
}
},
// remove class(es) from node
// `node` must be valid DOM node
// `className` String or Array to remove
// return TRUE if className changed
removeClass: function(node, className) {
var oldClass = ' ' + node.className + ' ';
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
oldClass = oldClass.replace(' ' + className[i] + ' ', ' ');
}
} else {
oldClass = oldClass.replace(' ' + className + ' ', ' ');
}
oldClass = oldClass.substr(1, oldClass.length - 2);
if (node.className != oldClass) {
node.className = oldClass;
return true;
}
return false;
},
// remove class(es) from nodes
// `nodes` Array of DOM nodes
// @see `removeClass`
removeListClass: function(nodes, className, callback) {
for (var i = 0; i < nodes.length; i++) {
this.removeClass(nodes[i], className);
if (callback) {
callback.call(this, nodes[i]);
}
}
},
// toggle node class(es)
// `node` must be valid DOM node
// `className` String or Array to toggle
// `add` TRUE to add them
// return TRUE if className changed
toggleClass: function(node, className, add) {
if (add) {
return this.addClass(node, className);
} else {
return this.removeClass(node, className);
}
},
// toggle nodes class(es)
// `nodes` Array of DOM nodes
// @see `toggleClass`
toggleListClass: function(nodes, className, add, callback) {
for (var i = 0; i < nodes.length; i++) {
this.toggleClass(nodes[i], className, add);
if (callback) {
callback.call(this, nodes[i]);
}
}
},
// add/remove and keep old class(es)
// `node` must be valid DOM node
// `addClass` String or Array to add
// `removeClass` String or Array to remove
// return TRUE if className changed
addRemoveClass: function(node, addClass, removeClass) {
var oldClass = ' ' + node.className + ' ';
if (removeClass) {
if (removeClass instanceof Array) {
for (var i = 0; i < removeClass.length; i++) {
oldClass = oldClass.replace(' ' + removeClass[i] + ' ', ' ');
}
} else {
oldClass = oldClass.replace(' ' + removeClass + ' ', ' ');
}
}
if (addClass) {
var append = '';
if (addClass instanceof Array) {
for (var i = 0; i < addClass.length; i++) {
if (oldClass.indexOf(' ' + addClass[i] + ' ') == -1) {
append += addClass[i] + ' ';
}
}
} else {
if (oldClass.indexOf(' ' + addClass + ' ') == -1) {
append += addClass + ' ';
}
}
oldClass += append;
}
oldClass = oldClass.substr(1, oldClass.length - 2);
if (node.className != oldClass) {
node.className = oldClass;
return true;
}
return false;
},
// add/remove and keep old class(es)
// `nodes` Array of DOM nodes
// @see `addRemoveClass`
addRemoveListClass: function(nodes, addClass, removeClass, callback) {
for (var i = 0; i < nodes.length; i++) {
this.addRemoveClass(nodes[i], addClass, removeClass);
if (callback) {
callback.call(this, nodes[i]);
}
}
}
};