dynatrace-cordova-outsystems-plugin
Version:
This plugin gives you the ability to use the Dynatrace instrumentation in your hybrid application (Cordova, Ionic, ..). It uses the Mobile Agent, the JavaScript Agent and the Javascript Bridge. The Mobile Agent will give you all device specific values con
1,280 lines (1,169 loc) • 66.1 kB
JavaScript
/*
* Copyright (C) 2007-2019 Diego Perini
* All rights reserved.
*
* nwsapi.js - Fast CSS Selectors API Engine
*
* Author: Diego Perini <diego.perini at gmail com>
* Version: 2.2.0
* Created: 20070722
* Release: 20191102
*
* License:
* http://javascript.nwbox.com/nwsapi/MIT-LICENSE
* Download:
* http://javascript.nwbox.com/nwsapi/nwsapi.js
*/
(function Export(global, factory) {
'use strict';
if (typeof module == 'object' && typeof exports == 'object') {
module.exports = factory;
} else if (typeof define == 'function' && define['amd']) {
define(factory);
} else {
global.NW || (global.NW = { });
global.NW.Dom = factory(global, Export);
}
})(this, function Factory(global, Export) {
var version = 'nwsapi-2.2.0',
doc = global.document,
root = doc.documentElement,
slice = Array.prototype.slice,
WSP = '[\\x20\\t\\r\\n\\f]',
CFG = {
// extensions
operators: '[~*^$|]=|=',
combinators: '[\\x20\\t>+~](?=[^>+~])'
},
NOT = {
// not enclosed in double/single/parens/square
double_enc: '(?=(?:[^"]*["][^"]*["])*[^"]*$)',
single_enc: "(?=(?:[^']*['][^']*['])*[^']*$)",
parens_enc: '(?![^\\x28]*\\x29)',
square_enc: '(?![^\\x5b]*\\x5d)'
},
REX = {
// regular expressions
HasEscapes: RegExp('\\\\'),
HexNumbers: RegExp('^[0-9a-fA-F]'),
EscOrQuote: RegExp('^\\\\|[\\x22\\x27]'),
RegExpChar: RegExp('(?:(?!\\\\)[\\\\^$.*+?()[\\]{}|\\/])', 'g'),
TrimSpaces: RegExp('[\\r\\n\\f]|^' + WSP + '+|' + WSP + '+$', 'g'),
CommaGroup: RegExp('(\\s*,\\s*)' + NOT.square_enc + NOT.parens_enc, 'g'),
SplitGroup: RegExp('((?:\\x28[^\\x29]*\\x29|\\[[^\\]]*\\]|\\\\.|[^,])+)', 'g'),
FixEscapes: RegExp('\\\\([0-9a-fA-F]{1,6}' + WSP + '?|.)|([\\x22\\x27])', 'g'),
CombineWSP: RegExp('[\\n\\r\\f\\x20]+' + NOT.single_enc + NOT.double_enc, 'g'),
TabCharWSP: RegExp('(\\x20?\\t+\\x20?)' + NOT.single_enc + NOT.double_enc, 'g'),
PseudosWSP: RegExp('\\s+([-+])\\s+' + NOT.square_enc, 'g')
},
STD = {
combinator: RegExp('\\s?([>+~])\\s?', 'g'),
apimethods: RegExp('^(?:[a-z]+|\\*)\\|', 'i'),
namespaces: RegExp('(\\*|[a-z]+)\\|[-a-z]+', 'i')
},
GROUPS = {
// pseudo-classes requiring parameters
linguistic: '(dir|lang)\\x28\\s?([-\\w]{2,})\\s?(?:\\x29|$)',
logicalsel: '(matches|not)\\x28\\s?([^()]*|[^\\x28]*\\x28[^\\x29]*\\x29)\\s?(?:\\x29|$)',
treestruct: '(nth(?:-last)?(?:-child|-of-type))(?:\\x28\\s?(even|odd|(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)?)\\s?(?:\\x29|$))',
// pseudo-classes not requiring parameters
locationpc: '(link|visited|target)\\b',
useraction: '(hover|active|focus|focus-within)\\b',
structural: '(root|empty|(?:(?:first|last|only)(?:-child|-of-type)))\\b',
inputstate: '(enabled|disabled|read-only|read-write|placeholder-shown|default)\\b',
inputvalue: '(checked|indeterminate|required|optional|valid|invalid|in-range|out-of-range)\\b',
// pseudo-elements starting with single colon (:)
pseudo_sng: '(after|before|first-letter|first-line)\\b',
// pseudo-elements starting with double colon (::)
pseudo_dbl: ':(after|before|first-letter|first-line|selection|placeholder|-webkit-[-a-zA-Z0-9]{2,})\\b'
},
Patterns = {
// pseudo-classes
treestruct: RegExp('^:(?:' + GROUPS.treestruct + ')(.*)', 'i'),
structural: RegExp('^:(?:' + GROUPS.structural + ')(.*)', 'i'),
linguistic: RegExp('^:(?:' + GROUPS.linguistic + ')(.*)', 'i'),
useraction: RegExp('^:(?:' + GROUPS.useraction + ')(.*)', 'i'),
inputstate: RegExp('^:(?:' + GROUPS.inputstate + ')(.*)', 'i'),
inputvalue: RegExp('^:(?:' + GROUPS.inputvalue + ')(.*)', 'i'),
locationpc: RegExp('^:(?:' + GROUPS.locationpc + ')(.*)', 'i'),
logicalsel: RegExp('^:(?:' + GROUPS.logicalsel + ')(.*)', 'i'),
pseudo_dbl: RegExp('^:(?:' + GROUPS.pseudo_dbl + ')(.*)', 'i'),
pseudo_sng: RegExp('^:(?:' + GROUPS.pseudo_sng + ')(.*)', 'i'),
// combinator symbols
children: RegExp('^' + WSP + '?\\>' + WSP + '?(.*)'),
adjacent: RegExp('^' + WSP + '?\\+' + WSP + '?(.*)'),
relative: RegExp('^' + WSP + '?\\~' + WSP + '?(.*)'),
ancestor: RegExp('^' + WSP + '+(.*)'),
// universal & namespace
universal: RegExp('^\\*(.*)'),
namespace: RegExp('^(\\w+|\\*)?\\|(.*)')
},
// regexp to aproximate detection of RTL languages (Arabic)
RTL = RegExp('^[\\u0591-\\u08ff\\ufb1d-\\ufdfd\\ufe70-\\ufefc ]+$'),
// emulate firefox error strings
qsNotArgs = 'Not enough arguments',
qsInvalid = ' is not a valid selector',
// detect structural pseudo-classes in selectors
reNthElem = RegExp('(:nth(?:-last)?-child)', 'i'),
reNthType = RegExp('(:nth(?:-last)?-of-type)', 'i'),
// placeholder for global regexp
reOptimizer,
reValidator,
// special handling configuration flags
Config = {
IDS_DUPES: true,
MIXEDCASE: true,
LOGERRORS: true,
VERBOSITY: true
},
NAMESPACE,
QUIRKS_MODE,
HTML_DOCUMENT,
ATTR_STD_OPS = {
'=': 1, '^=': 1, '$=': 1, '|=': 1, '*=': 1, '~=': 1
},
HTML_TABLE = {
'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1,
'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1,
'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1,
'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1,
'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1,
'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1,
'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1,
'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1
},
Combinators = { },
Selectors = { },
Operators = {
'=': { p1: '^',
p2: '$',
p3: 'true' },
'^=': { p1: '^',
p2: '',
p3: 'true' },
'$=': { p1: '',
p2: '$',
p3: 'true' },
'*=': { p1: '',
p2: '',
p3: 'true' },
'|=': { p1: '^',
p2: '(-|$)',
p3: 'true' },
'~=': { p1: '(^|\\s)',
p2: '(\\s|$)',
p3: 'true' }
},
concatCall =
function(nodes, callback) {
var i = 0, l = nodes.length, list = Array(l);
while (l > i) {
if (false === callback(list[i] = nodes[i])) break;
++i;
}
return list;
},
concatList =
function(list, nodes) {
var i = -1, l = nodes.length;
while (l--) { list[list.length] = nodes[++i]; }
return list;
},
documentOrder =
function(a, b) {
if (!hasDupes && a === b) {
hasDupes = true;
return 0;
}
return a.compareDocumentPosition(b) & 4 ? -1 : 1;
},
hasDupes = false,
unique =
function(nodes) {
var i = 0, j = -1, l = nodes.length + 1, list = [ ];
while (--l) {
if (nodes[i++] === nodes[i]) continue;
list[++j] = nodes[i - 1];
}
hasDupes = false;
return list;
},
// check context for mixed content
hasMixedCaseTagNames =
function(context) {
var ns, api = 'getElementsByTagNameNS';
// current host context (ownerDocument)
context = context.ownerDocument || context;
// documentElement (root) element namespace or default html/xhtml namespace
ns = context.documentElement.namespaceURI || 'http://www.w3.org/1999/xhtml';
// checking the number of non HTML nodes in the document
return (context[api]('*', '*').length - context[api](ns, '*').length) > 0;
},
switchContext =
function(context, force) {
var oldDoc = doc;
doc = context.ownerDocument || context;
if (force || oldDoc !== doc) {
// force a new check for each document change
// performed before the next select operation
root = doc.documentElement;
HTML_DOCUMENT = isHTML(doc);
QUIRKS_MODE = HTML_DOCUMENT &&
doc.compatMode.indexOf('CSS') < 0;
NAMESPACE = root && root.namespaceURI;
Snapshot.doc = doc;
Snapshot.root = root;
}
return (Snapshot.from = context);
},
// convert single codepoint to UTF-16 encoding
codePointToUTF16 =
function(codePoint) {
// out of range, use replacement character
if (codePoint < 1 || codePoint > 0x10ffff ||
(codePoint > 0xd7ff && codePoint < 0xe000)) {
return '\\ufffd';
}
// javascript strings are UTF-16 encoded
if (codePoint < 0x10000) {
var lowHex = '000' + codePoint.toString(16);
return '\\u' + lowHex.substr(lowHex.length - 4);
}
// supplementary high + low surrogates
return '\\u' + (((codePoint - 0x10000) >> 0x0a) + 0xd800).toString(16) +
'\\u' + (((codePoint - 0x10000) % 0x400) + 0xdc00).toString(16);
},
// convert single codepoint to string
stringFromCodePoint =
function(codePoint) {
// out of range, use replacement character
if (codePoint < 1 || codePoint > 0x10ffff ||
(codePoint > 0xd7ff && codePoint < 0xe000)) {
return '\ufffd';
}
if (codePoint < 0x10000) {
return String.fromCharCode(codePoint);
}
return String.fromCodePoint ?
String.fromCodePoint(codePoint) :
String.fromCharCode(
((codePoint - 0x10000) >> 0x0a) + 0xd800,
((codePoint - 0x10000) % 0x400) + 0xdc00);
},
// convert escape sequence in a CSS string or identifier
// to javascript string with javascript escape sequences
convertEscapes =
function(str) {
return REX.HasEscapes.test(str) ?
str.replace(REX.FixEscapes,
function(substring, p1, p2) {
// unescaped " or '
return p2 ? '\\' + p2 :
// javascript strings are UTF-16 encoded
REX.HexNumbers.test(p1) ? codePointToUTF16(parseInt(p1, 16)) :
// \' \"
REX.EscOrQuote.test(p1) ? substring :
// \g \h \. \# etc
p1;
}
) : str;
},
// convert escape sequence in a CSS string or identifier
// to javascript string with characters representations
unescapeIdentifier =
function(str) {
return REX.HasEscapes.test(str) ?
str.replace(REX.FixEscapes,
function(substring, p1, p2) {
// unescaped " or '
return p2 ? p2 :
// javascript strings are UTF-16 encoded
REX.HexNumbers.test(p1) ? stringFromCodePoint(parseInt(p1, 16)) :
// \' \"
REX.EscOrQuote.test(p1) ? substring :
// \g \h \. \# etc
p1;
}
) : str;
},
method = {
'#': 'getElementById',
'*': 'getElementsByTagName',
'.': 'getElementsByClassName'
},
compat = {
'#': function(c, n) { REX.HasEscapes.test(n) && (n = unescapeIdentifier(n)); return function(e, f) { return byId(n, c); }; },
'*': function(c, n) { REX.HasEscapes.test(n) && (n = unescapeIdentifier(n)); return function(e, f) { return byTag(n, c); }; },
'.': function(c, n) { REX.HasEscapes.test(n) && (n = unescapeIdentifier(n)); return function(e, f) { return byClass(n, c); }; }
},
// find duplicate ids using iterative walk
byIdRaw =
function(id, context) {
var node = context, nodes = [ ], next = node.firstElementChild;
while ((node = next)) {
node.id == id && (nodes[nodes.length] = node);
if ((next = node.firstElementChild || node.nextElementSibling)) continue;
while (!next && (node = node.parentElement) && node !== context) {
next = node.nextElementSibling;
}
}
return nodes;
},
// context agnostic getElementById
byId =
function(id, context) {
var e, nodes, api = method['#'];
// duplicates id allowed
if (Config.IDS_DUPES === false) {
if (api in context) {
return (e = context[api](id)) ? [ e ] : none;
}
} else {
if ('all' in context) {
if ((e = context.all[id])) {
if (e.nodeType == 1) return e.getAttribute('id') != id ? [ ] : [ e ];
else if (id == 'length') return (e = context[api](id)) ? [ e ] : none;
for (i = 0, l = e.length, nodes = [ ]; l > i; ++i) {
if (e[i].id == id) nodes[nodes.length] = e[i];
}
return nodes && nodes.length ? nodes : [ nodes ];
} else return none;
}
}
return byIdRaw(id, context);
},
// context agnostic getElementsByTagName
byTag =
function(tag, context) {
var e, nodes, api = method['*'];
// DOCUMENT_NODE (9) & ELEMENT_NODE (1)
if (api in context) {
return slice.call(context[api](tag));
} else {
// DOCUMENT_FRAGMENT_NODE (11)
if ((e = context.firstElementChild)) {
tag = tag.toLowerCase();
if (!(e.nextElementSibling || tag == '*' || e.nodeName.toLowerCase() == tag)) {
return slice.call(e[api](tag));
} else {
nodes = [ ];
do {
if (tag == '*' || e.nodeName.toLowerCase() == tag) nodes[nodes.length] = e;
concatList(nodes, e[api](tag));
} while ((e = e.nextElementSibling));
}
} else nodes = none;
}
return nodes;
},
// context agnostic getElementsByClassName
byClass =
function(cls, context) {
var e, nodes, api = method['.'], reCls;
// DOCUMENT_NODE (9) & ELEMENT_NODE (1)
if (api in context) {
return slice.call(context[api](cls));
} else {
// DOCUMENT_FRAGMENT_NODE (11)
if ((e = context.firstElementChild)) {
reCls = RegExp('(^|\\s)' + cls + '(\\s|$)', QUIRKS_MODE ? 'i' : '');
if (!(e.nextElementSibling || reCls.test(e.className))) {
return slice.call(e[api](cls));
} else {
nodes = [ ];
do {
if (reCls.test(e.className)) nodes[nodes.length] = e;
concatList(nodes, e[api](cls));
} while ((e = e.nextElementSibling));
}
} else nodes = none;
}
return nodes;
},
// namespace aware hasAttribute
// helper for XML/XHTML documents
hasAttributeNS =
function(e, name) {
var i, l, attr = e.getAttributeNames();
name = RegExp(':?' + name + '$', HTML_DOCUMENT ? 'i' : '');
for (i = 0, l = attr.length; l > i; ++i) {
if (name.test(attr[i])) return true;
}
return false;
},
// fast resolver for the :nth-child() and :nth-last-child() pseudo-classes
nthElement = (function() {
var idx = 0, len = 0, set = 0, parent = undefined, parents = Array(), nodes = Array();
return function(element, dir) {
// ensure caches are emptied after each run, invoking with dir = 2
if (dir == 2) {
idx = 0; len = 0; set = 0; nodes.length = 0;
parents.length = 0; parent = undefined;
return -1;
}
var e, i, j, k, l;
if (parent === element.parentElement) {
i = set; j = idx; l = len;
} else {
l = parents.length;
parent = element.parentElement;
for (i = -1, j = 0, k = l - 1; l > j; ++j, --k) {
if (parents[j] === parent) { i = j; break; }
if (parents[k] === parent) { i = k; break; }
}
if (i < 0) {
parents[i = l] = parent;
l = 0; nodes[i] = Array();
e = parent && parent.firstElementChild || element;
while (e) { nodes[i][l] = e; if (e === element) j = l; e = e.nextElementSibling; ++l; }
set = i; idx = 0; len = l;
if (l < 2) return l;
} else {
l = nodes[i].length;
set = i;
}
}
if (element !== nodes[i][j] && element !== nodes[i][j = 0]) {
for (j = 0, e = nodes[i], k = l - 1; l > j; ++j, --k) {
if (e[j] === element) { break; }
if (e[k] === element) { j = k; break; }
}
}
idx = j + 1; len = l;
return dir ? l - j : idx;
};
})(),
// fast resolver for the :nth-of-type() and :nth-last-of-type() pseudo-classes
nthOfType = (function() {
var idx = 0, len = 0, set = 0, parent = undefined, parents = Array(), nodes = Array();
return function(element, dir) {
// ensure caches are emptied after each run, invoking with dir = 2
if (dir == 2) {
idx = 0; len = 0; set = 0; nodes.length = 0;
parents.length = 0; parent = undefined;
return -1;
}
var e, i, j, k, l, name = element.nodeName;
if (nodes[set] && nodes[set][name] && parent === element.parentElement) {
i = set; j = idx; l = len;
} else {
l = parents.length;
parent = element.parentElement;
for (i = -1, j = 0, k = l - 1; l > j; ++j, --k) {
if (parents[j] === parent) { i = j; break; }
if (parents[k] === parent) { i = k; break; }
}
if (i < 0 || !nodes[i][name]) {
parents[i = l] = parent;
nodes[i] || (nodes[i] = Object());
l = 0; nodes[i][name] = Array();
e = parent && parent.firstElementChild || element;
while (e) { if (e === element) j = l; if (e.nodeName == name) { nodes[i][name][l] = e; ++l; } e = e.nextElementSibling; }
set = i; idx = j; len = l;
if (l < 2) return l;
} else {
l = nodes[i][name].length;
set = i;
}
}
if (element !== nodes[i][name][j] && element !== nodes[i][name][j = 0]) {
for (j = 0, e = nodes[i][name], k = l - 1; l > j; ++j, --k) {
if (e[j] === element) { break; }
if (e[k] === element) { j = k; break; }
}
}
idx = j + 1; len = l;
return dir ? l - j : idx;
};
})(),
// check if the document type is HTML
isHTML =
function(node) {
var doc = node.ownerDocument || node;
return doc.nodeType == 9 &&
// contentType not in IE <= 11
'contentType' in doc ?
doc.contentType.indexOf('/html') > 0 :
doc.createElement('DiV').nodeName == 'DIV';
},
// configure the engine to use special handling
configure =
function(option, clear) {
if (typeof option == 'string') { return !!Config[option]; }
if (typeof option != 'object') { return Config; }
for (var i in option) {
Config[i] = !!option[i];
}
// clear lambda cache
if (clear) {
matchResolvers = { };
selectResolvers = { };
}
setIdentifierSyntax();
return true;
},
// centralized error and exceptions handling
emit =
function(message, proto) {
var err;
if (Config.VERBOSITY) {
if (proto) {
err = new proto(message);
} else {
err = new global.DOMException(message, 'SyntaxError');
}
throw err;
}
if (Config.LOGERRORS && console && console.log) {
console.log(message);
}
},
// execute the engine initialization code
initialize =
function(doc) {
setIdentifierSyntax();
lastContext = switchContext(doc, true);
},
// build validation regexps used by the engine
setIdentifierSyntax =
function() {
//
// NOTE: SPECIAL CASES IN CSS SYNTAX PARSING RULES
//
// The <EOF-token> https://drafts.csswg.org/css-syntax/#typedef-eof-token
// allow mangled|unclosed selector syntax at the end of selectors strings
//
// Literal equivalent hex representations of the characters: " ' ` ] )
//
// \\x22 = " - double quotes \\x5b = [ - open square bracket
// \\x27 = ' - single quote \\x5d = ] - closed square bracket
// \\x60 = ` - back tick \\x28 = ( - open round parens
// \\x5c = \ - back slash \\x29 = ) - closed round parens
//
// using hex format prevents false matches of opened/closed instances
// pairs, coloring breakage and other editors highlightning problems.
//
var identifier =
// doesn't start with a digit
'(?=[^0-9])' +
// can start with double dash
'(?:-{2}' +
// may include ascii chars
'|[a-zA-Z0-9-_]' +
// non-ascii chars
'|[^\\x00-\\x9f]' +
// escaped chars
'|\\\\[^\\r\\n\\f0-9a-fA-F]' +
// unicode chars
'|\\\\[0-9a-fA-F]{1,6}(?:\\r\\n|\\s)?' +
// any escaped chars
'|\\\\.' +
')+',
pseudonames = '[-\\w]+',
pseudoparms = '(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)',
doublequote = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*(?:"|$)',
singlequote = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*(?:'|$)",
attrparser = identifier + '|' + doublequote + '|' + singlequote,
attrvalues = '([\\x22\\x27]?)((?!\\3)*|(?:\\\\?.)*?)(?:\\3|$)',
attributes =
'\\[' +
// attribute presence
'(?:\\*\\|)?' +
WSP + '?' +
'(' + identifier + '(?::' + identifier + ')?)' +
WSP + '?' +
'(?:' +
'(' + CFG.operators + ')' + WSP + '?' +
'(?:' + attrparser + ')' +
')?' +
// attribute case sensitivity
WSP + '?' + '(i)?' + WSP + '?' +
'(?:\\]|$)',
attrmatcher = attributes.replace(attrparser, attrvalues),
pseudoclass =
'(?:\\x28' + WSP + '*' +
'(?:' + pseudoparms + '?)?|' +
// universal * &
// namespace *|*
'(?:\\*|\\|)|' +
'(?:' +
'(?::' + pseudonames +
'(?:\\x28' + pseudoparms + '?(?:\\x29|$))?|' +
')|' +
'(?:[.#]?' + identifier + ')|' +
'(?:' + attributes + ')' +
')+|' +
'(?:' + WSP + '?,' + WSP + '?)|' +
'(?:' + WSP + '?)|' +
'(?:\\x29|$))*',
standardValidator =
'(?=' + WSP + '?[^>+~(){}<>])' +
'(?:' +
// universal * &
// namespace *|*
'(?:\\*|\\|)|' +
'(?:[.#]?' + identifier + ')+|' +
'(?:' + attributes + ')+|' +
'(?:::?' + pseudonames + pseudoclass + ')|' +
'(?:' + WSP + '?' + CFG.combinators + WSP + '?)|' +
'(?:' + WSP + '?,' + WSP + '?)|' +
'(?:' + WSP + '?)' +
')+';
// the following global RE is used to return the
// deepest nodeName in selector strings and then
// use it to retrieve all possible matching nodes
// that will be filtered by compiled resolvers
reOptimizer = RegExp(
'(?:([.:#*]?)' +
'(' + identifier + ')' +
'(?:' +
':[-\\w]+|' +
'\\[[^\\]]+(?:\\]|$)|' +
'\\x28[^\\x29]+(?:\\x29|$)' +
')*)$');
// global
reValidator = RegExp(standardValidator, 'g');
Patterns.id = RegExp('^#(' + identifier + ')(.*)');
Patterns.tagName = RegExp('^(' + identifier + ')(.*)');
Patterns.className = RegExp('^\\.(' + identifier + ')(.*)');
Patterns.attribute = RegExp('^(?:' + attrmatcher + ')(.*)');
},
F_INIT = '"use strict";return function Resolver(c,f,x,r)',
S_HEAD = 'var e,n,o,j=r.length-1,k=-1',
M_HEAD = 'var e,n,o',
S_LOOP = 'main:while((e=c[++k]))',
N_LOOP = 'main:while((e=c.item(++k)))',
M_LOOP = 'e=c;',
S_BODY = 'r[++j]=c[k];',
N_BODY = 'r[++j]=c.item(k);',
M_BODY = '',
S_TAIL = 'continue main;',
M_TAIL = 'r=true;',
S_TEST = 'if(f(c[k])){break main;}',
N_TEST = 'if(f(c.item(k))){break main;}',
M_TEST = 'f(c);',
S_VARS = [ ],
M_VARS = [ ],
// compile groups or single selector strings into
// executable functions for matching or selecting
compile =
function(selector, mode, callback) {
var factory, token, head = '', loop = '', macro = '', source = '', vars = '';
// 'mode' can be boolean or null
// true = select / false = match
// null to use collection.item()
switch (mode) {
case true:
if (selectLambdas[selector]) { return selectLambdas[selector]; }
macro = S_BODY + (callback ? S_TEST : '') + S_TAIL;
head = S_HEAD;
loop = S_LOOP;
break;
case false:
if (matchLambdas[selector]) { return matchLambdas[selector]; }
macro = M_BODY + (callback ? M_TEST : '') + M_TAIL;
head = M_HEAD;
loop = M_LOOP;
break;
case null:
if (selectLambdas[selector]) { return selectLambdas[selector]; }
macro = N_BODY + (callback ? N_TEST : '') + S_TAIL;
head = S_HEAD;
loop = N_LOOP;
break;
default:
break;
}
source = compileSelector(selector, macro, mode, callback, false);
loop += mode || mode === null ? '{' + source + '}' : source;
if (mode || mode === null && selector.includes(':nth')) {
loop += reNthElem.test(selector) ? 's.nthElement(null, 2);' : '';
loop += reNthType.test(selector) ? 's.nthOfType(null, 2);' : '';
}
if (S_VARS[0] || M_VARS[0]) {
vars = ',' + (S_VARS.join(',') || M_VARS.join(','));
S_VARS.length = 0;
M_VARS.length = 0;
}
factory = Function('s', F_INIT + '{' + head + vars + ';' + loop + 'return r;}')(Snapshot);
return mode || mode === null ? (selectLambdas[selector] = factory) : (matchLambdas[selector] = factory);
},
// build conditional code to check components of selector strings
compileSelector =
function(expression, source, mode, callback, not) {
// N is the negation pseudo-class flag
// D is the default inverted negation flag
var a, b, n, f, i, l, name, nested, NS,
N = not ? '!' : '', D = not ? '' : '!',
compat, expr, match, result, status, symbol, test,
type, selector = expression, selector_string, vars;
// original 'select' or 'match' selector string before normalization
selector_string = mode ? lastSelected : lastMatched;
// isolate selector combinators/components and normalize whitespace
selector = selector.replace(STD.combinator, '$1');//.replace(STD.whitespace, ' ');
while (selector) {
// get namespace prefix if present or get first char of selector
symbol = STD.apimethods.test(selector) ? '|' : selector[0];
switch (symbol) {
// universal resolver
case '*':
match = selector.match(Patterns.universal);
if (N == '!') {
source = 'if(' + N + 'true' +
'){' + source + '}';
}
break;
// id resolver
case '#':
match = selector.match(Patterns.id);
source = 'if(' + N + '(/^' + match[1] + '$/.test(e.getAttribute("id"))' +
')){' + source + '}';
break;
// class name resolver
case '.':
match = selector.match(Patterns.className);
compat = (QUIRKS_MODE ? 'i' : '') + '.test(e.getAttribute("class"))';
source = 'if(' + N + '(/(^|\\s)' + match[1] + '(\\s|$)/' + compat +
')){' + source + '}';
break;
// tag name resolver
case (/[a-z]/i.test(symbol) ? symbol : undefined):
match = selector.match(Patterns.tagName);
source = 'if(' + N + '(e.nodeName' +
(Config.MIXEDCASE || hasMixedCaseTagNames(doc) ?
'.toLowerCase()=="' + match[1].toLowerCase() + '"' :
'=="' + match[1].toUpperCase() + '"') +
')){' + source + '}';
break;
// namespace resolver
case '|':
match = selector.match(Patterns.namespace);
if (match[1] == '*') {
source = 'if(' + N + 'true){' + source + '}';
} else if (!match[1]) {
source = 'if(' + N + '(!e.namespaceURI)){' + source + '}';
} else if (typeof match[1] == 'string' && root.prefix == match[1]) {
source = 'if(' + N + '(e.namespaceURI=="' + NAMESPACE + '")){' + source + '}';
} else {
emit('\'' + selector_string + '\'' + qsInvalid);
}
break;
// attributes resolver
case '[':
match = selector.match(Patterns.attribute);
NS = match[0].match(STD.namespaces);
name = match[1];
expr = name.split(':');
expr = expr.length == 2 ? expr[1] : expr[0];
if (match[2] && !(test = Operators[match[2]])) {
emit('\'' + selector_string + '\'' + qsInvalid);
return '';
}
if (match[4] === '') {
test = match[2] == '~=' ?
{ p1: '^\\s', p2: '+$', p3: 'true' } :
match[2] in ATTR_STD_OPS && match[2] != '~=' ?
{ p1: '^', p2: '$', p3: 'true' } : test;
} else if (match[2] == '~=' && match[4].includes(' ')) {
// whitespace separated list but value contains space
source = 'if(' + N + 'false){' + source + '}';
break;
} else if (match[4]) {
match[4] = convertEscapes(match[4]).replace(REX.RegExpChar, '\\$&');
}
type = match[5] == 'i' || (HTML_DOCUMENT && HTML_TABLE[expr.toLowerCase()]) ? 'i' : '';
source = 'if(' + N + '(' +
(!match[2] ? (NS ? 's.hasAttributeNS(e,"' + name + '")' : 'e.hasAttribute("' + name + '")') :
!match[4] && ATTR_STD_OPS[match[2]] && match[2] != '~=' ? 'e.getAttribute("' + name + '")==""' :
'(/' + test.p1 + match[4] + test.p2 + '/' + type + ').test(e.getAttribute("' + name + '"))==' + test.p3) +
')){' + source + '}';
break;
// *** General sibling combinator
// E ~ F (F relative sibling of E)
case '~':
match = selector.match(Patterns.relative);
source = 'n=e;while((e=e.previousElementSibling)){' + source + '}e=n;';
break;
// *** Adjacent sibling combinator
// E + F (F adiacent sibling of E)
case '+':
match = selector.match(Patterns.adjacent);
source = 'n=e;if((e=e.previousElementSibling)){' + source + '}e=n;';
break;
// *** Descendant combinator
// E F (E ancestor of F)
case '\x09':
case '\x20':
match = selector.match(Patterns.ancestor);
source = 'n=e;while((e=e.parentElement)){' + source + '}e=n;';
break;
// *** Child combinator
// E > F (F children of E)
case '>':
match = selector.match(Patterns.children);
source = 'n=e;if((e=e.parentElement)){' + source + '}e=n;';
break;
// *** user supplied combinators extensions
case (symbol in Combinators ? symbol : undefined):
// for other registered combinators extensions
match[match.length - 1] = '*';
source = Combinators[symbol](match) + source;
break;
// *** tree-structural pseudo-classes
// :root, :empty, :first-child, :last-child, :only-child, :first-of-type, :last-of-type, :only-of-type
case ':':
if ((match = selector.match(Patterns.structural))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'root':
// there can only be one :root element, so exit the loop once found
source = 'if(' + N + '(e===s.root)){' + source + (mode ? 'break main;' : '') + '}';
break;
case 'empty':
// matches elements that don't contain elements or text nodes
source = 'n=e.firstChild;while(n&&!(/1|3/).test(n.nodeType)){n=n.nextSibling}if(' + D + 'n){' + source + '}';
break;
// *** child-indexed pseudo-classes
// :first-child, :last-child, :only-child
case 'only-child':
source = 'if(' + N + '(!e.nextElementSibling&&!e.previousElementSibling)){' + source + '}';
break;
case 'last-child':
source = 'if(' + N + '(!e.nextElementSibling)){' + source + '}';
break;
case 'first-child':
source = 'if(' + N + '(!e.previousElementSibling)){' + source + '}';
break;
// *** typed child-indexed pseudo-classes
// :only-of-type, :last-of-type, :first-of-type
case 'only-of-type':
source = 'o=e.nodeName;' +
'n=e;while((n=n.nextElementSibling)&&n.nodeName!=o);if(!n){' +
'n=e;while((n=n.previousElementSibling)&&n.nodeName!=o);}if(' + D + 'n){' + source + '}';
break;
case 'last-of-type':
source = 'n=e;o=e.nodeName;while((n=n.nextElementSibling)&&n.nodeName!=o);if(' + D + 'n){' + source + '}';
break;
case 'first-of-type':
source = 'n=e;o=e.nodeName;while((n=n.previousElementSibling)&&n.nodeName!=o);if(' + D + 'n){' + source + '}';
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// *** child-indexed & typed child-indexed pseudo-classes
// :nth-child, :nth-of-type, :nth-last-child, :nth-last-of-type
else if ((match = selector.match(Patterns.treestruct))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'nth-child':
case 'nth-of-type':
case 'nth-last-child':
case 'nth-last-of-type':
expr = /-of-type/i.test(match[1]);
if (match[1] && match[2]) {
type = /last/i.test(match[1]);
if (match[2] == 'n') {
source = 'if(' + N + 'true){' + source + '}';
break;
} else if (match[2] == '1') {
test = type ? 'next' : 'previous';
source = expr ? 'n=e;o=e.nodeName;' +
'while((n=n.' + test + 'ElementSibling)&&n.nodeName!=o);if(' + D + 'n){' + source + '}' :
'if(' + N + '!e.' + test + 'ElementSibling){' + source + '}';
break;
} else if (match[2] == 'even' || match[2] == '2n0' || match[2] == '2n+0' || match[2] == '2n') {
test = 'n%2==0';
} else if (match[2] == 'odd' || match[2] == '2n1' || match[2] == '2n+1') {
test = 'n%2==1';
} else {
f = /n/i.test(match[2]);
n = match[2].split('n');
a = parseInt(n[0], 10) || 0;
b = parseInt(n[1], 10) || 0;
if (n[0] == '-') { a = -1; }
if (n[0] == '+') { a = +1; }
test = (b ? '(n' + (b > 0 ? '-' : '+') + Math.abs(b) + ')' : 'n') + '%' + a + '==0' ;
test =
a >= +1 ? (f ? 'n>' + (b - 1) + (Math.abs(a) != 1 ? '&&' + test : '') : 'n==' + a) :
a <= -1 ? (f ? 'n<' + (b + 1) + (Math.abs(a) != 1 ? '&&' + test : '') : 'n==' + a) :
a === 0 ? (n[0] ? 'n==' + b : 'n>' + (b - 1)) : 'false';
}
expr = expr ? 'OfType' : 'Element';
type = type ? 'true' : 'false';
source = 'n=s.nth' + expr + '(e,' + type + ');if(' + N + '(' + test + ')){' + source + '}';
} else {
emit('\'' + selector_string + '\'' + qsInvalid);
}
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// *** logical combination pseudo-classes
// :matches( s1, [ s2, ... ]), :not( s1, [ s2, ... ])
else if ((match = selector.match(Patterns.logicalsel))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'matches':
if (not === true || nested === true) {
emit(':matches() pseudo-class cannot be nested');
}
nested = true;
expr = match[2].replace(REX.CommaGroup, ',').replace(REX.TrimSpaces, '');
// check nested compound selectors s1, s2
expr = match[2].match(REX.SplitGroup);
for (i = 0, l = expr.length; l > i; ++i) {
expr[i] = expr[i].replace(REX.TrimSpaces, '');
source = 'if(s.match("' + expr[i].replace(/\x22/g, '\\"') + '",e)){' + source + '}';
}
break;
case 'not':
if (not === true || nested === true) {
emit(':not() pseudo-class cannot be nested');
}
expr = match[2].replace(REX.CommaGroup, ',').replace(REX.TrimSpaces, '');
// check nested compound selectors s1, s2
expr = match[2].match(REX.SplitGroup);
for (i = 0, l = expr.length; l > i; ++i) {
expr[i] = expr[i].replace(REX.TrimSpaces, '');
source = compileSelector(expr[i], source, false, callback, true);
}
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// *** linguistic pseudo-classes
// :dir( ltr / rtl ), :lang( en )
else if ((match = selector.match(Patterns.linguistic))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'dir':
source = 'var p;if(' + N + '(' +
'(/' + match[2] + '/i.test(e.dir))||(p=s.ancestor("[dir]", e))&&' +
'(/' + match[2] + '/i.test(p.dir))||(e.dir==""||e.dir=="auto")&&' +
'(' + (match[2] == 'ltr' ? '!':'')+ RTL +'.test(e.textContent)))' +
'){' + source + '};';
break;
case 'lang':
expr = '(?:^|-)' + match[2] + '(?:-|$)';
source = 'var p;if(' + N + '(' +
'(e.isConnected&&(e.lang==""&&(p=s.ancestor("[lang]",e)))&&' +
'(p.lang=="' + match[2] + '")||/'+ expr +'/i.test(e.lang)))' +
'){' + source + '};';
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// *** location pseudo-classes
// :link, :visited, :target
else if ((match = selector.match(Patterns.locationpc))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'link':
source = 'if(' + N + '(/^a|area|link$/i.test(e.nodeName)&&e.hasAttribute("href"))){' + source + '}';
break;
case 'visited':
source = 'if(' + N + '(/^a|area|link$/i.test(e.nodeName)&&e.hasAttribute("href")&&e.visited)){' + source + '}';
break;
case 'target':
source = 'if(' + N + '((s.doc.compareDocumentPosition(e)&16)&&s.doc.location.hash&&e.id==s.doc.location.hash.slice(1))){' + source + '}';
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// *** user actions pseudo-classes
// :hover, :active, :focus
else if ((match = selector.match(Patterns.useraction))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'hover':
source = 'hasFocus' in doc && doc.hasFocus() ?
'if(' + N + '(e===s.doc.hoverElement)){' + source + '}' :
'if(' + D + 'true){' + source + '}';
break;
case 'active':
source = 'hasFocus' in doc && doc.hasFocus() ?
'if(' + N + '(e===s.doc.activeElement)){' + source + '}' :
'if(' + D + 'true){' + source + '}';
break;
case 'focus':
source = 'hasFocus' in doc ?
'if(' + N + '(e===s.doc.activeElement&&s.doc.hasFocus()&&(e.type||e.href||typeof e.tabIndex=="number"))){' + source + '}' :
'if(' + N + '(e===s.doc.activeElement&&(e.type||e.href))){' + source + '}';
break;
case 'focus-within':
source = 'hasFocus' in doc ?
'n=s.doc.activeElement;while(e){if(e===n||e.parentNode===n)break;}' +
'if(' + N + '(e===n&&s.doc.hasFocus()&&(e.type||e.href||typeof e.tabIndex=="number"))){' + source + '}' : source;
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// *** user interface and form pseudo-classes
// :enabled, :disabled, :read-only, :read-write, :placeholder-shown, :default
else if ((match = selector.match(Patterns.inputstate))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'enabled':
source = 'if(' + N + '(("form" in e||/^optgroup$/i.test(e.nodeName))&&"disabled" in e &&e.disabled===false' +
')){' + source + '}';
break;
case 'disabled':
// https://www.w3.org/TR/html5/forms.html#enabling-and-disabling-form-controls:-the-disabled-attribute
source = 'if(' + N + '(("form" in e||/^optgroup$/i.test(e.nodeName))&&"disabled" in e&&' +
'(e.disabled===true||(n=s.ancestor("fieldset",e))&&(n=s.first("legend",n))&&!n.contains(e))' +
')){' + source + '}';
break;
case 'read-only':
source =
'if(' + N + '(' +
'(/^textarea$/i.test(e.nodeName)&&(e.readOnly||e.disabled))||' +
'("|password|text|".includes("|"+e.type+"|")&&e.readOnly)' +
')){' + source + '}';
break;
case 'read-write':
source =
'if(' + N + '(' +
'((/^textarea$/i.test(e.nodeName)&&!e.readOnly&&!e.disabled)||' +
'("|password|text|".includes("|"+e.type+"|")&&!e.readOnly&&!e.disabled))||' +
'(e.hasAttribute("contenteditable")||(s.doc.designMode=="on"))' +
')){' + source + '}';
break;
case 'placeholder-shown':
source =
'if(' + N + '(' +
'(/^input|textarea$/i.test(e.nodeName))&&e.hasAttribute("placeholder")&&' +
'("|textarea|password|number|search|email|text|tel|url|".includes("|"+e.type+"|"))&&' +
'(!s.match(":focus",e))' +
')){' + source + '}';
break;
case 'default':
source =
'if(' + N + '("form" in e && e.form)){' +
'var x=0;n=[];' +
'if(e.type=="image")n=e.form.getElementsByTagName("input");' +
'if(e.type=="submit")n=e.form.elements;' +
'while(n[x]&&e!==n[x]){' +
'if(n[x].type=="image")break;' +
'if(n[x].type=="submit")break;' +
'x++;' +
'}' +
'}' +
'if(' + N + '(e.form&&(e===n[x]&&"|image|submit|".includes("|"+e.type+"|"))||' +
'((/^option$/i.test(e.nodeName))&&e.defaultSelected)||' +
'(("|radio|checkbox|".includes("|"+e.type+"|"))&&e.defaultChecked)' +
')){' + source + '}';
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// *** input pseudo-classes (for form validation)
// :checked, :indeterminate, :valid, :invalid, :in-range, :out-of-range, :required, :optional
else if ((match = selector.match(Patterns.inputvalue))) {
match[1] = match[1].toLowerCase();
switch (match[1]) {
case 'checked':
source = 'if(' + N + '(/^input$/i.test(e.nodeName)&&' +
'("|radio|checkbox|".includes("|"+e.type+"|")&&e.checked)||' +
'(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' +
')){' + source + '}';
break;
case 'indeterminate':
source =
'if(' + N + '(/^progress$/i.test(e.nodeName)&&!e.hasAttribute("value"))||' +
'(/^input$/i.test(e.nodeName)&&("checkbox"==e.type&&e.indeterminate)||' +
'("radio"==e.type&&e.name&&!s.first("input[name="+e.name+"]:checked",e.form))' +
')){' + source + '}';
break;
case 'required':
source =
'if(' + N +
'(/^input|select|textarea$/i.test(e.nodeName)&&e.required)' +
'){' + source + '}';
break;
case 'optional':
source =
'if(' + N +
'(/^input|select|textarea$/i.test(e.nodeName)&&!e.required)' +
'){' + source + '}';
break;
case 'invalid':
source =
'if(' + N + '((' +
'(/^form$/i.test(e.nodeName)&&!e.noValidate)||' +
'(e.willValidate&&!e.formNoValidate))&&!e.checkValidity())||' +
'(/^fieldset$/i.test(e.nodeName)&&s.first(":invalid",e))' +
'){' + source + '}';
break;
case 'valid':
source =
'if(' + N + '((' +
'(/^form$/i.test(e.nodeName)&&!e.noValidate)||' +
'(e.willValidate&&!e.formNoValidate))&&e.checkValidity())||' +
'(/^fieldset$/i.test(e.nodeName)&&s.first(":valid",e))' +
'){' + source + '}';
break;
case 'in-range':
source =
'if(' + N +
'(/^input$/i.test(e.nodeName))&&' +
'(e.willValidate&&!e.formNoValidate)&&' +
'(!e.validity.rangeUnderflow&&!e.validity.rangeOverflow)&&' +
'("|date|datetime-local|month|number|range|time|week|".includes("|"+e.type+"|"))&&' +
'("range"==e.type||e.getAttribute("min")||e.getAttribute("max"))' +
'){' + source + '}';
break;
case 'out-of-range':
source =
'if(' + N +
'(/^input$/i.test(e.nodeName))&&' +
'(e.willValidate&&!e.formNoValidate)&&' +
'(e.validity.rangeUnderflow||e.validity.rangeOverflow)&&' +
'("|date|datetime-local|month|number|range|time|week|".includes("|"+e.type+"|"))&&' +
'("range"==e.type||e.getAttribute("min")||e.getAttribute("max"))' +
'){' + source + '}';
break;
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
}
// allow pseudo-elements starting with single colon (:)
// :after, :before, :first-letter, :first-line
else if ((match = selector.match(Patterns.pseudo_sng))) {
source = 'if(' + D + '(e.nodeType==1)){' + source + '}';
}
// allow pseudo-elements starting with double colon (::)
// ::after, ::before, ::marker, ::placeholder, ::inactive-selection, ::selection, ::-webkit-<foo-bar>
else if ((match = selector.match(Patterns.pseudo_dbl))) {
source = 'if(' + D + '(e.nodeType==1)){' + source + '}';
}
else {
// reset
expr = false;
status = false;
// process registered selector extensions
for (expr in Selectors) {
if ((match = selector.match(Selectors[expr].Expression))) {
result = Selectors[expr].Callback(match, source, mode, callback);
if ('match' in result) { match = result.match; }
vars = result.modvar;
if (mode) {
// add extra select() vars
vars && S_VARS.indexOf(vars) < 0 && (S_VARS[S_VARS.length] = vars);
} else {
// add extra match() vars
va