From c8fdbf3001b7c066a74dde9fa78202619827f3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20Ol=C3=A1h?= Date: Sun, 29 Jun 2014 15:56:17 +0200 Subject: [PATCH] get rid of the sync() method, `live` turns on asynchronous loading without needing to synchronise the tree --- README.md | 9 +++------ css/site.css | 8 ++++++++ demo.html | 9 ++++++++- dist/wow.js | 46 ++++++++++++++++++++++++++++++++-------------- dist/wow.min.js | 4 ++-- src/wow.coffee | 27 +++++++++++++++++---------- 6 files changed, 70 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index d6c83c1..6d1068f 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,8 @@ var wow = new WOW( boxClass: 'wow', // animated element css class (default is wow) animateClass: 'animated', // animation css class (default is animated) offset: 0, // distance to the element when triggering the animation (default is 0) - mobile: true // trigger animations on mobile devices (true is default) - live: false // allow later synchronization (false is default) + mobile: true, // trigger animations on mobile devices (default is true) + live: false // act on asynchronously loaded content (default is false) } ); wow.init(); @@ -86,14 +86,11 @@ var wow = new WOW( ); wow.init(); -// Example +// Example content loading setTimeout(function () { var moarItems = document.createElement('section'); moarItems.className = 'wow slideInRight'; document.body.appendChild(moarItems); - - // Use `.sync()` method to let WOW.js know there are new elements appended - wow.sync(); }); ``` diff --git a/css/site.css b/css/site.css index 9b9f1df..7004371 100644 --- a/css/site.css +++ b/css/site.css @@ -26,3 +26,11 @@ section { .section--green { background-color: #2ecc71; } + +#main { + text-align: center; +} + +#more { + margin: 20px auto 48px; +} diff --git a/demo.html b/demo.html index b268cce..87dac2d 100644 --- a/demo.html +++ b/demo.html @@ -27,6 +27,7 @@

WOW.js

+ @@ -34,10 +35,16 @@

WOW.js

wow = new WOW( { animateClass: 'animated', - offset: 100 + offset: 100, + live: true } ); wow.init(); + document.getElementById('moar').onclick = function() { + var section = document.createElement('section'); + section.className = 'section--purple wow fadeInDown'; + this.parentNode.insertBefore(section, this); + }; diff --git a/dist/wow.js b/dist/wow.js index 2d2559a..993f835 100644 --- a/dist/wow.js +++ b/dist/wow.js @@ -92,10 +92,11 @@ WOW.prototype.start = function() { var box, _i, _len, _ref; + this.stopped = false; this.boxes = this.element.getElementsByClassName(this.config.boxClass); if (this.boxes.length) { if (this.disabled()) { - return this.resetStyle(); + this.resetStyle(); } else { _ref = this.boxes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -104,12 +105,41 @@ } window.addEventListener('scroll', this.scrollHandler, false); window.addEventListener('resize', this.scrollHandler, false); - return this.interval = setInterval(this.scrollCallback, 50); + this.interval = setInterval(this.scrollCallback, 50); } } + if (this.config.live) { + return new MutationObserver((function(_this) { + return function(records) { + var newElements, node, record, _j, _k, _l, _len1, _len2, _len3, _ref1, _ref2; + if (!_this.stopped) { + newElements = []; + for (_j = 0, _len1 = records.length; _j < _len1; _j++) { + record = records[_j]; + _ref1 = record.addedNodes || []; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + node = _ref1[_k]; + if (node.classList.contains(_this.config.boxClass)) { + newElements.push(node); + } + } + } + for (_l = 0, _len3 = newElements.length; _l < _len3; _l++) { + box = newElements[_l]; + _this.applyStyle(box, true); + } + return (_ref2 = _this.boxes).push.apply(_ref2, newElements); + } + }; + })(this)).observe(document.body, { + childList: true, + subtree: true + }); + } }; WOW.prototype.stop = function() { + this.stopped = true; window.removeEventListener('scroll', this.scrollHandler, false); window.removeEventListener('resize', this.scrollHandler, false); if (this.interval != null) { @@ -300,18 +330,6 @@ return !this.config.mobile && this.util().isMobile(navigator.userAgent); }; - WOW.prototype.sync = function() { - var box, newElements, _i, _len, _ref; - if (this.config.live) { - newElements = this.element.querySelectorAll('.' + this.config.boxClass + ':not(.' + this.config.animateClass + ')'); - for (_i = 0, _len = newElements.length; _i < _len; _i++) { - box = newElements[_i]; - this.applyStyle(box, true); - } - return (_ref = this.boxes).push.apply(_ref, newElements); - } - }; - return WOW; })(); diff --git a/dist/wow.min.js b/dist/wow.min.js index ae9510a..aae88c4 100644 --- a/dist/wow.min.js +++ b/dist/wow.min.js @@ -1,2 +1,2 @@ -/*! WOW - v0.1.9 - 2014-05-17 -* Copyright (c) 2014 Matthieu Aussaguel; Licensed MIT */(function(){var a,b,c=function(a,b){return function(){return a.apply(b,arguments)}};a=function(){function a(){}return a.prototype.extend=function(a,b){var c,d;for(c in a)d=a[c],null!=d&&(b[c]=d);return b},a.prototype.isMobile=function(a){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(a)},a}(),b=this.WeakMap||(b=function(){function a(){this.keys=[],this.values=[]}return a.prototype.get=function(a){var b,c,d,e,f;for(f=this.keys,b=d=0,e=f.length;e>d;b=++d)if(c=f[b],c===a)return this.values[b]},a.prototype.set=function(a,b){var c,d,e,f,g;for(g=this.keys,c=e=0,f=g.length;f>e;c=++e)if(d=g[c],d===a)return void(this.values[c]=b);return this.keys.push(a),this.values.push(b)},a}()),this.WOW=function(){function d(a){null==a&&(a={}),this.scrollCallback=c(this.scrollCallback,this),this.scrollHandler=c(this.scrollHandler,this),this.start=c(this.start,this),this.scrolled=!0,this.config=this.util().extend(a,this.defaults),this.animationNameCache=new b}return d.prototype.defaults={boxClass:"wow",animateClass:"animated",offset:0,mobile:!0,live:!1},d.prototype.init=function(){var a;return this.element=window.document.documentElement,"interactive"===(a=document.readyState)||"complete"===a?this.start():document.addEventListener("DOMContentLoaded",this.start)},d.prototype.start=function(){var a,b,c,d;if(this.boxes=this.element.getElementsByClassName(this.config.boxClass),this.boxes.length){if(this.disabled())return this.resetStyle();for(d=this.boxes,b=0,c=d.length;c>b;b++)a=d[b],this.applyStyle(a,!0);return window.addEventListener("scroll",this.scrollHandler,!1),window.addEventListener("resize",this.scrollHandler,!1),this.interval=setInterval(this.scrollCallback,50)}},d.prototype.stop=function(){return window.removeEventListener("scroll",this.scrollHandler,!1),window.removeEventListener("resize",this.scrollHandler,!1),null!=this.interval?clearInterval(this.interval):void 0},d.prototype.show=function(a){return this.applyStyle(a),a.className=""+a.className+" "+this.config.animateClass},d.prototype.applyStyle=function(a,b){var c,d,e;return d=a.getAttribute("data-wow-duration"),c=a.getAttribute("data-wow-delay"),e=a.getAttribute("data-wow-iteration"),this.animate(function(f){return function(){return f.customStyle(a,b,d,c,e)}}(this))},d.prototype.animate=function(){return"requestAnimationFrame"in window?function(a){return window.requestAnimationFrame(a)}:function(a){return a()}}(),d.prototype.resetStyle=function(){var a,b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(a.setAttribute("style","visibility: visible;"));return e},d.prototype.customStyle=function(a,b,c,d,e){return b&&this.cacheAnimationName(a),a.style.visibility=b?"hidden":"visible",c&&this.vendorSet(a.style,{animationDuration:c}),d&&this.vendorSet(a.style,{animationDelay:d}),e&&this.vendorSet(a.style,{animationIterationCount:e}),this.vendorSet(a.style,{animationName:b?"none":this.cachedAnimationName(a)}),a},d.prototype.vendors=["moz","webkit"],d.prototype.vendorSet=function(a,b){var c,d,e,f;f=[];for(c in b)d=b[c],a[""+c]=d,f.push(function(){var b,f,g,h;for(g=this.vendors,h=[],b=0,f=g.length;f>b;b++)e=g[b],h.push(a[""+e+c.charAt(0).toUpperCase()+c.substr(1)]=d);return h}.call(this));return f},d.prototype.vendorCSS=function(a,b){var c,d,e,f,g,h;for(d=window.getComputedStyle(a),c=d.getPropertyCSSValue(b),h=this.vendors,f=0,g=h.length;g>f;f++)e=h[f],c=c||d.getPropertyCSSValue("-"+e+"-"+b);return c},d.prototype.animationName=function(a){var b;try{b=this.vendorCSS(a,"animation-name").cssText}catch(c){b=window.getComputedStyle(a).getPropertyValue("animation-name")}return"none"===b?"":b},d.prototype.cacheAnimationName=function(a){return this.animationNameCache.set(a,this.animationName(a))},d.prototype.cachedAnimationName=function(a){return this.animationNameCache.get(a)},d.prototype.scrollHandler=function(){return this.scrolled=!0},d.prototype.scrollCallback=function(){var a;return!this.scrolled||(this.scrolled=!1,this.boxes=function(){var b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],a&&(this.isVisible(a)?this.show(a):e.push(a));return e}.call(this),this.boxes.length||this.config.live)?void 0:this.stop()},d.prototype.offsetTop=function(a){for(var b;void 0===a.offsetTop;)a=a.parentNode;for(b=a.offsetTop;a=a.offsetParent;)b+=a.offsetTop;return b},d.prototype.isVisible=function(a){var b,c,d,e,f;return c=a.getAttribute("data-wow-offset")||this.config.offset,f=window.pageYOffset,e=f+this.element.clientHeight-c,d=this.offsetTop(a),b=d+a.clientHeight,e>=d&&b>=f},d.prototype.util=function(){return this._util||(this._util=new a)},d.prototype.disabled=function(){return!this.config.mobile&&this.util().isMobile(navigator.userAgent)},d.prototype.sync=function(){var a,b,c,d,e;if(this.config.live){for(b=this.element.querySelectorAll("."+this.config.boxClass+":not(."+this.config.animateClass+")"),c=0,d=b.length;d>c;c++)a=b[c],this.applyStyle(a,!0);return(e=this.boxes).push.apply(e,b)}},d}()}).call(this); \ No newline at end of file +/*! WOW - v0.1.9 - 2014-06-29 +* Copyright (c) 2014 Matthieu Aussaguel; Licensed MIT */(function(){var a,b,c=function(a,b){return function(){return a.apply(b,arguments)}};a=function(){function a(){}return a.prototype.extend=function(a,b){var c,d;for(c in a)d=a[c],null!=d&&(b[c]=d);return b},a.prototype.isMobile=function(a){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(a)},a}(),b=this.WeakMap||(b=function(){function a(){this.keys=[],this.values=[]}return a.prototype.get=function(a){var b,c,d,e,f;for(f=this.keys,b=d=0,e=f.length;e>d;b=++d)if(c=f[b],c===a)return this.values[b]},a.prototype.set=function(a,b){var c,d,e,f,g;for(g=this.keys,c=e=0,f=g.length;f>e;c=++e)if(d=g[c],d===a)return void(this.values[c]=b);return this.keys.push(a),this.values.push(b)},a}()),this.WOW=function(){function d(a){null==a&&(a={}),this.scrollCallback=c(this.scrollCallback,this),this.scrollHandler=c(this.scrollHandler,this),this.start=c(this.start,this),this.scrolled=!0,this.config=this.util().extend(a,this.defaults),this.animationNameCache=new b}return d.prototype.defaults={boxClass:"wow",animateClass:"animated",offset:0,mobile:!0,live:!1},d.prototype.init=function(){var a;return this.element=window.document.documentElement,"interactive"===(a=document.readyState)||"complete"===a?this.start():document.addEventListener("DOMContentLoaded",this.start)},d.prototype.start=function(){var a,b,c,d;if(this.stopped=!1,this.boxes=this.element.getElementsByClassName(this.config.boxClass),this.boxes.length)if(this.disabled())this.resetStyle();else{for(d=this.boxes,b=0,c=d.length;c>b;b++)a=d[b],this.applyStyle(a,!0);window.addEventListener("scroll",this.scrollHandler,!1),window.addEventListener("resize",this.scrollHandler,!1),this.interval=setInterval(this.scrollCallback,50)}return this.config.live?new MutationObserver(function(b){return function(c){var d,e,f,g,h,i,j,k,l,m,n;if(!b.stopped){for(d=[],g=0,j=c.length;j>g;g++)for(f=c[g],m=f.addedNodes||[],h=0,k=m.length;k>h;h++)e=m[h],e.classList.contains(b.config.boxClass)&&d.push(e);for(i=0,l=d.length;l>i;i++)a=d[i],b.applyStyle(a,!0);return(n=b.boxes).push.apply(n,d)}}}(this)).observe(document.body,{childList:!0,subtree:!0}):void 0},d.prototype.stop=function(){return this.stopped=!0,window.removeEventListener("scroll",this.scrollHandler,!1),window.removeEventListener("resize",this.scrollHandler,!1),null!=this.interval?clearInterval(this.interval):void 0},d.prototype.show=function(a){return this.applyStyle(a),a.className=""+a.className+" "+this.config.animateClass},d.prototype.applyStyle=function(a,b){var c,d,e;return d=a.getAttribute("data-wow-duration"),c=a.getAttribute("data-wow-delay"),e=a.getAttribute("data-wow-iteration"),this.animate(function(f){return function(){return f.customStyle(a,b,d,c,e)}}(this))},d.prototype.animate=function(){return"requestAnimationFrame"in window?function(a){return window.requestAnimationFrame(a)}:function(a){return a()}}(),d.prototype.resetStyle=function(){var a,b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(a.setAttribute("style","visibility: visible;"));return e},d.prototype.customStyle=function(a,b,c,d,e){return b&&this.cacheAnimationName(a),a.style.visibility=b?"hidden":"visible",c&&this.vendorSet(a.style,{animationDuration:c}),d&&this.vendorSet(a.style,{animationDelay:d}),e&&this.vendorSet(a.style,{animationIterationCount:e}),this.vendorSet(a.style,{animationName:b?"none":this.cachedAnimationName(a)}),a},d.prototype.vendors=["moz","webkit"],d.prototype.vendorSet=function(a,b){var c,d,e,f;f=[];for(c in b)d=b[c],a[""+c]=d,f.push(function(){var b,f,g,h;for(g=this.vendors,h=[],b=0,f=g.length;f>b;b++)e=g[b],h.push(a[""+e+c.charAt(0).toUpperCase()+c.substr(1)]=d);return h}.call(this));return f},d.prototype.vendorCSS=function(a,b){var c,d,e,f,g,h;for(d=window.getComputedStyle(a),c=d.getPropertyCSSValue(b),h=this.vendors,f=0,g=h.length;g>f;f++)e=h[f],c=c||d.getPropertyCSSValue("-"+e+"-"+b);return c},d.prototype.animationName=function(a){var b;try{b=this.vendorCSS(a,"animation-name").cssText}catch(c){b=window.getComputedStyle(a).getPropertyValue("animation-name")}return"none"===b?"":b},d.prototype.cacheAnimationName=function(a){return this.animationNameCache.set(a,this.animationName(a))},d.prototype.cachedAnimationName=function(a){return this.animationNameCache.get(a)},d.prototype.scrollHandler=function(){return this.scrolled=!0},d.prototype.scrollCallback=function(){var a;return!this.scrolled||(this.scrolled=!1,this.boxes=function(){var b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],a&&(this.isVisible(a)?this.show(a):e.push(a));return e}.call(this),this.boxes.length||this.config.live)?void 0:this.stop()},d.prototype.offsetTop=function(a){for(var b;void 0===a.offsetTop;)a=a.parentNode;for(b=a.offsetTop;a=a.offsetParent;)b+=a.offsetTop;return b},d.prototype.isVisible=function(a){var b,c,d,e,f;return c=a.getAttribute("data-wow-offset")||this.config.offset,f=window.pageYOffset,e=f+this.element.clientHeight-c,d=this.offsetTop(a),b=d+a.clientHeight,e>=d&&b>=f},d.prototype.util=function(){return this._util||(this._util=new a)},d.prototype.disabled=function(){return!this.config.mobile&&this.util().isMobile(navigator.userAgent)},d}()}).call(this); \ No newline at end of file diff --git a/src/wow.coffee b/src/wow.coffee index 83da439..d9a1948 100644 --- a/src/wow.coffee +++ b/src/wow.coffee @@ -57,6 +57,7 @@ class @WOW document.addEventListener 'DOMContentLoaded', @start start: => + @stopped = false @boxes = @element.getElementsByClassName(@config.boxClass) if @boxes.length if @disabled() @@ -66,9 +67,24 @@ class @WOW window.addEventListener('scroll', @scrollHandler, false) window.addEventListener('resize', @scrollHandler, false) @interval = setInterval @scrollCallback, 50 + if @config.live + new MutationObserver (records) => + unless @stopped + newElements = [] + for record in records + for node in record.addedNodes or [] + # Not every browser supports `classList`, + # but those that support `MutationObserver` all do. + newElements.push(node) if node.classList.contains(@config.boxClass) + @applyStyle(box, true) for box in newElements + @boxes.push newElements... + .observe document.body, + childList: true + subtree: true # unbind the scroll event stop: -> + @stopped = true window.removeEventListener('scroll', @scrollHandler, false) window.removeEventListener('resize', @scrollHandler, false) clearInterval @interval if @interval? @@ -148,7 +164,7 @@ class @WOW @show(box) continue box - @stop() unless @boxes.length || @config.live + @stop() unless @boxes.length or @config.live # Calculate element offset top @@ -176,12 +192,3 @@ class @WOW disabled: -> not @config.mobile and @util().isMobile(navigator.userAgent) - - # refresh method for new elements - sync: -> - if @config.live - # Using querySelector as it's even better browser support - # @see https://developer.mozilla.org/en-US/docs/Web/API/element.querySelector - newElements = @element.querySelectorAll('.' + @config.boxClass + ':not(.' + @config.animateClass + ')') - @applyStyle(box, true) for box in newElements - @boxes.push newElements...