/**! * mixitup v2.1.11 * * @copyright copyright 2015 kunkalabs limited. * @author kunkalabs limited. * @link https://mixitup.kunkalabs.com * * @license commercial use requires a commercial license. * https://mixitup.kunkalabs.com/licenses/ * * non-commercial use permitted under terms of cc-by-nc license. * http://creativecommons.org/licenses/by-nc/3.0/ */ (function($, undf){ 'use strict'; /** * mixitup constructor function * @constructor * @extends jquery */ $.mixitup = function(){ var self = this; self._execaction('_constructor', 0); $.extend(self, { /* public properties ---------------------------------------------------------------------- */ selectors: { target: '.mix', filter: '.filter', sort: '.sort' }, animation: { enable: true, effects: 'fade scale', duration: 600, easing: 'ease', perspectivedistance: '3000', perspectiveorigin: '50% 50%', queue: true, queuelimit: 1, animatechangelayout: false, animateresizecontainer: true, animateresizetargets: false, staggersequence: false, reverseout: false }, callbacks: { onmixload: false, onmixstart: false, onmixbusy: false, onmixend: false, onmixfail: false, _user: false }, controls: { enable: true, live: false, togglefilterbuttons: false, togglelogic: 'or', activeclass: 'active' }, layout: { display: 'inline-block', containerclass: '', containerclassfail: 'fail' }, load: { filter: 'all', sort: false }, /* private properties ---------------------------------------------------------------------- */ _$body: null, _$container: null, _$targets: null, _$parent: null, _$sortbuttons: null, _$filterbuttons: null, _suckmode: false, _mixing: false, _sorting: false, _clicking: false, _loading: true, _changinglayout: false, _changingclass: false, _changingdisplay: false, _origorder: [], _startorder: [], _neworder: [], _activefilter: null, _togglearray: [], _togglestring: '', _activesort: 'default:asc', _newsort: null, _startheight: null, _newheight: null, _incpadding: true, _newdisplay: null, _newclass: null, _targetsbound: 0, _targetsdone: 0, _queue: [], _$show: $(), _$hide: $() }); self._execaction('_constructor', 1); }; /** * mixitup prototype * @override */ $.mixitup.prototype = { constructor: $.mixitup, /* static properties ---------------------------------------------------------------------- */ _instances: {}, _handled: { _filter: {}, _sort: {} }, _bound: { _filter: {}, _sort: {} }, _actions: {}, _filters: {}, /* static methods ---------------------------------------------------------------------- */ /** * extend * @since 2.1.0 * @param {object} new properties/methods * @extends {object} prototype */ extend: function(extension){ for(var key in extension){ $.mixitup.prototype[key] = extension[key]; } }, /** * add action * @since 2.1.0 * @param {string} hook name * @param {string} namespace * @param {function} function to execute * @param {number} priority * @extends {object} $.mixitup.prototype._actions */ addaction: function(hook, name, func, priority){ $.mixitup.prototype._addhook('_actions', hook, name, func, priority); }, /** * add filter * @since 2.1.0 * @param {string} hook name * @param {string} namespace * @param {function} function to execute * @param {number} priority * @extends {object} $.mixitup.prototype._filters */ addfilter: function(hook, name, func, priority){ $.mixitup.prototype._addhook('_filters', hook, name, func, priority); }, /** * add hook * @since 2.1.0 * @param {string} type of hook * @param {string} hook name * @param {function} function to execute * @param {number} priority * @extends {object} $.mixitup.prototype._filters */ _addhook: function(type, hook, name, func, priority){ var collection = $.mixitup.prototype[type], obj = {}; priority = (priority === 1 || priority === 'post') ? 'post' : 'pre'; obj[hook] = {}; obj[hook][priority] = {}; obj[hook][priority][name] = func; $.extend(true, collection, obj); }, /* private methods ---------------------------------------------------------------------- */ /** * initialise * @since 2.0.0 * @param {object} domnode * @param {object} config */ _init: function(domnode, config){ var self = this; self._execaction('_init', 0, arguments); config && $.extend(true, self, config); self._$body = $('body'); self._domnode = domnode; self._$container = $(domnode); self._$container.addclass(self.layout.containerclass); self._id = domnode.id; self._platformdetect(); self._brake = self._getprefixedcss('transition', 'none'); self._refresh(true); self._$parent = self._$targets.parent().length ? self._$targets.parent() : self._$container; if(self.load.sort){ self._newsort = self._parsesort(self.load.sort); self._newsortstring = self.load.sort; self._activesort = self.load.sort; self._sort(); self._printsort(); } self._activefilter = self.load.filter === 'all' ? self.selectors.target : self.load.filter === 'none' ? '' : self.load.filter; self.controls.enable && self._bindhandlers(); if(self.controls.togglefilterbuttons){ self._buildtogglearray(); for(var i = 0; i < self._togglearray.length; i++){ self._updatecontrols({filter: self._togglearray[i], sort: self._activesort}, true); }; } else if(self.controls.enable){ self._updatecontrols({filter: self._activefilter, sort: self._activesort}); } self._filter(); self._init = true; self._$container.data('mixitup',self); self._execaction('_init', 1, arguments); self._buildstate(); self._$targets.css(self._brake); self._gomix(self.animation.enable); }, /** * platform detect * @since 2.0.0 */ _platformdetect: function(){ var self = this, vendorstrans = ['webkit', 'moz', 'o', 'ms'], vendorsraf = ['webkit', 'moz'], chrome = window.navigator.appversion.match(/chrome\/(\d+)\./) || false, ff = typeof installtrigger !== 'undefined', prefix = function(el){ for (var i = 0; i < vendorstrans.length; i++){ if (vendorstrans[i] + 'transition' in el.style){ return { prefix: '-'+vendorstrans[i].tolowercase()+'-', vendor: vendorstrans[i] }; }; }; return 'transition' in el.style ? '' : false; }, transprefix = prefix(self._domnode); self._execaction('_platformdetect', 0); self._chrome = chrome ? parseint(chrome[1], 10) : false; self._ff = ff ? parseint(window.navigator.useragent.match(/rv:([^)]+)\)/)[1]) : false; self._prefix = transprefix.prefix; self._vendor = transprefix.vendor; self._suckmode = window.atob && self._prefix ? false : true; self._suckmode && (self.animation.enable = false); (self._ff && self._ff <= 4) && (self.animation.enable = false); /* polyfills ---------------------------------------------------------------------- */ /** * window.requestanimationframe */ for(var x = 0; x < vendorsraf.length && !window.requestanimationframe; x++){ window.requestanimationframe = window[vendorsraf[x]+'requestanimationframe']; } /** * object.getprototypeof */ if(typeof object.getprototypeof !== 'function'){ if(typeof 'test'.__proto__ === 'object'){ object.getprototypeof = function(object){ return object.__proto__; }; } else { object.getprototypeof = function(object){ return object.constructor.prototype; }; } } /** * element.nextelementsibling */ if(self._domnode.nextelementsibling === undf){ object.defineproperty(element.prototype, 'nextelementsibling',{ get: function(){ var el = this.nextsibling; while(el){ if(el.nodetype ===1){ return el; } el = el.nextsibling; } return null; } }); } self._execaction('_platformdetect', 1); }, /** * refresh * @since 2.0.0 * @param {boolean} init * @param {boolean} force */ _refresh: function(init, force){ var self = this; self._execaction('_refresh', 0, arguments); self._$targets = self._$container.find(self.selectors.target); for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i]; if(target.dataset === undf || force){ target.dataset = {}; for(var j = 0; j < target.attributes.length; j++){ var attr = target.attributes[j], name = attr.name, val = attr.value; if(name.indexof('data-') > -1){ var dataname = self._helpers._camelcase(name.substring(5,name.length)); target.dataset[dataname] = val; } } } if(target.mixparent === undf){ target.mixparent = self._id; } } if( (self._$targets.length && init) || (!self._origorder.length && self._$targets.length) ){ self._origorder = []; for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i]; self._origorder.push(target); } } self._execaction('_refresh', 1, arguments); }, /** * bind handlers * @since 2.0.0 */ _bindhandlers: function(){ var self = this, filters = $.mixitup.prototype._bound._filter, sorts = $.mixitup.prototype._bound._sort; self._execaction('_bindhandlers', 0); if(self.controls.live){ self._$body .on('click.mixitup.'+self._id, self.selectors.sort, function(){ self._processclick($(this), 'sort'); }) .on('click.mixitup.'+self._id, self.selectors.filter, function(){ self._processclick($(this), 'filter'); }); } else { self._$sortbuttons = $(self.selectors.sort); self._$filterbuttons = $(self.selectors.filter); self._$sortbuttons.on('click.mixitup.'+self._id, function(){ self._processclick($(this), 'sort'); }); self._$filterbuttons.on('click.mixitup.'+self._id, function(){ self._processclick($(this), 'filter'); }); } filters[self.selectors.filter] = (filters[self.selectors.filter] === undf) ? 1 : filters[self.selectors.filter] + 1; sorts[self.selectors.sort] = (sorts[self.selectors.sort] === undf) ? 1 : sorts[self.selectors.sort] + 1; self._execaction('_bindhandlers', 1); }, /** * process click * @since 2.0.0 * @param {object} $button * @param {string} type */ _processclick: function($button, type){ var self = this, trackclick = function($button, type, off){ var proto = $.mixitup.prototype; proto._handled['_'+type][self.selectors[type]] = (proto._handled['_'+type][self.selectors[type]] === undf) ? 1 : proto._handled['_'+type][self.selectors[type]] + 1; if(proto._handled['_'+type][self.selectors[type]] === proto._bound['_'+type][self.selectors[type]]){ $button[(off ? 'remove' : 'add')+'class'](self.controls.activeclass); delete proto._handled['_'+type][self.selectors[type]]; } }; self._execaction('_processclick', 0, arguments); if(!self._mixing || (self.animation.queue && self._queue.length < self.animation.queuelimit)){ self._clicking = true; if(type === 'sort'){ var sort = $button.attr('data-sort'); if(!$button.hasclass(self.controls.activeclass) || sort.indexof('random') > -1){ $(self.selectors.sort).removeclass(self.controls.activeclass); trackclick($button, type); self.sort(sort); } } if(type === 'filter') { var filter = $button.attr('data-filter'), ndx, seperator = self.controls.togglelogic === 'or' ? ',' : ''; if(!self.controls.togglefilterbuttons){ if(!$button.hasclass(self.controls.activeclass)){ $(self.selectors.filter).removeclass(self.controls.activeclass); trackclick($button, type); self.filter(filter); } } else { self._buildtogglearray(); if(!$button.hasclass(self.controls.activeclass)){ trackclick($button, type); self._togglearray.push(filter); } else { trackclick($button, type, true); ndx = self._togglearray.indexof(filter); self._togglearray.splice(ndx, 1); } self._togglearray = $.grep(self._togglearray,function(n){return(n);}); self._togglestring = self._togglearray.join(seperator); self.filter(self._togglestring); } } self._execaction('_processclick', 1, arguments); } else { if(typeof self.callbacks.onmixbusy === 'function'){ self.callbacks.onmixbusy.call(self._domnode, self._state, self); } self._execaction('_processclickbusy', 1, arguments); } }, /** * build toggle array * @since 2.0.0 */ _buildtogglearray: function(){ var self = this, activefilter = self._activefilter.replace(/\s/g, ''); self._execaction('_buildtogglearray', 0, arguments); if(self.controls.togglelogic === 'or'){ self._togglearray = activefilter.split(','); } else { self._togglearray = activefilter.split('.'); !self._togglearray[0] && self._togglearray.shift(); for(var i = 0, filter; filter = self._togglearray[i]; i++){ self._togglearray[i] = '.'+filter; } } self._execaction('_buildtogglearray', 1, arguments); }, /** * update controls * @since 2.0.0 * @param {object} command * @param {boolean} multi */ _updatecontrols: function(command, multi){ var self = this, output = { filter: command.filter, sort: command.sort }, update = function($el, filter){ try { (multi && type === 'filter' && !(output.filter === 'none' || output.filter === '')) ? $el.filter(filter).addclass(self.controls.activeclass) : $el.removeclass(self.controls.activeclass).filter(filter).addclass(self.controls.activeclass); } catch(e) {} }, type = 'filter', $el = null; self._execaction('_updatecontrols', 0, arguments); (command.filter === undf) && (output.filter = self._activefilter); (command.sort === undf) && (output.sort = self._activesort); (output.filter === self.selectors.target) && (output.filter = 'all'); for(var i = 0; i < 2; i++){ $el = self.controls.live ? $(self.selectors[type]) : self['_$'+type+'buttons']; $el && update($el, '[data-'+type+'="'+output[type]+'"]'); type = 'sort'; } self._execaction('_updatecontrols', 1, arguments); }, /** * filter (private) * @since 2.0.0 */ _filter: function(){ var self = this; self._execaction('_filter', 0); for(var i = 0; i < self._$targets.length; i++){ var $target = $(self._$targets[i]); if($target.is(self._activefilter)){ self._$show = self._$show.add($target); } else { self._$hide = self._$hide.add($target); } } self._execaction('_filter', 1); }, /** * sort (private) * @since 2.0.0 */ _sort: function(){ var self = this, arrayshuffle = function(oldarray){ var newarray = oldarray.slice(), len = newarray.length, i = len; while(i--){ var p = parseint(math.random()*len); var t = newarray[i]; newarray[i] = newarray[p]; newarray[p] = t; }; return newarray; }; self._execaction('_sort', 0); self._startorder = []; for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i]; self._startorder.push(target); } switch(self._newsort[0].sortby){ case 'default': self._neworder = self._origorder; break; case 'random': self._neworder = arrayshuffle(self._startorder); break; case 'custom': self._neworder = self._newsort[0].order; break; default: self._neworder = self._startorder.concat().sort(function(a, b){ return self._compare(a, b); }); } self._execaction('_sort', 1); }, /** * compare algorithm * @since 2.0.0 * @param {string|number} a * @param {string|number} b * @param {number} depth (recursion) * @return {number} */ _compare: function(a, b, depth){ depth = depth ? depth : 0; var self = this, order = self._newsort[depth].order, getdata = function(el){ return el.dataset[self._newsort[depth].sortby] || 0; }, attra = isnan(getdata(a) * 1) ? getdata(a).tolowercase() : getdata(a) * 1, attrb = isnan(getdata(b) * 1) ? getdata(b).tolowercase() : getdata(b) * 1; if(attra < attrb) return order === 'asc' ? -1 : 1; if(attra > attrb) return order === 'asc' ? 1 : -1; if(attra === attrb && self._newsort.length > depth+1) return self._compare(a, b, depth+1); return 0; }, /** * print sort * @since 2.0.0 * @param {boolean} reset */ _printsort: function(reset){ var self = this, order = reset ? self._startorder : self._neworder, targets = self._$parent[0].queryselectorall(self.selectors.target), nextsibling = targets.length ? targets[targets.length -1].nextelementsibling : null, frag = document.createdocumentfragment(); self._execaction('_printsort', 0, arguments); for(var i = 0; i < targets.length; i++){ var target = targets[i], whitespace = target.nextsibling; if(target.style.position === 'absolute') continue; if(whitespace && whitespace.nodename === '#text'){ self._$parent[0].removechild(whitespace); } self._$parent[0].removechild(target); } for(var i = 0; i < order.length; i++){ var el = order[i]; if(self._newsort[0].sortby === 'default' && self._newsort[0].order === 'desc' && !reset){ var firstchild = frag.firstchild; frag.insertbefore(el, firstchild); frag.insertbefore(document.createtextnode(' '), el); } else { frag.appendchild(el); frag.appendchild(document.createtextnode(' ')); } } nextsibling ? self._$parent[0].insertbefore(frag, nextsibling) : self._$parent[0].appendchild(frag); self._execaction('_printsort', 1, arguments); }, /** * parse sort * @since 2.0.0 * @param {string} sortstring * @return {array} newsort */ _parsesort: function(sortstring){ var self = this, rules = typeof sortstring === 'string' ? sortstring.split(' ') : [sortstring], newsort = []; for(var i = 0; i < rules.length; i++){ var rule = typeof sortstring === 'string' ? rules[i].split(':') : ['custom', rules[i]], ruleobj = { sortby: self._helpers._camelcase(rule[0]), order: rule[1] || 'asc' }; newsort.push(ruleobj); if(ruleobj.sortby === 'default' || ruleobj.sortby === 'random') break; } return self._execfilter('_parsesort', newsort, arguments); }, /** * parse effects * @since 2.0.0 * @return {object} effects */ _parseeffects: function(){ var self = this, effects = { opacity: '', transformin: '', transformout: '', filter: '' }, parse = function(effect, extract, reverse){ if(self.animation.effects.indexof(effect) > -1){ if(extract){ var propindex = self.animation.effects.indexof(effect+'('); if(propindex > -1){ var str = self.animation.effects.substring(propindex), match = /\(([^)]+)\)/.exec(str), val = match[1]; return {val: val}; } } return true; } else { return false; } }, negate = function(value, invert){ if(invert){ return value.charat(0) === '-' ? value.substr(1, value.length) : '-'+value; } else { return value; } }, buildtransform = function(key, invert){ var transforms = [ ['scale', '.01'], ['translatex', '20px'], ['translatey', '20px'], ['translatez', '20px'], ['rotatex', '90deg'], ['rotatey', '90deg'], ['rotatez', '180deg'], ]; for(var i = 0; i < transforms.length; i++){ var prop = transforms[i][0], def = transforms[i][1], inverted = invert && prop !== 'scale'; effects[key] += parse(prop) ? prop+'('+negate(parse(prop, true).val || def, inverted)+') ' : ''; } }; effects.opacity = parse('fade') ? parse('fade',true).val || '0' : '1'; buildtransform('transformin'); self.animation.reverseout ? buildtransform('transformout', true) : (effects.transformout = effects.transformin); effects.transition = {}; effects.transition = self._getprefixedcss('transition','all '+self.animation.duration+'ms '+self.animation.easing+', opacity '+self.animation.duration+'ms linear'); self.animation.stagger = parse('stagger') ? true : false; self.animation.staggerduration = parseint(parse('stagger') ? (parse('stagger',true).val ? parse('stagger',true).val : 100) : 100); return self._execfilter('_parseeffects', effects); }, /** * build state * @since 2.0.0 * @param {boolean} future * @return {object} futurestate */ _buildstate: function(future){ var self = this, state = {}; self._execaction('_buildstate', 0); state = { activefilter: self._activefilter === '' ? 'none' : self._activefilter, activesort: future && self._newsortstring ? self._newsortstring : self._activesort, fail: !self._$show.length && self._activefilter !== '', $targets: self._$targets, $show: self._$show, $hide: self._$hide, totaltargets: self._$targets.length, totalshow: self._$show.length, totalhide: self._$hide.length, display: future && self._newdisplay ? self._newdisplay : self.layout.display }; if(future){ return self._execfilter('_buildstate', state); } else { self._state = state; self._execaction('_buildstate', 1); } }, /** * go mix * @since 2.0.0 * @param {boolean} animate */ _gomix: function(animate){ var self = this, phase1 = function(){ if(self._chrome && (self._chrome === 31)){ chromefix(self._$parent[0]); } self._setinter(); phase2(); }, phase2 = function(){ var scrolltop = window.pageyoffset, scrollleft = window.pagexoffset, docheight = document.documentelement.scrollheight; self._getintermixdata(); self._setfinal(); self._getfinalmixdata(); (window.pageyoffset !== scrolltop) && window.scrollto(scrollleft, scrolltop); self._preptargets(); if(window.requestanimationframe){ requestanimationframe(phase3); } else { settimeout(function(){ phase3(); },20); } }, phase3 = function(){ self._animatetargets(); if(self._targetsbound === 0){ self._cleanup(); } }, chromefix = function(grid){ var parent = grid.parentelement, placeholder = document.createelement('div'), frag = document.createdocumentfragment(); parent.insertbefore(placeholder, grid); frag.appendchild(grid); parent.replacechild(grid, placeholder); }, futurestate = self._buildstate(true); self._execaction('_gomix', 0, arguments); !self.animation.duration && (animate = false); self._mixing = true; self._$container.removeclass(self.layout.containerclassfail); if(typeof self.callbacks.onmixstart === 'function'){ self.callbacks.onmixstart.call(self._domnode, self._state, futurestate, self); } self._$container.trigger('mixstart', [self._state, futurestate, self]); self._getorigmixdata(); if(animate && !self._suckmode){ window.requestanimationframe ? requestanimationframe(phase1) : phase1(); } else { self._cleanup(); } self._execaction('_gomix', 1, arguments); }, /** * get target data * @since 2.0.0 */ _gettargetdata: function(el, stage){ var self = this, elstyle; el.dataset[stage+'posx'] = el.offsetleft; el.dataset[stage+'posy'] = el.offsettop; if(self.animation.animateresizetargets){ elstyle = !self._suckmode ? window.getcomputedstyle(el) : { marginbottom: '', marginright: '' }; el.dataset[stage+'marginbottom'] = parseint(elstyle.marginbottom); el.dataset[stage+'marginright'] = parseint(elstyle.marginright); el.dataset[stage+'width'] = el.offsetwidth; el.dataset[stage+'height'] = el.offsetheight; } }, /** * get original mix data * @since 2.0.0 */ _getorigmixdata: function(){ var self = this, parentstyle = !self._suckmode ? window.getcomputedstyle(self._$parent[0]) : {boxsizing: ''}, parentbs = parentstyle.boxsizing || parentstyle[self._vendor+'boxsizing']; self._incpadding = (parentbs === 'border-box'); self._execaction('_getorigmixdata', 0); !self._suckmode && (self.effects = self._parseeffects()); self._$tohide = self._$hide.filter(':visible'); self._$toshow = self._$show.filter(':hidden'); self._$pre = self._$targets.filter(':visible'); self._startheight = self._incpadding ? self._$parent.outerheight() : self._$parent.height(); for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i]; self._gettargetdata(el, 'orig'); } self._execaction('_getorigmixdata', 1); }, /** * set intermediate positions * @since 2.0.0 */ _setinter: function(){ var self = this; self._execaction('_setinter', 0); if(self._changinglayout && self.animation.animatechangelayout){ self._$toshow.css('display',self._newdisplay); if(self._changingclass){ self._$container .removeclass(self.layout.containerclass) .addclass(self._newclass); } } else { self._$toshow.css('display', self.layout.display); } self._execaction('_setinter', 1); }, /** * get intermediate mix data * @since 2.0.0 */ _getintermixdata: function(){ var self = this; self._execaction('_getintermixdata', 0); for(var i = 0; i < self._$toshow.length; i++){ var el = self._$toshow[i]; self._gettargetdata(el, 'inter'); } for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i]; self._gettargetdata(el, 'inter'); } self._execaction('_getintermixdata', 1); }, /** * set final positions * @since 2.0.0 */ _setfinal: function(){ var self = this; self._execaction('_setfinal', 0); self._sorting && self._printsort(); self._$tohide.removestyle('display'); if(self._changinglayout && self.animation.animatechangelayout){ self._$pre.css('display',self._newdisplay); } self._execaction('_setfinal', 1); }, /** * get final mix data * @since 2.0.0 */ _getfinalmixdata: function(){ var self = this; self._execaction('_getfinalmixdata', 0); for(var i = 0; i < self._$toshow.length; i++){ var el = self._$toshow[i]; self._gettargetdata(el, 'final'); } for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i]; self._gettargetdata(el, 'final'); } self._newheight = self._incpadding ? self._$parent.outerheight() : self._$parent.height(); self._sorting && self._printsort(true); self._$toshow.removestyle('display'); self._$pre.css('display',self.layout.display); if(self._changingclass && self.animation.animatechangelayout){ self._$container .removeclass(self._newclass) .addclass(self.layout.containerclass); } self._execaction('_getfinalmixdata', 1); }, /** * prepare targets * @since 2.0.0 */ _preptargets: function(){ var self = this, transformcss = { _in: self._getprefixedcss('transform', self.effects.transformin), _out: self._getprefixedcss('transform', self.effects.transformout) }; self._execaction('_preptargets', 0); if(self.animation.animateresizecontainer){ self._$parent.css('height',self._startheight+'px'); } for(var i = 0; i < self._$toshow.length; i++){ var el = self._$toshow[i], $el = $(el); el.style.opacity = self.effects.opacity; el.style.display = (self._changinglayout && self.animation.animatechangelayout) ? self._newdisplay : self.layout.display; $el.css(transformcss._in); if(self.animation.animateresizetargets){ el.style.width = el.dataset.finalwidth+'px'; el.style.height = el.dataset.finalheight+'px'; el.style.marginright = -(el.dataset.finalwidth - el.dataset.interwidth) + (el.dataset.finalmarginright * 1)+'px'; el.style.marginbottom = -(el.dataset.finalheight - el.dataset.interheight) + (el.dataset.finalmarginbottom * 1)+'px'; } } for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i], $el = $(el), translate = { x: el.dataset.origposx - el.dataset.interposx, y: el.dataset.origposy - el.dataset.interposy }, transformcss = self._getprefixedcss('transform','translate('+translate.x+'px,'+translate.y+'px)'); $el.css(transformcss); if(self.animation.animateresizetargets){ el.style.width = el.dataset.origwidth+'px'; el.style.height = el.dataset.origheight+'px'; if(el.dataset.origwidth - el.dataset.finalwidth){ el.style.marginright = -(el.dataset.origwidth - el.dataset.interwidth) + (el.dataset.origmarginright * 1)+'px'; } if(el.dataset.origheight - el.dataset.finalheight){ el.style.marginbottom = -(el.dataset.origheight - el.dataset.interheight) + (el.dataset.origmarginbottom * 1) +'px'; } } } self._execaction('_preptargets', 1); }, /** * animate targets * @since 2.0.0 */ _animatetargets: function(){ var self = this; self._execaction('_animatetargets', 0); self._targetsdone = 0; self._targetsbound = 0; self._$parent .css(self._getprefixedcss('perspective', self.animation.perspectivedistance+'px')) .css(self._getprefixedcss('perspective-origin', self.animation.perspectiveorigin)); if(self.animation.animateresizecontainer){ self._$parent .css(self._getprefixedcss('transition','height '+self.animation.duration+'ms ease')) .css('height',self._newheight+'px'); } for(var i = 0; i < self._$toshow.length; i++){ var el = self._$toshow[i], $el = $(el), translate = { x: el.dataset.finalposx - el.dataset.interposx, y: el.dataset.finalposy - el.dataset.interposy }, delay = self._getdelay(i), toshowcss = {}; el.style.opacity = ''; for(var j = 0; j < 2; j++){ var a = j === 0 ? a = self._prefix : ''; if(self._ff && self._ff <= 20){ toshowcss[a+'transition-property'] = 'all'; toshowcss[a+'transition-timing-function'] = self.animation.easing+'ms'; toshowcss[a+'transition-duration'] = self.animation.duration+'ms'; } toshowcss[a+'transition-delay'] = delay+'ms'; toshowcss[a+'transform'] = 'translate('+translate.x+'px,'+translate.y+'px)'; } if(self.effects.transform || self.effects.opacity){ self._bindtargetdone($el); } (self._ff && self._ff <= 20) ? $el.css(toshowcss) : $el.css(self.effects.transition).css(toshowcss); } for(var i = 0; i < self._$pre.length; i++){ var el = self._$pre[i], $el = $(el), translate = { x: el.dataset.finalposx - el.dataset.interposx, y: el.dataset.finalposy - el.dataset.interposy }, delay = self._getdelay(i); if(!( el.dataset.finalposx === el.dataset.origposx && el.dataset.finalposy === el.dataset.origposy )){ self._bindtargetdone($el); } $el.css(self._getprefixedcss('transition', 'all '+self.animation.duration+'ms '+self.animation.easing+' '+delay+'ms')); $el.css(self._getprefixedcss('transform', 'translate('+translate.x+'px,'+translate.y+'px)')); if(self.animation.animateresizetargets){ if(el.dataset.origwidth - el.dataset.finalwidth && el.dataset.finalwidth * 1){ el.style.width = el.dataset.finalwidth+'px'; el.style.marginright = -(el.dataset.finalwidth - el.dataset.interwidth)+(el.dataset.finalmarginright * 1)+'px'; } if(el.dataset.origheight - el.dataset.finalheight && el.dataset.finalheight * 1){ el.style.height = el.dataset.finalheight+'px'; el.style.marginbottom = -(el.dataset.finalheight - el.dataset.interheight)+(el.dataset.finalmarginbottom * 1) +'px'; } } } if(self._changingclass){ self._$container .removeclass(self.layout.containerclass) .addclass(self._newclass); } for(var i = 0; i < self._$tohide.length; i++){ var el = self._$tohide[i], $el = $(el), delay = self._getdelay(i), tohidecss = {}; for(var j = 0; j<2; j++){ var a = j === 0 ? a = self._prefix : ''; tohidecss[a+'transition-delay'] = delay+'ms'; tohidecss[a+'transform'] = self.effects.transformout; tohidecss.opacity = self.effects.opacity; } $el.css(self.effects.transition).css(tohidecss); if(self.effects.transform || self.effects.opacity){ self._bindtargetdone($el); }; } self._execaction('_animatetargets', 1); }, /** * bind targets transitionend * @since 2.0.0 * @param {object} $el */ _bindtargetdone: function($el){ var self = this, el = $el[0]; self._execaction('_bindtargetdone', 0, arguments); if(!el.dataset.bound){ el.dataset.bound = true; self._targetsbound++; $el.on('webkittransitionend.mixitup transitionend.mixitup',function(e){ if( (e.originalevent.propertyname.indexof('transform') > -1 || e.originalevent.propertyname.indexof('opacity') > -1) && $(e.originalevent.target).is(self.selectors.target) ){ $el.off('.mixitup'); el.dataset.bound = ''; self._targetdone(); } }); } self._execaction('_bindtargetdone', 1, arguments); }, /** * target done * @since 2.0.0 */ _targetdone: function(){ var self = this; self._execaction('_targetdone', 0); self._targetsdone++; (self._targetsdone === self._targetsbound) && self._cleanup(); self._execaction('_targetdone', 1); }, /** * clean up * @since 2.0.0 */ _cleanup: function(){ var self = this, targetstyles = self.animation.animateresizetargets ? 'transform opacity width height margin-bottom margin-right' : 'transform opacity', unbrake = function(){ self._$targets.removestyle('transition', self._prefix); }; self._execaction('_cleanup', 0); !self._changinglayout ? self._$show.css('display',self.layout.display) : self._$show.css('display',self._newdisplay); self._$targets.css(self._brake); self._$targets .removestyle(targetstyles, self._prefix) .removeattr('data-inter-pos-x data-inter-pos-y data-final-pos-x data-final-pos-y data-orig-pos-x data-orig-pos-y data-orig-height data-orig-width data-final-height data-final-width data-inter-width data-inter-height data-orig-margin-right data-orig-margin-bottom data-inter-margin-right data-inter-margin-bottom data-final-margin-right data-final-margin-bottom'); self._$hide.removestyle('display'); self._$parent.removestyle('height transition perspective-distance perspective perspective-origin-x perspective-origin-y perspective-origin perspectiveorigin', self._prefix); if(self._sorting){ self._printsort(); self._activesort = self._newsortstring; self._sorting = false; } if(self._changinglayout){ if(self._changingdisplay){ self.layout.display = self._newdisplay; self._changingdisplay = false; } if(self._changingclass){ self._$parent.removeclass(self.layout.containerclass).addclass(self._newclass); self.layout.containerclass = self._newclass; self._changingclass = false; } self._changinglayout = false; } self._refresh(); self._buildstate(); if(self._state.fail){ self._$container.addclass(self.layout.containerclassfail); } self._$show = $(); self._$hide = $(); if(window.requestanimationframe){ requestanimationframe(unbrake); } self._mixing = false; if(typeof self.callbacks._user === 'function'){ self.callbacks._user.call(self._domnode, self._state, self); } if(typeof self.callbacks.onmixend === 'function'){ self.callbacks.onmixend.call(self._domnode, self._state, self); } self._$container.trigger('mixend', [self._state, self]); if(self._state.fail){ (typeof self.callbacks.onmixfail === 'function') && self.callbacks.onmixfail.call(self._domnode, self._state, self); self._$container.trigger('mixfail', [self._state, self]); } if(self._loading){ (typeof self.callbacks.onmixload === 'function') && self.callbacks.onmixload.call(self._domnode, self._state, self); self._$container.trigger('mixload', [self._state, self]); } if(self._queue.length){ self._execaction('_queue', 0); self.multimix(self._queue[0][0],self._queue[0][1],self._queue[0][2]); self._queue.splice(0, 1); } self._execaction('_cleanup', 1); self._loading = false; }, /** * get prefixed css * @since 2.0.0 * @param {string} property * @param {string} value * @param {boolean} prefixvalue * @return {object} styles */ _getprefixedcss: function(property, value, prefixvalue){ var self = this, styles = {}, prefix = '', i = -1; for(i = 0; i < 2; i++){ prefix = i === 0 ? self._prefix : ''; prefixvalue ? styles[prefix+property] = prefix+value : styles[prefix+property] = value; } return self._execfilter('_getprefixedcss', styles, arguments); }, /** * get delay * @since 2.0.0 * @param {number} i * @return {number} delay */ _getdelay: function(i){ var self = this, n = typeof self.animation.staggersequence === 'function' ? self.animation.staggersequence.call(self._domnode, i, self._state) : i, delay = self.animation.stagger ? n * self.animation.staggerduration : 0; return self._execfilter('_getdelay', delay, arguments); }, /** * parse multimix arguments * @since 2.0.0 * @param {array} args * @return {object} output */ _parsemultimixargs: function(args){ var self = this, output = { command: null, animate: self.animation.enable, callback: null }; for(var i = 0; i < args.length; i++){ var arg = args[i]; if(arg !== null){ if(typeof arg === 'object' || typeof arg === 'string'){ output.command = arg; } else if(typeof arg === 'boolean'){ output.animate = arg; } else if(typeof arg === 'function'){ output.callback = arg; } } } return self._execfilter('_parsemultimixargs', output, arguments); }, /** * parse insert arguments * @since 2.0.0 * @param {array} args * @return {object} output */ _parseinsertargs: function(args){ var self = this, output = { index: 0, $object: $(), multimix: {filter: self._state.activefilter}, callback: null }; for(var i = 0; i < args.length; i++){ var arg = args[i]; if(typeof arg === 'number'){ output.index = arg; } else if(typeof arg === 'object' && arg instanceof $){ output.$object = arg; } else if(typeof arg === 'object' && self._helpers._iselement(arg)){ output.$object = $(arg); } else if(typeof arg === 'object' && arg !== null){ output.multimix = arg; } else if(typeof arg === 'boolean' && !arg){ output.multimix = false; } else if(typeof arg === 'function'){ output.callback = arg; } } return self._execfilter('_parseinsertargs', output, arguments); }, /** * execute action * @since 2.0.0 * @param {string} methodname * @param {boolean} ispost * @param {array} args */ _execaction: function(methodname, ispost, args){ var self = this, context = ispost ? 'post' : 'pre'; if(!self._actions.isemptyobject && self._actions.hasownproperty(methodname)){ for(var key in self._actions[methodname][context]){ self._actions[methodname][context][key].call(self, args); } } }, /** * execute filter * @since 2.0.0 * @param {string} methodname * @param {mixed} value * @return {mixed} value */ _execfilter: function(methodname, value, args){ var self = this; if(!self._filters.isemptyobject && self._filters.hasownproperty(methodname)){ for(var key in self._filters[methodname]){ return self._filters[methodname][key].call(self, args); } } else { return value; } }, /* helpers ---------------------------------------------------------------------- */ _helpers: { /** * camelcase * @since 2.0.0 * @param {string} * @return {string} */ _camelcase: function(string){ return string.replace(/-([a-z])/g, function(g){ return g[1].touppercase(); }); }, /** * is element * @since 2.1.3 * @param {object} element to test * @return {boolean} */ _iselement: function(el){ if(window.htmlelement){ return el instanceof htmlelement; } else { return ( el !== null && el.nodetype === 1 && el.nodename === 'string' ); } } }, /* public methods ---------------------------------------------------------------------- */ /** * is mixing * @since 2.0.0 * @return {boolean} */ ismixing: function(){ var self = this; return self._execfilter('ismixing', self._mixing); }, /** * filter (public) * @since 2.0.0 * @param {array} arguments */ filter: function(){ var self = this, args = self._parsemultimixargs(arguments); self._clicking && (self._togglestring = ''); self.multimix({filter: args.command}, args.animate, args.callback); }, /** * sort (public) * @since 2.0.0 * @param {array} arguments */ sort: function(){ var self = this, args = self._parsemultimixargs(arguments); self.multimix({sort: args.command}, args.animate, args.callback); }, /** * change layout (public) * @since 2.0.0 * @param {array} arguments */ changelayout: function(){ var self = this, args = self._parsemultimixargs(arguments); self.multimix({changelayout: args.command}, args.animate, args.callback); }, /** * multimix * @since 2.0.0 * @param {array} arguments */ multimix: function(){ var self = this, args = self._parsemultimixargs(arguments); self._execaction('multimix', 0, arguments); if(!self._mixing){ if(self.controls.enable && !self._clicking){ self.controls.togglefilterbuttons && self._buildtogglearray(); self._updatecontrols(args.command, self.controls.togglefilterbuttons); } (self._queue.length < 2) && (self._clicking = false); delete self.callbacks._user; if(args.callback) self.callbacks._user = args.callback; var sort = args.command.sort, filter = args.command.filter, changelayout = args.command.changelayout; self._refresh(); if(sort){ self._newsort = self._parsesort(sort); self._newsortstring = sort; self._sorting = true; self._sort(); } if(filter !== undf){ filter = (filter === 'all') ? self.selectors.target : filter; self._activefilter = filter; } self._filter(); if(changelayout){ self._newdisplay = (typeof changelayout === 'string') ? changelayout : changelayout.display || self.layout.display; self._newclass = changelayout.containerclass || ''; if( self._newdisplay !== self.layout.display || self._newclass !== self.layout.containerclass ){ self._changinglayout = true; self._changingclass = (self._newclass !== self.layout.containerclass); self._changingdisplay = (self._newdisplay !== self.layout.display); } } self._$targets.css(self._brake); self._gomix(args.animate ^ self.animation.enable ? args.animate : self.animation.enable); self._execaction('multimix', 1, arguments); } else { if(self.animation.queue && self._queue.length < self.animation.queuelimit){ self._queue.push(arguments); (self.controls.enable && !self._clicking) && self._updatecontrols(args.command); self._execaction('multimixqueue', 1, arguments); } else { if(typeof self.callbacks.onmixbusy === 'function'){ self.callbacks.onmixbusy.call(self._domnode, self._state, self); } self._$container.trigger('mixbusy', [self._state, self]); self._execaction('multimixbusy', 1, arguments); } } }, /** * insert * @since 2.0.0 * @param {array} arguments */ insert: function(){ var self = this, args = self._parseinsertargs(arguments), callback = (typeof args.callback === 'function') ? args.callback : null, frag = document.createdocumentfragment(), target = (function(){ self._refresh(); if(self._$targets.length){ return (args.index < self._$targets.length || !self._$targets.length) ? self._$targets[args.index] : self._$targets[self._$targets.length-1].nextelementsibling; } else { return self._$parent[0].children[0]; } })(); self._execaction('insert', 0, arguments); if(args.$object){ for(var i = 0; i < args.$object.length; i++){ var el = args.$object[i]; frag.appendchild(el); frag.appendchild(document.createtextnode(' ')); } self._$parent[0].insertbefore(frag, target); } self._execaction('insert', 1, arguments); if(typeof args.multimix === 'object'){ self.multimix(args.multimix, callback); } }, /** * prepend * @since 2.0.0 * @param {array} arguments */ prepend: function(){ var self = this, args = self._parseinsertargs(arguments); self.insert(0, args.$object, args.multimix, args.callback); }, /** * append * @since 2.0.0 * @param {array} arguments */ append: function(){ var self = this, args = self._parseinsertargs(arguments); self.insert(self._state.totaltargets, args.$object, args.multimix, args.callback); }, /** * get option * @since 2.0.0 * @param {string} string * @return {mixed} value */ getoption: function(string){ var self = this, getproperty = function(obj, prop){ var parts = prop.split('.'), last = parts.pop(), l = parts.length, i = 1, current = parts[0] || prop; while((obj = obj[current]) && i < l){ current = parts[i]; i++; } if(obj !== undf){ return obj[last] !== undf ? obj[last] : obj; } }; return string ? self._execfilter('getoption', getproperty(self, string), arguments) : self; }, /** * set options * @since 2.0.0 * @param {object} config */ setoptions: function(config){ var self = this; self._execaction('setoptions', 0, arguments); typeof config === 'object' && $.extend(true, self, config); self._execaction('setoptions', 1, arguments); }, /** * get state * @since 2.0.0 * @return {object} state */ getstate: function(){ var self = this; return self._execfilter('getstate', self._state, self); }, /** * force refresh * @since 2.1.2 */ forcerefresh: function(){ var self = this; self._refresh(false, true); }, /** * destroy * @since 2.0.0 * @param {boolean} hideall */ destroy: function(hideall){ var self = this, filters = $.mixitup.prototype._bound._filter, sorts = $.mixitup.prototype._bound._sort; self._execaction('destroy', 0, arguments); self._$body .add($(self.selectors.sort)) .add($(self.selectors.filter)) .off('.mixitup'); for(var i = 0; i < self._$targets.length; i++){ var target = self._$targets[i]; hideall && (target.style.display = ''); delete target.mixparent; } self._execaction('destroy', 1, arguments); if(filters[self.selectors.filter] && filters[self.selectors.filter] > 1) { filters[self.selectors.filter]--; } else if(filters[self.selectors.filter] === 1) { delete filters[self.selectors.filter]; } if(sorts[self.selectors.sort] && sorts[self.selectors.sort] > 1) { sorts[self.selectors.sort]--; } else if(sorts[self.selectors.sort] === 1) { delete sorts[self.selectors.sort]; } delete $.mixitup.prototype._instances[self._id]; } }; /* jquery methods ---------------------------------------------------------------------- */ /** * jquery .mixitup() method * @since 2.0.0 * @extends $.fn */ $.fn.mixitup = function(){ var args = arguments, datareturn = [], eachreturn, _instantiate = function(domnode, settings){ var instance = new $.mixitup(), rand = function(){ return ('00000'+(math.random()*16777216<<0).tostring(16)).substr(-6).touppercase(); }; instance._execaction('_instantiate', 0, arguments); domnode.id = !domnode.id ? 'mixitup'+rand() : domnode.id; if(!instance._instances[domnode.id]){ instance._instances[domnode.id] = instance; instance._init(domnode, settings); } instance._execaction('_instantiate', 1, arguments); }; eachreturn = this.each(function(){ if(args && typeof args[0] === 'string'){ var instance = $.mixitup.prototype._instances[this.id]; if(args[0] === 'isloaded'){ datareturn.push(instance ? true : false); } else { var data = instance[args[0]](args[1], args[2], args[3]); if(data !== undf)datareturn.push(data); } } else { _instantiate(this, args[0]); } }); if(datareturn.length){ return datareturn.length > 1 ? datareturn : datareturn[0]; } else { return eachreturn; } }; /** * jquery .removestyle() method * @since 2.0.0 * @extends $.fn */ $.fn.removestyle = function(style, prefix){ prefix = prefix ? prefix : ''; return this.each(function(){ var el = this, styles = style.split(' '); for(var i = 0; i < styles.length; i++){ for(var j = 0; j < 4; j++){ switch (j) { case 0: var prop = styles[i]; break; case 1: var prop = $.mixitup.prototype._helpers._camelcase(prop); break; case 2: var prop = prefix+styles[i]; break; case 3: var prop = $.mixitup.prototype._helpers._camelcase(prefix+styles[i]); } if( el.style[prop] !== undf && typeof el.style[prop] !== 'unknown' && el.style[prop].length > 0 ){ el.style[prop] = ''; } if(!prefix && j === 1)break; } } if(el.attributes && el.attributes.style && el.attributes.style !== undf && el.attributes.style.value === ''){ el.attributes.removenameditem('style'); } }); }; })(jquery);