Skip to content

Instantly share code, notes, and snippets.

@lewisje
Last active March 31, 2016 18:38
Show Gist options
  • Save lewisje/55f210b6097cb5de65831168c43c42df to your computer and use it in GitHub Desktop.
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
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