{ "version": 3, "sources": ["../../../../../node_modules/.pnpm/mixitup@3.3.1/node_modules/mixitup/dist/mixitup.js", "../../../../../node_modules/.pnpm/lazysizes@5.3.2/node_modules/lazysizes/lazysizes.js", "../../../../../node_modules/.pnpm/lazysizes@5.3.2/node_modules/lazysizes/plugins/parent-fit/ls.parent-fit.js", "../../../../../node_modules/.pnpm/lazysizes@5.3.2/node_modules/lazysizes/plugins/aspectratio/ls.aspectratio.js", "../../../../../node_modules/.pnpm/lazysizes@5.3.2/node_modules/lazysizes/plugins/native-loading/ls.native-loading.js", "../../../../../node_modules/.pnpm/alpinejs@3.13.1/node_modules/alpinejs/dist/module.esm.js", "../../../../../node_modules/.pnpm/@alpinejs+collapse@3.13.1/node_modules/@alpinejs/collapse/dist/module.esm.js", "../../../../../node_modules/.pnpm/@alpinejs+focus@3.13.1/node_modules/@alpinejs/focus/dist/module.esm.js", "../../../../../node_modules/.pnpm/@alpinejs+intersect@3.13.1/node_modules/@alpinejs/intersect/dist/module.esm.js", "../../../../../node_modules/.pnpm/@alpinejs+persist@3.13.1/node_modules/@alpinejs/persist/dist/module.esm.js", "../../Private/Fusion/Presentation/Universal/Fetch.js", "../../Private/Fusion/Presentation/Universal/index.js", "../../Private/Fusion/Presentation/Block/Newsletter/index.js", "../../Private/Fusion/Presentation/Module/Slider/SwipeEvents.js", "../../Private/Fusion/Presentation/Module/Slider/index.js", "../../Private/Fusion/Presentation/Module/Filter/index.js", "../../../../../Packages/Carbon/Carbon.Image/Resources/Private/Assets/Main.js", "../../../../Schuetz.Projects/Resources/Private/Fusion/Presentation/Module/Teaser/index.js", "../../../../Schuetz.Projects/Resources/Private/Fusion/Presentation/Template/Container/index.js", "../../../../Schuetz.Projects/Resources/Private/Fusion/Presentation/Template/ProjectPage/index.js", "../../Private/Fusion/Main.js"], "sourcesContent": ["/**!\n * MixItUp v3.3.1\n * A high-performance, dependency-free library for animated filtering, sorting and more\n * Build 94e0fbf6-cd0b-4987-b3c0-14b59b67b8a0\n *\n * @copyright Copyright 2014-2018 KunkaLabs Limited.\n * @author KunkaLabs Limited.\n * @link https://www.kunkalabs.com/mixitup/\n *\n * @license Commercial use requires a commercial license.\n * https://www.kunkalabs.com/mixitup/licenses/\n *\n * Non-commercial use permitted under same terms as CC BY-NC 3.0 license.\n * http://creativecommons.org/licenses/by-nc/3.0/\n */\n\n(function(window) {\n 'use strict';\n\n var mixitup = null,\n h = null;\n\n (function() {\n var VENDORS = ['webkit', 'moz', 'o', 'ms'],\n canary = window.document.createElement('div'),\n i = -1;\n\n // window.requestAnimationFrame\n\n for (i = 0; i < VENDORS.length && !window.requestAnimationFrame; i++) {\n window.requestAnimationFrame = window[VENDORS[i] + 'RequestAnimationFrame'];\n }\n\n // Element.nextElementSibling\n\n if (typeof canary.nextElementSibling === 'undefined') {\n Object.defineProperty(window.Element.prototype, 'nextElementSibling', {\n get: function() {\n var el = this.nextSibling;\n\n while (el) {\n if (el.nodeType === 1) {\n return el;\n }\n\n el = el.nextSibling;\n }\n\n return null;\n }\n });\n }\n\n // Element.matches\n\n (function(ElementPrototype) {\n ElementPrototype.matches =\n ElementPrototype.matches ||\n ElementPrototype.machesSelector ||\n ElementPrototype.mozMatchesSelector ||\n ElementPrototype.msMatchesSelector ||\n ElementPrototype.oMatchesSelector ||\n ElementPrototype.webkitMatchesSelector ||\n function (selector) {\n return Array.prototype.indexOf.call(this.parentElement.querySelectorAll(selector), this) > -1;\n };\n })(window.Element.prototype);\n\n // Object.keys\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys\n\n if (!Object.keys) {\n Object.keys = (function() {\n var hasOwnProperty = Object.prototype.hasOwnProperty,\n hasDontEnumBug = false,\n dontEnums = [],\n dontEnumsLength = -1;\n\n hasDontEnumBug = !({\n toString: null\n })\n .propertyIsEnumerable('toString');\n\n dontEnums = [\n 'toString',\n 'toLocaleString',\n 'valueOf',\n 'hasOwnProperty',\n 'isPrototypeOf',\n 'propertyIsEnumerable',\n 'constructor'\n ];\n\n dontEnumsLength = dontEnums.length;\n\n return function(obj) {\n var result = [],\n prop = '',\n i = -1;\n\n if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {\n throw new TypeError('Object.keys called on non-object');\n }\n\n for (prop in obj) {\n if (hasOwnProperty.call(obj, prop)) {\n result.push(prop);\n }\n }\n\n if (hasDontEnumBug) {\n for (i = 0; i < dontEnumsLength; i++) {\n if (hasOwnProperty.call(obj, dontEnums[i])) {\n result.push(dontEnums[i]);\n }\n }\n }\n\n return result;\n };\n }());\n }\n\n // Array.isArray\n // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray\n\n if (!Array.isArray) {\n Array.isArray = function(arg) {\n return Object.prototype.toString.call(arg) === '[object Array]';\n };\n }\n\n // Object.create\n // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create\n\n if (typeof Object.create !== 'function') {\n Object.create = (function(undefined) {\n var Temp = function() {};\n\n return function (prototype, propertiesObject) {\n if (prototype !== Object(prototype) && prototype !== null) {\n throw TypeError('Argument must be an object, or null');\n }\n\n Temp.prototype = prototype || {};\n\n var result = new Temp();\n\n Temp.prototype = null;\n\n if (propertiesObject !== undefined) {\n Object.defineProperties(result, propertiesObject);\n }\n\n if (prototype === null) {\n /* jshint ignore:start */\n result.__proto__ = null;\n /* jshint ignore:end */\n }\n\n return result;\n };\n })();\n }\n\n // String.prototyoe.trim\n\n if (!String.prototype.trim) {\n String.prototype.trim = function() {\n return this.replace(/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g, '');\n };\n }\n\n // Array.prototype.indexOf\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf\n\n if (!Array.prototype.indexOf) {\n Array.prototype.indexOf = function(searchElement) {\n var n, k, t, len;\n\n if (this === null) {\n throw new TypeError();\n }\n\n t = Object(this);\n\n len = t.length >>> 0;\n\n if (len === 0) {\n return -1;\n }\n\n n = 0;\n\n if (arguments.length > 1) {\n n = Number(arguments[1]);\n\n if (n !== n) {\n n = 0;\n } else if (n !== 0 && n !== Infinity && n !== -Infinity) {\n n = (n > 0 || -1) * Math.floor(Math.abs(n));\n }\n }\n\n if (n >= len) {\n return -1;\n }\n\n for (k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); k < len; k++) {\n if (k in t && t[k] === searchElement) {\n return k;\n }\n }\n\n return -1;\n };\n }\n\n // Function.prototype.bind\n // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind\n\n if (!Function.prototype.bind) {\n Function.prototype.bind = function(oThis) {\n var aArgs, self, FNOP, fBound;\n\n if (typeof this !== 'function') {\n throw new TypeError();\n }\n\n aArgs = Array.prototype.slice.call(arguments, 1);\n\n self = this;\n\n FNOP = function() {};\n\n fBound = function() {\n return self.apply(this instanceof FNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));\n };\n\n if (this.prototype) {\n FNOP.prototype = this.prototype;\n }\n\n fBound.prototype = new FNOP();\n\n return fBound;\n };\n }\n\n // Element.prototype.dispatchEvent\n\n if (!window.Element.prototype.dispatchEvent) {\n window.Element.prototype.dispatchEvent = function(event) {\n try {\n return this.fireEvent('on' + event.type, event);\n } catch (err) {}\n };\n }\n })();\n\n /**\n * The `mixitup()` \"factory\" function creates and returns individual instances\n * of MixItUp, known as \"mixers\", on which API methods can be called.\n *\n * When loading MixItUp via a script tag, the factory function is accessed\n * via the global variable `mixitup`. When using a module loading\n * system (e.g. ES2015, CommonJS, RequireJS), the factory function is\n * exported into your module when you require the MixItUp library.\n *\n * @example\n * mixitup(container [,config] [,foreignDoc])\n *\n * @example Example 1: Creating a mixer instance with an element reference\n * var containerEl = document.querySelector('.container');\n *\n * var mixer = mixitup(containerEl);\n *\n * @example Example 2: Creating a mixer instance with a selector string\n * var mixer = mixitup('.container');\n *\n * @example Example 3: Passing a configuration object\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effects: 'fade scale(0.5)'\n * }\n * });\n *\n * @example Example 4: Passing an iframe reference\n * var mixer = mixitup(containerEl, config, foreignDocument);\n *\n * @global\n * @namespace\n * @public\n * @kind function\n * @since 3.0.0\n * @param {(Element|string)} container\n * A DOM element or selector string representing the container(s) on which to instantiate MixItUp.\n * @param {object} [config]\n * An optional \"configuration object\" used to customize the behavior of the MixItUp instance.\n * @param {object} [foreignDoc]\n * An optional reference to a `document`, which can be used to control a MixItUp instance in an iframe.\n * @return {mixitup.Mixer}\n * A \"mixer\" object holding the MixItUp instance.\n */\n\n mixitup = function(container, config, foreignDoc) {\n var el = null,\n returnCollection = false,\n instance = null,\n facade = null,\n doc = null,\n output = null,\n instances = [],\n id = '',\n elements = [],\n i = -1;\n\n doc = foreignDoc || window.document;\n\n if (returnCollection = arguments[3]) {\n // A non-documented 4th paramater enabling control of multiple instances\n\n returnCollection = typeof returnCollection === 'boolean';\n }\n\n if (typeof container === 'string') {\n elements = doc.querySelectorAll(container);\n } else if (container && typeof container === 'object' && h.isElement(container, doc)) {\n elements = [container];\n } else if (container && typeof container === 'object' && container.length) {\n // Although not documented, the container may also be an array-like list of\n // elements such as a NodeList or jQuery collection, is returnCollection is true\n\n elements = container;\n } else {\n throw new Error(mixitup.messages.errorFactoryInvalidContainer());\n }\n\n if (elements.length < 1) {\n throw new Error(mixitup.messages.errorFactoryContainerNotFound());\n }\n\n for (i = 0; el = elements[i]; i++) {\n if (i > 0 && !returnCollection) break;\n\n if (!el.id) {\n id = 'MixItUp' + h.randomHex();\n\n el.id = id;\n } else {\n id = el.id;\n }\n\n if (mixitup.instances[id] instanceof mixitup.Mixer) {\n instance = mixitup.instances[id];\n\n if (!config || (config && config.debug && config.debug.showWarnings !== false)) {\n console.warn(mixitup.messages.warningFactoryPreexistingInstance());\n }\n } else {\n instance = new mixitup.Mixer();\n\n instance.attach(el, doc, id, config);\n\n mixitup.instances[id] = instance;\n }\n\n facade = new mixitup.Facade(instance);\n\n if (config && config.debug && config.debug.enable) {\n instances.push(instance);\n } else {\n instances.push(facade);\n }\n }\n\n if (returnCollection) {\n output = new mixitup.Collection(instances);\n } else {\n // Return the first instance regardless\n\n output = instances[0];\n }\n\n return output;\n };\n\n /**\n * The `.use()` static method is used to extend the functionality of mixitup with compatible\n * extensions and libraries in an environment with modular scoping e.g. ES2015, CommonJS, or RequireJS.\n *\n * You need only call the `.use()` function once per project, per extension, as module loaders\n * will cache a single reference to MixItUp inclusive of all changes made.\n *\n * @example\n * mixitup.use(extension)\n *\n * @example Example 1: Extending MixItUp with the Pagination Extension\n *\n * import mixitup from 'mixitup';\n * import mixitupPagination from 'mixitup-pagination';\n *\n * mixitup.use(mixitupPagination);\n *\n * // All mixers created by the factory function in all modules will now\n * // have pagination functionality\n *\n * var mixer = mixitup('.container');\n *\n * @public\n * @name use\n * @memberof mixitup\n * @kind function\n * @static\n * @since 3.0.0\n * @param {*} extension A reference to the extension or library to be used.\n * @return {void}\n */\n\n mixitup.use = function(extension) {\n mixitup.Base.prototype.callActions.call(mixitup, 'beforeUse', arguments);\n\n // Call the extension's factory function, passing\n // the mixitup factory as a paramater\n\n if (typeof extension === 'function' && extension.TYPE === 'mixitup-extension') {\n // Mixitup extension\n\n if (typeof mixitup.extensions[extension.NAME] === 'undefined') {\n extension(mixitup);\n\n mixitup.extensions[extension.NAME] = extension;\n }\n } else if (extension.fn && extension.fn.jquery) {\n // jQuery\n\n mixitup.libraries.$ = extension;\n }\n\n mixitup.Base.prototype.callActions.call(mixitup, 'afterUse', arguments);\n };\n\n mixitup.instances = {};\n mixitup.extensions = {};\n mixitup.libraries = {};\n\n /**\n * @private\n */\n\n h = {\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} cls\n * @return {boolean}\n */\n\n hasClass: function(el, cls) {\n return !!el.className.match(new RegExp('(\\\\s|^)' + cls + '(\\\\s|$)'));\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} cls\n * @return {void}\n */\n\n addClass: function(el, cls) {\n if (!this.hasClass(el, cls)) el.className += el.className ? ' ' + cls : cls;\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} cls\n * @return {void}\n */\n\n removeClass: function(el, cls) {\n if (this.hasClass(el, cls)) {\n var reg = new RegExp('(\\\\s|^)' + cls + '(\\\\s|$)');\n\n el.className = el.className.replace(reg, ' ').trim();\n }\n },\n\n /**\n * Merges the properties of the source object onto the\n * target object. Alters the target object.\n *\n * @private\n * @param {object} destination\n * @param {object} source\n * @param {boolean} [deep=false]\n * @param {boolean} [handleErrors=false]\n * @return {void}\n */\n\n extend: function(destination, source, deep, handleErrors) {\n var sourceKeys = [],\n key = '',\n i = -1;\n\n deep = deep || false;\n handleErrors = handleErrors || false;\n\n try {\n if (Array.isArray(source)) {\n for (i = 0; i < source.length; i++) {\n sourceKeys.push(i);\n }\n } else if (source) {\n sourceKeys = Object.keys(source);\n }\n\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n\n if (!deep || typeof source[key] !== 'object' || this.isElement(source[key])) {\n // All non-object properties, or all properties if shallow extend\n\n destination[key] = source[key];\n } else if (Array.isArray(source[key])) {\n // Arrays\n\n if (!destination[key]) {\n destination[key] = [];\n }\n\n this.extend(destination[key], source[key], deep, handleErrors);\n } else {\n // Objects\n\n if (!destination[key]) {\n destination[key] = {};\n }\n\n this.extend(destination[key], source[key], deep, handleErrors);\n }\n }\n } catch(err) {\n if (handleErrors) {\n this.handleExtendError(err, destination);\n } else {\n throw err;\n }\n }\n\n return destination;\n },\n\n /**\n * @private\n * @param {Error} err\n * @param {object} destination\n * @return {void}\n */\n\n handleExtendError: function(err, destination) {\n var re = /property \"?(\\w*)\"?[,:] object/i,\n matches = null,\n erroneous = '',\n message = '',\n suggestion = '',\n probableMatch = '',\n key = '',\n mostMatchingChars = -1,\n i = -1;\n\n if (err instanceof TypeError && (matches = re.exec(err.message))) {\n erroneous = matches[1];\n\n for (key in destination) {\n i = 0;\n\n while (i < erroneous.length && erroneous.charAt(i) === key.charAt(i)) {\n i++;\n }\n\n if (i > mostMatchingChars) {\n mostMatchingChars = i;\n probableMatch = key;\n }\n }\n\n if (mostMatchingChars > 1) {\n suggestion = mixitup.messages.errorConfigInvalidPropertySuggestion({\n probableMatch: probableMatch\n });\n }\n\n message = mixitup.messages.errorConfigInvalidProperty({\n erroneous: erroneous,\n suggestion: suggestion\n });\n\n throw new TypeError(message);\n }\n\n throw err;\n },\n\n /**\n * @private\n * @param {string} str\n * @return {function}\n */\n\n template: function(str) {\n var re = /\\${([\\w]*)}/g,\n dynamics = {},\n matches = null;\n\n while ((matches = re.exec(str))) {\n dynamics[matches[1]] = new RegExp('\\\\${' + matches[1] + '}', 'g');\n }\n\n return function(data) {\n var key = '',\n output = str;\n\n data = data || {};\n\n for (key in dynamics) {\n output = output.replace(dynamics[key], typeof data[key] !== 'undefined' ? data[key] : '');\n }\n\n return output;\n };\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} type\n * @param {function} fn\n * @param {boolean} useCapture\n * @return {void}\n */\n\n on: function(el, type, fn, useCapture) {\n if (!el) return;\n\n if (el.addEventListener) {\n el.addEventListener(type, fn, useCapture);\n } else if (el.attachEvent) {\n el['e' + type + fn] = fn;\n\n el[type + fn] = function() {\n el['e' + type + fn](window.event);\n };\n\n el.attachEvent('on' + type, el[type + fn]);\n }\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} type\n * @param {function} fn\n * @return {void}\n */\n\n off: function(el, type, fn) {\n if (!el) return;\n\n if (el.removeEventListener) {\n el.removeEventListener(type, fn, false);\n } else if (el.detachEvent) {\n el.detachEvent('on' + type, el[type + fn]);\n el[type + fn] = null;\n }\n },\n\n /**\n * @private\n * @param {string} eventType\n * @param {object} detail\n * @param {Document} [doc]\n * @return {CustomEvent}\n */\n\n getCustomEvent: function(eventType, detail, doc) {\n var event = null;\n\n doc = doc || window.document;\n\n if (typeof window.CustomEvent === 'function') {\n event = new window.CustomEvent(eventType, {\n detail: detail,\n bubbles: true,\n cancelable: true\n });\n } else if (typeof doc.createEvent === 'function') {\n event = doc.createEvent('CustomEvent');\n event.initCustomEvent(eventType, true, true, detail);\n } else {\n event = doc.createEventObject(),\n event.type = eventType;\n\n event.returnValue = false;\n event.cancelBubble = false;\n event.detail = detail;\n }\n\n return event;\n },\n\n /**\n * @private\n * @param {Event} e\n * @return {Event}\n */\n\n getOriginalEvent: function(e) {\n if (e.touches && e.touches.length) {\n return e.touches[0];\n } else if (e.changedTouches && e.changedTouches.length) {\n return e.changedTouches[0];\n } else {\n return e;\n }\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} selector\n * @return {Number}\n */\n\n index: function(el, selector) {\n var i = 0;\n\n while ((el = el.previousElementSibling) !== null) {\n if (!selector || el.matches(selector)) {\n ++i;\n }\n }\n\n return i;\n },\n\n /**\n * Converts a dash or snake-case string to camel case.\n *\n * @private\n * @param {string} str\n * @param {boolean} [isPascal]\n * @return {string}\n */\n\n camelCase: function(str) {\n return str.toLowerCase().replace(/([_-][a-z])/g, function($1) {\n return $1.toUpperCase().replace(/[_-]/, '');\n });\n },\n\n /**\n * Converts a dash or snake-case string to pascal case.\n *\n * @private\n * @param {string} str\n * @param {boolean} [isPascal]\n * @return {string}\n */\n\n pascalCase: function(str) {\n return (str = this.camelCase(str)).charAt(0).toUpperCase() + str.slice(1);\n },\n\n /**\n * Converts a camel or pascal-case string to dash case.\n *\n * @private\n * @param {string} str\n * @return {string}\n */\n\n dashCase: function(str) {\n return str.replace(/([A-Z])/g, '-$1').replace(/^-/, '').toLowerCase();\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {HTMLHtmlElement} [doc]\n * @return {boolean}\n */\n\n isElement: function(el, doc) {\n doc = doc || window.document;\n\n if (\n window.HTMLElement &&\n el instanceof window.HTMLElement\n ) {\n return true;\n } else if (\n doc.defaultView &&\n doc.defaultView.HTMLElement &&\n el instanceof doc.defaultView.HTMLElement\n ) {\n return true;\n } else {\n return (\n el !== null &&\n el.nodeType === 1 &&\n typeof el.nodeName === 'string'\n );\n }\n },\n\n /**\n * @private\n * @param {string} htmlString\n * @param {HTMLHtmlElement} [doc]\n * @return {DocumentFragment}\n */\n\n createElement: function(htmlString, doc) {\n var frag = null,\n temp = null;\n\n doc = doc || window.document;\n\n frag = doc.createDocumentFragment();\n temp = doc.createElement('div');\n\n temp.innerHTML = htmlString.trim();\n\n while (temp.firstChild) {\n frag.appendChild(temp.firstChild);\n }\n\n return frag;\n },\n\n /**\n * @private\n * @param {Node} node\n * @return {void}\n */\n\n removeWhitespace: function(node) {\n var deleting;\n\n while (node && node.nodeName === '#text') {\n deleting = node;\n\n node = node.previousSibling;\n\n deleting.parentElement && deleting.parentElement.removeChild(deleting);\n }\n },\n\n /**\n * @private\n * @param {Array<*>} a\n * @param {Array<*>} b\n * @return {boolean}\n */\n\n isEqualArray: function(a, b) {\n var i = a.length;\n\n if (i !== b.length) return false;\n\n while (i--) {\n if (a[i] !== b[i]) return false;\n }\n\n return true;\n },\n\n /**\n * @private\n * @param {object} a\n * @param {object} b\n * @return {boolean}\n */\n\n deepEquals: function(a, b) {\n var key;\n\n if (typeof a === 'object' && a && typeof b === 'object' && b) {\n if (Object.keys(a).length !== Object.keys(b).length) return false;\n\n for (key in a) {\n if (!b.hasOwnProperty(key) || !this.deepEquals(a[key], b[key])) return false;\n }\n } else if (a !== b) {\n return false;\n }\n\n return true;\n },\n\n /**\n * @private\n * @param {Array<*>} oldArray\n * @return {Array<*>}\n */\n\n arrayShuffle: function(oldArray) {\n var newArray = oldArray.slice(),\n len = newArray.length,\n i = len,\n p = -1,\n t = [];\n\n while (i--) {\n p = ~~(Math.random() * len);\n t = newArray[i];\n\n newArray[i] = newArray[p];\n newArray[p] = t;\n }\n\n return newArray;\n },\n\n /**\n * @private\n * @param {object} list\n */\n\n arrayFromList: function(list) {\n var output, i;\n\n try {\n return Array.prototype.slice.call(list);\n } catch(err) {\n output = [];\n\n for (i = 0; i < list.length; i++) {\n output.push(list[i]);\n }\n\n return output;\n }\n },\n\n /**\n * @private\n * @param {function} func\n * @param {Number} wait\n * @param {boolean} immediate\n * @return {function}\n */\n\n debounce: function(func, wait, immediate) {\n var timeout;\n\n return function() {\n var self = this,\n args = arguments,\n callNow = immediate && !timeout,\n later = null;\n\n later = function() {\n timeout = null;\n\n if (!immediate) {\n func.apply(self, args);\n }\n };\n\n clearTimeout(timeout);\n\n timeout = setTimeout(later, wait);\n\n if (callNow) func.apply(self, args);\n };\n },\n\n /**\n * @private\n * @param {HTMLElement} element\n * @return {object}\n */\n\n position: function(element) {\n var xPosition = 0,\n yPosition = 0,\n offsetParent = element;\n\n while (element) {\n xPosition -= element.scrollLeft;\n yPosition -= element.scrollTop;\n\n if (element === offsetParent) {\n xPosition += element.offsetLeft;\n yPosition += element.offsetTop;\n\n offsetParent = element.offsetParent;\n }\n\n element = element.parentElement;\n }\n\n return {\n x: xPosition,\n y: yPosition\n };\n },\n\n /**\n * @private\n * @param {object} node1\n * @param {object} node2\n * @return {Number}\n */\n\n getHypotenuse: function(node1, node2) {\n var distanceX = node1.x - node2.x,\n distanceY = node1.y - node2.y;\n\n distanceX = distanceX < 0 ? distanceX * -1 : distanceX,\n distanceY = distanceY < 0 ? distanceY * -1 : distanceY;\n\n return Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));\n },\n\n /**\n * Calcuates the area of intersection between two rectangles and expresses it as\n * a ratio in comparison to the area of the first rectangle.\n *\n * @private\n * @param {Rect} box1\n * @param {Rect} box2\n * @return {number}\n */\n\n getIntersectionRatio: function(box1, box2) {\n var controlArea = box1.width * box1.height,\n intersectionX = -1,\n intersectionY = -1,\n intersectionArea = -1,\n ratio = -1;\n\n intersectionX =\n Math.max(0, Math.min(box1.left + box1.width, box2.left + box2.width) - Math.max(box1.left, box2.left));\n\n intersectionY =\n Math.max(0, Math.min(box1.top + box1.height, box2.top + box2.height) - Math.max(box1.top, box2.top));\n\n intersectionArea = intersectionY * intersectionX;\n\n ratio = intersectionArea / controlArea;\n\n return ratio;\n },\n\n /**\n * @private\n * @param {object} el\n * @param {string} selector\n * @param {boolean} [includeSelf]\n * @param {HTMLHtmlElement} [doc]\n * @return {Element|null}\n */\n\n closestParent: function(el, selector, includeSelf, doc) {\n var parent = el.parentNode;\n\n doc = doc || window.document;\n\n if (includeSelf && el.matches(selector)) {\n return el;\n }\n\n while (parent && parent != doc.body) {\n if (parent.matches && parent.matches(selector)) {\n return parent;\n } else if (parent.parentNode) {\n parent = parent.parentNode;\n } else {\n return null;\n }\n }\n\n return null;\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} selector\n * @param {HTMLHtmlElement} [doc]\n * @return {NodeList}\n */\n\n children: function(el, selector, doc) {\n var children = [],\n tempId = '';\n\n doc = doc || window.doc;\n\n if (el) {\n if (!el.id) {\n tempId = 'Temp' + this.randomHexKey();\n\n el.id = tempId;\n }\n\n children = doc.querySelectorAll('#' + el.id + ' > ' + selector);\n\n if (tempId) {\n el.removeAttribute('id');\n }\n }\n\n return children;\n },\n\n /**\n * Creates a clone of a provided array, with any empty strings removed.\n *\n * @private\n * @param {Array<*>} originalArray\n * @return {Array<*>}\n */\n\n clean: function(originalArray) {\n var cleanArray = [],\n i = -1;\n\n for (i = 0; i < originalArray.length; i++) {\n if (originalArray[i] !== '') {\n cleanArray.push(originalArray[i]);\n }\n }\n\n return cleanArray;\n },\n\n /**\n * Abstracts an ES6 promise into a q-like deferred interface for storage and deferred resolution.\n *\n * @private\n * @param {object} libraries\n * @return {h.Deferred}\n */\n\n defer: function(libraries) {\n var deferred = null,\n promiseWrapper = null,\n $ = null;\n\n promiseWrapper = new this.Deferred();\n\n if (mixitup.features.has.promises) {\n // ES6 native promise or polyfill\n\n promiseWrapper.promise = new Promise(function(resolve, reject) {\n promiseWrapper.resolve = resolve;\n promiseWrapper.reject = reject;\n });\n } else if (($ = (window.jQuery || libraries.$)) && typeof $.Deferred === 'function') {\n // jQuery\n\n deferred = $.Deferred();\n\n promiseWrapper.promise = deferred.promise();\n promiseWrapper.resolve = deferred.resolve;\n promiseWrapper.reject = deferred.reject;\n } else if (window.console) {\n // No implementation\n\n console.warn(mixitup.messages.warningNoPromiseImplementation());\n }\n\n return promiseWrapper;\n },\n\n /**\n * @private\n * @param {Array} tasks\n * @param {object} libraries\n * @return {Promise}\n */\n\n all: function(tasks, libraries) {\n var $ = null;\n\n if (mixitup.features.has.promises) {\n return Promise.all(tasks);\n } else if (($ = (window.jQuery || libraries.$)) && typeof $.when === 'function') {\n return $.when.apply($, tasks)\n .done(function() {\n // jQuery when returns spread arguments rather than an array or resolutions\n\n return arguments;\n });\n }\n\n // No implementation\n\n if (window.console) {\n console.warn(mixitup.messages.warningNoPromiseImplementation());\n }\n\n return [];\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} property\n * @param {Array} vendors\n * @return {string}\n */\n\n getPrefix: function(el, property, vendors) {\n var i = -1,\n prefix = '';\n\n if (h.dashCase(property) in el.style) return '';\n\n for (i = 0; prefix = vendors[i]; i++) {\n if (prefix + property in el.style) {\n return prefix.toLowerCase();\n }\n }\n\n return 'unsupported';\n },\n\n /**\n * @private\n * @return {string}\n */\n\n randomHex: function() {\n return ('00000' + (Math.random() * 16777216 << 0).toString(16)).substr(-6).toUpperCase();\n },\n\n /**\n * @private\n * @param {HTMLDocument} [doc]\n * @return {object}\n */\n\n getDocumentState: function(doc) {\n doc = typeof doc.body === 'object' ? doc : window.document;\n\n return {\n scrollTop: window.pageYOffset,\n scrollLeft: window.pageXOffset,\n docHeight: doc.documentElement.scrollHeight,\n docWidth: doc.documentElement.scrollWidth,\n viewportHeight: doc.documentElement.clientHeight,\n viewportWidth: doc.documentElement.clientWidth\n };\n },\n\n /**\n * @private\n * @param {object} obj\n * @param {function} fn\n * @return {function}\n */\n\n bind: function(obj, fn) {\n return function() {\n return fn.apply(obj, arguments);\n };\n },\n\n /**\n * @private\n * @param {HTMLElement} el\n * @return {boolean}\n */\n\n isVisible: function(el) {\n var styles = null;\n\n if (el.offsetParent) return true;\n\n styles = window.getComputedStyle(el);\n\n if (\n styles.position === 'fixed' &&\n styles.visibility !== 'hidden' &&\n styles.opacity !== '0'\n ) {\n // Fixed elements report no offsetParent,\n // but may still be invisible\n\n return true;\n }\n\n return false;\n },\n\n /**\n * @private\n * @param {object} obj\n */\n\n seal: function(obj) {\n if (typeof Object.seal === 'function') {\n Object.seal(obj);\n }\n },\n\n /**\n * @private\n * @param {object} obj\n */\n\n freeze: function(obj) {\n if (typeof Object.freeze === 'function') {\n Object.freeze(obj);\n }\n },\n\n /**\n * @private\n * @param {string} control\n * @param {string} specimen\n * @return {boolean}\n */\n\n compareVersions: function(control, specimen) {\n var controlParts = control.split('.'),\n specimenParts = specimen.split('.'),\n controlPart = -1,\n specimenPart = -1,\n i = -1;\n\n for (i = 0; i < controlParts.length; i++) {\n controlPart = parseInt(controlParts[i].replace(/[^\\d.]/g, ''));\n specimenPart = parseInt(specimenParts[i].replace(/[^\\d.]/g, '') || 0);\n\n if (specimenPart < controlPart) {\n return false;\n } else if (specimenPart > controlPart) {\n return true;\n }\n }\n\n return true;\n },\n\n /**\n * @private\n * @constructor\n */\n\n Deferred: function() {\n this.promise = null;\n this.resolve = null;\n this.reject = null;\n this.id = h.randomHex();\n },\n\n /**\n * @private\n * @param {object} obj\n * @return {boolean}\n */\n\n isEmptyObject: function(obj) {\n var key = '';\n\n if (typeof Object.keys === 'function') {\n return Object.keys(obj).length === 0;\n }\n\n for (key in obj) {\n if (obj.hasOwnProperty(key)) {\n return false;\n }\n }\n\n return true;\n },\n\n /**\n * @param {mixitup.Config.ClassNames} classNames\n * @param {string} elementName\n * @param {string} [modifier]\n * @return {string}\n */\n\n getClassname: function(classNames, elementName, modifier) {\n var classname = '';\n\n classname += classNames.block;\n\n if (classname.length) {\n classname += classNames.delineatorElement;\n }\n\n classname += classNames['element' + this.pascalCase(elementName)];\n\n if (!modifier) return classname;\n\n if (classname.length) {\n classname += classNames.delineatorModifier;\n }\n\n classname += modifier;\n\n return classname;\n },\n\n /**\n * Returns the value of a property on a given object via its string key.\n *\n * @param {object} obj\n * @param {string} stringKey\n * @return {*} value\n */\n\n getProperty: function(obj, stringKey) {\n var parts = stringKey.split('.'),\n returnCurrent = null,\n current = '',\n i = 0;\n\n if (!stringKey) {\n return obj;\n }\n\n returnCurrent = function(obj) {\n if (!obj) {\n return null;\n } else {\n return obj[current];\n }\n };\n\n while (i < parts.length) {\n current = parts[i];\n\n obj = returnCurrent(obj);\n\n i++;\n }\n\n if (typeof obj !== 'undefined') {\n return obj;\n } else {\n return null;\n }\n }\n };\n\n mixitup.h = h;\n\n /**\n * The Base class adds instance methods to all other extensible MixItUp classes,\n * enabling the calling of any registered hooks.\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.Base = function() {};\n\n mixitup.Base.prototype = {\n constructor: mixitup.Base,\n\n /**\n * Calls any registered hooks for the provided action.\n *\n * @memberof mixitup.Base\n * @private\n * @instance\n * @since 2.0.0\n * @param {string} actionName\n * @param {Array<*>} args\n * @return {void}\n */\n\n callActions: function(actionName, args) {\n var self = this,\n hooks = self.constructor.actions[actionName],\n extensionName = '';\n\n if (!hooks || h.isEmptyObject(hooks)) return;\n\n for (extensionName in hooks) {\n hooks[extensionName].apply(self, args);\n }\n },\n\n /**\n * Calls any registered hooks for the provided filter.\n *\n * @memberof mixitup.Base\n * @private\n * @instance\n * @since 2.0.0\n * @param {string} filterName\n * @param {*} input\n * @param {Array<*>} args\n * @return {*}\n */\n\n callFilters: function(filterName, input, args) {\n var self = this,\n hooks = self.constructor.filters[filterName],\n output = input,\n extensionName = '';\n\n if (!hooks || h.isEmptyObject(hooks)) return output;\n\n args = args || [];\n\n for (extensionName in hooks) {\n args = h.arrayFromList(args);\n\n args.unshift(output);\n\n output = hooks[extensionName].apply(self, args);\n }\n\n return output;\n }\n };\n\n /**\n * The BaseStatic class holds a set of static methods which are then added to all other\n * extensible MixItUp classes as a means of integrating extensions via the addition of new\n * methods and/or actions and hooks.\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.BaseStatic = function() {\n this.actions = {};\n this.filters = {};\n\n /**\n * Performs a shallow extend on the class's prototype, adding one or more new members to\n * the class in a single operation.\n *\n * @memberof mixitup.BaseStatic\n * @public\n * @static\n * @since 2.1.0\n * @param {object} extension\n * @return {void}\n */\n\n this.extend = function(extension) {\n h.extend(this.prototype, extension);\n };\n\n /**\n * Registers a function to be called on the action hook of the provided name.\n *\n * @memberof mixitup.BaseStatic\n * @public\n * @static\n * @since 2.1.0\n * @param {string} hookName\n * @param {string} extensionName\n * @param {function} func\n * @return {void}\n */\n\n this.registerAction = function(hookName, extensionName, func) {\n (this.actions[hookName] = this.actions[hookName] || {})[extensionName] = func;\n };\n\n /**\n * Registers a function to be called on the filter of the provided name.\n *\n * @memberof mixitup.BaseStatic\n * @public\n * @static\n * @since 2.1.0\n * @param {string} hookName\n * @param {string} extensionName\n * @param {function} func\n * @return {void}\n */\n\n this.registerFilter = function(hookName, extensionName, func) {\n (this.filters[hookName] = this.filters[hookName] || {})[extensionName] = func;\n };\n };\n\n /**\n * The `mixitup.Features` class performs all feature and CSS prefix detection\n * neccessary for MixItUp to function correctly, as well as storing various\n * string and array constants. All feature decection is on evaluation of the\n * library and stored in a singleton instance for use by other internal classes.\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.Features = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.boxSizingPrefix = '';\n this.transformPrefix = '';\n this.transitionPrefix = '';\n\n this.boxSizingPrefix = '';\n this.transformProp = '';\n this.transformRule = '';\n this.transitionProp = '';\n this.perspectiveProp = '';\n this.perspectiveOriginProp = '';\n\n this.has = new mixitup.Has();\n\n this.canary = null;\n\n this.BOX_SIZING_PROP = 'boxSizing';\n this.TRANSITION_PROP = 'transition';\n this.TRANSFORM_PROP = 'transform';\n this.PERSPECTIVE_PROP = 'perspective';\n this.PERSPECTIVE_ORIGIN_PROP = 'perspectiveOrigin';\n this.VENDORS = ['Webkit', 'moz', 'O', 'ms'];\n\n this.TWEENABLE = [\n 'opacity',\n 'width', 'height',\n 'marginRight', 'marginBottom',\n 'x', 'y',\n 'scale',\n 'translateX', 'translateY', 'translateZ',\n 'rotateX', 'rotateY', 'rotateZ'\n ];\n\n this.callActions('afterConstruct');\n };\n\n mixitup.BaseStatic.call(mixitup.Features);\n\n mixitup.Features.prototype = Object.create(mixitup.Base.prototype);\n\n h.extend(mixitup.Features.prototype,\n /** @lends mixitup.Features */\n {\n constructor: mixitup.Features,\n\n /**\n * @private\n * @return {void}\n */\n\n init: function() {\n var self = this;\n\n self.callActions('beforeInit', arguments);\n\n self.canary = document.createElement('div');\n\n self.setPrefixes();\n self.runTests();\n\n self.callActions('beforeInit', arguments);\n },\n\n /**\n * @private\n * @return {void}\n */\n\n runTests: function() {\n var self = this;\n\n self.callActions('beforeRunTests', arguments);\n\n self.has.promises = typeof window.Promise === 'function';\n self.has.transitions = self.transitionPrefix !== 'unsupported';\n\n self.callActions('afterRunTests', arguments);\n\n h.freeze(self.has);\n },\n\n /**\n * @private\n * @return {void}\n */\n\n setPrefixes: function() {\n var self = this;\n\n self.callActions('beforeSetPrefixes', arguments);\n\n self.transitionPrefix = h.getPrefix(self.canary, 'Transition', self.VENDORS);\n self.transformPrefix = h.getPrefix(self.canary, 'Transform', self.VENDORS);\n self.boxSizingPrefix = h.getPrefix(self.canary, 'BoxSizing', self.VENDORS);\n\n self.boxSizingProp = self.boxSizingPrefix ?\n self.boxSizingPrefix + h.pascalCase(self.BOX_SIZING_PROP) : self.BOX_SIZING_PROP;\n\n self.transitionProp = self.transitionPrefix ?\n self.transitionPrefix + h.pascalCase(self.TRANSITION_PROP) : self.TRANSITION_PROP;\n\n self.transformProp = self.transformPrefix ?\n self.transformPrefix + h.pascalCase(self.TRANSFORM_PROP) : self.TRANSFORM_PROP;\n\n self.transformRule = self.transformPrefix ?\n '-' + self.transformPrefix + '-' + self.TRANSFORM_PROP : self.TRANSFORM_PROP;\n\n self.perspectiveProp = self.transformPrefix ?\n self.transformPrefix + h.pascalCase(self.PERSPECTIVE_PROP) : self.PERSPECTIVE_PROP;\n\n self.perspectiveOriginProp = self.transformPrefix ?\n self.transformPrefix + h.pascalCase(self.PERSPECTIVE_ORIGIN_PROP) :\n self.PERSPECTIVE_ORIGIN_PROP;\n\n self.callActions('afterSetPrefixes', arguments);\n }\n });\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.Has = function() {\n this.transitions = false;\n this.promises = false;\n\n h.seal(this);\n };\n\n // Assign a singleton instance to `mixitup.features` and initialise:\n\n mixitup.features = new mixitup.Features();\n\n mixitup.features.init();\n\n /**\n * A group of properties defining the mixer's animation and effects settings.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name animation\n * @namespace\n * @public\n * @since 2.0.0\n */\n\n mixitup.ConfigAnimation = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A boolean dictating whether or not animation should be enabled for the MixItUp instance.\n * If `false`, all operations will occur instantly and syncronously, although callback\n * functions and any returned promises will still be fulfilled.\n *\n * @example Example: Create a mixer with all animations disabled\n * var mixer = mixitup(containerEl, {\n * animation: {\n * enable: false\n * }\n * });\n *\n * @name enable\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.enable = true;\n\n /**\n * A string of one or more space-seperated properties to which transitions will be\n * applied for all filtering animations.\n *\n * Properties can be listed any order or combination, although they will be applied in a specific\n * predefined order to produce consistent results.\n *\n * To learn more about available effects, experiment with our \n * sandbox demo and try out the \"Export config\" button in the Animation options drop down.\n *\n * @example Example: Apply \"fade\" and \"translateZ\" effects to all animations\n * // As targets are filtered in and out, they will fade between\n * // opacity 1 and 0 and transform between translateZ(-100px) and\n * // translateZ(0).\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effects: 'fade translateZ(-100px)'\n * }\n * });\n *\n * @name effects\n * @memberof mixitup.Config.animation\n * @instance\n * @type {string}\n * @default 'fade scale'\n */\n\n this.effects = 'fade scale';\n\n /**\n * A string of one or more space-seperated effects to be applied only to filter-in\n * animations, overriding `config.animation.effects` if set.\n *\n * @example Example: Apply downwards vertical translate to targets being filtered in\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effectsIn: 'fade translateY(-100%)'\n * }\n * });\n *\n * @name effectsIn\n * @memberof mixitup.Config.animation\n * @instance\n * @type {string}\n * @default ''\n */\n\n this.effectsIn = '';\n\n /**\n * A string of one or more space-seperated effects to be applied only to filter-out\n * animations, overriding `config.animation.effects` if set.\n *\n * @example Example: Apply upwards vertical translate to targets being filtered out\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effectsOut: 'fade translateY(-100%)'\n * }\n * });\n *\n * @name effectsOut\n * @memberof mixitup.Config.animation\n * @instance\n * @type {string}\n * @default ''\n */\n\n this.effectsOut = '';\n\n /**\n * An integer dictating the duration of all MixItUp animations in milliseconds, not\n * including any additional delay apllied via the `'stagger'` effect.\n *\n * @example Example: Apply an animation duration of 200ms to all mixitup animations\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * duration: 200\n * }\n * });\n *\n * @name duration\n * @memberof mixitup.Config.animation\n * @instance\n * @type {number}\n * @default 600\n */\n\n this.duration = 600;\n\n /**\n * A valid CSS3 transition-timing function or shorthand. For a full list of accepted\n * values, visit easings.net.\n *\n * @example Example 1: Apply \"ease-in-out\" easing to all animations\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * easing: 'ease-in-out'\n * }\n * });\n *\n * @example Example 2: Apply a custom \"cubic-bezier\" easing function to all animations\n * var mixer = mixitup(containerEl, {\n * animation: {\n * easing: 'cubic-bezier(0.645, 0.045, 0.355, 1)'\n * }\n * });\n *\n * @name easing\n * @memberof mixitup.Config.animation\n * @instance\n * @type {string}\n * @default 'ease'\n */\n\n this.easing = 'ease';\n\n /**\n * A boolean dictating whether or not to apply perspective to the MixItUp container\n * during animations. By default, perspective is always applied and creates the\n * illusion of three-dimensional space for effects such as `translateZ`, `rotateX`,\n * and `rotateY`.\n *\n * You may wish to disable this and define your own perspective settings via CSS.\n *\n * @example Example: Prevent perspective from being applied to any 3D transforms\n * var mixer = mixitup(containerEl, {\n * animation: {\n * applyPerspective: false\n * }\n * });\n *\n * @name applyPerspective\n * @memberof mixitup.Config.animation\n * @instance\n * @type {bolean}\n * @default true\n */\n\n this.applyPerspective = true;\n\n /**\n * The perspective distance value to be applied to the container during animations,\n * affecting any 3D-transform-based effects.\n *\n * @example Example: Set a perspective distance of 2000px\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effects: 'rotateY(-25deg)',\n * perspectiveDistance: '2000px'\n * }\n * });\n *\n * @name perspectiveDistance\n * @memberof mixitup.Config.animation\n * @instance\n * @type {string}\n * @default '3000px'\n */\n\n this.perspectiveDistance = '3000px';\n\n /**\n * The perspective-origin value to be applied to the container during animations,\n * affecting any 3D-transform-based effects.\n *\n * @example Example: Set a perspective origin in the top-right of the container\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effects: 'transateZ(-200px)',\n * perspectiveOrigin: '100% 0'\n * }\n * });\n *\n * @name perspectiveOrigin\n * @memberof mixitup.Config.animation\n * @instance\n * @type {string}\n * @default '50% 50%'\n */\n\n this.perspectiveOrigin = '50% 50%';\n\n /**\n * A boolean dictating whether or not to enable the queuing of operations.\n *\n * If `true` (default), and a control is clicked or an API call is made while another\n * operation is progress, the operation will go into the queue and will be automatically exectuted\n * when the previous operaitons is finished.\n *\n * If `false`, any requested operations will be ignored, and the `onMixBusy` callback and `mixBusy`\n * event will be fired. If `debug.showWarnings` is enabled, a console warning will also occur.\n *\n * @example Example: Disable queuing\n * var mixer = mixitup(containerEl, {\n * animation: {\n * queue: false\n * }\n * });\n *\n * @name queue\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.queue = true;\n\n /**\n * An integer dictacting the maximum number of operations allowed in the queue at\n * any time, when queuing is enabled.\n *\n * @example Example: Allow a maximum of 5 operations in the queue at any time\n * var mixer = mixitup(containerEl, {\n * animation: {\n * queueLimit: 5\n * }\n * });\n *\n * @name queueLimit\n * @memberof mixitup.Config.animation\n * @instance\n * @type {number}\n * @default 3\n */\n\n this.queueLimit = 3;\n\n /**\n * A boolean dictating whether or not to transition the height and width of the\n * container as elements are filtered in and out. If disabled, the container height\n * will change abruptly.\n *\n * It may be desirable to disable this on mobile devices as the CSS `height` and\n * `width` properties do not receive GPU-acceleration and can therefore cause stuttering.\n *\n * @example Example 1: Disable the transitioning of the container height and/or width\n * var mixer = mixitup(containerEl, {\n * animation: {\n * animateResizeContainer: false\n * }\n * });\n *\n * @example Example 2: Disable the transitioning of the container height and/or width for mobile devices only\n * var mixer = mixitup(containerEl, {\n * animation: {\n * animateResizeContainer: myFeatureTests.isMobile ? false : true\n * }\n * });\n *\n * @name animateResizeContainer\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.animateResizeContainer = true;\n\n /**\n * A boolean dictating whether or not to transition the height and width of target\n * elements as they change throughout the course of an animation.\n *\n * This is often a must for flex-box grid layouts where the size of target elements may change\n * depending on final their position in relation to their siblings, or for `.changeLayout()`\n * operations where the size of targets change between layouts.\n *\n * NB: This feature requires additional calculations and manipulation to non-hardware-accelerated\n * properties which may adversely affect performance on slower devices, and is therefore\n * disabled by default.\n *\n * @example Example: Enable the transitioning of target widths and heights\n * var mixer = mixitup(containerEl, {\n * animation: {\n * animateResizeTargets: true\n * }\n * });\n *\n * @name animateResizeTargets\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default false\n */\n\n this.animateResizeTargets = false;\n\n /**\n * A custom function used to manipulate the order in which the stagger delay is\n * incremented when using the \u2018stagger\u2019 effect.\n *\n * When using the 'stagger' effect, the delay applied to each target element is incremented\n * based on its index. You may create a custom function to manipulate the order in which the\n * delay is incremented and create engaging non-linear stagger effects.\n *\n * The function receives the index of the target element as a parameter, and must\n * return an integer which serves as the multiplier for the stagger delay.\n *\n * @example Example 1: Stagger target elements by column in a 3-column grid\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effects: 'fade stagger(100ms)',\n * staggerSequence: function(i) {\n * return i % 3;\n * }\n * }\n * });\n *\n * @example Example 2: Using an algorithm to produce a more complex sequence\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effects: 'fade stagger(100ms)',\n * staggerSequence: function(i) {\n * return (2*i) - (5*((i/3) - ((1/3) * (i%3))));\n * }\n * }\n * });\n *\n * @name staggerSequence\n * @memberof mixitup.Config.animation\n * @instance\n * @type {function}\n * @default null\n */\n\n this.staggerSequence = null;\n\n /**\n * A boolean dictating whether or not to reverse the direction of `translate`\n * and `rotate` transforms for elements being filtered out.\n *\n * It can be used to create carousel-like animations where elements enter and exit\n * from opposite directions. If enabled, the effect `translateX(-100%)` for elements\n * being filtered in would become `translateX(100%)` for targets being filtered out.\n *\n * This functionality can also be achieved by providing seperate effects\n * strings for `config.animation.effectsIn` and `config.animation.effectsOut`.\n *\n * @example Example: Reverse the desired direction on any translate/rotate effect for targets being filtered out\n * // Elements being filtered in will be translated from '100%' to '0' while\n * // elements being filtered out will be translated from 0 to '-100%'\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * effects: 'fade translateX(100%)',\n * reverseOut: true,\n * nudge: false // Disable nudging to create a carousel-like effect\n * }\n * });\n *\n * @name reverseOut\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default false\n */\n\n this.reverseOut = false;\n\n /**\n * A boolean dictating whether or not to \"nudge\" the animation path of targets\n * when they are being filtered in and out simulatenously.\n *\n * This has been the default behavior of MixItUp since version 1, but it\n * may be desirable to disable this effect when filtering directly from\n * one exclusive set of targets to a different exclusive set of targets,\n * to create a carousel-like effect, or a generally more subtle animation.\n *\n * @example Example: Disable the \"nudging\" of targets being filtered in and out simulatenously\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * nudge: false\n * }\n * });\n *\n * @name nudge\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.nudge = true;\n\n /**\n * A boolean dictating whether or not to clamp the height of the container while MixItUp's\n * geometry tests are carried out before an operation.\n *\n * To prevent scroll-bar flicker, clamping is turned on by default. But in the case where the\n * height of the container might affect its vertical positioning in the viewport\n * (e.g. a vertically-centered container), this should be turned off to ensure accurate\n * test results and a smooth animation.\n *\n * @example Example: Disable container height-clamping\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * clampHeight: false\n * }\n * });\n *\n * @name clampHeight\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.clampHeight = true;\n\n /**\n * A boolean dictating whether or not to clamp the width of the container while MixItUp's\n * geometry tests are carried out before an operation.\n *\n * To prevent scroll-bar flicker, clamping is turned on by default. But in the case where the\n * width of the container might affect its horitzontal positioning in the viewport\n * (e.g. a horizontall-centered container), this should be turned off to ensure accurate\n * test results and a smooth animation.\n *\n * @example Example: Disable container width-clamping\n *\n * var mixer = mixitup(containerEl, {\n * animation: {\n * clampWidth: false\n * }\n * });\n *\n * @name clampWidth\n * @memberof mixitup.Config.animation\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.clampWidth = true;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigAnimation);\n\n mixitup.ConfigAnimation.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigAnimation.prototype.constructor = mixitup.ConfigAnimation;\n\n /**\n * A group of properties relating to the behavior of the Mixer.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name behavior\n * @namespace\n * @public\n * @since 3.1.12\n */\n\n mixitup.ConfigBehavior = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A boolean dictating whether to allow \"live\" sorting of the mixer.\n *\n * Because of the expensive nature of sorting, MixItUp makes use of several\n * internal optimizations to skip redundant sorting operations, such as when\n * the newly requested sort command is the same as the active one. The caveat\n * to this optimization is that \"live\" edits to the value of a target's sorting\n * attribute will be ignored when requesting a re-sort by the same attribute.\n *\n * By setting to `behavior.liveSort` to `true`, the mixer will always re-sort\n * regardless of whether or not the sorting attribute and order have changed.\n *\n * @example Example: Enabling `liveSort` to allow for re-sorting\n *\n * var mixer = mixitup(containerEl, {\n * behavior: {\n * liveSort: true\n * },\n * load: {\n * sort: 'edited:desc'\n * }\n * });\n *\n * var target = containerEl.children[3];\n *\n * console.log(target.getAttribute('data-edited')); // '2015-04-24'\n *\n * target.setAttribute('data-edited', '2017-08-10'); // Update the target's edited date\n *\n * mixer.sort('edited:desc')\n * .then(function(state) {\n * // The target is now at the top of the list\n *\n * console.log(state.targets[0] === target); // true\n * });\n *\n * @name liveSort\n * @memberof mixitup.Config.behavior\n * @instance\n * @type {boolean}\n * @default false\n */\n\n this.liveSort = false;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigBehavior);\n\n mixitup.ConfigBehavior.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigBehavior.prototype.constructor = mixitup.ConfigBehavior;\n\n /**\n * A group of optional callback functions to be invoked at various\n * points within the lifecycle of a mixer operation.\n *\n * Each function is analogous to an event of the same name triggered from the\n * container element, and is invoked immediately after it.\n *\n * All callback functions receive the current `state` object as their first\n * argument, as well as other more specific arguments described below.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name callbacks\n * @namespace\n * @public\n * @since 2.0.0\n */\n\n mixitup.ConfigCallbacks = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A callback function invoked immediately after any MixItUp operation is requested\n * and before animations have begun.\n *\n * A second `futureState` argument is passed to the function which represents the final\n * state of the mixer once the requested operation has completed.\n *\n * @example Example: Adding an `onMixStart` callback function\n * var mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixStart: function(state, futureState) {\n * console.log('Starting operation...');\n * }\n * }\n * });\n *\n * @name onMixStart\n * @memberof mixitup.Config.callbacks\n * @instance\n * @type {function}\n * @default null\n */\n\n this.onMixStart = null;\n\n /**\n * A callback function invoked when a MixItUp operation is requested while another\n * operation is in progress, and the animation queue is full, or queueing\n * is disabled.\n *\n * @example Example: Adding an `onMixBusy` callback function\n * var mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixBusy: function(state) {\n * console.log('Mixer busy');\n * }\n * }\n * });\n *\n * @name onMixBusy\n * @memberof mixitup.Config.callbacks\n * @instance\n * @type {function}\n * @default null\n */\n\n this.onMixBusy = null;\n\n /**\n * A callback function invoked after any MixItUp operation has completed, and the\n * state has been updated.\n *\n * @example Example: Adding an `onMixEnd` callback function\n * var mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixEnd: function(state) {\n * console.log('Operation complete');\n * }\n * }\n * });\n *\n * @name onMixEnd\n * @memberof mixitup.Config.callbacks\n * @instance\n * @type {function}\n * @default null\n */\n\n this.onMixEnd = null;\n\n /**\n * A callback function invoked whenever an operation \"fails\", i.e. no targets\n * could be found matching the requested filter.\n *\n * @example Example: Adding an `onMixFail` callback function\n * var mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixFail: function(state) {\n * console.log('No items could be found matching the requested filter');\n * }\n * }\n * });\n *\n * @name onMixFail\n * @memberof mixitup.Config.callbacks\n * @instance\n * @type {function}\n * @default null\n */\n\n this.onMixFail = null;\n\n /**\n * A callback function invoked whenever a MixItUp control is clicked, and before its\n * respective operation is requested.\n *\n * The clicked element is assigned to the `this` keyword within the function. The original\n * click event is passed to the function as the second argument, which can be useful if\n * using `` tags as controls where the default behavior needs to be prevented.\n *\n * Returning `false` from the callback will prevent the control click from triggering\n * an operation.\n *\n * @example Example 1: Adding an `onMixClick` callback function\n * var mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixClick: function(state, originalEvent) {\n * console.log('The control \"' + this.innerText + '\" was clicked');\n * }\n * }\n * });\n *\n * @example Example 2: Using `onMixClick` to manipulate the original click event\n * var mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixClick: function(state, originalEvent) {\n * // Prevent original click event from bubbling up:\n * originalEvent.stopPropagation();\n *\n * // Prevent default behavior of clicked element:\n * originalEvent.preventDefault();\n * }\n * }\n * });\n *\n * @example Example 3: Using `onMixClick` to conditionally cancel operations\n * var mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixClick: function(state, originalEvent) {\n * // Perform some conditional check:\n *\n * if (myApp.isLoading) {\n * // By returning false, we can prevent the control click from triggering an operation.\n *\n * return false;\n * }\n * }\n * }\n * });\n *\n * @name onMixClick\n * @memberof mixitup.Config.callbacks\n * @instance\n * @type {function}\n * @default null\n */\n\n this.onMixClick = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigCallbacks);\n\n mixitup.ConfigCallbacks.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigCallbacks.prototype.constructor = mixitup.ConfigCallbacks;\n\n /**\n * A group of properties relating to clickable control elements.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name controls\n * @namespace\n * @public\n * @since 2.0.0\n */\n\n mixitup.ConfigControls = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A boolean dictating whether or not controls should be enabled for the mixer instance.\n *\n * If `true` (default behavior), MixItUp will search the DOM for any clickable elements with\n * `data-filter`, `data-sort` or `data-toggle` attributes, and bind them for click events.\n *\n * If `false`, no click handlers will be bound, and all functionality must therefore be performed\n * via the mixer's API methods.\n *\n * If you do not intend to use the default controls, setting this property to `false` will\n * marginally improve the startup time of your mixer instance, and will also prevent any other active\n * mixer instances in the DOM which are bound to controls from controlling the instance.\n *\n * @example Example: Disabling controls\n * var mixer = mixitup(containerEl, {\n * controls: {\n * enable: false\n * }\n * });\n *\n * // With the default controls disabled, we can only control\n * // the mixer via its API methods, e.g.:\n *\n * mixer.filter('.cat-1');\n *\n * @name enable\n * @memberof mixitup.Config.controls\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.enable = true;\n\n /**\n * A boolean dictating whether or not to use event delegation when binding click events\n * to the default controls.\n *\n * If `false` (default behavior), each control button in the DOM will be found and\n * individually bound when a mixer is instantiated, with their corresponding actions\n * cached for performance.\n *\n * If `true`, a single click handler will be applied to the `window` (or container element - see\n * `config.controls.scope`), and any click events triggered by elements with `data-filter`,\n * `data-sort` or `data-toggle` attributes present will be handled as they propagate upwards.\n *\n * If you require a user interface where control buttons may be added, removed, or changed during the\n * lifetime of a mixer, `controls.live` should be set to `true`. There is a marginal but unavoidable\n * performance deficit when using live controls, as the value of each control button must be read\n * from the DOM in real time once the click event has propagated.\n *\n * @example Example: Setting live controls\n * var mixer = mixitup(containerEl, {\n * controls: {\n * live: true\n * }\n * });\n *\n * // Control buttons can now be added, remove and changed without breaking\n * // the mixer's UI\n *\n * @name live\n * @memberof mixitup.Config.controls\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.live = false;\n\n /**\n * A string dictating the \"scope\" to use when binding or querying the default controls. The available\n * values are `'global'` or `'local'`.\n *\n * When set to `'global'` (default behavior), MixItUp will query the entire document for control buttons\n * to bind, or delegate click events from (see `config.controls.live`).\n *\n * When set to `'local'`, MixItUp will only query (or bind click events to) its own container element.\n * This may be desireable if you require multiple active mixer instances within the same document, with\n * controls that would otherwise intefere with each other if scoped globally.\n *\n * Conversely, if you wish to control multiple instances with a single UI, you would create one\n * set of controls and keep the controls scope of each mixer set to `global`.\n *\n * @example Example: Setting 'local' scoped controls\n * var mixerOne = mixitup(containerOne, {\n * controls: {\n * scope: 'local'\n * }\n * });\n *\n * var mixerTwo = mixitup(containerTwo, {\n * controls: {\n * scope: 'local'\n * }\n * });\n *\n * // Both mixers can now exist within the same document with\n * // isolated controls placed within their container elements.\n *\n * @name scope\n * @memberof mixitup.Config.controls\n * @instance\n * @type {string}\n * @default 'global'\n */\n\n this.scope = 'global'; // enum: ['local' ,'global']\n\n /**\n * A string dictating the type of logic to apply when concatenating the filter selectors of\n * active toggle buttons (i.e. any clickable element with a `data-toggle` attribute).\n *\n * If set to `'or'` (default behavior), selectors will be concatenated together as\n * a comma-seperated list. For example:\n *\n * `'.cat-1, .cat-2'` (shows any elements matching `'.cat-1'` OR `'.cat-2'`)\n *\n * If set to `'and'`, selectors will be directly concatenated together. For example:\n *\n * `'.cat-1.cat-2'` (shows any elements which match both `'.cat-1'` AND `'.cat-2'`)\n *\n * @example Example: Setting \"and\" toggle logic\n * var mixer = mixitup(containerEl, {\n * controls: {\n * toggleLogic: 'and'\n * }\n * });\n *\n * @name toggleLogic\n * @memberof mixitup.Config.controls\n * @instance\n * @type {string}\n * @default 'or'\n */\n\n this.toggleLogic = 'or'; // enum: ['or', 'and']\n\n /**\n * A string dictating the filter behavior when all toggles are inactive.\n *\n * When set to `'all'` (default behavior), *all* targets will be shown by default\n * when no toggles are active, or at the moment all active toggles are toggled off.\n *\n * When set to `'none'`, no targets will be shown by default when no toggles are\n * active, or at the moment all active toggles are toggled off.\n *\n * @example Example 1: Setting the default toggle behavior to `'all'`\n * var mixer = mixitup(containerEl, {\n * controls: {\n * toggleDefault: 'all'\n * }\n * });\n *\n * mixer.toggleOn('.cat-2')\n * .then(function() {\n * // Deactivate all active toggles\n *\n * return mixer.toggleOff('.cat-2')\n * })\n * .then(function(state) {\n * console.log(state.activeFilter.selector); // 'all'\n * console.log(state.totalShow); // 12\n * });\n *\n * @example Example 2: Setting the default toggle behavior to `'none'`\n * var mixer = mixitup(containerEl, {\n * controls: {\n * toggleDefault: 'none'\n * }\n * });\n *\n * mixer.toggleOn('.cat-2')\n * .then(function() {\n * // Deactivate all active toggles\n *\n * return mixer.toggleOff('.cat-2')\n * })\n * .then(function(state) {\n * console.log(state.activeFilter.selector); // 'none'\n * console.log(state.totalShow); // 0\n * });\n *\n * @name toggleDefault\n * @memberof mixitup.Config.controls\n * @instance\n * @type {string}\n * @default 'all'\n */\n\n this.toggleDefault = 'all'; // enum: ['all', 'none']\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigControls);\n\n mixitup.ConfigControls.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigControls.prototype.constructor = mixitup.ConfigControls;\n\n /**\n * A group of properties defining the output and structure of class names programmatically\n * added to controls and containers to reflect the state of the mixer.\n *\n * Most commonly, class names are added to controls by MixItUp to indicate that\n * the control is active so that it can be styled accordingly - `'mixitup-control-active'` by default.\n *\n * Using a \"BEM\" like structure, each classname is broken into the three parts:\n * a block namespace (`'mixitup'`), an element name (e.g. `'control'`), and an optional modifier\n * name (e.g. `'active'`) reflecting the state of the element.\n *\n * By default, each part of the classname is concatenated together using single hyphens as\n * delineators, but this can be easily customised to match the naming convention and style of\n * your project.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name classNames\n * @namespace\n * @public\n * @since 3.0.0\n */\n\n mixitup.ConfigClassNames = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * The \"block\" portion, or top-level namespace added to the start of any class names created by MixItUp.\n *\n * @example Example 1: changing the `config.classNames.block` value\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * block: 'portfolio'\n * }\n * });\n *\n * // Active control output: \"portfolio-control-active\"\n *\n * @example Example 2: Removing `config.classNames.block`\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * block: ''\n * }\n * });\n *\n * // Active control output: \"control-active\"\n *\n * @name block\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'mixitup'\n */\n\n this.block = 'mixitup';\n\n /**\n * The \"element\" portion of the class name added to container.\n *\n * @name elementContainer\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'container'\n */\n\n this.elementContainer = 'container';\n\n /**\n * The \"element\" portion of the class name added to filter controls.\n *\n * By default, all filter, sort, multimix and toggle controls take the same element value of `'control'`, but\n * each type's element value can be individually overwritten to match the unique classNames of your controls as needed.\n *\n * @example Example 1: changing the `config.classNames.elementFilter` value\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * elementFilter: 'filter'\n * }\n * });\n *\n * // Active filter output: \"mixitup-filter-active\"\n *\n * @example Example 2: changing the `config.classNames.block` and `config.classNames.elementFilter` values\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * block: 'portfolio',\n * elementFilter: 'filter'\n * }\n * });\n *\n * // Active filter output: \"portfolio-filter-active\"\n *\n * @name elementFilter\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'control'\n */\n\n this.elementFilter = 'control';\n\n /**\n * The \"element\" portion of the class name added to sort controls.\n *\n * By default, all filter, sort, multimix and toggle controls take the same element value of `'control'`, but\n * each type's element value can be individually overwritten to match the unique classNames of your controls as needed.\n *\n * @example Example 1: changing the `config.classNames.elementSort` value\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * elementSort: 'sort'\n * }\n * });\n *\n * // Active sort output: \"mixitup-sort-active\"\n *\n * @example Example 2: changing the `config.classNames.block` and `config.classNames.elementSort` values\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * block: 'portfolio',\n * elementSort: 'sort'\n * }\n * });\n *\n * // Active sort output: \"portfolio-sort-active\"\n *\n * @name elementSort\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'control'\n */\n\n this.elementSort = 'control';\n\n /**\n * The \"element\" portion of the class name added to multimix controls.\n *\n * By default, all filter, sort, multimix and toggle controls take the same element value of `'control'`, but\n * each type's element value can be individually overwritten to match the unique classNames of your controls as needed.\n *\n * @example Example 1: changing the `config.classNames.elementMultimix` value\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * elementMultimix: 'multimix'\n * }\n * });\n *\n * // Active multimix output: \"mixitup-multimix-active\"\n *\n * @example Example 2: changing the `config.classNames.block` and `config.classNames.elementMultimix` values\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * block: 'portfolio',\n * elementSort: 'multimix'\n * }\n * });\n *\n * // Active multimix output: \"portfolio-multimix-active\"\n *\n * @name elementMultimix\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'control'\n */\n\n this.elementMultimix = 'control';\n\n /**\n * The \"element\" portion of the class name added to toggle controls.\n *\n * By default, all filter, sort, multimix and toggle controls take the same element value of `'control'`, but\n * each type's element value can be individually overwritten to match the unique classNames of your controls as needed.\n *\n * @example Example 1: changing the `config.classNames.elementToggle` value\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * elementToggle: 'toggle'\n * }\n * });\n *\n * // Active toggle output: \"mixitup-toggle-active\"\n *\n * @example Example 2: changing the `config.classNames.block` and `config.classNames.elementToggle` values\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * block: 'portfolio',\n * elementToggle: 'toggle'\n * }\n * });\n *\n * // Active toggle output: \"portfolio-toggle-active\"\n *\n * @name elementToggle\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'control'\n */\n\n this.elementToggle = 'control';\n\n /**\n * The \"modifier\" portion of the class name added to active controls.\n * @name modifierActive\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'active'\n */\n\n this.modifierActive = 'active';\n\n /**\n * The \"modifier\" portion of the class name added to disabled controls.\n *\n * @name modifierDisabled\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'disabled'\n */\n\n this.modifierDisabled = 'disabled';\n\n /**\n * The \"modifier\" portion of the class name added to the container when in a \"failed\" state.\n *\n * @name modifierFailed\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default 'failed'\n */\n\n this.modifierFailed = 'failed';\n\n /**\n * The delineator used between the \"block\" and \"element\" portions of any class name added by MixItUp.\n *\n * If the block portion is ommited by setting it to an empty string, no delineator will be added.\n *\n * @example Example: changing the delineator to match BEM convention\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * delineatorElement: '__'\n * }\n * });\n *\n * // example active control output: \"mixitup__control-active\"\n *\n * @name delineatorElement\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default '-'\n */\n\n this.delineatorElement = '-';\n\n /**\n * The delineator used between the \"element\" and \"modifier\" portions of any class name added by MixItUp.\n *\n * If the element portion is ommited by setting it to an empty string, no delineator will be added.\n *\n * @example Example: changing both delineators to match BEM convention\n * var mixer = mixitup(containerEl, {\n * classNames: {\n * delineatorElement: '__'\n * delineatorModifier: '--'\n * }\n * });\n *\n * // Active control output: \"mixitup__control--active\"\n *\n * @name delineatorModifier\n * @memberof mixitup.Config.classNames\n * @instance\n * @type {string}\n * @default '-'\n */\n\n this.delineatorModifier = '-';\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigClassNames);\n\n mixitup.ConfigClassNames.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigClassNames.prototype.constructor = mixitup.ConfigClassNames;\n\n /**\n * A group of properties relating to MixItUp's dataset API.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name data\n * @namespace\n * @public\n * @since 3.0.0\n */\n\n mixitup.ConfigData = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A string specifying the name of the key containing your data model's unique\n * identifier (UID). To use the dataset API, a UID key must be specified and\n * be present and unique on all objects in the dataset you provide to MixItUp.\n *\n * For example, if your dataset is made up of MongoDB documents, the UID\n * key would be `'id'` or `'_id'`.\n *\n * @example Example: Setting the UID to `'id'`\n * var mixer = mixitup(containerEl, {\n * data: {\n * uidKey: 'id'\n * }\n * });\n *\n * @name uidKey\n * @memberof mixitup.Config.data\n * @instance\n * @type {string}\n * @default ''\n */\n\n this.uidKey = '';\n\n /**\n * A boolean dictating whether or not MixItUp should \"dirty check\" each object in\n * your dataset for changes whenever `.dataset()` is called, and re-render any targets\n * for which a change is found.\n *\n * Depending on the complexity of your data model, dirty checking can be expensive\n * and is therefore disabled by default.\n *\n * NB: For changes to be detected, a new immutable instance of the edited model must be\n * provided to mixitup, rather than manipulating properties on the existing instance.\n * If your changes are a result of a DB write and read, you will most likely be calling\n * `.dataset()` with a clean set of objects each time, so this will not be an issue.\n *\n * @example Example: Enabling dirty checking\n *\n * var myDataset = [\n * {\n * id: 0,\n * title: \"Blog Post Title 0\"\n * ...\n * },\n * {\n * id: 1,\n * title: \"Blog Post Title 1\"\n * ...\n * }\n * ];\n *\n * // Instantiate a mixer with a pre-loaded dataset, and a target renderer\n * // function defined\n *\n * var mixer = mixitup(containerEl, {\n * data: {\n * uidKey: 'id',\n * dirtyCheck: true\n * },\n * load: {\n * dataset: myDataset\n * },\n * render: {\n * target: function() { ... }\n * }\n * });\n *\n * // For illustration, we will clone and edit the second object in the dataset.\n * // NB: this would typically be done server-side in response to a DB update,\n * and then re-queried via an API.\n *\n * myDataset[1] = Object.assign({}, myDataset[1]);\n *\n * myDataset[1].title = 'Blog Post Title 11';\n *\n * mixer.dataset(myDataset)\n * .then(function() {\n * // the target with ID \"1\", will be re-rendered reflecting its new title\n * });\n *\n * @name dirtyCheck\n * @memberof mixitup.Config.data\n * @instance\n * @type {boolean}\n * @default false\n */\n\n this.dirtyCheck = false;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigData);\n\n mixitup.ConfigData.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigData.prototype.constructor = mixitup.ConfigData;\n\n /**\n * A group of properties allowing the toggling of various debug features.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name debug\n * @namespace\n * @public\n * @since 3.0.0\n */\n\n mixitup.ConfigDebug = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A boolean dictating whether or not the mixer instance returned by the\n * `mixitup()` factory function should expose private properties and methods.\n *\n * By default, mixer instances only expose their public API, but enabling\n * debug mode will give you access to various mixer internals which may aid\n * in debugging, or the authoring of extensions.\n *\n * @example Example: Enabling debug mode\n *\n * var mixer = mixitup(containerEl, {\n * debug: {\n * enable: true\n * }\n * });\n *\n * // Private properties and methods will now be visible on the mixer instance:\n *\n * console.log(mixer);\n *\n * @name enable\n * @memberof mixitup.Config.debug\n * @instance\n * @type {boolean}\n * @default false\n */\n\n this.enable = false;\n\n /**\n * A boolean dictating whether or not warnings should be shown when various\n * common gotchas occur.\n *\n * Warnings are intended to provide insights during development when something\n * occurs that is not a fatal, but may indicate an issue with your integration,\n * and are therefore turned on by default. However, you may wish to disable\n * them in production.\n *\n * @example Example 1: Disabling warnings\n *\n * var mixer = mixitup(containerEl, {\n * debug: {\n * showWarnings: false\n * }\n * });\n *\n * @example Example 2: Disabling warnings based on environment\n *\n * var showWarnings = myAppConfig.environment === 'development' ? true : false;\n *\n * var mixer = mixitup(containerEl, {\n * debug: {\n * showWarnings: showWarnings\n * }\n * });\n *\n * @name showWarnings\n * @memberof mixitup.Config.debug\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.showWarnings = true;\n\n /**\n * Used for server-side testing only.\n *\n * @private\n * @name fauxAsync\n * @memberof mixitup.Config.debug\n * @instance\n * @type {boolean}\n * @default false\n */\n\n this.fauxAsync = false;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigDebug);\n\n mixitup.ConfigDebug.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigDebug.prototype.constructor = mixitup.ConfigDebug;\n\n /**\n * A group of properties relating to the layout of the container.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name layout\n * @namespace\n * @public\n * @since 3.0.0\n */\n\n mixitup.ConfigLayout = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A boolean dictating whether or not mixitup should query all descendants\n * of the container for targets, or only immediate children.\n *\n * By default, mixitup will query all descendants matching the\n * `selectors.target` selector when indexing targets upon instantiation.\n * This allows for targets to be nested inside a sub-container which is\n * useful when ring-fencing targets from locally scoped controls in your\n * markup (see `controls.scope`).\n *\n * However, if you are building a more complex UI requiring the nesting\n * of mixers within mixers, you will most likely want to limit targets to\n * immediate children of the container by setting this property to `false`.\n *\n * @example Example: Restricting targets to immediate children\n *\n * var mixer = mixitup(containerEl, {\n * layout: {\n * allowNestedTargets: false\n * }\n * });\n *\n * @name allowNestedTargets\n * @memberof mixitup.Config.layout\n * @instance\n * @type {boolean}\n * @default true\n */\n\n this.allowNestedTargets = true;\n\n /**\n * A string specifying an optional class name to apply to the container when in\n * its default state.\n *\n * By changing this class name or adding a class name to the container via the\n * `.changeLayout()` API method, the CSS layout of the container can be changed,\n * and MixItUp will attemp to gracefully animate the container and its targets\n * between states.\n *\n * @example Example 1: Specifying a container class name\n *\n * var mixer = mixitup(containerEl, {\n * layout: {\n * containerClassName: 'grid'\n * }\n * });\n *\n * @example Example 2: Changing the default class name with `.changeLayout()`\n *\n * var mixer = mixitup(containerEl, {\n * layout: {\n * containerClassName: 'grid'\n * }\n * });\n *\n * mixer.changeLayout('list')\n * .then(function(state) {\n * console.log(state.activeContainerClass); // \"list\"\n * });\n *\n * @name containerClassName\n * @memberof mixitup.Config.layout\n * @instance\n * @type {string}\n * @default ''\n */\n\n this.containerClassName = '';\n\n /**\n * A reference to a non-target sibling element after which to insert targets\n * when there are no targets in the container.\n *\n * @example Example: Setting a `siblingBefore` reference element\n *\n * var addButton = containerEl.querySelector('button');\n *\n * var mixer = mixitup(containerEl, {\n * layout: {\n * siblingBefore: addButton\n * }\n * });\n *\n * @name siblingBefore\n * @memberof mixitup.Config.layout\n * @instance\n * @type {HTMLElement}\n * @default null\n */\n\n this.siblingBefore = null;\n\n /**\n * A reference to a non-target sibling element before which to insert targets\n * when there are no targets in the container.\n *\n * @example Example: Setting an `siblingAfter` reference element\n *\n * var gap = containerEl.querySelector('.gap');\n *\n * var mixer = mixitup(containerEl, {\n * layout: {\n * siblingAfter: gap\n * }\n * });\n *\n * @name siblingAfter\n * @memberof mixitup.Config.layout\n * @instance\n * @type {HTMLElement}\n * @default null\n */\n\n this.siblingAfter = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigLayout);\n\n mixitup.ConfigLayout.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigLayout.prototype.constructor = mixitup.ConfigLayout;\n\n /**\n * A group of properties defining the initial state of the mixer on load (instantiation).\n *\n * @constructor\n * @memberof mixitup.Config\n * @name load\n * @namespace\n * @public\n * @since 2.0.0\n */\n\n mixitup.ConfigLoad = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A string defining any filtering to be statically applied to the mixer on load.\n * As per the `.filter()` API, this can be any valid selector string, or the\n * values `'all'` or `'none'`.\n *\n * @example Example 1: Defining an initial filter selector to be applied on load\n *\n * // The mixer will show only those targets matching '.category-a' on load.\n *\n * var mixer = mixitup(containerEl, {\n * load: {\n * filter: '.category-a'\n * }\n * });\n *\n * @example Example 2: Hiding all targets on load\n *\n * // The mixer will show hide all targets on load.\n *\n * var mixer = mixitup(containerEl, {\n * load: {\n * filter: 'none'\n * }\n * });\n *\n * @name filter\n * @memberof mixitup.Config.load\n * @instance\n * @type {string}\n * @default 'all'\n */\n\n this.filter = 'all';\n\n /**\n * A string defining any sorting to be statically applied to the mixer on load.\n * As per the `.sort()` API, this should be a valid \"sort string\" made up of\n * an attribute to sort by (or `'default'`) followed by an optional sorting\n * order, or the value `'random'`;\n *\n * @example Example: Defining sorting to be applied on load\n *\n * // The mixer will sort the container by the value of the `data-published-date`\n * // attribute, in descending order.\n *\n * var mixer = mixitup(containerEl, {\n * load: {\n * sort: 'published-date:desc'\n * }\n * });\n *\n * @name sort\n * @memberof mixitup.Config.load\n * @instance\n * @type {string}\n * @default 'default:asc'\n */\n\n this.sort = 'default:asc';\n\n /**\n * An array of objects representing the underlying data of any pre-rendered targets,\n * when using the `.dataset()` API.\n *\n * NB: If targets are pre-rendered when the mixer is instantiated, this must be set.\n *\n * @example Example: Defining the initial underyling dataset\n *\n * var myDataset = [\n * {\n * id: 0,\n * title: \"Blog Post Title 0\",\n * ...\n * },\n * {\n * id: 1,\n * title: \"Blog Post Title 1\",\n * ...\n * }\n * ];\n *\n * var mixer = mixitup(containerEl, {\n * data: {\n * uidKey: 'id'\n * },\n * load: {\n * dataset: myDataset\n * }\n * });\n *\n * @name dataset\n * @memberof mixitup.Config.load\n * @instance\n * @type {Array.}\n * @default null\n */\n\n this.dataset = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigLoad);\n\n mixitup.ConfigLoad.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigLoad.prototype.constructor = mixitup.ConfigLoad;\n\n /**\n * A group of properties defining the selectors used to query elements within a mixitup container.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name selectors\n * @namespace\n * @public\n * @since 3.0.0\n */\n\n mixitup.ConfigSelectors = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A selector string used to query and index target elements within the container.\n *\n * By default, the class selector `'.mix'` is used, but this can be changed to an\n * attribute or element selector to match the style of your project.\n *\n * @example Example 1: Changing the target selector\n *\n * var mixer = mixitup(containerEl, {\n * selectors: {\n * target: '.portfolio-item'\n * }\n * });\n *\n * @example Example 2: Using an attribute selector as a target selector\n *\n * // The mixer will search for any children with the attribute `data-ref=\"mix\"`\n *\n * var mixer = mixitup(containerEl, {\n * selectors: {\n * target: '[data-ref=\"mix\"]'\n * }\n * });\n *\n * @name target\n * @memberof mixitup.Config.selectors\n * @instance\n * @type {string}\n * @default '.mix'\n */\n\n this.target = '.mix';\n\n /**\n * A optional selector string used to add further specificity to the querying of control elements,\n * in addition to their mandatory data attribute (e.g. `data-filter`, `data-toggle`, `data-sort`).\n *\n * This can be used if other elements in your document must contain the above attributes\n * (e.g. for use in third-party scripts), and would otherwise interfere with MixItUp. Adding\n * an additional `control` selector of your choice allows MixItUp to restrict event handling\n * to only those elements matching the defined selector.\n *\n * @name control\n * @memberof mixitup.Config.selectors\n * @instance\n * @type {string}\n * @default ''\n *\n * @example Example 1: Adding a `selectors.control` selector\n *\n * var mixer = mixitup(containerEl, {\n * selectors: {\n * control: '.mixitup-control'\n * }\n * });\n *\n * // Will not be handled:\n * // \n *\n * // Will be handled:\n * // \n */\n\n this.control = '';\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigSelectors);\n\n mixitup.ConfigSelectors.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigSelectors.prototype.constructor = mixitup.ConfigSelectors;\n\n /**\n * A group of optional render functions for creating and updating elements.\n *\n * All render functions receive a data object, and should return a valid HTML string.\n *\n * @constructor\n * @memberof mixitup.Config\n * @name render\n * @namespace\n * @public\n * @since 3.0.0\n */\n\n mixitup.ConfigRender = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A function returning an HTML string representing a target element, or a reference to a\n * single DOM element.\n *\n * The function is invoked as part of the `.dataset()` API, whenever a new item is added\n * to the dataset, or an item in the dataset changes (if `dataset.dirtyCheck` is enabled).\n *\n * The function receives the relevant dataset item as its first parameter.\n *\n * @example Example 1: Using string concatenation\n *\n * var mixer = mixitup(containerEl, {\n * render: {\n * target: function(item) {\n * return (\n * '<div class=\"mix\">' +\n * '<h2>' + item.title + '</h2>' +\n * '</div>'\n * );\n * }\n * }\n * });\n *\n * @example Example 2: Using an ES2015 template literal\n *\n * var mixer = mixitup(containerEl, {\n * render: {\n * target: function(item) {\n * return (\n * `<div class=\"mix\">\n * <h2>${item.title}</h2>\n * </div>`\n * );\n * }\n * }\n * });\n *\n * @example Example 3: Using a Handlebars template\n *\n * var targetTemplate = Handlebars.compile('<div class=\"mix\"><h2>{{title}}</h2></div>');\n *\n * var mixer = mixitup(containerEl, {\n * render: {\n * target: targetTemplate\n * }\n * });\n *\n * @example Example 4: Returning a DOM element\n *\n * var mixer = mixitup(containerEl, {\n * render: {\n * target: function(item) {\n * // Create a single element using your framework's built-in renderer\n *\n * var el = ...\n *\n * return el;\n * }\n * }\n * });\n *\n * @name target\n * @memberof mixitup.Config.render\n * @instance\n * @type {function}\n * @default 'null'\n */\n\n this.target = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigRender);\n\n mixitup.ConfigRender.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigRender.prototype.constructor = mixitup.ConfigRender;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.ConfigTemplates = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ConfigTemplates);\n\n mixitup.ConfigTemplates.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ConfigTemplates.prototype.constructor = mixitup.ConfigTemplates;\n\n /**\n * `mixitup.Config` is an interface used for customising the functionality of a\n * mixer instance. It is organised into several semantically distinct sub-objects,\n * each one pertaining to a particular aspect of MixItUp functionality.\n *\n * An object literal containing any or all of the available properies,\n * known as the \"configuration object\", can be passed as the second parameter to\n * the `mixitup` factory function when creating a mixer instance to customise its\n * functionality as needed.\n *\n * If no configuration object is passed, the mixer instance will take on the default\n * configuration values detailed below.\n *\n * @example Example 1: Creating and passing the configuration object\n * // Create a configuration object with desired values\n *\n * var config = {\n * animation: {\n * enable: false\n * },\n * selectors: {\n * target: '.item'\n * }\n * };\n *\n * // Pass the configuration object to the mixitup factory function\n *\n * var mixer = mixitup(containerEl, config);\n *\n * @example Example 2: Passing the configuration object inline\n * // Typically, the configuration object is passed inline for brevity.\n *\n * var mixer = mixitup(containerEl, {\n * controls: {\n * live: true,\n * toggleLogic: 'and'\n * }\n * });\n *\n *\n * @constructor\n * @memberof mixitup\n * @namespace\n * @public\n * @since 2.0.0\n */\n\n mixitup.Config = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.animation = new mixitup.ConfigAnimation();\n this.behavior = new mixitup.ConfigBehavior();\n this.callbacks = new mixitup.ConfigCallbacks();\n this.controls = new mixitup.ConfigControls();\n this.classNames = new mixitup.ConfigClassNames();\n this.data = new mixitup.ConfigData();\n this.debug = new mixitup.ConfigDebug();\n this.layout = new mixitup.ConfigLayout();\n this.load = new mixitup.ConfigLoad();\n this.selectors = new mixitup.ConfigSelectors();\n this.render = new mixitup.ConfigRender();\n this.templates = new mixitup.ConfigTemplates();\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Config);\n\n mixitup.Config.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.Config.prototype.constructor = mixitup.Config;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.MixerDom = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.document = null;\n this.body = null;\n this.container = null;\n this.parent = null;\n this.targets = [];\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.MixerDom);\n\n mixitup.MixerDom.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.MixerDom.prototype.constructor = mixitup.MixerDom;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.UiClassNames = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.base = '';\n this.active = '';\n this.disabled = '';\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.UiClassNames);\n\n mixitup.UiClassNames.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.UiClassNames.prototype.constructor = mixitup.UiClassNames;\n\n /**\n * An object into which all arbitrary arguments sent to '.dataset()' are mapped.\n *\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.CommandDataset = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.dataset = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.CommandDataset);\n\n mixitup.CommandDataset.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.CommandDataset.prototype.constructor = mixitup.CommandDataset;\n\n /**\n * An object into which all arbitrary arguments sent to '.multimix()' are mapped.\n *\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.CommandMultimix = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.filter = null;\n this.sort = null;\n this.insert = null;\n this.remove = null;\n this.changeLayout = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.CommandMultimix);\n\n mixitup.CommandMultimix.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.CommandMultimix.prototype.constructor = mixitup.CommandMultimix;\n\n /**\n * An object into which all arbitrary arguments sent to '.filter()' are mapped.\n *\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.CommandFilter = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.selector = '';\n this.collection = null;\n this.action = 'show'; // enum: ['show', 'hide']\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.CommandFilter);\n\n mixitup.CommandFilter.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.CommandFilter.prototype.constructor = mixitup.CommandFilter;\n\n /**\n * An object into which all arbitrary arguments sent to '.sort()' are mapped.\n *\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.CommandSort = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.sortString = '';\n this.attribute = '';\n this.order = 'asc';\n this.collection = null;\n this.next = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.CommandSort);\n\n mixitup.CommandSort.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.CommandSort.prototype.constructor = mixitup.CommandSort;\n\n /**\n * An object into which all arbitrary arguments sent to '.insert()' are mapped.\n *\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.CommandInsert = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.index = 0;\n this.collection = [];\n this.position = 'before'; // enum: ['before', 'after']\n this.sibling = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.CommandInsert);\n\n mixitup.CommandInsert.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.CommandInsert.prototype.constructor = mixitup.CommandInsert;\n\n /**\n * An object into which all arbitrary arguments sent to '.remove()' are mapped.\n *\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.CommandRemove = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.targets = [];\n this.collection = [];\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.CommandRemove);\n\n mixitup.CommandRemove.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.CommandRemove.prototype.constructor = mixitup.CommandRemove;\n\n /**\n * An object into which all arbitrary arguments sent to '.changeLayout()' are mapped.\n *\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.CommandChangeLayout = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.containerClassName = '';\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.CommandChangeLayout);\n\n mixitup.CommandChangeLayout.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.CommandChangeLayout.prototype.constructor = mixitup.CommandChangeLayout;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n * @param {string} type\n * @param {string} selector\n * @param {boolean} [live]\n * @param {string} [parent]\n * An optional string representing the name of the mixer.dom property containing a reference to a parent element.\n */\n\n mixitup.ControlDefinition = function(type, selector, live, parent) {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.type = type;\n this.selector = selector;\n this.live = live || false;\n this.parent = parent || '';\n\n this.callActions('afterConstruct');\n\n h.freeze(this);\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.ControlDefinition);\n\n mixitup.ControlDefinition.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.ControlDefinition.prototype.constructor = mixitup.ControlDefinition;\n\n mixitup.controlDefinitions = [];\n\n mixitup.controlDefinitions.push(new mixitup.ControlDefinition('multimix', '[data-filter][data-sort]'));\n mixitup.controlDefinitions.push(new mixitup.ControlDefinition('filter', '[data-filter]'));\n mixitup.controlDefinitions.push(new mixitup.ControlDefinition('sort', '[data-sort]'));\n mixitup.controlDefinitions.push(new mixitup.ControlDefinition('toggle', '[data-toggle]'));\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.Control = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.el = null;\n this.selector = '';\n this.bound = [];\n this.pending = -1;\n this.type = '';\n this.status = 'inactive'; // enum: ['inactive', 'active', 'disabled', 'live']\n this.filter = '';\n this.sort = '';\n this.canDisable = false;\n this.handler = null;\n this.classNames = new mixitup.UiClassNames();\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Control);\n\n mixitup.Control.prototype = Object.create(mixitup.Base.prototype);\n\n h.extend(mixitup.Control.prototype,\n /** @lends mixitup.Control */\n {\n constructor: mixitup.Control,\n\n /**\n * @private\n * @param {HTMLElement} el\n * @param {string} type\n * @param {string} selector\n */\n\n init: function(el, type, selector) {\n var self = this;\n\n this.callActions('beforeInit', arguments);\n\n self.el = el;\n self.type = type;\n self.selector = selector;\n\n if (self.selector) {\n self.status = 'live';\n } else {\n self.canDisable = typeof self.el.disable === 'boolean';\n\n switch (self.type) {\n case 'filter':\n self.filter = self.el.getAttribute('data-filter');\n\n break;\n case 'toggle':\n self.filter = self.el.getAttribute('data-toggle');\n\n break;\n case 'sort':\n self.sort = self.el.getAttribute('data-sort');\n\n break;\n case 'multimix':\n self.filter = self.el.getAttribute('data-filter');\n self.sort = self.el.getAttribute('data-sort');\n\n break;\n }\n }\n\n self.bindClick();\n\n mixitup.controls.push(self);\n\n this.callActions('afterInit', arguments);\n },\n\n /**\n * @private\n * @param {mixitup.Mixer} mixer\n * @return {boolean}\n */\n\n isBound: function(mixer) {\n var self = this,\n isBound = false;\n\n this.callActions('beforeIsBound', arguments);\n\n isBound = self.bound.indexOf(mixer) > -1;\n\n return self.callFilters('afterIsBound', isBound, arguments);\n },\n\n /**\n * @private\n * @param {mixitup.Mixer} mixer\n * @return {void}\n */\n\n addBinding: function(mixer) {\n var self = this;\n\n this.callActions('beforeAddBinding', arguments);\n\n if (!self.isBound()) {\n self.bound.push(mixer);\n }\n\n this.callActions('afterAddBinding', arguments);\n },\n\n /**\n * @private\n * @param {mixitup.Mixer} mixer\n * @return {void}\n */\n\n removeBinding: function(mixer) {\n var self = this,\n removeIndex = -1;\n\n this.callActions('beforeRemoveBinding', arguments);\n\n if ((removeIndex = self.bound.indexOf(mixer)) > -1) {\n self.bound.splice(removeIndex, 1);\n }\n\n if (self.bound.length < 1) {\n // No bindings exist, unbind event click handlers\n\n self.unbindClick();\n\n // Remove from `mixitup.controls` list\n\n removeIndex = mixitup.controls.indexOf(self);\n\n mixitup.controls.splice(removeIndex, 1);\n\n if (self.status === 'active') {\n self.renderStatus(self.el, 'inactive');\n }\n }\n\n this.callActions('afterRemoveBinding', arguments);\n },\n\n /**\n * @private\n * @return {void}\n */\n\n bindClick: function() {\n var self = this;\n\n this.callActions('beforeBindClick', arguments);\n\n self.handler = function(e) {\n self.handleClick(e);\n };\n\n h.on(self.el, 'click', self.handler);\n\n this.callActions('afterBindClick', arguments);\n },\n\n /**\n * @private\n * @return {void}\n */\n\n unbindClick: function() {\n var self = this;\n\n this.callActions('beforeUnbindClick', arguments);\n\n h.off(self.el, 'click', self.handler);\n\n self.handler = null;\n\n this.callActions('afterUnbindClick', arguments);\n },\n\n /**\n * @private\n * @param {MouseEvent} e\n * @return {void}\n */\n\n handleClick: function(e) {\n var self = this,\n button = null,\n mixer = null,\n isActive = false,\n returnValue = void(0),\n command = {},\n clone = null,\n commands = [],\n i = -1;\n\n this.callActions('beforeHandleClick', arguments);\n\n this.pending = 0;\n\n mixer = self.bound[0];\n\n if (!self.selector) {\n button = self.el;\n } else {\n button = h.closestParent(e.target, mixer.config.selectors.control + self.selector, true, mixer.dom.document);\n }\n\n if (!button) {\n self.callActions('afterHandleClick', arguments);\n\n return;\n }\n\n switch (self.type) {\n case 'filter':\n command.filter = self.filter || button.getAttribute('data-filter');\n\n break;\n case 'sort':\n command.sort = self.sort || button.getAttribute('data-sort');\n\n break;\n case 'multimix':\n command.filter = self.filter || button.getAttribute('data-filter');\n command.sort = self.sort || button.getAttribute('data-sort');\n\n break;\n case 'toggle':\n command.filter = self.filter || button.getAttribute('data-toggle');\n\n if (self.status === 'live') {\n isActive = h.hasClass(button, self.classNames.active);\n } else {\n isActive = self.status === 'active';\n }\n\n break;\n }\n\n for (i = 0; i < self.bound.length; i++) {\n // Create a clone of the command for each bound mixer instance\n\n clone = new mixitup.CommandMultimix();\n\n h.extend(clone, command);\n\n commands.push(clone);\n }\n\n commands = self.callFilters('commandsHandleClick', commands, arguments);\n\n self.pending = self.bound.length;\n\n for (i = 0; mixer = self.bound[i]; i++) {\n command = commands[i];\n\n if (!command) {\n // An extension may set a command null to indicate that the click should not be handled\n\n continue;\n }\n\n if (!mixer.lastClicked) {\n mixer.lastClicked = button;\n }\n\n mixitup.events.fire('mixClick', mixer.dom.container, {\n state: mixer.state,\n instance: mixer,\n originalEvent: e,\n control: mixer.lastClicked\n }, mixer.dom.document);\n\n if (typeof mixer.config.callbacks.onMixClick === 'function') {\n returnValue = mixer.config.callbacks.onMixClick.call(mixer.lastClicked, mixer.state, e, mixer);\n\n if (returnValue === false) {\n // User has returned `false` from the callback, so do not handle click\n\n continue;\n }\n }\n\n if (self.type === 'toggle') {\n isActive ? mixer.toggleOff(command.filter) : mixer.toggleOn(command.filter);\n } else {\n mixer.multimix(command);\n }\n }\n\n this.callActions('afterHandleClick', arguments);\n },\n\n /**\n * @param {object} command\n * @param {Array} toggleArray\n * @return {void}\n */\n\n update: function(command, toggleArray) {\n var self = this,\n actions = new mixitup.CommandMultimix();\n\n self.callActions('beforeUpdate', arguments);\n\n self.pending--;\n\n self.pending = Math.max(0, self.pending);\n\n if (self.pending > 0) return;\n\n if (self.status === 'live') {\n // Live control (status unknown)\n\n self.updateLive(command, toggleArray);\n } else {\n // Static control\n\n actions.sort = self.sort;\n actions.filter = self.filter;\n\n self.callFilters('actionsUpdate', actions, arguments);\n\n self.parseStatusChange(self.el, command, actions, toggleArray);\n }\n\n self.callActions('afterUpdate', arguments);\n },\n\n /**\n * @param {mixitup.CommandMultimix} command\n * @param {Array} toggleArray\n * @return {void}\n */\n\n updateLive: function(command, toggleArray) {\n var self = this,\n controlButtons = null,\n actions = null,\n button = null,\n i = -1;\n\n self.callActions('beforeUpdateLive', arguments);\n\n if (!self.el) return;\n\n controlButtons = self.el.querySelectorAll(self.selector);\n\n for (i = 0; button = controlButtons[i]; i++) {\n actions = new mixitup.CommandMultimix();\n\n switch (self.type) {\n case 'filter':\n actions.filter = button.getAttribute('data-filter');\n\n break;\n case 'sort':\n actions.sort = button.getAttribute('data-sort');\n\n break;\n case 'multimix':\n actions.filter = button.getAttribute('data-filter');\n actions.sort = button.getAttribute('data-sort');\n\n break;\n case 'toggle':\n actions.filter = button.getAttribute('data-toggle');\n\n break;\n }\n\n actions = self.callFilters('actionsUpdateLive', actions, arguments);\n\n self.parseStatusChange(button, command, actions, toggleArray);\n }\n\n self.callActions('afterUpdateLive', arguments);\n },\n\n /**\n * @param {HTMLElement} button\n * @param {mixitup.CommandMultimix} command\n * @param {mixitup.CommandMultimix} actions\n * @param {Array} toggleArray\n * @return {void}\n */\n\n parseStatusChange: function(button, command, actions, toggleArray) {\n var self = this,\n alias = '',\n toggle = '',\n i = -1;\n\n self.callActions('beforeParseStatusChange', arguments);\n\n switch (self.type) {\n case 'filter':\n if (command.filter === actions.filter) {\n self.renderStatus(button, 'active');\n } else {\n self.renderStatus(button, 'inactive');\n }\n\n break;\n case 'multimix':\n if (command.sort === actions.sort && command.filter === actions.filter) {\n self.renderStatus(button, 'active');\n } else {\n self.renderStatus(button, 'inactive');\n }\n\n break;\n case 'sort':\n if (command.sort.match(/:asc/g)) {\n alias = command.sort.replace(/:asc/g, '');\n }\n\n if (command.sort === actions.sort || alias === actions.sort) {\n self.renderStatus(button, 'active');\n } else {\n self.renderStatus(button, 'inactive');\n }\n\n break;\n case 'toggle':\n if (toggleArray.length < 1) self.renderStatus(button, 'inactive');\n\n if (command.filter === actions.filter) {\n self.renderStatus(button, 'active');\n }\n\n for (i = 0; i < toggleArray.length; i++) {\n toggle = toggleArray[i];\n\n if (toggle === actions.filter) {\n // Button matches one active toggle\n\n self.renderStatus(button, 'active');\n\n break;\n }\n\n self.renderStatus(button, 'inactive');\n }\n\n break;\n }\n\n self.callActions('afterParseStatusChange', arguments);\n },\n\n /**\n * @param {HTMLElement} button\n * @param {string} status\n * @return {void}\n */\n\n renderStatus: function(button, status) {\n var self = this;\n\n self.callActions('beforeRenderStatus', arguments);\n\n switch (status) {\n case 'active':\n h.addClass(button, self.classNames.active);\n h.removeClass(button, self.classNames.disabled);\n\n if (self.canDisable) self.el.disabled = false;\n\n break;\n case 'inactive':\n h.removeClass(button, self.classNames.active);\n h.removeClass(button, self.classNames.disabled);\n\n if (self.canDisable) self.el.disabled = false;\n\n break;\n case 'disabled':\n if (self.canDisable) self.el.disabled = true;\n\n h.addClass(button, self.classNames.disabled);\n h.removeClass(button, self.classNames.active);\n\n break;\n }\n\n if (self.status !== 'live') {\n // Update the control's status propery if not live\n\n self.status = status;\n }\n\n self.callActions('afterRenderStatus', arguments);\n }\n });\n\n mixitup.controls = [];\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.StyleData = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.x = 0;\n this.y = 0;\n this.top = 0;\n this.right = 0;\n this.bottom = 0;\n this.left = 0;\n this.width = 0;\n this.height = 0;\n this.marginRight = 0;\n this.marginBottom = 0;\n this.opacity = 0;\n this.scale = new mixitup.TransformData();\n this.translateX = new mixitup.TransformData();\n this.translateY = new mixitup.TransformData();\n this.translateZ = new mixitup.TransformData();\n this.rotateX = new mixitup.TransformData();\n this.rotateY = new mixitup.TransformData();\n this.rotateZ = new mixitup.TransformData();\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.StyleData);\n\n mixitup.StyleData.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.StyleData.prototype.constructor = mixitup.StyleData;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.TransformData = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.value = 0;\n this.unit = '';\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.TransformData);\n\n mixitup.TransformData.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.TransformData.prototype.constructor = mixitup.TransformData;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.TransformDefaults = function() {\n mixitup.StyleData.apply(this);\n\n this.callActions('beforeConstruct');\n\n this.scale.value = 0.01;\n this.scale.unit = '';\n\n this.translateX.value = 20;\n this.translateX.unit = 'px';\n\n this.translateY.value = 20;\n this.translateY.unit = 'px';\n\n this.translateZ.value = 20;\n this.translateZ.unit = 'px';\n\n this.rotateX.value = 90;\n this.rotateX.unit = 'deg';\n\n this.rotateY.value = 90;\n this.rotateY.unit = 'deg';\n\n this.rotateX.value = 90;\n this.rotateX.unit = 'deg';\n\n this.rotateZ.value = 180;\n this.rotateZ.unit = 'deg';\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.TransformDefaults);\n\n mixitup.TransformDefaults.prototype = Object.create(mixitup.StyleData.prototype);\n\n mixitup.TransformDefaults.prototype.constructor = mixitup.TransformDefaults;\n\n /**\n * @private\n * @static\n * @since 3.0.0\n * @type {mixitup.TransformDefaults}\n */\n\n mixitup.transformDefaults = new mixitup.TransformDefaults();\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.EventDetail = function() {\n this.state = null;\n this.futureState = null;\n this.instance = null;\n this.originalEvent = null;\n };\n\n /**\n * The `mixitup.Events` class contains all custom events dispatched by MixItUp at various\n * points within the lifecycle of a mixer operation.\n *\n * Each event is analogous to the callback function of the same name defined in\n * the `callbacks` configuration object, and is triggered immediately before it.\n *\n * Events are always triggered from the container element on which MixItUp is instantiated\n * upon.\n *\n * As with any event, registered event handlers receive the event object as a parameter\n * which includes a `detail` property containting references to the current `state`,\n * the `mixer` instance, and other event-specific properties described below.\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @public\n * @since 3.0.0\n */\n\n mixitup.Events = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * A custom event triggered immediately after any MixItUp operation is requested\n * and before animations have begun.\n *\n * The `mixStart` event also exposes a `futureState` property via the\n * `event.detail` object, which represents the final state of the mixer once\n * the requested operation has completed.\n *\n * @name mixStart\n * @memberof mixitup.Events\n * @static\n * @type {CustomEvent}\n */\n\n this.mixStart = null;\n\n /**\n * A custom event triggered when a MixItUp operation is requested while another\n * operation is in progress, and the animation queue is full, or queueing\n * is disabled.\n *\n * @name mixBusy\n * @memberof mixitup.Events\n * @static\n * @type {CustomEvent}\n */\n\n this.mixBusy = null;\n\n /**\n * A custom event triggered after any MixItUp operation has completed, and the\n * state has been updated.\n *\n * @name mixEnd\n * @memberof mixitup.Events\n * @static\n * @type {CustomEvent}\n */\n\n this.mixEnd = null;\n\n /**\n * A custom event triggered whenever a filter operation \"fails\", i.e. no targets\n * could be found matching the requested filter.\n *\n * @name mixFail\n * @memberof mixitup.Events\n * @static\n * @type {CustomEvent}\n */\n\n this.mixFail = null;\n\n /**\n * A custom event triggered whenever a MixItUp control is clicked, and before its\n * respective operation is requested.\n *\n * This event also exposes an `originalEvent` property via the `event.detail`\n * object, which holds a reference to the original click event.\n *\n * @name mixClick\n * @memberof mixitup.Events\n * @static\n * @type {CustomEvent}\n */\n\n this.mixClick = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Events);\n\n mixitup.Events.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.Events.prototype.constructor = mixitup.Events;\n\n /**\n * @private\n * @param {string} eventType\n * @param {Element} el\n * @param {object} detail\n * @param {Document} [doc]\n */\n\n mixitup.Events.prototype.fire = function(eventType, el, detail, doc) {\n var self = this,\n event = null,\n eventDetail = new mixitup.EventDetail();\n\n self.callActions('beforeFire', arguments);\n\n if (typeof self[eventType] === 'undefined') {\n throw new Error('Event type \"' + eventType + '\" not found.');\n }\n\n eventDetail.state = new mixitup.State();\n\n h.extend(eventDetail.state, detail.state);\n\n if (detail.futureState) {\n eventDetail.futureState = new mixitup.State();\n\n h.extend(eventDetail.futureState, detail.futureState);\n }\n\n eventDetail.instance = detail.instance;\n\n if (detail.originalEvent) {\n eventDetail.originalEvent = detail.originalEvent;\n }\n\n event = h.getCustomEvent(eventType, eventDetail, doc);\n\n self.callFilters('eventFire', event, arguments);\n\n el.dispatchEvent(event);\n };\n\n // Asign a singleton instance to `mixitup.events`:\n\n mixitup.events = new mixitup.Events();\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.QueueItem = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.args = [];\n this.instruction = null;\n this.triggerElement = null;\n this.deferred = null;\n this.isToggling = false;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.QueueItem);\n\n mixitup.QueueItem.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.QueueItem.prototype.constructor = mixitup.QueueItem;\n\n /**\n * The `mixitup.Mixer` class is used to hold discreet, user-configured\n * instances of MixItUp on a provided container element.\n *\n * Mixer instances are returned whenever the `mixitup()` factory function is called,\n * which expose a range of methods enabling API-based filtering, sorting,\n * insertion, removal and more.\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @public\n * @since 3.0.0\n */\n\n mixitup.Mixer = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.config = new mixitup.Config();\n\n this.id = '';\n\n this.isBusy = false;\n this.isToggling = false;\n this.incPadding = true;\n\n this.controls = [];\n this.targets = [];\n this.origOrder = [];\n this.cache = {};\n\n this.toggleArray = [];\n\n this.targetsMoved = 0;\n this.targetsImmovable = 0;\n this.targetsBound = 0;\n this.targetsDone = 0;\n\n this.staggerDuration = 0;\n this.effectsIn = null;\n this.effectsOut = null;\n this.transformIn = [];\n this.transformOut = [];\n this.queue = [];\n\n this.state = null;\n this.lastOperation = null;\n this.lastClicked = null;\n this.userCallback = null;\n this.userDeferred = null;\n\n this.dom = new mixitup.MixerDom();\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Mixer);\n\n mixitup.Mixer.prototype = Object.create(mixitup.Base.prototype);\n\n h.extend(mixitup.Mixer.prototype,\n /** @lends mixitup.Mixer */\n {\n constructor: mixitup.Mixer,\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {HTMLElement} container\n * @param {HTMLElement} document\n * @param {string} id\n * @param {object} [config]\n */\n\n attach: function(container, document, id, config) {\n var self = this,\n target = null,\n i = -1;\n\n self.callActions('beforeAttach', arguments);\n\n self.id = id;\n\n if (config) {\n h.extend(self.config, config, true, true);\n }\n\n self.sanitizeConfig();\n\n self.cacheDom(container, document);\n\n if (self.config.layout.containerClassName) {\n h.addClass(self.dom.container, self.config.layout.containerClassName);\n }\n\n if (!mixitup.features.has.transitions) {\n self.config.animation.enable = false;\n }\n\n if (typeof window.console === 'undefined') {\n self.config.debug.showWarnings = false;\n }\n\n if (self.config.data.uidKey) {\n // If the dataset API is in use, force disable controls\n\n self.config.controls.enable = false;\n }\n\n self.indexTargets();\n\n self.state = self.getInitialState();\n\n for (i = 0; target = self.lastOperation.toHide[i]; i++) {\n target.hide();\n }\n\n if (self.config.controls.enable) {\n self.initControls();\n\n self.buildToggleArray(null, self.state);\n\n self.updateControls({\n filter: self.state.activeFilter,\n sort: self.state.activeSort\n });\n }\n\n self.parseEffects();\n\n self.callActions('afterAttach', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @return {void}\n */\n\n sanitizeConfig: function() {\n var self = this;\n\n self.callActions('beforeSanitizeConfig', arguments);\n\n // Sanitize enum/string config options\n\n self.config.controls.scope = self.config.controls.scope.toLowerCase().trim();\n self.config.controls.toggleLogic = self.config.controls.toggleLogic.toLowerCase().trim();\n self.config.controls.toggleDefault = self.config.controls.toggleDefault.toLowerCase().trim();\n\n self.config.animation.effects = self.config.animation.effects.trim();\n\n self.callActions('afterSanitizeConfig', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @return {mixitup.State}\n */\n\n getInitialState: function() {\n var self = this,\n state = new mixitup.State(),\n operation = new mixitup.Operation();\n\n self.callActions('beforeGetInitialState', arguments);\n\n // Map initial values into a mock state object in order to construct an operation\n\n state.activeContainerClassName = self.config.layout.containerClassName;\n\n if (self.config.load.dataset) {\n // Dataset API\n\n if (!self.config.data.uidKey || typeof self.config.data.uidKey !== 'string') {\n throw new TypeError(mixitup.messages.errorConfigDataUidKeyNotSet());\n }\n\n operation.startDataset = operation.newDataset = state.activeDataset = self.config.load.dataset.slice();\n operation.startContainerClassName = operation.newContainerClassName = state.activeContainerClassName;\n operation.show = self.targets.slice();\n\n state = self.callFilters('stateGetInitialState', state, arguments);\n } else {\n // DOM API\n\n state.activeFilter = self.parseFilterArgs([self.config.load.filter]).command;\n state.activeSort = self.parseSortArgs([self.config.load.sort]).command;\n state.totalTargets = self.targets.length;\n\n state = self.callFilters('stateGetInitialState', state, arguments);\n\n if (\n state.activeSort.collection || state.activeSort.attribute ||\n state.activeSort.order === 'random' || state.activeSort.order === 'desc'\n ) {\n // Sorting on load\n\n operation.newSort = state.activeSort;\n\n self.sortOperation(operation);\n\n self.printSort(false, operation);\n\n self.targets = operation.newOrder;\n } else {\n operation.startOrder = operation.newOrder = self.targets;\n }\n\n operation.startFilter = operation.newFilter = state.activeFilter;\n operation.startSort = operation.newSort = state.activeSort;\n operation.startContainerClassName = operation.newContainerClassName = state.activeContainerClassName;\n\n if (operation.newFilter.selector === 'all') {\n operation.newFilter.selector = self.config.selectors.target;\n } else if (operation.newFilter.selector === 'none') {\n operation.newFilter.selector = '';\n }\n }\n\n operation = self.callFilters('operationGetInitialState', operation, [state]);\n\n self.lastOperation = operation;\n\n if (operation.newFilter) {\n self.filterOperation(operation);\n }\n\n state = self.buildState(operation);\n\n return state;\n },\n\n /**\n * Caches references of DOM elements neccessary for the mixer's functionality.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {HTMLElement} el\n * @param {HTMLHtmlElement} document\n * @return {void}\n */\n\n cacheDom: function(el, document) {\n var self = this;\n\n self.callActions('beforeCacheDom', arguments);\n\n self.dom.document = document;\n self.dom.body = self.dom.document.querySelector('body');\n self.dom.container = el;\n self.dom.parent = el;\n\n self.callActions('afterCacheDom', arguments);\n },\n\n /**\n * Indexes all child elements of the mixer matching the `selectors.target`\n * selector, instantiating a mixitup.Target for each one.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @return {void}\n */\n\n indexTargets: function() {\n var self = this,\n target = null,\n el = null,\n dataset = null,\n i = -1;\n\n self.callActions('beforeIndexTargets', arguments);\n\n self.dom.targets = self.config.layout.allowNestedTargets ?\n self.dom.container.querySelectorAll(self.config.selectors.target) :\n h.children(self.dom.container, self.config.selectors.target, self.dom.document);\n\n self.dom.targets = h.arrayFromList(self.dom.targets);\n\n self.targets = [];\n\n if ((dataset = self.config.load.dataset) && dataset.length !== self.dom.targets.length) {\n throw new Error(mixitup.messages.errorDatasetPrerenderedMismatch());\n }\n\n if (self.dom.targets.length) {\n for (i = 0; el = self.dom.targets[i]; i++) {\n target = new mixitup.Target();\n\n target.init(el, self, dataset ? dataset[i] : void(0));\n\n target.isInDom = true;\n\n self.targets.push(target);\n }\n\n self.dom.parent = self.dom.targets[0].parentElement === self.dom.container ?\n self.dom.container :\n self.dom.targets[0].parentElement;\n }\n\n self.origOrder = self.targets;\n\n self.callActions('afterIndexTargets', arguments);\n },\n\n initControls: function() {\n var self = this,\n definition = '',\n controlElements = null,\n el = null,\n parent = null,\n delagators = null,\n control = null,\n i = -1,\n j = -1;\n\n self.callActions('beforeInitControls', arguments);\n\n switch (self.config.controls.scope) {\n case 'local':\n parent = self.dom.container;\n\n break;\n case 'global':\n parent = self.dom.document;\n\n break;\n default:\n throw new Error(mixitup.messages.errorConfigInvalidControlsScope());\n }\n\n for (i = 0; definition = mixitup.controlDefinitions[i]; i++) {\n if (self.config.controls.live || definition.live) {\n if (definition.parent) {\n delagators = self.dom[definition.parent];\n\n if (!delagators || delagators.length < 0) continue;\n\n if (typeof delagators.length !== 'number') {\n delagators = [delagators];\n }\n } else {\n delagators = [parent];\n }\n\n for (j = 0; (el = delagators[j]); j++) {\n control = self.getControl(el, definition.type, definition.selector);\n\n self.controls.push(control);\n }\n } else {\n controlElements = parent.querySelectorAll(self.config.selectors.control + definition.selector);\n\n for (j = 0; (el = controlElements[j]); j++) {\n control = self.getControl(el, definition.type, '');\n\n if (!control) continue;\n\n self.controls.push(control);\n }\n }\n }\n\n self.callActions('afterInitControls', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {HTMLElement} el\n * @param {string} type\n * @param {string} selector\n * @return {mixitup.Control|null}\n */\n\n getControl: function(el, type, selector) {\n var self = this,\n control = null,\n i = -1;\n\n self.callActions('beforeGetControl', arguments);\n\n if (!selector) {\n // Static controls only\n\n for (i = 0; control = mixitup.controls[i]; i++) {\n if (control.el === el && control.isBound(self)) {\n // Control already bound to this mixer (as another type).\n\n // NB: This prevents duplicate controls from being registered where a selector\n // might collide, eg: \"[data-filter]\" and \"[data-filter][data-sort]\"\n\n return self.callFilters('controlGetControl', null, arguments);\n } else if (control.el === el && control.type === type && control.selector === selector) {\n // Another mixer is already using this control, add this mixer as a binding\n\n control.addBinding(self);\n\n return self.callFilters('controlGetControl', control, arguments);\n }\n }\n }\n\n // Create new control\n\n control = new mixitup.Control();\n\n control.init(el, type, selector);\n\n control.classNames.base = h.getClassname(self.config.classNames, type);\n control.classNames.active = h.getClassname(self.config.classNames, type, self.config.classNames.modifierActive);\n control.classNames.disabled = h.getClassname(self.config.classNames, type, self.config.classNames.modifierDisabled);\n\n // Add a reference to this mixer as a binding\n\n control.addBinding(self);\n\n return self.callFilters('controlGetControl', control, arguments);\n },\n\n /**\n * Creates a compound selector by joining the `toggleArray` value as per the\n * defined toggle logic.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @return {string}\n */\n\n getToggleSelector: function() {\n var self = this,\n delineator = self.config.controls.toggleLogic === 'or' ? ', ' : '',\n toggleSelector = '';\n\n self.callActions('beforeGetToggleSelector', arguments);\n\n self.toggleArray = h.clean(self.toggleArray);\n\n toggleSelector = self.toggleArray.join(delineator);\n\n if (toggleSelector === '') {\n toggleSelector = self.config.controls.toggleDefault;\n }\n\n return self.callFilters('selectorGetToggleSelector', toggleSelector, arguments);\n },\n\n /**\n * Breaks compound selector strings in an array of discreet selectors,\n * as per the active `controls.toggleLogic` configuration option. Accepts\n * either a dynamic command object, or a state object.\n *\n * @private\n * @instance\n * @since 2.0.0\n * @param {object} [command]\n * @param {mixitup.State} [state]\n * @return {void}\n */\n\n buildToggleArray: function(command, state) {\n var self = this,\n activeFilterSelector = '';\n\n self.callActions('beforeBuildToggleArray', arguments);\n\n if (command && command.filter) {\n activeFilterSelector = command.filter.selector.replace(/\\s/g, '');\n } else if (state) {\n activeFilterSelector = state.activeFilter.selector.replace(/\\s/g, '');\n } else {\n return;\n }\n\n if (activeFilterSelector === self.config.selectors.target || activeFilterSelector === 'all') {\n activeFilterSelector = '';\n }\n\n if (self.config.controls.toggleLogic === 'or') {\n self.toggleArray = activeFilterSelector.split(',');\n } else {\n self.toggleArray = self.splitCompoundSelector(activeFilterSelector);\n }\n\n self.toggleArray = h.clean(self.toggleArray);\n\n self.callActions('afterBuildToggleArray', arguments);\n },\n\n /**\n * Takes a compound selector (e.g. `.cat-1.cat-2`, `[data-cat=\"1\"][data-cat=\"2\"]`)\n * and breaks into its individual selectors.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {string} compoundSelector\n * @return {string[]}\n */\n\n splitCompoundSelector: function(compoundSelector) {\n // Break at a `.` or `[`, capturing the delineator\n\n var partials = compoundSelector.split(/([\\.\\[])/g),\n toggleArray = [],\n selector = '',\n i = -1;\n\n if (partials[0] === '') {\n partials.shift();\n }\n\n for (i = 0; i < partials.length; i++) {\n if (i % 2 === 0) {\n selector = '';\n }\n\n selector += partials[i];\n\n if (i % 2 !== 0) {\n toggleArray.push(selector);\n }\n }\n\n return toggleArray;\n },\n\n /**\n * Updates controls to their active/inactive state based on the command or\n * current state of the mixer.\n *\n * @private\n * @instance\n * @since 2.0.0\n * @param {object} command\n * @return {void}\n */\n\n updateControls: function(command) {\n var self = this,\n control = null,\n output = new mixitup.CommandMultimix(),\n i = -1;\n\n self.callActions('beforeUpdateControls', arguments);\n\n // Sanitise to defaults\n\n if (command.filter) {\n output.filter = command.filter.selector;\n } else {\n output.filter = self.state.activeFilter.selector;\n }\n\n if (command.sort) {\n output.sort = self.buildSortString(command.sort);\n } else {\n output.sort = self.buildSortString(self.state.activeSort);\n }\n\n if (output.filter === self.config.selectors.target) {\n output.filter = 'all';\n }\n\n if (output.filter === '') {\n output.filter = 'none';\n }\n\n h.freeze(output);\n\n for (i = 0; control = self.controls[i]; i++) {\n control.update(output, self.toggleArray);\n }\n\n self.callActions('afterUpdateControls', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {mixitup.CommandSort} command\n * @return {string}\n */\n\n buildSortString: function(command) {\n var self = this;\n var output = '';\n\n output += command.sortString;\n\n if (command.next) {\n output += ' ' + self.buildSortString(command.next);\n }\n\n return output;\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {object} command\n * @param {Operation} operation\n * @return {Promise.}\n */\n\n insertTargets: function(command, operation) {\n var self = this,\n nextSibling = null,\n insertionIndex = -1,\n frag = null,\n target = null,\n el = null,\n i = -1;\n\n self.callActions('beforeInsertTargets', arguments);\n\n if (typeof command.index === 'undefined') command.index = 0;\n\n nextSibling = self.getNextSibling(command.index, command.sibling, command.position);\n frag = self.dom.document.createDocumentFragment();\n\n if (nextSibling) {\n insertionIndex = h.index(nextSibling, self.config.selectors.target);\n } else {\n insertionIndex = self.targets.length;\n }\n\n if (command.collection) {\n for (i = 0; el = command.collection[i]; i++) {\n if (self.dom.targets.indexOf(el) > -1) {\n throw new Error(mixitup.messages.errorInsertPreexistingElement());\n }\n\n // Ensure elements are hidden when they are added to the DOM, so they can\n // be animated in gracefully\n\n el.style.display = 'none';\n\n frag.appendChild(el);\n frag.appendChild(self.dom.document.createTextNode(' '));\n\n if (!h.isElement(el, self.dom.document) || !el.matches(self.config.selectors.target)) continue;\n\n target = new mixitup.Target();\n\n target.init(el, self);\n\n target.isInDom = true;\n\n self.targets.splice(insertionIndex, 0, target);\n\n insertionIndex++;\n }\n\n self.dom.parent.insertBefore(frag, nextSibling);\n }\n\n // Since targets have been added, the original order must be updated\n\n operation.startOrder = self.origOrder = self.targets;\n\n self.callActions('afterInsertTargets', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Number} [index]\n * @param {Element} [sibling]\n * @param {string} [position]\n * @return {Element}\n */\n\n getNextSibling: function(index, sibling, position) {\n var self = this,\n element = null;\n\n index = Math.max(index, 0);\n\n if (sibling && position === 'before') {\n // Explicit sibling\n\n element = sibling;\n } else if (sibling && position === 'after') {\n // Explicit sibling\n\n element = sibling.nextElementSibling || null;\n } else if (self.targets.length > 0 && typeof index !== 'undefined') {\n // Index and targets exist\n\n element = (index < self.targets.length || !self.targets.length) ?\n self.targets[index].dom.el :\n self.targets[self.targets.length - 1].dom.el.nextElementSibling;\n } else if (self.targets.length === 0 && self.dom.parent.children.length > 0) {\n // No targets but other siblings\n\n if (self.config.layout.siblingAfter) {\n element = self.config.layout.siblingAfter;\n } else if (self.config.layout.siblingBefore) {\n element = self.config.layout.siblingBefore.nextElementSibling;\n } else {\n self.dom.parent.children[0];\n }\n } else {\n element === null;\n }\n\n return self.callFilters('elementGetNextSibling', element, arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n filterOperation: function(operation) {\n var self = this,\n testResult = false,\n index = -1,\n action = '',\n target = null,\n i = -1;\n\n self.callActions('beforeFilterOperation', arguments);\n\n action = operation.newFilter.action;\n\n for (i = 0; target = operation.newOrder[i]; i++) {\n if (operation.newFilter.collection) {\n // show via collection\n\n testResult = operation.newFilter.collection.indexOf(target.dom.el) > -1;\n } else {\n // show via selector\n\n if (operation.newFilter.selector === '') {\n testResult = false;\n } else {\n testResult = target.dom.el.matches(operation.newFilter.selector);\n }\n }\n\n self.evaluateHideShow(testResult, target, action, operation);\n }\n\n if (operation.toRemove.length) {\n for (i = 0; target = operation.show[i]; i++) {\n if (operation.toRemove.indexOf(target) > -1) {\n // If any shown targets should be removed, move them into the toHide array\n\n operation.show.splice(i, 1);\n\n if ((index = operation.toShow.indexOf(target)) > -1) {\n operation.toShow.splice(index, 1);\n }\n\n operation.toHide.push(target);\n operation.hide.push(target);\n\n i--;\n }\n }\n }\n\n operation.matching = operation.show.slice();\n\n if (operation.show.length === 0 && operation.newFilter.selector !== '' && self.targets.length !== 0) {\n operation.hasFailed = true;\n }\n\n self.callActions('afterFilterOperation', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {boolean} testResult\n * @param {Element} target\n * @param {string} action\n * @param {Operation} operation\n * @return {void}\n */\n\n evaluateHideShow: function(testResult, target, action, operation) {\n var self = this,\n filteredTestResult = false,\n args = Array.prototype.slice.call(arguments, 1);\n\n filteredTestResult = self.callFilters('testResultEvaluateHideShow', testResult, args);\n\n self.callActions('beforeEvaluateHideShow', arguments);\n\n if (\n filteredTestResult === true && action === 'show' ||\n filteredTestResult === false && action === 'hide'\n ) {\n operation.show.push(target);\n\n !target.isShown && operation.toShow.push(target);\n } else {\n operation.hide.push(target);\n\n target.isShown && operation.toHide.push(target);\n }\n\n self.callActions('afterEvaluateHideShow', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n sortOperation: function(operation) {\n var self = this,\n newOrder = [],\n target = null,\n el = null,\n i = -1;\n\n self.callActions('beforeSortOperation', arguments);\n\n operation.startOrder = self.targets;\n\n if (operation.newSort.collection) {\n // Sort by collection\n\n newOrder = [];\n\n for (i = 0; (el = operation.newSort.collection[i]); i++) {\n if (self.dom.targets.indexOf(el) < 0) {\n throw new Error(mixitup.messages.errorSortNonExistentElement());\n }\n\n target = new mixitup.Target();\n\n target.init(el, self);\n\n target.isInDom = true;\n\n newOrder.push(target);\n }\n\n operation.newOrder = newOrder;\n } else if (operation.newSort.order === 'random') {\n // Sort random\n\n operation.newOrder = h.arrayShuffle(operation.startOrder);\n } else if (operation.newSort.attribute === '') {\n // Sort by default\n\n operation.newOrder = self.origOrder.slice();\n\n if (operation.newSort.order === 'desc') {\n operation.newOrder.reverse();\n }\n } else {\n // Sort by attribute\n\n operation.newOrder = operation.startOrder.slice();\n\n operation.newOrder.sort(function(a, b) {\n return self.compare(a, b, operation.newSort);\n });\n }\n\n if (h.isEqualArray(operation.newOrder, operation.startOrder)) {\n operation.willSort = false;\n }\n\n self.callActions('afterSortOperation', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {mixitup.Target} a\n * @param {mixitup.Target} b\n * @param {mixitup.CommandSort} command\n * @return {Number}\n */\n\n compare: function(a, b, command) {\n var self = this,\n order = command.order,\n attrA = self.getAttributeValue(a, command.attribute),\n attrB = self.getAttributeValue(b, command.attribute);\n\n if (isNaN(attrA * 1) || isNaN(attrB * 1)) {\n attrA = attrA.toLowerCase();\n attrB = attrB.toLowerCase();\n } else {\n attrA = attrA * 1;\n attrB = attrB * 1;\n }\n\n if (attrA < attrB) {\n return order === 'asc' ? -1 : 1;\n }\n\n if (attrA > attrB) {\n return order === 'asc' ? 1 : -1;\n }\n\n if (attrA === attrB && command.next) {\n return self.compare(a, b, command.next);\n }\n\n return 0;\n },\n\n /**\n * Reads the values of any data attributes present the provided target element\n * which match the current sort command.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {mixitup.Target} target\n * @param {string} [attribute]\n * @return {(String|Number)}\n */\n\n getAttributeValue: function(target, attribute) {\n var self = this,\n value = '';\n\n value = target.dom.el.getAttribute('data-' + attribute);\n\n if (value === null) {\n if (self.config.debug.showWarnings) {\n // Encourage users to assign values to all targets to avoid erroneous sorting\n // when types are mixed\n\n console.warn(mixitup.messages.warningInconsistentSortingAttributes({\n attribute: 'data-' + attribute\n }));\n }\n }\n\n // If an attribute is not present, return 0 as a safety value\n\n return self.callFilters('valueGetAttributeValue', value || 0, arguments);\n },\n\n /**\n * Inserts elements into the DOM in the appropriate\n * order using a document fragment for minimal\n * DOM thrashing\n *\n * @private\n * @instance\n * @since 2.0.0\n * @param {boolean} isResetting\n * @param {Operation} operation\n * @return {void}\n */\n\n printSort: function(isResetting, operation) {\n var self = this,\n startOrder = isResetting ? operation.newOrder : operation.startOrder,\n newOrder = isResetting ? operation.startOrder : operation.newOrder,\n nextSibling = startOrder.length ? startOrder[startOrder.length - 1].dom.el.nextElementSibling : null,\n frag = window.document.createDocumentFragment(),\n whitespace = null,\n target = null,\n el = null,\n i = -1;\n\n self.callActions('beforePrintSort', arguments);\n\n // Empty the container\n\n for (i = 0; target = startOrder[i]; i++) {\n el = target.dom.el;\n\n if (el.style.position === 'absolute') continue;\n\n h.removeWhitespace(el.previousSibling);\n\n el.parentElement.removeChild(el);\n }\n\n whitespace = nextSibling ? nextSibling.previousSibling : self.dom.parent.lastChild;\n\n if (whitespace && whitespace.nodeName === '#text') {\n h.removeWhitespace(whitespace);\n }\n\n for (i = 0; target = newOrder[i]; i++) {\n // Add targets into a document fragment\n\n el = target.dom.el;\n\n if (h.isElement(frag.lastChild)) {\n frag.appendChild(window.document.createTextNode(' '));\n }\n\n frag.appendChild(el);\n }\n\n // Insert the document fragment into the container\n // before any other non-target elements\n\n if (self.dom.parent.firstChild && self.dom.parent.firstChild !== nextSibling) {\n frag.insertBefore(window.document.createTextNode(' '), frag.childNodes[0]);\n }\n\n if (nextSibling) {\n frag.appendChild(window.document.createTextNode(' '));\n\n self.dom.parent.insertBefore(frag, nextSibling);\n } else {\n self.dom.parent.appendChild(frag);\n }\n\n self.callActions('afterPrintSort', arguments);\n },\n\n /**\n * Parses user-defined sort strings (i.e. `default:asc`) into sort commands objects.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {string} sortString\n * @param {mixitup.CommandSort} command\n * @return {mixitup.CommandSort}\n */\n\n parseSortString: function(sortString, command) {\n var self = this,\n rules = sortString.split(' '),\n current = command,\n rule = [],\n i = -1;\n\n // command.sortString = sortString;\n\n for (i = 0; i < rules.length; i++) {\n rule = rules[i].split(':');\n\n current.sortString = rules[i];\n current.attribute = h.dashCase(rule[0]);\n current.order = rule[1] || 'asc';\n\n switch (current.attribute) {\n case 'default':\n // treat \"default\" as sorting by no attribute\n\n current.attribute = '';\n\n break;\n case 'random':\n // treat \"random\" as an order not an attribute\n\n current.attribute = '';\n current.order = 'random';\n\n break;\n }\n\n if (!current.attribute || current.order === 'random') break;\n\n if (i < rules.length - 1) {\n // Embed reference to the next command\n\n current.next = new mixitup.CommandSort();\n\n h.freeze(current);\n\n current = current.next;\n }\n }\n\n return self.callFilters('commandsParseSort', command, arguments);\n },\n\n /**\n * Parses all effects out of the user-defined `animation.effects` string into\n * their respective properties and units.\n *\n * @private\n * @instance\n * @since 2.0.0\n * @return {void}\n */\n\n parseEffects: function() {\n var self = this,\n transformName = '',\n effectsIn = self.config.animation.effectsIn || self.config.animation.effects,\n effectsOut = self.config.animation.effectsOut || self.config.animation.effects;\n\n self.callActions('beforeParseEffects', arguments);\n\n self.effectsIn = new mixitup.StyleData();\n self.effectsOut = new mixitup.StyleData();\n self.transformIn = [];\n self.transformOut = [];\n\n self.effectsIn.opacity = self.effectsOut.opacity = 1;\n\n self.parseEffect('fade', effectsIn, self.effectsIn, self.transformIn);\n self.parseEffect('fade', effectsOut, self.effectsOut, self.transformOut, true);\n\n for (transformName in mixitup.transformDefaults) {\n if (!(mixitup.transformDefaults[transformName] instanceof mixitup.TransformData)) {\n continue;\n }\n\n self.parseEffect(transformName, effectsIn, self.effectsIn, self.transformIn);\n self.parseEffect(transformName, effectsOut, self.effectsOut, self.transformOut, true);\n }\n\n self.parseEffect('stagger', effectsIn, self.effectsIn, self.transformIn);\n self.parseEffect('stagger', effectsOut, self.effectsOut, self.transformOut, true);\n\n self.callActions('afterParseEffects', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {string} effectName\n * @param {string} effectString\n * @param {StyleData} effects\n * @param {String[]} transform\n * @param {boolean} [isOut]\n */\n\n parseEffect: function(effectName, effectString, effects, transform, isOut) {\n var self = this,\n re = /\\(([^)]+)\\)/,\n propIndex = -1,\n str = '',\n match = [],\n val = '',\n units = ['%', 'px', 'em', 'rem', 'vh', 'vw', 'deg'],\n unit = '',\n i = -1;\n\n self.callActions('beforeParseEffect', arguments);\n\n if (typeof effectString !== 'string') {\n throw new TypeError(mixitup.messages.errorConfigInvalidAnimationEffects());\n }\n\n if (effectString.indexOf(effectName) < 0) {\n // The effect is not present in the effects string\n\n if (effectName === 'stagger') {\n // Reset stagger to 0\n\n self.staggerDuration = 0;\n }\n\n return;\n }\n\n // The effect is present\n\n propIndex = effectString.indexOf(effectName + '(');\n\n if (propIndex > -1) {\n // The effect has a user defined value in parentheses\n\n // Extract from the first parenthesis to the end of string\n\n str = effectString.substring(propIndex);\n\n // Match any number of characters between \"(\" and \")\"\n\n match = re.exec(str);\n\n val = match[1];\n }\n\n switch (effectName) {\n case 'fade':\n effects.opacity = val ? parseFloat(val) : 0;\n\n break;\n case 'stagger':\n self.staggerDuration = val ? parseFloat(val) : 100;\n\n // TODO: Currently stagger must be applied globally, but\n // if seperate values are specified for in/out, this should\n // be respected\n\n break;\n default:\n // All other effects are transforms following the same structure\n\n if (isOut && self.config.animation.reverseOut && effectName !== 'scale') {\n effects[effectName].value =\n (val ? parseFloat(val) : mixitup.transformDefaults[effectName].value) * -1;\n } else {\n effects[effectName].value =\n (val ? parseFloat(val) : mixitup.transformDefaults[effectName].value);\n }\n\n if (val) {\n for (i = 0; unit = units[i]; i++) {\n if (val.indexOf(unit) > -1) {\n effects[effectName].unit = unit;\n\n break;\n }\n }\n } else {\n effects[effectName].unit = mixitup.transformDefaults[effectName].unit;\n }\n\n transform.push(\n effectName +\n '(' +\n effects[effectName].value +\n effects[effectName].unit +\n ')'\n );\n }\n\n self.callActions('afterParseEffect', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {State}\n */\n\n buildState: function(operation) {\n var self = this,\n state = new mixitup.State(),\n target = null,\n i = -1;\n\n self.callActions('beforeBuildState', arguments);\n\n // Map target elements into state arrays.\n // the real target objects should never be exposed\n\n for (i = 0; target = self.targets[i]; i++) {\n if (!operation.toRemove.length || operation.toRemove.indexOf(target) < 0) {\n state.targets.push(target.dom.el);\n }\n }\n\n for (i = 0; target = operation.matching[i]; i++) {\n state.matching.push(target.dom.el);\n }\n\n for (i = 0; target = operation.show[i]; i++) {\n state.show.push(target.dom.el);\n }\n\n for (i = 0; target = operation.hide[i]; i++) {\n if (!operation.toRemove.length || operation.toRemove.indexOf(target) < 0) {\n state.hide.push(target.dom.el);\n }\n }\n\n state.id = self.id;\n state.container = self.dom.container;\n state.activeFilter = operation.newFilter;\n state.activeSort = operation.newSort;\n state.activeDataset = operation.newDataset;\n state.activeContainerClassName = operation.newContainerClassName;\n state.hasFailed = operation.hasFailed;\n state.totalTargets = self.targets.length;\n state.totalShow = operation.show.length;\n state.totalHide = operation.hide.length;\n state.totalMatching = operation.matching.length;\n state.triggerElement = operation.triggerElement;\n\n return self.callFilters('stateBuildState', state, arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {boolean} shouldAnimate\n * @param {Operation} operation\n * @return {void}\n */\n\n goMix: function(shouldAnimate, operation) {\n var self = this,\n deferred = null;\n\n self.callActions('beforeGoMix', arguments);\n\n // If the animation duration is set to 0ms,\n // or no effects specified,\n // or the container is hidden\n // then abort animation\n\n if (\n !self.config.animation.duration || !self.config.animation.effects || !h.isVisible(self.dom.container)\n ) {\n shouldAnimate = false;\n }\n\n if (\n !operation.toShow.length &&\n !operation.toHide.length &&\n !operation.willSort &&\n !operation.willChangeLayout\n ) {\n // If nothing to show or hide, and not sorting or\n // changing layout\n\n shouldAnimate = false;\n }\n\n if (\n !operation.startState.show.length &&\n !operation.show.length\n ) {\n // If nothing currently shown, nothing to show\n\n shouldAnimate = false;\n }\n\n mixitup.events.fire('mixStart', self.dom.container, {\n state: operation.startState,\n futureState: operation.newState,\n instance: self\n }, self.dom.document);\n\n if (typeof self.config.callbacks.onMixStart === 'function') {\n self.config.callbacks.onMixStart.call(\n self.dom.container,\n operation.startState,\n operation.newState,\n self\n );\n }\n\n h.removeClass(self.dom.container, h.getClassname(self.config.classNames, 'container', self.config.classNames.modifierFailed));\n\n if (!self.userDeferred) {\n // Queue empty, no pending operations\n\n deferred = self.userDeferred = h.defer(mixitup.libraries);\n } else {\n // Use existing deferred\n\n deferred = self.userDeferred;\n }\n\n self.isBusy = true;\n\n if (!shouldAnimate || !mixitup.features.has.transitions) {\n // Abort\n\n if (self.config.debug.fauxAsync) {\n setTimeout(function() {\n self.cleanUp(operation);\n }, self.config.animation.duration);\n } else {\n self.cleanUp(operation);\n }\n\n return self.callFilters('promiseGoMix', deferred.promise, arguments);\n }\n\n // If we should animate and the platform supports transitions, go for it\n\n if (window.pageYOffset !== operation.docState.scrollTop) {\n window.scrollTo(operation.docState.scrollLeft, operation.docState.scrollTop);\n }\n\n if (self.config.animation.applyPerspective) {\n self.dom.parent.style[mixitup.features.perspectiveProp] =\n self.config.animation.perspectiveDistance;\n\n self.dom.parent.style[mixitup.features.perspectiveOriginProp] =\n self.config.animation.perspectiveOrigin;\n }\n\n if (\n self.config.animation.animateResizeContainer &&\n operation.startHeight !== operation.newHeight &&\n operation.viewportDeltaY !== operation.startHeight - operation.newHeight\n ) {\n self.dom.parent.style.height = operation.startHeight + 'px';\n }\n\n if (\n self.config.animation.animateResizeContainer &&\n operation.startWidth !== operation.newWidth &&\n operation.viewportDeltaX !== operation.startWidth - operation.newWidth\n ) {\n self.dom.parent.style.width = operation.startWidth + 'px';\n }\n\n if (operation.startHeight === operation.newHeight) {\n self.dom.parent.style.height = operation.startHeight + 'px';\n }\n\n if (operation.startWidth === operation.newWidth) {\n self.dom.parent.style.width = operation.startWidth + 'px';\n }\n\n if (operation.startHeight === operation.newHeight && operation.startWidth === operation.newWidth) {\n self.dom.parent.style.overflow = 'hidden';\n }\n\n requestAnimationFrame(function() {\n self.moveTargets(operation);\n });\n\n return self.callFilters('promiseGoMix', deferred.promise, arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n getStartMixData: function(operation) {\n var self = this,\n parentStyle = window.getComputedStyle(self.dom.parent),\n parentRect = self.dom.parent.getBoundingClientRect(),\n target = null,\n data = {},\n i = -1,\n boxSizing = parentStyle[mixitup.features.boxSizingProp];\n\n self.incPadding = (boxSizing === 'border-box');\n\n self.callActions('beforeGetStartMixData', arguments);\n\n for (i = 0; target = operation.show[i]; i++) {\n data = target.getPosData();\n\n operation.showPosData[i] = {\n startPosData: data\n };\n }\n\n for (i = 0; target = operation.toHide[i]; i++) {\n data = target.getPosData();\n\n operation.toHidePosData[i] = {\n startPosData: data\n };\n }\n\n operation.startX = parentRect.left;\n operation.startY = parentRect.top;\n\n operation.startHeight = self.incPadding ?\n parentRect.height :\n parentRect.height -\n parseFloat(parentStyle.paddingTop) -\n parseFloat(parentStyle.paddingBottom) -\n parseFloat(parentStyle.borderTop) -\n parseFloat(parentStyle.borderBottom);\n\n operation.startWidth = self.incPadding ?\n parentRect.width :\n parentRect.width -\n parseFloat(parentStyle.paddingLeft) -\n parseFloat(parentStyle.paddingRight) -\n parseFloat(parentStyle.borderLeft) -\n parseFloat(parentStyle.borderRight);\n\n self.callActions('afterGetStartMixData', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n setInter: function(operation) {\n var self = this,\n target = null,\n i = -1;\n\n self.callActions('beforeSetInter', arguments);\n\n // Prevent scrollbar flicker on non-inertial scroll platforms by clamping height/width\n\n if (self.config.animation.clampHeight) {\n self.dom.parent.style.height = operation.startHeight + 'px';\n self.dom.parent.style.overflow = 'hidden';\n }\n\n if (self.config.animation.clampWidth) {\n self.dom.parent.style.width = operation.startWidth + 'px';\n self.dom.parent.style.overflow = 'hidden';\n }\n\n for (i = 0; target = operation.toShow[i]; i++) {\n target.show();\n }\n\n if (operation.willChangeLayout) {\n h.removeClass(self.dom.container, operation.startContainerClassName);\n h.addClass(self.dom.container, operation.newContainerClassName);\n }\n\n self.callActions('afterSetInter', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n getInterMixData: function(operation) {\n var self = this,\n target = null,\n i = -1;\n\n self.callActions('beforeGetInterMixData', arguments);\n\n for (i = 0; target = operation.show[i]; i++) {\n operation.showPosData[i].interPosData = target.getPosData();\n }\n\n for (i = 0; target = operation.toHide[i]; i++) {\n operation.toHidePosData[i].interPosData = target.getPosData();\n }\n\n self.callActions('afterGetInterMixData', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n setFinal: function(operation) {\n var self = this,\n target = null,\n i = -1;\n\n self.callActions('beforeSetFinal', arguments);\n\n operation.willSort && self.printSort(false, operation);\n\n for (i = 0; target = operation.toHide[i]; i++) {\n target.hide();\n }\n\n self.callActions('afterSetFinal', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n getFinalMixData: function(operation) {\n var self = this,\n parentStyle = null,\n parentRect = null,\n target = null,\n i = -1;\n\n self.callActions('beforeGetFinalMixData', arguments);\n\n for (i = 0; target = operation.show[i]; i++) {\n operation.showPosData[i].finalPosData = target.getPosData();\n }\n\n for (i = 0; target = operation.toHide[i]; i++) {\n operation.toHidePosData[i].finalPosData = target.getPosData();\n }\n\n // Remove clamping\n\n if (self.config.animation.clampHeight || self.config.animation.clampWidth) {\n self.dom.parent.style.height =\n self.dom.parent.style.width =\n self.dom.parent.style.overflow = '';\n }\n\n if (!self.incPadding) {\n parentStyle = window.getComputedStyle(self.dom.parent);\n }\n\n parentRect = self.dom.parent.getBoundingClientRect();\n\n operation.newX = parentRect.left;\n operation.newY = parentRect.top;\n\n operation.newHeight = self.incPadding ?\n parentRect.height :\n parentRect.height -\n parseFloat(parentStyle.paddingTop) -\n parseFloat(parentStyle.paddingBottom) -\n parseFloat(parentStyle.borderTop) -\n parseFloat(parentStyle.borderBottom);\n\n operation.newWidth = self.incPadding ?\n parentRect.width :\n parentRect.width -\n parseFloat(parentStyle.paddingLeft) -\n parseFloat(parentStyle.paddingRight) -\n parseFloat(parentStyle.borderLeft) -\n parseFloat(parentStyle.borderRight);\n\n operation.viewportDeltaX = operation.docState.viewportWidth - this.dom.document.documentElement.clientWidth;\n operation.viewportDeltaY = operation.docState.viewportHeight - this.dom.document.documentElement.clientHeight;\n\n if (operation.willSort) {\n self.printSort(true, operation);\n }\n\n for (i = 0; target = operation.toShow[i]; i++) {\n target.hide();\n }\n\n for (i = 0; target = operation.toHide[i]; i++) {\n target.show();\n }\n\n if (operation.willChangeLayout) {\n h.removeClass(self.dom.container, operation.newContainerClassName);\n h.addClass(self.dom.container, self.config.layout.containerClassName);\n }\n\n self.callActions('afterGetFinalMixData', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Operation} operation\n */\n\n getTweenData: function(operation) {\n var self = this,\n target = null,\n posData = null,\n effectNames = Object.getOwnPropertyNames(self.effectsIn),\n effectName = '',\n effect = null,\n widthChange = -1,\n heightChange = -1,\n i = -1,\n j = -1;\n\n self.callActions('beforeGetTweenData', arguments);\n\n for (i = 0; target = operation.show[i]; i++) {\n posData = operation.showPosData[i];\n posData.posIn = new mixitup.StyleData();\n posData.posOut = new mixitup.StyleData();\n posData.tweenData = new mixitup.StyleData();\n\n // Process x and y\n\n if (target.isShown) {\n posData.posIn.x = posData.startPosData.x - posData.interPosData.x;\n posData.posIn.y = posData.startPosData.y - posData.interPosData.y;\n } else {\n posData.posIn.x = posData.posIn.y = 0;\n }\n\n posData.posOut.x = posData.finalPosData.x - posData.interPosData.x;\n posData.posOut.y = posData.finalPosData.y - posData.interPosData.y;\n\n // Process opacity\n\n posData.posIn.opacity = target.isShown ? 1 : self.effectsIn.opacity;\n posData.posOut.opacity = 1;\n posData.tweenData.opacity = posData.posOut.opacity - posData.posIn.opacity;\n\n // Adjust x and y if not nudging\n\n if (!target.isShown && !self.config.animation.nudge) {\n posData.posIn.x = posData.posOut.x;\n posData.posIn.y = posData.posOut.y;\n }\n\n posData.tweenData.x = posData.posOut.x - posData.posIn.x;\n posData.tweenData.y = posData.posOut.y - posData.posIn.y;\n\n // Process width, height, and margins\n\n if (self.config.animation.animateResizeTargets) {\n posData.posIn.width = posData.startPosData.width;\n posData.posIn.height = posData.startPosData.height;\n\n // \"||\" Prevents width/height change from including 0 width/height if hiding or showing\n\n widthChange = (posData.startPosData.width || posData.finalPosData.width) - posData.interPosData.width;\n\n posData.posIn.marginRight = posData.startPosData.marginRight - widthChange;\n\n heightChange = (posData.startPosData.height || posData.finalPosData.height) - posData.interPosData.height;\n\n posData.posIn.marginBottom = posData.startPosData.marginBottom - heightChange;\n\n posData.posOut.width = posData.finalPosData.width;\n posData.posOut.height = posData.finalPosData.height;\n\n widthChange = (posData.finalPosData.width || posData.startPosData.width) - posData.interPosData.width;\n\n posData.posOut.marginRight = posData.finalPosData.marginRight - widthChange;\n\n heightChange = (posData.finalPosData.height || posData.startPosData.height) - posData.interPosData.height;\n\n posData.posOut.marginBottom = posData.finalPosData.marginBottom - heightChange;\n\n posData.tweenData.width = posData.posOut.width - posData.posIn.width;\n posData.tweenData.height = posData.posOut.height - posData.posIn.height;\n posData.tweenData.marginRight = posData.posOut.marginRight - posData.posIn.marginRight;\n posData.tweenData.marginBottom = posData.posOut.marginBottom - posData.posIn.marginBottom;\n }\n\n // Process transforms\n\n for (j = 0; effectName = effectNames[j]; j++) {\n effect = self.effectsIn[effectName];\n\n if (!(effect instanceof mixitup.TransformData) || !effect.value) continue;\n\n posData.posIn[effectName].value = effect.value;\n posData.posOut[effectName].value = 0;\n\n posData.tweenData[effectName].value =\n posData.posOut[effectName].value - posData.posIn[effectName].value;\n\n posData.posIn[effectName].unit =\n posData.posOut[effectName].unit =\n posData.tweenData[effectName].unit =\n effect.unit;\n }\n }\n\n for (i = 0; target = operation.toHide[i]; i++) {\n posData = operation.toHidePosData[i];\n posData.posIn = new mixitup.StyleData();\n posData.posOut = new mixitup.StyleData();\n posData.tweenData = new mixitup.StyleData();\n\n // Process x and y\n\n posData.posIn.x = target.isShown ? posData.startPosData.x - posData.interPosData.x : 0;\n posData.posIn.y = target.isShown ? posData.startPosData.y - posData.interPosData.y : 0;\n posData.posOut.x = self.config.animation.nudge ? 0 : posData.posIn.x;\n posData.posOut.y = self.config.animation.nudge ? 0 : posData.posIn.y;\n posData.tweenData.x = posData.posOut.x - posData.posIn.x;\n posData.tweenData.y = posData.posOut.y - posData.posIn.y;\n\n // Process width, height, and margins\n\n if (self.config.animation.animateResizeTargets) {\n posData.posIn.width = posData.startPosData.width;\n posData.posIn.height = posData.startPosData.height;\n\n widthChange = posData.startPosData.width - posData.interPosData.width;\n\n posData.posIn.marginRight = posData.startPosData.marginRight - widthChange;\n\n heightChange = posData.startPosData.height - posData.interPosData.height;\n\n posData.posIn.marginBottom = posData.startPosData.marginBottom - heightChange;\n }\n\n // Process opacity\n\n posData.posIn.opacity = 1;\n posData.posOut.opacity = self.effectsOut.opacity;\n posData.tweenData.opacity = posData.posOut.opacity - posData.posIn.opacity;\n\n // Process transforms\n\n for (j = 0; effectName = effectNames[j]; j++) {\n effect = self.effectsOut[effectName];\n\n if (!(effect instanceof mixitup.TransformData) || !effect.value) continue;\n\n posData.posIn[effectName].value = 0;\n posData.posOut[effectName].value = effect.value;\n\n posData.tweenData[effectName].value =\n posData.posOut[effectName].value - posData.posIn[effectName].value;\n\n posData.posIn[effectName].unit =\n posData.posOut[effectName].unit =\n posData.tweenData[effectName].unit =\n effect.unit;\n }\n }\n\n self.callActions('afterGetTweenData', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n moveTargets: function(operation) {\n var self = this,\n target = null,\n moveData = null,\n posData = null,\n statusChange = '',\n willTransition = false,\n staggerIndex = -1,\n i = -1,\n checkProgress = self.checkProgress.bind(self);\n\n self.callActions('beforeMoveTargets', arguments);\n\n // TODO: this is an extra loop in addition to the calcs\n // done in getOperation, could some of this be done there?\n\n for (i = 0; target = operation.show[i]; i++) {\n moveData = new mixitup.IMoveData();\n posData = operation.showPosData[i];\n\n statusChange = target.isShown ? 'none' : 'show';\n\n willTransition = self.willTransition(\n statusChange,\n operation.hasEffect,\n posData.posIn,\n posData.posOut\n );\n\n if (willTransition) {\n // Prevent non-transitioning targets from incrementing the staggerIndex\n\n staggerIndex++;\n }\n\n target.show();\n\n moveData.posIn = posData.posIn;\n moveData.posOut = posData.posOut;\n moveData.statusChange = statusChange;\n moveData.staggerIndex = staggerIndex;\n moveData.operation = operation;\n moveData.callback = willTransition ? checkProgress : null;\n\n target.move(moveData);\n }\n\n for (i = 0; target = operation.toHide[i]; i++) {\n posData = operation.toHidePosData[i];\n moveData = new mixitup.IMoveData();\n\n statusChange = 'hide';\n\n willTransition = self.willTransition(statusChange, posData.posIn, posData.posOut);\n\n moveData.posIn = posData.posIn;\n moveData.posOut = posData.posOut;\n moveData.statusChange = statusChange;\n moveData.staggerIndex = i;\n moveData.operation = operation;\n moveData.callback = willTransition ? checkProgress : null;\n\n target.move(moveData);\n }\n\n if (self.config.animation.animateResizeContainer) {\n self.dom.parent.style[mixitup.features.transitionProp] =\n 'height ' + self.config.animation.duration + 'ms ease, ' +\n 'width ' + self.config.animation.duration + 'ms ease ';\n\n requestAnimationFrame(function() {\n if (\n operation.startHeight !== operation.newHeight &&\n operation.viewportDeltaY !== operation.startHeight - operation.newHeight\n ) {\n self.dom.parent.style.height = operation.newHeight + 'px';\n }\n\n if (\n operation.startWidth !== operation.newWidth &&\n operation.viewportDeltaX !== operation.startWidth - operation.newWidth\n ) {\n self.dom.parent.style.width = operation.newWidth + 'px';\n }\n });\n }\n\n if (operation.willChangeLayout) {\n h.removeClass(self.dom.container, self.config.layout.ContainerClassName);\n h.addClass(self.dom.container, operation.newContainerClassName);\n }\n\n self.callActions('afterMoveTargets', arguments);\n },\n\n /**\n * @private\n * @instance\n * @return {boolean}\n */\n\n hasEffect: function() {\n var self = this,\n EFFECTABLES = [\n 'scale',\n 'translateX', 'translateY', 'translateZ',\n 'rotateX', 'rotateY', 'rotateZ'\n ],\n effectName = '',\n effect = null,\n result = false,\n value = -1,\n i = -1;\n\n if (self.effectsIn.opacity !== 1) {\n return self.callFilters('resultHasEffect', true, arguments);\n }\n\n for (i = 0; effectName = EFFECTABLES[i]; i++) {\n effect = self.effectsIn[effectName];\n value = (typeof effect && effect.value !== 'undefined') ?\n effect.value : effect;\n\n if (value !== 0) {\n result = true;\n\n break;\n }\n }\n\n return self.callFilters('resultHasEffect', result, arguments);\n },\n\n /**\n * Determines if a target element will transition in\n * some fasion and therefore requires binding of\n * transitionEnd\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {string} statusChange\n * @param {boolean} hasEffect\n * @param {StyleData} posIn\n * @param {StyleData} posOut\n * @return {boolean}\n */\n\n willTransition: function(statusChange, hasEffect, posIn, posOut) {\n var self = this,\n result = false;\n\n if (!h.isVisible(self.dom.container)) {\n // If the container is not visible, the transitionEnd\n // event will not occur and MixItUp will hang\n\n result = false;\n } else if (\n (statusChange !== 'none' && hasEffect) ||\n posIn.x !== posOut.x ||\n posIn.y !== posOut.y\n ) {\n // If opacity and/or translate will change\n\n result = true;\n } else if (self.config.animation.animateResizeTargets) {\n // Check if width, height or margins will change\n\n result = (\n posIn.width !== posOut.width ||\n posIn.height !== posOut.height ||\n posIn.marginRight !== posOut.marginRight ||\n posIn.marginTop !== posOut.marginTop\n );\n } else {\n result = false;\n }\n\n return self.callFilters('resultWillTransition', result, arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n checkProgress: function(operation) {\n var self = this;\n\n self.targetsDone++;\n\n if (self.targetsBound === self.targetsDone) {\n self.cleanUp(operation);\n }\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Operation} operation\n * @return {void}\n */\n\n cleanUp: function(operation) {\n var self = this,\n target = null,\n whitespaceBefore = null,\n whitespaceAfter = null,\n nextInQueue = null,\n i = -1;\n\n self.callActions('beforeCleanUp', arguments);\n\n self.targetsMoved =\n self.targetsImmovable =\n self.targetsBound =\n self.targetsDone = 0;\n\n for (i = 0; target = operation.show[i]; i++) {\n target.cleanUp();\n\n target.show();\n }\n\n for (i = 0; target = operation.toHide[i]; i++) {\n target.cleanUp();\n\n target.hide();\n }\n\n if (operation.willSort) {\n self.printSort(false, operation);\n }\n\n // Remove any styles applied to the parent container\n\n self.dom.parent.style[mixitup.features.transitionProp] =\n self.dom.parent.style.height =\n self.dom.parent.style.width =\n self.dom.parent.style.overflow =\n self.dom.parent.style[mixitup.features.perspectiveProp] =\n self.dom.parent.style[mixitup.features.perspectiveOriginProp] = '';\n\n if (operation.willChangeLayout) {\n h.removeClass(self.dom.container, operation.startContainerClassName);\n h.addClass(self.dom.container, operation.newContainerClassName);\n }\n\n if (operation.toRemove.length) {\n for (i = 0; target = self.targets[i]; i++) {\n if (operation.toRemove.indexOf(target) > -1) {\n if (\n (whitespaceBefore = target.dom.el.previousSibling) && whitespaceBefore.nodeName === '#text' &&\n (whitespaceAfter = target.dom.el.nextSibling) && whitespaceAfter.nodeName === '#text'\n ) {\n h.removeWhitespace(whitespaceBefore);\n }\n\n if (!operation.willSort) {\n // NB: Sorting will remove targets as a bi-product of `printSort()`\n\n self.dom.parent.removeChild(target.dom.el);\n }\n\n self.targets.splice(i, 1);\n\n target.isInDom = false;\n\n i--;\n }\n }\n\n // Since targets have been removed, the original order must be updated\n\n self.origOrder = self.targets;\n }\n\n if (operation.willSort) {\n self.targets = operation.newOrder;\n }\n\n self.state = operation.newState;\n self.lastOperation = operation;\n\n self.dom.targets = self.state.targets;\n\n // mixEnd\n\n mixitup.events.fire('mixEnd', self.dom.container, {\n state: self.state,\n instance: self\n }, self.dom.document);\n\n if (typeof self.config.callbacks.onMixEnd === 'function') {\n self.config.callbacks.onMixEnd.call(self.dom.container, self.state, self);\n }\n\n if (operation.hasFailed) {\n // mixFail\n\n mixitup.events.fire('mixFail', self.dom.container, {\n state: self.state,\n instance: self\n }, self.dom.document);\n\n if (typeof self.config.callbacks.onMixFail === 'function') {\n self.config.callbacks.onMixFail.call(self.dom.container, self.state, self);\n }\n\n h.addClass(self.dom.container, h.getClassname(self.config.classNames, 'container', self.config.classNames.modifierFailed));\n }\n\n // User-defined callback function\n\n if (typeof self.userCallback === 'function') {\n self.userCallback.call(self.dom.container, self.state, self);\n }\n\n if (typeof self.userDeferred.resolve === 'function') {\n self.userDeferred.resolve(self.state);\n }\n\n self.userCallback = null;\n self.userDeferred = null;\n self.lastClicked = null;\n self.isToggling = false;\n self.isBusy = false;\n\n if (self.queue.length) {\n self.callActions('beforeReadQueueCleanUp', arguments);\n\n nextInQueue = self.queue.shift();\n\n // Update non-public API properties stored in queue\n\n self.userDeferred = nextInQueue.deferred;\n self.isToggling = nextInQueue.isToggling;\n self.lastClicked = nextInQueue.triggerElement;\n\n if (nextInQueue.instruction.command instanceof mixitup.CommandMultimix) {\n self.multimix.apply(self, nextInQueue.args);\n } else {\n self.dataset.apply(self, nextInQueue.args);\n }\n }\n\n self.callActions('afterCleanUp', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Array<*>} args\n * @return {mixitup.UserInstruction}\n */\n\n parseMultimixArgs: function(args) {\n var self = this,\n instruction = new mixitup.UserInstruction(),\n arg = null,\n i = -1;\n\n instruction.animate = self.config.animation.enable;\n instruction.command = new mixitup.CommandMultimix();\n\n for (i = 0; i < args.length; i++) {\n arg = args[i];\n\n if (arg === null) continue;\n\n if (typeof arg === 'object') {\n h.extend(instruction.command, arg);\n } else if (typeof arg === 'boolean') {\n instruction.animate = arg;\n } else if (typeof arg === 'function') {\n instruction.callback = arg;\n }\n }\n\n // Coerce arbitrary command arguments into typed command objects\n\n if (instruction.command.insert && !(instruction.command.insert instanceof mixitup.CommandInsert)) {\n instruction.command.insert = self.parseInsertArgs([instruction.command.insert]).command;\n }\n\n if (instruction.command.remove && !(instruction.command.remove instanceof mixitup.CommandRemove)) {\n instruction.command.remove = self.parseRemoveArgs([instruction.command.remove]).command;\n }\n\n if (instruction.command.filter && !(instruction.command.filter instanceof mixitup.CommandFilter)) {\n instruction.command.filter = self.parseFilterArgs([instruction.command.filter]).command;\n }\n\n if (instruction.command.sort && !(instruction.command.sort instanceof mixitup.CommandSort)) {\n instruction.command.sort = self.parseSortArgs([instruction.command.sort]).command;\n }\n\n if (instruction.command.changeLayout && !(instruction.command.changeLayout instanceof mixitup.CommandChangeLayout)) {\n instruction.command.changeLayout = self.parseChangeLayoutArgs([instruction.command.changeLayout]).command;\n }\n\n instruction = self.callFilters('instructionParseMultimixArgs', instruction, arguments);\n\n h.freeze(instruction);\n\n return instruction;\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Array<*>} args\n * @return {mixitup.UserInstruction}\n */\n\n parseFilterArgs: function(args) {\n var self = this,\n instruction = new mixitup.UserInstruction(),\n arg = null,\n i = -1;\n\n instruction.animate = self.config.animation.enable;\n instruction.command = new mixitup.CommandFilter();\n\n for (i = 0; i < args.length; i++) {\n arg = args[i];\n\n if (typeof arg === 'string') {\n // Selector\n\n instruction.command.selector = arg;\n } else if (arg === null) {\n instruction.command.collection = [];\n } else if (typeof arg === 'object' && h.isElement(arg, self.dom.document)) {\n // Single element\n\n instruction.command.collection = [arg];\n } else if (typeof arg === 'object' && typeof arg.length !== 'undefined') {\n // Multiple elements in array, NodeList or jQuery collection\n\n instruction.command.collection = h.arrayFromList(arg);\n } else if (typeof arg === 'object') {\n // Filter command\n\n h.extend(instruction.command, arg);\n } else if (typeof arg === 'boolean') {\n instruction.animate = arg;\n } else if (typeof arg === 'function') {\n instruction.callback = arg;\n }\n }\n\n if (instruction.command.selector && instruction.command.collection) {\n throw new Error(mixitup.messages.errorFilterInvalidArguments());\n }\n\n instruction = self.callFilters('instructionParseFilterArgs', instruction, arguments);\n\n h.freeze(instruction);\n\n return instruction;\n },\n\n parseSortArgs: function(args) {\n var self = this,\n instruction = new mixitup.UserInstruction(),\n arg = null,\n sortString = '',\n i = -1;\n\n instruction.animate = self.config.animation.enable;\n instruction.command = new mixitup.CommandSort();\n\n for (i = 0; i < args.length; i++) {\n arg = args[i];\n\n if (arg === null) continue;\n\n switch (typeof arg) {\n case 'string':\n // Sort string\n\n sortString = arg;\n\n break;\n case 'object':\n // Array of element references\n\n if (arg.length) {\n instruction.command.collection = h.arrayFromList(arg);\n }\n\n break;\n case 'boolean':\n instruction.animate = arg;\n\n break;\n case 'function':\n instruction.callback = arg;\n\n break;\n }\n }\n\n if (sortString) {\n instruction.command = self.parseSortString(sortString, instruction.command);\n }\n\n instruction = self.callFilters('instructionParseSortArgs', instruction, arguments);\n\n h.freeze(instruction);\n\n return instruction;\n },\n\n /**\n * @private\n * @instance\n * @since 2.0.0\n * @param {Array<*>} args\n * @return {mixitup.UserInstruction}\n */\n\n parseInsertArgs: function(args) {\n var self = this,\n instruction = new mixitup.UserInstruction(),\n arg = null,\n i = -1;\n\n instruction.animate = self.config.animation.enable;\n instruction.command = new mixitup.CommandInsert();\n\n for (i = 0; i < args.length; i++) {\n arg = args[i];\n\n if (arg === null) continue;\n\n if (typeof arg === 'number') {\n // Insert index\n\n instruction.command.index = arg;\n } else if (typeof arg === 'string' && ['before', 'after'].indexOf(arg) > -1) {\n // 'before'/'after'\n\n instruction.command.position = arg;\n } else if (typeof arg === 'string') {\n // Markup\n\n instruction.command.collection =\n h.arrayFromList(h.createElement(arg).childNodes);\n } else if (typeof arg === 'object' && h.isElement(arg, self.dom.document)) {\n // Single element\n\n !instruction.command.collection.length ?\n (instruction.command.collection = [arg]) :\n (instruction.command.sibling = arg);\n } else if (typeof arg === 'object' && arg.length) {\n // Multiple elements in array or jQuery collection\n\n !instruction.command.collection.length ?\n (instruction.command.collection = arg) :\n instruction.command.sibling = arg[0];\n } else if (typeof arg === 'object' && arg.childNodes && arg.childNodes.length) {\n // Document fragment\n\n !instruction.command.collection.length ?\n instruction.command.collection = h.arrayFromList(arg.childNodes) :\n instruction.command.sibling = arg.childNodes[0];\n } else if (typeof arg === 'object') {\n // Insert command\n\n h.extend(instruction.command, arg);\n } else if (typeof arg === 'boolean') {\n instruction.animate = arg;\n } else if (typeof arg === 'function') {\n instruction.callback = arg;\n }\n }\n\n if (instruction.command.index && instruction.command.sibling) {\n throw new Error(mixitup.messages.errorInsertInvalidArguments());\n }\n\n if (!instruction.command.collection.length && self.config.debug.showWarnings) {\n console.warn(mixitup.messages.warningInsertNoElements());\n }\n\n instruction = self.callFilters('instructionParseInsertArgs', instruction, arguments);\n\n h.freeze(instruction);\n\n return instruction;\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Array<*>} args\n * @return {mixitup.UserInstruction}\n */\n\n parseRemoveArgs: function(args) {\n var self = this,\n instruction = new mixitup.UserInstruction(),\n target = null,\n arg = null,\n i = -1;\n\n instruction.animate = self.config.animation.enable;\n instruction.command = new mixitup.CommandRemove();\n\n for (i = 0; i < args.length; i++) {\n arg = args[i];\n\n if (arg === null) continue;\n\n switch (typeof arg) {\n case 'number':\n if (self.targets[arg]) {\n instruction.command.targets[0] = self.targets[arg];\n }\n\n break;\n case 'string':\n instruction.command.collection = h.arrayFromList(self.dom.parent.querySelectorAll(arg));\n\n break;\n case 'object':\n if (arg && arg.length) {\n instruction.command.collection = arg;\n } else if (h.isElement(arg, self.dom.document)) {\n instruction.command.collection = [arg];\n } else {\n // Remove command\n\n h.extend(instruction.command, arg);\n }\n\n break;\n case 'boolean':\n instruction.animate = arg;\n\n break;\n case 'function':\n instruction.callback = arg;\n\n break;\n }\n }\n\n if (instruction.command.collection.length) {\n for (i = 0; target = self.targets[i]; i++) {\n if (instruction.command.collection.indexOf(target.dom.el) > -1) {\n instruction.command.targets.push(target);\n }\n }\n }\n\n if (!instruction.command.targets.length && self.config.debug.showWarnings) {\n console.warn(mixitup.messages.warningRemoveNoElements());\n }\n\n h.freeze(instruction);\n\n return instruction;\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Array<*>} args\n * @return {mixitup.UserInstruction}\n */\n\n parseDatasetArgs: function(args) {\n var self = this,\n instruction = new mixitup.UserInstruction(),\n arg = null,\n i = -1;\n\n instruction.animate = self.config.animation.enable;\n instruction.command = new mixitup.CommandDataset();\n\n for (i = 0; i < args.length; i++) {\n arg = args[i];\n\n if (arg === null) continue;\n\n switch (typeof arg) {\n case 'object':\n if (Array.isArray(arg) || typeof arg.length === 'number') {\n instruction.command.dataset = arg;\n } else {\n // Change layout command\n\n h.extend(instruction.command, arg);\n }\n\n break;\n case 'boolean':\n instruction.animate = arg;\n\n break;\n case 'function':\n instruction.callback = arg;\n\n break;\n }\n }\n\n h.freeze(instruction);\n\n return instruction;\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Array<*>} args\n * @return {mixitup.UserInstruction}\n */\n\n parseChangeLayoutArgs: function(args) {\n var self = this,\n instruction = new mixitup.UserInstruction(),\n arg = null,\n i = -1;\n\n instruction.animate = self.config.animation.enable;\n instruction.command = new mixitup.CommandChangeLayout();\n\n for (i = 0; i < args.length; i++) {\n arg = args[i];\n\n if (arg === null) continue;\n\n switch (typeof arg) {\n case 'string':\n instruction.command.containerClassName = arg;\n\n break;\n case 'object':\n // Change layout command\n\n h.extend(instruction.command, arg);\n\n break;\n case 'boolean':\n instruction.animate = arg;\n\n break;\n case 'function':\n instruction.callback = arg;\n\n break;\n }\n }\n\n h.freeze(instruction);\n\n return instruction;\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {mixitup.QueueItem} queueItem\n * @return {Promise.}\n */\n\n queueMix: function(queueItem) {\n var self = this,\n deferred = null,\n toggleSelector = '';\n\n self.callActions('beforeQueueMix', arguments);\n\n deferred = h.defer(mixitup.libraries);\n\n if (self.config.animation.queue && self.queue.length < self.config.animation.queueLimit) {\n queueItem.deferred = deferred;\n\n self.queue.push(queueItem);\n\n // Keep controls in sync with user interactions. Mixer will catch up as it drains the queue.\n\n if (self.config.controls.enable) {\n if (self.isToggling) {\n self.buildToggleArray(queueItem.instruction.command);\n\n toggleSelector = self.getToggleSelector();\n\n self.updateControls({\n filter: {\n selector: toggleSelector\n }\n });\n } else {\n self.updateControls(queueItem.instruction.command);\n }\n }\n } else {\n if (self.config.debug.showWarnings) {\n console.warn(mixitup.messages.warningMultimixInstanceQueueFull());\n }\n\n deferred.resolve(self.state);\n\n mixitup.events.fire('mixBusy', self.dom.container, {\n state: self.state,\n instance: self\n }, self.dom.document);\n\n if (typeof self.config.callbacks.onMixBusy === 'function') {\n self.config.callbacks.onMixBusy.call(self.dom.container, self.state, self);\n }\n }\n\n return self.callFilters('promiseQueueMix', deferred.promise, arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Array.} newDataset\n * @return {Operation}\n */\n\n getDataOperation: function(newDataset) {\n var self = this,\n operation = new mixitup.Operation(),\n startDataset = [];\n\n operation = self.callFilters('operationUnmappedGetDataOperation', operation, arguments);\n\n if (self.dom.targets.length && !(startDataset = (self.state.activeDataset || [])).length) {\n throw new Error(mixitup.messages.errorDatasetNotSet());\n }\n\n operation.id = h.randomHex();\n operation.startState = self.state;\n operation.startDataset = startDataset;\n operation.newDataset = newDataset.slice();\n\n self.diffDatasets(operation);\n\n operation.startOrder = self.targets;\n operation.newOrder = operation.show;\n\n if (self.config.animation.enable) {\n self.getStartMixData(operation);\n self.setInter(operation);\n\n operation.docState = h.getDocumentState(self.dom.document);\n\n self.getInterMixData(operation);\n self.setFinal(operation);\n self.getFinalMixData(operation);\n\n self.parseEffects();\n\n operation.hasEffect = self.hasEffect();\n\n self.getTweenData(operation);\n }\n\n self.targets = operation.show.slice();\n\n operation.newState = self.buildState(operation);\n\n // NB: Targets to be removed must be included in `self.targets` for removal during clean up,\n // but are added after state is built so that state is accurate\n\n Array.prototype.push.apply(self.targets, operation.toRemove);\n\n operation = self.callFilters('operationMappedGetDataOperation', operation, arguments);\n\n return operation;\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {mixitup.Operation} operation\n * @return {void}\n */\n\n diffDatasets: function(operation) {\n var self = this,\n persistantStartIds = [],\n persistantNewIds = [],\n insertedTargets = [],\n data = null,\n target = null,\n el = null,\n frag = null,\n nextEl = null,\n uids = {},\n id = '',\n i = -1;\n\n self.callActions('beforeDiffDatasets', arguments);\n\n for (i = 0; data = operation.newDataset[i]; i++) {\n if (typeof (id = data[self.config.data.uidKey]) === 'undefined' || id.toString().length < 1) {\n throw new TypeError(mixitup.messages.errorDatasetInvalidUidKey({\n uidKey: self.config.data.uidKey\n }));\n }\n\n if (!uids[id]) {\n uids[id] = true;\n } else {\n throw new Error(mixitup.messages.errorDatasetDuplicateUid({\n uid: id\n }));\n }\n\n if ((target = self.cache[id]) instanceof mixitup.Target) {\n // Already in cache\n\n if (self.config.data.dirtyCheck && !h.deepEquals(data, target.data)) {\n // change detected\n\n el = target.render(data);\n\n target.data = data;\n\n if (el !== target.dom.el) {\n // Update target element reference\n\n if (target.isInDom) {\n target.unbindEvents();\n\n self.dom.parent.replaceChild(el, target.dom.el);\n }\n\n if (!target.isShown) {\n el.style.display = 'none';\n }\n\n target.dom.el = el;\n\n if (target.isInDom) {\n target.bindEvents();\n }\n }\n }\n\n el = target.dom.el;\n } else {\n // New target\n\n target = new mixitup.Target();\n\n target.init(null, self, data);\n\n target.hide();\n }\n\n if (!target.isInDom) {\n // Adding to DOM\n\n if (!frag) {\n // Open frag\n\n frag = self.dom.document.createDocumentFragment();\n }\n\n if (frag.lastElementChild) {\n frag.appendChild(self.dom.document.createTextNode(' '));\n }\n\n frag.appendChild(target.dom.el);\n\n target.isInDom = true;\n\n target.unbindEvents();\n target.bindEvents();\n target.hide();\n\n operation.toShow.push(target);\n\n insertedTargets.push(target);\n } else {\n // Already in DOM\n\n nextEl = target.dom.el.nextElementSibling;\n\n persistantNewIds.push(id);\n\n if (frag) {\n // Close and insert previously opened frag\n\n if (frag.lastElementChild) {\n frag.appendChild(self.dom.document.createTextNode(' '));\n }\n\n self.insertDatasetFrag(frag, target.dom.el, insertedTargets);\n\n frag = null;\n }\n }\n\n operation.show.push(target);\n }\n\n if (frag) {\n // Unclosed frag remaining\n\n nextEl = nextEl || self.config.layout.siblingAfter;\n\n if (nextEl) {\n frag.appendChild(self.dom.document.createTextNode(' '));\n }\n\n self.insertDatasetFrag(frag, nextEl, insertedTargets);\n }\n\n for (i = 0; data = operation.startDataset[i]; i++) {\n id = data[self.config.data.uidKey];\n\n target = self.cache[id];\n\n if (operation.show.indexOf(target) < 0) {\n // Previously shown but now absent\n\n operation.hide.push(target);\n operation.toHide.push(target);\n operation.toRemove.push(target);\n } else {\n persistantStartIds.push(id);\n }\n }\n\n if (!h.isEqualArray(persistantStartIds, persistantNewIds)) {\n operation.willSort = true;\n }\n\n self.callActions('afterDiffDatasets', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.1.5\n * @param {DocumentFragment} frag\n * @param {(HTMLElement|null)} nextEl\n * @param {Array.} targets\n * @return {void}\n */\n\n insertDatasetFrag: function(frag, nextEl, targets) {\n var self = this;\n var insertAt = nextEl ? h.arrayFromList(self.dom.parent.children).indexOf(nextEl) : self.targets.length;\n\n self.dom.parent.insertBefore(frag, nextEl);\n\n while (targets.length) {\n self.targets.splice(insertAt, 0, targets.shift());\n\n insertAt++;\n }\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {mixitup.CommandSort} sortCommandA\n * @param {mixitup.CommandSort} sortCommandB\n * @return {boolean}\n */\n\n willSort: function(sortCommandA, sortCommandB) {\n var self = this,\n result = false;\n\n if (\n self.config.behavior.liveSort ||\n sortCommandA.order === 'random' ||\n sortCommandA.attribute !== sortCommandB.attribute ||\n sortCommandA.order !== sortCommandB.order ||\n sortCommandA.collection !== sortCommandB.collection ||\n (sortCommandA.next === null && sortCommandB.next) ||\n (sortCommandA.next && sortCommandB.next === null)\n ) {\n result = true;\n } else if (sortCommandA.next && sortCommandB.next) {\n result = self.willSort(sortCommandA.next, sortCommandB.next);\n } else {\n result = false;\n }\n\n return self.callFilters('resultWillSort', result, arguments);\n },\n\n /**\n * A shorthand method for `.filter('all')`. Shows all targets in the container.\n *\n * @example\n *\n * .show()\n *\n * @example Example: Showing all targets\n *\n * mixer.show()\n * .then(function(state) {\n * console.log(state.totalShow === state.totalTargets); // true\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @return {Promise.}\n */\n\n show: function() {\n var self = this;\n\n return self.filter('all');\n },\n\n /**\n * A shorthand method for `.filter('none')`. Hides all targets in the container.\n *\n * @example\n *\n * .hide()\n *\n * @example Example: Hiding all targets\n *\n * mixer.hide()\n * .then(function(state) {\n * console.log(state.totalShow === 0); // true\n * console.log(state.totalHide === state.totalTargets); // true\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @return {Promise.}\n */\n\n hide: function() {\n var self = this;\n\n return self.filter('none');\n },\n\n /**\n * Returns a boolean indicating whether or not a MixItUp operation is\n * currently in progress.\n *\n * @example\n *\n * .isMixing()\n *\n * @example Example: Checking the status of a mixer\n *\n * mixer.sort('random', function() {\n * console.log(mixer.isMixing()) // false\n * });\n *\n * console.log(mixer.isMixing()) // true\n *\n * @public\n * @instance\n * @since 2.0.0\n * @return {boolean}\n */\n\n isMixing: function() {\n var self = this;\n\n return self.isBusy;\n },\n\n /**\n * Filters all targets in the container by a provided selector string, or the values `'all'`\n * or `'none'`. Only targets matching the selector will be shown.\n *\n * @example\n *\n * .filter(selector [, animate] [, callback])\n *\n * @example Example 1: Filtering targets by a class selector\n *\n * mixer.filter('.category-a')\n * .then(function(state) {\n * console.log(state.totalShow === containerEl.querySelectorAll('.category-a').length); // true\n * });\n *\n * @example Example 2: Filtering targets by an attribute selector\n *\n * mixer.filter('[data-category~=\"a\"]')\n * .then(function(state) {\n * console.log(state.totalShow === containerEl.querySelectorAll('[data-category~=\"a\"]').length); // true\n * });\n *\n * @example Example 3: Filtering targets by a compound selector\n *\n * // Show only those targets with the classes 'category-a' AND 'category-b'\n *\n * mixer.filter('.category-a.category-c')\n * .then(function(state) {\n * console.log(state.totalShow === containerEl.querySelectorAll('.category-a.category-c').length); // true\n * });\n *\n * @example Example 4: Filtering via an element collection\n *\n * var collection = Array.from(container.querySelectorAll('.mix'));\n *\n * console.log(collection.length); // 34\n *\n * // Filter the collection manually using Array.prototype.filter\n *\n * var filtered = collection.filter(function(target) {\n * return parseInt(target.getAttribute('data-price')) > 10;\n * });\n *\n * console.log(filtered.length); // 22\n *\n * // Pass the filtered collection to MixItUp\n *\n * mixer.filter(filtered)\n * .then(function(state) {\n * console.log(state.activeFilter.collection.length === 22); // true\n * });\n *\n * @public\n * @instance\n * @since 2.0.0\n * @param {(string|HTMLElement|Array.)} selector\n * Any valid CSS selector (i.e. `'.category-a'`), or the values `'all'` or `'none'`. The filter method also accepts a reference to single target element or a collection of target elements to show.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n filter: function() {\n var self = this,\n instruction = self.parseFilterArgs(arguments);\n\n return self.multimix({\n filter: instruction.command\n }, instruction.animate, instruction.callback);\n },\n\n /**\n * Adds an additional selector to the currently active filter selector, concatenating\n * as per the logic defined in `controls.toggleLogic`.\n *\n * @example\n *\n * .toggleOn(selector [, animate] [, callback])\n *\n * @example Example: Toggling on a filter selector\n *\n * console.log(mixer.getState().activeFilter.selector); // '.category-a'\n *\n * mixer.toggleOn('.category-b')\n * .then(function(state) {\n * console.log(state.activeFilter.selector); // '.category-a, .category-b'\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {string} selector\n * Any valid CSS selector (i.e. `'.category-a'`)\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n toggleOn: function() {\n var self = this,\n instruction = self.parseFilterArgs(arguments),\n selector = instruction.command.selector,\n toggleSelector = '';\n\n self.isToggling = true;\n\n if (self.toggleArray.indexOf(selector) < 0) {\n self.toggleArray.push(selector);\n }\n\n toggleSelector = self.getToggleSelector();\n\n return self.multimix({\n filter: toggleSelector\n }, instruction.animate, instruction.callback);\n },\n\n /**\n * Removes a selector from the active filter selector.\n *\n * @example\n *\n * .toggleOff(selector [, animate] [, callback])\n *\n * @example Example: Toggling off a filter selector\n *\n * console.log(mixer.getState().activeFilter.selector); // '.category-a, .category-b'\n *\n * mixer.toggleOff('.category-b')\n * .then(function(state) {\n * console.log(state.activeFilter.selector); // '.category-a'\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {string} selector\n * Any valid CSS selector (i.e. `'.category-a'`)\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n toggleOff: function() {\n var self = this,\n instruction = self.parseFilterArgs(arguments),\n selector = instruction.command.selector,\n selectorIndex = self.toggleArray.indexOf(selector),\n toggleSelector = '';\n\n self.isToggling = true;\n\n if (selectorIndex > -1) {\n self.toggleArray.splice(selectorIndex, 1);\n }\n\n toggleSelector = self.getToggleSelector();\n\n return self.multimix({\n filter: toggleSelector\n }, instruction.animate, instruction.callback);\n },\n\n /**\n * Sorts all targets in the container according to a provided sort string.\n *\n * @example\n *\n * .sort(sortString [, animate] [, callback])\n *\n * @example Example 1: Sorting by the default DOM order\n *\n * // Reverse the default order of the targets\n *\n * mixer.sort('default:desc')\n * .then(function(state) {\n * console.log(state.activeSort.attribute === 'default'); // true\n * console.log(state.activeSort.order === 'desc'); // true\n * });\n *\n * @example Example 2: Sorting by a custom data-attribute\n *\n * // Sort the targets by the value of a `data-published-date` attribute\n *\n * mixer.sort('published-date:asc')\n * .then(function(state) {\n * console.log(state.activeSort.attribute === 'published-date'); // true\n * console.log(state.activeSort.order === 'asc'); // true\n * });\n *\n * @example Example 3: Sorting by multiple attributes\n *\n * // Sort the targets by the value of a `data-published-date` attribute, then by `data-title`\n *\n * mixer.sort('published-date:desc data-title:asc')\n * .then(function(state) {\n * console.log(state.activeSort.attribute === 'published-date'); // true\n * console.log(state.activeSort.order === 'desc'); // true\n *\n * console.log(state.activeSort.next.attribute === 'title'); // true\n * console.log(state.activeSort.next.order === 'asc'); // true\n * });\n *\n * @example Example 4: Sorting by random\n *\n * mixer.sort('random')\n * .then(function(state) {\n * console.log(state.activeSort.order === 'random') // true\n * });\n *\n * @example Example 5: Sorting via an element collection\n *\n * var collection = Array.from(container.querySelectorAll('.mix'));\n *\n * // Swap the position of two elements in the collection:\n *\n * var temp = collection[1];\n *\n * collection[1] = collection[0];\n * collection[0] = temp;\n *\n * // Pass the sorted collection to MixItUp\n *\n * mixer.sort(collection)\n * .then(function(state) {\n * console.log(state.targets[0] === collection[0]); // true\n * });\n *\n * @public\n * @instance\n * @since 2.0.0\n * @param {(string|Array.)} sortString\n * A valid sort string (e.g. `'default'`, `'published-date:asc'`, or `'random'`). The sort method also accepts an array of all target elements in a user-defined order.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n sort: function() {\n var self = this,\n instruction = self.parseSortArgs(arguments);\n\n return self.multimix({\n sort: instruction.command\n }, instruction.animate, instruction.callback);\n },\n\n /**\n * Changes the layout of the container by adding, removing or updating a\n * layout-specific class name. If `animation.animateResizetargets` is\n * enabled, MixItUp will attempt to gracefully animate the width, height,\n * and position of targets between layout states.\n *\n * @example\n *\n * .changeLayout(containerClassName [, animate] [, callback])\n *\n * @example Example 1: Adding a new class name to the container\n *\n * mixer.changeLayout('container-list')\n * .then(function(state) {\n * console.log(state.activeContainerClass === 'container-list'); // true\n * });\n *\n * @example Example 2: Removing a previously added class name from the container\n *\n * mixer.changeLayout('')\n * .then(function(state) {\n * console.log(state.activeContainerClass === ''); // true\n * });\n *\n * @public\n * @instance\n * @since 2.0.0\n * @param {string} containerClassName\n * A layout-specific class name to add to the container.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n changeLayout: function() {\n var self = this,\n instruction = self.parseChangeLayoutArgs(arguments);\n\n return self.multimix({\n changeLayout: instruction.command\n }, instruction.animate, instruction.callback);\n },\n\n /**\n * Updates the contents and order of the container to reflect the provided dataset,\n * if the dataset API is in use.\n *\n * The dataset API is designed for use in API-driven JavaScript applications, and\n * can be used instead of DOM-based methods such as `.filter()`, `.sort()`,\n * `.insert()`, etc. When used, insertion, removal, sorting and pagination can be\n * achieved purely via changes to your data model, without the uglyness of having\n * to interact with or query the DOM directly.\n *\n * @example\n *\n * .dataset(dataset [, animate] [, callback])\n *\n * @example Example 1: Rendering a dataset\n *\n * var myDataset = [\n * {id: 1, ...},\n * {id: 2, ...},\n * {id: 3, ...}\n * ];\n *\n * mixer.dataset(myDataset)\n * .then(function(state) {\n * console.log(state.totalShow === 3); // true\n * });\n *\n * @example Example 2: Sorting a dataset\n *\n * // Create a new dataset in reverse order\n *\n * var newDataset = myDataset.slice().reverse();\n *\n * mixer.dataset(newDataset)\n * .then(function(state) {\n * console.log(state.activeDataset[0] === myDataset[2]); // true\n * });\n *\n * @example Example 3: Removing an item from the dataset\n *\n * console.log(myDataset.length); // 3\n *\n * // Create a new dataset with the last item removed.\n *\n * var newDataset = myDataset.slice().pop();\n *\n * mixer.dataset(newDataset)\n * .then(function(state) {\n * console.log(state.totalShow === 2); // true\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {Array.} dataset\n * An array of objects, each one representing the underlying data model of a target to be rendered.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n dataset: function() {\n var self = this,\n instruction = self.parseDatasetArgs(arguments),\n operation = null,\n queueItem = null,\n animate = false;\n\n self.callActions('beforeDataset', arguments);\n\n if (!self.isBusy) {\n if (instruction.callback) self.userCallback = instruction.callback;\n\n animate = (instruction.animate ^ self.config.animation.enable) ? instruction.animate : self.config.animation.enable;\n\n operation = self.getDataOperation(instruction.command.dataset);\n\n return self.goMix(animate, operation);\n } else {\n queueItem = new mixitup.QueueItem();\n\n queueItem.args = arguments;\n queueItem.instruction = instruction;\n\n return self.queueMix(queueItem);\n }\n },\n\n /**\n * Performs simultaneous `filter`, `sort`, `insert`, `remove` and `changeLayout`\n * operations as requested.\n *\n * @example\n *\n * .multimix(multimixCommand [, animate] [, callback])\n *\n * @example Example 1: Performing simultaneous filtering and sorting\n *\n * mixer.multimix({\n * filter: '.category-b',\n * sort: 'published-date:desc'\n * })\n * .then(function(state) {\n * console.log(state.activeFilter.selector === '.category-b'); // true\n * console.log(state.activeSort.attribute === 'published-date'); // true\n * });\n *\n * @example Example 2: Performing simultaneous sorting, insertion, and removal\n *\n * console.log(mixer.getState().totalShow); // 6\n *\n * // NB: When inserting via `multimix()`, an object should be provided as the value\n * // for the `insert` portion of the command, allowing for a collection of elements\n * // and an insertion index to be specified.\n *\n * mixer.multimix({\n * sort: 'published-date:desc', // Sort the container, including any new elements\n * insert: {\n * collection: [newElementReferenceA, newElementReferenceB], // Add 2 new elements at index 5\n * index: 5\n * },\n * remove: existingElementReference // Remove 1 existing element\n * })\n * .then(function(state) {\n * console.log(state.activeSort.attribute === 'published-date'); // true\n * console.log(state.totalShow === 7); // true\n * });\n *\n * @public\n * @instance\n * @since 2.0.0\n * @param {object} multimixCommand\n * An object containing one or more things to do\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n multimix: function() {\n var self = this,\n operation = null,\n animate = false,\n queueItem = null,\n instruction = self.parseMultimixArgs(arguments);\n\n self.callActions('beforeMultimix', arguments);\n\n if (!self.isBusy) {\n operation = self.getOperation(instruction.command);\n\n if (self.config.controls.enable) {\n // Update controls for API calls\n\n if (instruction.command.filter && !self.isToggling) {\n // As we are not toggling, reset the toggle array\n // so new filter overrides existing toggles\n\n self.toggleArray.length = 0;\n self.buildToggleArray(operation.command);\n }\n\n if (self.queue.length < 1) {\n self.updateControls(operation.command);\n }\n }\n\n if (instruction.callback) self.userCallback = instruction.callback;\n\n // Always allow the instruction to override the instance setting\n\n animate = (instruction.animate ^ self.config.animation.enable) ?\n instruction.animate :\n self.config.animation.enable;\n\n self.callFilters('operationMultimix', operation, arguments);\n\n return self.goMix(animate, operation);\n } else {\n queueItem = new mixitup.QueueItem();\n\n queueItem.args = arguments;\n queueItem.instruction = instruction;\n queueItem.triggerElement = self.lastClicked;\n queueItem.isToggling = self.isToggling;\n\n return self.queueMix(queueItem);\n }\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {object} multimixCommand\n * @param {boolean} [isPreFetch]\n * An optional boolean indicating that the operation is being pre-fetched for execution at a later time.\n * @return {Operation|null}\n */\n\n getOperation: function(multimixCommand) {\n var self = this,\n sortCommand = multimixCommand.sort,\n filterCommand = multimixCommand.filter,\n changeLayoutCommand = multimixCommand.changeLayout,\n removeCommand = multimixCommand.remove,\n insertCommand = multimixCommand.insert,\n operation = new mixitup.Operation();\n\n operation = self.callFilters('operationUnmappedGetOperation', operation, arguments);\n\n operation.id = h.randomHex();\n operation.command = multimixCommand;\n operation.startState = self.state;\n operation.triggerElement = self.lastClicked;\n\n if (self.isBusy) {\n if (self.config.debug.showWarnings) {\n console.warn(mixitup.messages.warningGetOperationInstanceBusy());\n }\n\n return null;\n }\n\n if (insertCommand) {\n self.insertTargets(insertCommand, operation);\n }\n\n if (removeCommand) {\n operation.toRemove = removeCommand.targets;\n }\n\n operation.startSort = operation.newSort = operation.startState.activeSort;\n operation.startOrder = operation.newOrder = self.targets;\n\n if (sortCommand) {\n operation.startSort = operation.startState.activeSort;\n operation.newSort = sortCommand;\n\n operation.willSort = self.willSort(sortCommand, operation.startState.activeSort);\n\n if (operation.willSort) {\n self.sortOperation(operation);\n }\n }\n\n operation.startFilter = operation.startState.activeFilter;\n\n if (filterCommand) {\n operation.newFilter = filterCommand;\n } else {\n operation.newFilter = h.extend(new mixitup.CommandFilter(), operation.startFilter);\n }\n\n if (operation.newFilter.selector === 'all') {\n operation.newFilter.selector = self.config.selectors.target;\n } else if (operation.newFilter.selector === 'none') {\n operation.newFilter.selector = '';\n }\n\n self.filterOperation(operation);\n\n operation.startContainerClassName = operation.startState.activeContainerClassName;\n\n if (changeLayoutCommand) {\n operation.newContainerClassName = changeLayoutCommand.containerClassName;\n\n if (operation.newContainerClassName !== operation.startContainerClassName) {\n operation.willChangeLayout = true;\n }\n } else {\n operation.newContainerClassName = operation.startContainerClassName;\n }\n\n if (self.config.animation.enable) {\n // Populate the operation's position data\n\n self.getStartMixData(operation);\n self.setInter(operation);\n\n operation.docState = h.getDocumentState(self.dom.document);\n\n self.getInterMixData(operation);\n self.setFinal(operation);\n self.getFinalMixData(operation);\n\n self.parseEffects();\n\n operation.hasEffect = self.hasEffect();\n\n self.getTweenData(operation);\n }\n\n if (operation.willSort) {\n self.targets = operation.newOrder;\n }\n\n operation.newState = self.buildState(operation);\n\n return self.callFilters('operationMappedGetOperation', operation, arguments);\n },\n\n /**\n * Renders a previously created operation at a specific point in its path, as\n * determined by a multiplier between 0 and 1.\n *\n * @example\n * .tween(operation, multiplier)\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {mixitup.Operation} operation\n * An operation object created via the `getOperation` method\n *\n * @param {Float} multiplier\n * Any number between 0 and 1 representing the percentage complete of the operation\n * @return {void}\n */\n\n tween: function(operation, multiplier) {\n var target = null,\n posData = null,\n toHideIndex = -1,\n i = -1;\n\n multiplier = Math.min(multiplier, 1);\n multiplier = Math.max(multiplier, 0);\n\n for (i = 0; target = operation.show[i]; i++) {\n posData = operation.showPosData[i];\n\n target.applyTween(posData, multiplier);\n }\n\n for (i = 0; target = operation.hide[i]; i++) {\n if (target.isShown) {\n target.hide();\n }\n\n if ((toHideIndex = operation.toHide.indexOf(target)) > -1) {\n posData = operation.toHidePosData[toHideIndex];\n\n if (!target.isShown) {\n target.show();\n }\n\n target.applyTween(posData, multiplier);\n }\n }\n },\n\n /**\n * Inserts one or more new target elements into the container at a specified\n * index.\n *\n * To be indexed as targets, new elements must match the `selectors.target`\n * selector (`'.mix'` by default).\n *\n * @example\n *\n * .insert(newElements [, index] [, animate], [, callback])\n *\n * @example Example 1: Inserting a single element via reference\n *\n * console.log(mixer.getState().totalShow); // 0\n *\n * // Create a new element\n *\n * var newElement = document.createElement('div');\n * newElement.classList.add('mix');\n *\n * mixer.insert(newElement)\n * .then(function(state) {\n * console.log(state.totalShow === 1); // true\n * });\n *\n * @example Example 2: Inserting a single element via HTML string\n *\n * console.log(mixer.getState().totalShow); // 1\n *\n * // Create a new element via reference\n *\n * var newElementHtml = '<div class=\"mix\"></div>';\n *\n * // Create and insert the new element at index 1\n *\n * mixer.insert(newElementHtml, 1)\n * .then(function(state) {\n * console.log(state.totalShow === 2); // true\n * console.log(state.show[1].outerHTML === newElementHtml); // true\n * });\n *\n * @example Example 3: Inserting multiple elements via reference\n *\n * console.log(mixer.getState().totalShow); // 2\n *\n * // Create an array of new elements to insert.\n *\n * var newElement1 = document.createElement('div');\n * var newElement2 = document.createElement('div');\n *\n * newElement1.classList.add('mix');\n * newElement2.classList.add('mix');\n *\n * var newElementsCollection = [newElement1, newElement2];\n *\n * // Insert the new elements starting at index 1\n *\n * mixer.insert(newElementsCollection, 1)\n * .then(function(state) {\n * console.log(state.totalShow === 4); // true\n * console.log(state.show[1] === newElement1); // true\n * console.log(state.show[2] === newElement2); // true\n * });\n *\n * @example Example 4: Inserting a jQuery collection object containing one or more elements\n *\n * console.log(mixer.getState().totalShow); // 4\n *\n * var $newElement = $('<div class=\"mix\"></div>');\n *\n * // Insert the new elements starting at index 3\n *\n * mixer.insert($newElement, 3)\n * .then(function(state) {\n * console.log(state.totalShow === 5); // true\n * console.log(state.show[3] === $newElement[0]); // true\n * });\n *\n * @public\n * @instance\n * @since 2.0.0\n * @param {(HTMLElement|Array.|string)} newElements\n * A reference to a single element to insert, an array-like collection of elements, or an HTML string representing a single element.\n * @param {number} index=0\n * The index at which to insert the new element(s). `0` by default.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n insert: function() {\n var self = this,\n args = self.parseInsertArgs(arguments);\n\n return self.multimix({\n insert: args.command\n }, args.animate, args.callback);\n },\n\n /**\n * Inserts one or more new elements before a provided reference element.\n *\n * @example\n *\n * .insertBefore(newElements, referenceElement [, animate] [, callback])\n *\n * @example Example: Inserting a new element before a reference element\n *\n * // An existing reference element is chosen at index 2\n *\n * var referenceElement = mixer.getState().show[2];\n *\n * // Create a new element\n *\n * var newElement = document.createElement('div');\n * newElement.classList.add('mix');\n *\n * mixer.insertBefore(newElement, referenceElement)\n * .then(function(state) {\n * // The new element is inserted into the container at index 2, before the reference element\n *\n * console.log(state.show[2] === newElement); // true\n *\n * // The reference element is now at index 3\n *\n * console.log(state.show[3] === referenceElement); // true\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {(HTMLElement|Array.|string)} newElements\n * A reference to a single element to insert, an array-like collection of elements, or an HTML string representing a single element.\n * @param {HTMLElement} referenceElement\n * A reference to an existing element in the container to insert new elements before.\n *@param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n insertBefore: function() {\n var self = this,\n args = self.parseInsertArgs(arguments);\n\n return self.insert(args.command.collection, 'before', args.command.sibling, args.animate, args.callback);\n },\n\n /**\n * Inserts one or more new elements after a provided reference element.\n *\n * @example\n *\n * .insertAfter(newElements, referenceElement [, animate] [, callback])\n *\n * @example Example: Inserting a new element after a reference element\n *\n * // An existing reference element is chosen at index 2\n *\n * var referenceElement = mixer.getState().show[2];\n *\n * // Create a new element\n *\n * var newElement = document.createElement('div');\n * newElement.classList.add('mix');\n *\n * mixer.insertAfter(newElement, referenceElement)\n * .then(function(state) {\n * // The new element is inserted into the container at index 3, after the reference element\n *\n * console.log(state.show[3] === newElement); // true\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {(HTMLElement|Array.|string)} newElements\n * A reference to a single element to insert, an array-like collection of elements, or an HTML string representing a single element.\n * @param {HTMLElement} referenceElement\n * A reference to an existing element in the container to insert new elements after.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n insertAfter: function() {\n var self = this,\n args = self.parseInsertArgs(arguments);\n\n return self.insert(args.command.collection, 'after', args.command.sibling, args.animate, args.callback);\n },\n\n /**\n * Inserts one or more new elements into the container before all existing targets.\n *\n * @example\n *\n * .prepend(newElements [,animate] [,callback])\n *\n * @example Example: Prepending a new element\n *\n * // Create a new element\n *\n * var newElement = document.createElement('div');\n * newElement.classList.add('mix');\n *\n * // Insert the element into the container\n *\n * mixer.prepend(newElement)\n * .then(function(state) {\n * console.log(state.show[0] === newElement); // true\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {(HTMLElement|Array.|string)} newElements\n * A reference to a single element to insert, an array-like collection of elements, or an HTML string representing a single element.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n prepend: function() {\n var self = this,\n args = self.parseInsertArgs(arguments);\n\n return self.insert(0, args.command.collection, args.animate, args.callback);\n },\n\n /**\n * Inserts one or more new elements into the container after all existing targets.\n *\n * @example\n *\n * .append(newElements [,animate] [,callback])\n *\n * @example Example: Appending a new element\n *\n * // Create a new element\n *\n * var newElement = document.createElement('div');\n * newElement.classList.add('mix');\n *\n * // Insert the element into the container\n *\n * mixer.append(newElement)\n * .then(function(state) {\n * console.log(state.show[state.show.length - 1] === newElement); // true\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {(HTMLElement|Array.|string)} newElements\n * A reference to a single element to insert, an array-like collection of elements, or an HTML string representing a single element.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n append: function() {\n var self = this,\n args = self.parseInsertArgs(arguments);\n\n return self.insert(self.state.totalTargets, args.command.collection, args.animate, args.callback);\n },\n\n /**\n * Removes one or more existing target elements from the container.\n *\n * @example\n *\n * .remove(elements [, animate] [, callback])\n *\n * @example Example 1: Removing an element by reference\n *\n * var elementToRemove = containerEl.firstElementChild;\n *\n * mixer.remove(elementToRemove)\n * .then(function(state) {\n * console.log(state.targets.indexOf(elementToRemove) === -1); // true\n * });\n *\n * @example Example 2: Removing a collection of elements by reference\n *\n * var elementsToRemove = containerEl.querySelectorAll('.category-a');\n *\n * console.log(elementsToRemove.length) // 3\n *\n * mixer.remove(elementsToRemove)\n * .then(function() {\n * console.log(containerEl.querySelectorAll('.category-a').length); // 0\n * });\n *\n * @example Example 3: Removing one or more elements by selector\n *\n * mixer.remove('.category-a')\n * .then(function() {\n * console.log(containerEl.querySelectorAll('.category-a').length); // 0\n * });\n *\n * @example Example 4: Removing an element by index\n *\n * console.log(mixer.getState.totalShow); // 4\n *\n * // Remove the element at index 3\n *\n * mixer.remove(3)\n * .then(function(state) {\n * console.log(state.totalShow); // 3\n * console.log(state.show[3]); // undefined\n * });\n *\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {(HTMLElement|Array.|string|number)} elements\n * A reference to a single element to remove, an array-like collection of elements, a selector string, or the index of an element to remove.\n * @param {boolean} [animate=true]\n * An optional boolean dictating whether the operation should animate, or occur syncronously with no animation. `true` by default.\n * @param {function} [callback=null]\n * An optional callback function to be invoked after the operation has completed.\n * @return {Promise.}\n * A promise resolving with the current state object.\n */\n\n remove: function() {\n var self = this,\n args = self.parseRemoveArgs(arguments);\n\n return self.multimix({\n remove: args.command\n }, args.animate, args.callback);\n },\n\n /**\n * Retrieves the the value of any property or sub-object within the current\n * mixitup configuration, or the whole configuration object.\n *\n * @example\n *\n * .getConfig([stringKey])\n *\n * @example Example 1: retrieve the entire configuration object\n *\n * var config = mixer.getConfig(); // Config { ... }\n *\n * @example Example 2: retrieve a named sub-object of configuration object\n *\n * var animation = mixer.getConfig('animation'); // ConfigAnimation { ... }\n *\n * @example Example 3: retrieve a value of configuration object via a dot-notation string key\n *\n * var effects = mixer.getConfig('animation.effects'); // 'fade scale'\n *\n * @public\n * @instance\n * @since 2.0.0\n * @param {string} [stringKey] A \"dot-notation\" string key\n * @return {*}\n */\n\n getConfig: function(stringKey) {\n var self = this,\n value = null;\n\n if (!stringKey) {\n value = self.config;\n } else {\n value = h.getProperty(self.config, stringKey);\n }\n\n return self.callFilters('valueGetConfig', value, arguments);\n },\n\n /**\n * Updates the configuration of the mixer, after it has been instantiated.\n *\n * See the Configuration Object documentation for a full list of avilable\n * configuration options.\n *\n * @example\n *\n * .configure(config)\n *\n * @example Example 1: Updating animation options\n *\n * mixer.configure({\n * animation: {\n * effects: 'fade translateX(-100%)',\n * duration: 300\n * }\n * });\n *\n * @example Example 2: Removing a callback after it has been set\n *\n * var mixer;\n *\n * function handleMixEndOnce() {\n * // Do something ..\n *\n * // Then nullify the callback\n *\n * mixer.configure({\n * callbacks: {\n * onMixEnd: null\n * }\n * });\n * };\n *\n * // Instantiate a mixer with a callback defined\n *\n * mixer = mixitup(containerEl, {\n * callbacks: {\n * onMixEnd: handleMixEndOnce\n * }\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {object} config\n * An object containing one of more configuration options.\n * @return {void}\n */\n\n configure: function(config) {\n var self = this;\n\n self.callActions('beforeConfigure', arguments);\n\n h.extend(self.config, config, true, true);\n\n self.callActions('afterConfigure', arguments);\n },\n\n /**\n * Returns an object containing information about the current state of the\n * mixer. See the State Object documentation for more information.\n *\n * NB: State objects are immutable and should therefore be regenerated\n * after any operation.\n *\n * @example\n *\n * .getState();\n *\n * @example Example: Retrieving a state object\n *\n * var state = mixer.getState();\n *\n * console.log(state.totalShow + 'targets are currently shown');\n *\n * @public\n * @instance\n * @since 2.0.0\n * @return {mixitup.State} An object reflecting the current state of the mixer.\n */\n\n getState: function() {\n var self = this,\n state = null;\n\n state = new mixitup.State();\n\n h.extend(state, self.state);\n\n h.freeze(state);\n\n return self.callFilters('stateGetState', state, arguments);\n },\n\n /**\n * Forces the re-indexing all targets within the container.\n *\n * This should only be used if some other piece of code in your application\n * has manipulated the contents of your container, which should be avoided.\n *\n * If you need to add or remove target elements from the container, use\n * the built-in `.insert()` or `.remove()` methods, and MixItUp will keep\n * itself up to date.\n *\n * @example\n *\n * .forceRefresh()\n *\n * @example Example: Force refreshing the mixer after external DOM manipulation\n *\n * console.log(mixer.getState().totalShow); // 3\n *\n * // An element is removed from the container via some external DOM manipulation code:\n *\n * containerEl.removeChild(containerEl.firstElementChild);\n *\n * // The mixer does not know that the number of targets has changed:\n *\n * console.log(mixer.getState().totalShow); // 3\n *\n * mixer.forceRefresh();\n *\n * // After forceRefresh, the mixer is in sync again:\n *\n * console.log(mixer.getState().totalShow); // 2\n *\n * @public\n * @instance\n * @since 2.1.2\n * @return {void}\n */\n\n forceRefresh: function() {\n var self = this;\n\n self.indexTargets();\n },\n\n /**\n * Forces the re-rendering of all targets when using the Dataset API.\n *\n * By default, targets are only re-rendered when `data.dirtyCheck` is\n * enabled, and an item's data has changed when `dataset()` is called.\n *\n * The `forceRender()` method allows for the re-rendering of all targets\n * in response to some arbitrary event, such as the changing of the target\n * render function.\n *\n * Targets are rendered against their existing data.\n *\n * @example\n *\n * .forceRender()\n *\n * @example Example: Force render targets after changing the target render function\n *\n * console.log(container.innerHTML); // ... <span class=\"mix\">Foo</span> ...\n *\n * mixer.configure({\n * render: {\n * target: (item) => `<a href=\"/${item.slug}/\" class=\"mix\">${item.title}</a>`\n * }\n * });\n *\n * mixer.forceRender();\n *\n * console.log(container.innerHTML); // ... <a href=\"/foo/\" class=\"mix\">Foo</a> ...\n *\n * @public\n * @instance\n * @since 3.2.1\n * @return {void}\n */\n\n forceRender: function() {\n var self = this,\n target = null,\n el = null,\n id = '';\n\n for (id in self.cache) {\n target = self.cache[id];\n\n el = target.render(target.data);\n\n if (el !== target.dom.el) {\n // Update target element reference\n\n if (target.isInDom) {\n target.unbindEvents();\n\n self.dom.parent.replaceChild(el, target.dom.el);\n }\n\n if (!target.isShown) {\n el.style.display = 'none';\n }\n\n target.dom.el = el;\n\n if (target.isInDom) {\n target.bindEvents();\n }\n }\n }\n\n self.state = self.buildState(self.lastOperation);\n },\n\n /**\n * Removes mixitup functionality from the container, unbinds all control\n * event handlers, and deletes the mixer instance from MixItUp's internal\n * cache.\n *\n * This should be performed whenever a mixer's container is removed from\n * the DOM, such as during a page change in a single page application,\n * or React's `componentWillUnmount()`.\n *\n * @example\n *\n * .destroy([cleanUp])\n *\n * @example Example: Destroying the mixer before removing its container element\n *\n * mixer.destroy();\n *\n * containerEl.parentElement.removeChild(containerEl);\n *\n * @public\n * @instance\n * @since 2.0.0\n * @param {boolean} [cleanUp=false]\n * An optional boolean dictating whether or not to clean up any inline `display: none;` styling applied to hidden targets.\n * @return {void}\n */\n\n destroy: function(cleanUp) {\n var self = this,\n control = null,\n target = null,\n i = 0;\n\n self.callActions('beforeDestroy', arguments);\n\n for (i = 0; control = self.controls[i]; i++) {\n control.removeBinding(self);\n }\n\n for (i = 0; target = self.targets[i]; i++) {\n if (cleanUp) {\n target.show();\n }\n\n target.unbindEvents();\n }\n\n if (self.dom.container.id.match(/^MixItUp/)) {\n self.dom.container.removeAttribute('id');\n }\n\n delete mixitup.instances[self.id];\n\n self.callActions('afterDestroy', arguments);\n }\n });\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.IMoveData = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.posIn = null;\n this.posOut = null;\n this.operation = null;\n this.callback = null;\n this.statusChange = '';\n this.duration = -1;\n this.staggerIndex = -1;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.IMoveData);\n\n mixitup.IMoveData.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.IMoveData.prototype.constructor = mixitup.IMoveData;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.TargetDom = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.el = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.TargetDom);\n\n mixitup.TargetDom.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.TargetDom.prototype.constructor = mixitup.TargetDom;\n\n /**\n * @constructor\n * @namespace\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.Target = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.id = '';\n this.sortString = '';\n this.mixer = null;\n this.callback = null;\n this.isShown = false;\n this.isBound = false;\n this.isExcluded = false;\n this.isInDom = false;\n this.handler = null;\n this.operation = null;\n this.data = null;\n this.dom = new mixitup.TargetDom();\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Target);\n\n mixitup.Target.prototype = Object.create(mixitup.Base.prototype);\n\n h.extend(mixitup.Target.prototype, {\n constructor: mixitup.Target,\n\n /**\n * Initialises a newly instantiated Target.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {(Element|null)} el\n * @param {object} mixer\n * @param {object} [data]\n * @return {void}\n */\n\n init: function(el, mixer, data) {\n var self = this,\n id = '';\n\n self.callActions('beforeInit', arguments);\n\n self.mixer = mixer;\n\n if (!el) {\n // If no element is provided, render it\n\n el = self.render(data);\n }\n\n self.cacheDom(el);\n\n self.bindEvents();\n\n if (self.dom.el.style.display !== 'none') {\n self.isShown = true;\n }\n\n if (data && mixer.config.data.uidKey) {\n if (typeof (id = data[mixer.config.data.uidKey]) === 'undefined' || id.toString().length < 1) {\n throw new TypeError(mixitup.messages.errorDatasetInvalidUidKey({\n uidKey: mixer.config.data.uidKey\n }));\n }\n\n self.id = id;\n self.data = data;\n\n mixer.cache[id] = self;\n }\n\n self.callActions('afterInit', arguments);\n },\n\n /**\n * Renders the target element using a user-defined renderer function.\n *\n * @private\n * @instance\n * @since 3.1.4\n * @param {object} data\n * @return {void}\n */\n\n render: function(data) {\n var self = this,\n render = null,\n el = null,\n temp = null,\n output = '';\n\n self.callActions('beforeRender', arguments);\n\n render = self.callFilters('renderRender', self.mixer.config.render.target, arguments);\n\n if (typeof render !== 'function') {\n throw new TypeError(mixitup.messages.errorDatasetRendererNotSet());\n }\n\n output = render(data);\n\n if (output && typeof output === 'object' && h.isElement(output)) {\n el = output;\n } else if (typeof output === 'string') {\n temp = document.createElement('div');\n temp.innerHTML = output;\n\n el = temp.firstElementChild;\n }\n\n return self.callFilters('elRender', el, arguments);\n },\n\n /**\n * Caches references of DOM elements neccessary for the target's functionality.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {Element} el\n * @return {void}\n */\n\n cacheDom: function(el) {\n var self = this;\n\n self.callActions('beforeCacheDom', arguments);\n\n self.dom.el = el;\n\n self.callActions('afterCacheDom', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {string} attributeName\n * @return {void}\n */\n\n getSortString: function(attributeName) {\n var self = this,\n value = self.dom.el.getAttribute('data-' + attributeName) || '';\n\n self.callActions('beforeGetSortString', arguments);\n\n value = isNaN(value * 1) ?\n value.toLowerCase() :\n value * 1;\n\n self.sortString = value;\n\n self.callActions('afterGetSortString', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @return {void}\n */\n\n show: function() {\n var self = this;\n\n self.callActions('beforeShow', arguments);\n\n if (!self.isShown) {\n self.dom.el.style.display = '';\n\n self.isShown = true;\n }\n\n self.callActions('afterShow', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @return {void}\n */\n\n hide: function() {\n var self = this;\n\n self.callActions('beforeHide', arguments);\n\n if (self.isShown) {\n self.dom.el.style.display = 'none';\n\n self.isShown = false;\n }\n\n self.callActions('afterHide', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {mixitup.IMoveData} moveData\n * @return {void}\n */\n\n move: function(moveData) {\n var self = this;\n\n self.callActions('beforeMove', arguments);\n\n if (!self.isExcluded) {\n self.mixer.targetsMoved++;\n }\n\n self.applyStylesIn(moveData);\n\n requestAnimationFrame(function() {\n self.applyStylesOut(moveData);\n });\n\n self.callActions('afterMove', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {object} posData\n * @param {number} multiplier\n * @return {void}\n */\n\n applyTween: function(posData, multiplier) {\n var self = this,\n propertyName = '',\n tweenData = null,\n posIn = posData.posIn,\n currentTransformValues = [],\n currentValues = new mixitup.StyleData(),\n i = -1;\n\n self.callActions('beforeApplyTween', arguments);\n\n currentValues.x = posIn.x;\n currentValues.y = posIn.y;\n\n if (multiplier === 0) {\n self.hide();\n } else if (!self.isShown) {\n self.show();\n }\n\n for (i = 0; propertyName = mixitup.features.TWEENABLE[i]; i++) {\n tweenData = posData.tweenData[propertyName];\n\n if (propertyName === 'x') {\n if (!tweenData) continue;\n\n currentValues.x = posIn.x + (tweenData * multiplier);\n } else if (propertyName === 'y') {\n if (!tweenData) continue;\n\n currentValues.y = posIn.y + (tweenData * multiplier);\n } else if (tweenData instanceof mixitup.TransformData) {\n if (!tweenData.value) continue;\n\n currentValues[propertyName].value =\n posIn[propertyName].value + (tweenData.value * multiplier);\n\n currentValues[propertyName].unit = tweenData.unit;\n\n currentTransformValues.push(\n propertyName + '(' + currentValues[propertyName].value + tweenData.unit + ')'\n );\n } else {\n if (!tweenData) continue;\n\n currentValues[propertyName] = posIn[propertyName] + (tweenData * multiplier);\n\n self.dom.el.style[propertyName] = currentValues[propertyName];\n }\n }\n\n if (currentValues.x || currentValues.y) {\n currentTransformValues.unshift('translate(' + currentValues.x + 'px, ' + currentValues.y + 'px)');\n }\n\n if (currentTransformValues.length) {\n self.dom.el.style[mixitup.features.transformProp] = currentTransformValues.join(' ');\n }\n\n self.callActions('afterApplyTween', arguments);\n },\n\n /**\n * Applies the initial styling to a target element before any transition\n * is applied.\n *\n * @private\n * @instance\n * @param {mixitup.IMoveData} moveData\n * @return {void}\n */\n\n applyStylesIn: function(moveData) {\n var self = this,\n posIn = moveData.posIn,\n isFading = self.mixer.effectsIn.opacity !== 1,\n transformValues = [];\n\n self.callActions('beforeApplyStylesIn', arguments);\n\n transformValues.push('translate(' + posIn.x + 'px, ' + posIn.y + 'px)');\n\n if (self.mixer.config.animation.animateResizeTargets) {\n if (moveData.statusChange !== 'show') {\n // Don't apply posIn width or height or showing, as will be 0\n\n self.dom.el.style.width = posIn.width + 'px';\n self.dom.el.style.height = posIn.height + 'px';\n }\n\n self.dom.el.style.marginRight = posIn.marginRight + 'px';\n self.dom.el.style.marginBottom = posIn.marginBottom + 'px';\n }\n\n isFading && (self.dom.el.style.opacity = posIn.opacity);\n\n if (moveData.statusChange === 'show') {\n transformValues = transformValues.concat(self.mixer.transformIn);\n }\n\n self.dom.el.style[mixitup.features.transformProp] = transformValues.join(' ');\n\n self.callActions('afterApplyStylesIn', arguments);\n },\n\n /**\n * Applies a transition followed by the final styles for the element to\n * transition towards.\n *\n * @private\n * @instance\n * @param {mixitup.IMoveData} moveData\n * @return {void}\n */\n\n applyStylesOut: function(moveData) {\n var self = this,\n transitionRules = [],\n transformValues = [],\n isResizing = self.mixer.config.animation.animateResizeTargets,\n isFading = typeof self.mixer.effectsIn.opacity !== 'undefined';\n\n self.callActions('beforeApplyStylesOut', arguments);\n\n // Build the transition rules\n\n transitionRules.push(self.writeTransitionRule(\n mixitup.features.transformRule,\n moveData.staggerIndex\n ));\n\n if (moveData.statusChange !== 'none') {\n transitionRules.push(self.writeTransitionRule(\n 'opacity',\n moveData.staggerIndex,\n moveData.duration\n ));\n }\n\n if (isResizing) {\n transitionRules.push(self.writeTransitionRule(\n 'width',\n moveData.staggerIndex,\n moveData.duration\n ));\n\n transitionRules.push(self.writeTransitionRule(\n 'height',\n moveData.staggerIndex,\n moveData.duration\n ));\n\n transitionRules.push(self.writeTransitionRule(\n 'margin',\n moveData.staggerIndex,\n moveData.duration\n ));\n }\n\n // If no callback was provided, the element will\n // not transition in any way so tag it as \"immovable\"\n\n if (!moveData.callback) {\n self.mixer.targetsImmovable++;\n\n if (self.mixer.targetsMoved === self.mixer.targetsImmovable) {\n // If the total targets moved is equal to the\n // number of immovable targets, the operation\n // should be considered finished\n\n self.mixer.cleanUp(moveData.operation);\n }\n\n return;\n }\n\n // If the target will transition in some fasion,\n // assign a callback function\n\n self.operation = moveData.operation;\n self.callback = moveData.callback;\n\n // As long as the target is not excluded, increment\n // the total number of targets bound\n\n !self.isExcluded && self.mixer.targetsBound++;\n\n // Tag the target as bound to differentiate from transitionEnd\n // events that may come from stylesheet driven effects\n\n self.isBound = true;\n\n // Apply the transition\n\n self.applyTransition(transitionRules);\n\n // Apply width, height and margin negation\n\n if (isResizing && moveData.posOut.width > 0 && moveData.posOut.height > 0) {\n self.dom.el.style.width = moveData.posOut.width + 'px';\n self.dom.el.style.height = moveData.posOut.height + 'px';\n self.dom.el.style.marginRight = moveData.posOut.marginRight + 'px';\n self.dom.el.style.marginBottom = moveData.posOut.marginBottom + 'px';\n }\n\n if (!self.mixer.config.animation.nudge && moveData.statusChange === 'hide') {\n // If we're not nudging, the translation should be\n // applied before any other transforms to prevent\n // lateral movement\n\n transformValues.push('translate(' + moveData.posOut.x + 'px, ' + moveData.posOut.y + 'px)');\n }\n\n // Apply fade\n\n switch (moveData.statusChange) {\n case 'hide':\n isFading && (self.dom.el.style.opacity = self.mixer.effectsOut.opacity);\n\n transformValues = transformValues.concat(self.mixer.transformOut);\n\n break;\n case 'show':\n isFading && (self.dom.el.style.opacity = 1);\n }\n\n if (\n self.mixer.config.animation.nudge ||\n (!self.mixer.config.animation.nudge && moveData.statusChange !== 'hide')\n ) {\n // Opposite of above - apply translate after\n // other transform\n\n transformValues.push('translate(' + moveData.posOut.x + 'px, ' + moveData.posOut.y + 'px)');\n }\n\n // Apply transforms\n\n self.dom.el.style[mixitup.features.transformProp] = transformValues.join(' ');\n\n self.callActions('afterApplyStylesOut', arguments);\n },\n\n /**\n * Combines the name of a CSS property with the appropriate duration and delay\n * values to created a valid transition rule.\n *\n * @private\n * @instance\n * @since 3.0.0\n * @param {string} property\n * @param {number} staggerIndex\n * @param {number} duration\n * @return {string}\n */\n\n writeTransitionRule: function(property, staggerIndex, duration) {\n var self = this,\n delay = self.getDelay(staggerIndex),\n rule = '';\n\n rule = property + ' ' +\n (duration > 0 ? duration : self.mixer.config.animation.duration) + 'ms ' +\n delay + 'ms ' +\n (property === 'opacity' ? 'linear' : self.mixer.config.animation.easing);\n\n return self.callFilters('ruleWriteTransitionRule', rule, arguments);\n },\n\n /**\n * Calculates the transition delay for each target element based on its index, if\n * staggering is applied. If defined, A custom `animation.staggerSeqeuence`\n * function can be used to manipulate the order of indices to produce custom\n * stagger effects (e.g. for use in a grid with irregular row lengths).\n *\n * @private\n * @instance\n * @since 2.0.0\n * @param {number} index\n * @return {number}\n */\n\n getDelay: function(index) {\n var self = this,\n delay = -1;\n\n if (typeof self.mixer.config.animation.staggerSequence === 'function') {\n index = self.mixer.config.animation.staggerSequence.call(self, index, self.state);\n }\n\n delay = !!self.mixer.staggerDuration ? index * self.mixer.staggerDuration : 0;\n\n return self.callFilters('delayGetDelay', delay, arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {string[]} rules\n * @return {void}\n */\n\n applyTransition: function(rules) {\n var self = this,\n transitionString = rules.join(', ');\n\n self.callActions('beforeApplyTransition', arguments);\n\n self.dom.el.style[mixitup.features.transitionProp] = transitionString;\n\n self.callActions('afterApplyTransition', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Event} e\n * @return {void}\n */\n\n handleTransitionEnd: function(e) {\n var self = this,\n propName = e.propertyName,\n canResize = self.mixer.config.animation.animateResizeTargets;\n\n self.callActions('beforeHandleTransitionEnd', arguments);\n\n if (\n self.isBound &&\n e.target.matches(self.mixer.config.selectors.target) &&\n (\n propName.indexOf('transform') > -1 ||\n propName.indexOf('opacity') > -1 ||\n canResize && propName.indexOf('height') > -1 ||\n canResize && propName.indexOf('width') > -1 ||\n canResize && propName.indexOf('margin') > -1\n )\n ) {\n self.callback.call(self, self.operation);\n\n self.isBound = false;\n self.callback = null;\n self.operation = null;\n }\n\n self.callActions('afterHandleTransitionEnd', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {Event} e\n * @return {void}\n */\n\n eventBus: function(e) {\n var self = this;\n\n self.callActions('beforeEventBus', arguments);\n\n switch (e.type) {\n case 'webkitTransitionEnd':\n case 'transitionend':\n self.handleTransitionEnd(e);\n }\n\n self.callActions('afterEventBus', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @return {void}\n */\n\n unbindEvents: function() {\n var self = this;\n\n self.callActions('beforeUnbindEvents', arguments);\n\n h.off(self.dom.el, 'webkitTransitionEnd', self.handler);\n h.off(self.dom.el, 'transitionend', self.handler);\n\n self.callActions('afterUnbindEvents', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @return {void}\n */\n\n bindEvents: function() {\n var self = this,\n transitionEndEvent = '';\n\n self.callActions('beforeBindEvents', arguments);\n\n transitionEndEvent = mixitup.features.transitionPrefix === 'webkit' ? 'webkitTransitionEnd' : 'transitionend';\n\n self.handler = function(e) {\n return self.eventBus(e);\n };\n\n h.on(self.dom.el, transitionEndEvent, self.handler);\n\n self.callActions('afterBindEvents', arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @param {boolean} [getBox]\n * @return {PosData}\n */\n\n getPosData: function(getBox) {\n var self = this,\n styles = {},\n rect = null,\n posData = new mixitup.StyleData();\n\n self.callActions('beforeGetPosData', arguments);\n\n posData.x = self.dom.el.offsetLeft;\n posData.y = self.dom.el.offsetTop;\n\n if (self.mixer.config.animation.animateResizeTargets || getBox) {\n rect = self.dom.el.getBoundingClientRect();\n\n posData.top = rect.top;\n posData.right = rect.right;\n posData.bottom = rect.bottom;\n posData.left = rect.left;\n\n posData.width = rect.width;\n posData.height = rect.height;\n }\n\n if (self.mixer.config.animation.animateResizeTargets) {\n styles = window.getComputedStyle(self.dom.el);\n\n posData.marginBottom = parseFloat(styles.marginBottom);\n posData.marginRight = parseFloat(styles.marginRight);\n }\n\n return self.callFilters('posDataGetPosData', posData, arguments);\n },\n\n /**\n * @private\n * @instance\n * @since 3.0.0\n * @return {void}\n */\n\n cleanUp: function() {\n var self = this;\n\n self.callActions('beforeCleanUp', arguments);\n\n self.dom.el.style[mixitup.features.transformProp] = '';\n self.dom.el.style[mixitup.features.transitionProp] = '';\n self.dom.el.style.opacity = '';\n\n if (self.mixer.config.animation.animateResizeTargets) {\n self.dom.el.style.width = '';\n self.dom.el.style.height = '';\n self.dom.el.style.marginRight = '';\n self.dom.el.style.marginBottom = '';\n }\n\n self.callActions('afterCleanUp', arguments);\n }\n });\n\n /**\n * A jQuery-collection-like wrapper around one or more `mixitup.Mixer` instances\n * allowing simultaneous control of said instances similar to the MixItUp 2 API.\n *\n * @example\n * new mixitup.Collection(instances)\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @private\n * @since 3.0.0\n * @param {mixitup.Mixer[]} instances\n */\n\n mixitup.Collection = function(instances) {\n var instance = null,\n i = -1;\n\n this.callActions('beforeConstruct');\n\n for (i = 0; instance = instances[i]; i++) {\n this[i] = instance;\n }\n\n this.length = instances.length;\n\n this.callActions('afterConstruct');\n\n h.freeze(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Collection);\n\n mixitup.Collection.prototype = Object.create(mixitup.Base.prototype);\n\n h.extend(mixitup.Collection.prototype,\n /** @lends mixitup.Collection */\n {\n constructor: mixitup.Collection,\n\n /**\n * Calls a method on all instances in the collection by passing the method\n * name as a string followed by any applicable parameters to be curried into\n * to the method.\n *\n * @example\n * .mixitup(methodName[,arg1][,arg2..]);\n *\n * @example\n * var collection = new Collection([mixer1, mixer2]);\n *\n * return collection.mixitup('filter', '.category-a')\n * .then(function(states) {\n * state.forEach(function(state) {\n * console.log(state.activeFilter.selector); // .category-a\n * });\n * });\n *\n * @public\n * @instance\n * @since 3.0.0\n * @param {string} methodName\n * @return {Promise>}\n */\n\n mixitup: function(methodName) {\n var self = this,\n instance = null,\n args = Array.prototype.slice.call(arguments),\n tasks = [],\n i = -1;\n\n this.callActions('beforeMixitup');\n\n args.shift();\n\n for (i = 0; instance = self[i]; i++) {\n tasks.push(instance[methodName].apply(instance, args));\n }\n\n return self.callFilters('promiseMixitup', h.all(tasks, mixitup.libraries), arguments);\n }\n });\n\n /**\n * `mixitup.Operation` objects contain all data neccessary to describe the full\n * lifecycle of any MixItUp operation. They can be used to compute and store an\n * operation for use at a later time (e.g. programmatic tweening).\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.Operation = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.id = '';\n\n this.args = [];\n this.command = null;\n this.showPosData = [];\n this.toHidePosData = [];\n\n this.startState = null;\n this.newState = null;\n this.docState = null;\n\n this.willSort = false;\n this.willChangeLayout = false;\n this.hasEffect = false;\n this.hasFailed = false;\n\n this.triggerElement = null;\n\n this.show = [];\n this.hide = [];\n this.matching = [];\n this.toShow = [];\n this.toHide = [];\n this.toMove = [];\n this.toRemove = [];\n this.startOrder = [];\n this.newOrder = [];\n this.startSort = null;\n this.newSort = null;\n this.startFilter = null;\n this.newFilter = null;\n this.startDataset = null;\n this.newDataset = null;\n this.viewportDeltaX = 0;\n this.viewportDeltaY = 0;\n this.startX = 0;\n this.startY = 0;\n this.startHeight = 0;\n this.startWidth = 0;\n this.newX = 0;\n this.newY = 0;\n this.newHeight = 0;\n this.newWidth = 0;\n this.startContainerClassName = '';\n this.startDisplay = '';\n this.newContainerClassName = '';\n this.newDisplay = '';\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Operation);\n\n mixitup.Operation.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.Operation.prototype.constructor = mixitup.Operation;\n\n /**\n * `mixitup.State` objects expose various pieces of data detailing the state of\n * a MixItUp instance. They are provided at the start and end of any operation via\n * callbacks and events, with the most recent state stored between operations\n * for retrieval at any time via the API.\n *\n * @constructor\n * @namespace\n * @memberof mixitup\n * @public\n * @since 3.0.0\n */\n\n mixitup.State = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /**\n * The ID of the mixer instance.\n *\n * @name id\n * @memberof mixitup.State\n * @instance\n * @type {string}\n * @default ''\n */\n\n this.id = '';\n\n /**\n * The currently active filter command as set by a control click or API call.\n *\n * @name activeFilter\n * @memberof mixitup.State\n * @instance\n * @type {mixitup.CommandFilter}\n * @default null\n */\n\n this.activeFilter = null;\n\n /**\n * The currently active sort command as set by a control click or API call.\n *\n * @name activeSort\n * @memberof mixitup.State\n * @instance\n * @type {mixitup.CommandSort}\n * @default null\n */\n\n this.activeSort = null;\n\n /**\n * The current layout-specific container class name, if applied.\n *\n * @name activeContainerClassName\n * @memberof mixitup.State\n * @instance\n * @type {string}\n * @default ''\n */\n\n this.activeContainerClassName = '';\n\n /**\n * A reference to the container element that the mixer is instantiated on.\n *\n * @name container\n * @memberof mixitup.State\n * @instance\n * @type {Element}\n * @default null\n */\n\n this.container = null;\n\n /**\n * An array of all target elements indexed by the mixer.\n *\n * @name targets\n * @memberof mixitup.State\n * @instance\n * @type {Array.}\n * @default []\n */\n\n this.targets = [];\n\n /**\n * An array of all target elements not matching the current filter.\n *\n * @name hide\n * @memberof mixitup.State\n * @instance\n * @type {Array.}\n * @default []\n */\n\n this.hide = [];\n\n /**\n * An array of all target elements matching the current filter and any additional\n * limits applied such as pagination.\n *\n * @name show\n * @memberof mixitup.State\n * @instance\n * @type {Array.}\n * @default []\n */\n\n this.show = [];\n\n /**\n * An array of all target elements matching the current filter irrespective of\n * any additional limits applied such as pagination.\n *\n * @name matching\n * @memberof mixitup.State\n * @instance\n * @type {Array.}\n * @default []\n */\n\n this.matching = [];\n\n /**\n * An integer representing the total number of target elements indexed by the\n * mixer. Equivalent to `state.targets.length`.\n *\n * @name totalTargets\n * @memberof mixitup.State\n * @instance\n * @type {number}\n * @default -1\n */\n\n this.totalTargets = -1;\n\n /**\n * An integer representing the total number of target elements matching the\n * current filter and any additional limits applied such as pagination.\n * Equivalent to `state.show.length`.\n *\n * @name totalShow\n * @memberof mixitup.State\n * @instance\n * @type {number}\n * @default -1\n */\n\n this.totalShow = -1;\n\n /**\n * An integer representing the total number of target elements not matching\n * the current filter. Equivalent to `state.hide.length`.\n *\n * @name totalHide\n * @memberof mixitup.State\n * @instance\n * @type {number}\n * @default -1\n */\n\n this.totalHide = -1;\n\n /**\n * An integer representing the total number of target elements matching the\n * current filter irrespective of any other limits applied such as pagination.\n * Equivalent to `state.matching.length`.\n *\n * @name totalMatching\n * @memberof mixitup.State\n * @instance\n * @type {number}\n * @default -1\n */\n\n this.totalMatching = -1;\n\n /**\n * A boolean indicating whether the last operation \"failed\", i.e. no targets\n * could be found matching the filter.\n *\n * @name hasFailed\n * @memberof mixitup.State\n * @instance\n * @type {boolean}\n * @default false\n */\n\n this.hasFailed = false;\n\n /**\n * The DOM element that was clicked if the last operation was triggered by the\n * clicking of a control and not an API call.\n *\n * @name triggerElement\n * @memberof mixitup.State\n * @instance\n * @type {Element|null}\n * @default null\n */\n\n this.triggerElement = null;\n\n /**\n * The currently active dataset underlying the rendered targets, if the\n * dataset API is in use.\n *\n * @name activeDataset\n * @memberof mixitup.State\n * @instance\n * @type {Array.}\n * @default null\n */\n\n this.activeDataset = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.State);\n\n mixitup.State.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.State.prototype.constructor = mixitup.State;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.UserInstruction = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n this.command = {};\n this.animate = false;\n this.callback = null;\n\n this.callActions('afterConstruct');\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.UserInstruction);\n\n mixitup.UserInstruction.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.UserInstruction.prototype.constructor = mixitup.UserInstruction;\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n */\n\n mixitup.Messages = function() {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct');\n\n /* Errors\n ----------------------------------------------------------------------------- */\n\n this.ERROR_FACTORY_INVALID_CONTAINER =\n '[MixItUp] An invalid selector or element reference was passed to the mixitup factory function';\n\n this.ERROR_FACTORY_CONTAINER_NOT_FOUND =\n '[MixItUp] The provided selector yielded no container element';\n\n this.ERROR_CONFIG_INVALID_ANIMATION_EFFECTS =\n '[MixItUp] Invalid value for `animation.effects`';\n\n this.ERROR_CONFIG_INVALID_CONTROLS_SCOPE =\n '[MixItUp] Invalid value for `controls.scope`';\n\n this.ERROR_CONFIG_INVALID_PROPERTY =\n '[MixitUp] Invalid configuration object property \"${erroneous}\"${suggestion}';\n\n this.ERROR_CONFIG_INVALID_PROPERTY_SUGGESTION =\n '. Did you mean \"${probableMatch}\"?';\n\n this.ERROR_CONFIG_DATA_UID_KEY_NOT_SET =\n '[MixItUp] To use the dataset API, a UID key must be specified using `data.uidKey`';\n\n this.ERROR_DATASET_INVALID_UID_KEY =\n '[MixItUp] The specified UID key \"${uidKey}\" is not present on one or more dataset items';\n\n this.ERROR_DATASET_DUPLICATE_UID =\n '[MixItUp] The UID \"${uid}\" was found on two or more dataset items. UIDs must be unique.';\n\n this.ERROR_INSERT_INVALID_ARGUMENTS =\n '[MixItUp] Please provider either an index or a sibling and position to insert, not both';\n\n this.ERROR_INSERT_PREEXISTING_ELEMENT =\n '[MixItUp] An element to be inserted already exists in the container';\n\n this.ERROR_FILTER_INVALID_ARGUMENTS =\n '[MixItUp] Please provide either a selector or collection `.filter()`, not both';\n\n this.ERROR_DATASET_NOT_SET =\n '[MixItUp] To use the dataset API with pre-rendered targets, a starting dataset must be set using `load.dataset`';\n\n this.ERROR_DATASET_PRERENDERED_MISMATCH =\n '[MixItUp] `load.dataset` does not match pre-rendered targets';\n\n this.ERROR_DATASET_RENDERER_NOT_SET =\n '[MixItUp] To insert an element via the dataset API, a target renderer function must be provided to `render.target`';\n\n this.ERROR_SORT_NON_EXISTENT_ELEMENT =\n '[MixItUp] An element to be sorted does not already exist in the container';\n\n /* Warnings\n ----------------------------------------------------------------------------- */\n\n this.WARNING_FACTORY_PREEXISTING_INSTANCE =\n '[MixItUp] WARNING: This element already has an active MixItUp instance. The provided configuration object will be ignored.' +\n ' If you wish to perform additional methods on this instance, please create a reference.';\n\n this.WARNING_INSERT_NO_ELEMENTS =\n '[MixItUp] WARNING: No valid elements were passed to `.insert()`';\n\n this.WARNING_REMOVE_NO_ELEMENTS =\n '[MixItUp] WARNING: No valid elements were passed to `.remove()`';\n\n this.WARNING_MULTIMIX_INSTANCE_QUEUE_FULL =\n '[MixItUp] WARNING: An operation was requested but the MixItUp instance was busy. The operation was rejected because the ' +\n 'queue is full or queuing is disabled.';\n\n this.WARNING_GET_OPERATION_INSTANCE_BUSY =\n '[MixItUp] WARNING: Operations can be be created while the MixItUp instance is busy.';\n\n this.WARNING_NO_PROMISE_IMPLEMENTATION =\n '[MixItUp] WARNING: No Promise implementations could be found. If you wish to use promises with MixItUp please install' +\n ' an ES6 Promise polyfill.';\n\n this.WARNING_INCONSISTENT_SORTING_ATTRIBUTES =\n '[MixItUp] WARNING: The requested sorting data attribute \"${attribute}\" was not present on one or more target elements' +\n ' which may product unexpected sort output';\n\n this.callActions('afterConstruct');\n\n this.compileTemplates();\n\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Messages);\n\n mixitup.Messages.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.Messages.prototype.constructor = mixitup.Messages;\n\n /**\n * @return {void}\n */\n\n mixitup.Messages.prototype.compileTemplates = function() {\n var errorKey = '';\n var errorMessage = '';\n\n for (errorKey in this) {\n if (typeof (errorMessage = this[errorKey]) !== 'string') continue;\n\n this[h.camelCase(errorKey)] = h.template(errorMessage);\n }\n };\n\n mixitup.messages = new mixitup.Messages();\n\n /**\n * @constructor\n * @memberof mixitup\n * @private\n * @since 3.0.0\n * @param {mixitup.Mixer} mixer\n */\n\n mixitup.Facade = function Mixer(mixer) {\n mixitup.Base.call(this);\n\n this.callActions('beforeConstruct', arguments);\n\n this.configure = mixer.configure.bind(mixer);\n this.show = mixer.show.bind(mixer);\n this.hide = mixer.hide.bind(mixer);\n this.filter = mixer.filter.bind(mixer);\n this.toggleOn = mixer.toggleOn.bind(mixer);\n this.toggleOff = mixer.toggleOff.bind(mixer);\n this.sort = mixer.sort.bind(mixer);\n this.changeLayout = mixer.changeLayout.bind(mixer);\n this.multimix = mixer.multimix.bind(mixer);\n this.dataset = mixer.dataset.bind(mixer);\n this.tween = mixer.tween.bind(mixer);\n this.insert = mixer.insert.bind(mixer);\n this.insertBefore = mixer.insertBefore.bind(mixer);\n this.insertAfter = mixer.insertAfter.bind(mixer);\n this.prepend = mixer.prepend.bind(mixer);\n this.append = mixer.append.bind(mixer);\n this.remove = mixer.remove.bind(mixer);\n this.destroy = mixer.destroy.bind(mixer);\n this.forceRefresh = mixer.forceRefresh.bind(mixer);\n this.forceRender = mixer.forceRender.bind(mixer);\n this.isMixing = mixer.isMixing.bind(mixer);\n this.getOperation = mixer.getOperation.bind(mixer);\n this.getConfig = mixer.getConfig.bind(mixer);\n this.getState = mixer.getState.bind(mixer);\n\n this.callActions('afterConstruct', arguments);\n\n h.freeze(this);\n h.seal(this);\n };\n\n mixitup.BaseStatic.call(mixitup.Facade);\n\n mixitup.Facade.prototype = Object.create(mixitup.Base.prototype);\n\n mixitup.Facade.prototype.constructor = mixitup.Facade;\n\n if (typeof exports === 'object' && typeof module === 'object') {\n module.exports = mixitup;\n } else if (typeof define === 'function' && define.amd) {\n define(function() {\n return mixitup;\n });\n } else if (typeof window.mixitup === 'undefined' || typeof window.mixitup !== 'function') {\n window.mixitup = mixitup;\n }\n mixitup.BaseStatic.call(mixitup.constructor);\n\n mixitup.NAME = 'mixitup';\n mixitup.CORE_VERSION = '3.3.1';\n})(window);", "(function(window, factory) {\n\tvar lazySizes = factory(window, window.document, Date);\n\twindow.lazySizes = lazySizes;\n\tif(typeof module == 'object' && module.exports){\n\t\tmodule.exports = lazySizes;\n\t}\n}(typeof window != 'undefined' ?\n window : {}, \n/**\n * import(\"./types/global\")\n * @typedef { import(\"./types/lazysizes-config\").LazySizesConfigPartial } LazySizesConfigPartial\n */\nfunction l(window, document, Date) { // Pass in the window Date function also for SSR because the Date class can be lost\n\t'use strict';\n\t/*jshint eqnull:true */\n\n\tvar lazysizes,\n\t\t/**\n\t\t * @type { LazySizesConfigPartial }\n\t\t */\n\t\tlazySizesCfg;\n\n\t(function(){\n\t\tvar prop;\n\n\t\tvar lazySizesDefaults = {\n\t\t\tlazyClass: 'lazyload',\n\t\t\tloadedClass: 'lazyloaded',\n\t\t\tloadingClass: 'lazyloading',\n\t\t\tpreloadClass: 'lazypreload',\n\t\t\terrorClass: 'lazyerror',\n\t\t\t//strictClass: 'lazystrict',\n\t\t\tautosizesClass: 'lazyautosizes',\n\t\t\tfastLoadedClass: 'ls-is-cached',\n\t\t\tiframeLoadMode: 0,\n\t\t\tsrcAttr: 'data-src',\n\t\t\tsrcsetAttr: 'data-srcset',\n\t\t\tsizesAttr: 'data-sizes',\n\t\t\t//preloadAfterLoad: false,\n\t\t\tminSize: 40,\n\t\t\tcustomMedia: {},\n\t\t\tinit: true,\n\t\t\texpFactor: 1.5,\n\t\t\thFac: 0.8,\n\t\t\tloadMode: 2,\n\t\t\tloadHidden: true,\n\t\t\tricTimeout: 0,\n\t\t\tthrottleDelay: 125,\n\t\t};\n\n\t\tlazySizesCfg = window.lazySizesConfig || window.lazysizesConfig || {};\n\n\t\tfor(prop in lazySizesDefaults){\n\t\t\tif(!(prop in lazySizesCfg)){\n\t\t\t\tlazySizesCfg[prop] = lazySizesDefaults[prop];\n\t\t\t}\n\t\t}\n\t})();\n\n\tif (!document || !document.getElementsByClassName) {\n\t\treturn {\n\t\t\tinit: function () {},\n\t\t\t/**\n\t\t\t * @type { LazySizesConfigPartial }\n\t\t\t */\n\t\t\tcfg: lazySizesCfg,\n\t\t\t/**\n\t\t\t * @type { true }\n\t\t\t */\n\t\t\tnoSupport: true,\n\t\t};\n\t}\n\n\tvar docElem = document.documentElement;\n\n\tvar supportPicture = window.HTMLPictureElement;\n\n\tvar _addEventListener = 'addEventListener';\n\n\tvar _getAttribute = 'getAttribute';\n\n\t/**\n\t * Update to bind to window because 'this' becomes null during SSR\n\t * builds.\n\t */\n\tvar addEventListener = window[_addEventListener].bind(window);\n\n\tvar setTimeout = window.setTimeout;\n\n\tvar requestAnimationFrame = window.requestAnimationFrame || setTimeout;\n\n\tvar requestIdleCallback = window.requestIdleCallback;\n\n\tvar regPicture = /^picture$/i;\n\n\tvar loadEvents = ['load', 'error', 'lazyincluded', '_lazyloaded'];\n\n\tvar regClassCache = {};\n\n\tvar forEach = Array.prototype.forEach;\n\n\t/**\n\t * @param ele {Element}\n\t * @param cls {string}\n\t */\n\tvar hasClass = function(ele, cls) {\n\t\tif(!regClassCache[cls]){\n\t\t\tregClassCache[cls] = new RegExp('(\\\\s|^)'+cls+'(\\\\s|$)');\n\t\t}\n\t\treturn regClassCache[cls].test(ele[_getAttribute]('class') || '') && regClassCache[cls];\n\t};\n\n\t/**\n\t * @param ele {Element}\n\t * @param cls {string}\n\t */\n\tvar addClass = function(ele, cls) {\n\t\tif (!hasClass(ele, cls)){\n\t\t\tele.setAttribute('class', (ele[_getAttribute]('class') || '').trim() + ' ' + cls);\n\t\t}\n\t};\n\n\t/**\n\t * @param ele {Element}\n\t * @param cls {string}\n\t */\n\tvar removeClass = function(ele, cls) {\n\t\tvar reg;\n\t\tif ((reg = hasClass(ele,cls))) {\n\t\t\tele.setAttribute('class', (ele[_getAttribute]('class') || '').replace(reg, ' '));\n\t\t}\n\t};\n\n\tvar addRemoveLoadEvents = function(dom, fn, add){\n\t\tvar action = add ? _addEventListener : 'removeEventListener';\n\t\tif(add){\n\t\t\taddRemoveLoadEvents(dom, fn);\n\t\t}\n\t\tloadEvents.forEach(function(evt){\n\t\t\tdom[action](evt, fn);\n\t\t});\n\t};\n\n\t/**\n\t * @param elem { Element }\n\t * @param name { string }\n\t * @param detail { any }\n\t * @param noBubbles { boolean }\n\t * @param noCancelable { boolean }\n\t * @returns { CustomEvent }\n\t */\n\tvar triggerEvent = function(elem, name, detail, noBubbles, noCancelable){\n\t\tvar event = document.createEvent('Event');\n\n\t\tif(!detail){\n\t\t\tdetail = {};\n\t\t}\n\n\t\tdetail.instance = lazysizes;\n\n\t\tevent.initEvent(name, !noBubbles, !noCancelable);\n\n\t\tevent.detail = detail;\n\n\t\telem.dispatchEvent(event);\n\t\treturn event;\n\t};\n\n\tvar updatePolyfill = function (el, full){\n\t\tvar polyfill;\n\t\tif( !supportPicture && ( polyfill = (window.picturefill || lazySizesCfg.pf) ) ){\n\t\t\tif(full && full.src && !el[_getAttribute]('srcset')){\n\t\t\t\tel.setAttribute('srcset', full.src);\n\t\t\t}\n\t\t\tpolyfill({reevaluate: true, elements: [el]});\n\t\t} else if(full && full.src){\n\t\t\tel.src = full.src;\n\t\t}\n\t};\n\n\tvar getCSS = function (elem, style){\n\t\treturn (getComputedStyle(elem, null) || {})[style];\n\t};\n\n\t/**\n\t *\n\t * @param elem { Element }\n\t * @param parent { Element }\n\t * @param [width] {number}\n\t * @returns {number}\n\t */\n\tvar getWidth = function(elem, parent, width){\n\t\twidth = width || elem.offsetWidth;\n\n\t\twhile(width < lazySizesCfg.minSize && parent && !elem._lazysizesWidth){\n\t\t\twidth = parent.offsetWidth;\n\t\t\tparent = parent.parentNode;\n\t\t}\n\n\t\treturn width;\n\t};\n\n\tvar rAF = (function(){\n\t\tvar running, waiting;\n\t\tvar firstFns = [];\n\t\tvar secondFns = [];\n\t\tvar fns = firstFns;\n\n\t\tvar run = function(){\n\t\t\tvar runFns = fns;\n\n\t\t\tfns = firstFns.length ? secondFns : firstFns;\n\n\t\t\trunning = true;\n\t\t\twaiting = false;\n\n\t\t\twhile(runFns.length){\n\t\t\t\trunFns.shift()();\n\t\t\t}\n\n\t\t\trunning = false;\n\t\t};\n\n\t\tvar rafBatch = function(fn, queue){\n\t\t\tif(running && !queue){\n\t\t\t\tfn.apply(this, arguments);\n\t\t\t} else {\n\t\t\t\tfns.push(fn);\n\n\t\t\t\tif(!waiting){\n\t\t\t\t\twaiting = true;\n\t\t\t\t\t(document.hidden ? setTimeout : requestAnimationFrame)(run);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\trafBatch._lsFlush = run;\n\n\t\treturn rafBatch;\n\t})();\n\n\tvar rAFIt = function(fn, simple){\n\t\treturn simple ?\n\t\t\tfunction() {\n\t\t\t\trAF(fn);\n\t\t\t} :\n\t\t\tfunction(){\n\t\t\t\tvar that = this;\n\t\t\t\tvar args = arguments;\n\t\t\t\trAF(function(){\n\t\t\t\t\tfn.apply(that, args);\n\t\t\t\t});\n\t\t\t}\n\t\t;\n\t};\n\n\tvar throttle = function(fn){\n\t\tvar running;\n\t\tvar lastTime = 0;\n\t\tvar gDelay = lazySizesCfg.throttleDelay;\n\t\tvar rICTimeout = lazySizesCfg.ricTimeout;\n\t\tvar run = function(){\n\t\t\trunning = false;\n\t\t\tlastTime = Date.now();\n\t\t\tfn();\n\t\t};\n\t\tvar idleCallback = requestIdleCallback && rICTimeout > 49 ?\n\t\t\tfunction(){\n\t\t\t\trequestIdleCallback(run, {timeout: rICTimeout});\n\n\t\t\t\tif(rICTimeout !== lazySizesCfg.ricTimeout){\n\t\t\t\t\trICTimeout = lazySizesCfg.ricTimeout;\n\t\t\t\t}\n\t\t\t} :\n\t\t\trAFIt(function(){\n\t\t\t\tsetTimeout(run);\n\t\t\t}, true)\n\t\t;\n\n\t\treturn function(isPriority){\n\t\t\tvar delay;\n\n\t\t\tif((isPriority = isPriority === true)){\n\t\t\t\trICTimeout = 33;\n\t\t\t}\n\n\t\t\tif(running){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\trunning = true;\n\n\t\t\tdelay = gDelay - (Date.now() - lastTime);\n\n\t\t\tif(delay < 0){\n\t\t\t\tdelay = 0;\n\t\t\t}\n\n\t\t\tif(isPriority || delay < 9){\n\t\t\t\tidleCallback();\n\t\t\t} else {\n\t\t\t\tsetTimeout(idleCallback, delay);\n\t\t\t}\n\t\t};\n\t};\n\n\t//based on http://modernjavascript.blogspot.de/2013/08/building-better-debounce.html\n\tvar debounce = function(func) {\n\t\tvar timeout, timestamp;\n\t\tvar wait = 99;\n\t\tvar run = function(){\n\t\t\ttimeout = null;\n\t\t\tfunc();\n\t\t};\n\t\tvar later = function() {\n\t\t\tvar last = Date.now() - timestamp;\n\n\t\t\tif (last < wait) {\n\t\t\t\tsetTimeout(later, wait - last);\n\t\t\t} else {\n\t\t\t\t(requestIdleCallback || run)(run);\n\t\t\t}\n\t\t};\n\n\t\treturn function() {\n\t\t\ttimestamp = Date.now();\n\n\t\t\tif (!timeout) {\n\t\t\t\ttimeout = setTimeout(later, wait);\n\t\t\t}\n\t\t};\n\t};\n\n\tvar loader = (function(){\n\t\tvar preloadElems, isCompleted, resetPreloadingTimer, loadMode, started;\n\n\t\tvar eLvW, elvH, eLtop, eLleft, eLright, eLbottom, isBodyHidden;\n\n\t\tvar regImg = /^img$/i;\n\t\tvar regIframe = /^iframe$/i;\n\n\t\tvar supportScroll = ('onscroll' in window) && !(/(gle|ing)bot/.test(navigator.userAgent));\n\n\t\tvar shrinkExpand = 0;\n\t\tvar currentExpand = 0;\n\n\t\tvar isLoading = 0;\n\t\tvar lowRuns = -1;\n\n\t\tvar resetPreloading = function(e){\n\t\t\tisLoading--;\n\t\t\tif(!e || isLoading < 0 || !e.target){\n\t\t\t\tisLoading = 0;\n\t\t\t}\n\t\t};\n\n\t\tvar isVisible = function (elem) {\n\t\t\tif (isBodyHidden == null) {\n\t\t\t\tisBodyHidden = getCSS(document.body, 'visibility') == 'hidden';\n\t\t\t}\n\n\t\t\treturn isBodyHidden || !(getCSS(elem.parentNode, 'visibility') == 'hidden' && getCSS(elem, 'visibility') == 'hidden');\n\t\t};\n\n\t\tvar isNestedVisible = function(elem, elemExpand){\n\t\t\tvar outerRect;\n\t\t\tvar parent = elem;\n\t\t\tvar visible = isVisible(elem);\n\n\t\t\teLtop -= elemExpand;\n\t\t\teLbottom += elemExpand;\n\t\t\teLleft -= elemExpand;\n\t\t\teLright += elemExpand;\n\n\t\t\twhile(visible && (parent = parent.offsetParent) && parent != document.body && parent != docElem){\n\t\t\t\tvisible = ((getCSS(parent, 'opacity') || 1) > 0);\n\n\t\t\t\tif(visible && getCSS(parent, 'overflow') != 'visible'){\n\t\t\t\t\touterRect = parent.getBoundingClientRect();\n\t\t\t\t\tvisible = eLright > outerRect.left &&\n\t\t\t\t\t\teLleft < outerRect.right &&\n\t\t\t\t\t\teLbottom > outerRect.top - 1 &&\n\t\t\t\t\t\teLtop < outerRect.bottom + 1\n\t\t\t\t\t;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn visible;\n\t\t};\n\n\t\tvar checkElements = function() {\n\t\t\tvar eLlen, i, rect, autoLoadElem, loadedSomething, elemExpand, elemNegativeExpand, elemExpandVal,\n\t\t\t\tbeforeExpandVal, defaultExpand, preloadExpand, hFac;\n\t\t\tvar lazyloadElems = lazysizes.elements;\n\n\t\t\tif((loadMode = lazySizesCfg.loadMode) && isLoading < 8 && (eLlen = lazyloadElems.length)){\n\n\t\t\t\ti = 0;\n\n\t\t\t\tlowRuns++;\n\n\t\t\t\tfor(; i < eLlen; i++){\n\n\t\t\t\t\tif(!lazyloadElems[i] || lazyloadElems[i]._lazyRace){continue;}\n\n\t\t\t\t\tif(!supportScroll || (lazysizes.prematureUnveil && lazysizes.prematureUnveil(lazyloadElems[i]))){unveilElement(lazyloadElems[i]);continue;}\n\n\t\t\t\t\tif(!(elemExpandVal = lazyloadElems[i][_getAttribute]('data-expand')) || !(elemExpand = elemExpandVal * 1)){\n\t\t\t\t\t\telemExpand = currentExpand;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!defaultExpand) {\n\t\t\t\t\t\tdefaultExpand = (!lazySizesCfg.expand || lazySizesCfg.expand < 1) ?\n\t\t\t\t\t\t\tdocElem.clientHeight > 500 && docElem.clientWidth > 500 ? 500 : 370 :\n\t\t\t\t\t\t\tlazySizesCfg.expand;\n\n\t\t\t\t\t\tlazysizes._defEx = defaultExpand;\n\n\t\t\t\t\t\tpreloadExpand = defaultExpand * lazySizesCfg.expFactor;\n\t\t\t\t\t\thFac = lazySizesCfg.hFac;\n\t\t\t\t\t\tisBodyHidden = null;\n\n\t\t\t\t\t\tif(currentExpand < preloadExpand && isLoading < 1 && lowRuns > 2 && loadMode > 2 && !document.hidden){\n\t\t\t\t\t\t\tcurrentExpand = preloadExpand;\n\t\t\t\t\t\t\tlowRuns = 0;\n\t\t\t\t\t\t} else if(loadMode > 1 && lowRuns > 1 && isLoading < 6){\n\t\t\t\t\t\t\tcurrentExpand = defaultExpand;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcurrentExpand = shrinkExpand;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(beforeExpandVal !== elemExpand){\n\t\t\t\t\t\teLvW = innerWidth + (elemExpand * hFac);\n\t\t\t\t\t\telvH = innerHeight + elemExpand;\n\t\t\t\t\t\telemNegativeExpand = elemExpand * -1;\n\t\t\t\t\t\tbeforeExpandVal = elemExpand;\n\t\t\t\t\t}\n\n\t\t\t\t\trect = lazyloadElems[i].getBoundingClientRect();\n\n\t\t\t\t\tif ((eLbottom = rect.bottom) >= elemNegativeExpand &&\n\t\t\t\t\t\t(eLtop = rect.top) <= elvH &&\n\t\t\t\t\t\t(eLright = rect.right) >= elemNegativeExpand * hFac &&\n\t\t\t\t\t\t(eLleft = rect.left) <= eLvW &&\n\t\t\t\t\t\t(eLbottom || eLright || eLleft || eLtop) &&\n\t\t\t\t\t\t(lazySizesCfg.loadHidden || isVisible(lazyloadElems[i])) &&\n\t\t\t\t\t\t((isCompleted && isLoading < 3 && !elemExpandVal && (loadMode < 3 || lowRuns < 4)) || isNestedVisible(lazyloadElems[i], elemExpand))){\n\t\t\t\t\t\tunveilElement(lazyloadElems[i]);\n\t\t\t\t\t\tloadedSomething = true;\n\t\t\t\t\t\tif(isLoading > 9){break;}\n\t\t\t\t\t} else if(!loadedSomething && isCompleted && !autoLoadElem &&\n\t\t\t\t\t\tisLoading < 4 && lowRuns < 4 && loadMode > 2 &&\n\t\t\t\t\t\t(preloadElems[0] || lazySizesCfg.preloadAfterLoad) &&\n\t\t\t\t\t\t(preloadElems[0] || (!elemExpandVal && ((eLbottom || eLright || eLleft || eLtop) || lazyloadElems[i][_getAttribute](lazySizesCfg.sizesAttr) != 'auto')))){\n\t\t\t\t\t\tautoLoadElem = preloadElems[0] || lazyloadElems[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(autoLoadElem && !loadedSomething){\n\t\t\t\t\tunveilElement(autoLoadElem);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvar throttledCheckElements = throttle(checkElements);\n\n\t\tvar switchLoadingClass = function(e){\n\t\t\tvar elem = e.target;\n\n\t\t\tif (elem._lazyCache) {\n\t\t\t\tdelete elem._lazyCache;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tresetPreloading(e);\n\t\t\taddClass(elem, lazySizesCfg.loadedClass);\n\t\t\tremoveClass(elem, lazySizesCfg.loadingClass);\n\t\t\taddRemoveLoadEvents(elem, rafSwitchLoadingClass);\n\t\t\ttriggerEvent(elem, 'lazyloaded');\n\t\t};\n\t\tvar rafedSwitchLoadingClass = rAFIt(switchLoadingClass);\n\t\tvar rafSwitchLoadingClass = function(e){\n\t\t\trafedSwitchLoadingClass({target: e.target});\n\t\t};\n\n\t\tvar changeIframeSrc = function(elem, src){\n\t\t\tvar loadMode = elem.getAttribute('data-load-mode') || lazySizesCfg.iframeLoadMode;\n\n\t\t\t// loadMode can be also a string!\n\t\t\tif (loadMode == 0) {\n\t\t\t\telem.contentWindow.location.replace(src);\n\t\t\t} else if (loadMode == 1) {\n\t\t\t\telem.src = src;\n\t\t\t}\n\t\t};\n\n\t\tvar handleSources = function(source){\n\t\t\tvar customMedia;\n\n\t\t\tvar sourceSrcset = source[_getAttribute](lazySizesCfg.srcsetAttr);\n\n\t\t\tif( (customMedia = lazySizesCfg.customMedia[source[_getAttribute]('data-media') || source[_getAttribute]('media')]) ){\n\t\t\t\tsource.setAttribute('media', customMedia);\n\t\t\t}\n\n\t\t\tif(sourceSrcset){\n\t\t\t\tsource.setAttribute('srcset', sourceSrcset);\n\t\t\t}\n\t\t};\n\n\t\tvar lazyUnveil = rAFIt(function (elem, detail, isAuto, sizes, isImg){\n\t\t\tvar src, srcset, parent, isPicture, event, firesLoad;\n\n\t\t\tif(!(event = triggerEvent(elem, 'lazybeforeunveil', detail)).defaultPrevented){\n\n\t\t\t\tif(sizes){\n\t\t\t\t\tif(isAuto){\n\t\t\t\t\t\taddClass(elem, lazySizesCfg.autosizesClass);\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.setAttribute('sizes', sizes);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsrcset = elem[_getAttribute](lazySizesCfg.srcsetAttr);\n\t\t\t\tsrc = elem[_getAttribute](lazySizesCfg.srcAttr);\n\n\t\t\t\tif(isImg) {\n\t\t\t\t\tparent = elem.parentNode;\n\t\t\t\t\tisPicture = parent && regPicture.test(parent.nodeName || '');\n\t\t\t\t}\n\n\t\t\t\tfiresLoad = detail.firesLoad || (('src' in elem) && (srcset || src || isPicture));\n\n\t\t\t\tevent = {target: elem};\n\n\t\t\t\taddClass(elem, lazySizesCfg.loadingClass);\n\n\t\t\t\tif(firesLoad){\n\t\t\t\t\tclearTimeout(resetPreloadingTimer);\n\t\t\t\t\tresetPreloadingTimer = setTimeout(resetPreloading, 2500);\n\t\t\t\t\taddRemoveLoadEvents(elem, rafSwitchLoadingClass, true);\n\t\t\t\t}\n\n\t\t\t\tif(isPicture){\n\t\t\t\t\tforEach.call(parent.getElementsByTagName('source'), handleSources);\n\t\t\t\t}\n\n\t\t\t\tif(srcset){\n\t\t\t\t\telem.setAttribute('srcset', srcset);\n\t\t\t\t} else if(src && !isPicture){\n\t\t\t\t\tif(regIframe.test(elem.nodeName)){\n\t\t\t\t\t\tchangeIframeSrc(elem, src);\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.src = src;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(isImg && (srcset || isPicture)){\n\t\t\t\t\tupdatePolyfill(elem, {src: src});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(elem._lazyRace){\n\t\t\t\tdelete elem._lazyRace;\n\t\t\t}\n\t\t\tremoveClass(elem, lazySizesCfg.lazyClass);\n\n\t\t\trAF(function(){\n\t\t\t\t// Part of this can be removed as soon as this fix is older: https://bugs.chromium.org/p/chromium/issues/detail?id=7731 (2015)\n\t\t\t\tvar isLoaded = elem.complete && elem.naturalWidth > 1;\n\n\t\t\t\tif( !firesLoad || isLoaded){\n\t\t\t\t\tif (isLoaded) {\n\t\t\t\t\t\taddClass(elem, lazySizesCfg.fastLoadedClass);\n\t\t\t\t\t}\n\t\t\t\t\tswitchLoadingClass(event);\n\t\t\t\t\telem._lazyCache = true;\n\t\t\t\t\tsetTimeout(function(){\n\t\t\t\t\t\tif ('_lazyCache' in elem) {\n\t\t\t\t\t\t\tdelete elem._lazyCache;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 9);\n\t\t\t\t}\n\t\t\t\tif (elem.loading == 'lazy') {\n\t\t\t\t\tisLoading--;\n\t\t\t\t}\n\t\t\t}, true);\n\t\t});\n\n\t\t/**\n\t\t *\n\t\t * @param elem { Element }\n\t\t */\n\t\tvar unveilElement = function (elem){\n\t\t\tif (elem._lazyRace) {return;}\n\t\t\tvar detail;\n\n\t\t\tvar isImg = regImg.test(elem.nodeName);\n\n\t\t\t//allow using sizes=\"auto\", but don't use. it's invalid. Use data-sizes=\"auto\" or a valid value for sizes instead (i.e.: sizes=\"80vw\")\n\t\t\tvar sizes = isImg && (elem[_getAttribute](lazySizesCfg.sizesAttr) || elem[_getAttribute]('sizes'));\n\t\t\tvar isAuto = sizes == 'auto';\n\n\t\t\tif( (isAuto || !isCompleted) && isImg && (elem[_getAttribute]('src') || elem.srcset) && !elem.complete && !hasClass(elem, lazySizesCfg.errorClass) && hasClass(elem, lazySizesCfg.lazyClass)){return;}\n\n\t\t\tdetail = triggerEvent(elem, 'lazyunveilread').detail;\n\n\t\t\tif(isAuto){\n\t\t\t\t autoSizer.updateElem(elem, true, elem.offsetWidth);\n\t\t\t}\n\n\t\t\telem._lazyRace = true;\n\t\t\tisLoading++;\n\n\t\t\tlazyUnveil(elem, detail, isAuto, sizes, isImg);\n\t\t};\n\n\t\tvar afterScroll = debounce(function(){\n\t\t\tlazySizesCfg.loadMode = 3;\n\t\t\tthrottledCheckElements();\n\t\t});\n\n\t\tvar altLoadmodeScrollListner = function(){\n\t\t\tif(lazySizesCfg.loadMode == 3){\n\t\t\t\tlazySizesCfg.loadMode = 2;\n\t\t\t}\n\t\t\tafterScroll();\n\t\t};\n\n\t\tvar onload = function(){\n\t\t\tif(isCompleted){return;}\n\t\t\tif(Date.now() - started < 999){\n\t\t\t\tsetTimeout(onload, 999);\n\t\t\t\treturn;\n\t\t\t}\n\n\n\t\t\tisCompleted = true;\n\n\t\t\tlazySizesCfg.loadMode = 3;\n\n\t\t\tthrottledCheckElements();\n\n\t\t\taddEventListener('scroll', altLoadmodeScrollListner, true);\n\t\t};\n\n\t\treturn {\n\t\t\t_: function(){\n\t\t\t\tstarted = Date.now();\n\n\t\t\t\tlazysizes.elements = document.getElementsByClassName(lazySizesCfg.lazyClass);\n\t\t\t\tpreloadElems = document.getElementsByClassName(lazySizesCfg.lazyClass + ' ' + lazySizesCfg.preloadClass);\n\n\t\t\t\taddEventListener('scroll', throttledCheckElements, true);\n\n\t\t\t\taddEventListener('resize', throttledCheckElements, true);\n\n\t\t\t\taddEventListener('pageshow', function (e) {\n\t\t\t\t\tif (e.persisted) {\n\t\t\t\t\t\tvar loadingElements = document.querySelectorAll('.' + lazySizesCfg.loadingClass);\n\n\t\t\t\t\t\tif (loadingElements.length && loadingElements.forEach) {\n\t\t\t\t\t\t\trequestAnimationFrame(function () {\n\t\t\t\t\t\t\t\tloadingElements.forEach( function (img) {\n\t\t\t\t\t\t\t\t\tif (img.complete) {\n\t\t\t\t\t\t\t\t\t\tunveilElement(img);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif(window.MutationObserver){\n\t\t\t\t\tnew MutationObserver( throttledCheckElements ).observe( docElem, {childList: true, subtree: true, attributes: true} );\n\t\t\t\t} else {\n\t\t\t\t\tdocElem[_addEventListener]('DOMNodeInserted', throttledCheckElements, true);\n\t\t\t\t\tdocElem[_addEventListener]('DOMAttrModified', throttledCheckElements, true);\n\t\t\t\t\tsetInterval(throttledCheckElements, 999);\n\t\t\t\t}\n\n\t\t\t\taddEventListener('hashchange', throttledCheckElements, true);\n\n\t\t\t\t//, 'fullscreenchange'\n\t\t\t\t['focus', 'mouseover', 'click', 'load', 'transitionend', 'animationend'].forEach(function(name){\n\t\t\t\t\tdocument[_addEventListener](name, throttledCheckElements, true);\n\t\t\t\t});\n\n\t\t\t\tif((/d$|^c/.test(document.readyState))){\n\t\t\t\t\tonload();\n\t\t\t\t} else {\n\t\t\t\t\taddEventListener('load', onload);\n\t\t\t\t\tdocument[_addEventListener]('DOMContentLoaded', throttledCheckElements);\n\t\t\t\t\tsetTimeout(onload, 20000);\n\t\t\t\t}\n\n\t\t\t\tif(lazysizes.elements.length){\n\t\t\t\t\tcheckElements();\n\t\t\t\t\trAF._lsFlush();\n\t\t\t\t} else {\n\t\t\t\t\tthrottledCheckElements();\n\t\t\t\t}\n\t\t\t},\n\t\t\tcheckElems: throttledCheckElements,\n\t\t\tunveil: unveilElement,\n\t\t\t_aLSL: altLoadmodeScrollListner,\n\t\t};\n\t})();\n\n\n\tvar autoSizer = (function(){\n\t\tvar autosizesElems;\n\n\t\tvar sizeElement = rAFIt(function(elem, parent, event, width){\n\t\t\tvar sources, i, len;\n\t\t\telem._lazysizesWidth = width;\n\t\t\twidth += 'px';\n\n\t\t\telem.setAttribute('sizes', width);\n\n\t\t\tif(regPicture.test(parent.nodeName || '')){\n\t\t\t\tsources = parent.getElementsByTagName('source');\n\t\t\t\tfor(i = 0, len = sources.length; i < len; i++){\n\t\t\t\t\tsources[i].setAttribute('sizes', width);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!event.detail.dataAttr){\n\t\t\t\tupdatePolyfill(elem, event.detail);\n\t\t\t}\n\t\t});\n\t\t/**\n\t\t *\n\t\t * @param elem {Element}\n\t\t * @param dataAttr\n\t\t * @param [width] { number }\n\t\t */\n\t\tvar getSizeElement = function (elem, dataAttr, width){\n\t\t\tvar event;\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif(parent){\n\t\t\t\twidth = getWidth(elem, parent, width);\n\t\t\t\tevent = triggerEvent(elem, 'lazybeforesizes', {width: width, dataAttr: !!dataAttr});\n\n\t\t\t\tif(!event.defaultPrevented){\n\t\t\t\t\twidth = event.detail.width;\n\n\t\t\t\t\tif(width && width !== elem._lazysizesWidth){\n\t\t\t\t\t\tsizeElement(elem, parent, event, width);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvar updateElementsSizes = function(){\n\t\t\tvar i;\n\t\t\tvar len = autosizesElems.length;\n\t\t\tif(len){\n\t\t\t\ti = 0;\n\n\t\t\t\tfor(; i < len; i++){\n\t\t\t\t\tgetSizeElement(autosizesElems[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvar debouncedUpdateElementsSizes = debounce(updateElementsSizes);\n\n\t\treturn {\n\t\t\t_: function(){\n\t\t\t\tautosizesElems = document.getElementsByClassName(lazySizesCfg.autosizesClass);\n\t\t\t\taddEventListener('resize', debouncedUpdateElementsSizes);\n\t\t\t},\n\t\t\tcheckElems: debouncedUpdateElementsSizes,\n\t\t\tupdateElem: getSizeElement\n\t\t};\n\t})();\n\n\tvar init = function(){\n\t\tif(!init.i && document.getElementsByClassName){\n\t\t\tinit.i = true;\n\t\t\tautoSizer._();\n\t\t\tloader._();\n\t\t}\n\t};\n\n\tsetTimeout(function(){\n\t\tif(lazySizesCfg.init){\n\t\t\tinit();\n\t\t}\n\t});\n\n\tlazysizes = {\n\t\t/**\n\t\t * @type { LazySizesConfigPartial }\n\t\t */\n\t\tcfg: lazySizesCfg,\n\t\tautoSizer: autoSizer,\n\t\tloader: loader,\n\t\tinit: init,\n\t\tuP: updatePolyfill,\n\t\taC: addClass,\n\t\trC: removeClass,\n\t\thC: hasClass,\n\t\tfire: triggerEvent,\n\t\tgW: getWidth,\n\t\trAF: rAF,\n\t};\n\n\treturn lazysizes;\n}\n));\n", "(function(window, factory) {\n\tif(!window) {return;}\n\tvar globalInstall = function(){\n\t\tfactory(window.lazySizes);\n\t\twindow.removeEventListener('lazyunveilread', globalInstall, true);\n\t};\n\n\tfactory = factory.bind(null, window, window.document);\n\n\tif(typeof module == 'object' && module.exports){\n\t\tfactory(require('lazysizes'));\n\t} else if (typeof define == 'function' && define.amd) {\n\t\tdefine(['lazysizes'], factory);\n\t} else if(window.lazySizes) {\n\t\tglobalInstall();\n\t} else {\n\t\twindow.addEventListener('lazyunveilread', globalInstall, true);\n\t}\n}(typeof window != 'undefined' ?\n\twindow : 0, function(window, document, lazySizes) {\n\t'use strict';\n\n\tif(!window.addEventListener){return;}\n\n\tvar regDescriptors = /\\s+(\\d+)(w|h)\\s+(\\d+)(w|h)/;\n\tvar regCssFit = /parent-fit[\"']*\\s*:\\s*[\"']*(contain|cover|width)/;\n\tvar regCssObject = /parent-container[\"']*\\s*:\\s*[\"']*(.+?)(?=(\\s|$|,|'|\"|;))/;\n\tvar regPicture = /^picture$/i;\n\tvar cfg = lazySizes.cfg;\n\n\tvar getCSS = function (elem){\n\t\treturn (getComputedStyle(elem, null) || {});\n\t};\n\n\tvar parentFit = {\n\n\t\tgetParent: function(element, parentSel){\n\t\t\tvar parent = element;\n\t\t\tvar parentNode = element.parentNode;\n\n\t\t\tif((!parentSel || parentSel == 'prev') && parentNode && regPicture.test(parentNode.nodeName || '')){\n\t\t\t\tparentNode = parentNode.parentNode;\n\t\t\t}\n\n\t\t\tif(parentSel != 'self'){\n\t\t\t\tif(parentSel == 'prev'){\n\t\t\t\t\tparent = element.previousElementSibling;\n\t\t\t\t} else if(parentSel && (parentNode.closest || window.jQuery)){\n\t\t\t\t\tparent = (parentNode.closest ?\n\t\t\t\t\t\t\tparentNode.closest(parentSel) :\n\t\t\t\t\t\t\tjQuery(parentNode).closest(parentSel)[0]) ||\n\t\t\t\t\t\tparentNode\n\t\t\t\t\t;\n\t\t\t\t} else {\n\t\t\t\t\tparent = parentNode;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn parent;\n\t\t},\n\n\t\tgetFit: function(element){\n\t\t\tvar tmpMatch, parentObj;\n\t\t\tvar css = getCSS(element);\n\t\t\tvar content = css.content || css.fontFamily;\n\t\t\tvar obj = {\n\t\t\t\tfit: element._lazysizesParentFit || element.getAttribute('data-parent-fit')\n\t\t\t};\n\n\t\t\tif(!obj.fit && content && (tmpMatch = content.match(regCssFit))){\n\t\t\t\tobj.fit = tmpMatch[1];\n\t\t\t}\n\n\t\t\tif(obj.fit){\n\t\t\t\tparentObj = element._lazysizesParentContainer || element.getAttribute('data-parent-container');\n\n\t\t\t\tif(!parentObj && content && (tmpMatch = content.match(regCssObject))){\n\t\t\t\t\tparentObj = tmpMatch[1];\n\t\t\t\t}\n\n\t\t\t\tobj.parent = parentFit.getParent(element, parentObj);\n\n\n\t\t\t} else {\n\t\t\t\tobj.fit = css.objectFit;\n\t\t\t}\n\n\t\t\treturn obj;\n\t\t},\n\n\t\tgetImageRatio: function(element){\n\t\t\tvar i, srcset, media, ratio, match, width, height;\n\t\t\tvar parent = element.parentNode;\n\t\t\tvar elements = parent && regPicture.test(parent.nodeName || '') ?\n\t\t\t\t\tparent.querySelectorAll('source, img') :\n\t\t\t\t\t[element]\n\t\t\t\t;\n\n\t\t\tfor(i = 0; i < elements.length; i++){\n\t\t\t\telement = elements[i];\n\t\t\t\tsrcset = element.getAttribute(cfg.srcsetAttr) || element.getAttribute('srcset') || element.getAttribute('data-pfsrcset') || element.getAttribute('data-risrcset') || '';\n\t\t\t\tmedia = element._lsMedia || element.getAttribute('media');\n\t\t\t\tmedia = cfg.customMedia[element.getAttribute('data-media') || media] || media;\n\n\t\t\t\tif(srcset && (!media || (window.matchMedia && matchMedia(media) || {}).matches )){\n\t\t\t\t\tratio = parseFloat(element.getAttribute('data-aspectratio'));\n\n\t\t\t\t\tif (!ratio) {\n\t\t\t\t\t\tmatch = srcset.match(regDescriptors);\n\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tif(match[2] == 'w'){\n\t\t\t\t\t\t\t\twidth = match[1];\n\t\t\t\t\t\t\t\theight = match[3];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twidth = match[3];\n\t\t\t\t\t\t\t\theight = match[1];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twidth = element.getAttribute('width');\n\t\t\t\t\t\t\theight = element.getAttribute('height');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tratio = width / height;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ratio;\n\t\t},\n\n\t\tcalculateSize: function(element, width){\n\t\t\tvar displayRatio, height, imageRatio, retWidth;\n\t\t\tvar fitObj = this.getFit(element);\n\t\t\tvar fit = fitObj.fit;\n\t\t\tvar fitElem = fitObj.parent;\n\n\t\t\tif(fit != 'width' && ((fit != 'contain' && fit != 'cover') || !(imageRatio = this.getImageRatio(element)))){\n\t\t\t\treturn width;\n\t\t\t}\n\n\t\t\tif(fitElem){\n\t\t\t\twidth = fitElem.clientWidth;\n\t\t\t} else {\n\t\t\t\tfitElem = element;\n\t\t\t}\n\n\t\t\tretWidth = width;\n\n\t\t\tif(fit == 'width'){\n\t\t\t\tretWidth = width;\n\t\t\t} else {\n\t\t\t\theight = fitElem.clientHeight;\n\n\t\t\t\tif((displayRatio = width / height) && ((fit == 'cover' && displayRatio < imageRatio) || (fit == 'contain' && displayRatio > imageRatio))){\n\t\t\t\t\tretWidth = width * (imageRatio / displayRatio);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn retWidth;\n\t\t}\n\t};\n\n\tlazySizes.parentFit = parentFit;\n\n\tdocument.addEventListener('lazybeforesizes', function(e){\n\t\tif(e.defaultPrevented || e.detail.instance != lazySizes){return;}\n\n\t\tvar element = e.target;\n\t\te.detail.width = parentFit.calculateSize(element, e.detail.width);\n\t});\n}));\n", "(function(window, factory) {\n\tvar globalInstall = function(){\n\t\tfactory(window.lazySizes);\n\t\twindow.removeEventListener('lazyunveilread', globalInstall, true);\n\t};\n\n\tfactory = factory.bind(null, window, window.document);\n\n\tif(typeof module == 'object' && module.exports){\n\t\tfactory(require('lazysizes'));\n\t} else if (typeof define == 'function' && define.amd) {\n\t\tdefine(['lazysizes'], factory);\n\t} else if(window.lazySizes) {\n\t\tglobalInstall();\n\t} else {\n\t\twindow.addEventListener('lazyunveilread', globalInstall, true);\n\t}\n}(window, function(window, document, lazySizes) {\n\t'use strict';\n\n\tif(!window.addEventListener){return;}\n\n\tvar forEach = Array.prototype.forEach;\n\n\tvar imageRatio, extend$, $;\n\n\tvar regPicture = /^picture$/i;\n\tvar aspectRatioAttr = 'data-aspectratio';\n\tvar aspectRatioSel = 'img[' + aspectRatioAttr + ']';\n\n\tvar matchesMedia = function(media){\n\t\tif(window.matchMedia){\n\t\t\tmatchesMedia = function(media){\n\t\t\t\treturn !media || (matchMedia(media) || {}).matches;\n\t\t\t};\n\t\t} else if(window.Modernizr && Modernizr.mq){\n\t\t\treturn !media || Modernizr.mq(media);\n\t\t} else {\n\t\t\treturn !media;\n\t\t}\n\t\treturn matchesMedia(media);\n\t};\n\n\tvar addClass = lazySizes.aC;\n\tvar removeClass = lazySizes.rC;\n\tvar lazySizesConfig = lazySizes.cfg;\n\n\tfunction AspectRatio(){\n\t\tthis.ratioElems = document.getElementsByClassName('lazyaspectratio');\n\t\tthis._setupEvents();\n\t\tthis.processImages();\n\t}\n\n\tAspectRatio.prototype = {\n\t\t_setupEvents: function(){\n\t\t\tvar module = this;\n\n\t\t\tvar addRemoveAspectRatio = function(elem){\n\t\t\t\tif(elem.naturalWidth < 36){\n\t\t\t\t\tmodule.addAspectRatio(elem, true);\n\t\t\t\t} else {\n\t\t\t\t\tmodule.removeAspectRatio(elem, true);\n\t\t\t\t}\n\t\t\t};\n\t\t\tvar onload = function(){\n\t\t\t\tmodule.processImages();\n\t\t\t};\n\n\t\t\tdocument.addEventListener('load', function(e){\n\t\t\t\tif(e.target.getAttribute && e.target.getAttribute(aspectRatioAttr)){\n\t\t\t\t\taddRemoveAspectRatio(e.target);\n\t\t\t\t}\n\t\t\t}, true);\n\n\t\t\taddEventListener('resize', (function(){\n\t\t\t\tvar timer;\n\t\t\t\tvar resize = function(){\n\t\t\t\t\tforEach.call(module.ratioElems, addRemoveAspectRatio);\n\t\t\t\t};\n\n\t\t\t\treturn function(){\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\ttimer = setTimeout(resize, 99);\n\t\t\t\t};\n\t\t\t})());\n\n\t\t\tdocument.addEventListener('DOMContentLoaded', onload);\n\n\t\t\taddEventListener('load', onload);\n\t\t},\n\t\tprocessImages: function(context){\n\t\t\tvar elements, i;\n\n\t\t\tif(!context){\n\t\t\t\tcontext = document;\n\t\t\t}\n\n\t\t\tif('length' in context && !context.nodeName){\n\t\t\t\telements = context;\n\t\t\t} else {\n\t\t\t\telements = context.querySelectorAll(aspectRatioSel);\n\t\t\t}\n\n\t\t\tfor(i = 0; i < elements.length; i++){\n\t\t\t\tif(elements[i].naturalWidth > 36){\n\t\t\t\t\tthis.removeAspectRatio(elements[i]);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.addAspectRatio(elements[i]);\n\t\t\t}\n\t\t},\n\t\tgetSelectedRatio: function(img){\n\t\t\tvar i, len, sources, customMedia, ratio;\n\t\t\tvar parent = img.parentNode;\n\t\t\tif(parent && regPicture.test(parent.nodeName || '')){\n\t\t\t\tsources = parent.getElementsByTagName('source');\n\n\t\t\t\tfor(i = 0, len = sources.length; i < len; i++){\n\t\t\t\t\tcustomMedia = sources[i].getAttribute('data-media') || sources[i].getAttribute('media');\n\n\t\t\t\t\tif(lazySizesConfig.customMedia[customMedia]){\n\t\t\t\t\t\tcustomMedia = lazySizesConfig.customMedia[customMedia];\n\t\t\t\t\t}\n\n\t\t\t\t\tif(matchesMedia(customMedia)){\n\t\t\t\t\t\tratio = sources[i].getAttribute(aspectRatioAttr);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ratio || img.getAttribute(aspectRatioAttr) || '';\n\t\t},\n\t\tparseRatio: (function(){\n\t\t\tvar regRatio = /^\\s*([+\\d\\.]+)(\\s*[\\/x]\\s*([+\\d\\.]+))?\\s*$/;\n\t\t\tvar ratioCache = {};\n\t\t\treturn function(ratio){\n\t\t\t\tvar match;\n\n\t\t\t\tif(!ratioCache[ratio] && (match = ratio.match(regRatio))){\n\t\t\t\t\tif(match[3]){\n\t\t\t\t\t\tratioCache[ratio] = match[1] / match[3];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tratioCache[ratio] = match[1] * 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ratioCache[ratio];\n\t\t\t};\n\t\t})(),\n\t\taddAspectRatio: function(img, notNew){\n\t\t\tvar ratio;\n\t\t\tvar width = img.offsetWidth;\n\t\t\tvar height = img.offsetHeight;\n\n\t\t\tif(!notNew){\n\t\t\t\taddClass(img, 'lazyaspectratio');\n\t\t\t}\n\n\t\t\tif(width < 36 && height <= 0){\n\t\t\t\tif(width || height && window.console){\n\t\t\t\t\tconsole.log('Define width or height of image, so we can calculate the other dimension');\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tratio = this.getSelectedRatio(img);\n\t\t\tratio = this.parseRatio(ratio);\n\n\t\t\tif(ratio){\n\t\t\t\tif(width){\n\t\t\t\t\timg.style.height = (width / ratio) + 'px';\n\t\t\t\t} else {\n\t\t\t\t\timg.style.width = (height * ratio) + 'px';\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tremoveAspectRatio: function(img){\n\t\t\tremoveClass(img, 'lazyaspectratio');\n\t\t\timg.style.height = '';\n\t\t\timg.style.width = '';\n\t\t\timg.removeAttribute(aspectRatioAttr);\n\t\t}\n\t};\n\n\textend$ = function(){\n\t\t$ = window.jQuery || window.Zepto || window.shoestring || window.$;\n\t\tif($ && $.fn && !$.fn.imageRatio && $.fn.filter && $.fn.add && $.fn.find){\n\t\t\t$.fn.imageRatio = function(){\n\t\t\t\timageRatio.processImages(this.find(aspectRatioSel).add(this.filter(aspectRatioSel)));\n\t\t\t\treturn this;\n\t\t\t};\n\t\t} else {\n\t\t\t$ = false;\n\t\t}\n\t};\n\n\textend$();\n\tsetTimeout(extend$);\n\n\timageRatio = new AspectRatio();\n\n\twindow.imageRatio = imageRatio;\n\n\tif(typeof module == 'object' && module.exports){\n\t\tmodule.exports = imageRatio;\n\t} else if (typeof define == 'function' && define.amd) {\n\t\tdefine(imageRatio);\n\t}\n\n}));\n", "(function(window, factory) {\n\tvar globalInstall = function(){\n\t\tfactory(window.lazySizes);\n\t\twindow.removeEventListener('lazyunveilread', globalInstall, true);\n\t};\n\n\tfactory = factory.bind(null, window, window.document);\n\n\tif(typeof module == 'object' && module.exports){\n\t\tfactory(require('lazysizes'));\n\t} else if (typeof define == 'function' && define.amd) {\n\t\tdefine(['lazysizes'], factory);\n\t} else if(window.lazySizes) {\n\t\tglobalInstall();\n\t} else {\n\t\twindow.addEventListener('lazyunveilread', globalInstall, true);\n\t}\n}(window, function(window, document, lazySizes) {\n\t'use strict';\n\n\tvar imgSupport = 'loading' in HTMLImageElement.prototype;\n\tvar iframeSupport = 'loading' in HTMLIFrameElement.prototype;\n\tvar isConfigSet = false;\n\tvar oldPrematureUnveil = lazySizes.prematureUnveil;\n\tvar cfg = lazySizes.cfg;\n\tvar listenerMap = {\n\t\tfocus: 1,\n\t\tmouseover: 1,\n\t\tclick: 1,\n\t\tload: 1,\n\t\ttransitionend: 1,\n\t\tanimationend: 1,\n\t\tscroll: 1,\n\t\tresize: 1,\n\t};\n\n\tif (!cfg.nativeLoading) {\n\t\tcfg.nativeLoading = {};\n\t}\n\n\tif (!window.addEventListener || !window.MutationObserver || (!imgSupport && !iframeSupport)) {\n\t\treturn;\n\t}\n\n\tfunction disableEvents() {\n\t\tvar loader = lazySizes.loader;\n\t\tvar throttledCheckElements = loader.checkElems;\n\t\tvar removeALSL = function(){\n\t\t\tsetTimeout(function(){\n\t\t\t\twindow.removeEventListener('scroll', loader._aLSL, true);\n\t\t\t}, 1000);\n\t\t};\n\t\tvar currentListenerMap = typeof cfg.nativeLoading.disableListeners == 'object' ?\n\t\t\tcfg.nativeLoading.disableListeners :\n\t\t\tlistenerMap;\n\n\t\tif (currentListenerMap.scroll) {\n\t\t\twindow.addEventListener('load', removeALSL);\n\t\t\tremoveALSL();\n\n\t\t\twindow.removeEventListener('scroll', throttledCheckElements, true);\n\t\t}\n\n\t\tif (currentListenerMap.resize) {\n\t\t\twindow.removeEventListener('resize', throttledCheckElements, true);\n\t\t}\n\n\t\tObject.keys(currentListenerMap).forEach(function(name) {\n\t\t\tif (currentListenerMap[name]) {\n\t\t\t\tdocument.removeEventListener(name, throttledCheckElements, true);\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction runConfig() {\n\t\tif (isConfigSet) {return;}\n\t\tisConfigSet = true;\n\n\t\tif (imgSupport && iframeSupport && cfg.nativeLoading.disableListeners) {\n\t\t\tif (cfg.nativeLoading.disableListeners === true) {\n\t\t\t\tcfg.nativeLoading.setLoadingAttribute = true;\n\t\t\t}\n\n\t\t\tdisableEvents();\n\t\t}\n\n\t\tif (cfg.nativeLoading.setLoadingAttribute) {\n\t\t\twindow.addEventListener('lazybeforeunveil', function(e){\n\t\t\t\tvar element = e.target;\n\n\t\t\t\tif ('loading' in element && !element.getAttribute('loading')) {\n\t\t\t\t\telement.setAttribute('loading', 'lazy');\n\t\t\t\t}\n\t\t\t}, true);\n\t\t}\n\t}\n\n\tlazySizes.prematureUnveil = function prematureUnveil(element) {\n\n\t\tif (!isConfigSet) {\n\t\t\trunConfig();\n\t\t}\n\n\t\tif ('loading' in element &&\n\t\t\t(cfg.nativeLoading.setLoadingAttribute || element.getAttribute('loading')) &&\n\t\t\t(element.getAttribute('data-sizes') != 'auto' || element.offsetWidth)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (oldPrematureUnveil) {\n\t\t\treturn oldPrematureUnveil(element);\n\t\t}\n\t};\n\n}));\n", "// packages/alpinejs/src/scheduler.js\nvar flushPending = false;\nvar flushing = false;\nvar queue = [];\nvar lastFlushedIndex = -1;\nfunction scheduler(callback) {\n queueJob(callback);\n}\nfunction queueJob(job) {\n if (!queue.includes(job))\n queue.push(job);\n queueFlush();\n}\nfunction dequeueJob(job) {\n let index = queue.indexOf(job);\n if (index !== -1 && index > lastFlushedIndex)\n queue.splice(index, 1);\n}\nfunction queueFlush() {\n if (!flushing && !flushPending) {\n flushPending = true;\n queueMicrotask(flushJobs);\n }\n}\nfunction flushJobs() {\n flushPending = false;\n flushing = true;\n for (let i = 0; i < queue.length; i++) {\n queue[i]();\n lastFlushedIndex = i;\n }\n queue.length = 0;\n lastFlushedIndex = -1;\n flushing = false;\n}\n\n// packages/alpinejs/src/reactivity.js\nvar reactive;\nvar effect;\nvar release;\nvar raw;\nvar shouldSchedule = true;\nfunction disableEffectScheduling(callback) {\n shouldSchedule = false;\n callback();\n shouldSchedule = true;\n}\nfunction setReactivityEngine(engine) {\n reactive = engine.reactive;\n release = engine.release;\n effect = (callback) => engine.effect(callback, { scheduler: (task) => {\n if (shouldSchedule) {\n scheduler(task);\n } else {\n task();\n }\n } });\n raw = engine.raw;\n}\nfunction overrideEffect(override) {\n effect = override;\n}\nfunction elementBoundEffect(el) {\n let cleanup2 = () => {\n };\n let wrappedEffect = (callback) => {\n let effectReference = effect(callback);\n if (!el._x_effects) {\n el._x_effects = /* @__PURE__ */ new Set();\n el._x_runEffects = () => {\n el._x_effects.forEach((i) => i());\n };\n }\n el._x_effects.add(effectReference);\n cleanup2 = () => {\n if (effectReference === void 0)\n return;\n el._x_effects.delete(effectReference);\n release(effectReference);\n };\n return effectReference;\n };\n return [wrappedEffect, () => {\n cleanup2();\n }];\n}\n\n// packages/alpinejs/src/utils/dispatch.js\nfunction dispatch(el, name, detail = {}) {\n el.dispatchEvent(\n new CustomEvent(name, {\n detail,\n bubbles: true,\n // Allows events to pass the shadow DOM barrier.\n composed: true,\n cancelable: true\n })\n );\n}\n\n// packages/alpinejs/src/utils/walk.js\nfunction walk(el, callback) {\n if (typeof ShadowRoot === \"function\" && el instanceof ShadowRoot) {\n Array.from(el.children).forEach((el2) => walk(el2, callback));\n return;\n }\n let skip = false;\n callback(el, () => skip = true);\n if (skip)\n return;\n let node = el.firstElementChild;\n while (node) {\n walk(node, callback, false);\n node = node.nextElementSibling;\n }\n}\n\n// packages/alpinejs/src/utils/warn.js\nfunction warn(message, ...args) {\n console.warn(`Alpine Warning: ${message}`, ...args);\n}\n\n// packages/alpinejs/src/lifecycle.js\nvar started = false;\nfunction start() {\n if (started)\n warn(\"Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems.\");\n started = true;\n if (!document.body)\n warn(\"Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's `