1480 lines
133 KiB
JavaScript
1480 lines
133 KiB
JavaScript
|
(function webpackUniversalModuleDefinition(root, factory) {
|
||
|
if(typeof exports === 'object' && typeof module === 'object')
|
||
|
module.exports = factory();
|
||
|
else if(typeof define === 'function' && define.amd)
|
||
|
define([], factory);
|
||
|
else if(typeof exports === 'object')
|
||
|
exports["OptimalSelect"] = factory();
|
||
|
else
|
||
|
root["OptimalSelect"] = factory();
|
||
|
})(this, function() {
|
||
|
return /******/ (function(modules) { // webpackBootstrap
|
||
|
/******/ // The module cache
|
||
|
/******/ var installedModules = {};
|
||
|
/******/
|
||
|
/******/ // The require function
|
||
|
/******/ function __webpack_require__(moduleId) {
|
||
|
/******/
|
||
|
/******/ // Check if module is in cache
|
||
|
/******/ if(installedModules[moduleId])
|
||
|
/******/ return installedModules[moduleId].exports;
|
||
|
/******/
|
||
|
/******/ // Create a new module (and put it into the cache)
|
||
|
/******/ var module = installedModules[moduleId] = {
|
||
|
/******/ i: moduleId,
|
||
|
/******/ l: false,
|
||
|
/******/ exports: {}
|
||
|
/******/ };
|
||
|
/******/
|
||
|
/******/ // Execute the module function
|
||
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||
|
/******/
|
||
|
/******/ // Flag the module as loaded
|
||
|
/******/ module.l = true;
|
||
|
/******/
|
||
|
/******/ // Return the exports of the module
|
||
|
/******/ return module.exports;
|
||
|
/******/ }
|
||
|
/******/
|
||
|
/******/
|
||
|
/******/ // expose the modules object (__webpack_modules__)
|
||
|
/******/ __webpack_require__.m = modules;
|
||
|
/******/
|
||
|
/******/ // expose the module cache
|
||
|
/******/ __webpack_require__.c = installedModules;
|
||
|
/******/
|
||
|
/******/ // identity function for calling harmony imports with the correct context
|
||
|
/******/ __webpack_require__.i = function(value) { return value; };
|
||
|
/******/
|
||
|
/******/ // define getter function for harmony exports
|
||
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
||
|
/******/ Object.defineProperty(exports, name, {
|
||
|
/******/ configurable: false,
|
||
|
/******/ enumerable: true,
|
||
|
/******/ get: getter
|
||
|
/******/ });
|
||
|
/******/ }
|
||
|
/******/ };
|
||
|
/******/
|
||
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||
|
/******/ __webpack_require__.n = function(module) {
|
||
|
/******/ var getter = module && module.__esModule ?
|
||
|
/******/ function getDefault() { return module['default']; } :
|
||
|
/******/ function getModuleExports() { return module; };
|
||
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
||
|
/******/ return getter;
|
||
|
/******/ };
|
||
|
/******/
|
||
|
/******/ // Object.prototype.hasOwnProperty.call
|
||
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||
|
/******/
|
||
|
/******/ // __webpack_public_path__
|
||
|
/******/ __webpack_require__.p = "";
|
||
|
/******/
|
||
|
/******/ // Load entry module and return exports
|
||
|
/******/ return __webpack_require__(__webpack_require__.s = 6);
|
||
|
/******/ })
|
||
|
/************************************************************************/
|
||
|
/******/ ([
|
||
|
/* 0 */
|
||
|
/***/ function(module, exports, __webpack_require__) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.convertNodeList = convertNodeList;
|
||
|
exports.escapeValue = escapeValue;
|
||
|
/**
|
||
|
* # Utilities
|
||
|
*
|
||
|
* Convenience helpers.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Create an array with the DOM nodes of the list
|
||
|
*
|
||
|
* @param {NodeList} nodes - [description]
|
||
|
* @return {Array.<HTMLElement>} - [description]
|
||
|
*/
|
||
|
function convertNodeList(nodes) {
|
||
|
var length = nodes.length;
|
||
|
|
||
|
var arr = new Array(length);
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
arr[i] = nodes[i];
|
||
|
}
|
||
|
return arr;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Escape special characters and line breaks as a simplified version of 'CSS.escape()'
|
||
|
*
|
||
|
* Description of valid characters: https://mathiasbynens.be/notes/css-escapes
|
||
|
*
|
||
|
* @param {String?} value - [description]
|
||
|
* @return {String} - [description]
|
||
|
*/
|
||
|
function escapeValue(value) {
|
||
|
return value && value.replace(/['"`\\/:\?&!#$%^()[\]{|}*+;,.<=>@~]/g, '\\$&').replace(/\n/g, '\A');
|
||
|
}
|
||
|
|
||
|
/***/ },
|
||
|
/* 1 */
|
||
|
/***/ function(module, exports, __webpack_require__) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.getCommonAncestor = getCommonAncestor;
|
||
|
exports.getCommonProperties = getCommonProperties;
|
||
|
/**
|
||
|
* # Common
|
||
|
*
|
||
|
* Process collections for similarities.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Find the last common ancestor of elements
|
||
|
*
|
||
|
* @param {Array.<HTMLElements>} elements - [description]
|
||
|
* @return {HTMLElement} - [description]
|
||
|
*/
|
||
|
function getCommonAncestor(elements) {
|
||
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
|
var _options$root = options.root,
|
||
|
root = _options$root === undefined ? document : _options$root;
|
||
|
|
||
|
|
||
|
var ancestors = [];
|
||
|
|
||
|
elements.forEach(function (element, index) {
|
||
|
var parents = [];
|
||
|
while (element !== root) {
|
||
|
element = element.parentNode;
|
||
|
parents.unshift(element);
|
||
|
}
|
||
|
ancestors[index] = parents;
|
||
|
});
|
||
|
|
||
|
ancestors.sort(function (curr, next) {
|
||
|
return curr.length - next.length;
|
||
|
});
|
||
|
|
||
|
var shallowAncestor = ancestors.shift();
|
||
|
|
||
|
var ancestor = null;
|
||
|
|
||
|
var _loop = function _loop() {
|
||
|
var parent = shallowAncestor[i];
|
||
|
var missing = ancestors.some(function (otherParents) {
|
||
|
return !otherParents.some(function (otherParent) {
|
||
|
return otherParent === parent;
|
||
|
});
|
||
|
});
|
||
|
|
||
|
if (missing) {
|
||
|
// TODO: find similar sub-parents, not the top root, e.g. sharing a class selector
|
||
|
return 'break';
|
||
|
}
|
||
|
|
||
|
ancestor = parent;
|
||
|
};
|
||
|
|
||
|
for (var i = 0, l = shallowAncestor.length; i < l; i++) {
|
||
|
var _ret = _loop();
|
||
|
|
||
|
if (_ret === 'break') break;
|
||
|
}
|
||
|
|
||
|
return ancestor;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get a set of common properties of elements
|
||
|
*
|
||
|
* @param {Array.<HTMLElement>} elements - [description]
|
||
|
* @return {Object} - [description]
|
||
|
*/
|
||
|
function getCommonProperties(elements) {
|
||
|
|
||
|
var commonProperties = {
|
||
|
classes: [],
|
||
|
attributes: {},
|
||
|
tag: null
|
||
|
};
|
||
|
|
||
|
elements.forEach(function (element) {
|
||
|
var commonClasses = commonProperties.classes,
|
||
|
commonAttributes = commonProperties.attributes,
|
||
|
commonTag = commonProperties.tag;
|
||
|
|
||
|
// ~ classes
|
||
|
|
||
|
if (commonClasses !== undefined) {
|
||
|
var classes = element.getAttribute('class');
|
||
|
if (classes) {
|
||
|
classes = classes.trim().split(' ');
|
||
|
if (!commonClasses.length) {
|
||
|
commonProperties.classes = classes;
|
||
|
} else {
|
||
|
commonClasses = commonClasses.filter(function (entry) {
|
||
|
return classes.some(function (name) {
|
||
|
return name === entry;
|
||
|
});
|
||
|
});
|
||
|
if (commonClasses.length) {
|
||
|
commonProperties.classes = commonClasses;
|
||
|
} else {
|
||
|
delete commonProperties.classes;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// TODO: restructure removal as 2x set / 2x delete, instead of modify always replacing with new collection
|
||
|
delete commonProperties.classes;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ~ attributes
|
||
|
if (commonAttributes !== undefined) {
|
||
|
(function () {
|
||
|
var elementAttributes = element.attributes;
|
||
|
var attributes = Object.keys(elementAttributes).reduce(function (attributes, key) {
|
||
|
var attribute = elementAttributes[key];
|
||
|
var attributeName = attribute.name;
|
||
|
// NOTE: workaround detection for non-standard phantomjs NamedNodeMap behaviour
|
||
|
// (issue: https://github.com/ariya/phantomjs/issues/14634)
|
||
|
if (attribute && attributeName !== 'class') {
|
||
|
attributes[attributeName] = attribute.value;
|
||
|
}
|
||
|
return attributes;
|
||
|
}, {});
|
||
|
|
||
|
var attributesNames = Object.keys(attributes);
|
||
|
var commonAttributesNames = Object.keys(commonAttributes);
|
||
|
|
||
|
if (attributesNames.length) {
|
||
|
if (!commonAttributesNames.length) {
|
||
|
commonProperties.attributes = attributes;
|
||
|
} else {
|
||
|
commonAttributes = commonAttributesNames.reduce(function (nextCommonAttributes, name) {
|
||
|
var value = commonAttributes[name];
|
||
|
if (value === attributes[name]) {
|
||
|
nextCommonAttributes[name] = value;
|
||
|
}
|
||
|
return nextCommonAttributes;
|
||
|
}, {});
|
||
|
if (Object.keys(commonAttributes).length) {
|
||
|
commonProperties.attributes = commonAttributes;
|
||
|
} else {
|
||
|
delete commonProperties.attributes;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
delete commonProperties.attributes;
|
||
|
}
|
||
|
})();
|
||
|
}
|
||
|
|
||
|
// ~ tag
|
||
|
if (commonTag !== undefined) {
|
||
|
var tag = element.tagName.toLowerCase();
|
||
|
if (!commonTag) {
|
||
|
commonProperties.tag = tag;
|
||
|
} else if (tag !== commonTag) {
|
||
|
delete commonProperties.tag;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return commonProperties;
|
||
|
}
|
||
|
|
||
|
/***/ },
|
||
|
/* 2 */
|
||
|
/***/ function(module, exports, __webpack_require__) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.default = optimize;
|
||
|
|
||
|
var _adapt = __webpack_require__(3);
|
||
|
|
||
|
var _adapt2 = _interopRequireDefault(_adapt);
|
||
|
|
||
|
var _utilities = __webpack_require__(0);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
/**
|
||
|
* Apply different optimization techniques
|
||
|
*
|
||
|
* @param {string} selector - [description]
|
||
|
* @param {HTMLElement|Array.<HTMLElement>} element - [description]
|
||
|
* @param {Object} options - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
/**
|
||
|
* # Optimize
|
||
|
*
|
||
|
* 1.) Improve efficiency through shorter selectors by removing redundancy
|
||
|
* 2.) Improve robustness through selector transformation
|
||
|
*/
|
||
|
|
||
|
function optimize(selector, elements) {
|
||
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
||
|
|
||
|
|
||
|
// convert single entry and NodeList
|
||
|
if (!Array.isArray(elements)) {
|
||
|
elements = !elements.length ? [elements] : (0, _utilities.convertNodeList)(elements);
|
||
|
}
|
||
|
|
||
|
if (!elements.length || elements.some(function (element) {
|
||
|
return element.nodeType !== 1;
|
||
|
})) {
|
||
|
throw new Error('Invalid input - to compare HTMLElements its necessary to provide a reference of the selected node(s)! (missing "elements")');
|
||
|
}
|
||
|
|
||
|
var globalModified = (0, _adapt2.default)(elements[0], options);
|
||
|
|
||
|
// chunk parts outside of quotes (http://stackoverflow.com/a/25663729)
|
||
|
var path = selector.replace(/> /g, '>').split(/\s+(?=(?:(?:[^"]*"){2})*[^"]*$)/);
|
||
|
|
||
|
if (path.length < 2) {
|
||
|
return optimizePart('', selector, '', elements);
|
||
|
}
|
||
|
|
||
|
var shortened = [path.pop()];
|
||
|
while (path.length > 1) {
|
||
|
var current = path.pop();
|
||
|
var prePart = path.join(' ');
|
||
|
var postPart = shortened.join(' ');
|
||
|
|
||
|
var pattern = prePart + ' ' + postPart;
|
||
|
var matches = document.querySelectorAll(pattern);
|
||
|
if (matches.length !== elements.length) {
|
||
|
shortened.unshift(optimizePart(prePart, current, postPart, elements));
|
||
|
}
|
||
|
}
|
||
|
shortened.unshift(path[0]);
|
||
|
path = shortened;
|
||
|
|
||
|
// optimize start + end
|
||
|
path[0] = optimizePart('', path[0], path.slice(1).join(' '), elements);
|
||
|
path[path.length - 1] = optimizePart(path.slice(0, -1).join(' '), path[path.length - 1], '', elements);
|
||
|
|
||
|
if (globalModified) {
|
||
|
delete true;
|
||
|
}
|
||
|
|
||
|
return path.join(' ').replace(/>/g, '> ').trim();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Improve a chunk of the selector
|
||
|
*
|
||
|
* @param {string} prePart - [description]
|
||
|
* @param {string} current - [description]
|
||
|
* @param {string} postPart - [description]
|
||
|
* @param {Array.<HTMLElement>} elements - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
function optimizePart(prePart, current, postPart, elements) {
|
||
|
if (prePart.length) prePart = prePart + ' ';
|
||
|
if (postPart.length) postPart = ' ' + postPart;
|
||
|
|
||
|
// robustness: attribute without value (generalization)
|
||
|
if (/\[*\]/.test(current)) {
|
||
|
var key = current.replace(/=.*$/, ']');
|
||
|
var pattern = '' + prePart + key + postPart;
|
||
|
var matches = document.querySelectorAll(pattern);
|
||
|
if (compareResults(matches, elements)) {
|
||
|
current = key;
|
||
|
} else {
|
||
|
// robustness: replace specific key-value with base tag (heuristic)
|
||
|
var references = document.querySelectorAll('' + prePart + key);
|
||
|
|
||
|
var _loop = function _loop() {
|
||
|
var reference = references[i];
|
||
|
if (elements.some(function (element) {
|
||
|
return reference.contains(element);
|
||
|
})) {
|
||
|
var description = reference.tagName.toLowerCase();
|
||
|
pattern = '' + prePart + description + postPart;
|
||
|
matches = document.querySelectorAll(pattern);
|
||
|
|
||
|
if (compareResults(matches, elements)) {
|
||
|
current = description;
|
||
|
}
|
||
|
return 'break';
|
||
|
}
|
||
|
};
|
||
|
|
||
|
for (var i = 0, l = references.length; i < l; i++) {
|
||
|
var pattern;
|
||
|
var matches;
|
||
|
|
||
|
var _ret = _loop();
|
||
|
|
||
|
if (_ret === 'break') break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// robustness: descendant instead child (heuristic)
|
||
|
if (/>/.test(current)) {
|
||
|
var descendant = current.replace(/>/, '');
|
||
|
var pattern = '' + prePart + descendant + postPart;
|
||
|
var matches = document.querySelectorAll(pattern);
|
||
|
if (compareResults(matches, elements)) {
|
||
|
current = descendant;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// robustness: 'nth-of-type' instead 'nth-child' (heuristic)
|
||
|
if (/:nth-child/.test(current)) {
|
||
|
// TODO: consider complete coverage of 'nth-of-type' replacement
|
||
|
var type = current.replace(/nth-child/g, 'nth-of-type');
|
||
|
var pattern = '' + prePart + type + postPart;
|
||
|
var matches = document.querySelectorAll(pattern);
|
||
|
if (compareResults(matches, elements)) {
|
||
|
current = type;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// efficiency: combinations of classname (partial permutations)
|
||
|
if (/\.\S+\.\S+/.test(current)) {
|
||
|
var names = current.trim().split('.').slice(1).map(function (name) {
|
||
|
return '.' + name;
|
||
|
}).sort(function (curr, next) {
|
||
|
return curr.length - next.length;
|
||
|
});
|
||
|
while (names.length) {
|
||
|
var partial = current.replace(names.shift(), '').trim();
|
||
|
var pattern = ('' + prePart + partial + postPart).trim();
|
||
|
if (!pattern.length || pattern.charAt(0) === '>' || pattern.charAt(pattern.length - 1) === '>') {
|
||
|
break;
|
||
|
}
|
||
|
var matches = document.querySelectorAll(pattern);
|
||
|
if (compareResults(matches, elements)) {
|
||
|
current = partial;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// robustness: degrade complex classname (heuristic)
|
||
|
names = current && current.match(/\./g);
|
||
|
if (names && names.length > 2) {
|
||
|
var _references = document.querySelectorAll('' + prePart + current);
|
||
|
|
||
|
var _loop2 = function _loop2() {
|
||
|
var reference = _references[i];
|
||
|
if (elements.some(function (element) {
|
||
|
return reference.contains(element);
|
||
|
})) {
|
||
|
// TODO:
|
||
|
// - check using attributes + regard excludes
|
||
|
var description = reference.tagName.toLowerCase();
|
||
|
pattern = '' + prePart + description + postPart;
|
||
|
matches = document.querySelectorAll(pattern);
|
||
|
|
||
|
if (compareResults(matches, elements)) {
|
||
|
current = description;
|
||
|
}
|
||
|
return 'break';
|
||
|
}
|
||
|
};
|
||
|
|
||
|
for (var i = 0, l = _references.length; i < l; i++) {
|
||
|
var pattern;
|
||
|
var matches;
|
||
|
|
||
|
var _ret2 = _loop2();
|
||
|
|
||
|
if (_ret2 === 'break') break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return current;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Evaluate matches with expected elements
|
||
|
*
|
||
|
* @param {Array.<HTMLElement>} matches - [description]
|
||
|
* @param {Array.<HTMLElement>} elements - [description]
|
||
|
* @return {Boolean} - [description]
|
||
|
*/
|
||
|
function compareResults(matches, elements) {
|
||
|
var length = matches.length;
|
||
|
|
||
|
return length === elements.length && elements.every(function (element) {
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
if (matches[i] === element) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
});
|
||
|
}
|
||
|
module.exports = exports['default'];
|
||
|
|
||
|
/***/ },
|
||
|
/* 3 */
|
||
|
/***/ function(module, exports, __webpack_require__) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
|
||
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||
|
|
||
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
||
|
|
||
|
exports.default = adapt;
|
||
|
/**
|
||
|
* # Adapt
|
||
|
*
|
||
|
* Check and extend the environment for universal usage.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Modify the context based on the environment
|
||
|
*
|
||
|
* @param {HTMLELement} element - [description]
|
||
|
* @param {Object} options - [description]
|
||
|
* @return {boolean} - [description]
|
||
|
*/
|
||
|
function adapt(element, options) {
|
||
|
|
||
|
// detect environment setup
|
||
|
if (true) {
|
||
|
return false;
|
||
|
} else {
|
||
|
global.document = options.context || function () {
|
||
|
var root = element;
|
||
|
while (root.parent) {
|
||
|
root = root.parent;
|
||
|
}
|
||
|
return root;
|
||
|
}();
|
||
|
}
|
||
|
|
||
|
// https://github.com/fb55/domhandler/blob/master/index.js#L75
|
||
|
var ElementPrototype = Object.getPrototypeOf(true);
|
||
|
|
||
|
// alternative descriptor to access elements with filtering invalid elements (e.g. textnodes)
|
||
|
if (!Object.getOwnPropertyDescriptor(ElementPrototype, 'childTags')) {
|
||
|
Object.defineProperty(ElementPrototype, 'childTags', {
|
||
|
enumerable: true,
|
||
|
get: function get() {
|
||
|
return this.children.filter(function (node) {
|
||
|
// https://github.com/fb55/domelementtype/blob/master/index.js#L12
|
||
|
return node.type === 'tag' || node.type === 'script' || node.type === 'style';
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (!Object.getOwnPropertyDescriptor(ElementPrototype, 'attributes')) {
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap
|
||
|
Object.defineProperty(ElementPrototype, 'attributes', {
|
||
|
enumerable: true,
|
||
|
get: function get() {
|
||
|
var attribs = this.attribs;
|
||
|
|
||
|
var attributesNames = Object.keys(attribs);
|
||
|
var NamedNodeMap = attributesNames.reduce(function (attributes, attributeName, index) {
|
||
|
attributes[index] = {
|
||
|
name: attributeName,
|
||
|
value: attribs[attributeName]
|
||
|
};
|
||
|
return attributes;
|
||
|
}, {});
|
||
|
Object.defineProperty(NamedNodeMap, 'length', {
|
||
|
enumerable: false,
|
||
|
configurable: false,
|
||
|
value: attributesNames.length
|
||
|
});
|
||
|
return NamedNodeMap;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (!ElementPrototype.getAttribute) {
|
||
|
// https://docs.webplatform.org/wiki/dom/Element/getAttribute
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute
|
||
|
ElementPrototype.getAttribute = function (name) {
|
||
|
return this.attribs[name] || null;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (!ElementPrototype.getElementsByTagName) {
|
||
|
// https://docs.webplatform.org/wiki/dom/Document/getElementsByTagName
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName
|
||
|
ElementPrototype.getElementsByTagName = function (tagName) {
|
||
|
var HTMLCollection = [];
|
||
|
traverseDescendants(this.childTags, function (descendant) {
|
||
|
if (descendant.name === tagName || tagName === '*') {
|
||
|
HTMLCollection.push(descendant);
|
||
|
}
|
||
|
});
|
||
|
return HTMLCollection;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (!ElementPrototype.getElementsByClassName) {
|
||
|
// https://docs.webplatform.org/wiki/dom/Document/getElementsByClassName
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByClassName
|
||
|
ElementPrototype.getElementsByClassName = function (className) {
|
||
|
var names = className.trim().replace(/\s+/g, ' ').split(' ');
|
||
|
var HTMLCollection = [];
|
||
|
traverseDescendants([this], function (descendant) {
|
||
|
var descendantClassName = descendant.attribs.class;
|
||
|
if (descendantClassName && names.every(function (name) {
|
||
|
return descendantClassName.indexOf(name) > -1;
|
||
|
})) {
|
||
|
HTMLCollection.push(descendant);
|
||
|
}
|
||
|
});
|
||
|
return HTMLCollection;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (!ElementPrototype.querySelectorAll) {
|
||
|
// https://docs.webplatform.org/wiki/css/selectors_api/querySelectorAll
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll
|
||
|
ElementPrototype.querySelectorAll = function (selectors) {
|
||
|
var _this = this;
|
||
|
|
||
|
selectors = selectors.replace(/(>)(\S)/g, '$1 $2').trim(); // add space for '>' selector
|
||
|
|
||
|
// using right to left execution => https://github.com/fb55/css-select#how-does-it-work
|
||
|
var instructions = getInstructions(selectors);
|
||
|
var discover = instructions.shift();
|
||
|
|
||
|
var total = instructions.length;
|
||
|
return discover(this).filter(function (node) {
|
||
|
var step = 0;
|
||
|
while (step < total) {
|
||
|
node = instructions[step](node, _this);
|
||
|
if (!node) {
|
||
|
// hierarchy doesn't match
|
||
|
return false;
|
||
|
}
|
||
|
step += 1;
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (!ElementPrototype.contains) {
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
|
||
|
ElementPrototype.contains = function (element) {
|
||
|
var inclusive = false;
|
||
|
traverseDescendants([this], function (descendant, done) {
|
||
|
if (descendant === element) {
|
||
|
inclusive = true;
|
||
|
done();
|
||
|
}
|
||
|
});
|
||
|
return inclusive;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve transformation steps
|
||
|
*
|
||
|
* @param {Array.<string>} selectors - [description]
|
||
|
* @return {Array.<Function>} - [description]
|
||
|
*/
|
||
|
function getInstructions(selectors) {
|
||
|
return selectors.split(' ').reverse().map(function (selector, step) {
|
||
|
var discover = step === 0;
|
||
|
|
||
|
var _selector$split = selector.split(':'),
|
||
|
_selector$split2 = _slicedToArray(_selector$split, 2),
|
||
|
type = _selector$split2[0],
|
||
|
pseudo = _selector$split2[1];
|
||
|
|
||
|
var validate = null;
|
||
|
var instruction = null;
|
||
|
|
||
|
(function () {
|
||
|
switch (true) {
|
||
|
|
||
|
// child: '>'
|
||
|
case />/.test(type):
|
||
|
instruction = function checkParent(node) {
|
||
|
return function (validate) {
|
||
|
return validate(node.parent) && node.parent;
|
||
|
};
|
||
|
};
|
||
|
break;
|
||
|
|
||
|
// class: '.'
|
||
|
case /^\./.test(type):
|
||
|
var names = type.substr(1).split('.');
|
||
|
validate = function validate(node) {
|
||
|
var nodeClassName = node.attribs.class;
|
||
|
return nodeClassName && names.every(function (name) {
|
||
|
return nodeClassName.indexOf(name) > -1;
|
||
|
});
|
||
|
};
|
||
|
instruction = function checkClass(node, root) {
|
||
|
if (discover) {
|
||
|
return node.getElementsByClassName(names.join(' '));
|
||
|
}
|
||
|
return typeof node === 'function' ? node(validate) : getAncestor(node, root, validate);
|
||
|
};
|
||
|
break;
|
||
|
|
||
|
// attribute: '[key="value"]'
|
||
|
case /^\[/.test(type):
|
||
|
var _type$replace$split = type.replace(/\[|\]|"/g, '').split('='),
|
||
|
_type$replace$split2 = _slicedToArray(_type$replace$split, 2),
|
||
|
attributeKey = _type$replace$split2[0],
|
||
|
attributeValue = _type$replace$split2[1];
|
||
|
|
||
|
validate = function validate(node) {
|
||
|
var hasAttribute = Object.keys(node.attribs).indexOf(attributeKey) > -1;
|
||
|
if (hasAttribute) {
|
||
|
// regard optional attributeValue
|
||
|
if (!attributeValue || node.attribs[attributeKey] === attributeValue) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
instruction = function checkAttribute(node, root) {
|
||
|
if (discover) {
|
||
|
var _ret2 = function () {
|
||
|
var NodeList = [];
|
||
|
traverseDescendants([node], function (descendant) {
|
||
|
if (validate(descendant)) {
|
||
|
NodeList.push(descendant);
|
||
|
}
|
||
|
});
|
||
|
return {
|
||
|
v: NodeList
|
||
|
};
|
||
|
}();
|
||
|
|
||
|
if ((typeof _ret2 === 'undefined' ? 'undefined' : _typeof(_ret2)) === "object") return _ret2.v;
|
||
|
}
|
||
|
return typeof node === 'function' ? node(validate) : getAncestor(node, root, validate);
|
||
|
};
|
||
|
break;
|
||
|
|
||
|
// id: '#'
|
||
|
case /^#/.test(type):
|
||
|
var id = type.substr(1);
|
||
|
validate = function validate(node) {
|
||
|
return node.attribs.id === id;
|
||
|
};
|
||
|
instruction = function checkId(node, root) {
|
||
|
if (discover) {
|
||
|
var _ret3 = function () {
|
||
|
var NodeList = [];
|
||
|
traverseDescendants([node], function (descendant, done) {
|
||
|
if (validate(descendant)) {
|
||
|
NodeList.push(descendant);
|
||
|
done();
|
||
|
}
|
||
|
});
|
||
|
return {
|
||
|
v: NodeList
|
||
|
};
|
||
|
}();
|
||
|
|
||
|
if ((typeof _ret3 === 'undefined' ? 'undefined' : _typeof(_ret3)) === "object") return _ret3.v;
|
||
|
}
|
||
|
return typeof node === 'function' ? node(validate) : getAncestor(node, root, validate);
|
||
|
};
|
||
|
break;
|
||
|
|
||
|
// universal: '*'
|
||
|
case /\*/.test(type):
|
||
|
validate = function validate(node) {
|
||
|
return true;
|
||
|
};
|
||
|
instruction = function checkUniversal(node, root) {
|
||
|
if (discover) {
|
||
|
var _ret4 = function () {
|
||
|
var NodeList = [];
|
||
|
traverseDescendants([node], function (descendant) {
|
||
|
return NodeList.push(descendant);
|
||
|
});
|
||
|
return {
|
||
|
v: NodeList
|
||
|
};
|
||
|
}();
|
||
|
|
||
|
if ((typeof _ret4 === 'undefined' ? 'undefined' : _typeof(_ret4)) === "object") return _ret4.v;
|
||
|
}
|
||
|
return typeof node === 'function' ? node(validate) : getAncestor(node, root, validate);
|
||
|
};
|
||
|
break;
|
||
|
|
||
|
// tag: '...'
|
||
|
default:
|
||
|
validate = function validate(node) {
|
||
|
return node.name === type;
|
||
|
};
|
||
|
instruction = function checkTag(node, root) {
|
||
|
if (discover) {
|
||
|
var _ret5 = function () {
|
||
|
var NodeList = [];
|
||
|
traverseDescendants([node], function (descendant) {
|
||
|
if (validate(descendant)) {
|
||
|
NodeList.push(descendant);
|
||
|
}
|
||
|
});
|
||
|
return {
|
||
|
v: NodeList
|
||
|
};
|
||
|
}();
|
||
|
|
||
|
if ((typeof _ret5 === 'undefined' ? 'undefined' : _typeof(_ret5)) === "object") return _ret5.v;
|
||
|
}
|
||
|
return typeof node === 'function' ? node(validate) : getAncestor(node, root, validate);
|
||
|
};
|
||
|
}
|
||
|
})();
|
||
|
|
||
|
if (!pseudo) {
|
||
|
return instruction;
|
||
|
}
|
||
|
|
||
|
var rule = pseudo.match(/-(child|type)\((\d+)\)$/);
|
||
|
var kind = rule[1];
|
||
|
var index = parseInt(rule[2], 10) - 1;
|
||
|
|
||
|
var validatePseudo = function validatePseudo(node) {
|
||
|
if (node) {
|
||
|
var compareSet = node.parent.childTags;
|
||
|
if (kind === 'type') {
|
||
|
compareSet = compareSet.filter(validate);
|
||
|
}
|
||
|
var nodeIndex = compareSet.findIndex(function (child) {
|
||
|
return child === node;
|
||
|
});
|
||
|
if (nodeIndex === index) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
return function enhanceInstruction(node) {
|
||
|
var match = instruction(node);
|
||
|
if (discover) {
|
||
|
return match.reduce(function (NodeList, matchedNode) {
|
||
|
if (validatePseudo(matchedNode)) {
|
||
|
NodeList.push(matchedNode);
|
||
|
}
|
||
|
return NodeList;
|
||
|
}, []);
|
||
|
}
|
||
|
return validatePseudo(match) && match;
|
||
|
};
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Walking recursive to invoke callbacks
|
||
|
*
|
||
|
* @param {Array.<HTMLElement>} nodes - [description]
|
||
|
* @param {Function} handler - [description]
|
||
|
*/
|
||
|
function traverseDescendants(nodes, handler) {
|
||
|
nodes.forEach(function (node) {
|
||
|
var progress = true;
|
||
|
handler(node, function () {
|
||
|
return progress = false;
|
||
|
});
|
||
|
if (node.childTags && progress) {
|
||
|
traverseDescendants(node.childTags, handler);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Bubble up from bottom to top
|
||
|
*
|
||
|
* @param {HTMLELement} node - [description]
|
||
|
* @param {HTMLELement} root - [description]
|
||
|
* @param {Function} validate - [description]
|
||
|
* @return {HTMLELement} - [description]
|
||
|
*/
|
||
|
function getAncestor(node, root, validate) {
|
||
|
while (node.parent) {
|
||
|
node = node.parent;
|
||
|
if (validate(node)) {
|
||
|
return node;
|
||
|
}
|
||
|
if (node === root) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
module.exports = exports['default'];
|
||
|
|
||
|
/***/ },
|
||
|
/* 4 */
|
||
|
/***/ function(module, exports, __webpack_require__) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
|
||
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
|
||
|
* # Select
|
||
|
*
|
||
|
* Construct a unique CSS query selector to access the selected DOM element(s).
|
||
|
* For longevity it applies different matching and optimization strategies.
|
||
|
*/
|
||
|
|
||
|
exports.getSingleSelector = getSingleSelector;
|
||
|
exports.getMultiSelector = getMultiSelector;
|
||
|
exports.default = getQuerySelector;
|
||
|
|
||
|
var _adapt = __webpack_require__(3);
|
||
|
|
||
|
var _adapt2 = _interopRequireDefault(_adapt);
|
||
|
|
||
|
var _match = __webpack_require__(5);
|
||
|
|
||
|
var _match2 = _interopRequireDefault(_match);
|
||
|
|
||
|
var _optimize = __webpack_require__(2);
|
||
|
|
||
|
var _optimize2 = _interopRequireDefault(_optimize);
|
||
|
|
||
|
var _utilities = __webpack_require__(0);
|
||
|
|
||
|
var _common = __webpack_require__(1);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
/**
|
||
|
* Get a selector for the provided element
|
||
|
*
|
||
|
* @param {HTMLElement} element - [description]
|
||
|
* @param {Object} options - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
function getSingleSelector(element) {
|
||
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
|
|
||
|
|
||
|
if (element.nodeType === 3) {
|
||
|
element = element.parentNode;
|
||
|
}
|
||
|
|
||
|
if (element.nodeType !== 1) {
|
||
|
throw new Error('Invalid input - only HTMLElements or representations of them are supported! (not "' + (typeof element === 'undefined' ? 'undefined' : _typeof(element)) + '")');
|
||
|
}
|
||
|
|
||
|
var globalModified = (0, _adapt2.default)(element, options);
|
||
|
|
||
|
var selector = (0, _match2.default)(element, options);
|
||
|
var optimized = (0, _optimize2.default)(selector, element, options);
|
||
|
|
||
|
// debug
|
||
|
// console.log(`
|
||
|
// selector: ${selector}
|
||
|
// optimized: ${optimized}
|
||
|
// `)
|
||
|
|
||
|
if (globalModified) {
|
||
|
delete true;
|
||
|
}
|
||
|
|
||
|
return optimized;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get a selector to match multiple descendants from an ancestor
|
||
|
*
|
||
|
* @param {Array.<HTMLElement>|NodeList} elements - [description]
|
||
|
* @param {Object} options - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
function getMultiSelector(elements) {
|
||
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
|
|
||
|
|
||
|
if (!Array.isArray(elements)) {
|
||
|
elements = (0, _utilities.convertNodeList)(elements);
|
||
|
}
|
||
|
|
||
|
if (elements.some(function (element) {
|
||
|
return element.nodeType !== 1;
|
||
|
})) {
|
||
|
throw new Error('Invalid input - only an Array of HTMLElements or representations of them is supported!');
|
||
|
}
|
||
|
|
||
|
var globalModified = (0, _adapt2.default)(elements[0], options);
|
||
|
|
||
|
var ancestor = (0, _common.getCommonAncestor)(elements, options);
|
||
|
var ancestorSelector = getSingleSelector(ancestor, options);
|
||
|
|
||
|
// TODO: consider usage of multiple selectors + parent-child relation + check for part redundancy
|
||
|
var commonSelectors = getCommonSelectors(elements);
|
||
|
var descendantSelector = commonSelectors[0];
|
||
|
|
||
|
var selector = (0, _optimize2.default)(ancestorSelector + ' ' + descendantSelector, elements, options);
|
||
|
var selectorMatches = (0, _utilities.convertNodeList)(document.querySelectorAll(selector));
|
||
|
|
||
|
if (!elements.every(function (element) {
|
||
|
return selectorMatches.some(function (entry) {
|
||
|
return entry === element;
|
||
|
});
|
||
|
})) {
|
||
|
// TODO: cluster matches to split into similar groups for sub selections
|
||
|
return console.warn('\n The selected elements can\'t be efficiently mapped.\n Its probably best to use multiple single selectors instead!\n ', elements);
|
||
|
}
|
||
|
|
||
|
if (globalModified) {
|
||
|
delete true;
|
||
|
}
|
||
|
|
||
|
return selector;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get selectors to describe a set of elements
|
||
|
*
|
||
|
* @param {Array.<HTMLElements>} elements - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
function getCommonSelectors(elements) {
|
||
|
var _getCommonProperties = (0, _common.getCommonProperties)(elements),
|
||
|
classes = _getCommonProperties.classes,
|
||
|
attributes = _getCommonProperties.attributes,
|
||
|
tag = _getCommonProperties.tag;
|
||
|
|
||
|
var selectorPath = [];
|
||
|
|
||
|
if (tag) {
|
||
|
selectorPath.push(tag);
|
||
|
}
|
||
|
|
||
|
if (classes) {
|
||
|
var classSelector = classes.map(function (name) {
|
||
|
return '.' + name;
|
||
|
}).join('');
|
||
|
selectorPath.push(classSelector);
|
||
|
}
|
||
|
|
||
|
if (attributes) {
|
||
|
var attributeSelector = Object.keys(attributes).reduce(function (parts, name) {
|
||
|
parts.push('[' + name + '="' + attributes[name] + '"]');
|
||
|
return parts;
|
||
|
}, []).join('');
|
||
|
selectorPath.push(attributeSelector);
|
||
|
}
|
||
|
|
||
|
if (selectorPath.length) {
|
||
|
// TODO: check for parent-child relation
|
||
|
}
|
||
|
|
||
|
return [selectorPath.join('')];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Choose action depending on the input (multiple/single)
|
||
|
*
|
||
|
* NOTE: extended detection is used for special cases like the <select> element with <options>
|
||
|
*
|
||
|
* @param {HTMLElement|NodeList|Array.<HTMLElement>} input - [description]
|
||
|
* @param {Object} options - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
function getQuerySelector(input) {
|
||
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
|
|
||
|
if (input.length && !input.name) {
|
||
|
return getMultiSelector(input, options);
|
||
|
}
|
||
|
return getSingleSelector(input, options);
|
||
|
}
|
||
|
|
||
|
/***/ },
|
||
|
/* 5 */
|
||
|
/***/ function(module, exports, __webpack_require__) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.default = match;
|
||
|
|
||
|
var _utilities = __webpack_require__(0);
|
||
|
|
||
|
var defaultIgnore = {
|
||
|
attribute: function attribute(attributeName) {
|
||
|
return ['style', 'data-reactid', 'data-react-checksum'].indexOf(attributeName) > -1;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get the path of the element
|
||
|
*
|
||
|
* @param {HTMLElement} node - [description]
|
||
|
* @param {Object} options - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
/**
|
||
|
* # Match
|
||
|
*
|
||
|
* Retrieve selector for a node.
|
||
|
*/
|
||
|
|
||
|
function match(node, options) {
|
||
|
var _options$root = options.root,
|
||
|
root = _options$root === undefined ? document : _options$root,
|
||
|
_options$skip = options.skip,
|
||
|
skip = _options$skip === undefined ? null : _options$skip,
|
||
|
_options$priority = options.priority,
|
||
|
priority = _options$priority === undefined ? ['id', 'class', 'href', 'src'] : _options$priority,
|
||
|
_options$ignore = options.ignore,
|
||
|
ignore = _options$ignore === undefined ? {} : _options$ignore;
|
||
|
|
||
|
|
||
|
var path = [];
|
||
|
var element = node;
|
||
|
var length = path.length;
|
||
|
var ignoreClass = false;
|
||
|
|
||
|
var skipCompare = skip && (Array.isArray(skip) ? skip : [skip]).map(function (entry) {
|
||
|
if (typeof entry !== 'function') {
|
||
|
return function (element) {
|
||
|
return element === entry;
|
||
|
};
|
||
|
}
|
||
|
return entry;
|
||
|
});
|
||
|
|
||
|
var skipChecks = function skipChecks(element) {
|
||
|
return skip && skipCompare.some(function (compare) {
|
||
|
return compare(element);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
Object.keys(ignore).forEach(function (type) {
|
||
|
if (type === 'class') {
|
||
|
ignoreClass = true;
|
||
|
}
|
||
|
var predicate = ignore[type];
|
||
|
if (typeof predicate === 'function') return;
|
||
|
if (typeof predicate === 'number') {
|
||
|
predicate = predicate.toString();
|
||
|
}
|
||
|
if (typeof predicate === 'string') {
|
||
|
predicate = new RegExp((0, _utilities.escapeValue)(predicate).replace(/\\/g, '\\\\'));
|
||
|
}
|
||
|
if (typeof predicate === 'boolean') {
|
||
|
predicate = predicate ? /(?:)/ : /.^/;
|
||
|
}
|
||
|
// check class-/attributename for regex
|
||
|
ignore[type] = function (name, value) {
|
||
|
return predicate.test(value);
|
||
|
};
|
||
|
});
|
||
|
|
||
|
if (ignoreClass) {
|
||
|
(function () {
|
||
|
var ignoreAttribute = ignore.attribute;
|
||
|
ignore.attribute = function (name, value, defaultPredicate) {
|
||
|
return ignore.class(value) || ignoreAttribute && ignoreAttribute(name, value, defaultPredicate);
|
||
|
};
|
||
|
})();
|
||
|
}
|
||
|
|
||
|
while (element !== root) {
|
||
|
if (skipChecks(element) !== true) {
|
||
|
// ~ global
|
||
|
if (checkAttributes(priority, element, ignore, path, root)) break;
|
||
|
if (checkTag(element, ignore, path, root)) break;
|
||
|
|
||
|
// ~ local
|
||
|
checkAttributes(priority, element, ignore, path);
|
||
|
if (path.length === length) {
|
||
|
checkTag(element, ignore, path);
|
||
|
}
|
||
|
|
||
|
// define only one part each iteration
|
||
|
if (path.length === length) {
|
||
|
checkChilds(priority, element, ignore, path);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
element = element.parentNode;
|
||
|
length = path.length;
|
||
|
}
|
||
|
|
||
|
if (element === root) {
|
||
|
var pattern = findPattern(priority, element, ignore);
|
||
|
path.unshift(pattern);
|
||
|
}
|
||
|
|
||
|
return path.join(' ');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Extend path with attribute identifier
|
||
|
*
|
||
|
* @param {Array.<string>} priority - [description]
|
||
|
* @param {HTMLElement} element - [description]
|
||
|
* @param {Object} ignore - [description]
|
||
|
* @param {Array.<string>} path - [description]
|
||
|
* @param {HTMLElement} parent - [description]
|
||
|
* @return {boolean} - [description]
|
||
|
*/
|
||
|
function checkAttributes(priority, element, ignore, path) {
|
||
|
var parent = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : element.parentNode;
|
||
|
|
||
|
var pattern = findAttributesPattern(priority, element, ignore);
|
||
|
if (pattern) {
|
||
|
var matches = parent.querySelectorAll(pattern);
|
||
|
if (matches.length === 1) {
|
||
|
path.unshift(pattern);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Lookup attribute identifier
|
||
|
*
|
||
|
* @param {Array.<string>} priority - [description]
|
||
|
* @param {HTMLElement} element - [description]
|
||
|
* @param {Object} ignore - [description]
|
||
|
* @return {string?} - [description]
|
||
|
*/
|
||
|
function findAttributesPattern(priority, element, ignore) {
|
||
|
var attributes = element.attributes;
|
||
|
var sortedKeys = Object.keys(attributes).sort(function (curr, next) {
|
||
|
var currPos = priority.indexOf(attributes[curr].name);
|
||
|
var nextPos = priority.indexOf(attributes[next].name);
|
||
|
if (nextPos === -1) {
|
||
|
if (currPos === -1) {
|
||
|
return 0;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
return currPos - nextPos;
|
||
|
});
|
||
|
|
||
|
for (var i = 0, l = sortedKeys.length; i < l; i++) {
|
||
|
var key = sortedKeys[i];
|
||
|
var attribute = attributes[key];
|
||
|
var attributeName = attribute.name;
|
||
|
var attributeValue = (0, _utilities.escapeValue)(attribute.value);
|
||
|
|
||
|
var currentIgnore = ignore[attributeName] || ignore.attribute;
|
||
|
var currentDefaultIgnore = defaultIgnore[attributeName] || defaultIgnore.attribute;
|
||
|
if (checkIgnore(currentIgnore, attributeName, attributeValue, currentDefaultIgnore)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var pattern = '[' + attributeName + '="' + attributeValue + '"]';
|
||
|
|
||
|
if (/\b\d/.test(attributeValue) === false) {
|
||
|
if (attributeName === 'id') {
|
||
|
pattern = '#' + attributeValue;
|
||
|
}
|
||
|
|
||
|
if (attributeName === 'class') {
|
||
|
var className = attributeValue.trim().replace(/\s+/g, '.');
|
||
|
pattern = '.' + className;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pattern;
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Extend path with tag identifier
|
||
|
*
|
||
|
* @param {HTMLElement} element - [description]
|
||
|
* @param {Object} ignore - [description]
|
||
|
* @param {Array.<string>} path - [description]
|
||
|
* @param {HTMLElement} parent - [description]
|
||
|
* @return {boolean} - [description]
|
||
|
*/
|
||
|
function checkTag(element, ignore, path) {
|
||
|
var parent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : element.parentNode;
|
||
|
|
||
|
var pattern = findTagPattern(element, ignore);
|
||
|
if (pattern) {
|
||
|
var matches = parent.getElementsByTagName(pattern);
|
||
|
if (matches.length === 1) {
|
||
|
path.unshift(pattern);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Lookup tag identifier
|
||
|
*
|
||
|
* @param {HTMLElement} element - [description]
|
||
|
* @param {Object} ignore - [description]
|
||
|
* @return {boolean} - [description]
|
||
|
*/
|
||
|
function findTagPattern(element, ignore) {
|
||
|
var tagName = element.tagName.toLowerCase();
|
||
|
if (checkIgnore(ignore.tag, null, tagName)) {
|
||
|
return null;
|
||
|
}
|
||
|
return tagName;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Extend path with specific child identifier
|
||
|
*
|
||
|
* NOTE: 'childTags' is a custom property to use as a view filter for tags using 'adapter.js'
|
||
|
*
|
||
|
* @param {Array.<string>} priority - [description]
|
||
|
* @param {HTMLElement} element - [description]
|
||
|
* @param {Object} ignore - [description]
|
||
|
* @param {Array.<string>} path - [description]
|
||
|
* @return {boolean} - [description]
|
||
|
*/
|
||
|
function checkChilds(priority, element, ignore, path) {
|
||
|
var parent = element.parentNode;
|
||
|
var children = parent.childTags || parent.children;
|
||
|
for (var i = 0, l = children.length; i < l; i++) {
|
||
|
var child = children[i];
|
||
|
if (child === element) {
|
||
|
var childPattern = findPattern(priority, child, ignore);
|
||
|
if (!childPattern) {
|
||
|
return console.warn('\n Element couldn\'t be matched through strict ignore pattern!\n ', child, ignore, childPattern);
|
||
|
}
|
||
|
var pattern = '> ' + childPattern + ':nth-child(' + (i + 1) + ')';
|
||
|
path.unshift(pattern);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Lookup identifier
|
||
|
*
|
||
|
* @param {Array.<string>} priority - [description]
|
||
|
* @param {HTMLElement} element - [description]
|
||
|
* @param {Object} ignore - [description]
|
||
|
* @return {string} - [description]
|
||
|
*/
|
||
|
function findPattern(priority, element, ignore) {
|
||
|
var pattern = findAttributesPattern(priority, element, ignore);
|
||
|
if (!pattern) {
|
||
|
pattern = findTagPattern(element, ignore);
|
||
|
}
|
||
|
return pattern;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Validate with custom and default functions
|
||
|
*
|
||
|
* @param {Function} predicate - [description]
|
||
|
* @param {string?} name - [description]
|
||
|
* @param {string} value - [description]
|
||
|
* @param {Function} defaultPredicate - [description]
|
||
|
* @return {boolean} - [description]
|
||
|
*/
|
||
|
function checkIgnore(predicate, name, value, defaultPredicate) {
|
||
|
if (!value) {
|
||
|
return true;
|
||
|
}
|
||
|
var check = predicate || defaultPredicate;
|
||
|
if (!check) {
|
||
|
return false;
|
||
|
}
|
||
|
return check(name, value, defaultPredicate);
|
||
|
}
|
||
|
module.exports = exports['default'];
|
||
|
|
||
|
/***/ },
|
||
|
/* 6 */
|
||
|
/***/ function(module, exports, __webpack_require__) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.default = exports.common = exports.optimize = exports.getMultiSelector = exports.getSingleSelector = exports.select = undefined;
|
||
|
|
||
|
var _select2 = __webpack_require__(4);
|
||
|
|
||
|
Object.defineProperty(exports, 'getSingleSelector', {
|
||
|
enumerable: true,
|
||
|
get: function get() {
|
||
|
return _select2.getSingleSelector;
|
||
|
}
|
||
|
});
|
||
|
Object.defineProperty(exports, 'getMultiSelector', {
|
||
|
enumerable: true,
|
||
|
get: function get() {
|
||
|
return _select2.getMultiSelector;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
var _select3 = _interopRequireDefault(_select2);
|
||
|
|
||
|
var _optimize2 = __webpack_require__(2);
|
||
|
|
||
|
var _optimize3 = _interopRequireDefault(_optimize2);
|
||
|
|
||
|
var _common2 = __webpack_require__(1);
|
||
|
|
||
|
var _common = _interopRequireWildcard(_common2);
|
||
|
|
||
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
exports.select = _select3.default;
|
||
|
exports.optimize = _optimize3.default;
|
||
|
exports.common = _common;
|
||
|
exports.default = _select3.default;
|
||
|
|
||
|
/***/ }
|
||
|
/******/ ]);
|
||
|
});
|
||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCBhOGUwMjk3Y2RkNDE2YmMwZjMyNiIsIndlYnBhY2s6Ly8vLi9zcmMvdXRpbGl0aWVzLmpzIiwid2VicGFjazovLy8uL3NyYy9jb21tb24uanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL29wdGltaXplLmpzIiwid2VicGFjazovLy8uL3NyYy9hZGFwdC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvc2VsZWN0LmpzIiwid2VicGFjazovLy8uL3NyYy9tYXRjaC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXguanMiXSwibmFtZXMiOlsiY29udmVydE5vZGVMaXN0IiwiZXNjYXBlVmFsdWUiLCJub2RlcyIsImxlbmd0aCIsImFyciIsIkFycmF5IiwiaSIsInZhbHVlIiwicmVwbGFjZSIsImdldENvbW1vbkFuY2VzdG9yIiwiZ2V0Q29tbW9uUHJvcGVydGllcyIsImVsZW1lbnRzIiwib3B0aW9ucyIsInJvb3QiLCJkb2N1bWVudCIsImFuY2VzdG9ycyIsImZvckVhY2giLCJlbGVtZW50IiwiaW5kZXgiLCJwYXJlbnRzIiwicGFyZW50Tm9kZSIsInVuc2hpZnQiLCJzb3J0IiwiY3VyciIsIm5leHQiLCJzaGFsbG93QW5jZXN0b3IiLCJzaGlmdCIsImFuY2VzdG9yIiwicGFyZW50IiwibWlzc2luZyIsInNvbWUiLCJvdGhlclBhcmVudHMiLCJvdGhlclBhcmVudCIsImwiLCJjb21tb25Qcm9wZXJ0aWVzIiwiY2xhc3NlcyIsImF0dHJpYnV0ZXMiLCJ0YWciLCJjb21tb25DbGFzc2VzIiwiY29tbW9uQXR0cmlidXRlcyIsImNvbW1vblRhZyIsInVuZGVmaW5lZCIsImdldEF0dHJpYnV0ZSIsInRyaW0iLCJzcGxpdCIsImZpbHRlciIsImVudHJ5IiwibmFtZSIsImVsZW1lbnRBdHRyaWJ1dGVzIiwiT2JqZWN0Iiwia2V5cyIsInJlZHVjZSIsImtleSIsImF0dHJpYnV0ZSIsImF0dHJpYnV0ZU5hbWUiLCJhdHRyaWJ1dGVzTmFtZXMiLCJjb21tb25BdHRyaWJ1dGVzTmFtZXMiLCJuZXh0Q29tbW9uQXR0cmlidXRlcyIsInRhZ05hbWUiLCJ0b0xvd2VyQ2FzZSIsIm9wdGltaXplIiwic2VsZWN0b3IiLCJpc0FycmF5Iiwibm9kZVR5cGUiLCJFcnJvciIsImdsb2JhbE1vZGlmaWVkIiwicGF0aCIsIm9wdGltaXplUGFydCIsInNob3J0ZW5lZCIsInBvcCIsImN1cnJlbnQiLCJwcmVQYXJ0Iiwiam9pbiIsInBvc3RQYXJ0IiwicGF0dGVybiIsIm1hdGNoZXMiLCJxdWVyeVNlbGVjdG9yQWxsIiwic2xpY2UiLCJ0ZXN0IiwiY29tcGFyZVJlc3VsdHMiLCJyZWZlcmVuY2VzIiwicmVmZXJlbmNlIiwiY29udGFpbnMiLCJkZXNjcmlwdGlvbiIsImRlc2NlbmRhbnQiLCJ0eXBlIiwibmFtZXMiLCJtYXAiLCJwYXJ0aWFsIiwiY2hhckF0IiwibWF0Y2giLCJldmVyeSIsImFkYXB0IiwiZ2xvYmFsIiwiY29udGV4dCIsIkVsZW1lbnRQcm90b3R5cGUiLCJnZXRQcm90b3R5cGVPZiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImRlZmluZVByb3BlcnR5IiwiZW51bWVyYWJsZSIsImdldCIsImNoaWxkcmVuIiwibm9kZSIsImF0dHJpYnMiLCJOYW1lZE5vZGVNYXAiLCJjb25maWd1cmFibGUiLCJnZXRFbGVtZW50c0J5VGFnTmFtZSIsIkhUTUxDb2xsZWN0aW9uIiwidHJhdmVyc2VEZXNjZW5kYW50cyIsImNoaWxkVGFncyIsInB1c2giLCJnZXRFbGVtZW50c0J5Q2xhc3NOYW1lIiwiY2xhc3NOYW1lIiwiZGVzY2VuZGFudENsYXNzTmFtZSIsImNsYXNzIiwiaW5kZXhPZiIsInNlbGVjdG9ycyIsImluc3RydWN0aW9ucyIsImdldEluc3RydWN0aW9ucyIsImRpc2NvdmVyIiwidG90YWwiLCJzdGVwIiwiaW5jbHVzaXZlIiwiZG9uZSIsInJldmVyc2UiLCJwc2V1ZG8iLCJ2YWxpZGF0ZSIsImluc3RydWN0aW9uIiwiY2hlY2tQYXJlbnQiLCJzdWJzdHIiLCJub2RlQ2xhc3NOYW1lIiwiY2hlY2tDbGFzcyIsImdldEFuY2VzdG9yIiwiYXR0cmlidXRlS2V5IiwiYXR0cmlidXRlVmFsdWUiLCJoYXNBdHRyaWJ1dGUiLCJjaGVja0F0dHJpYnV0ZSIsIk5vZGVMaXN0IiwiaWQiLCJjaGVja0lkIiwiY2hlY2tVbml2ZXJzYWwiLCJjaGVja1RhZyIsInJ1bGUiLCJraW5kIiwicGFyc2VJbnQiLCJ2YWxpZGF0ZVBzZXVkbyIsImNvbXBhcmVTZXQiLCJub2RlSW5kZXgiLCJmaW5kSW5kZXgiLCJjaGlsZCIsImVuaGFuY2VJbnN0cnVjdGlvbiIsIm1hdGNoZWROb2RlIiwiaGFuZGxlciIsInByb2dyZXNzIiwiZ2V0U2luZ2xlU2VsZWN0b3IiLCJnZXRNdWx0aVNlbGVjdG9yIiwiZ2V0UXVlcnlTZWxlY3RvciIsIm9wdGltaXplZCIsImFuY2VzdG9yU2VsZWN0b3IiLCJjb21tb25TZWxlY3RvcnMiLCJnZXRDb21tb25TZWxlY3RvcnMiLCJkZXNjZW5kYW50U2VsZWN0b3IiLCJzZWxlY3Rvck1hdGNoZXMiLCJjb25zb2xlIiwid2FybiIsInNlbGVjdG9yUGF0aCIsImNsYXNzU2VsZWN0b3IiLCJhdHRyaWJ1dGVTZWxlY3RvciIsInBhcnRzIiwiaW5wdXQiLCJkZWZhdWx0SWdub3JlIiwic2tpcCIsInByaW9yaXR5IiwiaWdub3JlIiwiaWdub3JlQ2xhc3MiLCJza2lwQ29tcGFyZSIsInNraXBDaGVja3MiLCJjb21wYXJlIiwicHJlZGljYXRlIiwidG9TdHJpbmciLCJSZWdFeHAiLCJpZ25vcmVBdHRyaWJ1dGUiLCJkZWZhdWx0UHJlZGljYXRlIiwiY2hlY2tBdHRyaWJ1dGVzIiwiY2hlY2tDaGlsZHMiLCJmaW5kUGF0dGVybiIsImZpbmRBdHRyaWJ1dGVzUGF0dGVybiIsInNvcnRlZEtleXMiLCJjdXJyUG9zIiwibmV4dFBvcyIsImN1cnJlbnRJZ25vcmUiLCJjdXJyZW50RGVmYXVsdElnbm9yZSIsImNoZWNrSWdub3JlIiwiZmluZFRhZ1BhdHRlcm4iLCJjaGlsZFBhdHRlcm4iLCJjaGVjayIsInNlbGVjdCIsImNvbW1vbiIsImRlZmF1bHQiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRCxPO0FDVkE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsbURBQTJDLGN
|