Team:ETH Zurich/js/jquery.mixitup.js

From 2014.igem.org

/**!

* MixItUp v2.1.6
*
* @copyright Copyright 2014 KunkaLabs Limited.
* @author    KunkaLabs Limited.
* @link      https://mixitup.kunkalabs.com
*
* @license   Commercial use requires a commercial license.
*            https://mixitup.kunkalabs.com/licenses/
*
*            Non-commercial use permitted under terms of CC-BY-NC license.
*            http://creativecommons.org/licenses/by-nc/3.0/
*/

(function($, undf){

/** * MixItUp Constructor Function * @constructor * @extends jQuery */

$.MixItUp = function(){ var self = this;

self._execAction('_constructor', 0);

$.extend(self, {

/* Public Properties ---------------------------------------------------------------------- */

selectors: { target: '.mix', filter: '.filter', sort: '.sort' },

animation: { enable: true, effects: 'fade scale', duration: 600, easing: 'ease', perspectiveDistance: '3000', perspectiveOrigin: '50% 50%', queue: true, queueLimit: 1, animateChangeLayout: false, animateResizeContainer: true, animateResizeTargets: false, staggerSequence: false, reverseOut: false },

callbacks: { onMixLoad: false, onMixStart: false, onMixBusy: false, onMixEnd: false, onMixFail: false, _user: false },

controls: { enable: true, live: false, toggleFilterButtons: false, toggleLogic: 'or', activeClass: 'active' },

layout: { display: 'block', containerClass: , containerClassFail: 'fail' },

load: { filter: 'all', sort: false },

/* Private Properties ---------------------------------------------------------------------- */

_$body: null, _$container: null, _$targets: null, _$parent: null, _$sortButtons: null, _$filterButtons: null,

_suckMode: false, _mixing: false, _sorting: false, _clicking: false, _loading: true, _changingLayout: false, _changingClass: false, _changingDisplay: false,

_origOrder: [], _startOrder: [], _newOrder: [], _activeFilter: null, _toggleArray: [], _toggleString: , _activeSort: 'default:asc', _newSort: null, _startHeight: null, _newHeight: null, _incPadding: true, _newDisplay: null, _newClass: null, _targetsBound: 0, _targetsDone: 0, _queue: [],

_$show: $(), _$hide: $() });

self._execAction('_constructor', 1); };

/** * MixItUp Prototype * @override */

$.MixItUp.prototype = { constructor: $.MixItUp,

/* Static Properties ---------------------------------------------------------------------- */

_instances: {}, _handled: { _filter: {}, _sort: {} }, _bound: { _filter: {}, _sort: {} }, _actions: {}, _filters: {},

/* Static Methods ---------------------------------------------------------------------- */

/** * Extend * @since 2.1.0 * @param {object} new properties/methods * @extends {object} prototype */

extend: function(extension){ for(var key in extension){ $.MixItUp.prototype[key] = extension[key]; } },

/** * Add Action * @since 2.1.0 * @param {string} hook name * @param {string} namespace * @param {function} function to execute * @param {number} priority * @extends {object} $.MixItUp.prototype._actions */

addAction: function(hook, name, func, priority){ $.MixItUp.prototype._addHook('_actions', hook, name, func, priority); },

/** * Add Filter * @since 2.1.0 * @param {string} hook name * @param {string} namespace * @param {function} function to execute * @param {number} priority * @extends {object} $.MixItUp.prototype._filters */

addFilter: function(hook, name, func, priority){ $.MixItUp.prototype._addHook('_filters', hook, name, func, priority); },

/** * Add Hook * @since 2.1.0 * @param {string} type of hook * @param {string} hook name * @param {function} function to execute * @param {number} priority * @extends {object} $.MixItUp.prototype._filters */

_addHook: function(type, hook, name, func, priority){ var collection = $.MixItUp.prototype[type], obj = {};

priority = (priority === 1 || priority === 'post') ? 'post' : 'pre';

obj[hook] = {}; obj[hook][priority] = {}; obj[hook][priority][name] = func;

$.extend(true, collection, obj); },


/* Private Methods ---------------------------------------------------------------------- */

/** * Initialise * @since 2.0.0 * @param {object} domNode * @param {object} config */

_init: function(domNode, config){ var self = this;

self._execAction('_init', 0, arguments);

config && $.extend(true, self, config);

self._$body = $('body'); self._domNode = domNode; self._$container = $(domNode); self._$container.addClass(self.layout.containerClass); self._id = domNode.id;

self._platformDetect();

self._brake = self._getPrefixedCSS('transition', 'none');

self._refresh(true);

self._$parent = self._$targets.parent().length ? self._$targets.parent() : self._$container;

if(self.load.sort){ self._newSort = self._parseSort(self.load.sort); self._newSortString = self.load.sort; self._activeSort = self.load.sort; self._sort(); self._printSort(); }

self._activeFilter = self.load.filter === 'all' ? self.selectors.target : self.load.filter === 'none' ?  : self.load.filter;

self.controls.enable && self._bindHandlers();

if(self.controls.toggleFilterButtons){ self._buildToggleArray();

for(var i = 0; i < self._toggleArray.length; i++){ self._updateControls({filter: self._toggleArray[i], sort: self._activeSort}, true); }; } else if(self.controls.enable){ self._updateControls({filter: self._activeFilter, sort: self._activeSort}); }

self._filter();

self._init = true;

self._$container.data('mixItUp',self);

self._execAction('_init', 1, arguments);

self._buildState();

self._$targets.css(self._brake);

self._goMix(self.animation.enable); },

/** * Platform Detect * @since 2.0.0 */

_platformDetect: function(){ var self = this, vendorsTrans = ['Webkit', 'Moz', 'O', 'ms'], vendorsRAF = ['webkit', 'moz'], chrome = window.navigator.appVersion.match(/Chrome\/(\d+)\./) || false, ff = typeof InstallTrigger !== 'undefined', prefix = function(el){ for (var i = 0; i < vendorsTrans.length; i++){ if (vendorsTrans[i] + 'Transition' in el.style){ return { prefix: '-'+vendorsTrans[i].toLowerCase()+'-', vendor: vendorsTrans[i] }; }; }; return 'transition' in el.style ?  : false; }, transPrefix = prefix(self._domNode);

self._execAction('_platformDetect', 0);

self._chrome = chrome ? parseInt(chrome[1], 10) : false; self._ff = ff ? parseInt(window.navigator.userAgent.match(/rv:([^)]+)\)/)[1]) : false; self._prefix = transPrefix.prefix; self._vendor = transPrefix.vendor; self._suckMode = window.atob && self._prefix ? false : true;

self._suckMode && (self.animation.enable = false); (self._ff && self._ff <= 4) && (self.animation.enable = false);

/* Polyfills ---------------------------------------------------------------------- */

/** * window.requestAnimationFrame */

for(var x = 0; x < vendorsRAF.length && !window.requestAnimationFrame; x++){ window.requestAnimationFrame = window[vendorsRAF[x]+'RequestAnimationFrame']; }

/** * Object.getPrototypeOf */

if(typeof Object.getPrototypeOf !== 'function'){ if(typeof 'test'.__proto__ === 'object'){ Object.getPrototypeOf = function(object){ return object.__proto__; }; } else { Object.getPrototypeOf = function(object){ return object.constructor.prototype; }; } }

/** * Element.nextElementSibling */

if(self._domNode.nextElementSibling === undf){ Object.defineProperty(Element.prototype, 'nextElementSibling',{ get: function(){ var el = this.nextSibling;

while(el){ if(el.nodeType ===1){ return el; } el = el.nextSibling; } return null; } }); }

self._execAction('_platformDetect', 1); },

/** * Refresh * @since 2.0.0 * @param {boolean} init * @param {boolean} force */

_refresh: function(init, force){ var self = this;

self._execAction('_refresh', 0, arguments);

self._$targets = self._$container.find(self.selectors.target);

for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i];

if(target.dataset === undf || force){

target.dataset = {};

for(var j = 0; j < target.attributes.length; j++){

var attr = target.attributes[j], name = attr.name, val = attr.value;

if(name.indexOf('data-') > -1){ var dataName = self._helpers._camelCase(name.substring(5,name.length)); target.dataset[dataName] = val; } } }

if(target.mixParent === undf){ target.mixParent = self._id; } }

