1/**! 2 * MixItUp v2.1.4 3 * 4 * @copyright Copyright 2014 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.nodeValue; 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 (multi && type == 'filter' && !(output.filter === 'none' || output.f
586ilter === '')) ? 587 $el.filter(filter).addClass(self.controls.activeClass) : 588 $el.removeClass(self.controls.activeClass).filter(filter).addClass(self.controls.activeClass); 589 }, 590 type = 'filter', 591 $el = null; 592 593 self._execAction('_updateControls', 0, arguments); 594 595 (command.filter === undf) && (output.filter = self._activeFilter); 596 (command.sort === undf) && (output.sort = self._activeSort); 597 (output.filter === self.selectors.target) && (output.filter = 'all'); 598 599 for(var i = 0; i < 2; i++){ 600 $el = self.controls.live ? $(self.selectors[type]) : self['_$'+type+'Buttons']; 601 $el && update($el, '[data-'+type+'="'+output[type]+'"]'); 602 type = 'sort'; 603 } 604 605 self._execAction('_updateControls', 1, arguments); 606 }, 607 608 /** 609 * Filter (private) 610 * @since 2.0.0 611 */ 612 613 _filter: function(){ 614 var self = this; 615 616 self._execAction('_filter', 0); 617 618 for(var i = 0; i < self._$targets.length; i++){ 619 var $target = $(self._$targets[i]); 620 621 if($target.is(self._activeFilter)){ 622 self._$show = self._$show.add($target); 623 } else { 624 self._$hide = self._$hide.add($target); 625 } 626 } 627 628 self._execAction('_filter', 1); 629 }, 630 631 /** 632 * Sort (private) 633 * @since 2.0.0 634 */ 635 636 _sort: function(){ 637 var self = this, 638 arrayShuffle = function(oldArray){ 639 var newArray = oldArray.slice(), 640 len = newArray.length, 641 i = len; 642 643 while(i--){ 644 var p = parseInt(Math.random()*len); 645 var t = newArray[i]; 646 newArray[i] = newArray[p]; 647 newArray[p] = t; 648 }; 649 return newArray; 650 }; 651 652 self._execAction('_sort', 0); 653 654 self._startOrder = []; 655 656 for(var i = 0; i < self._$targets.length; i++){ 657 var target = self._$targets[i]; 658 659 self._startOrder.push(target); 660 } 661 662 switch(self._newSort[0].sortBy){ 663 case 'default': 664 self._newOrder = self._origOrder; 665 break; 666 case 'random': 667 self._newOrder = arrayShuffle(self._startOrder); 668 break; 669 case 'custom': 670 self._newOrder = self._newSort[0].order; 671 break; 672 default: 673 self._newOrder = self._startOrder.concat().sort(function(a, b){ 674 return self._compare(a, b); 675 }); 676 } 677 678 self._execAction('_sort', 1); 679 }, 680 681 /** 682 * Compare Algorithm 683 * @since 2.0.0 684 * @param {string|number} a 685 * @param {string|number} b 686 * @param {number} depth (recursion) 687 * @return {number} 688 */ 689 690 _compare: function(a, b, depth){ 691 depth = depth ? depth : 0; 692 693 var self = this, 694 order = self._newSort[depth].order, 695 getData = function(el){ 696 return el.dataset[self._newSort[depth].sortBy] || 0; 697 }, 698 attrA = isNaN(getData(a) * 1) ? getData(a).toLowerCase() : getData(a) * 1, 699 attrB = isNaN(getData(b) * 1) ? getData(b).toLowerCase() : getData(b) * 1; 700 701 if(attrA < attrB) 702 return order == 'asc' ? -1 : 1; 703 if(attrA > attrB) 704 return order == 'asc' ? 1 : -1; 705 if(attrA == attrB && self._newSort.length > depth+1) 706 return self._compare(a, b, depth+1); 707 708 return 0; 709 }, 710 711 /** 712 * Print Sort 713 * @since 2.0.0 714 * @param {boolean} reset 715 */ 716 717 _printSort: function(reset){ 718 var self = this, 719 order = reset ? self._startOrder : self._newOrder, 720 targets = self._$parent[0].querySelectorAll(self.selectors.target), 721 nextSibling = targets[targets.length -1].nextElementSibling, 722 frag = document.createDocumentFragment(); 723 724 self._execAction('_printSort', 0, arguments); 725 726 for(var i = 0; i < targets.length; i++){ 727 var target = targets[i], 728 whiteSpace = target.nextSibling; 729 730 if(target.style.position === 'absolute') continue; 731 732 if(whiteSpace && whiteSpace.nodeName == '#text'){ 733 self._$parent[0].removeChild(whiteSpace); 734 } 735 736 self._$parent[0].removeChild(target); 737 } 738 739 for(var i = 0; i < order.length; i++){ 740 var el = order[i]; 741 742 if(self._newSort[0].sortBy == 'default' && self._newSort[0].order == 'desc' && !reset){ 743 var firstChild = frag.firstChild; 744 frag.insertBefore(el, firstChild); 745 frag.insertBefore(document.createTextNode(' '), el); 746 } else { 747 frag.appendChild(el); 748 frag.appendChild(document.createTextNode(' ')); 749 } 750 } 751 752 nextSibling ? 753 self._$parent[0].insertBefore(frag, nextSibling) : 754 self._$parent[0].appendChild(frag); 755
756 self._execAction('_printSort', 1, arguments); 757 }, 758 759 /** 760 * Parse Sort 761 * @since 2.0.0 762 * @param {string} sortString 763 * @return {array} newSort 764 */ 765 766 _parseSort: function(sortString){ 767 var self = this, 768 rules = typeof sortString === 'string' ? sortString.split(' ') : [sortString], 769 newSort = []; 770 771 for(var i = 0; i < rules.length; i++){ 772 var rule = typeof sortString === 'string' ? rules[i].split(':') : ['custom', rules[i]], 773 ruleObj = { 774 sortBy: self._helpers._camelCase(rule[0]), 775 order: rule[1] || 'asc' 776 }; 777 778 newSort.push(ruleObj); 779 780 if(ruleObj.sortBy == 'default' || ruleObj.sortBy == 'random') break; 781 } 782 783 return self._execFilter('_parseSort', newSort, arguments); 784 }, 785 786 /** 787 * Parse Effects 788 * @since 2.0.0 789 * @return {object} effects 790 */ 791 792 _parseEffects: function(){ 793 var self = this, 794 effects = { 795 opacity: '', 796 transformIn: '', 797 transformOut: '', 798 filter: '' 799 }, 800 parse = function(effect, extract, reverse){ 801 if(self.animation.effects.indexOf(effect) > -1){ 802 if(extract){ 803 var propIndex = self.animation.effects.indexOf(effect+'('); 804 if(propIndex > -1){ 805 var str = self.animation.effects.substring(propIndex), 806 match = /\(([^)]+)\)/.exec(str), 807 val = match[1]; 808 809 return {val: val}; 810 } 811 } 812 return true; 813 } else { 814 return false; 815 } 816 }, 817 negate = function(value, invert){ 818 if(invert){ 819 return value.charAt(0) === '-' ? value.substr(1, value.length) : '-'+value; 820 } else { 821 return value; 822 } 823 }, 824 buildTransform = function(key, invert){ 825 var transforms = [ 826 ['scale', '.01'], 827 ['translateX', '20px'], 828 ['translateY', '20px'], 829 ['translateZ', '20px'], 830 ['rotateX', '90deg'], 831 ['rotateY', '90deg'], 832 ['rotateZ', '180deg'], 833 ]; 834 835 for(var i = 0; i < transforms.length; i++){ 836 var prop = transforms[i][0], 837 def = transforms[i][1], 838 inverted = invert && prop !== 'scale'; 839 840 effects[key] += parse(prop) ? prop+'('+negate(parse(prop, true).val || def, inverted)+') ' : ''; 841 } 842 }; 843 844 effects.opacity = parse('fade') ? parse('fade',true).val || '0' : ''; 845 846 buildTransform('transformIn'); 847 848 self.animation.reverseOut ? buildTransform('transformOut', true) : (effects.transformOut = effects.transformIn); 849 850 effects.transition = {}; 851 852 effects.transition = self._getPrefixedCSS('transition','all '+self.animation.duration+'ms '+self.animation.easing+', opacity '+self.animation.duration+'ms linear'); 853 854 self.animation.stagger = parse('stagger') ? true : false; 855 self.animation.staggerDuration = parseInt(parse('stagger') ? (parse('stagger',true).val ? parse('stagger',true).val : 100) : 100); 856 857 return self._execFilter('_parseEffects', effects); 858 }, 859 860 /** 861 * Build State 862 * @since 2.0.0 863 * @param {boolean} future 864 * @return {object} futureState 865 */ 866 867 _buildState: function(future){ 868 var self = this, 869 state = {}; 870
871 self._execAction('_buildState', 0); 872 873 state = { 874 activeFilter: self._activeFilter === '' ? 'none' : self._activeFilter, 875 activeSort: future && self._newSortString ? self._newSortString : self._activeSort, 876 fail: !self._$show.length && self._activeFilter !== '', 877 $targets: self._$targets, 878 $show: self._$show, 879 $hide: self._$hide, 880 totalTargets: self._$targets.length, 881 totalShow: self._$show.length, 882 totalHide: self._$hide.length, 883 display: future && self._newDisplay ? self._newDisplay : self.layout.display 884 }; 885 886 if(future){ 887 return self._execFilter('_buildState', state); 888 } else { 889 self._state = state; 890 891 self._execAction('_buildState', 1); 892 } 893 }, 894 895 /** 896 * Go Mix 897 * @since 2.0.0 898 * @param {boolean} animate 899 */ 900 901 _goMix: function(animate){ 902 var self = this, 903 phase1 = function(){ 904 if(self._chrome && (self._chrome === 31)){ 905 chromeFix(self._$parent[0]); 906 } 907 908 self._setInter(); 909 910 phase2(); 911 }, 912 phase2 = function(){ 913 var scrollTop = window.pageYOffset, 914 scrollLeft = window.pageXOffset, 915 docHeight = document.documentElement.scrollHeight; 916 917 self._getInterMixData(); 918 919 self._setFinal(); 920 921 self._getFinalMixData(); 922 923 (window.pageYOffset !== scrollTop) && window.scrollTo(scrollLeft, scrollTop); 924 925 self._prepTargets(); 926 927 if(window.requestAnimationFrame){ 928 requestAnimationFrame(phase3); 929 } else { 930 setTimeout(function(){ 931 phase3(); 932 },20); 933 } 934 }, 935 phase3 = function(){ 936 self._animateTargets(); 937 938 if(self._targetsBound === 0){ 939 self._cleanUp(); 940 } 941 }, 942 chromeFix = function(grid){ 943 var parent = grid.parentElement, 944 placeholder = document.createElement('div'), 945 frag = document.createDocumentFragment(); 946 947 parent.insertBefore(placeholder, grid); 948 frag.appendChild(grid); 949 parent.replaceChild(grid, placeholder); 950 }, 951 futureState = self._buildState(true); 952 953 self._execAction('_goMix', 0, arguments); 954 955 !self.animation.duration && (animate = false); 956 957 self._mixing = true; 958 959 self._$container.removeClass(self.layout.containerClassFail); 960 961 if(typeof self.callbacks.onMixStart === 'function'){ 962 self.callbacks.onMixStart.call(self._domNode, self._state, futureState, self); 963 } 964 965 self._$container.trigger('mixStart', [self._state, futureState, self]); 966 967 self._getOrigMixData(); 968 969 if(animate && !self._suckMode){ 970 971 window.requestAnimationFrame ? 972 requestAnimationFrame(phase1) : 973 phase1(); 974 975 } else { 976 self._cleanUp(); 977 } 978 979 self._execAction('_goMix', 1, arguments); 980 }, 981 982 /** 983 * Get Target Data 984 * @since 2.0.0 985 */ 986 987 _getTargetData: function(el, stage){ 988 var self = this, 989 elStyle; 990 991 el.dataset[stage+'PosX'] = el.offsetLeft; 992 el.dataset[stage+'PosY'] = el.offsetTop; 993 994 if(self.animation.animateResizeTargets){ 995 elStyle = window.getComputedStyle(el); 996 997 el.dataset[stage+'MarginBottom'] = parseInt(elStyle.marginBottom); 998 el.dataset[stage+'MarginRight'] = parseInt(elStyle.marginRight); 999 el.dataset[stage+'Width'] = el.offsetWidth; 1000 el.dataset[stage+'Height'] = el.offsetHeight; 1001 } 1002 }, 1003 1004 /** 1005 * Get Original Mix Data 1006 * @since 2.0.0 1007 */ 1008 1009 _getOrigMixData: function(){ 1010 var self = this, 1011 parentStyle = !self._suckMode ? window.getComputedStyle(self._$parent[0]) : {boxSizing: ''}, 1012 parentBS = parentStyle.boxSizing || parentStyle[self._vendor+'BoxSizing']; 1013 1014 self._incPadding = (parentBS === 'border-box'); 1015 1016 self._execAction('_getOrigMixData', 0); 1017 1018 !self._suckMode && (self.effects = self._parseEffects()); 1019 1020 self._$toHide = self._$hide.filter(':visible'); 1021 self._$toShow = self._$show.filter(':hidden'); 1022 self._$pre = self._$targets.filter(':visible'); 1023 1024 self._startHeight = self._incPadding ? 1025 self._$parent.outerHeight() : 1026 self._$parent.height(); 1027 1028 for(var i = 0; i < self._$pre.length; i++){ 1029 var el = self._$pre[i]; 1030 1031 self._getTargetData(el, 'orig'); 1032 } 1033 1034 self._execAction('_getOrigMixData', 1); 1035 }, 1036 1037 /** 1038 * Set Intermediate Positions 1039 * @since 2.0.0 1040 */ 1041 1042 _setInter: function(){ 1043 var self = this; 1044 1045 self._execAction('_setInter', 0); 1046 1047 if(self._changingLayout && self.animation.animateChangeLayout){
1048 self._$toShow.css('display',self._newDisplay); 1049 1050 if(self._changingClass){ 1051 self._$container 1052 .removeClass(self.layout.containerClass) 1053 .addClass(self._newClass); 1054 } 1055 } else { 1056 self._$toShow.css('display', self.layout.display); 1057 } 1058 1059 self._execAction('_setInter', 1); 1060 }, 1061 1062 /** 1063 * Get Intermediate Mix Data 1064 * @since 2.0.0 1065 */ 1066 1067 _getInterMixData: function(){ 1068 var self = this; 1069 1070 self._execAction('_getInterMixData', 0); 1071 1072 for(var i = 0; i < self._$toShow.length; i++){ 1073 var el = self._$toShow[i]; 1074 1075 self._getTargetData(el, 'inter'); 1076 } 1077 1078 for(var i = 0; i < self._$pre.length; i++){ 1079 var el = self._$pre[i]; 1080 1081 self._getTargetData(el, 'inter'); 1082 } 1083 1084 self._execAction('_getInterMixData', 1); 1085 }, 1086 1087 /** 1088 * Set Final Positions 1089 * @since 2.0.0 1090 */ 1091 1092 _setFinal: function(){ 1093 var self = this; 1094 1095 self._execAction('_setFinal', 0); 1096 1097 self._sorting && self._printSort(); 1098 1099 self._$toHide.removeStyle('display'); 1100 1101 if(self._changingLayout && self.animation.animateChangeLayout){
1102 self._$pre.css('display',self._newDisplay); 1103 } 1104 1105 self._execAction('_setFinal', 1); 1106 }, 1107 1108 /** 1109 * Get Final Mix Data 1110 * @since 2.0.0 1111 */ 1112 1113 _getFinalMixData: function(){ 1114 var self = this; 1115 1116 self._execAction('_getFinalMixData', 0); 1117 1118 for(var i = 0; i < self._$toShow.length; i++){ 1119 var el = self._$toShow[i]; 1120 1121 self._getTargetData(el, 'final'); 1122 } 1123 1124 for(var i = 0; i < self._$pre.length; i++){ 1125 var el = self._$pre[i]; 1126 1127 self._getTargetData(el, 'final'); 1128 } 1129 1130 self._newHeight = self._incPadding ? 1131 self._$parent.outerHeight() : 1132 self._$parent.height(); 1133 1134 self._sorting && self._printSort(true); 1135 1136 self._$toShow.removeStyle('display'); 1137
1138 self._$pre.css('display',self.layout.display); 1139 1140 if(self._changingClass && self.animation.animateChangeLayout){ 1141 self._$container 1142 .removeClass(self._newClass) 1143 .addClass(self.layout.containerClass); 1144 } 1145 1146 self._execAction('_getFinalMixData', 1); 1147 }, 1148 1149 /** 1150 * Prepare Targets 1151 * @since 2.0.0 1152 */ 1153 1154 _prepTargets: function(){ 1155 var self = this, 1156 transformCSS = { 1157 _in: self._getPrefixedCSS('transform', self.effects.transformIn), 1158 _out: self._getPrefixedCSS('transform', self.effects.transformOut) 1159 }; 1160 1161 self._execAction('_prepTargets', 0); 1162 1163 if(self.animation.animateResizeContainer){ 1164 self._$parent.css('height',self._startHeight+'px'); 1165 } 1166 1167 for(var i = 0; i < self._$toShow.length; i++){ 1168 var el = self._$toShow[i], 1169 $el = $(el); 1170 1171 el.style.opacity = self.effects.opacity; 1172 el.style.display = (self._changingLayout && self.animation.animateChangeLayout) ? 1173 self._newDisplay : 1174 self.layout.display; 1175 1176 $el.css(transformCSS._in); 1177 1178 if(self.animation.animateResizeTargets){ 1179 el.style.width = el.dataset.finalWidth+'px'; 1180 el.style.height = el.dataset.finalHeight+'px'; 1181 el.style.marginRight = -(el.dataset.finalWidth - el.dataset.interWidth) + (el.dataset.finalMarginRight * 1)+'px'; 1182 el.style.marginBottom = -(el.dataset.finalHeight - el.dataset.interHeight) + (el.dataset.finalMarginBottom * 1)+'px'; 1183 } 1184 } 1185 1186 for(var i = 0; i < self._$pre.length; i++){ 1187 var el = self._$pre[i], 1188 $el = $(el), 1189 translate = { 1190 x: el.dataset.origPosX - el.dataset.interPosX, 1191 y: el.dataset.origPosY - el.dataset.interPosY 1192 }, 1193 transformCSS = self._getPrefixedCSS('transform','translate('+translate.x+'px,'+translate.y+'px)'); 1194 1195 $el.css(transformCSS); 1196 1197 if(self.animation.animateResizeTargets){ 1198 el.style.width = el.dataset.origWidth+'px'; 1199 el.style.height = el.dataset.origHeight+'px'; 1200 1201 if(el.dataset.origWidth - el.dataset.finalWidth){ 1202 el.style.marginRight = -(el.dataset.origWidth - el.dataset.interWidth) + (el.dataset.origMarginRight * 1)+'px'; 1203 } 1204 1205 if(el.dataset.origHeight - el.dataset.finalHeight){ 1206 el.style.marginBottom = -(el.dataset.origHeight - el.dataset.interHeight) + (el.dataset.origMarginBottom * 1) +'px'; 1207 } 1208 } 1209 } 1210 1211 self._execAction('_prepTargets', 1); 1212 }, 1213 1214 /** 1215 * Animate Targets 1216 * @since 2.0.0 1217 */ 1218 1219 _animateTargets: function(){ 1220 var self = this; 1221 1222 self._execAction('_animateTargets', 0); 1223 1224 self._targetsDone = 0; 1225 self._targetsBound = 0; 1226 1227 self._$parent 1228 .css(self._getPrefixedCSS('perspective', self.animation.perspectiveDistance+'px')) 1229 .css(self._getPrefixedCSS('perspective-origin', self.animation.perspectiveOrigin)); 1230 1231 if(self.animation.animateResizeContainer){ 1232 self._$parent 1233 .css(self._getPrefixedCSS('transition','height '+self.animation.duration+'ms ease')) 1234 .css('height',self._newHeight+'px'); 1235 } 1236 1237 for(var i = 0; i < self._$toShow.length; i++){ 1238 var el = self._$toShow[i], 1239 $el = $(el), 1240 translate = {
1241 x: el.dataset.finalPosX - el.dataset.interPosX, 1242 y: el.dataset.finalPosY - el.dataset.interPosY 1243 }, 1244 delay = self._getDelay(i), 1245 toShowCSS = {}; 1246 1247 el.style.opacity = ''; 1248 1249 for(var j = 0; j < 2; j++){ 1250 var a = j === 0 ? a = self._prefix : ''; 1251 1252 if(self._ff && self._ff <= 20){ 1253 toShowCSS[a+'transition-property'] = 'all'; 1254 toShowCSS[a+'transition-timing-function'] = self.animation.easing+'ms'; 1255 toShowCSS[a+'transition-duration'] = self.animation.duration+'ms'; 1256 } 1257 1258 toShowCSS[a+'transition-delay'] = delay+'ms'; 1259 toShowCSS[a+'transform'] = 'translate('+translate.x+'px,'+translate.y+'px)'; 1260 } 1261 1262 if(self.effects.transform || self.effects.opacity){ 1263 self._bindTargetDone($el); 1264 } 1265 1266 (self._ff && self._ff <= 20) ? 1267 $el.css(toShowCSS) : 1268 $el.css(self.effects.transition).css(toShowCSS); 1269 } 1270 1271 for(var i = 0; i < self._$pre.length; i++){ 1272 var el = self._$pre[i], 1273 $el = $(el), 1274 translate = { 1275 x: el.dataset.finalPosX - el.dataset.interPosX, 1276 y: el.dataset.finalPosY - el.dataset.interPosY 1277 }, 1278 delay = self._getDelay(i); 1279 1280 if(!( 1281 el.dataset.finalPosX === el.dataset.origPosX && 1282 el.dataset.finalPosY === el.dataset.origPosY 1283 )){ 1284 self._bindTargetDone($el); 1285 } 1286 1287 $el.css(self._getPrefixedCSS('transition', 'all '+self.animation.duration+'ms '+self.animation.easing+' '+delay+'ms')); 1288 $el.css(self._getPrefixedCSS('transform', 'translate('+translate.x+'px,'+translate.y+'px)')); 1289 1290 if(self.animation.animateResizeTargets){ 1291 if(el.dataset.origWidth - el.dataset.finalWidth && el.dataset.finalWidth * 1){ 1292 el.style.width = el.dataset.finalWidth+'px'; 1293 el.style.marginRight = -(el.dataset.finalWidth - el.dataset.interWidth)+(el.dataset.finalMarginRight * 1)+'px'; 1294 } 1295 1296 if(el.dataset.origHeight - el.dataset.finalHeight && el.dataset.finalHeight * 1){ 1297 el.style.height = el.dataset.finalHeight+'px'; 1298 el.style.marginBottom = -(el.dataset.finalHeight - el.dataset.interHeight)+(el.dataset.finalMarginBottom * 1) +'px'; 1299 } 1300 } 1301 } 1302 1303 if(self._changingClass){ 1304 self._$container 1305 .removeClass(self.layout.containerClass) 1306 .addClass(self._newClass); 1307 } 1308 1309 for(var i = 0; i < self._$toHide.length; i++){ 1310 var el = self._$toHide[i], 1311 $el = $(el), 1312 delay = self._getDelay(i), 1313 toHideCSS = {}; 1314 1315 for(var j = 0; j<2; j++){ 1316 var a = j === 0 ? a = self._prefix : ''; 1317 1318 toHideCSS[a+'transition-delay'] = delay+'ms'; 1319 toHideCSS[a+'transform'] = self.effects.transformOut; 1320 toHideCSS.opacity = self.effects.opacity; 1321 } 1322 1323 $el.css(self.effects.transition).css(toHideCSS); 1324 1325 if(self.effects.transform || self.effects.opacity){ 1326 self._bindTargetDone($el); 1327 }; 1328 } 1329 1330 self._execAction('_animateTargets', 1); 1331 1332 }, 1333 1334 /** 1335 * Bind Targets TransitionEnd 1336 * @since 2.0.0 1337 * @param {object} $el 1338 */ 1339 1340 _bindTargetDone: function($el){ 1341 var self = this, 1342 el = $el[0]; 1343 1344 self._execAction('_bindTargetDone', 0, arguments); 1345 1346 if(!el.dataset.bound){ 1347 1348 el.dataset.bound = true; 1349 self._targetsBound++; 1350 1351 $el.on('webkitTransitionEnd.mixItUp transitionend.mixItUp',function(e){ 1352 if( 1353 (e.originalEvent.propertyName.indexOf('transform') > -1 || 1354 e.originalEvent.propertyName.indexOf('opacity') > -1) && 1355 $(e.originalEvent.target).is(self.selectors.target) 1356 ){ 1357 $el.off('.mixItUp'); 1358 delete el.dataset.bound; 1359 self._targetDone(); 1360 } 1361 }); 1362 } 1363 1364 self._execAction('_bindTargetDone', 1, arguments); 1365 }, 1366 1367 /** 1368 * Target Done 1369 * @since 2.0.0 1370 */ 1371 1372 _targetDone: function(){ 1373 var self = this; 1374 1375 self._execAction('_targetDone', 0); 1376 1377 self._targetsDone++; 1378 1379 (self._targetsDone === self._targetsBound) && self._cleanUp(); 1380 1381 self._execAction('_targetDone', 1); 1382 }, 1383 1384 /** 1385 * Clean Up 1386 * @since 2.0.0 1387 */ 1388 1389 _cleanUp: function(){ 1390 var self = this, 1391 targetStyles = self.animation.animateResizeTargets ? 'transform opacity width height margin-bottom margin-right' : 'transform opacity'; 1392 unBrake = function(){ 1393 self._$targets.removeStyle('transition', self._prefix); 1394 }; 1395 1396 self._execAction('_cleanUp', 0); 1397 1398 !self._changingLayout ?
1399 self._$show.css('display',self.layout.display) : 1400 self._$show.css('display',self._newDisplay); 1401 1402 self._$targets.css(self._brake); 1403 1404 self._$targets 1405 .removeStyle(targetStyles, self._prefix) 1406 .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'); 1407 1408 self._$hide.removeStyle('display'); 1409 1410 self._$parent.removeStyle('height transition perspective-distance perspective perspective-origin-x perspective-origin-y perspective-origin perspectiveOrigin', self._prefix); 1411 1412 if(self._sorting){ 1413 self._printSort(); 1414 self._activeSort = self._newSortString; 1415 self._sorting = false; 1416 } 1417 1418 if(self._changingLayout){ 1419 if(self._changingDisplay){ 1420 self.layout.display = self._newDisplay; 1421 self._changingDisplay = false; 1422 } 1423 1424 if(self._changingClass){ 1425 self._$parent.removeClass(self.layout.containerClass).addClass(self._newClass); 1426 self.layout.containerClass = self._newClass; 1427 self._changingClass = false; 1428 } 1429 1430 self._changingLayout = false; 1431 } 1432 1433 self._refresh(); 1434 1435 self._buildState(); 1436 1437 if(self._state.fail){ 1438 self._$container.addClass(self.layout.containerClassFail); 1439 } 1440 1441 self._$show = $(); 1442 self._$hide = $(); 1443 1444 if(window.requestAnimationFrame){ 1445 requestAnimationFrame(unBrake); 1446 } 1447 1448 self._mixing = false; 1449 1450 if(typeof self.callbacks._user === 'function'){ 1451 self.callbacks._user.call(self._domNode, self._state, self); 1452 } 1453 1454 if(typeof self.callbacks.onMixEnd === 'function'){ 1455 self.callbacks.onMixEnd.call(self._domNode, self._state, self); 1456 } 1457 1458 self._$container.trigger('mixEnd', [self._state, self]); 1459 1460 if(self._state.fail){ 1461 (typeof self.callbacks.onMixFail === 'function') && self.callbacks.onMixFail.call(self._domNode, self._state, self); 1462 self._$container.trigger('mixFail', [self._state, self]); 1463 } 1464 1465 if(self._loading){ 1466 (typeof self.callbacks.onMixLoad === 'function') && self.callbacks.onMixLoad.call(self._domNode, self._state, self); 1467 self._$container.trigger('mixLoad', [self._state, self]); 1468 } 1469 1470 if(self._queue.length){ 1471 self._execAction('_queue', 0); 1472 1473 self.multiMix(self._queue[0][0],self._queue[0][1],self._queue[0][2]); 1474 self._queue.splice(0, 1); 1475 } 1476 1477 self._execAction('_cleanUp', 1); 1478 1479 self._loading = false; 1480 }, 1481 1482 /** 1483 * Get Prefixed CSS 1484 * @since 2.0.0 1485 * @param {string} property 1486 * @param {string} value 1487 * @param {boolean} prefixValue 1488 * @return {object} styles 1489 */ 1490 1491 _getPrefixedCSS: function(property, value, prefixValue){ 1492 var self = this, 1493 styles = {}; 1494 1495 for(i = 0; i < 2; i++){ 1496 var prefix = i === 0 ? self._prefix : ''; 1497 prefixValue ? styles[prefix+property] = prefix+value : styles[prefix+property] = value; 1498 } 1499 1500 return self._execFilter('_getPrefixedCSS', styles, arguments); 1501 }, 1502 1503 /** 1504 * Get Delay 1505 * @since 2.0.0 1506 * @param {number} i 1507 * @return {number} delay 1508 */ 1509 1510 _getDelay: function(i){ 1511 var self = this, 1512 n = typeof self.animation.staggerFunction === 'function' ? self.animation.staggerFunction.call(self._domNode, i, self._state) : i,
1513 delay = self.animation.stagger ? n * self.animation.staggerDuration : 0; 1514 1515 return self._execFilter('_getDelay', delay, arguments); 1516 }, 1517 1518 /** 1519 * Parse MultiMix Arguments 1520 * @since 2.0.0 1521 * @param {array} args 1522 * @return {object} output 1523 */ 1524 1525 _parseMultiMixArgs: function(args){ 1526 var self = this, 1527 output = { 1528 command: null, 1529 animate: self.animation.enable, 1530 callback: null 1531 }; 1532 1533 for(var i = 0; i < args.length; i++){ 1534 var arg = args[i]; 1535 1536 if(arg !== null){ 1537 if(typeof arg === 'object' || typeof arg === 'string'){ 1538 output.command = arg; 1539 } else if(typeof arg === 'boolean'){ 1540 output.animate = arg; 1541 } else if(typeof arg === 'function'){ 1542 output.callback = arg; 1543 } 1544 } 1545 } 1546 1547 return self._execFilter('_parseMultiMixArgs', output, arguments); 1548 }, 1549 1550 /** 1551 * Parse Insert Arguments 1552 * @since 2.0.0 1553 * @param {array} args 1554 * @return {object} output 1555 */ 1556 1557 _parseInsertArgs: function(args){ 1558 var self = this, 1559 output = { 1560 index: 0, 1561 $object: $(), 1562 multiMix: {filter: self._state.activeFilter}, 1563 callback: null 1564 }; 1565 1566 for(var i = 0; i < args.length; i++){ 1567 var arg = args[i]; 1568 1569 if(typeof arg === 'number'){ 1570 output.index = arg; 1571 } else if(typeof arg === 'object' && arg instanceof $){ 1572 output.$object = arg; 1573 } else if(typeof arg === 'object' && self._helpers._isElement(arg)){ 1574 output.$object = $(arg); 1575 } else if(typeof arg === 'object' && arg !== null){ 1576 output.multiMix = arg; 1577 } else if(typeof arg === 'boolean' && !arg){ 1578 output.multiMix = false; 1579 } else if(typeof arg === 'function'){ 1580 output.callback = arg; 1581 } 1582 } 1583 1584 return self._execFilter('_parseInsertArgs', output, arguments); 1585 }, 1586 1587 /** 1588 * Execute Action 1589 * @since 2.0.0 1590 * @param {string} methodName 1591 * @param {boolean} isPost 1592 * @param {array} args 1593 */ 1594 1595 _execAction: function(methodName, isPost, args){ 1596 var self = this, 1597 context = isPost ? 'post' : 'pre'; 1598 1599 if(!self._actions.isEmptyObject && self._actions.hasOwnProperty(methodName)){ 1600 for(var key in self._actions[methodName][context]){ 1601 self._actions[methodName][context][key].call(self, args); 1602 } 1603 } 1604 }, 1605 1606 /** 1607 * Execute Filter 1608 * @since 2.0.0 1609 * @param {string} methodName 1610 * @param {mixed} value 1611 * @return {mixed} value 1612 */ 1613 1614 _execFilter: function(methodName, value, args){ 1615 var self = this; 1616 1617 if(!self._filters.isEmptyObject && self._filters.hasOwnProperty(methodName)){ 1618 for(var key in self._filters[methodName]){ 1619 return self._filters[methodName][key].call(self, args); 1620 } 1621 } else { 1622 return value; 1623 } 1624 }, 1625 1626 /* Helpers 1627 ---------------------------------------------------------------------- */ 1628 1629 _helpers: { 1630 1631 /** 1632 * CamelCase 1633 * @since 2.0.0 1634 * @param {string} 1635 * @return {string} 1636 */ 1637 1638 _camelCase: function(string){ 1639 return string.replace(/-([a-z])/g, function(g){ 1640 return g[1].toUpperCase(); 1641 }); 1642 }, 1643 1644 /** 1645 * Is Element 1646 * @since 2.1.3 1647 * @param {object} element to test 1648 * @return {boolean} 1649 */ 1650 1651 _isElement: function(el){ 1652 if(window.HTMLElement){ 1653 return el instanceof HTMLElement; 1654 } else { 1655 return ( 1656 el !== null && 1657 el.nodeType === 1 && 1658 el.nodeName === 'string' 1659 ); 1660 } 1661 } 1662 }, 1663 1664 /* Public Methods 1665 ---------------------------------------------------------------------- */ 1666 1667 /** 1668 * Is Mixing 1669 * @since 2.0.0 1670 * @return {boolean} 1671 */ 1672 1673 isMixing: function(){ 1674 var self = this; 1675 1676 return self._execFilter('isMixing', self._mixing); 1677 }, 1678 1679 /** 1680 * Filter (public) 1681 * @since 2.0.0 1682 * @param {array} arguments 1683 */ 1684 1685 filter: function(){ 1686 var self = this, 1687 args = self._parseMultiMixArgs(arguments); 1688 1689 self._clicking && (self._toggleString = ''); 1690 1691 self.multiMix({filter: args.command}, args.animate, args.callback); 1692 }, 1693 1694 /** 1695 * Sort (public) 1696 * @since 2.0.0 1697 * @param {array} arguments 1698 */ 1699 1700 sort: function(){ 1701 var self = this, 1702 args = self._parseMultiMixArgs(arguments); 1703 1704 self.multiMix({sort: args.command}, args.animate, args.callback); 1705 }, 1706 1707 /** 1708 * Change Layout (public) 1709 * @since 2.0.0 1710 * @param {array} arguments 1711 */ 1712 1713 changeLayout: function(){ 1714 var self = this, 1715 args = self._parseMultiMixArgs(arguments); 1716 1717 self.multiMix({changeLayout: args.command}, args.animate, args.callback); 1718 }, 1719 1720 /** 1721 * MultiMix 1722 * @since 2.0.0 1723 * @param {array} arguments 1724 */ 1725 1726 multiMix: function(){ 1727 var self = this, 1728 args = self._parseMultiMixArgs(arguments); 1729 1730 self._execAction('multiMix', 0, arguments); 1731 1732 if(!self._mixing){ 1733 if(self.controls.enable && !self._clicking){ 1734 self.controls.toggleFilterButtons && self._buildToggleArray(); 1735 self._updateControls(args.command, self.controls.toggleFilterButtons); 1736 } 1737 1738 (self._queue.length < 2) && (self._clicking = false); 1739 1740 delete self.callbacks._user; 1741 if(args.callback) self.callbacks._user = args.callback; 1742 1743 var sort = args.command.sort, 1744 filter = args.command.filter, 1745 changeLayout = args.command.changeLayout; 1746 1747 self._refresh(); 1748 1749 if(sort){ 1750 self._newSort = self._parseSort(sort); 1751 self._newSortString = sort; 1752 1753 self._sorting = true; 1754 self._sort(); 1755 } 1756 1757 if(filter !== undf){ 1758 filter = (filter === 'all') ? self.selectors.target : filter; 1759
1760 self._activeFilter = filter; 1761 } 1762 1763 self._filter(); 1764 1765 if(changeLayout){ 1766 self._newDisplay = (typeof changeLayout === 'string') ? changeLayout : changeLayout.display || self.layout.display; 1767 self._newClass = changeLayout.containerClass || ''; 1768 1769 if( 1770 self._newDisplay !== self.layout.display || 1771 self._newClass !== self.layout.containerClass 1772 ){ 1773 self._changingLayout = true; 1774 1775 self._changingClass = (self._newClass !== self.layout.containerClass); 1776 self._changingDisplay = (self._newDisplay !== self.layout.display); 1777 } 1778 } 1779 1780 self._$targets.css(self._brake); 1781 1782 self._goMix(args.animate ^ self.animation.enable ? args.animate : self.animation.enable); 1783 1784 self._execAction('multiMix', 1, arguments); 1785 1786 } else { 1787 if(self.animation.queue && self._queue.length < self.animation.queueLimit){ 1788 self._queue.push(arguments); 1789 1790 (self.controls.enable && !self._clicking) && self._updateControls(args.command); 1791 1792 self._execAction('multiMixQueue', 1, arguments); 1793 1794 } else { 1795 if(typeof self.callbacks.onMixBusy === 'function'){ 1796 self.callbacks.onMixBusy.call(self._domNode, self._state, self); 1797 } 1798 self._$container.trigger('mixBusy', [self._state, self]); 1799 1800 self._execAction('multiMixBusy', 1, arguments); 1801 } 1802 } 1803 }, 1804 1805 /** 1806 * Insert 1807 * @since 2.0.0 1808 * @param {array} arguments 1809 */ 1810 1811 insert: function(){ 1812 var self = this, 1813 args = self._parseInsertArgs(arguments), 1814 callback = (typeof args.callback === 'function') ? args.callback : null, 1815 frag = document.createDocumentFragment(), 1816 target = (function(){ 1817 self._refresh(); 1818 1819 if(self._$targets.length){ 1820 return (args.index < self._$targets.length || !self._$targets.length) ? 1821 self._$targets[args.index] : 1822 self._$targets[self._$targets.length-1].nextElementSibling; 1823 } else { 1824 return self._$parent[0].children[0]; 1825 } 1826 })(); 1827 1828 self._execAction('insert', 0, arguments); 1829 1830 if(args.$object){ 1831 for(var i = 0; i < args.$object.length; i++){ 1832 var el = args.$object[i]; 1833 1834 frag.appendChild(el); 1835 frag.appendChild(document.createTextNode(' ')); 1836 } 1837 1838 self._$parent[0].insertBefore(frag, target); 1839 } 1840 1841 self._execAction('insert', 1, arguments); 1842 1843 if(typeof args.multiMix === 'object'){ 1844 self.multiMix(args.multiMix, callback); 1845 } 1846 }, 1847 1848 /** 1849 * Prepend 1850 * @since 2.0.0 1851 * @param {array} arguments 1852 */ 1853 1854 prepend: function(){ 1855 var self = this, 1856 args = self._parseInsertArgs(arguments); 1857 1858 self.insert(0, args.$object, args.multiMix, args.callback); 1859 }, 1860 1861 /** 1862 * Append 1863 * @since 2.0.0 1864 * @param {array} arguments 1865 */ 1866 1867 append: function(){ 1868 var self = this, 1869 args = self._parseInsertArgs(arguments); 1870 1871 self.insert(self._state.totalTargets, args.$object, args.multiMix, args.callback); 1872 }, 1873 1874 /** 1875 * Get Option 1876 * @since 2.0.0 1877 * @param {string} string 1878 * @return {mixed} value 1879 */ 1880 1881 getOption: function(string){ 1882 var self = this, 1883 getProperty = function(obj, prop){ 1884 var parts = prop.split('.'), 1885 last = parts.pop(), 1886 l = parts.length, 1887 i = 1, 1888 current = parts[0] || prop; 1889 1890 while((obj = obj[current]) && i < l){ 1891 current = parts[i]; 1892 i++; 1893 } 1894 1895 if(obj !== undf){ 1896 return obj[last] !== undf ? obj[last] : obj; 1897 } 1898 }; 1899 1900 return string ? self._execFilter('getOption', getProperty(self, string), arguments) : self; 1901 }, 1902 1903 /** 1904 * Set Options 1905 * @since 2.0.0 1906 * @param {object} config 1907 */ 1908 1909 setOptions: function(config){ 1910 var self = this; 1911 1912 self._execAction('setOptions', 0, arguments); 1913 1914 typeof config === 'object' && $.extend(true, self, config); 1915 1916 self._execAction('setOptions', 1, arguments); 1917 }, 1918 1919 /** 1920 * Get State 1921 * @since 2.0.0 1922 * @return {object} state 1923 */ 1924 1925 getState: function(){ 1926 var self = this; 1927 1928 return self._execFilter('getState', self._state, self); 1929 }, 1930 1931 /** 1932 * Force Refresh 1933 * @since 2.1.2 1934 */ 1935 1936 forceRefresh: function(){ 1937 var self = this; 1938 1939 self._refresh(false, true); 1940 }, 1941 1942 /** 1943 * Destroy 1944 * @since 2.0.0 1945 * @param {boolean} hideAll 1946 */ 1947 1948 destroy: function(hideAll){ 1949 var self = this; 1950 1951 self._execAction('destroy', 0, arguments); 1952 1953 self._$body 1954 .add($(self.selectors.sort)) 1955 .add($(self.selectors.filter)) 1956 .off('.mixItUp'); 1957 1958 for(var i = 0; i < self._$targets.length; i++){ 1959 var target = self._$targets[i]; 1960 1961 hideAll && (target.style.display = ''); 1962 1963 delete target.mixParent; 1964 } 1965 1966 self._execAction('destroy', 1, arguments); 1967 1968 delete $.MixItUp.prototype._instances[self._id]; 1969 } 1970 1971 }; 1972 1973 /* jQuery Methods 1974 ---------------------------------------------------------------------- */ 1975 1976 /** 1977 * jQuery .mixItUp() method 1978 * @since 2.0.0 1979 * @extends $.fn 1980 */ 1981 1982 $.fn.mixItUp = function(){ 1983 var args = arguments, 1984 dataReturn = [], 1985 eachReturn, 1986 _instantiate = function(domNode, settings){ 1987 var instance = new $.MixItUp(), 1988 rand = function(){ 1989 return ('00000'+(Math.random()*16777216<<0).toString(16)).substr(-6).toUpperCase(); 1990 }; 1991 1992 instance._execAction('_instantiate', 0, arguments); 1993 1994 domNode.id = !domNode.id ? 'MixItUp'+rand() : domNode.id; 1995 1996 if(!instance._instances[domNode.id]){ 1997 instance._instances[domNode.id] = instance; 1998 instance._init(domNode, settings); 1999 } 2000 2001 instance._execAction('_instantiate', 1, arguments); 2002 }; 2003 2004 eachReturn = this.each(function(){ 2005 if(args && typeof args[0] === 'string'){ 2006 var instance = $.MixItUp.prototype._instances[this.id]; 2007 if(args[0] == 'isLoaded'){ 2008 dataReturn.push(instance ? true : false); 2009 } else { 2010 var data = instance[args[0]](args[1], args[2], args[3]); 2011 if(data !== undf)dataReturn.push(data); 2012 } 2013 } else { 2014 _instantiate(this, args[0]); 2015 } 2016 }); 2017 2018 if(dataReturn.length){ 2019 return dataReturn.length > 1 ? dataReturn : dataReturn[0]; 2020 } else { 2021 return eachReturn; 2022 } 2023 }; 2024 2025 /** 2026 * jQuery .removeStyle() method 2027 * @since 2.0.0 2028 * @extends $.fn 2029 */ 2030 2031 $.fn.removeStyle = function(style, prefix){ 2032 prefix = prefix ? prefix : ''; 2033 2034 return this.each(function(){ 2035 var el = this, 2036 styles = style.split(' '); 2037 2038 for(var i = 0; i < styles.length; i++){ 2039 for(var j = 0; j < 2; j++){ 2040 var prop = j ? styles[i] : prefix+styles[i]; 2041 if( 2042 el.style[prop] !== undf && 2043 typeof el.style[prop] !== 'unknown' && 2044 el.style[prop].length > 0 2045 ){ 2046 el.style[prop] = ''; 2047 } 2048 if(!prefix)break; 2049 } 2050 } 2051 2052 if(el.attributes && el.attributes.style && el.attributes.style !== undf && el.attributes.style.nodeValue === ''){ 2053 el.attributes.removeNamedItem('style'); 2054 } 2055 }); 2056 }; 2057 2058})(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.