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