|
| 1 | +/** |
| 2 | + * Create an element with classname. |
| 3 | + * |
| 4 | + * @param {string} selector The nodeName and classnames for the element to create. |
| 5 | + * @return {HTMLElement} The created element. |
| 6 | + */ |
| 7 | +export function create(selector) { |
| 8 | + var args = selector.split('.'); |
| 9 | + var elem = document.createElement(args.shift()); |
| 10 | + // IE11: |
| 11 | + args.forEach(function (classname) { |
| 12 | + elem.classList.add(classname); |
| 13 | + }); |
| 14 | + // Better browsers: |
| 15 | + // elem.classList.add(...args); |
| 16 | + return elem; |
| 17 | +} |
| 18 | +/** |
| 19 | + * Find all elements matching the selector. |
| 20 | + * Basically the same as element.querySelectorAll() but it returns an actuall array. |
| 21 | + * |
| 22 | + * @param {HTMLElement} element Element to search in. |
| 23 | + * @param {string} filter The filter to match. |
| 24 | + * @return {array} Array of elements that match the filter. |
| 25 | + */ |
| 26 | +export function find(element, filter) { |
| 27 | + return Array.prototype.slice.call(element.querySelectorAll(filter)); |
| 28 | +} |
| 29 | +/** |
| 30 | + * Find all child elements matching the (optional) selector. |
| 31 | + * |
| 32 | + * @param {HTMLElement} element Element to search in. |
| 33 | + * @param {string} filter The filter to match. |
| 34 | + * @return {array} Array of child elements that match the filter. |
| 35 | + */ |
| 36 | +export function children(element, filter) { |
| 37 | + var children = Array.prototype.slice.call(element.children); |
| 38 | + return filter |
| 39 | + ? children.filter(function (child) { return child.matches(filter); }) |
| 40 | + : children; |
| 41 | +} |
| 42 | +/** |
| 43 | + * Find text excluding text from within child elements. |
| 44 | + * @param {HTMLElement} element Element to search in. |
| 45 | + * @return {string} The text. |
| 46 | + */ |
| 47 | +export function text(element) { |
| 48 | + return Array.prototype.slice |
| 49 | + .call(element.childNodes) |
| 50 | + .filter(function (child) { return child.nodeType == 3; }) |
| 51 | + .map(function (child) { return child.textContent; }) |
| 52 | + .join(' '); |
| 53 | +} |
| 54 | +/** |
| 55 | + * Find all preceding elements matching the selector. |
| 56 | + * |
| 57 | + * @param {HTMLElement} element Element to start searching from. |
| 58 | + * @param {string} filter The filter to match. |
| 59 | + * @return {array} Array of preceding elements that match the selector. |
| 60 | + */ |
| 61 | +export function parents(element, filter) { |
| 62 | + /** Array of preceding elements that match the selector. */ |
| 63 | + var parents = []; |
| 64 | + /** Array of preceding elements that match the selector. */ |
| 65 | + var parent = element.parentElement; |
| 66 | + while (parent) { |
| 67 | + parents.push(parent); |
| 68 | + parent = parent.parentElement; |
| 69 | + } |
| 70 | + return filter |
| 71 | + ? parents.filter(function (parent) { return parent.matches(filter); }) |
| 72 | + : parents; |
| 73 | +} |
| 74 | +/** |
| 75 | + * Find all previous siblings matching the selecotr. |
| 76 | + * |
| 77 | + * @param {HTMLElement} element Element to start searching from. |
| 78 | + * @param {string} filter The filter to match. |
| 79 | + * @return {array} Array of previous siblings that match the selector. |
| 80 | + */ |
| 81 | +export function prevAll(element, filter) { |
| 82 | + /** Array of previous siblings that match the selector. */ |
| 83 | + var previous = []; |
| 84 | + /** Current element in the loop */ |
| 85 | + var current = element.previousElementSibling; |
| 86 | + while (current) { |
| 87 | + if (!filter || current.matches(filter)) { |
| 88 | + previous.push(current); |
| 89 | + } |
| 90 | + current = current.previousElementSibling; |
| 91 | + } |
| 92 | + return previous; |
| 93 | +} |
| 94 | +/** |
| 95 | + * Get an element offset relative to the document. |
| 96 | + * |
| 97 | + * @param {HTMLElement} element Element to start measuring from. |
| 98 | + * @param {string} [direction=top] Offset top or left. |
| 99 | + * @return {number} The element offset relative to the document. |
| 100 | + */ |
| 101 | +export function offset(element, direction) { |
| 102 | + return (element.getBoundingClientRect()[direction] + |
| 103 | + document.body[direction === 'left' ? 'scrollLeft' : 'scrollTop']); |
| 104 | +} |
| 105 | +/** |
| 106 | + * Filter out non-listitem listitems. |
| 107 | + * @param {array} listitems Elements to filter. |
| 108 | + * @return {array} The filtered set of listitems. |
| 109 | + */ |
| 110 | +export function filterLI(listitems) { |
| 111 | + return listitems.filter(function (listitem) { return !listitem.matches('.mm-hidden'); }); |
| 112 | +} |
| 113 | +/** |
| 114 | + * Find anchors in listitems (excluding anchor that open a sub-panel). |
| 115 | + * @param {array} listitems Elements to filter. |
| 116 | + * @return {array} The found set of anchors. |
| 117 | + */ |
| 118 | +export function filterLIA(listitems) { |
| 119 | + var anchors = []; |
| 120 | + filterLI(listitems).forEach(function (listitem) { |
| 121 | + anchors.push.apply(anchors, children(listitem, 'a.mm-listitem__text')); |
| 122 | + }); |
| 123 | + return anchors.filter(function (anchor) { return !anchor.matches('.mm-btn_next'); }); |
| 124 | +} |
| 125 | +/** |
| 126 | + * Refactor a classname on multiple elements. |
| 127 | + * @param {HTMLElement} element Element to refactor. |
| 128 | + * @param {string} oldClass Classname to remove. |
| 129 | + * @param {string} newClass Classname to add. |
| 130 | + */ |
| 131 | +export function reClass(element, oldClass, newClass) { |
| 132 | + if (element.matches('.' + oldClass)) { |
| 133 | + element.classList.remove(oldClass); |
| 134 | + element.classList.add(newClass); |
| 135 | + } |
| 136 | +} |
0 commit comments