From c9105289e1a2dca943b13a588dcb043d3c7bc22a Mon Sep 17 00:00:00 2001 From: Glen Cheney Date: Fri, 9 May 2014 00:47:19 -0700 Subject: [PATCH] Update add items 3rd mode to mix in to the current set. When the items are sorted, using the mix in method is much better looking, but adding items to the end is better for infinite scrolling and DOM order. * Mix in. * Add to end. * Add to end with sequential delay. --- Gruntfile.js | 3 +- _posts/demos/2013-06-19-adding-removing.html | 40 +++++++++-- dist/jquery.shuffle.js | 76 ++++++++++++-------- dist/jquery.shuffle.min.js | 2 +- dist/jquery.shuffle.modernizr.js | 76 ++++++++++++-------- dist/jquery.shuffle.modernizr.min.js | 2 +- js/demos/adding-removing.js | 51 ++++++++++--- src/shuffle.js | 76 ++++++++++++-------- test/.jshintrc | 1 + test/specs.js | 72 ++++++++++++------- todo.md | 1 - 11 files changed, 264 insertions(+), 136 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 4230768..1900cdd 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -148,7 +148,8 @@ module.exports = function(grunt) { 'concat:main', 'concat:modernizr', 'uglify:main', - 'uglify:modernizr' + 'uglify:modernizr', + 'test' ]); }); diff --git a/_posts/demos/2013-06-19-adding-removing.html b/_posts/demos/2013-06-19-adding-removing.html index 56e6a0e..b57d6ad 100644 --- a/_posts/demos/2013-06-19-adding-removing.html +++ b/_posts/demos/2013-06-19-adding-removing.html @@ -31,6 +31,14 @@ extraJS: [ "demos/adding-removing.js" ] left: .5em; } + .box::after { + content: 'Box SKU: ' attr(created); + position: absolute; + color: white; + bottom: .5em; + left: .5em; + } + .box.shuffle-item, .box:first-child { margin-left: 0; @@ -56,19 +64,37 @@ extraJS: [ "demos/adding-removing.js" ]
- +
+ Add mode: + +
+
+ +
+
+ Sort: + +
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/dist/jquery.shuffle.js b/dist/jquery.shuffle.js index 41ae81b..e7c99b7 100644 --- a/dist/jquery.shuffle.js +++ b/dist/jquery.shuffle.js @@ -370,7 +370,7 @@ Shuffle.prototype = { * Filter the elements by a category. * @param {string} [category] Category to filter by. If it's given, the last * category will be used to filter the items. - * @param {jQuery} [$collection] Optionally filter a collection. Defaults to + * @param {ArrayLike} [$collection] Optionally filter a collection. Defaults to * all the items. * @return {jQuery} Filtered items. */ @@ -401,7 +401,7 @@ Shuffle.prototype = { /** * Returns an object containing the filtered and concealed elements. * @param {string|Function} category Category or function to filter by. - * @param {jQuery} $items jQuery collection of items to filter. + * @param {ArrayLike.} $items A collection of items to filter. * @return {!{filtered: jQuery, concealed: jQuery}} * @private */ @@ -417,7 +417,7 @@ Shuffle.prototype = { // whether to hide it or not. } else { var self = this; - $items.each(function(i, el) { + $.each($items, function(i, el) { var $item = $(el); if ( self._doesPassFilter( category, $item ) ) { $filtered = $filtered.add( $item ); @@ -502,6 +502,11 @@ Shuffle.prototype = { }); }, + /** + * Sets a transition delay on a collection of elements, making each delay + * greater than the last. + * @param {ArrayLike.} $collection Array to iterate over. + */ _setSequentialDelay : function( $collection ) { var self = this; @@ -701,13 +706,7 @@ Shuffle.prototype = { _reLayout : function() { this._resetCols(); - - // If we've already sorted the elements, keep them sorted - if ( this.lastSort ) { - this.sort( this.lastSort, true ); - } else { - this._layout( this._getFilteredItems().get(), this._filterEnd ); - } + this.sort( this.lastSort, true ); }, _getItemPosition : function( $item ) { @@ -933,6 +932,8 @@ Shuffle.prototype = { // Use timeouts so that all the items have been set to hidden before the // callbacks are executed. + // Note(glen): I'm still not convinced this is the best way to handle firing + // a callback when all items have finished. if ( this._layoutList.length > 0 && $.inArray( item, this._layoutList ) > -1 ) { this._layoutEnd( callback ); this._layoutList.length = 0; @@ -984,44 +985,55 @@ Shuffle.prototype = { }, _addItems : function( $newItems, animateIn, isSequential ) { - var self = this; + this._initItems( $newItems ); + this._setTransitions( $newItems ); + this.$items = this._getItems(); - if ( !self.supported ) { - animateIn = false; - } + // Hide all items + // $newItems.css('opacity', 0); - self._initItems( $newItems ); - self._setTransitions( $newItems ); - self.$items = self._getItems(); + // Shrink all items (without transitions). + this._shrink( $newItems, $.noop ); + $.each(this.styleQueue, function(i, transitionObj) { + transitionObj.skipTransition = true; + }); + this._processStyleQueue(); - // Hide all items - $newItems.css('opacity', 0); + if ( this.supported && animateIn ) { + this._addItemsToEnd( $newItems, isSequential ); + } else { + this.shuffle( this.lastFilter ); + } + }, + + _addItemsToEnd : function( $newItems, isSequential ) { // Get ones that passed the current filter - var $passed = self._filter( null, $newItems ); + var $passed = this._filter( null, $newItems ); var passed = $passed.get(); // How many filtered elements? - self._updateItemCount(); - - if ( animateIn ) { - self._layout( passed, null, true ); + this._updateItemCount(); - if ( isSequential ) { - self._setSequentialDelay( $passed ); - } + this._layout( passed, null, true ); - self._revealAppended( $passed ); - } else { - self._layout( passed ); + if ( isSequential ) { + this._setSequentialDelay( passed ); } + + this._revealAppended( passed ); }, + /** + * Triggers appended elements to fade in. + * @param {ArrayLike.} $newFilteredItems Collection of elements. + * @private + */ _revealAppended : function( $newFilteredItems ) { var self = this; setTimeout(function() { - $newFilteredItems.each(function(i, el) { + $.each($newFilteredItems, function(i, el) { self._transition({ $item: $(el), opacity: 1, @@ -1257,6 +1269,8 @@ Shuffle.settings = { }, offset: { top: 0, left: 0 }, revealAppendedDelay: 300, + lastSort: {}, + lastFilter: ALL_ITEMS, enabled: true, destroyed: false, initialized: false, diff --git a/dist/jquery.shuffle.min.js b/dist/jquery.shuffle.min.js index 019827f..e575aa2 100644 --- a/dist/jquery.shuffle.min.js +++ b/dist/jquery.shuffle.min.js @@ -5,4 +5,4 @@ * @license MIT license * @version 2.1.1 */ -!function(a){"function"==typeof define&&define.amd?define(["jquery","modernizr"],a):a(window.$,window.Modernizr)}(function(a,b,c){"use strict";function d(a){return a?a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-"):""}function e(b,c,d){var e,f,g,h=null,i=0;d=d||{};var j=function(){i=d.leading===!1?0:a.now(),h=null,g=b.apply(e,f),e=f=null};return function(){var k=a.now();i||d.leading!==!1||(i=k);var l=c-(k-i);return e=this,f=arguments,0>=l||l>c?(clearTimeout(h),h=null,i=k,g=b.apply(e,f),e=f=null):h||d.trailing===!1||(h=setTimeout(j,l)),g}}if("object"!=typeof b)throw new Error("Shuffle.js requires Modernizr.\nhttp://vestride.github.io/Shuffle/#dependencies");var f=b.prefixed("transition"),g=b.prefixed("transitionDelay"),h=b.prefixed("transitionDuration"),i={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[f],j=b.prefixed("transform"),k=d(j),l=b.csstransforms&&b.csstransitions,m=b.csstransforms3d,n="shuffle",o="all",p="groups",q=1,r=.001,s=0,t=a(window),u=function(b,c){c=c||{},a.extend(this,u.options,c,u.settings),this.$el=a(b),this.unique="shuffle_"+s++,this._fire(u.EventType.LOADING),this._init(),setTimeout(a.proxy(function(){this.initialized=!0,this._fire(u.EventType.DONE)},this),16)};return u.EventType={LOADING:"loading",DONE:"done",SHRINK:"shrink",SHRUNK:"shrunk",FILTER:"filter",FILTERED:"filtered",SORTED:"sorted",LAYOUT:"layout",REMOVED:"removed"},u.ClassName={BASE:n,SHUFFLE_ITEM:"shuffle-item",FILTERED:"filtered",CONCEALED:"concealed"},u._getItemTransformString=function(a,b,c){return m?"translate3d("+a+"px, "+b+"px, 0) scale3d("+c+", "+c+", 1)":"translate("+a+"px, "+b+"px) scale("+c+", "+c+")"},u._getPreciseDimension=function(b,c){var d;return d=window.getComputedStyle?window.getComputedStyle(b,null)[c]:a(b).css(c),parseFloat(d)},u._getOuterWidth=function(b,c){var d=b.offsetWidth;if(c){var e=a(b).css(["marginLeft","marginRight"]),f=parseFloat(e.marginLeft)||0,g=parseFloat(e.marginRight)||0;d+=f+g}return d},u._getOuterHeight=function(b,c){var d=b.offsetHeight;if(c){var e=a(b).css(["marginTop","marginBottom"]),f=parseFloat(e.marginTop)||0,g=parseFloat(e.marginBottom)||0;d+=f+g}return d},u._skipTransition=function(b,c,d){var e=b.style[h];b.style[h]="0ms",a.isFunction(c)?c():b.style[c]=d;var f=b.offsetWidth;f=null,b.style[h]=e},u.prototype={_init:function(){var a=this;a._layoutList=[],a._shrinkList=[],a._setVars(),a._resetCols(),this.$el.addClass(u.ClassName.BASE),a._initItems(),t.on("resize."+n+"."+a.unique,a._getResizeFunction());var b=a.$el.css(["paddingLeft","paddingRight","position"]),c=u._getOuterWidth(a.$el[0]);"static"===b.position&&(a.$el[0].style.position="relative"),a.offset={left:parseInt(b.paddingLeft,10)||0,top:parseInt(b.paddingTop,10)||0},a._setColumns(parseInt(c,10)),a.shuffle(a.group,a.initialSort),a.supported&&setTimeout(function(){a._setTransitions(),a.$el[0].style[f]="height "+a.speed+"ms "+a.easing},0)},_getResizeFunction:function(){var b=a.proxy(this._onResize,this);return this.throttle?this.throttle(b,this.throttleTime):b},_setVars:function(){var b=this,c=b.columnWidth;b.$items=b._getItems(),0===c&&null!==b.sizer&&(c=b.sizer),"string"==typeof c?b.$sizer=b.$el.find(c):c&&c.nodeType&&1===c.nodeType?b.$sizer=a(c):c&&c.jquery&&(b.$sizer=c),b.$sizer&&b.$sizer.length&&(b.useSizer=!0,b.sizer=b.$sizer[0])},_filter:function(a,b){a=a||this.lastFilter,b=b||this.$items,this._fire(u.EventType.FILTER);var c=this._getFilteredSets(a,b);return this._toggleFilterClasses(c.filtered,c.concealed),this.lastFilter=a,"string"==typeof a&&(this.group=a),c.filtered},_getFilteredSets:function(b,c){var d=a(),e=a();if(b===o)d=c;else{var f=this;c.each(function(c,g){var h=a(g);f._doesPassFilter(b,h)?d=d.add(h):e=e.add(h)})}return{filtered:d,concealed:e}},_doesPassFilter:function(b,c){if(a.isFunction(b))return b.call(c[0],c,this);var d=c.data(p),e=this.delimeter&&!a.isArray(d)?d.split(this.delimeter):d;return a.inArray(b,e)>-1},_toggleFilterClasses:function(a,b){a.removeClass(u.ClassName.CONCEALED).addClass(u.ClassName.FILTERED),b.removeClass(u.ClassName.FILTERED).addClass(u.ClassName.CONCEALED)},_initItems:function(a){a=a||this.$items,a.addClass([u.ClassName.SHUFFLE_ITEM,u.ClassName.FILTERED].join(" ")),a.css(this.itemCss).data("position",{x:0,y:0})},_updateItemCount:function(){this.visibleItems=this._getFilteredItems().length},_setTransition:function(a){a.style[f]=k+" "+this.speed+"ms "+this.easing+", opacity "+this.speed+"ms "+this.easing},_setTransitions:function(a){var b=this;a=a||b.$items,a.each(function(){b._setTransition(this)})},_setSequentialDelay:function(b){var c=this;c.supported&&a.each(b,function(b,d){d.style[g]="0ms,"+(b+1)*c.sequentialFadeDelay+"ms",a(d).on(i+"."+c.unique,function(b){var d=b.currentTarget;d===b.target&&(d.style[g]="0ms",a(d).off(i+"."+c.unique))})})},_getItems:function(){return this.$el.children(this.itemSelector)},_getFilteredItems:function(){return this.$items.filter("."+u.ClassName.FILTERED)},_getConcealedItems:function(){return this.$items.filter("."+u.ClassName.CONCEALED)},_getColumnSize:function(b,c){var d;return d=a.isFunction(this.columnWidth)?this.columnWidth(c):this.useSizer?u._getPreciseDimension(this.sizer,"width"):this.columnWidth?this.columnWidth:this.$items.length>0?u._getOuterWidth(this.$items[0],!0):c,0===d&&(d=c),d+b},_getGutterSize:function(b){var c;return c=a.isFunction(this.gutterWidth)?this.gutterWidth(b):this.useSizer?u._getPreciseDimension(this.sizer,"marginLeft"):this.gutterWidth},_setColumns:function(a){var b=a||u._getOuterWidth(this.$el[0]),c=this._getGutterSize(b),d=this._getColumnSize(c,b),e=(b+c)/d;Math.abs(Math.round(e)-e)<.03&&(e=Math.round(e)),this.cols=Math.max(Math.floor(e),1),this.containerWidth=b,this.colWidth=d},_setContainerSize:function(){this.$el.css("height",this._getContainerSize())},_getContainerSize:function(){return Math.max.apply(Math,this.colYs)},_fire:function(a,b){this.$el.trigger(a+"."+n,b&&b.length?b:[this])},_layout:function(b,c,d){var e=this;c=c||e._filterEnd,a.each(b,function(b,f){var g=a(f),h=g.data(),i=h.position,j=e._getItemPosition(g);if(g.data("position",j),j.x!==i.x||j.y!==i.y||h.scale!==q){var k={$item:g,x:j.x,y:j.y,scale:q};d?(k.skipTransition=!0,k.opacity=0):(k.opacity=1,k.callback=c),e.styleQueue.push(k),e._layoutList.push(g[0])}}),e._processStyleQueue(),b.length>0&&0===e._layoutList.length&&e._layoutEnd(c),e._setContainerSize()},_resetCols:function(){var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0)},_reLayout:function(){this._resetCols(),this.lastSort?this.sort(this.lastSort,!0):this._layout(this._getFilteredItems().get(),this._filterEnd)},_getItemPosition:function(a){var b=this,c=u._getOuterWidth(a[0],!0),d=c/b.colWidth;Math.abs(Math.round(d)-d)<.03&&(d=Math.round(d));var e=Math.min(Math.ceil(d),b.cols);if(1===e)return b._placeItem(a,b.colYs);var f,g,h=b.cols+1-e,i=[];for(g=0;h>g;g++)f=b.colYs.slice(g,g+e),i[g]=Math.max.apply(Math,f);return b._placeItem(a,i)},_placeItem:function(a,b){for(var c=this,d=Math.min.apply(Math,b),e=0,f=0,g=b.length;g>f;f++)if(b[f]>=d-c.buffer&&b[f]<=d+c.buffer){e=f;break}var h={x:Math.round(c.colWidth*e+c.offset.left),y:Math.round(d+c.offset.top)},i=d+u._getOuterHeight(a[0],!0),j=c.cols+1-g;for(f=0;j>f;f++)c.colYs[e+f]=i;return h},_shrink:function(b,c){var d=this,e=b||d._getConcealedItems();c=c||d._shrinkEnd,e.length&&(d._fire(u.EventType.SHRINK),e.each(function(){var b=a(this),e=b.data(),f=e.scale===r;if(!f){var g={$item:b,x:e.position.x,y:e.position.y,scale:r,opacity:0,callback:c};d.styleQueue.push(g),d._shrinkList.push(b[0])}}))},_onResize:function(){if(this.enabled&&!this.destroyed){var a=u._getOuterWidth(this.$el[0]);a!==this.containerWidth&&this.resized()}},_getStylesForTransition:function(a){var b={opacity:a.opacity};return this.supported?a.x!==c&&(b[j]=u._getItemTransformString(a.x,a.y,a.scale)):(b.left=a.x,b.top=a.y),1===a.opacity&&(b.visibility="visible"),b},_transition:function(a){a.$item.data("scale",a.scale);var b=this._getStylesForTransition(a);this._startItemAnimation(a.$item,b,a.callback)},_startItemAnimation:function(b,c,d){var e=1===c.opacity,f=a.proxy(this._handleItemAnimationEnd,this,d||a.noop,b[0],e);this.supported?(b.css(c),this.initialized?b.on(i+".shuffleitem",f):f()):("visibility"in c&&(b.css("visibility",c.visibility),delete c.visibility),b.stop(!0).animate(c,this.speed,"swing",f))},_handleItemAnimationEnd:function(b,c,d,e){if(e){if(e.target!==c)return;a(c).off(".shuffleitem")}this._layoutList.length>0&&a.inArray(c,this._layoutList)>-1?(this._layoutEnd(b),this._layoutList.length=0):this._shrinkList.length>0&&a.inArray(c,this._shrinkList)>-1&&(this._shrinkList.length=0,setTimeout(a.proxy(b,this),0)),d||(c.style.visibility="hidden")},_processStyleQueue:function(){var b=this;a.each(this.styleQueue,function(a,c){c.skipTransition?u._skipTransition(c.$item[0],function(){c.$item.css(b._getStylesForTransition(c))}):b._transition(c)}),b.styleQueue.length=0},_shrinkEnd:function(){this._fire(u.EventType.SHRUNK)},_filterEnd:function(){this._fire(u.EventType.FILTERED)},_sortEnd:function(){this._fire(u.EventType.SORTED)},_layoutEnd:function(b){setTimeout(a.proxy(function(){this._fire(u.EventType.LAYOUT),b.call(this)},this),0)},_addItems:function(a,b,c){var d=this;d.supported||(b=!1),d._initItems(a),d._setTransitions(a),d.$items=d._getItems(),a.css("opacity",0);var e=d._filter(null,a),f=e.get();d._updateItemCount(),b?(d._layout(f,null,!0),c&&d._setSequentialDelay(e),d._revealAppended(e)):d._layout(f)},_revealAppended:function(b){var c=this;setTimeout(function(){b.each(function(b,d){c._transition({$item:a(d),opacity:1,scale:q})})},c.revealAppendedDelay)},shuffle:function(a,b){var c=this;c.enabled&&(a||(a=o),c._filter(a),c._updateItemCount(),c._shrink(),b&&(c.lastSort=b),c._reLayout())},sort:function(a,b){var c=this,d=c._getFilteredItems().sorted(a);b||c._resetCols(),c._layout(d,function(){b&&c._filterEnd(),c._sortEnd()}),c.lastSort=a},resized:function(a){this.enabled&&(a||this._setColumns(),this._reLayout())},layout:function(){this.update(!0)},update:function(a){this.resized(a)},appended:function(a,b,c){b=b===!1?!1:!0,c=c===!1?!1:!0,this._addItems(a,b,c)},disable:function(){this.enabled=!1},enable:function(a){this.enabled=!0,a!==!1&&this.update()},remove:function(a){if(a.length&&a.jquery){var b=this;return b._shrink(a,function(){var b=this;a.remove(),setTimeout(function(){b.$items=b._getItems(),b.layout(),b._updateItemCount(),b._fire(u.EventType.REMOVED,[a,b]),a=null},0)}),b._processStyleQueue(),b}},destroy:function(){var a=this;t.off("."+a.unique),a.$el.removeClass(n).removeAttr("style").removeData(n),a.$items.removeAttr("style").removeClass("concealed filtered shuffle-item"),a.$items=null,a.$el=null,a.$sizer=null,a.sizer=null,a.destroyed=!0}},u.options={group:o,speed:250,easing:"ease-out",itemSelector:"",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,initialSort:null,throttle:e,throttleTime:300,sequentialFadeDelay:150,supported:l},u.settings={$sizer:null,useSizer:!1,itemCss:{position:"absolute",top:0,left:0},offset:{top:0,left:0},revealAppendedDelay:300,enabled:!0,destroyed:!1,initialized:!1,styleQueue:[]},a.fn.shuffle=function(b){var c=Array.prototype.slice.call(arguments,1);return this.each(function(){var d=a(this),e=d.data(n);e||(e=new u(d,b),d.data(n,e)),"string"==typeof b&&e[b]&&e[b].apply(e,c)})},a.fn.sorted=function(b){var d=a.extend({},a.fn.sorted.defaults,b),e=this.get(),f=!1;return e.length?d.randomize?a.fn.sorted.randomize(e):(a.isFunction(d.by)&&e.sort(function(b,e){if(f)return 0;var g=d.by(a(b)),h=d.by(a(e));return g===c&&h===c?(f=!0,0):h>g||"sortFirst"===g||"sortLast"===h?-1:g>h||"sortLast"===g||"sortFirst"===h?1:0}),f?this.get():(d.reverse&&e.reverse(),e)):[]},a.fn.sorted.defaults={reverse:!1,by:null,randomize:!1},a.fn.sorted.randomize=function(a){var b,c,d=a.length;if(!d)return a;for(;--d;)c=Math.floor(Math.random()*(d+1)),b=a[c],a[c]=a[d],a[d]=b;return a},u}); \ No newline at end of file +!function(a){"function"==typeof define&&define.amd?define(["jquery","modernizr"],a):a(window.$,window.Modernizr)}(function(a,b,c){"use strict";function d(a){return a?a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-"):""}function e(b,c,d){var e,f,g,h=null,i=0;d=d||{};var j=function(){i=d.leading===!1?0:a.now(),h=null,g=b.apply(e,f),e=f=null};return function(){var k=a.now();i||d.leading!==!1||(i=k);var l=c-(k-i);return e=this,f=arguments,0>=l||l>c?(clearTimeout(h),h=null,i=k,g=b.apply(e,f),e=f=null):h||d.trailing===!1||(h=setTimeout(j,l)),g}}if("object"!=typeof b)throw new Error("Shuffle.js requires Modernizr.\nhttp://vestride.github.io/Shuffle/#dependencies");var f=b.prefixed("transition"),g=b.prefixed("transitionDelay"),h=b.prefixed("transitionDuration"),i={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[f],j=b.prefixed("transform"),k=d(j),l=b.csstransforms&&b.csstransitions,m=b.csstransforms3d,n="shuffle",o="all",p="groups",q=1,r=.001,s=0,t=a(window),u=function(b,c){c=c||{},a.extend(this,u.options,c,u.settings),this.$el=a(b),this.unique="shuffle_"+s++,this._fire(u.EventType.LOADING),this._init(),setTimeout(a.proxy(function(){this.initialized=!0,this._fire(u.EventType.DONE)},this),16)};return u.EventType={LOADING:"loading",DONE:"done",SHRINK:"shrink",SHRUNK:"shrunk",FILTER:"filter",FILTERED:"filtered",SORTED:"sorted",LAYOUT:"layout",REMOVED:"removed"},u.ClassName={BASE:n,SHUFFLE_ITEM:"shuffle-item",FILTERED:"filtered",CONCEALED:"concealed"},u._getItemTransformString=function(a,b,c){return m?"translate3d("+a+"px, "+b+"px, 0) scale3d("+c+", "+c+", 1)":"translate("+a+"px, "+b+"px) scale("+c+", "+c+")"},u._getPreciseDimension=function(b,c){var d;return d=window.getComputedStyle?window.getComputedStyle(b,null)[c]:a(b).css(c),parseFloat(d)},u._getOuterWidth=function(b,c){var d=b.offsetWidth;if(c){var e=a(b).css(["marginLeft","marginRight"]),f=parseFloat(e.marginLeft)||0,g=parseFloat(e.marginRight)||0;d+=f+g}return d},u._getOuterHeight=function(b,c){var d=b.offsetHeight;if(c){var e=a(b).css(["marginTop","marginBottom"]),f=parseFloat(e.marginTop)||0,g=parseFloat(e.marginBottom)||0;d+=f+g}return d},u._skipTransition=function(b,c,d){var e=b.style[h];b.style[h]="0ms",a.isFunction(c)?c():b.style[c]=d;var f=b.offsetWidth;f=null,b.style[h]=e},u.prototype={_init:function(){var a=this;a._layoutList=[],a._shrinkList=[],a._setVars(),a._resetCols(),this.$el.addClass(u.ClassName.BASE),a._initItems(),t.on("resize."+n+"."+a.unique,a._getResizeFunction());var b=a.$el.css(["paddingLeft","paddingRight","position"]),c=u._getOuterWidth(a.$el[0]);"static"===b.position&&(a.$el[0].style.position="relative"),a.offset={left:parseInt(b.paddingLeft,10)||0,top:parseInt(b.paddingTop,10)||0},a._setColumns(parseInt(c,10)),a.shuffle(a.group,a.initialSort),a.supported&&setTimeout(function(){a._setTransitions(),a.$el[0].style[f]="height "+a.speed+"ms "+a.easing},0)},_getResizeFunction:function(){var b=a.proxy(this._onResize,this);return this.throttle?this.throttle(b,this.throttleTime):b},_setVars:function(){var b=this,c=b.columnWidth;b.$items=b._getItems(),0===c&&null!==b.sizer&&(c=b.sizer),"string"==typeof c?b.$sizer=b.$el.find(c):c&&c.nodeType&&1===c.nodeType?b.$sizer=a(c):c&&c.jquery&&(b.$sizer=c),b.$sizer&&b.$sizer.length&&(b.useSizer=!0,b.sizer=b.$sizer[0])},_filter:function(a,b){a=a||this.lastFilter,b=b||this.$items,this._fire(u.EventType.FILTER);var c=this._getFilteredSets(a,b);return this._toggleFilterClasses(c.filtered,c.concealed),this.lastFilter=a,"string"==typeof a&&(this.group=a),c.filtered},_getFilteredSets:function(b,c){var d=a(),e=a();if(b===o)d=c;else{var f=this;a.each(c,function(c,g){var h=a(g);f._doesPassFilter(b,h)?d=d.add(h):e=e.add(h)})}return{filtered:d,concealed:e}},_doesPassFilter:function(b,c){if(a.isFunction(b))return b.call(c[0],c,this);var d=c.data(p),e=this.delimeter&&!a.isArray(d)?d.split(this.delimeter):d;return a.inArray(b,e)>-1},_toggleFilterClasses:function(a,b){a.removeClass(u.ClassName.CONCEALED).addClass(u.ClassName.FILTERED),b.removeClass(u.ClassName.FILTERED).addClass(u.ClassName.CONCEALED)},_initItems:function(a){a=a||this.$items,a.addClass([u.ClassName.SHUFFLE_ITEM,u.ClassName.FILTERED].join(" ")),a.css(this.itemCss).data("position",{x:0,y:0})},_updateItemCount:function(){this.visibleItems=this._getFilteredItems().length},_setTransition:function(a){a.style[f]=k+" "+this.speed+"ms "+this.easing+", opacity "+this.speed+"ms "+this.easing},_setTransitions:function(a){var b=this;a=a||b.$items,a.each(function(){b._setTransition(this)})},_setSequentialDelay:function(b){var c=this;c.supported&&a.each(b,function(b,d){d.style[g]="0ms,"+(b+1)*c.sequentialFadeDelay+"ms",a(d).on(i+"."+c.unique,function(b){var d=b.currentTarget;d===b.target&&(d.style[g]="0ms",a(d).off(i+"."+c.unique))})})},_getItems:function(){return this.$el.children(this.itemSelector)},_getFilteredItems:function(){return this.$items.filter("."+u.ClassName.FILTERED)},_getConcealedItems:function(){return this.$items.filter("."+u.ClassName.CONCEALED)},_getColumnSize:function(b,c){var d;return d=a.isFunction(this.columnWidth)?this.columnWidth(c):this.useSizer?u._getPreciseDimension(this.sizer,"width"):this.columnWidth?this.columnWidth:this.$items.length>0?u._getOuterWidth(this.$items[0],!0):c,0===d&&(d=c),d+b},_getGutterSize:function(b){var c;return c=a.isFunction(this.gutterWidth)?this.gutterWidth(b):this.useSizer?u._getPreciseDimension(this.sizer,"marginLeft"):this.gutterWidth},_setColumns:function(a){var b=a||u._getOuterWidth(this.$el[0]),c=this._getGutterSize(b),d=this._getColumnSize(c,b),e=(b+c)/d;Math.abs(Math.round(e)-e)<.03&&(e=Math.round(e)),this.cols=Math.max(Math.floor(e),1),this.containerWidth=b,this.colWidth=d},_setContainerSize:function(){this.$el.css("height",this._getContainerSize())},_getContainerSize:function(){return Math.max.apply(Math,this.colYs)},_fire:function(a,b){this.$el.trigger(a+"."+n,b&&b.length?b:[this])},_layout:function(b,c,d){var e=this;c=c||e._filterEnd,a.each(b,function(b,f){var g=a(f),h=g.data(),i=h.position,j=e._getItemPosition(g);if(g.data("position",j),j.x!==i.x||j.y!==i.y||h.scale!==q){var k={$item:g,x:j.x,y:j.y,scale:q};d?(k.skipTransition=!0,k.opacity=0):(k.opacity=1,k.callback=c),e.styleQueue.push(k),e._layoutList.push(g[0])}}),e._processStyleQueue(),b.length>0&&0===e._layoutList.length&&e._layoutEnd(c),e._setContainerSize()},_resetCols:function(){var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0)},_reLayout:function(){this._resetCols(),this.sort(this.lastSort,!0)},_getItemPosition:function(a){var b=this,c=u._getOuterWidth(a[0],!0),d=c/b.colWidth;Math.abs(Math.round(d)-d)<.03&&(d=Math.round(d));var e=Math.min(Math.ceil(d),b.cols);if(1===e)return b._placeItem(a,b.colYs);var f,g,h=b.cols+1-e,i=[];for(g=0;h>g;g++)f=b.colYs.slice(g,g+e),i[g]=Math.max.apply(Math,f);return b._placeItem(a,i)},_placeItem:function(a,b){for(var c=this,d=Math.min.apply(Math,b),e=0,f=0,g=b.length;g>f;f++)if(b[f]>=d-c.buffer&&b[f]<=d+c.buffer){e=f;break}var h={x:Math.round(c.colWidth*e+c.offset.left),y:Math.round(d+c.offset.top)},i=d+u._getOuterHeight(a[0],!0),j=c.cols+1-g;for(f=0;j>f;f++)c.colYs[e+f]=i;return h},_shrink:function(b,c){var d=this,e=b||d._getConcealedItems();c=c||d._shrinkEnd,e.length&&(d._fire(u.EventType.SHRINK),e.each(function(){var b=a(this),e=b.data(),f=e.scale===r;if(!f){var g={$item:b,x:e.position.x,y:e.position.y,scale:r,opacity:0,callback:c};d.styleQueue.push(g),d._shrinkList.push(b[0])}}))},_onResize:function(){if(this.enabled&&!this.destroyed){var a=u._getOuterWidth(this.$el[0]);a!==this.containerWidth&&this.resized()}},_getStylesForTransition:function(a){var b={opacity:a.opacity};return this.supported?a.x!==c&&(b[j]=u._getItemTransformString(a.x,a.y,a.scale)):(b.left=a.x,b.top=a.y),1===a.opacity&&(b.visibility="visible"),b},_transition:function(a){a.$item.data("scale",a.scale);var b=this._getStylesForTransition(a);this._startItemAnimation(a.$item,b,a.callback)},_startItemAnimation:function(b,c,d){var e=1===c.opacity,f=a.proxy(this._handleItemAnimationEnd,this,d||a.noop,b[0],e);this.supported?(b.css(c),this.initialized?b.on(i+".shuffleitem",f):f()):("visibility"in c&&(b.css("visibility",c.visibility),delete c.visibility),b.stop(!0).animate(c,this.speed,"swing",f))},_handleItemAnimationEnd:function(b,c,d,e){if(e){if(e.target!==c)return;a(c).off(".shuffleitem")}this._layoutList.length>0&&a.inArray(c,this._layoutList)>-1?(this._layoutEnd(b),this._layoutList.length=0):this._shrinkList.length>0&&a.inArray(c,this._shrinkList)>-1&&(this._shrinkList.length=0,setTimeout(a.proxy(b,this),0)),d||(c.style.visibility="hidden")},_processStyleQueue:function(){var b=this;a.each(this.styleQueue,function(a,c){c.skipTransition?u._skipTransition(c.$item[0],function(){c.$item.css(b._getStylesForTransition(c))}):b._transition(c)}),b.styleQueue.length=0},_shrinkEnd:function(){this._fire(u.EventType.SHRUNK)},_filterEnd:function(){this._fire(u.EventType.FILTERED)},_sortEnd:function(){this._fire(u.EventType.SORTED)},_layoutEnd:function(b){setTimeout(a.proxy(function(){this._fire(u.EventType.LAYOUT),b.call(this)},this),0)},_addItems:function(a,b,c){this._initItems(a),this._setTransitions(a),this.$items=this._getItems(),this.supported&&b?this._addItemsToEnd(c):this.shuffle(this.lastFilter)},_addItemsToEnd:function(a,b){a.css("opacity",0);var c=this._filter(null,a),d=c.get();this._updateItemCount(),this._layout(d,null,!0),b&&this._setSequentialDelay(d),this._revealAppended(d)},_revealAppended:function(b){var c=this;setTimeout(function(){a.each(b,function(b,d){c._transition({$item:a(d),opacity:1,scale:q})})},c.revealAppendedDelay)},shuffle:function(a,b){var c=this;c.enabled&&(a||(a=o),c._filter(a),c._updateItemCount(),c._shrink(),b&&(c.lastSort=b),c._reLayout())},sort:function(a,b){var c=this,d=c._getFilteredItems().sorted(a);b||c._resetCols(),c._layout(d,function(){b&&c._filterEnd(),c._sortEnd()}),c.lastSort=a},resized:function(a){this.enabled&&(a||this._setColumns(),this._reLayout())},layout:function(){this.update(!0)},update:function(a){this.resized(a)},appended:function(a,b,c){b=b===!1?!1:!0,c=c===!1?!1:!0,this._addItems(a,b,c)},disable:function(){this.enabled=!1},enable:function(a){this.enabled=!0,a!==!1&&this.update()},remove:function(a){if(a.length&&a.jquery){var b=this;return b._shrink(a,function(){var b=this;a.remove(),setTimeout(function(){b.$items=b._getItems(),b.layout(),b._updateItemCount(),b._fire(u.EventType.REMOVED,[a,b]),a=null},0)}),b._processStyleQueue(),b}},destroy:function(){var a=this;t.off("."+a.unique),a.$el.removeClass(n).removeAttr("style").removeData(n),a.$items.removeAttr("style").removeClass("concealed filtered shuffle-item"),a.$items=null,a.$el=null,a.$sizer=null,a.sizer=null,a.destroyed=!0}},u.options={group:o,speed:250,easing:"ease-out",itemSelector:"",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,initialSort:null,throttle:e,throttleTime:300,sequentialFadeDelay:150,supported:l},u.settings={$sizer:null,useSizer:!1,itemCss:{position:"absolute",top:0,left:0},offset:{top:0,left:0},revealAppendedDelay:300,lastSort:{},lastFilter:o,enabled:!0,destroyed:!1,initialized:!1,styleQueue:[]},a.fn.shuffle=function(b){var c=Array.prototype.slice.call(arguments,1);return this.each(function(){var d=a(this),e=d.data(n);e||(e=new u(d,b),d.data(n,e)),"string"==typeof b&&e[b]&&e[b].apply(e,c)})},a.fn.sorted=function(b){var d=a.extend({},a.fn.sorted.defaults,b),e=this.get(),f=!1;return e.length?d.randomize?a.fn.sorted.randomize(e):(a.isFunction(d.by)&&e.sort(function(b,e){if(f)return 0;var g=d.by(a(b)),h=d.by(a(e));return g===c&&h===c?(f=!0,0):h>g||"sortFirst"===g||"sortLast"===h?-1:g>h||"sortLast"===g||"sortFirst"===h?1:0}),f?this.get():(d.reverse&&e.reverse(),e)):[]},a.fn.sorted.defaults={reverse:!1,by:null,randomize:!1},a.fn.sorted.randomize=function(a){var b,c,d=a.length;if(!d)return a;for(;--d;)c=Math.floor(Math.random()*(d+1)),b=a[c],a[c]=a[d],a[d]=b;return a},u}); \ No newline at end of file diff --git a/dist/jquery.shuffle.modernizr.js b/dist/jquery.shuffle.modernizr.js index 78b4a14..595ee50 100644 --- a/dist/jquery.shuffle.modernizr.js +++ b/dist/jquery.shuffle.modernizr.js @@ -376,7 +376,7 @@ Shuffle.prototype = { * Filter the elements by a category. * @param {string} [category] Category to filter by. If it's given, the last * category will be used to filter the items. - * @param {jQuery} [$collection] Optionally filter a collection. Defaults to + * @param {ArrayLike} [$collection] Optionally filter a collection. Defaults to * all the items. * @return {jQuery} Filtered items. */ @@ -407,7 +407,7 @@ Shuffle.prototype = { /** * Returns an object containing the filtered and concealed elements. * @param {string|Function} category Category or function to filter by. - * @param {jQuery} $items jQuery collection of items to filter. + * @param {ArrayLike.} $items A collection of items to filter. * @return {!{filtered: jQuery, concealed: jQuery}} * @private */ @@ -423,7 +423,7 @@ Shuffle.prototype = { // whether to hide it or not. } else { var self = this; - $items.each(function(i, el) { + $.each($items, function(i, el) { var $item = $(el); if ( self._doesPassFilter( category, $item ) ) { $filtered = $filtered.add( $item ); @@ -508,6 +508,11 @@ Shuffle.prototype = { }); }, + /** + * Sets a transition delay on a collection of elements, making each delay + * greater than the last. + * @param {ArrayLike.} $collection Array to iterate over. + */ _setSequentialDelay : function( $collection ) { var self = this; @@ -707,13 +712,7 @@ Shuffle.prototype = { _reLayout : function() { this._resetCols(); - - // If we've already sorted the elements, keep them sorted - if ( this.lastSort ) { - this.sort( this.lastSort, true ); - } else { - this._layout( this._getFilteredItems().get(), this._filterEnd ); - } + this.sort( this.lastSort, true ); }, _getItemPosition : function( $item ) { @@ -939,6 +938,8 @@ Shuffle.prototype = { // Use timeouts so that all the items have been set to hidden before the // callbacks are executed. + // Note(glen): I'm still not convinced this is the best way to handle firing + // a callback when all items have finished. if ( this._layoutList.length > 0 && $.inArray( item, this._layoutList ) > -1 ) { this._layoutEnd( callback ); this._layoutList.length = 0; @@ -990,44 +991,55 @@ Shuffle.prototype = { }, _addItems : function( $newItems, animateIn, isSequential ) { - var self = this; + this._initItems( $newItems ); + this._setTransitions( $newItems ); + this.$items = this._getItems(); - if ( !self.supported ) { - animateIn = false; - } + // Hide all items + // $newItems.css('opacity', 0); - self._initItems( $newItems ); - self._setTransitions( $newItems ); - self.$items = self._getItems(); + // Shrink all items (without transitions). + this._shrink( $newItems, $.noop ); + $.each(this.styleQueue, function(i, transitionObj) { + transitionObj.skipTransition = true; + }); + this._processStyleQueue(); - // Hide all items - $newItems.css('opacity', 0); + if ( this.supported && animateIn ) { + this._addItemsToEnd( $newItems, isSequential ); + } else { + this.shuffle( this.lastFilter ); + } + }, + + _addItemsToEnd : function( $newItems, isSequential ) { // Get ones that passed the current filter - var $passed = self._filter( null, $newItems ); + var $passed = this._filter( null, $newItems ); var passed = $passed.get(); // How many filtered elements? - self._updateItemCount(); - - if ( animateIn ) { - self._layout( passed, null, true ); + this._updateItemCount(); - if ( isSequential ) { - self._setSequentialDelay( $passed ); - } + this._layout( passed, null, true ); - self._revealAppended( $passed ); - } else { - self._layout( passed ); + if ( isSequential ) { + this._setSequentialDelay( passed ); } + + this._revealAppended( passed ); }, + /** + * Triggers appended elements to fade in. + * @param {ArrayLike.} $newFilteredItems Collection of elements. + * @private + */ _revealAppended : function( $newFilteredItems ) { var self = this; setTimeout(function() { - $newFilteredItems.each(function(i, el) { + $.each($newFilteredItems, function(i, el) { self._transition({ $item: $(el), opacity: 1, @@ -1263,6 +1275,8 @@ Shuffle.settings = { }, offset: { top: 0, left: 0 }, revealAppendedDelay: 300, + lastSort: {}, + lastFilter: ALL_ITEMS, enabled: true, destroyed: false, initialized: false, diff --git a/dist/jquery.shuffle.modernizr.min.js b/dist/jquery.shuffle.modernizr.min.js index a9a3000..699e656 100644 --- a/dist/jquery.shuffle.modernizr.min.js +++ b/dist/jquery.shuffle.modernizr.min.js @@ -5,4 +5,4 @@ * @license MIT license * @version 2.1.1 */ -window.Modernizr=function(a,b,c){function d(a){s.cssText=a}function e(a,b){return typeof a===b}function f(a,b){return!!~(""+a).indexOf(b)}function g(a,b){for(var d in a){var e=a[d];if(!f(e,"-")&&s[e]!==c)return"pfx"==b?e:!0}return!1}function h(a,b,d){for(var f in a){var g=b[a[f]];if(g!==c)return d===!1?a[f]:e(g,"function")?g.bind(d||b):g}return!1}function i(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),f=(a+" "+v.join(d+" ")+d).split(" ");return e(b,"string")||e(b,"undefined")?g(f,b):(f=(a+" "+w.join(d+" ")+d).split(" "),h(f,b,c))}var j,k,l,m="2.6.2",n={},o=!0,p=b.documentElement,q="modernizr",r=b.createElement(q),s=r.style,t=({}.toString," -webkit- -moz- -o- -ms- ".split(" ")),u="Webkit Moz O ms",v=u.split(" "),w=u.toLowerCase().split(" "),x={},y=[],z=y.slice,A=function(a,c,d,e){var f,g,h,i,j=b.createElement("div"),k=b.body,l=k||b.createElement("body");if(parseInt(d,10))for(;d--;)h=b.createElement("div"),h.id=e?e[d]:q+(d+1),j.appendChild(h);return f=["­",'"].join(""),j.id=q,(k?j:l).innerHTML+=f,l.appendChild(j),k||(l.style.background="",l.style.overflow="hidden",i=p.style.overflow,p.style.overflow="hidden",p.appendChild(l)),g=c(j,a),k?j.parentNode.removeChild(j):(l.parentNode.removeChild(l),p.style.overflow=i),!!g},B={}.hasOwnProperty;l=e(B,"undefined")||e(B.call,"undefined")?function(a,b){return b in a&&e(a.constructor.prototype[b],"undefined")}:function(a,b){return B.call(a,b)},Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if("function"!=typeof b)throw new TypeError;var c=z.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,g=b.apply(f,c.concat(z.call(arguments)));return Object(g)===g?g:f}return b.apply(a,c.concat(z.call(arguments)))};return d}),x.csstransforms=function(){return!!i("transform")},x.csstransforms3d=function(){var a=!!i("perspective");return a&&"webkitPerspective"in p.style&&A("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b){a=9===b.offsetLeft&&3===b.offsetHeight}),a},x.csstransitions=function(){return i("transition")};for(var C in x)l(x,C)&&(k=C.toLowerCase(),n[k]=x[C](),y.push((n[k]?"":"no-")+k));return n.addTest=function(a,b){if("object"==typeof a)for(var d in a)l(a,d)&&n.addTest(d,a[d]);else{if(a=a.toLowerCase(),n[a]!==c)return n;b="function"==typeof b?b():b,"undefined"!=typeof o&&o&&(p.className+=" "+(b?"":"no-")+a),n[a]=b}return n},d(""),r=j=null,n._version=m,n._prefixes=t,n._domPrefixes=w,n._cssomPrefixes=v,n.testProp=function(a){return g([a])},n.testAllProps=i,n.testStyles=A,n.prefixed=function(a,b,c){return b?i(a,b,c):i(a,"pfx")},p.className=p.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(o?" js "+y.join(" "):""),n}(this,this.document),function(a){"function"==typeof define&&define.amd?define(["jquery","modernizr"],a):a(window.$,window.Modernizr)}(function(a,b,c){"use strict";function d(a){return a?a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-"):""}function e(b,c,d){var e,f,g,h=null,i=0;d=d||{};var j=function(){i=d.leading===!1?0:a.now(),h=null,g=b.apply(e,f),e=f=null};return function(){var k=a.now();i||d.leading!==!1||(i=k);var l=c-(k-i);return e=this,f=arguments,0>=l||l>c?(clearTimeout(h),h=null,i=k,g=b.apply(e,f),e=f=null):h||d.trailing===!1||(h=setTimeout(j,l)),g}}if("object"!=typeof b)throw new Error("Shuffle.js requires Modernizr.\nhttp://vestride.github.io/Shuffle/#dependencies");var f=b.prefixed("transition"),g=b.prefixed("transitionDelay"),h=b.prefixed("transitionDuration"),i={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[f],j=b.prefixed("transform"),k=d(j),l=b.csstransforms&&b.csstransitions,m=b.csstransforms3d,n="shuffle",o="all",p="groups",q=1,r=.001,s=0,t=a(window),u=function(b,c){c=c||{},a.extend(this,u.options,c,u.settings),this.$el=a(b),this.unique="shuffle_"+s++,this._fire(u.EventType.LOADING),this._init(),setTimeout(a.proxy(function(){this.initialized=!0,this._fire(u.EventType.DONE)},this),16)};return u.EventType={LOADING:"loading",DONE:"done",SHRINK:"shrink",SHRUNK:"shrunk",FILTER:"filter",FILTERED:"filtered",SORTED:"sorted",LAYOUT:"layout",REMOVED:"removed"},u.ClassName={BASE:n,SHUFFLE_ITEM:"shuffle-item",FILTERED:"filtered",CONCEALED:"concealed"},u._getItemTransformString=function(a,b,c){return m?"translate3d("+a+"px, "+b+"px, 0) scale3d("+c+", "+c+", 1)":"translate("+a+"px, "+b+"px) scale("+c+", "+c+")"},u._getPreciseDimension=function(b,c){var d;return d=window.getComputedStyle?window.getComputedStyle(b,null)[c]:a(b).css(c),parseFloat(d)},u._getOuterWidth=function(b,c){var d=b.offsetWidth;if(c){var e=a(b).css(["marginLeft","marginRight"]),f=parseFloat(e.marginLeft)||0,g=parseFloat(e.marginRight)||0;d+=f+g}return d},u._getOuterHeight=function(b,c){var d=b.offsetHeight;if(c){var e=a(b).css(["marginTop","marginBottom"]),f=parseFloat(e.marginTop)||0,g=parseFloat(e.marginBottom)||0;d+=f+g}return d},u._skipTransition=function(b,c,d){var e=b.style[h];b.style[h]="0ms",a.isFunction(c)?c():b.style[c]=d;var f=b.offsetWidth;f=null,b.style[h]=e},u.prototype={_init:function(){var a=this;a._layoutList=[],a._shrinkList=[],a._setVars(),a._resetCols(),this.$el.addClass(u.ClassName.BASE),a._initItems(),t.on("resize."+n+"."+a.unique,a._getResizeFunction());var b=a.$el.css(["paddingLeft","paddingRight","position"]),c=u._getOuterWidth(a.$el[0]);"static"===b.position&&(a.$el[0].style.position="relative"),a.offset={left:parseInt(b.paddingLeft,10)||0,top:parseInt(b.paddingTop,10)||0},a._setColumns(parseInt(c,10)),a.shuffle(a.group,a.initialSort),a.supported&&setTimeout(function(){a._setTransitions(),a.$el[0].style[f]="height "+a.speed+"ms "+a.easing},0)},_getResizeFunction:function(){var b=a.proxy(this._onResize,this);return this.throttle?this.throttle(b,this.throttleTime):b},_setVars:function(){var b=this,c=b.columnWidth;b.$items=b._getItems(),0===c&&null!==b.sizer&&(c=b.sizer),"string"==typeof c?b.$sizer=b.$el.find(c):c&&c.nodeType&&1===c.nodeType?b.$sizer=a(c):c&&c.jquery&&(b.$sizer=c),b.$sizer&&b.$sizer.length&&(b.useSizer=!0,b.sizer=b.$sizer[0])},_filter:function(a,b){a=a||this.lastFilter,b=b||this.$items,this._fire(u.EventType.FILTER);var c=this._getFilteredSets(a,b);return this._toggleFilterClasses(c.filtered,c.concealed),this.lastFilter=a,"string"==typeof a&&(this.group=a),c.filtered},_getFilteredSets:function(b,c){var d=a(),e=a();if(b===o)d=c;else{var f=this;c.each(function(c,g){var h=a(g);f._doesPassFilter(b,h)?d=d.add(h):e=e.add(h)})}return{filtered:d,concealed:e}},_doesPassFilter:function(b,c){if(a.isFunction(b))return b.call(c[0],c,this);var d=c.data(p),e=this.delimeter&&!a.isArray(d)?d.split(this.delimeter):d;return a.inArray(b,e)>-1},_toggleFilterClasses:function(a,b){a.removeClass(u.ClassName.CONCEALED).addClass(u.ClassName.FILTERED),b.removeClass(u.ClassName.FILTERED).addClass(u.ClassName.CONCEALED)},_initItems:function(a){a=a||this.$items,a.addClass([u.ClassName.SHUFFLE_ITEM,u.ClassName.FILTERED].join(" ")),a.css(this.itemCss).data("position",{x:0,y:0})},_updateItemCount:function(){this.visibleItems=this._getFilteredItems().length},_setTransition:function(a){a.style[f]=k+" "+this.speed+"ms "+this.easing+", opacity "+this.speed+"ms "+this.easing},_setTransitions:function(a){var b=this;a=a||b.$items,a.each(function(){b._setTransition(this)})},_setSequentialDelay:function(b){var c=this;c.supported&&a.each(b,function(b,d){d.style[g]="0ms,"+(b+1)*c.sequentialFadeDelay+"ms",a(d).on(i+"."+c.unique,function(b){var d=b.currentTarget;d===b.target&&(d.style[g]="0ms",a(d).off(i+"."+c.unique))})})},_getItems:function(){return this.$el.children(this.itemSelector)},_getFilteredItems:function(){return this.$items.filter("."+u.ClassName.FILTERED)},_getConcealedItems:function(){return this.$items.filter("."+u.ClassName.CONCEALED)},_getColumnSize:function(b,c){var d;return d=a.isFunction(this.columnWidth)?this.columnWidth(c):this.useSizer?u._getPreciseDimension(this.sizer,"width"):this.columnWidth?this.columnWidth:this.$items.length>0?u._getOuterWidth(this.$items[0],!0):c,0===d&&(d=c),d+b},_getGutterSize:function(b){var c;return c=a.isFunction(this.gutterWidth)?this.gutterWidth(b):this.useSizer?u._getPreciseDimension(this.sizer,"marginLeft"):this.gutterWidth},_setColumns:function(a){var b=a||u._getOuterWidth(this.$el[0]),c=this._getGutterSize(b),d=this._getColumnSize(c,b),e=(b+c)/d;Math.abs(Math.round(e)-e)<.03&&(e=Math.round(e)),this.cols=Math.max(Math.floor(e),1),this.containerWidth=b,this.colWidth=d},_setContainerSize:function(){this.$el.css("height",this._getContainerSize())},_getContainerSize:function(){return Math.max.apply(Math,this.colYs)},_fire:function(a,b){this.$el.trigger(a+"."+n,b&&b.length?b:[this])},_layout:function(b,c,d){var e=this;c=c||e._filterEnd,a.each(b,function(b,f){var g=a(f),h=g.data(),i=h.position,j=e._getItemPosition(g);if(g.data("position",j),j.x!==i.x||j.y!==i.y||h.scale!==q){var k={$item:g,x:j.x,y:j.y,scale:q};d?(k.skipTransition=!0,k.opacity=0):(k.opacity=1,k.callback=c),e.styleQueue.push(k),e._layoutList.push(g[0])}}),e._processStyleQueue(),b.length>0&&0===e._layoutList.length&&e._layoutEnd(c),e._setContainerSize()},_resetCols:function(){var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0)},_reLayout:function(){this._resetCols(),this.lastSort?this.sort(this.lastSort,!0):this._layout(this._getFilteredItems().get(),this._filterEnd)},_getItemPosition:function(a){var b=this,c=u._getOuterWidth(a[0],!0),d=c/b.colWidth;Math.abs(Math.round(d)-d)<.03&&(d=Math.round(d));var e=Math.min(Math.ceil(d),b.cols);if(1===e)return b._placeItem(a,b.colYs);var f,g,h=b.cols+1-e,i=[];for(g=0;h>g;g++)f=b.colYs.slice(g,g+e),i[g]=Math.max.apply(Math,f);return b._placeItem(a,i)},_placeItem:function(a,b){for(var c=this,d=Math.min.apply(Math,b),e=0,f=0,g=b.length;g>f;f++)if(b[f]>=d-c.buffer&&b[f]<=d+c.buffer){e=f;break}var h={x:Math.round(c.colWidth*e+c.offset.left),y:Math.round(d+c.offset.top)},i=d+u._getOuterHeight(a[0],!0),j=c.cols+1-g;for(f=0;j>f;f++)c.colYs[e+f]=i;return h},_shrink:function(b,c){var d=this,e=b||d._getConcealedItems();c=c||d._shrinkEnd,e.length&&(d._fire(u.EventType.SHRINK),e.each(function(){var b=a(this),e=b.data(),f=e.scale===r;if(!f){var g={$item:b,x:e.position.x,y:e.position.y,scale:r,opacity:0,callback:c};d.styleQueue.push(g),d._shrinkList.push(b[0])}}))},_onResize:function(){if(this.enabled&&!this.destroyed){var a=u._getOuterWidth(this.$el[0]);a!==this.containerWidth&&this.resized()}},_getStylesForTransition:function(a){var b={opacity:a.opacity};return this.supported?a.x!==c&&(b[j]=u._getItemTransformString(a.x,a.y,a.scale)):(b.left=a.x,b.top=a.y),1===a.opacity&&(b.visibility="visible"),b},_transition:function(a){a.$item.data("scale",a.scale);var b=this._getStylesForTransition(a);this._startItemAnimation(a.$item,b,a.callback)},_startItemAnimation:function(b,c,d){var e=1===c.opacity,f=a.proxy(this._handleItemAnimationEnd,this,d||a.noop,b[0],e);this.supported?(b.css(c),this.initialized?b.on(i+".shuffleitem",f):f()):("visibility"in c&&(b.css("visibility",c.visibility),delete c.visibility),b.stop(!0).animate(c,this.speed,"swing",f))},_handleItemAnimationEnd:function(b,c,d,e){if(e){if(e.target!==c)return;a(c).off(".shuffleitem")}this._layoutList.length>0&&a.inArray(c,this._layoutList)>-1?(this._layoutEnd(b),this._layoutList.length=0):this._shrinkList.length>0&&a.inArray(c,this._shrinkList)>-1&&(this._shrinkList.length=0,setTimeout(a.proxy(b,this),0)),d||(c.style.visibility="hidden")},_processStyleQueue:function(){var b=this;a.each(this.styleQueue,function(a,c){c.skipTransition?u._skipTransition(c.$item[0],function(){c.$item.css(b._getStylesForTransition(c))}):b._transition(c)}),b.styleQueue.length=0},_shrinkEnd:function(){this._fire(u.EventType.SHRUNK)},_filterEnd:function(){this._fire(u.EventType.FILTERED)},_sortEnd:function(){this._fire(u.EventType.SORTED)},_layoutEnd:function(b){setTimeout(a.proxy(function(){this._fire(u.EventType.LAYOUT),b.call(this)},this),0)},_addItems:function(a,b,c){var d=this;d.supported||(b=!1),d._initItems(a),d._setTransitions(a),d.$items=d._getItems(),a.css("opacity",0);var e=d._filter(null,a),f=e.get();d._updateItemCount(),b?(d._layout(f,null,!0),c&&d._setSequentialDelay(e),d._revealAppended(e)):d._layout(f)},_revealAppended:function(b){var c=this;setTimeout(function(){b.each(function(b,d){c._transition({$item:a(d),opacity:1,scale:q})})},c.revealAppendedDelay)},shuffle:function(a,b){var c=this;c.enabled&&(a||(a=o),c._filter(a),c._updateItemCount(),c._shrink(),b&&(c.lastSort=b),c._reLayout())},sort:function(a,b){var c=this,d=c._getFilteredItems().sorted(a);b||c._resetCols(),c._layout(d,function(){b&&c._filterEnd(),c._sortEnd()}),c.lastSort=a},resized:function(a){this.enabled&&(a||this._setColumns(),this._reLayout())},layout:function(){this.update(!0)},update:function(a){this.resized(a)},appended:function(a,b,c){b=b===!1?!1:!0,c=c===!1?!1:!0,this._addItems(a,b,c)},disable:function(){this.enabled=!1},enable:function(a){this.enabled=!0,a!==!1&&this.update()},remove:function(a){if(a.length&&a.jquery){var b=this;return b._shrink(a,function(){var b=this;a.remove(),setTimeout(function(){b.$items=b._getItems(),b.layout(),b._updateItemCount(),b._fire(u.EventType.REMOVED,[a,b]),a=null},0)}),b._processStyleQueue(),b}},destroy:function(){var a=this;t.off("."+a.unique),a.$el.removeClass(n).removeAttr("style").removeData(n),a.$items.removeAttr("style").removeClass("concealed filtered shuffle-item"),a.$items=null,a.$el=null,a.$sizer=null,a.sizer=null,a.destroyed=!0}},u.options={group:o,speed:250,easing:"ease-out",itemSelector:"",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,initialSort:null,throttle:e,throttleTime:300,sequentialFadeDelay:150,supported:l},u.settings={$sizer:null,useSizer:!1,itemCss:{position:"absolute",top:0,left:0},offset:{top:0,left:0},revealAppendedDelay:300,enabled:!0,destroyed:!1,initialized:!1,styleQueue:[]},a.fn.shuffle=function(b){var c=Array.prototype.slice.call(arguments,1);return this.each(function(){var d=a(this),e=d.data(n);e||(e=new u(d,b),d.data(n,e)),"string"==typeof b&&e[b]&&e[b].apply(e,c)})},a.fn.sorted=function(b){var d=a.extend({},a.fn.sorted.defaults,b),e=this.get(),f=!1;return e.length?d.randomize?a.fn.sorted.randomize(e):(a.isFunction(d.by)&&e.sort(function(b,e){if(f)return 0;var g=d.by(a(b)),h=d.by(a(e));return g===c&&h===c?(f=!0,0):h>g||"sortFirst"===g||"sortLast"===h?-1:g>h||"sortLast"===g||"sortFirst"===h?1:0}),f?this.get():(d.reverse&&e.reverse(),e)):[]},a.fn.sorted.defaults={reverse:!1,by:null,randomize:!1},a.fn.sorted.randomize=function(a){var b,c,d=a.length;if(!d)return a;for(;--d;)c=Math.floor(Math.random()*(d+1)),b=a[c],a[c]=a[d],a[d]=b;return a},u}); \ No newline at end of file +window.Modernizr=function(a,b,c){function d(a){s.cssText=a}function e(a,b){return typeof a===b}function f(a,b){return!!~(""+a).indexOf(b)}function g(a,b){for(var d in a){var e=a[d];if(!f(e,"-")&&s[e]!==c)return"pfx"==b?e:!0}return!1}function h(a,b,d){for(var f in a){var g=b[a[f]];if(g!==c)return d===!1?a[f]:e(g,"function")?g.bind(d||b):g}return!1}function i(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),f=(a+" "+v.join(d+" ")+d).split(" ");return e(b,"string")||e(b,"undefined")?g(f,b):(f=(a+" "+w.join(d+" ")+d).split(" "),h(f,b,c))}var j,k,l,m="2.6.2",n={},o=!0,p=b.documentElement,q="modernizr",r=b.createElement(q),s=r.style,t=({}.toString," -webkit- -moz- -o- -ms- ".split(" ")),u="Webkit Moz O ms",v=u.split(" "),w=u.toLowerCase().split(" "),x={},y=[],z=y.slice,A=function(a,c,d,e){var f,g,h,i,j=b.createElement("div"),k=b.body,l=k||b.createElement("body");if(parseInt(d,10))for(;d--;)h=b.createElement("div"),h.id=e?e[d]:q+(d+1),j.appendChild(h);return f=["­",'"].join(""),j.id=q,(k?j:l).innerHTML+=f,l.appendChild(j),k||(l.style.background="",l.style.overflow="hidden",i=p.style.overflow,p.style.overflow="hidden",p.appendChild(l)),g=c(j,a),k?j.parentNode.removeChild(j):(l.parentNode.removeChild(l),p.style.overflow=i),!!g},B={}.hasOwnProperty;l=e(B,"undefined")||e(B.call,"undefined")?function(a,b){return b in a&&e(a.constructor.prototype[b],"undefined")}:function(a,b){return B.call(a,b)},Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if("function"!=typeof b)throw new TypeError;var c=z.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,g=b.apply(f,c.concat(z.call(arguments)));return Object(g)===g?g:f}return b.apply(a,c.concat(z.call(arguments)))};return d}),x.csstransforms=function(){return!!i("transform")},x.csstransforms3d=function(){var a=!!i("perspective");return a&&"webkitPerspective"in p.style&&A("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b){a=9===b.offsetLeft&&3===b.offsetHeight}),a},x.csstransitions=function(){return i("transition")};for(var C in x)l(x,C)&&(k=C.toLowerCase(),n[k]=x[C](),y.push((n[k]?"":"no-")+k));return n.addTest=function(a,b){if("object"==typeof a)for(var d in a)l(a,d)&&n.addTest(d,a[d]);else{if(a=a.toLowerCase(),n[a]!==c)return n;b="function"==typeof b?b():b,"undefined"!=typeof o&&o&&(p.className+=" "+(b?"":"no-")+a),n[a]=b}return n},d(""),r=j=null,n._version=m,n._prefixes=t,n._domPrefixes=w,n._cssomPrefixes=v,n.testProp=function(a){return g([a])},n.testAllProps=i,n.testStyles=A,n.prefixed=function(a,b,c){return b?i(a,b,c):i(a,"pfx")},p.className=p.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(o?" js "+y.join(" "):""),n}(this,this.document),function(a){"function"==typeof define&&define.amd?define(["jquery","modernizr"],a):a(window.$,window.Modernizr)}(function(a,b,c){"use strict";function d(a){return a?a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-"):""}function e(b,c,d){var e,f,g,h=null,i=0;d=d||{};var j=function(){i=d.leading===!1?0:a.now(),h=null,g=b.apply(e,f),e=f=null};return function(){var k=a.now();i||d.leading!==!1||(i=k);var l=c-(k-i);return e=this,f=arguments,0>=l||l>c?(clearTimeout(h),h=null,i=k,g=b.apply(e,f),e=f=null):h||d.trailing===!1||(h=setTimeout(j,l)),g}}if("object"!=typeof b)throw new Error("Shuffle.js requires Modernizr.\nhttp://vestride.github.io/Shuffle/#dependencies");var f=b.prefixed("transition"),g=b.prefixed("transitionDelay"),h=b.prefixed("transitionDuration"),i={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[f],j=b.prefixed("transform"),k=d(j),l=b.csstransforms&&b.csstransitions,m=b.csstransforms3d,n="shuffle",o="all",p="groups",q=1,r=.001,s=0,t=a(window),u=function(b,c){c=c||{},a.extend(this,u.options,c,u.settings),this.$el=a(b),this.unique="shuffle_"+s++,this._fire(u.EventType.LOADING),this._init(),setTimeout(a.proxy(function(){this.initialized=!0,this._fire(u.EventType.DONE)},this),16)};return u.EventType={LOADING:"loading",DONE:"done",SHRINK:"shrink",SHRUNK:"shrunk",FILTER:"filter",FILTERED:"filtered",SORTED:"sorted",LAYOUT:"layout",REMOVED:"removed"},u.ClassName={BASE:n,SHUFFLE_ITEM:"shuffle-item",FILTERED:"filtered",CONCEALED:"concealed"},u._getItemTransformString=function(a,b,c){return m?"translate3d("+a+"px, "+b+"px, 0) scale3d("+c+", "+c+", 1)":"translate("+a+"px, "+b+"px) scale("+c+", "+c+")"},u._getPreciseDimension=function(b,c){var d;return d=window.getComputedStyle?window.getComputedStyle(b,null)[c]:a(b).css(c),parseFloat(d)},u._getOuterWidth=function(b,c){var d=b.offsetWidth;if(c){var e=a(b).css(["marginLeft","marginRight"]),f=parseFloat(e.marginLeft)||0,g=parseFloat(e.marginRight)||0;d+=f+g}return d},u._getOuterHeight=function(b,c){var d=b.offsetHeight;if(c){var e=a(b).css(["marginTop","marginBottom"]),f=parseFloat(e.marginTop)||0,g=parseFloat(e.marginBottom)||0;d+=f+g}return d},u._skipTransition=function(b,c,d){var e=b.style[h];b.style[h]="0ms",a.isFunction(c)?c():b.style[c]=d;var f=b.offsetWidth;f=null,b.style[h]=e},u.prototype={_init:function(){var a=this;a._layoutList=[],a._shrinkList=[],a._setVars(),a._resetCols(),this.$el.addClass(u.ClassName.BASE),a._initItems(),t.on("resize."+n+"."+a.unique,a._getResizeFunction());var b=a.$el.css(["paddingLeft","paddingRight","position"]),c=u._getOuterWidth(a.$el[0]);"static"===b.position&&(a.$el[0].style.position="relative"),a.offset={left:parseInt(b.paddingLeft,10)||0,top:parseInt(b.paddingTop,10)||0},a._setColumns(parseInt(c,10)),a.shuffle(a.group,a.initialSort),a.supported&&setTimeout(function(){a._setTransitions(),a.$el[0].style[f]="height "+a.speed+"ms "+a.easing},0)},_getResizeFunction:function(){var b=a.proxy(this._onResize,this);return this.throttle?this.throttle(b,this.throttleTime):b},_setVars:function(){var b=this,c=b.columnWidth;b.$items=b._getItems(),0===c&&null!==b.sizer&&(c=b.sizer),"string"==typeof c?b.$sizer=b.$el.find(c):c&&c.nodeType&&1===c.nodeType?b.$sizer=a(c):c&&c.jquery&&(b.$sizer=c),b.$sizer&&b.$sizer.length&&(b.useSizer=!0,b.sizer=b.$sizer[0])},_filter:function(a,b){a=a||this.lastFilter,b=b||this.$items,this._fire(u.EventType.FILTER);var c=this._getFilteredSets(a,b);return this._toggleFilterClasses(c.filtered,c.concealed),this.lastFilter=a,"string"==typeof a&&(this.group=a),c.filtered},_getFilteredSets:function(b,c){var d=a(),e=a();if(b===o)d=c;else{var f=this;a.each(c,function(c,g){var h=a(g);f._doesPassFilter(b,h)?d=d.add(h):e=e.add(h)})}return{filtered:d,concealed:e}},_doesPassFilter:function(b,c){if(a.isFunction(b))return b.call(c[0],c,this);var d=c.data(p),e=this.delimeter&&!a.isArray(d)?d.split(this.delimeter):d;return a.inArray(b,e)>-1},_toggleFilterClasses:function(a,b){a.removeClass(u.ClassName.CONCEALED).addClass(u.ClassName.FILTERED),b.removeClass(u.ClassName.FILTERED).addClass(u.ClassName.CONCEALED)},_initItems:function(a){a=a||this.$items,a.addClass([u.ClassName.SHUFFLE_ITEM,u.ClassName.FILTERED].join(" ")),a.css(this.itemCss).data("position",{x:0,y:0})},_updateItemCount:function(){this.visibleItems=this._getFilteredItems().length},_setTransition:function(a){a.style[f]=k+" "+this.speed+"ms "+this.easing+", opacity "+this.speed+"ms "+this.easing},_setTransitions:function(a){var b=this;a=a||b.$items,a.each(function(){b._setTransition(this)})},_setSequentialDelay:function(b){var c=this;c.supported&&a.each(b,function(b,d){d.style[g]="0ms,"+(b+1)*c.sequentialFadeDelay+"ms",a(d).on(i+"."+c.unique,function(b){var d=b.currentTarget;d===b.target&&(d.style[g]="0ms",a(d).off(i+"."+c.unique))})})},_getItems:function(){return this.$el.children(this.itemSelector)},_getFilteredItems:function(){return this.$items.filter("."+u.ClassName.FILTERED)},_getConcealedItems:function(){return this.$items.filter("."+u.ClassName.CONCEALED)},_getColumnSize:function(b,c){var d;return d=a.isFunction(this.columnWidth)?this.columnWidth(c):this.useSizer?u._getPreciseDimension(this.sizer,"width"):this.columnWidth?this.columnWidth:this.$items.length>0?u._getOuterWidth(this.$items[0],!0):c,0===d&&(d=c),d+b},_getGutterSize:function(b){var c;return c=a.isFunction(this.gutterWidth)?this.gutterWidth(b):this.useSizer?u._getPreciseDimension(this.sizer,"marginLeft"):this.gutterWidth},_setColumns:function(a){var b=a||u._getOuterWidth(this.$el[0]),c=this._getGutterSize(b),d=this._getColumnSize(c,b),e=(b+c)/d;Math.abs(Math.round(e)-e)<.03&&(e=Math.round(e)),this.cols=Math.max(Math.floor(e),1),this.containerWidth=b,this.colWidth=d},_setContainerSize:function(){this.$el.css("height",this._getContainerSize())},_getContainerSize:function(){return Math.max.apply(Math,this.colYs)},_fire:function(a,b){this.$el.trigger(a+"."+n,b&&b.length?b:[this])},_layout:function(b,c,d){var e=this;c=c||e._filterEnd,a.each(b,function(b,f){var g=a(f),h=g.data(),i=h.position,j=e._getItemPosition(g);if(g.data("position",j),j.x!==i.x||j.y!==i.y||h.scale!==q){var k={$item:g,x:j.x,y:j.y,scale:q};d?(k.skipTransition=!0,k.opacity=0):(k.opacity=1,k.callback=c),e.styleQueue.push(k),e._layoutList.push(g[0])}}),e._processStyleQueue(),b.length>0&&0===e._layoutList.length&&e._layoutEnd(c),e._setContainerSize()},_resetCols:function(){var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0)},_reLayout:function(){this._resetCols(),this.sort(this.lastSort,!0)},_getItemPosition:function(a){var b=this,c=u._getOuterWidth(a[0],!0),d=c/b.colWidth;Math.abs(Math.round(d)-d)<.03&&(d=Math.round(d));var e=Math.min(Math.ceil(d),b.cols);if(1===e)return b._placeItem(a,b.colYs);var f,g,h=b.cols+1-e,i=[];for(g=0;h>g;g++)f=b.colYs.slice(g,g+e),i[g]=Math.max.apply(Math,f);return b._placeItem(a,i)},_placeItem:function(a,b){for(var c=this,d=Math.min.apply(Math,b),e=0,f=0,g=b.length;g>f;f++)if(b[f]>=d-c.buffer&&b[f]<=d+c.buffer){e=f;break}var h={x:Math.round(c.colWidth*e+c.offset.left),y:Math.round(d+c.offset.top)},i=d+u._getOuterHeight(a[0],!0),j=c.cols+1-g;for(f=0;j>f;f++)c.colYs[e+f]=i;return h},_shrink:function(b,c){var d=this,e=b||d._getConcealedItems();c=c||d._shrinkEnd,e.length&&(d._fire(u.EventType.SHRINK),e.each(function(){var b=a(this),e=b.data(),f=e.scale===r;if(!f){var g={$item:b,x:e.position.x,y:e.position.y,scale:r,opacity:0,callback:c};d.styleQueue.push(g),d._shrinkList.push(b[0])}}))},_onResize:function(){if(this.enabled&&!this.destroyed){var a=u._getOuterWidth(this.$el[0]);a!==this.containerWidth&&this.resized()}},_getStylesForTransition:function(a){var b={opacity:a.opacity};return this.supported?a.x!==c&&(b[j]=u._getItemTransformString(a.x,a.y,a.scale)):(b.left=a.x,b.top=a.y),1===a.opacity&&(b.visibility="visible"),b},_transition:function(a){a.$item.data("scale",a.scale);var b=this._getStylesForTransition(a);this._startItemAnimation(a.$item,b,a.callback)},_startItemAnimation:function(b,c,d){var e=1===c.opacity,f=a.proxy(this._handleItemAnimationEnd,this,d||a.noop,b[0],e);this.supported?(b.css(c),this.initialized?b.on(i+".shuffleitem",f):f()):("visibility"in c&&(b.css("visibility",c.visibility),delete c.visibility),b.stop(!0).animate(c,this.speed,"swing",f))},_handleItemAnimationEnd:function(b,c,d,e){if(e){if(e.target!==c)return;a(c).off(".shuffleitem")}this._layoutList.length>0&&a.inArray(c,this._layoutList)>-1?(this._layoutEnd(b),this._layoutList.length=0):this._shrinkList.length>0&&a.inArray(c,this._shrinkList)>-1&&(this._shrinkList.length=0,setTimeout(a.proxy(b,this),0)),d||(c.style.visibility="hidden")},_processStyleQueue:function(){var b=this;a.each(this.styleQueue,function(a,c){c.skipTransition?u._skipTransition(c.$item[0],function(){c.$item.css(b._getStylesForTransition(c))}):b._transition(c)}),b.styleQueue.length=0},_shrinkEnd:function(){this._fire(u.EventType.SHRUNK)},_filterEnd:function(){this._fire(u.EventType.FILTERED)},_sortEnd:function(){this._fire(u.EventType.SORTED)},_layoutEnd:function(b){setTimeout(a.proxy(function(){this._fire(u.EventType.LAYOUT),b.call(this)},this),0)},_addItems:function(a,b,c){this._initItems(a),this._setTransitions(a),this.$items=this._getItems(),this.supported&&b?this._addItemsToEnd(c):this.shuffle(this.lastFilter)},_addItemsToEnd:function(a,b){a.css("opacity",0);var c=this._filter(null,a),d=c.get();this._updateItemCount(),this._layout(d,null,!0),b&&this._setSequentialDelay(d),this._revealAppended(d)},_revealAppended:function(b){var c=this;setTimeout(function(){a.each(b,function(b,d){c._transition({$item:a(d),opacity:1,scale:q})})},c.revealAppendedDelay)},shuffle:function(a,b){var c=this;c.enabled&&(a||(a=o),c._filter(a),c._updateItemCount(),c._shrink(),b&&(c.lastSort=b),c._reLayout())},sort:function(a,b){var c=this,d=c._getFilteredItems().sorted(a);b||c._resetCols(),c._layout(d,function(){b&&c._filterEnd(),c._sortEnd()}),c.lastSort=a},resized:function(a){this.enabled&&(a||this._setColumns(),this._reLayout())},layout:function(){this.update(!0)},update:function(a){this.resized(a)},appended:function(a,b,c){b=b===!1?!1:!0,c=c===!1?!1:!0,this._addItems(a,b,c)},disable:function(){this.enabled=!1},enable:function(a){this.enabled=!0,a!==!1&&this.update()},remove:function(a){if(a.length&&a.jquery){var b=this;return b._shrink(a,function(){var b=this;a.remove(),setTimeout(function(){b.$items=b._getItems(),b.layout(),b._updateItemCount(),b._fire(u.EventType.REMOVED,[a,b]),a=null},0)}),b._processStyleQueue(),b}},destroy:function(){var a=this;t.off("."+a.unique),a.$el.removeClass(n).removeAttr("style").removeData(n),a.$items.removeAttr("style").removeClass("concealed filtered shuffle-item"),a.$items=null,a.$el=null,a.$sizer=null,a.sizer=null,a.destroyed=!0}},u.options={group:o,speed:250,easing:"ease-out",itemSelector:"",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,initialSort:null,throttle:e,throttleTime:300,sequentialFadeDelay:150,supported:l},u.settings={$sizer:null,useSizer:!1,itemCss:{position:"absolute",top:0,left:0},offset:{top:0,left:0},revealAppendedDelay:300,lastSort:{},lastFilter:o,enabled:!0,destroyed:!1,initialized:!1,styleQueue:[]},a.fn.shuffle=function(b){var c=Array.prototype.slice.call(arguments,1);return this.each(function(){var d=a(this),e=d.data(n);e||(e=new u(d,b),d.data(n,e)),"string"==typeof b&&e[b]&&e[b].apply(e,c)})},a.fn.sorted=function(b){var d=a.extend({},a.fn.sorted.defaults,b),e=this.get(),f=!1;return e.length?d.randomize?a.fn.sorted.randomize(e):(a.isFunction(d.by)&&e.sort(function(b,e){if(f)return 0;var g=d.by(a(b)),h=d.by(a(e));return g===c&&h===c?(f=!0,0):h>g||"sortFirst"===g||"sortLast"===h?-1:g>h||"sortLast"===g||"sortFirst"===h?1:0}),f?this.get():(d.reverse&&e.reverse(),e)):[]},a.fn.sorted.defaults={reverse:!1,by:null,randomize:!1},a.fn.sorted.randomize=function(a){var b,c,d=a.length;if(!d)return a;for(;--d;)c=Math.floor(Math.random()*(d+1)),b=a[c],a[c]=a[d],a[d]=b;return a},u}); \ No newline at end of file diff --git a/js/demos/adding-removing.js b/js/demos/adding-removing.js index 3f0850a..353cc09 100644 --- a/js/demos/adding-removing.js +++ b/js/demos/adding-removing.js @@ -8,6 +8,9 @@ window.Manipulator = (function($) { self.$el = $( element ); self.init(); + + this.addToEnd = true; + this.sequentialDelay = true; }; Manipulator.prototype.init = function() { @@ -44,6 +47,8 @@ window.Manipulator = (function($) { $('#add').on('click', $.proxy( self.onAddClick, self )); $('#randomize').on('click', $.proxy( self.onRandomize, self )); $('#remove').on('click', $.proxy( self.onRemoveClick, self )); + $('#sorter').on('change', $.proxy( self.onSortChange, self )); + $('#mode').on('change', $.proxy( self.onModeChange, self )); // Show off some shuffle events self.$el.on('removed.shuffle', function( evt, $collection, shuffle ) { @@ -74,6 +79,7 @@ window.Manipulator = (function($) { random = Math.random(); box = document.createElement('div'); box.className = 'box'; + box.setAttribute('created', this.getRandomInt(1, 150)); // Randomly add a class if ( random > 0.8 ) { @@ -90,7 +96,7 @@ window.Manipulator = (function($) { // Tell shuffle items have been appended. // It expects a jQuery object as the parameter. - self.shuffle.appended( $items ); + self.shuffle.appended( $items, this.addToEnd, this.sequentialDelay ); // or // self.$el.shuffle('appended', $items ); }; @@ -131,14 +137,43 @@ window.Manipulator = (function($) { }; Manipulator.prototype.onRandomize = function() { - var self = this, - sortObj = { - randomize: true - }; + $('#sorter').val('random').trigger('change'); + }; - self.shuffle.sort( sortObj ); - // or - // self.$el.shuffle('sort', sortObj); + Manipulator.prototype.onSortChange = function(evt) { + var value = evt.target.value; + var opts = {}; + + // We're given the element wrapped in jQuery + if ( value === 'created' ) { + opts = { + by: function($el) { + return parseInt($el.attr('created'), 10); + } + }; + } else if ( value === 'random' ) { + opts = { + randomize: true + }; + } + + // Filter elements + this.$el.shuffle('sort', opts); + }; + + Manipulator.prototype.onModeChange = function(evt) { + var value = evt.target.value; + + if (value === 'end') { + this.addToEnd = true; + this.sequentialDelay = false; + } else if (value === 'end-sequential') { + this.addToEnd = true; + this.sequentialDelay = true; + } else if (value === 'mix') { + this.addToEnd = false; + this.sequentialDelay = false; + } }; return Manipulator; diff --git a/src/shuffle.js b/src/shuffle.js index 9607942..e1557d3 100644 --- a/src/shuffle.js +++ b/src/shuffle.js @@ -353,7 +353,7 @@ Shuffle.prototype = { * Filter the elements by a category. * @param {string} [category] Category to filter by. If it's given, the last * category will be used to filter the items. - * @param {jQuery} [$collection] Optionally filter a collection. Defaults to + * @param {ArrayLike} [$collection] Optionally filter a collection. Defaults to * all the items. * @return {jQuery} Filtered items. */ @@ -384,7 +384,7 @@ Shuffle.prototype = { /** * Returns an object containing the filtered and concealed elements. * @param {string|Function} category Category or function to filter by. - * @param {jQuery} $items jQuery collection of items to filter. + * @param {ArrayLike.} $items A collection of items to filter. * @return {!{filtered: jQuery, concealed: jQuery}} * @private */ @@ -400,7 +400,7 @@ Shuffle.prototype = { // whether to hide it or not. } else { var self = this; - $items.each(function(i, el) { + $.each($items, function(i, el) { var $item = $(el); if ( self._doesPassFilter( category, $item ) ) { $filtered = $filtered.add( $item ); @@ -485,6 +485,11 @@ Shuffle.prototype = { }); }, + /** + * Sets a transition delay on a collection of elements, making each delay + * greater than the last. + * @param {ArrayLike.} $collection Array to iterate over. + */ _setSequentialDelay : function( $collection ) { var self = this; @@ -684,13 +689,7 @@ Shuffle.prototype = { _reLayout : function() { this._resetCols(); - - // If we've already sorted the elements, keep them sorted - if ( this.lastSort ) { - this.sort( this.lastSort, true ); - } else { - this._layout( this._getFilteredItems().get(), this._filterEnd ); - } + this.sort( this.lastSort, true ); }, _getItemPosition : function( $item ) { @@ -916,6 +915,8 @@ Shuffle.prototype = { // Use timeouts so that all the items have been set to hidden before the // callbacks are executed. + // Note(glen): I'm still not convinced this is the best way to handle firing + // a callback when all items have finished. if ( this._layoutList.length > 0 && $.inArray( item, this._layoutList ) > -1 ) { this._layoutEnd( callback ); this._layoutList.length = 0; @@ -967,44 +968,55 @@ Shuffle.prototype = { }, _addItems : function( $newItems, animateIn, isSequential ) { - var self = this; + this._initItems( $newItems ); + this._setTransitions( $newItems ); + this.$items = this._getItems(); - if ( !self.supported ) { - animateIn = false; - } + // Hide all items + // $newItems.css('opacity', 0); - self._initItems( $newItems ); - self._setTransitions( $newItems ); - self.$items = self._getItems(); + // Shrink all items (without transitions). + this._shrink( $newItems, $.noop ); + $.each(this.styleQueue, function(i, transitionObj) { + transitionObj.skipTransition = true; + }); + this._processStyleQueue(); - // Hide all items - $newItems.css('opacity', 0); + if ( this.supported && animateIn ) { + this._addItemsToEnd( $newItems, isSequential ); + } else { + this.shuffle( this.lastFilter ); + } + }, + + _addItemsToEnd : function( $newItems, isSequential ) { // Get ones that passed the current filter - var $passed = self._filter( null, $newItems ); + var $passed = this._filter( null, $newItems ); var passed = $passed.get(); // How many filtered elements? - self._updateItemCount(); - - if ( animateIn ) { - self._layout( passed, null, true ); + this._updateItemCount(); - if ( isSequential ) { - self._setSequentialDelay( $passed ); - } + this._layout( passed, null, true ); - self._revealAppended( $passed ); - } else { - self._layout( passed ); + if ( isSequential ) { + this._setSequentialDelay( passed ); } + + this._revealAppended( passed ); }, + /** + * Triggers appended elements to fade in. + * @param {ArrayLike.} $newFilteredItems Collection of elements. + * @private + */ _revealAppended : function( $newFilteredItems ) { var self = this; setTimeout(function() { - $newFilteredItems.each(function(i, el) { + $.each($newFilteredItems, function(i, el) { self._transition({ $item: $(el), opacity: 1, @@ -1240,6 +1252,8 @@ Shuffle.settings = { }, offset: { top: 0, left: 0 }, revealAppendedDelay: 300, + lastSort: {}, + lastFilter: ALL_ITEMS, enabled: true, destroyed: false, initialized: false, diff --git a/test/.jshintrc b/test/.jshintrc index 811aec5..3037fa3 100644 --- a/test/.jshintrc +++ b/test/.jshintrc @@ -31,6 +31,7 @@ "loadFixtures": true, "jasmine": true, "expect": true, + "spyOn": true, "$": true, "Modernizr": true } diff --git a/test/specs.js b/test/specs.js index 5bc03e0..c82b534 100644 --- a/test/specs.js +++ b/test/specs.js @@ -212,33 +212,60 @@ describe('Shuffle.js', function() { expect(shuffle.lastSort).toEqual(sortObj); }); - it('can add items', function(done) { + // it('can add items', function(done) { + // var $shuffle = $('#regular-shuffle'); + // var shuffle = $shuffle.shuffle({ + // speed: 100, + // group: 'black' + // }).data('shuffle'); + + // function first() { + // var $eleven = $('
', { + // 'class': 'item', + // 'data-age': 36, + // 'data-groups': '["ux", "black"]', + // id: 'item11', + // text: 'Person 11' + // }); + // var $twelve = $('
', { + // 'class': 'item', + // 'data-age': 37, + // 'data-groups': '["strategy", "blue"]', + // id: 'item12', + // text: 'Person 12' + // }); + + // var $collection = $eleven.add($twelve); + // $shuffle.append($collection); + // shuffle.appended($collection); + + // // Already 2 in the items, plus number 11. + // expect(shuffle.visibleItems).toBe(3); + + + // done(); + // } + + // $shuffle.one('done.shuffle', first); + // }); + + + it('can call appended with different options', function() { var $shuffle = $('#regular-shuffle'); var shuffle = $shuffle.shuffle({ speed: 100 }).data('shuffle'); - function first() { - var $eleven = $('
', { - 'class': 'item', - 'data-age': 36, - 'data-groups': '["ux", "black"]', - id: 'item11', - text: 'Person 11' - }); - var $twelve = $('
', { - 'class': 'item', - 'data-age': 37, - 'data-groups': '["strategy", "blue"]', - id: 'item12', - text: 'Person 12' - }); + spyOn(shuffle, '_addItems').and.callFake(function() {}); - var $collection = $eleven.add($twelve); - done(); - } - - $shuffle.one('done.shuffle', first); + shuffle.appended(null, true, true); + expect(shuffle._addItems).toHaveBeenCalledWith(null, true, true); + shuffle.appended(null, false, false); + expect(shuffle._addItems).toHaveBeenCalledWith(null, false, false); + shuffle.appended(null); + expect(shuffle._addItems).toHaveBeenCalledWith(null, true, true); + shuffle.appended(null, null, null); + expect(shuffle._addItems).toHaveBeenCalledWith(null, true, true); }); @@ -251,9 +278,6 @@ describe('Shuffle.js', function() { loadFixtures('regular.html'); }); - afterEach(function() { - }); - it('will catch empty jQuery objects', function() { var $items = $(); diff --git a/todo.md b/todo.md index 2edd810..842058e 100644 --- a/todo.md +++ b/todo.md @@ -1,7 +1,6 @@ # Todos and other improvements ## Improvements -* TESTS! * More JSDoc * Create an `Item` class for shuffle items so they can handle storing values and more. * Horizontal layout