Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added support for 'live' option to monitor dom for changes

  • Loading branch information...
commit fbc418daa41d864e18a9a89e5380f71d0121a532 1 parent 65a9845
@hakimel authored
View
2  css/example.css
@@ -4,7 +4,6 @@
html, body {
margin: 0px;
padding: 0px;
- line-height: 1;
}
body {
@@ -13,6 +12,7 @@ body {
font-size: 16px;
color: #eee;
margin-bottom: 40px;
+ line-height: 1;
}
header {
View
2  css/stroll.css
@@ -1,5 +1,5 @@
/*!
- * stroll.js 1.0 - CSS scroll effects
+ * stroll.js 1.1 - CSS scroll effects
* http://lab.hakim.se/scroll-effects
* MIT licensed
*
View
2  css/stroll.min.css
@@ -1,5 +1,5 @@
/*!
- * stroll.js 1.0 - CSS scroll effects
+ * stroll.js 1.1 - CSS scroll effects
* http://lab.hakim.se/scroll-effects
* MIT licensed
*
View
123 js/stroll.js
@@ -1,5 +1,5 @@
/*!
- * stroll.js 1.0 - CSS scroll effects
+ * stroll.js 1.1 - CSS scroll effects
* http://lab.hakim.se/scroll-effects
* MIT licensed
*
@@ -9,6 +9,10 @@
"use strict";
+ // When a list is configured as 'live', this is how frequently
+ // the DOM will be polled for changes
+ var LIVE_INTERVAL = 500;
+
// All of the lists that are currently bound
var lists = [];
@@ -33,49 +37,61 @@
* its contained elements based on its position relative to
* the list's viewport.
*
- * @param {HTMLElement} list
- * @param {Object} options
+ * @param {HTMLElement} element
+ * @param {Object} options Additional arguments;
+ * - live; Flags if the DOM should be repeatedly checked for changes
+ * repeatedly. Useful if the list contents is changing. Use
+ * scarcely as it has an impact on performance.
*/
- function add( list, options ) {
+ function add( element, options ) {
// Only allow ul/ol
- if( !list.nodeName || /^(ul|li)$/i.test( list.nodeName ) === false ) {
+ if( !element.nodeName || /^(ul|li)$/i.test( element.nodeName ) === false ) {
return false;
}
// Delete duplicates (but continue and re-bind this list to get the
// latest properties and list items)
- else if( contains( list ) ) {
- remove( list );
+ else if( contains( element ) ) {
+ remove( element );
}
- // TODO: Create and measure element if the list is empty.
-
- var items = Array.prototype.slice.apply( list.children );
+ var list = {
+ element: element,
- // Caching some heights so we don't need to go back to the DOM so much
- var listHeight = list.offsetHeight;
+ /**
+ * Fetches the latest properties from the DOM to ensure that
+ * this list is in sync with its contents.
+ */
+ sync: function() {
+ this.items = Array.prototype.slice.apply( element.children );
- // One loop to get the offsets from the DOM
- for( var i = 0, len = items.length; i < len; i++ ) {
- items[i]._offsetTop = items[i].offsetTop;
- items[i]._offsetHeight = items[i].offsetHeight;
- }
+ // Caching some heights so we don't need to go back to the DOM so much
+ this.listHeight = element.offsetHeight;
- // Add this element to the collection
- lists.push( {
- domElement: list,
+ // One loop to get the offsets from the DOM
+ for( var i = 0, len = this.items.length; i < len; i++ ) {
+ var item = this.items[i];
+ item._offsetTop = item.offsetTop;
+ item._offsetHeight = item.offsetHeight;
+ }
+
+ // Force an update
+ this.update( true );
+ },
- // Apply past/future classes to list items outside of the viewport
+ /**
+ * Apply past/future classes to list items outside of the viewport
+ */
update: function( force ) {
- var scrollTop = list.pageYOffset || list.scrollTop,
- scrollBottom = scrollTop + listHeight;
+ var scrollTop = element.pageYOffset || element.scrollTop,
+ scrollBottom = scrollTop + this.listHeight;
// Quit if nothing changed
- if( scrollTop !== this.lastTop ) {
+ if( scrollTop !== this.lastTop || force ) {
this.lastTop = scrollTop;
// One loop to make our changes to the DOM
- for( var i = 0, len = items.length; i < len; i++ ) {
- var item = items[i];
+ for( var i = 0, len = this.items.length; i < len; i++ ) {
+ var item = this.items[i];
var itemClass = item.className;
// Above list viewport
@@ -99,8 +115,35 @@
}
}
}
+ },
+
+ /**
+ * Cleans up after this list and disposes of it.
+ */
+ destroy: function() {
+ clearInterval( this.syncInterval );
+
+ for( var j = 0, len = this.items.length; j < len; j++ ) {
+ var item = this.items[j];
+
+ item.classList.remove( 'past' );
+ item.classList.remove( 'future' );
+ }
}
- } );
+ };
+
+ // Handle options
+ if( options && options.live ) {
+ list.syncInterval = setInterval( function() {
+ list.sync.call( list );
+ }, LIVE_INTERVAL );
+ }
+
+ // Synchronize the list with the DOM
+ list.sync();
+
+ // Add this element to the collection
+ lists.push( list );
// Start refreshing if this was the first list to be added
if( lists.length === 1 ) {
@@ -113,22 +156,16 @@
* Stops monitoring a list element and removes any classes
* that were applied to its list items.
*
- * @param {HTMLElement} list
+ * @param {HTMLElement} element
*/
- function remove( list ) {
+ function remove( element ) {
for( var i = 0; i < lists.length; i++ ) {
- if( lists[i].domElement == list ) {
+ var list = lists[i];
+
+ if( list.element == element ) {
+ list.destroy();
lists.splice( i, 1 );
i--;
-
- var items = Array.prototype.slice.apply( list.children );
-
- for( var j = 0, len = items.length; j < len; j++ ) {
- var item = items[j];
-
- item.classList.remove( 'past' );
- item.classList.remove( 'future' );
- }
}
}
@@ -141,9 +178,9 @@
/**
* Checks if the specified element has already been bound.
*/
- function contains( list ) {
+ function contains( element ) {
for( var i = 0, len = lists.length; i < len; i++ ) {
- if( lists[i].domElement == list ) {
+ if( lists[i].element == element ) {
return true;
}
}
@@ -198,7 +235,7 @@
/**
* Binds one or more lists for scroll effects.
*
- * @param {Object} options
+ * @see #add()
*/
bind: function( target, options ) {
if( isCapable() ) {
@@ -208,6 +245,8 @@
/**
* Unbinds one or more lists from scroll effects.
+ *
+ * @see #remove()
*/
unbind: function( target ) {
if( isCapable() ) {
View
25 js/stroll.min.js
@@ -1,19 +1,20 @@
/*!
- * stroll.js 1.0 - CSS scroll effects
+ * stroll.js 1.1 - CSS scroll effects
* http://lab.hakim.se/scroll-effects
* MIT licensed
*
* Created by Hakim El Hattab, http://hakim.se
*/
-(function(){var b=[];
-var h=false;function f(){if(h){requestAnimFrame(f);for(var k=0,j=b.length;k<j;k++){b[k].update();}}}function g(o,m){if(!o.nodeName||/^(ul|li)$/i.test(o.nodeName)===false){return false;
-}else{if(e(o)){a(o);}}var k=Array.prototype.slice.apply(o.children);var l=o.offsetHeight;for(var n=0,j=k.length;n<j;n++){k[n]._offsetTop=k[n].offsetTop;
-k[n]._offsetHeight=k[n].offsetHeight;}b.push({domElement:o,update:function(t){var u=o.pageYOffset||o.scrollTop,s=u+l;if(u!==this.lastTop){this.lastTop=u;
-for(var q=0,p=k.length;q<p;q++){var r=k[q];var v=r.className;if(r._offsetTop+r._offsetHeight<u){if(v.indexOf("past")===-1){r.classList.add("past");}}else{if(r._offsetTop>s){if(v.indexOf("future")===-1){r.classList.add("future");
-}}else{if(v.length){r.classList.remove("past");r.classList.remove("future");}}}}}}});if(b.length===1){h=true;f();}}function a(p){for(var n=0;n<b.length;
-n++){if(b[n].domElement==p){b.splice(n,1);n--;var l=Array.prototype.slice.apply(p.children);for(var m=0,k=l.length;m<k;m++){var o=l[m];o.classList.remove("past");
-o.classList.remove("future");}}}if(b.length===0){h=false;}}function e(l){for(var k=0,j=b.length;k<j;k++){if(b[k].domElement==l){return true;}}return false;
-}function c(n,o,l){var m,j;if(typeof n==="string"){var k=document.querySelectorAll(n);for(m=0,j=k.length;m<j;m++){o.call(null,k[m],l);}}else{if(typeof n==="object"&&typeof n.length==="number"){for(m=0,j=n.length;
-m<j;m++){o.call(null,n[m],l);}}else{if(n.nodeName){o.call(null,n,l);}else{throw"Stroll target was of unexpected type.";}}}}function d(){return !!document.body.classList;
-}window.stroll={bind:function(j,i){if(d()){c(j,g,i);}},unbind:function(i){if(d()){c(i,a);}}};window.requestAnimFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(i){window.setTimeout(i,1000/60);
+(function(){var f=500;
+var h=[];var b=false;function g(){if(b){requestAnimFrame(g);for(var k=0,j=h.length;k<j;k++){h[k].update();}}}function i(k,j){if(!k.nodeName||/^(ul|li)$/i.test(k.nodeName)===false){return false;
+}else{if(c(k)){e(k);}}var l={element:k,sync:function(){this.items=Array.prototype.slice.apply(k.children);this.listHeight=k.offsetHeight;for(var n=0,m=this.items.length;
+n<m;n++){var o=this.items[n];o._offsetTop=o.offsetTop;o._offsetHeight=o.offsetHeight;}this.update(true);},update:function(q){var r=k.pageYOffset||k.scrollTop,p=r+this.listHeight;
+if(r!==this.lastTop||q){this.lastTop=r;for(var n=0,m=this.items.length;n<m;n++){var o=this.items[n];var s=o.className;if(o._offsetTop+o._offsetHeight<r){if(s.indexOf("past")===-1){o.classList.add("past");
+}}else{if(o._offsetTop>p){if(s.indexOf("future")===-1){o.classList.add("future");}}else{if(s.length){o.classList.remove("past");o.classList.remove("future");
+}}}}}},destroy:function(){clearInterval(this.syncInterval);for(var n=0,m=this.items.length;n<m;n++){var o=this.items[n];o.classList.remove("past");o.classList.remove("future");
+}}};if(j&&j.live){l.syncInterval=setInterval(function(){l.sync.call(l);},f);}l.sync();h.push(l);if(h.length===1){b=true;g();}}function e(k){for(var j=0;
+j<h.length;j++){var l=h[j];if(l.element==k){l.destroy();h.splice(j,1);j--;}}if(h.length===0){b=false;}}function c(l){for(var k=0,j=h.length;k<j;k++){if(h[k].element==l){return true;
+}}return false;}function d(n,o,l){var m,j;if(typeof n==="string"){var k=document.querySelectorAll(n);for(m=0,j=k.length;m<j;m++){o.call(null,k[m],l);}}else{if(typeof n==="object"&&typeof n.length==="number"){for(m=0,j=n.length;
+m<j;m++){o.call(null,n[m],l);}}else{if(n.nodeName){o.call(null,n,l);}else{throw"Stroll target was of unexpected type.";}}}}function a(){return !!document.body.classList;
+}window.stroll={bind:function(k,j){if(a()){d(k,i,j);}},unbind:function(j){if(a()){d(j,e);}}};window.requestAnimFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(j){window.setTimeout(j,1000/60);
};})();})();
Please sign in to comment.
Something went wrong with that request. Please try again.