2 * Walks the dom tree from the given node up until it finds a match
3 * Designed for optimal performance.
5 * @param {Element} node The from which to check the parent nodes
6 * @param {Object} matchingSet Object to match against (possible properties: nodeName, className, classRegExp)
7 * @param {Number} [levels] How many parents should the function check up from the current node (defaults to 50)
8 * @return {null|Element} Returns the first element that matched the desiredNodeName(s)
10 * var listElement = wysihtml5.dom.getParentElement(document.querySelector("li"), { nodeName: ["MENU", "UL", "OL"] });
12 * var unorderedListElement = wysihtml5.dom.getParentElement(document.querySelector("li"), { nodeName: "UL" });
14 * var coloredElement = wysihtml5.dom.getParentElement(myTextNode, { nodeName: "SPAN", className: "wysiwyg-color-red", classRegExp: /wysiwyg-color-[a-z]/g });
16 wysihtml5.dom.getParentElement = (function() {
18 function _isSameNodeName(nodeName, desiredNodeNames) {
19 if (!desiredNodeNames || !desiredNodeNames.length) {
23 if (typeof(desiredNodeNames) === "string") {
24 return nodeName === desiredNodeNames;
26 return wysihtml5.lang.array(desiredNodeNames).contains(nodeName);
30 function _isElement(node) {
31 return node.nodeType === wysihtml5.ELEMENT_NODE;
34 function _hasClassName(element, className, classRegExp) {
35 var classNames = (element.className || "").match(classRegExp) || [];
37 return !!classNames.length;
39 return classNames[classNames.length - 1] === className;
42 function _hasStyle(element, cssStyle, styleRegExp) {
43 var styles = (element.getAttribute('style') || "").match(styleRegExp) || [];
45 return !!styles.length;
47 return styles[styles.length - 1] === cssStyle;
50 return function(node, matchingSet, levels, container) {
51 var findByStyle = (matchingSet.cssStyle || matchingSet.styleRegExp),
52 findByClass = (matchingSet.className || matchingSet.classRegExp);
54 levels = levels || 50; // Go max 50 nodes upwards from current node
56 // make the matching class regex from class name if omitted
57 if (findByClass && !matchingSet.classRegExp) {
58 matchingSet.classRegExp = new RegExp(matchingSet.className);
61 while (levels-- && node && node.nodeName !== "BODY" && (!container || node !== container)) {
62 if (_isElement(node) && (!matchingSet.nodeName || _isSameNodeName(node.nodeName, matchingSet.nodeName)) &&
63 (!findByStyle || _hasStyle(node, matchingSet.cssStyle, matchingSet.styleRegExp)) &&
64 (!findByClass || _hasClassName(node, matchingSet.className, matchingSet.classRegExp))
68 node = node.parentNode;