if( (self._$targets.length && init) || (!self._origOrder.length && self._$targets.length) ){ self._origOrder = [];

for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i];

self._origOrder.push(target); } }

self._execAction('_refresh', 1, arguments); },

/** * Bind Handlers * @since 2.0.0 */

_bindHandlers: function(){ var self = this, filters = $.MixItUp.prototype._bound._filter, sorts = $.MixItUp.prototype._bound._sort;

self._execAction('_bindHandlers', 0);

if(self.controls.live){ self._$body .on('click.mixItUp.'+self._id, self.selectors.sort, function(){ self._processClick($(this), 'sort'); }) .on('click.mixItUp.'+self._id, self.selectors.filter, function(){ self._processClick($(this), 'filter'); }); } else { self._$sortButtons = $(self.selectors.sort); self._$filterButtons = $(self.selectors.filter);

self._$sortButtons.on('click.mixItUp.'+self._id, function(){ self._processClick($(this), 'sort'); });

self._$filterButtons.on('click.mixItUp.'+self._id, function(){ self._processClick($(this), 'filter'); }); }

filters[self.selectors.filter] = (filters[self.selectors.filter] === undf) ? 1 : filters[self.selectors.filter] + 1; sorts[self.selectors.sort] = (sorts[self.selectors.sort] === undf) ? 1 : sorts[self.selectors.sort] + 1;

self._execAction('_bindHandlers', 1); },

/** * Process Click * @since 2.0.0 * @param {object} $button * @param {string} type */

_processClick: function($button, type){ var self = this, trackClick = function($button, type, off){ var proto = $.MixItUp.prototype;

proto._handled['_'+type][self.selectors[type]] = (proto._handled['_'+type][self.selectors[type]] === undf) ? 1 : proto._handled['_'+type][self.selectors[type]] + 1;

if(proto._handled['_'+type][self.selectors[type]] === proto._bound['_'+type][self.selectors[type]]){ $button[(off ? 'remove' : 'add')+'Class'](self.controls.activeClass); delete proto._handled['_'+type][self.selectors[type]]; } };

self._execAction('_processClick', 0, arguments);

if(!self._mixing || (self.animation.queue && self._queue.length < self.animation.queueLimit)){ self._clicking = true;

if(type === 'sort'){ var sort = $button.attr('data-sort');

if(!$button.hasClass(self.controls.activeClass) || sort.indexOf('random') > -1){ $(self.selectors.sort).removeClass(self.controls.activeClass); trackClick($button, type); self.sort(sort); } }

if(type === 'filter') { var filter = $button.attr('data-filter'), ndx, seperator = self.controls.toggleLogic === 'or' ? ',' : ;

if(!self.controls.toggleFilterButtons){ if(!$button.hasClass(self.controls.activeClass)){ $(self.selectors.filter).removeClass(self.controls.activeClass); trackClick($button, type); self.filter(filter); } } else { self._buildToggleArray();

if(!$button.hasClass(self.controls.activeClass)){ trackClick($button, type);

self._toggleArray.push(filter); } else { trackClick($button, type, true); ndx = self._toggleArray.indexOf(filter); self._toggleArray.splice(ndx, 1); }

self._toggleArray = $.grep(self._toggleArray,function(n){return(n);});

self._toggleString = self._toggleArray.join(seperator);

self.filter(self._toggleString); } }

self._execAction('_processClick', 1, arguments); } else { if(typeof self.callbacks.onMixBusy === 'function'){ self.callbacks.onMixBusy.call(self._domNode, self._state, self); } self._execAction('_processClickBusy', 1, arguments); } },

