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