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