/** * Build Toggle Array * @since 2.0.0 */

_buildToggleArray: function(){ var self = this, activeFilter = self._activeFilter.replace(/\s/g, );

self._execAction('_buildToggleArray', 0, arguments);

if(self.controls.toggleLogic === 'or'){ self._toggleArray = activeFilter.split(','); } else { self._toggleArray = activeFilter.split('.');

!self._toggleArray[0] && self._toggleArray.shift();

for(var i = 0, filter; filter = self._toggleArray[i]; i++){ self._toggleArray[i] = '.'+filter; } }

self._execAction('_buildToggleArray', 1, arguments); },

/** * Update Controls * @since 2.0.0 * @param {object} command * @param {boolean} multi */

_updateControls: function(command, multi){ var self = this, output = { filter: command.filter, sort: command.sort }, update = function($el, filter){ (multi && type == 'filter' && !(output.filter === 'none' || output.filter === )) ? $el.filter(filter).addClass(self.controls.activeClass) : $el.removeClass(self.controls.activeClass).filter(filter).addClass(self.controls.activeClass); }, type = 'filter', $el = null;

self._execAction('_updateControls', 0, arguments);

(command.filter === undf) && (output.filter = self._activeFilter); (command.sort === undf) && (output.sort = self._activeSort); (output.filter === self.selectors.target) && (output.filter = 'all');

for(var i = 0; i < 2; i++){ $el = self.controls.live ? $(self.selectors[type]) : self['_$'+type+'Buttons']; $el && update($el, '[data-'+type+'="'+output[type]+'"]'); type = 'sort'; }

self._execAction('_updateControls', 1, arguments); },

/** * Filter (private) * @since 2.0.0 */

_filter: function(){ var self = this;

self._execAction('_filter', 0);

for(var i = 0; i < self._$targets.length; i++){ var $target = $(self._$targets[i]);

if($target.is(self._activeFilter)){ self._$show = self._$show.add($target); } else { self._$hide = self._$hide.add($target); } }

self._execAction('_filter', 1); },

/** * Sort (private) * @since 2.0.0 */

_sort: function(){ var self = this, arrayShuffle = function(oldArray){ var newArray = oldArray.slice(), len = newArray.length, i = len;

while(i--){ var p = parseInt(Math.random()*len); var t = newArray[i]; newArray[i] = newArray[p]; newArray[p] = t; }; return newArray; };

self._execAction('_sort', 0);

self._startOrder = [];

for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i];

self._startOrder.push(target); }

switch(self._newSort[0].sortBy){ case 'default': self._newOrder = self._origOrder; break; case 'random': self._newOrder = arrayShuffle(self._startOrder); break; case 'custom': self._newOrder = self._newSort[0].order; break; default: self._newOrder = self._startOrder.concat().sort(function(a, b){ return self._compare(a, b); }); }

self._execAction('_sort', 1); },

/** * Compare Algorithm * @since 2.0.0 * @param {string|number} a * @param {string|number} b * @param {number} depth (recursion) * @return {number} */

_compare: function(a, b, depth){ depth = depth ? depth : 0;

var self = this, order = self._newSort[depth].order, getData = function(el){ return el.dataset[self._newSort[depth].sortBy] || 0; }, attrA = isNaN(getData(a) * 1) ? getData(a).toLowerCase() : getData(a) * 1, attrB = isNaN(getData(b) * 1) ? getData(b).toLowerCase() : getData(b) * 1;

if(attrA < attrB) return order == 'asc' ? -1 : 1; if(attrA > attrB) return order == 'asc' ? 1 : -1; if(attrA == attrB && self._newSort.length > depth+1) return self._compare(a, b, depth+1);

return 0; },

/** * Print Sort * @since 2.0.0 * @param {boolean} reset */

_printSort: function(reset){ var self = this, order = reset ? self._startOrder : self._newOrder, targets = self._$parent[0].querySelectorAll(self.selectors.target), nextSibling = targets[targets.length -1].nextElementSibling, frag = document.createDocumentFragment();

self._execAction('_printSort', 0, arguments);

for(var i = 0; i < targets.length; i++){ var target = targets[i], whiteSpace = target.nextSibling;

if(target.style.position === 'absolute') continue;

if(whiteSpace && whiteSpace.nodeName == '#text'){ self._$parent[0].removeChild(whiteSpace); }

self._$parent[0].removeChild(target); }

for(var i = 0; i < order.length; i++){ var el = order[i];

if(self._newSort[0].sortBy == 'default' && self._newSort[0].order == 'desc' && !reset){ var firstChild = frag.firstChild; frag.insertBefore(el, firstChild); frag.insertBefore(document.createTextNode(' '), el); } else { frag.appendChild(el); frag.appendChild(document.createTextNode(' ')); } }

nextSibling ? self._$parent[0].insertBefore(frag, nextSibling) : self._$parent[0].appendChild(frag);

self._execAction('_printSort', 1, arguments); },

/** * Parse Sort * @since 2.0.0 * @param {string} sortString * @return {array} newSort */

_parseSort: function(sortString){ var self = this, rules = typeof sortString === 'string' ? sortString.split(' ') : [sortString], newSort = [];

for(var i = 0; i < rules.length; i++){ var rule = typeof sortString === 'string' ? rules[i].split(':') : ['custom', rules[i]], ruleObj = { sortBy: self._helpers._camelCase(rule[0]), order: rule[1] || 'asc' };

newSort.push(ruleObj);

if(ruleObj.sortBy == 'default' || ruleObj.sortBy == 'random') break; }

return self._execFilter('_parseSort', newSort, arguments); },

