From 266ce37e92bf90b2f09221a11c900442c72d1ffe Mon Sep 17 00:00:00 2001 From: Riyaz Shaikh Date: Tue, 13 Oct 2015 14:55:41 -0500 Subject: [PATCH 1/4] Ability to cancel future events on return false Primary use is to listen to first match on comma separated selectors. --- selector-listeners.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selector-listeners.js b/selector-listeners.js index bcc6a63..ed36c8b 100644 --- a/selector-listeners.js +++ b/selector-listeners.js @@ -9,7 +9,7 @@ startEvent = function(event){ event.selector = (events[event.animationName] || {}).selector; ((this.selectorListeners || {})[event.animationName] || []).forEach(function(fn){ - fn.call(this, event); + if (fn.call(this, event) === false) this.removeSelectorListener(event.selector, fn); }, this); }, prefix = (function() { From c09e85fb2a9c462deb626e1318db556c6ba23978 Mon Sep 17 00:00:00 2001 From: Riyaz Shaikh Date: Tue, 13 Oct 2015 15:40:43 -0500 Subject: [PATCH 2/4] Avoid generating keyframe selectors with same id Fixes bug with initializing multiple selector-listeners at the same time. --- selector-listeners.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selector-listeners.js b/selector-listeners.js index ed36c8b..e888cc3 100644 --- a/selector-listeners.js +++ b/selector-listeners.js @@ -34,7 +34,7 @@ if (key) events[key].count++; else { - key = selectors[selector] = 'SelectorListener-' + new Date().getTime(); + key = selectors[selector] = 'SelectorListener-' + Math.random().toString(16).substr(2, 9); var node = document.createTextNode('@' + (prefix.keyframes ? prefix.css : '') + 'keyframes ' + key + ' {' +'from { outline-color: #fff; } to { outline-color: #000; }' + '}'); From d6499f217400690925035e957421b1fb50bb675c Mon Sep 17 00:00:00 2001 From: Riyaz Shaikh Date: Mon, 23 Nov 2015 10:55:49 -0600 Subject: [PATCH 3/4] Some improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added onSelector() to stop after single selector. Added visibility:hidden to hide elements we’re listening for, until they have been modified. Better way to delete stylesheet rules --- selector-listeners.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/selector-listeners.js b/selector-listeners.js index e888cc3..4fd9e26 100644 --- a/selector-listeners.js +++ b/selector-listeners.js @@ -8,18 +8,23 @@ startNames = ['animationstart', 'oAnimationStart', 'MSAnimationStart', 'webkitAnimationStart'], startEvent = function(event){ event.selector = (events[event.animationName] || {}).selector; + var removeList = []; ((this.selectorListeners || {})[event.animationName] || []).forEach(function(fn){ - if (fn.call(this, event) === false) this.removeSelectorListener(event.selector, fn); + if (fn.call(this, event) === false) removeList.push(fn); + }, this); + removeList.forEach(function(fn) { + this.removeSelectorListener(event.selector, fn); }, this); }, prefix = (function() { var duration = 'animation-duration: 0.001s;', name = 'animation-name: SelectorListener !important;', + visibility = 'visibility:hidden;', computed = window.getComputedStyle(document.documentElement, ''), pre = (Array.prototype.slice.call(computed).join('').match(/moz|webkit|ms/)||(computed.OLink===''&&['o']))[0]; return { css: '-' + pre + '-', - properties: '{' + duration + name + '-' + pre + '-' + duration + '-' + pre + '-' + name + '}', + properties: '{' + visibility + duration + name + '-' + pre + '-' + duration + '-' + pre + '-' + name + '}', keyframes: !!(window.CSSKeyframesRule || window[('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1] + 'CSSKeyframesRule']) }; })(); @@ -39,8 +44,9 @@ +'from { outline-color: #fff; } to { outline-color: #000; }' + '}'); keyframes.appendChild(node); - styles.sheet.insertRule(selector + prefix.properties.replace(/SelectorListener/g, key), 0); - events[key] = { count: 1, selector: selector, keyframe: node, rule: styles.sheet.cssRules[0] }; + var rule = document.createTextNode(selector + prefix.properties.replace(/SelectorListener/g, key)); + styles.appendChild(rule); + events[key] = { count: 1, selector: selector, keyframe: node, rule: rule }; } if (listeners.count) listeners.count++; @@ -64,7 +70,7 @@ var event = events[selectors[selector]]; event.count--; if (!event.count){ - styles.sheet.deleteRule(styles.sheet.cssRules.item(event.rule)); + styles.removeChild(event.rule); keyframes.removeChild(event.keyframe); delete events[key]; delete selectors[selector]; @@ -77,5 +83,10 @@ }, this); } }; - + + // Single invocation version + HTMLDocument.prototype.onSelector = HTMLElement.prototype.onSelector = function(selector,fn) { + this.addSelectorListener(selector, function(event) { fn(event); return false; }); + }; + })(); From 338479fe60d23fb1cce21e0b1930e22914d643fd Mon Sep 17 00:00:00 2001 From: Riyaz Shaikh Date: Tue, 9 Feb 2016 09:57:58 -0600 Subject: [PATCH 4/4] fix for IE --- selector-listeners.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/selector-listeners.js b/selector-listeners.js index 4fd9e26..dc0148f 100644 --- a/selector-listeners.js +++ b/selector-listeners.js @@ -2,6 +2,8 @@ var events = {}, selectors = {}, + docProto = typeof HTMLDocument !== 'undefined' ? HTMLDocument.prototype : Document.prototype, + elemProto = typeof HTMLElement !== 'undefined' ? HTMLElement.prototype : Element.prototype, styles = document.createElement('style'), keyframes = document.createElement('style'), head = document.getElementsByTagName('head')[0], @@ -33,7 +35,7 @@ head.appendChild(styles); head.appendChild(keyframes); - HTMLDocument.prototype.addSelectorListener = HTMLElement.prototype.addSelectorListener = function(selector, fn){ + docProto.addSelectorListener = elemProto.addSelectorListener = function(selector, fn){ var key = selectors[selector], listeners = this.selectorListeners = this.selectorListeners || {}; @@ -60,7 +62,7 @@ (listeners[key] = listeners[key] || []).push(fn); }; - HTMLDocument.prototype.removeSelectorListener = HTMLElement.prototype.removeSelectorListener = function(selector, fn){ + docProto.removeSelectorListener = elemProto.removeSelectorListener = function(selector, fn){ var listeners = this.selectorListeners || {}, key = selectors[selector], listener = listeners[key] || [],