From eb97a68abbcc0c9c9fec0b2e79db33b603a62262 Mon Sep 17 00:00:00 2001 From: lxjwlt Date: Sat, 7 Oct 2017 21:28:51 +0800 Subject: [PATCH] support detect selector when the DOM element has css animation-name defined #4 --- src/sentinel.js | 50 ++++++++++++++++++++++++++++++++----------------- test/tests.js | 40 ++++++++++++++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/sentinel.js b/src/sentinel.js index 2e79c0f..a1b793f 100644 --- a/src/sentinel.js +++ b/src/sentinel.js @@ -3,8 +3,15 @@ var isArray = Array.isArray, animationCallbacks = {}, styleEl, styleSheet, - cssRules; + cssRules, + ANIM = 'sentinel-animation-name'; +function matches (elem, selector) { + try { + return elem.matches(selector); + } catch (e) {} + return false; +} return { /** @@ -22,16 +29,25 @@ return { // add animationstart event listener doc.addEventListener('animationstart', function(ev, callbacks, l, i) { - callbacks = animationCallbacks[ev.animationName]; + callbacks = animationCallbacks[ev.animationName] || []; + + Object.keys(selectorToAnimationMap).forEach(function (selector) { + if (matches(ev.target, selector)) { + callbacks = callbacks.concat( + animationCallbacks[selectorToAnimationMap[selector]] || [] + ); + } + }); + + // iterate through callbacks + l = callbacks.length; // exit if callbacks haven't been registered - if (!callbacks) return; + if (!l) return; // stop other callbacks from firing ev.stopImmediatePropagation(); - // iterate through callbacks - l = callbacks.length; for (i=0; i < l; i++) callbacks[i](ev.target); }, true); @@ -40,6 +56,13 @@ return { head.insertBefore(styleEl, head.firstChild); styleSheet = styleEl.sheet; cssRules = styleSheet.cssRules; + + styleSheet.insertRule('* {animation-name:' + ANIM +';}', cssRules.length); + + styleSheet.insertRule( + '@keyframes ' + ANIM + '{from{transform:none;}to{transform:none;}}', + cssRules.length + ); } // listify argument and add css rules/ cache callbacks @@ -54,19 +77,12 @@ return { selectorToAnimationMap[selector] = animId = isCustomName ? selector.slice(1) : 'sentinel-' + Math.random().toString(16).slice(2); - - // add keyframe rule - cssRules[styleSheet.insertRule( - '@keyframes ' + animId + - '{from{transform:none;}to{transform:none;}}', - cssRules.length)] - ._id = selector; - - // add selector animation rule - if (!isCustomName) { + + if (isCustomName) { + // add keyframe rule cssRules[styleSheet.insertRule( - selector + '{animation-duration:0.0001s;animation-name:' + - animId + ';}', + '@keyframes ' + animId + + '{from{transform:none;}to{transform:none;}}', cssRules.length)] ._id = selector; } diff --git a/test/tests.js b/test/tests.js index 2d2faf2..59d390a 100644 --- a/test/tests.js +++ b/test/tests.js @@ -111,7 +111,7 @@ describe('SentinelJS tests', function() { // check CSS rules var cssRules = getSentinelStyleEl().sheet.cssRules; - assert.equal(cssRules.length, 2); + assert.equal(cssRules.length, 4); done(); }); @@ -126,6 +126,36 @@ describe('SentinelJS tests', function() { testEl.className = 'my-div'; document.body.appendChild(testEl); }); + + it('detect new nodes with custom animation names', function(done) { + + // add css rule + var styleEl = document.createElement('style'); + document.head.appendChild(styleEl); + var sheet = styleEl.sheet; + sheet.insertRule( + '.my-div2{animation-duration:0.0001s;animation-name:node-inserted2;}', + sheet.cssRules.length) + + sheet.insertRule( + '@keyframes node-inserted2 {from{transform:none;}to{transform:none;}}', + sheet.cssRules.length) + + // add watch + sentinel.on('.my-div2', function(el) { + assert.equal(el.className, 'my-div2'); + + assert.ok(getComputedStyle(el).animationName.indexOf('node-inserted2') >= 0); + + document.head.removeChild(styleEl); + + done(); + }); + + // add element to dom + testEl.className = 'my-div2'; + document.body.appendChild(testEl); + }); }); @@ -145,7 +175,7 @@ describe('SentinelJS tests', function() { // when queue is empty css rules will be removed sentinel.off('.test-div', fn2); - assert.equal(cssRules.length, 0); + assert.equal(cssRules.length, 2); }); @@ -157,7 +187,7 @@ describe('SentinelJS tests', function() { assert.equal(cssRules.length, 2); sentinel.off('.test-div'); - assert.equal(cssRules.length, 0); + assert.equal(cssRules.length, 2); }); @@ -173,11 +203,11 @@ describe('SentinelJS tests', function() { // removing first one will keep css rules sentinel.off('!node-inserted', fn1); - assert.equal(cssRules.length, 1); + assert.equal(cssRules.length, 3); // when queue is empty css rules will be removed sentinel.off('!node-inserted', fn2); - assert.equal(cssRules.length, 0); + assert.equal(cssRules.length, 2); }); }); });