/** * Parse Effects * @since 2.0.0 * @return {object} effects */

_parseEffects: function(){ var self = this, effects = { opacity: , transformIn: , transformOut: , filter: }, parse = function(effect, extract, reverse){ if(self.animation.effects.indexOf(effect) > -1){ if(extract){ var propIndex = self.animation.effects.indexOf(effect+'('); if(propIndex > -1){ var str = self.animation.effects.substring(propIndex), match = /\(([^)]+)\)/.exec(str), val = match[1];

return {val: val}; } } return true; } else { return false; } }, negate = function(value, invert){ if(invert){ return value.charAt(0) === '-' ? value.substr(1, value.length) : '-'+value; } else { return value; } }, buildTransform = function(key, invert){ var transforms = [ ['scale', '.01'], ['translateX', '20px'], ['translateY', '20px'], ['translateZ', '20px'], ['rotateX', '90deg'], ['rotateY', '90deg'], ['rotateZ', '180deg'], ];

for(var i = 0; i < transforms.length; i++){ var prop = transforms[i][0], def = transforms[i][1], inverted = invert && prop !== 'scale';

effects[key] += parse(prop) ? prop+'('+negate(parse(prop, true).val || def, inverted)+') ' : ; } };

effects.opacity = parse('fade') ? parse('fade',true).val || '0' : '1';

buildTransform('transformIn');

self.animation.reverseOut ? buildTransform('transformOut', true) : (effects.transformOut = effects.transformIn);

effects.transition = {};

effects.transition = self._getPrefixedCSS('transition','all '+self.animation.duration+'ms '+self.animation.easing+', opacity '+self.animation.duration+'ms linear');

self.animation.stagger = parse('stagger') ? true : false; self.animation.staggerDuration = parseInt(parse('stagger') ? (parse('stagger',true).val ? parse('stagger',true).val : 100) : 100);

return self._execFilter('_parseEffects', effects); },

/** * Build State * @since 2.0.0 * @param {boolean} future * @return {object} futureState */

_buildState: function(future){ var self = this, state = {};

self._execAction('_buildState', 0);

state = { activeFilter: self._activeFilter ===  ? 'none' : self._activeFilter, activeSort: future && self._newSortString ? self._newSortString : self._activeSort, fail: !self._$show.length && self._activeFilter !== , $targets: self._$targets, $show: self._$show, $hide: self._$hide, totalTargets: self._$targets.length, totalShow: self._$show.length, totalHide: self._$hide.length, display: future && self._newDisplay ? self._newDisplay : self.layout.display };

if(future){ return self._execFilter('_buildState', state); } else { self._state = state;

self._execAction('_buildState', 1); } },

/** * Go Mix * @since 2.0.0 * @param {boolean} animate */

_goMix: function(animate){ var self = this, phase1 = function(){ if(self._chrome && (self._chrome === 31)){ chromeFix(self._$parent[0]); }

self._setInter();

phase2(); }, phase2 = function(){ var scrollTop = window.pageYOffset, scrollLeft = window.pageXOffset, docHeight = document.documentElement.scrollHeight;

self._getInterMixData();

self._setFinal();

self._getFinalMixData();

(window.pageYOffset !== scrollTop) && window.scrollTo(scrollLeft, scrollTop);

self._prepTargets();

if(window.requestAnimationFrame){ requestAnimationFrame(phase3); } else { setTimeout(function(){ phase3(); },20); } }, phase3 = function(){ self._animateTargets();

if(self._targetsBound === 0){ self._cleanUp(); } }, chromeFix = function(grid){ var parent = grid.parentElement, placeholder = document.createElement('div'), frag = document.createDocumentFragment();

parent.insertBefore(placeholder, grid); frag.appendChild(grid); parent.replaceChild(grid, placeholder); }, futureState = self._buildState(true);

self._execAction('_goMix', 0, arguments);

!self.animation.duration && (animate = false);

self._mixing = true;

self._$container.removeClass(self.layout.containerClassFail);

if(typeof self.callbacks.onMixStart === 'function'){ self.callbacks.onMixStart.call(self._domNode, self._state, futureState, self); }

self._$container.trigger('mixStart', [self._state, futureState, self]);

self._getOrigMixData();

if(animate && !self._suckMode){

window.requestAnimationFrame ? requestAnimationFrame(phase1) : phase1();

} else { self._cleanUp(); }

self._execAction('_goMix', 1, arguments); },

/** * Get Target Data * @since 2.0.0 */

_getTargetData: function(el, stage){ var self = this, elStyle;

el.dataset[stage+'PosX'] = el.offsetLeft; el.dataset[stage+'PosY'] = el.offsetTop;

if(self.animation.animateResizeTargets){ elStyle = window.getComputedStyle(el);

el.dataset[stage+'MarginBottom'] = parseInt(elStyle.marginBottom); el.dataset[stage+'MarginRight'] = parseInt(elStyle.marginRight); el.dataset[stage+'Width'] = el.offsetWidth; el.dataset[stage+'Height'] = el.offsetHeight; } },

/** * Get Original Mix Data * @since 2.0.0 */

_getOrigMixData: function(){ var self = this, parentStyle = !self._suckMode ? window.getComputedStyle(self._$parent[0]) : {boxSizing: }, parentBS = parentStyle.boxSizing || parentStyle[self._vendor+'BoxSizing'];

self._incPadding = (parentBS === 'border-box');

self._execAction('_getOrigMixData', 0);

!self._suckMode && (self.effects = self._parseEffects());

self._$toHide = self._$hide.filter(':visible'); self._$toShow = self._$show.filter(':hidden'); self._$pre = self._$targets.filter(':visible');

self._startHeight = self._incPadding ? self._$parent.outerHeight() : self._$parent.height();

for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i];

