-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathselector-listeners.js
63 lines (54 loc) · 2.48 KB
/
selector-listeners.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
(function(){
var events = {},
selectors = {},
animationCount = 0,
styles = document.createElement('style'),
keyframes = document.head.appendChild(document.head.appendChild(styles).cloneNode()),
prefix = window.CSSKeyframesRule ? { css: '', event: 'animationstart' } : { css: '-webkit-', event: 'webkitAnimationStart' },
trimJoin = function(z){ return z.map(Function.prototype.call, String.prototype.trim).join(' ') },
startEvent = function(e){
e.selector = (events[e.animationName] || {}).selector;
((this.selectorListeners || {})[e.animationName] || []).forEach(function(fn) { fn.call(this, e) }, this);
}
HTMLDocument.prototype.addSelectorListener = HTMLElement.prototype.addSelectorListener = function(values, fn){
var rules = typeof values === 'string' ? [values] : values,
id = rules.length > 1 ? trimJoin(values) : values,
key = selectors[id],
listeners = this.selectorListeners = this.selectorListeners || { count: 0 };
if (key) events[key].count++;
else {
key = selectors[id] = 'selector-listener-' + animationCount++;
var style = rules.pop() + '::before { content: ""; ' + prefix.css + 'animation: ' + key + ' 0.01s; }';
styles.sheet.insertRule(rules.reduceRight(function(current, next) {
return next + '{' + current + '}'
}, style), 0);
events[key] = {
count: 1,
selector: id,
keyframe: keyframes.appendChild(document.createTextNode('@' + prefix.css + 'keyframes ' + key + ' { to { outline-color: rgba(0,0,0,0) } }')),
rule: styles.sheet.cssRules[0]
};
}
listeners.count ? listeners.count++ : this.addEventListener(prefix.event, startEvent, true);
(listeners[key] = listeners[key] || []).push(fn);
};
HTMLDocument.prototype.removeSelectorListener = HTMLElement.prototype.removeSelectorListener = function(values, fn){
var id = typeof values === 'string' ? values : trimJoin(values),
listeners = this.selectorListeners || {},
key = selectors[id],
listener = listeners[key] || [],
index = listener.indexOf(fn);
if (index > -1){
var event = events[selectors[id]];
if (!--event.count){
styles.sheet.deleteRule(styles.sheet.cssRules.item(event.rule));
keyframes.removeChild(event.keyframe);
delete events[key];
delete selectors[id];
}
listeners.count--;
listener.splice(index, 1);
if (!listeners.count) this.removeEventListener(prefix.event, startEvent);
}
};
})();