text: /**!
   * MixItUp v2.1.11
   *
   * @copyright Copyright 2015 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.
   *            https://creativecommons.org/licenses/by-nc/3.0/
   */
  
  (function($, undf){
  	'use strict';
  
  	/**
  	 * 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: 'inline-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){
  					try {
  						(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);
  					} catch(e) {}
  				},
  				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.length ? targets[targets.length -1].nextElementSibling : null,
  				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 = !self._suckMode ?
  					window.getComputedStyle(el) :
  					{
  						marginBottom: '',
  						marginRight: ''
  					};
  
  				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');
  						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 = {},
  				prefix = '',
  				i = -1;
  
  			for(i = 0; i < 2; i++){
  				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,
  				filters = $.MixItUp.prototype._bound._filter,
  				sorts = $.MixItUp.prototype._bound._sort;
  
  			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);
  
  			if(filters[self.selectors.filter] && filters[self.selectors.filter] > 1) {
  				filters[self.selectors.filter]--;
  			} else if(filters[self.selectors.filter] === 1) {
  				delete filters[self.selectors.filter];
  			}
  
  			if(sorts[self.selectors.sort] && sorts[self.selectors.sort] > 1) {
  				sorts[self.selectors.sort]--;
  			} else if(sorts[self.selectors.sort] === 1) {
  				delete sorts[self.selectors.sort];
  			}
  
  			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 < 4; j++){
  					switch (j) {
  						case 0:
  							var prop = styles[i];
  							break;
  						case 1:
  							var prop = $.MixItUp.prototype._helpers._camelCase(prop);
  							break;
  						case 2:
  							var prop = prefix+styles[i];
  							break;
  						case 3:
  							var prop = $.MixItUp.prototype._helpers._camelCase(prefix+styles[i]);
  					}
  
  					if(
  						el.style[prop] !== undf &&
  						typeof el.style[prop] !== 'unknown' &&
  						el.style[prop].length > 0
  					){
  						el.style[prop] = '';
  					}
  
  					if(!prefix && j === 1)break;
  				}
  			}
  
  			if(el.attributes && el.attributes.style && el.attributes.style !== undf && el.attributes.style.value === ''){
  				el.attributes.removeNamedItem('style');
  			}
  		});
  	};
  
  })(jQuery);