self._getTargetData(el, 'orig'); }

self._execAction('_getOrigMixData', 1); },

/** * Set Intermediate Positions * @since 2.0.0 */

_setInter: function(){ var self = this;

self._execAction('_setInter', 0);

if(self._changingLayout && self.animation.animateChangeLayout){ self._$toShow.css('display',self._newDisplay);

if(self._changingClass){ self._$container .removeClass(self.layout.containerClass) .addClass(self._newClass); } } else { self._$toShow.css('display', self.layout.display); }

self._execAction('_setInter', 1); },

/** * Get Intermediate Mix Data * @since 2.0.0 */

_getInterMixData: function(){ var self = this;

self._execAction('_getInterMixData', 0);

for(var i = 0; i < self._$toShow.length; i++){ var el = self._$toShow[i];

self._getTargetData(el, 'inter'); }

for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i];

self._getTargetData(el, 'inter'); }

self._execAction('_getInterMixData', 1); },

/** * Set Final Positions * @since 2.0.0 */

_setFinal: function(){ var self = this;

self._execAction('_setFinal', 0);

self._sorting && self._printSort();

self._$toHide.removeStyle('display');

if(self._changingLayout && self.animation.animateChangeLayout){ self._$pre.css('display',self._newDisplay); }

self._execAction('_setFinal', 1); },

/** * Get Final Mix Data * @since 2.0.0 */

_getFinalMixData: function(){ var self = this;

self._execAction('_getFinalMixData', 0);

for(var i = 0; i < self._$toShow.length; i++){ var el = self._$toShow[i];

self._getTargetData(el, 'final'); }

for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i];

self._getTargetData(el, 'final'); }

self._newHeight = self._incPadding ? self._$parent.outerHeight() : self._$parent.height();

self._sorting && self._printSort(true);

self._$toShow.removeStyle('display');

self._$pre.css('display',self.layout.display);

if(self._changingClass && self.animation.animateChangeLayout){ self._$container .removeClass(self._newClass) .addClass(self.layout.containerClass); }

self._execAction('_getFinalMixData', 1); },

/** * Prepare Targets * @since 2.0.0 */

_prepTargets: function(){ var self = this, transformCSS = { _in: self._getPrefixedCSS('transform', self.effects.transformIn), _out: self._getPrefixedCSS('transform', self.effects.transformOut) };

self._execAction('_prepTargets', 0);

if(self.animation.animateResizeContainer){ self._$parent.css('height',self._startHeight+'px'); }

for(var i = 0; i < self._$toShow.length; i++){ var el = self._$toShow[i], $el = $(el);

el.style.opacity = self.effects.opacity; el.style.display = (self._changingLayout && self.animation.animateChangeLayout) ? self._newDisplay : self.layout.display;

$el.css(transformCSS._in);

if(self.animation.animateResizeTargets){ el.style.width = el.dataset.finalWidth+'px'; el.style.height = el.dataset.finalHeight+'px'; el.style.marginRight = -(el.dataset.finalWidth - el.dataset.interWidth) + (el.dataset.finalMarginRight * 1)+'px'; el.style.marginBottom = -(el.dataset.finalHeight - el.dataset.interHeight) + (el.dataset.finalMarginBottom * 1)+'px'; } }

for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i], $el = $(el), translate = { x: el.dataset.origPosX - el.dataset.interPosX, y: el.dataset.origPosY - el.dataset.interPosY }, transformCSS = self._getPrefixedCSS('transform','translate('+translate.x+'px,'+translate.y+'px)');

$el.css(transformCSS);

if(self.animation.animateResizeTargets){ el.style.width = el.dataset.origWidth+'px'; el.style.height = el.dataset.origHeight+'px';

if(el.dataset.origWidth - el.dataset.finalWidth){ el.style.marginRight = -(el.dataset.origWidth - el.dataset.interWidth) + (el.dataset.origMarginRight * 1)+'px'; }

if(el.dataset.origHeight - el.dataset.finalHeight){ el.style.marginBottom = -(el.dataset.origHeight - el.dataset.interHeight) + (el.dataset.origMarginBottom * 1) +'px'; } } }

self._execAction('_prepTargets', 1); },

/** * Animate Targets * @since 2.0.0 */

_animateTargets: function(){ var self = this;

self._execAction('_animateTargets', 0);

self._targetsDone = 0; self._targetsBound = 0;

self._$parent .css(self._getPrefixedCSS('perspective', self.animation.perspectiveDistance+'px')) .css(self._getPrefixedCSS('perspective-origin', self.animation.perspectiveOrigin));

if(self.animation.animateResizeContainer){ self._$parent .css(self._getPrefixedCSS('transition','height '+self.animation.duration+'ms ease')) .css('height',self._newHeight+'px'); }

for(var i = 0; i < self._$toShow.length; i++){ var el = self._$toShow[i], $el = $(el), translate = { x: el.dataset.finalPosX - el.dataset.interPosX, y: el.dataset.finalPosY - el.dataset.interPosY }, delay = self._getDelay(i), toShowCSS = {};

el.style.opacity = ;

for(var j = 0; j < 2; j++){ var a = j === 0 ? a = self._prefix : ;

if(self._ff && self._ff <= 20){ toShowCSS[a+'transition-property'] = 'all'; toShowCSS[a+'transition-timing-function'] = self.animation.easing+'ms'; toShowCSS[a+'transition-duration'] = self.animation.duration+'ms'; }

toShowCSS[a+'transition-delay'] = delay+'ms'; toShowCSS[a+'transform'] = 'translate('+translate.x+'px,'+translate.y+'px)'; }

if(self.effects.transform || self.effects.opacity){ self._bindTargetDone($el); }

(self._ff && self._ff <= 20) ? $el.css(toShowCSS) : $el.css(self.effects.transition).css(toShowCSS); }

for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i], $el = $(el), translate = { x: el.dataset.finalPosX - el.dataset.interPosX, y: el.dataset.finalPosY - el.dataset.interPosY }, delay = self._getDelay(i);

