UNPKG

3.69 kBJavaScriptView Raw
1
2
3/*
4 * @version 0.1.1
5 * @date 2015-05-10
6 * @stability 2 - Unstable
7 * @author Lauri Rooden <lauri@rooden.ee>
8 * @license MIT License
9 */
10
11
12
13!function(exports) {
14 var undef
15 , selectorRe = /([.#:[])([-\w]+)(?:\((.+?)\)|([~^$*|]?)=(("|')(?:\\?.)*?\6|[-\w]+))?]?/g
16 , selectorLastRe = /([~\s>+]*)(?:("|')(?:\\?.)*?\2|\(.+?\)|[^\s+>])+$/
17 , selectorSplitRe = /\s*,\s*(?=(?:[^'"()]|"(?:\\?.)*?"|'(?:\\?.)*?'|\(.+?\))+$)/
18 , selectorCache = {}
19 , selectorMap = {
20 "any": "m(_,v)",
21 "empty": "!_.lastChild",
22 "enabled": "!m(_,':disabled')",
23 "first-child": "(a=_.parentNode)&&a.firstChild==_",
24 "first-of-type": "!p(_,_.tagName)",
25 "lang": "m(c(_,'[lang]'),'[lang|='+v+']')",
26 "last-child": "(a=_.parentNode)&&a.lastChild==_",
27 "last-of-type": "!n(_,_.tagName)",
28 "link": "m(_,'a[href]')",
29 "not": "!m(_,v)",
30 "nth-child": "(a=2,'odd'==v?b=1:'even'==v?b=0:a=1 in(v=v.split('n'))?(b=v[1],v[0]):(b=v[0],0),v=_.parentNode.childNodes,v=1+v.indexOf(_),0==a?v==b:('-'==a||0==(v-b)%a)&&(0<a||v<=b))",
31 "only-child": "(a=_.parentNode)&&a.firstChild==a.lastChild",
32 "only-of-type": "!p(_,_.tagName)&&!n(_,_.tagName)",
33 "optional": "!m(_,':required')",
34 "root": "(a=_.parentNode)&&!a.tagName",
35 ".": "~_.className.split(/\\s+/).indexOf(a)",
36 "#": "_.id==a",
37 "^": "!a.indexOf(v)",
38 "|": "a.split('-')[0]==v",
39 "$": "a.slice(-v.length)==v",
40 "~": "~a.split(/\\s+/).indexOf(v)",
41 "*": "~a.indexOf(v)",
42 ">>": "m(_.parentNode,v)",
43 "++": "m(_.previousSibling,v)",
44 "~~": "p(_,v)",
45 "": "c(_.parentNode,v)"
46 }
47
48 selectorMap["nth-last-child"] = selectorMap["nth-child"].replace("1+", "v.length-")
49
50 function selectorFn(str) {
51 // jshint evil:true
52 return selectorCache[str] ||
53 (selectorCache[str] = Function("m,c,n,p", "return function(_,v,a,b){return " +
54 str.split(selectorSplitRe).map(function(sel) {
55 var relation, from
56 , rules = ["_&&_.nodeType==1"]
57 , parentSel = sel.replace(selectorLastRe, function(_, _rel, a, start) {
58 from = start + _rel.length
59 relation = _rel.trim()
60 return ""
61 })
62 , tag = sel.slice(from).replace(selectorRe, function(_, op, key, subSel, fn, val, quotation) {
63 rules.push(
64 "((v='" +
65 (subSel || (quotation ? val.slice(1, -1) : val) || "").replace(/'/g, "\\'") +
66 "'),(a='" + key + "'),1)"
67 ,
68 selectorMap[op == ":" ? key : op] ||
69 "(a=_.getAttribute(a))" +
70 (fn ? "&&" + selectorMap[fn] : val ? "==v" : "")
71 )
72 return ""
73 })
74
75 if (tag && tag != "*") rules[0] += "&&_.tagName=='" + tag.toUpperCase() + "'"
76 if (parentSel) rules.push("(v='" + parentSel + "')", selectorMap[relation + relation])
77 return rules.join("&&")
78 }).join("||") + "}"
79 )(matches, closest, next, prev))
80 }
81
82
83 function walk(next, el, sel, first, nextFn) {
84 var out = []
85 sel = selectorFn(sel)
86 for (; el; el = el[next] || nextFn && nextFn(el)) if (sel(el)) {
87 if (first) return el
88 out.push(el)
89 }
90 return first ? null : out
91 }
92
93 function find(node, sel, first) {
94 return walk("firstChild", node.firstChild, sel, first, function(el) {
95 var next = el.nextSibling
96 while (!next && ((el = el.parentNode) !== node)) next = el.nextSibling
97 return next
98 })
99 }
100
101 function matches(el, sel) {
102 return !!selectorFn(sel)(el)
103 }
104
105 function closest(el, sel) {
106 return walk("parentNode", el, sel, 1)
107 }
108
109 function next(el, sel) {
110 return walk("nextSibling", el.nextSibling, sel, 1)
111 }
112
113 function prev(el, sel) {
114 return walk("previousSibling", el.previousSibling, sel, 1)
115 }
116
117
118 exports.find = find
119 exports.fn = selectorFn
120 exports.matches = matches
121 exports.closest = closest
122 exports.next = next
123 exports.prev = prev
124 exports.selectorMap = selectorMap
125}(this)
126