|
|
|
/*!
|
|
|
|
* Isotope v3.0.0-beta1
|
|
|
|
*
|
|
|
|
* Licensed GPLv3 for open source use
|
|
|
|
* or Isotope Commercial License for commercial use
|
|
|
|
*
|
|
|
|
* http://isotope.metafizzy.co
|
|
|
|
* Copyright 2016 Metafizzy
|
|
|
|
*/
|
|
|
|
|
|
|
|
( function( window, factory ) {
|
|
|
|
'use strict';
|
|
|
|
// universal module definition
|
|
|
|
|
|
|
|
if ( typeof define == 'function' && define.amd ) {
|
|
|
|
// AMD
|
|
|
|
define( [
|
|
|
|
'outlayer/outlayer',
|
|
|
|
'get-size/get-size',
|
|
|
|
'desandro-matches-selector/matches-selector',
|
|
|
|
'fizzy-ui-utils/utils',
|
|
|
|
'./item',
|
|
|
|
'./layout-mode',
|
|
|
|
// include default layout modes
|
|
|
|
'./layout-modes/masonry',
|
|
|
|
'./layout-modes/fit-rows',
|
|
|
|
'./layout-modes/vertical'
|
|
|
|
],
|
|
|
|
function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
|
|
|
|
return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
|
|
|
|
});
|
|
|
|
} else if ( typeof exports == 'object' ) {
|
|
|
|
// CommonJS
|
|
|
|
module.exports = factory(
|
|
|
|
window,
|
|
|
|
require('outlayer'),
|
|
|
|
require('get-size'),
|
|
|
|
require('desandro-matches-selector'),
|
|
|
|
require('fizzy-ui-utils'),
|
|
|
|
require('./item'),
|
|
|
|
require('./layout-mode'),
|
|
|
|
// include default layout modes
|
|
|
|
require('./layout-modes/masonry'),
|
|
|
|
require('./layout-modes/fit-rows'),
|
|
|
|
require('./layout-modes/vertical')
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// browser global
|
|
|
|
window.Isotope = factory(
|
|
|
|
window,
|
|
|
|
window.Outlayer,
|
|
|
|
window.getSize,
|
|
|
|
window.matchesSelector,
|
|
|
|
window.fizzyUIUtils,
|
|
|
|
window.Isotope.Item,
|
|
|
|
window.Isotope.LayoutMode
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
|
|
|
|
Item, LayoutMode ) {
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
// -------------------------- vars -------------------------- //
|
|
|
|
|
|
|
|
var jQuery = window.jQuery;
|
|
|
|
|
|
|
|
// -------------------------- helpers -------------------------- //
|
|
|
|
|
|
|
|
var trim = String.prototype.trim ?
|
|
|
|
function( str ) {
|
|
|
|
return str.trim();
|
|
|
|
} :
|
|
|
|
function( str ) {
|
|
|
|
return str.replace( /^\s+|\s+$/g, '' );
|
|
|
|
};
|
|
|
|
|
|
|
|
// -------------------------- isotopeDefinition -------------------------- //
|
|
|
|
|
|
|
|
// create an Outlayer layout class
|
|
|
|
var Isotope = Outlayer.create( 'isotope', {
|
|
|
|
layoutMode: "masonry",
|
|
|
|
isJQueryFiltering: true,
|
|
|
|
sortAscending: true
|
|
|
|
});
|
|
|
|
|
|
|
|
Isotope.Item = Item;
|
|
|
|
Isotope.LayoutMode = LayoutMode;
|
|
|
|
|
|
|
|
Isotope.prototype._create = function() {
|
|
|
|
this.itemGUID = 0;
|
|
|
|
// functions that sort items
|
|
|
|
this._sorters = {};
|
|
|
|
this._getSorters();
|
|
|
|
// call super
|
|
|
|
Outlayer.prototype._create.call( this );
|
|
|
|
|
|
|
|
// create layout modes
|
|
|
|
this.modes = {};
|
|
|
|
// start filteredItems with all items
|
|
|
|
this.filteredItems = this.items;
|
|
|
|
// keep of track of sortBys
|
|
|
|
this.sortHistory = [ 'original-order' ];
|
|
|
|
// create from registered layout modes
|
|
|
|
for ( var name in LayoutMode.modes ) {
|
|
|
|
this._initLayoutMode( name );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype.reloadItems = function() {
|
|
|
|
// reset item ID counter
|
|
|
|
this.itemGUID = 0;
|
|
|
|
// call super
|
|
|
|
Outlayer.prototype.reloadItems.call( this );
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype._itemize = function() {
|
|
|
|
var items = Outlayer.prototype._itemize.apply( this, arguments );
|
|
|
|
// assign ID for original-order
|
|
|
|
for ( var i=0; i < items.length; i++ ) {
|
|
|
|
var item = items[i];
|
|
|
|
item.id = this.itemGUID++;
|
|
|
|
}
|
|
|
|
this._updateItemsSortData( items );
|
|
|
|
return items;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------- layout -------------------------- //
|
|
|
|
|
|
|
|
Isotope.prototype._initLayoutMode = function( name ) {
|
|
|
|
var Mode = LayoutMode.modes[ name ];
|
|
|
|
// set mode options
|
|
|
|
// HACK extend initial options, back-fill in default options
|
|
|
|
var initialOpts = this.options[ name ] || {};
|
|
|
|
this.options[ name ] = Mode.options ?
|
|
|
|
utils.extend( Mode.options, initialOpts ) : initialOpts;
|
|
|
|
// init layout mode instance
|
|
|
|
this.modes[ name ] = new Mode( this );
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Isotope.prototype.layout = function() {
|
|
|
|
// if first time doing layout, do all magic
|
|
|
|
if ( !this._isLayoutInited && this._getOption('initLayout') ) {
|
|
|
|
this.arrange();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this._layout();
|
|
|
|
};
|
|
|
|
|
|
|
|
// private method to be used in layout() & magic()
|
|
|
|
Isotope.prototype._layout = function() {
|
|
|
|
// don't animate first layout
|
|
|
|
var isInstant = this._getIsInstant();
|
|
|
|
// layout flow
|
|
|
|
this._resetLayout();
|
|
|
|
this._manageStamps();
|
|
|
|
this.layoutItems( this.filteredItems, isInstant );
|
|
|
|
|
|
|
|
// flag for initalized
|
|
|
|
this._isLayoutInited = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
// filter + sort + layout
|
|
|
|
Isotope.prototype.arrange = function( opts ) {
|
|
|
|
// set any options pass
|
|
|
|
this.option( opts );
|
|
|
|
this._getIsInstant();
|
|
|
|
// filter, sort, and layout
|
|
|
|
|
|
|
|
// filter
|
|
|
|
var filtered = this._filter( this.items );
|
|
|
|
this.filteredItems = filtered.matches;
|
|
|
|
|
|
|
|
this._bindArrangeComplete();
|
|
|
|
|
|
|
|
if ( this._isInstant ) {
|
|
|
|
this._noTransition( this._hideReveal, [ filtered ] );
|
|
|
|
} else {
|
|
|
|
this._hideReveal( filtered );
|
|
|
|
}
|
|
|
|
|
|
|
|
this._sort();
|
|
|
|
this._layout();
|
|
|
|
};
|
|
|
|
// alias to _init for main plugin method
|
|
|
|
Isotope.prototype._init = Isotope.prototype.arrange;
|
|
|
|
|
|
|
|
Isotope.prototype._hideReveal = function( filtered ) {
|
|
|
|
this.reveal( filtered.needReveal );
|
|
|
|
this.hide( filtered.needHide );
|
|
|
|
};
|
|
|
|
|
|
|
|
// HACK
|
|
|
|
// Don't animate/transition first layout
|
|
|
|
// Or don't animate/transition other layouts
|
|
|
|
Isotope.prototype._getIsInstant = function() {
|
|
|
|
var isLayoutInstant = this._getOption('layoutInstant');
|
|
|
|
var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
|
|
|
|
!this._isLayoutInited;
|
|
|
|
this._isInstant = isInstant;
|
|
|
|
return isInstant;
|
|
|
|
};
|
|
|
|
|
|
|
|
// listen for layoutComplete, hideComplete and revealComplete
|
|
|
|
// to trigger arrangeComplete
|
|
|
|
Isotope.prototype._bindArrangeComplete = function() {
|
|
|
|
// listen for 3 events to trigger arrangeComplete
|
|
|
|
var isLayoutComplete, isHideComplete, isRevealComplete;
|
|
|
|
var _this = this;
|
|
|
|
function arrangeParallelCallback() {
|
|
|
|
if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
|
|
|
|
_this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.once( 'layoutComplete', function() {
|
|
|
|
isLayoutComplete = true;
|
|
|
|
arrangeParallelCallback();
|
|
|
|
});
|
|
|
|
this.once( 'hideComplete', function() {
|
|
|
|
isHideComplete = true;
|
|
|
|
arrangeParallelCallback();
|
|
|
|
});
|
|
|
|
this.once( 'revealComplete', function() {
|
|
|
|
isRevealComplete = true;
|
|
|
|
arrangeParallelCallback();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// -------------------------- filter -------------------------- //
|
|
|
|
|
|
|
|
Isotope.prototype._filter = function( items ) {
|
|
|
|
var filter = this.options.filter;
|
|
|
|
filter = filter || '*';
|
|
|
|
var matches = [];
|
|
|
|
var hiddenMatched = [];
|
|
|
|
var visibleUnmatched = [];
|
|
|
|
|
|
|
|
var test = this._getFilterTest( filter );
|
|
|
|
|
|
|
|
// test each item
|
|
|
|
for ( var i=0; i < items.length; i++ ) {
|
|
|
|
var item = items[i];
|
|
|
|
if ( item.isIgnored ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// add item to either matched or unmatched group
|
|
|
|
var isMatched = test( item );
|
|
|
|
// item.isFilterMatched = isMatched;
|
|
|
|
// add to matches if its a match
|
|
|
|
if ( isMatched ) {
|
|
|
|
matches.push( item );
|
|
|
|
}
|
|
|
|
// add to additional group if item needs to be hidden or revealed
|
|
|
|
if ( isMatched && item.isHidden ) {
|
|
|
|
hiddenMatched.push( item );
|
|
|
|
} else if ( !isMatched && !item.isHidden ) {
|
|
|
|
visibleUnmatched.push( item );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// return collections of items to be manipulated
|
|
|
|
return {
|
|
|
|
matches: matches,
|
|
|
|
needReveal: hiddenMatched,
|
|
|
|
needHide: visibleUnmatched
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// get a jQuery, function, or a matchesSelector test given the filter
|
|
|
|
Isotope.prototype._getFilterTest = function( filter ) {
|
|
|
|
if ( jQuery && this.options.isJQueryFiltering ) {
|
|
|
|
// use jQuery
|
|
|
|
return function( item ) {
|
|
|
|
return jQuery( item.element ).is( filter );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if ( typeof filter == 'function' ) {
|
|
|
|
// use filter as function
|
|
|
|
return function( item ) {
|
|
|
|
return filter( item.element );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
// default, use filter as selector string
|
|
|
|
return function( item ) {
|
|
|
|
return matchesSelector( item.element, filter );
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// -------------------------- sorting -------------------------- //
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @params {Array} elems
|
|
|
|
* @public
|
|
|
|
*/
|
|
|
|
Isotope.prototype.updateSortData = function( elems ) {
|
|
|
|
// get items
|
|
|
|
var items;
|
|
|
|
if ( elems ) {
|
|
|
|
elems = utils.makeArray( elems );
|
|
|
|
items = this.getItems( elems );
|
|
|
|
} else {
|
|
|
|
// update all items if no elems provided
|
|
|
|
items = this.items;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._getSorters();
|
|
|
|
this._updateItemsSortData( items );
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype._getSorters = function() {
|
|
|
|
var getSortData = this.options.getSortData;
|
|
|
|
for ( var key in getSortData ) {
|
|
|
|
var sorter = getSortData[ key ];
|
|
|
|
this._sorters[ key ] = mungeSorter( sorter );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @params {Array} items - of Isotope.Items
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Isotope.prototype._updateItemsSortData = function( items ) {
|
|
|
|
// do not update if no items
|
|
|
|
var len = items && items.length;
|
|
|
|
|
|
|
|
for ( var i=0; len && i < len; i++ ) {
|
|
|
|
var item = items[i];
|
|
|
|
item.updateSortData();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ----- munge sorter ----- //
|
|
|
|
|
|
|
|
// encapsulate this, as we just need mungeSorter
|
|
|
|
// other functions in here are just for munging
|
|
|
|
var mungeSorter = ( function() {
|
|
|
|
// add a magic layer to sorters for convienent shorthands
|
|
|
|
// `.foo-bar` will use the text of .foo-bar querySelector
|
|
|
|
// `[foo-bar]` will use attribute
|
|
|
|
// you can also add parser
|
|
|
|
// `.foo-bar parseInt` will parse that as a number
|
|
|
|
function mungeSorter( sorter ) {
|
|
|
|
// if not a string, return function or whatever it is
|
|
|
|
if ( typeof sorter != 'string' ) {
|
|
|
|
return sorter;
|
|
|
|
}
|
|
|
|
// parse the sorter string
|
|
|
|
var args = trim( sorter ).split(' ');
|
|
|
|
var query = args[0];
|
|
|
|
// check if query looks like [an-attribute]
|
|
|
|
var attrMatch = query.match( /^\[(.+)\]$/ );
|
|
|
|
var attr = attrMatch && attrMatch[1];
|
|
|
|
var getValue = getValueGetter( attr, query );
|
|
|
|
// use second argument as a parser
|
|
|
|
var parser = Isotope.sortDataParsers[ args[1] ];
|
|
|
|
// parse the value, if there was a parser
|
|
|
|
sorter = parser ? function( elem ) {
|
|
|
|
return elem && parser( getValue( elem ) );
|
|
|
|
} :
|
|
|
|
// otherwise just return value
|
|
|
|
function( elem ) {
|
|
|
|
return elem && getValue( elem );
|
|
|
|
};
|
|
|
|
|
|
|
|
return sorter;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get an attribute getter, or get text of the querySelector
|
|
|
|
function getValueGetter( attr, query ) {
|
|
|
|
// if query looks like [foo-bar], get attribute
|
|
|
|
if ( attr ) {
|
|
|
|
return function getAttribute( elem ) {
|
|
|
|
return elem.getAttribute( attr );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise, assume its a querySelector, and get its text
|
|
|
|
return function getChildText( elem ) {
|
|
|
|
var child = elem.querySelector( query );
|
|
|
|
return child && child.textContent;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return mungeSorter;
|
|
|
|
})();
|
|
|
|
|
|
|
|
// parsers used in getSortData shortcut strings
|
|
|
|
Isotope.sortDataParsers = {
|
|
|
|
'parseInt': function( val ) {
|
|
|
|
return parseInt( val, 10 );
|
|
|
|
},
|
|
|
|
'parseFloat': function( val ) {
|
|
|
|
return parseFloat( val );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ----- sort method ----- //
|
|
|
|
|
|
|
|
// sort filteredItem order
|
|
|
|
Isotope.prototype._sort = function() {
|
|
|
|
var sortByOpt = this.options.sortBy;
|
|
|
|
if ( !sortByOpt ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// concat all sortBy and sortHistory
|
|
|
|
var sortBys = [].concat.apply( sortByOpt, this.sortHistory );
|
|
|
|
// sort magic
|
|
|
|
var itemSorter = getItemSorter( sortBys, this.options.sortAscending );
|
|
|
|
this.filteredItems.sort( itemSorter );
|
|
|
|
// keep track of sortBy History
|
|
|
|
if ( sortByOpt != this.sortHistory[0] ) {
|
|
|
|
// add to front, oldest goes in last
|
|
|
|
this.sortHistory.unshift( sortByOpt );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// returns a function used for sorting
|
|
|
|
function getItemSorter( sortBys, sortAsc ) {
|
|
|
|
return function sorter( itemA, itemB ) {
|
|
|
|
// cycle through all sortKeys
|
|
|
|
for ( var i = 0; i < sortBys.length; i++ ) {
|
|
|
|
var sortBy = sortBys[i];
|
|
|
|
var a = itemA.sortData[ sortBy ];
|
|
|
|
var b = itemB.sortData[ sortBy ];
|
|
|
|
if ( a > b || a < b ) {
|
|
|
|
// if sortAsc is an object, use the value given the sortBy key
|
|
|
|
var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
|
|
|
|
var direction = isAscending ? 1 : -1;
|
|
|
|
return ( a > b ? 1 : -1 ) * direction;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// -------------------------- methods -------------------------- //
|
|
|
|
|
|
|
|
// get layout mode
|
|
|
|
Isotope.prototype._mode = function() {
|
|
|
|
var layoutMode = this.options.layoutMode;
|
|
|
|
var mode = this.modes[ layoutMode ];
|
|
|
|
if ( !mode ) {
|
|
|
|
// TODO console.error
|
|
|
|
throw new Error( 'No layout mode: ' + layoutMode );
|
|
|
|
}
|
|
|
|
// HACK sync mode's options
|
|
|
|
// any options set after init for layout mode need to be synced
|
|
|
|
mode.options = this.options[ layoutMode ];
|
|
|
|
return mode;
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype._resetLayout = function() {
|
|
|
|
// trigger original reset layout
|
|
|
|
Outlayer.prototype._resetLayout.call( this );
|
|
|
|
this._mode()._resetLayout();
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype._getItemLayoutPosition = function( item ) {
|
|
|
|
return this._mode()._getItemLayoutPosition( item );
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype._manageStamp = function( stamp ) {
|
|
|
|
this._mode()._manageStamp( stamp );
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype._getContainerSize = function() {
|
|
|
|
return this._mode()._getContainerSize();
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype.needsResizeLayout = function() {
|
|
|
|
return this._mode().needsResizeLayout();
|
|
|
|
};
|
|
|
|
|
|
|
|
// -------------------------- adding & removing -------------------------- //
|
|
|
|
|
|
|
|
// HEADS UP overwrites default Outlayer appended
|
|
|
|
Isotope.prototype.appended = function( elems ) {
|
|
|
|
var items = this.addItems( elems );
|
|
|
|
if ( !items.length ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// filter, layout, reveal new items
|
|
|
|
var filteredItems = this._filterRevealAdded( items );
|
|
|
|
// add to filteredItems
|
|
|
|
this.filteredItems = this.filteredItems.concat( filteredItems );
|
|
|
|
};
|
|
|
|
|
|
|
|
// HEADS UP overwrites default Outlayer prepended
|
|
|
|
Isotope.prototype.prepended = function( elems ) {
|
|
|
|
var items = this._itemize( elems );
|
|
|
|
if ( !items.length ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// start new layout
|
|
|
|
this._resetLayout();
|
|
|
|
this._manageStamps();
|
|
|
|
// filter, layout, reveal new items
|
|
|
|
var filteredItems = this._filterRevealAdded( items );
|
|
|
|
// layout previous items
|
|
|
|
this.layoutItems( this.filteredItems );
|
|
|
|
// add to items and filteredItems
|
|
|
|
this.filteredItems = filteredItems.concat( this.filteredItems );
|
|
|
|
this.items = items.concat( this.items );
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype._filterRevealAdded = function( items ) {
|
|
|
|
var filtered = this._filter( items );
|
|
|
|
this.hide( filtered.needHide );
|
|
|
|
// reveal all new items
|
|
|
|
this.reveal( filtered.matches );
|
|
|
|
// layout new items, no transition
|
|
|
|
this.layoutItems( filtered.matches, true );
|
|
|
|
return filtered.matches;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Filter, sort, and layout newly-appended item elements
|
|
|
|
* @param {Array or NodeList or Element} elems
|
|
|
|
*/
|
|
|
|
Isotope.prototype.insert = function( elems ) {
|
|
|
|
var items = this.addItems( elems );
|
|
|
|
if ( !items.length ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// append item elements
|
|
|
|
var i, item;
|
|
|
|
var len = items.length;
|
|
|
|
for ( i=0; i < len; i++ ) {
|
|
|
|
item = items[i];
|
|
|
|
this.element.appendChild( item.element );
|
|
|
|
}
|
|
|
|
// filter new stuff
|
|
|
|
var filteredInsertItems = this._filter( items ).matches;
|
|
|
|
// set flag
|
|
|
|
for ( i=0; i < len; i++ ) {
|
|
|
|
items[i].isLayoutInstant = true;
|
|
|
|
}
|
|
|
|
this.arrange();
|
|
|
|
// reset flag
|
|
|
|
for ( i=0; i < len; i++ ) {
|
|
|
|
delete items[i].isLayoutInstant;
|
|
|
|
}
|
|
|
|
this.reveal( filteredInsertItems );
|
|
|
|
};
|
|
|
|
|
|
|
|
var _remove = Isotope.prototype.remove;
|
|
|
|
Isotope.prototype.remove = function( elems ) {
|
|
|
|
elems = utils.makeArray( elems );
|
|
|
|
var removeItems = this.getItems( elems );
|
|
|
|
// do regular thing
|
|
|
|
_remove.call( this, elems );
|
|
|
|
// bail if no items to remove
|
|
|
|
var len = removeItems && removeItems.length;
|
|
|
|
if ( !len ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// remove elems from filteredItems
|
|
|
|
for ( var i=0; i < len; i++ ) {
|
|
|
|
var item = removeItems[i];
|
|
|
|
// remove item from collection
|
|
|
|
utils.removeFrom( this.filteredItems, item );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Isotope.prototype.shuffle = function() {
|
|
|
|
// update random sortData
|
|
|
|
for ( var i=0; i < this.items.length; i++ ) {
|
|
|
|
var item = this.items[i];
|
|
|
|
item.sortData.random = Math.random();
|
|
|
|
}
|
|
|
|
this.options.sortBy = 'random';
|
|
|
|
this._sort();
|
|
|
|
this._layout();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* trigger fn without transition
|
|
|
|
* kind of hacky to have this in the first place
|
|
|
|
* @param {Function} fn
|
|
|
|
* @param {Array} args
|
|
|
|
* @returns ret
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Isotope.prototype._noTransition = function( fn, args ) {
|
|
|
|
// save transitionDuration before disabling
|
|
|
|
var transitionDuration = this.options.transitionDuration;
|
|
|
|
// disable transition
|
|
|
|
this.options.transitionDuration = 0;
|
|
|
|
// do it
|
|
|
|
var returnValue = fn.apply( this, args );
|
|
|
|
// re-enable transition for reveal
|
|
|
|
this.options.transitionDuration = transitionDuration;
|
|
|
|
return returnValue;
|
|
|
|
};
|
|
|
|
|
|
|
|
// ----- helper methods ----- //
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getter method for getting filtered item elements
|
|
|
|
* @returns {Array} elems - collection of item elements
|
|
|
|
*/
|
|
|
|
Isotope.prototype.getFilteredItemElements = function() {
|
|
|
|
return this.filteredItems.map( function( item ) {
|
|
|
|
return item.element;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// ----- ----- //
|
|
|
|
|
|
|
|
return Isotope;
|
|
|
|
|
|
|
|
}));
|