if(!( el.dataset.finalPosX === el.dataset.origPosX && el.dataset.finalPosY === el.dataset.origPosY )){ self._bindTargetDone($el); }

$el.css(self._getPrefixedCSS('transition', 'all '+self.animation.duration+'ms '+self.animation.easing+' '+delay+'ms')); $el.css(self._getPrefixedCSS('transform', 'translate('+translate.x+'px,'+translate.y+'px)'));

if(self.animation.animateResizeTargets){ if(el.dataset.origWidth - el.dataset.finalWidth && el.dataset.finalWidth * 1){ el.style.width = el.dataset.finalWidth+'px'; el.style.marginRight = -(el.dataset.finalWidth - el.dataset.interWidth)+(el.dataset.finalMarginRight * 1)+'px'; }

if(el.dataset.origHeight - el.dataset.finalHeight && el.dataset.finalHeight * 1){ el.style.height = el.dataset.finalHeight+'px'; el.style.marginBottom = -(el.dataset.finalHeight - el.dataset.interHeight)+(el.dataset.finalMarginBottom * 1) +'px'; } } }

if(self._changingClass){ self._$container .removeClass(self.layout.containerClass) .addClass(self._newClass); }

for(var i = 0; i < self._$toHide.length; i++){ var el = self._$toHide[i], $el = $(el), delay = self._getDelay(i), toHideCSS = {};

for(var j = 0; j<2; j++){ var a = j === 0 ? a = self._prefix : ;

toHideCSS[a+'transition-delay'] = delay+'ms'; toHideCSS[a+'transform'] = self.effects.transformOut; toHideCSS.opacity = self.effects.opacity; }

$el.css(self.effects.transition).css(toHideCSS);

if(self.effects.transform || self.effects.opacity){ self._bindTargetDone($el); }; }

self._execAction('_animateTargets', 1);

},

/** * Bind Targets TransitionEnd * @since 2.0.0 * @param {object} $el */

_bindTargetDone: function($el){ var self = this, el = $el[0];

self._execAction('_bindTargetDone', 0, arguments);

if(!el.dataset.bound){

el.dataset.bound = true; self._targetsBound++;

$el.on('webkitTransitionEnd.mixItUp transitionend.mixItUp',function(e){ if( (e.originalEvent.propertyName.indexOf('transform') > -1 || e.originalEvent.propertyName.indexOf('opacity') > -1) && $(e.originalEvent.target).is(self.selectors.target) ){ $el.off('.mixItUp'); delete el.dataset.bound; self._targetDone(); } }); }

self._execAction('_bindTargetDone', 1, arguments); },

/** * Target Done * @since 2.0.0 */

_targetDone: function(){ var self = this;

self._execAction('_targetDone', 0);

self._targetsDone++;

(self._targetsDone === self._targetsBound) && self._cleanUp();

self._execAction('_targetDone', 1); },

/** * Clean Up * @since 2.0.0 */

_cleanUp: function(){ var self = this, targetStyles = self.animation.animateResizeTargets ? 'transform opacity width height margin-bottom margin-right' : 'transform opacity'; unBrake = function(){ self._$targets.removeStyle('transition', self._prefix); };

self._execAction('_cleanUp', 0);

!self._changingLayout ? self._$show.css('display',self.layout.display) : self._$show.css('display',self._newDisplay);

self._$targets.css(self._brake);

self._$targets .removeStyle(targetStyles, self._prefix) .removeAttr('data-inter-pos-x data-inter-pos-y data-final-pos-x data-final-pos-y data-orig-pos-x data-orig-pos-y data-orig-height data-orig-width data-final-height data-final-width data-inter-width data-inter-height data-orig-margin-right data-orig-margin-bottom data-inter-margin-right data-inter-margin-bottom data-final-margin-right data-final-margin-bottom');

self._$hide.removeStyle('display');

self._$parent.removeStyle('height transition perspective-distance perspective perspective-origin-x perspective-origin-y perspective-origin perspectiveOrigin', self._prefix);

if(self._sorting){ self._printSort(); self._activeSort = self._newSortString; self._sorting = false; }

if(self._changingLayout){ if(self._changingDisplay){ self.layout.display = self._newDisplay; self._changingDisplay = false; }

if(self._changingClass){ self._$parent.removeClass(self.layout.containerClass).addClass(self._newClass); self.layout.containerClass = self._newClass; self._changingClass = false; }

self._changingLayout = false; }

self._refresh();

self._buildState();

if(self._state.fail){ self._$container.addClass(self.layout.containerClassFail); }

self._$show = $(); self._$hide = $();

if(window.requestAnimationFrame){ requestAnimationFrame(unBrake); }

self._mixing = false;

if(typeof self.callbacks._user === 'function'){ self.callbacks._user.call(self._domNode, self._state, self); }

if(typeof self.callbacks.onMixEnd === 'function'){ self.callbacks.onMixEnd.call(self._domNode, self._state, self); }

self._$container.trigger('mixEnd', [self._state, self]);

if(self._state.fail){ (typeof self.callbacks.onMixFail === 'function') && self.callbacks.onMixFail.call(self._domNode, self._state, self); self._$container.trigger('mixFail', [self._state, self]); }

if(self._loading){ (typeof self.callbacks.onMixLoad === 'function') && self.callbacks.onMixLoad.call(self._domNode, self._state, self); self._$container.trigger('mixLoad', [self._state, self]); }

if(self._queue.length){ self._execAction('_queue', 0);

self.multiMix(self._queue[0][0],self._queue[0][1],self._queue[0][2]); self._queue.splice(0, 1); }

self._execAction('_cleanUp', 1);

self._loading = false; },

