1/* ---------------------------------------------------------- 2 * Plugins 3 * ---------------------------------------------------------- */ 4 5(function(window, $) { 6 'use strict'; 7 var counter = 0, 8 $headCache = $('head'), 9 oldBigText = window.BigText, 10 oldjQueryMethod = $.fn.bigtext, 11 BigText = { 12 DEBUG_MODE: false, 13 DEFAULT_MIN_FONT_SIZE_PX: null, 14 DEFAULT_MAX_FONT_SIZE_PX: 528, 15 GLOBAL_STYLE_ID: 'bigtext-style', 16 STYLE_ID: 'bigtext-id', 17 LINE_CLASS_PREFIX: 'bigtext-line', 18 EXEMPT_CLASS: 'bigtext-exempt', 19 noConflict: function(restore) 20 { 21 if(restore) { 22 $.fn.bigtext = oldjQueryMethod; 23 window.BigText = oldBigText; 24 } 25 return BigText; 26 }, 27 supports: { 28 wholeNumberFontSizeOnly: (function() { 29 if( !( 'getComputedStyle' in window ) ) { 30 return true; 31 } 32 var test = $('<div/>').css({ 33 position: 'absolute', 34 'font-size': '14.1px' 35 }).insertBefore( $('script').eq(0) ), 36 computedStyle = window.getComputedStyle( test[0], null ); 37 38 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 39 test.remove(); 40 return ret; 41 })() 42 }, 43 init: function() { 44 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 45 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 46 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 47 } 48 }, 49 bindResize: function(eventName, resizeFunction) { 50 var timeoutId; 51 $(window).unbind(eventName).bind(eventName, function() { 52 if( timeoutId ) { 53 clearTimeout( timeoutId ); 54 } 55 timeoutId = setTimeout( resizeFunction, 300 ); 56 }); 57 }, 58 getStyleId: function(id) 59 { 60 return BigText.STYLE_ID + '-' + id; 61 }, 62 generateStyleTag: function(id, css) 63 { 64 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 65 }, 66 clearCss: function(id) 67 { 68 var styleId = BigText.getStyleId(id); 69 $('#' + styleId).remove(); 70 }, 71 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 72 { 73 var css = []; 74 75 BigText.clearCss(id); 76 77 for(var j=0, k=linesFontSizes.length; j<k; j++) { 78 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 79 (minFontSizes[j] ? ' white-space: normal;' : '') + 80 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 81 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 82 '}'); 83 } 84 85 return BigText.generateStyleTag(BigText.getStyleId(id), css); 86 }, 87 jQueryMethod: function(options) 88 { 89 BigText.init(); 90 91 options = $.extend({ 92 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 93 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 94 childSelector: '', 95 resize: true 96 }, options || {}); 97 98 this.each(function() 99 { 100 var $t = $(this).addClass('bigtext'), 101 maxWidth = $t.width(), 102 id = $t.attr('id'), 103 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 104 105 if(!id) { 106 id = 'bigtext-id' + (counter++); 107 $t.attr('id', id); 108 } 109 110 if(options.resize) { 111 BigText.bindResize('resize.bigtext-event-' + id, function() 112 { 113 // TODO only call this if the width has changed. 114 BigText.jQueryMethod.call($('#' + id), options); 115 }); 116 } 117 118 BigText.clearCss(id); 119 120 $children.addClass(function(lineNumber, className) 121 { 122 // remove existing line classes. 123 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 124 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 125 }); 126 127 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 128 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 129 }); 130 131 return this.trigger('bigtext:complete'); 132 } 133 }; 134 135 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 136 { 137 var width; 138 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 139 $line.css(property, size + units); 140 141 width = $line.width(); 142 143 if(width >= maxWidth) { 144 145 $line.css(property, ''); 146 147 if(width === maxWidth) { 148 return { 149 match: 'exact', 150 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 151 }; 152 } 153 154 // Since this is an estimate, we calculate how far over the width we went with the new value. 155 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 156 // Otherwise, we revert to the underestimate. 157 var under = maxWidth - previousWidth, 158 over = width - maxWidth; 159 160 return { 161 match: 'estimate', 162 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 163 }; 164 } 165 166 return width; 167 } 168 169 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 170 { 171 var $c = $t.clone(true) 172 .addClass('bigtext-cloned') 173 .css({ 174 fontFamily: $t.css('font-family'), 175 textTransform: $t.css('text-transform'), 176 wordSpacing: $t.css('word-spacing'), 177 letterSpacing: $t.css('letter-spacing'), 178 position: 'absolute', 179 left: BigText.DEBUG_MODE ? 0 : -9999, 180 top: BigText.DEBUG_MODE ? 0 : -9999
181 }) 182 .appendTo(document.body); 183 184 // font-size isn't the only thing we can modify, we can also mess with: 185 // word-spacing and letter-spacing. WebKit does not respect subpixel 186 // letter-spacing, word-spacing, or font-size. 187 // TODO try -webkit-transform: scale() as a workaround. 188 var fontSizes = [], 189 wordSpacings = [], 190 minFontSizes = [], 191 ratios = []; 192 193 $children.css('float', 'left').each(function() { 194 var $line = $(this), 195 // TODO replace 8, 4 with a proportional size to the calculated font-size. 196 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 197 lineMax, 198 newFontSize; 199 200 if($line.hasClass(BigText.EXEMPT_CLASS)) { 201 fontSizes.push(null); 202 ratios.push(null); 203 minFontSizes.push(false); 204 return; 205 } 206 207 // TODO we can cache this ratio? 208 var autoGuessSubtraction = 32, // font size in px 209 currentFontSize = parseFloat($line.css('font-size')), 210 ratio = ( $line.width() / currentFontSize ).toFixed(6); 211 212 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 213 214 outer: for(var m=0, n=intervals.length; m<n; m++) { 215 inner: for(var j=1, k=10; j<=k; j++) { 216 if(newFontSize + j*intervals[m] > maxFontSize) { 217 newFontSize = maxFontSize; 218 break outer; 219 } 220 221 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 222 if(typeof lineMax !== 'number') { 223 newFontSize = lineMax.size; 224 225 if(lineMax.match === 'exact') { 226 break outer; 227 } 228 break inner; 229 } 230 } 231 } 232 233 ratios.push(maxWidth / newFontSize); 234 235 if(newFontSize > maxFontSize) { 236 fontSizes.push(maxFontSize); 237 minFontSizes.push(false); 238 } else if(!!minFontSize && newFontSize < minFontSize) { 239 fontSizes.push(minFontSize); 240 minFontSizes.push(true); 241 } else { 242 fontSizes.push(newFontSize); 243 minFontSizes.push(false); 244 } 245 }).each(function(lineNumber) { 246 var $line = $(this), 247 wordSpacing = 0, 248 interval = 1, 249 maxWordSpacing; 250 251 if($line.hasClass(BigText.EXEMPT_CLASS)) { 252 wordSpacings.push(null); 253 return; 254 } 255 256 // must re-use font-size, even though it was removed above. 257 $line.css('font-size', fontSizes[lineNumber] + 'px'); 258 259 for(var m=1, n=3; m<n; m+=interval) { 260 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 261 if(typeof maxWordSpacing !== 'number') { 262 wordSpacing = maxWordSpacing.size; 263 break; 264 } 265 } 266 267 $line.css('font-size', ''); 268 wordSpacings.push(wordSpacing); 269 }).removeAttr('style'); 270 271 if( !BigText.DEBUG_MODE ) { 272 $c.remove(); 273 } else { 274 $c.css({ 275 'background-color': 'rgba(255,255,255,.4)' 276 }); 277 } 278 279 return { 280 fontSizes: fontSizes, 281 wordSpacings: wordSpacings, 282 ratios: ratios, 283 minFontSizes: minFontSizes 284 }; 285 } 286 287 $.fn.bigtext = BigText.jQueryMethod; 288 window.BigText = BigText; 289 290})(this, jQuery); 291 292/*! 293 * Isotope PACKAGED v2.2.2 294 * 295 * Licensed GPLv3 for open source use 296 * or Isotope Commercial License for commercial use 297 * 298 * http://isotope.metafizzy.co 299 * Copyright 2015 Metafizzy 300 */ 301 302/** 303 * Bridget makes jQuery widgets 304 * v1.1.0 305 * MIT license 306 */ 307 308( function( window ) { 309 310 311 312// -------------------------- utils -------------------------- // 313 314var slice = Array.prototype.slice; 315 316function noop() {} 317 318// -------------------------- definition -------------------------- // 319 320function defineBridget( $ ) { 321 322// bail if no jQuery 323if ( !$ ) { 324 return; 325} 326 327// -------------------------- addOptionMethod -------------------------- // 328 329/** 330 * adds option method -> $().plugin('option', {...}) 331 * @param {Function} PluginClass - constructor class 332 */ 333function addOptionMethod( PluginClass ) { 334 // don't overwrite original option method 335 if ( PluginClass.prototype.option ) { 336 return; 337 } 338 339 // option setter 340 PluginClass.prototype.option = function( opts ) { 341 // bail out if not an object 342 if ( !$.isPlainObject( opts ) ){ 343 return; 344 } 345 this.options = $.extend( true, this.options, opts ); 346 }; 347} 348 349// -------------------------- plugin bridge -------------------------- // 350 351// helper function for logging errors 352// $.error breaks jQuery chaining 353var logError = typeof console === 'undefined' ? noop : 354 function( message ) { 355 console.error( message ); 356 }; 357 358/** 359 * jQuery plugin bridge, access methods like $elem.plugin('method') 360 * @param {String} namespace - plugin name 361 * @param {Function} PluginClass - constructor class 362 */ 363function bridge( namespace, PluginClass ) { 364 // add to jQuery fn namespace 365 $.fn[ namespace ] = function( options ) { 366 if ( typeof options === 'string' ) { 367 // call plugin method when first argument is a string 368 // get arguments for method 369 var args = slice.call( arguments, 1 ); 370 371 for ( var i=0, len = this.length; i < len; i++ ) { 372 var elem = this[i]; 373 var instance = $.data( elem, namespace ); 374 if ( !instance ) { 375 logError( "cannot call methods on " + namespace + " prior to initialization; " + 376 "attempted to call '" + options + "'" ); 377 continue; 378 } 379 if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { 380 logError( "no such method '" + options + "' for " + namespace + " instance" ); 381 continue; 382 } 383 384 // trigger method with arguments 385 var returnValue = instance[ options ].apply( instance, args ); 386 387 // break look and return first value if provided 388 if ( returnValue !== undefined ) { 389 return returnValue; 390 } 391 } 392 // return this if no return value 393 return this; 394 } else { 395 return this.each( function() { 396 var instance = $.data( this, namespace ); 397 if ( instance ) { 398 // apply options & init 399 instance.option( options ); 400 instance._init(); 401 } else { 402 // initialize new instance 403 instance = new PluginClass( this, options ); 404 $.data( this, namespace, instance ); 405 } 406 }); 407 } 408 }; 409 410} 411 412// -------------------------- bridget -------------------------- // 413 414/** 415 * converts a Prototypical class into a proper jQuery plugin 416 * the class must have a ._init method 417 * @param {String} namespace - plugin name, used in $().pluginName 418 * @param {Function} PluginClass - constructor class 419 */ 420$.bridget = function( namespace, PluginClass ) { 421 addOptionMethod( PluginClass ); 422 bridge( namespace, PluginClass ); 423}; 424 425return $.bridget; 426 427} 428 429// transport 430if ( typeof define === 'function' && define.amd ) { 431 // AMD 432 define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget ); 433} else if ( typeof exports === 'object' ) { 434 defineBridget( require('jquery') ); 435} else { 436 // get jquery from browser global 437 defineBridget( window.jQuery ); 438} 439 440})( window ); 441 442/*! 443 * eventie v1.0.6 444 * event binding helper 445 * eventie.bind( elem, 'click', myFn ) 446 * eventie.unbind( elem, 'click', myFn ) 447 * MIT license 448 */ 449 450/*jshint browser: true, undef: true, unused: true */ 451/*global define: false, module: false */ 452 453( function( window ) { 454 455 456 457var docElem = document.documentElement; 458 459var bind = function() {}; 460 461function getIEEvent( obj ) { 462 var event = window.event; 463 // add event.target 464 event.target = event.target || event.srcElement || obj; 465 return event; 466} 467 468if ( docElem.addEventListener ) { 469 bind = function( obj, type, fn ) { 470 obj.addEventListener( type, fn, false ); 471 }; 472} else if ( docElem.attachEvent ) { 473 bind = function( obj, type, fn ) { 474 obj[ type + fn ] = fn.handleEvent ? 475 function() { 476 var event = getIEEvent( obj ); 477 fn.handleEvent.call( fn, event ); 478 } : 479 function() { 480 var event = getIEEvent( obj ); 481 fn.call( obj, event ); 482 }; 483 obj.attachEvent( "on" + type, obj[ type + fn ] ); 484 }; 485} 486 487var unbind = function() {}; 488 489if ( docElem.removeEventListener ) { 490 unbind = function( obj, type, fn ) { 491 obj.removeEventListener( type, fn, false ); 492 }; 493} else if ( docElem.detachEvent ) { 494 unbind = function( obj, type, fn ) { 495 obj.detachEvent( "on" + type, obj[ type + fn ] ); 496 try { 497 delete obj[ type + fn ]; 498 } catch ( err ) { 499 // can't delete window object properties 500 obj[ type + fn ] = undefined; 501 } 502 }; 503} 504 505var eventie = { 506 bind: bind, 507 unbind: unbind 508}; 509 510// ----- module definition ----- // 511 512if ( typeof define === 'function' && define.amd ) { 513 // AMD 514 define( 'eventie/eventie',eventie ); 515} else if ( typeof exports === 'object' ) { 516 // CommonJS 517 module.exports = eventie; 518} else { 519 // browser global 520 window.eventie = eventie; 521} 522 523})( window ); 524 525/*! 526 * EventEmitter v4.2.11 - git.io/ee 527 * Unlicense - http://unlicense.org/ 528 * Oliver Caldwell - http://oli.me.uk/ 529 * @preserve 530 */ 531 532;(function () { 533 'use strict'; 534 535 /** 536 * Class for managing events. 537 * Can be extended to provide event functionality in other classes. 538 * 539 * @class EventEmitter Manages event registering and emitting. 540 */ 541 function EventEmitter() {} 542 543 // Shortcuts to improve speed and size 544 var proto = EventEmitter.prototype; 545 var exports = this; 546 var originalGlobalValue = exports.EventEmitter; 547 548 /** 549 * Finds the index of the listener for the event in its storage array. 550 * 551 * @param {Function[]} listeners Array of listeners to search through. 552 * @param {Function} listener Method to look for. 553 * @return {Number} Index of the specified listener, -1 if not found 554 * @api private 555 */ 556 function indexOfListener(listeners, listener) { 557 var i = listeners.length; 558 while (i--) { 559 if (listeners[i].listener === listener) { 560 return i; 561 } 562 } 563 564 return -1; 565 } 566 567 /** 568 * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 568-971
568writing of target method. 569 * 570 * @param {String} name The name of the target method. 571 * @return {Function} The aliased method 572 * @api private 573 */ 574 function alias(name) { 575 return function aliasClosure() { 576 return this[name].apply(this, arguments); 577 }; 578 } 579 580 /** 581 * Returns the listener array for the specified event. 582 * Will initialise the event object and listener arrays if required. 583 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. 584 * Each property in the object response is an array of listener functions. 585 * 586 * @param {String|RegExp} evt Name of the event to return the listeners from. 587 * @return {Function[]|Object} All listener functions for the event. 588 */ 589 proto.getListeners = function getListeners(evt) { 590 var events = this._getEvents(); 591 var response; 592 var key; 593 594 // Return a concatenated array of all matching events if 595 // the selector is a regular expression. 596 if (evt instanceof RegExp) { 597 response = {}; 598 for (key in events) { 599 if (events.hasOwnProperty(key) && evt.test(key)) { 600 response[key] = events[key]; 601 } 602 } 603 } 604 else { 605 response = events[evt] || (events[evt] = []); 606 } 607 608 return response; 609 }; 610 611 /** 612 * Takes a list of listener objects and flattens it into a list of listener functions. 613 * 614 * @param {Object[]} listeners Raw listener objects. 615 * @return {Function[]} Just the listener functions. 616 */ 617 proto.flattenListeners = function flattenListeners(listeners) { 618 var flatListeners = []; 619 var i; 620 621 for (i = 0; i < listeners.length; i += 1) { 622 flatListeners.push(listeners[i].listener); 623 } 624 625 return flatListeners; 626 }; 627 628 /** 629 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. 630 * 631 * @param {String|RegExp} evt Name of the event to return the listeners from. 632 * @return {Object} All listener functions for an event in an object. 633 */ 634 proto.getListenersAsObject = function getListenersAsObject(evt) { 635 var listeners = this.getListeners(evt); 636 var response; 637 638 if (listeners instanceof Array) { 639 response = {}; 640 response[evt] = listeners; 641 } 642 643 return response || listeners; 644 }; 645 646 /** 647 * Adds a listener function to the specified event. 648 * The listener will not be added if it is a duplicate. 649 * If the listener returns true then it will be removed after it is called. 650 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 651 * 652 * @param {String|RegExp} evt Name of the event to attach the listener to. 653 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 654 * @return {Object} Current instance of EventEmitter for chaining. 655 */ 656 proto.addListener = function addListener(evt, listener) { 657 var listeners = this.getListenersAsObject(evt); 658 var listenerIsWrapped = typeof listener === 'object'; 659 var key; 660 661 for (key in listeners) { 662 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 663 listeners[key].push(listenerIsWrapped ? listener : { 664 listener: listener, 665 once: false 666 }); 667 } 668 } 669 670 return this; 671 }; 672 673 /** 674 * Alias of addListener 675 */ 676 proto.on = alias('addListener'); 677 678 /** 679 * Semi-alias of addListener. It will add a listener that will be 680 * automatically removed after its first execution. 681 * 682 * @param {String|RegExp} evt Name of the event to attach the listener to. 683 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 684 * @return {Object} Current instance of EventEmitter for chaining. 685 */ 686 proto.addOnceListener = function addOnceListener(evt, listener) { 687 return this.addListener(evt, { 688 listener: listener, 689 once: true 690 }); 691 }; 692 693 /** 694 * Alias of addOnceListener. 695 */ 696 proto.once = alias('addOnceListener'); 697 698 /** 699 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. 700 * You need to tell it what event names should be matched by a regex. 701 * 702 * @param {String} evt Name of the event to create. 703 * @return {Object} Current instance of EventEmitter for chaining. 704 */ 705 proto.defineEvent = function defineEvent(evt) { 706 this.getListeners(evt); 707 return this; 708 }; 709 710 /** 711 * Uses defineEvent to define multiple events. 712 * 713 * @param {String[]} evts An array of event names to define. 714 * @return {Object} Current instance of EventEmitter for chaining. 715 */ 716 proto.defineEvents = function defineEvents(evts) { 717 for (var i = 0; i < evts.length; i += 1) { 718 this.defineEvent(evts[i]); 719 } 720 return this; 721 }; 722 723 /** 724 * Removes a listener function from the specified event. 725 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 726 * 727 * @param {String|RegExp} evt Name of the event to remove the listener from. 728 * @param {Function} listener Method to remove from the event. 729 * @return {Object} Current instance of EventEmitter for chaining. 730 */ 731 proto.removeListener = function removeListener(evt, listener) { 732 var listeners = this.getListenersAsObject(evt); 733 var index; 734 var key; 735 736 for (key in listeners) { 737 if (listeners.hasOwnProperty(key)) { 738 index = indexOfListener(listeners[key], listener); 739 740 if (index !== -1) { 741 listeners[key].splice(index, 1); 742 } 743 } 744 } 745 746 return this; 747 }; 748 749 /** 750 * Alias of removeListener 751 */ 752 proto.off = alias('removeListener'); 753 754 /** 755 * Adds listeners in bulk using the manipulateListeners method. 756 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. 757 * You can also pass it a regular expression to add the array of listeners to all events that match it. 758 * Yeah, this function does quite a bit. That's probably a bad thing. 759 * 760 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. 761 * @param {Function[]} [listeners] An optional array of listener functions to add. 762 * @return {Object} Current instance of EventEmitter for chaining. 763 */ 764 proto.addListeners = function addListeners(evt, listeners) { 765 // Pass through to manipulateListeners 766 return this.manipulateListeners(false, evt, listeners); 767 }; 768 769 /** 770 * Removes listeners in bulk using the manipulateListeners method. 771 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 772 * You can also pass it an event name and an array of listeners to be removed. 773 * You can also pass it a regular expression to remove the listeners from all events that match it. 774 * 775 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. 776 * @param {Function[]} [listeners] An optional array of listener functions to remove. 777 * @return {Object} Current instance of EventEmitter for chaining. 778 */ 779 proto.removeListeners = function removeListeners(evt, listeners) { 780 // Pass through to manipulateListeners 781 return this.manipulateListeners(true, evt, listeners); 782 }; 783 784 /** 785 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. 786 * The first argument will determine if the listeners are removed (true) or added (false). 787 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 788 * You can also pass it an event name and an array of listeners to be added/removed. 789 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 790 * 791 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 792 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. 793 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 794 * @return {Object} Current instance of EventEmitter for chaining. 795 */ 796 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 797 var i; 798 var value; 799 var single = remove ? this.removeListener : this.addListener; 800 var multiple = remove ? this.removeListeners : this.addListeners; 801 802 // If evt is an object then pass each of its properties to this method 803 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 804 for (i in evt) { 805 if (evt.hasOwnProperty(i) && (value = evt[i])) { 806 // Pass the single listener straight through to the singular method 807 if (typeof value === 'function') { 808 single.call(this, i, value); 809 } 810 else { 811 // Otherwise pass back to the multiple function 812 multiple.call(this, i, value); 813 } 814 } 815 } 816 } 817 else { 818 // So evt must be a string 819 // And listeners must be an array of listeners 820 // Loop over it and pass each one to the multiple method 821 i = listeners.length; 822 while (i--) { 823 single.call(this, evt, listeners[i]); 824 } 825 } 826 827 return this; 828 }; 829 830 /** 831 * Removes all listeners from a specified event. 832 * If you do not specify an event then all listeners will be removed. 833 * That means every event will be emptied. 834 * You can also pass a regex to remove all events that match it. 835 * 836 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 837 * @return {Object} Current instance of EventEmitter for chaining. 838 */ 839 proto.removeEvent = function removeEvent(evt) { 840 var type = typeof evt; 841 var events = this._getEvents(); 842 var key; 843 844 // Remove different things depending on the state of evt 845 if (type === 'string') { 846 // Remove all listeners for the specified event 847 delete events[evt]; 848 } 849 else if (evt instanceof RegExp) { 850 // Remove all events matching the regex. 851 for (key in events) { 852 if (events.hasOwnProperty(key) && evt.test(key)) { 853 delete events[key]; 854 } 855 } 856 } 857 else { 858 // Remove all listeners in all events 859 delete this._events; 860 } 861 862 return this; 863 }; 864 865 /** 866 * Alias of removeEvent. 867 * 868 * Added to mirror the node API. 869 */ 870 proto.removeAllListeners = alias('removeEvent'); 871 872 /** 873 * Emits an event of your choice. 874 * When emitted, every listener attached to that event will be executed. 875 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 876 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. 877 * So they will not arrive within the array on the other side, they will be separate. 878 * You can also pass a regular expression to emit to all events that match it. 879 * 880 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 881 * @param {Array} [args] Optional array of arguments to be passed to each listener. 882 * @return {Object} Current instance of EventEmitter for chaining. 883 */ 884 proto.emitEvent = function emitEvent(evt, args) { 885 var listeners = this.getListenersAsObject(evt); 886 var listener; 887 var i; 888 var key; 889 var response; 890 891 for (key in listeners) { 892 if (listeners.hasOwnProperty(key)) { 893 i = listeners[key].length; 894 895 while (i--) { 896 // If the listener returns true then it shall be removed from the event 897 // The function is executed either with a basic call or an apply if there is an args array 898 listener = listeners[key][i]; 899 900 if (listener.once === true) { 901 this.removeListener(evt, listener.listener); 902 } 903 904 response = listener.listener.apply(this, args || []); 905 906 if (response === this._getOnceReturnValue()) { 907 this.removeListener(evt, listener.listener); 908 } 909 } 910 } 911 } 912 913 return this; 914 }; 915 916 /** 917 * Alias of emitEvent 918 */ 919 proto.trigger = alias('emitEvent'); 920 921 /** 922 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. 923 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 924 * 925 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 926 * @param {...*} Optional additional arguments to be passed to each listener. 927 * @return {Object} Current instance of EventEmitter for chaining. 928 */ 929 proto.emit = function emit(evt) { 930 var args = Array.prototype.slice.call(arguments, 1); 931 return this.emitEvent(evt, args); 932 }; 933 934 /** 935 * Sets the current value to check against when executing listeners. If a 936 * listeners return value matches the one set here then it will be removed 937 * after execution. This value defaults to true. 938 * 939 * @param {*} value The new value to check for when executing listeners. 940 * @return {Object} Current instance of EventEmitter for chaining. 941 */ 942 proto.setOnceReturnValue = function setOnceReturnValue(value) { 943 this._onceReturnValue = value; 944 return this; 945 }; 946 947 /** 948 * Fetches the current value to check against when executing listeners. If 949 * the listeners return value matches this one then it should be removed 950 * automatically. It will return true by default. 951 * 952 * @return {*|Boolean} The current value to check for or the default, true. 953 * @api private 954 */ 955 proto._getOnceReturnValue = function _getOnceReturnValue() { 956 if (this.hasOwnProperty('_onceReturnValue')) { 957 return this._onceReturnValue; 958 } 959 else { 960 return true; 961 } 962 }; 963 964 /** 965 * Fetches the events object and creates one if required. 966 * 967 * @return {Object} The events storage object. 968 * @api private 969 */ 970 proto._getEvents = function _getEvents() { 971 return this._events || (this
971._events = {}); 972 }; 973 974 /** 975 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. 976 * 977 * @return {Function} Non conflicting EventEmitter class. 978 */ 979 EventEmitter.noConflict = function noConflict() { 980 exports.EventEmitter = originalGlobalValue; 981 return EventEmitter; 982 }; 983 984 // Expose the class either via AMD, CommonJS or the global object 985 if (typeof define === 'function' && define.amd) { 986 define('eventEmitter/EventEmitter',[],function () { 987 return EventEmitter; 988 }); 989 } 990 else if (typeof module === 'object' && module.exports){ 991 module.exports = EventEmitter; 992 } 993 else { 994 exports.EventEmitter = EventEmitter; 995 } 996}.call(this)); 997 998/*! 999 * getStyleProperty v1.0.4 1000 * original by kangax 1001 * http://perfectionkills.com/feature-testing-css-properties/ 1002 * MIT license 1003 */ 1004 1005/*jshint browser: true, strict: true, undef: true */ 1006/*global define: false, exports: false, module: false */ 1007 1008( function( window ) { 1009 1010 1011 1012var prefixes = 'Webkit Moz ms Ms O'.split(' '); 1013var docElemStyle = document.documentElement.style; 1014 1015function getStyleProperty( propName ) { 1016 if ( !propName ) { 1017 return; 1018 } 1019 1020 // test standard property first 1021 if ( typeof docElemStyle[ propName ] === 'string' ) { 1022 return propName; 1023 } 1024 1025 // capitalize 1026 propName = propName.charAt(0).toUpperCase() + propName.slice(1); 1027 1028 // test vendor specific properties 1029 var prefixed; 1030 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1031 prefixed = prefixes[i] + propName; 1032 if ( typeof docElemStyle[ prefixed ] === 'string' ) { 1033 return prefixed; 1034 } 1035 } 1036} 1037 1038// transport 1039if ( typeof define === 'function' && define.amd ) { 1040 // AMD 1041 define( 'get-style-property/get-style-property',[],function() { 1042 return getStyleProperty; 1043 }); 1044} else if ( typeof exports === 'object' ) { 1045 // CommonJS for Component 1046 module.exports = getStyleProperty; 1047} else { 1048 // browser global 1049 window.getStyleProperty = getStyleProperty; 1050} 1051 1052})( window ); 1053 1054/*! 1055 * getSize v1.2.2 1056 * measure size of elements 1057 * MIT license 1058 */ 1059 1060/*jshint browser: true, strict: true, undef: true, unused: true */ 1061/*global define: false, exports: false, require: false, module: false, console: false */ 1062 1063( function( window, undefined ) { 1064 1065 1066 1067// -------------------------- helpers -------------------------- // 1068 1069// get a number from a string, not a percentage 1070function getStyleSize( value ) { 1071 var num = parseFloat( value ); 1072 // not a percent like '100%', and a number 1073 var isValid = value.indexOf('%') === -1 && !isNaN( num ); 1074 return isValid && num; 1075} 1076 1077function noop() {} 1078 1079var logError = typeof console === 'undefined' ? noop : 1080 function( message ) { 1081 console.error( message ); 1082 }; 1083 1084// -------------------------- measurements -------------------------- // 1085 1086var measurements = [ 1087 'paddingLeft', 1088 'paddingRight', 1089 'paddingTop', 1090 'paddingBottom', 1091 'marginLeft', 1092 'marginRight', 1093 'marginTop', 1094 'marginBottom', 1095 'borderLeftWidth', 1096 'borderRightWidth', 1097 'borderTopWidth', 1098 'borderBottomWidth' 1099]; 1100 1101function getZeroSize() { 1102 var size = { 1103 width: 0, 1104 height: 0, 1105 innerWidth: 0, 1106 innerHeight: 0, 1107 outerWidth: 0, 1108 outerHeight: 0 1109 }; 1110 for ( var i=0, len = measurements.length; i < len; i++ ) { 1111 var measurement = measurements[i]; 1112 size[ measurement ] = 0; 1113 } 1114 return size; 1115} 1116 1117 1118 1119function defineGetSize( getStyleProperty ) { 1120 1121// -------------------------- setup -------------------------- // 1122 1123var isSetup = false; 1124 1125var getStyle, boxSizingProp, isBoxSizeOuter; 1126 1127/** 1128 * setup vars and functions 1129 * do it on initial getSize(), rather than on script load 1130 * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397 1131 */ 1132function setup() { 1133 // setup once 1134 if ( isSetup ) { 1135 return; 1136 } 1137 isSetup = true; 1138 1139 var getComputedStyle = window.getComputedStyle; 1140 getStyle = ( function() { 1141 var getStyleFn = getComputedStyle ? 1142 function( elem ) { 1143 return getComputedStyle( elem, null ); 1144 } : 1145 function( elem ) { 1146 return elem.currentStyle; 1147 }; 1148 1149 return function getStyle( elem ) { 1150 var style = getStyleFn( elem ); 1151 if ( !style ) { 1152 logError( 'Style returned ' + style + 1153 '. Are you running this code in a hidden iframe on Firefox? ' + 1154 'See http://bit.ly/getsizebug1' ); 1155 } 1156 return style; 1157 }; 1158 })(); 1159 1160 // -------------------------- box sizing -------------------------- // 1161 1162 boxSizingProp = getStyleProperty('boxSizing'); 1163 1164 /** 1165 * WebKit measures the outer-width on style.width on border-box elems 1166 * IE & Firefox measures the inner-width 1167 */ 1168 if ( boxSizingProp ) { 1169 var div = document.createElement('div'); 1170 div.style.width = '200px'; 1171 div.style.padding = '1px 2px 3px 4px'; 1172 div.style.borderStyle = 'solid'; 1173 div.style.borderWidth = '1px 2px 3px 4px'; 1174 div.style[ boxSizingProp ] = 'border-box'; 1175 1176 var body = document.body || document.documentElement; 1177 body.appendChild( div ); 1178 var style = getStyle( div ); 1179 1180 isBoxSizeOuter = getStyleSize( style.width ) === 200; 1181 body.removeChild( div ); 1182 } 1183 1184} 1185 1186// -------------------------- getSize -------------------------- // 1187 1188function getSize( elem ) { 1189 setup(); 1190 1191 // use querySeletor if elem is string 1192 if ( typeof elem === 'string' ) { 1193 elem = document.querySelector( elem ); 1194 } 1195 1196 // do not proceed on non-objects 1197 if ( !elem || typeof elem !== 'object' || !elem.nodeType ) { 1198 return; 1199 } 1200 1201 var style = getStyle( elem ); 1202 1203 // if hidden, everything is 0 1204 if ( style.display === 'none' ) { 1205 return getZeroSize(); 1206 } 1207 1208 var size = {}; 1209 size.width = elem.offsetWidth; 1210 size.height = elem.offsetHeight; 1211 1212 var isBorderBox = size.isBorderBox = !!( boxSizingProp && 1213 style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' ); 1214 1215 // get all measurements 1216 for ( var i=0, len = measurements.length; i < len; i++ ) { 1217 var measurement = measurements[i]; 1218 var value = style[ measurement ]; 1219 value = mungeNonPixel( elem, value ); 1220 var num = parseFloat( value ); 1221 // any 'auto', 'medium' value will be 0 1222 size[ measurement ] = !isNaN( num ) ? num : 0; 1223 } 1224 1225 var paddingWidth = size.paddingLeft + size.paddingRight; 1226 var paddingHeight = size.paddingTop + size.paddingBottom; 1227 var marginWidth = size.marginLeft + size.marginRight; 1228 var marginHeight = size.marginTop + size.marginBottom; 1229 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 1230 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 1231 1232 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 1233 1234 // overwrite width and height if we can get it from style 1235 var styleWidth = getStyleSize( style.width ); 1236 if ( styleWidth !== false ) { 1237 size.width = styleWidth + 1238 // add padding and border unless it's already including it 1239 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 1240 } 1241 1242 var styleHeight = getStyleSize( style.height ); 1243 if ( styleHeight !== false ) { 1244 size.height = styleHeight + 1245 // add padding and border unless it's already including it 1246 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 1247 } 1248 1249 size.innerWidth = size.width - ( paddingWidth + borderWidth );
1250 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 1251 1252 size.outerWidth = size.width + marginWidth; 1253 size.outerHeight = size.height + marginHeight; 1254 1255 return size; 1256} 1257 1258// IE8 returns percent values, not pixels 1259// taken from jQuery's curCSS 1260function mungeNonPixel( elem, value ) { 1261 // IE8 and has percent value 1262 if ( window.getComputedStyle || value.indexOf('%') === -1 ) { 1263 return value; 1264 } 1265 var style = elem.style; 1266 // Remember the original values 1267 var left = style.left; 1268 var rs = elem.runtimeStyle; 1269 var rsLeft = rs && rs.left; 1270 1271 // Put in the new values to get a computed value out 1272 if ( rsLeft ) { 1273 rs.left = elem.currentStyle.left; 1274 } 1275 style.left = value; 1276 value = style.pixelLeft; 1277 1278 // Revert the changed values 1279 style.left = left; 1280 if ( rsLeft ) { 1281 rs.left = rsLeft; 1282 } 1283 1284 return value; 1285} 1286 1287return getSize; 1288 1289} 1290 1291// transport 1292if ( typeof define === 'function' && define.amd ) { 1293 // AMD for RequireJS 1294 define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize ); 1295} else if ( typeof exports === 'object' ) { 1296 // CommonJS for Component 1297 module.exports = defineGetSize( require('desandro-get-style-property') ); 1298} else { 1299 // browser global 1300 window.getSize = defineGetSize( window.getStyleProperty ); 1301} 1302 1303})( window ); 1304 1305/*! 1306 * docReady v1.0.4 1307 * Cross browser DOMContentLoaded event emitter 1308 * MIT license 1309 */ 1310 1311/*jshint browser: true, strict: true, undef: true, unused: true*/ 1312/*global define: false, require: false, module: false */ 1313 1314( function( window ) { 1315 1316 1317 1318var document = window.document; 1319// collection of functions to be triggered on ready 1320var queue = []; 1321 1322function docReady( fn ) { 1323 // throw out non-functions 1324 if ( typeof fn !== 'function' ) { 1325 return; 1326 } 1327 1328 if ( docReady.isReady ) { 1329 // ready now, hit it 1330 fn(); 1331 } else { 1332 // queue function when ready 1333 queue.push( fn ); 1334 } 1335} 1336 1337docReady.isReady = false; 1338 1339// triggered on various doc ready events 1340function onReady( event ) { 1341 // bail if already triggered or IE8 document is not ready just yet 1342 var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete'; 1343 if ( docReady.isReady || isIE8NotReady ) { 1344 return; 1345 } 1346 1347 trigger(); 1348} 1349 1350function trigger() { 1351 docReady.isReady = true; 1352 // process queue 1353 for ( var i=0, len = queue.length; i < len; i++ ) { 1354 var fn = queue[i]; 1355 fn(); 1356 } 1357} 1358 1359function defineDocReady( eventie ) { 1360 // trigger ready if page is ready 1361 if ( document.readyState === 'complete' ) { 1362 trigger(); 1363 } else { 1364 // listen for events 1365 eventie.bind( document, 'DOMContentLoaded', onReady ); 1366 eventie.bind( document, 'readystatechange', onReady ); 1367 eventie.bind( window, 'load', onReady ); 1368 } 1369 1370 return docReady; 1371} 1372 1373// transport 1374if ( typeof define === 'function' && define.amd ) { 1375 // AMD 1376 define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady ); 1377} else if ( typeof exports === 'object' ) { 1378 module.exports = defineDocReady( require('eventie') ); 1379} else { 1380 // browser global 1381 window.docReady = defineDocReady( window.eventie ); 1382} 1383 1384})( window ); 1385 1386/** 1387 * matchesSelector v1.0.3 1388 * matchesSelector( element, '.selector' ) 1389 * MIT license 1390 */ 1391 1392/*jshint browser: true, strict: true, undef: true, unused: true */ 1393/*global define: false, module: false */ 1394 1395( function( ElemProto ) { 1396 1397 'use strict'; 1398 1399 var matchesMethod = ( function() { 1400 // check for the standard method name first 1401 if ( ElemProto.matches ) { 1402 return 'matches'; 1403 } 1404 // check un-prefixed 1405 if ( ElemProto.matchesSelector ) { 1406 return 'matchesSelector'; 1407 } 1408 // check vendor prefixes 1409 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 1410 1411 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1412 var prefix = prefixes[i]; 1413 var method = prefix + 'MatchesSelector'; 1414 if ( ElemProto[ method ] ) { 1415 return method; 1416 } 1417 } 1418 })(); 1419 1420 // ----- match ----- // 1421 1422 function match( elem, selector ) { 1423 return elem[ matchesMethod ]( selector ); 1424 } 1425 1426 // ----- appendToFragment ----- // 1427 1428 function checkParent( elem ) { 1429 // not needed if already has parent 1430 if ( elem.parentNode ) { 1431 return; 1432 } 1433 var fragment = document.createDocumentFragment(); 1434 fragment.appendChild( elem ); 1435 } 1436 1437 // ----- query ----- // 1438 1439 // fall back to using QSA 1440 // thx @jonathantneal https://gist.github.com/3062955 1441 function query( elem, selector ) { 1442 // append to fragment if no parent 1443 checkParent( elem ); 1444 1445 // match elem with all selected elems of parent 1446 var elems = elem.parentNode.querySelectorAll( selector ); 1447 for ( var i=0, len = elems.length; i < len; i++ ) { 1448 // return true if match 1449 if ( elems[i] === elem ) { 1450 return true; 1451 } 1452 } 1453 // otherwise return false 1454 return false;
1455 } 1456 1457 // ----- matchChild ----- // 1458 1459 function matchChild( elem, selector ) { 1460 checkParent( elem ); 1461 return match( elem, selector ); 1462 } 1463 1464 // ----- matchesSelector ----- // 1465 1466 var matchesSelector; 1467 1468 if ( matchesMethod ) { 1469 // IE9 supports matchesSelector, but doesn't work on orphaned elems 1470 // check for that 1471 var div = document.createElement('div'); 1472 var supportsOrphans = match( div, 'div' ); 1473 matchesSelector = supportsOrphans ? match : matchChild; 1474 } else { 1475 matchesSelector = query; 1476 } 1477 1478 // transport 1479 if ( typeof define === 'function' && define.amd ) { 1480 // AMD 1481 define( 'matches-selector/matches-selector',[],function() { 1482 return matchesSelector; 1483 }); 1484 } else if ( typeof exports === 'object' ) { 1485 module.exports = matchesSelector; 1486 } 1487 else { 1488 // browser global 1489 window.matchesSelector = matchesSelector; 1490 } 1491 1492})( Element.prototype ); 1493 1494/** 1495 * Fizzy UI utils v1.0.1 1496 * MIT license 1497 */ 1498 1499/*jshint browser: true, undef: true, unused: true, strict: true */ 1500 1501( function( window, factory ) { 1502 /*global define: false, module: false, require: false */ 1503 'use strict'; 1504 // universal module definition 1505 1506 if ( typeof define == 'function' && define.amd ) { 1507 // AMD 1508 define( 'fizzy-ui-utils/utils',[ 1509 'doc-ready/doc-ready', 1510 'matches-selector/matches-selector' 1511 ], function( docReady, matchesSelector ) { 1512 return factory( window, docReady, matchesSelector ); 1513 }); 1514 } else if ( typeof exports == 'object' ) { 1515 // CommonJS 1516 module.exports = factory( 1517 window, 1518 require('doc-ready'), 1519 require('desandro-matches-selector') 1520 ); 1521 } else { 1522 // browser global 1523 window.fizzyUIUtils = factory( 1524 window, 1525 window.docReady, 1526 window.matchesSelector 1527 ); 1528 } 1529 1530}( window, function factory( window, docReady, matchesSelector ) { 1531 1532 1533 1534var utils = {}; 1535 1536// ----- extend ----- // 1537 1538// extends objects 1539utils.extend = function( a, b ) { 1540 for ( var prop in b ) { 1541 a[ prop ] = b[ prop ]; 1542 } 1543 return a; 1544}; 1545 1546// ----- modulo ----- // 1547 1548utils.modulo = function( num, div ) { 1549 return ( ( num % div ) + div ) % div; 1550}; 1551 1552// ----- isArray ----- // 1553 1554var objToString = Object.prototype.toString; 1555utils.isArray = function( obj ) { 1556 return objToString.call( obj ) == '[object Array]'; 1557}; 1558 1559// ----- makeArray ----- // 1560 1561// turn element or nodeList into an array 1562utils.makeArray = function( obj ) { 1563 var ary = []; 1564 if ( utils.isArray( obj ) ) { 1565 // use object if already an array 1566 ary = obj; 1567 } else if ( obj && typeof obj.length == 'number' ) { 1568 // convert nodeList to array 1569 for ( var i=0, len = obj.length; i < len; i++ ) { 1570 ary.push( obj[i] ); 1571 } 1572 } else { 1573 // array of single index 1574 ary.push( obj ); 1575 } 1576 return ary; 1577}; 1578 1579// ----- indexOf ----- // 1580 1581// index of helper cause IE8 1582utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) { 1583 return ary.indexOf( obj ); 1584 } : function( ary, obj ) { 1585 for ( var i=0, len = ary.length; i < len; i++ ) { 1586 if ( ary[i] === obj ) { 1587 return i; 1588 } 1589 } 1590 return -1; 1591 }; 1592 1593// ----- removeFrom ----- // 1594 1595utils.removeFrom = function( ary, obj ) { 1596 var index = utils.indexOf( ary, obj ); 1597 if ( index != -1 ) { 1598 ary.splice( index, 1 ); 1599 } 1600}; 1601 1602// ----- isElement ----- // 1603 1604// http://stackoverflow.com/a/384380/182183 1605utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ? 1606 function isElementDOM2( obj ) { 1607 return obj instanceof HTMLElement; 1608 } : 1609 function isElementQuirky( obj ) { 1610 return obj && typeof obj == 'object' && 1611 obj.nodeType == 1 && typeof obj.nodeName == 'string'; 1612 }; 1613 1614// ----- setText ----- // 1615 1616utils.setText = ( function() { 1617 var setTextProperty; 1618 function setText( elem, text ) { 1619 // only check setTextProperty once 1620 setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' ); 1621 elem[ setTextProperty ] = text; 1622 } 1623 return setText; 1624})(); 1625 1626// ----- getParent ----- // 1627 1628utils.getParent = function( elem, selector ) { 1629 while ( elem != document.body ) { 1630 elem = elem.parentNode; 1631 if ( matchesSelector( elem, selector ) ) { 1632 return elem; 1633 } 1634 } 1635}; 1636 1637// ----- getQueryElement ----- // 1638 1639// use element as selector string 1640utils.getQueryElement = function( elem ) { 1641 if ( typeof elem == 'string' ) { 1642 return document.querySelector( elem ); 1643 } 1644 return elem; 1645}; 1646 1647// ----- handleEvent ----- // 1648 1649// enable .ontype to trigger from .addEventListener( elem, 'type' ) 1650utils.handleEvent = function( event ) { 1651 var method = 'on' + event.type; 1652 if ( this[ method ] ) { 1653 this[ method ]( event ); 1654 } 1655}; 1656 1657// ----- filterFindElements ----- // 1658 1659utils.filterFindElements = function( elems, selector ) { 1660 // make array of elems 1661 elems = utils.makeArray( elems ); 1662 var ffElems = []; 1663 1664 for ( var i=0, len = elems.length; i < len; i++ ) { 1665 var elem = elems[i]; 1666 // check that elem is an actual element 1667 if ( !utils.isElement( elem ) ) { 1668 continue; 1669 } 1670 // filter & find items if we have a selector 1671 if ( selector ) { 1672 // filter siblings 1673 if ( matchesSelector( elem, selector ) ) { 1674 ffElems.push( elem ); 1675 } 1676 // find children 1677 var childElems = elem.querySelectorAll( selector ); 1678 // concat childElems to filterFound array 1679 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 1680 ffElems.push( childElems[j] ); 1681 } 1682 } else { 1683 ffElems.push( elem ); 1684 } 1685 } 1686 1687 return ffElems; 1688}; 1689 1690// ----- debounceMethod ----- // 1691 1692utils.debounceMethod = function( _class, methodName, threshold ) { 1693 // original method 1694 var method = _class.prototype[ methodName ]; 1695 var timeoutName = methodName + 'Timeout'; 1696 1697 _class.prototype[ methodName ] = function() { 1698 var timeout = this[ timeoutName ]; 1699 if ( timeout ) { 1700 clearTimeout( timeout ); 1701 } 1702 var args = arguments; 1703 1704 var _this = this; 1705 this[ timeoutName ] = setTimeout( function() { 1706 method.apply( _this, args ); 1707 delete _this[ timeoutName ]; 1708 }, threshold || 100 ); 1709 }; 1710}; 1711 1712// ----- htmlInit ----- // 1713 1714// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 1715utils.toDashed = function( str ) { 1716 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 1717 return $1 + '-' + $2; 1718 }).toLowerCase(); 1719}; 1720
1721var console = window.console; 1722/** 1723 * allow user to initialize classes via .js-namespace class 1724 * htmlInit( Widget, 'widgetName' ) 1725 * options are parsed from data-namespace-option attribute 1726 */ 1727utils.htmlInit = function( WidgetClass, namespace ) { 1728 docReady( function() { 1729 var dashedNamespace = utils.toDashed( namespace ); 1730 var elems = document.querySelectorAll( '.js-' + dashedNamespace ); 1731 var dataAttr = 'data-' + dashedNamespace + '-options'; 1732 1733 for ( var i=0, len = elems.length; i < len; i++ ) { 1734 var elem = elems[i]; 1735 var attr = elem.getAttribute( dataAttr ); 1736 var options; 1737 try { 1738 options = attr && JSON.parse( attr ); 1739 } catch ( error ) { 1740 // log error, do not initialize 1741 if ( console ) { 1742 console.error( 'Error parsing ' + dataAttr + ' on ' + 1743 elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' + 1744 error ); 1745 } 1746 continue; 1747 } 1748 // initialize 1749 var instance = new WidgetClass( elem, options ); 1750 // make available via $().data('layoutname') 1751 var jQuery = window.jQuery; 1752 if ( jQuery ) { 1753 jQuery.data( elem, namespace, instance ); 1754 } 1755 } 1756 }); 1757}; 1758 1759// ----- ----- // 1760 1761return utils; 1762 1763})); 1764 1765/** 1766 * Outlayer Item 1767 */ 1768 1769( function( window, factory ) { 1770 'use strict'; 1771 // universal module definition 1772 if ( typeof define === 'function' && define.amd ) { 1773 // AMD 1774 define( 'outlayer/item',[ 1775 'eventEmitter/EventEmitter', 1776 'get-size/get-size', 1777 'get-style-property/get-style-property', 1778 'fizzy-ui-utils/utils' 1779 ], 1780 function( EventEmitter, getSize, getStyleProperty, utils ) { 1781 return factory( window, EventEmitter, getSize, getStyleProperty, utils ); 1782 } 1783 ); 1784 } else if (typeof exports === 'object') { 1785 // CommonJS 1786 module.exports = factory( 1787 window, 1788 require('wolfy87-eventemitter'), 1789 require('get-size'), 1790 require('desandro-get-style-property'), 1791 require('fizzy-ui-utils') 1792 ); 1793 } else { 1794 // browser global 1795 window.Outlayer = {}; 1796 window.Outlayer.Item = factory( 1797 window, 1798 window.EventEmitter, 1799 window.getSize, 1800 window.getStyleProperty, 1801 window.fizzyUIUtils 1802 ); 1803 } 1804 1805}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) { 1806'use strict'; 1807 1808// ----- helpers ----- // 1809 1810var getComputedStyle = window.getComputedStyle; 1811var getStyle = getComputedStyle ? 1812 function( elem ) { 1813 return getComputedStyle( elem, null ); 1814 } : 1815 function( elem ) { 1816 return elem.currentStyle; 1817 }; 1818 1819 1820function isEmptyObj( obj ) { 1821 for ( var prop in obj ) { 1822 return false; 1823 } 1824 prop = null; 1825 return true; 1826} 1827 1828// -------------------------- CSS3 support -------------------------- // 1829 1830var transitionProperty = getStyleProperty('transition'); 1831var transformProperty = getStyleProperty('transform'); 1832var supportsCSS3 = transitionProperty && transformProperty; 1833var is3d = !!getStyleProperty('perspective'); 1834 1835var transitionEndEvent = { 1836 WebkitTransition: 'webkitTransitionEnd', 1837 MozTransition: 'transitionend', 1838 OTransition: 'otransitionend', 1839 transition: 'transitionend' 1840}[ transitionProperty ]; 1841 1842// properties that could have vendor prefix 1843var prefixableProperties = [ 1844 'transform', 1845 'transition', 1846 'transitionDuration', 1847 'transitionProperty' 1848]; 1849 1850// cache all vendor properties 1851var vendorProperties = ( function() { 1852 var cache = {}; 1853 for ( var i=0, len = prefixableProperties.length; i < len; i++ ) { 1854 var prop = prefixableProperties[i]; 1855 var supportedProp = getStyleProperty( prop ); 1856 if ( supportedProp && supportedProp !== prop ) { 1857 cache[ prop ] = supportedProp; 1858 } 1859 } 1860 return cache; 1861})(); 1862 1863// -------------------------- Item -------------------------- // 1864 1865function Item( element, layout ) { 1866 if ( !element ) { 1867 return; 1868 } 1869 1870 this.element = element; 1871 // parent layout class, i.e. Masonry, Isotope, or Packery 1872 this.layout = layout; 1873 this.position = { 1874 x: 0, 1875 y: 0 1876 }; 1877 1878 this._create(); 1879} 1880 1881// inherit EventEmitter 1882utils.extend( Item.prototype, EventEmitter.prototype ); 1883 1884Item.prototype._create = function() { 1885 // transition objects 1886 this._transn = { 1887 ingProperties: {}, 1888 clean: {}, 1889 onEnd: {} 1890 }; 1891 1892 this.css({ 1893 position: 'absolute' 1894 }); 1895}; 1896 1897// trigger specified handler for event type 1898Item.prototype.handleEvent = function( event ) { 1899 var method = 'on' + event.type; 1900 if ( this[ method ] ) { 1901 this[ method ]( event ); 1902 } 1903}; 1904 1905Item.prototype.getSize = function() { 1906 this.size = getSize( this.element ); 1907}; 1908 1909/** 1910 * apply CSS styles to element 1911 * @param {Object} style 1912 */ 1913Item.prototype.css = function( style ) { 1914 var elemStyle = this.element.style; 1915 1916 for ( var prop in style ) { 1917 // use vendor property if available
1918 var supportedProp = vendorProperties[ prop ] || prop; 1919 elemStyle[ supportedProp ] = style[ prop ]; 1920 } 1921}; 1922 1923 // measure position, and sets it 1924Item.prototype.getPosition = function() { 1925 var style = getStyle( this.element ); 1926 var layoutOptions = this.layout.options; 1927 var isOriginLeft = layoutOptions.isOriginLeft; 1928 var isOriginTop = layoutOptions.isOriginTop; 1929 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 1930 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 1931 // convert percent to pixels 1932 var layoutSize = this.layout.size; 1933 var x = xValue.indexOf('%') != -1 ? 1934 ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 ); 1935 var y = yValue.indexOf('%') != -1 ? 1936 ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 ); 1937 1938 // clean up 'auto' or other non-integer values 1939 x = isNaN( x ) ? 0 : x; 1940 y = isNaN( y ) ? 0 : y; 1941 // remove padding from measurement 1942 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 1943 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 1944 1945 this.position.x = x; 1946 this.position.y = y; 1947}; 1948 1949// set settled position, apply padding 1950Item.prototype.layoutPosition = function() { 1951 var layoutSize = this.layout.size; 1952 var layoutOptions = this.layout.options; 1953 var style = {}; 1954 1955 // x 1956 var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight'; 1957 var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right'; 1958 var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left'; 1959 1960 var x = this.position.x + layoutSize[ xPadding ]; 1961 // set in percentage or pixels 1962 style[ xProperty ] = this.getXValue( x ); 1963 // reset other property 1964 style[ xResetProperty ] = ''; 1965 1966 // y 1967 var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom'; 1968 var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom'; 1969 var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top'; 1970 1971 var y = this.position.y + layoutSize[ yPadding ]; 1972 // set in percentage or pixels 1973 style[ yProperty ] = this.getYValue( y ); 1974 // reset other property 1975 style[ yResetProperty ] = ''; 1976 1977 this.css( style ); 1978 this.emitEvent( 'layout', [ this ] ); 1979}; 1980 1981Item.prototype.getXValue = function( x ) { 1982 var layoutOptions = this.layout.options; 1983 return layoutOptions.percentPosition && !layoutOptions.isHorizontal ? 1984 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 1985}; 1986 1987Item.prototype.getYValue = function( y ) { 1988 var layoutOptions = this.layout.options; 1989 return layoutOptions.percentPosition && layoutOptions.isHorizontal ? 1990 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 1991}; 1992 1993 1994Item.prototype._transitionTo = function( x, y ) { 1995 this.getPosition(); 1996 // get current x & y from top/left 1997 var curX = this.position.x; 1998 var curY = this.position.y; 1999 2000 var compareX = parseInt( x, 10 ); 2001 var compareY = parseInt( y, 10 ); 2002 var didNotMove = compareX === this.position.x && compareY === this.position.y; 2003 2004 // save end position 2005 this.setPosition( x, y ); 2006 2007 // if did not move and not transitioning, just go to layout 2008 if ( didNotMove && !this.isTransitioning ) { 2009 this.layoutPosition(); 2010 return; 2011 } 2012 2013 var transX = x - curX; 2014 var transY = y - curY; 2015 var transitionStyle = {}; 2016 transitionStyle.transform = this.getTranslate( transX, transY ); 2017 2018 this.transition({ 2019 to: transitionStyle, 2020 onTransitionEnd: { 2021 transform: this.layoutPosition 2022 }, 2023 isCleaning: true 2024 }); 2025}; 2026 2027Item.prototype.getTranslate = function( x, y ) { 2028 // flip cooridinates if origin on right or bottom 2029 var layoutOptions = this.layout.options; 2030 x = layoutOptions.isOriginLeft ? x : -x; 2031 y = layoutOptions.isOriginTop ? y : -y; 2032 2033 if ( is3d ) { 2034 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 2035 } 2036 2037 return 'translate(' + x + 'px, ' + y + 'px)'; 2038}; 2039 2040// non transition + transform support 2041Item.prototype.goTo = function( x, y ) { 2042 this.setPosition( x, y ); 2043 this.layoutPosition(); 2044}; 2045 2046// use transition and transforms if supported 2047Item.prototype.moveTo = supportsCSS3 ? 2048 Item.prototype._transitionTo : Item.prototype.goTo; 2049 2050Item.prototype.setPosition = function( x, y ) { 2051 this.position.x = parseInt( x, 10 ); 2052 this.position.y = parseInt( y, 10 ); 2053}; 2054 2055// ----- transition ----- // 2056 2057/** 2058 * @param {Object} style - CSS 2059 * @param {Function} onTransitionEnd 2060 */ 2061 2062// non transition, just trigger callback 2063Item.prototype._nonTransition = function( args ) { 2064 this.css( args.to ); 2065 if ( args.isCleaning ) { 2066 this._removeStyles( args.to ); 2067 } 2068 for ( var prop in args.onTransitionEnd ) { 2069 args.onTransitionEnd[ prop ].call( this ); 2070 } 2071}; 2072 2073/** 2074 * proper transition 2075 * @param {Object} args - arguments 2076 * @param {Object} to - style to transition to 2077 * @param {Object} from - style to start transition from 2078 * @param {Boolean} isCleaning - removes transition styles after transition 2079 * @param {Function} onTransitionEnd - callback 2080 */ 2081Item.prototype._transition = function( args ) { 2082 // redirect to nonTransition if no transition duration 2083 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 2084 this._nonTransition( args ); 2085 return; 2086 } 2087 2088 var _transition = this._transn; 2089 // keep track of onTransitionEnd callback by css property 2090 for ( var prop in args.onTransitionEnd ) { 2091 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 2092 } 2093 // keep track of properties that are transitioning 2094 for ( prop in args.to ) { 2095 _transition.ingProperties[ prop ] = true; 2096 // keep track of properties to clean up when transition is done 2097 if ( args.isCleaning ) { 2098 _transition.clean[ prop ] = true; 2099 } 2100 } 2101 2102 // set from styles 2103 if ( args.from ) { 2104 this.css( args.from ); 2105 // force redraw. http://blog.alexmaccaw.com/css-transitions 2106 var h = this.element.offsetHeight; 2107 // hack for JSHint to hush about unused var 2108 h = null; 2109 } 2110 // enable transition 2111 this.enableTransition( args.to ); 2112 // set styles that are transitioning 2113 this.css( args.to ); 2114 2115 this.isTransitioning = true; 2116 2117}; 2118 2119// dash before all cap letters, including first for 2120// WebkitTransform => -webkit-transform 2121function toDashedAll( str ) { 2122 return str.replace( /([A-Z])/g, function( $1 ) { 2123 return '-' + $1.toLowerCase(); 2124 }); 2125} 2126 2127var transitionProps = 'opacity,' +
vendor: 11,190 bytes, lines 2128-2574
2128 toDashedAll( vendorProperties.transform || 'transform' ); 2129 2130Item.prototype.enableTransition = function(/* style */) { 2131 // HACK changing transitionProperty during a transition 2132 // will cause transition to jump 2133 if ( this.isTransitioning ) { 2134 return; 2135 } 2136 2137 // make `transition: foo, bar, baz` from style object 2138 // HACK un-comment this when enableTransition can work 2139 // while a transition is happening 2140 // var transitionValues = []; 2141 // for ( var prop in style ) { 2142 // // dash-ify camelCased properties like WebkitTransition 2143 // prop = vendorProperties[ prop ] || prop; 2144 // transitionValues.push( toDashedAll( prop ) ); 2145 // } 2146 // enable transition styles 2147 this.css({ 2148 transitionProperty: transitionProps, 2149 transitionDuration: this.layout.options.transitionDuration 2150 }); 2151 // listen for transition end event 2152 this.element.addEventListener( transitionEndEvent, this, false ); 2153}; 2154 2155Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ]; 2156 2157// ----- events ----- // 2158 2159Item.prototype.onwebkitTransitionEnd = function( event ) { 2160 this.ontransitionend( event ); 2161}; 2162 2163Item.prototype.onotransitionend = function( event ) { 2164 this.ontransitionend( event ); 2165}; 2166 2167// properties that I munge to make my life easier 2168var dashedVendorProperties = { 2169 '-webkit-transform': 'transform', 2170 '-moz-transform': 'transform', 2171 '-o-transform': 'transform' 2172}; 2173 2174Item.prototype.ontransitionend = function( event ) { 2175 // disregard bubbled events from children 2176 if ( event.target !== this.element ) { 2177 return; 2178 } 2179 var _transition = this._transn; 2180 // get property name of transitioned property, convert to prefix-free 2181 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 2182 2183 // remove property that has completed transitioning 2184 delete _transition.ingProperties[ propertyName ]; 2185 // check if any properties are still transitioning 2186 if ( isEmptyObj( _transition.ingProperties ) ) { 2187 // all properties have completed transitioning 2188 this.disableTransition(); 2189 } 2190 // clean style 2191 if ( propertyName in _transition.clean ) { 2192 // clean up style 2193 this.element.style[ event.propertyName ] = ''; 2194 delete _transition.clean[ propertyName ]; 2195 } 2196 // trigger onTransitionEnd callback 2197 if ( propertyName in _transition.onEnd ) { 2198 var onTransitionEnd = _transition.onEnd[ propertyName ]; 2199 onTransitionEnd.call( this ); 2200 delete _transition.onEnd[ propertyName ]; 2201 } 2202 2203 this.emitEvent( 'transitionEnd', [ this ] ); 2204}; 2205 2206Item.prototype.disableTransition = function() { 2207 this.removeTransitionStyles(); 2208 this.element.removeEventListener( transitionEndEvent, this, false ); 2209 this.isTransitioning = false; 2210}; 2211 2212/** 2213 * removes style property from element 2214 * @param {Object} style 2215**/ 2216Item.prototype._removeStyles = function( style ) { 2217 // clean up transition styles 2218 var cleanStyle = {}; 2219 for ( var prop in style ) { 2220 cleanStyle[ prop ] = ''; 2221 } 2222 this.css( cleanStyle ); 2223}; 2224 2225var cleanTransitionStyle = { 2226 transitionProperty: '', 2227 transitionDuration: '' 2228}; 2229 2230Item.prototype.removeTransitionStyles = function() { 2231 // remove transition 2232 this.css( cleanTransitionStyle ); 2233}; 2234 2235// ----- show/hide/remove ----- // 2236 2237// remove element from DOM 2238Item.prototype.removeElem = function() { 2239 this.element.parentNode.removeChild( this.element ); 2240 // remove display: none 2241 this.css({ display: '' }); 2242 this.emitEvent( 'remove', [ this ] ); 2243}; 2244 2245Item.prototype.remove = function() { 2246 // just remove element if no transition support or no transition 2247 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 2248 this.removeElem(); 2249 return; 2250 } 2251 2252 // start transition 2253 var _this = this; 2254 this.once( 'transitionEnd', function() { 2255 _this.removeElem(); 2256 }); 2257 this.hide(); 2258}; 2259 2260Item.prototype.reveal = function() { 2261 delete this.isHidden; 2262 // remove display: none 2263 this.css({ display: '' }); 2264 2265 var options = this.layout.options; 2266 2267 var onTransitionEnd = {}; 2268 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 2269 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 2270 2271 this.transition({ 2272 from: options.hiddenStyle, 2273 to: options.visibleStyle, 2274 isCleaning: true, 2275 onTransitionEnd: onTransitionEnd 2276 }); 2277}; 2278 2279Item.prototype.onRevealTransitionEnd = function() { 2280 // check if still visible 2281 // during transition, item may have been hidden 2282 if ( !this.isHidden ) { 2283 this.emitEvent('reveal'); 2284 } 2285}; 2286 2287/** 2288 * get style property use for hide/reveal transition end 2289 * @param {String} styleProperty - hiddenStyle/visibleStyle 2290 * @returns {String} 2291 */ 2292Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) { 2293 var optionStyle = this.layout.options[ styleProperty ]; 2294 // use opacity 2295 if ( optionStyle.opacity ) { 2296 return 'opacity'; 2297 } 2298 // get first property 2299 for ( var prop in optionStyle ) { 2300 return prop; 2301 } 2302}; 2303 2304Item.prototype.hide = function() { 2305 // set flag 2306 this.isHidden = true; 2307 // remove display: none 2308 this.css({ display: '' }); 2309 2310 var options = this.layout.options; 2311 2312 var onTransitionEnd = {}; 2313 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 2314 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 2315 2316 this.transition({ 2317 from: options.visibleStyle, 2318 to: options.hiddenStyle, 2319 // keep hidden stuff hidden 2320 isCleaning: true, 2321 onTransitionEnd: onTransitionEnd 2322 }); 2323}; 2324 2325Item.prototype.onHideTransitionEnd = function() { 2326 // check if still hidden 2327 // during transition, item may have been un-hidden 2328 if ( this.isHidden ) { 2329 this.css({ display: 'none' }); 2330 this.emitEvent('hide'); 2331 } 2332}; 2333 2334Item.prototype.destroy = function() { 2335 this.css({ 2336 position: '', 2337 left: '', 2338 right: '', 2339 top: '', 2340 bottom: '', 2341 transition: '', 2342 transform: '' 2343 }); 2344}; 2345 2346return Item; 2347 2348})); 2349 2350/*! 2351 * Outlayer v1.4.2 2352 * the brains and guts of a layout library 2353 * MIT license 2354 */ 2355 2356( function( window, factory ) { 2357 'use strict'; 2358 // universal module definition 2359 2360 if ( typeof define == 'function' && define.amd ) { 2361 // AMD 2362 define( 'outlayer/outlayer',[ 2363 'eventie/eventie', 2364 'eventEmitter/EventEmitter', 2365 'get-size/get-size', 2366 'fizzy-ui-utils/utils', 2367 './item' 2368 ], 2369 function( eventie, EventEmitter, getSize, utils, Item ) { 2370 return factory( window, eventie, EventEmitter, getSize, utils, Item); 2371 } 2372 ); 2373 } else if ( typeof exports == 'object' ) { 2374 // CommonJS 2375 module.exports = factory( 2376 window, 2377 require('eventie'), 2378 require('wolfy87-eventemitter'), 2379 require('get-size'), 2380 require('fizzy-ui-utils'), 2381 require('./item') 2382 ); 2383 } else { 2384 // browser global 2385 window.Outlayer = factory( 2386 window, 2387 window.eventie, 2388 window.EventEmitter, 2389 window.getSize, 2390 window.fizzyUIUtils, 2391 window.Outlayer.Item 2392 ); 2393 } 2394 2395}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) { 2396'use strict'; 2397 2398// ----- vars ----- // 2399 2400var console = window.console; 2401var jQuery = window.jQuery; 2402var noop = function() {}; 2403 2404// -------------------------- Outlayer -------------------------- // 2405 2406// globally unique identifiers 2407var GUID = 0; 2408// internal store of all Outlayer intances 2409var instances = {}; 2410 2411 2412/** 2413 * @param {Element, String} element 2414 * @param {Object} options 2415 * @constructor 2416 */ 2417function Outlayer( element, options ) { 2418 var queryElement = utils.getQueryElement( element ); 2419 if ( !queryElement ) { 2420 if ( console ) { 2421 console.error( 'Bad element for ' + this.constructor.namespace + 2422 ': ' + ( queryElement || element ) ); 2423 } 2424 return; 2425 } 2426 this.element = queryElement; 2427 // add jQuery 2428 if ( jQuery ) { 2429 this.$element = jQuery( this.element ); 2430 } 2431 2432 // options 2433 this.options = utils.extend( {}, this.constructor.defaults ); 2434 this.option( options ); 2435 2436 // add id for Outlayer.getFromElement 2437 var id = ++GUID; 2438 this.element.outlayerGUID = id; // expando 2439 instances[ id ] = this; // associate via id 2440 2441 // kick it off 2442 this._create(); 2443 2444 if ( this.options.isInitLayout ) { 2445 this.layout(); 2446 } 2447} 2448 2449// settings are for internal use only 2450Outlayer.namespace = 'outlayer'; 2451Outlayer.Item = Item; 2452 2453// default options 2454Outlayer.defaults = { 2455 containerStyle: { 2456 position: 'relative' 2457 }, 2458 isInitLayout: true, 2459 isOriginLeft: true, 2460 isOriginTop: true, 2461 isResizeBound: true, 2462 isResizingContainer: true, 2463 // item options 2464 transitionDuration: '0.4s', 2465 hiddenStyle: { 2466 opacity: 0, 2467 transform: 'scale(0.001)' 2468 }, 2469 visibleStyle: { 2470 opacity: 1, 2471 transform: 'scale(1)' 2472 } 2473}; 2474 2475// inherit EventEmitter 2476utils.extend( Outlayer.prototype, EventEmitter.prototype ); 2477 2478/** 2479 * set options 2480 * @param {Object} opts 2481 */ 2482Outlayer.prototype.option = function( opts ) { 2483 utils.extend( this.options, opts ); 2484}; 2485 2486Outlayer.prototype._create = function() { 2487 // get items from children 2488 this.reloadItems(); 2489 // elements that affect layout, but are not laid out 2490 this.stamps = []; 2491 this.stamp( this.options.stamp ); 2492 // set container style 2493 utils.extend( this.element.style, this.options.containerStyle ); 2494 2495 // bind resize method 2496 if ( this.options.isResizeBound ) { 2497 this.bindResize(); 2498 } 2499}; 2500 2501// goes through all children again and gets bricks in proper order 2502Outlayer.prototype.reloadItems = function() { 2503 // collection of item elements 2504 this.items = this._itemize( this.element.children ); 2505}; 2506 2507 2508/** 2509 * turn elements into Outlayer.Items to be used in layout 2510 * @param {Array or NodeList or HTMLElement} elems 2511 * @returns {Array} items - collection of new Outlayer Items 2512 */ 2513Outlayer.prototype._itemize = function( elems ) { 2514 2515 var itemElems = this._filterFindItemElements( elems ); 2516 var Item = this.constructor.Item; 2517 2518 // create new Outlayer Items for collection 2519 var items = []; 2520 for ( var i=0, len = itemElems.length; i < len; i++ ) { 2521 var elem = itemElems[i]; 2522 var item = new Item( elem, this ); 2523 items.push( item ); 2524 } 2525 2526 return items; 2527}; 2528 2529/** 2530 * get item elements to be used in layout 2531 * @param {Array or NodeList or HTMLElement} elems 2532 * @returns {Array} items - item elements 2533 */ 2534Outlayer.prototype._filterFindItemElements = function( elems ) { 2535 return utils.filterFindElements( elems, this.options.itemSelector ); 2536}; 2537 2538/** 2539 * getter method for getting item elements 2540 * @returns {Array} elems - collection of item elements 2541 */ 2542Outlayer.prototype.getItemElements = function() { 2543 var elems = []; 2544 for ( var i=0, len = this.items.length; i < len; i++ ) { 2545 elems.push( this.items[i].element ); 2546 } 2547 return elems; 2548}; 2549 2550// ----- init & layout ----- // 2551 2552/** 2553 * lays out all items 2554 */ 2555Outlayer.prototype.layout = function() { 2556 this._resetLayout(); 2557 this._manageStamps(); 2558 2559 // don't animate first layout 2560 var isInstant = this.options.isLayoutInstant !== undefined ? 2561 this.options.isLayoutInstant : !this._isLayoutInited; 2562 this.layoutItems( this.items, isInstant ); 2563 2564 // flag for initalized 2565 this._isLayoutInited = true; 2566}; 2567 2568// _init is alias for layout 2569Outlayer.prototype._init = Outlayer.prototype.layout; 2570 2571/** 2572 * logic before any new layout 2573 */ 2574Outlayer.prototype._resetLayout = function() {
2575 this.getSize(); 2576}; 2577 2578 2579Outlayer.prototype.getSize = function() { 2580 this.size = getSize( this.element ); 2581}; 2582 2583/** 2584 * get measurement from option, for columnWidth, rowHeight, gutter 2585 * if option is String -> get element from selector string, & get size of element 2586 * if option is Element -> get size of element 2587 * else use option as a number 2588 * 2589 * @param {String} measurement 2590 * @param {String} size - width or height 2591 * @private 2592 */ 2593Outlayer.prototype._getMeasurement = function( measurement, size ) { 2594 var option = this.options[ measurement ]; 2595 var elem; 2596 if ( !option ) { 2597 // default to 0 2598 this[ measurement ] = 0; 2599 } else { 2600 // use option as an element 2601 if ( typeof option === 'string' ) { 2602 elem = this.element.querySelector( option ); 2603 } else if ( utils.isElement( option ) ) { 2604 elem = option; 2605 } 2606 // use size of element, if element 2607 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 2608 } 2609}; 2610 2611/** 2612 * layout a collection of item elements 2613 * @api public 2614 */ 2615Outlayer.prototype.layoutItems = function( items, isInstant ) { 2616 items = this._getItemsForLayout( items ); 2617 2618 this._layoutItems( items, isInstant ); 2619 2620 this._postLayout(); 2621}; 2622 2623/** 2624 * get the items to be laid out 2625 * you may want to skip over some items 2626 * @param {Array} items 2627 * @returns {Array} items 2628 */ 2629Outlayer.prototype._getItemsForLayout = function( items ) { 2630 var layoutItems = []; 2631 for ( var i=0, len = items.length; i < len; i++ ) { 2632 var item = items[i]; 2633 if ( !item.isIgnored ) { 2634 layoutItems.push( item ); 2635 } 2636 } 2637 return layoutItems; 2638}; 2639 2640/** 2641 * layout items 2642 * @param {Array} items 2643 * @param {Boolean} isInstant 2644 */ 2645Outlayer.prototype._layoutItems = function( items, isInstant ) { 2646 this._emitCompleteOnItems( 'layout', items ); 2647 2648 if ( !items || !items.length ) { 2649 // no items, emit event with empty array 2650 return; 2651 } 2652 2653 var queue = []; 2654 2655 for ( var i=0, len = items.length; i < len; i++ ) { 2656 var item = items[i]; 2657 // get x/y object from method 2658 var position = this._getItemLayoutPosition( item ); 2659 // enqueue 2660 position.item = item; 2661 position.isInstant = isInstant || item.isLayoutInstant; 2662 queue.push( position ); 2663 } 2664 2665 this._processLayoutQueue( queue ); 2666}; 2667 2668/** 2669 * get item layout position 2670 * @param {Outlayer.Item} item 2671 * @returns {Object} x and y position 2672 */ 2673Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) { 2674 return { 2675 x: 0, 2676 y: 0 2677 }; 2678}; 2679 2680/** 2681 * iterate over array and position each item 2682 * Reason being - separating this logic prevents 'layout invalidation' 2683 * thx @paul_irish 2684 * @param {Array} queue 2685 */ 2686Outlayer.prototype._processLayoutQueue = function( queue ) { 2687 for ( var i=0, len = queue.length; i < len; i++ ) { 2688 var obj = queue[i]; 2689 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant ); 2690 } 2691}; 2692 2693/** 2694 * Sets position of item in DOM 2695 * @param {Outlayer.Item} item 2696 * @param {Number} x - horizontal position 2697 * @param {Number} y - vertical position 2698 * @param {Boolean} isInstant - disables transitions 2699 */ 2700Outlayer.prototype._positionItem = function( item, x, y, isInstant ) { 2701 if ( isInstant ) { 2702 // if not transition, just set CSS 2703 item.goTo( x, y ); 2704 } else { 2705 item.moveTo( x, y ); 2706 } 2707}; 2708 2709/** 2710 * Any logic you want to do after each layout, 2711 * i.e. size the container 2712 */ 2713Outlayer.prototype._postLayout = function() { 2714 this.resizeContainer(); 2715}; 2716 2717Outlayer.prototype.resizeContainer = function() { 2718 if ( !this.options.isResizingContainer ) { 2719 return; 2720 } 2721 var size = this._getContainerSize(); 2722 if ( size ) { 2723 this._setContainerMeasure( size.width, true ); 2724 this._setContainerMeasure( size.height, false ); 2725 } 2726}; 2727 2728/** 2729 * Sets width or height of container if returned 2730 * @returns {Object} size 2731 * @param {Number} width 2732 * @param {Number} height 2733 */ 2734Outlayer.prototype._getContainerSize = noop; 2735 2736/** 2737 * @param {Number} measure - size of width or height 2738 * @param {Boolean} isWidth 2739 */ 2740Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) { 2741 if ( measure === undefined ) { 2742 return; 2743 } 2744 2745 var elemSize = this.size; 2746 // add padding and border width if border box 2747 if ( elemSize.isBorderBox ) { 2748 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 2749 elemSize.borderLeftWidth + elemSize.borderRightWidth : 2750 elemSize.paddingBottom + elemSize.paddingTop + 2751 elemSize.borderTopWidth + elemSize.borderBottomWidth; 2752 } 2753 2754 measure = Math.max( measure, 0 ); 2755 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 2756}; 2757 2758/** 2759 * emit eventComplete on a collection of items events 2760 * @param {String} eventName 2761 * @param {Array} items - Outlayer.Items 2762 */ 2763Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) { 2764 var _this = this; 2765 function onComplete() { 2766 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 2767 } 2768 2769 var count = items.length; 2770 if ( !items || !count ) { 2771 onComplete(); 2772 return; 2773 } 2774 2775 var doneCount = 0; 2776 function tick() { 2777 doneCount++; 2778 if ( doneCount === count ) { 2779 onComplete(); 2780 } 2781 } 2782 2783 // bind callback 2784 for ( var i=0, len = items.length; i < len; i++ ) { 2785 var item = items[i]; 2786 item.once( eventName, tick ); 2787 } 2788}; 2789 2790/** 2791 * emits events via eventEmitter and jQuery events 2792 * @param {String} type - name of event 2793 * @param {Event} event - original event 2794 * @param {Array} args - extra arguments 2795 */ 2796Outlayer.prototype.dispatchEvent = function( type, event, args ) { 2797 // add original event to arguments 2798 var emitArgs = event ? [ event ].concat( args ) : args; 2799 this.emitEvent( type, emitArgs ); 2800 2801 if ( jQuery ) { 2802 // set this.$element 2803 this.$element = this.$element || jQuery( this.element ); 2804 if ( event ) { 2805 // create jQuery event 2806 var $event = jQuery.Event( event ); 2807 $event.type = type; 2808 this.$element.trigger( $event, args ); 2809 } else { 2810 // just trigger with type if no event available 2811 this.$element.trigger( type, args ); 2812 } 2813 } 2814}; 2815 2816// -------------------------- ignore & stamps -------------------------- // 2817 2818 2819/** 2820 * keep item in collection, but do not lay it out 2821 * ignored items do not get skipped in layout 2822 * @param {Element} elem 2823 */ 2824Outlayer.prototype.ignore = function( elem ) { 2825 var item = this.getItem( elem ); 2826 if ( item ) { 2827 item.isIgnored = true; 2828 } 2829}; 2830 2831/** 2832 * return item to layout collection 2833 * @param {Element} elem 2834 */ 2835Outlayer.prototype.unignore = function( elem ) { 2836 var item = this.getItem( elem ); 2837 if ( item ) { 2838 delete item.isIgnored; 2839 } 2840}; 2841 2842/** 2843 * adds elements to stamps 2844 * @param {NodeList, Array, Element, or String} elems 2845 */ 2846Outlayer.prototype.stamp = function( elems ) { 2847 elems = this._find( elems ); 2848 if ( !elems ) { 2849 return; 2850 } 2851
2852 this.stamps = this.stamps.concat( elems ); 2853 // ignore 2854 for ( var i=0, len = elems.length; i < len; i++ ) { 2855 var elem = elems[i]; 2856 this.ignore( elem ); 2857 } 2858}; 2859 2860/** 2861 * removes elements to stamps 2862 * @param {NodeList, Array, or Element} elems 2863 */ 2864Outlayer.prototype.unstamp = function( elems ) { 2865 elems = this._find( elems ); 2866 if ( !elems ){ 2867 return; 2868 } 2869 2870 for ( var i=0, len = elems.length; i < len; i++ ) { 2871 var elem = elems[i]; 2872 // filter out removed stamp elements 2873 utils.removeFrom( this.stamps, elem ); 2874 this.unignore( elem ); 2875 } 2876 2877}; 2878 2879/** 2880 * finds child elements 2881 * @param {NodeList, Array, Element, or String} elems 2882 * @returns {Array} elems 2883 */ 2884Outlayer.prototype._find = function( elems ) { 2885 if ( !elems ) { 2886 return; 2887 } 2888 // if string, use argument as selector string 2889 if ( typeof elems === 'string' ) { 2890 elems = this.element.querySelectorAll( elems ); 2891 } 2892 elems = utils.makeArray( elems ); 2893 return elems; 2894}; 2895 2896Outlayer.prototype._manageStamps = function() { 2897 if ( !this.stamps || !this.stamps.length ) { 2898 return; 2899 } 2900 2901 this._getBoundingRect(); 2902 2903 for ( var i=0, len = this.stamps.length; i < len; i++ ) { 2904 var stamp = this.stamps[i]; 2905 this._manageStamp( stamp ); 2906 } 2907}; 2908 2909// update boundingLeft / Top 2910Outlayer.prototype._getBoundingRect = function() { 2911 // get bounding rect for container element 2912 var boundingRect = this.element.getBoundingClientRect(); 2913 var size = this.size; 2914 this._boundingRect = { 2915 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 2916 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 2917 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 2918 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 2919 }; 2920}; 2921 2922/** 2923 * @param {Element} stamp 2924**/ 2925Outlayer.prototype._manageStamp = noop; 2926 2927/** 2928 * get x/y position of element relative to container element 2929 * @param {Element} elem 2930 * @returns {Object} offset - has left, top, right, bottom 2931 */ 2932Outlayer.prototype._getElementOffset = function( elem ) { 2933 var boundingRect = elem.getBoundingClientRect(); 2934 var thisRect = this._boundingRect; 2935 var size = getSize( elem ); 2936 var offset = { 2937 left: boundingRect.left - thisRect.left - size.marginLeft, 2938 top: boundingRect.top - thisRect.top - size.marginTop, 2939 right: thisRect.right - boundingRect.right - size.marginRight, 2940 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 2941 }; 2942 return offset; 2943}; 2944 2945// -------------------------- resize -------------------------- // 2946 2947// enable event handlers for listeners 2948// i.e. resize -> onresize 2949Outlayer.prototype.handleEvent = function( event ) { 2950 var method = 'on' + event.type; 2951 if ( this[ method ] ) { 2952 this[ method ]( event ); 2953 } 2954}; 2955 2956/** 2957 * Bind layout to window resizing 2958 */ 2959Outlayer.prototype.bindResize = function() { 2960 // bind just one listener 2961 if ( this.isResizeBound ) { 2962 return; 2963 } 2964 eventie.bind( window, 'resize', this ); 2965 this.isResizeBound = true; 2966}; 2967 2968/** 2969 * Unbind layout to window resizing 2970 */ 2971Outlayer.prototype.unbindResize = function() { 2972 if ( this.isResizeBound ) { 2973 eventie.unbind( window, 'resize', this ); 2974 } 2975 this.isResizeBound = false; 2976}; 2977 2978// original debounce by John Hann 2979// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 2980 2981// this fires every resize 2982Outlayer.prototype.onresize = function() { 2983 if ( this.resizeTimeout ) { 2984 clearTimeout( this.resizeTimeout ); 2985 } 2986 2987 var _this = this; 2988 function delayed() { 2989 _this.resize(); 2990 delete _this.resizeTimeout; 2991 } 2992 2993 this.resizeTimeout = setTimeout( delayed, 100 ); 2994}; 2995 2996// debounced, layout on resize 2997Outlayer.prototype.resize = function() { 2998 // don't trigger if size did not change 2999 // or if resize was unbound. See #9 3000 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 3001 return; 3002 } 3003 3004 this.layout(); 3005}; 3006 3007/** 3008 * check if layout is needed post layout 3009 * @returns Boolean 3010 */ 3011Outlayer.prototype.needsResizeLayout = function() { 3012 var size = getSize( this.element ); 3013 // check that this.size and size are there 3014 // IE8 triggers resize on body size change, so they might not be 3015 var hasSizes = this.size && size; 3016 return hasSizes && size.innerWidth !== this.size.innerWidth; 3017}; 3018 3019// -------------------------- methods -------------------------- // 3020 3021/** 3022 * add items to Outlayer instance 3023 * @param {Array or NodeList or Element} elems 3024 * @returns {Array} items - Outlayer.Items 3025**/ 3026Outlayer.prototype.addItems = function( elems ) { 3027 var items = this._itemize( elems ); 3028 // add items to collection 3029 if ( items.length ) { 3030 this.items = this.items.concat( items ); 3031 } 3032 return items; 3033}; 3034 3035/** 3036 * Layout newly-appended item elements 3037 * @param {Array or NodeList or Element} elems 3038 */ 3039Outlayer.prototype.appended = function( elems ) { 3040 var items = this.addItems( elems ); 3041 if ( !items.length ) { 3042 return; 3043 } 3044 // layout and reveal just the new items 3045 this.layoutItems( items, true ); 3046 this.reveal( items ); 3047}; 3048 3049/** 3050 * Layout prepended elements 3051 * @param {Array or NodeList or Element} elems 3052 */ 3053Outlayer.prototype.prepended = function( elems ) { 3054 var items = this._itemize( elems ); 3055 if ( !items.length ) { 3056 return; 3057 } 3058 // add items to beginning of collection 3059 var previousItems = this.items.slice(0); 3060 this.items = items.concat( previousItems ); 3061 // start new layout 3062 this._resetLayout(); 3063 this._manageStamps(); 3064 // layout new stuff without transition 3065 this.layoutItems( items, true ); 3066 this.reveal( items ); 3067 // layout previous items 3068 this.layoutItems( previousItems ); 3069}; 3070 3071/** 3072 * reveal a collection of items 3073 * @param {Array of Outlayer.Items} items 3074 */ 3075Outlayer.prototype.reveal = function( items ) { 3076 this._emitCompleteOnItems( 'reveal', items ); 3077 3078 var len = items && items.length; 3079 for ( var i=0; len && i < len; i++ ) { 3080 var item = items[i]; 3081 item.reveal(); 3082 } 3083}; 3084 3085/** 3086 * hide a collection of items 3087 * @param {Array of Outlayer.Items} items 3088 */ 3089Outlayer.prototype.hide = function( items ) { 3090 this._emitCompleteOnItems( 'hide', items ); 3091 3092 var len = items && items.length; 3093 for ( var i=0; len && i < len; i++ ) { 3094 var item = items[i]; 3095 item.hide(); 3096 } 3097}; 3098 3099/** 3100 * reveal item elements 3101 * @param {Array}, {Element}, {NodeList} items 3102 */ 3103Outlayer.prototype.revealItemElements = function( elems ) { 3104 var items = this.getItems( elems ); 3105 this.reveal( items ); 3106}; 3107 3108/** 3109 * hide item elements 3110 * @param {Array}, {Element}, {NodeList} items 3111 */ 3112Outlayer.prototype.hideItemElements = function( elems ) { 3113 var items = this.getItems( elems ); 3114 this.hide( items ); 3115}; 3116 3117/** 3118 * get Outlayer.Item, given an Element 3119 * @param {Element} elem 3120 * @param {Function} callback 3121 * @returns {Outlayer.Item} item 3122 */ 3123Outlayer.prototype.getItem = function( elem ) { 3124 // loop through items to get the one that matches 3125 for ( var i=0, len = this.items.length; i < len; i++ ) { 3126 var item = this.items[i]; 3127 if ( item.element === elem ) { 3128 // return item 3129 return item; 3130 } 3131 } 3132}; 3133 3134/** 3135 * get collection of Outlayer.Items, given Elements 3136 * @param {Array} elems 3137 * @returns {Array} items - Outlayer.Items 3138 */ 3139Outlayer.prototype.getItems = function( elems ) { 3140 elems = utils.makeArray( elems ); 3141 var items = []; 3142 for ( var i=0, len = elems.length; i < len; i++ ) { 3143 var elem = elems[i]; 3144 var item = this.getItem( elem ); 3145 if ( item ) { 3146 items.push( item ); 3147 } 3148 } 3149 3150 return items; 3151}; 3152 3153/**
3154 * remove element(s) from instance and DOM 3155 * @param {Array or NodeList or Element} elems 3156 */ 3157Outlayer.prototype.remove = function( elems ) { 3158 var removeItems = this.getItems( elems ); 3159 3160 this._emitCompleteOnItems( 'remove', removeItems ); 3161 3162 // bail if no items to remove 3163 if ( !removeItems || !removeItems.length ) { 3164 return; 3165 } 3166 3167 for ( var i=0, len = removeItems.length; i < len; i++ ) { 3168 var item = removeItems[i]; 3169 item.remove(); 3170 // remove item from collection 3171 utils.removeFrom( this.items, item ); 3172 } 3173}; 3174 3175// ----- destroy ----- // 3176 3177// remove and disable Outlayer instance 3178Outlayer.prototype.destroy = function() { 3179 // clean up dynamic styles 3180 var style = this.element.style; 3181 style.height = ''; 3182 style.position = ''; 3183 style.width = ''; 3184 // destroy items 3185 for ( var i=0, len = this.items.length; i < len; i++ ) { 3186 var item = this.items[i]; 3187 item.destroy(); 3188 } 3189 3190 this.unbindResize(); 3191 3192 var id = this.element.outlayerGUID; 3193 delete instances[ id ]; // remove reference to instance by id 3194 delete this.element.outlayerGUID; 3195 // remove data for jQuery 3196 if ( jQuery ) { 3197 jQuery.removeData( this.element, this.constructor.namespace ); 3198 } 3199 3200}; 3201 3202// -------------------------- data -------------------------- // 3203 3204/** 3205 * get Outlayer instance from element 3206 * @param {Element} elem 3207 * @returns {Outlayer} 3208 */ 3209Outlayer.data = function( elem ) { 3210 elem = utils.getQueryElement( elem ); 3211 var id = elem && elem.outlayerGUID; 3212 return id && instances[ id ]; 3213}; 3214 3215 3216// -------------------------- create Outlayer class -------------------------- // 3217 3218/** 3219 * create a layout class 3220 * @param {String} namespace 3221 */ 3222Outlayer.create = function( namespace, options ) { 3223 // sub-class Outlayer 3224 function Layout() { 3225 Outlayer.apply( this, arguments ); 3226 } 3227 // inherit Outlayer prototype, use Object.create if there 3228 if ( Object.create ) { 3229 Layout.prototype = Object.create( Outlayer.prototype ); 3230 } else { 3231 utils.extend( Layout.prototype, Outlayer.prototype ); 3232 } 3233 // set contructor, used for namespace and Item 3234 Layout.prototype.constructor = Layout; 3235 3236 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 3237 // apply new options 3238 utils.extend( Layout.defaults, options ); 3239 // keep prototype.settings for backwards compatibility (Packery v1.2.0) 3240 Layout.prototype.settings = {}; 3241 3242 Layout.namespace = namespace; 3243 3244 Layout.data = Outlayer.data; 3245 3246 // sub-class Item 3247 Layout.Item = function LayoutItem() { 3248 Item.apply( this, arguments ); 3249 }; 3250 3251 Layout.Item.prototype = new Item(); 3252 3253 // -------------------------- declarative -------------------------- // 3254 3255 utils.htmlInit( Layout, namespace ); 3256 3257 // -------------------------- jQuery bridge -------------------------- // 3258 3259 // make into jQuery plugin 3260 if ( jQuery && jQuery.bridget ) { 3261 jQuery.bridget( namespace, Layout ); 3262 } 3263 3264 return Layout; 3265}; 3266 3267// ----- fin ----- // 3268 3269// back in global 3270Outlayer.Item = Item; 3271 3272return Outlayer; 3273 3274})); 3275 3276 3277/** 3278 * Isotope Item 3279**/ 3280 3281( function( window, factory ) { 3282'use strict'; 3283 // universal module definition 3284 if ( typeof define == 'function' && define.amd ) { 3285 // AMD 3286 define( 'isotope/js/item',[ 3287 'outlayer/outlayer' 3288 ], 3289 factory ); 3290 } else if ( typeof exports == 'object' ) { 3291 // CommonJS 3292 module.exports = factory( 3293 require('outlayer') 3294 ); 3295 } else { 3296 // browser global 3297 window.Isotope = window.Isotope || {}; 3298 window.Isotope.Item = factory( 3299 window.Outlayer 3300 ); 3301 } 3302 3303}( window, function factory( Outlayer ) { 3304'use strict'; 3305 3306// -------------------------- Item -------------------------- // 3307 3308// sub-class Outlayer Item 3309function Item() { 3310 Outlayer.Item.apply( this, arguments ); 3311} 3312 3313Item.prototype = new Outlayer.Item(); 3314 3315Item.prototype._create = function() { 3316 // assign id, used for original-order sorting 3317 this.id = this.layout.itemGUID++; 3318 Outlayer.Item.prototype._create.call( this ); 3319 this.sortData = {}; 3320}; 3321 3322Item.prototype.updateSortData = function() { 3323 if ( this.isIgnored ) { 3324 return; 3325 } 3326 // default sorters 3327 this.sortData.id = this.id; 3328 // for backward compatibility 3329 this.sortData['original-order'] = this.id; 3330 this.sortData.random = Math.random(); 3331 // go thru getSortData obj and apply the sorters 3332 var getSortData = this.layout.options.getSortData; 3333 var sorters = this.layout._sorters; 3334 for ( var key in getSortData ) { 3335 var sorter = sorters[ key ]; 3336 this.sortData[ key ] = sorter( this.element, this ); 3337 } 3338}; 3339 3340var _destroy = Item.prototype.destroy; 3341Item.prototype.destroy = function() { 3342 // call super 3343 _destroy.apply( this, arguments ); 3344 // reset display, #741 3345 this.css({ 3346 display: '' 3347 }); 3348}; 3349 3350return Item; 3351 3352})); 3353 3354/** 3355 * Isotope LayoutMode 3356 */ 3357 3358( function( window, factory ) { 3359 'use strict'; 3360 // universal module definition 3361 3362 if ( typeof define == 'function' && define.amd ) { 3363 // AMD 3364 define( 'isotope/js/layout-mode',[ 3365 'get-size/get-size', 3366 'outlayer/outlayer' 3367 ], 3368 factory ); 3369 } else if ( typeof exports == 'object' ) { 3370 // CommonJS 3371 module.exports = factory( 3372 require('get-size'), 3373 require('outlayer') 3374 ); 3375 } else { 3376 // browser global 3377 window.Isotope = window.Isotope || {}; 3378 window.Isotope.LayoutMode = factory( 3379 window.getSize, 3380 window.Outlayer 3381 ); 3382 } 3383 3384}( window, function factory( getSize, Outlayer ) { 3385 'use strict'; 3386 3387 // layout mode class 3388 function LayoutMode( isotope ) { 3389 this.isotope = isotope; 3390 // link properties 3391 if ( isotope ) { 3392 this.options = isotope.options[ this.namespace ]; 3393 this.element = isotope.element; 3394 this.items = isotope.filteredItems; 3395 this.size = isotope.size; 3396 } 3397 } 3398 3399 /** 3400 * some methods should just defer to default Outlayer method 3401 * and reference the Isotope instance as `this` 3402 **/ 3403 ( function() { 3404 var facadeMethods = [ 3405 '_resetLayout', 3406 '_getItemLayoutPosition', 3407 '_manageStamp', 3408 '_getContainerSize', 3409 '_getElementOffset', 3410 'needsResizeLayout' 3411 ]; 3412 3413 for ( var i=0, len = facadeMethods.length; i < len; i++ ) { 3414 var methodName = facadeMethods[i]; 3415 LayoutMode.prototype[ methodName ] = getOutlayerMethod( methodName ); 3416 } 3417 3418 function getOutlayerMethod( methodName ) { 3419 return function() { 3420 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 3421 }; 3422 } 3423 })(); 3424 3425 // ----- ----- // 3426 3427 // for horizontal layout modes, check vertical size 3428 LayoutMode.prototype.needsVerticalResizeLayout = function() {
vendor: 20,029 bytes, lines 3429-4164
3429 // don't trigger if size did not change 3430 var size = getSize( this.isotope.element ); 3431 // check that this.size and size are there 3432 // IE8 triggers resize on body size change, so they might not be 3433 var hasSizes = this.isotope.size && size; 3434 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 3435 }; 3436 3437 // ----- measurements ----- // 3438 3439 LayoutMode.prototype._getMeasurement = function() { 3440 this.isotope._getMeasurement.apply( this, arguments ); 3441 }; 3442 3443 LayoutMode.prototype.getColumnWidth = function() { 3444 this.getSegmentSize( 'column', 'Width' ); 3445 }; 3446 3447 LayoutMode.prototype.getRowHeight = function() { 3448 this.getSegmentSize( 'row', 'Height' ); 3449 }; 3450 3451 /** 3452 * get columnWidth or rowHeight 3453 * segment: 'column' or 'row' 3454 * size 'Width' or 'Height' 3455 **/ 3456 LayoutMode.prototype.getSegmentSize = function( segment, size ) { 3457 var segmentName = segment + size; 3458 var outerSize = 'outer' + size; 3459 // columnWidth / outerWidth // rowHeight / outerHeight 3460 this._getMeasurement( segmentName, outerSize ); 3461 // got rowHeight or columnWidth, we can chill 3462 if ( this[ segmentName ] ) { 3463 return; 3464 } 3465 // fall back to item of first element 3466 var firstItemSize = this.getFirstItemSize(); 3467 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 3468 // or size of container 3469 this.isotope.size[ 'inner' + size ]; 3470 }; 3471 3472 LayoutMode.prototype.getFirstItemSize = function() { 3473 var firstItem = this.isotope.filteredItems[0]; 3474 return firstItem && firstItem.element && getSize( firstItem.element ); 3475 }; 3476 3477 // ----- methods that should reference isotope ----- // 3478 3479 LayoutMode.prototype.layout = function() { 3480 this.isotope.layout.apply( this.isotope, arguments ); 3481 }; 3482 3483 LayoutMode.prototype.getSize = function() { 3484 this.isotope.getSize(); 3485 this.size = this.isotope.size; 3486 }; 3487 3488 // -------------------------- create -------------------------- // 3489 3490 LayoutMode.modes = {}; 3491 3492 LayoutMode.create = function( namespace, options ) { 3493 3494 function Mode() { 3495 LayoutMode.apply( this, arguments ); 3496 } 3497 3498 Mode.prototype = new LayoutMode(); 3499 3500 // default options 3501 if ( options ) { 3502 Mode.options = options; 3503 } 3504 3505 Mode.prototype.namespace = namespace; 3506 // register in Isotope 3507 LayoutMode.modes[ namespace ] = Mode; 3508 3509 return Mode; 3510 }; 3511 3512 return LayoutMode; 3513 3514})); 3515 3516/*! 3517 * Masonry v3.3.1 3518 * Cascading grid layout library 3519 * http://masonry.desandro.com 3520 * MIT License 3521 * by David DeSandro 3522 */ 3523 3524( function( window, factory ) { 3525 'use strict'; 3526 // universal module definition 3527 if ( typeof define === 'function' && define.amd ) { 3528 // AMD 3529 define( 'masonry/masonry',[ 3530 'outlayer/outlayer', 3531 'get-size/get-size', 3532 'fizzy-ui-utils/utils' 3533 ], 3534 factory ); 3535 } else if ( typeof exports === 'object' ) { 3536 // CommonJS 3537 module.exports = factory( 3538 require('outlayer'), 3539 require('get-size'), 3540 require('fizzy-ui-utils') 3541 ); 3542 } else { 3543 // browser global 3544 window.Masonry = factory( 3545 window.Outlayer, 3546 window.getSize, 3547 window.fizzyUIUtils 3548 ); 3549 } 3550 3551}( window, function factory( Outlayer, getSize, utils ) { 3552 3553 3554 3555// -------------------------- masonryDefinition -------------------------- // 3556 3557 // create an Outlayer layout class 3558 var Masonry = Outlayer.create('masonry'); 3559 3560 Masonry.prototype._resetLayout = function() { 3561 this.getSize(); 3562 this._getMeasurement( 'columnWidth', 'outerWidth' ); 3563 this._getMeasurement( 'gutter', 'outerWidth' ); 3564 this.measureColumns(); 3565 3566 // reset column Y 3567 var i = this.cols; 3568 this.colYs = []; 3569 while (i--) { 3570 this.colYs.push( 0 ); 3571 } 3572 3573 this.maxY = 0; 3574 }; 3575 3576 Masonry.prototype.measureColumns = function() { 3577 this.getContainerWidth(); 3578 // if columnWidth is 0, default to outerWidth of first item 3579 if ( !this.columnWidth ) { 3580 var firstItem = this.items[0]; 3581 var firstItemElem = firstItem && firstItem.element; 3582 // columnWidth fall back to item of first element 3583 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 3584 // if first elem has no width, default to size of container 3585 this.containerWidth; 3586 } 3587 3588 var columnWidth = this.columnWidth += this.gutter; 3589 3590 // calculate columns 3591 var containerWidth = this.containerWidth + this.gutter; 3592 var cols = containerWidth / columnWidth; 3593 // fix rounding errors, typically with gutters 3594 var excess = columnWidth - containerWidth % columnWidth; 3595 // if overshoot is less than a pixel, round up, otherwise floor it 3596 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 3597 cols = Math[ mathMethod ]( cols ); 3598 this.cols = Math.max( cols, 1 ); 3599 }; 3600 3601 Masonry.prototype.getContainerWidth = function() { 3602 // container is parent if fit width 3603 var container = this.options.isFitWidth ? this.element.parentNode : this.element; 3604 // check that this.size and size are there 3605 // IE8 triggers resize on body size change, so they might not be 3606 var size = getSize( container ); 3607 this.containerWidth = size && size.innerWidth; 3608 }; 3609 3610 Masonry.prototype._getItemLayoutPosition = function( item ) { 3611 item.getSize(); 3612 // how many columns does this brick span 3613 var remainder = item.size.outerWidth % this.columnWidth; 3614 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 3615 // round if off by 1 pixel, otherwise use ceil 3616 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 3617 colSpan = Math.min( colSpan, this.cols ); 3618 3619 var colGroup = this._getColGroup( colSpan ); 3620 // get the minimum Y value from the columns 3621 var minimumY = Math.min.apply( Math, colGroup ); 3622 var shortColIndex = utils.indexOf( colGroup, minimumY ); 3623 3624 // position the brick 3625 var position = { 3626 x: this.columnWidth * shortColIndex, 3627 y: minimumY 3628 }; 3629 3630 // apply setHeight to necessary columns 3631 var setHeight = minimumY + item.size.outerHeight; 3632 var setSpan = this.cols + 1 - colGroup.length; 3633 for ( var i = 0; i < setSpan; i++ ) { 3634 this.colYs[ shortColIndex + i ] = setHeight; 3635 } 3636 3637 return position; 3638 }; 3639 3640 /** 3641 * @param {Number} colSpan - number of columns the element spans 3642 * @returns {Array} colGroup 3643 */ 3644 Masonry.prototype._getColGroup = function( colSpan ) { 3645 if ( colSpan < 2 ) { 3646 // if brick spans only one column, use all the column Ys 3647 return this.colYs; 3648 } 3649 3650 var colGroup = []; 3651 // how many different places could this brick fit horizontally 3652 var groupCount = this.cols + 1 - colSpan; 3653 // for each group potential horizontal position 3654 for ( var i = 0; i < groupCount; i++ ) { 3655 // make an array of colY values for that one group 3656 var groupColYs = this.colYs.slice( i, i + colSpan ); 3657 // and get the max value of the array 3658 colGroup[i] = Math.max.apply( Math, groupColYs ); 3659 } 3660 return colGroup; 3661 }; 3662 3663 Masonry.prototype._manageStamp = function( stamp ) { 3664 var stampSize = getSize( stamp ); 3665 var offset = this._getElementOffset( stamp ); 3666 // get the columns that this stamp affects 3667 var firstX = this.options.isOriginLeft ? offset.left : offset.right; 3668 var lastX = firstX + stampSize.outerWidth; 3669 var firstCol = Math.floor( firstX / this.columnWidth ); 3670 firstCol = Math.max( 0, firstCol ); 3671 var lastCol = Math.floor( lastX / this.columnWidth ); 3672 // lastCol should not go over if multiple of columnWidth #425 3673 lastCol -= lastX % this.columnWidth ? 0 : 1; 3674 lastCol = Math.min( this.cols - 1, lastCol ); 3675 // set colYs to bottom of the stamp 3676 var stampMaxY = ( this.options.isOriginTop ? offset.top : offset.bottom ) + 3677 stampSize.outerHeight; 3678 for ( var i = firstCol; i <= lastCol; i++ ) { 3679 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 3680 } 3681 }; 3682 3683 Masonry.prototype._getContainerSize = function() { 3684 this.maxY = Math.max.apply( Math, this.colYs ); 3685 var size = { 3686 height: this.maxY 3687 }; 3688 3689 if ( this.options.isFitWidth ) { 3690 size.width = this._getContainerFitWidth(); 3691 } 3692 3693 return size; 3694 }; 3695 3696 Masonry.prototype._getContainerFitWidth = function() { 3697 var unusedCols = 0; 3698 // count unused columns 3699 var i = this.cols; 3700 while ( --i ) { 3701 if ( this.colYs[i] !== 0 ) { 3702 break; 3703 } 3704 unusedCols++; 3705 } 3706 // fit container to columns that have been used 3707 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 3708 }; 3709 3710 Masonry.prototype.needsResizeLayout = function() { 3711 var previousWidth = this.containerWidth; 3712 this.getContainerWidth(); 3713 return previousWidth !== this.containerWidth; 3714 }; 3715 3716 return Masonry; 3717 3718})); 3719 3720/*! 3721 * Masonry layout mode 3722 * sub-classes Masonry 3723 * http://masonry.desandro.com 3724 */ 3725 3726( function( window, factory ) { 3727 'use strict'; 3728 // universal module definition 3729 if ( typeof define == 'function' && define.amd ) { 3730 // AMD 3731 define( 'isotope/js/layout-modes/masonry',[ 3732 '../layout-mode', 3733 'masonry/masonry' 3734 ], 3735 factory ); 3736 } else if ( typeof exports == 'object' ) { 3737 // CommonJS 3738 module.exports = factory( 3739 require('../layout-mode'), 3740 require('masonry-layout') 3741 ); 3742 } else { 3743 // browser global 3744 factory( 3745 window.Isotope.LayoutMode, 3746 window.Masonry 3747 ); 3748 } 3749 3750}( window, function factory( LayoutMode, Masonry ) { 3751'use strict'; 3752 3753// -------------------------- helpers -------------------------- // 3754 3755// extend objects 3756function extend( a, b ) { 3757 for ( var prop in b ) { 3758 a[ prop ] = b[ prop ]; 3759 } 3760 return a; 3761} 3762 3763// -------------------------- masonryDefinition -------------------------- // 3764 3765 // create an Outlayer layout class 3766 var MasonryMode = LayoutMode.create('masonry'); 3767 3768 // save on to these methods 3769 var _getElementOffset = MasonryMode.prototype._getElementOffset; 3770 var layout = MasonryMode.prototype.layout; 3771 var _getMeasurement = MasonryMode.prototype._getMeasurement; 3772 3773 // sub-class Masonry 3774 extend( MasonryMode.prototype, Masonry.prototype ); 3775 3776 // set back, as it was overwritten by Masonry 3777 MasonryMode.prototype._getElementOffset = _getElementOffset; 3778 MasonryMode.prototype.layout = layout; 3779 MasonryMode.prototype._getMeasurement = _getMeasurement; 3780 3781 var measureColumns = MasonryMode.prototype.measureColumns; 3782 MasonryMode.prototype.measureColumns = function() { 3783 // set items, used if measuring first item 3784 this.items = this.isotope.filteredItems; 3785 measureColumns.call( this ); 3786 }; 3787 3788 // HACK copy over isOriginLeft/Top options 3789 var _manageStamp = MasonryMode.prototype._manageStamp; 3790 MasonryMode.prototype._manageStamp = function() { 3791 this.options.isOriginLeft = this.isotope.options.isOriginLeft; 3792 this.options.isOriginTop = this.isotope.options.isOriginTop; 3793 _manageStamp.apply( this, arguments ); 3794 }; 3795 3796 return MasonryMode; 3797 3798})); 3799 3800/** 3801 * fitRows layout mode 3802 */ 3803 3804( function( window, factory ) { 3805 'use strict'; 3806 // universal module definition 3807 if ( typeof define == 'function' && define.amd ) { 3808 // AMD 3809 define( 'isotope/js/layout-modes/fit-rows',[ 3810 '../layout-mode' 3811 ], 3812 factory ); 3813 } else if ( typeof exports == 'object' ) { 3814 // CommonJS 3815 module.exports = factory( 3816 require('../layout-mode') 3817 ); 3818 } else { 3819 // browser global 3820 factory( 3821 window.Isotope.LayoutMode 3822 ); 3823 } 3824 3825}( window, function factory( LayoutMode ) { 3826'use strict'; 3827 3828var FitRows = LayoutMode.create('fitRows'); 3829 3830FitRows.prototype._resetLayout = function() { 3831 this.x = 0; 3832 this.y = 0; 3833 this.maxY = 0; 3834 this._getMeasurement( 'gutter', 'outerWidth' ); 3835}; 3836 3837FitRows.prototype._getItemLayoutPosition = function( item ) { 3838 item.getSize(); 3839 3840 var itemWidth = item.size.outerWidth + this.gutter; 3841 // if this element cannot fit in the current row 3842 var containerWidth = this.isotope.size.innerWidth + this.gutter; 3843 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 3844 this.x = 0; 3845 this.y = this.maxY; 3846 } 3847 3848 var position = { 3849 x: this.x, 3850 y: this.y 3851 }; 3852 3853 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 3854 this.x += itemWidth; 3855 3856 return position; 3857}; 3858 3859FitRows.prototype._getContainerSize = function() { 3860 return { height: this.maxY }; 3861}; 3862 3863return FitRows; 3864 3865})); 3866 3867/** 3868 * vertical layout mode 3869 */ 3870 3871( function( window, factory ) { 3872 'use strict'; 3873 // universal module definition 3874 if ( typeof define == 'function' && define.amd ) { 3875 // AMD 3876 define( 'isotope/js/layout-modes/vertical',[ 3877 '../layout-mode' 3878 ], 3879 factory ); 3880 } else if ( typeof exports == 'object' ) { 3881 // CommonJS 3882 module.exports = factory( 3883 require('../layout-mode') 3884 ); 3885 } else { 3886 // browser global 3887 factory( 3888 window.Isotope.LayoutMode 3889 ); 3890 } 3891 3892}( window, function factory( LayoutMode ) { 3893'use strict'; 3894 3895var Vertical = LayoutMode.create( 'vertical', { 3896 horizontalAlignment: 0 3897}); 3898 3899Vertical.prototype._resetLayout = function() { 3900 this.y = 0; 3901}; 3902 3903Vertical.prototype._getItemLayoutPosition = function( item ) { 3904 item.getSize(); 3905 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 3906 this.options.horizontalAlignment; 3907 var y = this.y; 3908 this.y += item.size.outerHeight; 3909 return { x: x, y: y }; 3910}; 3911 3912Vertical.prototype._getContainerSize = function() { 3913 return { height: this.y }; 3914}; 3915 3916return Vertical; 3917 3918})); 3919 3920/*! 3921 * Isotope v2.2.2 3922 * 3923 * Licensed GPLv3 for open source use 3924 * or Isotope Commercial License for commercial use 3925 * 3926 * http://isotope.metafizzy.co 3927 * Copyright 2015 Metafizzy 3928 */ 3929 3930( function( window, factory ) { 3931 'use strict'; 3932 // universal module definition 3933 3934 if ( typeof define == 'function' && define.amd ) { 3935 // AMD 3936 define( [ 3937 'outlayer/outlayer', 3938 'get-size/get-size', 3939 'matches-selector/matches-selector', 3940 'fizzy-ui-utils/utils', 3941 'isotope/js/item', 3942 'isotope/js/layout-mode', 3943 // include default layout modes 3944 'isotope/js/layout-modes/masonry', 3945 'isotope/js/layout-modes/fit-rows', 3946 'isotope/js/layout-modes/vertical' 3947 ], 3948 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 3949 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 3950 }); 3951 } else if ( typeof exports == 'object' ) { 3952 // CommonJS 3953 module.exports = factory( 3954 window, 3955 require('outlayer'), 3956 require('get-size'), 3957 require('desandro-matches-selector'), 3958 require('fizzy-ui-utils'), 3959 require('./item'), 3960 require('./layout-mode'), 3961 // include default layout modes 3962 require('./layout-modes/masonry'), 3963 require('./layout-modes/fit-rows'), 3964 require('./layout-modes/vertical') 3965 ); 3966 } else { 3967 // browser global 3968 window.Isotope = factory( 3969 window, 3970 window.Outlayer, 3971 window.getSize, 3972 window.matchesSelector, 3973 window.fizzyUIUtils, 3974 window.Isotope.Item, 3975 window.Isotope.LayoutMode 3976 ); 3977 } 3978 3979}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 3980 Item, LayoutMode ) { 3981 3982 3983 3984// -------------------------- vars -------------------------- // 3985 3986var jQuery = window.jQuery; 3987 3988// -------------------------- helpers -------------------------- // 3989 3990var trim = String.prototype.trim ? 3991 function( str ) { 3992 return str.trim(); 3993 } : 3994 function( str ) { 3995 return str.replace( /^\s+|\s+$/g, '' ); 3996 }; 3997 3998var docElem = document.documentElement; 3999 4000var getText = docElem.textContent ? 4001 function( elem ) { 4002 return elem.textContent; 4003 } : 4004 function( elem ) { 4005 return elem.innerText; 4006 }; 4007 4008// -------------------------- isotopeDefinition -------------------------- // 4009 4010 // create an Outlayer layout class 4011 var Isotope = Outlayer.create( 'isotope', { 4012 layoutMode: "masonry", 4013 isJQueryFiltering: true, 4014 sortAscending: true 4015 }); 4016 4017 Isotope.Item = Item; 4018 Isotope.LayoutMode = LayoutMode; 4019 4020 Isotope.prototype._create = function() { 4021 this.itemGUID = 0; 4022 // functions that sort items 4023 this._sorters = {}; 4024 this._getSorters(); 4025 // call super 4026 Outlayer.prototype._create.call( this ); 4027 4028 // create layout modes 4029 this.modes = {}; 4030 // start filteredItems with all items 4031 this.filteredItems = this.items; 4032 // keep of track of sortBys 4033 this.sortHistory = [ 'original-order' ]; 4034 // create from registered layout modes 4035 for ( var name in LayoutMode.modes ) { 4036 this._initLayoutMode( name ); 4037 } 4038 }; 4039 4040 Isotope.prototype.reloadItems = function() { 4041 // reset item ID counter 4042 this.itemGUID = 0; 4043 // call super 4044 Outlayer.prototype.reloadItems.call( this ); 4045 }; 4046 4047 Isotope.prototype._itemize = function() { 4048 var items = Outlayer.prototype._itemize.apply( this, arguments ); 4049 // assign ID for original-order 4050 for ( var i=0, len = items.length; i < len; i++ ) { 4051 var item = items[i]; 4052 item.id = this.itemGUID++; 4053 } 4054 this._updateItemsSortData( items ); 4055 return items; 4056 }; 4057 4058 4059 // -------------------------- layout -------------------------- // 4060 4061 Isotope.prototype._initLayoutMode = function( name ) { 4062 var Mode = LayoutMode.modes[ name ]; 4063 // set mode options 4064 // HACK extend initial options, back-fill in default options 4065 var initialOpts = this.options[ name ] || {}; 4066 this.options[ name ] = Mode.options ? 4067 utils.extend( Mode.options, initialOpts ) : initialOpts; 4068 // init layout mode instance 4069 this.modes[ name ] = new Mode( this ); 4070 }; 4071 4072 4073 Isotope.prototype.layout = function() { 4074 // if first time doing layout, do all magic 4075 if ( !this._isLayoutInited && this.options.isInitLayout ) { 4076 this.arrange(); 4077 return; 4078 } 4079 this._layout(); 4080 }; 4081 4082 // private method to be used in layout() & magic() 4083 Isotope.prototype._layout = function() { 4084 // don't animate first layout 4085 var isInstant = this._getIsInstant(); 4086 // layout flow 4087 this._resetLayout(); 4088 this._manageStamps(); 4089 this.layoutItems( this.filteredItems, isInstant ); 4090 4091 // flag for initalized 4092 this._isLayoutInited = true; 4093 }; 4094 4095 // filter + sort + layout 4096 Isotope.prototype.arrange = function( opts ) { 4097 // set any options pass 4098 this.option( opts ); 4099 this._getIsInstant(); 4100 // filter, sort, and layout 4101 4102 // filter 4103 var filtered = this._filter( this.items ); 4104 this.filteredItems = filtered.matches; 4105 4106 var _this = this; 4107 function hideReveal() { 4108 _this.reveal( filtered.needReveal ); 4109 _this.hide( filtered.needHide ); 4110 } 4111 4112 this._bindArrangeComplete(); 4113 4114 if ( this._isInstant ) { 4115 this._noTransition( hideReveal ); 4116 } else { 4117 hideReveal(); 4118 } 4119 4120 this._sort(); 4121 this._layout(); 4122 }; 4123 // alias to _init for main plugin method 4124 Isotope.prototype._init = Isotope.prototype.arrange; 4125 4126 // HACK 4127 // Don't animate/transition first layout 4128 // Or don't animate/transition other layouts 4129 Isotope.prototype._getIsInstant = function() { 4130 var isInstant = this.options.isLayoutInstant !== undefined ? 4131 this.options.isLayoutInstant : !this._isLayoutInited; 4132 this._isInstant = isInstant; 4133 return isInstant; 4134 }; 4135 4136 // listen for layoutComplete, hideComplete and revealComplete 4137 // to trigger arrangeComplete 4138 Isotope.prototype._bindArrangeComplete = function() { 4139 // listen for 3 events to trigger arrangeComplete 4140 var isLayoutComplete, isHideComplete, isRevealComplete; 4141 var _this = this; 4142 function arrangeParallelCallback() { 4143 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 4144 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 4145 } 4146 } 4147 this.once( 'layoutComplete', function() { 4148 isLayoutComplete = true; 4149 arrangeParallelCallback(); 4150 }); 4151 this.once( 'hideComplete', function() { 4152 isHideComplete = true; 4153 arrangeParallelCallback(); 4154 }); 4155 this.once( 'revealComplete', function() { 4156 isRevealComplete = true; 4157 arrangeParallelCallback(); 4158 }); 4159 }; 4160 4161 // -------------------------- filter -------------------------- // 4162 4163 Isotope.prototype._filter = function( items ) { 4164 var filter = this.options.filter;
4165 filter = filter || '*'; 4166 var matches = []; 4167 var hiddenMatched = []; 4168 var visibleUnmatched = []; 4169 4170 var test = this._getFilterTest( filter ); 4171 4172 // test each item 4173 for ( var i=0, len = items.length; i < len; i++ ) { 4174 var item = items[i]; 4175 if ( item.isIgnored ) { 4176 continue; 4177 } 4178 // add item to either matched or unmatched group 4179 var isMatched = test( item ); 4180 // item.isFilterMatched = isMatched; 4181 // add to matches if its a match 4182 if ( isMatched ) { 4183 matches.push( item ); 4184 } 4185 // add to additional group if item needs to be hidden or revealed 4186 if ( isMatched && item.isHidden ) { 4187 hiddenMatched.push( item ); 4188 } else if ( !isMatched && !item.isHidden ) { 4189 visibleUnmatched.push( item ); 4190 } 4191 } 4192 4193 // return collections of items to be manipulated 4194 return { 4195 matches: matches, 4196 needReveal: hiddenMatched, 4197 needHide: visibleUnmatched 4198 }; 4199 }; 4200 4201 // get a jQuery, function, or a matchesSelector test given the filter 4202 Isotope.prototype._getFilterTest = function( filter ) { 4203 if ( jQuery && this.options.isJQueryFiltering ) { 4204 // use jQuery 4205 return function( item ) { 4206 return jQuery( item.element ).is( filter ); 4207 }; 4208 } 4209 if ( typeof filter == 'function' ) { 4210 // use filter as function 4211 return function( item ) { 4212 return filter( item.element ); 4213 }; 4214 } 4215 // default, use filter as selector string 4216 return function( item ) { 4217 return matchesSelector( item.element, filter ); 4218 }; 4219 }; 4220 4221 // -------------------------- sorting -------------------------- // 4222 4223 /** 4224 * @params {Array} elems 4225 * @public 4226 */ 4227 Isotope.prototype.updateSortData = function( elems ) { 4228 // get items 4229 var items; 4230 if ( elems ) { 4231 elems = utils.makeArray( elems ); 4232 items = this.getItems( elems ); 4233 } else { 4234 // update all items if no elems provided 4235 items = this.items; 4236 } 4237 4238 this._getSorters(); 4239 this._updateItemsSortData( items ); 4240 }; 4241 4242 Isotope.prototype._getSorters = function() { 4243 var getSortData = this.options.getSortData; 4244 for ( var key in getSortData ) { 4245 var sorter = getSortData[ key ]; 4246 this._sorters[ key ] = mungeSorter( sorter ); 4247 } 4248 }; 4249 4250 /** 4251 * @params {Array} items - of Isotope.Items 4252 * @private 4253 */ 4254 Isotope.prototype._updateItemsSortData = function( items ) { 4255 // do not update if no items 4256 var len = items && items.length; 4257 4258 for ( var i=0; len && i < len; i++ ) { 4259 var item = items[i]; 4260 item.updateSortData(); 4261 } 4262 }; 4263 4264 // ----- munge sorter ----- // 4265 4266 // encapsulate this, as we just need mungeSorter 4267 // other functions in here are just for munging 4268 var mungeSorter = ( function() { 4269 // add a magic layer to sorters for convienent shorthands 4270 // `.foo-bar` will use the text of .foo-bar querySelector 4271 // `[foo-bar]` will use attribute 4272 // you can also add parser 4273 // `.foo-bar parseInt` will parse that as a number 4274 function mungeSorter( sorter ) { 4275 // if not a string, return function or whatever it is 4276 if ( typeof sorter != 'string' ) { 4277 return sorter; 4278 } 4279 // parse the sorter string 4280 var args = trim( sorter ).split(' '); 4281 var query = args[0]; 4282 // check if query looks like [an-attribute] 4283 var attrMatch = query.match( /^\[(.+)\]$/ ); 4284 var attr = attrMatch && attrMatch[1]; 4285 var getValue = getValueGetter( attr, query ); 4286 // use second argument as a parser 4287 var parser = Isotope.sortDataParsers[ args[1] ]; 4288 // parse the value, if there was a parser 4289 sorter = parser ? function( elem ) { 4290 return elem && parser( getValue( elem ) ); 4291 } : 4292 // otherwise just return value 4293 function( elem ) { 4294 return elem && getValue( elem ); 4295 }; 4296 4297 return sorter; 4298 } 4299 4300 // get an attribute getter, or get text of the querySelector 4301 function getValueGetter( attr, query ) { 4302 var getValue; 4303 // if query looks like [foo-bar], get attribute 4304 if ( attr ) { 4305 getValue = function( elem ) { 4306 return elem.getAttribute( attr ); 4307 }; 4308 } else { 4309 // otherwise, assume its a querySelector, and get its text 4310 getValue = function( elem ) { 4311 var child = elem.querySelector( query ); 4312 return child && getText( child ); 4313 }; 4314 } 4315 return getValue; 4316 } 4317 4318 return mungeSorter; 4319 })(); 4320 4321 // parsers used in getSortData shortcut strings 4322 Isotope.sortDataParsers = { 4323 'parseInt': function( val ) { 4324 return parseInt( val, 10 ); 4325 }, 4326 'parseFloat': function( val ) { 4327 return parseFloat( val ); 4328 } 4329 }; 4330 4331 // ----- sort method ----- // 4332 4333 // sort filteredItem order 4334 Isotope.prototype._sort = function() { 4335 var sortByOpt = this.options.sortBy; 4336 if ( !sortByOpt ) { 4337 return; 4338 } 4339 // concat all sortBy and sortHistory 4340 var sortBys = [].concat.apply( sortByOpt, this.sortHistory ); 4341 // sort magic 4342 var itemSorter = getItemSorter( sortBys, this.options.sortAscending ); 4343 this.filteredItems.sort( itemSorter ); 4344 // keep track of sortBy History 4345 if ( sortByOpt != this.sortHistory[0] ) { 4346 // add to front, oldest goes in last 4347 this.sortHistory.unshift( sortByOpt ); 4348 } 4349 }; 4350 4351 // returns a function used for sorting 4352 function getItemSorter( sortBys, sortAsc ) { 4353 return function sorter( itemA, itemB ) { 4354 // cycle through all sortKeys 4355 for ( var i = 0, len = sortBys.length; i < len; i++ ) { 4356 var sortBy = sortBys[i]; 4357 var a = itemA.sortData[ sortBy ]; 4358 var b = itemB.sortData[ sortBy ]; 4359 if ( a > b || a < b ) { 4360 // if sortAsc is an object, use the value given the sortBy key
4361 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 4362 var direction = isAscending ? 1 : -1; 4363 return ( a > b ? 1 : -1 ) * direction; 4364 } 4365 } 4366 return 0; 4367 }; 4368 } 4369 4370 // -------------------------- methods -------------------------- // 4371 4372 // get layout mode 4373 Isotope.prototype._mode = function() { 4374 var layoutMode = this.options.layoutMode; 4375 var mode = this.modes[ layoutMode ]; 4376 if ( !mode ) { 4377 // TODO console.error 4378 throw new Error( 'No layout mode: ' + layoutMode ); 4379 } 4380 // HACK sync mode's options 4381 // any options set after init for layout mode need to be synced 4382 mode.options = this.options[ layoutMode ]; 4383 return mode; 4384 }; 4385 4386 Isotope.prototype._resetLayout = function() { 4387 // trigger original reset layout 4388 Outlayer.prototype._resetLayout.call( this ); 4389 this._mode()._resetLayout(); 4390 }; 4391 4392 Isotope.prototype._getItemLayoutPosition = function( item ) { 4393 return this._mode()._getItemLayoutPosition( item ); 4394 }; 4395 4396 Isotope.prototype._manageStamp = function( stamp ) { 4397 this._mode()._manageStamp( stamp ); 4398 }; 4399 4400 Isotope.prototype._getContainerSize = function() { 4401 return this._mode()._getContainerSize(); 4402 }; 4403 4404 Isotope.prototype.needsResizeLayout = function() { 4405 return this._mode().needsResizeLayout(); 4406 }; 4407 4408 // -------------------------- adding & removing -------------------------- // 4409 4410 // HEADS UP overwrites default Outlayer appended 4411 Isotope.prototype.appended = function( elems ) { 4412 var items = this.addItems( elems ); 4413 if ( !items.length ) { 4414 return; 4415 } 4416 // filter, layout, reveal new items 4417 var filteredItems = this._filterRevealAdded( items ); 4418 // add to filteredItems 4419 this.filteredItems = this.filteredItems.concat( filteredItems ); 4420 }; 4421 4422 // HEADS UP overwrites default Outlayer prepended 4423 Isotope.prototype.prepended = function( elems ) { 4424 var items = this._itemize( elems ); 4425 if ( !items.length ) { 4426 return; 4427 } 4428 // start new layout 4429 this._resetLayout(); 4430 this._manageStamps(); 4431 // filter, layout, reveal new items 4432 var filteredItems = this._filterRevealAdded( items ); 4433 // layout previous items 4434 this.layoutItems( this.filteredItems ); 4435 // add to items and filteredItems 4436 this.filteredItems = filteredItems.concat( this.filteredItems ); 4437 this.items = items.concat( this.items ); 4438 }; 4439 4440 Isotope.prototype._filterRevealAdded = function( items ) { 4441 var filtered = this._filter( items ); 4442 this.hide( filtered.needHide ); 4443 // reveal all new items 4444 this.reveal( filtered.matches ); 4445 // layout new items, no transition 4446 this.layoutItems( filtered.matches, true ); 4447 return filtered.matches; 4448 }; 4449 4450 /** 4451 * Filter, sort, and layout newly-appended item elements 4452 * @param {Array or NodeList or Element} elems 4453 */ 4454 Isotope.prototype.insert = function( elems ) { 4455 var items = this.addItems( elems ); 4456 if ( !items.length ) { 4457 return; 4458 } 4459 // append item elements 4460 var i, item; 4461 var len = items.length; 4462 for ( i=0; i < len; i++ ) { 4463 item = items[i]; 4464 this.element.appendChild( item.element ); 4465 } 4466 // filter new stuff 4467 var filteredInsertItems = this._filter( items ).matches; 4468 // set flag 4469 for ( i=0; i < len; i++ ) { 4470 items[i].isLayoutInstant = true; 4471 } 4472 this.arrange(); 4473 // reset flag 4474 for ( i=0; i < len; i++ ) { 4475 delete items[i].isLayoutInstant; 4476 } 4477 this.reveal( filteredInsertItems ); 4478 }; 4479 4480 var _remove = Isotope.prototype.remove; 4481 Isotope.prototype.remove = function( elems ) { 4482 elems = utils.makeArray( elems ); 4483 var removeItems = this.getItems( elems ); 4484 // do regular thing 4485 _remove.call( this, elems ); 4486 // bail if no items to remove 4487 var len = removeItems && removeItems.length; 4488 if ( !len ) { 4489 return; 4490 } 4491 // remove elems from filteredItems 4492 for ( var i=0; i < len; i++ ) { 4493 var item = removeItems[i]; 4494 // remove item from collection 4495 utils.removeFrom( this.filteredItems, item ); 4496 } 4497 }; 4498 4499 Isotope.prototype.shuffle = function() { 4500 // update random sortData 4501 for ( var i=0, len = this.items.length; i < len; i++ ) { 4502 var item = this.items[i]; 4503 item.sortData.random = Math.random(); 4504 } 4505 this.options.sortBy = 'random'; 4506 this._sort(); 4507 this._layout(); 4508 }; 4509 4510 /** 4511 * trigger fn without transition 4512 * kind of hacky to have this in the first place 4513 * @param {Function} fn 4514 * @returns ret 4515 * @private 4516 */ 4517 Isotope.prototype._noTransition = function( fn ) { 4518 // save transitionDuration before disabling 4519 var transitionDuration = this.options.transitionDuration; 4520 // disable transition 4521 this.options.transitionDuration = 0; 4522 // do it 4523 var returnValue = fn.call( this ); 4524 // re-enable transition for reveal 4525 this.options.transitionDuration = transitionDuration; 4526 return returnValue; 4527 }; 4528 4529 // ----- helper methods ----- // 4530 4531 /** 4532 * getter method for getting filtered item elements 4533 * @returns {Array} elems - collection of item elements 4534 */ 4535 Isotope.prototype.getFilteredItemElements = function() { 4536 var elems = []; 4537 for ( var i=0, len = this.filteredItems.length; i < len; i++ ) { 4538 elems.push( this.filteredItems[i].element ); 4539 } 4540 return elems; 4541 }; 4542 4543 // ----- ----- // 4544 4545 return Isotope; 4546 4547})); 4548 4549 4550/*! 4551 * Packery layout mode PACKAGED v1.1.1 4552 * sub-classes Packery 4553 * http://packery.metafizzy.co 4554 */ 4555 4556!function(a){function b(a){return new RegExp("(^|\\s+)"+a+"(\\s+|$)")}function c(a,b){var c=d(a,b)?f:e;c(a,b)}var d,e,f;"classList"in document.documentElement?(d=function(a,b){return a.classList.contains(b)}
4556,e=function(a,b){a.classList.add(b)},f=function(a,b){a.classList.remove(b)}):(d=function(a,c){return b(c).test(a.className)},e=function(a,b){d(a,b)||(a.className=a.className+" "+b)},f=function(a,c){a.className=a.className.replace(b(c)," ")});var g={hasClass:d,addClass:e,removeClass:f,toggleClass:c,has:d,add:e,remove:f,toggle:c};"function"==typeof define&&define.amd?define("classie/classie",g):"object"==typeof exports?module.exports=g:a.classie=g}(window),function(a){function b(){function a(b){for(var c in a.defaults)this[c]=a.defaults[c];for(c in b)this[c]=b[c]}return c.Rect=a,a.defaults={x:0,y:0,width:0,height:0},a.prototype.contains=function(a){var b=a.width||0,c=a.height||0;return this.x<=a.x&&this.y<=a.y&&this.x+this.width>=a.x+b&&this.y+this.height>=a.y+c},a.prototype.overlaps=function(a){var b=this.x+this.width,c=this.y+this.height,d=a.x+a.width,e=a.y+a.height;return this.x<d&&b>a.x&&this.y<e&&c>a.y},a.prototype.getMaximalFreeRects=function(b){if(!this.overlaps(b))return!1;var c,d=[],e=this.x+this.width,f=this.y+this.height,g=b.x+b.width,h=b.y+b.height;return this.y<b.y&&(c=new a({x:this.x,y:this.y,width:this.width,height:b.y-this.y}),d.push(c)),e>g&&(c=new a({x:g,y:this.y,width:e-g,height:this.height}),d.push(c)),f>h&&(c=new a({x:this.x,y:h,width:this.width,height:f-h}),d.push(c)),this.x<b.x&&(c=new a({x:this.x,y:this.y,width:b.x-this.x,height:this.height}),d.push(c)),d},a.prototype.canFit=function(a){return this.width>=a.width&&this.height>=a.height},a}var c=a.Packery=function(){};"function"==typeof define&&define.amd?define("packery/js/rect",b):"object"==typeof exports?module.exports=b():(a.Packery=a.Packery||{},a.Packery.Rect=b())}(window),function(a){function b(a){function b(a,b,c){this.width=a||0,this.height=b||0,this.sortDirection=c||"downwardLeftToRight",this.reset()}b.prototype.reset=function(){this.spaces=[],this.newSpaces=[];var b=new a({x:0,y:0,width:this.width,height:this.height});this.spaces.push(b),this.sorter=c[this.sortDirection]||c.downwardLeftToRight},b.prototype.pack=function(a){for(var b=0,c=this.spaces.length;c>b;b++){var d=this.spaces[b];if(d.canFit(a)){this.placeInSpace(a,d);break}}},b.prototype.placeInSpace=function(a,b){a.x=b.x,a.y=b.y,this.placed(a)},b.prototype.placed=function(a){for(var b=[],c=0,d=this.spaces.length;d>c;c++){var e=this.spaces[c],f=e.getMaximalFreeRects(a);f?b.push.apply(b,f):b.push(e)}this.spaces=b,this.mergeSortSpaces()},b.prototype.mergeSortSpaces=function(){b.mergeRects(this.spaces),this.spaces.sort(this.sorter)},b.prototype.addSpace=function(a){this.spaces.push(a),this.mergeSortSpaces()},b.mergeRects=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];if(d){var e=a.slice(0);e.splice(b,1);for(var f=0,g=0,h=e.length;h>g;g++){var i=e[g],j=b>g?0:1;d.contains(i)&&(a.splice(g+j-f,1),f++)}}}return a};var c={downwardLeftToRight:function(a,b){return a.y-b.y||a.x-b.x},rightwardTopToBottom:function(a,b){return a.x-b.x||a.y-b.y}};return b}if("function"==typeof define&&define.amd)define("packery/js/packer",["./rect"],b);else if("object"==typeof exports)module.exports=b(require("./rect"));else{var c=a.Packery=a.Packery||{};c.Packer=b(c.Rect)}}(window),function(a){function b(a,b,c){var d=a("transform"),e=function(){b.Item.apply(this,arguments)};e.prototype=new b.Item;var f=e.prototype._create;return e.prototype._create=function(){f.call(this),this.rect=new c,this.placeRect=new c},e.prototype.dragStart=function(){this.getPosition(),this.removeTransitionStyles(),this.isTransitioning&&d&&(this.element.style[d]="none"),this.getSize(),this.isPlacing=!0,this.needsPositioning=!1,this.positionPlaceRect(this.position.x,this.position.y),this.isTransitioning=!1,this.didDrag=!1},e.prototype.dragMove=function(a,b){this.didDrag=!0;var c=this.layout.size;a-=c.paddingLeft,b-=c.paddingTop,this.positionPlaceRect(a,b)},e.prototype.dragStop=function(){this.getPosition();var a=this.position.x!==this.placeRect.x,b=this.position.y!==this.placeRect.y;this.needsPositioning=a||b,this.didDrag=!1},e.prototype.positionPlaceRect=function(a,b,c){this.placeRect.x=this.getPlaceRectCoord(a,!0),this.placeRect.y=this.getPlaceRectCoord(b,!1,c)},e.prototype.getPlaceRectCoord=function(a,b,c){var d=b?"Width":"Height",e=this.size["outer"+d],f=this.layout[b?"columnWidth":"rowHeight"],g=this.layout.size["inner"+d];b||(g=Math.max(g,this.layout.maxY),this.layout.rowHeight||(g-=this.layout.gutter));var h;if(f){f+=this.layout.gutter,g+=b?this.layout.gutter:0,a=Math.round(a/f);var i;i=this.layout.options.isHorizontal?b?"ceil":"floor":b?"floor":"ceil";var j=Math[i](g/f);j-=Math.ceil(e/f),h=j}else h=g-e;return a=c?a:Math.min(a,h),a*=f||1,Math.max(0,a)},e.prototype.copyPlaceRectPosition=function(){this.rect.x=this.placeRect.x,this.rect.y=this.placeRect.y},e.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.layout.packer.addSpace(this.rect),this.emitEvent("remove",[this])},e}"function"==typeof define&&define.amd?define("packery/js/item",["get-style-property/get-style-property","outlayer/outlayer","./rect"],b):"object"==typeof exports?module.exports=b(require("desandro-get-style-property"),require("outlayer"),require("./rect")):a.Packery.Item=b(a.getStyleProperty,a.Outlayer,a.Packery.Rect)}(window),function(a){function b(a,b,c,d,e,f){function g(a,b){return a.position.y-b.position.y||a.position.x-b.position.x}function h(a,b){return a.position.x-b.position.x||a.position.y-b.position.y}d.prototype.canFit=function(a){return this.width>=a.width-1&&this.height>=a.height-1};var i=c.create("packery");return i.Item=f,i.prototype._create=function(){c.prototype._create.call(this),this.packer=new e,this.stamp(this.options.stamped);var a=this;this.handleDraggabilly={dragStart:function(b){a.itemDragStart(b.element)},dragMove:function(b){a.itemDragMove(b.element,b.position.x,b.position.y)},dragEnd:function(b){a.itemDragEnd(b.element)}},this.handleUIDraggable={start:function(b){a.itemDragStart(b.currentTarget)},drag:function(b,c){a.itemDragMove(b.currentTarget,c.position.left,c.position.top)},stop:function(b){a.itemDragEnd(b.currentTarget)}}}
4556,i.prototype._resetLayout=function(){this.getSize(),this._getMeasurements();var a=this.packer;this.options.isHorizontal?(a.width=Number.POSITIVE_INFINITY,a.height=this.size.innerHeight+this.gutter,a.sortDirection="rightwardTopToBottom"):(a.width=this.size.innerWidth+this.gutter,a.height=Number.POSITIVE_INFINITY,a.sortDirection="downwardLeftToRight"),a.reset(),this.maxY=0,this.maxX=0},i.prototype._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},i.prototype._getItemLayoutPosition=function(a){return this._packItem(a),a.rect},i.prototype._packItem=function(a){this._setRectSize(a.element,a.rect),this.packer.pack(a.rect),this._setMaxXY(a.rect)},i.prototype._setMaxXY=function(a){this.maxX=Math.max(a.x+a.width,this.maxX),this.maxY=Math.max(a.y+a.height,this.maxY)},i.prototype._setRectSize=function(a,c){var d=b(a),e=d.outerWidth,f=d.outerHeight;(e||f)&&(e=this._applyGridGutter(e,this.columnWidth),f=this._applyGridGutter(f,this.rowHeight)),c.width=Math.min(e,this.packer.width),c.height=Math.min(f,this.packer.height)},i.prototype._applyGridGutter=function(a,b){if(!b)return a+this.gutter;b+=this.gutter;var c=a%b,d=c&&1>c?"round":"ceil";return a=Math[d](a/b)*b},i.prototype._getContainerSize=function(){return this.options.isHorizontal?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},i.prototype._manageStamp=function(a){var b,c=this.getItem(a);if(c&&c.isPlacing)b=c.placeRect;else{var e=this._getElementOffset(a);b=new d({x:this.options.isOriginLeft?e.left:e.right,y:this.options.isOriginTop?e.top:e.bottom})}this._setRectSize(a,b),this.packer.placed(b),this._setMaxXY(b)},i.prototype.sortItemsByPosition=function(){var a=this.options.isHorizontal?h:g;this.items.sort(a)},i.prototype.fit=function(a,b,c){var d=this.getItem(a);d&&(this._getMeasurements(),this.stamp(d.element),d.getSize(),d.isPlacing=!0,b=void 0===b?d.rect.x:b,c=void 0===c?d.rect.y:c,d.positionPlaceRect(b,c,!0),this._bindFitEvents(d),d.moveTo(d.placeRect.x,d.placeRect.y),this.layout(),this.unstamp(d.element),this.sortItemsByPosition(),d.isPlacing=!1,d.copyPlaceRectPosition())},i.prototype._bindFitEvents=function(a){function b(){d++,2===d&&c.emitEvent("fitComplete",[c,a])}var c=this,d=0;a.on("layout",function(){return b(),!0}),this.on("layoutComplete",function(){return b(),!0})},i.prototype.resize=function(){var a=b(this.element),c=this.size&&a,d=this.options.isHorizontal?"innerHeight":"innerWidth";c&&a[d]===this.size[d]||this.layout()},i.prototype.itemDragStart=function(a){this.stamp(a);var b=this.getItem(a);b&&b.dragStart()},i.prototype.itemDragMove=function(a,b,c){function d(){f.layout(),delete f.dragTimeout}var e=this.getItem(a);e&&e.dragMove(b,c);var f=this;this.clearDragTimeout(),this.dragTimeout=setTimeout(d,40)},i.prototype.clearDragTimeout=function(){this.dragTimeout&&clearTimeout(this.dragTimeout)},i.prototype.itemDragEnd=function(b){var c,d=this.getItem(b);if(d&&(c=d.didDrag,d.dragStop()),!d||!c&&!d.needsPositioning)return void this.unstamp(b);a.add(d.element,"is-positioning-post-drag");var e=this._getDragEndLayoutComplete(b,d);d.needsPositioning?(d.on("layout",e),d.moveTo(d.placeRect.x,d.placeRect.y)):d&&d.copyPlaceRectPosition(),this.clearDragTimeout(),this.on("layoutComplete",e),this.layout()},i.prototype._getDragEndLayoutComplete=function(b,c){var d=c&&c.needsPositioning,e=0,f=d?2:1,g=this;return function(){return e++,e!==f?!0:(c&&(a.remove(c.element,"is-positioning-post-drag"),c.isPlacing=!1,
4556c.copyPlaceRectPosition()),g.unstamp(b),g.sortItemsByPosition(),d&&g.emitEvent("dragItemPositioned",[g,c]),!0)}},i.prototype.bindDraggabillyEvents=function(a){a.on("dragStart",this.handleDraggabilly.dragStart),a.on("dragMove",this.handleDraggabilly.dragMove),a.on("dragEnd",this.handleDraggabilly.dragEnd)},i.prototype.bindUIDraggableEvents=function(a){a.on("dragstart",this.handleUIDraggable.start).on("drag",this.handleUIDraggable.drag).on("dragstop",this.handleUIDraggable.stop)},i.Rect=d,i.Packer=e,i}"function"==typeof define&&define.amd?define("packery/js/packery",["classie/classie","get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],b):"object"==typeof exports?module.exports=b(require("desandro-classie"),require("get-size"),require("outlayer"),require("./rect"),require("./packer"),require("./item")):a.Packery=b(a.classie,a.getSize,a.Outlayer,a.Packery.Rect,a.Packery.Packer,a.Packery.Item)}(window),function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}function c(a,c,d){var e=a.create("packery"),f=e.prototype._getElementOffset,g=e.prototype._getMeasurement;b(e.prototype,c.prototype),e.prototype._getElementOffset=f,e.prototype._getMeasurement=g;var h=e.prototype._resetLayout;e.prototype._resetLayout=function(){this.packer=this.packer||new c.Packer,h.apply(this,arguments)};var i=e.prototype._getItemLayoutPosition;e.prototype._getItemLayoutPosition=function(a){return a.rect=a.rect||new c.Rect,i.call(this,a)};var j=e.prototype._manageStamp;return e.prototype._manageStamp=function(){this.options.isOriginLeft=this.isotope.options.isOriginLeft,this.options.isOriginTop=this.isotope.options.isOriginTop,j.apply(this,arguments)},e.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a,c=this.options.isHorizontal?"innerHeight":"innerWidth";return b&&a[c]!==this.size[c]},e}"function"==typeof define&&define.amd?define(["isotope/js/layout-mode","packery/js/packery","get-size/get-size"],c):"object"==typeof exports?module.exports=c(require("isotope-layout/js/layout-mode"),require("packery"),require("get-size")):c(a.Isotope.LayoutMode,a.Packery,a.getSize)}(window); 4557 4558/*! 4559 * cellsByRows layout mode for Isotope 4560 * v1.1.2 4561 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 4562 */ 4563 4564/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 4565 4566( function( window ) { 4567 4568'use strict'; 4569 4570function cellsByRowDefinition( LayoutMode ) { 4571 4572 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 4573 4574 CellsByRow.prototype._resetLayout = function() { 4575 // reset properties 4576 this.itemIndex = 0; 4577 // measurements 4578 this.getColumnWidth(); 4579 this.getRowHeight(); 4580 // set cols 4581 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 4582 this.cols = Math.max( this.cols, 1 ); 4583 }; 4584 4585 CellsByRow.prototype._getItemLayoutPosition = function( item ) { 4586 item.getSize(); 4587 var col = this.itemIndex % this.cols; 4588 var row = Math.floor( this.itemIndex / this.cols ); 4589 // center item within cell 4590 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 4591 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 4592 this.itemIndex++; 4593 return { x: x, y: y }; 4594 }; 4595 4596 CellsByRow.prototype._getContainerSize = function() { 4597 return { 4598 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 4599 }; 4600 }; 4601 4602 return CellsByRow; 4603 4604} 4605 4606if ( typeof define === 'function' && define.amd ) { 4607 // AMD 4608 define( [ 4609 'isotope/js/layout-mode' 4610 ], 4611 cellsByRowDefinition ); 4612} else if ( typeof exports === 'object' ) { 4613 // CommonJS 4614 module.exports = cellsByRowDefinition( 4615 require('isotope-layout/js/layout-mode') 4616 ); 4617} else { 4618 // browser global 4619 cellsByRowDefinition( 4620 window.Isotope.LayoutMode 4621 ); 4622} 4623 4624})( window ); 4625 4626/*! 4627 -------------------------------- 4628 Infinite Scroll 4629 -------------------------------- 4630 + https://github.com/paulirish/infinite-scroll 4631 + version 2.1.0 4632 + Copyright 2011/12 Paul Irish & Luke Shumard 4633 + Licensed under the MIT license 4634 4635 + Documentation: http://infinite-scroll.com/ 4636*/ 4637;(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(jQuery)}})(function(e,t){"use strict";e.infinitescroll=function(n,r,i){this.element=e(i);if(!this._create(n,r)){this.failed=true}};e.infinitescroll.defaults={loading:{finished:t,finishedMsg:"<em>Congratulations, you've reached the end of the internet.</em>",img:"data:image/gif;
4637base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oXHlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSH
4637MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2G
4637iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7",msg:null,msgText:"<em>Loading the next set of posts...</em>",selector:null,speed:"fast",start:t},state:{isDuringAjax:false,isInvalidPage:false,isDestroyed:false,isDone:false,isPaused:false,isBeyondMaxPage:false,currPage:1},debug:false,behavior:t,binder:e(window),nextSelector:"div.navigation a:first",navSelector:"div.navigation",contentSelector:null,extraScrollPx:150,itemSelector:"div.post",animate:false,pathParse:t,dataType:"html",appendCallback:true,bufferPx:40,errorCallback:function(){},infid:0,pixelsFromNavToBottom:t,path:t,prefill:false,maxPage:t};e.infinitescroll.prototype={_binding:function(n){var r=this,i=r.options;i.v="2.0b2.120520";if(!!i.behavior&&this["_binding_"+i.behavior]!==t){this["_binding_"+i.behavior].call(this);return}if(n!=="bind"&&n!=="unbind"){this._debug("Binding value "+n+" not valid");return false}if(n==="unbind"){this.options.binder.unbind("smartscroll.infscr."+r.options.infid)}else{this.options.binder[n]("smartscroll.infscr."+r.options.infid,function(){r.scroll()})}this._debug("Binding",n)},_create:function(r,i){var s=e.extend(true,{},e.infinitescroll.defaults,r);this.options=s;var o=e(window);var u=this;if(!u._validate(r)){return false}var a=e(s.nextSelector).attr("href");if(!a){this._debug("Navigation selector not found");return false}s.path=s.path||this._determinepath(a);s.contentSelector=s.contentSelector||this.element;s.loading.selector=s.loading.selector||s.contentSelector;s.loading.msg=s.loading.msg||e('<div id="infscr-loading"><img alt="Loading..." src="'+s.loading.img+'" /><div>'+s.loading.msgText+"</div></div>");(new Image).src=s.loading.img;if(s.pixelsFromNavToBottom===t){s.pixelsFromNavToBottom=e(document).height()-e(s.navSelector).offset().top;this._debug("pixelsFromNavToBottom: "+s.pixelsFromNavToBottom)}var f=this;s.loading.start=s.loading.start||function(){e(s.navSelector).hide();s.loading.msg.appendTo(s.loading.selector).show(s.loading.speed,e.proxy(function(){this.beginAjax(s)},f))};s.loading.finished=s.loading.finished||function(){if(!s.state.isBeyondMaxPage)s.loading.msg.fadeOut(s.loading.speed)};s.callback=function(n,r,u){if(!!s.behavior&&n["_callback_"+s.behavior]!==t){n["_callback_"+s.behavior].call(e(s.contentSelector)[0],r,u)}if(i){i.call(e(s.contentSelector)[0],r,s,u)}if(s.prefill){o.bind("resize.infinite-scroll",n._prefill)}};if(r.debug){if(Function.prototype.bind&&(typeof console==="object"||typeof console==="function")&&typeof console.log==="object"){["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function(e){console[e]=this.call(console[e],console)},Function.prototype.bind)}}this._setup();if(s.prefill){this._prefill()}return true},_prefill:function(){function i(){return e(n.options.contentSelector).height()<=r.height()}var n=this;var r=e(window);this._prefill=function(){if(i()){n.scroll()}r.bind("resize.infinite-scroll",function(){if(i()){r.unbind("resize.infinite-scroll");n.scroll()}})};this._prefill()},_debug:function(){if(true!==this.options.debug){return}if(typeof console!=="undefined"&&typeof console.log==="function"){if(Array.prototype.slice.call(arguments).length===1&&typeof Array.prototype.slice.call(arguments)[0]==="str
4637ing"){console.log(Array.prototype.slice.call(arguments).toString())}else{console.log(Array.prototype.slice.call(arguments))}}else if(!Function.prototype.bind&&typeof console!=="undefined"&&typeof console.log==="object"){Function.prototype.call.call(console.log,console,Array.prototype.slice.call(arguments))}},_determinepath:function(n){var r=this.options;if(!!r.behavior&&this["_determinepath_"+r.behavior]!==t){return this["_determinepath_"+r.behavior].call(this,n)}if(!!r.pathParse){this._debug("pathParse manual");return r.pathParse(n,this.options.state.currPage+1)}else if(n.match(/^(.*?)\b2\b(.*?$)/)){n=n.match(/^(.*?)\b2\b(.*?$)/).slice(1)}else if(n.match(/^(.*?)2(.*?$)/)){if(n.match(/^(.*?page=)2(\/.*|$)/)){n=n.match(/^(.*?page=)2(\/.*|$)/).slice(1);return n}n=n.match(/^(.*?)2(.*?$)/).slice(1)}else{if(n.match(/^(.*?page=)1(\/.*|$)/)){n=n.match(/^(.*?page=)1(\/.*|$)/).slice(1);return n}else{this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.");r.state.isInvalidPage=true}}this._debug("determinePath",n);return n},_error:function(n){var r=this.options;if(!!r.behavior&&this["_error_"+r.behavior]!==t){this["_error_"+r.behavior].call(this,n);return}if(n!=="destroy"&&n!=="end"){n="unknown"}this._debug("Error",n);if(n==="end"||r.state.isBeyondMaxPage){this._showdonemsg()}r.state.isDone=true;r.state.currPage=1;
4637r.state.isPaused=false;r.state.isBeyondMaxPage=false;this._binding("unbind")},_loadcallback:function(r,i,s){var o=this.options,u=this.options.callback,a=o.state.isDone?"done":!o.appendCallback?"no-append":"append",f;if(!!o.behavior&&this["_loadcallback_"+o.behavior]!==t){this["_loadcallback_"+o.behavior].call(this,r,i);return}switch(a){case"done":this._showdonemsg();return false;case"no-append":if(o.dataType==="html"){i="<div>"+i+"</div>";i=e(i).find(o.itemSelector)}if(i.length===0){return this._error("end")}break;case"append":var l=r.children();if(l.length===0){return this._error("end")}f=document.createDocumentFragment();while(r[0].firstChild){f.appendChild(r[0].firstChild)}this._debug("contentSelector",e(o.contentSelector)[0]);e(o.contentSelector)[0].appendChild(f);i=l.get();break}o.loading.finished.call(e(o.contentSelector)[0],o);if(o.animate){var c=e(window).scrollTop()+e(o.loading.msg).height()+o.extraScrollPx+"px";e("html,body").animate({scrollTop:c},800,function(){o.state.isDuringAjax=false})}if(!o.animate){o.state.isDuringAjax=false}u(this,i,s);if(o.prefill){this._prefill()}},_nearbottom:function(){var r=this.options,i=0+e(document).height()-r.binder.scrollTop()-e(window).height();if(!!r.behavior&&this["_nearbottom_"+r.behavior]!==t){return this["_nearbottom_"+r.behavior].call(this)}this._debug("math:",i,r.pixelsFromNavToBottom);return i-r.bufferPx<r.pixelsFromNavToBottom},_pausing:function(n){var r=this.options;if(!!r.behavior&&this["_pausing_"+r.behavior]!==t){this["_pausing_"+r.behavior].call(this,n);return}if(n!=="pause"&&n!=="resume"&&n!==null){this._debug("Invalid argument. Toggling pause value instead")}n=n&&(n==="pause"||n==="resume")?n:"toggle";
4637switch(n){case"pause":r.state.isPaused=true;break;case"resume":r.state.isPaused=false;break;case"toggle":r.state.isPaused=!r.state.isPaused;break}this._debug("Paused",r.state.isPaused);return false},_setup:function(){var n=this.options;if(!!n.behavior&&this["_setup_"+n.behavior]!==t){this["_setup_"+n.behavior].call(this);return}this._binding("bind");return false},_showdonemsg:function(){var r=this.options;if(!!r.behavior&&this["_showdonemsg_"+r.behavior]!==t){this["_showdonemsg_"+r.behavior].call(this);return}r.loading.msg.find("img").hide().parent().find("div").html(r.loading.finishedMsg).animate({opacity:1},2e3,function(){e(this).parent().fadeOut(r.loading.speed)});r.errorCallback.call(e(r.contentSelector)[0],"done")},_validate:function(n){for(var r in n){if(r.indexOf&&r.indexOf("Selector")>-1&&e(n[r]).length===0){this._debug("Your "+r+" found no elements.");return false}}return true},bind:function(){this._binding("bind")},destroy:function(){this.options.state.isDestroyed=true;this.options.loading.finished();return this._error("destroy")},pause:function(){this._pausing("pause")},resume:function(){this._pausing("resume")},beginAjax:function(r){var i=this,s=r.path,o,u,a,f;r.state.currPage++;if(r.maxPage!==t&&r.state.currPage>r.maxPage){r.state.isBeyondMaxPage=true;this.destroy();return}o=e(r.contentSelector).is("table, tbody")?e("<tbody/>"):e("<div/>");u=typeof s==="function"?s(r.state.currPage):s.join(r.state.currPage);i._debug("heading into ajax",u);a=r.dataType==="html"||r.dataType==="json"?r.dataType:"html+callback";if(r.appendCallback&&r.dataType==="html"){a+="+callback"}switch(a){case"html+callback":i._debug("Using HTML via .load() method");o.load(u+" "+r.itemSelector,t,function(t){i._loadcallback(o,t,u)});break;case"html":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({url:u,dataType:r.dataType,complete:function(t,n){f=typeof t.isResolved!=="undefined"?t.isResolved():n==="success"||n==="notmodified";if(f){i._loadcallback(o,t.responseText,u)}else{i._error("end")}}});break;case"json":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({dataType:"json",type:"GET",url:u,success:function(e,n,s){f=typeof s.isResolved!=="undefined"?s.isResolved():n==="success"||n==="notmodified";if(r.appendCallback){if(r.template!==t){var a=r.template(e);o.append(a);if(f){i._loadcallback(o,a)}else{i._error("end")}}else{i._debug("template must be defined.");i._error("end")}}else{if(f){i._loadcallback(o,e,u)}else{i._error("end")}}},error:function(){i._debug("JSON ajax request failed.");i._error("end")}});break}},retrieve:function(r){r=r||null;var i=this,s=i.options;if(!!s.behavior&&this["retrieve_"+s.behavior]!==t){this["retrieve_"+s.behavior].call(this,r);return}if(s.state.isDestroyed){this._debug("Instance is destroyed");return false}s.state.isDuringAjax=true;s.loading.start.call(e(s.contentSelector)[0],s)},scroll:function(){var n=this.options,r=n.state;if(!!n.behavior&&this["scroll_"+n.behavior]!==t){this["scroll_"+n.behavior].call(this);return}if(r.isDuringAjax||r.isInvalidPage||r.isDone||r.isDestroyed||r.isPaused){return}if(!this._nearbottom()){return}this.retrieve()},toggle:function(){this._pausing()},unbind:function(){this._binding("unbind")},update:function(n){if(e.isPlainObject(n)){this.options=e.extend(true,this.options,n)}}};e.fn.infinitescroll=function(n,r){var i=typeof n;switch(i){case"string":var s=Array.prototype.slice.call(arguments,1);this.each(function(){var t=e.data(this,"infinitescroll");if(!t){return false}if(!e.isFunction(t[n])||n.charAt(0)==="_"){return false}t[n].apply(t,s)});break;case"object":this.each(function(){var t=e.data(this,"infinitescroll");if(t){t.update(n)}else{t=new e.infinitescroll(n,r,this);if(!t.failed){e.data(this,"infinitescroll",t)}}});break}return this};var n=e.event,r;n.special.smartscroll={setup:function(){e(this).bind("scroll",n.special.smartscroll.handler)},teardown:function(){e(this).unbind("scroll",n.special.smartscroll.handler)},handler:function(t,n){var i=this,s=arguments;t.type="smartscroll";if(r){clearTimeout(r)}r=setTimeout(function(){e(i).trigger("smartscroll",s)},n==="execAsap"?0:100)}};e.fn.smartscroll=function(e){return e?this.bind("smartscroll",e):this.trigger("smartscroll",["execAsap"])}}); 4638 4639/*!
4640Waypoints - 4.0.0 4641Copyright © 2011-2015 Caleb Troughton 4642Licensed under the MIT license. 4643https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 4644*/ 4645(function() { 4646 'use strict' 4647 4648 var keyCounter = 0 4649 var allWaypoints = {} 4650 4651 /* http://imakewebthings.com/waypoints/api/waypoint */ 4652 function Waypoint(options) { 4653 if (!options) { 4654 throw new Error('No options passed to Waypoint constructor') 4655 } 4656 if (!options.element) { 4657 throw new Error('No element option passed to Waypoint constructor') 4658 } 4659 if (!options.handler) { 4660 throw new Error('No handler option passed to Waypoint constructor') 4661 } 4662 4663 this.key = 'waypoint-' + keyCounter 4664 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 4665 this.element = this.options.element 4666 this.adapter = new Waypoint.Adapter(this.element) 4667 this.callback = options.handler 4668 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 4669 this.enabled = this.options.enabled 4670 this.triggerPoint = null 4671 this.group = Waypoint.Group.findOrCreate({ 4672 name: this.options.group, 4673 axis: this.axis 4674 }) 4675 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 4676 4677 if (Waypoint.offsetAliases[this.options.offset]) { 4678 this.options.offset = Waypoint.offsetAliases[this.options.offset] 4679 } 4680 this.group.add(this) 4681 this.context.add(this) 4682 allWaypoints[this.key] = this 4683 keyCounter += 1 4684 } 4685 4686 /* Private */ 4687 Waypoint.prototype.queueTrigger = function(direction) { 4688 this.group.queueTrigger(this, direction) 4689 } 4690 4691 /* Private */ 4692 Waypoint.prototype.trigger = function(args) { 4693 if (!this.enabled) { 4694 return 4695 } 4696 if (this.callback) { 4697 this.callback.apply(this, args) 4698 } 4699 } 4700 4701 /* Public */ 4702 /* http://imakewebthings.com/waypoints/api/destroy */ 4703 Waypoint.prototype.destroy = function() { 4704 this.context.remove(this) 4705 this.group.remove(this) 4706 delete allWaypoints[this.key] 4707 } 4708 4709 /* Public */ 4710 /* http://imakewebthings.com/waypoints/api/disable */ 4711 Waypoint.prototype.disable = function() { 4712 this.enabled = false 4713 return this 4714 } 4715 4716 /* Public */ 4717 /* http://imakewebthings.com/waypoints/api/enable */ 4718 Waypoint.prototype.enable = function() { 4719 this.context.refresh() 4720 this.enabled = true 4721 return this 4722 } 4723 4724 /* Public */ 4725 /* http://imakewebthings.com/waypoints/api/next */ 4726 Waypoint.prototype.next = function() { 4727 return this.group.next(this) 4728 } 4729 4730 /* Public */ 4731 /* http://imakewebthings.com/waypoints/api/previous */ 4732 Waypoint.prototype.previous = function() { 4733 return this.group.previous(this) 4734 } 4735 4736 /* Private */ 4737 Waypoint.invokeAll = function(method) { 4738 var allWaypointsArray = []
4739 for (var waypointKey in allWaypoints) { 4740 allWaypointsArray.push(allWaypoints[waypointKey]) 4741 } 4742 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 4743 allWaypointsArray[i][method]() 4744 } 4745 } 4746 4747 /* Public */ 4748 /* http://imakewebthings.com/waypoints/api/destroy-all */ 4749 Waypoint.destroyAll = function() { 4750 Waypoint.invokeAll('destroy') 4751 } 4752 4753 /* Public */ 4754 /* http://imakewebthings.com/waypoints/api/disable-all */ 4755 Waypoint.disableAll = function() { 4756 Waypoint.invokeAll('disable') 4757 } 4758 4759 /* Public */ 4760 /* http://imakewebthings.com/waypoints/api/enable-all */ 4761 Waypoint.enableAll = function() { 4762 Waypoint.invokeAll('enable') 4763 } 4764 4765 /* Public */ 4766 /* http://imakewebthings.com/waypoints/api/refresh-all */ 4767 Waypoint.refreshAll = function() { 4768 Waypoint.Context.refreshAll() 4769 } 4770 4771 /* Public */ 4772 /* http://imakewebthings.com/waypoints/api/viewport-height */ 4773 Waypoint.viewportHeight = function() { 4774 return window.innerHeight || document.documentElement.clientHeight 4775 } 4776 4777 /* Public */ 4778 /* http://imakewebthings.com/waypoints/api/viewport-width */ 4779 Waypoint.viewportWidth = function() { 4780 return document.documentElement.clientWidth 4781 } 4782 4783 Waypoint.adapters = [] 4784 4785 Waypoint.defaults = { 4786 context: window, 4787 continuous: true, 4788 enabled: true, 4789 group: 'default', 4790 horizontal: false, 4791 offset: 0 4792 } 4793 4794 Waypoint.offsetAliases = { 4795 'bottom-in-view': function() { 4796 return this.context.innerHeight() - this.adapter.outerHeight() 4797 }, 4798 'right-in-view': function() { 4799 return this.context.innerWidth() - this.adapter.outerWidth() 4800 } 4801 } 4802 4803 window.Waypoint = Waypoint 4804}()) 4805;(function() { 4806 'use strict' 4807 4808 function requestAnimationFrameShim(callback) { 4809 window.setTimeout(callback, 1000 / 60) 4810 } 4811 4812 var keyCounter = 0 4813 var contexts = {} 4814 var Waypoint = window.Waypoint 4815 var oldWindowLoad = window.onload 4816 4817 /* http://imakewebthings.com/waypoints/api/context */ 4818 function Context(element) { 4819 this.element = element 4820 this.Adapter = Waypoint.Adapter 4821 this.adapter = new this.Adapter(element) 4822 this.key = 'waypoint-context-' + keyCounter 4823 this.didScroll = false 4824 this.didResize = false 4825 this.oldScroll = { 4826 x: this.adapter.scrollLeft(), 4827 y: this.adapter.scrollTop() 4828 } 4829 this.waypoints = { 4830 vertical: {}, 4831 horizontal: {} 4832 } 4833 4834 element.waypointContextKey = this.key 4835 contexts[element.waypointContextKey] = this 4836 keyCounter += 1 4837 4838 this.createThrottledScrollHandler() 4839 this.createThrottledResizeHandler() 4840 } 4841 4842 /* Private */ 4843 Context.prototype.add = function(waypoint) { 4844 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 4845 this.waypoints[axis][waypoint.key] = waypoint 4846 this.refresh() 4847 } 4848 4849 /* Private */ 4850 Context.prototype.checkEmpty = function() { 4851 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 4852 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 4853 if (horizontalEmpty && verticalEmpty) { 4854 this.adapter.off('.waypoints') 4855 delete contexts[this.key] 4856 } 4857 } 4858 4859 /* Private */ 4860 Context.prototype.createThrottledResizeHandler = function() { 4861 var self = this 4862 4863 function resizeHandler() { 4864 self.handleResize() 4865 self.didResize = false 4866 } 4867 4868 this.adapter.on('resize.waypoints', function() { 4869 if (!self.didResize) { 4870 self.didResize = true 4871 Waypoint.requestAnimationFrame(resizeHandler) 4872 } 4873 }) 4874 } 4875 4876 /* Private */ 4877 Context.prototype.createThrottledScrollHandler = function() { 4878 var self = this 4879 function scrollHandler() { 4880 self.handleScroll() 4881 self.didScroll = false 4882 } 4883 4884 this.adapter.on('scroll.waypoints', function() { 4885 if (!self.didScroll || Waypoint.isTouch) { 4886 self.didScroll = true 4887 Waypoint.requestAnimationFrame(scrollHandler) 4888 } 4889 }) 4890 } 4891 4892 /* Private */ 4893 Context.prototype.handleResize = function() { 4894 Waypoint.Context.refreshAll() 4895 } 4896 4897 /* Private */ 4898 Context.prototype.handleScroll = function() { 4899 var triggeredGroups = {} 4900 var axes = { 4901 horizontal: { 4902 newScroll: this.adapter.scrollLeft(), 4903 oldScroll: this.oldScroll.x, 4904 forward: 'right', 4905 backward: 'left' 4906 }, 4907 vertical: { 4908 newScroll: this.adapter.scrollTop(), 4909 oldScroll: this.oldScroll.y, 4910 forward: 'down', 4911 backward: 'up' 4912 } 4913 } 4914 4915 for (var axisKey in axes) { 4916 var axis = axes[axisKey] 4917 var isForward = axis.newScroll > axis.oldScroll 4918 var direction = isForward ? axis.forward : axis.backward 4919
4920 for (var waypointKey in this.waypoints[axisKey]) { 4921 var waypoint = this.waypoints[axisKey][waypointKey] 4922 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 4923 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 4924 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 4925 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 4926 if (crossedForward || crossedBackward) { 4927 waypoint.queueTrigger(direction) 4928 triggeredGroups[waypoint.group.id] = waypoint.group 4929 } 4930 } 4931 } 4932 4933 for (var groupKey in triggeredGroups) { 4934 triggeredGroups[groupKey].flushTriggers() 4935 } 4936 4937 this.oldScroll = { 4938 x: axes.horizontal.newScroll, 4939 y: axes.vertical.newScroll 4940 } 4941 } 4942 4943 /* Private */ 4944 Context.prototype.innerHeight = function() { 4945 /*eslint-disable eqeqeq */ 4946 if (this.element == this.element.window) { 4947 return Waypoint.viewportHeight() 4948 } 4949 /*eslint-enable eqeqeq */ 4950 return this.adapter.innerHeight() 4951 } 4952 4953 /* Private */ 4954 Context.prototype.remove = function(waypoint) { 4955 delete this.waypoints[waypoint.axis][waypoint.key] 4956 this.checkEmpty() 4957 } 4958 4959 /* Private */ 4960 Context.prototype.innerWidth = function() { 4961 /*eslint-disable eqeqeq */ 4962 if (this.element == this.element.window) { 4963 return Waypoint.viewportWidth() 4964 } 4965 /*eslint-enable eqeqeq */ 4966 return this.adapter.innerWidth() 4967 } 4968 4969 /* Public */ 4970 /* http://imakewebthings.com/waypoints/api/context-destroy */ 4971 Context.prototype.destroy = function() { 4972 var allWaypoints = [] 4973 for (var axis in this.waypoints) {
4974 for (var waypointKey in this.waypoints[axis]) { 4975 allWaypoints.push(this.waypoints[axis][waypointKey]) 4976 } 4977 } 4978 for (var i = 0, end = allWaypoints.length; i < end; i++) { 4979 allWaypoints[i].destroy() 4980 } 4981 } 4982 4983 /* Public */ 4984 /* http://imakewebthings.com/waypoints/api/context-refresh */ 4985 Context.prototype.refresh = function() { 4986 /*eslint-disable eqeqeq */ 4987 var isWindow = this.element == this.element.window 4988 /*eslint-enable eqeqeq */ 4989 var contextOffset = isWindow ? undefined : this.adapter.offset() 4990 var triggeredGroups = {} 4991 var axes 4992 4993 this.handleScroll() 4994 axes = { 4995 horizontal: { 4996 contextOffset: isWindow ? 0 : contextOffset.left, 4997 contextScroll: isWindow ? 0 : this.oldScroll.x, 4998 contextDimension: this.innerWidth(), 4999 oldScroll: this.oldScroll.x, 5000 forward: 'right', 5001 backward: 'left', 5002 offsetProp: 'left' 5003 }, 5004 vertical: { 5005 contextOffset: isWindow ? 0 : contextOffset.top, 5006 contextScroll: isWindow ? 0 : this.oldScroll.y, 5007 contextDimension: this.innerHeight(), 5008 oldScroll: this.oldScroll.y, 5009 forward: 'down', 5010 backward: 'up', 5011 offsetProp: 'top' 5012 } 5013 } 5014 5015 for (var axisKey in axes) { 5016 var axis = axes[axisKey]
5017 for (var waypointKey in this.waypoints[axisKey]) { 5018 var waypoint = this.waypoints[axisKey][waypointKey] 5019 var adjustment = waypoint.options.offset 5020 var oldTriggerPoint = waypoint.triggerPoint 5021 var elementOffset = 0 5022 var freshWaypoint = oldTriggerPoint == null 5023 var contextModifier, wasBeforeScroll, nowAfterScroll 5024 var triggeredBackward, triggeredForward 5025 5026 if (waypoint.element !== waypoint.element.window) { 5027 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 5028 } 5029 5030 if (typeof adjustment === 'function') { 5031 adjustment = adjustment.apply(waypoint) 5032 } 5033 else if (typeof adjustment === 'string') { 5034 adjustment = parseFloat(adjustment) 5035 if (waypoint.options.offset.indexOf('%') > - 1) { 5036 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 5037 } 5038 } 5039 5040 contextModifier = axis.contextScroll - axis.contextOffset 5041 waypoint.triggerPoint = elementOffset + contextModifier - adjustment 5042 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 5043 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 5044 triggeredBackward = wasBeforeScroll && nowAfterScroll 5045 triggeredForward = !wasBeforeScroll && !nowAfterScroll 5046 5047 if (!freshWaypoint && triggeredBackward) { 5048 waypoint.queueTrigger(axis.backward) 5049 triggeredGroups[waypoint.group.id] = waypoint.group 5050 } 5051 else if (!freshWaypoint && triggeredForward) { 5052 waypoint.queueTrigger(axis.forward) 5053 triggeredGroups[waypoint.group.id] = waypoint.group 5054 } 5055 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 5056 waypoint.queueTrigger(axis.forward) 5057 triggeredGroups[waypoint.group.id] = waypoint.group 5058 } 5059 } 5060 } 5061 5062 Waypoint.requestAnimationFrame(function() { 5063 for (var groupKey in triggeredGroups) { 5064 triggeredGroups[groupKey].flushTriggers() 5065 } 5066 }) 5067 5068 return this 5069 } 5070 5071 /* Private */ 5072 Context.findOrCreateByElement = function(element) { 5073 return Context.findByElement(element) || new Context(element) 5074 } 5075 5076 /* Private */ 5077 Context.refreshAll = function() { 5078 for (var contextId in contexts) { 5079 contexts[contextId].refresh() 5080 } 5081 } 5082 5083 /* Public */ 5084 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 5085 Context.findByElement = function(element) { 5086 return contexts[element.waypointContextKey] 5087 } 5088 5089 window.onload = function() { 5090 if (oldWindowLoad) { 5091 oldWindowLoad() 5092 } 5093 Context.refreshAll() 5094 } 5095 5096 Waypoint.requestAnimationFrame = function(callback) { 5097 var requestFn = window.requestAnimationFrame || 5098 window.mozRequestAnimationFrame || 5099 window.webkitRequestAnimationFrame || 5100 requestAnimationFrameShim 5101 requestFn.call(window, callback) 5102 } 5103 Waypoint.Context = Context 5104}()) 5105;(function() { 5106 'use strict' 5107 5108 function byTriggerPoint(a, b) { 5109 return a.triggerPoint - b.triggerPoint 5110 } 5111 5112 function byReverseTriggerPoint(a, b) { 5113 return b.triggerPoint - a.triggerPoint 5114 } 5115 5116 var groups = { 5117 vertical: {}, 5118 horizontal: {} 5119 } 5120 var Waypoint = window.Waypoint 5121 5122 /* http://imakewebthings.com/waypoints/api/group */ 5123 function Group(options) { 5124 this.name = options.name 5125 this.axis = options.axis 5126 this.id = this.name + '-' + this.axis 5127 this.waypoints = [] 5128 this.clearTriggerQueues() 5129 groups[this.axis][this.name] = this 5130 } 5131 5132 /* Private */ 5133 Group.prototype.add = function(waypoint) { 5134 this.waypoints.push(waypoint) 5135 } 5136 5137 /* Private */ 5138 Group.prototype.clearTriggerQueues = function() { 5139 this.triggerQueues = { 5140 up: [], 5141 down: [], 5142 left: [], 5143 right: [] 5144 } 5145 } 5146 5147 /* Private */ 5148 Group.prototype.flushTriggers = function() { 5149 for (var direction in this.triggerQueues) { 5150 var waypoints = this.triggerQueues[direction] 5151 var reverse = direction === 'up' || direction === 'left' 5152 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 5153 for (var i = 0, end = waypoints.length; i < end; i += 1) { 5154 var waypoint = waypoints[i] 5155 if (waypoint.options.continuous || i === waypoints.length - 1) { 5156 waypoint.trigger([direction]) 5157 } 5158 } 5159 } 5160 this.clearTriggerQueues() 5161 } 5162 5163 /* Private */ 5164 Group.prototype.next = function(waypoint) { 5165 this.waypoints.sort(byTriggerPoint) 5166 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5167 var isLast = index === this.waypoints.length - 1 5168 return isLast ? null : this.waypoints[index + 1] 5169 } 5170 5171 /* Private */ 5172 Group.prototype.previous = function(waypoint) { 5173 this.waypoints.sort(byTriggerPoint) 5174 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5175 return index ? this.waypoints[index - 1] : null 5176 } 5177 5178 /* Private */ 5179 Group.prototype.queueTrigger = function(waypoint, direction) { 5180 this.triggerQueues[direction].push(waypoint) 5181 } 5182 5183 /* Private */ 5184 Group.prototype.remove = function(waypoint) { 5185 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5186 if (index > -1) { 5187 this.waypoints.splice(index, 1) 5188 } 5189 } 5190 5191 /* Public */ 5192 /* http://imakewebthings.com/waypoints/api/first */ 5193 Group.prototype.first = function() { 5194 return this.waypoints[0] 5195 } 5196 5197 /* Public */ 5198 /* http://imakewebthings.com/waypoints/api/last */ 5199 Group.prototype.last = function() { 5200 return this.waypoints[this.waypoints.length - 1] 5201 } 5202 5203 /* Private */ 5204 Group.findOrCreate = function(options) { 5205 return groups[options.axis][options.name] || new Group(options) 5206 } 5207 5208 Waypoint.Group = Group 5209}()) 5210;(function() { 5211 'use strict' 5212 5213 var $ = window.jQuery 5214 var Waypoint = window.Waypoint 5215 5216 function JQueryAdapter(element) { 5217 this.$element = $(element) 5218 } 5219 5220 $.each([
5221 'innerHeight', 5222 'innerWidth', 5223 'off', 5224 'offset', 5225 'on', 5226 'outerHeight', 5227 'outerWidth', 5228 'scrollLeft', 5229 'scrollTop' 5230 ], function(i, method) { 5231 JQueryAdapter.prototype[method] = function() { 5232 var args = Array.prototype.slice.call(arguments) 5233 return this.$element[method].apply(this.$element, args) 5234 } 5235 }) 5236 5237 $.each([ 5238 'extend', 5239 'inArray', 5240 'isEmptyObject' 5241 ], function(i, method) { 5242 JQueryAdapter[method] = $[method] 5243 }) 5244 5245 Waypoint.adapters.push({ 5246 name: 'jquery', 5247 Adapter: JQueryAdapter 5248 }) 5249 Waypoint.Adapter = JQueryAdapter 5250}()) 5251;(function() { 5252 'use strict' 5253 5254 var Waypoint = window.Waypoint 5255 5256 function createExtension(framework) { 5257 return function() { 5258 var waypoints = [] 5259 var overrides = arguments[0] 5260 5261 if (framework.isFunction(arguments[0])) { 5262 overrides = framework.extend({}, arguments[1]) 5263 overrides.handler = arguments[0] 5264 } 5265 5266 this.each(function() { 5267 var options = framework.extend({}, overrides, { 5268 element: this 5269 }) 5270 if (typeof options.context === 'string') { 5271 options.context = framework(this).closest(options.context)[0] 5272 } 5273 waypoints.push(new Waypoint(options)) 5274 }) 5275 5276 return waypoints 5277 } 5278 } 5279 5280 if (window.jQuery) { 5281 window.jQuery.fn.waypoint = createExtension(window.jQuery) 5282 } 5283 if (window.Zepto) { 5284 window.Zepto.fn.waypoint = createExtension(window.Zepto) 5285 } 5286}()) 5287; 5288 5289/*! 5290Waypoints Inview Shortcut - 4.0.0 5291Copyright © 2011-2015 Caleb Troughton 5292Licensed under the MIT license. 5293https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 5294*/ 5295(function() { 5296 'use strict' 5297 5298 function noop() {} 5299 5300 var Waypoint = window.Waypoint 5301 5302 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 5303 function Inview(options) { 5304 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 5305 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 5306 this.waypoints = [] 5307 this.element = this.options.element 5308 this.createWaypoints() 5309 } 5310 5311 /* Private */ 5312 Inview.prototype.createWaypoints = function() { 5313 var configs = { 5314 vertical: [{ 5315 down: 'enter', 5316 up: 'exited', 5317 offset: '100%' 5318 }, { 5319 down: 'entered', 5320 up: 'exit', 5321 offset: 'bottom-in-view' 5322 }, { 5323 down: 'exit', 5324 up: 'entered', 5325 offset: 0 5326 }, { 5327 down: 'exited', 5328 up: 'enter', 5329 offset: function() { 5330 return -this.adapter.outerHeight() 5331 } 5332 }], 5333 horizontal: [{ 5334 right: 'enter', 5335 left: 'exited', 5336 offset: '100%' 5337 }, { 5338 right: 'entered', 5339 left: 'exit', 5340 offset: 'right-in-view' 5341 }, { 5342 right: 'exit', 5343 left: 'entered', 5344 offset: 0 5345 }, { 5346 right: 'exited', 5347 left: 'enter', 5348 offset: function() { 5349 return -this.adapter.outerWidth() 5350 } 5351 }] 5352 } 5353 5354 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 5355 var config = configs[this.axis][i] 5356 this.createWaypoint(config) 5357 } 5358 } 5359 5360 /* Private */ 5361 Inview.prototype.createWaypoint = function(config) { 5362 var self = this 5363 this.waypoints.push(new Waypoint({ 5364 context: this.options.context, 5365 element: this.options.element, 5366 enabled: this.options.enabled, 5367 handler: (function(config) { 5368 return function(direction) { 5369 self.options[config[direction]].call(self, direction) 5370 } 5371 }(config)), 5372 offset: config.offset, 5373 horizontal: this.options.horizontal 5374 })) 5375 } 5376 5377 /* Public */ 5378 Inview.prototype.destroy = function() { 5379 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5380 this.waypoints[i].destroy() 5381 } 5382 this.waypoints = [] 5383 } 5384 5385 Inview.prototype.disable = function() { 5386 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5387 this.waypoints[i].disable() 5388 } 5389 } 5390 5391 Inview.prototype.enable = function() { 5392 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5393 this.waypoints[i].enable() 5394 } 5395 } 5396 5397 Inview.defaults = { 5398 context: window, 5399 enabled: true, 5400 enter: noop, 5401 entered: noop,
5402 exit: noop, 5403 exited: noop 5404 } 5405 5406 Waypoint.Inview = Inview 5407}()) 5408; 5409 5410/* 5411 * SmartMenus jQuery v0.9.6 5412 * http://www.smartmenus.org/ 5413 * 5414 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 5415 * http://vadikom.com/ 5416 * 5417 * Released under the MIT license: 5418 * http://www.opensource.org/licenses/MIT 5419 */ 5420 5421(function($) { 5422 5423 var menuTrees = [], 5424 IE = !!window.createPopup, // we need to detect it, unfortunately 5425 IElt9 = IE && !document.defaultView, 5426 IElt8 = IE && !document.querySelector, 5427 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 5428 mouse = false, // optimize for touch by default - we will detect for mouse input 5429 mouseDetectionEnabled = false; 5430 5431 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 5432 function initMouseDetection(disable) { 5433 if (!mouseDetectionEnabled && !disable) { 5434 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 5435 // in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events) 5436 var firstTime = true, 5437 lastMove = null; 5438 $(document).bind({ 5439 'mousemove.smartmenus_mouse': function(e) { 5440 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 5441 if (lastMove) { 5442 var deltaX = Math.abs(lastMove.x - thisMove.x), 5443 deltaY = Math.abs(lastMove.y - thisMove.y); 5444 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 5445 mouse = true; 5446 // if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes 5447 if (firstTime) { 5448 var $a = $(e.target).closest('a'); 5449 if ($a.is('a')) { 5450 $.each(menuTrees, function() { 5451 if ($.contains(this.$root[0], $a[0])) { 5452 this.itemEnter({ currentTarget: $a[0] }); 5453 return false; 5454 } 5455 }); 5456 } 5457 firstTime = false; 5458 } 5459 } 5460 } 5461 lastMove = thisMove; 5462 }, 5463 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 5464 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 5465 mouse = false; 5466 } 5467 } 5468 }); 5469 mouseDetectionEnabled = true; 5470 } else if (mouseDetectionEnabled && disable) { 5471 $(document).unbind('.smartmenus_mouse'); 5472 mouseDetectionEnabled = false; 5473 } 5474 }; 5475 5476 $.SmartMenus = function(elm, options) { 5477 this.$root = $(elm); 5478 this.opts = options; 5479 this.rootId = ''; // internal 5480 this.$subArrow = null; 5481 this.subMenus = []; // all sub menus in the tree (UL elms) in no particular order (only real - e.g. UL's in mega sub menus won't be counted) 5482 this.activatedItems = []; // stores last activated A's for each level 5483 this.visibleSubMenus = []; // stores visible sub menus UL's 5484 this.showTimeout = 0; 5485 this.hideTimeout = 0; 5486 this.scrollTimeout = 0; 5487 this.clickActivated = false; 5488 this.zIndexInc = 0; 5489 this.$firstLink = null; // we'll use these for some tests 5490 this.$firstSub = null; // at runtime so we'll cache them 5491 this.disabled = false; 5492 this.$disableOverlay = null; 5493 this.init(); 5494 }; 5495 5496 $.extend($.SmartMenus, { 5497 hideAll: function() { 5498 $.each(menuTrees, function() { 5499 this.menuHideAll(); 5500 }); 5501 }, 5502 destroy: function() { 5503 while (menuTrees.length) { 5504 menuTrees[0].destroy(); 5505 } 5506 initMouseDetection(true); 5507 }, 5508 prototype: { 5509 init: function(refresh) { 5510 var self = this; 5511 5512 if (!refresh) { 5513 menuTrees.push(this); 5514 5515 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 5516 5517 if (this.$root.hasClass('sm-rtl')) { 5518 this.opts.rightToLeftSubMenus = true; 5519 } 5520 5521 // init root (main menu) 5522 this.$root 5523 .data('smartmenus', this) 5524 .attr('data-smartmenus-id', this.rootId) 5525 .dataSM('level', 1) 5526 .bind({ 5527 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
5528 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 5529 }) 5530 .delegate('a', { 5531 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 5532 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 5533 'mousedown.smartmenus': $.proxy(this.itemDown, this), 5534 'focus.smartmenus': $.proxy(this.itemFocus, this), 5535 'blur.smartmenus': $.proxy(this.itemBlur, this), 5536 'click.smartmenus': $.proxy(this.itemClick, this), 5537 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 5538 }); 5539 5540 var eNamespace = '.smartmenus' + this.rootId; 5541 // hide menus on tap or click outside the root UL 5542 if (this.opts.hideOnClick) { 5543 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 5544 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 5545 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 5546 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 5547 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 5548 } 5549 // hide sub menus on resize 5550 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5551 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5552 5553 if (this.opts.subIndicators) { 5554 this.$subArrow = $('<span/>').addClass('sub-arrow'); 5555 if (this.opts.subIndicatorsText) { 5556 this.$subArrow.html(this.opts.subIndicatorsText); 5557 } 5558 } 5559 5560 // make sure mouse detection is enabled 5561 initMouseDetection(); 5562 } 5563 5564 // init sub menus 5565 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 5566 5567 this.$firstLink = this.$root.find('a').eq(0); 5568 5569 // find current item 5570 if (this.opts.markCurrentItem) { 5571 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 5572 reHash = /#.*/, 5573 locHref = window.location.href.replace(reDefaultDoc, ''), 5574 locHrefNoHash = locHref.replace(reHash, ''); 5575 this.$root.find('a').each(function() { 5576 var href = this.href.replace(reDefaultDoc, ''), 5577 $this = $(this); 5578 if (href == locHref || href == locHrefNoHash) { 5579 $this.addClass('current'); 5580 if (self.opts.markCurrentTree) { 5581 $this.parents('li').each(function() { 5582 var $this = $(this); 5583 if ($this.dataSM('sub')) { 5584 $this.children('a').addClass('current'); 5585 } 5586 }); 5587 } 5588 } 5589 }); 5590 } 5591 }, 5592 destroy: function() { 5593 this.menuHideAll(); 5594 this.$root 5595 .removeData('smartmenus') 5596 .removeAttr('data-smartmenus-id') 5597 .removeDataSM('level') 5598 .unbind('.smartmenus') 5599 .undelegate('.smartmenus'); 5600 var eNamespace = '.smartmenus' + this.rootId; 5601 $(document).unbind(eNamespace); 5602 $(window).unbind(eNamespace); 5603 if (this.opts.subIndicators) { 5604 this.$subArrow = null; 5605 } 5606 var self = this; 5607 $.each(this.subMenus, function() { 5608 if (this.hasClass('mega-menu')) { 5609 this.find('ul').removeDataSM('in-mega'); 5610 } 5611 if (this.dataSM('shown-before')) { 5612 if (IElt8) { 5613 this.children().css({ styleFloat: '', width: '' }); 5614 } 5615 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 5616 if (!IE6) { 5617 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 5618 } else { 5619 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 5620 } 5621 } 5622 if (this.dataSM('scroll-arrows')) { 5623 this.dataSM('scroll-arrows').remove(); 5624 } 5625 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 5626 } 5627 if (self.opts.subIndicators) { 5628 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 5629 } 5630 this.removeDataSM('shown-before') 5631 .removeDataSM('ie-shim') 5632 .removeDataSM('scroll-arrows') 5633 .removeDataSM('parent-a') 5634 .removeDataSM('level') 5635 .removeDataSM('beforefirstshowfired') 5636 .parent().removeDataSM('sub'); 5637 }); 5638 if (this.opts.markCurrentItem) { 5639 this.$root.find('a.current').removeClass('current'); 5640 } 5641 this.$root = null; 5642 this.$firstLink = null; 5643 this.$firstSub = null; 5644 if (this.$disableOverlay) { 5645 this.$disableOverlay.remove(); 5646 this.$disableOverlay = null; 5647 } 5648 menuTrees.splice($.inArray(this, menuTrees), 1); 5649 }, 5650 disable: function(noOverlay) { 5651 if (!this.disabled) { 5652 this.menuHideAll(); 5653 // display overlay over the menu to prevent interaction 5654 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 5655 var pos = this.$root.offset(); 5656 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 5657 position: 'absolute', 5658 top: pos.top, 5659 left: pos.left, 5660 width: this.$root.outerWidth(), 5661 height: this.$root.outerHeight(),
5662 zIndex: this.getStartZIndex() + 1, 5663 opacity: 0 5664 }).appendTo(document.body); 5665 } 5666 this.disabled = true; 5667 } 5668 }, 5669 docClick: function(e) { 5670 // hide on any click outside the menu or on a menu link 5671 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 5672 this.menuHideAll(); 5673 } 5674 }, 5675 docTouchEnd: function(e) { 5676 if (!this.lastTouch) { 5677 return; 5678 } 5679 if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) { 5680 if (this.hideTimeout) { 5681 clearTimeout(this.hideTimeout); 5682 this.hideTimeout = 0; 5683 } 5684 // hide with a delay to prevent triggering accidental unwanted click on some page element 5685 var self = this; 5686 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, 350); 5687 } 5688 this.lastTouch = null; 5689 }, 5690 docTouchMove: function(e) { 5691 if (!this.lastTouch) { 5692 return; 5693 } 5694 var touchPoint = e.originalEvent.touches[0]; 5695 this.lastTouch.x2 = touchPoint.pageX; 5696 this.lastTouch.y2 = touchPoint.pageY; 5697 }, 5698 docTouchStart: function(e) { 5699 var touchPoint = e.originalEvent.touches[0]; 5700 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 5701 }, 5702 enable: function() { 5703 if (this.disabled) { 5704 if (this.$disableOverlay) { 5705 this.$disableOverlay.remove(); 5706 this.$disableOverlay = null; 5707 } 5708 this.disabled = false; 5709 } 5710 }, 5711 getHeight: function($elm) { 5712 return this.getOffset($elm, true); 5713 }, 5714 // returns precise width/height float values in IE9+, FF4+, recent WebKit 5715 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 5716 getOffset: function($elm, height) { 5717 var old; 5718 if ($elm.css('display') == 'none') { 5719 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 5720 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 5721 } 5722 var defaultView = $elm[0].ownerDocument.defaultView, 5723 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 5724 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 5725 if (val) { 5726 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 5727 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 5728 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 5729 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 5730 } else { 5731 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 5732 } 5733 if (old) { 5734 $elm.hide().css(old); 5735 } 5736 return val; 5737 }, 5738 getWidth: function($elm) { 5739 return this.getOffset($elm); 5740 }, 5741 getStartZIndex: function() { 5742 var zIndex = parseInt(this.$root.css('z-index')); 5743 return !isNaN(zIndex) ? zIndex : 1; 5744 }, 5745 handleEvents: function() { 5746 return !this.disabled && this.isCSSOn(); 5747 }, 5748 handleItemEvents: function($a) { 5749 return this.handleEvents() && !this.isLinkInMegaMenu($a); 5750 }, 5751 isCollapsible: function() { 5752 return this.$firstSub.css('position') == 'static'; 5753 }, 5754 isCSSOn: function() { 5755 return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'inline'; 5756 }, 5757 isFixed: function() { 5758 return this.$root.css('position') == 'fixed'; 5759 }, 5760 isLinkInMegaMenu: function($a) { 5761 return !$a.parent().parent().dataSM('level'); 5762 }, 5763 isTouchMode: function() { 5764 return !mouse || this.isCollapsible(); 5765 }, 5766 itemActivate: function($a) { 5767 var $li = $a.parent(), 5768 $ul = $li.parent(), 5769 level = $ul.dataSM('level'); 5770 // if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first 5771 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 5772 var self = this; 5773 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 5774 self.itemActivate($(this).dataSM('parent-a')); 5775 }); 5776 } 5777 // hide any visible deeper level sub menus 5778 if (this.visibleSubMenus.length > level) { 5779 for (var i = this.visibleSubMenus.length - 1, l = !this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level; i > l; i--) { 5780 this.menuHide(this.visibleSubMenus[i]); 5781 } 5782 } 5783 // save new active item and sub menu for this level 5784 this.activatedItems[level - 1] = $a; 5785 this.visibleSubMenus[level - 1] = $ul; 5786 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 5787 return; 5788 } 5789 // show the sub menu if this item has one 5790 var $sub = $li.dataSM('sub'); 5791 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 5792 this.menuShow($sub); 5793 } 5794 }, 5795 itemBlur: function(e) { 5796 var $a = $(e.currentTarget); 5797 if (!this.handleItemEvents($a)) { 5798 return; 5799 } 5800 this.$root.triggerHandler('blur.smapi', $a[0]); 5801 }, 5802 itemClick: function(e) { 5803 var $a = $(e.currentTarget); 5804 5805 if (!this.handleItemEvents($a)) { 5806 return; 5807 } 5808 $a.removeDataSM('mousedown'); 5809 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 5810 return false;
5811 } 5812 var $sub = $a.parent().dataSM('sub'); 5813 if (this.isTouchMode()) { 5814 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 5815 if ($a.dataSM('href')) { 5816 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 5817 } 5818 // if the sub is not visible 5819 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5820 // try to activate the item and show the sub 5821 this.itemActivate($a); 5822 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 5823 // if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded 5824 if ($sub.is(':visible')) { 5825 return false; 5826 } 5827 } 5828 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 5829 this.clickActivated = true; 5830 this.menuShow($sub); 5831 return false; 5832 } 5833 if ($a.hasClass('disabled')) { 5834 return false; 5835 } 5836 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 5837 return false; 5838 } 5839 }, 5840 itemDown: function(e) { 5841 var $a = $(e.currentTarget); 5842 if (!this.handleItemEvents($a)) { 5843 return; 5844 } 5845 $a.dataSM('mousedown', true); 5846 }, 5847 itemEnter: function(e) { 5848 var $a = $(e.currentTarget); 5849 if (!this.handleItemEvents($a)) { 5850 return; 5851 } 5852 if (!this.isTouchMode()) { 5853 if (this.showTimeout) { 5854 clearTimeout(this.showTimeout); 5855 this.showTimeout = 0; 5856 } 5857 var self = this; 5858 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 5859 } 5860 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 5861 }, 5862 itemFocus: function(e) { 5863 var $a = $(e.currentTarget); 5864 if (!this.handleItemEvents($a)) { 5865 return; 5866 } 5867 // fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus 5868 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 5869 this.itemActivate($a); 5870 } 5871 this.$root.triggerHandler('focus.smapi', $a[0]); 5872 }, 5873 itemLeave: function(e) { 5874 var $a = $(e.currentTarget); 5875 if (!this.handleItemEvents($a)) { 5876 return; 5877 } 5878 if (!this.isTouchMode()) { 5879 if ($a[0].blur) { 5880 $a[0].blur(); 5881 } 5882 if (this.showTimeout) { 5883 clearTimeout(this.showTimeout); 5884 this.showTimeout = 0; 5885 } 5886 } 5887 $a.removeDataSM('mousedown'); 5888 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 5889 }, 5890 itemTouchEnd: function(e) { 5891 var $a = $(e.currentTarget); 5892 if (!this.handleItemEvents($a)) { 5893 return; 5894 } 5895 // prevent the address bar on iPhone from sliding down when expanding a sub menu 5896 var $sub = $a.parent().dataSM('sub'); 5897 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5898 $a.dataSM('href', $a.attr('href')); 5899 $a.attr('href', '#'); 5900 } 5901 }, 5902 menuFixLayout: function($ul) { 5903 // fixes a menu that is being shown for the first time 5904 if (!$ul.dataSM('shown-before')) { 5905 $ul.hide().dataSM('shown-before', true); 5906 // fix the layout of the items in IE<8 5907 if (IElt8) { 5908 $ul.children().css({ styleFloat: 'left', width: '100%' }); 5909 } 5910 } 5911 }, 5912 menuHide: function($sub) { 5913 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 5914 return; 5915 } 5916 $sub.stop(true, true); 5917 if ($sub.is(':visible')) { 5918 var complete = function() { 5919 // unset z-index 5920 if (IElt9) { 5921 $sub.parent().css('z-index', ''); 5922 } else { 5923 $sub.css('z-index', ''); 5924 } 5925 }; 5926 // if ($('html.firefox').length) { 5927 // $('#menu-main-menu > li > a').removeAttr('style'); 5928 // // var menuel = $('.main-menu-container'); 5929 // // setTimeout(function(){ 5930 // // menuel.data('tempheight',undefined).removeAttr('style'); 5931 // // }, 300); 5932 // } 5933 // if sub is collapsible (mobile view) 5934 if (this.isCollapsible()) { 5935 if (this.opts.collapsibleHideFunction) { 5936 this.opts.collapsibleHideFunction.call(this, $sub, complete); 5937 } else { 5938 $sub.hide(this.opts.collapsibleHideDuration, complete); 5939 } 5940 } else { 5941 if (this.opts.hideFunction) { 5942 this.opts.hideFunction.call(this, $sub, complete); 5943 } else { 5944 $sub.hide(this.opts.hideDuration, complete); 5945 } 5946 } 5947 // remove IE iframe shim 5948 if ($sub.dataSM('ie-shim')) { 5949 $sub.dataSM('ie-shim').remove(); 5950 } 5951 // deactivate scrolling if it is activated for this sub 5952 if ($sub.dataSM('scroll')) { 5953 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 5954 } 5955 // unhighlight parent item 5956 $sub.dataSM('parent-a').removeClass('highlighted'); 5957 var level = $sub.dataSM('level'); 5958 this.activatedItems.splice(level - 1, 1); 5959 this.visibleSubMenus.splice(level - 1, 1); 5960 this.$root.triggerHandler('hide.smapi', $sub[0]); 5961 } 5962 }, 5963 menuHideAll: function() { 5964 if (this.showTimeout) { 5965 clearTimeout(this.showTimeout); 5966 this.showTimeout = 0; 5967 } 5968 // hide all subs 5969 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 5970 this.menuHide(this.visibleSubMenus[i]); 5971 } 5972 // hide root if it's popup 5973 if (this.opts.isPopup) { 5974 this.$root.stop(true, true); 5975 if (this.$root.is(':visible')) { 5976 if (this.opts.hideFunction) { 5977 this.opts.hideFunction.call(this, this.$root); 5978 } else { 5979 this.$root.hide(this.opts.hideDuration); 5980 } 5981 // remove IE iframe shim 5982 if (this.$root.dataSM('ie-shim')) { 5983 this.$root.dataSM('ie-shim').remove(); 5984 } 5985 } 5986 } 5987 this.activatedItems = []; 5988 this.visibleSubMenus = []; 5989 this.clickActivated = false;
5990 // reset z-index increment 5991 this.zIndexInc = 0; 5992 }, 5993 menuIframeShim: function($ul) { 5994 // create iframe shim for the menu 5995 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 5996 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 5997 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 5998 ); 5999 } 6000 }, 6001 menuInit: function($ul) { 6002 if (!$ul.dataSM('in-mega')) { 6003 this.subMenus.push($ul); 6004 // mark UL's in mega drop downs (if any) so we can neglect them 6005 if ($ul.hasClass('mega-menu')) { 6006 $ul.find('ul').dataSM('in-mega', true); 6007 } 6008 // get level (much faster than, for example, using parentsUntil) 6009 var level = 2, 6010 par = $ul[0]; 6011 while ((par = par.parentNode.parentNode) != this.$root[0]) { 6012 level++; 6013 } 6014 // cache stuff 6015 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 6016 .dataSM('level', level) 6017 .parent().dataSM('sub', $ul); 6018 // add sub indicator to parent item 6019 if (this.opts.subIndicators) { 6020 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 6021 } 6022 } 6023 }, 6024 menuPosition: function($sub) { 6025 var fixIE = $('html.ie').length; 6026 // if (fixIE) { 6027 // var $rowParent = $($sub).closest('.main-menu-container'); 6028 // $rowParent.height($rowParent.height()); 6029 // } 6030 var $a = $sub.dataSM('parent-a'), 6031 $li = $sub.parent(), 6032 $ul = $sub.parent().parent(), 6033 $container = $ul.closest('.row-menu-inner'), 6034 level = $sub.dataSM('level'), 6035 subW = this.getWidth($sub), 6036 subH = this.getHeight($sub), 6037 itemOffset = $a.offset(), 6038 itemX = itemOffset.left, 6039 itemY = itemOffset.top, 6040 itemW = this.getWidth($a), 6041 itemH = this.getHeight($a), 6042 $win = $(window), 6043 winX = $win.scrollLeft(), 6044 winY = $win.scrollTop(), 6045 winW = $win.width(), 6046 winH = $win.height(), 6047 containerW = $container.width(), 6048 containerOffsetX = containerW + ((winW - containerW) / 2), 6049 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 6050 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 6051 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 6052 x, y, leftPos; 6053 if (horizontalParent) { 6054 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 6055 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 6056 } else { 6057 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX; 6058 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 6059 } 6060 if (this.opts.keepInViewport && !this.isCollapsible()) { 6061 if (this.isFixed()) { 6062 itemX -= winX; 6063 itemY -= winY; 6064 winX = winY = 0; 6065 } 6066 var absX = itemX + x, 6067 absY = itemY + y; 6068 if (this.opts.rightToLeftSubMenus && absX < winX) { 6069 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 6070 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 6071 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 6072 } 6073 if (!horizontalParent) { 6074 if (subH < winH && absY + subH > winY + winH) { 6075 y += winY + winH - subH - absY; 6076 } else if (subH >= winH || absY < winY) { 6077 y += winY - absY; 6078 } 6079 } 6080 // do we need scrolling? 6081 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 6082 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 6083 var self = this; 6084 if (!$sub.dataSM('scroll-arrows')) { 6085 $sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]) 6086 .bind({ 6087 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 6088 mouseleave: function(e) { 6089 self.menuScrollStop($sub); 6090 self.menuScrollOut($sub, e); 6091 }, 6092 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 6093 }) 6094 .insertAfter($sub) 6095 ); 6096 } 6097 // bind events to show/hide arrows on hover and save scrolling data for this sub 6098 var vportY = winY - (itemY + itemH); 6099 $sub.dataSM('scroll', { 6100 vportY: vportY, 6101 subH: subH, 6102 winH: winH, 6103 step: 1 6104 }) 6105 .bind({ 6106 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 6107 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 6108 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 6109 }) 6110 .dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: this.getWidth($sub) - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: this.get
6110StartZIndex() + this.zIndexInc }) 6111 .eq(0).css('margin-top', vportY).end() 6112 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 6113 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 6114 } 6115 } 6116 // if ($sub.hasClass('mega-menu-inner')) { 6117 // if ($('.menu-wrapper .megamenu-diff').length > 0) { 6118 // leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth()); 6119 // leftPos = -leftPos; 6120 // } else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft')); 6121 6122 // if ($('body.header-full-width').length > 0) { 6123 // $sub.css({ width: $('.box-container').width()}); 6124 // leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft'))); 6125 // } else $sub.css({ width: containerW}); 6126 // leftPos = leftPos + 'px'; 6127 6128 // } else { 6129 // leftPos = $li.position().left + 'px'; 6130 // } 6131 if ($sub.hasClass('mega-menu-inner')) { 6132 $sub.css({ width: containerW}); 6133 if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0) { 6134 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 6135 } else { 6136 leftPos = '0px'; 6137 } 6138 } else { 6139 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 6140 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 6141 } 6142 6143 $sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) }); 6144 // IE iframe shim 6145 this.menuIframeShim($sub); 6146 if ($sub.dataSM('ie-shim')) { 6147 $sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) }); 6148 } 6149 }, 6150 menuScroll: function($sub, up, wheel) { 6151 var y = parseFloat($sub.css('margin-top')), 6152 scroll = $sub.dataSM('scroll'), 6153 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 6154 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 6155 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 6156 y = parseFloat($sub.css('margin-top')); 6157 // show opposite arrow if appropriate 6158 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 6159 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 6160 } 6161 // accelerate when not using mousewheel to scroll 6162 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 6163 $sub.dataSM('scroll').step += 0.5; 6164 } 6165 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 6166 if (Math.abs(y - end) < 1) { 6167 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 6168 $sub.dataSM('scroll').step = 1; 6169 } else if (!wheel) { 6170 var self = this; 6171 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 6172 } 6173 }, 6174 menuScrollMousewheel: function($sub, e) { 6175 var $closestSub = $(e.target).closest('ul'); 6176 while ($closestSub.dataSM('in-mega')) { 6177 $closestSub = $closestSub.parent().closest('ul'); 6178 } 6179 if ($closestSub[0] == $sub[0]) { 6180 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 6181 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 6182 this.menuScroll($sub, up, true); 6183 } 6184 } 6185 e.preventDefault(); 6186 }, 6187 menuScrollOut: function($sub, e) { 6188 var reClass = /^scroll-(up|down)/, 6189 $closestSub = $(e.relatedTarget).closest('ul'); 6190 while ($closestSub.dataSM('in-mega')) { 6191 $closestSub = $closestSub.parent().closest('ul'); 6192 } 6193 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 6194 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 6195 } 6196 }, 6197 menuScrollOver: function($sub, e) { 6198 var reClass = /^scroll-(up|down)/, 6199 $closestSub = $(e.target).closest('ul'); 6200 while ($closestSub.dataSM('in-mega')) { 6201 $closestSub = $closestSub.parent().closest('ul'); 6202 } 6203 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 6204 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 6205 } 6206 }, 6207 menuScrollStop: function($sub) { 6208 if (this.scrollTimeout) { 6209 clearTimeout(this.scrollTimeout); 6210 this.scrollTimeout = 0; 6211 $sub.dataSM('scroll').step = 1; 6212 } 6213 }, 6214 menuShow: function($sub) { 6215 if (!$sub.dataSM('beforefirstshowfired')) { 6216 $sub.dataSM('beforefirstshowfired', true); 6217 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 6218 return; 6219 } 6220 } 6221 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 6222 return; 6223 } 6224 this.menuFixLayout($sub); 6225 $sub.stop(true, true); 6226 if (!$sub.is(':visible')) { 6227 // if ($('html.firefox').length) { 6228 // if ($sub.dataSM('level') == 2) { 6229 // $('#menu-main-menu > li > a').css('height','0'); 6230 // $('#menu-main-menu > li > a').removeAttr('style'); 6231 // // var menuel = $('.main-menu-container'), 6232 // // menuelHeight = menuel.outerHeight(true); 6233 // // menuel.removeAttr('style');
6234 // // if (menuel.data('tempheight') == undefined) menuel.data('tempheight',menuelHeight).css('height',menuelHeight+'px'); 6235 // // else menuel.css('height',menuel.data('tempheight')+'px'); 6236 // } 6237 // } 6238 // set z-index - for IE < 9 set it to the parent LI 6239 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 6240 if (IElt9) { 6241 $sub.parent().css('z-index', zIndex); 6242 } else { 6243 $sub.css('z-index', zIndex); 6244 } 6245 // highlight parent item 6246 if (this.opts.keepHighlighted || this.isCollapsible()) { 6247 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 6248 $sub.dataSM('parent-a').addClass('highlighted'); 6249 } 6250 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 6251 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 6252 if (!IElt8) { 6253 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6254 if (this.opts.subMenusMinWidth) { 6255 $sub.css('min-width', this.opts.subMenusMinWidth); 6256 } 6257 if (this.opts.subMenusMaxWidth) { 6258 var noMaxWidth = this.getWidth($sub); 6259 $sub.css('max-width', this.opts.subMenusMaxWidth); 6260 if (noMaxWidth > this.getWidth($sub)) { 6261 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6262 } 6263 } 6264 // IE6,7 6265 } else { 6266 $sub.children().css('styleFloat', 'none'); 6267 if (IE6) { 6268 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 6269 .children().children('a').css('white-space', 'nowrap'); 6270 } else { // IE7 6271 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6272 if (this.opts.subMenusMinWidth) { 6273 $sub.css('min-width', this.opts.subMenusMinWidth); 6274 } 6275 } 6276 if (this.opts.subMenusMaxWidth) { 6277 var noMaxWidth = $sub.width(); 6278 if (IE6) { 6279 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 6280 if (noMaxWidth > maxWidth) { 6281 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 6282 } else { 6283 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 6284 } 6285 } else { // IE7 6286 $sub.css('max-width', this.opts.subMenusMaxWidth); 6287 if (noMaxWidth > $sub.width()) { 6288 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6289 } else { 6290 $sub.width(noMaxWidth); 6291 } 6292 } 6293 } else { 6294 $sub.width($sub.width()); 6295 } 6296 $sub.children().css('styleFloat', 'left'); 6297 } 6298 } 6299 this.menuPosition($sub); 6300 // insert IE iframe shim 6301 if ($sub.dataSM('ie-shim')) { 6302 $sub.dataSM('ie-shim').insertBefore($sub); 6303 } 6304 var complete = function() { 6305 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 6306 $sub.css('overflow', ''); 6307 }; 6308 // if sub is collapsible (mobile view) 6309 if (this.isCollapsible()) { 6310 if (this.opts.collapsibleShowFunction) { 6311 this.opts.collapsibleShowFunction.call(this, $sub, complete); 6312 } else { 6313 $sub.show(this.opts.collapsibleShowDuration, complete); 6314 } 6315 } else { 6316 if (this.opts.showFunction) { 6317 this.opts.showFunction.call(this, $sub, complete); 6318 } else { 6319 $sub.show(this.opts.showDuration, complete); 6320 } 6321 } 6322 // save new sub menu for this level 6323 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 6324 this.$root.triggerHandler('show.smapi', $sub[0]); 6325 } 6326 }, 6327 popupHide: function(noHideTimeout) { 6328 if (this.hideTimeout) { 6329 clearTimeout(this.hideTimeout); 6330 this.hideTimeout = 0; 6331 } 6332 var self = this; 6333 this.hideTimeout = setTimeout(function() { 6334 self.menuHideAll(); 6335 }, noHideTimeout ? 1 : this.opts.hideTimeout); 6336 }, 6337 popupShow: function(left, top) { 6338 if (!this.opts.isPopup) { 6339 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 6340 return; 6341 } 6342 if (this.hideTimeout) { 6343 clearTimeout(this.hideTimeout); 6344 this.hideTimeout = 0; 6345 } 6346 this.menuFixLayout(this.$root); 6347 this.$root.stop(true, true); 6348 if (!this.$root.is(':visible')) { 6349 this.$root.css({ left: left, top: top }); 6350 // IE iframe shim 6351 this.menuIframeShim(this.$root); 6352 if (this.$root.dataSM('ie-shim')) { 6353 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6353: left, top: top }).insertBefore(this.$root); 6354 } 6355 // show menu 6356 if (this.opts.showFunction) { 6357 this.opts.showFunction.call(this, this.$root); 6358 } else { 6359 this.$root.show(this.opts.showDuration); 6360 } 6361 this.visibleSubMenus[0] = this.$root; 6362 } 6363 }, 6364 refresh: function() { 6365 this.menuHideAll(); 6366 this.$root.find('ul').each(function() { 6367 var $this = $(this); 6368 if ($this.dataSM('scroll-arrows')) { 6369 $this.dataSM('scroll-arrows').remove(); 6370 } 6371 }) 6372 .removeDataSM('in-mega') 6373 .removeDataSM('shown-before') 6374 .removeDataSM('ie-shim') 6375 .removeDataSM('scroll-arrows') 6376 .removeDataSM('parent-a') 6377 .removeDataSM('level') 6378 .removeDataSM('beforefirstshowfired'); 6379 this.$root.find('a.has-submenu').removeClass('has-submenu') 6380 .parent().removeDataSM('sub'); 6381 if (this.opts.subIndicators) { 6382 this.$root.find('span.sub-arrow').remove(); 6383 } 6384 if (this.opts.markCurrentItem) { 6385 this.$root.find('a.current').removeClass('current'); 6386 } 6387 this.subMenus = []; 6388 this.init(true); 6389 }, 6390 rootOut: function(e) { 6391 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6392 return; 6393 } 6394 if (this.hideTimeout) { 6395 clearTimeout(this.hideTimeout); 6396 this.hideTimeout = 0; 6397 } 6398 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 6399 var self = this; 6400 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 6401 } 6402 }, 6403 rootOver: function(e) { 6404 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6405 return; 6406 } 6407 if (this.hideTimeout) { 6408 clearTimeout(this.hideTimeout); 6409 this.hideTimeout = 0; 6410 } 6411 }, 6412 winResize: function(e) { 6413 if (!this.handleEvents()) { 6414 // we still need to resize the disable overlay if it's visible 6415 if (this.$disableOverlay) { 6416 var pos = this.$root.offset(); 6417 this.$disableOverlay.css({ 6418 top: pos.top, 6419 left: pos.left, 6420 width: this.$root.outerWidth(), 6421 height: this.$root.outerHeight() 6422 }); 6423 } 6424 return; 6425 } 6426 // hide sub menus on resize - on mobile do it only on orientation change 6427 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 6428 if (this.activatedItems.length) { 6429 this.activatedItems[this.activatedItems.length - 1][0].blur(); 6430 } 6431 this.menuHideAll(); 6432 } 6433 } 6434 } 6435 }); 6436 6437 $.fn.dataSM = function(key, val) { 6438 if (val) { 6439 return this.data(key + '_smartmenus', val); 6440 } 6441 return this.data(key + '_smartmenus'); 6442 } 6443 6444 $.fn.removeDataSM = function(key) { 6445 return this.removeData(key + '_smartmenus'); 6446 } 6447 6448 $.fn.smartmenus = function(options) { 6449 if (typeof options == 'string') { 6450 var args = arguments, 6451 method = options; 6452 Array.prototype.shift.call(args); 6453 return this.each(function() { 6454 var smartmenus = $(this).data('smartmenus'); 6455 if (smartmenus && smartmenus[method]) { 6456 smartmenus[method].apply(smartmenus, args); 6457 } 6458 }); 6459 } 6460 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 6461 return this.each(function() { 6462 new $.SmartMenus(this, opts); 6463 }); 6464 } 6465 6466 // default settings 6467 $.fn.smartmenus.defaults = { 6468 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 6469 mainMenuSubOffsetX: 0, // pixels offset from default position
6470 mainMenuSubOffsetY: 0, // pixels offset from default position 6471 subMenusSubOffsetX: 0, // pixels offset from default position 6472 subMenusSubOffsetY: 0, // pixels offset from default position 6473 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6474 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6475 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 6476 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 6477 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 6478 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 6479 scrollInterval: 30, // interval between each scrolling step 6480 scrollAccelerate: true, // accelerate scrolling or use a fixed step 6481 showTimeout: 250, // timeout before showing the sub menus 6482 hideTimeout: 500, // timeout before hiding the sub menus 6483 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 6484 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 6485 // don't forget to call complete() at the end of whatever you do 6486 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 6487 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 6488 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 6489 // don't forget to call complete() at the end of whatever you do 6490 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 6491 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 6492 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 6493 // (i.e. when mobile styles are used to make the sub menus collapsible) 6494 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 6495 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 6496 // (i.e. when mobile styles are used to make the sub menus collapsible) 6497 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 6498 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 6499 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 6500 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 6501 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 6502 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 6503 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 6504 bottomToTopSubMenus: false, // bottom to top display of the sub menus 6505 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 6506 }; 6507 6508})(jQuery); 6509 6510/* 6511 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 6512 * 6513 * Uses the built in easing capabilities added In jQuery 1.1 6514 * to offer multiple easing options 6515 * 6516 * TERMS OF USE - jQuery Easing 6517 * 6518 * Open source under the BSD License. 6519 * 6520 * Copyright © 2008 George McGinley Smith 6521 * All rights reserved. 6522 * 6523 * Redistribution and use in source and binary forms, with or without modification, 6524 * are permitted provided that the following conditions are met: 6525 * 6526 * Redistributions of source code must retain the above copyright notice, this list of 6527 * conditions and the following disclaimer. 6528 * Redistributions in binary form must reproduce the above copyright notice, this list 6529 * of conditions and the following disclaimer in the documentation and/or other materials 6530 * provided with the distribution. 6531 * 6532 * Neither the name of the author nor the names of contributors may be used to endorse 6533 * or promote products derived from this software without specific prior written permission. 6534 * 6535 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6536 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6537 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6538 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6539-6684
6539 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6540 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6541 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6542 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6543 * OF THE POSSIBILITY OF SUCH DAMAGE. 6544 * 6545*/ 6546 6547// t: current time, b: begInnIng value, c: change In value, d: duration 6548jQuery.easing['jswing'] = jQuery.easing['swing']; 6549 6550jQuery.extend( jQuery.easing, 6551{ 6552 def: 'easeOutQuad', 6553 swing: function (x, t, b, c, d) { 6554 //alert(jQuery.easing.default); 6555 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 6556 }, 6557 easeInQuad: function (x, t, b, c, d) { 6558 return c*(t/=d)*t + b; 6559 }, 6560 easeOutQuad: function (x, t, b, c, d) { 6561 return -c *(t/=d)*(t-2) + b; 6562 }, 6563 easeInOutQuad: function (x, t, b, c, d) { 6564 if ((t/=d/2) < 1) return c/2*t*t + b; 6565 return -c/2 * ((--t)*(t-2) - 1) + b; 6566 }, 6567 easeInCubic: function (x, t, b, c, d) { 6568 return c*(t/=d)*t*t + b; 6569 }, 6570 easeOutCubic: function (x, t, b, c, d) { 6571 return c*((t=t/d-1)*t*t + 1) + b; 6572 }, 6573 easeInOutCubic: function (x, t, b, c, d) { 6574 if ((t/=d/2) < 1) return c/2*t*t*t + b; 6575 return c/2*((t-=2)*t*t + 2) + b; 6576 }, 6577 easeInQuart: function (x, t, b, c, d) { 6578 return c*(t/=d)*t*t*t + b; 6579 }, 6580 easeOutQuart: function (x, t, b, c, d) { 6581 return -c * ((t=t/d-1)*t*t*t - 1) + b; 6582 }, 6583 easeInOutQuart: function (x, t, b, c, d) { 6584 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 6585 return -c/2 * ((t-=2)*t*t*t - 2) + b; 6586 }, 6587 easeInQuint: function (x, t, b, c, d) { 6588 return c*(t/=d)*t*t*t*t + b; 6589 }, 6590 easeOutQuint: function (x, t, b, c, d) { 6591 return c*((t=t/d-1)*t*t*t*t + 1) + b; 6592 }, 6593 easeInOutQuint: function (x, t, b, c, d) { 6594 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 6595 return c/2*((t-=2)*t*t*t*t + 2) + b; 6596 }, 6597 easeInSine: function (x, t, b, c, d) { 6598 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 6599 }, 6600 easeOutSine: function (x, t, b, c, d) { 6601 return c * Math.sin(t/d * (Math.PI/2)) + b; 6602 }, 6603 easeInOutSine: function (x, t, b, c, d) { 6604 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 6605 }, 6606 easeInExpo: function (x, t, b, c, d) { 6607 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 6608 }, 6609 easeOutExpo: function (x, t, b, c, d) { 6610 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 6611 }, 6612 easeInOutExpo: function (x, t, b, c, d) { 6613 if (t==0) return b; 6614 if (t==d) return b+c; 6615 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 6616 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 6617 }, 6618 easeInCirc: function (x, t, b, c, d) { 6619 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 6620 }, 6621 easeOutCirc: function (x, t, b, c, d) { 6622 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 6623 }, 6624 easeInOutCirc: function (x, t, b, c, d) { 6625 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 6626 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 6627 }, 6628 easeInElastic: function (x, t, b, c, d) { 6629 var s=1.70158;var p=0;var a=c; 6630 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6631 if (a < Math.abs(c)) { a=c; var s=p/4; } 6632 else var s = p/(2*Math.PI) * Math.asin (c/a); 6633 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6634 }, 6635 easeOutElastic: function (x, t, b, c, d) { 6636 var s=1.70158;var p=0;var a=c; 6637 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6638 if (a < Math.abs(c)) { a=c; var s=p/4; } 6639 else var s = p/(2*Math.PI) * Math.asin (c/a); 6640 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 6641 }, 6642 easeInOutElastic: function (x, t, b, c, d) { 6643 var s=1.70158;var p=0;var a=c; 6644 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 6645 if (a < Math.abs(c)) { a=c; var s=p/4; } 6646 else var s = p/(2*Math.PI) * Math.asin (c/a); 6647 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6648 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 6649 }, 6650 easeInBack: function (x, t, b, c, d, s) { 6651 if (s == undefined) s = 1.70158; 6652 return c*(t/=d)*t*((s+1)*t - s) + b; 6653 }, 6654 easeOutBack: function (x, t, b, c, d, s) { 6655 if (s == undefined) s = 1.70158; 6656 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 6657 }, 6658 easeInOutBack: function (x, t, b, c, d, s) { 6659 if (s == undefined) s = 1.70158; 6660 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 6661 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 6662 }, 6663 easeInBounce: function (x, t, b, c, d) { 6664 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 6665 }, 6666 easeOutBounce: function (x, t, b, c, d) { 6667 if ((t/=d) < (1/2.75)) { 6668 return c*(7.5625*t*t) + b; 6669 } else if (t < (2/2.75)) { 6670 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 6671 } else if (t < (2.5/2.75)) { 6672 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 6673 } else { 6674 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 6675 } 6676 }, 6677 easeInOutBounce: function (x, t, b, c, d) { 6678 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 6679 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 6680 } 6681}); 6682 6683/* 6684 *
6685 * TERMS OF USE - EASING EQUATIONS 6686 * 6687 * Open source under the BSD License. 6688 * 6689 * Copyright © 2001 Robert Penner 6690 * All rights reserved. 6691 * 6692 * Redistribution and use in source and binary forms, with or without modification, 6693 * are permitted provided that the following conditions are met: 6694 * 6695 * Redistributions of source code must retain the above copyright notice, this list of 6696 * conditions and the following disclaimer. 6697 * Redistributions in binary form must reproduce the above copyright notice, this list 6698 * of conditions and the following disclaimer in the documentation and/or other materials 6699 * provided with the distribution. 6700 * 6701 * Neither the name of the author nor the names of contributors may be used to endorse 6702 * or promote products derived from this software without specific prior written permission. 6703 * 6704 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6705 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6706 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6707 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 6708 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6709 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6710 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6711 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6712 * OF THE POSSIBILITY OF SUCH DAMAGE. 6713 * 6714 */ 6715 6716(function($, window, undefined) { 6717 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 6718 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 6719 6720 // requestAnimationFrame polyfill by Erik Möller 6721 // fixes from Paul Irish and Tino Zijdel 6722 6723 var lastTime = 0, 6724 running, 6725 animate = function (elem) { 6726 if (running) { 6727 window.requestAnimationFrame(animate, elem); 6728 jQuery.fx.tick(); 6729 } 6730 }, 6731 vendors = ['ms', 'moz', 'webkit', 'o']; 6732 6733 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 6734 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 6735 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 6736 || window[vendors[x]+'CancelRequestAnimationFrame']; 6737 } 6738 6739 if (!window.requestAnimationFrame) 6740 window.requestAnimationFrame = function(fn, element) { 6741 var currTime = new Date().getTime(), 6742 delta = currTime - lastTime, 6743 timeToCall = Math.max(0, 16 - delta); 6744 6745 var id = window.setTimeout(function() { 6746 fn(currTime + timeToCall); 6747 }, 6748 timeToCall 6749 ); 6750 6751 lastTime = currTime + timeToCall; 6752 6753 return id; 6754 }; 6755 6756 if (!window.cancelAnimationFrame) { 6757 window.cancelAnimationFrame = function(id) { 6758 clearTimeout(id); 6759 }; 6760 } 6761 6762 jQuery.fx.timer = function (timer) { 6763 if (timer() && jQuery.timers.push(timer) && !running) { 6764 running = true; 6765 animate(timer.elem); 6766 } 6767 }; 6768 6769 jQuery.fx.stop = function() { 6770 running = false; 6771 }; 6772 6773}(jQuery, this)); 6774 6775/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 6776 * Licensed under the MIT License (LICENSE.txt). 6777 * 6778 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 6779 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6780 * Thanks to: Seamus Leahy for adding deltaX and deltaY 6781 * 6782 * Version: 3.0.6 6783 * 6784 * Requires: 1.2.2+ 6785 */ 6786(function($) { 6787 var types = ['DOMMouseScroll', 'mousewheel']; 6788 if ($.event.fixHooks) { 6789 for (var i = types.length; i;) { 6790 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 6791 } 6792 } 6793 $.event.special.mousewheel = { 6794 setup: function() { 6795 if (this.addEventListener) { 6796 for (var i = types.length; i;) { 6797 this.addEventListener(types[--i], handler, false); 6798 } 6799 } else { 6800 this.onmousewheel = handler; 6801 } 6802 }, 6803 teardown: function() { 6804 if (this.removeEventListener) { 6805 for (var i = types.length; i;) { 6806 this.removeEventListener(types[--i], handler, false); 6807 } 6808 } else { 6809 this.onmousewheel = null; 6810 } 6811 } 6812 }; 6813 $.fn.extend({ 6814 mousewheel: function(fn) { 6815 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 6816 }, 6817 unmousewheel: function(fn) { 6818 return this.unbind("mousewheel", fn); 6819 } 6820 }); 6821 6822 function handler(event) { 6823 var orgEvent = event || window.event, 6824 args = [].slice.call(arguments, 1), 6825 delta = 0, 6826 returnValue = true, 6827 deltaX = 0, 6828 deltaY = 0; 6829 event = $.event.fix(orgEvent); 6830 event.type = "mousewheel"; 6831 // Old school scrollwheel delta 6832 if (orgEvent.wheelDelta) { 6833 delta = orgEvent.wheelDelta / 120; 6834 } 6835 if (orgEvent.detail) { 6836 delta = -orgEvent.detail / 3; 6837 } 6838 // New school multidimensional scroll (touchpads) deltas 6839 deltaY = delta; 6840 // Gecko 6841 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 6842 deltaY = 0; 6843 deltaX = -1 * delta; 6844 } 6845 // Webkit 6846 if (orgEvent.wheelDeltaY !== undefined) { 6847 deltaY = orgEvent.wheelDeltaY / 120; 6848 } 6849 if (orgEvent.wheelDeltaX !== undefined) { 6850 deltaX = -1 * orgEvent.wheelDeltaX / 120; 6851 } 6852 // Add event and delta to the front of the arguments 6853 args.unshift(event, delta, deltaX, deltaY); 6854 return ($.event.dispatch || $.event.handle).apply(this, args); 6855 } 6856})(jQuery); 6857 6858/** 6859 * jQuery iLightBox - Revolutionary Lightbox Plugin 6860 * http://www.ilightbox.net/ 6861 * 6862 * @version: 2.2.0 - September 23, 2014 6863 * 6864 * @author: Hemn Chawroka 6865 * http://www.iprodev.com/ 6866 * 6867 */ 6868(function($, window, undefined) { 6869 6870 var extensions = { 6871 flash: ['swf'], 6872 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 6873 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 6874 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 6875 }, 6876 6877 // Global DOM elements 6878 $win = $(window), 6879 $doc = $(document), 6880
6881 // Support indicators 6882 browser, 6883 transform, 6884 gpuAcceleration, 6885 fullScreenApi = '', 6886 supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)), 6887 6888 // Events 6889 clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox", 6890 touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 6891 touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 6892 touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 6893 6894 // Math shorthands 6895 abs = Math.abs, 6896 sqrt = Math.sqrt, 6897 round = Math.round, 6898 max = Math.max, 6899 min = Math.min, 6900 floor = Math.floor, 6901 random = Math.random, 6902 6903 pluginspages = { 6904 quicktime: 'http://www.apple.com/quicktime/download', 6905 flash: 'http://www.adobe.com/go/getflash' 6906 }, 6907 6908 iLightBox = function(el, options, items, instant) { 6909 var iL = this; 6910 6911 iL.options = options, 6912 iL.selector = el.selector || el, 6913 iL.context = el.context, 6914 iL.instant = instant; 6915 6916 if (items.length < 1) iL.attachItems(); 6917 else iL.items = items; 6918 6919 iL.vars = { 6920 total: iL.items.length, 6921 start: 0, 6922 current: null, 6923 next: null, 6924 prev: null, 6925 BODY: $('body'), 6926 loadRequests: 0, 6927 overlay: $('<div class="ilightbox-overlay"></div>'), 6928 loader: $('<div class="ilightbox-loader"><div></div></div>'), 6929 toolbar: $('<div class="ilightbox-toolbar"></div>'), 6930 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 6931 title: $('<div class="ilightbox-title"></div>'), 6932 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 6933 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 6934 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 6935 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 6936 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 6937 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6938 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6939 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6940 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 6941 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'), 6942 thumbnails: $('<div class="ilightbox-thumbnails" ondragstart="return false;"><div class="ilightbox-thumbnails-container"><a class="ilightbox-thumbnails-dragger"></a><div class="ilightbox-thumbnails-grid"></div></div></div>'), 6943 thumbs: false, 6944 nextLock: false, 6945 prevLock: false, 6946 hashLock: false, 6947 isMobile: false, 6948 mobileMaxWidth: 980, 6949 isInFullScreen: false, 6950 isSwipe: false, 6951 mouseID: 0, 6952 cycleID: 0, 6953 isPaused: 0 6954 }; 6955 6956 // Hideable elements with mousemove event 6957 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 6958 6959 iL.normalizeItems(); 6960 6961 //Check necessary plugins 6962 iL.availPlugins(); 6963 6964 //Set startFrom 6965 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 6966 6967 //If randomStart 6968 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 6969 iL.vars.start = iL.options.startFrom; 6970 6971 if (instant) iL.instantCall(); 6972 else iL.patchItemsEvents(); 6973 6974 if (iL.options.linkId) { 6975 iL.hashChangeHandler(); 6976 $win.iLightBoxHashChange(function() { 6977 iL.hashChangeHandler(); 6978 }); 6979 } 6980 6981 if (supportTouch) {
6982 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 6983 replace = "itap"; 6984 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 6985 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 6986 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 6987 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 6988 } 6989 6990 if (iL.options.controls.arrows) { 6991 $.extend(iL.options.styles, { 6992 nextOffsetX: 36, 6993 prevOffsetX: 36, 6994 nextOpacity: 0, 6995 prevOpacity: 0 6996 }); 6997 } 6998 }; 6999 7000 //iLightBox helpers 7001 iLightBox.prototype = { 7002 showLoader: function() { 7003 var iL = this; 7004 iL.vars.loadRequests += 1; 7005 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.stop().animate({ 7006 //top: '2px' 7007 opacity: '1' 7008 }, iL.options.show.speed, 'easeOutCirc'); 7009 else iL.vars.loader.stop().animate({ 7010 // left: '2px' 7011 opacity: '1' 7012 }, iL.options.show.speed, 'easeOutCirc'); 7013 }, 7014 7015 hideLoader: function() { 7016 var iL = this; 7017 iL.vars.loadRequests -= 1; 7018 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 7019 if (iL.options.path.toLowerCase() == "horizontal") { 7020 if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({ 7021 //top: '-20px' 7022 opacity: '0' 7023 }, iL.options.show.speed, 'easeInCirc'); 7024 } else { 7025 if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({ 7026 //left: '-20px' 7027 opacity: '0' 7028 }, iL.options.show.speed, 'easeInCirc'); 7029 } 7030 }, 7031 7032 createUI: function() { 7033 var iL = this; 7034 7035 iL.ui = { 7036 currentElement: iL.vars.holder, 7037 nextElement: iL.vars.nextPhoto, 7038 prevElement: iL.vars.prevPhoto, 7039 currentItem: iL.vars.current, 7040 nextItem: iL.vars.next, 7041 prevItem: iL.vars.prev, 7042 hide: function() { 7043 iL.closeAction(); 7044 }, 7045 refresh: function() { 7046 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7047 }, 7048 fullscreen: function() { 7049 iL.fullScreenAction(); 7050 } 7051 }; 7052 }, 7053 7054 attachItems: function() { 7055 var iL = this, 7056 itemsObject = new Array(), 7057 items = new Array(); 7058 7059 $(iL.selector, iL.context).each(function() { 7060 var t = $(this), 7061 URL = t.attr(iL.options.attr) || null, 7062 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 7063 caption = t.data('caption'), 7064 title = t.data('title'), 7065 type = t.data('type') || getTypeByExtension(URL); 7066 7067 items.push({ 7068 URL: URL, 7069 caption: caption, 7070 title: title, 7071 type: type, 7072 options: options 7073 }); 7074 7075 if (!iL.instant) itemsObject.push(t); 7076 }); 7077 7078 iL.items = items, 7079 iL.itemsObject = itemsObject; 7080 }, 7081 7082 normalizeItems: function() { 7083 var iL = this, 7084 newItems = new Array(); 7085 7086 $.each(iL.items, function(key, val) { 7087 7088 if (typeof val == "string") val = { 7089 url: val 7090 }; 7091 7092 var URL = val.url || val.URL || null, 7093 options = val.options || {}, 7094 caption = val.caption || null, 7095 title = val.title || null, 7096 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 7097 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 7098 7099 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null), 7100 options.videoType = options.videoType || null, 7101 options.skin = options.skin || iL.options.skin, 7102 options.width = options.width || null, 7103 options.height = options.height || null, 7104 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 7105 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 7106 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 7107 7108 if (type == "video") { 7109 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 7110 7111 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 7112 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 7113 options.html5video.preload = options.html5video.preload || "metadata"; 7114 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
7115 } 7116 7117 if (!options.width || !options.height) { 7118 if (type == "video") options.width = 1280, options.height = 720; 7119 else if (type == "iframe") options.width = '100%', options.height = '90%'; 7120 else if (type == "flash") options.width = 1280, options.height = 720; 7121 } 7122 7123 delete val.url; 7124 val.index = key; 7125 val.URL = URL; 7126 val.caption = caption; 7127 val.title = title; 7128 val.type = type; 7129 val.options = options; 7130 val.ext = ext; 7131 7132 newItems.push(val); 7133 }); 7134 7135 iL.items = newItems; 7136 }, 7137 7138 instantCall: function() { 7139 var iL = this, 7140 key = iL.vars.start; 7141 7142 iL.vars.current = key; 7143 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 7144 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 7145 7146 iL.addContents(); 7147 iL.patchEvents(); 7148 }, 7149 7150 addContents: function() { 7151 var iL = this, 7152 vars = iL.vars, 7153 opts = iL.options, 7154 viewport = getViewport(), 7155 path = opts.path.toLowerCase(), 7156 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 7157 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 7158 }), 7159 needRecognition = recognizingItems.length > 0; 7160 7161 if (opts.mobileOptimizer && !opts.innerToolbar) 7162 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7163 7164 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 7165 7166 if (opts.linkId) 7167 vars.overlay[0].setAttribute('linkid', opts.linkId); 7168 7169 //Add Toolbar Buttons 7170 if (opts.controls.toolbar) { 7171 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 7172 if (opts.controls.fullscreen) 7173 vars.toolbar.append(vars.fullScreenButton); 7174 if (opts.controls.slideshow) 7175 vars.toolbar.append(vars.innerPlayButton); 7176 if (vars.total > 1) 7177 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 7178 } 7179 7180 //Append elements to body 7181 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 7182 7183 if (!opts.innerToolbar) 7184 vars.BODY.append(vars.toolbar); 7185 if (opts.controls.arrows) 7186 vars.BODY.append(vars.nextButton).append(vars.prevButton); 7187 7188 if (opts.controls.thumbnail && vars.total > 1) { 7189 vars.BODY.append(vars.thumbnails); 7190 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 7191 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 7192 vars.thumbs = true; 7193 } 7194 7195 //Configure loader and arrows 7196 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 7197 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 7198 } : { 7199 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 7200 }; 7201 vars.loader.addClass(opts.skin).css(loaderCss); 7202 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 7203 if (path == "horizontal") 7204 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 7205 7206 // Configure arrow buttons 7207 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7208 7209 if (!opts.infinite) { 7210 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 7211 7212 if (vars.current == 0) 7213 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 7214 if (vars.current >= vars.total - 1) 7215 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 7216 } 7217 7218 if (opts.show.effect) { 7219 vars.overlay.stop().fadeIn(opts.show.speed); 7220 vars.toolbar.stop().fadeIn(opts.show.speed); 7221 } else { 7222 vars.overlay.show(); 7223 vars.toolbar.show(); 7224 } 7225 7226 var length = recognizingItems.length; 7227 if (needRecognition) { 7228 iL.showLoader(); 7229 7230 $.each(recognizingItems, function(key, val) { 7231 var resultFnc = function(result) { 7232 var key = -1, 7233 filter = iL.items.filter(function(e, i, arr) { 7234 if (e.URL == result.url) 7235 key = i; 7236 7237 return e.URL == result.url; 7238 }), 7239 self = iL.items[key]; 7240 7241 if (result) 7242 $.extend(true, self, { 7243 URL: result.source, 7244 type: result.type, 7245 recognized: true, 7246 options: { 7247 html5video: result.html5video, 7248 width: (result.type == "image") ? 0 : (result.width || self.width), 7249 height: (result.type == "image") ? 0 : (result.height || self.height), 7250 thumbnail: self.options.thumbnail || result.thumbnail 7251 } 7252 }); 7253 7254 length--; 7255 7256 if (length == 0) { 7257 iL.hideLoader(); 7258 7259 vars.dontGenerateThumbs = false;
7260 iL.generateThumbnails(); 7261 7262 if (opts.show.effect) 7263 setTimeout(function() { 7264 iL.generateBoxes(); 7265 }, opts.show.speed); 7266 else 7267 iL.generateBoxes(); 7268 } 7269 }; 7270 7271 iL.ogpRecognition(this, resultFnc); 7272 }); 7273 } 7274 else { 7275 if (opts.show.effect) 7276 setTimeout(function() { 7277 iL.generateBoxes(); 7278 }, opts.show.speed); 7279 else 7280 iL.generateBoxes(); 7281 } 7282 7283 iL.createUI(); 7284 7285 window.iLightBox = { 7286 close: function() { 7287 iL.closeAction(); 7288 }, 7289 fullscreen: function() { 7290 iL.fullScreenAction(); 7291 }, 7292 moveNext: function() { 7293 iL.moveTo('next'); 7294 }, 7295 movePrev: function() { 7296 iL.moveTo('prev'); 7297 }, 7298 goTo: function(index) { 7299 iL.goTo(index); 7300 }, 7301 refresh: function() { 7302 iL.refresh(); 7303 }, 7304 reposition: function() { 7305 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7306 }, 7307 setOption: function(options) { 7308 iL.setOption(options); 7309 }, 7310 destroy: function() { 7311 iL.closeAction(); 7312 iL.dispatchItemsEvents(); 7313 } 7314 }; 7315 7316 if (opts.linkId) { 7317 vars.hashLock = true; 7318 window.location.hash = opts.linkId + '/' + vars.current; 7319 setTimeout(function() { 7320 vars.hashLock = false; 7321 }, 55); 7322 } 7323 7324 if (!opts.slideshow.startPaused) { 7325 iL.resume(); 7326 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 7327 } 7328 7329 //Trigger the onOpen callback 7330 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 7331 7332 }, 7333 7334 loadContent: function(obj, opt, speed) { 7335 var iL = this, 7336 holder, item; 7337 7338 iL.createUI(); 7339 7340 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 7341 7342 if (opt == 'current') { 7343 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 7344 else iL.vars.lockWheel = false; 7345 7346 if (!obj.options.swipe) iL.vars.lockSwipe = true; 7347 else iL.vars.lockSwipe = false; 7348 } 7349 7350 switch (opt) { 7351 case 'current': 7352 holder = iL.vars.holder, item = iL.vars.current; 7353 break; 7354 case 'next': 7355 holder = iL.vars.nextPhoto, item = iL.vars.next; 7356 break; 7357 case 'prev': 7358 holder = iL.vars.prevPhoto, item = iL.vars.prev; 7359 break; 7360 } 7361 7362 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 7363 $('div.ilightbox-inner-toolbar', holder).remove(); 7364 7365 if (obj.title || iL.options.innerToolbar) { 7366 var innerToolbar = iL.vars.innerToolbar.clone(); 7367 if (obj.title && iL.options.show.title) { 7368 var title = iL.vars.title.clone(); 7369 title.empty().html(obj.title); 7370 innerToolbar.append(title); 7371 } 7372 if (iL.options.innerToolbar) { 7373 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 7374 } 7375 holder.prepend(innerToolbar); 7376 } 7377 7378 iL.loadSwitcher(obj, holder, item, opt); 7379 }, 7380 7381 loadSwitcher: function(obj, holder, item, opt) { 7382 var iL = this, 7383 opts = iL.options, 7384 api = { 7385 element: holder, 7386 position: item 7387 }; 7388 7389 switch (obj.type) { 7390 case 'image': 7391 //Trigger the onBeforeLoad callback 7392 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7393 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7394 7395 iL.loadImage(obj.URL, function(img) { 7396 //Trigger the onAfterLoad callback 7397 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7398 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7399 7400 var width = (img) ? img.width : 400, 7401 height = (img) ? img.height : 200; 7402 7403 holder.data({ 7404 naturalWidth: width, 7405 naturalHeight: height 7406 }); 7407 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 7408 7409 //Trigger the onRender callback 7410 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7411 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7412 7413 iL.configureHolder(obj, opt, holder); 7414 }); 7415 7416 break; 7417
7418 case 'video': 7419 holder.data({ 7420 naturalWidth: obj.options.width, 7421 naturalHeight: obj.options.height 7422 }); 7423 7424 iL.addContent(holder, obj); 7425 7426 //Trigger the onRender callback 7427 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7428 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7429 7430 iL.configureHolder(obj, opt, holder); 7431 7432 break; 7433 7434 case 'iframe': 7435 iL.showLoader(); 7436 holder.data({ 7437 naturalWidth: obj.options.width, 7438 naturalHeight: obj.options.height 7439 }); 7440 var el = iL.addContent(holder, obj); 7441 7442 //Trigger the onRender callback 7443 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7444 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7445 7446 //Trigger the onBeforeLoad callback 7447 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7448 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7449 7450 el.bind('load', function() { 7451 //Trigger the onAfterLoad callback 7452 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7453 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7454 7455 iL.hideLoader(); 7456 iL.configureHolder(obj, opt, holder); 7457 el.unbind('load'); 7458 }); 7459 7460 break; 7461 7462 case 'inline': 7463 var el = $(obj.URL), 7464 content = iL.addContent(holder, obj), 7465 images = findImageInElement(holder); 7466 7467 holder.data({ 7468 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7469 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7470 }); 7471 content.children().eq(0).show(); 7472 7473 //Trigger the onRender callback 7474 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7475 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7476 7477 //Trigger the onBeforeLoad callback 7478 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7479 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7480 7481 iL.loadImage(images, function() { 7482 //Trigger the onAfterLoad callback 7483 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7484 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7485 7486 iL.configureHolder(obj, opt, holder); 7487 }); 7488 7489 break; 7490 7491 case 'flash': 7492 var el = iL.addContent(holder, obj); 7493 7494 holder.data({ 7495 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7496 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7497 }); 7498 7499 //Trigger the onRender callback 7500 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7501 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7502 7503 iL.configureHolder(obj, opt, holder); 7504 7505 break; 7506 7507 case 'ajax': 7508 var ajax = obj.options.ajax || {}; 7509 //Trigger the onBeforeLoad callback 7510 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7511 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7512 7513 iL.showLoader(); 7514 $.ajax({ 7515 url: obj.URL || opts.ajaxSetup.url, 7516 data: ajax.data || null, 7517 dataType: ajax.dataType || "html", 7518 type: ajax.type || opts.ajaxSetup.type, 7519 cache: ajax.cache || opts.ajaxSetup.cache, 7520 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 7521 global: ajax.global || opts.ajaxSetup.global, 7522 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 7523 username: ajax.username || opts.ajaxSetup.username, 7524 password: ajax.password || opts.ajaxSetup.password, 7525 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 7526 complete: ajax.complete || opts.ajaxSetup.complete, 7527 success: function(data, textStatus, jqXHR) { 7528 iL.hideLoader(); 7529 7530 var el = $(data), 7531 container = $('div.ilightbox-container', holder), 7532 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 7533 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 7534 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 7535 'overflow': 'hidden' 7536 } : {}; 7537 7538 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 7539 holder.show().data({
7540 naturalWidth: (elWidth || container.outerWidth()), 7541 naturalHeight: (elHeight || container.outerHeight()) 7542 }).hide(); 7543 7544 //Trigger the onRender callback 7545 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7546 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7547 7548 var images = findImageInElement(holder); 7549 iL.loadImage(images, function() { 7550 //Trigger the onAfterLoad callback 7551 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7552 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7553 7554 iL.configureHolder(obj, opt, holder); 7555 }); 7556 7557 opts.ajaxSetup.success(data, textStatus, jqXHR); 7558 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 7559 }, 7560 error: function(jqXHR, textStatus, errorThrown) { 7561 //Trigger the onAfterLoad callback 7562 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7563 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7564 7565 iL.hideLoader(); 7566 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 7567 iL.configureHolder(obj, opt, holder); 7568 7569 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 7570 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 7571 } 7572 }); 7573 7574 break; 7575 7576 case 'html': 7577 var object = obj.URL, 7578 el 7579 container = $('div.ilightbox-container', holder); 7580 7581 if (object[0].nodeName) el = object.clone(); 7582 else { 7583 var dom = $(object); 7584 if (dom.selector) el = $('<div>' + dom + '</div>'); 7585 else el = dom; 7586 } 7587 7588 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 7589 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 7590 7591 iL.addContent(holder, obj); 7592 7593 el.appendTo(document.documentElement).hide(); 7594 7595 //Trigger the onRender callback 7596 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7597 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7598 7599 var images = findImageInElement(holder); 7600 7601 //Trigger the onBeforeLoad callback 7602 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7603 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7604 7605 iL.loadImage(images, function() { 7606 //Trigger the onAfterLoad callback 7607 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7608 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7609 7610 holder.show().data({ 7611 naturalWidth: (elWidth || container.outerWidth()), 7612 naturalHeight: (elHeight || container.outerHeight()) 7613 }).hide(); 7614 el.remove(); 7615 7616 iL.configureHolder(obj, opt, holder); 7617 }); 7618 7619 break; 7620 } 7621 }, 7622 7623 configureHolder: function(obj, opt, holder) { 7624 var iL = this, 7625 vars = iL.vars, 7626 opts = iL.options; 7627 7628 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 7629 7630 if (opt == "current") 7631 var item = vars.current; 7632 else if (opt == "next") 7633 var opacity = opts.styles.nextOpacity, 7634 item = vars.next; 7635 else 7636 var opacity = opts.styles.prevOpacity, 7637 item = vars.prev; 7638 7639 var api = { 7640 element: holder, 7641 position: item 7642 }; 7643 7644 iL.items[item].options.width = iL.items[item].options.width || 0, 7645 iL.items[item].options.height = iL.items[item].options.height || 0; 7646 7647 if (opt == "current") { 7648 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 7649 holder.css(transform, ''); 7650 if (obj.caption) { 7651 iL.setCaption(obj, holder); 7652 var caption = $('div.ilightbox-caption', holder), 7653 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 7654 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7654Speed); 7655 } 7656 7657 var social = obj.options.social; 7658 if (social) { 7659 iL.setSocial(social, obj.URL, holder); 7660 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 7661 } 7662 7663 //Generate thumbnails 7664 iL.generateThumbnails(); 7665 7666 //Trigger the onShow callback 7667 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7668 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7669 }); 7670 else { 7671 holder.show(); 7672 7673 //Generate thumbnails 7674 iL.generateThumbnails(); 7675 7676 //Trigger the onShow callback 7677 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7678 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7679 } 7680 } else { 7681 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 7682 if (opt == "next") vars.nextLock = false; 7683 else vars.prevLock = false; 7684 7685 //Generate thumbnails 7686 iL.generateThumbnails(); 7687 7688 //Trigger the onShow callback 7689 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7690 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7691 }); 7692 else { 7693 holder.css({ 7694 opacity: opacity 7695 }).show(); 7696 if (opt == "next") vars.nextLock = false; 7697 else vars.prevLock = false; 7698 7699 //Generate thumbnails 7700 iL.generateThumbnails(); 7701 7702 //Trigger the onShow callback 7703 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7704 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7705 } 7706 } 7707 7708 setTimeout(function() { 7709 iL.repositionPhoto(); 7710 }, 0); 7711 }, 7712 7713 generateBoxes: function() { 7714 var iL = this, 7715 vars = iL.vars, 7716 opts = iL.options; 7717 7718 if (opts.infinite && vars.total >= 3) { 7719 if (vars.current == vars.total - 1) vars.next = 0; 7720 if (vars.current == 0) vars.prev = vars.total - 1; 7721 } else opts.infinite = false; 7722 7723 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 7724 7725 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 7726 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 7727 }, 7728 7729 generateThumbnails: function() { 7730 var iL = this, 7731 vars = iL.vars, 7732 opts = iL.options, 7733 timeOut = null; 7734 7735 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 7736 var thumbnails = vars.thumbnails, 7737 container = $('div.ilightbox-thumbnails-container', thumbnails), 7738 grid = $('div.ilightbox-thumbnails-grid', container), 7739 i = 0; 7740 7741 grid.removeAttr('style').empty(); 7742 7743 $.each(iL.items, function(key, val) { 7744 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 7745 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 7746 thumb = val.options.thumbnail, 7747 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 7748 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 7749 7750 thumbnail.css({ 7751 opacity: 0 7752 }).addClass(isActive); 7753 7754 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 7755 icon.addClass('ilightbox-thumbnail-video'); 7756 thumbnail.append(icon); 7757 } else if (val.options.icon) { 7758 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 7759 thumbnail.append(icon); 7760 } 7761 7762 if (thumb) iL.loadImage(thumb, function(img) { 7763 i++; 7764 if (img) thumbnail.data({ 7765 naturalWidth: img.width, 7766 naturalHeight: img.height 7767 }).append('<img src="' + thumb + '" border="0" />'); 7768 else thumbnail.data({ 7769 naturalWidth: opts.thumbnails.maxWidth, 7770 naturalHeight: opts.thumbnails.maxHeight 7771 }); 7772 7773 clearTimeout(timeOut); 7774 timeOut = setTimeout(function() { 7775 iL.positionThumbnails(thumbnails, container, grid); 7776 }, 20); 7777 setTimeout(function() { 7778 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 7779 }, i * 20); 7780 }); 7781 7782 grid.append(thumbnail); 7783 }); 7784 iL.vars.dontGenerateThumbs = true; 7785 } 7786 }, 7787
7788 positionThumbnails: function(thumbnails, container, grid) { 7789 var iL = this, 7790 vars = iL.vars, 7791 opts = iL.options, 7792 viewport = getViewport(), 7793 path = opts.path.toLowerCase(); 7794 7795 if (!thumbnails) thumbnails = vars.thumbnails; 7796 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 7797 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 7798 7799 var thumbs = $('.ilightbox-thumbnail', grid), 7800 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 7801 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 7802 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 7803 gridHeight = (path == 'horizontal') ? heightAvail : 0, 7804 active = $('.ilightbox-active', grid), 7805 gridCss = {}, 7806 css = {}; 7807 7808 if (arguments.length < 3) { 7809 thumbs.css({ 7810 opacity: opts.thumbnails.normalOpacity 7811 }); 7812 active.css({ 7813 opacity: opts.thumbnails.activeOpacity 7814 }); 7815 } 7816 7817 thumbs.each(function(i) { 7818 var t = $(this), 7819 data = t.data(), 7820 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 7821 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 7822 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 7823 7824 t.css({ 7825 width: dims.width, 7826 height: dims.height 7827 }); 7828 if (path == 'horizontal') t.css({ 7829 'float': 'left' 7830 }); 7831 7832 (path == 'horizontal') ? ( 7833 gridWidth += t.outerWidth() 7834 ) : ( 7835 gridHeight += t.outerHeight() 7836 ); 7837 }); 7838 7839 gridCss = { 7840 width: gridWidth, 7841 height: gridHeight 7842 }; 7843 7844 grid.css(gridCss); 7845 7846 gridCss = {}; 7847 7848 var gridOffset = grid.offset(), 7849 activeOffset = (active.length) ? active.offset() : { 7850 top: parseInt(heightAvail / 2), 7851 left: parseInt(widthAvail / 2) 7852 }; 7853 7854 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 7855 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 7856 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 7857 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 7858 7859 (path == 'horizontal') ? ( 7860 gridCss.top = 0, 7861 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 7862 ) : ( 7863 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 7864 gridCss.left = 0 7865 ); 7866 7867 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 7868 else grid.css(gridCss); 7869 }, 7870 7871 loadImage: function(image, callback) { 7872 if (!$.isArray(image)) image = [image]; 7873 7874 var iL = this, 7875 length = image.length; 7876 7877 if (length > 0) { 7878 iL.showLoader(); 7879 $.each(image, function(index, value) { 7880 var img = new Image(); 7881 img.onload = function() { 7882 length -= 1; 7883 if (length == 0) { 7884 iL.hideLoader(); 7885 callback(img); 7886 } 7887 }; 7888 img.onerror = img.onabort = function() { 7889 length -= 1; 7890 if (length == 0) { 7891 iL.hideLoader(); 7892 callback(false); 7893 } 7894 }; 7895 img.src = image[index]; 7896 }); 7897 } else callback(false); 7898 }, 7899 7900 patchItemsEvents: function() { 7901 var iL = this, 7902 vars = iL.vars, 7903 clickEvent = supportTouch ? "itap.iL" : "click.iL", 7904 vEvent = supportTouch ? "click.iL" : "itap.iL"; 7905 7906 if (iL.context && iL.selector) { 7907 var $items = $(iL.selector, iL.context); 7908 7909 $(iL.context).on(clickEvent, iL.selector, function() { 7910 7911 var $this = $(this), 7912 key = $items.index($this); 7913 if (UNCODE.isMobile) { 7914 var isCarousel = $this.closest('.owl-carousel'); 7915 if (isCarousel.length) { 7916 if (isCarousel.hasClass('owl-translating')) return false; 7917 } 7918 } 7919 7920 vars.current = key; 7921 vars.next = iL.items[key + 1] ? key + 1 : null; 7922 vars.prev = iL.items[key - 1] ? key - 1 : null; 7923 7924 iL.addContents(); 7925 iL.patchEvents(); 7926 7927 return false; 7928 }).on(vEvent, iL.selector, function() { 7929 return false; 7930 }); 7931 } else 7932 $.each(iL.itemsObject, function(key, val) { 7933 val.on(clickEvent, function() { 7934 vars.current = key; 7935 vars.next = iL.items[key + 1] ? key + 1 : null; 7936 vars.prev = iL.items[key - 1] ? key - 1 : null; 7937 7938 iL.addContents(); 7939 iL.patchEvents(); 7940 7941 return false;
7942 }).on(vEvent, function() { 7943 return false; 7944 }); 7945 }); 7946 }, 7947 7948 dispatchItemsEvents: function() { 7949 var iL = this, 7950 vars = iL.vars, 7951 opts = iL.options; 7952 7953 if (iL.context && iL.selector) 7954 $(iL.context).off('.iL', iL.selector); 7955 else 7956 $.each(iL.itemsObject, function(key, val) { 7957 val.off('.iL'); 7958 }); 7959 }, 7960 7961 refresh: function() { 7962 var iL = this; 7963 7964 iL.dispatchItemsEvents(); 7965 iL.attachItems(); 7966 iL.normalizeItems(); 7967 iL.patchItemsEvents(); 7968 }, 7969 7970 patchEvents: function() { 7971 var iL = this, 7972 vars = iL.vars, 7973 opts = iL.options, 7974 path = opts.path.toLowerCase(), 7975 holders = $('.ilightbox-holder'), 7976 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 7977 durationThreshold = 1000, 7978 horizontalDistanceThreshold = 7979 verticalDistanceThreshold = 100, 7980 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 7981 7982 $win.bind('resize.iLightBox', function() { 7983 var viewport = getViewport(); 7984 7985 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7986 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7987 7988 iL.repositionPhoto(null); 7989 if (supportTouch) { 7990 clearTimeout(vars.setTime); 7991 vars.setTime = setTimeout(function() { 7992 var scrollTop = getScrollXY().y; 7993 window.scrollTo(0, scrollTop - 30); 7994 window.scrollTo(0, scrollTop + 30); 7995 window.scrollTo(0, scrollTop); 7996 }, 2000); 7997 } 7998 if (vars.thumbs) iL.positionThumbnails(); 7999 }).bind('keydown.iLightBox', function(event) { 8000 if (opts.controls.keyboard) { 8001 switch (event.keyCode) { 8002 case 13: 8003 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 8004 break; 8005 case 27: 8006 if (opts.keyboard.esc) iL.closeAction(); 8007 break; 8008 case 37: 8009 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 8010 break; 8011 case 38: 8012 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 8013 break; 8014 case 39: 8015 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 8016 break; 8017 case 40: 8018 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 8019 break; 8020 } 8021 } 8022 }); 8023 8024 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 8025 iL.doFullscreen(); 8026 }); 8027 8028 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 8029 return arr.lastIndexOf(e) === i; 8030 }), 8031 holderEvents = ""; 8032 8033 $.each(holderEventsArr, function(key, val) { 8034 if (key != 0) holderEvents += ' '; 8035 holderEvents += val; 8036 }); 8037 8038 $doc.on(clickEvent, '.ilightbox-overlay', function() { 8039 if (opts.overlay.blur) iL.closeAction(); 8040 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 8041 iL.moveTo('next'); 8042 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 8043 iL.moveTo('prev'); 8044 }).on(clickEvent, '.ilightbox-thumbnail', function() { 8045 var t = $(this), 8046 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 8047 index = thumbs.index(t); 8048 8049 if (index != vars.current) iL.goTo(index); 8050 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8051 var caption = $('div.ilightbox-caption', vars.holder), 8052 social = $('div.ilightbox-social', vars.holder), 8053 fadeSpeed = opts.effects.fadeSpeed; 8054 8055 if (vars.nextLock || vars.prevLock) { 8056 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 8057 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 8058 8059 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 8060 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 8061 } else { 8062 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 8063 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 8064 8065 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 8066 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 8067 } 8068 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 8069 if (e.type == 'mouseenter') vars.lockWheel = true; 8070 else vars.lockWheel = false;
8071 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 8072 var t = $(this); 8073 8074 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 8075 else if (t.hasClass('ilightbox-play')) { 8076 iL.resume(); 8077 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 8078 } else if (t.hasClass('ilightbox-pause')) { 8079 iL.pause(); 8080 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 8081 } else iL.closeAction(); 8082 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 8083 // prevent scrolling 8084 e.preventDefault(); 8085 }); 8086 8087 function mouseMoveHandler(e) { 8088 if (!vars.isMobile) { 8089 if (!vars.mouseID) { 8090 vars.hideableElements.show(); 8091 } 8092 8093 vars.mouseID = clearTimeout(vars.mouseID); 8094 8095 if (buttonsArray.indexOf(e.target) === -1) 8096 vars.mouseID = setTimeout(function() { 8097 vars.hideableElements.hide(); 8098 vars.mouseID = clearTimeout(vars.mouseID); 8099 }, 3000); 8100 } 8101 } 8102 8103 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 8104 8105 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8106 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 8107 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 8108 }); 8109 8110 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'); 8111 8112 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 8113 if (!vars.lockWheel) { 8114 event.preventDefault(); 8115 if (delta < 0) iL.moveTo('next'); 8116 else if (delta > 0) iL.moveTo('prev'); 8117 } 8118 }); 8119 8120 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 8121 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 8122 8123 vars.BODY.addClass('ilightbox-closedhand'); 8124 8125 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 8126 scrollTop = $doc.scrollTop(), 8127 scrollLeft = $doc.scrollLeft(), 8128 offsets = [ 8129 holders.eq(0).offset(), 8130 holders.eq(1).offset(), 8131 holders.eq(2).offset() 8132 ], 8133 offSet = [{ 8134 top: offsets[0].top - scrollTop, 8135 left: offsets[0].left - scrollLeft 8136 }, { 8137 top: offsets[1].top - scrollTop, 8138 left: offsets[1].left - scrollLeft 8139 }, { 8140 top: offsets[2].top - scrollTop, 8141 left: offsets[2].left - scrollLeft 8142 }], 8143 start = { 8144 time: (new Date()).getTime(), 8145 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8146 }, 8147 stop; 8148 8149 function moveEachHandler(i) { 8150 var t = $(this), 8151 offset = offSet[i], 8152 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 8153 8154 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 8155 } 8156 8157 function moveHandler(event) { 8158 8159 if (!start) return; 8160 8161 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 8162 8163 stop = { 8164 time: (new Date()).getTime(), 8165 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8166 }; 8167 8168 holders.each(moveEachHandler); 8169 8170 // prevent scrolling 8171 event.preventDefault(); 8172 } 8173 8174 function repositionHolders() { 8175 holders.each(function() { 8176 var t = $(this), 8177 offset = t.data('offset') || { 8178 top: t.offset().top - scrollTop, 8179 left: t.offset().left - scrollLeft 8180 }, 8181 top = offset.top, 8182 left = offset.left; 8183 8184 t.css(transform, gpuAcceleration).stop().animate({ 8185 top: top, 8186 left: left 8187 }, 500, 'easeOutCirc', function() { 8188 t.css(transform, ''); 8189 }); 8190 }); 8191 } 8192 8193 holders.bind(touchMoveEvent, moveHandler); 8194 $doc.one(touchStopEvent, function(event) { 8195 holders.unbind(touchMoveEvent, moveHandler); 8196 8197 vars.BODY.removeClass('ilightbox-closedhand'); 8198 8199 if (start && stop) { 8200 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 8201 if (start.coords[0] > stop.coords[0]) { 8202 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8203 else { 8204 vars.isSwipe = true; 8205 iL.moveTo('next'); 8206 } 8207 } else { 8208 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8209 else { 8210 vars.isSwipe = true; 8211 iL.moveTo('prev'); 8212 } 8213 } 8214 } else if (path == "vertical" && stop.time - start.time < durationThreshold && abs(start.coords[1] - stop.coords[1]) > horizontalDistanceThreshold && abs(start.coords[0] - stop.coords[0]) < verticalDistanceThreshold) { 8215 if (start.coords[1] > stop.coords[1]) { 8216 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8217 else { 8218 vars.isSwipe = true; 8219 iL.moveTo('next'); 8220 } 8221 } else { 8222 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8223 else { 8224 vars.isSwipe = true; 8225 iL.moveTo('prev'); 8226 } 8227 } 8228 } else repositionHolders(); 8229 } 8230 start = stop = undefined; 8231 }); 8232 }); 8233 8234 }, 8235 8236 goTo: function(index) { 8237 var iL = this, 8238 vars = iL.vars, 8239 opts = iL.options, 8240 diff = (index - vars.current); 8241 8242 if (opts.infinite) { 8243 if (index == vars.total - 1 && vars.current == 0) diff = -1; 8244 if (vars.current == vars.total - 1 && index == 0) diff = 1; 8245 } 8246 8247 if (diff == 1) iL.moveTo('next'); 8248 else if (diff == -1) iL.moveTo('prev'); 8249 else { 8250 8251 if (vars.nextLock || vars.prevLock) return false;
8252 8253 //Trigger the onBeforeChange callback 8254 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 8255 8256 if (opts.linkId) { 8257 vars.hashLock = true; 8258 window.location.hash = opts.linkId + '/' + index; 8259 } 8260 8261 if (iL.items[index]) { 8262 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 8263 else iL.vars.lockWheel = false; 8264 8265 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 8266 else vars.lockSwipe = false; 8267 } 8268 8269 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 8270 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 8271 }); 8272 8273 vars.current = index; 8274 vars.next = index + 1; 8275 vars.prev = index - 1; 8276 8277 iL.createUI(); 8278 8279 setTimeout(function() { 8280 iL.generateBoxes(); 8281 }, opts.effects.loadedFadeSpeed + 50); 8282 8283 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 8284 iL.positionThumbnails(); 8285 8286 if (opts.linkId) setTimeout(function() { 8287 vars.hashLock = false; 8288 }, 55); 8289 8290 // Configure arrow buttons 8291 if (!opts.infinite) { 8292 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8293 8294 if (vars.current == 0) { 8295 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8296 } 8297 if (vars.current >= vars.total - 1) { 8298 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8299 } 8300 } 8301 8302 // Reset next cycle timeout 8303 iL.resetCycle(); 8304 8305 //Trigger the onAfterChange callback 8306 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 8307 } 8308 }, 8309 8310 moveTo: function(side) { 8311 var iL = this, 8312 vars = iL.vars, 8313 opts = iL.options, 8314 path = opts.path.toLowerCase(), 8315 viewport = getViewport(), 8316 switchSpeed = opts.effects.switchSpeed; 8317 8318 if (vars.nextLock || vars.prevLock) return false; 8319 else { 8320 8321 var item = (side == "next") ? vars.next : vars.prev; 8322 8323 if (opts.linkId) { 8324 vars.hashLock = true; 8325 window.location.hash = opts.linkId + '/' + item; 8326 } 8327 8328 if (side == "next") { 8329 if (!iL.items[item]) return false; 8330 var firstHolder = vars.nextPhoto, 8331 secondHolder = vars.holder, 8332 lastHolder = vars.prevPhoto, 8333 firstClass = 'ilightbox-prev', 8334 secondClass = 'ilightbox-next'; 8335 } else if (side == "prev") { 8336 if (!iL.items[item]) return false; 8337 var firstHolder = vars.prevPhoto, 8338 secondHolder = vars.holder, 8339 lastHolder = vars.nextPhoto, 8340 firstClass = 'ilightbox-next', 8341 secondClass = 'ilightbox-prev'; 8342 } 8343 8344 //Trigger the onBeforeChange callback 8345 if (typeof opts.callback.onBeforeChange == 'function') 8346 opts.callback.onBeforeChange.call(iL, iL.ui); 8347 8348 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 8349 8350 var captionFirst = $('div.ilightbox-caption', secondHolder), 8351 socialFirst = $('div.ilightbox-social', secondHolder); 8352 8353 if (captionFirst.length) 8354 captionFirst.stop().fadeOut(switchSpeed, function() { 8355 $(this).remove(); 8356 }); 8357 if (socialFirst.length) 8358 socialFirst.stop().fadeOut(switchSpeed, function() { 8359 $(this).remove(); 8360 }); 8361 8362 if (iL.items[item].caption) { 8363 iL.setCaption(iL.items[item], firstHolder); 8364 var caption = $('div.ilightbox-caption', firstHolder), 8365 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 8366 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 8367 } 8368 8369 var social = iL.items[item].options.social; 8370 if (social) { 8371 iL.setSocial(social, iL.items[item].URL, firstHolder); 8372 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 8373 } 8374 8375 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 8376 val.removeClass('ilightbox-next ilightbox-prev'); 8377 }); 8378 8379 var firstOffset = firstHolder.data('offset'), 8380 winW = (viewport.width - (opts.styles.pageOffsetX)), 8381 winH = (viewport.height - (opts.styles.pageOffsetY)), 8382 width = firstOffset.newDims.width, 8383 height = firstOffset.newDims.height, 8384 thumbsOffset = firstOffset.thumbsOffset, 8385 diff = firstOffset.diff, 8386 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8387 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8388 8389 firstHolder.css(transform, gpuAcceleration).animate({ 8390 top: top, 8391 left: left, 8392 opacity: 1 8393 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8394 firstHolder.css(transform, ''); 8395 }); 8396 8397 $('div.ilightbox-container', firstHolder).animate({ 8398 width: width, 8399 height: height 8400 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8401 8402 var secondOffset = secondHolder.data('offset'), 8403 object = secondOffset.object; 8404 8405 diff = secondOffset.diff; 8406 8407 width = secondOffset.newDims.width, 8408 height = secondOffset.newDims.height; 8409 8410 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8411 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8412 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 8413 8414 if (side == 'prev') 8415 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 8416 else { 8417 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 8418 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8419 } 8420 8421 $('div.ilightbox-container', secondHolder).animate({ 8422 width: width, 8423 height: height 8424 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8425 8426 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 8427 top: top, 8428 left: left, 8429 opacity: opts.styles.prevOpacity 8430 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8431 secondHolder.css(transform, ''); 8432
8433 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 8434 iL.positionThumbnails(); 8435 8436 if (iL.items[item]) { 8437 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 8438 else vars.lockWheel = false; 8439 8440 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 8441 else vars.lockSwipe = false; 8442 } 8443 8444 vars.isSwipe = false; 8445 8446 if (side == "next") { 8447 vars.nextPhoto = lastHolder, 8448 vars.prevPhoto = secondHolder, 8449 vars.holder = firstHolder; 8450 8451 vars.nextPhoto.hide(); 8452 8453 vars.next = vars.next + 1, 8454 vars.prev = vars.current, 8455 vars.current = vars.current + 1; 8456 8457 if (opts.infinite) { 8458 if (vars.current > vars.total - 1) vars.current = 0; 8459 if (vars.current == vars.total - 1) vars.next = 0; 8460 if (vars.current == 0) vars.prev = vars.total - 1; 8461 } 8462 8463 iL.createUI(); 8464 8465 if (!iL.items[vars.next]) 8466 vars.nextLock = false; 8467 else 8468 iL.loadContent(iL.items[vars.next], 'next'); 8469 } else { 8470 vars.prevPhoto = lastHolder; 8471 vars.nextPhoto = secondHolder; 8472 vars.holder = firstHolder; 8473 8474 vars.prevPhoto.hide(); 8475 8476 vars.next = vars.current; 8477 vars.current = vars.prev; 8478 vars.prev = vars.current - 1; 8479 8480 if (opts.infinite) { 8481 if (vars.current == vars.total - 1) vars.next = 0; 8482 if (vars.current == 0) vars.prev = vars.total - 1; 8483 } 8484 8485 iL.createUI(); 8486 8487 if (!iL.items[vars.prev]) 8488 vars.prevLock = false; 8489 else 8490 iL.loadContent(iL.items[vars.prev], 'prev'); 8491 } 8492 8493 if (opts.linkId) setTimeout(function() { 8494 vars.hashLock = false; 8495 }, 55); 8496 8497 // Configure arrow buttons 8498 if (!opts.infinite) { 8499 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8500 8501 if (vars.current == 0) 8502 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8503 if (vars.current >= vars.total - 1) 8504 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8505 } 8506 8507 iL.repositionPhoto(); 8508 8509 // Reset next cycle timeout 8510 iL.resetCycle(); 8511 8512 //Trigger the onAfterChange callback 8513 if (typeof opts.callback.onAfterChange == 'function') 8514 opts.callback.onAfterChange.call(iL, iL.ui); 8515 }); 8516 8517 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 8518 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 8519 8520 lastHolder.css(transform, gpuAcceleration).animate({ 8521 top: top, 8522 left: left, 8523 opacity: opts.styles.nextOpacity 8524 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8525 lastHolder.css(transform, ''); 8526 }).addClass(secondClass); 8527 8528 } 8529 }, 8530 8531 setCaption: function(obj, target) { 8532 var iL = this, 8533 caption = $('<div class="ilightbox-caption"></div>'); 8534 8535 if (obj.caption) { 8536 caption.html(obj.caption); 8537 $('div.ilightbox-container', target).append(caption); 8538 } 8539 }, 8540 8541 normalizeSocial: function(obj, url) { 8542 var iL = this, 8543 vars = iL.vars, 8544 opts = iL.options, 8545 baseURL = window.location.href; 8546 8547 $.each(obj, function(key, value) { 8548 if (!value) 8549 return true; 8550 8551 var item = key.toLowerCase(), 8552 source, text; 8553 8554 switch (item) { 8555 case 'facebook': 8556 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 8557 text = "Share on Facebook"; 8558 break; 8559 case 'twitter': 8560 source = "http://twitter.com/home?status={URL}", 8561 text = "Share on Twitter"; 8562 break; 8563 case 'googleplus': 8564 source = "https://plus.google.com/share?url={URL}", 8565 text = "Share on Google+"; 8566 break; 8567 case 'delicious': 8568 source = "http://delicious.com/post?url={URL}", 8569 text = "Share on Delicious"; 8570 break; 8571 case 'digg': 8572 source = "http://digg.com/submit?phase=2&url={URL}", 8573 text = "Share on Digg"; 8574 break; 8575 case 'reddit': 8576 source = "http://reddit.com/submit?url={URL}", 8577 text = "Share on reddit"; 8578 break; 8579 } 8580 8581 obj[key] = { 8582 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 8583 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 8584 text: value.text || text || "Share on " + key, 8585 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 8586 height: value.height || 360 8587 }; 8588 8589 }); 8590 8591 return obj; 8592 }, 8593 8594 setSocial: function(obj, url, target) { 8595 var iL = this, 8596 socialBar = $('<div class="ilightbox-social"></div>'), 8597 buttons = '<ul>'; 8598 8599 obj = iL.normalizeSocial(obj, url); 8600 8601 $.each(obj, function(key, value) { 8602 var item = key.toLowerCase(), 8603 source = value.source.replace(/\{URL\}/g, encodeURIComponent(value.URL).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+')); 8604 buttons += '<li class="' + key + '"><a href="' + source + '" onclick="javascript:window.open(this.href' + ((value.width <= 0 || value.height <= 0) ? '' : ', \'\', \'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=' + value.height + ',width=' + value.width + ',left=40,top=40\'') + ');return false;" title="' + value.text + '" target="_blank"></a></li>'; 8605 }); 8606 8607 buttons += '</ul>'; 8608 8609 socialBar.html(buttons); 8610 $('div.ilightbox-container', target).append(socialBar); 8611 }, 8612 8613 fullScreenAction: function() { 8614 var iL = this, 8615 vars = iL.vars; 8616 8617 if (fullScreenApi.supportsFullScreen) { 8618 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 8619 else fullScreenApi.requestFullScreen(document.documentElement); 8620 } else { 8621 iL.doFullscreen(); 8622 } 8623 }, 8624 8625 doFullscreen: function() { 8626 var iL = this, 8627 vars = iL.vars, 8628 viewport = getViewport(), 8629 opts = iL.options; 8630 8631 if (opts.fullAlone) { 8632 var currentHolder = vars.holder, 8633 current = iL.items[vars.current], 8634 windowWidth = viewport.width, 8635 windowHeight = viewport.height, 8636 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 8637 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8638 8639 if (!vars.isInFullScreen) { 8640 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 8641 vars.overlay.css({ 8642 opacity: 1 8643 }); 8644 8645 $.each(hideElements, function(i, element) { 8646 element.hide(); 8647 }); 8648 8649 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 8650 8651 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8652 naturalWidthOld: currentHolder.data('naturalWidth'), 8653 naturalHeightOld: currentHolder.data('naturalHeight'), 8654 naturalWidth: windowWidth, 8655 naturalHeight: windowHeight 8656 }); 8657 else { 8658 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 8659 newWidth = windowWidth, 8660 newHeight = windowHeight, 8661 width = currentHolder.data('naturalWidth'), 8662 height = currentHolder.data('naturalHeight'); 8663 8664 if (viewport.toLowerCase() == 'fill') { 8665 newHeight = (newWidth / width) * height; 8666 8667 if (newHeight < windowHeight) { 8668 newWidth = (windowHeight / height) * width, 8669 newHeight = windowHeight; 8670 } 8671 } else if (viewport.toLowerCase() == 'fit') { 8672 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 8673 8674 newWidth = dims.width, 8675 newHeight = dims.height; 8676 } else if (viewport.toLowerCase() == 'stretch') { 8677 newWidth = newWidth, 8678 newHeight = newHeight; 8679 } else { 8680 var scale = (width > newWidth || height > newHeight) ? true : false, 8681 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 8682 newWidth = dims.width, 8683 newHeight = dims.height; 8684 } 8685 8686 currentHolder.data({ 8687 naturalWidthOld: currentHolder.data('naturalWidth'), 8688 naturalHeightOld: currentHolder.data('naturalHeight'), 8689 naturalWidth: newWidth, 8690 naturalHeight: newHeight 8691 }); 8692 } 8693 8694 $.each(elements, function(key, val) { 8695 val.addClass('ilightbox-fullscreen'); 8696 }); 8697 8698 //Trigger the onEnterFullScreen callback 8699 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 8700 } else { 8701 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 8702 vars.overlay.css({ 8703 opacity: iL.options.overlay.opacity 8704 }); 8705 8706 $.each(hideElements, function(i, element) { 8707 element.show(); 8708 }); 8709 8710 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 8711 8712 currentHolder.data({ 8713 naturalWidth: currentHolder.data('naturalWidthOld'), 8714 naturalHeight: currentHolder.data('naturalHeightOld'), 8715 naturalWidthOld: null, 8716 naturalHeightOld: null 8717 }); 8718 8719 $.each(elements, function(key, val) { 8720 val.removeClass('ilightbox-fullscreen'); 8721 }); 8722 8723 //Trigger the onExitFullScreen callback 8724 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 8725 } 8726 } else { 8727 if (!vars.isInFullScreen) vars.isInFullScreen = true; 8728 else vars.isInFullScreen = false; 8729 } 8730 iL.repositionPhoto(true); 8731 }, 8732 8733 closeAction: function() { 8734 var iL = this, 8735 vars = iL.vars, 8736 opts = iL.options; 8737 8738 $win.unbind('.iLightBox'); 8739 $doc.off('.iLightBox'); 8740 8741 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 8742 8743 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 8744 8745 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 8746 vars.overlay.remove(); 8747 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8748 }); 8749 else { 8750 vars.overlay.remove(); 8751 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8752 } 8753 8754 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8755 8756 $.each(fadeOuts, function(i, element) { 8757 element.removeAttr('style').remove(); 8758 }); 8759 8760 vars.dontGenerateThumbs = vars.isInFullScreen = false; 8761 8762 window.iLightBox = null; 8763 8764 if (opts.linkId) { 8765 vars.hashLock = true; 8766 removeHash(); 8767 setTimeout(function() { 8768 vars.hashLock = false; 8769 }, 55); 8770 } 8771 8772 //Trigger the onHide callback 8773 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 8774 }, 8775 8776 repositionPhoto: function() { 8777 var iL = this, 8778 vars = iL.vars, 8779 opts = iL.options, 8780 path = opts.path.toLowerCase(), 8781 viewport = getViewport(), 8782 winWidth = viewport.width, 8783 winHeight = viewport.height; 8784 8785 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 8786 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 8787 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 8788 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 8789 offsetW = (path == 'horizontal') ? parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((width / 10) <= 30) ? 30 : (width / 10))) : parseInt(((width / 10) <= 30) ? 30 : (width / 10)) + thumbsOffsetW, 8790 offsetH = (path == 'horizontal') ? parseInt(((height / 10) <= 30) ? 30 : (height / 10)) + thumbsOffsetH : parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((height / 10) <= 30) ? 30 : (height / 10))); 8791 8792 var elObject = { 8793 type: 'current', 8794 width: width, 8795 height: height, 8796 item: iL.items[vars.current], 8797 offsetW: offsetW, 8798 offsetH: offsetH,
8799 thumbsOffsetW: thumbsOffsetW, 8800 thumbsOffsetH: thumbsOffsetH, 8801 animate: arguments.length, 8802 holder: vars.holder 8803 }; 8804 8805 iL.repositionEl(elObject); 8806 8807 if (iL.items[vars.next]) { 8808 elObject = $.extend(elObject, { 8809 type: 'next', 8810 item: iL.items[vars.next], 8811 offsetX: opts.styles.nextOffsetX, 8812 offsetY: opts.styles.nextOffsetY, 8813 holder: vars.nextPhoto 8814 }); 8815 8816 iL.repositionEl(elObject); 8817 } 8818 8819 if (iL.items[vars.prev]) { 8820 elObject = $.extend(elObject, { 8821 type: 'prev', 8822 item: iL.items[vars.prev], 8823 offsetX: opts.styles.prevOffsetX, 8824 offsetY: opts.styles.prevOffsetY, 8825 holder: vars.prevPhoto 8826 }); 8827 8828 iL.repositionEl(elObject); 8829 } 8830 8831 var loaderCss = (path == "horizontal") ? { 8832 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 8833 } : { 8834 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 8835 }; 8836 vars.loader.css(loaderCss); 8837 }, 8838 8839 repositionEl: function(obj) { 8840 var iL = this, 8841 vars = iL.vars, 8842 opts = iL.options, 8843 path = opts.path.toLowerCase(), 8844 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 8845 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 8846 itemParent = obj.item, 8847 item = obj.item.options, 8848 holder = obj.holder, 8849 offsetX = obj.offsetX || 0, 8850 offsetY = obj.offsetY || 0, 8851 thumbsOffsetW = obj.thumbsOffsetW, 8852 thumbsOffsetH = obj.thumbsOffsetH; 8853 8854 if (obj.type == 'current') { 8855 if (typeof item.width == 'number' && item.width) widthAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? widthAvail : ((item.width > widthAvail) ? widthAvail : item.width); 8856 if (typeof item.height == 'number' && item.height) heightAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? heightAvail : ((item.height > heightAvail) ? heightAvail : item.height); 8857 } else { 8858 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 8859 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 8860 } 8861 8862 heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 8863 8864 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 8865 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 8866 8867 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 8868 width: width, 8869 height: height 8870 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 8871 newDims = $.extend({}, dims, {}); 8872 8873 if (obj.type == 'prev' || obj.type == 'next') 8874 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 8875 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 8876 else 8877 width = dims.width, 8878 height = dims.height; 8879 8880 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 8881 heightDiff = parseInt((getPixel(holder, 'padding-top') + getPixel(holder, 'padding-bottom') + getPixel(holder, 'border-top-width') + getPixel(holder, 'border-bottom-width') + $('.ilightbox-inner-toolbar', holder).outerHeight()) / 2); 8882 8883 switch (obj.type) { 8884 case 'current': 8885 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 8886 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8887 break; 8888
8889 case 'next': 8890 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 8891 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 8892 break; 8893 8894 case 'prev': 8895 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 8896 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8897 break; 8898 } 8899 8900 holder.data('offset', { 8901 top: top, 8902 left: left, 8903 newDims: newDims, 8904 diff: { 8905 W: widthDiff, 8906 H: heightDiff 8907 }, 8908 thumbsOffset: { 8909 W: thumbsOffsetW, 8910 H: thumbsOffsetH 8911 }, 8912 object: obj 8913 }); 8914 8915 if (obj.animate > 0 && opts.effects.reposition) { 8916 holder.css(transform, gpuAcceleration).stop().animate({ 8917 top: top, 8918 left: left 8919 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 8920 holder.css(transform, ''); 8921 }); 8922 $('div.ilightbox-container', holder).stop().animate({ 8923 width: width, 8924 height: height 8925 }, opts.effects.repositionSpeed, 'easeOutCirc'); 8926 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 8927 width: width 8928 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 8929 $(this).css('overflow', 'visible'); 8930 }); 8931 } else { 8932 holder.css({ 8933 top: top, 8934 left: left 8935 }); 8936 $('div.ilightbox-container', holder).css({ 8937 width: width, 8938 height: height 8939 }); 8940 $('div.ilightbox-inner-toolbar', holder).css({ 8941 width: width 8942 }); 8943 } 8944 }, 8945 8946 resume: function(priority) { 8947 var iL = this, 8948 vars = iL.vars, 8949 opts = iL.options; 8950 8951 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 8952 return; 8953 } 8954 8955 vars.isPaused = 0; 8956 8957 if (vars.cycleID) { 8958 vars.cycleID = clearTimeout(vars.cycleID); 8959 } 8960 8961 vars.cycleID = setTimeout(function() { 8962 if (vars.current == vars.total - 1) iL.goTo(0); 8963 else iL.moveTo('next'); 8964 }, opts.slideshow.pauseTime); 8965 }, 8966 8967 pause: function(priority) { 8968 var iL = this, 8969 vars = iL.vars, 8970 opts = iL.options; 8971 8972 if (priority < vars.isPaused) { 8973 return; 8974 } 8975 8976 vars.isPaused = priority || 100; 8977 8978 if (vars.cycleID) { 8979 vars.cycleID = clearTimeout(vars.cycleID); 8980 } 8981 }, 8982 8983 resetCycle: function() { 8984 var iL = this, 8985 vars = iL.vars, 8986 opts = iL.options; 8987 8988 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 8989 iL.resume(); 8990 } 8991 }, 8992 8993 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 8994 var iL = this; 8995 8996 if (!width) factor = height / height_old; 8997 else if (!height) factor = width / width_old; 8998 else factor = min(width / width_old, height / height_old); 8999 9000 if (!thumb) { 9001 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 9002 else if (factor < iL.options.minScale) factor = iL.options.minScale; 9003 } 9004 9005 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 9006 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 9007 9008 return { 9009 width: final_width, 9010 height: final_height, 9011 ratio: factor 9012 }; 9013 }, 9014 9015 setOption: function(options) { 9016 var iL = this; 9017 9018 iL.options = $.extend(true, iL.options, options || {}); 9019 iL.refresh(); 9020 }, 9021 9022 availPlugins: function() { 9023 var iL = this, 9024 testEl = document.createElement("video"); 9025 9026 iL.plugins = { 9027 flash: (parseInt(PluginDetect.getVersion("Shockwave")) >= 0 || parseInt(PluginDetect.getVersion("Flash")) >= 0) ? true : false, 9028 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 9029 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 9030 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 9031 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 9032 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 9033 }; 9034 }, 9035 9036 addContent: function(element, obj) { 9037 var iL = this, 9038 el; 9039 9040 switch (obj.type) { 9041 case 'video': 9042 var HTML5 = false, 9043 videoType = obj.videoType, 9044 html5video = obj.options.html5video; 9045 9046 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 9047 obj.ext = 'mp4', 9048 obj.URL = html5video.h264 || obj.URL; 9049 else if (html5video.webm && iL.plugins.html5WebM) 9050 obj.ext = 'webm', 9051 obj.URL = html5video.webm || obj.URL; 9052 else if (html5video.ogg && iL.plugins.html5Vorbis) 9053 obj.ext = 'ogv', 9054 obj.URL = html5video.ogg || obj.URL; 9055 9056 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 9057 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 9058 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 9059 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 9060 9061 if (HTML5) { 9062 el = $('<video />
9062', { 9063 "width": "100%", 9064 "height": "100%", 9065 "preload": html5video.preload, 9066 "autoplay": html5video.autoplay, 9067 "poster": html5video.poster, 9068 "controls": html5video.controls 9069 }).append($('<source />', { 9070 "src": obj.URL, 9071 "type": videoType 9072 })); 9073 } else { 9074 if (!iL.plugins.quicktime) el = $('<span />', { 9075 "class": "ilightbox-alert", 9076 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 9077 }); 9078 else { 9079 9080 el = $('<object />', { 9081 "type": "video/quicktime", 9082 "pluginspage": pluginspages.quicktime 9083 }).attr({ 9084 "data": obj.URL, 9085 "width": "100%", 9086 "height": "100%" 9087 }).append($('<param />', { 9088 "name": "src", 9089 "value": obj.URL 9090 })).append($('<param />', { 9091 "name": "autoplay", 9092 "value": "false" 9093 })).append($('<param />', { 9094 "name": "loop", 9095 "value": "false" 9096 })).append($('<param />', { 9097 "name": "scale", 9098 "value": "tofit" 9099 })); 9100 9101 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 9102 } 9103 } 9104 9105 break; 9106 9107 case 'flash': 9108 if (!iL.plugins.flash) el = $('<span />', { 9109 "class": "ilightbox-alert", 9110 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 9111 }); 9112 else { 9113 var flashvars = "", 9114 i = 0; 9115 9116 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 9117 if (i != 0) flashvars += "&"; 9118 flashvars += k + "=" + encodeURIComponent(v); 9119 i++; 9120 }); 9121 else flashvars = null; 9122 9123 el = $('<embed />').attr({ 9124 "type": "application/x-shockwave-flash", 9125 "src": obj.URL, 9126 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9127 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9128 "quality": "high", 9129 "bgcolor": "#000000", 9130 "play": "true", 9131 "loop": "true", 9132 "menu": "true", 9133 "wmode": "transparent", 9134 "scale": "showall", 9135 "allowScriptAccess": "always", 9136 "allowFullScreen": "true", 9137 "flashvars": flashvars, 9138 "fullscreen": "yes" 9139 }); 9140 } 9141 9142 break; 9143 9144 case 'iframe': 9145 el = $('<iframe />').attr({ 9146 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9147 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9148 src: obj.URL, 9149 frameborder: 0, 9150 'hspace': 0, 9151 'vspace': 0, 9152 'scrolling': supportTouch ? 'auto' : 'scroll', 9153 'webkitAllowFullScreen': '', 9154 'mozallowfullscreen': '', 9155 'allowFullScreen': '' 9156 }); 9157 9158 break; 9159 9160 case 'inline': 9161 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 9162 9163 break; 9164 9165 case 'html': 9166 var object = obj.URL, 9167 el; 9168 9169 if (object[0].nodeName) { 9170 el = $('<div class="ilightbox-wrapper"></div>').html(object); 9171 } else { 9172 var dom = $(obj.URL), 9173 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 9174 el = $('<div class="ilightbox-wrapper"></div>').html(html); 9175 } 9176 9177 break; 9178 } 9179 9180 $('div.ilightbox-container', element).empty().html(el); 9181 9182 // For fixing Chrome about just playing the video for first time 9183 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 9184 var src = el[0].currentSrc + '?' + floor(random() * 30000); 9185 el[0].currentSrc = src; 9186 el[0].src = src; 9187 }); 9188 9189 return el; 9190 }, 9191 9192 ogpRecognition: function(obj, callback) { 9193 var iL = this, 9194 url = obj.URL; 9195 9196 iL.showLoader(); 9197 doAjax(url, function(data) { 9198 iL.hideLoader(); 9199 9200 if (data) { 9201 var object = new Object(); 9202 9203 object.length = false, 9204 object.url = data.url; 9205 9206 if (data.status == 200) { 9207 var result = data.results, 9208 type = result.type, 9209 source = result.source; 9210 9211 object.source = source.src, 9212 object.width = source.width && parseInt(source.width) || 0, 9213 object.height = source.height && parseInt(source.height) || 0, 9214 object.type = type, 9215 object.thumbnail = source.thumbnail || result.images[0], 9216 object.html5video = result.html5video || {}, 9217 object.length = true; 9218 9219 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 9220 else if (source.type.indexOf("video/") != -1) object.type = "video"; 9221 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 9222 else if (source.type.indexOf("image/") != -1) object.type = "image"; 9223 9224 } else if (typeof data.response != 'undefined') 9225 throw data.response; 9226 9227 callback.call(this, object.length ? object : false); 9228 } 9229 }); 9230 }, 9231 9232 hashChangeHandler: function(url) { 9233 var iL = this, 9234 vars = iL.vars, 9235 opts = iL.options, 9236 URL = url || window.location.href, 9237 hash = parseURI(URL).hash, 9238 split = hash.split('/'), 9239 index = split[1]; 9240 9241 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 9242 9243 if (index) { 9244 var target = split[1] || 0; 9245 if (iL.items[target]) {
9246 var overlay = $('.ilightbox-overlay'); 9247 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 9248 iL.goTo(target); 9249 } else { 9250 iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click'); 9251 } 9252 } else { 9253 var overlay = $('.ilightbox-overlay'); 9254 if (overlay.length) iL.closeAction(); 9255 } 9256 } else { 9257 var overlay = $('.ilightbox-overlay'); 9258 if (overlay.length) iL.closeAction(); 9259 } 9260 } 9261 }; 9262 9263 /** 9264 * Parse style to pixels. 9265 * 9266 * @param {Object} $element jQuery object with element. 9267 * @param {Property} property CSS property to get the pixels from. 9268 * 9269 * @return {Int} 9270 */ 9271 function getPixel($element, property) { 9272 return parseInt($element.css(property), 10) || 0; 9273 } 9274 9275 /** 9276 * Make sure that number is within the limits. 9277 * 9278 * @param {Number} number 9279 * @param {Number} min 9280 * @param {Number} max 9281 * 9282 * @return {Number} 9283 */ 9284 function within(number, min, max) { 9285 return number < min ? min : number > max ? max : number; 9286 } 9287 9288 /** 9289 * Get viewport/window size (width and height). 9290 * 9291 * @return {Object} 9292 */ 9293 function getViewport() { 9294 var e = window, 9295 a = 'inner'; 9296 if (!('innerWidth' in window)) { 9297 a = 'client'; 9298 e = document.documentElement || document.body; 9299 } 9300 return { 9301 width: e[a + 'Width'], 9302 height: e[a + 'Height'] 9303 } 9304 } 9305 9306 /** 9307 * Remove hash tag from the URL 9308 * 9309 * @return {Void} 9310 */ 9311 function removeHash() { 9312 var scroll = getScrollXY(); 9313 9314 window.location.hash = ""; 9315 9316 // Restore the scroll offset, should be flicker free 9317 window.scrollTo(scroll.x, scroll.y); 9318 } 9319 9320 /** 9321 * Do the ajax requests with callback. 9322 * 9323 * @param {String} url 9324 * @param {Function} callback 9325 * 9326 * @return {Void} 9327 */ 9328 function doAjax(url, callback) { 9329 var url = "http://ilightbox.net/getSource/jsonp.php?url=" + encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A'); 9330 $.ajax({ 9331 url: url, 9332 dataType: 'jsonp' 9333 }); 9334 9335 iLCallback = function(data) { 9336 callback.call(this, data); 9337 }; 9338 } 9339 9340 /** 9341 * Find image from DOM elements 9342 * 9343 * @param {Element} element 9344 * 9345 * @return {Void} 9346 */ 9347 function findImageInElement(element) { 9348 var elements = $('*', element), 9349 imagesArr = new Array(); 9350 9351 elements.each(function() { 9352 var url = "", 9353 element = this; 9354 9355 if ($(element).css("background-image") != "none") { 9356 url = $(element).css("background-image"); 9357 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 9358 url = $(element).attr("src"); 9359 } 9360 9361 if (url.indexOf("gradient") == -1) { 9362 url = url.replace(/url\(\"/g, ""); 9363 url = url.replace(/url\(/g, ""); 9364 url = url.replace(/\"\)/g, ""); 9365 url = url.replace(/\)/g, ""); 9366 9367 var urls = url.split(","); 9368 9369 for (var i = 0; i < urls.length; i++) { 9370 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 9371 var extra = ""; 9372 if (browser.msie && browser.version < 9) { 9373 extra = "?" + floor(random() * 3000); 9374 } 9375 imagesArr.push(urls[i] + extra); 9376 } 9377 } 9378 } 9379 }); 9380 9381 return imagesArr; 9382 } 9383 9384 /** 9385 * Get file extension. 9386 * 9387 * @param {String} URL 9388 * 9389 * @return {String} 9390 */ 9391 function getExtension(URL) { 9392 if (URL !== null) { 9393 var ext = URL.split('.').pop().toLowerCase(), 9394 extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : ''; 9395 9396 return ext.replace(extra, ''); 9397 } 9398 } 9399 9400 /** 9401 * Get type via extension. 9402 * 9403 * @param {String} URL 9404 * 9405 * @return {String} 9406 */ 9407 function getTypeByExtension(URL) { 9408 var type, 9409 ext = getExtension(URL); 9410 9411 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 9412 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 9413 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 9414 else type = 'iframe'; 9415 9416 return type; 9417 } 9418 9419 /** 9420 * Return value from percent of a number. 9421 * 9422 * @param {Number} percent 9423 * @param {Number} total 9424 * 9425 * @return {Number} 9426 */ 9427 function percentToValue(percent, total) { 9428 return parseInt((total / 100) * percent); 9429 } 9430 9431 /** 9432 * A JavaScript equivalent of PHP’s parse_url. 9433 * 9434 * @param {String} url The URL to parse. 9435 * 9436 * @return {Mixed} 9437 */ 9438 function parseURI(url) { 9439 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 9440 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 9441 return (m ? { 9442 href: m[0] || '', 9443 protocol: m[1] || '', 9444 authority: m[2] || '', 9445 host: m[3] || '', 9446 hostname: m[4] || '', 9447 port: m[5] || '', 9448 pathname: m[6] || '', 9449 search: m[7] || '', 9450 hash: m[8] || '' 9451 } : null); 9452 } 9453 9454 /** 9455 * Gets the absolute URI. 9456 * 9457 * @param {String} href The relative URL. 9458 * @param {String} base The base URL. 9459 * 9460 * @return {String} The absolute URL. 9461 */ 9462 function absolutizeURI(base, href) { // RFC 3986 9463 var iL = this; 9464 9465 function removeDotSegments(input) { 9466 var output = []; 9467 input.replace(/^(\.\.?(\/|$))+/, '') 9468 .replace(/\/(\.(\/|$))+/g, '/') 9469 .replace(/\/\.\.$/, '/../') 9470 .replace(/\/?[^\/]*/g, function(p) { 9471 if (p === '/..') { 9472 output.pop(); 9473 } else { 9474 output.push(p); 9475 } 9476 }); 9477 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 9478 } 9479 9480 href = parseURI(href || ''); 9481 base = parseURI(base || ''); 9482 9483 return !href || !base ? null : (href.protocol || base.protocol) + 9484 (href.protocol || href.authority ? href.authority : base.authority) + 9485 removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) + 9486 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 9487 href.hash; 9488 } 9489 9490 /** 9491 * A JavaScript equivalent of PHP’s version_compare. 9492 * 9493 * @param {String} v1 9494 * @param {String} v2 9495 * @param {String} operator
9496 * 9497 * @return {Boolean} 9498 */ 9499 function version_compare(v1, v2, operator) { 9500 this.php_js = this.php_js || {}; 9501 this.php_js.ENV = this.php_js.ENV || {}; 9502 var i = 0, 9503 x = 0, 9504 compare = 0, 9505 vm = { 9506 'dev': -6, 9507 'alpha': -5, 9508 'a': -5, 9509 'beta': -4, 9510 'b': -4, 9511 'RC': -3, 9512 'rc': -3, 9513 '#': -2, 9514 'p': 1, 9515 'pl': 1 9516 }, 9517 prepVersion = function(v) { 9518 v = ('' + v).replace(/[_\-+]/g, '.'); 9519 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 9520 return (!v.length ? [-8] : v.split('.')); 9521 }, 9522 numVersion = function(v) { 9523 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 9524 }; 9525 v1 = prepVersion(v1); 9526 v2 = prepVersion(v2); 9527 x = max(v1.length, v2.length); 9528 for (i = 0; i < x; i++) { 9529 if (v1[i] == v2[i]) { 9530 continue; 9531 } 9532 v1[i] = numVersion(v1[i]); 9533 v2[i] = numVersion(v2[i]); 9534 if (v1[i] < v2[i]) { 9535 compare = -1; 9536 break; 9537 } else if (v1[i] > v2[i]) { 9538 compare = 1; 9539 break; 9540 } 9541 } 9542 if (!operator) { 9543 return compare; 9544 } 9545 9546 switch (operator) { 9547 case '>': 9548 case 'gt': 9549 return (compare > 0); 9550 case '>=': 9551 case 'ge': 9552 return (compare >= 0); 9553 case '<=': 9554 case 'le': 9555 return (compare <= 0); 9556 case '==': 9557 case '=': 9558 case 'eq': 9559 return (compare === 0); 9560 case '<>': 9561 case '!=': 9562 case 'ne': 9563 return (compare !== 0); 9564 case '': 9565 case '<': 9566 case 'lt': 9567 return (compare < 0); 9568 default: 9569 return null; 9570 } 9571 } 9572 9573 9574 // Begin the iLightBox plugin 9575 $.fn.iLightBox = function() { 9576 9577 var args = arguments, 9578 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 9579 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 9580 9581 if (!opt) opt = {}; 9582 9583 // Default options. Play carefully. 9584 var options = $.extend(true, { 9585 attr: 'href', 9586 path: 'vertical', 9587 skin: 'dark', 9588 linkId: false, 9589 infinite: false, 9590 startFrom: 0, 9591 randomStart: false, 9592 keepAspectRatio: true, 9593 maxScale: 1, 9594 minScale: .2, 9595 innerToolbar: false, 9596 smartRecognition: false, 9597 mobileOptimizer: true, 9598 fullAlone: true, 9599 fullViewPort: null, 9600 fullStretchTypes: 'flash, video', 9601 overlay: { 9602 blur: true, 9603 opacity: .85 9604 }, 9605 controls: { 9606 arrows: false, 9607 slideshow: false, 9608 toolbar: true, 9609 fullscreen: true, 9610 thumbnail: true, 9611 keyboard: true, 9612 mousewheel: true, 9613 swipe: true 9614 }, 9615 keyboard: { 9616 left: true, // previous 9617 right: true, // next 9618 up: true, // previous 9619 down: true, // next 9620 esc: true, // close 9621 shift_enter: true // fullscreen 9622 }, 9623 show: { 9624 effect: true, 9625 speed: 300, 9626 title: true 9627 }, 9628 hide: { 9629 effect: true, 9630 speed: 300 9631 }, 9632 caption: { 9633 start: true, 9634 show: 'mouseenter', 9635 hide: 'mouseleave' 9636 }, 9637 social: { 9638 start: true, 9639 show: 'mouseenter', 9640 hide: 'mouseleave',
9641 buttons: false 9642 }, 9643 styles: { 9644 pageOffsetX: 0, 9645 pageOffsetY: 0, 9646 nextOffsetX: 45, 9647 nextOffsetY: 0, 9648 nextOpacity: 1, 9649 nextScale: 1, 9650 prevOffsetX: 45, 9651 prevOffsetY: 0, 9652 prevOpacity: 1, 9653 prevScale: 1 9654 }, 9655 thumbnails: { 9656 maxWidth: 120, 9657 maxHeight: 80, 9658 normalOpacity: 1, 9659 activeOpacity: .6 9660 }, 9661 effects: { 9662 reposition: true, 9663 repositionSpeed: 200, 9664 switchSpeed: 500, 9665 loadedFadeSpeed: 180, 9666 fadeSpeed: 200 9667 }, 9668 slideshow: { 9669 pauseTime: 5000, 9670 pauseOnHover: false, 9671 startPaused: true 9672 }, 9673 text: { 9674 close: "Press Esc to close", 9675 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 9676 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 9677 slideShow: "Slideshow", 9678 next: "Next", 9679 previous: "Previous" 9680 }, 9681 errors: { 9682 loadImage: "An error occurred when trying to load photo.", 9683 loadContents: "An error occurred when trying to load contents.", 9684 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 9685 }, 9686 ajaxSetup: { 9687 url: '', 9688 beforeSend: function(jqXHR, settings) {}, 9689 cache: false, 9690 complete: function(jqXHR, textStatus) {}, 9691 crossDomain: false, 9692 error: function(jqXHR, textStatus, errorThrown) {}, 9693 success: function(data, textStatus, jqXHR) {}, 9694 global: true, 9695 ifModified: false, 9696 username: null, 9697 password: null, 9698 type: 'GET' 9699 }, 9700 callback: {} 9701 }, opt); 9702 9703 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 9704 9705 items = $.isArray(items) ? items : new Array(); 9706 9707 if (typeof args[0] == 'string') items[0] = args[0]; 9708 9709 if (version_compare($.fn.jquery, '1.8', '>=')) { 9710 var iLB = new iLightBox($(this), options, items, instant); 9711 return { 9712 close: function() { 9713 iLB.closeAction(); 9714 }, 9715 fullscreen: function() { 9716 iLB.fullScreenAction(); 9717 }, 9718 moveNext: function() { 9719 iLB.moveTo('next'); 9720 }, 9721 movePrev: function() { 9722 iLB.moveTo('prev'); 9723 }, 9724 goTo: function(index) { 9725 iLB.goTo(index); 9726 }, 9727 refresh: function() { 9728 iLB.refresh(); 9729 }, 9730 reposition: function() { 9731 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 9732 }, 9733 setOption: function(options) { 9734 iLB.setOption(options); 9735 }, 9736 destroy: function() { 9737 iLB.closeAction(); 9738 iLB.dispatchItemsEvents(); 9739 } 9740 }; 9741 } else { 9742 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 9743 } 9744 9745 }; 9746 9747 9748 $.iLightBox = function() { 9749 return $.fn.iLightBox(arguments[0], arguments[1]); 9750 }; 9751 9752 9753 $.extend($.easing, { 9754 easeInCirc: function(x, t, b, c, d) { 9755 return -c * (sqrt(1 - (t /= d) * t) - 1) + b; 9756 }, 9757 easeOutCirc: function(x, t, b, c, d) { 9758 return c * sqrt(1 - (t = t / d - 1) * t) + b; 9759 }, 9760 easeInOutCirc: function(x, t, b, c, d) { 9761 if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; 9762 return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b; 9763 } 9764 }); 9765 9766 function getScrollXY() { 9767 var scrOfX = 0, 9768 scrOfY = 0; 9769 if (typeof(window.pageYOffset) == 'number') { 9770 //Netscape compliant 9771 scrOfY = window.pageYOffset; 9772 scrOfX = window.pageXOffset; 9773 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 9774 //DOM compliant 9775 scrOfY = document.body.scrollTop; 9776 scrOfX = document.body.scrollLeft; 9777 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 9778 //IE6 standards compliant mode 9779 scrOfY = document.documentElement.scrollTop; 9780 scrOfX = document.documentElement.scrollLeft; 9781 } 9782 return { 9783 x: scrOfX, 9784 y: scrOfY 9785 }; 9786 } 9787 9788 (function() { 9789 // add new event shortcuts 9790 $.each(("touchstart touchmove touchend " + 9791 "tap taphold " + 9792 "swipe swipeleft swiperight " + 9793 "scrollstart scrollstop").split(" "), function(i, name) { 9794 9795 $.fn[name] = function(fn) { 9796 return fn ? this.bind(name, fn) : this.trigger(name); 9797 }; 9798 9799 // jQuery < 1.8 9800 if ($.attrFn) { 9801 $.attrFn[name] = true; 9802 } 9803 }); 9804 9805 var tapSettings = { 9806 startEvent: 'touchstart.iTap', 9807 endEvent: 'touchend.iTap' 9808 }; 9809 9810 // tap Event: 9811 $.event.special.itap = { 9812 setup: function() { 9813 9814 var self = this, 9815 $self = $(this), 9816 start, stop; 9817 9818 $self.bind(tapSettings.startEvent, function(event) { 9819 start = getScrollXY(); 9820 9821 $self.one(tapSettings.endEvent, function(event) { 9822 stop = getScrollXY(); 9823 9824 var orgEvent = event || window.event; 9825 event = $.event.fix(orgEvent); 9826 event.type = "itap"; 9827 9828 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 9829 9830 start = stop = undefined; 9831 }); 9832 }); 9833 }, 9834 9835 teardown: function() { 9836 $(this).unbind(tapSettings.startEvent); 9837 } 9838 }; 9839 }()); 9840 9841 9842 //Fullscreen API 9843 (function() { 9844 fullScreenApi = { 9845 supportsFullScreen: false, 9846 isFullScreen: function() { 9847 return false;
9848 }, 9849 requestFullScreen: function() {}, 9850 cancelFullScreen: function() {}, 9851 fullScreenEventName: '', 9852 prefix: '' 9853 }, 9854 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 9855 9856 // check for native support 9857 if (typeof document.cancelFullScreen != 'undefined') { 9858 fullScreenApi.supportsFullScreen = true; 9859 } else { 9860 // check for fullscreen support by vendor prefix 9861 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 9862 fullScreenApi.prefix = browserPrefixes[i]; 9863 9864 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 9865 fullScreenApi.supportsFullScreen = true; 9866 9867 break; 9868 } 9869 } 9870 } 9871 9872 // update methods to do something useful 9873 if (fullScreenApi.supportsFullScreen) { 9874 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 9875 9876 fullScreenApi.isFullScreen = function() { 9877 switch (this.prefix) { 9878 case '': 9879 return document.fullScreen; 9880 case 'webkit': 9881 return document.webkitIsFullScreen; 9882 default: 9883 return document[this.prefix + 'FullScreen']; 9884 } 9885 } 9886 fullScreenApi.requestFullScreen = function(el) { 9887 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 9888 } 9889 fullScreenApi.cancelFullScreen = function(el) { 9890 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 9891 } 9892 } 9893 }()); 9894 9895 // Browser detect 9896 (function() { 9897 function uaMatch(ua) { 9898 ua = ua.toLowerCase(); 9899 9900 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 9901 /(webkit)[ \/]([\w.]+)/.exec(ua) || 9902 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 9903 /(msie) ([\w.]+)/.exec(ua) || 9904 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 9905 9906 return { 9907 browser: match[1] || "", 9908 version: match[2] || "0" 9909 }; 9910 } 9911 9912 var matched = uaMatch(navigator.userAgent); 9913 browser = {}; 9914 9915 if (matched.browser) { 9916 browser[matched.browser] = true; 9917 browser.version = matched.version; 9918 } 9919 9920 // Chrome is Webkit, but Webkit is also Safari. 9921 if (browser.chrome) { 9922 browser.webkit = true; 9923 } else if (browser.webkit) { 9924 browser.safari = true; 9925 } 9926 }()); 9927 9928 // Feature detects 9929 (function() { 9930 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 9931 var el = document.createElement('div'); 9932 9933 function testProp(prop) { 9934 for (var p = 0, pl = prefixes.length; p < pl; p++) { 9935 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 9936 if (el.style[prefixedProp] !== undefined) { 9937 return prefixedProp; 9938 } 9939 } 9940 } 9941 9942 // Global support indicators 9943 transform = testProp('transform') || ''; 9944 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 9945 }()); 9946 9947 9948 /* 9949 PluginDetect v0.7.9 9950 www.pinlady.net/PluginDetect/license/ 9951 [ getVersion onWindowLoaded BetterIE ] 9952 [ Flash QuickTime Shockwave ] 9953 */ 9954 var PluginDetect={version:"0.7.9",name:"PluginDetect",handler:function(c,b,a){return function(){c(b,a)}},openTag:"<",isDefined:function(b){return typeof b!="undefined"},isArray:function(b){return(/array/i).test(Object.prototype.toString.call(b))},isFunc:function(b){return typeof b=="function"},isString:function(b){return typeof b=="string"},isNum:function(b){return typeof b=="number"},isStrNum:function(b){return(typeof b=="string"&&(/\d/).test(b))},getNumRegx:/[\d][\d\.\_,-]*/,splitNumRegx:/[\.\_,-]/g,getNum:function(b,c){var d=this,a=d.isStrNum(b)?(d.isDefined(c)?new RegExp(c):d.getNumRegx).exec(b):null;return a?a[0]:null},compareNums:function(h,f,d){var e=this,c,b,a,g=parseInt;if(e.isStrNum(h)&&e.isStrNum(f)){if(e.isDefined(d)&&d.compareNums){return d.compareNums(h,f)}c=h.split(e.splitNumRegx);b=f.split(e.splitNumRegx);for(a=0;a<min(c.length,b.length);a++){if(g(c[a],10)>g(b[a],10)){return 1}if(g(c[a],10)<g(b[a],10)){return -1}}}return 0},formatNum:function(b,c){var d=this,a,e;if(!d.isStrNum(b)){return null}if(!d.isNum(c)){c=4}c--;e=b.replace(/\s/g,"").split(d.splitNumRegx).concat(["0","0","0","0"]);for(a=0;a<4;a++){if(/^(0+)(.+)$/.test(e[a])){e[a]=RegExp.$2}if(a>c||!(/\d/).test(e[a])){e[a]="0"}}return e.slice(0,4).join(",")},$$hasMimeType:function(a){return function(c){if(!a.isIE&&c){var f,e,b,d=a.isArray(c)?c:(a.isString(c)?[c]:[]);for(b=0;b<d.length;b++){if(a.isString(d[b])&&/[^\s]/.test(d[b])){f=navigator.mimeTypes[d[b]];e=f?f.enabledPlugin:0;if(e&&(e.name||e.description)){return f}}}}return null}},findNavPlugin:function(l,e,c){var j=this,h=new RegExp(l,"i"),d=(!j.isDefined(e)||e)?/\d/:0,k=c?new RegExp(c,"i"):0,a=navigator.plugins,g="",f,b,m;for(f=0;f<a.length;f++){m=a[f].description||g;b=a[f].name||g;if((h.test(m)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))||(h.test(b)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))){if(!k||!(k.test(m)||k.test(b))){return a[f]}}}return null},getMimeEnabledPlugin:function(k,m,c){var e=this,f,b=new RegExp(m,"i"),h="",g=c?new RegExp(c,"i"):0,a,l,d,j=e.isString(k)?[k]:k;for(d=0;d<j.length;
9954d++){if((f=e.hasMimeType(j[d]))&&(f=f.enabledPlugin)){l=f.description||h;a=f.name||h;if(b.test(l)||b.test(a)){if(!g||!(g.test(l)||g.test(a))){return f}}}}return 0},getPluginFileVersion:function(f,b){var h=this,e,d,g,a,c=-1;if(h.OS>2||!f||!f.version||!(e=h.getNum(f.version))){return b}if(!b){return e}e=h.formatNum(e);b=h.formatNum(b);d=b.split(h.splitNumRegx);g=e.split(h.splitNumRegx);for(a=0;a<d.length;a++){if(c>-1&&a>c&&d[a]!="0"){return b}if(g[a]!=d[a]){if(c==-1){c=a}if(d[a]!="0"){return b}}}return e},AXO:window.ActiveXObject,getAXO:function(a){var f=null,d,b=this,c={};try{f=new b.AXO(a)}catch(d){}return f},convertFuncs:function(f){var a,g,d,b=/^[\$][\$]/,c=this;for(a in f){if(b.test(a)){try{g=a.slice(2);if(g.length>0&&!f[g]){f[g]=f[a](f);delete f[a]}}catch(d){}}}},initObj:function(e,b,d){var a,c;if(e){if(e[b[0]]==1||d){for(a=0;a<b.length;a=a+2){e[b[a]]=b[a+1]}}for(a in e){c=e[a];if(c&&c[b[0]]==1){this.initObj(c,b)}}}},initScript:function(){var d=this,a=navigator,h,i=document,l=a.userAgent||"",j=a.vendor||"",b=a.platform||"",k=a.product||"";d.initObj(d,["$",d]);for(h in d.Plugins){if(d.Plugins[h]){d.initObj(d.Plugins[h],["$",d,"$$",d.Plugins[h]],1)}}d.convertFuncs(d);d.OS=100;if(b){var g=["Win",1,"Mac",2,"Linux",3,"FreeBSD",4,"iPhone",21.1,"iPod",21.2,"iPad",21.3,"Win.*CE",22.1,"Win.*Mobile",22.2,"Pocket\\s*PC",22.3,"",100];for(h=g.length-2;h>=0;h=h-2){if(g[h]&&new RegExp(g[h],"i").test(b)){d.OS=g[h+1];break}}};d.head=i.getElementsByTagName("head")[0]||i.getElementsByTagName("body")[0]||i.body||null;d.isIE=new Function("return/*@cc_on!@*/!1")();d.verIE=d.isIE&&(/MSIE\s*(\d+\.?\d*)/i).test(l)?parseFloat(RegExp.$1,10):null;d.verIEfull=null;d.docModeIE=null;if(d.isIE){var f,n,c=document.createElement("div");try{c.style.behavior="url(#default#clientcaps)";d.verIEfull=(c.getComponentVersion("{89820200-ECBD-11CF-8B85-00AA005B4383}","componentid")).replace(/,/g,".")}catch(f){}n=parseFloat(d.verIEfull||"0",10);d.docModeIE=i.documentMode||((/back/i).test(i.compatMode||"")?5:n)||d.verIE;d.verIE=n||d.docModeIE};d.ActiveXEnabled=false;if(d.isIE){var h,m=["Msxml2.XMLHTTP","Msxml2.DOMDocument","Microsoft.XMLDOM","ShockwaveFlash.ShockwaveFlash","TDCCtl.TDCCtl","Shell.UIHelper","Scripting.Dictionary","wmplayer.ocx"];for(h=0;h<m.length;h++){if(d.getAXO(m[h])){d.ActiveXEnabled=true;break}}};d.isGecko=(/Gecko/i).test(k)&&(/Gecko\s*\/\s*\d/i).test(l);
9954d.verGecko=d.isGecko?d.formatNum((/rv\s*\:\s*([\.\,\d]+)/i).test(l)?RegExp.$1:"0.9"):null;d.isChrome=(/Chrome\s*\/\s*(\d[\d\.]*)/i).test(l);d.verChrome=d.isChrome?d.formatNum(RegExp.$1):null;d.isSafari=((/Apple/i).test(j)||(!j&&!d.isChrome))&&(/Safari\s*\/\s*(\d[\d\.]*)/i).test(l);d.verSafari=d.isSafari&&(/Version\s*\/\s*(\d[\d\.]*)/i).test(l)?d.formatNum(RegExp.$1):null;d.isOpera=(/Opera\s*[\/]?\s*(\d+\.?\d*)/i).test(l);d.verOpera=d.isOpera&&((/Version\s*\/\s*(\d+\.?\d*)/i).test(l)||1)?parseFloat(RegExp.$1,10):null;d.addWinEvent("load",d.handler(d.runWLfuncs,d))},init:function(d){var c=this,b,d,a={status:-3,plugin:0};if(!c.isString(d)){return a}if(d.length==1){c.getVersionDelimiter=d;return a}d=d.toLowerCase().replace(/\s/g,"");b=c.Plugins[d];if(!b||!b.getVersion){return a}a.plugin=b;if(!c.isDefined(b.installed)){b.installed=null;b.version=null;b.version0=null;b.getVersionDone=null;b.pluginName=d}c.garbage=false;if(c.isIE&&!c.ActiveXEnabled&&d!=="java"){a.status=-2;return a}a.status=1;return a},fPush:function(b,a){var c=this;if(c.isArray(a)&&(c.isFunc(b)||(c.isArray(b)&&b.length>0&&c.isFunc(b[0])))){a.push(b)}},callArray:function(b){var c=this,a;if(c.isArray(b)){for(a=0;a<b.length;a++){if(b[a]===null){return}c.call(b[a]);b[a]=null}}},call:function(c){var b=this,a=b.isArray(c)?c.length:-1;if(a>0&&b.isFunc(c[0])){c[0](b,a>1?c[1]:0,a>2?c[2]:0,a>3?c[3]:0)}else{if(b.isFunc(c)){c(b)}}},getVersionDelimiter:",",$$getVersion:function(a){return function(g,d,c){var e=a.init(g),f,b,h={};if(e.status<0){return null};f=e.plugin;if(f.getVersionDone!=1){f.getVersion(null,d,c);if(f.getVersionDone===null){f.getVersionDone=1}}a.cleanup();b=(f.version||f.version0);b=b?b.replace(a.splitNumRegx,a.getVersionDelimiter):b;return b}},cleanup:function(){var a=this;if(a.garbage&&a.isDefined(window.CollectGarbage)){window.CollectGarbage()}},isActiveXObject:function(d,b){var f=this,a=false,g,c='<object width="1" height="1" style="display:none" '+d.getCodeBaseVersion(b)+">"+d.HTML+f.openTag+"/object>";if(!f.head){return a}f.head.insertBefore(document.createElement("object"),f.head.firstChild);f.head.firstChild.outerHTML=c;try{f.head.firstChild.classid=d.classID}catch(g){}try{if(f.head.firstChild.object){a=true}}catch(g){}try{if(a&&f.head.firstChild.readyState<4){f.garbage=true}}catch(g){}f.head.removeChild(f.head.firstChild);return a},codebaseSearch:function(f,b){var c=this;if(!c.ActiveXEnabled||!f){return null}if(f.BIfuncs&&f.BIfuncs.length&&f.BIfuncs[f.BIfuncs.length-1]!==null){c.callArray(f.BIfuncs)}var d,o=f.SEARCH,k={};if(c.isStrNum(b)){if(o.match&&o.min&&c.compareNums(b,o.min)<=0){return true}if(o.match&&o.max&&c.compareNums(b,o.max)>=0){return false}d=c.isActiveXObject(f,b);if(d&&(!o.min||c.compareNums(b,o.min)>0)){o.min=b}if(!d&&(!o.max||c.compareNums(b,o.max)<0)){o.max=b}return d};var e=[0,0,0,0],l=[].concat(o.digits),a=o.min?1:0,j,i,h,g,m,n=function(p,r){var q=[].concat(e);q[p]=r;return c.isActiveXObject(f,q.join(","))};if(o.max){g=o.max.split(c.splitNumRegx);for(j=0;j<g.length;j++){g[j]=parseInt(g[j],10)}if(g[0]<l[0]){l[0]=g[0]}}if(o.min){m=o.min.split(c.splitNumRegx);for(j=0;j<m.length;j++){m[j]=parseInt(m[j],10)}if(m[0]>e[0]){e[0]=m[0]}}if(m&&g){for(j=1;j<m.length;j++){if(m[j-1]!=g[j-1]){break}if(g[j]<l[j]){l[j]=g[j]}if(m[j]>e[j]){e[j]=m[j]}}}if(o.max){for(j=1;j<l.length;j++){if(g[j]>0&&l[j]==0&&l[j-1]<o.digits[j-1]){l[j-1]+=1;break}}};for(j=0;j<l.length;j++){h={};for(i=0;i<20;i++){if(l[j]-e[j]<1){break}d=round((l[j]+e[j])/2);if(h["a"+d]){break}h["a"+d]=1;if(n(j,d)){e[j]=d;a=1}else{l[j]=d}}l[j]=e[j];if(!a&&n(j,e[j])){a=1};if(!a){break}};return a?e.join(","):null},addWinEvent:function(d,c){var e=this,a=window,b;if(e.isFunc(c)){if(a.addEventListener){a.addEventListener(d,c,false)}else{if(a.attachEvent){a.attachEvent("on"+d,c)}else{b=a["on"+d];a["on"+d]=e.winHandler(c,b)}}}},winHandler:function(d,c){return function(){d();if(typeof c=="function"){c()}}},WLfuncs0:[],WLfuncs:[],runWLfuncs:function(a){var b={};a.winLoaded=true;a.callArray(a.WLfuncs0);a.callArray(a.WLfuncs);if(a.onDoneEmptyDiv){a.onDoneEmptyDiv()}},winLoaded:false,$$onWindowLoaded:function(a){return function(b){if(a.winLoaded){a.call(b)}else{a.fPush(b,a.WLfuncs)}}},div:null,divID:"plugindetect",divWidth:50,pluginSize:1,emptyDiv:function(){var d=this,b,h,c,a,f,g;if(d.div&&d.div.childNodes){for(b=d.div.childNodes.length-1;b>=0;b--){c=d.div.childNodes[b];if(c&&c.childNodes){for(h=c.childNodes.length-1;h>=0;h--){g=c.childNodes[h];try{c.removeChild(g)}catch(f){}}}if(c){try{d.div.removeChild(c)}catch(f){}}}}if(!d.div){a=document.getElementById(d.divID);if(a){d.div=a}}if(d.div&&d.div.parentNode){try{d.div.parentNode.removeChild(d.div)}catch(f){}d.div=null}},DONEfuncs:[],onDoneEmptyDiv:function(){var c=this,a,b;if(!c.winLoaded){return}if(c.WLfuncs&&c.WLfuncs.length&&c.WLfuncs[c.WLfuncs.length-1]!==null){return}for(a in c){b=c[a];if(b&&b.funcs){if(b.OTF==3){return}if(b.funcs.length&&b.funcs[b.funcs.length-1]!==null){return}}}for(a=0;a<c.DONEfuncs.length;a++){c.callArray(c.DONEfuncs)}
9954c.emptyDiv()},getWidth:function(c){if(c){var a=c.scrollWidth||c.offsetWidth,b=this;if(b.isNum(a)){return a}}return -1},getTagStatus:function(m,g,a,b){var c=this,f,k=m.span,l=c.getWidth(k),h=a.span,j=c.getWidth(h),d=g.span,i=c.getWidth(d);if(!k||!h||!d||!c.getDOMobj(m)){return -2}if(j<i||l<0||j<0||i<0||i<=c.pluginSize||c.pluginSize<1){return 0}if(l>=i){return -1}try{if(l==c.pluginSize&&(!c.isIE||c.getDOMobj(m).readyState==4)){if(!m.winLoaded&&c.winLoaded){return 1}if(m.winLoaded&&c.isNum(b)){if(!c.isNum(m.count)){m.count=b}if(b-m.count>=10){return 1}}}}catch(f){}return 0},getDOMobj:function(g,a){var f,d=this,c=g?g.span:0,b=c&&c.firstChild?1:0;try{if(b&&a){d.div.focus()}}catch(f){}return b?c.firstChild:null},setStyle:function(b,g){var f=b.style,a,d,c=this;if(f&&g){for(a=0;a<g.length;a=a+2){try{f[g[a]]=g[a+1]}catch(d){}}}},insertDivInBody:function(i,g){var f,c=this,h="pd33993399",b=null,d=g?window.top.document:window.document,a=d.getElementsByTagName("body")[0]||d.body;if(!a){try{d.write('<div id="'+h+'">.'+c.openTag+"/div>");b=d.getElementById(h)}catch(f){}}a=d.getElementsByTagName("body")[0]||d.body;if(a){a.insertBefore(i,a.firstChild);if(b){a.removeChild(b)}}},insertHTML:function(f,b,g,a,k){var l,m=document,j=this,p,o=m.createElement("span"),n,i;var c=["outlineStyle","none","borderStyle","none","padding","0px","margin","0px","visibility","visible"];var h="outline-style:none;border-style:none;padding:0px;margin:0px;visibility:visible;";if(!j.isDefined(a)){a=""}if(j.isString(f)&&(/[^\s]/).test(f)){f=f.toLowerCase().replace(/\s/g,"");p=j.openTag+f+' width="'+j.pluginSize+'" height="'+j.pluginSize+'" ';p+='style="'+h+'display:inline;" ';for(n=0;n<b.length;n=n+2){if(/[^\s]/.test(b[n+1])){p+=b[n]+'="'+b[n+1]+'" '}}p+=">";for(n=0;n<g.length;n=n+2){if(/[^\s]/.test(g[n+1])){p+=j.openTag+'param name="'+g[n]+'" value="'+g[n+1]+'" />'}}p+=a+j.openTag+"/"+f+">"}else{p=a}if(!j.div){i=m.getElementById(j.divID);if(i){j.div=i}else{j.div=m.createElement("div");j.div.id=j.divID}j.setStyle(j.div,c.concat(["width",j.divWidth+"px","height",(j.pluginSize+3)+"px","fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","block"]));if(!i){j.setStyle(j.div,["position","absolute","right","0px","top","0px"]);j.insertDivInBody(j.div)}}if(j.div&&j.div.parentNode){j.setStyle(o,c.concat(["fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","inline"]));try{o.innerHTML=p}catch(l){};try{j.div.appendChild(o)}catch(l){};return{span:o,winLoaded:j.winLoaded,tagName:f,outerHTML:p}}return{span:null,winLoaded:j.winLoaded,tagName:"",outerHTML:p}},Plugins:{quicktime:{mimeType:["video/quicktime","application/x-quicktimeplayer","image/x-macpaint","image/x-quicktime"],progID:"QuickTimeCheckObject.QuickTimeCheck.1",progID0:"QuickTime.QuickTime",classID:"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B",minIEver:7,HTML:'<param name="src" value="" /><param name="controller" value="false" />',getCodeBaseVersion:function(a){return'codebase="#version='+a+'"'},SEARCH:{min:0,max:0,match:0,digits:[16,128,128,0]},getVersion:function(c){var f=this,d=f.$,a=null,e=null,b;if(!d.isIE){if(d.hasMimeType(f.mimeType)){e=d.OS!=3?d.findNavPlugin("QuickTime.*Plug-?in",0):null;if(e&&e.name){a=d.getNum(e.name)}}}else{if(d.isStrNum(c)){b=c.split(d.splitNumRegx);if(b.length>3&&parseInt(b[3],10)>0){b[3]="9999"}c=b.join(",")}if(d.isStrNum(c)&&d.verIE>=f.minIEver&&f.canUseIsMin()>0){f.installed=f.isMin(c);f.getVersionDone=0;return}f.getVersionDone=1;if(!a&&d.verIE>=f.minIEver){a=f.CDBASE2VER(d.codebaseSearch(f))}if(!a){e=d.getAXO(f.progID);if(e&&e.QuickTimeVersion){a=e.QuickTimeVersion.toString(16);a=parseInt(a.charAt(0),16)+"."+parseInt(a.charAt(1),16)+"."+parseInt(a.charAt(2),16)}}}f.installed=a?1:(e?0:-1);f.version=d.formatNum(a,3)},cdbaseUpper:["7,60,0,0","0,0,0,0"],cdbaseLower:["7,50,0,0",null],cdbase2ver:[function(c,b){var a=b.split(c.$.splitNumRegx);return[a[0],a[1].charAt(0),a[1].charAt(1),a[2]].join(",")},null],CDBASE2VER:function(f){var e=this,c=e.$,b,a=e.cdbaseUpper,d=e.cdbaseLower;
9954if(f){f=c.formatNum(f);for(b=0;b<a.length;b++){if(a[b]&&c.compareNums(f,a[b])<0&&d[b]&&c.compareNums(f,d[b])>=0&&e.cdbase2ver[b]){return e.cdbase2ver[b](e,f)}}}return f},canUseIsMin:function(){var f=this,d=f.$,b,c=f.canUseIsMin,a=f.cdbaseUpper,e=f.cdbaseLower;if(!c.value){c.value=-1;for(b=0;b<a.length;b++){if(a[b]&&d.codebaseSearch(f,a[b])){c.value=1;break}if(e[b]&&d.codebaseSearch(f,e[b])){c.value=-1;break}}}f.SEARCH.match=c.value==1?1:0;return c.value},isMin:function(c){var b=this,a=b.$;return a.codebaseSearch(b,c)?0.7:-1}},flash:{mimeType:"application/x-shockwave-flash",progID:"ShockwaveFlash.ShockwaveFlash",classID:"clsid:D27CDB6E-AE6D-11CF-96B8-444553540000",getVersion:function(){var b=function(i){if(!i){return null}var e=/[\d][\d\,\.\s]*[rRdD]{0,1}[\d\,]*/.exec(i);return e?e[0].replace(/[rRdD\.]/g,",").replace(/\s/g,""):null};var j=this,g=j.$,k,h,l=null,c=null,a=null,f,m,d;if(!g.isIE){m=g.hasMimeType(j.mimeType);if(m){f=g.getDOMobj(g.insertHTML("object",["type",j.mimeType],[],"",j));try{l=g.getNum(f.GetVariable("$version"))}catch(k){}}if(!l){d=m?m.enabledPlugin:null;if(d&&d.description){l=b(d.description)}if(l){l=g.getPluginFileVersion(d,l)}}}else{for(h=15;h>2;h--){c=g.getAXO(j.progID+"."+h);if(c){a=h.toString();break}}if(!c){c=g.getAXO(j.progID)}if(a=="6"){try{c.AllowScriptAccess="always"}catch(k){return"6,0,21,0"}}try{l=b(c.GetVariable("$version"))}catch(k){}if(!l&&a){l=a}}j.installed=l?1:-1;j.version=g.formatNum(l);return true}},shockwave:{mimeType:"application/x-director",progID:"SWCtl.SWCtl",classID:"clsid:166B1BCA-3F9C-11CF-8075-444553540000",getVersion:function(){var a=null,b=null,g,f,d=this,c=d.$;if(!c.isIE){f=c.findNavPlugin("Shockwave\\s*for\\s*Director");if(f&&f.description&&c.hasMimeType(d.mimeType)){a=c.getNum(f.description)}if(a){a=c.getPluginFileVersion(f,a)}}else{try{b=c.getAXO(d.progID).ShockwaveVersion("")}catch(g){}if(c.isString(b)&&b.length>0){a=c.getNum(b)}else{if(c.getAXO(d.progID+".8")){a="8"}else{if(c.getAXO(d.progID+".7")){a="7"}else{if(c.getAXO(d.progID+".1")){a="6"}}}}}d.installed=a?1:-1;d.version=c.formatNum(a)}},zz:0}};PluginDetect.initScript(); 9955 9956 var gArgCountErr='The "%%" function requires an even number of arguments.\nArguments should be in the form "atttributeName", "attributeValue", ...',gTagAttrs=null,gQTGeneratorVersion=1;function AC_QuickTimeVersion(){return gQTGeneratorVersion}function _QTComplain(a,b){b=b.replace("%%",a);alert(b)}function _QTAddAttribute(a,b,c){var d;d=gTagAttrs[a+b];null==d&&(d=gTagAttrs[b]);return null!=d?(0==b.indexOf(a)&&null==c&&(c=b.substring(a.length)),null==c&&(c=b),c+'="'+d+'" '):""}function _QTAddObjectAttr(a,b){if(0==a.indexOf("emb#"))return"";0==a.indexOf("obj#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("obj#",a,b)}function _QTAddEmbedAttr(a,b){if(0==a.indexOf("obj#"))return"";0==a.indexOf("emb#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("emb#",a,b)}function _QTAddObjectParam(a,b){var c,d="",e=b?" />":">";-1==a.indexOf("emb#")&&(c=gTagAttrs["obj#"+a],null==c&&(c=gTagAttrs[a]),0==a.indexOf("obj#")&&(a=a.substring(4)),null!=c&&(d=' <param name="'+a+'" value="'+c+'"'+e+"\n"));return d}function _QTDeleteTagAttrs(){for(var a=0;a<arguments.length;a++){var b=arguments[a];delete gTagAttrs[b];delete gTagAttrs["emb#"+b];delete gTagAttrs["obj#"+b]}}function _QTGenerate(a,b,c){if(4>c.length||0!=c.length%2)return _QTComplain(a,gArgCountErr),"";gTagAttrs=[];gTagAttrs.src=c[0];gTagAttrs.width=c[1];gTagAttrs.height=c[2];gTagAttrs.classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";gTagAttrs.pluginspage="http://www.apple.com/quicktime/download/";a=c[3];if(null==a||""==a)a="6,0,2,0";gTagAttrs.codebase="http://www.apple.com/qtactivex/qtplugin.cab#version="+a;for(var d,e=4;e<c.length;e+=2)d=c[e].toLowerCase(),a=c[e+1],"name"==d||"id"==d?gTagAttrs.name=a:gTagAttrs[d]=a;c="<object "+_QTAddObjectAttr("classid")+_QTAddObjectAttr("width")+_QTAddObjectAttr("height")+_QTAddObjectAttr("codebase")+_QTAddObjectAttr("name","id")+_QTAddObjectAttr("tabindex")+_QTAddObjectAttr("hspace")+_QTAddObjectAttr("vspace")+_QTAddObjectAttr("border")+_QTAddObjectAttr("align")+_QTAddObjectAttr("class")+_QTAddObjectAttr("title")+_QTAddObjectAttr("accesskey")+_QTAddObjectAttr("noexternaldata")+">\n"+_QTAddObjectParam("src",b);e=" <embed "+_QTAddEmbedAttr("src")+_QTAddEmbedAttr("width")+_QTAddEmbedAttr("height")+_QTAddEmbedAttr("pluginspage")+_QTAddEmbedAttr("name")+_QTAddEmbedAttr("align")+_QTAddEmbedAttr("tabindex");_QTDeleteTagAttrs("src","width","height","pluginspage","classid","codebase","name","tabindex","hspace","vspace","border","align","noexternaldata","class","title","accesskey");for(d in gTagAttrs)a=gTagAttrs[d],null!=a&&(e+=_QTAddEmbedAttr(d),c+=_QTAddObjectParam(d,b));return c+e+"> </embed>\n</object>"}function QT_GenerateOBJECTText(){return _QTGenerate("QT_GenerateOBJECTText",!1,arguments)}; 9957 9958 9959 /* 9960 jQuery hashchange event v1.3 9961 https://github.com/cowboy/jquery-hashchange 9962 Copyright (c) 2010 "Cowboy" Ben Alman 9963 Dual licensed under the MIT and GPL licenses. 9964 */ 9965 (function(){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var k=document,b,f=$.event.special,p=k.documentMode,m="oniLightBoxHashChange"in window&&(void 0===p||7<p);$.fn.iLightBoxHashChange=function(a){return a?this.bind("iLightBoxHashChange",a):this.trigger("iLightBoxHashChange")};$.fn.iLightBoxHashChange.delay=50;f.iLightBoxHashChange=$.extend(f.iLightBoxHashChange,{setup:function(){if(m)return!1;$(b.start)},teardown:function(){if(m)return!1;$(b.stop)}});b=function(){function a(){var c= 9966 e(),d=f(l);c!==l?(n(l=c,d),$(window).trigger("iLightBoxHashChange")):d!==l&&(location.href=location.href.replace(/#.*/,"")+d);g=setTimeout(a,$.fn.iLightBoxHashChange.delay)}var h={},g,l=e(),b=function(c){return c},n=b,f=b;h.start=function(){g||a()};h.stop=function(){g&&clearTimeout(g);g=void 0};browser.msie&&!m&&function(){var c,d;h.start=function(){c||(d=(d=$.fn.iLightBoxHashChange.src)&&d+e(),c=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||n(e());a()}).attr("src",d|| 9967 "javascript:0").insertAfter("body")[0].contentWindow,k.onpropertychange=function(){try{"title"===event.propertyName&&(c.document.title=k.title)}catch(a){}})};h.stop=b;f=function(){return e(c.location.href)};n=function(a,d){var b=c.document,e=$.fn.iLightBoxHashChange.domain;
9967a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 9968 9969 if (!Array.prototype.filter) { 9970 Array.prototype.filter = function(fun /*, thisp */ ) { 9971 "use strict"; 9972 9973 if (this == null) 9974 throw new TypeError(); 9975 9976 var t = Object(this); 9977 var len = t.length >>> 0; 9978 if (typeof fun != "function") 9979 throw new TypeError(); 9980 9981 var res = []; 9982 var thisp = arguments[1]; 9983 for (var i = 0; i < len; i++) { 9984 if (i in t) { 9985 var val = t[i]; // in case fun mutates this 9986 if (fun.call(thisp, val, i, t)) 9987 res.push(val); 9988 } 9989 } 9990 9991 return res; 9992 }; 9993 } 9994 9995 if (!Array.prototype.indexOf) { 9996 Array.prototype.indexOf = function(searchElement, fromIndex) { 9997 var k; 9998 9999 if (this == null) { 10000 throw new TypeError('"this" is null or not defined'); 10001 } 10002 10003 var O = Object(this); 10004 10005 var len = O.length >>> 0; 10006 10007 if (len === 0) { 10008 return -1; 10009 } 10010 10011 var n = +fromIndex || 0; 10012 10013 if (abs(n) === Infinity) { 10014 n = 0; 10015 } 10016 10017 if (n >= len) { 10018 return -1; 10019 } 10020 10021 k = max(n >= 0 ? n : len - abs(n), 0); 10022 10023 while (k < len) { 10024 var kValue; 10025 if (k in O && O[k] === searchElement) { 10026 return k; 10027 } 10028 k++; 10029 } 10030 return -1; 10031 }; 10032 } 10033 10034 if (!Array.prototype.lastIndexOf) { 10035 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 10036 "use strict"; 10037 10038 if (this == null) 10039 throw new TypeError(); 10040 10041 var t = Object(this); 10042 var len = t.length >>> 0; 10043 if (len === 0) 10044 return -1; 10045 10046 var n = len; 10047 if (arguments.length > 1) { 10048 n = Number(arguments[1]); 10049 if (n != n) 10050 n = 0; 10051 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 10052 n = (n > 0 || -1) * floor(abs(n)); 10053 } 10054 10055 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 10056 10057 for (; k >= 0; k--) { 10058 if (k in t && t[k] === searchElement) 10059 return k; 10060 } 10061 return -1; 10062 }; 10063 } 10064})(jQuery, this); 10065 10066 10067/** 10068 * Owl carousel
vendor: 31,056 bytes, lines 10069-11268
10069 * @version 2.0.0-beta.3 10070 * @author Bartosz Wojciechowski 10071 * @license The MIT License (MIT) 10072 * @todo Lazy Load Icon 10073 * @todo prevent animationend bubling 10074 * @todo itemsScaleUp 10075 * @todo Test Zepto 10076 * @todo stagePadding calculate wrong active classes 10077 */ 10078;(function($, window, document, undefined) { 10079 10080 /** 10081 * Creates a carousel. 10082 * @class The Owl Carousel. 10083 * @public 10084 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 10085 * @param {Object} [options] - The options 10086 */ 10087 function Owl(element, options) { 10088 10089 /** 10090 * Current settings for the carousel. 10091 * @public 10092 */ 10093 this.settings = null; 10094 10095 /** 10096 * Current options set by the caller including defaults. 10097 * @public 10098 */ 10099 this.options = $.extend({}, Owl.Defaults, options); 10100 10101 /** 10102 * Plugin element. 10103 * @public 10104 */ 10105 this.$element = $(element); 10106 10107 /** 10108 * Proxied event handlers. 10109 * @protected 10110 */ 10111 this._handlers = {}; 10112 10113 /** 10114 * References to the running plugins of this carousel. 10115 * @protected 10116 */ 10117 this._plugins = {}; 10118 10119 /** 10120 * Currently suppressed events to prevent them from beeing retriggered. 10121 * @protected 10122 */ 10123 this._supress = {}; 10124 10125 /** 10126 * Absolute current position. 10127 * @protected 10128 */ 10129 this._current = null; 10130 10131 /** 10132 * Animation speed in milliseconds. 10133 * @protected 10134 */ 10135 this._speed = null; 10136 10137 /** 10138 * Coordinates of all items in pixel. 10139 * @todo The name of this member is missleading. 10140 * @protected 10141 */ 10142 this._coordinates = []; 10143 10144 /** 10145 * Current breakpoint. 10146 * @todo Real media queries would be nice. 10147 * @protected 10148 */ 10149 this._breakpoint = null; 10150 10151 /** 10152 * Current width of the plugin element. 10153 */ 10154 this._width = null; 10155 10156 /** 10157 * All real items. 10158 * @protected 10159 */ 10160 this._items = []; 10161 10162 /** 10163 * All cloned items. 10164 * @protected 10165 */ 10166 this._clones = []; 10167 10168 /** 10169 * Merge values of all items. 10170 * @todo Maybe this could be part of a plugin. 10171 * @protected 10172 */ 10173 this._mergers = []; 10174 10175 /** 10176 * Widths of all items. 10177 */ 10178 this._widths = []; 10179 10180 /** 10181 * Invalidated parts within the update process. 10182 * @protected 10183 */ 10184 this._invalidated = {}; 10185 10186 /** 10187 * Ordered list of workers for the update process. 10188 * @protected 10189 */ 10190 this._pipe = []; 10191 10192 /** 10193 * Current state information for the drag operation. 10194 * @todo #261 10195 * @protected 10196 */ 10197 this._drag = { 10198 time: null, 10199 target: null, 10200 pointer: null, 10201 stage: { 10202 start: null, 10203 current: null 10204 }, 10205 direction: null 10206 }; 10207 10208 /** 10209 * Current state information and their tags. 10210 * @type {Object} 10211 * @protected 10212 */ 10213 this._states = { 10214 current: {}, 10215 tags: { 10216 'initializing': [ 'busy' ], 10217 'animating': [ 'busy' ], 10218 'dragging': [ 'interacting' ] 10219 } 10220 }; 10221 10222 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 10223 this._handlers[handler] = $.proxy(this[handler], this); 10224 }, this)); 10225 10226 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 10227 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 10228 = new plugin(this); 10229 }, this)); 10230 10231 $.each(Owl.Workers, $.proxy(function(priority, worker) { 10232 this._pipe.push({ 10233 'filter': worker.filter, 10234 'run': $.proxy(worker.run, this) 10235 }); 10236 }, this)); 10237 10238 this.setup(); 10239 this.initialize(); 10240 } 10241 10242 /** 10243 * Default options for the carousel. 10244 * @public 10245 */ 10246 Owl.Defaults = { 10247 items: 3, 10248 loop: false, 10249 center: false, 10250 rewind: false, 10251 10252 mouseDrag: true, 10253 touchDrag: true, 10254 pullDrag: true, 10255 freeDrag: false, 10256 10257 margin: 0, 10258 stagePadding: 0, 10259 10260 merge: false, 10261 mergeFit: true, 10262 autoWidth: false, 10263 10264 startPosition: 0, 10265 rtl: false, 10266 10267 smartSpeed: 250, 10268 fluidSpeed: false, 10269 dragEndSpeed: false, 10270 10271 responsive: {}, 10272 responsiveRefreshRate: 200, 10273 responsiveBaseElement: window, 10274 10275 fallbackEasing: 'swing', 10276 10277 info: false, 10278 10279 nestedItemSelector: false, 10280 itemElement: 'div', 10281 stageElement: 'div', 10282 10283 refreshClass: 'owl-refresh', 10284 loadedClass: 'owl-loaded', 10285 loadingClass: 'owl-loading', 10286 rtlClass: 'owl-rtl', 10287 responsiveClass: 'owl-responsive', 10288 dragClass: 'owl-drag', 10289 itemClass: 'owl-item', 10290 stageClass: 'owl-stage', 10291 stageOuterClass: 'owl-stage-outer', 10292 grabClass: 'owl-grab' 10293 }; 10294 10295 /** 10296 * Enumeration for width. 10297 * @public 10298 * @readonly 10299 * @enum {String} 10300 */ 10301 Owl.Width = { 10302 Default: 'default', 10303 Inner: 'inner', 10304 Outer: 'outer' 10305 }; 10306 10307 /** 10308 * Enumeration for types. 10309 * @public 10310 * @readonly 10311 * @enum {String} 10312 */ 10313 Owl.Type = { 10314 Event: 'event', 10315 State: 'state' 10316 }; 10317 10318 /** 10319 * Contains all registered plugins. 10320 * @public 10321 */ 10322 Owl.Plugins = {}; 10323 10324 /** 10325 * List of workers involved in the update process. 10326 */ 10327 Owl.Workers = [ { 10328 filter: [ 'width', 'settings' ], 10329 run: function() { 10330 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 10331 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 10332 } 10333 }, { 10334 filter: [ 'width', 'items', 'settings' ], 10335 run: function(cache) { 10336 cache.current = this._items && this._items[this.relative(this._current)]; 10337 } 10338 }, { 10339 filter: [ 'items', 'settings' ], 10340 run: function() { 10341 this.$stage.children('.cloned').remove(); 10342 } 10343 }, { 10344 filter: [ 'width', 'items', 'settings' ], 10345 run: function(cache) { 10346 var margin = this.settings.margin || '', 10347 grid = !this.settings.autoWidth, 10348 rtl = this.settings.rtl, 10349 css = { 10350 'width': 'auto', 10351 'margin-left': rtl ? margin : '', 10352 'margin-right': rtl ? '' : margin 10353 }; 10354 10355 !grid && this.$stage.children().css(css); 10356 10357 cache.css = css; 10358 } 10359 }, { 10360 filter: [ 'width', 'items', 'settings' ], 10361 run: function(cache) { 10362 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 10363 merge = null, 10364 iterator = this._items.length, 10365 grid = !this.settings.autoWidth, 10366 widths = []; 10367 10368 cache.items = { 10369 merge: false, 10370 width: width 10371 }; 10372 10373 while (iterator--) { 10374 merge = this._mergers[iterator]; 10375 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 10376 10377 cache.items.merge = merge > 1 || cache.items.merge; 10378 10379 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 10380 } 10381 10382 this._widths = widths; 10383 } 10384 }, { 10385 filter: [ 'items', 'settings' ], 10386 run: function() { 10387 var clones = [], 10388 items = this._items, 10389 settings = this.settings, 10390 view = Math.max(settings.items * 2, 4), 10391 size = Math.ceil(items.length / 2) * 2, 10392 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 10393 append = '', 10394 prepend = ''; 10395 10396 repeat /= 2; 10397 10398 while (repeat--) { 10399 clones.push(this.normalize(clones.length / 2, true)); 10400 append = append + items[clones[clones.length - 1]][0].outerHTML; 10401 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 10402 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 10403 } 10404 10405 this._clones = clones; 10406 10407 // var appendVideo = $(append).find('.uncode-video-container'); 10408 // if (appendVideo.length) { 10409 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 10410 // } 10411 // var prependVideo = $(prepend).find('.uncode-video-container'); 10412 // if (prependVideo.length) { 10413 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 10414 // } 10415 $(append).addClass('cloned').appendTo(this.$stage); 10416 $(prepend).addClass('cloned').prependTo(this.$stage); 10417 } 10418 }, { 10419 filter: [ 'width', 'items', 'settings' ], 10420 run: function() { 10421 var rtl = this.settings.rtl ? 1 : -1, 10422 size = this._clones.length + this._items.length, 10423 iterator = -1, 10424 previous = 0, 10425 current = 0, 10426 coordinates = []; 10427 10428 while (++iterator < size) { 10429 previous = coordinates[iterator - 1] || 0; 10430 current = this._widths[this.relative(iterator)] + this.settings.margin; 10431 coordinates.push(previous + current * rtl); 10432 } 10433 10434 this._coordinates = coordinates; 10435 } 10436 }, { 10437 filter: [ 'width', 'items', 'settings' ], 10438 run: function() { 10439 var padding = this.settings.stagePadding, 10440 coordinates = this._coordinates, 10441 css = { 10442 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 10443 'padding-left': padding || '', 10444 'padding-right': padding || '' 10445 }; 10446 10447 this.$stage.css(css); 10448 } 10449 }, { 10450 filter: [ 'width', 'items', 'settings' ], 10451 run: function(cache) { 10452 var iterator = this._coordinates.length, 10453 grid = !this.settings.autoWidth, 10454 items = this.$stage.children(); 10455 10456 if (grid && cache.items.merge) { 10457 while (iterator--) { 10458 cache.css.width = this._widths[this.relative(iterator)]; 10459 items.eq(iterator).css(cache.css); 10460 } 10461 } else if (grid) { 10462 cache.css.width = cache.items.width; 10463 items.css(cache.css); 10464 } 10465 } 10466 }, { 10467 filter: [ 'items' ], 10468 run: function() { 10469 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 10470 } 10471 }, { 10472 filter: [ 'width', 'items', 'settings' ], 10473 run: function(cache) { 10474 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 10475 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 10476 this.reset(cache.current); 10477 } 10478 }, { 10479 filter: [ 'position' ], 10480 run: function() { 10481 this.animate(this.coordinates(this._current)); 10482 } 10483 }, { 10484 filter: [ 'width', 'position', 'items', 'settings' ], 10485 run: function() { 10486 var rtl = this.settings.rtl ? 1 : -1, 10487 padding = this.settings.stagePadding * 2, 10488 begin = this.coordinates(this.current()) + padding, 10489 end = begin + this.width() * rtl, 10490 inner, outer, matches = [], i, n; 10491 10492 for (i = 0, n = this._coordinates.length; i < n; i++) { 10493 inner = this._coordinates[i - 1] || 0; 10494 outer = Math.abs(this._coordinates[i]) + padding * rtl; 10495 10496 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 10497 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 10498 matches.push(i); 10499 } 10500 } 10501 10502 this.$stage.children('.active').removeClass('active'); 10503 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 10504 10505 if (this.settings.center) { 10506 this.$stage.children('.center').removeClass('center'); 10507 this.$stage.children().eq(this.current()).addClass('center'); 10508 } 10509 } 10510 } ]; 10511 10512 /** 10513 * Initializes the carousel. 10514 * @protected 10515 */ 10516 Owl.prototype.initialize = function() { 10517 this.enter('initializing'); 10518 this.trigger('initialize'); 10519 10520 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 10521 10522 if (this.settings.autoWidth && !this.is('pre-loading')) { 10523 var imgs, nestedSelector, width; 10524 imgs = this.$element.find('img'); 10525 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 10526 width = this.$element.children(nestedSelector).width(); 10527 10528 if (imgs.length && width <= 0) { 10529 this.preloadAutoWidthImages(imgs); 10530 } 10531 } 10532 10533 this.$element.addClass(this.options.loadingClass); 10534 10535 // create stage 10536 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 10537 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 10538 10539 // append stage 10540 this.$element.append(this.$stage.parent()); 10541 10542 // append content 10543 this.replace(this.$element.children().not(this.$stage.parent())); 10544 10545 // check visibility 10546 if (this.$element.is(':visible')) { 10547 // update view 10548 this.refresh(); 10549 } else { 10550 // invalidate width 10551 this.invalidate('width'); 10552 } 10553 10554 this.$element 10555 .removeClass(this.options.loadingClass) 10556 .addClass(this.options.loadedClass); 10557 10558 // register event handlers 10559 this.registerEventHandlers(); 10560 10561 this.leave('initializing'); 10562 this.trigger('initialized'); 10563 }; 10564 10565 /** 10566 * Setups the current settings. 10567 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 10568 * @todo Support for media queries by using `matchMedia` would be nice. 10569 * @public 10570 */ 10571 Owl.prototype.setup = function() { 10572 var viewport = this.viewport(), 10573 overwrites = this.options.responsive, 10574 match = -1, 10575 settings = null; 10576 10577 if (!overwrites) { 10578 settings = $.extend({}, this.options); 10579 } else { 10580 $.each(overwrites, function(breakpoint) { 10581 if (breakpoint <= viewport && breakpoint > match) { 10582 match = Number(breakpoint); 10583 } 10584 }); 10585 10586 settings = $.extend({}, this.options, overwrites[match]); 10587 delete settings.responsive; 10588 10589 // responsive class 10590 if (settings.responsiveClass) { 10591 this.$element.attr('class', 10592 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 10593 ); 10594 } 10595 } 10596 10597 if (this.settings === null || this._breakpoint !== match) { 10598 this.trigger('change', { property: { name: 'settings', value: settings } }); 10599 this._breakpoint = match; 10600 this.settings = settings; 10601 this.invalidate('settings'); 10602 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 10603 } 10604 }; 10605 10606 /** 10607 * Updates option logic if necessery. 10608 * @protected 10609 */ 10610 Owl.prototype.optionsLogic = function() { 10611 if (this.settings.autoWidth) { 10612 this.settings.stagePadding = false; 10613 this.settings.merge = false; 10614 } 10615 }; 10616 10617 /** 10618 * Prepares an item before add. 10619 * @todo Rename event parameter `content` to `item`. 10620 * @protected 10621 * @returns {jQuery|HTMLElement} - The item container. 10622 */ 10623 Owl.prototype.prepare = function(item, index) { 10624 var event = this.trigger('prepare', { content: item }); 10625 if (!event.data) { 10626 event.data = $('<' + this.settings.itemElement + '/>') 10627 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 10628 } 10629 10630 this.trigger('prepared', { content: event.data }); 10631 10632 return event.data; 10633 }; 10634 10635 /** 10636 * Updates the view. 10637 * @public 10638 */ 10639 Owl.prototype.update = function() { 10640 var i = 0, 10641 n = this._pipe.length, 10642 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 10643 cache = {}; 10644 10645 while (i < n) { 10646 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 10647 this._pipe[i].run(cache); 10648 } 10649 i++; 10650 } 10651 10652 this._invalidated = {}; 10653 10654 !this.is('valid') && this.enter('valid'); 10655 }; 10656 10657 /** 10658 * Gets the width of the view. 10659 * @public 10660 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 10661 * @returns {Number} - The width of the view in pixel. 10662 */ 10663 Owl.prototype.width = function(dimension) { 10664 dimension = dimension || Owl.Width.Default; 10665 switch (dimension) { 10666 case Owl.Width.Inner: 10667 case Owl.Width.Outer: 10668 return this._width; 10669 default: 10670 return this._width - this.settings.stagePadding * 2 + this.settings.margin; 10671 } 10672 }; 10673 10674 /** 10675 * Refreshes the carousel primarily for adaptive purposes. 10676 * @public 10677 */ 10678 Owl.prototype.refresh = function() { 10679 this.enter('refreshing'); 10680 this.trigger('refresh'); 10681 10682 this.setup(); 10683 10684 this.optionsLogic(); 10685 10686 this.$element.addClass(this.options.refreshClass); 10687 10688 this.update(); 10689 10690 this.$element.removeClass(this.options.refreshClass); 10691 10692 this.leave('refreshing'); 10693 this.trigger('refreshed'); 10694 }; 10695 10696 /** 10697 * Checks window `resize` event. 10698 * @protected 10699 */ 10700 Owl.prototype.onThrottledResize = function() { 10701 window.clearTimeout(this.resizeTimer); 10702 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 10703 }; 10704 10705 /** 10706 * Checks window `resize` event. 10707 * @protected 10708 */ 10709 Owl.prototype.onResize = function() { 10710 if (!this._items.length) { 10711 return false; 10712 } 10713 10714 if (this._width === this.$element.width()) { 10715 return false; 10716 } 10717 10718 if (!this.$element.is(':visible')) { 10719 return false; 10720 } 10721 10722 this.enter('resizing'); 10723 10724 if (this.trigger('resize').isDefaultPrevented()) { 10725 this.leave('resizing'); 10726 return false; 10727 } 10728 10729 this.invalidate('width'); 10730 10731 this.refresh(); 10732 10733 this.leave('resizing'); 10734 this.trigger('resized'); 10735 }; 10736 10737 /** 10738 * Registers event handlers. 10739 * @todo Check `msPointerEnabled` 10740 * @todo #261 10741 * @protected 10742 */ 10743 Owl.prototype.registerEventHandlers = function() { 10744 if ($.support.transition) { 10745 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 10746 } 10747 10748 if (this.settings.responsive !== false) { 10749 this.on(window, 'resize', this._handlers.onThrottledResize); 10750 } 10751 10752 if (this.settings.mouseDrag) { 10753 this.$element.addClass(this.options.dragClass); 10754 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 10755 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 10756 } 10757 10758 if (this.settings.touchDrag){ 10759 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 10760 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 10761 } 10762 }; 10763 10764 /** 10765 * Handles `touchstart` and `mousedown` events. 10766 * @todo Horizontal swipe threshold as option 10767 * @todo #261 10768 * @protected 10769 * @param {Event} event - The event arguments. 10770 */ 10771 Owl.prototype.onDragStart = function(event) { 10772 var stage = null; 10773 10774 if (event.which === 3) { 10775 return; 10776 } 10777 10778 if ($.support.transform) { 10779 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 10780 stage = { 10781 x: stage[stage.length === 16 ? 12 : 4], 10782 y: stage[stage.length === 16 ? 13 : 5] 10783 }; 10784 } else { 10785 stage = this.$stage.position(); 10786 stage = { 10787 x: this.settings.rtl ? 10788 stage.left + this.$stage.width() - this.width() + this.settings.margin : 10789 stage.left, 10790 y: stage.top 10791 }; 10792 } 10793 10794 if (this.is('animating')) { 10795 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 10796 this.invalidate('position'); 10797 } 10798 10799 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 10800 10801 this.speed(0); 10802 10803 this._drag.time = new Date().getTime(); 10804 this._drag.target = $(event.target); 10805 this._drag.stage.start = stage; 10806 this._drag.stage.current = stage; 10807 this._drag.pointer = this.pointer(event); 10808 10809 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 10810 10811 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 10812 var delta = this.difference(this._drag.pointer, this.pointer(event)); 10813 10814 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 10815 10816 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 10817 return; 10818 } 10819 10820 event.preventDefault(); 10821 10822 this.enter('dragging'); 10823 this.trigger('drag'); 10824 }, this)); 10825 }; 10826 10827 /** 10828 * Handles the `touchmove` and `mousemove` events. 10829 * @todo #261 10830 * @protected 10831 * @param {Event} event - The event arguments. 10832 */ 10833 Owl.prototype.onDragMove = function(event) { 10834 var minimum = null, 10835 maximum = null, 10836 pull = null, 10837 delta = this.difference(this._drag.pointer, this.pointer(event)), 10838 stage = this.difference(this._drag.stage.start, delta); 10839 10840 if (!this.is('dragging')) { 10841 return; 10842 } 10843 10844 event.preventDefault(); 10845 10846 if (this.settings.loop) { 10847 minimum = this.coordinates(this.minimum()); 10848 maximum = this.coordinates(this.maximum() + 1) - minimum; 10849 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 10850 } else { 10851 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 10852 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 10853 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 10854 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 10855 } 10856 10857 this._drag.stage.current = stage; 10858 10859 this.animate(stage.x); 10860 }; 10861 10862 /** 10863 * Handles the `touchend` and `mouseup` events. 10864 * @todo #261 10865 * @todo Threshold for click event 10866 * @protected 10867 * @param {Event} event - The event arguments. 10868 */ 10869 Owl.prototype.onDragEnd = function(event) { 10870 var delta = this.difference(this._drag.pointer, this.pointer(event)), 10871 stage = this._drag.stage.current, 10872 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 10873 10874 $(document).off('.owl.core'); 10875 10876 this.$element.removeClass(this.options.grabClass); 10877 10878 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 10879 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 10880 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 10881 this.invalidate('position'); 10882 this.update(); 10883 10884 this._drag.direction = direction; 10885 10886 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 10887 this._drag.target.one('click.owl.core', function() { return false; }); 10888 } 10889 } 10890 10891 if (!this.is('dragging')) { 10892 return; 10893 } 10894 10895 this.leave('dragging'); 10896 this.trigger('dragged'); 10897 }; 10898 10899 /** 10900 * Gets absolute position of the closest item for a coordinate. 10901 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 10902 * @protected 10903 * @param {Number} coordinate - The coordinate in pixel. 10904 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 10905 * @return {Number} - The absolute position of the closest item. 10906 */ 10907 Owl.prototype.closest = function(coordinate, direction) { 10908 var position = -1, 10909 pull = 30, 10910 width = this.width(), 10911 coordinates = this.coordinates(); 10912 10913 if (!this.settings.freeDrag) { 10914 // check closest item 10915 $.each(coordinates, $.proxy(function(index, value) { 10916 if (coordinate > value - pull && coordinate < value + pull) { 10917 position = index; 10918 } else if (this.op(coordinate, '<', value) 10919 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 10920 position = direction === 'left' ? index + 1 : index; 10921 } 10922 return position === -1; 10923 }, this)); 10924 } 10925 10926 if (!this.settings.loop) { 10927 // non loop boundries 10928 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 10929 position = coordinate = this.minimum(); 10930 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 10931 position = coordinate = this.maximum(); 10932 } 10933 } 10934 10935 return position; 10936 }; 10937 10938 /** 10939 * Animates the stage. 10940 * @todo #270 10941 * @public 10942 * @param {Number} coordinate - The coordinate in pixels. 10943 */ 10944 Owl.prototype.animate = function(coordinate) { 10945 var animate = this.speed() > 0; 10946 10947 this.is('animating') && this.onTransitionEnd(); 10948 10949 if (animate) { 10950 this.enter('animating'); 10951 this.trigger('translate'); 10952 } 10953 10954 if ($.support.transform3d && $.support.transition) { 10955 this.$stage.css({ 10956 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 10957 transition: (this.speed() / 1000) + 's' 10958 }); 10959 } else if (animate) { 10960 this.$stage.animate({ 10961 left: coordinate + 'px' 10962 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 10963 } else { 10964 this.$stage.css({ 10965 left: coordinate + 'px' 10966 }); 10967 } 10968 }; 10969 10970 /** 10971 * Checks whether the carousel is in a specific state or not. 10972 * @param {String} state - The state to check. 10973 * @returns {Boolean} - The flag which indicates if the carousel is busy. 10974 */ 10975 Owl.prototype.is = function(state) { 10976 return this._states.current[state] && this._states.current[state] > 0; 10977 }; 10978 10979 /** 10980 * Sets the absolute position of the current item. 10981 * @public 10982 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 10983 * @returns {Number} - The absolute position of the current item. 10984 */ 10985 Owl.prototype.current = function(position) { 10986 if (position === undefined) { 10987 return this._current; 10988 } 10989 10990 if (this._items.length === 0) { 10991 return undefined; 10992 } 10993 10994 position = this.normalize(position); 10995 10996 if (this._current !== position) { 10997 var event = this.trigger('change', { property: { name: 'position', value: position } }); 10998 10999 if (event.data !== undefined) { 11000 position = this.normalize(event.data); 11001 } 11002 11003 this._current = position; 11004 11005 this.invalidate('position'); 11006 11007 this.trigger('changed', { property: { name: 'position', value: this._current } }); 11008 } 11009 11010 return this._current; 11011 }; 11012 11013 /** 11014 * Invalidates the given part of the update routine. 11015 * @param {String} [part] - The part to invalidate. 11016 * @returns {Array.<String>} - The invalidated parts. 11017 */ 11018 Owl.prototype.invalidate = function(part) { 11019 if ($.type(part) === 'string') { 11020 this._invalidated[part] = true; 11021 this.is('valid') && this.leave('valid'); 11022 } 11023 return $.map(this._invalidated, function(v, i) { return i }); 11024 }; 11025 11026 /** 11027 * Resets the absolute position of the current item. 11028 * @public 11029 * @param {Number} position - The absolute position of the new item. 11030 */ 11031 Owl.prototype.reset = function(position) { 11032 position = this.normalize(position); 11033 11034 if (position === undefined) { 11035 return; 11036 } 11037 11038 this._speed = 0; 11039 this._current = position; 11040 11041 this.suppress([ 'translate', 'translated' ]); 11042 11043 this.animate(this.coordinates(position)); 11044 11045 this.release([ 'translate', 'translated' ]); 11046 }; 11047 11048 /** 11049 * Normalizes an absolute or a relative position of an item. 11050 * @public 11051 * @param {Number} position - The absolute or relative position to normalize. 11052 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 11053 * @returns {Number} - The normalized position. 11054 */ 11055 Owl.prototype.normalize = function(position, relative) { 11056 var n = this._items.length, 11057 m = relative ? 0 : this._clones.length; 11058 11059 if (!$.isNumeric(position) || n < 1) { 11060 position = undefined; 11061 } else if (position < 0 || position >= n + m) { 11062 position = ((position - m / 2) % n + n) % n + m / 2; 11063 } 11064 11065 return position; 11066 }; 11067 11068 /** 11069 * Converts an absolute position of an item into a relative one. 11070 * @public 11071 * @param {Number} position - The absolute position to convert. 11072 * @returns {Number} - The converted position. 11073 */ 11074 Owl.prototype.relative = function(position) { 11075 position -= this._clones.length / 2; 11076 return this.normalize(position, true); 11077 }; 11078 11079 /** 11080 * Gets the maximum position for the current item. 11081 * @public 11082 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11083 * @returns {Number} 11084 */ 11085 Owl.prototype.maximum = function(relative) { 11086 var settings = this.settings, 11087 maximum = this._coordinates.length, 11088 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 11089 i = -1, j; 11090 11091 if (settings.loop) { 11092 maximum = this._clones.length / 2 + this._items.length - 1; 11093 } else if (settings.autoWidth || settings.merge) { 11094 // binary search 11095 while (maximum - i > 1) { 11096 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 11097 ? i = j : maximum = j; 11098 } 11099 } else if (settings.center) { 11100 maximum = this._items.length - 1; 11101 } else { 11102 maximum = this._items.length - settings.items; 11103 } 11104 11105 if (relative) { 11106 maximum -= this._clones.length / 2; 11107 } 11108 11109 return Math.max(maximum, 0); 11110 }; 11111 11112 /** 11113 * Gets the minimum position for the current item. 11114 * @public 11115 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11116 * @returns {Number} 11117 */ 11118 Owl.prototype.minimum = function(relative) { 11119 return relative ? 0 : this._clones.length / 2; 11120 }; 11121 11122 /** 11123 * Gets an item at the specified relative position. 11124 * @public 11125 * @param {Number} [position] - The relative position of the item. 11126 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11127 */ 11128 Owl.prototype.items = function(position) { 11129 if (position === undefined) { 11130 return this._items.slice(); 11131 } 11132 11133 position = this.normalize(position, true); 11134 return this._items[position]; 11135 }; 11136 11137 /** 11138 * Gets an item at the specified relative position. 11139 * @public 11140 * @param {Number} [position] - The relative position of the item. 11141 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11142 */ 11143 Owl.prototype.mergers = function(position) { 11144 if (position === undefined) { 11145 return this._mergers.slice(); 11146 } 11147 11148 position = this.normalize(position, true); 11149 return this._mergers[position]; 11150 }; 11151 11152 /** 11153 * Gets the absolute positions of clones for an item. 11154 * @public 11155 * @param {Number} [position] - The relative position of the item. 11156 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 11157 */ 11158 Owl.prototype.clones = function(position) { 11159 var odd = this._clones.length / 2, 11160 even = odd + this._items.length, 11161 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 11162 11163 if (position === undefined) { 11164 return $.map(this._clones, function(v, i) { return map(i) }); 11165 } 11166 11167 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 11168 }; 11169 11170 /** 11171 * Sets the current animation speed. 11172 * @public 11173 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 11174 * @returns {Number} - The current animation speed in milliseconds. 11175 */ 11176 Owl.prototype.speed = function(speed) { 11177 if (speed !== undefined) { 11178 this._speed = speed; 11179 } 11180 11181 return this._speed; 11182 }; 11183 11184 /** 11185 * Gets the coordinate of an item. 11186 * @todo The name of this method is missleanding. 11187 * @public 11188 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 11189 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 11190 */ 11191 Owl.prototype.coordinates = function(position) { 11192 var coordinate = null; 11193 11194 if (position === undefined) { 11195 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 11196 return this.coordinates(index); 11197 }, this)); 11198 } 11199 11200 if (this.settings.center) { 11201 coordinate = this._coordinates[position]; 11202 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 11203 } else { 11204 coordinate = this._coordinates[position - 1] || 0; 11205 } 11206 11207 return coordinate; 11208 }; 11209 11210 /** 11211 * Calculates the speed for a translation. 11212 * @protected 11213 * @param {Number} from - The absolute position of the start item. 11214 * @param {Number} to - The absolute position of the target item. 11215 * @param {Number} [factor=undefined] - The time factor in milliseconds. 11216 * @returns {Number} - The time in milliseconds for the translation. 11217 */ 11218 Owl.prototype.duration = function(from, to, factor) { 11219 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 11220 }; 11221 11222 /** 11223 * Slides to the specified item. 11224 * @public 11225 * @param {Number} position - The position of the item. 11226 * @param {Number} [speed] - The time in milliseconds for the transition. 11227 */ 11228 Owl.prototype.to = function(position, speed) { 11229 var current = this.current(), 11230 revert = null, 11231 distance = position - this.relative(current), 11232 direction = (distance > 0) - (distance < 0), 11233 items = this._items.length, 11234 minimum = this.minimum(), 11235 maximum = this.maximum(); 11236 11237 if (this.settings.loop) { 11238 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 11239 distance += direction * -1 * items; 11240 } 11241 11242 position = current + distance; 11243 revert = ((position - minimum) % items + items) % items + minimum; 11244 11245 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 11246 current = revert - distance; 11247 position = revert; 11248 this.reset(current); 11249 } 11250 } else if (this.settings.rewind) { 11251 maximum += 1; 11252 position = (position % maximum + maximum) % maximum; 11253 } else { 11254 position = Math.max(minimum, Math.min(maximum, position)); 11255 } 11256 11257 this.speed(this.duration(current, position, speed)); 11258 this.current(position); 11259 11260 if (this.$element.is(':visible')) { 11261 this.update(); 11262 } 11263 }; 11264 11265 /** 11266 * Slides to the next item. 11267 * @public 11268 * @param {Number}
vendor: 4,086 bytes, lines 11268-11404
11268 [speed] - The time in milliseconds for the transition. 11269 */ 11270 Owl.prototype.next = function(speed) { 11271 speed = speed || false; 11272 this.to(this.relative(this.current()) + 1, speed); 11273 }; 11274 11275 /** 11276 * Slides to the previous item. 11277 * @public 11278 * @param {Number} [speed] - The time in milliseconds for the transition. 11279 */ 11280 Owl.prototype.prev = function(speed) { 11281 speed = speed || false; 11282 this.to(this.relative(this.current()) - 1, speed); 11283 }; 11284 11285 /** 11286 * Handles the end of an animation. 11287 * @protected 11288 * @param {Event} event - The event arguments. 11289 */ 11290 Owl.prototype.onTransitionEnd = function(event) { 11291 11292 // if css2 animation then event object is undefined 11293 if (event !== undefined) { 11294 event.stopPropagation(); 11295 11296 // Catch only owl-stage transitionEnd event 11297 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 11298 return false; 11299 } 11300 } 11301 11302 this.leave('animating'); 11303 this.trigger('translated'); 11304 }; 11305 11306 /** 11307 * Gets viewport width. 11308 * @protected 11309 * @return {Number} - The width in pixel. 11310 */ 11311 Owl.prototype.viewport = function() { 11312 var width; 11313 if (this.options.responsiveBaseElement !== window) { 11314 width = $(this.options.responsiveBaseElement).width(); 11315 } else if (window.innerWidth) { 11316 width = window.innerWidth; 11317 } else if (document.documentElement && document.documentElement.clientWidth) { 11318 width = document.documentElement.clientWidth; 11319 } else { 11320 throw 'Can not detect viewport width.'; 11321 } 11322 11323 return width; 11324 }; 11325 11326 /** 11327 * Replaces the current content. 11328 * @public 11329 * @param {HTMLElement|jQuery|String} content - The new content. 11330 */ 11331 Owl.prototype.replace = function(content) { 11332 this.$stage.empty(); 11333 this._items = []; 11334 11335 if (content) { 11336 content = (content instanceof jQuery) ? content : $(content); 11337 } 11338 11339 if (this.settings.nestedItemSelector) { 11340 content = content.find('.' + this.settings.nestedItemSelector); 11341 } 11342 11343 content.filter(function() { 11344 return this.nodeType === 1; 11345 }).each($.proxy(function(index, item) { 11346 item = this.prepare(item, index); 11347 this.$stage.append(item); 11348 this._items.push(item); 11349 this._mergers.push(item.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11350 }, this)); 11351 11352 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 11353 11354 this.invalidate('items'); 11355 }; 11356 11357 /** 11358 * Adds an item. 11359 * @todo Use `item` instead of `content` for the event arguments. 11360 * @public 11361 * @param {HTMLElement|jQuery|String} content - The item content to add. 11362 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 11363 */ 11364 Owl.prototype.add = function(content, position) { 11365 var current = this.relative(this._current); 11366 11367 position = position === undefined ? this._items.length : this.normalize(position, true); 11368 content = content instanceof jQuery ? content : $(content); 11369 11370 this.trigger('add', { content: content, position: position }); 11371 11372 content = this.prepare(content, this._items[current].index()); 11373 11374 if (this._items.length === 0 || position === this._items.length) { 11375 this._items.length === 0 && this.$stage.append(content); 11376 this._items.length !== 0 && this._items[position - 1].after(content); 11377 this._items.push(content); 11378 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11379 } else { 11380 this._items[position].before(content); 11381 this._items.splice(position, 0, content); 11382 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11383 } 11384 11385 this._items[current] && this.reset(this._items[current].index()); 11386 11387 this.invalidate('items'); 11388 11389 this.trigger('added', { content: content, position: position }); 11390 }; 11391 11392 /** 11393 * Removes an item by its position. 11394 * @todo Use `item` instead of `content` for the event arguments. 11395 * @public 11396 * @param {Number} position - The relative position of the item to remove. 11397 */ 11398 Owl.prototype.remove = function(position) { 11399 position = this.normalize(position, true); 11400 11401 if (position === undefined) { 11402 return; 11403 } 11404
vendor: 40,434 bytes, lines 11405-12971
11405 this.trigger('remove', { content: this._items[position], position: position }); 11406 11407 this._items[position].remove(); 11408 this._items.splice(position, 1); 11409 this._mergers.splice(position, 1); 11410 11411 this.invalidate('items'); 11412 11413 this.trigger('removed', { content: null, position: position }); 11414 }; 11415 11416 /** 11417 * Preloads images with auto width. 11418 * @todo Replace by a more generic approach 11419 * @protected 11420 */ 11421 Owl.prototype.preloadAutoWidthImages = function(images) { 11422 images.each($.proxy(function(i, element) { 11423 this.enter('pre-loading'); 11424 element = $(element); 11425 $(new Image()).one('load', $.proxy(function(e) { 11426 element.attr('src', e.target.src); 11427 element.css('opacity', 1); 11428 this.leave('pre-loading'); 11429 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 11430 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 11431 }, this)); 11432 }; 11433 11434 /** 11435 * Destroys the carousel. 11436 * @public 11437 */ 11438 Owl.prototype.destroy = function() { 11439 11440 this.$element.off('.owl.core'); 11441 this.$stage.off('.owl.core'); 11442 $(document).off('.owl.core'); 11443 11444 if (this.settings.responsive !== false) { 11445 window.clearTimeout(this.resizeTimer); 11446 this.off(window, 'resize', this._handlers.onThrottledResize); 11447 } 11448 11449 for (var i in this._plugins) { 11450 this._plugins[i].destroy(); 11451 } 11452 11453 this.$stage.children('.cloned').remove(); 11454 11455 this.$stage.unwrap(); 11456 this.$stage.children().contents().unwrap(); 11457 this.$stage.children().unwrap(); 11458 11459 this.$element 11460 .removeClass(this.options.refreshClass) 11461 .removeClass(this.options.loadingClass) 11462 .removeClass(this.options.loadedClass) 11463 .removeClass(this.options.rtlClass) 11464 .removeClass(this.options.dragClass) 11465 .removeClass(this.options.grabClass) 11466 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 11467 .removeData('owl.carousel'); 11468 }; 11469 11470 /** 11471 * Operators to calculate right-to-left and left-to-right. 11472 * @protected 11473 * @param {Number} [a] - The left side operand. 11474 * @param {String} [o] - The operator. 11475 * @param {Number} [b] - The right side operand. 11476 */ 11477 Owl.prototype.op = function(a, o, b) { 11478 var rtl = this.settings.rtl; 11479 switch (o) { 11480 case '<': 11481 return rtl ? a > b : a < b; 11482 case '>': 11483 return rtl ? a < b : a > b; 11484 case '>=': 11485 return rtl ? a <= b : a >= b; 11486 case '<=': 11487 return rtl ? a >= b : a <= b; 11488 default: 11489 break; 11490 } 11491 }; 11492 11493 /** 11494 * Attaches to an internal event. 11495 * @protected 11496 * @param {HTMLElement} element - The event source. 11497 * @param {String} event - The event name. 11498 * @param {Function} listener - The event handler to attach. 11499 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 11500 */ 11501 Owl.prototype.on = function(element, event, listener, capture) { 11502 if (element.addEventListener) { 11503 element.addEventListener(event, listener, capture); 11504 } else if (element.attachEvent) { 11505 element.attachEvent('on' + event, listener); 11506 } 11507 }; 11508 11509 /** 11510 * Detaches from an internal event. 11511 * @protected 11512 * @param {HTMLElement} element - The event source. 11513 * @param {String} event - The event name. 11514 * @param {Function} listener - The attached event handler to detach. 11515 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 11516 */ 11517 Owl.prototype.off = function(element, event, listener, capture) { 11518 if (element.removeEventListener) { 11519 element.removeEventListener(event, listener, capture); 11520 } else if (element.detachEvent) { 11521 element.detachEvent('on' + event, listener); 11522 } 11523 }; 11524 11525 /** 11526 * Triggers a public event. 11527 * @todo Remove `status`, `relatedTarget` should be used instead. 11528 * @protected 11529 * @param {String} name - The event name. 11530 * @param {*} [data=null] - The event data. 11531 * @param {String} [namespace=carousel] - The event namespace. 11532 * @param {String} [state] - The state which is associated with the event. 11533 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 11534 * @returns {Event} - The event arguments. 11535 */ 11536 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 11537 var status = { 11538 item: { count: this._items.length, index: this.current() } 11539 }, handler = $.camelCase( 11540 $.grep([ 'on', name, namespace ], function(v) { return v }) 11541 .join('-').toLowerCase() 11542 ), event = $.Event( 11543 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 11544 $.extend({ relatedTarget: this }, status, data) 11545 ); 11546 11547 if (!this._supress[name]) { 11548 $.each(this._plugins, function(name, plugin) { 11549 if (plugin.onTrigger) { 11550 plugin.onTrigger(event); 11551 } 11552 }); 11553 11554 this.register({ type: Owl.Type.Event, name: name }); 11555 this.$element.trigger(event); 11556 11557 if (this.settings && typeof this.settings[handler] === 'function') { 11558 this.settings[handler].call(this, event); 11559 } 11560 } 11561 11562 return event; 11563 }; 11564 11565 /** 11566 * Enters a state. 11567 * @param name - The state name. 11568 */ 11569 Owl.prototype.enter = function(name) { 11570 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11571 if (this._states.current[name] === undefined) { 11572 this._states.current[name] = 0; 11573 } 11574 11575 this._states.current[name]++; 11576 }, this)); 11577 }; 11578 11579 /** 11580 * Leaves a state. 11581 * @param name - The state name. 11582 */ 11583 Owl.prototype.leave = function(name) { 11584 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11585 this._states.current[name]--; 11586 }, this)); 11587 }; 11588 11589 /** 11590 * Registers an event or state. 11591 * @public 11592 * @param {Object} object - The event or state to register. 11593 */ 11594 Owl.prototype.register = function(object) { 11595 if (object.type === Owl.Type.Event) { 11596 if (!$.event.special[object.name]) { 11597 $.event.special[object.name] = {}; 11598 } 11599 11600 if (!$.event.special[object.name].owl) { 11601 var _default = $.event.special[object.name]._default; 11602 $.event.special[object.name]._default = function(e) { 11603 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 11604 return _default.apply(this, arguments); 11605 } 11606 return e.namespace && e.namespace.indexOf('owl') > -1; 11607 }; 11608 $.event.special[object.name].owl = true; 11609 } 11610 } else if (object.type === Owl.Type.State) { 11611 if (!this._states.tags[object.name]) { 11612 this._states.tags[object.name] = object.tags; 11613 } else { 11614 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 11615 } 11616 11617 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 11618 return $.inArray(tag, this._states.tags[object.name]) === i; 11619 }, this)); 11620 } 11621 }; 11622 11623 /** 11624 * Suppresses events. 11625 * @protected 11626 * @param {Array.<String>} events - The events to suppress. 11627 */ 11628 Owl.prototype.suppress = function(events) { 11629 $.each(events, $.proxy(function(index, event) { 11630 this._supress[event] = true; 11631 }, this)); 11632 }; 11633 11634 /** 11635 * Releases suppressed events. 11636 * @protected 11637 * @param {Array.<String>} events - The events to release. 11638 */ 11639 Owl.prototype.release = function(events) { 11640 $.each(events, $.proxy(function(index, event) { 11641 delete this._supress[event]; 11642 }, this)); 11643 }; 11644 11645 /** 11646 * Gets unified pointer coordinates from event. 11647 * @todo #261 11648 * @protected 11649 * @param {Event} - The `mousedown` or `touchstart` event. 11650 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 11651 */ 11652 Owl.prototype.pointer = function(event) { 11653 var result = { x: null, y: null }; 11654 11655 event = event.originalEvent || event || window.event; 11656 11657 event = event.touches && event.touches.length ? 11658 event.touches[0] : event.changedTouches && event.changedTouches.length ? 11659 event.changedTouches[0] : event; 11660 11661 if (event.pageX) { 11662 result.x = event.pageX; 11663 result.y = event.pageY; 11664 } else { 11665 result.x = event.clientX; 11666 result.y = event.clientY; 11667 } 11668 11669 return result; 11670 }; 11671 11672 /** 11673 * Gets the difference of two vectors. 11674 * @todo #261 11675 * @protected 11676 * @param {Object} - The first vector. 11677 * @param {Object} - The second vector. 11678 * @returns {Object} - The difference. 11679 */ 11680 Owl.prototype.difference = function(first, second) { 11681 return { 11682 x: first.x - second.x, 11683 y: first.y - second.y 11684 }; 11685 }; 11686 11687 /** 11688 * The jQuery Plugin for the Owl Carousel 11689 * @todo Navigation plugin `next` and `prev` 11690 * @public 11691 */ 11692 $.fn.owlCarousel = function(option) { 11693 var args = Array.prototype.slice.call(arguments, 1); 11694 11695 return this.each(function() { 11696 var $this = $(this), 11697 data = $this.data('owl.carousel'); 11698 11699 if (!data) { 11700 data = new Owl(this, typeof option == 'object' && option); 11701 $this.data('owl.carousel', data); 11702 11703 $.each([ 11704 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 11705 ], function(i, event) { 11706 data.register({ type: Owl.Type.Event, name: event }); 11707 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 11708 if (e.namespace && e.relatedTarget !== this) { 11709 this.suppress([ event ]); 11710 data[event].apply(this, [].slice.call(arguments, 1)); 11711 this.release([ event ]); 11712 } 11713 }, data)); 11714 }); 11715 } 11716 11717 if (typeof option == 'string' && option.charAt(0) !== '_') { 11718 data[option].apply(data, args); 11719 } 11720 }); 11721 }; 11722 11723 /** 11724 * The constructor for the jQuery Plugin 11725 * @public 11726 */ 11727 $.fn.owlCarousel.Constructor = Owl; 11728 11729})(window.Zepto || window.jQuery, window, document); 11730 11731/** 11732 * AutoRefresh Plugin 11733 * @version 2.0.0-beta.3 11734 * @author Artus Kolanowski 11735 * @license The MIT License (MIT) 11736 */ 11737;(function($, window, document, undefined) { 11738 11739 /** 11740 * Creates the auto refresh plugin. 11741 * @class The Auto Refresh Plugin 11742 * @param {Owl} carousel - The Owl Carousel 11743 */ 11744 var AutoRefresh = function(carousel) { 11745 /** 11746 * Reference to the core. 11747 * @protected 11748 * @type {Owl} 11749 */ 11750 this._core = carousel; 11751 11752 /** 11753 * Refresh interval. 11754 * @protected 11755 * @type {number} 11756 */ 11757 this._interval = null; 11758 11759 /** 11760 * Whether the element is currently visible or not. 11761 * @protected 11762 * @type {Boolean} 11763 */ 11764 this._visible = null; 11765 11766 /** 11767 * All event handlers. 11768 * @protected 11769 * @type {Object} 11770 */ 11771 this._handlers = { 11772 'initialized.owl.carousel': $.proxy(function(e) { 11773 if (e.namespace && this._core.settings.autoRefresh) { 11774 this.watch(); 11775 } 11776 }, this) 11777 }; 11778 11779 // set default options 11780 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 11781 11782 // register event handlers 11783 this._core.$element.on(this._handlers); 11784 }; 11785 11786 /** 11787 * Default options. 11788 * @public 11789 */ 11790 AutoRefresh.Defaults = { 11791 autoRefresh: true, 11792 autoRefreshInterval: 500 11793 }; 11794 11795 /** 11796 * Watches the element. 11797 */ 11798 AutoRefresh.prototype.watch = function() { 11799 if (this._interval) { 11800 return; 11801 } 11802 11803 this._visible = this._core.$element.is(':visible'); 11804 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 11805 }; 11806 11807 /** 11808 * Refreshes the element. 11809 */ 11810 AutoRefresh.prototype.refresh = function() { 11811 if (this._core.$element.is(':visible') === this._visible) { 11812 return; 11813 } 11814 11815 this._visible = !this._visible; 11816 11817 this._core.$element.toggleClass('owl-hidden', !this._visible); 11818 11819 this._visible && (this._core.invalidate('width') && this._core.refresh()); 11820 }; 11821 11822 /** 11823 * Destroys the plugin. 11824 */ 11825 AutoRefresh.prototype.destroy = function() { 11826 var handler, property; 11827 11828 window.clearInterval(this._interval); 11829 11830 for (handler in this._handlers) { 11831 this._core.$element.off(handler, this._handlers[handler]); 11832 } 11833 for (property in Object.getOwnPropertyNames(this)) { 11834 typeof this[property] != 'function' && (this[property] = null); 11835 } 11836 }; 11837 11838 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 11839 11840})(window.Zepto || window.jQuery, window, document); 11841 11842/** 11843 * Lazy Plugin 11844 * @version 2.0.0-beta.3 11845 * @author Bartosz Wojciechowski 11846 * @license The MIT License (MIT) 11847 */ 11848;(function($, window, document, undefined) { 11849 11850 /** 11851 * Creates the lazy plugin. 11852 * @class The Lazy Plugin 11853 * @param {Owl} carousel - The Owl Carousel 11854 */ 11855 var Lazy = function(carousel) { 11856 11857 /** 11858 * Reference to the core. 11859 * @protected 11860 * @type {Owl} 11861 */ 11862 this._core = carousel; 11863 11864 /** 11865 * Already loaded items. 11866 * @protected 11867 * @type {Array.<jQuery>} 11868 */ 11869 this._loaded = []; 11870 11871 /** 11872 * Event handlers. 11873 * @protected 11874 * @type {Object} 11875 */ 11876 this._handlers = { 11877 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 11878 if (!e.namespace) { 11879 return; 11880 } 11881 11882 if (!this._core.settings || !this._core.settings.lazyLoad) { 11883 return; 11884 } 11885 11886 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 11887 var settings = this._core.settings, 11888 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 11889 i = ((settings.center && n * -1) || 0), 11890 position = ((e.property && e.property.value) || this._core.current()) + i, 11891 clones = this._core.clones().length, 11892 load = $.proxy(function(i, v) { this.load(v) }, this); 11893 11894 while (i++ < n) { 11895 this.load(clones / 2 + this._core.relative(position)); 11896 clones && $.each(this._core.clones(this._core.relative(position)), load); 11897 position++; 11898 } 11899 } 11900 }, this) 11901 }; 11902 11903 // set the default options 11904 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 11905 11906 // register event handler 11907 this._core.$element.on(this._handlers); 11908 } 11909 11910 /** 11911 * Default options. 11912 * @public 11913 */ 11914 Lazy.Defaults = { 11915 lazyLoad: false 11916 } 11917 11918 /** 11919 * Loads all resources of an item at the specified position. 11920 * @param {Number} position - The absolute position of the item. 11921 * @protected 11922 */ 11923 Lazy.prototype.load = function(position) { 11924 var $item = this._core.$stage.children().eq(position), 11925 $elements = $item && $item.find('.owl-lazy'); 11926 11927 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 11928 return; 11929 } 11930 11931 $elements.each($.proxy(function(index, element) { 11932 var $element = $(element), image, 11933 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 11934 11935 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 11936 11937 if ($element.is('img')) { 11938 $element.one('load.owl.lazy', $.proxy(function() { 11939 $element.css('opacity', 1); 11940 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 11941 }, this)).attr('src', url); 11942 } else { 11943 image = new Image(); 11944 image.onload = $.proxy(function() { 11945 $element.css({ 11946 'background-image': 'url(' + url + ')', 11947 'opacity': '1' 11948 }); 11949 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 11950 }, this); 11951 image.src = url; 11952 } 11953 }, this)); 11954 11955 this._loaded.push($item.get(0)); 11956 } 11957 11958 /** 11959 * Destroys the plugin. 11960 * @public 11961 */ 11962 Lazy.prototype.destroy = function() { 11963 var handler, property; 11964 11965 for (handler in this.handlers) { 11966 this._core.$element.off(handler, this.handlers[handler]); 11967 } 11968 for (property in Object.getOwnPropertyNames(this)) { 11969 typeof this[property] != 'function' && (this[property] = null); 11970 } 11971 }; 11972 11973 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 11974 11975})(window.Zepto || window.jQuery, window, document); 11976 11977/** 11978 * AutoHeight Plugin 11979 * @version 2.0.0-beta.3 11980 * @author Bartosz Wojciechowski 11981 * @license The MIT License (MIT) 11982 */ 11983;(function($, window, document, undefined) { 11984 11985 /** 11986 * Creates the auto height plugin. 11987 * @class The Auto Height Plugin 11988 * @param {Owl} carousel - The Owl Carousel 11989 */ 11990 var AutoHeight = function(carousel) { 11991 /** 11992 * Reference to the core. 11993 * @protected 11994 * @type {Owl} 11995 */ 11996 this._core = carousel; 11997 11998 /** 11999 * All event handlers. 12000 * @protected 12001 * @type {Object} 12002 */ 12003 this._handlers = { 12004 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 12005 if (e.namespace && this._core.settings.autoHeight) { 12006 this.update(); 12007 } 12008 }, this), 12009 'changed.owl.carousel': $.proxy(function(e) { 12010 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 12011 this.update(); 12012 } 12013 }, this), 12014 'loaded.owl.lazy': $.proxy(function(e) { 12015 if (e.namespace && this._core.settings.autoHeight 12016 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 12017 this.update(); 12018 } 12019 }, this) 12020 }; 12021 12022 // set default options 12023 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 12024 12025 // register event handlers 12026 this._core.$element.on(this._handlers); 12027 }; 12028 12029 /** 12030 * Default options. 12031 * @public 12032 */ 12033 AutoHeight.Defaults = { 12034 autoHeight: false, 12035 autoHeightClass: 'owl-height' 12036 }; 12037 12038 /** 12039 * Updates the view. 12040 */ 12041 AutoHeight.prototype.update = function() { 12042 var start = this._core._current, 12043 end = start + this._core.settings.items, 12044 visible = this._core.$stage.children().toArray().slice(start, end); 12045 heights = [], 12046 maxheight = 0; 12047 12048 $.each(visible, function(index, item) { 12049 heights.push($(item).height()); 12050 }); 12051 12052 maxheight = Math.max.apply(null, heights); 12053 12054 this._core.$stage.parent() 12055 .height(maxheight) 12056 .addClass(this._core.settings.autoHeightClass); 12057 }; 12058 12059 AutoHeight.prototype.destroy = function() { 12060 var handler, property; 12061 12062 for (handler in this._handlers) { 12063 this._core.$element.off(handler, this._handlers[handler]); 12064 } 12065 for (property in Object.getOwnPropertyNames(this)) { 12066 typeof this[property] != 'function' && (this[property] = null); 12067 } 12068 }; 12069 12070 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 12071 12072})(window.Zepto || window.jQuery, window, document); 12073 12074/** 12075 * Video Plugin 12076 * @version 2.0.0-beta.3 12077 * @author Bartosz Wojciechowski 12078 * @license The MIT License (MIT) 12079 */ 12080;(function($, window, document, undefined) { 12081 12082 /** 12083 * Creates the video plugin. 12084 * @class The Video Plugin 12085 * @param {Owl} carousel - The Owl Carousel 12086 */ 12087 var Video = function(carousel) { 12088 /** 12089 * Reference to the core. 12090 * @protected 12091 * @type {Owl} 12092 */ 12093 this._core = carousel; 12094 12095 /** 12096 * Cache all video URLs. 12097 * @protected 12098 * @type {Object} 12099 */ 12100 this._videos = {}; 12101 12102 /** 12103 * Current playing item. 12104 * @protected 12105 * @type {jQuery} 12106 */ 12107 this._playing = null; 12108 12109 /** 12110 * All event handlers. 12111 * @todo The cloned content removale is too late 12112 * @protected 12113 * @type {Object} 12114 */ 12115 this._handlers = { 12116 'initialized.owl.carousel': $.proxy(function(e) { 12117 if (e.namespace) { 12118 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 12119 } 12120 }, this), 12121 'resize.owl.carousel': $.proxy(function(e) { 12122 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 12123 e.preventDefault(); 12124 } 12125 }, this), 12126 'refreshed.owl.carousel': $.proxy(function(e) { 12127 if (e.namespace && this._core.is('resizing')) { 12128 this._core.$stage.find('.cloned .owl-video-frame').remove(); 12129 } 12130 }, this), 12131 'changed.owl.carousel': $.proxy(function(e) { 12132 if (e.namespace && e.property.name === 'position' && this._playing) { 12133 this.stop(); 12134 } 12135 }, this), 12136 'prepared.owl.carousel': $.proxy(function(e) { 12137 if (!e.namespace) { 12138 return; 12139 } 12140 12141 var $element = $(e.content).find('.owl-video'); 12142 12143 if ($element.length) { 12144 $element.css('display', 'none'); 12145 this.fetch($element, $(e.content)); 12146 } 12147 }, this) 12148 }; 12149 12150 // set default options 12151 this._core.options = $.extend({}, Video.Defaults, this._core.options); 12152 12153 // register event handlers 12154 this._core.$element.on(this._handlers); 12155 12156 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 12157 this.play(e); 12158 }, this)); 12159 }; 12160 12161 /** 12162 * Default options. 12163 * @public 12164 */ 12165 Video.Defaults = { 12166 video: false, 12167 videoHeight: false, 12168 videoWidth: false 12169 }; 12170 12171 /** 12172 * Gets the video ID and the type (YouTube/Vimeo only). 12173 * @protected 12174 * @param {jQuery} target - The target containing the video data. 12175 * @param {jQuery} item - The item containing the video. 12176 */ 12177 Video.prototype.fetch = function(target, item) { 12178 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 12179 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 12180 width = target.attr('data-width') || this._core.settings.videoWidth, 12181 height = target.attr('data-height') || this._core.settings.videoHeight, 12182 url = target.attr('href'); 12183 12184 if (url) { 12185 id = url.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/); 12186 12187 if (id[3].indexOf('youtu') > -1) { 12188 type = 'youtube'; 12189 } else if (id[3].indexOf('vimeo') > -1) { 12190 type = 'vimeo'; 12191 } else { 12192 throw new Error('Video URL not supported.'); 12193 } 12194 id = id[6]; 12195 } else { 12196 throw new Error('Missing video URL.'); 12197 } 12198 12199 this._videos[url] = { 12200 type: type, 12201 id: id, 12202 width: width, 12203 height: height 12204 }; 12205 12206 item.attr('data-video', url); 12207 12208 this.thumbnail(target, this._videos[url]); 12209 }; 12210 12211 /** 12212 * Creates video thumbnail. 12213 * @protected 12214 * @param {jQuery} target - The target containing the video data. 12215 * @param {Object} info - The video info object. 12216 * @see `fetch` 12217 */ 12218 Video.prototype.thumbnail = function(target, video) { 12219 var tnLink, 12220 icon, 12221 path, 12222 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 12223 customTn = target.find('img'), 12224 srcType = 'src', 12225 lazyClass = '', 12226 settings = this._core.settings, 12227 create = function(path) { 12228 icon = '<div class="owl-video-play-icon"></div>'; 12229 12230 if (settings.lazyLoad) { 12231 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 12232 } else { 12233 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 12234 } 12235 target.after(tnLink); 12236 target.after(icon); 12237 }; 12238 12239 // wrap video content into owl-video-wrapper div 12240 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 12241 12242 if (this._core.settings.lazyLoad) { 12243 srcType = 'data-src'; 12244 lazyClass = 'owl-lazy'; 12245 } 12246 12247 // custom thumbnail 12248 if (customTn.length) { 12249 create(customTn.attr(srcType)); 12250 customTn.remove(); 12251 return false; 12252 } 12253 12254 if (video.type === 'youtube') { 12255 path = "http://img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 12256 create(path); 12257 } else if (video.type === 'vimeo') { 12258 $.ajax({ 12259 type: 'GET', 12260 url: 'http://vimeo.com/api/v2/video/' + video.id + '.json', 12261 jsonp: 'callback', 12262 dataType: 'jsonp', 12263 success: function(data) { 12264 path = data[0].thumbnail_large; 12265 create(path); 12266 } 12267 }); 12268 } 12269 }; 12270 12271 /** 12272 * Stops the current video. 12273 * @public 12274 */ 12275 Video.prototype.stop = function() { 12276 this._core.trigger('stop', null, 'video'); 12277 this._playing.find('.owl-video-frame').remove(); 12278 this._playing.removeClass('owl-video-playing'); 12279 this._playing = null; 12280 this._core.leave('playing'); 12281 this._core.trigger('stopped', null, 'video'); 12282 }; 12283 12284 /** 12285 * Starts the current video. 12286 * @public 12287 * @param {Event} event - The event arguments. 12288 */ 12289 Video.prototype.play = function(event) { 12290 var target = $(event.target), 12291 item = target.closest('.' + this._core.settings.itemClass), 12292 video = this._videos[item.attr('data-video')], 12293 width = video.width || '100%', 12294 height = video.height || this._core.$stage.height(), 12295 html; 12296 12297 if (this._playing) { 12298 return; 12299 } 12300 12301 this._core.enter('playing'); 12302 this._core.trigger('play', null, 'video'); 12303 12304 item = this._core.items(this._core.relative(item.index())); 12305 12306 this._core.reset(item.index()); 12307 12308 if (video.type === 'youtube') { 12309 html = '<iframe width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/' + 12310 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 12311 } else if (video.type === 'vimeo') { 12312 html = '<iframe src="http://player.vimeo.com/video/' + video.id + 12313 '?autoplay=1" width="' + width + '" height="' + height + 12314 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 12315 } 12316 12317 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 12318 12319 this._playing = item.addClass('owl-video-playing'); 12320 }; 12321 12322 /** 12323 * Checks whether an video is currently in full screen mode or not. 12324 * @todo Bad style because looks like a readonly method but changes members. 12325 * @protected 12326 * @returns {Boolean} 12327 */ 12328 Video.prototype.isInFullScreen = function() { 12329 var element = document.fullscreenElement || document.mozFullScreenElement || 12330 document.webkitFullscreenElement; 12331 12332 return element && $(element).parent().hasClass('owl-video-frame'); 12333 }; 12334 12335 /** 12336 * Destroys the plugin. 12337 */ 12338 Video.prototype.destroy = function() { 12339 var handler, property; 12340 12341 this._core.$element.off('click.owl.video'); 12342 12343 for (handler in this._handlers) { 12344 this._core.$element.off(handler, this._handlers[handler]); 12345 } 12346 for (property in Object.getOwnPropertyNames(this)) { 12347 typeof this[property] != 'function' && (this[property] = null); 12348 } 12349 }; 12350 12351 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 12352 12353})(window.Zepto || window.jQuery, window, document); 12354 12355/** 12356 * Animate Plugin 12357 * @version 2.0.0-beta.3 12358 * @author Bartosz Wojciechowski 12359 * @license The MIT License (MIT) 12360 */ 12361;(function($, window, document, undefined) { 12362 12363 /** 12364 * Creates the animate plugin. 12365 * @class The Navigation Plugin 12366 * @param {Owl} scope - The Owl Carousel 12367 */ 12368 var Animate = function(scope) { 12369 this.core = scope; 12370 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 12371 this.swapping = true; 12372 this.previous = undefined; 12373 this.next = undefined; 12374 12375 this.handlers = { 12376 'change.owl.carousel': $.proxy(function(e) { 12377 if (e.namespace && e.property.name == 'position') { 12378 this.previous = this.core.current(); 12379 this.next = e.property.value; 12380 } 12381 }, this), 12382 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 12383 if (e.namespace) { 12384 this.swapping = e.type == 'translated'; 12385 } 12386 }, this), 12387 'translate.owl.carousel': $.proxy(function(e) { 12388 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 12389 this.swap(); 12390 } 12391 }, this) 12392 }; 12393 12394 this.core.$element.on(this.handlers); 12395 }; 12396 12397 /** 12398 * Default options. 12399 * @public 12400 */ 12401 Animate.Defaults = { 12402 animateOut: false, 12403 animateIn: false 12404 }; 12405 12406 /** 12407 * Toggles the animation classes whenever an translations starts. 12408 * @protected 12409 * @returns {Boolean|undefined} 12410 */ 12411 Animate.prototype.swap = function() { 12412 12413 if (this.core.settings.items !== 1) { 12414 return; 12415 } 12416 12417 if (!$.support.animation || !$.support.transition) { 12418 return; 12419 } 12420 12421 this.core.speed(0); 12422 12423 var left, 12424 clear = $.proxy(this.clear, this), 12425 previous = this.core.$stage.children().eq(this.previous), 12426 next = this.core.$stage.children().eq(this.next), 12427 incoming = this.core.settings.animateIn, 12428 outgoing = this.core.settings.animateOut; 12429 12430 if (this.core.current() === this.previous) { 12431 return; 12432 } 12433 12434 if (outgoing) { 12435 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 12436 previous.css( { 'left': left + 'px' } ) 12437 .addClass('animated owl-animated-out') 12438 .addClass(outgoing) 12439 .on($.support.animation.end, clear); 12440 } 12441 12442 if (incoming) { 12443 next.addClass('animated owl-animated-in') 12444 .addClass(incoming) 12445 .on($.support.animation.end, clear); 12446 } 12447 }; 12448 12449 Animate.prototype.clear = function(e) { 12450 if ($(e.target).hasClass('animated')) { 12451 $(e.target).css( { 'left': '' } ) 12452 .removeClass('animated owl-animated-out owl-animated-in') 12453 .removeClass(this.core.settings.animateIn) 12454 .removeClass(this.core.settings.animateOut); 12455 this.core.onTransitionEnd(); 12456 } 12457 }; 12458 12459 /** 12460 * Destroys the plugin. 12461 * @public 12462 */ 12463 Animate.prototype.destroy = function() { 12464 var handler, property; 12465 12466 for (handler in this.handlers) { 12467 this.core.$element.off(handler, this.handlers[handler]); 12468 } 12469 for (property in Object.getOwnPropertyNames(this)) { 12470 typeof this[property] != 'function' && (this[property] = null); 12471 } 12472 }; 12473 12474 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 12475 12476})(window.Zepto || window.jQuery, window, document); 12477 12478/** 12479 * Autoplay Plugin 12480 * @version 2.0.0-beta.3 12481 * @author Bartosz Wojciechowski 12482 * @author Artus Kolanowski 12483 * @license The MIT License (MIT) 12484 */ 12485;(function($, window, document, undefined) { 12486 12487 /** 12488 * Creates the autoplay plugin. 12489 * @class The Autoplay Plugin 12490 * @param {Owl} scope - The Owl Carousel 12491 */ 12492 var Autoplay = function(carousel) { 12493 /** 12494 * Reference to the core. 12495 * @protected 12496 * @type {Owl} 12497 */ 12498 this._core = carousel; 12499 12500 /** 12501 * The autoplay interval. 12502 * @type {Number} 12503 */ 12504 this._interval = null; 12505 12506 /** 12507 * Indicates whenever the autoplay is paused. 12508 * @type {Boolean} 12509 */ 12510 this._paused = false; 12511 12512 /** 12513 * All event handlers. 12514 * @protected 12515 * @type {Object} 12516 */ 12517 this._handlers = { 12518 'changed.owl.carousel': $.proxy(function(e) { 12519 if (e.namespace && e.property.name === 'settings') { 12520 if (this._core.settings.autoplay) { 12521 this.play(); 12522 } else { 12523 this.stop(); 12524 } 12525 } 12526 }, this), 12527 'initialized.owl.carousel': $.proxy(function(e) { 12528 if (e.namespace && this._core.settings.autoplay) { 12529 this.play(); 12530 } 12531 }, this), 12532 'play.owl.autoplay': $.proxy(function(e, t, s) { 12533 if (e.namespace) { 12534 this.play(t, s); 12535 } 12536 }, this), 12537 'stop.owl.autoplay': $.proxy(function(e) { 12538 if (e.namespace) { 12539 this.stop(); 12540 } 12541 }, this), 12542 'mouseover.owl.autoplay': $.proxy(function() { 12543 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12544 this.pause(); 12545 } 12546 }, this), 12547 'mouseleave.owl.autoplay': $.proxy(function() { 12548 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12549 this.play(); 12550 } 12551 }, this) 12552 }; 12553 12554 // register event handlers 12555 this._core.$element.on(this._handlers); 12556 12557 // set default options 12558 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 12559 }; 12560 12561 /** 12562 * Default options. 12563 * @public 12564 */ 12565 Autoplay.Defaults = { 12566 autoplay: false, 12567 autoplayTimeout: 5000, 12568 autoplayHoverPause: false, 12569 autoplaySpeed: false 12570 }; 12571 12572 /** 12573 * Starts the autoplay. 12574 * @public 12575 * @param {Number} [timeout] - The interval before the next animation starts. 12576 * @param {Number} [speed] - The animation speed for the animations. 12577 */ 12578 Autoplay.prototype.play = function(timeout, speed) { 12579 this._paused = false; 12580 12581 if (this._core.is('rotating')) { 12582 return; 12583 } 12584 12585 this._core.enter('rotating'); 12586 12587 this._interval = window.setInterval($.proxy(function() { 12588 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 12589 return; 12590 } 12591 this._core.next(speed || this._core.settings.autoplaySpeed); 12592 }, this), timeout || this._core.settings.autoplayTimeout); 12593 }; 12594 12595 /** 12596 * Stops the autoplay. 12597 * @public 12598 */ 12599 Autoplay.prototype.stop = function() { 12600 if (!this._core.is('rotating')) { 12601 return; 12602 } 12603 12604 window.clearInterval(this._interval); 12605 this._core.leave('rotating'); 12606 }; 12607 12608 /** 12609 * Stops the autoplay. 12610 * @public 12611 */ 12612 Autoplay.prototype.pause = function() { 12613 if (!this._core.is('rotating')) { 12614 return; 12615 } 12616 12617 this._paused = true; 12618 }; 12619 12620 /** 12621 * Destroys the plugin. 12622 */ 12623 Autoplay.prototype.destroy = function() { 12624 var handler, property; 12625 12626 this.stop(); 12627 12628 for (handler in this._handlers) { 12629 this._core.$element.off(handler, this._handlers[handler]); 12630 } 12631 for (property in Object.getOwnPropertyNames(this)) { 12632 typeof this[property] != 'function' && (this[property] = null); 12633 } 12634 }; 12635 12636 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 12637 12638})(window.Zepto || window.jQuery, window, document); 12639 12640/** 12641 * Navigation Plugin 12642 * @version 2.0.0-beta.3 12643 * @author Artus Kolanowski 12644 * @license The MIT License (MIT) 12645 */ 12646;(function($, window, document, undefined) { 12647 'use strict'; 12648 12649 /** 12650 * Creates the navigation plugin. 12651 * @class The Navigation Plugin 12652 * @param {Owl} carousel - The Owl Carousel. 12653 */ 12654 var Navigation = function(carousel) { 12655 /** 12656 * Reference to the core. 12657 * @protected 12658 * @type {Owl} 12659 */ 12660 this._core = carousel; 12661 12662 /** 12663 * Indicates whether the plugin is initialized or not. 12664 * @protected 12665 * @type {Boolean} 12666 */ 12667 this._initialized = false; 12668 12669 /** 12670 * The current paging indexes. 12671 * @protected 12672 * @type {Array} 12673 */ 12674 this._pages = []; 12675 12676 /** 12677 * All DOM elements of the user interface. 12678 * @protected 12679 * @type {Object} 12680 */ 12681 this._controls = {}; 12682 12683 /** 12684 * Markup for an indicator. 12685 * @protected 12686 * @type {Array.<String>} 12687 */ 12688 this._templates = []; 12689 12690 /** 12691 * The carousel element. 12692 * @type {jQuery} 12693 */ 12694 this.$element = this._core.$element; 12695 12696 /** 12697 * Overridden methods of the carousel. 12698 * @protected 12699 * @type {Object} 12700 */ 12701 this._overrides = { 12702 next: this._core.next, 12703 prev: this._core.prev, 12704 to: this._core.to 12705 }; 12706 12707 /** 12708 * All event handlers. 12709 * @protected 12710 * @type {Object} 12711 */ 12712 this._handlers = { 12713 'prepared.owl.carousel': $.proxy(function(e) { 12714 if (e.namespace && this._core.settings.dotsData) { 12715 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 12716 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 12717 } 12718 }, this), 12719 'added.owl.carousel': $.proxy(function(e) { 12720 if (e.namespace && this._core.settings.dotsData) { 12721 this._templates.splice(e.position, 0, this._templates.pop()); 12722 } 12723 }, this), 12724 'remove.owl.carousel': $.proxy(function(e) { 12725 if (e.namespace && this._core.settings.dotsData) { 12726 this._templates.splice(e.position, 1); 12727 } 12728 }, this), 12729 'changed.owl.carousel': $.proxy(function(e) { 12730 if (e.namespace && e.property.name == 'position') { 12731 this.draw(); 12732 } 12733 }, this), 12734 'initialized.owl.carousel': $.proxy(function(e) { 12735 if (e.namespace && !this._initialized) { 12736 this._core.trigger('initialize', null, 'navigation'); 12737 this.initialize(); 12738 this.update(); 12739 this.draw(); 12740 this._initialized = true; 12741 this._core.trigger('initialized', null, 'navigation'); 12742 } 12743 }, this), 12744 'refreshed.owl.carousel': $.proxy(function(e) { 12745 if (e.namespace && this._initialized) { 12746 this._core.trigger('refresh', null, 'navigation'); 12747 this.update(); 12748 this.draw(); 12749 this._core.trigger('refreshed', null, 'navigation'); 12750 } 12751 }, this) 12752 }; 12753 12754 // set default options 12755 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 12756 12757 // register event handlers 12758 this.$element.on(this._handlers); 12759 }; 12760 12761 /** 12762 * Default options. 12763 * @public 12764 * @todo Rename `slideBy` to `navBy` 12765 */ 12766 Navigation.Defaults = { 12767 nav: false, 12768 navText: [ 'prev', 'next' ], 12769 navSpeed: false, 12770 navElement: 'div', 12771 navContainer: false, 12772 navContainerClass: 'owl-nav', 12773 navClass: [ 'owl-prev', 'owl-next' ], 12774 slideBy: 1, 12775 dotClass: 'owl-dot', 12776 dotsClass: 'owl-dots', 12777 dots: true, 12778 dotsEach: false, 12779 dotsData: false, 12780 dotsSpeed: false, 12781 dotsContainer: false 12782 }; 12783 12784 /** 12785 * Initializes the layout of the plugin and extends the carousel. 12786 * @protected 12787 */ 12788 Navigation.prototype.initialize = function() { 12789 var override, 12790 settings = this._core.settings; 12791 12792 // create DOM structure for relative navigation 12793 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 12794 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 12795 12796 this._controls.$previous = $('<' + settings.navElement + '>') 12797 .addClass(settings.navClass[0]) 12798 .html(settings.navText[0]) 12799 .prependTo(this._controls.$relative) 12800 .on('click', $.proxy(function(e) { 12801 this.prev(settings.navSpeed); 12802 }, this)); 12803 this._controls.$next = $('<' + settings.navElement + '>') 12804 .addClass(settings.navClass[1]) 12805 .html(settings.navText[1]) 12806 .appendTo(this._controls.$relative) 12807 .on('click', $.proxy(function(e) { 12808 this.next(settings.navSpeed); 12809 }, this)); 12810 12811 // create DOM structure for absolute navigation 12812 if (!settings.dotsData) { 12813 this._templates = [ $('<div>') 12814 .addClass(settings.dotClass) 12815 .append($('<span>')) 12816 .prop('outerHTML') ]; 12817 } 12818 12819 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 12820 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 12821 12822 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 12823 var index = $(e.target).parent().is(this._controls.$absolute) 12824 ? $(e.target).index() : $(e.target).parent().index(); 12825 12826 e.preventDefault(); 12827 12828 this.to(index, settings.dotsSpeed); 12829 }, this)); 12830 12831 // override public methods of the carousel 12832 for (override in this._overrides) { 12833 this._core[override] = $.proxy(this[override], this); 12834 } 12835 }; 12836 12837 /** 12838 * Destroys the plugin. 12839 * @protected 12840 */ 12841 Navigation.prototype.destroy = function() { 12842 var handler, control, property, override; 12843 12844 for (handler in this._handlers) { 12845 this.$element.off(handler, this._handlers[handler]); 12846 } 12847 for (control in this._controls) { 12848 this._controls[control].remove(); 12849 } 12850 for (override in this.overides) { 12851 this._core[override] = this._overrides[override]; 12852 } 12853 for (property in Object.getOwnPropertyNames(this)) { 12854 typeof this[property] != 'function' && (this[property] = null); 12855 } 12856 }; 12857 12858 /** 12859 * Updates the internal state. 12860 * @protected 12861 */ 12862 Navigation.prototype.update = function() { 12863 var i, j, k, 12864 lower = this._core.clones().length / 2, 12865 upper = lower + this._core.items().length, 12866 maximum = this._core.maximum(true), 12867 settings = this._core.settings, 12868 size = settings.center || settings.autoWidth || settings.dotsData 12869 ? 1 : settings.dotsEach || settings.items; 12870 12871 if (settings.slideBy !== 'page') { 12872 settings.slideBy = Math.min(settings.slideBy, settings.items); 12873 } 12874 12875 if (settings.dots || settings.slideBy == 'page') { 12876 this._pages = []; 12877 12878 for (i = lower, j = 0, k = 0; i < upper; i++) { 12879 if (j >= size || j === 0) { 12880 this._pages.push({ 12881 start: Math.min(maximum, i - lower), 12882 end: i - lower + size - 1 12883 }); 12884 if (Math.min(maximum, i - lower) === maximum) { 12885 break; 12886 } 12887 j = 0, ++k; 12888 } 12889 j += this._core.mergers(this._core.relative(i)); 12890 } 12891 } 12892 }; 12893 12894 /** 12895 * Draws the user interface. 12896 * @todo The option `dotsData` wont work. 12897 * @protected 12898 */ 12899 Navigation.prototype.draw = function() { 12900 var difference, 12901 settings = this._core.settings, 12902 disabled = this._core.items().length <= settings.items, 12903 index = this._core.relative(this._core.current()), 12904 loop = settings.loop || settings.rewind; 12905 12906 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 12907 12908 if (settings.nav) { 12909 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 12910 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 12911 } 12912 12913 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 12914 12915 if (settings.dots) { 12916 difference = this._pages.length - this._controls.$absolute.children().length; 12917 12918 if (settings.dotsData && difference !== 0) { 12919 this._controls.$absolute.html(this._templates.join('')); 12920 } else if (difference > 0) { 12921 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 12922 } else if (difference < 0) { 12923 this._controls.$absolute.children().slice(difference).remove(); 12924 } 12925 12926 this._controls.$absolute.find('.active').removeClass('active'); 12927 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 12928 } 12929 }; 12930 12931 /** 12932 * Extends event data. 12933 * @protected 12934 * @param {Event} event - The event object which gets thrown. 12935 */ 12936 Navigation.prototype.onTrigger = function(event) { 12937 var settings = this._core.settings; 12938 12939 event.page = { 12940 index: $.inArray(this.current(), this._pages), 12941 count: this._pages.length, 12942 size: settings && (settings.center || settings.autoWidth || settings.dotsData 12943 ? 1 : settings.dotsEach || settings.items) 12944 }; 12945 }; 12946 12947 /** 12948 * Gets the current page position of the carousel. 12949 * @protected 12950 * @returns {Number} 12951 */ 12952 Navigation.prototype.current = function() { 12953 var current = this._core.relative(this._core.current()); 12954 return $.grep(this._pages, $.proxy(function(page, index) { 12955 return page.start <= current && page.end >= current; 12956 }, this)).pop(); 12957 }; 12958 12959 /** 12960 * Gets the current succesor/predecessor position. 12961 * @protected 12962 * @returns {Number} 12963 */ 12964 Navigation.prototype.getPosition = function(successor) { 12965 var position, length, 12966 settings = this._core.settings; 12967 12968 if (settings.slideBy == 'page') { 12969 position = $.inArray(this.current(), this._pages); 12970 length = this._pages.length; 12971 successor ? ++position : --position;
vendor: 5,670 bytes, lines 12972-13196
12972 position = this._pages[((position % length) + length) % length].start; 12973 } else { 12974 position = this._core.relative(this._core.current()); 12975 length = this._core.items().length; 12976 successor ? position += settings.slideBy : position -= settings.slideBy; 12977 } 12978 12979 return position; 12980 }; 12981 12982 /** 12983 * Slides to the next item or page. 12984 * @public 12985 * @param {Number} [speed=false] - The time in milliseconds for the transition. 12986 */ 12987 Navigation.prototype.next = function(speed) { 12988 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 12989 }; 12990 12991 /** 12992 * Slides to the previous item or page. 12993 * @public 12994 * @param {Number} [speed=false] - The time in milliseconds for the transition. 12995 */ 12996 Navigation.prototype.prev = function(speed) { 12997 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 12998 }; 12999 13000 /** 13001 * Slides to the specified item or page. 13002 * @public 13003 * @param {Number} position - The position of the item or page. 13004 * @param {Number} [speed] - The time in milliseconds for the transition. 13005 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 13006 */ 13007 Navigation.prototype.to = function(position, speed, standard) { 13008 var length; 13009 13010 if (!standard) { 13011 length = this._pages.length; 13012 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 13013 } else { 13014 $.proxy(this._overrides.to, this._core)(position, speed); 13015 } 13016 }; 13017 13018 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 13019 13020})(window.Zepto || window.jQuery, window, document); 13021 13022/** 13023 * Hash Plugin 13024 * @version 2.0.0-beta.3 13025 * @author Artus Kolanowski 13026 * @license The MIT License (MIT) 13027 */ 13028;(function($, window, document, undefined) { 13029 'use strict'; 13030 13031 /** 13032 * Creates the hash plugin. 13033 * @class The Hash Plugin 13034 * @param {Owl} carousel - The Owl Carousel 13035 */ 13036 var Hash = function(carousel) { 13037 /** 13038 * Reference to the core. 13039 * @protected 13040 * @type {Owl} 13041 */ 13042 this._core = carousel; 13043 13044 /** 13045 * Hash index for the items. 13046 * @protected 13047 * @type {Object} 13048 */ 13049 this._hashes = {}; 13050 13051 /** 13052 * The carousel element. 13053 * @type {jQuery} 13054 */ 13055 this.$element = this._core.$element; 13056 13057 /** 13058 * All event handlers. 13059 * @protected 13060 * @type {Object} 13061 */ 13062 this._handlers = { 13063 'initialized.owl.carousel': $.proxy(function(e) { 13064 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 13065 $(window).trigger('hashchange.owl.navigation'); 13066 } 13067 }, this), 13068 'prepared.owl.carousel': $.proxy(function(e) { 13069 if (e.namespace) { 13070 var hash = $(e.content).find('[data-hash]').andSelf('[data-hash]').attr('data-hash'); 13071 13072 if (!hash) { 13073 return; 13074 } 13075 13076 this._hashes[hash] = e.content; 13077 } 13078 }, this), 13079 'changed.owl.carousel': $.proxy(function(e) { 13080 if (e.namespace && e.property.name === 'position') { 13081 var current = this._core.items(this._core.relative(this._core.current())), 13082 hash = $.map(this._hashes, function(item, hash) { 13083 return item === current ? hash : null; 13084 }).join(); 13085 13086 if (!hash || window.location.hash.slice(1) === hash) { 13087 return; 13088 } 13089 13090 window.location.hash = hash; 13091 } 13092 }, this) 13093 }; 13094 13095 // set default options 13096 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 13097 13098 // register the event handlers 13099 this.$element.on(this._handlers); 13100 13101 // register event listener for hash navigation 13102 $(window).on('hashchange.owl.navigation', $.proxy(function(e) { 13103 var hash = window.location.hash.substring(1), 13104 items = this._core.$stage.children(), 13105 position = this._hashes[hash] && items.index(this._hashes[hash]); 13106 13107 if (position === undefined || position === this._core.current()) { 13108 return; 13109 } 13110 13111 this._core.to(this._core.relative(position), false, true); 13112 }, this)); 13113 }; 13114 13115 /** 13116 * Default options. 13117 * @public 13118 */ 13119 Hash.Defaults = { 13120 URLhashListener: false 13121 }; 13122 13123 /** 13124 * Destroys the plugin. 13125 * @public 13126 */ 13127 Hash.prototype.destroy = function() { 13128 var handler, property; 13129 13130 $(window).off('hashchange.owl.navigation'); 13131 13132 for (handler in this._handlers) { 13133 this._core.$element.off(handler, this._handlers[handler]); 13134 } 13135 for (property in Object.getOwnPropertyNames(this)) { 13136 typeof this[property] != 'function' && (this[property] = null); 13137 } 13138 }; 13139 13140 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 13141 13142})(window.Zepto || window.jQuery, window, document); 13143 13144/** 13145 * Support Plugin 13146 * 13147 * @version 2.0.0-beta.3 13148 * @author Vivid Planet Software GmbH 13149 * @author Artus Kolanowski 13150 * @license The MIT License (MIT) 13151 */ 13152;(function($, window, document, undefined) { 13153 13154 var style = $('<support>').get(0).style, 13155 prefixes = 'Webkit Moz O ms'.split(' '), 13156 events = { 13157 transition: { 13158 end: { 13159 WebkitTransition: 'webkitTransitionEnd', 13160 MozTransition: 'transitionend', 13161 OTransition: 'oTransitionEnd', 13162 transition: 'transitionend' 13163 } 13164 }, 13165 animation: { 13166 end: { 13167 WebkitAnimation: 'webkitAnimationEnd', 13168 MozAnimation: 'animationend', 13169 OAnimation: 'oAnimationEnd', 13170 animation: 'animationend' 13171 } 13172 } 13173 }, 13174 tests = { 13175 csstransforms: function() { 13176 return !!test('transform'); 13177 }, 13178 csstransforms3d: function() { 13179 return !!test('perspective'); 13180 }, 13181 csstransitions: function() { 13182 return !!test('transition'); 13183 }, 13184 cssanimations: function() { 13185 return !!test('animation'); 13186 } 13187 }; 13188 13189 function test(property, prefixed) { 13190 var result = false, 13191 upper = property.charAt(0).toUpperCase() + property.slice(1); 13192 13193 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 13194 if (style[property] !== undefined) { 13195 result = prefixed ? property : true; 13196 return false;
13197 } 13198 }); 13199 13200 return result; 13201 } 13202 13203 function prefixed(property) { 13204 return test(property, true); 13205 } 13206 13207 if (tests.csstransitions()) { 13208 /* jshint -W053 */ 13209 $.support.transition = new String(prefixed('transition')) 13210 $.support.transition.end = events.transition.end[ $.support.transition ]; 13211 } 13212 13213 if (tests.cssanimations()) { 13214 /* jshint -W053 */ 13215 $.support.animation = new String(prefixed('animation')) 13216 $.support.animation.end = events.animation.end[ $.support.animation ]; 13217 } 13218 13219 if (tests.csstransforms()) { 13220 /* jshint -W053 */ 13221 $.support.transform = new String(prefixed('transform')); 13222 $.support.transform3d = tests.csstransforms3d(); 13223 } 13224 13225})(window.Zepto || window.jQuery, window, document); 13226 13227(function(window, document, undefined) { 13228 13229 /** 13230 * Find the absolute position of an element 13231 */ 13232 var absPos = function(element) { 13233 var offsetLeft, offsetTop; 13234 offsetLeft = offsetTop = 0; 13235 if (element.offsetParent) { 13236 do { 13237 offsetLeft += element.offsetLeft; 13238 offsetTop += element.offsetTop; 13239 } while (element = element.offsetParent); 13240 } 13241 return [offsetLeft, offsetTop]; 13242 }; 13243 13244 /** 13245 * @constructor Progress Circle class 13246 * @param params.canvas Canvas on which the circles will be drawn. 13247 * @param params.minRadius Inner radius of the innermost circle, in px. 13248 * @param params.arcWidth Width of each circle(to be more accurate, ring). 13249 * @param params.gapWidth Space between each circle. 13250 * @param params.centerX X coordinate of the center of circles. 13251 * @param params.centerY Y coordinate of the center of circles. 13252 * @param params.infoLineBaseAngle Base angle of the info line. 13253 * @param params.infoLineAngleInterval Angles between the info lines. 13254 */ 13255 var ProgressCircle = function(params) { 13256 this.canvas = params.canvas; 13257 this.minRadius = params.minRadius || 15; 13258 this.arcWidth = params.arcWidth || 5; 13259 this.gapWidth = params.gapWidth || 3; 13260 this.centerX = params.centerX || this.canvas.width / 2; 13261 this.centerY = params.centerY || this.canvas.height / 2;
13262 this.infoLineLength = params.infoLineLength || 60; 13263 this.horizLineLength = params.horizLineLength || 10; 13264 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 13265 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 13266 13267 this.context = this.canvas.getContext('2d'); 13268 13269 this.width = this.canvas.width; 13270 this.height = this.canvas.height; 13271 13272 this.circles = []; 13273 this.runningCount = 0; 13274 }; 13275 13276 ProgressCircle.prototype = { 13277 constructor: ProgressCircle, 13278 13279 /** 13280 * @method Adds an progress monitor entry. 13281 * @param params.fillColor Color to fill in the circle. 13282 * @param params.outlineColor Color to outline the circle. 13283 * @param params.progressListener Callback function to fetch the progress. 13284 * @param params.infoListener Callback function to fetch the info. 13285 * @returns this 13286 */ 13287 addEntry: function(params) { 13288 this.circles.push(new Circle({ 13289 canvas: this.canvas, 13290 context: this.context, 13291 centerX: this.centerX, 13292 centerY: this.centerY, 13293 innerRadius: this.minRadius + this.circles.length * 13294 (this.gapWidth + this.arcWidth), 13295 arcWidth: this.arcWidth,
13296 infoLineLength: this.infoLineLength, 13297 horizLineLength: this.horizLineLength, 13298 13299 id: this.circles.length, 13300 fillColor: params.fillColor, 13301 outlineColor: params.outlineColor, 13302 progressListener: params.progressListener, 13303 infoListener: params.infoListener, 13304 infoLineAngle: this.infoLineBaseAngle + 13305 this.circles.length * this.infoLineAngleInterval, 13306 })); 13307 13308 return this; 13309 }, 13310 13311 /** 13312 * @method Starts the monitor and updates with the given interval. 13313 * @param interval Interval between updates, in millisecond. 13314 * @returns this 13315 */ 13316 start: function(interval) { 13317 var self = this; 13318 this.timer = setInterval(function() { 13319 self._update(); 13320 }, interval || 33); 13321 13322 return this; 13323 }, 13324 13325 /** 13326 * @method Stop the animation. 13327 */ 13328 stop: function() { 13329 clearTimeout(this.timer); 13330 }, 13331 13332 /** 13333 * @private 13334 * @method Call update on each circle and redraw them. 13335 * @returns this 13336 */ 13337 _update: function() { 13338 this._clear(); 13339 this.circles.forEach(function(circle, idx, array) { 13340 circle.update(); 13341 }); 13342 13343 return this; 13344 }, 13345 13346 /** 13347 * @private 13348 * @method Clear the canvas. 13349 * @returns this 13350 */ 13351 _clear: function() { 13352 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 13353 13354 return this; 13355 }, 13356 13357 }; 13358 13359 /** 13360 * @private 13361 * @class Individual progress circle. 13362 * @param params.canvas Canvas on which the circle will be drawn. 13363 * @param params.context Context of the canvas. 13364 * @param params.innerRadius Inner radius of the circle, in px. 13365 * @param params.arcWidth Width of each arc(circle). 13366 * @param params.gapWidth Distance between each arc. 13367 * @param params.centerX X coordinate of the center of circles. 13368 * @param params.centerY Y coordinate of the center of circles. 13369 * @param params.fillColor Color to fill in the circle. 13370 * @param params.outlineColor Color to outline the circle. 13371 * @param params.progressListener Callback function to fetch the progress. 13372 * @param params.infoListener Callback function to fetch the info. 13373 * @param params.infoLineAngle Angle of info line. 13374 */ 13375 var Circle = function(params) { 13376 this.id = params.id; 13377 this.canvas = params.canvas; 13378 this.context = params.context; 13379 this.centerX = params.centerX; 13380 this.centerY = params.centerY; 13381 this.arcWidth = params.arcWidth; 13382 this.innerRadius = params.innerRadius || 0; 13383 this.fillColor = params.fillColor || '#fff'; 13384 this.outlineColor = params.outlineColor || this.fillColor; 13385 this.progressListener = params.progressListener;
13386 this.infoLineLength = params.infoLineLength || 250; 13387 this.horizLineLength = params.horizLineLength || 50; 13388 this.infoListener = params.infoListener; 13389 this.infoLineAngle = params.infoLineAngle; 13390 13391 this.outerRadius = this.innerRadius + this.arcWidth; 13392 13393 // If the info listener is not registered, then don't calculate 13394 // the related coordinates 13395 if (!this.infoListener) return; 13396 13397 // calculate the info-line turning points 13398 var angle = this.infoLineAngle, 13399 arcDistance = (this.innerRadius + this.outerRadius) / 2, 13400 13401 sinA = Math.sin(angle), 13402 cosA = Math.cos(angle); 13403 13404 this.infoLineStartX = this.centerX + sinA * arcDistance; 13405 this.infoLineStartY = this.centerY - cosA * arcDistance; 13406 13407 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 13408 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 13409 13410 this.infoLineEndX = this.infoLineMidX + 13411 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 13412 this.infoLineEndY = this.infoLineMidY; 13413 13414 var infoText = document.createElement('div'), 13415 style = infoText.style; 13416 13417 style.color = this.fillColor; 13418 style.position = 'absolute'; 13419 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 13420 // style.top will be calculated in the `drawInfo` method. Since 13421 // user may want to change the size of the font, so the top offset 13422 // must be updated in each loop. 13423 infoText.className = 'ProgressCircleInfo'; // For css styling 13424 infoText.id = 'progress_circle_info_' + this.id; 13425 document.body.appendChild(infoText); 13426 this.infoText = infoText; 13427 }; 13428 13429 Circle.prototype = { 13430 constructor: Circle, 13431 13432 update: function() { 13433 this.progress = this.progressListener(); 13434 this._draw(); 13435 13436 if (this.infoListener) { 13437 this.info = this.infoListener(); 13438 this._drawInfo(); 13439 } 13440 }, 13441 13442 /** 13443 * @private 13444 * @method Draw the circle on the canvas. 13445 * @returns this 13446 */ 13447 _draw: function() { 13448 var ctx = this.context, 13449 13450 ANGLE_OFFSET = -Math.PI / 2, 13451 13452 startAngle = 0 + ANGLE_OFFSET, 13453 endAngle= startAngle + this.progress * Math.PI * 2, 13454 13455 x = this.centerX, 13456 y = this.centerY, 13457 13458 innerRadius = this.innerRadius - this.arcWidth - 1, 13459 outerRadius = this.outerRadius - this.arcWidth - 1; 13460 13461 ctx.fillStyle = this.fillColor; 13462 ctx.strokeStyle = this.outlineColor; 13463 13464 ctx.beginPath(); 13465 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 13466 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 13467 ctx.closePath(); 13468 ctx.stroke(); 13469 ctx.fill(); 13470 13471 return this; 13472 }, 13473 13474 /** 13475 * @private 13476 * @method Draw the info lines and info text. 13477 * @returns this 13478 */ 13479 _drawInfo: function() { 13480 13481 var pointList, lineHeight; 13482 13483 pointList = [ 13484 [this.infoLineStartX, this.infoLineStartY], 13485 [this.infoLineMidX, this.infoLineMidY], 13486 [this.infoLineEndX, this.infoLineEndY], 13487 ]; 13488 this._drawSegments(pointList, false); 13489 13490 this.infoText.innerHTML = this.info; 13491 13492 lineHeight = this.infoText.offsetHeight; 13493 this.infoText.style.top = this.infoLineEndY + 13494 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 13495 13496 return this; 13497 }, 13498 13499 /** 13500 * @private 13501 * @method Helper function to draw the segments 13502 * @param pointList An array of points in the form of [x, y]. 13503 * @param close Whether to connect the first and last point. 13504 */ 13505 _drawSegments: function(pointList, close) { 13506 var ctx = this.context; 13507 13508 ctx.beginPath(); 13509 ctx.moveTo(pointList[0][0], pointList[0][1]); 13510 for (var i = 1; i < pointList.length; ++i) { 13511 ctx.lineTo(pointList[i][0], pointList[i][1]); 13512 } 13513 13514 if (close) { 13515 ctx.closePath(); 13516 } 13517 ctx.stroke(); 13518 }, 13519 }; 13520 13521 window.ProgressCircle = ProgressCircle; 13522 13523})(window, document); 13524 13525 13526 13527 13528/* ========================================================= 13529 * jquery.vc_chart.js v1.0 13530 * ========================================================= 13531 * Copyright 2013 Wpbakery 13532 * 13533 * Jquery chart plugin for the Visual Composer.
13534 * ========================================================= */ 13535(function($){ 13536 /** 13537 * Pie chart animated. 13538 * @param element - DOM element 13539 * @param options - settings object. 13540 * @constructor 13541 */ 13542 var VcChart = function(element, options) { 13543 this.el = element; 13544 this.$el = $(this.el); 13545 this.options = $.extend({ 13546 color: 'wpb_button', 13547 units: '', 13548 width: '', 13549 label_selector: '.vc_pie_chart_value', 13550 back_selector: '.vc_pie_chart_back', 13551 responsive: true 13552 }, options); 13553 this.init(); 13554 }; 13555 VcChart.prototype = { 13556 constructor: VcChart, 13557 _progress_v: 0, 13558 animated: false, 13559 colors: { 13560 'wpb_button': 'rgba(247, 247, 247, 1)', 13561 'btn-primary': 'rgba(0, 136, 204, 1)', 13562 'btn-info': 'rgba(88, 185, 218, 1)', 13563 'btn-success': 'rgba(106, 177, 101, 1)', 13564 'btn-warning': 'rgba(255, 153, 0, 1)', 13565 'btn-danger': 'rgba(255, 103, 91, 1)', 13566 'btn-inverse': 'rgba(85, 85, 85, 1)' 13567 }, 13568 init: function() { 13569 this.setupColor(); 13570 this.value = this.$el.data('pie-value')/100; 13571 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 13572 this.$wrapper = $('.vc_pie_wrapper', this.$el); 13573 this.$label = $(this.options.label_selector, this.$el); 13574 this.$back = $(this.options.back_selector, this.$el); 13575 this.$canvas = this.$el.find('canvas'); 13576 this.arcWidth = this.$el.data('pie-width') * 2; 13577 this.draw(); 13578 this.setWayPoint(); 13579 if(this.options.responsive === true) this.setResponsive(); 13580 if (UNCODE.isMobile) this._progress_v = this.value; 13581 }, 13582 setupColor: function() { 13583 // if(typeof this.colors[this.options.color] !== 'undefined') { 13584 // this.color = this.colors[this.options.color]; 13585 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 13586 // this.color = this.options.color; 13587 // } else { 13588 // this.color = 'rgba(247, 247, 247, 0.2)'; 13589 // } 13590 if(typeof this.options.color !== 'undefined') { 13591 this.color = this.options.color; 13592 } else this.color = 'rgba(247, 247, 247, 0.2)'; 13593 13594 }, 13595 setResponsive: function() { 13596 var that = this; 13597 if (!UNCODE.isMobile) { 13598 $(window).resize(function(){ 13599 if(that.animated === true) that.circle.stop(); 13600 that.draw(true); 13601 }); 13602 } 13603 }, 13604 draw: function(redraw) { 13605 var w = this.$el.addClass('vc_ready').width() * 2, 13606 border_w = this.arcWidth, 13607 radius; 13608 if(!w) w = this.$el.parents(':visible').first().width()-2; 13609 //w = Math.round(w/100*80); 13610 //if (w < 250) w = 250; 13611 radius = w/2; 13612 this.$wrapper.css({"width" : (w / 2) + "px"}); 13613 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 13614 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 13615 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 13616 this.$el.addClass('vc_ready'); 13617 this.circle = new ProgressCircle({ 13618 canvas: this.$canvas.get(0), 13619 minRadius: radius, 13620 arcWidth: border_w 13621 }); 13622 if(redraw === true && this.animated === true) { 13623 this._progress_v = this.value; 13624 this.circle.addEntry({ 13625 fillColor: this.color, 13626 progressListener: $.proxy(this.setProgress, this) 13627 }).start(); 13628 } 13629 }, 13630 setProgress: function() { 13631 if (this._progress_v >= this.value) { 13632 this.circle.stop(); 13633 this.$label.html(this.label_value + this.options.units); 13634 return this._progress_v; 13635 } 13636 this._progress_v += 0.01; 13637 if (!isNaN(this.label_value)) { 13638 var label_value = this._progress_v/this.value*this.label_value; 13639 var val = Math.round(label_value) + this.options.units; 13640 this.$label.html(val); 13641 } else this.$label.html(this.label_value + this.options.units); 13642 return this._progress_v; 13643 }, 13644 animate: function() { 13645 if(this.animated !== true) { 13646 this.animated = true; 13647 this.circle.addEntry({ 13648 fillColor: this.color, 13649 progressListener: $.proxy(this.setProgress, this) 13650 }).start(5); 13651 } 13652 }, 13653 setWayPoint: function() { 13654 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 13655 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 13656 } else { 13657 this.animate(); 13658 } 13659 } 13660 }; 13661 /** 13662 * jQuery plugin 13663 * @param option - object with settings 13664 * @return {*} 13665 */ 13666 $.fn.vcChat = function(option, value) { 13667 return this.each(function () { 13668 var $this = $(this), 13669 data = $this.data('vc_chart'), 13670 options = typeof option === 'object' ? option : { 13671 color: $this.data('pie-color'), 13672 units: $this.data('pie-units') 13673 }; 13674 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 13675 if (typeof option == 'string') data[option](value); 13676 }); 13677 }; 13678 /** 13679 * Allows users to rewrite function inside theme. 13680 */ 13681 if ( typeof window['vc_pieChart'] !== 'function' ) { 13682 window.vc_pieChart = function() { 13683 $('.vc_pie_chart:visible').vcChat(); 13684 } 13685 } 13686 $(document).ready(function(){ 13687 !window.vc_iframe && vc_pieChart(); 13688 }); 13689 13690})(window.jQuery); 13691 13692 13693/* Progress bar 13694 ---------------------------------------------------------- */ 13695function uncode_progress_bar() {    13696 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 13697 if (!UNCODE.isMobile) { 13698 new Waypoint({ 13699 element: val, 13700 handler: function() { 13701 var element = jQuery(this.element); 13702 element.find('.vc_single_bar').each(function(index) {          13703 var $this = jQuery(this), 13704             bar = $this.find('.vc_bar'), 13705             val = bar.data('percentage-value');          13706 setTimeout(function() {            13707 bar.css({ 13708 "width": val + '%' 13709 });          13710 }, index * 200);        13711 }); 13712 }, 13713 offset: '80%' 13714 }); 13715 } else { 13716 var element = jQuery(val); 13717 element.find('.vc_single_bar').each(function(index) {          13718 var $this = jQuery(this), 13719             bar = $this.find('.vc_bar'), 13720             val = bar.data('percentage-value');          13721 setTimeout(function() {            13722 bar.css({ 13723 "width": val + '%' 13724 });          13725 }, index * 200);        13726 }); 13727 } 13728 }); 13729}; 13730uncode_progress_bar(); 13731 13732/*! 13733 * jquery.counterup.js 1.0 13734 * 13735 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 13736 * Released under the GPL v2 License 13737 * 13738 * Date: Nov 26, 2013 13739 */ 13740(function($) { 13741 "use strict"; 13742 $.fn.counterUp = function(options) { 13743 // Defaults 13744 var settings = $.extend({ 13745 'time': 400, 13746 'delay': 10 13747 }, options); 13748 return this.each(function() { 13749 // Store the object 13750 var $this = $(this); 13751 var $settings = settings; 13752 var counterUpper = function() { 13753 var nums = []; 13754 var divisions = $settings.time / $settings.delay; 13755 var num = $this.text(); 13756 var isComma = /[0-9]+,[0-9]+/.test(num); 13757 num = num.replace(/,/g, ''); 13758 var isInt = /^[0-9]+$/.test(num); 13759 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 13760 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 13761 // Generate list of incremental numbers to display 13762 for (var i = divisions; i >= 1; i--) { 13763 // Preserve as int if input was int 13764 var newNum = parseInt(num / divisions * i); 13765 // Preserve float if input was float 13766 if (isFloat) { 13767 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 13768 } 13769 // Preserve commas if input had commas 13770 if (isComma) { 13771 while (/(\d+)(\d{3})/.test(newNum.toString())) { 13772 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 13773 } 13774 } 13775 nums.unshift(newNum); 13776 } 13777 nums.push(num); 13778 $this.data('counterup-nums', nums); 13779 $this.text('0'); 13780 // Updates the number until we're done 13781 var f = function() { 13782 if ($this.data('counterup-nums') != null) { 13783 $this.text($this.data('counterup-nums').shift()); 13784 if ($this.data('counterup-nums').length) { 13785 setTimeout($this.data('counterup-func'), $settings.delay); 13786 } else { 13787 delete $this.data('counterup-nums'); 13788 $this.data('counterup-nums', null); 13789 $this.data('counterup-func', null); 13790 } 13791 } 13792 }; 13793 $this.data('counterup-func', f); 13794 // Start the count up 13795 setTimeout($this.data('counterup-func'), $settings.delay); 13796 }; 13797 // Perform counts when the element gets into view 13798 if (!UNCODE.isMobile) { 13799 new Waypoint({ 13800 element: this, 13801 handler: function() { 13802 counterUpper(); 13803 this.destroy(); 13804 }, 13805 offset: '80%' 13806 }); 13807 } 13808 }); 13809 }; 13810})(jQuery); 13811 13812/*! 13813 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 13814 * Copyright (c) 2014 Edson Hilios 13815 * 13816 * Permission is hereby granted, free of charge, to any person obtaining a copy of 13817 * this software and associated documentation files (the "Software"), to deal in 13818 * the Software without restriction, including without limitation the rights to 13819 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13820 * the Software, and to permit persons to whom the Software is furnished to do so, 13821 * subject to the following conditions: 13822 * 13823 * The above copyright notice and this permission notice shall be included in all 13824 * copies or substantial portions of the Software. 13825 * 13826 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13827 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13828 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13829 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13830 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 13831 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13832 */ 13833!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){"use strict";function b(a){if(a instanceof Date)return a;
13833if(String(a).match(h))return String(a).match(/^[0-9]*$/)&&(a=Number(a)),String(a).match(/\-/)&&(a=String(a).replace(/\-/g,"/")),new Date(a);throw new Error("Couldn't cast `"+a+"` to a date object.")}function c(a){var b=a.toString().replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1");return new RegExp(b)}function d(a){return function(b){var d=b.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);if(d)for(var f=0,g=d.length;g>f;++f){var h=d[f].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/),j=c(h[0]),k=h[1]||"",l=h[3]||"",m=null;h=h[2],i.hasOwnProperty(h)&&(m=i[h],m=Number(a[m])),null!==m&&("!"===k&&(m=e(l,m)),""===k&&10>m&&(m="0"+m.toString()),b=b.replace(j,m.toString()))}return b=b.replace(/%%/,"%")}}function e(a,b){var c="s",d="";return a&&(a=a.replace(/(:|;|\s)/gi,"").split(/\,/),1===a.length?c=a[0]:(d=a[0],c=a[1])),1===Math.abs(b)?d:c}var f=100,g=[],h=[];h.push(/^[0-9]*$/.source),h.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),h.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),h=new RegExp(h.join("|"));var i={Y:"years",m:"months",w:"weeks",d:"days",D:"totalDays",H:"hours",M:"minutes",S:"seconds"},j=function(b,c,d){this.el=b,this.$el=a(b),this.interval=null,this.offset={},this.instanceNumber=g.length,g.push(this),this.$el.data("countdown-instance",this.instanceNumber),d&&(this.$el.on("update.countdown",d),this.$el.on("stoped.countdown",d),this.$el.on("finish.countdown",d)),this.setFinalDate(c),this.start()};a.extend(j.prototype,{start:function(){null!==this.interval&&clearInterval(this.interval);var a=this;this.update(),this.interval=setInterval(function(){a.update.call(a)},f)},stop:function(){clearInterval(this.interval),this.interval=null,this.dispatchEvent("stoped")},toggle:function(){this.interval?this.stop():this.start()},pause:function(){this.stop()},resume:function(){this.start()},remove:function(){this.stop.call(this),g[this.instanceNumber]=null,delete this.$el.data().countdownInstance},setFinalDate:function(a){this.finalDate=b(a)},update:function(){return 0===this.$el.closest("html").length?void this.remove():(this.totalSecsLeft=this.finalDate.getTime()-(new Date).getTime(),this.totalSecsLeft=Math.ceil(this.totalSecsLeft/1e3),this.totalSecsLeft=this.totalSecsLeft<0?0:this.totalSecsLeft,this.offset={seconds:this.totalSecsLeft%60,minutes:Math.floor(this.totalSecsLeft/60)%60,hours:Math.floor(this.totalSecsLeft/60/60)%24,days:Math.floor(this.totalSecsLeft/60/60/24)%7,totalDays:Math.floor(this.totalSecsLeft/60/60/24),weeks:Math.floor(this.totalSecsLeft/60/60/24/7),months:Math.floor(this.totalSecsLeft/60/60/24/30),years:Math.floor(this.totalSecsLeft/60/60/24/365)},void(0===this.totalSecsLeft?(this.stop(),this.dispatchEvent("finish")):this.dispatchEvent("update")))},dispatchEvent:function(b){var c=a.Event(b+".countdown");c.finalDate=this.finalDate,c.offset=a.extend({},this.offset),c.strftime=d(this.offset),this.$el.trigger(c)}}),a.fn.countdown=function(){var b=Array.prototype.slice.call(arguments,0);return this.each(function(){var c=a(this).data("countdown-instance");if(void 0!==c){var d=g[c],e=b[0];j.prototype.hasOwnProperty(e)?d[e].apply(d,b.slice(1)):null===String(e).match(/^[$A-Z_][0-9A-Z_$]*$/i)?(d.setFinalDate.call(d,e),d.start()):a.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi,e))}else new j(this,b[0],b[1])})}}); 13834 13835/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 13836* https://github.com/alexanderdickson/waitForImages 13837* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 13838;(function (factory) { 13839 if (typeof define === 'function' && define.amd) { 13840 // AMD. Register as an anonymous module. 13841 define(['jquery'], factory); 13842 } else if (typeof exports === 'object') { 13843 // CommonJS / nodejs module 13844 module.exports = factory(require('jquery')); 13845 } else { 13846 // Browser globals 13847 factory(jQuery); 13848 } 13849}(function ($) { 13850 // Namespace all events. 13851 var eventNamespace = 'waitForImages'; 13852 13853 // CSS properties which contain references to images. 13854 $.waitForImages = { 13855 hasImageProperties: [ 13856 'backgroundImage', 13857 'listStyleImage', 13858 'borderImage', 13859 'borderCornerImage', 13860 'cursor' 13861 ], 13862 hasImageAttributes: ['srcset'] 13863 }; 13864 13865 // Custom selector to find `img` elements that have a valid `src` 13866 // attribute and have not already loaded. 13867 $.expr[':'].uncached = function (obj) { 13868 // Ensure we are dealing with an `img` element with a valid 13869 // `src` attribute. 13870 if (!$(obj).is('img[src][src!=""]')) { 13871 return false;
13872 } 13873 13874 return !obj.complete; 13875 }; 13876 13877 $.fn.waitForImages = function () { 13878 13879 var allImgsLength = 0; 13880 var allImgsLoaded = 0; 13881 var deferred = $.Deferred(); 13882 13883 var finishedCallback; 13884 var eachCallback; 13885 var waitForAll; 13886 13887 // Handle options object (if passed). 13888 if ($.isPlainObject(arguments[0])) { 13889 13890 waitForAll = arguments[0].waitForAll; 13891 eachCallback = arguments[0].each; 13892 finishedCallback = arguments[0].finished; 13893 13894 } else { 13895 13896 // Handle if using deferred object and only one param was passed in. 13897 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 13898 waitForAll = arguments[0]; 13899 } else { 13900 finishedCallback = arguments[0]; 13901 eachCallback = arguments[1]; 13902 waitForAll = arguments[2]; 13903 } 13904 13905 } 13906 13907 // Handle missing callbacks. 13908 finishedCallback = finishedCallback || $.noop; 13909 eachCallback = eachCallback || $.noop; 13910 13911 // Convert waitForAll to Boolean 13912 waitForAll = !! waitForAll; 13913 13914 // Ensure callbacks are functions. 13915 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 13916 throw new TypeError('An invalid callback was supplied.'); 13917 } 13918 13919 this.each(function () { 13920 // Build a list of all imgs, dependent on what images will 13921 // be considered. 13922 var obj = $(this); 13923 var allImgs = []; 13924 // CSS properties which may contain an image. 13925 var hasImgProperties = $.waitForImages.hasImageProperties || []; 13926 // Element attributes which may contain an image. 13927 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 13928 // To match `url()` references. 13929 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 13930 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 13931 13932 if (waitForAll) { 13933 13934 // Get all elements (including the original), as any one of 13935 // them could have a background image. 13936 obj.find('*').addBack().each(function () { 13937 var element = $(this); 13938 13939 // If an `img` element, add it. But keep iterating in 13940 // case it has a background image too. 13941 if (element.is('img:uncached')) { 13942 allImgs.push({ 13943 src: element.attr('src'), 13944 element: element[0] 13945 }); 13946 } 13947 13948 $.each(hasImgProperties, function (i, property) { 13949 var propertyValue = element.css(property); 13950 var match; 13951 13952 // If it doesn't contain this property, skip. 13953 if (!propertyValue) { 13954 return true; 13955 } 13956 13957 // Get all url() of this element. 13958 while (match = matchUrl.exec(propertyValue)) { 13959 allImgs.push({ 13960 src: match[2], 13961 element: element[0] 13962 }); 13963 } 13964 }); 13965 13966 $.each(hasImageAttributes, function (i, attribute) { 13967 var attributeValue = element.attr(attribute); 13968 var attributeValues; 13969 13970 // If it doesn't contain this property, skip. 13971 if (!attributeValue) { 13972 return true; 13973 } 13974 13975 // Check for multiple comma separated images 13976 attributeValues = attributeValue.split(','); 13977 13978 $.each(attributeValues, function(i, value) { 13979 // Trim value and get string before first 13980 // whitespace (for use with srcset). 13981 value = $.trim(value).split(' ')[0]; 13982 allImgs.push({ 13983 src: value, 13984 element: element[0] 13985 }); 13986 }); 13987 }); 13988 }); 13989 } else { 13990 // For images only, the task is simpler. 13991 obj.find('img:uncached') 13992 .each(function () { 13993 allImgs.push({ 13994 src: this.src, 13995 element: this 13996 }); 13997 }); 13998 } 13999 14000 allImgsLength = allImgs.length; 14001 allImgsLoaded = 0; 14002 14003 // If no images found, don't bother. 14004 if (allImgsLength === 0) { 14005 finishedCallback.call(obj[0]); 14006 deferred.resolveWith(obj[0]); 14007 } 14008 14009 $.each(allImgs, function (i, img) { 14010 14011 var image = new Image(); 14012 var events = 14013 'load.' + eventNamespace + ' error.' + eventNamespace; 14014 14015 // Handle the image loading and error with the same callback. 14016 $(image).one(events, function me (event) { 14017 // If an error occurred with loading the image, set the 14018 // third argument accordingly. 14019 var eachArguments = [ 14020 allImgsLoaded, 14021 allImgsLength,
14022 event.type == 'load' 14023 ]; 14024 allImgsLoaded++; 14025 14026 eachCallback.apply(img.element, eachArguments); 14027 deferred.notifyWith(img.element, eachArguments); 14028 14029 // Unbind the event listeners. I use this in addition to 14030 // `one` as one of those events won't be called (either 14031 // 'load' or 'error' will be called). 14032 $(this).off(events, me); 14033 14034 if (allImgsLoaded == allImgsLength) { 14035 finishedCallback.call(obj[0]); 14036 deferred.resolveWith(obj[0]); 14037 return false; 14038 } 14039 14040 }); 14041 14042 image.src = img.src; 14043 }); 14044 }); 14045 14046 return deferred.promise(); 14047 14048 }; 14049})); 14050 14051/** 14052 * @preserve textfill 14053 * @name jquery.textfill.js 14054 * @author Russ Painter 14055 * @author Yu-Jie Lin 14056 * @author Alexandre Dantas 14057 * @version 0.6.0 14058 * @date 2014-08-19 14059 * @copyright (c) 2014 Alexandre Dantas 14060 * @copyright (c) 2012-2013 Yu-Jie Lin 14061 * @copyright (c) 2009 Russ Painter 14062 * @license MIT License 14063 * @homepage https://github.com/jquery-textfill/jquery-textfill 14064 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 14065 */ 14066; (function($) { 14067 14068 /** 14069 * Resizes an inner element's font so that the 14070 * inner element completely fills the outer element. 14071 * 14072 * @param {Object} options User options that take 14073 * higher precedence when 14074 * merging with the default ones. 14075 * 14076 * @return All outer elements processed 14077 */ 14078 $.fn.textfill = function(options) { 14079 14080 // ______ _______ _______ _______ _ _ _______ _______ 14081 // | \ |______ |______ |_____| | | | | |______ 14082 // |_____/ |______ | | | |_____| |_____ | ______| 14083 // 14084 // Merging user options with the default values 14085 14086 var defaults = { 14087 debug : false, 14088 maxFontPixels : 40, 14089 minFontPixels : 4, 14090 innerTag : 'span', 14091 widthOnly : false, 14092 success : null, // callback when a resizing is done 14093 callback : null, // callback when a resizing is done (deprecated, use success) 14094 fail : null, // callback when a resizing is failed 14095 complete : null, // callback when all is done 14096 explicitWidth : null, 14097 explicitHeight : null, 14098 changeLineHeight : false 14099 }; 14100 14101 var Opts = $.extend(defaults, options); 14102 14103 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 14104 // |______ | | | \ | | | | | | | \ | |______ 14105 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 14106 // 14107 // Predefining the awesomeness 14108 14109 // Output arguments to the Debug console 14110 // if "Debug Mode" is enabled 14111 function _debug() { 14112 if (!Opts.debug 14113 || typeof console == 'undefined' 14114 || typeof console.debug == 'undefined') { 14115 return; 14116 } 14117 console.debug.apply(console, arguments); 14118 } 14119 14120 // Output arguments to the Warning console 14121 function _warn() { 14122 if (typeof console == 'undefined' || 14123 typeof console.warn == 'undefined') { 14124 return; 14125 } 14126 console.warn.apply(console, arguments); 14127 } 14128 14129 // Outputs all information on the current sizing 14130 // of the font. 14131 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14132 14133 function _m(v1, v2) { 14134 14135 var marker = ' / '; 14136 14137 if (v1 > v2) 14138 marker = ' > '; 14139 14140 else if (v1 == v2) 14141 marker = ' = '; 14142 14143 return marker; 14144 } 14145 14146 _debug( 14147 '[TextFill] ' + prefix + ' { ' + 14148 'font-size: ' + ourText.css('font-size') + ',' +
14149 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 14150 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 14151 'minFontPixels: ' + minFontPixels + 'px, ' + 14152 'maxFontPixels: ' + maxFontPixels + 'px }' 14153 ); 14154 } 14155 14156 /** 14157 * Calculates which size the font can get resized, 14158 * according to constrains. 14159 * 14160 * @param {String} prefix Gets shown on the console before 14161 * all the arguments, if debug mode is on. 14162 * @param {Object} ourText The DOM element to resize, 14163 * that contains the text. 14164 * @param {function} func Function called on `ourText` that's 14165 * used to compare with `max`. 14166 * @param {number} max Maximum value, that gets compared with 14167 * `func` called on `ourText`. 14168 * @param {number} minFontPixels Minimum value the font can 14169 * get resized to (in pixels). 14170 * @param {number} maxFontPixels Maximum value the font can 14171 * get resized to (in pixels). 14172 * 14173 * @return Size (in pixels) that the font can be resized. 14174 */ 14175 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14176 14177 _debug_sizing( 14178 prefix, ourText, 14179 maxHeight, maxWidth, 14180 minFontPixels, maxFontPixels 14181 ); 14182 14183 // The kernel of the whole plugin, take most attention 14184 // on this part. 14185 // 14186 // This is a loop that keeps increasing the `font-size` 14187 // until it fits the parent element. 14188 // 14189 // - Start from the minimal allowed value (`minFontPixels`) 14190 // - Guesses an average font size (in pixels) for the font, 14191 // - Resizes the text and sees if its size is within the 14192 // boundaries (`minFontPixels` and `maxFontPixels`). 14193 // - If so, keep guessing until we break. 14194 // - If not, return the last calculated size. 14195 // 14196 // I understand this is not optimized and we should 14197 // consider implementing something akin to 14198 // Daniel Hoffmann's answer here: 14199 // 14200 // http://stackoverflow.com/a/17433451/1094964 14201 // 14202 14203 while (minFontPixels < (maxFontPixels - 1)) { 14204 14205 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 14206 ourText.css('font-size', fontSize); 14207 14208 if (func.call(ourText) <= max) { 14209 minFontPixels = fontSize; 14210 14211 if (func.call(ourText) == max) 14212 break; 14213 } 14214 else 14215 maxFontPixels = fontSize; 14216 14217 _debug_sizing( 14218 prefix, ourText, 14219 maxHeight, maxWidth, 14220 minFontPixels, maxFontPixels 14221 ); 14222 } 14223 14224 ourText.css('font-size', maxFontPixels); 14225 14226 if (func.call(ourText) <= max) { 14227 minFontPixels = maxFontPixels; 14228 14229 _debug_sizing( 14230 prefix + '* ', ourText, 14231 maxHeight, maxWidth, 14232 minFontPixels, maxFontPixels 14233 ); 14234 } 14235 return minFontPixels; 14236 } 14237 14238 // _______ _______ _______ ______ _______ 14239 // |______ | |_____| |_____/ | 14240 // ______| | | | | \_ | 14241 // 14242 // Let's get it started (yeah)! 14243 14244 _debug('[TextFill] Start Debug'); 14245 14246 this.each(function() { 14247 14248 // Contains the child element we will resize. 14249 // $(this) means the parent container 14250 var ourText = $(Opts.innerTag + ':visible:first', this); 14251 14252 // Will resize to this dimensions. 14253 // Use explicit dimensions when specified 14254 var maxHeight = Opts.explicitHeight || $(this).height(); 14255 var maxWidth = Opts.explicitWidth || $(this).width(); 14256 14257 var oldFontSize = ourText.css('font-size'); 14258 14259 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 14260 14261 _debug('[TextFill] Inner text: ' + ourText.text()); 14262 _debug('[TextFill] All options: ', Opts); 14263 _debug('[TextFill] Maximum sizes: { ' + 14264 'Height: ' + maxHeight + 'px, ' + 14265 'Width: ' + maxWidth + 'px' + ' }' 14266 ); 14267 14268 var minFontPixels = Opts.minFontPixels; 14269 14270 // Remember, if this `maxFontPixels` is negative, 14271 // the text will resize to as long as the container 14272 // can accomodate 14273 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 14274 maxHeight : 14275 Opts.maxFontPixels); 14276 14277 14278 // Let's start it all! 14279 14280 // 1. Calculate which `font-size` would 14281 // be best for the Height 14282 var fontSizeHeight = undefined; 14283 14284 if (! Opts.widthOnly) 14285 fontSizeHeight = _sizing( 14286 'Height', ourText, 14287 $.fn.height, maxHeight, 14288 maxHeight, maxWidth, 14289 minFontPixels, maxFontPixels 14290 ); 14291 14292 // 2. Calculate which `font-size` would 14293 // be best for the Width 14294 var fontSizeWidth = undefined; 14295 14296 fontSizeWidth = _sizing( 14297 'Width', ourText, 14298 $.fn.width, maxWidth, 14299 maxHeight, maxWidth, 14300 minFontPixels, maxFontPixels 14301 ); 14302 14303 // 3. Actually resize the text! 14304 14305 if (Opts.widthOnly) { 14306 ourText.css({ 14307 'font-size' : fontSizeWidth, 14308 'white-space': 'nowrap' 14309 }); 14310 14311 if (Opts.changeLineHeight) 14312 ourText.parent().css( 14313 'line-height', 14314 (lineHeight * fontSizeWidth + 'px') 14315 ); 14316 } 14317 else { 14318 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 14319 14320 ourText.css('font-size', fontSizeFinal); 14321 14322 if (Opts.changeLineHeight) 14323 ourText.parent().css( 14324 'line-height', 14325 (lineHeight * fontSizeFinal) + 'px' 14326 ); 14327 } 14328 14329 _debug( 14330 '[TextFill] Finished { ' + 14331 'Old font-size: ' + oldFontSize + ', ' + 14332 'New font-size: ' + ourText.css('font-size') + ' }' 14333 ); 14334 14335 // Oops, something wrong happened! 14336 // We weren't supposed to exceed the original size 14337 if ((ourText.width() > maxWidth) ||
14338 (ourText.height() > maxHeight && !Opts.widthOnly)) { 14339 14340 ourText.css('font-size', oldFontSize); 14341 14342 // Failure callback 14343 if (Opts.fail) 14344 Opts.fail(this); 14345 14346 _debug( 14347 '[TextFill] Failure { ' + 14348 'Current Width: ' + ourText.width() + ', ' + 14349 'Maximum Width: ' + maxWidth + ', ' + 14350 'Current Height: ' + ourText.height() + ', ' + 14351 'Maximum Height: ' + maxHeight + ' }' 14352 ); 14353 } 14354 else if (Opts.success) { 14355 Opts.success(this); 14356 } 14357 else if (Opts.callback) { 14358 _warn('callback is deprecated, use success, instead'); 14359 14360 // Success callback 14361 Opts.callback(this); 14362 } 14363 }); 14364 14365 // Complete callback 14366 if (Opts.complete) 14367 Opts.complete(this); 14368 14369 _debug('[TextFill] End Debug'); 14370 return this; 14371 }; 14372 14373})(window.jQuery); 14374 14375 14376!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Share=e()}}(function(){var define,module,exports; 14377function getStyles(config){ 14378 // return ""+config.selector+"{width:92px;height:20px;-webkit-touch-callout:none;-khtml-user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}"+config.selector+" [class*=social-]:before{font-family:'uncodeicon'}"+config.selector+" label{font-size:16px;cursor:pointer;margin:0;padding:5px 10px;border-radius:5px;background:#a29baa;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}"+config.selector+" label:hover{opacity:.8}"+config.selector+" label span{text-transform:uppercase;font-size:.9em;font-family:Lato,sans-serif;font-weight:700;-webkit-font-smoothing:antialiased;padding-left:6px}"+config.selector+" .social{opacity:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;margin-left:-15px;visibility:hidden}"+config.selector+" .social.top{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;margin-top:-80px}"+config.selector+" .social.bottom{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;margin-top:5px}"+config.selector+" .social.middle{margin-top:-34px}"+config.selector+" .social.middle.right{-webkit-transform-origin:5% 50%;-ms-transform-origin:5% 50%;transform-origin:5% 50%;margin-left:105px}"+config.selector+" .social.middle.left{-webkit-transform-origin:5% 50%;-ms-transform-origin:5% 50%;transform-origin:5% 50%}"+config.selector+" .social.right{margin-left:14px}"+config.selector+" .social.load{-webkit-transition:none!important;transition:none!important}"+config.selector+" .social.networks-1{width:60px}"+config.selector+" .social.networks-1.center,"+config.selector+" .social.networks-1.left{margin-left:14px}"+config.selector+" .social.networks-1.middle.left{margin-left:-70px}"+config.selector+" .social.networks-1 ul{width:60px}"+config.selector+" .social.networks-2{width:120px}"+config.selector+" .social.networks-2.center{margin-left:-13px}"+config.selector+" .social.networks-2.left{margin-left:-44px}"+config.selector+" .social.networks-2.middle.left{margin-left:-130px}"+config.selector+" .social.networks-2 ul{width:120px}"+config.selector+" .social.networks-3{width:180px}"+config.selector+" .social.networks-3.center{margin-left:-45px}"+config.selector+" .social.networks-3.left{margin-left:-102px}"+config.selector+" .social.networks-3.middle.left{margin-left:-190px}"+config.selector+" .social.networks-3 ul{width:180px}"+config.selector+" .social.networks-4{width:240px}"+config.selector+" .social.networks-4.center{margin-left:-75px}"+config.selector+" .social.networks-4.left{margin-left:162px}"+config.selector+" .social.networks-4.middle.left{margin-left:-250px}"+config.selector+" .social.networks-4 ul{width:240px}"+config.selector+" .social.networks-5{width:300px}"+config.selector+" .social.networks-5.center{margin-left:-105px}"+config.selector+" .social.networks-5.left{margin-left:-225px}"+config.selector+" .social.networks-5.middle.left{margin-left:-320px}"+config.selector+" .social.networks-5 ul{width:300px}"+config.selector+" .social.active{opacity:1;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;visibility:visible}"+config.selector+" .social.active.top{-webkit-transform:scale(1) translateY(-20px);-ms-transform:scale(1) translateY(-20px);transform:scale(1) translateY(-20px)}"+config.selector+" .social.active.bottom{-webkit-transform:scale(1) translateY(15px);-ms-transform:scale(1) translateY(15px);transform:scale(1) translateY(15px)}"+config.selector+" .social.active.middle.right{-webkit-transform:scale(1) translateX(10px);-ms-transform:scale(1) translateX(10px);transform:scale(1) translateX(10px)}"+config.selector+" .social.active.middle.left{-webkit-transform:scale(1) translateX(-20px);-ms-transform:scale(1) translateX(-20px);transform:scale(1) translateX(-20px)}"+config.selector+" .social ul{position:relative;
14378left:0;right:0;height:46px;color:#fff;margin:auto;padding:0;list-style:none}"+config.selector+" .social ul li{font-size:20px;cursor:pointer;width:60px;margin:0;padding:12px 0;text-align:center;float:left;display:none;height:22px;position:relative;z-index:2;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}"+config.selector+" .social ul li:hover{}"+config.selector+" .social li[class*=facebook]{display:"+config.networks.facebook.display+"}"+config.selector+" .social li[class*=twitter]{display:"+config.networks.twitter.display+"}"+config.selector+" .social li[class*=gplus]{display:"+config.networks.google_plus.display+"}"+config.selector+" .social li[class*=pinterest]{display:"+config.networks.pinterest.display+"}"+config.selector+" .social li[class*=paper-plane]{display:"+config.networks.email.display+"}" 14379}; 14380 var ShareUtils; 14381 14382if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 14383 Object.defineProperty(HTMLElement.prototype, "classList", { 14384 get: function() { 14385 var ret, self, update; 14386 update = function(fn) { 14387 return function(value) { 14388 var classes, index; 14389 classes = self.className.split(/\s+/); 14390 index = classes.indexOf(value); 14391 fn(classes, index, value); 14392 self.className = classes.join(" "); 14393 }; 14394 }; 14395 self = this; 14396 ret = { 14397 add: update(function(classes, index, value) { 14398 ~index || classes.push(value); 14399 }), 14400 remove: update(function(classes, index) { 14401 ~index && classes.splice(index, 1); 14402 }), 14403 toggle: update(function(classes, index, value) { 14404 if (~index) { 14405 classes.splice(index, 1); 14406 } else { 14407 classes.push(value); 14408 } 14409 }), 14410 contains: function(value) { 14411 return !!~self.className.split(/\s+/).indexOf(value); 14412 }, 14413 item: function(i) { 14414 return self.className.split(/\s+/)[i] || null; 14415 } 14416 }; 14417 Object.defineProperty(ret, "length", { 14418 get: function() { 14419 return self.className.split(/\s+/).length; 14420 } 14421 }); 14422 return ret; 14423 } 14424 }); 14425} 14426 14427String.prototype.to_rfc3986 = function() { 14428 var tmp; 14429 tmp = encodeURIComponent(this); 14430 return tmp.replace(/[!'()*]/g, function(c) { 14431 return "%" + c.charCodeAt(0).toString(16); 14432 }); 14433}; 14434 14435ShareUtils = (function() { 14436 function ShareUtils() {} 14437 14438 ShareUtils.prototype.extend = function(to, from, overwrite) { 14439 var hasProp, prop; 14440 for (prop in from) { 14441 hasProp = to[prop] !== undefined; 14442 if (hasProp && typeof from[prop] === "object") { 14443 this.extend(to[prop], from[prop], overwrite); 14444 } else { 14445 if (overwrite || !hasProp) { 14446 to[prop] = from[prop]; 14447 } 14448 } 14449 } 14450 }; 14451 14452 ShareUtils.prototype.hide = function(el) { 14453 return el.style.display = "none"; 14454 }; 14455 14456 ShareUtils.prototype.show = function(el) { 14457 return el.style.display = "block"; 14458 }; 14459 14460 ShareUtils.prototype.has_class = function(el, class_name) { 14461 return el.classList.contains(class_name); 14462 }; 14463 14464 ShareUtils.prototype.add_class = function(el, class_name) { 14465 return el.classList.add(class_name); 14466 }; 14467 14468 ShareUtils.prototype.remove_class = function(el, class_name) { 14469 return el.classList.remove(class_name); 14470 }; 14471 14472 ShareUtils.prototype.is_encoded = function(str) { 14473 str = str.to_rfc3986(); 14474 return decodeURIComponent(str) !== str; 14475 }; 14476 14477 ShareUtils.prototype.encode = function(str) { 14478 if (typeof str === "undefined" || this.is_encoded(str)) { 14479 return str; 14480 } else { 14481 return str.to_rfc3986(); 14482 } 14483 }; 14484 14485 ShareUtils.prototype.popup = function(url, params) { 14486 var k, popup, qs, v; 14487 if (params == null) { 14488 params = {}; 14489 } 14490 popup = { 14491 width: 500, 14492 height: 350 14493 }; 14494 popup.top = (screen.height / 2) - (popup.height / 2); 14495 popup.left = (screen.width / 2) - (popup.width / 2); 14496 qs = ((function() { 14497 var _results; 14498 _results = []; 14499 for (k in params) { 14500 v = params[k]; 14501 _results.push("" + k + "=" + (this.encode(v))); 14502 } 14503 return _results; 14504 }).call(this)).join('&'); 14505 if (qs) { 14506 qs = "?" + qs; 14507 } 14508 return window.open(url + qs, 'targetWindow', "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,left=" + popup.left + ",top=" + popup.top + ",width="
14508+ popup.width + ",height=" + popup.height); 14509 }; 14510 14511 return ShareUtils; 14512 14513})(); 14514var Share, 14515 __hasProp = {}.hasOwnProperty, 14516 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; 14517 14518Share = (function(_super) { 14519 __extends(Share, _super); 14520 14521 function Share(element, options) { 14522 this.element = element; 14523 this.el = { 14524 head: document.getElementsByTagName('head')[0], 14525 body: document.getElementsByTagName('body')[0] 14526 }; 14527 this.config = { 14528 enabled_networks: 0, 14529 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 14530 url: window.location.href, 14531 caption: null, 14532 title: this.default_title(), 14533 image: this.default_image(), 14534 description: this.default_description(), 14535 ui: { 14536 flyout: 'top center', 14537 button_text: 'Share', 14538 button_font: true, 14539 icon_font: true 14540 }, 14541 networks: { 14542 google_plus: { 14543 enabled: true, 14544 url: null 14545 }, 14546 twitter: { 14547 enabled: true, 14548 url: null, 14549 title: null, 14550 description: null 14551 }, 14552 facebook: { 14553 enabled: true, 14554 load_sdk: true, 14555 url: null, 14556 app_id: null, 14557 title: null, 14558 caption: null, 14559 description: null, 14560 image: null 14561 }, 14562 pinterest: { 14563 enabled: true, 14564 url: null, 14565 image: null, 14566 description: null 14567 }, 14568 reddit: { 14569 enabled: true, 14570 url: null, 14571 title: null 14572 }, 14573 linkedin: { 14574 enabled: true, 14575 url: null, 14576 title: null, 14577 description: null 14578 }, 14579 xing: { 14580 enabled: true, 14581 url: null, 14582 title: null, 14583 image: null, 14584 description: null 14585 }, 14586 whatsapp: { 14587 enabled: true, 14588 description: null, 14589 url: null 14590 }, 14591 email: { 14592 enabled: true, 14593 title: null, 14594 description: null, 14595 url: null 14596 } 14597 } 14598 }; 14599 this.setup(element, options); 14600 return this; 14601 } 14602 14603 Share.prototype.setup = function(element, opts) { 14604 var index, instance, instances, _i, _len; 14605 instances = document.querySelectorAll(element); 14606 this.extend(this.config, opts, true); 14607 this.set_global_configuration(); 14608 this.normalize_network_configuration(); 14609 if (this.config.ui.icon_font) { 14610 this.inject_icons(); 14611 } 14612 if (this.config.ui.button_font) { 14613 this.inject_fonts(); 14614 } 14615 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 14616 this.inject_facebook_sdk(); 14617 } 14618 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 14619 instance = instances[index]; 14620 this.setup_instance(element, index); 14621 } 14622 }; 14623 14624 Share.prototype.setup_instance = function(element, index) { 14625 var button, instance, label, network, networks, _i, _len, _results, 14626 _this = this; 14627 instance = document.querySelectorAll(element)[index]; 14628 this.hide(instance); 14629 this.add_class(instance, "sharer-" + index); 14630 instance = document.querySelectorAll(element)[index]; 14631 this.inject_css(instance); 14632 this.inject_html(instance); 14633 this.show(instance); 14634 label = instance.getElementsByTagName("label")[0]; 14635 button = instance.getElementsByClassName("social")[0]; 14636 networks = instance.getElementsByTagName('li'); 14637 this.add_class(button, "networks-" + this.config.enabled_networks); 14638 label.addEventListener("click", function() { 14639 return _this.event_toggle(button); 14640 }); 14641 _this = this; 14642 _results = []; 14643 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 14644 network = networks[index]; 14645 _results.push(network.addEventListener("click", function() { 14646 _this.event_network(instance, this); 14647 return _this.event_close(button); 14648 })); 14649 } 14650 return _results; 14651 }; 14652 14653 Share.prototype.event_toggle = function(button) { 14654 if (this.has_class(button, "active")) { 14655 return this.event_close(button); 14656 } else { 14657 return this.event_open(button); 14658 } 14659 }; 14660 14661 Share.prototype.event_open = function(button) { 14662 if (this.has_class(button, "load")) { 14663 this.remove_class(button, "load"); 14664 } 14665 return this.add_class(button, "active"); 14666 }; 14667 14668 Share.prototype.event_close = function(button) { 14669 return this.remove_class(button, "active"); 14670 }; 14671 14672 Share.prototype.event_network = function(instance, network) { 14673 var name; 14674 name = network.getAttribute("data-network"); 14675 this.hook("before", name, instance);
14676 this["network_" + name](); 14677 return this.hook("after", name, instance); 14678 }; 14679 14680 Share.prototype.open = function() { 14681 return this["public"]("open"); 14682 }; 14683 14684 Share.prototype.close = function() { 14685 return this["public"]("close"); 14686 }; 14687 14688 Share.prototype.toggle = function() { 14689 return this["public"]("toggle"); 14690 }; 14691 14692 Share.prototype["public"] = function(action) { 14693 var button, index, instance, _i, _len, _ref, _results; 14694 _ref = document.querySelectorAll(this.element); 14695 _results = []; 14696 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 14697 instance = _ref[index]; 14698 button = instance.getElementsByClassName("social")[0]; 14699 _results.push(this["event_" + action](button)); 14700 } 14701 return _results; 14702 }; 14703 14704 Share.prototype.network_facebook = function() { 14705 if (this.config.networks.facebook.load_sdk) { 14706 if (!window.FB) { 14707 return console.error("The Facebook JS SDK hasn't loaded yet."); 14708 } 14709 return FB.ui({ 14710 method: 'feed', 14711 name: this.config.networks.facebook.title, 14712 link: this.config.networks.facebook.url, 14713 picture: this.config.networks.facebook.image, 14714 caption: this.config.networks.facebook.caption, 14715 description: this.config.networks.facebook.description 14716 }); 14717 } else { 14718 return this.popup('https://www.facebook.com/sharer/sharer.php', { 14719 u: this.config.networks.facebook.url 14720 }); 14721 } 14722 }; 14723 14724 Share.prototype.network_twitter = function() { 14725 return this.popup('https://twitter.com/intent/tweet', { 14726 text: this.config.networks.twitter.title, 14727 url: this.config.networks.twitter.url 14728 }); 14729 }; 14730 14731 Share.prototype.network_google_plus = function() { 14732 return this.popup('https://plus.google.com/share', { 14733 url: this.config.networks.google_plus.url 14734 }); 14735 }; 14736 14737 Share.prototype.network_pinterest = function() { 14738 return this.popup('https://www.pinterest.com/pin/create/button', { 14739 url: this.config.networks.pinterest.url, 14740 media: this.config.networks.pinterest.image, 14741 description: this.config.networks.pinterest.description 14742 }); 14743 }; 14744 14745 Share.prototype.network_linkedin = function() { 14746 return this.popup('https://www.linkedin.com/shareArticle', { 14747 url: this.config.networks.linkedin.url, 14748 title: this.config.networks.linkedin.title, 14749 summary: this.config.networks.linkedin.description 14750 }); 14751 } 14752 14753 Share.prototype.network_xing = function() { 14754 return this.popup('https://www.xing.com/spi/shares/new', { 14755 url: this.config.networks.xing.url, 14756 image: this.config.networks.xing.image, 14757 title: this.config.networks.xing.title, 14758 summary: this.config.networks.xing.description 14759 }); 14760 } 14761 14762 Share.prototype.network_email = function() { 14763 return this.popup('mailto:', { 14764 subject: this.config.networks.email.title, 14765 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 14766 }); 14767 }; 14768 14769 Share.prototype.inject_icons = function() { 14770 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 14771 }; 14772 14773 Share.prototype.inject_fonts = function() { 14774 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 14775 }; 14776 14777 Share.prototype.inject_stylesheet = function(url) { 14778 var link; 14779 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 14780 link = document.createElement("link"); 14781 link.setAttribute("rel", "stylesheet"); 14782 link.setAttribute("href", url); 14783 return this.el.head.appendChild(link); 14784 } 14785 }; 14786 14787 Share.prototype.inject_css = function(instance) { 14788 var css, meta, selector, style; 14789 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 14790 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 14791 this.config.selector = selector; 14792 css = getStyles(this.config); 14793 style = document.createElement("style"); 14794 style.type = "text/css"; 14795 if (style.styleSheet) { 14796 style.styleSheet.cssText = css; 14797 } else { 14798 style.appendChild(document.createTextNode(css)); 14799 } 14800 this.el.head.appendChild(style); 14801 delete this.config.selector; 14802 meta = document.createElement("meta"); 14803 meta.setAttribute("name", "sharer" + selector); 14804 return this.el.head.appendChild(meta); 14805 } 14806 }; 14807 14808 Share.prototype.inject_html = function(instance) { 14809 return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-gplus' data-network='google_plus' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>"; 14810 }; 14811 14812 Share.prototype.inject_facebook_sdk = function() { 14813 var fb_root, script; 14814 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 14815 script = document.createElement("script"); 14816 script.text = "window.fbAsyncInit=function(){FB.init({appId:'" + this.config.networks.facebook.app_id + "',status:true,xfbml:true})};(function(e,t,n){var r,i=e.getElementsByTagName(t)[0];if(e.getElementById(n)){return}r=e.createElement(t);r.id=n;r.src='" + this.config.protocol + "connect.facebook.net/en_US/all.js';i.parentNode.insertBefore(r,i)})(document,'script','facebook-jssdk')"; 14817 fb_root = document.createElement("div"); 14818 fb_root.id = "fb-root"; 14819 this.el.body.appendChild(fb_root); 14820 return this.el.body.appendChild(script); 14821 } 14822 }; 14823 14824 Share.prototype.hook = function(type, network, instance) { 14825 var fn, opts; 14826 fn = this.config.networks[network][type]; 14827 if (typeof fn === "function") { 14828 opts = fn.call(this.config.networks[network], instance); 14829 if (opts !== void 0) { 14830 opts = this.normalize_filter_config_updates(opts); 14831 this.extend(this.config.networks[network], opts, true); 14832 this.normalize_network_configuration(); 14833 } 14834 } 14835 }; 14836 14837 Share.prototype.default_title = function() { 14838 var content; 14839 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 14840 return encodeURIComponent(content.getAttribute('content')); 14841 } else if (content = document.querySelector('title')) { 14842 return encodeURIComponent(content.innerText); 14843 } 14844 }; 14845 14846 Share.prototype.default_image = function() { 14847 var content; 14848 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 14849 return content.getAttribute('content'); 14850 } 14851 }; 14852 14853 Share.prototype.default_description = function() { 14854 var content; 14855 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 14856 return content.getAttribute('content'); 14857 } else { 14858 return ''; 14859 } 14860 }; 14861 14862 Share.prototype.set_global_configuration = function() { 14863 var display, network, option, options, _ref, _results; 14864 _ref = this.config.networks; 14865 _results = []; 14866 for (network in _ref) { 14867 options = _ref[network]; 14868 for (option in options) { 14869 if (this.config.networks[network][option] == null) { 14870 this.config.networks[network][option] = this.config[option]; 14871 } 14872 } 14873 if (this.config.networks[network].enabled) { 14874 display = 'block'; 14875 this.config.enabled_networks += 1; 14876 } else { 14877 display = 'none'; 14878 } 14879 _results.push(this.config.networks[network].display = display); 14880 } 14881 return _results; 14882 }; 14883 14884 Share.prototype.normalize_network_configuration = function() { 14885 if (!this.config.networks.facebook.app_id) { 14886 this.config.networks.facebook.load_sdk = false;
14887 } 14888 if (!this.is_encoded(this.config.networks.twitter.description)) { 14889 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 14890 } 14891 if (typeof this.config.networks.facebook.app_id === 'number') { 14892 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 14893 } 14894 }; 14895 14896 Share.prototype.normalize_filter_config_updates = function(opts) { 14897 if (this.config.networks.facebook.app_id !== opts.app_id) { 14898 console.warn("You are unable to change the Facebook app_id after the button has been initialized. Please-in-out update your Facebook filters accordingly."); 14899 delete opts.app_id; 14900 } 14901 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 14902 console.warn("You are unable to change the Facebook load_sdk option after the button has been initialized. Please-in-out update your Facebook filters accordingly."); 14903 delete opts.app_id; 14904 } 14905 return opts; 14906 }; 14907 14908 return Share; 14909 14910})(ShareUtils); 14911 return Share; 14912}); 14913 14914 14915// Generated by CoffeeScript 1.9.2 14916 14917// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 14918 14919(function() { 14920 var $, win; 14921 14922 $ = this.jQuery || window.jQuery; 14923 14924 win = $(window); 14925 14926 $.fn.stick_in_parent = function(opts) { 14927 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 14928 if (opts == null) { 14929 opts = {}; 14930 } 14931 sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming; 14932 if (offset_top == null) { 14933 offset_top = 0; 14934 } 14935 if (parent_selector == null) { 14936 parent_selector = void 0; 14937 } 14938 if (inner_scrolling == null) { 14939 inner_scrolling = true; 14940 } 14941 if (sticky_class == null) { 14942 sticky_class = "is_stuck"; 14943 } 14944 doc = $(document); 14945 if (enable_bottoming == null) { 14946 enable_bottoming = true; 14947 } 14948 outer_width = function(el) { 14949 var _el, computed, w; 14950 if (window.getComputedStyle) { 14951 _el = el[0]; 14952 computed = window.getComputedStyle(el[0]); 14953 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 14954 if (computed.getPropertyValue("box-sizing") !== "border-box") { 14955 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 14956 } 14957 return w; 14958 } else { 14959 return el.outerWidth(true); 14960 } 14961 }; 14962 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 14963 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 14964 if (elm.data("sticky_kit")) { 14965 return; 14966 } 14967 elm.data("sticky_kit", true); 14968 last_scroll_height = doc.height(); 14969 parent = elm.parent(); 14970 if (parent_selector != null) { 14971 parent = parent.closest(parent_selector); 14972 } 14973 if (!parent.length) { 14974 throw "failed to find stick parent"; 14975 } 14976 fixed = false; 14977 bottomed = false; 14978 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 14979 if (spacer) { 14980 spacer.css('position', elm.css('position')); 14981 } 14982 recalc = function() { 14983 var border_top, padding_top, restore; 14984 if (detached) { 14985 return; 14986 } 14987 last_scroll_height = doc.height(); 14988 border_top = parseInt(parent.css("border-top-width"), 10); 14989 padding_top = parseInt(parent.css("padding-top"), 10); 14990 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 14991 parent_top = parent.offset().top + border_top + padding_top; 14992 parent_height = parent.height(); 14993 if (fixed) { 14994 fixed = false;
14995 bottomed = false; 14996 if (manual_spacer == null) { 14997 elm.insertAfter(spacer); 14998 spacer.detach(); 14999 } 15000 elm.css({ 15001 position: "", 15002 top: "", 15003 width: "", 15004 bottom: "" 15005 }).removeClass(sticky_class); 15006 restore = true; 15007 } 15008 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 15009 height = elm.outerHeight(true); 15010 el_float = elm.css("float"); 15011 if (spacer) { 15012 spacer.css({ 15013 width: outer_width(elm), 15014 height: height, 15015 display: elm.css("display"), 15016 "vertical-align": elm.css("vertical-align"), 15017 "float": el_float 15018 }); 15019 } 15020 if (restore) { 15021 return tick(); 15022 } 15023 }; 15024 recalc(); 15025 if (height === parent_height) { 15026 return; 15027 } 15028 last_pos = void 0; 15029 offset = offset_top; 15030 recalc_counter = recalc_every; 15031 tick = function() { 15032 var css, delta, recalced, scroll, will_bottom, win_height; 15033 if (detached) { 15034 return; 15035 } 15036 recalced = false; 15037 if (recalc_counter != null) { 15038 recalc_counter -= 1; 15039 if (recalc_counter <= 0) { 15040 recalc_counter = recalc_every; 15041 recalc(); 15042 recalced = true; 15043 } 15044 } 15045 if (!recalced && doc.height() !== last_scroll_height) { 15046 recalc(); 15047 recalced = true; 15048 } 15049 scroll = win.scrollTop(); 15050 if (last_pos != null) { 15051 delta = scroll - last_pos; 15052 } 15053 last_pos = scroll; 15054 if (fixed) { 15055 if (enable_bottoming) { 15056 will_bottom = scroll + height + offset > parent_height + parent_top; 15057 if (bottomed && !will_bottom) { 15058 bottomed = false; 15059 elm.css({ 15060 position: "fixed", 15061 bottom: "", 15062 top: offset 15063 }).trigger("sticky_kit:unbottom"); 15064 } 15065 } 15066 if (scroll < top) { 15067 fixed = false; 15068 offset = offset_top; 15069 if (manual_spacer == null) { 15070 if (el_float === "left" || el_float === "right") { 15071 elm.insertAfter(spacer); 15072 } 15073 spacer.detach(); 15074 } 15075 css = { 15076 position: "", 15077 width: "", 15078 top: "" 15079 }; 15080 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 15081 } 15082 if (inner_scrolling) { 15083 win_height = win.height(); 15084 if (height + offset_top > win_height) { 15085 if (!bottomed) { 15086 offset -= delta; 15087 offset = Math.max(win_height - height, offset); 15088 offset = Math.min(offset_top, offset); 15089 if (fixed) { 15090 elm.css({ 15091 top: offset + "px" 15092 }); 15093 } 15094 } 15095 } 15096 } 15097 } else { 15098 if (scroll > top) { 15099 fixed = true; 15100 css = { 15101 position: "fixed", 15102 top: offset 15103 }; 15104 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 15105 elm.css(css).addClass(sticky_class); 15106 if (manual_spacer == null) { 15107 elm.after(spacer); 15108 if (el_float === "left" || el_float === "right") { 15109 spacer.append(elm); 15110 } 15111 } 15112 elm.trigger("sticky_kit:stick"); 15113 } 15114 } 15115 if (fixed && enable_bottoming) { 15116 if (will_bottom == null) { 15117 will_bottom = scroll + height + offset > parent_height + parent_top; 15118 } 15119 if (!bottomed && will_bottom) { 15120 bottomed = true; 15121 if (parent.css("position") === "static") { 15122 parent.css({ 15123 position: "relative" 15124 }); 15125 } 15126 return elm.css({ 15127 position: "absolute", 15128 bottom: padding_bottom, 15129 top: "auto" 15130 }).trigger("sticky_kit:bottom"); 15131 } 15132 } 15133 }; 15134 recalc_and_tick = function() { 15135 recalc(); 15136 return tick(); 15137 }; 15138 detach = function() { 15139 detached = true; 15140 win.off("touchmove", tick); 15141 win.off("scroll", tick); 15142 win.off("resize", recalc_and_tick); 15143 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 15144 elm.off("sticky_kit:detach", detach); 15145 elm.removeData("sticky_kit"); 15146 elm.css({ 15147 position: "", 15148 bottom: "", 15149 top: "", 15150 width: "" 15151 }); 15152 parent.position("position", ""); 15153 if (fixed) { 15154 if (manual_spacer == null) { 15155 if (el_float === "left" || el_float === "right") { 15156 elm.insertAfter(spacer); 15157 } 15158 spacer.remove(); 15159 } 15160 return elm.removeClass(sticky_class); 15161 } 15162 }; 15163 win.on("touchmove", tick); 15164 win.on("scroll", tick); 15165 win.on("resize", recalc_and_tick); 15166 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 15167 elm.on("sticky_kit:detach", detach); 15168 return setTimeout(tick, 0); 15169 }; 15170 for (i = 0, len = this.length; i < len; i++) { 15171 elm = this[i]; 15172 fn($(elm)); 15173 } 15174 return this; 15175 }; 15176 15177}).call(this); 15178 15179 15180 15181/* ======================================================================== 15182 * Bootstrap: collapse.js v3.1.1 15183 * http://getbootstrap.com/javascript/#collapse 15184 * ======================================================================== 15185 * Copyright 2011-2014 Twitter, Inc. 15186 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15187 * ======================================================================== */ 15188 15189 15190+function ($) { 15191 'use strict'; 15192 15193 // COLLAPSE PUBLIC CLASS DEFINITION 15194 // ================================ 15195 15196 var Collapse = function (element, options) { 15197 this.$element = $(element) 15198 this.options = $.extend({}, Collapse.DEFAULTS, options) 15199 this.transitioning = null 15200 15201 if (this.options.parent) this.$parent = $(this.options.parent) 15202 if (this.options.toggle) this.toggle() 15203 } 15204 15205 Collapse.DEFAULTS = { 15206 toggle: true 15207 } 15208 15209 Collapse.prototype.dimension = function () { 15210 var hasWidth = this.$element.hasClass('width') 15211 return hasWidth ? 'width' : 'height' 15212 } 15213 15214 Collapse.prototype.show = function () { 15215 if (this.transitioning || this.$element.hasClass('in')) return 15216 15217 var startEvent = $.Event('show.bs.collapse') 15218 this.$element.trigger(startEvent) 15219 if (startEvent.isDefaultPrevented()) return 15220 15221 var actives = this.$parent && this.$parent.find('> .panel > .in') 15222 15223 if (actives && actives.length) { 15224 var hasData = actives.data('bs.collapse') 15225 if (hasData && hasData.transitioning) return 15226 actives.collapse('hide') 15227 hasData || actives.data('bs.collapse', null) 15228 } 15229 15230 var dimension = this.dimension() 15231 15232 this.$element 15233 .removeClass('collapse') 15234 .addClass('collapsing')[dimension](0) 15235 15236 this.transitioning = 1 15237 15238 var complete = function (e) { 15239 if (e && e.target != this.$element[0]) return 15240 this.$element 15241 .removeClass('collapsing') 15242 .addClass('collapse in')[dimension]('auto') 15243 this.transitioning = 0 15244 this.$element.trigger('shown.bs.collapse') 15245 } 15246 15247 if (!$.support.transition) return complete.call(this) 15248 15249 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 15250 15251 this.$element 15252 .one($.support.transition.end, $.proxy(complete, this)) 15253 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 15254 } 15255 15256 Collapse.prototype.hide = function () { 15257 if (this.transitioning || !this.$element.hasClass('in')) return 15258 15259 var startEvent = $.Event('hide.bs.collapse') 15260 this.$element.trigger(startEvent) 15261 if (startEvent.isDefaultPrevented()) return 15262 15263 var dimension = this.dimension() 15264 15265 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 15266 15267 this.$element 15268 .addClass('collapsing') 15269 .removeClass('collapse') 15270 .removeClass('in') 15271 15272 this.transitioning = 1 15273 15274 var complete = function (e) { 15275 if (e && e.target != this.$element[0]) return 15276 this.transitioning = 0 15277 this.$element 15278 .trigger('hidden.bs.collapse') 15279 .removeClass('collapsing') 15280 .addClass('collapse') 15281 } 15282 15283 if (!$.support.transition) return complete.call(this) 15284 15285 this.$element 15286 [dimension](0) 15287 .one($.support.transition.end, $.proxy(complete, this)) 15288 .emulateTransitionEnd(350) 15289 } 15290 15291 Collapse.prototype.toggle = function () { 15292 this[this.$element.hasClass('in') ? 'hide' : 'show']() 15293 } 15294 15295 15296 // COLLAPSE PLUGIN DEFINITION 15297 // ========================== 15298 15299 var old = $.fn.collapse 15300 15301 $.fn.collapse = function (option) { 15302 return this.each(function () { 15303 var $this = $(this) 15304 var data = $this.data('bs.collapse') 15305 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 15306 15307 if (!data && options.toggle && option == 'show') option = !option 15308 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 15309 if (typeof option == 'string') data[option]() 15310 }) 15311 } 15312 15313 $.fn.collapse.Constructor = Collapse 15314 15315 15316 // COLLAPSE NO CONFLICT 15317 // ==================== 15318 15319 $.fn.collapse.noConflict = function () { 15320 $.fn.collapse = old 15321 return this 15322 } 15323 15324 15325 // COLLAPSE DATA-API 15326 // ================= 15327 15328 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 15329 var $this = $(this), href 15330 var target = $this.attr('data-target') 15331 || e.preventDefault() 15332 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 15333 var $target = $(target) 15334 var data = $target.data('bs.collapse') 15335 var option = data ? 'toggle' : $this.data() 15336 var parent = $this.attr('data-parent') 15337 var $parent = parent && $(parent) 15338 15339 if (!data || !data.transitioning) { 15340 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 15341 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 15342 } 15343 15344 $target.collapse(option) 15345 }) 15346 15347}(jQuery); 15348 15349 15350/* ======================================================================== 15351 * Bootstrap: tab.js v3.1.1 15352 * http://getbootstrap.com/javascript/#tabs 15353 * ======================================================================== 15354 * Copyright 2011-2014 Twitter, Inc. 15355 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15356 * ======================================================================== */ 15357 15358 15359+function ($) { 15360 'use strict'; 15361 15362 // TAB CLASS DEFINITION 15363 // ==================== 15364 15365 var Tab = function (element) { 15366 this.element = $(element) 15367 } 15368 15369 Tab.prototype.show = function () { 15370 var $this = this.element 15371 var $ul = $this.closest('ul:not(.dropdown-menu)') 15372 var selector = $this.data('target') 15373 15374 if (!selector) { 15375 selector = $this.attr('href') 15376 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 15377 } 15378 15379 if ($this.parent('li').hasClass('active')) return 15380 15381 var previous = $ul.find('.active:last a')[0] 15382 var e = $.Event('show.bs.tab', { 15383 relatedTarget: previous 15384 }) 15385 15386 $this.trigger(e) 15387 15388 if (e.isDefaultPrevented()) return 15389 15390 var $target = $(selector) 15391 15392 this.activate($this.parent('li'), $ul) 15393 this.activate($target, $target.parent(), function () { 15394 $this.trigger({ 15395 type: 'shown.bs.tab', 15396 relatedTarget: previous 15397 }) 15398 }) 15399 } 15400 15401 Tab.prototype.activate = function (element, container, callback) { 15402 var $active = container.find('> .active') 15403 var transition = callback 15404 && $.support.transition 15405 && $active.hasClass('fade') 15406 15407 function next() { 15408 $active 15409 .removeClass('active') 15410 .find('> .dropdown-menu > .active') 15411 .removeClass('active') 15412 15413 element.addClass('active') 15414 15415 if (transition) { 15416 element[0].offsetWidth // reflow for transition 15417 element.addClass('in') 15418 } else { 15419 element.removeClass('fade') 15420 } 15421 15422 if (element.parent('.dropdown-menu')) { 15423 element.closest('li.dropdown').addClass('active') 15424 } 15425 15426 callback && callback() 15427 } 15428 15429 transition ? 15430 $active 15431 .one($.support.transition.end, next) 15432 .emulateTransitionEnd(150) : 15433 next() 15434 15435 $active.removeClass('in') 15436 } 15437 15438 15439 // TAB PLUGIN DEFINITION 15440 // ===================== 15441 15442 var old = $.fn.tab 15443 15444 $.fn.tab = function ( option ) { 15445 return this.each(function () { 15446 var $this = $(this) 15447 var data = $this.data('bs.tab') 15448 15449 if (!data) $this.data('bs.tab', (data = new Tab(this))) 15450 if (typeof option == 'string') data[option]() 15451 }) 15452 } 15453 15454 $.fn.tab.Constructor = Tab 15455 15456 15457 // TAB NO CONFLICT 15458 // =============== 15459 15460 $.fn.tab.noConflict = function () { 15461 $.fn.tab = old 15462 return this 15463 } 15464 15465 15466 // TAB DATA-API 15467 // ============ 15468 15469 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 15470 e.preventDefault() 15471 $(this).tab('show') 15472 }) 15473 15474}(jQuery); 15475 15476 15477/* ======================================================================== 15478 * Bootstrap: tooltip.js v3.1.1 15479 * http://getbootstrap.com/javascript/#tooltip 15480 * Inspired by the original jQuery.tipsy by Jason Frame 15481 * ======================================================================== 15482 * Copyright 2011-2014 Twitter, Inc. 15483 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15484 * ======================================================================== */ 15485 15486 15487+function ($) { 15488 'use strict'; 15489 15490 // TOOLTIP PUBLIC CLASS DEFINITION 15491 // =============================== 15492 15493 var Tooltip = function (element, options) { 15494 this.type = 15495 this.options = 15496 this.enabled = 15497 this.timeout = 15498 this.hoverState = 15499 this.$element = null 15500 15501 this.init('tooltip', element, options) 15502 } 15503 15504 Tooltip.DEFAULTS = { 15505 animation: true, 15506 placement: 'top', 15507 selector: false, 15508 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 15509 trigger: 'hover focus', 15510 title: '', 15511 delay: 0, 15512 html: false, 15513 container: false, 15514 viewport: { 15515 selector: 'body', 15516 padding: 0 15517 } 15518 } 15519 15520 Tooltip.prototype.init = function (type, element, options) { 15521 this.enabled = true 15522 this.type = type 15523 this.$element = $(element) 15524 this.options = this.getOptions(options) 15525 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 15526 15527 var triggers = this.options.trigger.split(' ') 15528 15529 for (var i = triggers.length; i--;) { 15530 var trigger = triggers[i] 15531 15532 if (trigger == 'click') { 15533 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 15534 } else if (trigger != 'manual') { 15535 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 15536 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 15537 15538 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 15539 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 15540 } 15541 } 15542 15543 this.options.selector ? 15544 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 15545 this.fixTitle() 15546 } 15547 15548 Tooltip.prototype.getDefaults = function () { 15549 return Tooltip.DEFAULTS 15550 } 15551 15552 Tooltip.prototype.getOptions = function (options) { 15553 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 15554 15555 if (options.delay && typeof options.delay == 'number') { 15556 options.delay = { 15557 show: options.delay, 15558 hide: options.delay 15559 } 15560 } 15561 15562 return options 15563 } 15564 15565 Tooltip.prototype.getDelegateOptions = function () { 15566 var options = {} 15567 var defaults = this.getDefaults() 15568 15569 this._options && $.each(this._options, function (key, value) { 15570 if (defaults[key] != value) options[key] = value 15571 }) 15572 15573 return options 15574 } 15575 15576 Tooltip.prototype.enter = function (obj) { 15577 var self = obj instanceof this.con
15577structor ? 15578 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 15579 15580 clearTimeout(self.timeout) 15581 15582 self.hoverState = 'in' 15583 15584 if (!self.options.delay || !self.options.delay.show) return self.show() 15585 15586 self.timeout = setTimeout(function () { 15587 if (self.hoverState == 'in') self.show() 15588 }, self.options.delay.show) 15589 } 15590 15591 Tooltip.prototype.leave = function (obj) { 15592 var self = obj instanceof this.constructor ? 15593 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 15594 15595 clearTimeout(self.timeout) 15596 15597 self.hoverState = 'out' 15598 15599 if (!self.options.delay || !self.options.delay.hide) return self.hide() 15600 15601 self.timeout = setTimeout(function () { 15602 if (self.hoverState == 'out') self.hide() 15603 }, self.options.delay.hide) 15604 } 15605 15606 Tooltip.prototype.show = function () { 15607 var e = $.Event('show.bs.' + this.type) 15608 15609 if (this.hasContent() && this.enabled) { 15610 this.$element.trigger(e) 15611 15612 if (e.isDefaultPrevented()) return 15613 var that = this; 15614 15615 var $tip = this.tip() 15616 15617 this.setContent() 15618 15619 if (this.options.animation) $tip.addClass('fade') 15620 15621 var placement = typeof this.options.placement == 'function' ? 15622 this.options.placement.call(this, $tip[0], this.$element[0]) : 15623 this.options.placement 15624 15625 var autoToken = /\s?auto?\s?/i 15626 var autoPlace = autoToken.test(placement) 15627 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 15628 15629 $tip 15630 .detach() 15631 .css({ top: 0, left: 0, display: 'block' }) 15632 .addClass(placement) 15633 15634 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 15635 15636 var pos = this.getPosition() 15637 var actualWidth = $tip[0].offsetWidth 15638 var actualHeight = $tip[0].offsetHeight 15639 15640 if (autoPlace) { 15641 var orgPlacement = placement 15642 var $parent = this.$element.parent() 15643 var parentDim = this.getPosition($parent) 15644 15645 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 15646 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 15647 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 15648 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 15649 placement 15650 15651 $tip 15652 .removeClass(orgPlacement) 15653 .addClass(placement) 15654 } 15655 15656 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 15657 15658 this.applyPlacement(calculatedOffset, placement) 15659 this.hoverState = null 15660 15661 var complete = function() { 15662 that.$element.trigger('shown.bs.' + that.type) 15663 } 15664 15665 $.support.transition && this.$tip.hasClass('fade') ? 15666 $tip 15667 .one($.support.transition.end, complete) 15668 .emulateTransitionEnd(150) : 15669 complete() 15670 } 15671 } 15672 15673 Tooltip.prototype.applyPlacement = function (offset, placement) { 15674 var $tip = this.tip() 15675 var width = $tip[0].offsetWidth 15676 var height = $tip[0].offsetHeight 15677 15678 // manually read margins because getBoundingClientRect includes difference 15679 var marginTop = parseInt($tip.css('margin-top'), 10) 15680 var marginLeft = parseInt($tip.css('margin-left'), 10) 15681 15682 // we must check for NaN for ie 8/9 15683 if (isNaN(marginTop)) marginTop = 0 15684 if (isNaN(marginLeft)) marginLeft = 0 15685 15686 offset.top = offset.top + marginTop 15687 offset.left = offset.left + marginLeft 15688 15689 // $.fn.offset doesn't round pixel values 15690 // so we use setOffset directly with our own function B-0 15691 $.offset.setOffset($tip[0], $.extend({ 15692 using: function (props) { 15693 $tip.css({ 15694 top: Math.round(props.top), 15695 left: Math.round(props.left) 15696 }) 15697 } 15698 }, offset), 0) 15699 15700 $tip.addClass('in') 15701 15702 // check to see if placing tip in new offset caused the tip to resize itself 15703 var actualWidth = $tip[0].offsetWidth 15704 var actualHeight = $tip[0].offsetHeight 15705 15706 if (placement == 'top' && actualHeight != height) { 15707 offset.top = offset.top + height - actualHeight 15708 } 15709 15710 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 15711 15712 if (delta.left) offset.left += delta.left 15713 else offset.top += delta.top 15714 15715 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 15716 var arrowPosition = delta.left ? 'left' : 'top' 15717 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 15718 15719 $tip.offset(offset) 15720 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 15721 } 15722 15723 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 15724 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 15725 } 15726 15727 Tooltip.prototype.setContent = function () { 15728 var $tip = this.tip() 15729 var title = this.getTitle() 15730 15731 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 15732 $tip.removeClass('fade in top bottom left right') 15733 } 15734 15735 Tooltip.prototype.hide = function () { 15736 var that = this 15737 var $tip = this.tip() 15738 var e = $.Event('hide.bs.' + this.type) 15739 15740 function complete() { 15741 if (that.hoverState != 'in') $tip.detach() 15742 that.$element.trigger('hidden.bs.' + that.type) 15743 } 15744 15745 this.$element.trigger(e) 15746 15747 if (e.isDefaultPrevented()) return 15748 15749 $tip.removeClass('in') 15750 15751 $.support.transition && this.$tip.hasClass('fade') ? 15752 $tip 15753 .one($.support.transition.end, complete) 15754 .emulateTransitionEnd(150) : 15755 complete() 15756 15757 this.hoverState = null 15758 15759 return this 15760 } 15761 15762 Tooltip.prototype.fixTitle = function () { 15763 var $e = this.$element 15764 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 15765 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 15766 } 15767 } 15768 15769 Tooltip.prototype.hasContent = function () { 15770 return this.getTitle() 15771 } 15772 15773 Tooltip.prototype.getPosition = function ($element) { 15774 $element = $element || this.$element 15775 var el = $element[0] 15776 var isBody = el.tagName == 'BODY' 15777 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 15778 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 15779 width: isBody ? $(window).width() : $element.outerWidth(), 15780 height: isBody ? $(window).height() : $element.outerHeight() 15781 }, isBody ? {top: 0, left: 0} : $element.offset()) 15782 } 15783 15784 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 15785 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 15786 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 15787 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 15788 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 15789 15790 } 15791 15792 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 15793 var delta = { top: 0, left: 0 } 15794 if (!this.$viewport) return delta 15795 15796 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 15797 var viewportDimensions = this.getPosition(this.$viewport) 15798 15799 if (/right|left/.test(placement)) { 15800 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 15801 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 15802 if (topEdgeOffset < viewportDimensions.top) { // top overflow 15803 delta.top = viewportDimensions.top - topEdgeOffset 15804 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 15805 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
15805EdgeOffset 15806 } 15807 } else { 15808 var leftEdgeOffset = pos.left - viewportPadding 15809 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 15810 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 15811 delta.left = viewportDimensions.left - leftEdgeOffset 15812 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 15813 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 15814 } 15815 } 15816 15817 return delta 15818 } 15819 15820 Tooltip.prototype.getTitle = function () { 15821 var title 15822 var $e = this.$element 15823 var o = this.options 15824 15825 title = $e.attr('data-original-title') 15826 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 15827 15828 return title 15829 } 15830 15831 Tooltip.prototype.tip = function () { 15832 return this.$tip = this.$tip || $(this.options.template) 15833 } 15834 15835 Tooltip.prototype.arrow = function () { 15836 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 15837 } 15838 15839 Tooltip.prototype.validate = function () { 15840 if (!this.$element[0].parentNode) { 15841 this.hide() 15842 this.$element = null 15843 this.options = null 15844 } 15845 } 15846 15847 Tooltip.prototype.enable = function () { 15848 this.enabled = true 15849 } 15850 15851 Tooltip.prototype.disable = function () { 15852 this.enabled = false 15853 } 15854 15855 Tooltip.prototype.toggleEnabled = function () { 15856 this.enabled = !this.enabled 15857 } 15858 15859 Tooltip.prototype.toggle = function (e) { 15860 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 15861 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 15862 } 15863 15864 Tooltip.prototype.destroy = function () { 15865 clearTimeout(this.timeout) 15866 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 15867 } 15868 15869 15870 // TOOLTIP PLUGIN DEFINITION 15871 // ========================= 15872 15873 var old = $.fn.tooltip 15874 15875 $.fn.tooltip = function (option) { 15876 return this.each(function () { 15877 var $this = $(this) 15878 var data = $this.data('bs.tooltip') 15879 var options = typeof option == 'object' && option 15880 15881 if (!data && option == 'destroy') return 15882 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 15883 if (typeof option == 'string') data[option]() 15884 }) 15885 } 15886 15887 $.fn.tooltip.Constructor = Tooltip 15888 15889 15890 // TOOLTIP NO CONFLICT 15891 // =================== 15892 15893 $.fn.tooltip.noConflict = function () { 15894 $.fn.tooltip = old 15895 return this 15896 } 15897 15898}(jQuery); 15899 15900 15901/* ======================================================================== 15902 * Bootstrap: transition.js v3.1.1 15903 * http://getbootstrap.com/javascript/#transitions 15904 * ======================================================================== 15905 * Copyright 2011-2014 Twitter, Inc. 15906 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15907 * ======================================================================== */ 15908 15909 15910+function ($) { 15911 'use strict'; 15912 15913 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 15914 // ============================================================ 15915 15916 function transitionEnd() { 15917 var el = document.createElement('bootstrap') 15918 15919 var transEndEventNames = { 15920 WebkitTransition : 'webkitTransitionEnd', 15921 MozTransition : 'transitionend', 15922 OTransition : 'oTransitionEnd otransitionend', 15923 transition : 'transitionend' 15924 } 15925 15926 for (var name in transEndEventNames) { 15927 if (el.style[name] !== undefined) { 15928 return { end: transEndEventNames[name] } 15929 } 15930 } 15931 15932 return false // explicit for ie8 ( ._.) 15933 } 15934 15935 // http://blog.alexmaccaw.com/css-transitions 15936 $.fn.emulateTransitionEnd = function (duration) { 15937 var called = false, $el = this 15938 $(this).one($.support.transition.end, function () { called = true }) 15939 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 15940 setTimeout(callback, duration) 15941 return this 15942 } 15943 15944 $(function () { 15945 $.support.transition = transitionEnd() 15946 }) 15947 15948}(jQuery); 15949 15950
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.