PageSourceSearch

https://baroquedub.co.uk/about/assets/js/jquery.mixitup.js

js baroquedub.co.uk collected 2026-09-24 08:27:08 UTC 50,986 bytes, 2,098 lines download raw bytes

1/**!
2 * MixItUp v2.1.11
3 *
4 * @copyright Copyright 2015 KunkaLabs Limited.
5 * @author    KunkaLabs Limited.
6 * @link      https://mixitup.kunkalabs.com
7 *
8 * @license   Commercial use requires a commercial license.
9 *            https://mixitup.kunkalabs.com/licenses/
10 *
11 *            Non-commercial use permitted under terms of CC-BY-NC license.
12 *            http://creativecommons.org/licenses/by-nc/3.0/
13 */
14
15(function($, undf){
16	'use strict';
17
18	/**
19	 * MixItUp Constructor Function
20	 * @constructor
21	 * @extends jQuery
22	 */
23
24	$.MixItUp = function(){
25		var self = this;
26
27		self._execAction('_constructor', 0);
28
29		$.extend(self, {
30
31			/* Public Properties
32			---------------------------------------------------------------------- */
33
34			selectors: {
35				target: '.mix',
36				filter: '.filter',
37				sort: '.sort'
38			},
39
40			animation: {
41				enable: true,
42				effects: 'fade scale',
43				duration: 600,
44				easing: 'ease',
45				perspectiveDistance: '3000',
46				perspectiveOrigin: '50% 50%',
47				queue: true,
48				queueLimit: 1,
49				animateChangeLayout: false,
50				animateResizeContainer: true,
51				animateResizeTargets: false,
52				staggerSequence: false,
53				reverseOut: false
54			},
55
56			callbacks: {
57				onMixLoad: false,
58				onMixStart: false,
59				onMixBusy: false,
60				onMixEnd: false,
61				onMixFail: false,
62				_user: false
63			},
64
65			controls: {
66				enable: true,
67				live: false,
68				toggleFilterButtons: false,
69				toggleLogic: 'or',
70				activeClass: 'active'
71			},
72
73			layout: {
74				display: 'inline-block',
75				containerClass: '',
76				containerClassFail: 'fail'
77			},
78
79			load: {
80				filter: 'all',
81				sort: false
82			},
83
84			/* Private Properties
85			---------------------------------------------------------------------- */
86
87			_$body: null,
88			_$container: null,
89			_$targets: null,
90			_$parent: null,
91			_$sortButtons: null,
92			_$filterButtons: null,
93
94			_suckMode: false,
95			_mixing: false,
96			_sorting: false,
97			_clicking: false,
98			_loading: true,
99			_changingLayout: false,
100			_changingClass: false,
101			_changingDisplay: false,
102
103			_origOrder: [],
104			_startOrder: [],
105			_newOrder: [],
106			_activeFilter: null,
107			_toggleArray: [],
108			_toggleString: '',
109			_activeSort: 'default:asc',
110			_newSort: null,
111			_startHeight: null,
112			_newHeight: null,
113			_incPadding: true,
114			_newDisplay: null,
115			_newClass: null,
116			_targetsBound: 0,
117			_targetsDone: 0,
118			_queue: [],
119
120			_$show: $(),
121			_$hide: $()
122		});
123
124		self._execAction('_constructor', 1);
125	};
126
127	/**
128	 * MixItUp Prototype
129	 * @override
130	 */
131
132	$.MixItUp.prototype = {
133		constructor: $.MixItUp,
134
135		/* Static Properties
136		---------------------------------------------------------------------- */
137
138		_instances: {},
139		_handled: {
140			_filter: {},
141			_sort: {}
142		},
143		_bound: {
144			_filter: {},
145			_sort: {}
146		},
147		_actions: {},
148		_filters: {},
149
150		/* Static Methods
151		---------------------------------------------------------------------- */
152
153		/**
154		 * Extend
155		 * @since 2.1.0
156		 * @param {object} new properties/methods
157		 * @extends {object} prototype
158		 */
159
160		extend: function(extension){
161			for(var key in extension){
162				$.MixItUp.prototype[key] = extension[key];
163			}
164		},
165
166		/**
167		 * Add Action
168		 * @since 2.1.0
169		 * @param {string} hook name
170		 * @param {string} namespace
171		 * @param {function} function to execute
172		 * @param {number} priority
173		 * @extends {object} $.MixItUp.prototype._actions
174		 */
175
176		addAction: function(hook, name, func, priority){
177			$.MixItUp.prototype._addHook('_actions', hook, name, func, priority);
178		},
179
180		/**
181		 * Add Filter
182		 * @since 2.1.0
183		 * @param {string} hook name
184		 * @param {string} namespace
185		 * @param {function} function to execute
186		 * @param {number} priority
187		 * @extends {object} $.MixItUp.prototype._filters
188		 */
189
190		addFilter: function(hook, name, func, priority){
191			$.MixItUp.prototype._addHook('_filters', hook, name, func, priority);
192		},
193
194		/**
195		 * Add Hook
196		 * @since 2.1.0
197		 * @param {string} type of hook
198		 * @param {string} hook name
199		 * @param {function} function to execute
200		 * @param {number} priority
201		 * @extends {object} $.MixItUp.prototype._filters
202		 */
203
204		_addHook: function(type, hook, name, func, priority){
205			var collection = $.MixItUp.prototype[type],
206				obj = {};
207
208			priority = (priority === 1 || priority === 'post') ? 'post' : 'pre';
209
210			obj[hook] = {};
211			obj[hook][priority] = {};
212			obj[hook][priority][name] = func;
213
214			$.extend(true, collection, obj);
215		},
216
217
218		/* Private Methods
219		---------------------------------------------------------------------- */
220
221		/**
222		 * Initialise
223		 * @since 2.0.0
224		 * @param {object} domNode
225		 * @param {object} config
226		 */
227
228		_init: function(domNode, config){
229			var self = this;
230
231			self._execAction('_init', 0, arguments);
232
233			config && $.extend(true, self, config);
234
235			self._$body = $('body');
236			self._domNode = domNode;
237			self._$container = $(domNode);
238			self._$container.addClass(self.layout.containerClass);
239			self._id = domNode.id;
240
241			self._platformDetect();
242
243			self._brake = self._getPrefixedCSS('transition', 'none');
244
245			self._refresh(true);
246
247			self._$parent = self._$targets.parent().length ? self._$targets.parent() : self._$container;
248
249			if(self.load.sort){
250				self._newSort = self._parseSort(self.load.sort);
251				self._newSortString = self.load.sort;
252				self._activeSort = self.load.sort;
253				self._sort();
254				self._printSort();
255			}
256
257			self._activeFilter = self.load.filter === 'all' ?
258				self.selectors.target :
259				self.load.filter === 'none' ?
260					'' :
261					self.load.filter;
262
263			self.controls.enable && self._bindHandlers();
264
265			if(self.controls.toggleFilterButtons){
266				self._buildToggleArray();
267
268				for(var i = 0; i < self._toggleArray.length; i++){
269					self._updateControls({filter: self._toggleArray[i], sort: self._activeSort}, true);
270				};
271			} else if(self.controls.enable){
272				self._updateControls({filter: self._activeFilter, sort: self._activeSort});
273			}
274
275			self._filter();
276
277			self._init = true;
278
279			self._$container.data('mixItUp',self);
280
281			self._execAction('_init', 1, arguments);
282
283			self._buildState();
284
285			self._$targets.css(self._brake);
286
287			self._goMix(self.animation.enable);
288		},
289
290		/**
291		 * Platform Detect
292		 * @since 2.0.0
293		 */
294
295		_platformDetect: function(){
296			var self = this,
297				vendorsTrans = ['Webkit', 'Moz', 'O', 'ms'],
298				vendorsRAF = ['webkit', 'moz'],
299				chrome = window.navigator.appVersion.match(/Chrome\/(\d+)\./) || false,
300				ff = typeof InstallTrigger !== 'undefined',
301				prefix = function(el){
302					for (var i = 0; i < vendorsTrans.length; i++){
303						if (vendorsTrans[i] + 'Transition' in el.style){
304							return {
305								prefix: '-'+vendorsTrans[i].toLowerCase()+'-',
306								vendor: vendorsTrans[i]
307							};
308						};
309					};
310					return 'transition' in el.style ? '' : false;
311				},
312				transPrefix = prefix(self._domNode);
313
314			self._execAction('_platformDetect', 0);
315
316			self._chrome = chrome ? parseInt(chrome[1], 10) : false;
317			self._ff = ff ? parseInt(window.navigator.userAgent.match(/rv:([^)]+)\)/)[1]) : false;
318			self._prefix = transPrefix.prefix;
319			self._vendor = transPrefix.vendor;
320			self._suckMode = window.atob && self._prefix ? false : true;
321
322			self._suckMode && (self.animation.enable = false);
323			(self._ff && self._ff <= 4) && (self.animation.enable = false);
324
325			/* Polyfills
326			---------------------------------------------------------------------- */
327
328			/**
329			 * window.requestAnimationFrame
330			 */
331
332			for(var x = 0; x < vendorsRAF.length && !window.requestAnimationFrame; x++){
333				window.requestAnimationFrame = window[vendorsRAF[x]+'RequestAnimationFrame'];
334			}
335
336			/**
337			 * Object.getPrototypeOf
338			 */
339
340			if(typeof Object.getPrototypeOf !== 'function'){
341				if(typeof 'test'.__proto__ === 'object'){
342					Object.getPrototypeOf = function(object){
343						return object.__proto__;
344					};
345				} else {
346					Object.getPrototypeOf = function(object){
347						return object.constructor.prototype;
348					};
349				}
350			}
351
352			/**
353			 * Element.nextElementSibling
354			 */
355
356			if(self._domNode.nextElementSibling === undf){
357				Object.defineProperty(Element.prototype, 'nextElementSibling',{
358					get: function(){
359						var el = this.nextSibling;
360
361						while(el){
362							if(el.nodeType ===1){
363								return el;
364							}
365							el = el.nextSibling;
366						}
367						return null;
368					}
369				});
370			}
371
372			self._execAction('_platformDetect', 1);
373		},
374
375		/**
376		 * Refresh
377		 * @since 2.0.0
378		 * @param {boolean} init
379		 * @param {boolean} force
380		 */
381
382		_refresh: function(init, force){
383			var self = this;
384
385			self._execAction('_refresh', 0, arguments);
386
387			self._$targets = self._$container.find(self.selectors.target);
388
389			for(var i = 0; i < self._$targets.length; i++){
390				var target = self._$targets[i];
391
392				if(target.dataset === undf || force){
393
394					target.dataset = {};
395
396					for(var j = 0; j < target.attributes.length; j++){
397
398						var attr = target.attributes[j],
399							name = attr.name,
400							val = attr.value;
401
402						if(name.indexOf('data-') > -1){
403							var dataName = self._helpers._camelCase(name.substring(5,name.length));
404							target.dataset[dataName] = val;
405						}
406					}
407				}
408
409				if(target.mixParent === undf){
410					target.mixParent = self._id;
411				}
412			}
413
414			if(
415				(self._$targets.length && init) ||
416				(!self._origOrder.length && self._$targets.length)
417			){
418				self._origOrder = [];
419
420				for(var i = 0; i < self._$targets.length; i++){
421					var target = self._$targets[i];
422
423					self._origOrder.push(target);
424				}
425			}
426
427			self._execAction('_refresh', 1, arguments);
428		},
429
430		/**
431		 * Bind Handlers
432		 * @since 2.0.0
433		 */
434
435		_bindHandlers: function(){
436			var self = this,
437				filters = $.MixItUp.prototype._bound._filter,
438				sorts = $.MixItUp.prototype._bound._sort;
439
440			self._execAction('_bindHandlers', 0);
441
442			if(self.controls.live){
443				self._$body
444					.on('click.mixItUp.'+self._id, self.selectors.sort, function(){
445						self._processClick($(this), 'sort');
446					})
447					.on('click.mixItUp.'+self._id, self.selectors.filter, function(){
448						self._processClick($(this), 'filter');
449					});
450			} else {
451				self._$sortButtons = $(self.selectors.sort);
452				self._$filterButtons = $(self.selectors.filter);
453
454				self._$sortButtons.on('click.mixItUp.'+self._id, function(){
455					self._processClick($(this), 'sort');
456				});
457
458				self._$filterButtons.on('click.mixItUp.'+self._id, function(){
459					self._processClick($(this), 'filter');
460				});
461			}
462
463			filters[self.selectors.filter] = (filters[self.selectors.filter] === undf) ? 1 : filters[self.selectors.filter] + 1;
464			sorts[self.selectors.sort] = (sorts[self.selectors.sort] === undf) ? 1 : sorts[self.selectors.sort] + 1;
465
466			self._execAction('_bindHandlers', 1);
467		},
468
469		/**
470		 * Process Click
471		 * @since 2.0.0
472		 * @param {object} $button
473		 * @param {string} type
474		 */
475
476		_processClick: function($button, type){
477			var self = this,
478				trackClick = function($button, type, off){
479					var proto = $.MixItUp.prototype;
480
481					proto._handled['_'+type][self.selectors[type]] = (proto._handled['_'+type][self.selectors[type]] === undf) ?
482						1 :
483						proto._handled['_'+type][self.selectors[type]] + 1;
484
485					if(proto._handled['_'+type][self.selectors[type]] === proto._bound['_'+type][self.selectors[type]]
485){
486						$button[(off ? 'remove' : 'add')+'Class'](self.controls.activeClass);
487						delete proto._handled['_'+type][self.selectors[type]];
488					}
489				};
490
491			self._execAction('_processClick', 0, arguments);
492
493			if(!self._mixing || (self.animation.queue && self._queue.length < self.animation.queueLimit)){
494				self._clicking = true;
495
496				if(type === 'sort'){
497					var sort = $button.attr('data-sort');
498
499					if(!$button.hasClass(self.controls.activeClass) || sort.indexOf('random') > -1){
500						$(self.selectors.sort).removeClass(self.controls.activeClass);
501						trackClick($button, type);
502						self.sort(sort);
503					}
504				}
505
506				if(type === 'filter') {
507					var filter = $button.attr('data-filter'),
508						ndx,
509						seperator = self.controls.toggleLogic === 'or' ? ',' : '';
510
511					if(!self.controls.toggleFilterButtons){
512						if(!$button.hasClass(self.controls.activeClass)){
513							$(self.selectors.filter).removeClass(self.controls.activeClass);
514							trackClick($button, type);
515							self.filter(filter);
516						}
517					} else {
518						self._buildToggleArray();
519
520						if(!$button.hasClass(self.controls.activeClass)){
521							trackClick($button, type);
522
523							self._toggleArray.push(filter);
524						} else {
525							trackClick($button, type, true);
526							ndx = self._toggleArray.indexOf(filter);
527							self._toggleArray.splice(ndx, 1);
528						}
529
530						self._toggleArray = $.grep(self._toggleArray,function(n){return(n);});
531
532						self._toggleString = self._toggleArray.join(seperator);
533
534						self.filter(self._toggleString);
535					}
536				}
537
538				self._execAction('_processClick', 1, arguments);
539			} else {
540				if(typeof self.callbacks.onMixBusy === 'function'){
541					self.callbacks.onMixBusy.call(self._domNode, self._state, self);
542				}
543				self._execAction('_processClickBusy', 1, arguments);
544			}
545		},
546
547		/**
548		 * Build Toggle Array
549		 * @since 2.0.0
550		 */
551
552		_buildToggleArray: function(){
553			var self = this,
554				activeFilter = self._activeFilter.replace(/\s/g, '');
555
556			self._execAction('_buildToggleArray', 0, arguments);
557
558			if(self.controls.toggleLogic === 'or'){
559				self._toggleArray = activeFilter.split(',');
560			} else {
561				self._toggleArray = activeFilter.split('.');
562
563				!self._toggleArray[0] && self._toggleArray.shift();
564
565				for(var i = 0, filter; filter = self._toggleArray[i]; i++){
566					self._toggleArray[i] = '.'+filter;
567				}
568			}
569
570			self._execAction('_buildToggleArray', 1, arguments);
571		},
572
573		/**
574		 * Update Controls
575		 * @since 2.0.0
576		 * @param {object} command
577		 * @param {boolean} multi
578		 */
579
580		_updateControls: function(command, multi){
581			var self = this,
582				output = {
583					filter: command.filter,
584					sort: command.sort
585				},
586				update = function($el, filter){
587					try {
588						(multi && type === 'filter' && !(output.filter === 'none' || output.f
588ilter === '')) ?
589								$el.filter(filter).addClass(self.controls.activeClass) :
590								$el.removeClass(self.controls.activeClass).filter(filter).addClass(self.controls.activeClass);
591					} catch(e) {}
592				},
593				type = 'filter',
594				$el = null;
595
596			self._execAction('_updateControls', 0, arguments);
597
598			(command.filter === undf) && (output.filter = self._activeFilter);
599			(command.sort === undf) && (output.sort = self._activeSort);
600			(output.filter === self.selectors.target) && (output.filter = 'all');
601
602			for(var i = 0; i < 2; i++){
603				$el = self.controls.live ? $(self.selectors[type]) : self['_$'+type+'Buttons'];
604				$el && update($el, '[data-'+type+'="'+output[type]+'"]');
605				type = 'sort';
606			}
607
608			self._execAction('_updateControls', 1, arguments);
609		},
610
611		/**
612		 * Filter (private)
613		 * @since 2.0.0
614		 */
615
616		_filter: function(){
617			var self = this;
618
619			self._execAction('_filter', 0);
620
621			for(var i = 0; i < self._$targets.length; i++){
622				var $target = $(self._$targets[i]);
623
624				if($target.is(self._activeFilter)){
625					self._$show = self._$show.add($target);
626				} else {
627					self._$hide = self._$hide.add($target);
628				}
629			}
630
631			self._execAction('_filter', 1);
632		},
633
634		/**
635		 * Sort (private)
636		 * @since 2.0.0
637		 */
638
639		_sort: function(){
640			var self = this,
641				arrayShuffle = function(oldArray){
642					var newArray = oldArray.slice(),
643						len = newArray.length,
644						i = len;
645
646					while(i--){
647						var p = parseInt(Math.random()*len);
648						var t = newArray[i];
649						newArray[i] = newArray[p];
650						newArray[p] = t;
651					};
652					return newArray;
653				};
654
655			self._execAction('_sort', 0);
656
657			self._startOrder = [];
658
659			for(var i = 0; i < self._$targets.length; i++){
660				var target = self._$targets[i];
661
662				self._startOrder.push(target);
663			}
664
665			switch(self._newSort[0].sortBy){
666				case 'default':
667					self._newOrder = self._origOrder;
668					break;
669				case 'random':
670					self._newOrder = arrayShuffle(self._startOrder);
671					break;
672				case 'custom':
673					self._newOrder = self._newSort[0].order;
674					break;
675				default:
676					self._newOrder = self._startOrder.concat().sort(function(a, b){
677						return self._compare(a, b);
678					});
679			}
680
681			self._execAction('_sort', 1);
682		},
683
684		/**
685		 * Compare Algorithm
686		 * @since 2.0.0
687		 * @param {string|number} a
688		 * @param {string|number} b
689		 * @param {number} depth (recursion)
690		 * @return {number}
691		 */
692
693		_compare: function(a, b, depth){
694			depth = depth ? depth : 0;
695
696			var self = this,
697				order = self._newSort[depth].order,
698				getData = function(el){
699					return el.dataset[self._newSort[depth].sortBy] || 0;
700				},
701				attrA = isNaN(getData(a) * 1) ? getData(a).toLowerCase() : getData(a) * 1,
702				attrB = isNaN(getData(b) * 1) ? getData(b).toLowerCase() : getData(b) * 1;
703
704			if(attrA < attrB)
705				return order === 'asc' ? -1 : 1;
706			if(attrA > attrB)
707				return order === 'asc' ? 1 : -1;
708			if(attrA === attrB && self._newSort.length > depth+1)
709				return self._compare(a, b, depth+1);
710
711			return 0;
712		},
713
714		/**
715		 * Print Sort
716		 * @since 2.0.0
717		 * @param {boolean} reset
718		 */
719
720		_printSort: function(reset){
721			var self = this,
722				order = reset ? self._startOrder : self._newOrder,
723				targets = self._$parent[0].querySelectorAll(self.selectors.target),
724				nextSibling = targets.length ? targets[targets.length -1].nextElementSibling : null,
725				frag = document.createDocumentFragment();
726
727			self._execAction('_printSort', 0, arguments);
728
729			for(var i = 0; i < targets.length; i++){
730				var target = targets[i],
731					whiteSpace = target.nextSibling;
732
733				if(target.style.position === 'absolute') continue;
734
735				if(whiteSpace && whiteSpace.nodeName === '#text'){
736					self._$parent[0].removeChild(whiteSpace);
737				}
738
739				self._$parent[0].removeChild(target);
740			}
741
742			for(var i = 0; i < order.length; i++){
743				var el = order[i];
744
745				if(self._newSort[0].sortBy === 'default' && self._newSort[0].order === 'desc' && !reset){
746					var firstChild = frag.firstChild;
747					frag.insertBefore(el, firstChild);
748					frag.insertBefore(document.createTextNode(' '), el);
749				} else {
750					frag.appendChild(el);
751					frag.appendChild(document.createTextNode(' '));
752				}
753			}
754
755			nextSibling ?
756				self._$parent[0].insertBefore(frag, nextSibling) :
757				self._$parent[0].appendChild(frag);
758
759			self._execAction('_printSort', 1, arguments);
760		},
761
762		/**
763		 * Parse Sort
764		 * @since 2.0.0
765		 * @param {string} sortString
766		 * @return {array} newSort
767		 */
768
769		_parseSort: function(sortString){
770			var self = this,
771				rules = typeof sortString === 'string' ? sortString.split(' ') : [sortString],
772				newSort = [];
773
774			for(var i = 0; i < rules.length; i++){
775				var rule = typeof sortString === 'string' ? rules[i].split(':') : ['custom', rules[i]],
776					ruleObj = {
777						sortBy: self._helpers._camelCase(rule[0]),
778						order: rule[1] || 'asc'
779					};
780
781				newSort.push(ruleObj);
782
783				if(ruleObj.sortBy === 'default' || ruleObj.sortBy === 'random') break;
784			}
785
786			return self._execFilter('_parseSort', newSort, arguments);
787		},
788
789		/**
790		 * Parse Effects
791		 * @since 2.0.0
792		 * @return {object} effects
793		 */
794
795		_parseEffects: function(){
796			var self = this,
797				effects = {
798					opacity: '',
799					transformIn: '',
800					transformOut: '',
801					filter: ''
802				},
803				parse = function(effect, extract, reverse){
804					if(self.animation.effects.indexOf(effect) > -1){
805						if(extract){
806							var propIndex = self.animation.effects.indexOf(effect+'(');
807							if(propIndex > -1){
808								var str = self.animation.effects.substring(propIndex),
809									match = /\(([^)]+)\)/.exec(str),
810									val = match[1];
811
812									return {val: val};
813							}
814						}
815						return true;
816					} else {
817						return false;
818					}
819				},
820				negate = function(value, invert){
821					if(invert){
822						return value.charAt(0) === '-' ? value.substr(1, value.length) : '-'+value;
823					} else {
824						return value;
825					}
826				},
827				buildTransform = function(key, invert){
828					var transforms = [
829						['scale', '.01'],
830						['translateX', '20px'],
831						['translateY', '20px'],
832						['translateZ', '20px'],
833						['rotateX', '90deg'],
834						['rotateY', '90deg'],
835						['rotateZ', '180deg'],
836					];
837
838					for(var i = 0; i < transforms.length; i++){
839						var prop = transforms[i][0],
840							def = transforms[i][1],
841							inverted = invert && prop !== 'scale';
842
843						effects[key] += parse(prop) ? prop+'('+negate(parse(prop, true).val || def, inverted)+') ' : '';
844					}
845				};
846
847			effects.opacity = parse('fade') ? parse('fade',true).val || '0' : '1';
848
849			buildTransform('transformIn');
850
851			self.animation.reverseOut ? buildTransform('transformOut', true) : (effects.transformOut = effects.transformIn);
852
853			effects.transition = {};
854
855			effects.transition = self._getPrefixedCSS('transition','all '+self.animation.duration+'ms '+self.animation.easing+', opacity '+self.animation.duration+'ms linear');
856
857			self.animation.stagger = parse('stagger') ? true : false;
858			self.animation.staggerDuration = parseInt(parse('stagger') ? (parse('stagger',true).val ? parse('stagger',true).val : 100) : 100);
859
860			return self._execFilter('_parseEffects', effects);
861		},
862
863		/**
864		 * Build State
865		 * @since 2.0.0
866		 * @param {boolean} future
867		 * @return {object} futureState
868		 */
869
870		_buildState: function(future){
871			var self = this,
872				state = {};
873
874			self._execAction('_buildState', 0);
875
876			state = {
877				activeFilter: self._activeFilter === '' ? 'none' : self._activeFilter,
878				activeSort: future && self._newSortString ? self._newSortString : self._activeSort,
879				fail: !self._$show.length && self._activeFilter !== '',
880				$targets: self._$targets,
881				$show: self._$show,
882				$hide: self._$hide,
883				totalTargets: self._$targets.length,
884				totalShow: self._$show.length,
885				totalHide: self._$hide.length,
886				display: future && self._newDisplay ? self._newDisplay : self.layout.display
887			};
888
889			if(future){
890				return self._execFilter('_buildState', state);
891			} else {
892				self._state = state;
893
894				self._execAction('_buildState', 1);
895			}
896		},
897
898		/**
899		 * Go Mix
900		 * @since 2.0.0
901		 * @param {boolean} animate
902		 */
903
904		_goMix: function(animate){
905			var self = this,
906				phase1 = function(){
907					if(self._chrome && (self._chrome === 31)){
908						chromeFix(self._$parent[0]);
909					}
910
911					self._setInter();
912
913					phase2();
914				},
915				phase2 = function(){
916					var scrollTop = window.pageYOffset,
917						scrollLeft = window.pageXOffset,
918						docHeight = document.documentElement.scrollHeight;
919
920					self._getInterMixData();
921
922					self._setFinal();
923
924					self._getFinalMixData();
925
926					(window.pageYOffset !== scrollTop) && window.scrollTo(scrollLeft, scrollTop);
927
928					self._prepTargets();
929
930					if(window.requestAnimationFrame){
931						requestAnimationFrame(phase3);
932					} else {
933						setTimeout(function(){
934							phase3();
935						},20);
936					}
937				},
938				phase3 = function(){
939					self._animateTargets();
940
941					if(self._targetsBound === 0){
942						self._cleanUp();
943					}
944				},
945				chromeFix = function(grid){
946					var parent = grid.parentElement,
947						placeholder = document.createElement('div'),
948						frag = document.createDocumentFragment();
949
950					parent.insertBefore(placeholder, grid);
951					frag.appendChild(grid);
952					parent.replaceChild(grid, placeholder);
953				},
954				futureState = self._buildState(true);
955
956			self._execAction('_goMix', 0, arguments);
957
958			!self.animation.duration && (animate = false);
959
960			self._mixing = true;
961
962			self._$container.removeClass(self.layout.containerClassFail);
963
964			if(typeof self.callbacks.onMixStart === 'function'){
965				self.callbacks.onMixStart.call(self._domNode, self._state, futureState, self);
966			}
967
968			self._$container.trigger('mixStart', [self._state, futureState, self]);
969
970			self._getOrigMixData();
971
972			if(animate && !self._suckMode){
973
974				window.requestAnimationFrame ?
975					requestAnimationFrame(phase1) :
976					phase1();
977
978			} else {
979				self._cleanUp();
980			}
981
982			self._execAction('_goMix', 1, arguments);
983		},
984
985		/**
986		 * Get Target Data
987		 * @since 2.0.0
988		 */
989
990		_getTargetData: function(el, stage){
991			var self = this,
992				elStyle;
993
994			el.dataset[stage+'PosX'] = el.offsetLeft;
995			el.dataset[stage+'PosY'] = el.offsetTop;
996
997			if(self.animation.animateResizeTargets){
998				elStyle = !self._suckMode ?
999					window.getComputedStyle(el) :
1000					{
1001						marginBottom: '',
1002						marginRight: ''
1003					};
1004
1005				el.dataset[stage+'MarginBottom'] = parseInt(elStyle.marginBottom);
1006				el.dataset[stage+'MarginRight'] = parseInt(elStyle.marginRight);
1007				el.dataset[stage+'Width'] = el.offsetWidth;
1008				el.dataset[stage+'Height'] = el.offsetHeight;
1009			}
1010		},
1011
1012		/**
1013		 * Get Original Mix Data
1014		 * @since 2.0.0
1015		 */
1016
1017		_getOrigMixData: function(){
1018			var self = this,
1019				parentStyle = !self._suckMode ? window.getComputedStyle(self._$parent[0]) : {boxSizing: ''},
1020				parentBS = parentStyle.boxSizing || parentStyle[self._vendor+'BoxSizing'];
1021
1022			self._incPadding = (parentBS === 'border-box');
1023
1024			self._execAction('_getOrigMixData', 0);
1025
1026			!self._suckMode && (self.effects = self._parseEffects());
1027
1028			self._$toHide = self._$hide.filter(':visible');
1029			self._$toShow = self._$show.filter(':hidden');
1030			self._$pre = self._$targets.filter(':visible');
1031
1032			self._startHeight = self._incPadding ?
1033				self._$parent.outerHeight() :
1034				self._$parent.height();
1035
1036			for(var i = 0; i < self._$pre.length; i++){
1037				var el = self._$pre[i];
1038
1039				self._getTargetData(el, 'orig');
1040			}
1041
1042			self._execAction('_getOrigMixData', 1);
1043		},
1044
1045		/**
1046		 * Set Intermediate Positions
1047		 * @since 2.0.0
1048		 */
1049
1050		_setInter: function(){
1051			var self = this;
1052
1053			self._execAction('_setInter', 0);
1054
1055			if(self._changingLayout && self.animation.animateChangeLayout){
1056				self._$toShow.css('display',self._newDisplay);
1057
1058				if(self._changingClass){
1059					self._$container
1060						.removeClass(self.layout.containerClass)
1061						.addClass(self._newClass);
1062				}
1063			} else {
1064				self._$toShow.css('display', self.layout.display);
1065			}
1066
1067			self._execAction('_setInter', 1);
1068		},
1069
1070		/**
1071		 * Get Intermediate Mix Data
1072		 * @since 2.0.0
1073		 */
1074
1075		_getInterMixData: function(){
1076			var self = this;
1077
1078			self._execAction('_getInterMixData', 0);
1079
1080			for(var i = 0; i < self._$toShow.length; i++){
1081				var el = self._$toShow[i];
1082
1083				self._getTargetData(el, 'inter');
1084			}
1085
1086			for(var i = 0; i < self._$pre.length; i++){
1087				var el = self._$pre[i];
1088
1089				self._getTargetData(el, 'inter');
1090			}
1091
1092			self._execAction('_getInterMixData', 1);
1093		},
1094
1095		/**
1096		 * Set Final Positions
1097		 * @since 2.0.0
1098		 */
1099
1100		_setFinal: function(){
1101			var self = this;
1102
1103			self._execAction('_setFinal', 0);
1104
1105			self._sorting && self._printSort();
1106
1107			self._$toHide.removeStyle('display');
1108
1109			if(self._changingLayout && self.animation.animateChangeLayout){
1110				self._$pre.css('display',self._newDisplay);
1111			}
1112
1113			self._execAction('_setFinal', 1);
1114		},
1115
1116		/**
1117		 * Get Final Mix Data
1118		 * @since 2.0.0
1119		 */
1120
1121		_getFinalMixData: function(){
1122			var self = this;
1123
1124			self._execAction('_getFinalMixData', 0);
1125
1126			for(var i = 0; i < self._$toShow.length; i++){
1127				var el = self._$toShow[i];
1128
1129				self._getTargetData(el, 'final');
1130			}
1131
1132			for(var i = 0; i < self._$pre.length; i++){
1133				var el = self._$pre[i];
1134
1135				self._getTargetData(el, 'final');
1136			}
1137
1138			self._newHeight = self._incPadding ?
1139				self._$parent.outerHeight() :
1140				self._$parent.height();
1141
1142			self._sorting && self._printSort(true);
1143
1144			self._$toShow.removeStyle('display');
1145
1146			self._$pre.css('display',self.layout.display);
1147
1148			if(self._changingClass && self.animation.animateChangeLayout){
1149				self._$container
1150					.removeClass(self._newClass)
1151					.addClass(self.layout.containerClass);
1152			}
1153
1154			self._execAction('_getFinalMixData', 1);
1155		},
1156
1157		/**
1158		 * Prepare Targets
1159		 * @since 2.0.0
1160		 */
1161
1162		_prepTargets: function(){
1163			var self = this,
1164				transformCSS = {
1165					_in: self._getPrefixedCSS('transform', self.effects.transformIn),
1166					_out: self._getPrefixedCSS('transform', self.effects.transformOut)
1167				};
1168
1169			self._execAction('_prepTargets', 0);
1170
1171			if(self.animation.animateResizeContainer){
1172				self._$parent.css('height',self._startHeight+'px');
1173			}
1174
1175			for(var i = 0; i < self._$toShow.length; i++){
1176				var el = self._$toShow[i],
1177					$el = $(el);
1178
1179				el.style.opacity = self.effects.opacity;
1180				el.style.display = (self._changingLayout && self.animation.animateChangeLayout) ?
1181					self._newDisplay :
1182					self.layout.display;
1183
1184				$el.css(transformCSS._in);
1185
1186				if(self.animation.animateResizeTargets){
1187					el.style.width = el.dataset.finalWidth+'px';
1188					el.style.height = el.dataset.finalHeight+'px';
1189					el.style.marginRight = -(el.dataset.finalWidth - el.dataset.interWidth) + (el.dataset.finalMarginRight * 1)+'px';
1190					el.style.marginBottom = -(el.dataset.finalHeight - el.dataset.interHeight) + (el.dataset.finalMarginBottom * 1)+'px';
1191				}
1192			}
1193
1194			for(var i = 0; i < self._$pre.length; i++){
1195				var el = self._$pre[i],
1196					$el = $(el),
1197					translate = {
1198						x: el.dataset.origPosX - el.dataset.interPosX,
1199						y: el.dataset.origPosY - el.dataset.interPosY
1200					},
1201					transformCSS = self._getPrefixedCSS('transform','translate('+translate.x+'px,'+translate.y+'px)');
1202
1203				$el.css(transformCSS);
1204
1205				if(self.animation.animateResizeTargets){
1206					el.style.width = el.dataset.origWidth+'px';
1207					el.style.height = el.dataset.origHeight+'px';
1208
1209					if(el.dataset.origWidth - el.dataset.finalWidth){
1210						el.style.marginRight = -(el.dataset.origWidth - el.dataset.interWidth) + (el.dataset.origMarginRight * 1)+'px';
1211					}
1212
1213					if(el.dataset.origHeight - el.dataset.finalHeight){
1214						el.style.marginBottom = -(el.dataset.origHeight - el.dataset.interHeight) + (el.dataset.origMarginBottom * 1) +'px';
1215					}
1216				}
1217			}
1218
1219			self._execAction('_prepTargets', 1);
1220		},
1221
1222		/**
1223		 * Animate Targets
1224		 * @since 2.0.0
1225		 */
1226
1227		_animateTargets: function(){
1228			var self = this;
1229
1230			self._execAction('_animateTargets', 0);
1231
1232			self._targetsDone = 0;
1233			self._targetsBound = 0;
1234
1235			self._$parent
1236				.css(self._getPrefixedCSS('perspective', self.animation.perspectiveDistance+'px'))
1237				.css(self._getPrefixedCSS('perspective-origin', self.animation.perspectiveOrigin));
1238
1239			if(self.animation.animateResizeContainer){
1240				self._$parent
1241					.css(self._getPrefixedCSS('transition','height '+self.animation.duration+'ms ease'))
1242					.css('height',self._newHeight+'px');
1243			}
1244
1245			for(var i = 0; i < self._$toShow.length; i++){
1246				var el = self._$toShow[i],
1247					$el = $(el),
1248					translate = {
1249						x: el.dataset.finalPosX - el.dataset.interPosX,
1250						y: el.dataset.finalPosY - el.dataset.interPosY
1251					},
1252					delay = self._getDelay(i),
1253					toShowCSS = {};
1254
1255				el.style.opacity = '';
1256
1257				for(var j = 0; j < 2; j++){
1258					var a = j === 0 ? a = self._prefix : '';
1259
1260					if(self._ff && self._ff <= 20){
1261						toShowCSS[a+'transition-property'] = 'all';
1262						toShowCSS[a+'transition-timing-function'] = self.animation.easing+'ms';
1263						toShowCSS[a+'transition-duration'] = self.animation.duration+'ms';
1264					}
1265
1266					toShowCSS[a+'transition-delay'] = delay+'ms';
1267					toShowCSS[a+'transform'] = 'translate('+translate.x+'px,'+translate.y+'px)';
1268				}
1269
1270				if(self.effects.transform || self.effects.opacity){
1271					self._bindTargetDone($el);
1272				}
1273
1274				(self._ff && self._ff <= 20) ?
1275					$el.css(toShowCSS) :
1276					$el.css(self.effects.transition).css(toShowCSS);
1277			}
1278
1279			for(var i = 0; i < self._$pre.length; i++){
1280				var el = self._$pre[i],
1281					$el = $(el),
1282					translate = {
1283						x: el.dataset.finalPosX - el.dataset.interPosX,
1284						y: el.dataset.finalPosY - el.dataset.interPosY
1285					},
1286					delay = self._getDelay(i);
1287
1288				if(!(
1289					el.dataset.finalPosX === el.dataset.origPosX &&
1290					el.dataset.finalPosY === el.dataset.origPosY
1291				)){
1292					self._bindTargetDone($el);
1293				}
1294
1295				$el.css(self._getPrefixedCSS('transition', 'all '+self.animation.duration+'ms '+self.animation.easing+' '+delay+'ms'));
1296				$el.css(self._getPrefixedCSS('transform', 'translate('+translate.x+'px,'+translate.y+'px)'));
1297
1298				if(self.animation.animateResizeTargets){
1299					if(el.dataset.origWidth - el.dataset.finalWidth && el.dataset.finalWidth * 1){
1300						el.style.width = el.dataset.finalWidth+'px';
1301						el.style.marginRight = -(el.dataset.finalWidth - el.dataset.interWidth)+(el.dataset.finalMarginRight * 1)+'px';
1302					}
1303
1304					if(el.dataset.origHeight - el.dataset.finalHeight && el.dataset.finalHeight * 1){
1305						el.style.height = el.dataset.finalHeight+'px';
1306						el.style.marginBottom = -(el.dataset.finalHeight - el.dataset.interHeight)+(el.dataset.finalMarginBottom * 1) +'px';
1307					}
1308				}
1309			}
1310
1311			if(self._changingClass){
1312				self._$container
1313					.removeClass(self.layout.containerClass)
1314					.addClass(self._newClass);
1315			}
1316
1317			for(var i = 0; i < self._$toHide.length; i++){
1318				var el = self._$toHide[i],
1319					$el = $(el),
1320					delay = self._getDelay(i),
1321					toHideCSS = {};
1322
1323				for(var j = 0; j<2; j++){
1324					var a = j === 0 ? a = self._prefix : '';
1325
1326					toHideCSS[a+'transition-delay'] = delay+'ms';
1327					toHideCSS[a+'transform'] = self.effects.transformOut;
1328					toHideCSS.opacity = self.effects.opacity;
1329				}
1330
1331				$el.css(self.effects.transition).css(toHideCSS);
1332
1333				if(self.effects.transform || self.effects.opacity){
1334					self._bindTargetDone($el);
1335				};
1336			}
1337
1338			self._execAction('_animateTargets', 1);
1339
1340		},
1341
1342		/**
1343		 * Bind Targets TransitionEnd
1344		 * @since 2.0.0
1345		 * @param {object} $el
1346		 */
1347
1348		_bindTargetDone: function($el){
1349			var self = this,
1350				el = $el[0];
1351
1352			self._execAction('_bindTargetDone', 0, arguments);
1353
1354			if(!el.dataset.bound){
1355
1356				el.dataset.bound = true;
1357				self._targetsBound++;
1358
1359				$el.on('webkitTransitionEnd.mixItUp transitionend.mixItUp',function(e){
1360					if(
1361						(e.originalEvent.propertyName.indexOf('transform') > -1 ||
1362						e.originalEvent.propertyName.indexOf('opacity') > -1) &&
1363						$(e.originalEvent.target).is(self.selectors.target)
1364					){
1365						$el.off('.mixItUp');
1366						el.dataset.bound = '';
1367						self._targetDone();
1368					}
1369				});
1370			}
1371
1372			self._execAction('_bindTargetDone', 1, arguments);
1373		},
1374
1375		/**
1376		 * Target Done
1377		 * @since 2.0.0
1378		 */
1379
1380		_targetDone: function(){
1381			var self = this;
1382
1383			self._execAction('_targetDone', 0);
1384
1385			self._targetsDone++;
1386
1387			(self._targetsDone === self._targetsBound) && self._cleanUp();
1388
1389			self._execAction('_targetDone', 1);
1390		},
1391
1392		/**
1393		 * Clean Up
1394		 * @since 2.0.0
1395		 */
1396
1397		_cleanUp: function(){
1398			var self = this,
1399				targetStyles = self.animation.animateResizeTargets ?
1400					'transform opacity width height margin-bottom margin-right' :
1401					'transform opacity',
1402				unBrake = function(){
1403					self._$targets.removeStyle('transition', self._prefix);
1404				};
1405
1406			self._execAction('_cleanUp', 0);
1407
1408			!self._changingLayout ?
1409				self._$show.css('display',self.layout.display) :
1410				self._$show.css('display',self._newDisplay);
1411
1412			self._$targets.css(self._brake);
1413
1414			self._$targets
1415				.removeStyle(targetStyles, self._prefix)
1416				.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');
1417
1418			self._$hide.removeStyle('display');
1419
1420			self._$parent.removeStyle('height transition perspective-distance perspective perspective-origin-x perspective-origin-y perspective-origin perspectiveOrigin', self._prefix);
1421
1422			if(self._sorting){
1423				self._printSort();
1424				self._activeSort = self._newSortString;
1425				self._sorting = false;
1426			}
1427
1428			if(self._changingLayout){
1429				if(self._changingDisplay){
1430					self.layout.display = self._newDisplay;
1431					self._changingDisplay = false;
1432				}
1433
1434				if(self._changingClass){
1435					self._$parent.removeClass(self.layout.containerClass).addClass(self._newClass);
1436					self.layout.containerClass = self._newClass;
1437					self._changingClass = false;
1438				}
1439
1440				self._changingLayout = false;
1441			}
1442
1443			self._refresh();
1444
1445			self._buildState();
1446
1447			if(self._state.fail){
1448				self._$container.addClass(self.layout.containerClassFail);
1449			}
1450
1451			self._$show = $();
1452			self._$hide = $();
1453
1454			if(window.requestAnimationFrame){
1455				requestAnimationFrame(unBrake);
1456			}
1457
1458			self._mixing = false;
1459
1460			if(typeof self.callbacks._user === 'function'){
1461				self.callbacks._user.call(self._domNode, self._state, self);
1462			}
1463
1464			if(typeof self.callbacks.onMixEnd === 'function'){
1465				self.callbacks.onMixEnd.call(self._domNode, self._state, self);
1466			}
1467
1468			self._$container.trigger('mixEnd', [self._state, self]);
1469
1470			if(self._state.fail){
1471				(typeof self.callbacks.onMixFail === 'function') && self.callbacks.onMixFail.call(self._domNode, self._state, self);
1472				self._$container.trigger('mixFail', [self._state, self]);
1473			}
1474
1475			if(self._loading){
1476				(typeof self.callbacks.onMixLoad === 'function') && self.callbacks.onMixLoad.call(self._domNode, self._state, self);
1477				self._$container.trigger('mixLoad', [self._state, self]);
1478			}
1479
1480			if(self._queue.length){
1481				self._execAction('_queue', 0);
1482
1483				self.multiMix(self._queue[0][0],self._queue[0][1],self._queue[0][2]);
1484				self._queue.splice(0, 1);
1485			}
1486
1487			self._execAction('_cleanUp', 1);
1488
1489			self._loading = false;
1490		},
1491
1492		/**
1493		 * Get Prefixed CSS
1494		 * @since 2.0.0
1495		 * @param {string} property
1496		 * @param {string} value
1497		 * @param {boolean} prefixValue
1498		 * @return {object} styles
1499		 */
1500
1501		_getPrefixedCSS: function(property, value, prefixValue){
1502			var self = this,
1503				styles = {},
1504				prefix = '',
1505				i = -1;
1506
1507			for(i = 0; i < 2; i++){
1508				prefix = i === 0 ? self._prefix : '';
1509				prefixValue ? styles[prefix+property] = prefix+value : styles[prefix+property] = value;
1510			}
1511
1512			return self._execFilter('_getPrefixedCSS', styles, arguments);
1513		},
1514
1515		/**
1516		 * Get Delay
1517		 * @since 2.0.0
1518		 * @param {number} i
1519		 * @return {number} delay
1520		 */
1521
1522		_getDelay: function(i){
1523			var self = this,
1524				n = typeof self.animation.staggerSequence === 'function' ? self.animation.staggerSequence.call(self._domNode, i, self._state) : i,
1525				delay = self.animation.stagger ? n * self.animation.staggerDuration : 0;
1526
1527			return self._execFilter('_getDelay', delay, arguments);
1528		},
1529
1530		/**
1531		 * Parse MultiMix Arguments
1532		 * @since 2.0.0
1533		 * @param {array} args
1534		 * @return {object} output
1535		 */
1536
1537		_parseMultiMixArgs: function(args){
1538			var self = this,
1539				output = {
1540					command: null,
1541					animate: self.animation.enable,
1542					callback: null
1543				};
1544
1545			for(var i = 0; i < args.length; i++){
1546				var arg = args[i];
1547
1548				if(arg !== null){
1549					if(typeof arg === 'object' || typeof arg === 'string'){
1550						output.command = arg;
1551					} else if(typeof arg === 'boolean'){
1552						output.animate = arg;
1553					} else if(typeof arg === 'function'){
1554						output.callback = arg;
1555					}
1556				}
1557			}
1558
1559			return self._execFilter('_parseMultiMixArgs', output, arguments);
1560		},
1561
1562		/**
1563		 * Parse Insert Arguments
1564		 * @since 2.0.0
1565		 * @param {array} args
1566		 * @return {object} output
1567		 */
1568
1569		_parseInsertArgs: function(args){
1570			var self = this,
1571				output = {
1572					index: 0,
1573					$object: $(),
1574					multiMix: {filter: self._state.activeFilter},
1575					callback: null
1576				};
1577
1578			for(var i = 0; i < args.length; i++){
1579				var arg = args[i];
1580
1581				if(typeof arg === 'number'){
1582					output.index = arg;
1583				} else if(typeof arg === 'object' && arg instanceof $){
1584					output.$object = arg;
1585				} else if(typeof arg === 'object' && self._helpers._isElement(arg)){
1586					output.$object = $(arg);
1587				} else if(typeof arg === 'object' && arg !== null){
1588					output.multiMix = arg;
1589				} else if(typeof arg === 'boolean' && !arg){
1590					output.multiMix = false;
1591				} else if(typeof arg === 'function'){
1592					output.callback = arg;
1593				}
1594			}
1595
1596			return self._execFilter('_parseInsertArgs', output, arguments);
1597		},
1598
1599		/**
1600		 * Execute Action
1601		 * @since 2.0.0
1602		 * @param {string} methodName
1603		 * @param {boolean} isPost
1604		 * @param {array} args
1605		 */
1606
1607		_execAction: function(methodName, isPost, args){
1608			var self = this,
1609				context = isPost ? 'post' : 'pre';
1610
1611			if(!self._actions.isEmptyObject && self._actions.hasOwnProperty(methodName)){
1612				for(var key in self._actions[methodName][context]){
1613					self._actions[methodName][context][key].call(self, args);
1614				}
1615			}
1616		},
1617
1618		/**
1619		 * Execute Filter
1620		 * @since 2.0.0
1621		 * @param {string} methodName
1622		 * @param {mixed} value
1623		 * @return {mixed} value
1624		 */
1625
1626		_execFilter: function(methodName, value, args){
1627			var self = this;
1628
1629			if(!self._filters.isEmptyObject && self._filters.hasOwnProperty(methodName)){
1630				for(var key in self._filters[methodName]){
1631					return self._filters[methodName][key].call(self, args);
1632				}
1633			} else {
1634				return value;
1635			}
1636		},
1637
1638		/* Helpers
1639		---------------------------------------------------------------------- */
1640
1641		_helpers: {
1642
1643			/**
1644			 * CamelCase
1645			 * @since 2.0.0
1646			 * @param {string}
1647			 * @return {string}
1648			 */
1649
1650			_camelCase: function(string){
1651				return string.replace(/-([a-z])/g, function(g){
1652						return g[1].toUpperCase();
1653				});
1654			},
1655
1656			/**
1657			 * Is Element
1658			 * @since 2.1.3
1659			 * @param {object} element to test
1660			 * @return {boolean}
1661			 */
1662
1663			_isElement: function(el){
1664				if(window.HTMLElement){
1665					return el instanceof HTMLElement;
1666				} else {
1667					return (
1668						el !== null &&
1669						el.nodeType === 1 &&
1670						el.nodeName === 'string'
1671					);
1672				}
1673			}
1674		},
1675
1676		/* Public Methods
1677		---------------------------------------------------------------------- */
1678
1679		/**
1680		 * Is Mixing
1681		 * @since 2.0.0
1682		 * @return {boolean}
1683		 */
1684
1685		isMixing: function(){
1686			var self = this;
1687
1688			return self._execFilter('isMixing', self._mixing);
1689		},
1690
1691		/**
1692		 * Filter (public)
1693		 * @since 2.0.0
1694		 * @param {array} arguments
1695		 */
1696
1697		filter: function(){
1698			var self = this,
1699				args = self._parseMultiMixArgs(arguments);
1700
1701			self._clicking && (self._toggleString = '');
1702
1703			self.multiMix({filter: args.command}, args.animate, args.callback);
1704		},
1705
1706		/**
1707		 * Sort (public)
1708		 * @since 2.0.0
1709		 * @param {array} arguments
1710		 */
1711
1712		sort: function(){
1713			var self = this,
1714				args = self._parseMultiMixArgs(arguments);
1715
1716			self.multiMix({sort: args.command}, args.animate, args.callback);
1717		},
1718
1719		/**
1720		 * Change Layout (public)
1721		 * @since 2.0.0
1722		 * @param {array} arguments
1723		 */
1724
1725		changeLayout: function(){
1726			var self = this,
1727				args = self._parseMultiMixArgs(arguments);
1728
1729			self.multiMix({changeLayout: args.command}, args.animate, args.callback);
1730		},
1731
1732		/**
1733		 * MultiMix
1734		 * @since 2.0.0
1735		 * @param {array} arguments
1736		 */
1737
1738		multiMix: function(){
1739			var self = this,
1740				args = self._parseMultiMixArgs(arguments);
1741
1742			self._execAction('multiMix', 0, arguments);
1743
1744			if(!self._mixing){
1745				if(self.controls.enable && !self._clicking){
1746					self.controls.toggleFilterButtons && self._buildToggleArray();
1747					self._updateControls(args.command, self.controls.toggleFilterButtons);
1748				}
1749
1750				(self._queue.length < 2) && (self._clicking = false);
1751
1752				delete self.callbacks._user;
1753				if(args.callback) self.callbacks._user = args.callback;
1754
1755				var sort = args.command.sort,
1756					filter = args.command.filter,
1757					changeLayout = args.command.changeLayout;
1758
1759				self._refresh();
1760
1761				if(sort){
1762					self._newSort = self._parseSort(sort);
1763					self._newSortString = sort;
1764
1765					self._sorting = true;
1766					self._sort();
1767				}
1768
1769				if(filter !== undf){
1770					filter = (filter === 'all') ? self.selectors.target : filter;
1771
1772					self._activeFilter = filter;
1773				}
1774
1775				self._filter();
1776
1777				if(changeLayout){
1778					self._newDisplay = (typeof changeLayout === 'string') ? changeLayout : changeLayout.display || self.layout.display;
1779					self._newClass = changeLayout.containerClass || '';
1780
1781					if(
1782						self._newDisplay !== self.layout.display ||
1783						self._newClass !== self.layout.containerClass
1784					){
1785						self._changingLayout = true;
1786
1787						self._changingClass = (self._newClass !== self.layout.containerClass);
1788						self._changingDisplay = (self._newDisplay !== self.layout.display);
1789					}
1790				}
1791
1792				self._$targets.css(self._brake);
1793
1794				self._goMix(args.animate ^ self.animation.enable ? args.animate : self.animation.enable);
1795
1796				self._execAction('multiMix', 1, arguments);
1797
1798			} else {
1799				if(self.animation.queue && self._queue.length < self.animation.queueLimit){
1800					self._queue.push(arguments);
1801
1802					(self.controls.enable && !self._clicking) && self._updateControls(args.command);
1803
1804					self._execAction('multiMixQueue', 1, arguments);
1805
1806				} else {
1807					if(typeof self.callbacks.onMixBusy === 'function'){
1808						self.callbacks.onMixBusy.call(self._domNode, self._state, self);
1809					}
1810					self._$container.trigger('mixBusy', [self._state, self]);
1811
1812					self._execAction('multiMixBusy', 1, arguments);
1813				}
1814			}
1815		},
1816
1817		/**
1818		 * Insert
1819		 * @since 2.0.0
1820		 * @param {array} arguments
1821		 */
1822
1823		insert: function(){
1824			var self = this,
1825				args = self._parseInsertArgs(arguments),
1826				callback = (typeof args.callback === 'function') ? args.callback : null,
1827				frag = document.createDocumentFragment(),
1828				target = (function(){
1829					self._refresh();
1830
1831					if(self._$targets.length){
1832						return (args.index < self._$targets.length || !self._$targets.length) ?
1833							self._$targets[args.index] :
1834							self._$targets[self._$targets.length-1].nextElementSibling;
1835					} else {
1836						return self._$parent[0].children[0];
1837					}
1838				})();
1839
1840			self._execAction('insert', 0, arguments);
1841
1842			if(args.$object){
1843				for(var i = 0; i < args.$object.length; i++){
1844					var el = args.$object[i];
1845
1846					frag.appendChild(el);
1847					frag.appendChild(document.createTextNode(' '));
1848				}
1849
1850				self._$parent[0].insertBefore(frag, target);
1851			}
1852
1853			self._execAction('insert', 1, arguments);
1854
1855			if(typeof args.multiMix === 'object'){
1856				self.multiMix(args.multiMix, callback);
1857			}
1858		},
1859
1860		/**
1861		 * Prepend
1862		 * @since 2.0.0
1863		 * @param {array} arguments
1864		 */
1865
1866		prepend: function(){
1867			var self = this,
1868				args = self._parseInsertArgs(arguments);
1869
1870			self.insert(0, args.$object, args.multiMix, args.callback);
1871		},
1872
1873		/**
1874		 * Append
1875		 * @since 2.0.0
1876		 * @param {array} arguments
1877		 */
1878
1879		append: function(){
1880			var self = this,
1881				args = self._parseInsertArgs(arguments);
1882
1883			self.insert(self._state.totalTargets, args.$object, args.multiMix, args.callback);
1884		},
1885
1886		/**
1887		 * Get Option
1888		 * @since 2.0.0
1889		 * @param {string} string
1890		 * @return {mixed} value
1891		 */
1892
1893		getOption: function(string){
1894			var self = this,
1895				getProperty = function(obj, prop){
1896					var parts = prop.split('.'),
1897						last = parts.pop(),
1898						l = parts.length,
1899						i = 1,
1900						current = parts[0] || prop;
1901
1902					while((obj = obj[current]) && i < l){
1903						current = parts[i];
1904						i++;
1905					}
1906
1907					if(obj !== undf){
1908						return obj[last] !== undf ? obj[last] : obj;
1909					}
1910				};
1911
1912			return string ? self._execFilter('getOption', getProperty(self, string), arguments) : self;
1913		},
1914
1915		/**
1916		 * Set Options
1917		 * @since 2.0.0
1918		 * @param {object} config
1919		 */
1920
1921		setOptions: function(config){
1922			var self = this;
1923
1924			self._execAction('setOptions', 0, arguments);
1925
1926			typeof config === 'object' && $.extend(true, self, config);
1927
1928			self._execAction('setOptions', 1, arguments);
1929		},
1930
1931		/**
1932		 * Get State
1933		 * @since 2.0.0
1934		 * @return {object} state
1935		 */
1936
1937		getState: function(){
1938			var self = this;
1939
1940			return self._execFilter('getState', self._state, self);
1941		},
1942
1943		/**
1944		 * Force Refresh
1945		 * @since 2.1.2
1946		 */
1947
1948		forceRefresh: function(){
1949			var self = this;
1950
1951			self._refresh(false, true);
1952		},
1953
1954		/**
1955		 * Destroy
1956		 * @since 2.0.0
1957		 * @param {boolean} hideAll
1958		 */
1959
1960		destroy: function(hideAll){
1961			var self = this,
1962				filters = $.MixItUp.prototype._bound._filter,
1963				sorts = $.MixItUp.prototype._bound._sort;
1964
1965			self._execAction('destroy', 0, arguments);
1966
1967			self._$body
1968				.add($(self.selectors.sort))
1969				.add($(self.selectors.filter))
1970				.off('.mixItUp');
1971
1972			for(var i = 0; i < self._$targets.length; i++){
1973				var target = self._$targets[i];
1974
1975				hideAll && (target.style.display = '');
1976
1977				delete target.mixParent;
1978			}
1979
1980			self._execAction('destroy', 1, arguments);
1981
1982			if(filters[self.selectors.filter] && filters[self.selectors.filter] > 1) {
1983				filters[self.selectors.filter]--;
1984			} else if(filters[self.selectors.filter] === 1) {
1985				delete filters[self.selectors.filter];
1986			}
1987
1988			if(sorts[self.selectors.sort] && sorts[self.selectors.sort] > 1) {
1989				sorts[self.selectors.sort]--;
1990			} else if(sorts[self.selectors.sort] === 1) {
1991				delete sorts[self.selectors.sort];
1992			}
1993
1994			delete $.MixItUp.prototype._instances[self._id];
1995		}
1996
1997	};
1998
1999	/* jQuery Methods
2000	---------------------------------------------------------------------- */
2001
2002	/**
2003	 * jQuery .mixItUp() method
2004	 * @since 2.0.0
2005	 * @extends $.fn
2006	 */
2007
2008	$.fn.mixItUp = function(){
2009		var args = arguments,
2010			dataReturn = [],
2011			eachReturn,
2012			_instantiate = function(domNode, settings){
2013				var instance = new $.MixItUp(),
2014					rand = function(){
2015						return ('00000'+(Math.random()*16777216<<0).toString(16)).substr(-6).toUpperCase();
2016					};
2017
2018				instance._execAction('_instantiate', 0, arguments);
2019
2020				domNode.id = !domNode.id ? 'MixItUp'+rand() : domNode.id;
2021
2022				if(!instance._instances[domNode.id]){
2023					instance._instances[domNode.id] = instance;
2024					instance._init(domNode, settings);
2025				}
2026
2027				instance._execAction('_instantiate', 1, arguments);
2028			};
2029
2030		eachReturn = this.each(function(){
2031			if(args && typeof args[0] === 'string'){
2032				var instance = $.MixItUp.prototype._instances[this.id];
2033				if(args[0] === 'isLoaded'){
2034					dataReturn.push(instance ? true : false);
2035				} else {
2036					var data = instance[args[0]](args[1], args[2], args[3]);
2037					if(data !== undf)dataReturn.push(data);
2038				}
2039			} else {
2040				_instantiate(this, args[0]);
2041			}
2042		});
2043
2044		if(dataReturn.length){
2045			return dataReturn.length > 1 ? dataReturn : dataReturn[0];
2046		} else {
2047			return eachReturn;
2048		}
2049	};
2050
2051	/**
2052	 * jQuery .removeStyle() method
2053	 * @since 2.0.0
2054	 * @extends $.fn
2055	 */
2056
2057	$.fn.removeStyle = function(style, prefix){
2058		prefix = prefix ? prefix : '';
2059
2060		return this.each(function(){
2061			var el = this,
2062				styles = style.split(' ');
2063
2064			for(var i = 0; i < styles.length; i++){
2065				for(var j = 0; j < 4; j++){
2066					switch (j) {
2067						case 0:
2068							var prop = styles[i];
2069							break;
2070						case 1:
2071							var prop = $.MixItUp.prototype._helpers._camelCase(prop);
2072							break;
2073						case 2:
2074							var prop = prefix+styles[i];
2075							break;
2076						case 3:
2077							var prop = $.MixItUp.prototype._helpers._camelCase(prefix+styles[i]);
2078					}
2079
2080					if(
2081						el.style[prop] !== undf &&
2082						typeof el.style[prop] !== 'unknown' &&
2083						el.style[prop].length > 0
2084					){
2085						el.style[prop] = '';
2086					}
2087
2088					if(!prefix && j === 1)break;
2089				}
2090			}
2091
2092			if(el.attributes && el.attributes.style && el.attributes.style !== undf && el.attributes.style.value === ''){
2093				el.attributes.removeNamedItem('style');
2094			}
2095		});
2096	};
2097
2098})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.