/** * Get Prefixed CSS * @since 2.0.0 * @param {string} property * @param {string} value * @param {boolean} prefixValue * @return {object} styles */

_getPrefixedCSS: function(property, value, prefixValue){ var self = this, styles = {};

for(i = 0; i < 2; i++){ var prefix = i === 0 ? self._prefix : ; prefixValue ? styles[prefix+property] = prefix+value : styles[prefix+property] = value; }

return self._execFilter('_getPrefixedCSS', styles, arguments); },

/** * Get Delay * @since 2.0.0 * @param {number} i * @return {number} delay */

_getDelay: function(i){ var self = this, n = typeof self.animation.staggerSequence === 'function' ? self.animation.staggerSequence.call(self._domNode, i, self._state) : i, delay = self.animation.stagger ? n * self.animation.staggerDuration : 0;

return self._execFilter('_getDelay', delay, arguments); },

/** * Parse MultiMix Arguments * @since 2.0.0 * @param {array} args * @return {object} output */

_parseMultiMixArgs: function(args){ var self = this, output = { command: null, animate: self.animation.enable, callback: null };

for(var i = 0; i < args.length; i++){ var arg = args[i];

if(arg !== null){ if(typeof arg === 'object' || typeof arg === 'string'){ output.command = arg; } else if(typeof arg === 'boolean'){ output.animate = arg; } else if(typeof arg === 'function'){ output.callback = arg; } } }

return self._execFilter('_parseMultiMixArgs', output, arguments); },

/** * Parse Insert Arguments * @since 2.0.0 * @param {array} args * @return {object} output */

_parseInsertArgs: function(args){ var self = this, output = { index: 0, $object: $(), multiMix: {filter: self._state.activeFilter}, callback: null };

for(var i = 0; i < args.length; i++){ var arg = args[i];

if(typeof arg === 'number'){ output.index = arg; } else if(typeof arg === 'object' && arg instanceof $){ output.$object = arg; } else if(typeof arg === 'object' && self._helpers._isElement(arg)){ output.$object = $(arg); } else if(typeof arg === 'object' && arg !== null){ output.multiMix = arg; } else if(typeof arg === 'boolean' && !arg){ output.multiMix = false; } else if(typeof arg === 'function'){ output.callback = arg; } }

return self._execFilter('_parseInsertArgs', output, arguments); },

/** * Execute Action * @since 2.0.0 * @param {string} methodName * @param {boolean} isPost * @param {array} args */

_execAction: function(methodName, isPost, args){ var self = this, context = isPost ? 'post' : 'pre';

if(!self._actions.isEmptyObject && self._actions.hasOwnProperty(methodName)){ for(var key in self._actions[methodName][context]){ self._actions[methodName][context][key].call(self, args); } } },

/** * Execute Filter * @since 2.0.0 * @param {string} methodName * @param {mixed} value * @return {mixed} value */

_execFilter: function(methodName, value, args){ var self = this;

if(!self._filters.isEmptyObject && self._filters.hasOwnProperty(methodName)){ for(var key in self._filters[methodName]){ return self._filters[methodName][key].call(self, args); } } else { return value; } },

/* Helpers ---------------------------------------------------------------------- */

_helpers: {

/** * CamelCase * @since 2.0.0 * @param {string} * @return {string} */

_camelCase: function(string){ return string.replace(/-([a-z])/g, function(g){ return g[1].toUpperCase(); }); },

/** * Is Element * @since 2.1.3 * @param {object} element to test * @return {boolean} */

_isElement: function(el){ if(window.HTMLElement){ return el instanceof HTMLElement; } else { return ( el !== null && el.nodeType === 1 && el.nodeName === 'string' ); } } },

/* Public Methods ---------------------------------------------------------------------- */

/** * Is Mixing * @since 2.0.0 * @return {boolean} */

isMixing: function(){ var self = this;

return self._execFilter('isMixing', self._mixing); },

/** * Filter (public) * @since 2.0.0 * @param {array} arguments */

filter: function(){ var self = this, args = self._parseMultiMixArgs(arguments);

self._clicking && (self._toggleString = );

self.multiMix({filter: args.command}, args.animate, args.callback); },

/** * Sort (public) * @since 2.0.0 * @param {array} arguments */

sort: function(){ var self = this, args = self._parseMultiMixArgs(arguments);

self.multiMix({sort: args.command}, args.animate, args.callback); },

/** * Change Layout (public) * @since 2.0.0 * @param {array} arguments */

changeLayout: function(){ var self = this, args = self._parseMultiMixArgs(arguments);

self.multiMix({changeLayout: args.command}, args.animate, args.callback); },

/** * MultiMix * @since 2.0.0 * @param {array} arguments */

multiMix: function(){ var self = this, args = self._parseMultiMixArgs(arguments);

self._execAction('multiMix', 0, arguments);

if(!self._mixing){ if(self.controls.enable && !self._clicking){ self.controls.toggleFilterButtons && self._buildToggleArray(); self._updateControls(args.command, self.controls.toggleFilterButtons); }

(self._queue.length < 2) && (self._clicking = false);

delete self.callbacks._user; if(args.callback) self.callbacks._user = args.callback;

var sort = args.command.sort, filter = args.command.filter, changeLayout = args.command.changeLayout;

self._refresh();

if(sort){ self._newSort = self._parseSort(sort); self._newSortString = sort;

self._sorting = true; self._sort(); }

if(filter !== undf){ filter = (filter === 'all') ? self.selectors.target : filter;

self._activeFilter = filter; }

self._filter();

if(changeLayout){ self._newDisplay = (typeof changeLayout === 'string') ? changeLayout : changeLayout.display || self.layout.display; self._newClass = changeLayout.containerClass || ;

if( self._newDisplay !== self.layout.display || self._newClass !== self.layout.containerClass ){ self._changingLayout = true;

self._changingClass = (self._newClass !== self.layout.containerClass); self._changingDisplay = (self._newDisplay !== self.layout.display); } }

self._$targets.css(self._brake);

self._goMix(args.animate ^ self.animation.enable ? args.animate : self.animation.enable);

self._execAction('multiMix', 1, arguments);

} else { if(self.animation.queue && self._queue.length < self.animation.queueLimit){ self._queue.push(arguments);

(self.controls.enable && !self._clicking) && self._updateControls(args.command);

self._execAction('multiMixQueue', 1, arguments);

} else { if(typeof self.callbacks.onMixBusy === 'function'){ self.callbacks.onMixBusy.call(self._domNode, self._state, self); } self._$container.trigger('mixBusy', [self._state, self]);

self._execAction('multiMixBusy', 1, arguments); } } },

