cryptpad/www/common/treesome.js

184 lines
5.6 KiB
JavaScript

define([], function () {
var tree = {};
// FIXME this isn't being used
var someElement = tree.some = function (root, predicate) {
// take the index of the last element in the current root
var last = root.childElementCount - 1;
// it might be a leaf node
if (last < 0) { return false; }
// otherwise it has children
while (last >= 0) {
// check from back to front
// check the node's children (depth first)
// if the predicate tests true, return true
if (tree.some(root.children[last], predicate)) {
return true;
} // otherwise none of the nodes inside it matched.
// check the node itself
if (predicate(root.children[last], last)) {
return true;
}
last--;
}
return false;
};
// FIXME this isn't being used
var someText = tree.someIncludingText = function (root, predicate) {
// take the index of the last element in the current root
var last = root.childNodes.length - 1;
// it might be a leaf node
if (last < 0) { return false; }
// otherwise it has children
while (last >= 0) {
// check from back to front
// check the node's children (depth first)
// if the predicate tests true, return true
if (tree.someIncludingText(root.childNodes[last], predicate)) {
return true;
} // otherwise none of the nodes inside it matched.
// check the node itself
if (predicate(root.childNodes[last], last)) {
return true;
}
last--;
}
return false;
};
// FIXME not being used
tree.findSameHierarchy = function (list, ancestor) {
var i = 0;
var success = true;
var last = list.length - 1;
var el;
tree.someIncludingText(ancestor, function (e) {
// don't out of bounds
if (i > last) {
// unsuccessful
success = false;
return true;
}
if (list[i] === (e.tagName||e.nodeName)) {
if (i === last) {
el = e;
return true;
}
i++;
} else {
// hierarchy has changed, what should we do?
success = false;
return true; // terminate
}
});
return success? el: false;
};
var indexOfNode = tree.indexOfNode = function (el) {
if (!(el && el.parentNode)) {
console.log("No parentNode found!");
throw new Error('No parentNode found!');
}
return Array.prototype.indexOf.call(el.parentNode.childNodes, el);
};
// not being used internally, but is useful externally
tree.contains = function (el, root) {
return el && root && root.contains && root.contains(el);
};
var siblingCount = tree.siblingCount = function (el) {
return el.parentNode.childNodes.length;
};
var childCount = tree.childCount = function (el) {
return el.childNodes.length;
};
var parentsOf = tree.parentsOf = function (el, root) {
var P = [];
var p = el;
while (p !== root) { P.push((p = p.parentNode)); }
return P;
};
/* rightmost and leftmost return the deepest right and left
leaf nodes of a tree
*/
var rightmostNode = tree.rightmostNode = function (el) {
var childNodeCount = childCount(el);
if (!childNodeCount) { // no children
return el; // return the element
} else {
return rightmostNode(el.childNodes[childNodeCount - 1]);
}
};
var leftmostNode = tree.leftmostNode = function (el) {
if (childCount(el)) {
return leftmostNode(el.childNodes[0]);
} else {
return el;
}
};
/* previousNode and nextNode traverse child elements of the dom
in the order in which they appear when selected by a cursor.
in particular, these algorithms traverse text nodes, not just tags
*/
var previousNode = tree.previousNode = function (el, root) {
if (!el || el === root) { return null; }
var i = indexOfNode(el);
if (!el.parentNode) { return null; }
if (i === 0) {
if (root && el.parentNode === root.childNodes[0]) { return null; }
return rightmostNode(previousNode(el.parentNode));
} else {
return rightmostNode(el.parentNode.childNodes[i-1]);
}
};
var nextNode = tree.nextNode = function (el, root) {
if (!el || el === root) { return null; }
var i = indexOfNode(el) + 1, // the index of the next node
l = siblingCount(el);
if (i === l) { // out of bounds
if (el.parentNode === root) { return null; }
return nextNode(el.parentNode, root);
} else {
return leftmostNode(el.parentNode.childNodes[i], root);
}
};
var orderOfNodes = tree.orderOfNodes = function (a, b, root) {
// b might not be supplied
if (!b) { return; }
// a and b might be the same element
if (a === b) { return 0; }
var cur = b;
while (cur) {
cur = previousNode(cur, root);
// if you find 'a' while traversing backwards
// they are in the expected order
if (cur === a) { return 1; }
}
// otherwise
return -1;
};
return tree;
});