Last active
March 31, 2016 18:38
-
-
Save lewisje/55f210b6097cb5de65831168c43c42df to your computer and use it in GitHub Desktop.
Encapsulates this hack from before MutationObservers existed (IE10+, no-ops on older browsers, MIT license): https://davidwalsh.name/detect-node-insertion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var nodeInsertion = (function (document, undefined) { | |
'use strict'; | |
function noop() {} | |
var result = {add: noop, remove: noop}; | |
if (typeof String.prototype.trim !== 'function') return result; // Every browser that supports animations also has String#trim | |
// a stylesheet that holds our special keyframe code: https://davidwalsh.name/add-rules-stylesheets | |
var animName = ('node_' + Math.random() + '_inserted').split('.').join(''), sheet = (function () { | |
var style = document.createElement('style'); | |
style.appendChild(document.createTextNode(['@-o-','@-moz-', '@-webkit-', '@', ''].join('keyframes ' + | |
animName + ' {\n from {opacity: 0.99;}\n to {opacity: 1;}\n}\n'))); | |
document.head.appendChild(style); | |
return style.sheet; | |
})(), addCSSRule = function (sheet, selector, rules, index) { | |
if (typeof sheet.insertRule === 'function') addCSSRule = function addCSSRule(sheet, selector, rules, index) { | |
return sheet.insertRule(selector + '{' + rules + '}', index); | |
}; | |
else if (typeof sheet.addRule === 'function') addCSSRule = function addCSSRule(sheet, selector, rules, index) { | |
return sheet.addRule(selector, rules, index); | |
}; | |
else addCSSRule = noop; | |
return addCSSRule(sheet, selector, rules, index); | |
}, animEvents = ['oAnimationStart','mozAnimationstart', 'MSAnimationStart', 'webkitAnimationStart', 'animationstart'], | |
alen = animEvents.length, prefixes = ['-o-', '-moz-', '-webkit-', '', ''], canDelete = typeof sheet.deleteRule === 'function', | |
animEvent = null, animFound = false, listeners = [], insertionAnim = prefixes.join('animation-duration: 0.001s; ') + | |
prefixes.join('animation-name: ' + animName + '; '); | |
if (addCSSRule === noop) return result; | |
var checkRule = function checkRule(rules, selector, index) { | |
return index in rules && rules[index].cssText.split('{')[0].indexOf(selector) !== -1; | |
}, defaultSel = function defaultSel(sel, def) { | |
return typeof sel !== 'string' ? def : sel.trim() || def; | |
}; | |
// listens solely for new direct descendants | |
// returns index to be passed into the `remove` method | |
result.add = function add(func, sel, desc) { | |
if (typeof func !== 'function') throw new TypeError('A function must be passed in'); | |
var s = defaultSel(sel, 'body'), d = defaultSel(desc, '*'), elts = document.querySelectorAll(s), i = elts.length, | |
rules = sheet.cssRules, len = rules.length, selector = s + ' > ' + d, wrapped = function wrapped(e) { | |
var evt = e || event; | |
if (!animEvent) animEvent = evt.type; | |
if (evt.type === animEvent && evt.animationName === animName) return func.call(this, evt); | |
}, j; | |
listeners.push({func: wrapped, sel: s, desc: d}); | |
while (i--) { | |
if (animEvent) elts[i].addEventListener(animEvent, wrapped, false); | |
else for (j = alen; j--;) elts[i].addEventListener(animEvents[j], wrapped, false); | |
} | |
for (i = len; i--;) if (checkRule(rules, selector, i)) return listeners.length; | |
addCSSRule(sheet, selector, insertionAnim, len); | |
return listeners.length; | |
}; | |
result.remove = function remove(index) { | |
if (!((index - 1) in listeners)) return; | |
var listener = listeners[index - 1], func = listener.func, s = listener.sel, | |
elts = document.querySelectorAll(s), i = elts.length, j; | |
while (i--) { | |
if (animEvent && animFound) elts[i].removeEventListener(animEvent, func, false); | |
else { | |
if (animEvent) animFound = true; | |
for (j = alen; j--;) elts[i].removeEventListener(animEvents[j], func, false); | |
} | |
} | |
if (canDelete) { | |
var rules = sheet.cssRules, selector = s + ' > ' + listener.desc; | |
for (i = rules.length; i--;) if (checkRule(rules, selector, i)) sheet.deleteRule(i); | |
} | |
listeners.splice(index - 1); | |
}; | |
return result; | |
})(document); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment