UNPKG

@lion/ui

Version:

A package of extendable web components

57 lines (51 loc) 1.63 kB
/** * Implementation based on: * https://github.com/PolymerElements/iron-overlay-behavior/blob/master/iron-focusables-helper.html * The original implementation does not work for non-Polymer web components, and contains several * bugs on IE11. */ /** * @param {HTMLElement} a * @param {HTMLElement} b * @returns {Boolean} */ function hasLowerTabOrder(a, b) { // Normalize tabIndexes // e.g. in Firefox `<div contenteditable>` has `tabIndex = -1` const ati = Math.max(a.tabIndex, 0); const bti = Math.max(b.tabIndex, 0); return ati === 0 || bti === 0 ? bti > ati : ati > bti; } /** * @param {HTMLElement[]} left * @param {HTMLElement[]} right * @returns {HTMLElement[]} */ function mergeSortByTabIndex(left, right) { /** @type {HTMLElement[]} */ const result = []; while (left.length > 0 && right.length > 0) { if (hasLowerTabOrder(left[0], right[0])) { result.push(/** @type {HTMLElement} */ (right.shift())); } else { result.push(/** @type {HTMLElement} */ (left.shift())); } } return [...result, ...left, ...right]; } /** * @param {HTMLElement[]} elements * @returns {HTMLElement[]} */ export function sortByTabIndex(elements) { // Implement a merge sort as Array.prototype.sort does a non-stable sort // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort const len = elements.length; if (len < 2) { return elements; } const pivot = Math.ceil(len / 2); const left = sortByTabIndex(elements.slice(0, pivot)); const right = sortByTabIndex(elements.slice(pivot)); return mergeSortByTabIndex(left, right); }