/** * Insert * @since 2.0.0 * @param {array} arguments */

insert: function(){ var self = this, args = self._parseInsertArgs(arguments), callback = (typeof args.callback === 'function') ? args.callback : null, frag = document.createDocumentFragment(), target = (function(){ self._refresh();

if(self._$targets.length){ return (args.index < self._$targets.length || !self._$targets.length) ? self._$targets[args.index] : self._$targets[self._$targets.length-1].nextElementSibling; } else { return self._$parent[0].children[0]; } })();

self._execAction('insert', 0, arguments);

if(args.$object){ for(var i = 0; i < args.$object.length; i++){ var el = args.$object[i];

frag.appendChild(el); frag.appendChild(document.createTextNode(' ')); }

self._$parent[0].insertBefore(frag, target); }

self._execAction('insert', 1, arguments);

if(typeof args.multiMix === 'object'){ self.multiMix(args.multiMix, callback); } },

/** * Prepend * @since 2.0.0 * @param {array} arguments */

prepend: function(){ var self = this, args = self._parseInsertArgs(arguments);

self.insert(0, args.$object, args.multiMix, args.callback); },

/** * Append * @since 2.0.0 * @param {array} arguments */

append: function(){ var self = this, args = self._parseInsertArgs(arguments);

self.insert(self._state.totalTargets, args.$object, args.multiMix, args.callback); },

/** * Get Option * @since 2.0.0 * @param {string} string * @return {mixed} value */

getOption: function(string){ var self = this, getProperty = function(obj, prop){ var parts = prop.split('.'), last = parts.pop(), l = parts.length, i = 1, current = parts[0] || prop;

while((obj = obj[current]) && i < l){ current = parts[i]; i++; }

if(obj !== undf){ return obj[last] !== undf ? obj[last] : obj; } };

return string ? self._execFilter('getOption', getProperty(self, string), arguments) : self; },

/** * Set Options * @since 2.0.0 * @param {object} config */

setOptions: function(config){ var self = this;

self._execAction('setOptions', 0, arguments);

typeof config === 'object' && $.extend(true, self, config);

self._execAction('setOptions', 1, arguments); },

/** * Get State * @since 2.0.0 * @return {object} state */

getState: function(){ var self = this;

return self._execFilter('getState', self._state, self); },

/** * Force Refresh * @since 2.1.2 */

forceRefresh: function(){ var self = this;

self._refresh(false, true); },

/** * Destroy * @since 2.0.0 * @param {boolean} hideAll */

destroy: function(hideAll){ var self = this;

self._execAction('destroy', 0, arguments);

self._$body .add($(self.selectors.sort)) .add($(self.selectors.filter)) .off('.mixItUp');

for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i];

hideAll && (target.style.display = );

delete target.mixParent; }

self._execAction('destroy', 1, arguments);

delete $.MixItUp.prototype._instances[self._id]; }

};

/* jQuery Methods ---------------------------------------------------------------------- */

/** * jQuery .mixItUp() method * @since 2.0.0 * @extends $.fn */

$.fn.mixItUp = function(){ var args = arguments, dataReturn = [], eachReturn, _instantiate = function(domNode, settings){ var instance = new $.MixItUp(), rand = function(){ return ('00000'+(Math.random()*16777216<<0).toString(16)).substr(-6).toUpperCase(); };

instance._execAction('_instantiate', 0, arguments);

domNode.id = !domNode.id ? 'MixItUp'+rand() : domNode.id;

if(!instance._instances[domNode.id]){ instance._instances[domNode.id] = instance; instance._init(domNode, settings); }

instance._execAction('_instantiate', 1, arguments); };

eachReturn = this.each(function(){ if(args && typeof args[0] === 'string'){ var instance = $.MixItUp.prototype._instances[this.id]; if(args[0] == 'isLoaded'){ dataReturn.push(instance ? true : false); } else { var data = instance[args[0]](args[1], args[2], args[3]); if(data !== undf)dataReturn.push(data); } } else { _instantiate(this, args[0]); } });

if(dataReturn.length){ return dataReturn.length > 1 ? dataReturn : dataReturn[0]; } else { return eachReturn; } };

/** * jQuery .removeStyle() method * @since 2.0.0 * @extends $.fn */

$.fn.removeStyle = function(style, prefix){ prefix = prefix ? prefix : ;

return this.each(function(){ var el = this, styles = style.split(' ');

for(var i = 0; i < styles.length; i++){ for(var j = 0; j < 2; j++){ var prop = j ? styles[i] : prefix+styles[i]; if( el.style[prop] !== undf && typeof el.style[prop] !== 'unknown' && el.style[prop].length > 0 ){ el.style[prop] = ; } if(!prefix)break; } }

if(el.attributes && el.attributes.style && el.attributes.style !== undf && el.attributes.style.value === ){ el.attributes.removeNamedItem('style'); } }); };

})(jQuery);