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($(e.target)); 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($(e.target)); }, 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 sub is collapsible (mobile view) 5927 if (this.isCollapsible()) { 5928 if (this.opts.collapsibleHideFunction) { 5929 this.opts.collapsibleHideFunction.call(this, $sub, complete); 5930 } else { 5931 $sub.hide(this.opts.collapsibleHideDuration, complete); 5932 } 5933 } else { 5934 if (this.opts.hideFunction) { 5935 this.opts.hideFunction.call(this, $sub, complete); 5936 } else { 5937 $sub.hide(this.opts.hideDuration, complete); 5938 } 5939 } 5940 // remove IE iframe shim 5941 if ($sub.dataSM('ie-shim')) { 5942 $sub.dataSM('ie-shim').remove(); 5943 } 5944 // deactivate scrolling if it is activated for this sub 5945 if ($sub.dataSM('scroll')) { 5946 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 5947 } 5948 // unhighlight parent item 5949 $sub.dataSM('parent-a').removeClass('highlighted'); 5950 var level = $sub.dataSM('level'); 5951 this.activatedItems.splice(level - 1, 1); 5952 this.visibleSubMenus.splice(level - 1, 1); 5953 this.$root.triggerHandler('hide.smapi', $sub[0]); 5954 } 5955 }, 5956 menuHideAll: function($item) { 5957 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 5958 if (this.showTimeout) { 5959 clearTimeout(this.showTimeout); 5960 this.showTimeout = 0; 5961 } 5962 // hide all subs 5963 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 5964 this.menuHide(this.visibleSubMenus[i]); 5965 } 5966 // hide root if it's popup 5967 if (this.opts.isPopup) { 5968 this.$root.stop(true, true); 5969 if (this.$root.is(':visible')) { 5970 if (this.opts.hideFunction) { 5971 this.opts.hideFunction.call(this, this.$root); 5972 } else { 5973 this.$root.hide(this.opts.hideDuration); 5974 } 5975 // remove IE iframe shim 5976 if (this.$root.dataSM('ie-shim')) { 5977 this.$root.dataSM('ie-shim').remove(); 5978 } 5979 } 5980 } 5981 this.activatedItems = []; 5982 this.visibleSubMenus = []; 5983 this.clickActivated = false;
5984 // reset z-index increment 5985 this.zIndexInc = 0; 5986 }, 5987 menuIframeShim: function($ul) { 5988 // create iframe shim for the menu 5989 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 5990 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 5991 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 5992 ); 5993 } 5994 }, 5995 menuInit: function($ul) { 5996 if (!$ul.dataSM('in-mega')) { 5997 this.subMenus.push($ul); 5998 // mark UL's in mega drop downs (if any) so we can neglect them 5999 if ($ul.hasClass('mega-menu')) { 6000 $ul.find('ul').dataSM('in-mega', true); 6001 } 6002 // get level (much faster than, for example, using parentsUntil) 6003 var level = 2, 6004 par = $ul[0]; 6005 while ((par = par.parentNode.parentNode) != this.$root[0]) { 6006 level++; 6007 } 6008 // cache stuff 6009 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 6010 .dataSM('level', level) 6011 .parent().dataSM('sub', $ul); 6012 // add sub indicator to parent item 6013 if (this.opts.subIndicators) { 6014 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 6015 } 6016 } 6017 }, 6018 menuPosition: function($sub) { 6019 var fixIE = $('html.ie').length; 6020 // if (fixIE) { 6021 // var $rowParent = $($sub).closest('.main-menu-container'); 6022 // $rowParent.height($rowParent.height()); 6023 // } 6024 var $a = $sub.dataSM('parent-a'), 6025 $li = $sub.parent(), 6026 $ul = $sub.parent().parent(), 6027 $container = $ul.closest('.row-menu-inner'), 6028 level = $sub.dataSM('level'), 6029 subW = this.getWidth($sub), 6030 subH = this.getHeight($sub), 6031 itemOffset = $a.offset(), 6032 itemX = itemOffset.left, 6033 itemY = itemOffset.top, 6034 itemW = this.getWidth($a), 6035 itemH = this.getHeight($a), 6036 $win = $(window), 6037 winX = $win.scrollLeft(), 6038 winY = $win.scrollTop(), 6039 winW = $win.width(), 6040 winH = $win.height(), 6041 containerW = $container.width(), 6042 containerOffsetX = containerW + ((winW - containerW) / 2), 6043 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 6044 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 6045 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 6046 x, y, leftPos; 6047 if (horizontalParent) { 6048 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 6049 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 6050 } else { 6051 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX; 6052 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 6053 } 6054 if (this.opts.keepInViewport && !this.isCollapsible()) { 6055 if (this.isFixed()) { 6056 itemX -= winX; 6057 itemY -= winY; 6058 winX = winY = 0; 6059 } 6060 var absX = itemX + x, 6061 absY = itemY + y; 6062 if (this.opts.rightToLeftSubMenus && absX < winX) { 6063 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 6064 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 6065 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 6066 } 6067 if (!horizontalParent) { 6068 if (subH < winH && absY + subH > winY + winH) { 6069 y += winY + winH - subH - absY; 6070 } else if (subH >= winH || absY < winY) { 6071 y += winY - absY; 6072 } 6073 } 6074 // do we need scrolling? 6075 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 6076 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 6077 var self = this; 6078 if (!$sub.dataSM('scroll-arrows')) { 6079 $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]]) 6080 .bind({ 6081 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 6082 mouseleave: function(e) { 6083 self.menuScrollStop($sub); 6084 self.menuScrollOut($sub, e); 6085 }, 6086 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 6087 }) 6088 .insertAfter($sub) 6089 ); 6090 } 6091 // bind events to show/hide arrows on hover and save scrolling data for this sub 6092 var vportY = winY - (itemY + itemH); 6093 $sub.dataSM('scroll', { 6094 vportY: vportY, 6095 subH: subH, 6096 winH: winH, 6097 step: 1 6098 }) 6099 .bind({ 6100 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 6101 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 6102 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 6103 }) 6104 .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
6104StartZIndex() + this.zIndexInc }) 6105 .eq(0).css('margin-top', vportY).end() 6106 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 6107 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 6108 } 6109 } 6110 // if ($sub.hasClass('mega-menu-inner')) { 6111 // if ($('.menu-wrapper .megamenu-diff').length > 0) { 6112 // leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth()); 6113 // leftPos = -leftPos; 6114 // } else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft')); 6115 6116 // if ($('body.header-full-width').length > 0) { 6117 // $sub.css({ width: $('.box-container').width()}); 6118 // leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft'))); 6119 // } else $sub.css({ width: containerW}); 6120 // leftPos = leftPos + 'px'; 6121 6122 // } else { 6123 // leftPos = $li.position().left + 'px'; 6124 // } 6125 if ($sub.hasClass('mega-menu-inner')) { 6126 $sub.css({ width: containerW}); 6127 if ($('body.hmenu-center-split').length > 0) { 6128 leftPos = - ($sub.closest('#menu-main-menu')[0].offsetLeft) + 'px'; 6129 } else { 6130 if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0) { 6131 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 6132 } else { 6133 leftPos = '0px'; 6134 } 6135 } 6136 } else { 6137 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 6138 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 6139 } 6140 6141 $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) }); 6142 // IE iframe shim 6143 this.menuIframeShim($sub); 6144 if ($sub.dataSM('ie-shim')) { 6145 $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) }); 6146 } 6147 }, 6148 menuScroll: function($sub, up, wheel) { 6149 var y = parseFloat($sub.css('margin-top')), 6150 scroll = $sub.dataSM('scroll'), 6151 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 6152 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 6153 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 6154 y = parseFloat($sub.css('margin-top')); 6155 // show opposite arrow if appropriate 6156 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 6157 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 6158 } 6159 // accelerate when not using mousewheel to scroll 6160 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 6161 $sub.dataSM('scroll').step += 0.5; 6162 } 6163 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 6164 if (Math.abs(y - end) < 1) { 6165 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 6166 $sub.dataSM('scroll').step = 1; 6167 } else if (!wheel) { 6168 var self = this; 6169 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 6170 } 6171 }, 6172 menuScrollMousewheel: function($sub, e) { 6173 var $closestSub = $(e.target).closest('ul'); 6174 while ($closestSub.dataSM('in-mega')) { 6175 $closestSub = $closestSub.parent().closest('ul'); 6176 } 6177 if ($closestSub[0] == $sub[0]) { 6178 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 6179 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 6180 this.menuScroll($sub, up, true); 6181 } 6182 } 6183 e.preventDefault(); 6184 }, 6185 menuScrollOut: function($sub, e) { 6186 var reClass = /^scroll-(up|down)/, 6187 $closestSub = $(e.relatedTarget).closest('ul'); 6188 while ($closestSub.dataSM('in-mega')) { 6189 $closestSub = $closestSub.parent().closest('ul'); 6190 } 6191 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 6192 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 6193 } 6194 }, 6195 menuScrollOver: function($sub, e) { 6196 var reClass = /^scroll-(up|down)/, 6197 $closestSub = $(e.target).closest('ul'); 6198 while ($closestSub.dataSM('in-mega')) { 6199 $closestSub = $closestSub.parent().closest('ul'); 6200 } 6201 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 6202 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 6203 } 6204 }, 6205 menuScrollStop: function($sub) { 6206 if (this.scrollTimeout) { 6207 clearTimeout(this.scrollTimeout); 6208 this.scrollTimeout = 0; 6209 $sub.dataSM('scroll').step = 1; 6210 } 6211 }, 6212 menuShow: function($sub) { 6213 if (!$sub.dataSM('beforefirstshowfired')) { 6214 $sub.dataSM('beforefirstshowfired', true); 6215 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 6216 return; 6217 } 6218 } 6219 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 6220 return; 6221 } 6222 this.menuFixLayout($sub); 6223 $sub.stop(true, true); 6224 if (!$sub.is(':visible')) { 6225 // set z-index - for IE < 9 set it to the parent LI
6226 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 6227 if (IElt9) { 6228 $sub.parent().css('z-index', zIndex); 6229 } else { 6230 $sub.css('z-index', zIndex); 6231 } 6232 // highlight parent item 6233 if (this.opts.keepHighlighted || this.isCollapsible()) { 6234 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 6235 $sub.dataSM('parent-a').addClass('highlighted'); 6236 } 6237 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 6238 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 6239 if (!IElt8) { 6240 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6241 if (this.opts.subMenusMinWidth) { 6242 $sub.css('min-width', this.opts.subMenusMinWidth); 6243 } 6244 if (this.opts.subMenusMaxWidth) { 6245 var noMaxWidth = this.getWidth($sub); 6246 $sub.css('max-width', this.opts.subMenusMaxWidth); 6247 if (noMaxWidth > this.getWidth($sub)) { 6248 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6249 } 6250 } 6251 // IE6,7 6252 } else { 6253 $sub.children().css('styleFloat', 'none'); 6254 if (IE6) { 6255 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 6256 .children().children('a').css('white-space', 'nowrap'); 6257 } else { // IE7 6258 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6259 if (this.opts.subMenusMinWidth) { 6260 $sub.css('min-width', this.opts.subMenusMinWidth); 6261 } 6262 } 6263 if (this.opts.subMenusMaxWidth) { 6264 var noMaxWidth = $sub.width(); 6265 if (IE6) { 6266 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 6267 if (noMaxWidth > maxWidth) { 6268 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 6269 } else { 6270 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 6271 } 6272 } else { // IE7 6273 $sub.css('max-width', this.opts.subMenusMaxWidth); 6274 if (noMaxWidth > $sub.width()) { 6275 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6276 } else { 6277 $sub.width(noMaxWidth); 6278 } 6279 } 6280 } else { 6281 $sub.width($sub.width()); 6282 } 6283 $sub.children().css('styleFloat', 'left'); 6284 } 6285 } 6286 this.menuPosition($sub); 6287 // insert IE iframe shim 6288 if ($sub.dataSM('ie-shim')) { 6289 $sub.dataSM('ie-shim').insertBefore($sub); 6290 } 6291 var complete = function() { 6292 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 6293 $sub.css('overflow', ''); 6294 }; 6295 // if sub is collapsible (mobile view) 6296 if (this.isCollapsible()) { 6297 if (this.opts.collapsibleShowFunction) { 6298 this.opts.collapsibleShowFunction.call(this, $sub, complete); 6299 } else { 6300 $sub.show(this.opts.collapsibleShowDuration, complete); 6301 } 6302 } else { 6303 if (this.opts.showFunction) { 6304 this.opts.showFunction.call(this, $sub, complete); 6305 } else { 6306 $sub.show(this.opts.showDuration, complete); 6307 } 6308 } 6309 // save new sub menu for this level 6310 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 6311 this.$root.triggerHandler('show.smapi', $sub[0]); 6312 } 6313 }, 6314 popupHide: function(noHideTimeout) { 6315 if (this.hideTimeout) { 6316 clearTimeout(this.hideTimeout); 6317 this.hideTimeout = 0; 6318 } 6319 var self = this; 6320 this.hideTimeout = setTimeout(function() { 6321 self.menuHideAll(); 6322 }, noHideTimeout ? 1 : this.opts.hideTimeout); 6323 }, 6324 popupShow: function(left, top) { 6325 if (!this.opts.isPopup) { 6326 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 6327 return; 6328 } 6329 if (this.hideTimeout) { 6330 clearTimeout(this.hideTimeout); 6331 this.hideTimeout = 0; 6332 } 6333 this.menuFixLayout(this.$root); 6334 this.$root.stop(true, true); 6335 if (!this.$root.is(':visible')) { 6336 this.$root.css({ left: left, top: top }); 6337 // IE iframe shim 6338 this.menuIframeShim(this.$root); 6339 if (this.$root.dataSM('ie-shim')) { 6340 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6340: left, top: top }).insertBefore(this.$root); 6341 } 6342 // show menu 6343 if (this.opts.showFunction) { 6344 this.opts.showFunction.call(this, this.$root); 6345 } else { 6346 this.$root.show(this.opts.showDuration); 6347 } 6348 this.visibleSubMenus[0] = this.$root; 6349 } 6350 }, 6351 refresh: function() { 6352 this.menuHideAll(); 6353 this.$root.find('ul').each(function() { 6354 var $this = $(this); 6355 if ($this.dataSM('scroll-arrows')) { 6356 $this.dataSM('scroll-arrows').remove(); 6357 } 6358 }) 6359 .removeDataSM('in-mega') 6360 .removeDataSM('shown-before') 6361 .removeDataSM('ie-shim') 6362 .removeDataSM('scroll-arrows') 6363 .removeDataSM('parent-a') 6364 .removeDataSM('level') 6365 .removeDataSM('beforefirstshowfired'); 6366 this.$root.find('a.has-submenu').removeClass('has-submenu') 6367 .parent().removeDataSM('sub'); 6368 if (this.opts.subIndicators) { 6369 this.$root.find('span.sub-arrow').remove(); 6370 } 6371 if (this.opts.markCurrentItem) { 6372 this.$root.find('a.current').removeClass('current'); 6373 } 6374 this.subMenus = []; 6375 this.init(true); 6376 }, 6377 rootOut: function(e) { 6378 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6379 return; 6380 } 6381 if (this.hideTimeout) { 6382 clearTimeout(this.hideTimeout); 6383 this.hideTimeout = 0; 6384 } 6385 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 6386 var self = this; 6387 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 6388 } 6389 }, 6390 rootOver: 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 }, 6399 winResize: function(e) { 6400 if (!this.handleEvents()) { 6401 // we still need to resize the disable overlay if it's visible 6402 if (this.$disableOverlay) { 6403 var pos = this.$root.offset(); 6404 this.$disableOverlay.css({ 6405 top: pos.top, 6406 left: pos.left, 6407 width: this.$root.outerWidth(), 6408 height: this.$root.outerHeight() 6409 }); 6410 } 6411 return; 6412 } 6413 // hide sub menus on resize - on mobile do it only on orientation change 6414 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 6415 if (this.activatedItems.length) { 6416 this.activatedItems[this.activatedItems.length - 1][0].blur(); 6417 } 6418 this.menuHideAll(); 6419 } 6420 } 6421 } 6422 }); 6423 6424 $.fn.dataSM = function(key, val) { 6425 if (val) { 6426 return this.data(key + '_smartmenus', val); 6427 } 6428 return this.data(key + '_smartmenus'); 6429 } 6430 6431 $.fn.removeDataSM = function(key) { 6432 return this.removeData(key + '_smartmenus'); 6433 } 6434 6435 $.fn.smartmenus = function(options) { 6436 if (typeof options == 'string') { 6437 var args = arguments, 6438 method = options; 6439 Array.prototype.shift.call(args); 6440 return this.each(function() { 6441 var smartmenus = $(this).data('smartmenus'); 6442 if (smartmenus && smartmenus[method]) { 6443 smartmenus[method].apply(smartmenus, args); 6444 } 6445 }); 6446 } 6447 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 6448 return this.each(function() { 6449 new $.SmartMenus(this, opts); 6450 }); 6451 } 6452 6453 // default settings 6454 $.fn.smartmenus.defaults = { 6455 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 6456 mainMenuSubOffsetX: 0, // pixels offset from default position
6457 mainMenuSubOffsetY: 0, // pixels offset from default position 6458 subMenusSubOffsetX: 0, // pixels offset from default position 6459 subMenusSubOffsetY: 0, // pixels offset from default position 6460 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6461 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6462 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 6463 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 6464 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 6465 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 6466 scrollInterval: 30, // interval between each scrolling step 6467 scrollAccelerate: true, // accelerate scrolling or use a fixed step 6468 showTimeout: 250, // timeout before showing the sub menus 6469 hideTimeout: 500, // timeout before hiding the sub menus 6470 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 6471 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 6472 // don't forget to call complete() at the end of whatever you do 6473 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 6474 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 6475 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 6476 // don't forget to call complete() at the end of whatever you do 6477 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 6478 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 6479 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 6480 // (i.e. when mobile styles are used to make the sub menus collapsible) 6481 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 6482 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 6483 // (i.e. when mobile styles are used to make the sub menus collapsible) 6484 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 6485 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 6486 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 6487 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 6488 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 6489 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 6490 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 6491 bottomToTopSubMenus: false, // bottom to top display of the sub menus 6492 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 6493 }; 6494 6495})(jQuery); 6496 6497/* 6498 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 6499 * 6500 * Uses the built in easing capabilities added In jQuery 1.1 6501 * to offer multiple easing options 6502 * 6503 * TERMS OF USE - jQuery Easing 6504 * 6505 * Open source under the BSD License. 6506 * 6507 * Copyright © 2008 George McGinley Smith 6508 * All rights reserved. 6509 * 6510 * Redistribution and use in source and binary forms, with or without modification, 6511 * are permitted provided that the following conditions are met: 6512 * 6513 * Redistributions of source code must retain the above copyright notice, this list of 6514 * conditions and the following disclaimer. 6515 * Redistributions in binary form must reproduce the above copyright notice, this list 6516 * of conditions and the following disclaimer in the documentation and/or other materials 6517 * provided with the distribution. 6518 * 6519 * Neither the name of the author nor the names of contributors may be used to endorse 6520 * or promote products derived from this software without specific prior written permission. 6521 * 6522 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6523 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6524 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6525 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6526-6671
6526 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6527 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6528 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6529 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6530 * OF THE POSSIBILITY OF SUCH DAMAGE. 6531 * 6532*/ 6533 6534// t: current time, b: begInnIng value, c: change In value, d: duration 6535jQuery.easing['jswing'] = jQuery.easing['swing']; 6536 6537jQuery.extend( jQuery.easing, 6538{ 6539 def: 'easeOutQuad', 6540 swing: function (x, t, b, c, d) { 6541 //alert(jQuery.easing.default); 6542 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 6543 }, 6544 easeInQuad: function (x, t, b, c, d) { 6545 return c*(t/=d)*t + b; 6546 }, 6547 easeOutQuad: function (x, t, b, c, d) { 6548 return -c *(t/=d)*(t-2) + b; 6549 }, 6550 easeInOutQuad: function (x, t, b, c, d) { 6551 if ((t/=d/2) < 1) return c/2*t*t + b; 6552 return -c/2 * ((--t)*(t-2) - 1) + b; 6553 }, 6554 easeInCubic: function (x, t, b, c, d) { 6555 return c*(t/=d)*t*t + b; 6556 }, 6557 easeOutCubic: function (x, t, b, c, d) { 6558 return c*((t=t/d-1)*t*t + 1) + b; 6559 }, 6560 easeInOutCubic: function (x, t, b, c, d) { 6561 if ((t/=d/2) < 1) return c/2*t*t*t + b; 6562 return c/2*((t-=2)*t*t + 2) + b; 6563 }, 6564 easeInQuart: function (x, t, b, c, d) { 6565 return c*(t/=d)*t*t*t + b; 6566 }, 6567 easeOutQuart: function (x, t, b, c, d) { 6568 return -c * ((t=t/d-1)*t*t*t - 1) + b; 6569 }, 6570 easeInOutQuart: function (x, t, b, c, d) { 6571 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 6572 return -c/2 * ((t-=2)*t*t*t - 2) + b; 6573 }, 6574 easeInQuint: function (x, t, b, c, d) { 6575 return c*(t/=d)*t*t*t*t + b; 6576 }, 6577 easeOutQuint: function (x, t, b, c, d) { 6578 return c*((t=t/d-1)*t*t*t*t + 1) + b; 6579 }, 6580 easeInOutQuint: function (x, t, b, c, d) { 6581 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 6582 return c/2*((t-=2)*t*t*t*t + 2) + b; 6583 }, 6584 easeInSine: function (x, t, b, c, d) { 6585 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 6586 }, 6587 easeOutSine: function (x, t, b, c, d) { 6588 return c * Math.sin(t/d * (Math.PI/2)) + b; 6589 }, 6590 easeInOutSine: function (x, t, b, c, d) { 6591 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 6592 }, 6593 easeInExpo: function (x, t, b, c, d) { 6594 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 6595 }, 6596 easeOutExpo: function (x, t, b, c, d) { 6597 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 6598 }, 6599 easeInOutExpo: function (x, t, b, c, d) { 6600 if (t==0) return b; 6601 if (t==d) return b+c; 6602 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 6603 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 6604 }, 6605 easeInCirc: function (x, t, b, c, d) { 6606 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 6607 }, 6608 easeOutCirc: function (x, t, b, c, d) { 6609 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 6610 }, 6611 easeInOutCirc: function (x, t, b, c, d) { 6612 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 6613 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 6614 }, 6615 easeInElastic: function (x, t, b, c, d) { 6616 var s=1.70158;var p=0;var a=c; 6617 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6618 if (a < Math.abs(c)) { a=c; var s=p/4; } 6619 else var s = p/(2*Math.PI) * Math.asin (c/a); 6620 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6621 }, 6622 easeOutElastic: function (x, t, b, c, d) { 6623 var s=1.70158;var p=0;var a=c; 6624 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6625 if (a < Math.abs(c)) { a=c; var s=p/4; } 6626 else var s = p/(2*Math.PI) * Math.asin (c/a); 6627 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 6628 }, 6629 easeInOutElastic: function (x, t, b, c, d) { 6630 var s=1.70158;var p=0;var a=c; 6631 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 6632 if (a < Math.abs(c)) { a=c; var s=p/4; } 6633 else var s = p/(2*Math.PI) * Math.asin (c/a); 6634 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6635 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 6636 }, 6637 easeInBack: function (x, t, b, c, d, s) { 6638 if (s == undefined) s = 1.70158; 6639 return c*(t/=d)*t*((s+1)*t - s) + b; 6640 }, 6641 easeOutBack: function (x, t, b, c, d, s) { 6642 if (s == undefined) s = 1.70158; 6643 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 6644 }, 6645 easeInOutBack: function (x, t, b, c, d, s) { 6646 if (s == undefined) s = 1.70158; 6647 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 6648 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 6649 }, 6650 easeInBounce: function (x, t, b, c, d) { 6651 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 6652 }, 6653 easeOutBounce: function (x, t, b, c, d) { 6654 if ((t/=d) < (1/2.75)) { 6655 return c*(7.5625*t*t) + b; 6656 } else if (t < (2/2.75)) { 6657 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 6658 } else if (t < (2.5/2.75)) { 6659 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 6660 } else { 6661 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 6662 } 6663 }, 6664 easeInOutBounce: function (x, t, b, c, d) { 6665 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 6666 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 6667 } 6668}); 6669 6670/* 6671 *
6672 * TERMS OF USE - EASING EQUATIONS 6673 * 6674 * Open source under the BSD License. 6675 * 6676 * Copyright © 2001 Robert Penner 6677 * All rights reserved. 6678 * 6679 * Redistribution and use in source and binary forms, with or without modification, 6680 * are permitted provided that the following conditions are met: 6681 * 6682 * Redistributions of source code must retain the above copyright notice, this list of 6683 * conditions and the following disclaimer. 6684 * Redistributions in binary form must reproduce the above copyright notice, this list 6685 * of conditions and the following disclaimer in the documentation and/or other materials 6686 * provided with the distribution. 6687 * 6688 * Neither the name of the author nor the names of contributors may be used to endorse 6689 * or promote products derived from this software without specific prior written permission. 6690 * 6691 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6692 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6693 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6694 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 6695 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6696 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6697 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6698 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6699 * OF THE POSSIBILITY OF SUCH DAMAGE. 6700 * 6701 */ 6702 6703(function($, window, undefined) { 6704 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 6705 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 6706 6707 // requestAnimationFrame polyfill by Erik Möller 6708 // fixes from Paul Irish and Tino Zijdel 6709 6710 var lastTime = 0, 6711 running, 6712 animate = function (elem) { 6713 if (running) { 6714 window.requestAnimationFrame(animate, elem); 6715 jQuery.fx.tick(); 6716 } 6717 }, 6718 vendors = ['ms', 'moz', 'webkit', 'o']; 6719 6720 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 6721 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 6722 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 6723 || window[vendors[x]+'CancelRequestAnimationFrame']; 6724 } 6725 6726 if (!window.requestAnimationFrame) 6727 window.requestAnimationFrame = function(fn, element) { 6728 var currTime = new Date().getTime(), 6729 delta = currTime - lastTime, 6730 timeToCall = Math.max(0, 16 - delta); 6731 6732 var id = window.setTimeout(function() { 6733 fn(currTime + timeToCall); 6734 }, 6735 timeToCall 6736 ); 6737 6738 lastTime = currTime + timeToCall; 6739 6740 return id; 6741 }; 6742 6743 if (!window.cancelAnimationFrame) { 6744 window.cancelAnimationFrame = function(id) { 6745 clearTimeout(id); 6746 }; 6747 } 6748 6749 jQuery.fx.timer = function (timer) { 6750 if (timer() && jQuery.timers.push(timer) && !running) { 6751 running = true; 6752 animate(timer.elem); 6753 } 6754 }; 6755 6756 jQuery.fx.stop = function() { 6757 running = false; 6758 }; 6759 6760}(jQuery, this)); 6761 6762/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 6763 * Licensed under the MIT License (LICENSE.txt). 6764 * 6765 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 6766 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6767 * Thanks to: Seamus Leahy for adding deltaX and deltaY 6768 * 6769 * Version: 3.0.6 6770 * 6771 * Requires: 1.2.2+ 6772 */ 6773(function($) { 6774 var types = ['DOMMouseScroll', 'mousewheel']; 6775 if ($.event.fixHooks) { 6776 for (var i = types.length; i;) { 6777 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 6778 } 6779 } 6780 $.event.special.mousewheel = { 6781 setup: function() { 6782 if (this.addEventListener) { 6783 for (var i = types.length; i;) { 6784 this.addEventListener(types[--i], handler, false); 6785 } 6786 } else { 6787 this.onmousewheel = handler; 6788 } 6789 }, 6790 teardown: function() { 6791 if (this.removeEventListener) { 6792 for (var i = types.length; i;) { 6793 this.removeEventListener(types[--i], handler, false); 6794 } 6795 } else { 6796 this.onmousewheel = null; 6797 } 6798 } 6799 }; 6800 $.fn.extend({ 6801 mousewheel: function(fn) { 6802 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 6803 }, 6804 unmousewheel: function(fn) { 6805 return this.unbind("mousewheel", fn); 6806 } 6807 }); 6808 6809 function handler(event) { 6810 var orgEvent = event || window.event, 6811 args = [].slice.call(arguments, 1), 6812 delta = 0, 6813 returnValue = true, 6814 deltaX = 0, 6815 deltaY = 0; 6816 event = $.event.fix(orgEvent); 6817 event.type = "mousewheel"; 6818 // Old school scrollwheel delta 6819 if (orgEvent.wheelDelta) { 6820 delta = orgEvent.wheelDelta / 120; 6821 } 6822 if (orgEvent.detail) { 6823 delta = -orgEvent.detail / 3; 6824 } 6825 // New school multidimensional scroll (touchpads) deltas 6826 deltaY = delta; 6827 // Gecko 6828 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 6829 deltaY = 0; 6830 deltaX = -1 * delta; 6831 } 6832 // Webkit 6833 if (orgEvent.wheelDeltaY !== undefined) { 6834 deltaY = orgEvent.wheelDeltaY / 120; 6835 } 6836 if (orgEvent.wheelDeltaX !== undefined) { 6837 deltaX = -1 * orgEvent.wheelDeltaX / 120; 6838 } 6839 // Add event and delta to the front of the arguments 6840 args.unshift(event, delta, deltaX, deltaY); 6841 return ($.event.dispatch || $.event.handle).apply(this, args); 6842 } 6843})(jQuery); 6844 6845/** 6846 * jQuery iLightBox - Revolutionary Lightbox Plugin 6847 * http://www.ilightbox.net/ 6848 * 6849 * @version: 2.2.0 - September 23, 2014 6850 * 6851 * @author: Hemn Chawroka 6852 * http://www.iprodev.com/ 6853 * 6854 */ 6855(function($, window, undefined) { 6856 6857 var extensions = { 6858 flash: ['swf'], 6859 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 6860 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 6861 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 6862 }, 6863 6864 // Global DOM elements 6865 $win = $(window), 6866 $doc = $(document), 6867
6868 // Support indicators 6869 browser, 6870 transform, 6871 gpuAcceleration, 6872 fullScreenApi = '', 6873 supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)), 6874 6875 // Events 6876 clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox", 6877 touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 6878 touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 6879 touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 6880 6881 // Math shorthands 6882 abs = Math.abs, 6883 sqrt = Math.sqrt, 6884 round = Math.round, 6885 max = Math.max, 6886 min = Math.min, 6887 floor = Math.floor, 6888 random = Math.random, 6889 6890 pluginspages = { 6891 quicktime: 'http://www.apple.com/quicktime/download', 6892 flash: 'http://www.adobe.com/go/getflash' 6893 }, 6894 6895 iLightBox = function(el, options, items, instant) { 6896 var iL = this; 6897 6898 iL.options = options, 6899 iL.selector = el.selector || el, 6900 iL.context = el.context, 6901 iL.instant = instant; 6902 6903 if (items.length < 1) iL.attachItems(); 6904 else iL.items = items; 6905 6906 iL.vars = { 6907 total: iL.items.length, 6908 start: 0, 6909 current: null, 6910 next: null, 6911 prev: null, 6912 BODY: $('body'), 6913 loadRequests: 0, 6914 overlay: $('<div class="ilightbox-overlay"></div>'), 6915 loader: $('<div class="ilightbox-loader"><div></div></div>'), 6916 toolbar: $('<div class="ilightbox-toolbar"></div>'), 6917 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 6918 title: $('<div class="ilightbox-title"></div>'), 6919 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 6920 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 6921 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 6922 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 6923 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 6924 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6925 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6926 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6927 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 6928 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'), 6929 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>'), 6930 thumbs: false, 6931 nextLock: false, 6932 prevLock: false, 6933 hashLock: false, 6934 isMobile: false, 6935 mobileMaxWidth: 980, 6936 isInFullScreen: false, 6937 isSwipe: false, 6938 mouseID: 0, 6939 cycleID: 0, 6940 isPaused: 0, 6941 captionHeight: 39, 6942 }; 6943 6944 // Hideable elements with mousemove event 6945 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 6946 6947 iL.normalizeItems(); 6948 6949 //Check necessary plugins 6950 iL.availPlugins(); 6951 6952 //Set startFrom 6953 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 6954 6955 //If randomStart 6956 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 6957 iL.vars.start = iL.options.startFrom; 6958 6959 if (instant) iL.instantCall(); 6960 else iL.patchItemsEvents(); 6961 6962 if (iL.options.linkId) { 6963 iL.hashChangeHandler(); 6964 $win.iLightBoxHashChange(function() { 6965 iL.hashChangeHandler(); 6966 }); 6967 } 6968 6969 if (supportTouch) {
6970 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 6971 replace = "itap"; 6972 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 6973 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 6974 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 6975 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 6976 } 6977 6978 if (iL.options.controls.arrows) { 6979 $.extend(iL.options.styles, { 6980 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6981 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6982 nextOpacity: 0, 6983 prevOpacity: 0 6984 }); 6985 } 6986 }; 6987 6988 //iLightBox helpers 6989 iLightBox.prototype = { 6990 showLoader: function() { 6991 var iL = this; 6992 iL.vars.loadRequests += 1; 6993 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.stop().animate({ 6994 //top: '2px' 6995 opacity: '1' 6996 }, iL.options.show.speed, 'easeOutCirc'); 6997 else iL.vars.loader.stop().animate({ 6998 // left: '2px' 6999 opacity: '1' 7000 }, iL.options.show.speed, 'easeOutCirc'); 7001 }, 7002 7003 hideLoader: function() { 7004 var iL = this; 7005 iL.vars.loadRequests -= 1; 7006 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 7007 if (iL.options.path.toLowerCase() == "horizontal") { 7008 if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({ 7009 //top: '-20px' 7010 opacity: '0' 7011 }, iL.options.show.speed, 'easeInCirc'); 7012 } else { 7013 if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({ 7014 //left: '-20px' 7015 opacity: '0' 7016 }, iL.options.show.speed, 'easeInCirc'); 7017 } 7018 }, 7019 7020 createUI: function() { 7021 var iL = this; 7022 7023 iL.ui = { 7024 currentElement: iL.vars.holder, 7025 nextElement: iL.vars.nextPhoto, 7026 prevElement: iL.vars.prevPhoto, 7027 currentItem: iL.vars.current, 7028 nextItem: iL.vars.next, 7029 prevItem: iL.vars.prev, 7030 hide: function() { 7031 iL.closeAction(); 7032 }, 7033 refresh: function() { 7034 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7035 }, 7036 fullscreen: function() { 7037 iL.fullScreenAction(); 7038 } 7039 }; 7040 }, 7041 7042 attachItems: function() { 7043 var iL = this, 7044 itemsObject = new Array(), 7045 items = new Array(); 7046 7047 $(iL.selector, iL.context).each(function() { 7048 var t = $(this), 7049 URL = t.attr(iL.options.attr) || null, 7050 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 7051 caption = t.data('caption'), 7052 title = t.data('title'), 7053 type = t.data('type') || getTypeByExtension(URL), 7054 clone = t.data('lbox-clone') || false; 7055 7056 items.push({ 7057 URL: URL, 7058 caption: caption, 7059 title: title, 7060 type: type, 7061 options: options, 7062 clone: clone 7063 }); 7064 7065 if (!iL.instant) itemsObject.push(t); 7066 }); 7067 7068 if (iL.vars != undefined) iL.vars.total = items.length; 7069 7070 iL.items = items, 7071 iL.itemsObject = itemsObject; 7072 }, 7073 7074 normalizeItems: function() { 7075 var iL = this, 7076 newItems = new Array(); 7077 7078 $.each(iL.items, function(key, val) { 7079 7080 if (typeof val == "string") val = { 7081 url: val 7082 }; 7083 7084 var URL = val.url || val.URL || null, 7085 options = val.options || {}, 7086 caption = val.caption || null, 7087 title = val.title || null, 7088 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 7089 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 7090 7091 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null), 7092 options.videoType = options.videoType || null, 7093 options.skin = options.skin || iL.options.skin, 7094 options.width = options.width || null, 7095 options.height = options.height || null, 7096 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 7097 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 7098 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 7099 7100 if (type == "video") { 7101 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 7102 7103 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 7104 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 7105 options.html5video.preload = options.html5video.preload || "metadata"; 7106 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
7107 } 7108 7109 if (!options.width || !options.height) { 7110 if (type == "video") options.width = 1280, options.height = 720; 7111 else if (type == "iframe") options.width = '100%', options.height = '90%'; 7112 else if (type == "flash") options.width = 1280, options.height = 720; 7113 } 7114 7115 delete val.url; 7116 val.index = key; 7117 val.URL = URL; 7118 val.caption = caption; 7119 val.title = title; 7120 val.type = type; 7121 val.options = options; 7122 val.ext = ext; 7123 7124 newItems.push(val); 7125 }); 7126 7127 iL.items = newItems; 7128 }, 7129 7130 instantCall: function() { 7131 var iL = this, 7132 key = iL.vars.start; 7133 7134 iL.vars.current = key; 7135 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 7136 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 7137 7138 iL.addContents(); 7139 iL.patchEvents(); 7140 }, 7141 7142 addContents: function() { 7143 var iL = this, 7144 vars = iL.vars, 7145 opts = iL.options, 7146 viewport = getViewport(), 7147 path = opts.path.toLowerCase(), 7148 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 7149 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 7150 }), 7151 needRecognition = recognizingItems.length > 0; 7152 7153 if (opts.mobileOptimizer && !opts.innerToolbar) 7154 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7155 7156 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 7157 7158 if (opts.linkId) 7159 vars.overlay[0].setAttribute('linkid', opts.linkId); 7160 7161 //Add Toolbar Buttons 7162 if (opts.controls.toolbar) { 7163 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 7164 if (opts.controls.fullscreen) 7165 vars.toolbar.append(vars.fullScreenButton); 7166 if (opts.controls.slideshow) 7167 vars.toolbar.append(vars.innerPlayButton); 7168 if (vars.total > 1) 7169 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 7170 } 7171 7172 //Append elements to body 7173 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 7174 7175 if (!opts.innerToolbar) 7176 vars.BODY.append(vars.toolbar); 7177 if (opts.controls.arrows) 7178 vars.BODY.append(vars.nextButton).append(vars.prevButton); 7179 7180 if (opts.controls.thumbnail && vars.total > 1) { 7181 vars.BODY.append(vars.thumbnails); 7182 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 7183 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 7184 vars.thumbs = true; 7185 } 7186 7187 //Configure loader and arrows 7188 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 7189 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 7190 } : { 7191 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 7192 }; 7193 vars.loader.addClass(opts.skin).css(loaderCss); 7194 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 7195 if (path == "horizontal") 7196 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 7197 7198 // Configure arrow buttons 7199 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7200 7201 if (!opts.infinite) { 7202 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.nextButton).add(vars.innerNextButton).removeClass('disabled'); 7203 7204 if (vars.current == 0) 7205 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 7206 7207 if (vars.current >= vars.total - 1) 7208 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 7209 } 7210 7211 if (opts.show.effect) { 7212 vars.overlay.stop().fadeIn(opts.show.speed); 7213 vars.toolbar.stop().fadeIn(opts.show.speed); 7214 } else { 7215 vars.overlay.show(); 7216 vars.toolbar.show(); 7217 } 7218 7219 var length = recognizingItems.length; 7220 if (needRecognition) { 7221 iL.showLoader(); 7222 7223 $.each(recognizingItems, function(key, val) { 7224 var resultFnc = function(result) { 7225 var key = -1, 7226 filter = iL.items.filter(function(e, i, arr) { 7227 if (e.URL == result.url) 7228 key = i; 7229 7230 return e.URL == result.url; 7231 }), 7232 self = iL.items[key]; 7233 7234 if (result) 7235 $.extend(true, self, { 7236 URL: result.source, 7237 type: result.type, 7238 recognized: true, 7239 options: { 7240 html5video: result.html5video, 7241 width: (result.type == "image") ? 0 : (result.width || self.width), 7242 height: (result.type == "image") ? 0 : (result.height || self.height), 7243 thumbnail: self.options.thumbnail || result.thumbnail 7244 } 7245 }); 7246 7247 length--; 7248 7249 if (length == 0) { 7250 iL.hideLoader(); 7251 7252 vars.dontGenerateThumbs = false;
7253 iL.generateThumbnails(); 7254 7255 if (opts.show.effect) 7256 setTimeout(function() { 7257 iL.generateBoxes(); 7258 }, opts.show.speed); 7259 else 7260 iL.generateBoxes(); 7261 } 7262 }; 7263 7264 iL.ogpRecognition(this, resultFnc); 7265 }); 7266 } 7267 else { 7268 if (opts.show.effect) 7269 setTimeout(function() { 7270 iL.generateBoxes(); 7271 }, opts.show.speed); 7272 else 7273 iL.generateBoxes(); 7274 } 7275 7276 iL.createUI(); 7277 7278 window.iLightBox = { 7279 close: function() { 7280 iL.closeAction(); 7281 }, 7282 fullscreen: function() { 7283 iL.fullScreenAction(); 7284 }, 7285 moveNext: function() { 7286 iL.moveTo('next'); 7287 }, 7288 movePrev: function() { 7289 iL.moveTo('prev'); 7290 }, 7291 goTo: function(index) { 7292 iL.goTo(index); 7293 }, 7294 refresh: function() { 7295 iL.refresh(); 7296 }, 7297 reposition: function() { 7298 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7299 }, 7300 setOption: function(options) { 7301 iL.setOption(options); 7302 }, 7303 destroy: function() { 7304 iL.closeAction(); 7305 iL.dispatchItemsEvents(); 7306 } 7307 }; 7308 7309 if (opts.linkId) { 7310 vars.hashLock = true; 7311 window.location.hash = opts.linkId + '/' + vars.current; 7312 setTimeout(function() { 7313 vars.hashLock = false; 7314 }, 55); 7315 } 7316 7317 if (!opts.slideshow.startPaused) { 7318 iL.resume(); 7319 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 7320 } 7321 7322 //Trigger the onOpen callback 7323 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 7324 7325 }, 7326 7327 loadContent: function(obj, opt, speed) { 7328 var iL = this, 7329 holder, item; 7330 7331 iL.createUI(); 7332 7333 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 7334 7335 if (opt == 'current') { 7336 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 7337 else iL.vars.lockWheel = false; 7338 7339 if (!obj.options.swipe) iL.vars.lockSwipe = true; 7340 else iL.vars.lockSwipe = false; 7341 } 7342 7343 switch (opt) { 7344 case 'current': 7345 holder = iL.vars.holder, item = iL.vars.current; 7346 break; 7347 case 'next': 7348 holder = iL.vars.nextPhoto, item = iL.vars.next; 7349 break; 7350 case 'prev': 7351 holder = iL.vars.prevPhoto, item = iL.vars.prev; 7352 break; 7353 } 7354 7355 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 7356 $('div.ilightbox-inner-toolbar', holder).remove(); 7357 7358 if (obj.title || iL.options.innerToolbar) { 7359 var innerToolbar = iL.vars.innerToolbar.clone(); 7360 if (obj.title && iL.options.show.title) { 7361 var title = iL.vars.title.clone(); 7362 title.empty().html(obj.title); 7363 innerToolbar.append(title); 7364 } 7365 if (iL.options.innerToolbar) { 7366 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 7367 } 7368 holder.prepend(innerToolbar); 7369 } 7370 7371 iL.loadSwitcher(obj, holder, item, opt); 7372 }, 7373 7374 loadSwitcher: function(obj, holder, item, opt) { 7375 var iL = this, 7376 opts = iL.options, 7377 api = { 7378 element: holder, 7379 position: item 7380 }; 7381 7382 switch (obj.type) { 7383 case 'image': 7384 //Trigger the onBeforeLoad callback 7385 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7386 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7387 7388 iL.loadImage(obj.URL, function(img) { 7389 //Trigger the onAfterLoad callback 7390 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7391 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7392 7393 var width = (img) ? img.width : 400, 7394 height = (img) ? img.height : 200; 7395 7396 holder.data({ 7397 naturalWidth: width, 7398 naturalHeight: height 7399 }); 7400 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 7401 7402 //Trigger the onRender callback 7403 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7404 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7405 7406 iL.configureHolder(obj, opt, holder); 7407 }); 7408 7409 break; 7410
7411 case 'video': 7412 holder.data({ 7413 naturalWidth: obj.options.width, 7414 naturalHeight: obj.options.height 7415 }); 7416 7417 iL.addContent(holder, obj); 7418 7419 //Trigger the onRender callback 7420 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7421 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7422 7423 iL.configureHolder(obj, opt, holder); 7424 7425 break; 7426 7427 case 'iframe': 7428 iL.showLoader(); 7429 holder.data({ 7430 naturalWidth: obj.options.width, 7431 naturalHeight: obj.options.height 7432 }); 7433 var el = iL.addContent(holder, obj); 7434 7435 //Trigger the onRender callback 7436 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7437 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7438 7439 //Trigger the onBeforeLoad callback 7440 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7441 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7442 7443 el.bind('load', function() { 7444 //Trigger the onAfterLoad callback 7445 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7446 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7447 7448 iL.hideLoader(); 7449 iL.configureHolder(obj, opt, holder); 7450 el.unbind('load'); 7451 }); 7452 7453 break; 7454 7455 case 'inline': 7456 var el = $(obj.URL), 7457 content = iL.addContent(holder, obj), 7458 images = findImageInElement(holder); 7459 7460 holder.data({ 7461 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7462 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7463 }); 7464 content.children().eq(0).show(); 7465 7466 //Trigger the onRender callback 7467 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7468 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7469 7470 //Trigger the onBeforeLoad callback 7471 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7472 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7473 7474 iL.loadImage(images, function() { 7475 //Trigger the onAfterLoad callback 7476 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7477 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7478 7479 iL.configureHolder(obj, opt, holder); 7480 }); 7481 7482 break; 7483 7484 case 'flash': 7485 var el = iL.addContent(holder, obj); 7486 7487 holder.data({ 7488 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7489 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7490 }); 7491 7492 //Trigger the onRender callback 7493 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7494 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7495 7496 iL.configureHolder(obj, opt, holder); 7497 7498 break; 7499 7500 case 'ajax': 7501 var ajax = obj.options.ajax || {}; 7502 //Trigger the onBeforeLoad callback 7503 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7504 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7505 7506 iL.showLoader(); 7507 $.ajax({ 7508 url: obj.URL || opts.ajaxSetup.url, 7509 data: ajax.data || null, 7510 dataType: ajax.dataType || "html", 7511 type: ajax.type || opts.ajaxSetup.type, 7512 cache: ajax.cache || opts.ajaxSetup.cache, 7513 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 7514 global: ajax.global || opts.ajaxSetup.global, 7515 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 7516 username: ajax.username || opts.ajaxSetup.username, 7517 password: ajax.password || opts.ajaxSetup.password, 7518 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 7519 complete: ajax.complete || opts.ajaxSetup.complete, 7520 success: function(data, textStatus, jqXHR) { 7521 iL.hideLoader(); 7522 7523 var el = $(data), 7524 container = $('div.ilightbox-container', holder), 7525 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 7526 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 7527 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 7528 'overflow': 'hidden' 7529 } : {}; 7530 7531 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 7532 holder.show().data({
7533 naturalWidth: (elWidth || container.outerWidth()), 7534 naturalHeight: (elHeight || container.outerHeight()) 7535 }).hide(); 7536 7537 //Trigger the onRender callback 7538 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7539 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7540 7541 var images = findImageInElement(holder); 7542 iL.loadImage(images, function() { 7543 //Trigger the onAfterLoad callback 7544 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7545 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7546 7547 iL.configureHolder(obj, opt, holder); 7548 }); 7549 7550 opts.ajaxSetup.success(data, textStatus, jqXHR); 7551 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 7552 }, 7553 error: function(jqXHR, textStatus, errorThrown) { 7554 //Trigger the onAfterLoad callback 7555 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7556 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7557 7558 iL.hideLoader(); 7559 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 7560 iL.configureHolder(obj, opt, holder); 7561 7562 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 7563 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 7564 } 7565 }); 7566 7567 break; 7568 7569 case 'html': 7570 var object = obj.URL, 7571 el 7572 container = $('div.ilightbox-container', holder); 7573 7574 if (object[0].nodeName) el = object.clone(); 7575 else { 7576 var dom = $(object); 7577 if (dom.selector) el = $('<div>' + dom + '</div>'); 7578 else el = dom; 7579 } 7580 7581 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 7582 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 7583 7584 iL.addContent(holder, obj); 7585 7586 el.appendTo(document.documentElement).hide(); 7587 7588 //Trigger the onRender callback 7589 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7590 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7591 7592 var images = findImageInElement(holder); 7593 7594 //Trigger the onBeforeLoad callback 7595 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7596 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7597 7598 iL.loadImage(images, function() { 7599 //Trigger the onAfterLoad callback 7600 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7601 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7602 7603 holder.show().data({ 7604 naturalWidth: (elWidth || container.outerWidth()), 7605 naturalHeight: (elHeight || container.outerHeight()) 7606 }).hide(); 7607 el.remove(); 7608 7609 iL.configureHolder(obj, opt, holder); 7610 }); 7611 7612 break; 7613 } 7614 }, 7615 7616 configureHolder: function(obj, opt, holder) { 7617 var iL = this, 7618 vars = iL.vars, 7619 opts = iL.options; 7620 7621 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 7622 7623 if (opt == "current") 7624 var item = vars.current; 7625 else if (opt == "next") 7626 var opacity = opts.styles.nextOpacity, 7627 item = vars.next; 7628 else 7629 var opacity = opts.styles.prevOpacity, 7630 item = vars.prev; 7631 7632 var api = { 7633 element: holder, 7634 position: item 7635 }; 7636 7637 iL.items[item].options.width = iL.items[item].options.width || 0, 7638 iL.items[item].options.height = iL.items[item].options.height || 0; 7639 7640 if (opt == "current") { 7641 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 7642 holder.css(transform, ''); 7643 if (obj.caption) { 7644 iL.setCaption(obj, holder); 7645 var caption = $('div.ilightbox-caption', holder), 7646 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 7647 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7647Speed); 7648 } 7649 7650 var social = obj.options.social; 7651 if (social) { 7652 iL.setSocial(social, obj.URL, holder); 7653 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 7654 } 7655 7656 //Generate thumbnails 7657 iL.generateThumbnails(); 7658 7659 //Trigger the onShow callback 7660 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7661 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7662 }); 7663 else { 7664 holder.show(); 7665 7666 //Generate thumbnails 7667 iL.generateThumbnails(); 7668 7669 //Trigger the onShow callback 7670 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7671 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7672 } 7673 } else { 7674 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 7675 if (opt == "next") vars.nextLock = false; 7676 else vars.prevLock = false; 7677 7678 //Generate thumbnails 7679 iL.generateThumbnails(); 7680 7681 //Trigger the onShow callback 7682 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7683 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7684 }); 7685 else { 7686 holder.css({ 7687 opacity: opacity 7688 }).show(); 7689 if (opt == "next") vars.nextLock = false; 7690 else vars.prevLock = false; 7691 7692 //Generate thumbnails 7693 iL.generateThumbnails(); 7694 7695 //Trigger the onShow callback 7696 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7697 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7698 } 7699 } 7700 7701 setTimeout(function() { 7702 iL.repositionPhoto(); 7703 }, 0); 7704 }, 7705 7706 generateBoxes: function() { 7707 var iL = this, 7708 vars = iL.vars, 7709 opts = iL.options; 7710 7711 if (opts.infinite && vars.total >= 3) { 7712 if (vars.current == vars.total - 1) vars.next = 0; 7713 if (vars.current == 0) vars.prev = vars.total - 1; 7714 } else opts.infinite = false; 7715 7716 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 7717 7718 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 7719 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 7720 }, 7721 7722 generateThumbnails: function() { 7723 var iL = this, 7724 vars = iL.vars, 7725 opts = iL.options, 7726 timeOut = null; 7727 7728 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 7729 var thumbnails = vars.thumbnails, 7730 container = $('div.ilightbox-thumbnails-container', thumbnails), 7731 grid = $('div.ilightbox-thumbnails-grid', container), 7732 i = 0; 7733 7734 grid.removeAttr('style').empty(); 7735 7736 $.each(iL.items, function(key, val) { 7737 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 7738 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 7739 thumb = val.options.thumbnail, 7740 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 7741 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 7742 7743 thumbnail.css({ 7744 opacity: 0 7745 }).addClass(isActive); 7746 7747 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 7748 icon.addClass('ilightbox-thumbnail-video'); 7749 thumbnail.append(icon); 7750 } else if (val.options.icon) { 7751 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 7752 thumbnail.append(icon); 7753 } 7754 7755 if (thumb) iL.loadImage(thumb, function(img) { 7756 if (val.clone) return; 7757 i++; 7758 if (img) thumbnail.data({ 7759 naturalWidth: img.width, 7760 naturalHeight: img.height 7761 }).append('<img src="' + thumb + '" border="0" />'); 7762 else thumbnail.data({ 7763 naturalWidth: opts.thumbnails.maxWidth, 7764 naturalHeight: opts.thumbnails.maxHeight 7765 }); 7766 7767 clearTimeout(timeOut); 7768 timeOut = setTimeout(function() { 7769 iL.positionThumbnails(thumbnails, container, grid); 7770 }, 20); 7771 setTimeout(function() { 7772 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 7773 }, i * 20); 7774 }); 7775 7776 grid.append(thumbnail); 7777 }); 7778 iL.vars.dontGenerateThumbs = true; 7779 } 7780 }, 7781
7782 positionThumbnails: function(thumbnails, container, grid) { 7783 var iL = this, 7784 vars = iL.vars, 7785 opts = iL.options, 7786 viewport = getViewport(), 7787 path = opts.path.toLowerCase(); 7788 7789 if (!thumbnails) thumbnails = vars.thumbnails; 7790 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 7791 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 7792 7793 var thumbs = $('.ilightbox-thumbnail', grid), 7794 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 7795 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 7796 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 7797 gridHeight = (path == 'horizontal') ? heightAvail : 0, 7798 active = $('.ilightbox-active', grid), 7799 gridCss = {}, 7800 css = {}; 7801 7802 if (arguments.length < 3) { 7803 thumbs.css({ 7804 opacity: opts.thumbnails.normalOpacity 7805 }); 7806 active.css({ 7807 opacity: opts.thumbnails.activeOpacity 7808 }); 7809 } 7810 7811 thumbs.each(function(i) { 7812 var t = $(this), 7813 data = t.data(), 7814 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 7815 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 7816 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 7817 7818 t.css({ 7819 width: dims.width, 7820 height: dims.height 7821 }); 7822 if (path == 'horizontal') t.css({ 7823 'float': 'left' 7824 }); 7825 7826 (path == 'horizontal') ? ( 7827 gridWidth += t.outerWidth() 7828 ) : ( 7829 gridHeight += t.outerHeight() 7830 ); 7831 }); 7832 7833 gridCss = { 7834 width: gridWidth, 7835 height: gridHeight 7836 }; 7837 7838 grid.css(gridCss); 7839 7840 gridCss = {}; 7841 7842 var gridOffset = grid.offset(), 7843 activeOffset = (active.length) ? active.offset() : { 7844 top: parseInt(heightAvail / 2), 7845 left: parseInt(widthAvail / 2) 7846 }; 7847 7848 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 7849 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 7850 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 7851 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 7852 7853 (path == 'horizontal') ? ( 7854 gridCss.top = 0, 7855 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 7856 ) : ( 7857 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 7858 gridCss.left = 0 7859 ); 7860 7861 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 7862 else grid.css(gridCss); 7863 }, 7864 7865 loadImage: function(image, callback) { 7866 if (!$.isArray(image)) image = [image]; 7867 7868 var iL = this, 7869 length = image.length; 7870 7871 if (length > 0) { 7872 iL.showLoader(); 7873 $.each(image, function(index, value) { 7874 var img = new Image(); 7875 img.onload = function() { 7876 length -= 1; 7877 if (length == 0) { 7878 iL.hideLoader(); 7879 callback(img); 7880 } 7881 }; 7882 img.onerror = img.onabort = function() { 7883 length -= 1; 7884 if (length == 0) { 7885 iL.hideLoader(); 7886 callback(false); 7887 } 7888 }; 7889 img.src = image[index]; 7890 }); 7891 } else callback(false); 7892 }, 7893 7894 patchItemsEvents: function() { 7895 var iL = this, 7896 vars = iL.vars, 7897 clickEvent = supportTouch ? "itap.iL" : "click.iL", 7898 vEvent = supportTouch ? "click.iL" : "itap.iL"; 7899 7900 if (iL.context && iL.selector) { 7901 var $items = $(iL.selector, iL.context); 7902 $(iL.context).on(clickEvent, iL.selector, function() { 7903 7904 var $this = $(this), 7905 key = $items.index($this); 7906 if (UNCODE.isMobile) { 7907 var isCarousel = $this.closest('.owl-carousel'); 7908 if (isCarousel.length) { 7909 if (isCarousel.hasClass('owl-translating')) return false; 7910 } 7911 } 7912 7913 vars.current = key; 7914 vars.next = iL.items[key + 1] ? key + 1 : null; 7915 vars.prev = iL.items[key - 1] ? key - 1 : null; 7916 7917 iL.addContents(); 7918 iL.patchEvents(); 7919 7920 return false; 7921 }).on(vEvent, iL.selector, function() { 7922 return false; 7923 }); 7924 } else 7925 $.each(iL.itemsObject, function(key, val) { 7926 val.on(clickEvent, function() { 7927 vars.current = key; 7928 vars.next = iL.items[key + 1] ? key + 1 : null; 7929 vars.prev = iL.items[key - 1] ? key - 1 : null; 7930 7931 iL.addContents(); 7932 iL.patchEvents(); 7933 7934 return false;
7935 }).on(vEvent, function() { 7936 return false; 7937 }); 7938 }); 7939 }, 7940 7941 dispatchItemsEvents: function() { 7942 var iL = this, 7943 vars = iL.vars, 7944 opts = iL.options; 7945 7946 if (iL.context && iL.selector) 7947 $(iL.context).off('.iL', iL.selector); 7948 else 7949 $.each(iL.itemsObject, function(key, val) { 7950 val.off('.iL'); 7951 }); 7952 }, 7953 7954 refresh: function() { 7955 var iL = this; 7956 7957 iL.dispatchItemsEvents(); 7958 iL.attachItems(); 7959 iL.normalizeItems(); 7960 iL.patchItemsEvents(); 7961 }, 7962 7963 patchEvents: function() { 7964 var iL = this, 7965 vars = iL.vars, 7966 opts = iL.options, 7967 path = opts.path.toLowerCase(), 7968 holders = $('.ilightbox-holder'), 7969 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 7970 durationThreshold = 1000, 7971 horizontalDistanceThreshold = 7972 verticalDistanceThreshold = 100, 7973 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 7974 7975 $win.bind('resize.iLightBox', function() { 7976 var viewport = getViewport(); 7977 7978 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7979 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7980 7981 iL.repositionPhoto(null); 7982 if (supportTouch) { 7983 clearTimeout(vars.setTime); 7984 vars.setTime = setTimeout(function() { 7985 var scrollTop = getScrollXY().y; 7986 window.scrollTo(0, scrollTop - 30); 7987 window.scrollTo(0, scrollTop + 30); 7988 window.scrollTo(0, scrollTop); 7989 }, 2000); 7990 } 7991 if (vars.thumbs) iL.positionThumbnails(); 7992 }).bind('keydown.iLightBox', function(event) { 7993 if (opts.controls.keyboard) { 7994 switch (event.keyCode) { 7995 case 13: 7996 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 7997 break; 7998 case 27: 7999 if (opts.keyboard.esc) iL.closeAction(); 8000 break; 8001 case 37: 8002 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 8003 break; 8004 case 38: 8005 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 8006 break; 8007 case 39: 8008 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 8009 break; 8010 case 40: 8011 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 8012 break; 8013 } 8014 } 8015 }); 8016 8017 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 8018 iL.doFullscreen(); 8019 }); 8020 8021 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 8022 return arr.lastIndexOf(e) === i; 8023 }), 8024 holderEvents = ""; 8025 8026 $.each(holderEventsArr, function(key, val) { 8027 if (key != 0) holderEvents += ' '; 8028 holderEvents += val; 8029 }); 8030 8031 $doc.on(clickEvent, '.ilightbox-overlay', function() { 8032 if (opts.overlay.blur) iL.closeAction(); 8033 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 8034 iL.moveTo('next'); 8035 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 8036 iL.moveTo('prev'); 8037 }).on(clickEvent, '.ilightbox-thumbnail', function() { 8038 var t = $(this), 8039 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 8040 index = thumbs.index(t); 8041 8042 if (index != vars.current) iL.goTo(index); 8043 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8044 var caption = $('div.ilightbox-caption', vars.holder), 8045 social = $('div.ilightbox-social', vars.holder), 8046 fadeSpeed = opts.effects.fadeSpeed; 8047 8048 if (vars.nextLock || vars.prevLock) { 8049 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 8050 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 8051 8052 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 8053 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 8054 } else { 8055 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 8056 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 8057 8058 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 8059 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 8060 } 8061 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 8062 if (e.type == 'mouseenter') vars.lockWheel = true; 8063 else vars.lockWheel = false;
8064 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 8065 var t = $(this); 8066 8067 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 8068 else if (t.hasClass('ilightbox-play')) { 8069 iL.resume(); 8070 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 8071 } else if (t.hasClass('ilightbox-pause')) { 8072 iL.pause(); 8073 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 8074 } else iL.closeAction(); 8075 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 8076 // prevent scrolling 8077 e.preventDefault(); 8078 }); 8079 8080 function mouseMoveHandler(e) { 8081 if (!vars.isMobile) { 8082 if (!vars.mouseID) { 8083 vars.hideableElements.show(); 8084 } 8085 8086 vars.mouseID = clearTimeout(vars.mouseID); 8087 8088 if (buttonsArray.indexOf(e.target) === -1) 8089 vars.mouseID = setTimeout(function() { 8090 vars.hideableElements.hide(); 8091 vars.mouseID = clearTimeout(vars.mouseID); 8092 }, 3000); 8093 } 8094 } 8095 8096 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 8097 8098 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8099 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 8100 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 8101 }); 8102 8103 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'); 8104 8105 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 8106 if (!vars.lockWheel) { 8107 event.preventDefault(); 8108 if (delta < 0) iL.moveTo('next'); 8109 else if (delta > 0) iL.moveTo('prev'); 8110 } 8111 }); 8112 8113 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 8114 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 8115 8116 vars.BODY.addClass('ilightbox-closedhand'); 8117 8118 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 8119 scrollTop = $doc.scrollTop(), 8120 scrollLeft = $doc.scrollLeft(), 8121 offsets = [ 8122 holders.eq(0).offset(), 8123 holders.eq(1).offset(), 8124 holders.eq(2).offset() 8125 ], 8126 offSet = [{ 8127 top: offsets[0].top - scrollTop, 8128 left: offsets[0].left - scrollLeft 8129 }, { 8130 top: offsets[1].top - scrollTop, 8131 left: offsets[1].left - scrollLeft 8132 }, { 8133 top: offsets[2].top - scrollTop, 8134 left: offsets[2].left - scrollLeft 8135 }], 8136 start = { 8137 time: (new Date()).getTime(), 8138 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8139 }, 8140 stop; 8141 8142 function moveEachHandler(i) { 8143 var t = $(this), 8144 offset = offSet[i], 8145 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 8146 8147 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 8148 } 8149 8150 function moveHandler(event) { 8151 8152 if (!start) return; 8153 8154 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 8155 8156 stop = { 8157 time: (new Date()).getTime(), 8158 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8159 }; 8160 8161 holders.each(moveEachHandler); 8162 8163 // prevent scrolling 8164 event.preventDefault(); 8165 } 8166 8167 function repositionHolders() { 8168 holders.each(function() { 8169 var t = $(this), 8170 offset = t.data('offset') || { 8171 top: t.offset().top - scrollTop, 8172 left: t.offset().left - scrollLeft 8173 }, 8174 top = offset.top, 8175 left = offset.left; 8176 8177 t.css(transform, gpuAcceleration).stop().animate({ 8178 top: top, 8179 left: left 8180 }, 500, 'easeOutCirc', function() { 8181 t.css(transform, ''); 8182 }); 8183 }); 8184 } 8185 8186 holders.bind(touchMoveEvent, moveHandler); 8187 $doc.one(touchStopEvent, function(event) { 8188 holders.unbind(touchMoveEvent, moveHandler); 8189 8190 vars.BODY.removeClass('ilightbox-closedhand'); 8191 8192 if (start && stop) { 8193 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 8194 if (start.coords[0] > stop.coords[0]) { 8195 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8196 else { 8197 vars.isSwipe = true; 8198 iL.moveTo('next'); 8199 } 8200 } else { 8201 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8202 else { 8203 vars.isSwipe = true; 8204 iL.moveTo('prev'); 8205 } 8206 } 8207 } 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) { 8208 if (start.coords[1] > stop.coords[1]) { 8209 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8210 else { 8211 vars.isSwipe = true; 8212 iL.moveTo('next'); 8213 } 8214 } else { 8215 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8216 else { 8217 vars.isSwipe = true; 8218 iL.moveTo('prev'); 8219 } 8220 } 8221 } else repositionHolders(); 8222 } 8223 start = stop = undefined; 8224 }); 8225 }); 8226 8227 }, 8228 8229 goTo: function(index) { 8230 var iL = this, 8231 vars = iL.vars, 8232 opts = iL.options, 8233 diff = (index - vars.current); 8234 8235 if (opts.infinite) { 8236 if (index == vars.total - 1 && vars.current == 0) diff = -1; 8237 if (vars.current == vars.total - 1 && index == 0) diff = 1; 8238 } 8239 8240 if (diff == 1) iL.moveTo('next'); 8241 else if (diff == -1) iL.moveTo('prev'); 8242 else { 8243 8244 if (vars.nextLock || vars.prevLock) return false;
8245 8246 //Trigger the onBeforeChange callback 8247 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 8248 8249 if (opts.linkId) { 8250 vars.hashLock = true; 8251 window.location.hash = opts.linkId + '/' + index; 8252 } 8253 8254 if (iL.items[index]) { 8255 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 8256 else iL.vars.lockWheel = false; 8257 8258 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 8259 else vars.lockSwipe = false; 8260 } 8261 8262 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 8263 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 8264 }); 8265 8266 vars.current = index; 8267 vars.next = index + 1; 8268 vars.prev = index - 1; 8269 8270 iL.createUI(); 8271 8272 setTimeout(function() { 8273 iL.generateBoxes(); 8274 }, opts.effects.loadedFadeSpeed + 50); 8275 8276 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 8277 iL.positionThumbnails(); 8278 8279 if (opts.linkId) setTimeout(function() { 8280 vars.hashLock = false; 8281 }, 55); 8282 8283 // Configure arrow buttons 8284 if (!opts.infinite) { 8285 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8286 8287 if (vars.current == 0) { 8288 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8289 } 8290 if (vars.current >= vars.total - 1) { 8291 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8292 } 8293 } 8294 8295 // Reset next cycle timeout 8296 iL.resetCycle(); 8297 8298 //Trigger the onAfterChange callback 8299 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 8300 } 8301 }, 8302 8303 moveTo: function(side) { 8304 var iL = this, 8305 vars = iL.vars, 8306 opts = iL.options, 8307 path = opts.path.toLowerCase(), 8308 viewport = getViewport(), 8309 switchSpeed = opts.effects.switchSpeed; 8310 8311 if (vars.nextLock || vars.prevLock) return false; 8312 else { 8313 8314 var item = (side == "next") ? vars.next : vars.prev; 8315 8316 if (opts.linkId) { 8317 vars.hashLock = true; 8318 window.location.hash = opts.linkId + '/' + item; 8319 } 8320 8321 if (side == "next") { 8322 if (!iL.items[item]) return false; 8323 var firstHolder = vars.nextPhoto, 8324 secondHolder = vars.holder, 8325 lastHolder = vars.prevPhoto, 8326 firstClass = 'ilightbox-prev', 8327 secondClass = 'ilightbox-next'; 8328 } else if (side == "prev") { 8329 if (!iL.items[item]) return false; 8330 var firstHolder = vars.prevPhoto, 8331 secondHolder = vars.holder, 8332 lastHolder = vars.nextPhoto, 8333 firstClass = 'ilightbox-next', 8334 secondClass = 'ilightbox-prev'; 8335 } 8336 8337 //Trigger the onBeforeChange callback 8338 if (typeof opts.callback.onBeforeChange == 'function') 8339 opts.callback.onBeforeChange.call(iL, iL.ui); 8340 8341 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 8342 8343 var captionFirst = $('div.ilightbox-caption', secondHolder), 8344 socialFirst = $('div.ilightbox-social', secondHolder); 8345 8346 if (captionFirst.length) 8347 captionFirst.stop().fadeOut(switchSpeed, function() { 8348 $(this).remove(); 8349 }); 8350 if (socialFirst.length) 8351 socialFirst.stop().fadeOut(switchSpeed, function() { 8352 $(this).remove(); 8353 }); 8354 8355 if (iL.items[item].caption) { 8356 iL.setCaption(iL.items[item], firstHolder); 8357 var caption = $('div.ilightbox-caption', firstHolder), 8358 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 8359 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 8360 } 8361 8362 var social = iL.items[item].options.social; 8363 if (social) { 8364 iL.setSocial(social, iL.items[item].URL, firstHolder); 8365 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 8366 } 8367 8368 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 8369 val.removeClass('ilightbox-next ilightbox-prev'); 8370 }); 8371 8372 var firstOffset = firstHolder.data('offset'), 8373 winW = (viewport.width - (opts.styles.pageOffsetX)), 8374 winH = (viewport.height - (opts.styles.pageOffsetY)), 8375 width = firstOffset.newDims.width, 8376 height = firstOffset.newDims.height, 8377 thumbsOffset = firstOffset.thumbsOffset, 8378 diff = firstOffset.diff, 8379 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8380 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8381 8382 var secondOffset = secondHolder.data('offset'), 8383 object = secondOffset.object; 8384 8385 if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8386 var objRatio = width / height; 8387 height = height - vars.captionHeight; 8388 width = height * objRatio; 8389 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8390 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8391 } 8392 8393 firstHolder.css(transform, gpuAcceleration).animate({ 8394 top: top, 8395 left: left, 8396 opacity: 1 8397 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8398 firstHolder.css(transform, ''); 8399 }); 8400 8401 $('div.ilightbox-container', firstHolder).animate({ 8402 width: width, 8403 height: height 8404 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8405 8406 8407 diff = secondOffset.diff; 8408 8409 width = secondOffset.newDims.width, 8410 height = secondOffset.newDims.height; 8411 8412 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8413 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8414 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 8415 8416 if (side == 'prev') 8417 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 8418 else { 8419 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 8420 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8421 } 8422 8423 if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8424 var objRatio = width / height; 8425 height = height - vars.captionHeight; 8426 width = height * objRatio; 8427 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)); 8428 } 8429 8430 $('div.ilightbox-container', secondHolder).animate({ 8431 width: width, 8432 height: height 8433 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8434 8435 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 8436 top: top, 8437 left: left, 8438 opacity: opts.styles.prevOpacity 8439 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8440 secondHolder.css(transform, ''); 8441
8442 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 8443 iL.positionThumbnails(); 8444 8445 if (iL.items[item]) { 8446 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 8447 else vars.lockWheel = false; 8448 8449 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 8450 else vars.lockSwipe = false; 8451 } 8452 8453 vars.isSwipe = false; 8454 8455 if (side == "next") { 8456 vars.nextPhoto = lastHolder, 8457 vars.prevPhoto = secondHolder, 8458 vars.holder = firstHolder; 8459 8460 vars.nextPhoto.hide(); 8461 8462 vars.next = vars.next + 1, 8463 vars.prev = vars.current, 8464 vars.current = vars.current + 1; 8465 8466 if (opts.infinite) { 8467 if (vars.current > vars.total - 1) vars.current = 0; 8468 if (vars.current == vars.total - 1) vars.next = 0; 8469 if (vars.current == 0) vars.prev = vars.total - 1; 8470 } 8471 8472 iL.createUI(); 8473 8474 if (!iL.items[vars.next]) 8475 vars.nextLock = false; 8476 else 8477 iL.loadContent(iL.items[vars.next], 'next'); 8478 } else { 8479 vars.prevPhoto = lastHolder; 8480 vars.nextPhoto = secondHolder; 8481 vars.holder = firstHolder; 8482 8483 vars.prevPhoto.hide(); 8484 8485 vars.next = vars.current; 8486 vars.current = vars.prev; 8487 vars.prev = vars.current - 1; 8488 8489 if (opts.infinite) { 8490 if (vars.current == vars.total - 1) vars.next = 0; 8491 if (vars.current == 0) vars.prev = vars.total - 1; 8492 } 8493 8494 iL.createUI(); 8495 8496 if (!iL.items[vars.prev]) 8497 vars.prevLock = false; 8498 else 8499 iL.loadContent(iL.items[vars.prev], 'prev'); 8500 } 8501 8502 if (opts.linkId) setTimeout(function() { 8503 vars.hashLock = false; 8504 }, 55); 8505 8506 // Configure arrow buttons 8507 if (!opts.infinite) { 8508 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8509 8510 if (vars.current == 0) 8511 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8512 if (vars.current >= vars.total - 1) 8513 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8514 } 8515 8516 iL.repositionPhoto(); 8517 8518 // Reset next cycle timeout 8519 iL.resetCycle(); 8520 8521 //Trigger the onAfterChange callback 8522 if (typeof opts.callback.onAfterChange == 'function') 8523 opts.callback.onAfterChange.call(iL, iL.ui); 8524 }); 8525 8526 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 8527 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 8528 8529 lastHolder.css(transform, gpuAcceleration).animate({ 8530 top: top, 8531 left: left, 8532 opacity: opts.styles.nextOpacity 8533 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8534 lastHolder.css(transform, ''); 8535 }).addClass(secondClass); 8536 8537 } 8538 }, 8539 8540 setCaption: function(obj, target) { 8541 var iL = this, 8542 caption = $('<div class="ilightbox-caption"></div>'); 8543 8544 if (obj.caption) { 8545 caption.html(obj.caption); 8546 $('div.ilightbox-container', target).append(caption); 8547 } 8548 }, 8549 8550 normalizeSocial: function(obj, url) { 8551 var iL = this, 8552 vars = iL.vars, 8553 opts = iL.options, 8554 baseURL = window.location.href; 8555 8556 $.each(obj, function(key, value) { 8557 if (!value) 8558 return true; 8559 8560 var item = key.toLowerCase(), 8561 source, text; 8562 8563 switch (item) { 8564 case 'facebook': 8565 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 8566 text = "Share on Facebook"; 8567 break; 8568 case 'twitter': 8569 source = "http://twitter.com/home?status={URL}", 8570 text = "Share on Twitter"; 8571 break; 8572 case 'googleplus': 8573 source = "https://plus.google.com/share?url={URL}", 8574 text = "Share on Google+"; 8575 break; 8576 case 'delicious': 8577 source = "http://delicious.com/post?url={URL}", 8578 text = "Share on Delicious"; 8579 break; 8580 case 'digg': 8581 source = "http://digg.com/submit?phase=2&url={URL}", 8582 text = "Share on Digg"; 8583 break; 8584 case 'reddit': 8585 source = "http://reddit.com/submit?url={URL}", 8586 text = "Share on reddit"; 8587 break; 8588 } 8589 8590 obj[key] = { 8591 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 8592 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 8593 text: value.text || text || "Share on " + key, 8594 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 8595 height: value.height || 360 8596 }; 8597 8598 }); 8599 8600 return obj; 8601 }, 8602 8603 setSocial: function(obj, url, target) { 8604 var iL = this, 8605 socialBar = $('<div class="ilightbox-social"></div>'), 8606 buttons = '<ul>'; 8607 8608 obj = iL.normalizeSocial(obj, url); 8609 8610 $.each(obj, function(key, value) { 8611 var item = key.toLowerCase(), 8612 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, '+')); 8613 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>'; 8614 }); 8615 8616 buttons += '</ul>'; 8617 8618 socialBar.html(buttons); 8619 $('div.ilightbox-container', target).append(socialBar); 8620 }, 8621 8622 fullScreenAction: function() { 8623 var iL = this, 8624 vars = iL.vars; 8625 8626 if (fullScreenApi.supportsFullScreen) { 8627 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 8628 else fullScreenApi.requestFullScreen(document.documentElement); 8629 } else { 8630 iL.doFullscreen(); 8631 } 8632 }, 8633 8634 doFullscreen: function() { 8635 var iL = this, 8636 vars = iL.vars, 8637 viewport = getViewport(), 8638 opts = iL.options; 8639 8640 if (opts.fullAlone) { 8641 var currentHolder = vars.holder, 8642 current = iL.items[vars.current], 8643 windowWidth = viewport.width, 8644 windowHeight = viewport.height, 8645 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 8646 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8647 8648 if (!vars.isInFullScreen) { 8649 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 8650 vars.overlay.css({ 8651 opacity: 1 8652 }); 8653 8654 $.each(hideElements, function(i, element) { 8655 element.hide(); 8656 }); 8657 8658 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 8659 8660 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8661 naturalWidthOld: currentHolder.data('naturalWidth'), 8662 naturalHeightOld: currentHolder.data('naturalHeight'), 8663 naturalWidth: windowWidth, 8664 naturalHeight: windowHeight 8665 }); 8666 else { 8667 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 8668 newWidth = windowWidth, 8669 newHeight = windowHeight, 8670 width = currentHolder.data('naturalWidth'), 8671 height = currentHolder.data('naturalHeight'); 8672 8673 if (viewport.toLowerCase() == 'fill') { 8674 newHeight = (newWidth / width) * height; 8675 8676 if (newHeight < windowHeight) { 8677 newWidth = (windowHeight / height) * width, 8678 newHeight = windowHeight; 8679 } 8680 } else if (viewport.toLowerCase() == 'fit') { 8681 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 8682 8683 newWidth = dims.width, 8684 newHeight = dims.height; 8685 } else if (viewport.toLowerCase() == 'stretch') { 8686 newWidth = newWidth, 8687 newHeight = newHeight; 8688 } else { 8689 var scale = (width > newWidth || height > newHeight) ? true : false, 8690 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 8691 newWidth = dims.width, 8692 newHeight = dims.height; 8693 } 8694 8695 currentHolder.data({ 8696 naturalWidthOld: currentHolder.data('naturalWidth'), 8697 naturalHeightOld: currentHolder.data('naturalHeight'), 8698 naturalWidth: newWidth, 8699 naturalHeight: newHeight 8700 }); 8701 } 8702 8703 $.each(elements, function(key, val) { 8704 val.addClass('ilightbox-fullscreen'); 8705 }); 8706 8707 //Trigger the onEnterFullScreen callback 8708 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 8709 } else { 8710 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 8711 vars.overlay.css({ 8712 opacity: iL.options.overlay.opacity 8713 }); 8714 8715 $.each(hideElements, function(i, element) { 8716 element.show(); 8717 }); 8718 8719 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 8720 8721 currentHolder.data({ 8722 naturalWidth: currentHolder.data('naturalWidthOld'), 8723 naturalHeight: currentHolder.data('naturalHeightOld'), 8724 naturalWidthOld: null, 8725 naturalHeightOld: null 8726 }); 8727 8728 $.each(elements, function(key, val) { 8729 val.removeClass('ilightbox-fullscreen'); 8730 }); 8731 8732 //Trigger the onExitFullScreen callback 8733 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 8734 } 8735 } else { 8736 if (!vars.isInFullScreen) vars.isInFullScreen = true; 8737 else vars.isInFullScreen = false; 8738 } 8739 iL.repositionPhoto(true); 8740 }, 8741 8742 closeAction: function() { 8743 var iL = this, 8744 vars = iL.vars, 8745 opts = iL.options; 8746 8747 $win.unbind('.iLightBox'); 8748 $doc.off('.iLightBox'); 8749 8750 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 8751 8752 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 8753 8754 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 8755 vars.overlay.remove(); 8756 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8757 }); 8758 else { 8759 vars.overlay.remove(); 8760 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8761 } 8762 8763 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8764 8765 $.each(fadeOuts, function(i, element) { 8766 element.removeAttr('style').remove(); 8767 }); 8768 8769 vars.dontGenerateThumbs = vars.isInFullScreen = false; 8770 8771 window.iLightBox = null; 8772 8773 if (opts.linkId) { 8774 vars.hashLock = true; 8775 removeHash(); 8776 setTimeout(function() { 8777 vars.hashLock = false; 8778 }, 55); 8779 } 8780 8781 //Trigger the onHide callback 8782 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 8783 }, 8784 8785 repositionPhoto: function() { 8786 var iL = this, 8787 vars = iL.vars, 8788 opts = iL.options, 8789 path = opts.path.toLowerCase(), 8790 viewport = getViewport(), 8791 winWidth = viewport.width, 8792 winHeight = viewport.height; 8793 8794 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 8795 8796 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 8797 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 8798 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 8799 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 8800 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, 8801 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))); 8802 8803 var elObject = { 8804 type: 'current', 8805 width: width, 8806 height: height, 8807 item: iL.items[vars.current], 8808 offsetW: offsetW, 8809 offsetH: offsetH,
8810 thumbsOffsetW: thumbsOffsetW, 8811 thumbsOffsetH: thumbsOffsetH, 8812 animate: arguments.length, 8813 holder: vars.holder 8814 }; 8815 8816 iL.repositionEl(elObject); 8817 if (iL.items[vars.next]) { 8818 elObject = $.extend(elObject, { 8819 type: 'next', 8820 item: iL.items[vars.next], 8821 offsetX: (viewport.width > UNCODE.mediaQuery) ? opts.styles.nextOffsetX : 0, 8822 offsetY: opts.styles.nextOffsetY, 8823 holder: vars.nextPhoto 8824 }); 8825 8826 iL.repositionEl(elObject); 8827 } 8828 8829 if (iL.items[vars.prev]) { 8830 elObject = $.extend(elObject, { 8831 type: 'prev', 8832 item: iL.items[vars.prev], 8833 offsetX: (viewport.width > UNCODE.mediaQuery) ? opts.styles.prevOffsetX : 0, 8834 offsetY: opts.styles.prevOffsetY, 8835 holder: vars.prevPhoto 8836 }); 8837 8838 iL.repositionEl(elObject); 8839 } 8840 8841 var loaderCss = (path == "horizontal") ? { 8842 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 8843 } : { 8844 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 8845 }; 8846 vars.loader.css(loaderCss); 8847 }, 8848 8849 repositionEl: function(obj) { 8850 var iL = this, 8851 vars = iL.vars, 8852 opts = iL.options, 8853 path = opts.path.toLowerCase(), 8854 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 8855 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 8856 itemParent = obj.item, 8857 item = obj.item.options, 8858 holder = obj.holder, 8859 offsetX = obj.offsetX || 0, 8860 offsetY = obj.offsetY || 0, 8861 thumbsOffsetW = obj.thumbsOffsetW, 8862 thumbsOffsetH = obj.thumbsOffsetH; 8863 8864 if (obj.type == 'current') { 8865 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); 8866 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); 8867 } else { 8868 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 8869 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 8870 } 8871 8872 heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 8873 8874 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 8875 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 8876 8877 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 8878 width: width, 8879 height: height 8880 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 8881 newDims = $.extend({}, dims, {}); 8882 8883 if (obj.type == 'prev' || obj.type == 'next') 8884 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 8885 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 8886 else 8887 width = dims.width, 8888 height = dims.height; 8889 8890 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 8891 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); 8892 8893 if (obj.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8894 var objRatio = width / height; 8895 height = height - vars.captionHeight; 8896 width = height * objRatio; 8897 } 8898 8899 switch (obj.type) { 8900 case 'current': 8901 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 8902 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8903 break; 8904
8905 case 'next': 8906 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 8907 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 8908 break; 8909 8910 case 'prev': 8911 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 8912 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8913 break; 8914 } 8915 8916 holder.data('offset', { 8917 top: top, 8918 left: left, 8919 newDims: newDims, 8920 diff: { 8921 W: widthDiff, 8922 H: heightDiff 8923 }, 8924 thumbsOffset: { 8925 W: thumbsOffsetW, 8926 H: thumbsOffsetH 8927 }, 8928 object: obj 8929 }); 8930 8931 if (obj.animate > 0 && opts.effects.reposition) { 8932 holder.css(transform, gpuAcceleration).stop().animate({ 8933 top: top, 8934 left: left 8935 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 8936 holder.css(transform, ''); 8937 }); 8938 $('div.ilightbox-container', holder).stop().animate({ 8939 width: width, 8940 height: height 8941 }, opts.effects.repositionSpeed, 'easeOutCirc'); 8942 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 8943 width: width 8944 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 8945 $(this).css('overflow', 'visible'); 8946 }); 8947 } else { 8948 holder.css({ 8949 top: top, 8950 left: left 8951 }); 8952 $('div.ilightbox-container', holder).css({ 8953 width: width, 8954 height: height 8955 }); 8956 $('div.ilightbox-inner-toolbar', holder).css({ 8957 width: width 8958 }); 8959 } 8960 }, 8961 8962 resume: function(priority) { 8963 var iL = this, 8964 vars = iL.vars, 8965 opts = iL.options; 8966 8967 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 8968 return; 8969 } 8970 8971 vars.isPaused = 0; 8972 8973 if (vars.cycleID) { 8974 vars.cycleID = clearTimeout(vars.cycleID); 8975 } 8976 8977 vars.cycleID = setTimeout(function() { 8978 if (vars.current == vars.total - 1) iL.goTo(0); 8979 else iL.moveTo('next'); 8980 }, opts.slideshow.pauseTime); 8981 }, 8982 8983 pause: function(priority) { 8984 var iL = this, 8985 vars = iL.vars, 8986 opts = iL.options; 8987 8988 if (priority < vars.isPaused) { 8989 return; 8990 } 8991 8992 vars.isPaused = priority || 100; 8993 8994 if (vars.cycleID) { 8995 vars.cycleID = clearTimeout(vars.cycleID); 8996 } 8997 }, 8998 8999 resetCycle: function() { 9000 var iL = this, 9001 vars = iL.vars, 9002 opts = iL.options; 9003 9004 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 9005 iL.resume(); 9006 } 9007 }, 9008 9009 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 9010 var iL = this; 9011 9012 if (!width) factor = height / height_old; 9013 else if (!height) factor = width / width_old; 9014 else factor = min(width / width_old, height / height_old); 9015 9016 if (!thumb) { 9017 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 9018 else if (factor < iL.options.minScale) factor = iL.options.minScale; 9019 } 9020 9021 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 9022 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 9023 9024 return { 9025 width: final_width, 9026 height: final_height, 9027 ratio: factor 9028 }; 9029 }, 9030 9031 setOption: function(options) { 9032 var iL = this; 9033 9034 iL.options = $.extend(true, iL.options, options || {}); 9035 iL.refresh(); 9036 }, 9037 9038 availPlugins: function() { 9039 var iL = this, 9040 testEl = document.createElement("video"); 9041 9042 iL.plugins = { 9043 flash: false, 9044 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 9045 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 9046 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 9047 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 9048 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 9049 }; 9050 }, 9051 9052 addContent: function(element, obj) { 9053 var iL = this, 9054 el; 9055 9056 switch (obj.type) { 9057 case 'video': 9058 var HTML5 = false, 9059 videoType = obj.videoType, 9060 html5video = obj.options.html5video; 9061 9062 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 9063 obj.ext = 'mp4', 9064 obj.URL = html5video.h264 || obj.URL; 9065 else if (html5video.webm && iL.plugins.html5WebM) 9066 obj.ext = 'webm', 9067 obj.URL = html5video.webm || obj.URL; 9068 else if (html5video.ogg && iL.plugins.html5Vorbis) 9069 obj.ext = 'ogv', 9070 obj.URL = html5video.ogg || obj.URL; 9071 9072 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 9073 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 9074 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 9075 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 9076 9077 if (HTML5) { 9078 el = $('<video />
9078', { 9079 "width": "100%", 9080 "height": "100%", 9081 "preload": html5video.preload, 9082 "autoplay": html5video.autoplay, 9083 "poster": html5video.poster, 9084 "controls": html5video.controls 9085 }).append($('<source />', { 9086 "src": obj.URL, 9087 "type": videoType 9088 })); 9089 } else { 9090 if (!iL.plugins.quicktime) el = $('<span />', { 9091 "class": "ilightbox-alert", 9092 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 9093 }); 9094 else { 9095 9096 el = $('<object />', { 9097 "type": "video/quicktime", 9098 "pluginspage": pluginspages.quicktime 9099 }).attr({ 9100 "data": obj.URL, 9101 "width": "100%", 9102 "height": "100%" 9103 }).append($('<param />', { 9104 "name": "src", 9105 "value": obj.URL 9106 })).append($('<param />', { 9107 "name": "autoplay", 9108 "value": "false" 9109 })).append($('<param />', { 9110 "name": "loop", 9111 "value": "false" 9112 })).append($('<param />', { 9113 "name": "scale", 9114 "value": "tofit" 9115 })); 9116 9117 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 9118 } 9119 } 9120 9121 break; 9122 9123 case 'flash': 9124 if (!iL.plugins.flash) el = $('<span />', { 9125 "class": "ilightbox-alert", 9126 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 9127 }); 9128 else { 9129 var flashvars = "", 9130 i = 0; 9131 9132 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 9133 if (i != 0) flashvars += "&"; 9134 flashvars += k + "=" + encodeURIComponent(v); 9135 i++; 9136 }); 9137 else flashvars = null; 9138 9139 el = $('<embed />').attr({ 9140 "type": "application/x-shockwave-flash", 9141 "src": obj.URL, 9142 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9143 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9144 "quality": "high", 9145 "bgcolor": "#000000", 9146 "play": "true", 9147 "loop": "true", 9148 "menu": "true", 9149 "wmode": "transparent", 9150 "scale": "showall", 9151 "allowScriptAccess": "always", 9152 "allowFullScreen": "true", 9153 "flashvars": flashvars, 9154 "fullscreen": "yes" 9155 }); 9156 } 9157 9158 break; 9159 9160 case 'iframe': 9161 el = $('<iframe />').attr({ 9162 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9163 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9164 src: obj.URL, 9165 frameborder: 0, 9166 'hspace': 0, 9167 'vspace': 0, 9168 'scrolling': supportTouch ? 'auto' : 'scroll', 9169 'webkitAllowFullScreen': '', 9170 'mozallowfullscreen': '', 9171 'allowFullScreen': '' 9172 }); 9173 9174 break; 9175 9176 case 'inline': 9177 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 9178 9179 break; 9180 9181 case 'html': 9182 var object = obj.URL, 9183 el; 9184 9185 if (object[0].nodeName) { 9186 el = $('<div class="ilightbox-wrapper"></div>').html(object); 9187 } else { 9188 var dom = $(obj.URL), 9189 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 9190 el = $('<div class="ilightbox-wrapper"></div>').html(html); 9191 } 9192 9193 break; 9194 } 9195 9196 $('div.ilightbox-container', element).empty().html(el); 9197 9198 // For fixing Chrome about just playing the video for first time 9199 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 9200 var src = el[0].currentSrc + '?' + floor(random() * 30000); 9201 el[0].currentSrc = src; 9202 el[0].src = src; 9203 }); 9204 9205 return el; 9206 }, 9207 9208 ogpRecognition: function(obj, callback) { 9209 var iL = this, 9210 url = obj.URL; 9211 9212 iL.showLoader(); 9213 doAjax(url, function(data) { 9214 iL.hideLoader(); 9215 9216 if (data) { 9217 var object = new Object(); 9218 9219 object.length = false, 9220 object.url = data.url; 9221 9222 if (data.status == 200) { 9223 var result = data.results, 9224 type = result.type, 9225 source = result.source; 9226 9227 object.source = source.src, 9228 object.width = source.width && parseInt(source.width) || 0, 9229 object.height = source.height && parseInt(source.height) || 0, 9230 object.type = type, 9231 object.thumbnail = source.thumbnail || result.images[0], 9232 object.html5video = result.html5video || {}, 9233 object.length = true; 9234 9235 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 9236 else if (source.type.indexOf("video/") != -1) object.type = "video"; 9237 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 9238 else if (source.type.indexOf("image/") != -1) object.type = "image"; 9239 9240 } else if (typeof data.response != 'undefined') 9241 throw data.response; 9242 9243 callback.call(this, object.length ? object : false); 9244 } 9245 }); 9246 }, 9247 9248 hashChangeHandler: function(url) { 9249 var iL = this, 9250 vars = iL.vars, 9251 opts = iL.options, 9252 URL = url || window.location.href, 9253 hash = parseURI(URL).hash, 9254 split = hash.split('/'), 9255 index = split[1]; 9256 9257 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 9258 9259 if (index) { 9260 var target = split[1] || 0; 9261 if (iL.items[target]) {
9262 var overlay = $('.ilightbox-overlay'); 9263 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 9264 iL.goTo(target); 9265 } else { 9266 iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click'); 9267 } 9268 } else { 9269 var overlay = $('.ilightbox-overlay'); 9270 if (overlay.length) iL.closeAction(); 9271 } 9272 } else { 9273 var overlay = $('.ilightbox-overlay'); 9274 if (overlay.length) iL.closeAction(); 9275 } 9276 } 9277 }; 9278 9279 /** 9280 * Parse style to pixels. 9281 * 9282 * @param {Object} $element jQuery object with element. 9283 * @param {Property} property CSS property to get the pixels from. 9284 * 9285 * @return {Int} 9286 */ 9287 function getPixel($element, property) { 9288 return parseInt($element.css(property), 10) || 0; 9289 } 9290 9291 /** 9292 * Make sure that number is within the limits. 9293 * 9294 * @param {Number} number 9295 * @param {Number} min 9296 * @param {Number} max 9297 * 9298 * @return {Number} 9299 */ 9300 function within(number, min, max) { 9301 return number < min ? min : number > max ? max : number; 9302 } 9303 9304 /** 9305 * Get viewport/window size (width and height). 9306 * 9307 * @return {Object} 9308 */ 9309 function getViewport() { 9310 var e = window, 9311 a = 'inner'; 9312 if (!('innerWidth' in window)) { 9313 a = 'client'; 9314 e = document.documentElement || document.body; 9315 } 9316 return { 9317 width: e[a + 'Width'], 9318 height: e[a + 'Height'] 9319 } 9320 } 9321 9322 /** 9323 * Remove hash tag from the URL 9324 * 9325 * @return {Void} 9326 */ 9327 function removeHash() { 9328 var scroll = getScrollXY(); 9329 9330 window.location.hash = ""; 9331 9332 // Restore the scroll offset, should be flicker free 9333 window.scrollTo(scroll.x, scroll.y); 9334 } 9335 9336 /** 9337 * Do the ajax requests with callback. 9338 * 9339 * @param {String} url 9340 * @param {Function} callback 9341 * 9342 * @return {Void} 9343 */ 9344 function doAjax(url, callback) { 9345 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'); 9346 $.ajax({ 9347 url: url, 9348 dataType: 'jsonp' 9349 }); 9350 9351 iLCallback = function(data) { 9352 callback.call(this, data); 9353 }; 9354 } 9355 9356 /** 9357 * Find image from DOM elements 9358 * 9359 * @param {Element} element 9360 * 9361 * @return {Void} 9362 */ 9363 function findImageInElement(element) { 9364 var elements = $('*', element), 9365 imagesArr = new Array(); 9366 9367 elements.each(function() { 9368 var url = "", 9369 element = this; 9370 9371 if ($(element).css("background-image") != "none") { 9372 url = $(element).css("background-image"); 9373 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 9374 url = $(element).attr("src"); 9375 } 9376 9377 if (url.indexOf("gradient") == -1) { 9378 url = url.replace(/url\(\"/g, ""); 9379 url = url.replace(/url\(/g, ""); 9380 url = url.replace(/\"\)/g, ""); 9381 url = url.replace(/\)/g, ""); 9382 9383 var urls = url.split(","); 9384 9385 for (var i = 0; i < urls.length; i++) { 9386 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 9387 var extra = ""; 9388 if (browser.msie && browser.version < 9) { 9389 extra = "?" + floor(random() * 3000); 9390 } 9391 imagesArr.push(urls[i] + extra); 9392 } 9393 } 9394 } 9395 }); 9396 9397 return imagesArr; 9398 } 9399 9400 /** 9401 * Get file extension. 9402 * 9403 * @param {String} URL 9404 * 9405 * @return {String} 9406 */ 9407 function getExtension(URL) { 9408 if (URL !== null) { 9409 var ext = URL.split('.').pop().toLowerCase(), 9410 extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : ''; 9411 9412 return ext.replace(extra, ''); 9413 } 9414 } 9415 9416 /** 9417 * Get type via extension. 9418 * 9419 * @param {String} URL 9420 * 9421 * @return {String} 9422 */ 9423 function getTypeByExtension(URL) { 9424 var type, 9425 ext = getExtension(URL); 9426 9427 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 9428 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 9429 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 9430 else type = 'iframe'; 9431 9432 return type; 9433 } 9434 9435 /** 9436 * Return value from percent of a number. 9437 * 9438 * @param {Number} percent 9439 * @param {Number} total 9440 * 9441 * @return {Number} 9442 */ 9443 function percentToValue(percent, total) { 9444 return parseInt((total / 100) * percent); 9445 } 9446 9447 /** 9448 * A JavaScript equivalent of PHP’s parse_url. 9449 * 9450 * @param {String} url The URL to parse. 9451 * 9452 * @return {Mixed} 9453 */ 9454 function parseURI(url) { 9455 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 9456 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 9457 return (m ? { 9458 href: m[0] || '', 9459 protocol: m[1] || '', 9460 authority: m[2] || '', 9461 host: m[3] || '', 9462 hostname: m[4] || '', 9463 port: m[5] || '', 9464 pathname: m[6] || '', 9465 search: m[7] || '', 9466 hash: m[8] || '' 9467 } : null); 9468 } 9469 9470 /** 9471 * Gets the absolute URI. 9472 * 9473 * @param {String} href The relative URL. 9474 * @param {String} base The base URL. 9475 * 9476 * @return {String} The absolute URL. 9477 */ 9478 function absolutizeURI(base, href) { // RFC 3986 9479 var iL = this; 9480 9481 function removeDotSegments(input) { 9482 var output = []; 9483 input.replace(/^(\.\.?(\/|$))+/, '') 9484 .replace(/\/(\.(\/|$))+/g, '/') 9485 .replace(/\/\.\.$/, '/../') 9486 .replace(/\/?[^\/]*/g, function(p) { 9487 if (p === '/..') { 9488 output.pop(); 9489 } else { 9490 output.push(p); 9491 } 9492 }); 9493 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 9494 } 9495 9496 href = parseURI(href || ''); 9497 base = parseURI(base || ''); 9498 9499 return !href || !base ? null : (href.protocol || base.protocol) + 9500 (href.protocol || href.authority ? href.authority : base.authority) + 9501 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)) + 9502 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 9503 href.hash; 9504 } 9505 9506 /** 9507 * A JavaScript equivalent of PHP’s version_compare. 9508 * 9509 * @param {String} v1 9510 * @param {String} v2 9511 * @param {String} operator
9512 * 9513 * @return {Boolean} 9514 */ 9515 function version_compare(v1, v2, operator) { 9516 this.php_js = this.php_js || {}; 9517 this.php_js.ENV = this.php_js.ENV || {}; 9518 var i = 0, 9519 x = 0, 9520 compare = 0, 9521 vm = { 9522 'dev': -6, 9523 'alpha': -5, 9524 'a': -5, 9525 'beta': -4, 9526 'b': -4, 9527 'RC': -3, 9528 'rc': -3, 9529 '#': -2, 9530 'p': 1, 9531 'pl': 1 9532 }, 9533 prepVersion = function(v) { 9534 v = ('' + v).replace(/[_\-+]/g, '.'); 9535 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 9536 return (!v.length ? [-8] : v.split('.')); 9537 }, 9538 numVersion = function(v) { 9539 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 9540 }; 9541 v1 = prepVersion(v1); 9542 v2 = prepVersion(v2); 9543 x = max(v1.length, v2.length); 9544 for (i = 0; i < x; i++) { 9545 if (v1[i] == v2[i]) { 9546 continue; 9547 } 9548 v1[i] = numVersion(v1[i]); 9549 v2[i] = numVersion(v2[i]); 9550 if (v1[i] < v2[i]) { 9551 compare = -1; 9552 break; 9553 } else if (v1[i] > v2[i]) { 9554 compare = 1; 9555 break; 9556 } 9557 } 9558 if (!operator) { 9559 return compare; 9560 } 9561 9562 switch (operator) { 9563 case '>': 9564 case 'gt': 9565 return (compare > 0); 9566 case '>=': 9567 case 'ge': 9568 return (compare >= 0); 9569 case '<=': 9570 case 'le': 9571 return (compare <= 0); 9572 case '==': 9573 case '=': 9574 case 'eq': 9575 return (compare === 0); 9576 case '<>': 9577 case '!=': 9578 case 'ne': 9579 return (compare !== 0); 9580 case '': 9581 case '<': 9582 case 'lt': 9583 return (compare < 0); 9584 default: 9585 return null; 9586 } 9587 } 9588 9589 9590 // Begin the iLightBox plugin 9591 $.fn.iLightBox = function() { 9592 9593 var args = arguments, 9594 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 9595 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 9596 9597 if (!opt) opt = {}; 9598 9599 // Default options. Play carefully. 9600 var options = $.extend(true, { 9601 attr: 'href', 9602 path: 'vertical', 9603 skin: 'dark', 9604 linkId: false, 9605 infinite: false, 9606 startFrom: 0, 9607 randomStart: false, 9608 keepAspectRatio: true, 9609 maxScale: 1, 9610 minScale: .2, 9611 innerToolbar: false, 9612 smartRecognition: false, 9613 mobileOptimizer: true, 9614 fullAlone: true, 9615 fullViewPort: null, 9616 fullStretchTypes: 'flash, video', 9617 overlay: { 9618 blur: true, 9619 opacity: .85 9620 }, 9621 controls: { 9622 arrows: false, 9623 slideshow: false, 9624 toolbar: true, 9625 fullscreen: true, 9626 thumbnail: true, 9627 keyboard: true, 9628 mousewheel: true, 9629 swipe: true 9630 }, 9631 keyboard: { 9632 left: true, // previous 9633 right: true, // next 9634 up: true, // previous 9635 down: true, // next 9636 esc: true, // close 9637 shift_enter: true // fullscreen 9638 }, 9639 show: { 9640 effect: true, 9641 speed: 300, 9642 title: true 9643 }, 9644 hide: { 9645 effect: true, 9646 speed: 300 9647 }, 9648 caption: { 9649 start: true, 9650 show: 'mouseenter', 9651 hide: 'mouseleave' 9652 }, 9653 social: { 9654 start: true, 9655 show: 'mouseenter', 9656 hide: 'mouseleave',
9657 buttons: false 9658 }, 9659 styles: { 9660 pageOffsetX: 0, 9661 pageOffsetY: 0, 9662 nextOffsetX: 45, 9663 nextOffsetY: 0, 9664 nextOpacity: 1, 9665 nextScale: 1, 9666 prevOffsetX: 45, 9667 prevOffsetY: 0, 9668 prevOpacity: 1, 9669 prevScale: 1 9670 }, 9671 thumbnails: { 9672 maxWidth: 120, 9673 maxHeight: 80, 9674 normalOpacity: 1, 9675 activeOpacity: .6 9676 }, 9677 effects: { 9678 reposition: true, 9679 repositionSpeed: 200, 9680 switchSpeed: 500, 9681 loadedFadeSpeed: 180, 9682 fadeSpeed: 200 9683 }, 9684 slideshow: { 9685 pauseTime: 5000, 9686 pauseOnHover: false, 9687 startPaused: true 9688 }, 9689 text: { 9690 close: "Press Esc to close", 9691 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 9692 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 9693 slideShow: "Slideshow", 9694 next: "Next", 9695 previous: "Previous" 9696 }, 9697 errors: { 9698 loadImage: "An error occurred when trying to load photo.", 9699 loadContents: "An error occurred when trying to load contents.", 9700 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 9701 }, 9702 ajaxSetup: { 9703 url: '', 9704 beforeSend: function(jqXHR, settings) {}, 9705 cache: false, 9706 complete: function(jqXHR, textStatus) {}, 9707 crossDomain: false, 9708 error: function(jqXHR, textStatus, errorThrown) {}, 9709 success: function(data, textStatus, jqXHR) {}, 9710 global: true, 9711 ifModified: false, 9712 username: null, 9713 password: null, 9714 type: 'GET' 9715 }, 9716 callback: {} 9717 }, opt); 9718 9719 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 9720 9721 items = $.isArray(items) ? items : new Array(); 9722 9723 if (typeof args[0] == 'string') items[0] = args[0]; 9724 9725 if (version_compare($.fn.jquery, '1.8', '>=')) { 9726 var iLB = new iLightBox($(this), options, items, instant); 9727 return { 9728 close: function() { 9729 iLB.closeAction(); 9730 }, 9731 fullscreen: function() { 9732 iLB.fullScreenAction(); 9733 }, 9734 moveNext: function() { 9735 iLB.moveTo('next'); 9736 }, 9737 movePrev: function() { 9738 iLB.moveTo('prev'); 9739 }, 9740 goTo: function(index) { 9741 iLB.goTo(index); 9742 }, 9743 refresh: function() { 9744 iLB.refresh(); 9745 }, 9746 reposition: function() { 9747 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 9748 }, 9749 setOption: function(options) { 9750 iLB.setOption(options); 9751 }, 9752 destroy: function() { 9753 iLB.closeAction(); 9754 iLB.dispatchItemsEvents(); 9755 } 9756 }; 9757 } else { 9758 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 9759 } 9760 9761 }; 9762 9763 9764 $.iLightBox = function() { 9765 return $.fn.iLightBox(arguments[0], arguments[1]); 9766 }; 9767 9768 9769 $.extend($.easing, { 9770 easeInCirc: function(x, t, b, c, d) { 9771 return -c * (sqrt(1 - (t /= d) * t) - 1) + b; 9772 }, 9773 easeOutCirc: function(x, t, b, c, d) { 9774 return c * sqrt(1 - (t = t / d - 1) * t) + b; 9775 }, 9776 easeInOutCirc: function(x, t, b, c, d) { 9777 if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; 9778 return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b; 9779 } 9780 }); 9781 9782 function getScrollXY() { 9783 var scrOfX = 0, 9784 scrOfY = 0; 9785 if (typeof(window.pageYOffset) == 'number') { 9786 //Netscape compliant 9787 scrOfY = window.pageYOffset; 9788 scrOfX = window.pageXOffset; 9789 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 9790 //DOM compliant 9791 scrOfY = document.body.scrollTop; 9792 scrOfX = document.body.scrollLeft; 9793 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 9794 //IE6 standards compliant mode 9795 scrOfY = document.documentElement.scrollTop; 9796 scrOfX = document.documentElement.scrollLeft; 9797 } 9798 return { 9799 x: scrOfX, 9800 y: scrOfY 9801 }; 9802 } 9803 9804 (function() { 9805 // add new event shortcuts 9806 $.each(("touchstart touchmove touchend " + 9807 "tap taphold " + 9808 "swipe swipeleft swiperight " + 9809 "scrollstart scrollstop").split(" "), function(i, name) { 9810 9811 $.fn[name] = function(fn) { 9812 return fn ? this.bind(name, fn) : this.trigger(name); 9813 }; 9814 9815 // jQuery < 1.8 9816 // if ($.attrFn) { 9817 // $.attrFn[name] = true; 9818 // } 9819 }); 9820 9821 var tapSettings = { 9822 startEvent: 'touchstart.iTap', 9823 endEvent: 'touchend.iTap' 9824 }; 9825 9826 // tap Event: 9827 $.event.special.itap = { 9828 setup: function() { 9829 9830 var self = this, 9831 $self = $(this), 9832 start, stop; 9833 9834 $self.bind(tapSettings.startEvent, function(event) { 9835 start = getScrollXY(); 9836 9837 $self.one(tapSettings.endEvent, function(event) { 9838 stop = getScrollXY(); 9839 9840 var orgEvent = event || window.event; 9841 event = $.event.fix(orgEvent); 9842 event.type = "itap"; 9843 9844 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 9845 9846 start = stop = undefined; 9847 }); 9848 }); 9849 }, 9850 9851 teardown: function() { 9852 $(this).unbind(tapSettings.startEvent); 9853 } 9854 }; 9855 }()); 9856 9857 9858 //Fullscreen API 9859 (function() { 9860 fullScreenApi = { 9861 supportsFullScreen: false, 9862 isFullScreen: function() { 9863 return false;
9864 }, 9865 requestFullScreen: function() {}, 9866 cancelFullScreen: function() {}, 9867 fullScreenEventName: '', 9868 prefix: '' 9869 }, 9870 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 9871 9872 // check for native support 9873 if (typeof document.cancelFullScreen != 'undefined') { 9874 fullScreenApi.supportsFullScreen = true; 9875 } else { 9876 // check for fullscreen support by vendor prefix 9877 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 9878 fullScreenApi.prefix = browserPrefixes[i]; 9879 9880 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 9881 fullScreenApi.supportsFullScreen = true; 9882 9883 break; 9884 } 9885 } 9886 } 9887 9888 // update methods to do something useful 9889 if (fullScreenApi.supportsFullScreen) { 9890 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 9891 9892 fullScreenApi.isFullScreen = function() { 9893 switch (this.prefix) { 9894 case '': 9895 return document.fullScreen; 9896 case 'webkit': 9897 return document.webkitIsFullScreen; 9898 default: 9899 return document[this.prefix + 'FullScreen']; 9900 } 9901 } 9902 fullScreenApi.requestFullScreen = function(el) { 9903 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 9904 } 9905 fullScreenApi.cancelFullScreen = function(el) { 9906 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 9907 } 9908 } 9909 }()); 9910 9911 // Browser detect 9912 (function() { 9913 function uaMatch(ua) { 9914 ua = ua.toLowerCase(); 9915 9916 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 9917 /(webkit)[ \/]([\w.]+)/.exec(ua) || 9918 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 9919 /(msie) ([\w.]+)/.exec(ua) || 9920 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 9921 9922 return { 9923 browser: match[1] || "", 9924 version: match[2] || "0" 9925 }; 9926 } 9927 9928 var matched = uaMatch(navigator.userAgent); 9929 browser = {}; 9930 9931 if (matched.browser) { 9932 browser[matched.browser] = true; 9933 browser.version = matched.version; 9934 } 9935 9936 // Chrome is Webkit, but Webkit is also Safari. 9937 if (browser.chrome) { 9938 browser.webkit = true; 9939 } else if (browser.webkit) { 9940 browser.safari = true; 9941 } 9942 }()); 9943 9944 // Feature detects 9945 (function() { 9946 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 9947 var el = document.createElement('div'); 9948 9949 function testProp(prop) { 9950 for (var p = 0, pl = prefixes.length; p < pl; p++) { 9951 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 9952 if (el.style[prefixedProp] !== undefined) { 9953 return prefixedProp; 9954 } 9955 } 9956 } 9957 9958 // Global support indicators 9959 transform = testProp('transform') || ''; 9960 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 9961 }()); 9962 9963 9964 /* 9965 PluginDetect v0.7.9 9966 www.pinlady.net/PluginDetect/license/ 9967 [ getVersion onWindowLoaded BetterIE ] 9968 [ Flash QuickTime Shockwave ] 9969 */ 9970 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;
9970d++){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);
9970d.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)}
9970c.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;
9970if(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(); 9971 9972 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)}; 9973 9974 9975 /* 9976 jQuery hashchange event v1.3 9977 https://github.com/cowboy/jquery-hashchange 9978 Copyright (c) 2010 "Cowboy" Ben Alman 9979 Dual licensed under the MIT and GPL licenses. 9980 */ 9981 (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= 9982 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|| 9983 "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;
9983a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 9984 9985 if (!Array.prototype.filter) { 9986 Array.prototype.filter = function(fun /*, thisp */ ) { 9987 "use strict"; 9988 9989 if (this == null) 9990 throw new TypeError(); 9991 9992 var t = Object(this); 9993 var len = t.length >>> 0; 9994 if (typeof fun != "function") 9995 throw new TypeError(); 9996 9997 var res = []; 9998 var thisp = arguments[1]; 9999 for (var i = 0; i < len; i++) { 10000 if (i in t) { 10001 var val = t[i]; // in case fun mutates this 10002 if (fun.call(thisp, val, i, t)) 10003 res.push(val); 10004 } 10005 } 10006 10007 return res; 10008 }; 10009 } 10010 10011 if (!Array.prototype.indexOf) { 10012 Array.prototype.indexOf = function(searchElement, fromIndex) { 10013 var k; 10014 10015 if (this == null) { 10016 throw new TypeError('"this" is null or not defined'); 10017 } 10018 10019 var O = Object(this); 10020 10021 var len = O.length >>> 0; 10022 10023 if (len === 0) { 10024 return -1; 10025 } 10026 10027 var n = +fromIndex || 0; 10028 10029 if (abs(n) === Infinity) { 10030 n = 0; 10031 } 10032 10033 if (n >= len) { 10034 return -1; 10035 } 10036 10037 k = max(n >= 0 ? n : len - abs(n), 0); 10038 10039 while (k < len) { 10040 var kValue; 10041 if (k in O && O[k] === searchElement) { 10042 return k; 10043 } 10044 k++; 10045 } 10046 return -1; 10047 }; 10048 } 10049 10050 if (!Array.prototype.lastIndexOf) { 10051 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 10052 "use strict"; 10053 10054 if (this == null) 10055 throw new TypeError(); 10056 10057 var t = Object(this); 10058 var len = t.length >>> 0; 10059 if (len === 0) 10060 return -1; 10061 10062 var n = len; 10063 if (arguments.length > 1) { 10064 n = Number(arguments[1]); 10065 if (n != n) 10066 n = 0; 10067 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 10068 n = (n > 0 || -1) * floor(abs(n)); 10069 } 10070 10071 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 10072 10073 for (; k >= 0; k--) { 10074 if (k in t && t[k] === searchElement) 10075 return k; 10076 } 10077 return -1; 10078 }; 10079 } 10080})(jQuery, this); 10081 10082 10083/** 10084 * Owl carousel
vendor: 25,822 bytes, lines 10085-11109
10085 * @version 2.0.0-beta.3 10086 * @author Bartosz Wojciechowski 10087 * @license The MIT License (MIT) 10088 * @todo Lazy Load Icon 10089 * @todo prevent animationend bubling 10090 * @todo itemsScaleUp 10091 * @todo Test Zepto 10092 * @todo stagePadding calculate wrong active classes 10093 */ 10094;(function($, window, document, undefined) { 10095 10096 /** 10097 * Creates a carousel. 10098 * @class The Owl Carousel. 10099 * @public 10100 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 10101 * @param {Object} [options] - The options 10102 */ 10103 function Owl(element, options) { 10104 10105 /** 10106 * Current settings for the carousel. 10107 * @public 10108 */ 10109 this.settings = null; 10110 10111 /** 10112 * Current options set by the caller including defaults. 10113 * @public 10114 */ 10115 this.options = $.extend({}, Owl.Defaults, options); 10116 10117 /** 10118 * Plugin element. 10119 * @public 10120 */ 10121 this.$element = $(element); 10122 10123 /** 10124 * Proxied event handlers. 10125 * @protected 10126 */ 10127 this._handlers = {}; 10128 10129 /** 10130 * References to the running plugins of this carousel. 10131 * @protected 10132 */ 10133 this._plugins = {}; 10134 10135 /** 10136 * Currently suppressed events to prevent them from beeing retriggered. 10137 * @protected 10138 */ 10139 this._supress = {}; 10140 10141 /** 10142 * Absolute current position. 10143 * @protected 10144 */ 10145 this._current = null; 10146 10147 /** 10148 * Animation speed in milliseconds. 10149 * @protected 10150 */ 10151 this._speed = null; 10152 10153 /** 10154 * Coordinates of all items in pixel. 10155 * @todo The name of this member is missleading. 10156 * @protected 10157 */ 10158 this._coordinates = []; 10159 10160 /** 10161 * Current breakpoint. 10162 * @todo Real media queries would be nice. 10163 * @protected 10164 */ 10165 this._breakpoint = null; 10166 10167 /** 10168 * Current width of the plugin element. 10169 */ 10170 this._width = null; 10171 10172 /** 10173 * All real items. 10174 * @protected 10175 */ 10176 this._items = []; 10177 10178 /** 10179 * All cloned items. 10180 * @protected 10181 */ 10182 this._clones = []; 10183 10184 /** 10185 * Merge values of all items. 10186 * @todo Maybe this could be part of a plugin. 10187 * @protected 10188 */ 10189 this._mergers = []; 10190 10191 /** 10192 * Widths of all items. 10193 */ 10194 this._widths = []; 10195 10196 /** 10197 * Invalidated parts within the update process. 10198 * @protected 10199 */ 10200 this._invalidated = {}; 10201 10202 /** 10203 * Ordered list of workers for the update process. 10204 * @protected 10205 */ 10206 this._pipe = []; 10207 10208 /** 10209 * Current state information for the drag operation. 10210 * @todo #261 10211 * @protected 10212 */ 10213 this._drag = { 10214 time: null, 10215 target: null, 10216 pointer: null, 10217 stage: { 10218 start: null, 10219 current: null 10220 }, 10221 direction: null 10222 }; 10223 10224 /** 10225 * Current state information and their tags. 10226 * @type {Object} 10227 * @protected 10228 */ 10229 this._states = { 10230 current: {}, 10231 tags: { 10232 'initializing': [ 'busy' ], 10233 'animating': [ 'busy' ], 10234 'dragging': [ 'interacting' ] 10235 } 10236 }; 10237 10238 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 10239 this._handlers[handler] = $.proxy(this[handler], this); 10240 }, this)); 10241 10242 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 10243 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 10244 = new plugin(this); 10245 }, this)); 10246 10247 $.each(Owl.Workers, $.proxy(function(priority, worker) { 10248 this._pipe.push({ 10249 'filter': worker.filter, 10250 'run': $.proxy(worker.run, this) 10251 }); 10252 }, this)); 10253 10254 this.setup(); 10255 this.initialize(); 10256 } 10257 10258 /** 10259 * Default options for the carousel. 10260 * @public 10261 */ 10262 Owl.Defaults = { 10263 items: 3, 10264 loop: false, 10265 center: false, 10266 rewind: false, 10267 10268 mouseDrag: true, 10269 touchDrag: true, 10270 pullDrag: true, 10271 freeDrag: false, 10272 10273 margin: 0, 10274 stagePadding: 0, 10275 10276 merge: false, 10277 mergeFit: true, 10278 autoWidth: false, 10279 10280 startPosition: 0, 10281 rtl: false, 10282 10283 smartSpeed: 250, 10284 fluidSpeed: false, 10285 dragEndSpeed: false, 10286 10287 responsive: {}, 10288 responsiveRefreshRate: 200, 10289 responsiveBaseElement: window, 10290 10291 fallbackEasing: 'swing', 10292 10293 info: false, 10294 10295 nestedItemSelector: false, 10296 itemElement: 'div', 10297 stageElement: 'div', 10298 10299 refreshClass: 'owl-refresh', 10300 loadedClass: 'owl-loaded', 10301 loadingClass: 'owl-loading', 10302 rtlClass: 'owl-rtl', 10303 responsiveClass: 'owl-responsive', 10304 dragClass: 'owl-drag', 10305 itemClass: 'owl-item', 10306 stageClass: 'owl-stage', 10307 stageOuterClass: 'owl-stage-outer', 10308 grabClass: 'owl-grab' 10309 }; 10310 10311 /** 10312 * Enumeration for width. 10313 * @public 10314 * @readonly 10315 * @enum {String} 10316 */ 10317 Owl.Width = { 10318 Default: 'default', 10319 Inner: 'inner', 10320 Outer: 'outer' 10321 }; 10322 10323 /** 10324 * Enumeration for types. 10325 * @public 10326 * @readonly 10327 * @enum {String} 10328 */ 10329 Owl.Type = { 10330 Event: 'event', 10331 State: 'state' 10332 }; 10333 10334 /** 10335 * Contains all registered plugins. 10336 * @public 10337 */ 10338 Owl.Plugins = {}; 10339 10340 /** 10341 * List of workers involved in the update process. 10342 */ 10343 Owl.Workers = [ { 10344 filter: [ 'width', 'settings' ], 10345 run: function() { 10346 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 10347 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 10348 } 10349 }, { 10350 filter: [ 'width', 'items', 'settings' ], 10351 run: function(cache) { 10352 cache.current = this._items && this._items[this.relative(this._current)]; 10353 } 10354 }, { 10355 filter: [ 'items', 'settings' ], 10356 run: function() { 10357 this.$stage.children('.cloned').remove(); 10358 } 10359 }, { 10360 filter: [ 'width', 'items', 'settings' ], 10361 run: function(cache) { 10362 var margin = this.settings.margin || '', 10363 grid = !this.settings.autoWidth, 10364 rtl = this.settings.rtl, 10365 css = { 10366 'width': 'auto', 10367 'margin-left': rtl ? margin : '', 10368 'margin-right': rtl ? '' : margin 10369 }; 10370 10371 !grid && this.$stage.children().css(css); 10372 10373 cache.css = css; 10374 } 10375 }, { 10376 filter: [ 'width', 'items', 'settings' ], 10377 run: function(cache) { 10378 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 10379 merge = null, 10380 iterator = this._items.length, 10381 grid = !this.settings.autoWidth, 10382 widths = []; 10383 10384 cache.items = { 10385 merge: false, 10386 width: width 10387 }; 10388 10389 while (iterator--) { 10390 merge = this._mergers[iterator]; 10391 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 10392 10393 cache.items.merge = merge > 1 || cache.items.merge; 10394 10395 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 10396 } 10397 10398 this._widths = widths; 10399 } 10400 }, { 10401 filter: [ 'items', 'settings' ], 10402 run: function() { 10403 var clones = [], 10404 items = this._items, 10405 settings = this.settings, 10406 view = Math.max(settings.items * 2, 4), 10407 size = Math.ceil(items.length / 2) * 2, 10408 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 10409 append = '', 10410 prepend = ''; 10411 10412 repeat /= 2; 10413 10414 while (repeat--) { 10415 clones.push(this.normalize(clones.length / 2, true)); 10416 append = append + items[clones[clones.length - 1]][0].outerHTML; 10417 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 10418 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 10419 } 10420 10421 this._clones = clones; 10422 10423 // var appendVideo = $(append).find('.uncode-video-container'); 10424 // if (appendVideo.length) { 10425 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 10426 // } 10427 // var prependVideo = $(prepend).find('.uncode-video-container'); 10428 // if (prependVideo.length) { 10429 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 10430 // } 10431 $(append).addClass('cloned').appendTo(this.$stage); 10432 $(prepend).addClass('cloned').prependTo(this.$stage); 10433 } 10434 }, { 10435 filter: [ 'width', 'items', 'settings' ], 10436 run: function() { 10437 var rtl = this.settings.rtl ? 1 : -1, 10438 size = this._clones.length + this._items.length, 10439 iterator = -1, 10440 previous = 0, 10441 current = 0, 10442 coordinates = []; 10443 10444 while (++iterator < size) { 10445 previous = coordinates[iterator - 1] || 0; 10446 current = this._widths[this.relative(iterator)] + this.settings.margin; 10447 coordinates.push(previous + current * rtl); 10448 } 10449 10450 this._coordinates = coordinates; 10451 } 10452 }, { 10453 filter: [ 'width', 'items', 'settings' ], 10454 run: function() { 10455 var padding = this.settings.stagePadding, 10456 coordinates = this._coordinates, 10457 css = { 10458 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 10459 'padding-left': padding || '', 10460 'padding-right': padding || '' 10461 }; 10462 10463 this.$stage.css(css); 10464 } 10465 }, { 10466 filter: [ 'width', 'items', 'settings' ], 10467 run: function(cache) { 10468 var iterator = this._coordinates.length, 10469 grid = !this.settings.autoWidth, 10470 items = this.$stage.children(); 10471 10472 if (grid && cache.items.merge) { 10473 while (iterator--) { 10474 cache.css.width = this._widths[this.relative(iterator)]; 10475 items.eq(iterator).css(cache.css); 10476 } 10477 } else if (grid) { 10478 cache.css.width = cache.items.width; 10479 items.css(cache.css); 10480 } 10481 } 10482 }, { 10483 filter: [ 'items' ], 10484 run: function() { 10485 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 10486 } 10487 }, { 10488 filter: [ 'width', 'items', 'settings' ], 10489 run: function(cache) { 10490 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 10491 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 10492 this.reset(cache.current); 10493 } 10494 }, { 10495 filter: [ 'position' ], 10496 run: function() { 10497 this.animate(this.coordinates(this._current)); 10498 } 10499 }, { 10500 filter: [ 'width', 'position', 'items', 'settings' ], 10501 run: function() { 10502 var rtl = this.settings.rtl ? 1 : -1, 10503 padding = this.settings.stagePadding * 2, 10504 begin = this.coordinates(this.current()) + padding, 10505 end = begin + this.width() * rtl, 10506 inner, outer, matches = [], i, n; 10507 10508 for (i = 0, n = this._coordinates.length; i < n; i++) { 10509 inner = this._coordinates[i - 1] || 0; 10510 outer = Math.abs(this._coordinates[i]) + padding * rtl; 10511 10512 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 10513 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 10514 matches.push(i); 10515 } 10516 } 10517 10518 this.$stage.children('.active').removeClass('active'); 10519 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 10520 10521 if (this.settings.center) { 10522 this.$stage.children('.center').removeClass('center'); 10523 this.$stage.children().eq(this.current()).addClass('center'); 10524 } 10525 } 10526 } ]; 10527 10528 /** 10529 * Initializes the carousel. 10530 * @protected 10531 */ 10532 Owl.prototype.initialize = function() { 10533 this.enter('initializing'); 10534 this.trigger('initialize'); 10535 10536 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 10537 10538 if (this.settings.autoWidth && !this.is('pre-loading')) { 10539 var imgs, nestedSelector, width; 10540 imgs = this.$element.find('img'); 10541 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 10542 width = this.$element.children(nestedSelector).width(); 10543 10544 if (imgs.length && width <= 0) { 10545 this.preloadAutoWidthImages(imgs); 10546 } 10547 } 10548 10549 this.$element.addClass(this.options.loadingClass); 10550 10551 // create stage 10552 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 10553 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 10554 10555 // append stage 10556 this.$element.append(this.$stage.parent()); 10557 10558 // append content 10559 this.replace(this.$element.children().not(this.$stage.parent())); 10560 10561 // check visibility 10562 if (this.$element.is(':visible')) { 10563 // update view 10564 this.refresh(); 10565 } else { 10566 // invalidate width 10567 this.invalidate('width'); 10568 } 10569 10570 this.$element 10571 .removeClass(this.options.loadingClass) 10572 .addClass(this.options.loadedClass); 10573 10574 // register event handlers 10575 this.registerEventHandlers(); 10576 10577 this.leave('initializing'); 10578 this.trigger('initialized'); 10579 }; 10580 10581 /** 10582 * Setups the current settings. 10583 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 10584 * @todo Support for media queries by using `matchMedia` would be nice. 10585 * @public 10586 */ 10587 Owl.prototype.setup = function() { 10588 var viewport = this.viewport(), 10589 overwrites = this.options.responsive, 10590 match = -1, 10591 settings = null; 10592 10593 if (!overwrites) { 10594 settings = $.extend({}, this.options); 10595 } else { 10596 $.each(overwrites, function(breakpoint) { 10597 if (breakpoint <= viewport && breakpoint > match) { 10598 match = Number(breakpoint); 10599 } 10600 }); 10601 10602 settings = $.extend({}, this.options, overwrites[match]); 10603 delete settings.responsive; 10604 10605 // responsive class 10606 if (settings.responsiveClass) { 10607 this.$element.attr('class', 10608 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 10609 ); 10610 } 10611 } 10612 10613 if (this.settings === null || this._breakpoint !== match) { 10614 this.trigger('change', { property: { name: 'settings', value: settings } }); 10615 this._breakpoint = match; 10616 this.settings = settings; 10617 this.invalidate('settings'); 10618 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 10619 } 10620 }; 10621 10622 /** 10623 * Updates option logic if necessery. 10624 * @protected 10625 */ 10626 Owl.prototype.optionsLogic = function() { 10627 if (this.settings.autoWidth) { 10628 this.settings.stagePadding = false; 10629 this.settings.merge = false; 10630 } 10631 }; 10632 10633 /** 10634 * Prepares an item before add. 10635 * @todo Rename event parameter `content` to `item`. 10636 * @protected 10637 * @returns {jQuery|HTMLElement} - The item container. 10638 */ 10639 Owl.prototype.prepare = function(item, index) { 10640 var event = this.trigger('prepare', { content: item }); 10641 if (!event.data) { 10642 event.data = $('<' + this.settings.itemElement + '/>') 10643 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 10644 } 10645 10646 this.trigger('prepared', { content: event.data }); 10647 10648 return event.data; 10649 }; 10650 10651 /** 10652 * Updates the view. 10653 * @public 10654 */ 10655 Owl.prototype.update = function() { 10656 var i = 0, 10657 n = this._pipe.length, 10658 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 10659 cache = {}; 10660 10661 while (i < n) { 10662 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 10663 this._pipe[i].run(cache); 10664 } 10665 i++; 10666 } 10667 10668 this._invalidated = {}; 10669 10670 !this.is('valid') && this.enter('valid'); 10671 }; 10672 10673 /** 10674 * Gets the width of the view. 10675 * @public 10676 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 10677 * @returns {Number} - The width of the view in pixel. 10678 */ 10679 Owl.prototype.width = function(dimension) { 10680 dimension = dimension || Owl.Width.Default; 10681 switch (dimension) { 10682 case Owl.Width.Inner: 10683 case Owl.Width.Outer: 10684 return this._width; 10685 default: 10686 return this._width - this.settings.stagePadding * 2 + this.settings.margin; 10687 } 10688 }; 10689 10690 /** 10691 * Refreshes the carousel primarily for adaptive purposes. 10692 * @public 10693 */ 10694 Owl.prototype.refresh = function() { 10695 this.enter('refreshing'); 10696 this.trigger('refresh'); 10697 10698 this.setup(); 10699 10700 this.optionsLogic(); 10701 10702 this.$element.addClass(this.options.refreshClass); 10703 10704 this.update(); 10705 10706 this.$element.removeClass(this.options.refreshClass); 10707 10708 this.leave('refreshing'); 10709 this.trigger('refreshed'); 10710 }; 10711 10712 /** 10713 * Checks window `resize` event. 10714 * @protected 10715 */ 10716 Owl.prototype.onThrottledResize = function() { 10717 window.clearTimeout(this.resizeTimer); 10718 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 10719 }; 10720 10721 /** 10722 * Checks window `resize` event. 10723 * @protected 10724 */ 10725 Owl.prototype.onResize = function() { 10726 if (!this._items.length) { 10727 return false; 10728 } 10729 10730 if (this._width === this.$element.width()) { 10731 return false; 10732 } 10733 10734 if (!this.$element.is(':visible')) { 10735 return false; 10736 } 10737 10738 this.enter('resizing'); 10739 10740 if (this.trigger('resize').isDefaultPrevented()) { 10741 this.leave('resizing'); 10742 return false; 10743 } 10744 10745 this.invalidate('width'); 10746 10747 this.refresh(); 10748 10749 this.leave('resizing'); 10750 this.trigger('resized'); 10751 }; 10752 10753 /** 10754 * Registers event handlers. 10755 * @todo Check `msPointerEnabled` 10756 * @todo #261 10757 * @protected 10758 */ 10759 Owl.prototype.registerEventHandlers = function() { 10760 if ($.support.transition) { 10761 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 10762 } 10763 10764 if (this.settings.responsive !== false) { 10765 this.on(window, 'resize', this._handlers.onThrottledResize); 10766 } 10767 10768 if (this.settings.mouseDrag) { 10769 this.$element.addClass(this.options.dragClass); 10770 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 10771 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 10772 } 10773 10774 if (this.settings.touchDrag){ 10775 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 10776 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 10777 } 10778 }; 10779 10780 /** 10781 * Handles `touchstart` and `mousedown` events. 10782 * @todo Horizontal swipe threshold as option 10783 * @todo #261 10784 * @protected 10785 * @param {Event} event - The event arguments. 10786 */ 10787 Owl.prototype.onDragStart = function(event) { 10788 var stage = null; 10789 10790 if (event.which === 3) { 10791 return; 10792 } 10793 10794 if ($.support.transform) { 10795 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 10796 stage = { 10797 x: stage[stage.length === 16 ? 12 : 4], 10798 y: stage[stage.length === 16 ? 13 : 5] 10799 }; 10800 } else { 10801 stage = this.$stage.position(); 10802 stage = { 10803 x: this.settings.rtl ? 10804 stage.left + this.$stage.width() - this.width() + this.settings.margin : 10805 stage.left, 10806 y: stage.top 10807 }; 10808 } 10809 10810 if (this.is('animating')) { 10811 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 10812 this.invalidate('position'); 10813 } 10814 10815 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 10816 10817 this.speed(0); 10818 10819 this._drag.time = new Date().getTime(); 10820 this._drag.target = $(event.target); 10821 this._drag.stage.start = stage; 10822 this._drag.stage.current = stage; 10823 this._drag.pointer = this.pointer(event); 10824 10825 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 10826 10827 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 10828 var delta = this.difference(this._drag.pointer, this.pointer(event)); 10829 10830 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 10831 10832 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 10833 return; 10834 } 10835 10836 event.preventDefault(); 10837 10838 this.enter('dragging'); 10839 this.trigger('drag'); 10840 }, this)); 10841 }; 10842 10843 /** 10844 * Handles the `touchmove` and `mousemove` events. 10845 * @todo #261 10846 * @protected 10847 * @param {Event} event - The event arguments. 10848 */ 10849 Owl.prototype.onDragMove = function(event) { 10850 var minimum = null, 10851 maximum = null, 10852 pull = null, 10853 delta = this.difference(this._drag.pointer, this.pointer(event)), 10854 stage = this.difference(this._drag.stage.start, delta); 10855 10856 if (!this.is('dragging')) { 10857 return; 10858 } 10859 10860 event.preventDefault(); 10861 10862 if (this.settings.loop) { 10863 minimum = this.coordinates(this.minimum()); 10864 maximum = this.coordinates(this.maximum() + 1) - minimum; 10865 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 10866 } else { 10867 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 10868 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 10869 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 10870 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 10871 } 10872 10873 this._drag.stage.current = stage; 10874 10875 this.animate(stage.x); 10876 }; 10877 10878 /** 10879 * Handles the `touchend` and `mouseup` events. 10880 * @todo #261 10881 * @todo Threshold for click event 10882 * @protected 10883 * @param {Event} event - The event arguments. 10884 */ 10885 Owl.prototype.onDragEnd = function(event) { 10886 var delta = this.difference(this._drag.pointer, this.pointer(event)), 10887 stage = this._drag.stage.current, 10888 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 10889 10890 $(document).off('.owl.core'); 10891 10892 this.$element.removeClass(this.options.grabClass); 10893 10894 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 10895 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 10896 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 10897 this.invalidate('position'); 10898 this.update(); 10899 10900 this._drag.direction = direction; 10901 10902 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 10903 this._drag.target.one('click.owl.core', function() { return false; }); 10904 } 10905 } 10906 10907 if (!this.is('dragging')) { 10908 return; 10909 } 10910 10911 this.leave('dragging'); 10912 this.trigger('dragged'); 10913 }; 10914 10915 /** 10916 * Gets absolute position of the closest item for a coordinate. 10917 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 10918 * @protected 10919 * @param {Number} coordinate - The coordinate in pixel. 10920 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 10921 * @return {Number} - The absolute position of the closest item. 10922 */ 10923 Owl.prototype.closest = function(coordinate, direction) { 10924 var position = -1, 10925 pull = 30, 10926 width = this.width(), 10927 coordinates = this.coordinates(); 10928 10929 if (!this.settings.freeDrag) { 10930 // check closest item 10931 $.each(coordinates, $.proxy(function(index, value) { 10932 if (coordinate > value - pull && coordinate < value + pull) { 10933 position = index; 10934 } else if (this.op(coordinate, '<', value) 10935 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 10936 position = direction === 'left' ? index + 1 : index; 10937 } 10938 return position === -1; 10939 }, this)); 10940 } 10941 10942 if (!this.settings.loop) { 10943 // non loop boundries 10944 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 10945 position = coordinate = this.minimum(); 10946 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 10947 position = coordinate = this.maximum(); 10948 } 10949 } 10950 10951 return position; 10952 }; 10953 10954 /** 10955 * Animates the stage. 10956 * @todo #270 10957 * @public 10958 * @param {Number} coordinate - The coordinate in pixels. 10959 */ 10960 Owl.prototype.animate = function(coordinate) { 10961 var animate = this.speed() > 0; 10962 10963 this.is('animating') && this.onTransitionEnd(); 10964 10965 if (animate) { 10966 this.enter('animating'); 10967 this.trigger('translate'); 10968 } 10969 10970 if ($.support.transform3d && $.support.transition) { 10971 this.$stage.css({ 10972 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 10973 transition: (this.speed() / 1000) + 's' 10974 }); 10975 } else if (animate) { 10976 this.$stage.animate({ 10977 left: coordinate + 'px' 10978 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 10979 } else { 10980 this.$stage.css({ 10981 left: coordinate + 'px' 10982 }); 10983 } 10984 }; 10985 10986 /** 10987 * Checks whether the carousel is in a specific state or not. 10988 * @param {String} state - The state to check. 10989 * @returns {Boolean} - The flag which indicates if the carousel is busy. 10990 */ 10991 Owl.prototype.is = function(state) { 10992 return this._states.current[state] && this._states.current[state] > 0; 10993 }; 10994 10995 /** 10996 * Sets the absolute position of the current item. 10997 * @public 10998 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 10999 * @returns {Number} - The absolute position of the current item. 11000 */ 11001 Owl.prototype.current = function(position) { 11002 if (position === undefined) { 11003 return this._current; 11004 } 11005 11006 if (this._items.length === 0) { 11007 return undefined; 11008 } 11009 11010 position = this.normalize(position); 11011 11012 if (this._current !== position) { 11013 var event = this.trigger('change', { property: { name: 'position', value: position } }); 11014 11015 if (event.data !== undefined) { 11016 position = this.normalize(event.data); 11017 } 11018 11019 this._current = position; 11020 11021 this.invalidate('position'); 11022 11023 this.trigger('changed', { property: { name: 'position', value: this._current } }); 11024 } 11025 11026 return this._current; 11027 }; 11028 11029 /** 11030 * Invalidates the given part of the update routine. 11031 * @param {String} [part] - The part to invalidate. 11032 * @returns {Array.<String>} - The invalidated parts. 11033 */ 11034 Owl.prototype.invalidate = function(part) { 11035 if ($.type(part) === 'string') { 11036 this._invalidated[part] = true; 11037 this.is('valid') && this.leave('valid'); 11038 } 11039 return $.map(this._invalidated, function(v, i) { return i }); 11040 }; 11041 11042 /** 11043 * Resets the absolute position of the current item. 11044 * @public 11045 * @param {Number} position - The absolute position of the new item. 11046 */ 11047 Owl.prototype.reset = function(position) { 11048 position = this.normalize(position); 11049 11050 if (position === undefined) { 11051 return; 11052 } 11053 11054 this._speed = 0; 11055 this._current = position; 11056 11057 this.suppress([ 'translate', 'translated' ]); 11058 11059 this.animate(this.coordinates(position)); 11060 11061 this.release([ 'translate', 'translated' ]); 11062 }; 11063 11064 /** 11065 * Normalizes an absolute or a relative position of an item. 11066 * @public 11067 * @param {Number} position - The absolute or relative position to normalize. 11068 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 11069 * @returns {Number} - The normalized position. 11070 */ 11071 Owl.prototype.normalize = function(position, relative) { 11072 var n = this._items.length, 11073 m = relative ? 0 : this._clones.length; 11074 11075 if (!$.isNumeric(position) || n < 1) { 11076 position = undefined; 11077 } else if (position < 0 || position >= n + m) { 11078 position = ((position - m / 2) % n + n) % n + m / 2; 11079 } 11080 11081 return position; 11082 }; 11083 11084 /** 11085 * Converts an absolute position of an item into a relative one. 11086 * @public 11087 * @param {Number} position - The absolute position to convert. 11088 * @returns {Number} - The converted position. 11089 */ 11090 Owl.prototype.relative = function(position) { 11091 position -= this._clones.length / 2; 11092 return this.normalize(position, true); 11093 }; 11094 11095 /** 11096 * Gets the maximum position for the current item. 11097 * @public 11098 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11099 * @returns {Number} 11100 */ 11101 Owl.prototype.maximum = function(relative) { 11102 var settings = this.settings, 11103 maximum = this._coordinates.length, 11104 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 11105 i = -1, j; 11106 11107 if (settings.loop) { 11108 maximum = this._clones.length / 2 + this._items.length - 1; 11109 } else if (settings.autoWidth || settings.merge) {
11110 // binary search 11111 while (maximum - i > 1) { 11112 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 11113 ? i = j : maximum = j; 11114 } 11115 } else if (settings.center) { 11116 maximum = this._items.length - 1; 11117 } else { 11118 maximum = this._items.length - settings.items; 11119 } 11120 11121 if (relative) { 11122 maximum -= this._clones.length / 2; 11123 } 11124 11125 return Math.max(maximum, 0); 11126 }; 11127 11128 /** 11129 * Gets the minimum position for the current item. 11130 * @public 11131 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11132 * @returns {Number} 11133 */ 11134 Owl.prototype.minimum = function(relative) { 11135 return relative ? 0 : this._clones.length / 2; 11136 }; 11137 11138 /** 11139 * Gets an item at the specified relative position. 11140 * @public 11141 * @param {Number} [position] - The relative position of the item. 11142 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11143 */ 11144 Owl.prototype.items = function(position) { 11145 if (position === undefined) { 11146 return this._items.slice(); 11147 } 11148 11149 position = this.normalize(position, true); 11150 return this._items[position]; 11151 }; 11152 11153 /** 11154 * Gets an item at the specified relative position. 11155 * @public 11156 * @param {Number} [position] - The relative position of the item. 11157 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11158 */ 11159 Owl.prototype.mergers = function(position) { 11160 if (position === undefined) { 11161 return this._mergers.slice(); 11162 } 11163 11164 position = this.normalize(position, true); 11165 return this._mergers[position]; 11166 }; 11167 11168 /** 11169 * Gets the absolute positions of clones for an item. 11170 * @public 11171 * @param {Number} [position] - The relative position of the item. 11172 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 11173 */ 11174 Owl.prototype.clones = function(position) { 11175 var odd = this._clones.length / 2, 11176 even = odd + this._items.length, 11177 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 11178 11179 if (position === undefined) { 11180 return $.map(this._clones, function(v, i) { return map(i) }); 11181 } 11182 11183 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 11184 }; 11185 11186 /** 11187 * Sets the current animation speed. 11188 * @public 11189 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 11190 * @returns {Number} - The current animation speed in milliseconds. 11191 */ 11192 Owl.prototype.speed = function(speed) { 11193 if (speed !== undefined) { 11194 this._speed = speed; 11195 } 11196 11197 return this._speed; 11198 }; 11199 11200 /** 11201 * Gets the coordinate of an item. 11202 * @todo The name of this method is missleanding. 11203 * @public 11204 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 11205 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 11206 */ 11207 Owl.prototype.coordinates = function(position) { 11208 var coordinate = null; 11209 11210 if (position === undefined) { 11211 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 11212 return this.coordinates(index); 11213 }, this)); 11214 } 11215 11216 if (this.settings.center) { 11217 coordinate = this._coordinates[position]; 11218 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 11219 } else { 11220 coordinate = this._coordinates[position - 1] || 0; 11221 } 11222 11223 return coordinate; 11224 }; 11225 11226 /** 11227 * Calculates the speed for a translation. 11228 * @protected 11229 * @param {Number} from - The absolute position of the start item. 11230 * @param {Number} to - The absolute position of the target item. 11231 * @param {Number} [factor=undefined] - The time factor in milliseconds. 11232 * @returns {Number} - The time in milliseconds for the translation. 11233 */ 11234 Owl.prototype.duration = function(from, to, factor) { 11235 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 11236 }; 11237 11238 /** 11239 * Slides to the specified item. 11240 * @public 11241 * @param {Number} position - The position of the item. 11242 * @param {Number} [speed] - The time in milliseconds for the transition. 11243 */ 11244 Owl.prototype.to = function(position, speed) { 11245 var current = this.current(), 11246 revert = null, 11247 distance = position - this.relative(current), 11248 direction = (distance > 0) - (distance < 0), 11249 items = this._items.length, 11250 minimum = this.minimum(), 11251 maximum = this.maximum(); 11252 11253 if (this.settings.loop) { 11254 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 11255 distance += direction * -1 * items; 11256 } 11257 11258 position = current + distance; 11259 revert = ((position - minimum) % items + items) % items + minimum; 11260 11261 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 11262 current = revert - distance; 11263 position = revert; 11264 this.reset(current); 11265 } 11266 } else if (this.settings.rewind) { 11267 maximum += 1; 11268 position = (position % maximum + maximum) % maximum; 11269 } else { 11270 position = Math.max(minimum, Math.min(maximum, position)); 11271 } 11272 11273 this.speed(this.duration(current, position, speed)); 11274 this.current(position); 11275 11276 if (this.$element.is(':visible')) { 11277 this.update(); 11278 } 11279 }; 11280 11281 /** 11282 * Slides to the next item. 11283 * @public 11284 * @param {Number}
vendor: 12,284 bytes, lines 11284-11704
11284 [speed] - The time in milliseconds for the transition. 11285 */ 11286 Owl.prototype.next = function(speed) { 11287 speed = speed || false; 11288 this.to(this.relative(this.current()) + 1, speed); 11289 }; 11290 11291 /** 11292 * Slides to the previous item. 11293 * @public 11294 * @param {Number} [speed] - The time in milliseconds for the transition. 11295 */ 11296 Owl.prototype.prev = function(speed) { 11297 speed = speed || false; 11298 this.to(this.relative(this.current()) - 1, speed); 11299 }; 11300 11301 /** 11302 * Handles the end of an animation. 11303 * @protected 11304 * @param {Event} event - The event arguments. 11305 */ 11306 Owl.prototype.onTransitionEnd = function(event) { 11307 11308 // if css2 animation then event object is undefined 11309 if (event !== undefined) { 11310 event.stopPropagation(); 11311 11312 // Catch only owl-stage transitionEnd event 11313 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 11314 return false; 11315 } 11316 } 11317 11318 this.leave('animating'); 11319 this.trigger('translated'); 11320 }; 11321 11322 /** 11323 * Gets viewport width. 11324 * @protected 11325 * @return {Number} - The width in pixel. 11326 */ 11327 Owl.prototype.viewport = function() { 11328 var width; 11329 if (this.options.responsiveBaseElement !== window) { 11330 width = $(this.options.responsiveBaseElement).width(); 11331 } else if (window.innerWidth) { 11332 width = window.innerWidth; 11333 } else if (document.documentElement && document.documentElement.clientWidth) { 11334 width = document.documentElement.clientWidth; 11335 } else { 11336 throw 'Can not detect viewport width.'; 11337 } 11338 11339 return width; 11340 }; 11341 11342 /** 11343 * Replaces the current content. 11344 * @public 11345 * @param {HTMLElement|jQuery|String} content - The new content. 11346 */ 11347 Owl.prototype.replace = function(content) { 11348 this.$stage.empty(); 11349 this._items = []; 11350 11351 if (content) { 11352 content = (content instanceof jQuery) ? content : $(content); 11353 } 11354 11355 if (this.settings.nestedItemSelector) { 11356 content = content.find('.' + this.settings.nestedItemSelector); 11357 } 11358 11359 content.filter(function() { 11360 return this.nodeType === 1; 11361 }).each($.proxy(function(index, item) { 11362 item = this.prepare(item, index); 11363 this.$stage.append(item); 11364 this._items.push(item); 11365 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 11366 }, this)); 11367 11368 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 11369 11370 this.invalidate('items'); 11371 }; 11372 11373 /** 11374 * Adds an item. 11375 * @todo Use `item` instead of `content` for the event arguments. 11376 * @public 11377 * @param {HTMLElement|jQuery|String} content - The item content to add. 11378 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 11379 */ 11380 Owl.prototype.add = function(content, position) { 11381 var current = this.relative(this._current); 11382 11383 position = position === undefined ? this._items.length : this.normalize(position, true); 11384 content = content instanceof jQuery ? content : $(content); 11385 11386 this.trigger('add', { content: content, position: position }); 11387 11388 content = this.prepare(content, this._items[current].index()); 11389 11390 if (this._items.length === 0 || position === this._items.length) { 11391 this._items.length === 0 && this.$stage.append(content); 11392 this._items.length !== 0 && this._items[position - 1].after(content); 11393 this._items.push(content); 11394 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11395 } else { 11396 this._items[position].before(content); 11397 this._items.splice(position, 0, content); 11398 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11399 } 11400 11401 this._items[current] && this.reset(this._items[current].index()); 11402 11403 this.invalidate('items'); 11404 11405 this.trigger('added', { content: content, position: position }); 11406 }; 11407 11408 /** 11409 * Removes an item by its position. 11410 * @todo Use `item` instead of `content` for the event arguments. 11411 * @public 11412 * @param {Number} position - The relative position of the item to remove. 11413 */ 11414 Owl.prototype.remove = function(position) { 11415 position = this.normalize(position, true); 11416 11417 if (position === undefined) { 11418 return; 11419 } 11420 11421 this.trigger('remove', { content: this._items[position], position: position }); 11422 11423 this._items[position].remove(); 11424 this._items.splice(position, 1); 11425 this._mergers.splice(position, 1); 11426 11427 this.invalidate('items'); 11428 11429 this.trigger('removed', { content: null, position: position }); 11430 }; 11431 11432 /** 11433 * Preloads images with auto width. 11434 * @todo Replace by a more generic approach 11435 * @protected 11436 */ 11437 Owl.prototype.preloadAutoWidthImages = function(images) { 11438 images.each($.proxy(function(i, element) { 11439 this.enter('pre-loading'); 11440 element = $(element); 11441 $(new Image()).one('load', $.proxy(function(e) { 11442 element.attr('src', e.target.src); 11443 element.css('opacity', 1); 11444 this.leave('pre-loading'); 11445 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 11446 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 11447 }, this)); 11448 }; 11449 11450 /** 11451 * Destroys the carousel. 11452 * @public 11453 */ 11454 Owl.prototype.destroy = function() { 11455 11456 this.$element.off('.owl.core'); 11457 this.$stage.off('.owl.core'); 11458 $(document).off('.owl.core'); 11459 11460 if (this.settings.responsive !== false) { 11461 window.clearTimeout(this.resizeTimer); 11462 this.off(window, 'resize', this._handlers.onThrottledResize); 11463 } 11464 11465 for (var i in this._plugins) { 11466 this._plugins[i].destroy(); 11467 } 11468 11469 this.$stage.children('.cloned').remove(); 11470 11471 this.$stage.unwrap(); 11472 this.$stage.children().contents().unwrap(); 11473 this.$stage.children().unwrap(); 11474 11475 this.$element 11476 .removeClass(this.options.refreshClass) 11477 .removeClass(this.options.loadingClass) 11478 .removeClass(this.options.loadedClass) 11479 .removeClass(this.options.rtlClass) 11480 .removeClass(this.options.dragClass) 11481 .removeClass(this.options.grabClass) 11482 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 11483 .removeData('owl.carousel'); 11484 }; 11485 11486 /** 11487 * Operators to calculate right-to-left and left-to-right. 11488 * @protected 11489 * @param {Number} [a] - The left side operand. 11490 * @param {String} [o] - The operator. 11491 * @param {Number} [b] - The right side operand. 11492 */ 11493 Owl.prototype.op = function(a, o, b) { 11494 var rtl = this.settings.rtl; 11495 switch (o) { 11496 case '<': 11497 return rtl ? a > b : a < b; 11498 case '>': 11499 return rtl ? a < b : a > b; 11500 case '>=': 11501 return rtl ? a <= b : a >= b; 11502 case '<=': 11503 return rtl ? a >= b : a <= b; 11504 default: 11505 break; 11506 } 11507 }; 11508 11509 /** 11510 * Attaches to an internal event. 11511 * @protected 11512 * @param {HTMLElement} element - The event source. 11513 * @param {String} event - The event name. 11514 * @param {Function} listener - The event handler to attach. 11515 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 11516 */ 11517 Owl.prototype.on = function(element, event, listener, capture) { 11518 if (element.addEventListener) { 11519 element.addEventListener(event, listener, capture); 11520 } else if (element.attachEvent) { 11521 element.attachEvent('on' + event, listener); 11522 } 11523 }; 11524 11525 /** 11526 * Detaches from an internal event. 11527 * @protected 11528 * @param {HTMLElement} element - The event source. 11529 * @param {String} event - The event name. 11530 * @param {Function} listener - The attached event handler to detach. 11531 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 11532 */ 11533 Owl.prototype.off = function(element, event, listener, capture) { 11534 if (element.removeEventListener) { 11535 element.removeEventListener(event, listener, capture); 11536 } else if (element.detachEvent) { 11537 element.detachEvent('on' + event, listener); 11538 } 11539 }; 11540 11541 /** 11542 * Triggers a public event. 11543 * @todo Remove `status`, `relatedTarget` should be used instead. 11544 * @protected 11545 * @param {String} name - The event name. 11546 * @param {*} [data=null] - The event data. 11547 * @param {String} [namespace=carousel] - The event namespace. 11548 * @param {String} [state] - The state which is associated with the event. 11549 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 11550 * @returns {Event} - The event arguments. 11551 */ 11552 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 11553 var status = { 11554 item: { count: this._items.length, index: this.current() } 11555 }, handler = $.camelCase( 11556 $.grep([ 'on', name, namespace ], function(v) { return v }) 11557 .join('-').toLowerCase() 11558 ), event = $.Event( 11559 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 11560 $.extend({ relatedTarget: this }, status, data) 11561 ); 11562 11563 if (!this._supress[name]) { 11564 $.each(this._plugins, function(name, plugin) { 11565 if (plugin.onTrigger) { 11566 plugin.onTrigger(event); 11567 } 11568 }); 11569 11570 this.register({ type: Owl.Type.Event, name: name }); 11571 this.$element.trigger(event); 11572 11573 if (this.settings && typeof this.settings[handler] === 'function') { 11574 this.settings[handler].call(this, event); 11575 } 11576 } 11577 11578 return event; 11579 }; 11580 11581 /** 11582 * Enters a state. 11583 * @param name - The state name. 11584 */ 11585 Owl.prototype.enter = function(name) { 11586 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11587 if (this._states.current[name] === undefined) { 11588 this._states.current[name] = 0; 11589 } 11590 11591 this._states.current[name]++; 11592 }, this)); 11593 }; 11594 11595 /** 11596 * Leaves a state. 11597 * @param name - The state name. 11598 */ 11599 Owl.prototype.leave = function(name) { 11600 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11601 this._states.current[name]--; 11602 }, this)); 11603 }; 11604 11605 /** 11606 * Registers an event or state. 11607 * @public 11608 * @param {Object} object - The event or state to register. 11609 */ 11610 Owl.prototype.register = function(object) { 11611 if (object.type === Owl.Type.Event) { 11612 if (!$.event.special[object.name]) { 11613 $.event.special[object.name] = {}; 11614 } 11615 11616 if (!$.event.special[object.name].owl) { 11617 var _default = $.event.special[object.name]._default; 11618 $.event.special[object.name]._default = function(e) { 11619 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 11620 return _default.apply(this, arguments); 11621 } 11622 return e.namespace && e.namespace.indexOf('owl') > -1; 11623 }; 11624 $.event.special[object.name].owl = true; 11625 } 11626 } else if (object.type === Owl.Type.State) { 11627 if (!this._states.tags[object.name]) { 11628 this._states.tags[object.name] = object.tags; 11629 } else { 11630 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 11631 } 11632 11633 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 11634 return $.inArray(tag, this._states.tags[object.name]) === i; 11635 }, this)); 11636 } 11637 }; 11638 11639 /** 11640 * Suppresses events. 11641 * @protected 11642 * @param {Array.<String>} events - The events to suppress. 11643 */ 11644 Owl.prototype.suppress = function(events) { 11645 $.each(events, $.proxy(function(index, event) { 11646 this._supress[event] = true; 11647 }, this)); 11648 }; 11649 11650 /** 11651 * Releases suppressed events. 11652 * @protected 11653 * @param {Array.<String>} events - The events to release. 11654 */ 11655 Owl.prototype.release = function(events) { 11656 $.each(events, $.proxy(function(index, event) { 11657 delete this._supress[event]; 11658 }, this)); 11659 }; 11660 11661 /** 11662 * Gets unified pointer coordinates from event. 11663 * @todo #261 11664 * @protected 11665 * @param {Event} - The `mousedown` or `touchstart` event. 11666 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 11667 */ 11668 Owl.prototype.pointer = function(event) { 11669 var result = { x: null, y: null }; 11670 11671 event = event.originalEvent || event || window.event; 11672 11673 event = event.touches && event.touches.length ? 11674 event.touches[0] : event.changedTouches && event.changedTouches.length ? 11675 event.changedTouches[0] : event; 11676 11677 if (event.pageX) { 11678 result.x = event.pageX; 11679 result.y = event.pageY; 11680 } else { 11681 result.x = event.clientX; 11682 result.y = event.clientY; 11683 } 11684 11685 return result; 11686 }; 11687 11688 /** 11689 * Gets the difference of two vectors. 11690 * @todo #261 11691 * @protected 11692 * @param {Object} - The first vector. 11693 * @param {Object} - The second vector. 11694 * @returns {Object} - The difference. 11695 */ 11696 Owl.prototype.difference = function(first, second) { 11697 return { 11698 x: first.x - second.x, 11699 y: first.y - second.y 11700 }; 11701 }; 11702 11703 /** 11704 * The jQuery Plugin for the Owl Carousel
vendor: 32,236 bytes, lines 11705-12987
11705 * @todo Navigation plugin `next` and `prev` 11706 * @public 11707 */ 11708 $.fn.owlCarousel = function(option) { 11709 var args = Array.prototype.slice.call(arguments, 1); 11710 11711 return this.each(function() { 11712 var $this = $(this), 11713 data = $this.data('owl.carousel'); 11714 11715 if (!data) { 11716 data = new Owl(this, typeof option == 'object' && option); 11717 $this.data('owl.carousel', data); 11718 11719 $.each([ 11720 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 11721 ], function(i, event) { 11722 data.register({ type: Owl.Type.Event, name: event }); 11723 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 11724 if (e.namespace && e.relatedTarget !== this) { 11725 this.suppress([ event ]); 11726 data[event].apply(this, [].slice.call(arguments, 1)); 11727 this.release([ event ]); 11728 } 11729 }, data)); 11730 }); 11731 } 11732 11733 if (typeof option == 'string' && option.charAt(0) !== '_') { 11734 data[option].apply(data, args); 11735 } 11736 }); 11737 }; 11738 11739 /** 11740 * The constructor for the jQuery Plugin 11741 * @public 11742 */ 11743 $.fn.owlCarousel.Constructor = Owl; 11744 11745})(window.Zepto || window.jQuery, window, document); 11746 11747/** 11748 * AutoRefresh Plugin 11749 * @version 2.0.0-beta.3 11750 * @author Artus Kolanowski 11751 * @license The MIT License (MIT) 11752 */ 11753;(function($, window, document, undefined) { 11754 11755 /** 11756 * Creates the auto refresh plugin. 11757 * @class The Auto Refresh Plugin 11758 * @param {Owl} carousel - The Owl Carousel 11759 */ 11760 var AutoRefresh = function(carousel) { 11761 /** 11762 * Reference to the core. 11763 * @protected 11764 * @type {Owl} 11765 */ 11766 this._core = carousel; 11767 11768 /** 11769 * Refresh interval. 11770 * @protected 11771 * @type {number} 11772 */ 11773 this._interval = null; 11774 11775 /** 11776 * Whether the element is currently visible or not. 11777 * @protected 11778 * @type {Boolean} 11779 */ 11780 this._visible = null; 11781 11782 /** 11783 * All event handlers. 11784 * @protected 11785 * @type {Object} 11786 */ 11787 this._handlers = { 11788 'initialized.owl.carousel': $.proxy(function(e) { 11789 if (e.namespace && this._core.settings.autoRefresh) { 11790 this.watch(); 11791 } 11792 }, this) 11793 }; 11794 11795 // set default options 11796 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 11797 11798 // register event handlers 11799 this._core.$element.on(this._handlers); 11800 }; 11801 11802 /** 11803 * Default options. 11804 * @public 11805 */ 11806 AutoRefresh.Defaults = { 11807 autoRefresh: true, 11808 autoRefreshInterval: 500 11809 }; 11810 11811 /** 11812 * Watches the element. 11813 */ 11814 AutoRefresh.prototype.watch = function() { 11815 if (this._interval) { 11816 return; 11817 } 11818 11819 this._visible = this._core.$element.is(':visible'); 11820 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 11821 }; 11822 11823 /** 11824 * Refreshes the element. 11825 */ 11826 AutoRefresh.prototype.refresh = function() { 11827 if (this._core.$element.is(':visible') === this._visible) { 11828 return; 11829 } 11830 11831 this._visible = !this._visible; 11832 11833 this._core.$element.toggleClass('owl-hidden', !this._visible); 11834 11835 this._visible && (this._core.invalidate('width') && this._core.refresh()); 11836 }; 11837 11838 /** 11839 * Destroys the plugin. 11840 */ 11841 AutoRefresh.prototype.destroy = function() { 11842 var handler, property; 11843 11844 window.clearInterval(this._interval); 11845 11846 for (handler in this._handlers) { 11847 this._core.$element.off(handler, this._handlers[handler]); 11848 } 11849 for (property in Object.getOwnPropertyNames(this)) { 11850 typeof this[property] != 'function' && (this[property] = null); 11851 } 11852 }; 11853 11854 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 11855 11856})(window.Zepto || window.jQuery, window, document); 11857 11858/** 11859 * Lazy Plugin 11860 * @version 2.0.0-beta.3 11861 * @author Bartosz Wojciechowski 11862 * @license The MIT License (MIT) 11863 */ 11864;(function($, window, document, undefined) { 11865 11866 /** 11867 * Creates the lazy plugin. 11868 * @class The Lazy Plugin 11869 * @param {Owl} carousel - The Owl Carousel 11870 */ 11871 var Lazy = function(carousel) { 11872 11873 /** 11874 * Reference to the core. 11875 * @protected 11876 * @type {Owl} 11877 */ 11878 this._core = carousel; 11879 11880 /** 11881 * Already loaded items. 11882 * @protected 11883 * @type {Array.<jQuery>} 11884 */ 11885 this._loaded = []; 11886 11887 /** 11888 * Event handlers. 11889 * @protected 11890 * @type {Object} 11891 */ 11892 this._handlers = { 11893 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 11894 if (!e.namespace) { 11895 return; 11896 } 11897 11898 if (!this._core.settings || !this._core.settings.lazyLoad) { 11899 return; 11900 } 11901 11902 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 11903 var settings = this._core.settings, 11904 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 11905 i = ((settings.center && n * -1) || 0), 11906 position = ((e.property && e.property.value) || this._core.current()) + i, 11907 clones = this._core.clones().length, 11908 load = $.proxy(function(i, v) { this.load(v) }, this); 11909 11910 while (i++ < n) { 11911 this.load(clones / 2 + this._core.relative(position)); 11912 clones && $.each(this._core.clones(this._core.relative(position)), load); 11913 position++; 11914 } 11915 } 11916 }, this) 11917 }; 11918 11919 // set the default options 11920 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 11921 11922 // register event handler 11923 this._core.$element.on(this._handlers); 11924 } 11925 11926 /** 11927 * Default options. 11928 * @public 11929 */ 11930 Lazy.Defaults = { 11931 lazyLoad: false 11932 } 11933 11934 /** 11935 * Loads all resources of an item at the specified position. 11936 * @param {Number} position - The absolute position of the item. 11937 * @protected 11938 */ 11939 Lazy.prototype.load = function(position) { 11940 var $item = this._core.$stage.children().eq(position), 11941 $elements = $item && $item.find('.owl-lazy'); 11942 11943 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 11944 return; 11945 } 11946 11947 $elements.each($.proxy(function(index, element) { 11948 var $element = $(element), image, 11949 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 11950 11951 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 11952 11953 if ($element.is('img')) { 11954 $element.one('load.owl.lazy', $.proxy(function() { 11955 $element.css('opacity', 1); 11956 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 11957 }, this)).attr('src', url); 11958 } else { 11959 image = new Image(); 11960 image.onload = $.proxy(function() { 11961 $element.css({ 11962 'background-image': 'url(' + url + ')', 11963 'opacity': '1' 11964 }); 11965 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 11966 }, this); 11967 image.src = url; 11968 } 11969 }, this)); 11970 11971 this._loaded.push($item.get(0)); 11972 } 11973 11974 /** 11975 * Destroys the plugin. 11976 * @public 11977 */ 11978 Lazy.prototype.destroy = function() { 11979 var handler, property; 11980 11981 for (handler in this.handlers) { 11982 this._core.$element.off(handler, this.handlers[handler]); 11983 } 11984 for (property in Object.getOwnPropertyNames(this)) { 11985 typeof this[property] != 'function' && (this[property] = null); 11986 } 11987 }; 11988 11989 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 11990 11991})(window.Zepto || window.jQuery, window, document); 11992 11993/** 11994 * AutoHeight Plugin 11995 * @version 2.0.0-beta.3 11996 * @author Bartosz Wojciechowski 11997 * @license The MIT License (MIT) 11998 */ 11999;(function($, window, document, undefined) { 12000 12001 /** 12002 * Creates the auto height plugin. 12003 * @class The Auto Height Plugin 12004 * @param {Owl} carousel - The Owl Carousel 12005 */ 12006 var AutoHeight = function(carousel) { 12007 /** 12008 * Reference to the core. 12009 * @protected 12010 * @type {Owl} 12011 */ 12012 this._core = carousel; 12013 12014 /** 12015 * All event handlers. 12016 * @protected 12017 * @type {Object} 12018 */ 12019 this._handlers = { 12020 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 12021 if (e.namespace && this._core.settings.autoHeight) { 12022 this.update(); 12023 } 12024 }, this), 12025 'changed.owl.carousel': $.proxy(function(e) { 12026 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 12027 this.update(); 12028 } 12029 }, this), 12030 'loaded.owl.lazy': $.proxy(function(e) { 12031 if (e.namespace && this._core.settings.autoHeight 12032 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 12033 this.update(); 12034 } 12035 }, this) 12036 }; 12037 12038 // set default options 12039 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 12040 12041 // register event handlers 12042 this._core.$element.on(this._handlers); 12043 }; 12044 12045 /** 12046 * Default options. 12047 * @public 12048 */ 12049 AutoHeight.Defaults = { 12050 autoHeight: false, 12051 autoHeightClass: 'owl-height' 12052 }; 12053 12054 /** 12055 * Updates the view. 12056 */ 12057 AutoHeight.prototype.update = function() { 12058 var start = this._core._current, 12059 end = start + this._core.settings.items, 12060 visible = this._core.$stage.children().toArray().slice(start, end); 12061 heights = [], 12062 maxheight = 0; 12063 12064 $.each(visible, function(index, item) { 12065 heights.push($(item).height()); 12066 }); 12067 12068 maxheight = Math.max.apply(null, heights); 12069 12070 this._core.$stage.parent() 12071 .height(maxheight) 12072 .addClass(this._core.settings.autoHeightClass); 12073 }; 12074 12075 AutoHeight.prototype.destroy = function() { 12076 var handler, property; 12077 12078 for (handler in this._handlers) { 12079 this._core.$element.off(handler, this._handlers[handler]); 12080 } 12081 for (property in Object.getOwnPropertyNames(this)) { 12082 typeof this[property] != 'function' && (this[property] = null); 12083 } 12084 }; 12085 12086 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 12087 12088})(window.Zepto || window.jQuery, window, document); 12089 12090/** 12091 * Video Plugin 12092 * @version 2.0.0-beta.3 12093 * @author Bartosz Wojciechowski 12094 * @license The MIT License (MIT) 12095 */ 12096;(function($, window, document, undefined) { 12097 12098 /** 12099 * Creates the video plugin. 12100 * @class The Video Plugin 12101 * @param {Owl} carousel - The Owl Carousel 12102 */ 12103 var Video = function(carousel) { 12104 /** 12105 * Reference to the core. 12106 * @protected 12107 * @type {Owl} 12108 */ 12109 this._core = carousel; 12110 12111 /** 12112 * Cache all video URLs. 12113 * @protected 12114 * @type {Object} 12115 */ 12116 this._videos = {}; 12117 12118 /** 12119 * Current playing item. 12120 * @protected 12121 * @type {jQuery} 12122 */ 12123 this._playing = null; 12124 12125 /** 12126 * All event handlers. 12127 * @todo The cloned content removale is too late 12128 * @protected 12129 * @type {Object} 12130 */ 12131 this._handlers = { 12132 'initialized.owl.carousel': $.proxy(function(e) { 12133 if (e.namespace) { 12134 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 12135 } 12136 }, this), 12137 'resize.owl.carousel': $.proxy(function(e) { 12138 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 12139 e.preventDefault(); 12140 } 12141 }, this), 12142 'refreshed.owl.carousel': $.proxy(function(e) { 12143 if (e.namespace && this._core.is('resizing')) { 12144 this._core.$stage.find('.cloned .owl-video-frame').remove(); 12145 } 12146 }, this), 12147 'changed.owl.carousel': $.proxy(function(e) { 12148 if (e.namespace && e.property.name === 'position' && this._playing) { 12149 this.stop(); 12150 } 12151 }, this), 12152 'prepared.owl.carousel': $.proxy(function(e) { 12153 if (!e.namespace) { 12154 return; 12155 } 12156 12157 var $element = $(e.content).find('.owl-video'); 12158 12159 if ($element.length) { 12160 $element.css('display', 'none'); 12161 this.fetch($element, $(e.content)); 12162 } 12163 }, this) 12164 }; 12165 12166 // set default options 12167 this._core.options = $.extend({}, Video.Defaults, this._core.options); 12168 12169 // register event handlers 12170 this._core.$element.on(this._handlers); 12171 12172 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 12173 this.play(e); 12174 }, this)); 12175 }; 12176 12177 /** 12178 * Default options. 12179 * @public 12180 */ 12181 Video.Defaults = { 12182 video: false, 12183 videoHeight: false, 12184 videoWidth: false 12185 }; 12186 12187 /** 12188 * Gets the video ID and the type (YouTube/Vimeo only). 12189 * @protected 12190 * @param {jQuery} target - The target containing the video data. 12191 * @param {jQuery} item - The item containing the video. 12192 */ 12193 Video.prototype.fetch = function(target, item) { 12194 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 12195 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 12196 width = target.attr('data-width') || this._core.settings.videoWidth, 12197 height = target.attr('data-height') || this._core.settings.videoHeight, 12198 url = target.attr('href'); 12199 12200 if (url) { 12201 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+)?/); 12202 12203 if (id[3].indexOf('youtu') > -1) { 12204 type = 'youtube'; 12205 } else if (id[3].indexOf('vimeo') > -1) { 12206 type = 'vimeo'; 12207 } else { 12208 throw new Error('Video URL not supported.'); 12209 } 12210 id = id[6]; 12211 } else { 12212 throw new Error('Missing video URL.'); 12213 } 12214 12215 this._videos[url] = { 12216 type: type, 12217 id: id, 12218 width: width, 12219 height: height 12220 }; 12221 12222 item.attr('data-video', url); 12223 12224 this.thumbnail(target, this._videos[url]); 12225 }; 12226 12227 /** 12228 * Creates video thumbnail. 12229 * @protected 12230 * @param {jQuery} target - The target containing the video data. 12231 * @param {Object} info - The video info object. 12232 * @see `fetch` 12233 */ 12234 Video.prototype.thumbnail = function(target, video) { 12235 var tnLink, 12236 icon, 12237 path, 12238 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 12239 customTn = target.find('img'), 12240 srcType = 'src', 12241 lazyClass = '', 12242 settings = this._core.settings, 12243 create = function(path) { 12244 icon = '<div class="owl-video-play-icon"></div>'; 12245 12246 if (settings.lazyLoad) { 12247 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 12248 } else { 12249 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 12250 } 12251 target.after(tnLink); 12252 target.after(icon); 12253 }; 12254 12255 // wrap video content into owl-video-wrapper div 12256 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 12257 12258 if (this._core.settings.lazyLoad) { 12259 srcType = 'data-src'; 12260 lazyClass = 'owl-lazy'; 12261 } 12262 12263 // custom thumbnail 12264 if (customTn.length) { 12265 create(customTn.attr(srcType)); 12266 customTn.remove(); 12267 return false; 12268 } 12269 12270 if (video.type === 'youtube') { 12271 path = "http://img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 12272 create(path); 12273 } else if (video.type === 'vimeo') { 12274 $.ajax({ 12275 type: 'GET', 12276 url: 'http://vimeo.com/api/v2/video/' + video.id + '.json', 12277 jsonp: 'callback', 12278 dataType: 'jsonp', 12279 success: function(data) { 12280 path = data[0].thumbnail_large; 12281 create(path); 12282 } 12283 }); 12284 } 12285 }; 12286 12287 /** 12288 * Stops the current video. 12289 * @public 12290 */ 12291 Video.prototype.stop = function() { 12292 this._core.trigger('stop', null, 'video'); 12293 this._playing.find('.owl-video-frame').remove(); 12294 this._playing.removeClass('owl-video-playing'); 12295 this._playing = null; 12296 this._core.leave('playing'); 12297 this._core.trigger('stopped', null, 'video'); 12298 }; 12299 12300 /** 12301 * Starts the current video. 12302 * @public 12303 * @param {Event} event - The event arguments. 12304 */ 12305 Video.prototype.play = function(event) { 12306 var target = $(event.target), 12307 item = target.closest('.' + this._core.settings.itemClass), 12308 video = this._videos[item.attr('data-video')], 12309 width = video.width || '100%', 12310 height = video.height || this._core.$stage.height(), 12311 html; 12312 12313 if (this._playing) { 12314 return; 12315 } 12316 12317 this._core.enter('playing'); 12318 this._core.trigger('play', null, 'video'); 12319 12320 item = this._core.items(this._core.relative(item.index())); 12321 12322 this._core.reset(item.index()); 12323 12324 if (video.type === 'youtube') { 12325 html = '<iframe width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/' + 12326 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 12327 } else if (video.type === 'vimeo') { 12328 html = '<iframe src="http://player.vimeo.com/video/' + video.id + 12329 '?autoplay=1" width="' + width + '" height="' + height + 12330 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 12331 } 12332 12333 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 12334 12335 this._playing = item.addClass('owl-video-playing'); 12336 }; 12337 12338 /** 12339 * Checks whether an video is currently in full screen mode or not. 12340 * @todo Bad style because looks like a readonly method but changes members. 12341 * @protected 12342 * @returns {Boolean} 12343 */ 12344 Video.prototype.isInFullScreen = function() { 12345 var element = document.fullscreenElement || document.mozFullScreenElement || 12346 document.webkitFullscreenElement; 12347 12348 return element && $(element).parent().hasClass('owl-video-frame'); 12349 }; 12350 12351 /** 12352 * Destroys the plugin. 12353 */ 12354 Video.prototype.destroy = function() { 12355 var handler, property; 12356 12357 this._core.$element.off('click.owl.video'); 12358 12359 for (handler in this._handlers) { 12360 this._core.$element.off(handler, this._handlers[handler]); 12361 } 12362 for (property in Object.getOwnPropertyNames(this)) { 12363 typeof this[property] != 'function' && (this[property] = null); 12364 } 12365 }; 12366 12367 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 12368 12369})(window.Zepto || window.jQuery, window, document); 12370 12371/** 12372 * Animate Plugin 12373 * @version 2.0.0-beta.3 12374 * @author Bartosz Wojciechowski 12375 * @license The MIT License (MIT) 12376 */ 12377;(function($, window, document, undefined) { 12378 12379 /** 12380 * Creates the animate plugin. 12381 * @class The Navigation Plugin 12382 * @param {Owl} scope - The Owl Carousel 12383 */ 12384 var Animate = function(scope) { 12385 this.core = scope; 12386 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 12387 this.swapping = true; 12388 this.previous = undefined; 12389 this.next = undefined; 12390 12391 this.handlers = { 12392 'change.owl.carousel': $.proxy(function(e) { 12393 if (e.namespace && e.property.name == 'position') { 12394 this.previous = this.core.current(); 12395 this.next = e.property.value; 12396 } 12397 }, this), 12398 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 12399 if (e.namespace) { 12400 this.swapping = e.type == 'translated'; 12401 } 12402 }, this), 12403 'translate.owl.carousel': $.proxy(function(e) { 12404 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 12405 this.swap(); 12406 } 12407 }, this) 12408 }; 12409 12410 this.core.$element.on(this.handlers); 12411 }; 12412 12413 /** 12414 * Default options. 12415 * @public 12416 */ 12417 Animate.Defaults = { 12418 animateOut: false, 12419 animateIn: false 12420 }; 12421 12422 /** 12423 * Toggles the animation classes whenever an translations starts. 12424 * @protected 12425 * @returns {Boolean|undefined} 12426 */ 12427 Animate.prototype.swap = function() { 12428 12429 if (this.core.settings.items !== 1) { 12430 return; 12431 } 12432 12433 if (!$.support.animation || !$.support.transition) { 12434 return; 12435 } 12436 12437 this.core.speed(0); 12438 12439 var left, 12440 clear = $.proxy(this.clear, this), 12441 previous = this.core.$stage.children().eq(this.previous), 12442 next = this.core.$stage.children().eq(this.next), 12443 incoming = this.core.settings.animateIn, 12444 outgoing = this.core.settings.animateOut; 12445 12446 if (this.core.current() === this.previous) { 12447 return; 12448 } 12449 12450 if (outgoing) { 12451 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 12452 previous.css( { 'left': left + 'px' } ) 12453 .addClass('animated owl-animated-out') 12454 .addClass(outgoing) 12455 .on($.support.animation.end, clear); 12456 } 12457 12458 if (incoming) { 12459 next.addClass('animated owl-animated-in') 12460 .addClass(incoming) 12461 .on($.support.animation.end, clear); 12462 } 12463 }; 12464 12465 Animate.prototype.clear = function(e) { 12466 if ($(e.target).hasClass('animated')) { 12467 $(e.target).css( { 'left': '' } ) 12468 .removeClass('animated owl-animated-out owl-animated-in') 12469 .removeClass(this.core.settings.animateIn) 12470 .removeClass(this.core.settings.animateOut); 12471 this.core.onTransitionEnd(); 12472 } 12473 }; 12474 12475 /** 12476 * Destroys the plugin. 12477 * @public 12478 */ 12479 Animate.prototype.destroy = function() { 12480 var handler, property; 12481 12482 for (handler in this.handlers) { 12483 this.core.$element.off(handler, this.handlers[handler]); 12484 } 12485 for (property in Object.getOwnPropertyNames(this)) { 12486 typeof this[property] != 'function' && (this[property] = null); 12487 } 12488 }; 12489 12490 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 12491 12492})(window.Zepto || window.jQuery, window, document); 12493 12494/** 12495 * Autoplay Plugin 12496 * @version 2.0.0-beta.3 12497 * @author Bartosz Wojciechowski 12498 * @author Artus Kolanowski 12499 * @license The MIT License (MIT) 12500 */ 12501;(function($, window, document, undefined) { 12502 12503 /** 12504 * Creates the autoplay plugin. 12505 * @class The Autoplay Plugin 12506 * @param {Owl} scope - The Owl Carousel 12507 */ 12508 var Autoplay = function(carousel) { 12509 /** 12510 * Reference to the core. 12511 * @protected 12512 * @type {Owl} 12513 */ 12514 this._core = carousel; 12515 12516 /** 12517 * The autoplay interval. 12518 * @type {Number} 12519 */ 12520 this._interval = null; 12521 12522 /** 12523 * Indicates whenever the autoplay is paused. 12524 * @type {Boolean} 12525 */ 12526 this._paused = false; 12527 12528 /** 12529 * All event handlers. 12530 * @protected 12531 * @type {Object} 12532 */ 12533 this._handlers = { 12534 'changed.owl.carousel': $.proxy(function(e) { 12535 if (e.namespace && e.property.name === 'settings') { 12536 if (this._core.settings.autoplay) { 12537 this.play(); 12538 } else { 12539 this.stop(); 12540 } 12541 } 12542 }, this), 12543 'initialized.owl.carousel': $.proxy(function(e) { 12544 if (e.namespace && this._core.settings.autoplay) { 12545 this.play(); 12546 } 12547 }, this), 12548 'play.owl.autoplay': $.proxy(function(e, t, s) { 12549 if (e.namespace) { 12550 this.play(t, s); 12551 } 12552 }, this), 12553 'stop.owl.autoplay': $.proxy(function(e) { 12554 if (e.namespace) { 12555 this.stop(); 12556 } 12557 }, this), 12558 'mouseover.owl.autoplay': $.proxy(function() { 12559 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12560 this.pause(); 12561 } 12562 }, this), 12563 'mouseleave.owl.autoplay': $.proxy(function() { 12564 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12565 this.play(); 12566 } 12567 }, this) 12568 }; 12569 12570 // register event handlers 12571 this._core.$element.on(this._handlers); 12572 12573 // set default options 12574 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 12575 }; 12576 12577 /** 12578 * Default options. 12579 * @public 12580 */ 12581 Autoplay.Defaults = { 12582 autoplay: false, 12583 autoplayTimeout: 5000, 12584 autoplayHoverPause: false, 12585 autoplaySpeed: false 12586 }; 12587 12588 /** 12589 * Starts the autoplay. 12590 * @public 12591 * @param {Number} [timeout] - The interval before the next animation starts. 12592 * @param {Number} [speed] - The animation speed for the animations. 12593 */ 12594 Autoplay.prototype.play = function(timeout, speed) { 12595 this._paused = false; 12596 12597 if (this._core.is('rotating')) { 12598 return; 12599 } 12600 12601 this._core.enter('rotating'); 12602 12603 this._interval = window.setInterval($.proxy(function() { 12604 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 12605 return; 12606 } 12607 this._core.next(speed || this._core.settings.autoplaySpeed); 12608 }, this), timeout || this._core.settings.autoplayTimeout); 12609 }; 12610 12611 /** 12612 * Stops the autoplay. 12613 * @public 12614 */ 12615 Autoplay.prototype.stop = function() { 12616 if (!this._core.is('rotating')) { 12617 return; 12618 } 12619 12620 window.clearInterval(this._interval); 12621 this._core.leave('rotating'); 12622 }; 12623 12624 /** 12625 * Stops the autoplay. 12626 * @public 12627 */ 12628 Autoplay.prototype.pause = function() { 12629 if (!this._core.is('rotating')) { 12630 return; 12631 } 12632 12633 this._paused = true; 12634 }; 12635 12636 /** 12637 * Destroys the plugin. 12638 */ 12639 Autoplay.prototype.destroy = function() { 12640 var handler, property; 12641 12642 this.stop(); 12643 12644 for (handler in this._handlers) { 12645 this._core.$element.off(handler, this._handlers[handler]); 12646 } 12647 for (property in Object.getOwnPropertyNames(this)) { 12648 typeof this[property] != 'function' && (this[property] = null); 12649 } 12650 }; 12651 12652 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 12653 12654})(window.Zepto || window.jQuery, window, document); 12655 12656/** 12657 * Navigation Plugin 12658 * @version 2.0.0-beta.3 12659 * @author Artus Kolanowski 12660 * @license The MIT License (MIT) 12661 */ 12662;(function($, window, document, undefined) { 12663 'use strict'; 12664 12665 /** 12666 * Creates the navigation plugin. 12667 * @class The Navigation Plugin 12668 * @param {Owl} carousel - The Owl Carousel. 12669 */ 12670 var Navigation = function(carousel) { 12671 /** 12672 * Reference to the core. 12673 * @protected 12674 * @type {Owl} 12675 */ 12676 this._core = carousel; 12677 12678 /** 12679 * Indicates whether the plugin is initialized or not. 12680 * @protected 12681 * @type {Boolean} 12682 */ 12683 this._initialized = false; 12684 12685 /** 12686 * The current paging indexes. 12687 * @protected 12688 * @type {Array} 12689 */ 12690 this._pages = []; 12691 12692 /** 12693 * All DOM elements of the user interface. 12694 * @protected 12695 * @type {Object} 12696 */ 12697 this._controls = {}; 12698 12699 /** 12700 * Markup for an indicator. 12701 * @protected 12702 * @type {Array.<String>} 12703 */ 12704 this._templates = []; 12705 12706 /** 12707 * The carousel element. 12708 * @type {jQuery} 12709 */ 12710 this.$element = this._core.$element; 12711 12712 /** 12713 * Overridden methods of the carousel. 12714 * @protected 12715 * @type {Object} 12716 */ 12717 this._overrides = { 12718 next: this._core.next, 12719 prev: this._core.prev, 12720 to: this._core.to 12721 }; 12722 12723 /** 12724 * All event handlers. 12725 * @protected 12726 * @type {Object} 12727 */ 12728 this._handlers = { 12729 'prepared.owl.carousel': $.proxy(function(e) { 12730 if (e.namespace && this._core.settings.dotsData) { 12731 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 12732 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 12733 } 12734 }, this), 12735 'added.owl.carousel': $.proxy(function(e) { 12736 if (e.namespace && this._core.settings.dotsData) { 12737 this._templates.splice(e.position, 0, this._templates.pop()); 12738 } 12739 }, this), 12740 'remove.owl.carousel': $.proxy(function(e) { 12741 if (e.namespace && this._core.settings.dotsData) { 12742 this._templates.splice(e.position, 1); 12743 } 12744 }, this), 12745 'changed.owl.carousel': $.proxy(function(e) { 12746 if (e.namespace && e.property.name == 'position') { 12747 this.draw(); 12748 } 12749 }, this), 12750 'initialized.owl.carousel': $.proxy(function(e) { 12751 if (e.namespace && !this._initialized) { 12752 this._core.trigger('initialize', null, 'navigation'); 12753 this.initialize(); 12754 this.update(); 12755 this.draw(); 12756 this._initialized = true; 12757 this._core.trigger('initialized', null, 'navigation'); 12758 } 12759 }, this), 12760 'refreshed.owl.carousel': $.proxy(function(e) { 12761 if (e.namespace && this._initialized) { 12762 this._core.trigger('refresh', null, 'navigation'); 12763 this.update(); 12764 this.draw(); 12765 this._core.trigger('refreshed', null, 'navigation'); 12766 } 12767 }, this) 12768 }; 12769 12770 // set default options 12771 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 12772 12773 // register event handlers 12774 this.$element.on(this._handlers); 12775 }; 12776 12777 /** 12778 * Default options. 12779 * @public 12780 * @todo Rename `slideBy` to `navBy` 12781 */ 12782 Navigation.Defaults = { 12783 nav: false, 12784 navText: [ 'prev', 'next' ], 12785 navSpeed: false, 12786 navElement: 'div', 12787 navContainer: false, 12788 navContainerClass: 'owl-nav', 12789 navClass: [ 'owl-prev', 'owl-next' ], 12790 slideBy: 1, 12791 dotClass: 'owl-dot', 12792 dotsClass: 'owl-dots', 12793 dots: true, 12794 dotsEach: false, 12795 dotsData: false, 12796 dotsSpeed: false, 12797 dotsContainer: false 12798 }; 12799 12800 /** 12801 * Initializes the layout of the plugin and extends the carousel. 12802 * @protected 12803 */ 12804 Navigation.prototype.initialize = function() { 12805 var override, 12806 settings = this._core.settings; 12807 12808 // create DOM structure for relative navigation 12809 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 12810 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 12811 12812 this._controls.$previous = $('<' + settings.navElement + '>') 12813 .addClass(settings.navClass[0]) 12814 .html(settings.navText[0]) 12815 .prependTo(this._controls.$relative) 12816 .on('click', $.proxy(function(e) { 12817 this.prev(settings.navSpeed); 12818 }, this)); 12819 this._controls.$next = $('<' + settings.navElement + '>') 12820 .addClass(settings.navClass[1]) 12821 .html(settings.navText[1]) 12822 .appendTo(this._controls.$relative) 12823 .on('click', $.proxy(function(e) { 12824 this.next(settings.navSpeed); 12825 }, this)); 12826 12827 // create DOM structure for absolute navigation 12828 if (!settings.dotsData) { 12829 this._templates = [ $('<div>') 12830 .addClass(settings.dotClass) 12831 .append($('<span>')) 12832 .prop('outerHTML') ]; 12833 } 12834 12835 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 12836 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 12837 12838 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 12839 var index = $(e.target).parent().is(this._controls.$absolute) 12840 ? $(e.target).index() : $(e.target).parent().index(); 12841 12842 e.preventDefault(); 12843 12844 this.to(index, settings.dotsSpeed); 12845 }, this)); 12846 12847 // override public methods of the carousel 12848 for (override in this._overrides) { 12849 this._core[override] = $.proxy(this[override], this); 12850 } 12851 }; 12852 12853 /** 12854 * Destroys the plugin. 12855 * @protected 12856 */ 12857 Navigation.prototype.destroy = function() { 12858 var handler, control, property, override; 12859 12860 for (handler in this._handlers) { 12861 this.$element.off(handler, this._handlers[handler]); 12862 } 12863 for (control in this._controls) { 12864 this._controls[control].remove(); 12865 } 12866 for (override in this.overides) { 12867 this._core[override] = this._overrides[override]; 12868 } 12869 for (property in Object.getOwnPropertyNames(this)) { 12870 typeof this[property] != 'function' && (this[property] = null); 12871 } 12872 }; 12873 12874 /** 12875 * Updates the internal state. 12876 * @protected 12877 */ 12878 Navigation.prototype.update = function() { 12879 var i, j, k, 12880 lower = this._core.clones().length / 2, 12881 upper = lower + this._core.items().length, 12882 maximum = this._core.maximum(true), 12883 settings = this._core.settings, 12884 size = settings.center || settings.autoWidth || settings.dotsData 12885 ? 1 : settings.dotsEach || settings.items; 12886 12887 if (settings.slideBy !== 'page') { 12888 settings.slideBy = Math.min(settings.slideBy, settings.items); 12889 } 12890 12891 if (settings.dots || settings.slideBy == 'page') { 12892 this._pages = []; 12893 12894 for (i = lower, j = 0, k = 0; i < upper; i++) { 12895 if (j >= size || j === 0) { 12896 this._pages.push({ 12897 start: Math.min(maximum, i - lower), 12898 end: i - lower + size - 1 12899 }); 12900 if (Math.min(maximum, i - lower) === maximum) { 12901 break; 12902 } 12903 j = 0, ++k; 12904 } 12905 j += this._core.mergers(this._core.relative(i)); 12906 } 12907 } 12908 }; 12909 12910 /** 12911 * Draws the user interface. 12912 * @todo The option `dotsData` wont work. 12913 * @protected 12914 */ 12915 Navigation.prototype.draw = function() { 12916 var difference, 12917 settings = this._core.settings, 12918 disabled = this._core.items().length <= settings.items, 12919 index = this._core.relative(this._core.current()), 12920 loop = settings.loop || settings.rewind; 12921 12922 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 12923 12924 if (settings.nav) { 12925 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 12926 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 12927 } 12928 12929 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 12930 12931 if (settings.dots) { 12932 difference = this._pages.length - this._controls.$absolute.children().length; 12933 12934 if (settings.dotsData && difference !== 0) { 12935 this._controls.$absolute.html(this._templates.join('')); 12936 } else if (difference > 0) { 12937 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 12938 } else if (difference < 0) { 12939 this._controls.$absolute.children().slice(difference).remove(); 12940 } 12941 12942 this._controls.$absolute.find('.active').removeClass('active'); 12943 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 12944 } 12945 }; 12946 12947 /** 12948 * Extends event data. 12949 * @protected 12950 * @param {Event} event - The event object which gets thrown. 12951 */ 12952 Navigation.prototype.onTrigger = function(event) { 12953 var settings = this._core.settings; 12954 12955 event.page = { 12956 index: $.inArray(this.current(), this._pages), 12957 count: this._pages.length, 12958 size: settings && (settings.center || settings.autoWidth || settings.dotsData 12959 ? 1 : settings.dotsEach || settings.items) 12960 }; 12961 }; 12962 12963 /** 12964 * Gets the current page position of the carousel. 12965 * @protected 12966 * @returns {Number} 12967 */ 12968 Navigation.prototype.current = function() { 12969 var current = this._core.relative(this._core.current()); 12970 return $.grep(this._pages, $.proxy(function(page, index) { 12971 return page.start <= current && page.end >= current; 12972 }, this)).pop(); 12973 }; 12974 12975 /** 12976 * Gets the current succesor/predecessor position. 12977 * @protected 12978 * @returns {Number} 12979 */ 12980 Navigation.prototype.getPosition = function(successor) { 12981 var position, length, 12982 settings = this._core.settings; 12983 12984 if (settings.slideBy == 'page') { 12985 position = $.inArray(this.current(), this._pages); 12986 length = this._pages.length; 12987 successor ? ++position : --position;
vendor: 5,670 bytes, lines 12988-13212
12988 position = this._pages[((position % length) + length) % length].start; 12989 } else { 12990 position = this._core.relative(this._core.current()); 12991 length = this._core.items().length; 12992 successor ? position += settings.slideBy : position -= settings.slideBy; 12993 } 12994 12995 return position; 12996 }; 12997 12998 /** 12999 * Slides to the next item or page. 13000 * @public 13001 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13002 */ 13003 Navigation.prototype.next = function(speed) { 13004 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 13005 }; 13006 13007 /** 13008 * Slides to the previous item or page. 13009 * @public 13010 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13011 */ 13012 Navigation.prototype.prev = function(speed) { 13013 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 13014 }; 13015 13016 /** 13017 * Slides to the specified item or page. 13018 * @public 13019 * @param {Number} position - The position of the item or page. 13020 * @param {Number} [speed] - The time in milliseconds for the transition. 13021 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 13022 */ 13023 Navigation.prototype.to = function(position, speed, standard) { 13024 var length; 13025 13026 if (!standard) { 13027 length = this._pages.length; 13028 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 13029 } else { 13030 $.proxy(this._overrides.to, this._core)(position, speed); 13031 } 13032 }; 13033 13034 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 13035 13036})(window.Zepto || window.jQuery, window, document); 13037 13038/** 13039 * Hash Plugin 13040 * @version 2.0.0-beta.3 13041 * @author Artus Kolanowski 13042 * @license The MIT License (MIT) 13043 */ 13044;(function($, window, document, undefined) { 13045 'use strict'; 13046 13047 /** 13048 * Creates the hash plugin. 13049 * @class The Hash Plugin 13050 * @param {Owl} carousel - The Owl Carousel 13051 */ 13052 var Hash = function(carousel) { 13053 /** 13054 * Reference to the core. 13055 * @protected 13056 * @type {Owl} 13057 */ 13058 this._core = carousel; 13059 13060 /** 13061 * Hash index for the items. 13062 * @protected 13063 * @type {Object} 13064 */ 13065 this._hashes = {}; 13066 13067 /** 13068 * The carousel element. 13069 * @type {jQuery} 13070 */ 13071 this.$element = this._core.$element; 13072 13073 /** 13074 * All event handlers. 13075 * @protected 13076 * @type {Object} 13077 */ 13078 this._handlers = { 13079 'initialized.owl.carousel': $.proxy(function(e) { 13080 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 13081 $(window).trigger('hashchange.owl.navigation'); 13082 } 13083 }, this), 13084 'prepared.owl.carousel': $.proxy(function(e) { 13085 if (e.namespace) { 13086 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 13087 13088 if (!hash) { 13089 return; 13090 } 13091 13092 this._hashes[hash] = e.content; 13093 } 13094 }, this), 13095 'changed.owl.carousel': $.proxy(function(e) { 13096 if (e.namespace && e.property.name === 'position') { 13097 var current = this._core.items(this._core.relative(this._core.current())), 13098 hash = $.map(this._hashes, function(item, hash) { 13099 return item === current ? hash : null; 13100 }).join(); 13101 13102 if (!hash || window.location.hash.slice(1) === hash) { 13103 return; 13104 } 13105 13106 window.location.hash = hash; 13107 } 13108 }, this) 13109 }; 13110 13111 // set default options 13112 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 13113 13114 // register the event handlers 13115 this.$element.on(this._handlers); 13116 13117 // register event listener for hash navigation 13118 $(window).on('hashchange.owl.navigation', $.proxy(function(e) { 13119 var hash = window.location.hash.substring(1), 13120 items = this._core.$stage.children(), 13121 position = this._hashes[hash] && items.index(this._hashes[hash]); 13122 13123 if (position === undefined || position === this._core.current()) { 13124 return; 13125 } 13126 13127 this._core.to(this._core.relative(position), false, true); 13128 }, this)); 13129 }; 13130 13131 /** 13132 * Default options. 13133 * @public 13134 */ 13135 Hash.Defaults = { 13136 URLhashListener: false 13137 }; 13138 13139 /** 13140 * Destroys the plugin. 13141 * @public 13142 */ 13143 Hash.prototype.destroy = function() { 13144 var handler, property; 13145 13146 $(window).off('hashchange.owl.navigation'); 13147 13148 for (handler in this._handlers) { 13149 this._core.$element.off(handler, this._handlers[handler]); 13150 } 13151 for (property in Object.getOwnPropertyNames(this)) { 13152 typeof this[property] != 'function' && (this[property] = null); 13153 } 13154 }; 13155 13156 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 13157 13158})(window.Zepto || window.jQuery, window, document); 13159 13160/** 13161 * Support Plugin 13162 * 13163 * @version 2.0.0-beta.3 13164 * @author Vivid Planet Software GmbH 13165 * @author Artus Kolanowski 13166 * @license The MIT License (MIT) 13167 */ 13168;(function($, window, document, undefined) { 13169 13170 var style = $('<support>').get(0).style, 13171 prefixes = 'Webkit Moz O ms'.split(' '), 13172 events = { 13173 transition: { 13174 end: { 13175 WebkitTransition: 'webkitTransitionEnd', 13176 MozTransition: 'transitionend', 13177 OTransition: 'oTransitionEnd', 13178 transition: 'transitionend' 13179 } 13180 }, 13181 animation: { 13182 end: { 13183 WebkitAnimation: 'webkitAnimationEnd', 13184 MozAnimation: 'animationend', 13185 OAnimation: 'oAnimationEnd', 13186 animation: 'animationend' 13187 } 13188 } 13189 }, 13190 tests = { 13191 csstransforms: function() { 13192 return !!test('transform'); 13193 }, 13194 csstransforms3d: function() { 13195 return !!test('perspective'); 13196 }, 13197 csstransitions: function() { 13198 return !!test('transition'); 13199 }, 13200 cssanimations: function() { 13201 return !!test('animation'); 13202 } 13203 }; 13204 13205 function test(property, prefixed) { 13206 var result = false, 13207 upper = property.charAt(0).toUpperCase() + property.slice(1); 13208 13209 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 13210 if (style[property] !== undefined) { 13211 result = prefixed ? property : true; 13212 return false;
13213 } 13214 }); 13215 13216 return result; 13217 } 13218 13219 function prefixed(property) { 13220 return test(property, true); 13221 } 13222 13223 if (tests.csstransitions()) { 13224 /* jshint -W053 */ 13225 $.support.transition = new String(prefixed('transition')) 13226 $.support.transition.end = events.transition.end[ $.support.transition ]; 13227 } 13228 13229 if (tests.cssanimations()) { 13230 /* jshint -W053 */ 13231 $.support.animation = new String(prefixed('animation')) 13232 $.support.animation.end = events.animation.end[ $.support.animation ]; 13233 } 13234 13235 if (tests.csstransforms()) { 13236 /* jshint -W053 */ 13237 $.support.transform = new String(prefixed('transform')); 13238 $.support.transform3d = tests.csstransforms3d(); 13239 } 13240 13241})(window.Zepto || window.jQuery, window, document); 13242 13243(function(window, document, undefined) { 13244 13245 /** 13246 * Find the absolute position of an element 13247 */ 13248 var absPos = function(element) { 13249 var offsetLeft, offsetTop; 13250 offsetLeft = offsetTop = 0; 13251 if (element.offsetParent) { 13252 do { 13253 offsetLeft += element.offsetLeft; 13254 offsetTop += element.offsetTop; 13255 } while (element = element.offsetParent); 13256 } 13257 return [offsetLeft, offsetTop]; 13258 }; 13259 13260 /** 13261 * @constructor Progress Circle class 13262 * @param params.canvas Canvas on which the circles will be drawn. 13263 * @param params.minRadius Inner radius of the innermost circle, in px. 13264 * @param params.arcWidth Width of each circle(to be more accurate, ring). 13265 * @param params.gapWidth Space between each circle. 13266 * @param params.centerX X coordinate of the center of circles. 13267 * @param params.centerY Y coordinate of the center of circles. 13268 * @param params.infoLineBaseAngle Base angle of the info line. 13269 * @param params.infoLineAngleInterval Angles between the info lines. 13270 */ 13271 var ProgressCircle = function(params) { 13272 this.canvas = params.canvas; 13273 this.minRadius = params.minRadius || 15; 13274 this.arcWidth = params.arcWidth || 5; 13275 this.gapWidth = params.gapWidth || 3; 13276 this.centerX = params.centerX || this.canvas.width / 2; 13277 this.centerY = params.centerY || this.canvas.height / 2;
13278 this.infoLineLength = params.infoLineLength || 60; 13279 this.horizLineLength = params.horizLineLength || 10; 13280 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 13281 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 13282 13283 this.context = this.canvas.getContext('2d'); 13284 13285 this.width = this.canvas.width; 13286 this.height = this.canvas.height; 13287 13288 this.circles = []; 13289 this.runningCount = 0; 13290 }; 13291 13292 ProgressCircle.prototype = { 13293 constructor: ProgressCircle, 13294 13295 /** 13296 * @method Adds an progress monitor entry. 13297 * @param params.fillColor Color to fill in the circle. 13298 * @param params.outlineColor Color to outline the circle. 13299 * @param params.progressListener Callback function to fetch the progress. 13300 * @param params.infoListener Callback function to fetch the info. 13301 * @returns this 13302 */ 13303 addEntry: function(params) { 13304 this.circles.push(new Circle({ 13305 canvas: this.canvas, 13306 context: this.context, 13307 centerX: this.centerX, 13308 centerY: this.centerY, 13309 innerRadius: this.minRadius + this.circles.length * 13310 (this.gapWidth + this.arcWidth), 13311 arcWidth: this.arcWidth,
13312 infoLineLength: this.infoLineLength, 13313 horizLineLength: this.horizLineLength, 13314 13315 id: this.circles.length, 13316 fillColor: params.fillColor, 13317 outlineColor: params.outlineColor, 13318 progressListener: params.progressListener, 13319 infoListener: params.infoListener, 13320 infoLineAngle: this.infoLineBaseAngle + 13321 this.circles.length * this.infoLineAngleInterval, 13322 })); 13323 13324 return this; 13325 }, 13326 13327 /** 13328 * @method Starts the monitor and updates with the given interval. 13329 * @param interval Interval between updates, in millisecond. 13330 * @returns this 13331 */ 13332 start: function(interval) { 13333 var self = this; 13334 this.timer = setInterval(function() { 13335 self._update(); 13336 }, interval || 33); 13337 13338 return this; 13339 }, 13340 13341 /** 13342 * @method Stop the animation. 13343 */ 13344 stop: function() { 13345 clearTimeout(this.timer); 13346 }, 13347 13348 /** 13349 * @private 13350 * @method Call update on each circle and redraw them. 13351 * @returns this 13352 */ 13353 _update: function() { 13354 this._clear(); 13355 this.circles.forEach(function(circle, idx, array) { 13356 circle.update(); 13357 }); 13358 13359 return this; 13360 }, 13361 13362 /** 13363 * @private 13364 * @method Clear the canvas. 13365 * @returns this 13366 */ 13367 _clear: function() { 13368 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 13369 13370 return this; 13371 }, 13372 13373 }; 13374 13375 /** 13376 * @private 13377 * @class Individual progress circle. 13378 * @param params.canvas Canvas on which the circle will be drawn. 13379 * @param params.context Context of the canvas. 13380 * @param params.innerRadius Inner radius of the circle, in px. 13381 * @param params.arcWidth Width of each arc(circle). 13382 * @param params.gapWidth Distance between each arc. 13383 * @param params.centerX X coordinate of the center of circles. 13384 * @param params.centerY Y coordinate of the center of circles. 13385 * @param params.fillColor Color to fill in the circle. 13386 * @param params.outlineColor Color to outline the circle. 13387 * @param params.progressListener Callback function to fetch the progress. 13388 * @param params.infoListener Callback function to fetch the info. 13389 * @param params.infoLineAngle Angle of info line. 13390 */ 13391 var Circle = function(params) { 13392 this.id = params.id; 13393 this.canvas = params.canvas; 13394 this.context = params.context; 13395 this.centerX = params.centerX; 13396 this.centerY = params.centerY; 13397 this.arcWidth = params.arcWidth; 13398 this.innerRadius = params.innerRadius || 0; 13399 this.fillColor = params.fillColor || '#fff'; 13400 this.outlineColor = params.outlineColor || this.fillColor; 13401 this.progressListener = params.progressListener;
13402 this.infoLineLength = params.infoLineLength || 250; 13403 this.horizLineLength = params.horizLineLength || 50; 13404 this.infoListener = params.infoListener; 13405 this.infoLineAngle = params.infoLineAngle; 13406 13407 this.outerRadius = this.innerRadius + this.arcWidth; 13408 13409 // If the info listener is not registered, then don't calculate 13410 // the related coordinates 13411 if (!this.infoListener) return; 13412 13413 // calculate the info-line turning points 13414 var angle = this.infoLineAngle, 13415 arcDistance = (this.innerRadius + this.outerRadius) / 2, 13416 13417 sinA = Math.sin(angle), 13418 cosA = Math.cos(angle); 13419 13420 this.infoLineStartX = this.centerX + sinA * arcDistance; 13421 this.infoLineStartY = this.centerY - cosA * arcDistance; 13422 13423 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 13424 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 13425 13426 this.infoLineEndX = this.infoLineMidX + 13427 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 13428 this.infoLineEndY = this.infoLineMidY; 13429 13430 var infoText = document.createElement('div'), 13431 style = infoText.style; 13432 13433 style.color = this.fillColor; 13434 style.position = 'absolute'; 13435 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 13436 // style.top will be calculated in the `drawInfo` method. Since 13437 // user may want to change the size of the font, so the top offset 13438 // must be updated in each loop. 13439 infoText.className = 'ProgressCircleInfo'; // For css styling 13440 infoText.id = 'progress_circle_info_' + this.id; 13441 document.body.appendChild(infoText); 13442 this.infoText = infoText; 13443 }; 13444 13445 Circle.prototype = { 13446 constructor: Circle, 13447 13448 update: function() { 13449 this.progress = this.progressListener(); 13450 this._draw(); 13451 13452 if (this.infoListener) { 13453 this.info = this.infoListener(); 13454 this._drawInfo(); 13455 } 13456 }, 13457 13458 /** 13459 * @private 13460 * @method Draw the circle on the canvas. 13461 * @returns this 13462 */ 13463 _draw: function() { 13464 var ctx = this.context, 13465 13466 ANGLE_OFFSET = -Math.PI / 2, 13467 13468 startAngle = 0 + ANGLE_OFFSET, 13469 endAngle= startAngle + this.progress * Math.PI * 2, 13470 13471 x = this.centerX, 13472 y = this.centerY, 13473 13474 innerRadius = this.innerRadius - this.arcWidth - 1, 13475 outerRadius = this.outerRadius - this.arcWidth - 1; 13476 13477 ctx.fillStyle = this.fillColor; 13478 ctx.strokeStyle = this.outlineColor; 13479 13480 ctx.beginPath(); 13481 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 13482 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 13483 ctx.closePath(); 13484 ctx.stroke(); 13485 ctx.fill(); 13486 13487 return this; 13488 }, 13489 13490 /** 13491 * @private 13492 * @method Draw the info lines and info text. 13493 * @returns this 13494 */ 13495 _drawInfo: function() { 13496 13497 var pointList, lineHeight; 13498 13499 pointList = [ 13500 [this.infoLineStartX, this.infoLineStartY], 13501 [this.infoLineMidX, this.infoLineMidY], 13502 [this.infoLineEndX, this.infoLineEndY], 13503 ]; 13504 this._drawSegments(pointList, false); 13505 13506 this.infoText.innerHTML = this.info; 13507 13508 lineHeight = this.infoText.offsetHeight; 13509 this.infoText.style.top = this.infoLineEndY + 13510 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 13511 13512 return this; 13513 }, 13514 13515 /** 13516 * @private 13517 * @method Helper function to draw the segments 13518 * @param pointList An array of points in the form of [x, y]. 13519 * @param close Whether to connect the first and last point. 13520 */ 13521 _drawSegments: function(pointList, close) { 13522 var ctx = this.context; 13523 13524 ctx.beginPath(); 13525 ctx.moveTo(pointList[0][0], pointList[0][1]); 13526 for (var i = 1; i < pointList.length; ++i) { 13527 ctx.lineTo(pointList[i][0], pointList[i][1]); 13528 } 13529 13530 if (close) { 13531 ctx.closePath(); 13532 } 13533 ctx.stroke(); 13534 }, 13535 }; 13536 13537 window.ProgressCircle = ProgressCircle; 13538 13539})(window, document); 13540 13541 13542 13543 13544/* ========================================================= 13545 * jquery.vc_chart.js v1.0 13546 * ========================================================= 13547 * Copyright 2013 Wpbakery 13548 * 13549 * Jquery chart plugin for the Visual Composer.
13550 * ========================================================= */ 13551(function($){ 13552 /** 13553 * Pie chart animated. 13554 * @param element - DOM element 13555 * @param options - settings object. 13556 * @constructor 13557 */ 13558 var VcChart = function(element, options) { 13559 this.el = element; 13560 this.$el = $(this.el); 13561 this.options = $.extend({ 13562 color: 'wpb_button', 13563 units: '', 13564 width: '', 13565 label_selector: '.vc_pie_chart_value', 13566 back_selector: '.vc_pie_chart_back', 13567 responsive: true 13568 }, options); 13569 this.init(); 13570 }; 13571 VcChart.prototype = { 13572 constructor: VcChart, 13573 _progress_v: 0, 13574 animated: false, 13575 colors: { 13576 'wpb_button': 'rgba(247, 247, 247, 1)', 13577 'btn-primary': 'rgba(0, 136, 204, 1)', 13578 'btn-info': 'rgba(88, 185, 218, 1)', 13579 'btn-success': 'rgba(106, 177, 101, 1)', 13580 'btn-warning': 'rgba(255, 153, 0, 1)', 13581 'btn-danger': 'rgba(255, 103, 91, 1)', 13582 'btn-inverse': 'rgba(85, 85, 85, 1)' 13583 }, 13584 init: function() { 13585 this.setupColor(); 13586 this.value = this.$el.data('pie-value')/100; 13587 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 13588 this.$wrapper = $('.vc_pie_wrapper', this.$el); 13589 this.$label = $(this.options.label_selector, this.$el); 13590 this.$back = $(this.options.back_selector, this.$el); 13591 this.$canvas = this.$el.find('canvas'); 13592 this.arcWidth = this.$el.data('pie-width') * 2; 13593 this.draw(); 13594 this.setWayPoint(); 13595 if(this.options.responsive === true) this.setResponsive(); 13596 if (UNCODE.isMobile) this._progress_v = this.value; 13597 }, 13598 setupColor: function() { 13599 // if(typeof this.colors[this.options.color] !== 'undefined') { 13600 // this.color = this.colors[this.options.color]; 13601 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 13602 // this.color = this.options.color; 13603 // } else { 13604 // this.color = 'rgba(247, 247, 247, 0.2)'; 13605 // } 13606 if(typeof this.options.color !== 'undefined') { 13607 this.color = this.options.color; 13608 } else this.color = 'rgba(247, 247, 247, 0.2)'; 13609 13610 }, 13611 setResponsive: function() { 13612 var that = this; 13613 if (!UNCODE.isMobile) { 13614 $(window).resize(function(){ 13615 if(that.animated === true) that.circle.stop(); 13616 that.draw(true); 13617 }); 13618 } 13619 }, 13620 draw: function(redraw) { 13621 var w = this.$el.addClass('vc_ready').width() * 2, 13622 border_w = this.arcWidth, 13623 radius; 13624 if(!w) w = this.$el.parents(':visible').first().width()-2; 13625 //w = Math.round(w/100*80); 13626 //if (w < 250) w = 250; 13627 radius = w/2; 13628 this.$wrapper.css({"width" : (w / 2) + "px"}); 13629 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 13630 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 13631 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 13632 this.$el.addClass('vc_ready'); 13633 this.circle = new ProgressCircle({ 13634 canvas: this.$canvas.get(0), 13635 minRadius: radius, 13636 arcWidth: border_w 13637 }); 13638 if(redraw === true && this.animated === true) { 13639 this._progress_v = this.value; 13640 this.circle.addEntry({ 13641 fillColor: this.color, 13642 progressListener: $.proxy(this.setProgress, this) 13643 }).start(); 13644 } 13645 }, 13646 setProgress: function() { 13647 if (this._progress_v >= this.value) { 13648 this.circle.stop(); 13649 this.$label.html(this.label_value + this.options.units); 13650 return this._progress_v; 13651 } 13652 this._progress_v += 0.01; 13653 if (!isNaN(this.label_value)) { 13654 var label_value = this._progress_v/this.value*this.label_value; 13655 var val = Math.round(label_value) + this.options.units; 13656 this.$label.html(val); 13657 } else this.$label.html(this.label_value + this.options.units); 13658 return this._progress_v; 13659 }, 13660 animate: function() { 13661 if(this.animated !== true) { 13662 this.animated = true; 13663 this.circle.addEntry({ 13664 fillColor: this.color, 13665 progressListener: $.proxy(this.setProgress, this) 13666 }).start(5); 13667 } 13668 }, 13669 setWayPoint: function() { 13670 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 13671 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 13672 } else { 13673 this.animate(); 13674 } 13675 } 13676 }; 13677 /** 13678 * jQuery plugin 13679 * @param option - object with settings 13680 * @return {*} 13681 */ 13682 $.fn.vcChat = function(option, value) { 13683 return this.each(function () { 13684 var $this = $(this), 13685 data = $this.data('vc_chart'), 13686 options = typeof option === 'object' ? option : { 13687 color: $this.data('pie-color'), 13688 units: $this.data('pie-units') 13689 }; 13690 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 13691 if (typeof option == 'string') data[option](value); 13692 }); 13693 }; 13694 /** 13695 * Allows users to rewrite function inside theme. 13696 */ 13697 if ( typeof window['vc_pieChart'] !== 'function' ) { 13698 window.vc_pieChart = function() { 13699 $('.vc_pie_chart:visible').vcChat(); 13700 } 13701 } 13702 $(document).ready(function(){ 13703 !window.vc_iframe && vc_pieChart(); 13704 }); 13705 13706})(window.jQuery); 13707 13708 13709/* Progress bar 13710 ---------------------------------------------------------- */ 13711function uncode_progress_bar() {    13712 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 13713 if (!UNCODE.isMobile) { 13714 new Waypoint({ 13715 element: val, 13716 handler: function() { 13717 var element = jQuery(this.element); 13718 element.find('.vc_single_bar').each(function(index) {          13719 var $this = jQuery(this), 13720             bar = $this.find('.vc_bar'), 13721             val = bar.data('percentage-value');          13722 setTimeout(function() {            13723 bar.css({ 13724 "width": val + '%' 13725 });          13726 }, index * 200);        13727 }); 13728 }, 13729 offset: '80%' 13730 }); 13731 } else { 13732 var element = jQuery(val); 13733 element.find('.vc_single_bar').each(function(index) {          13734 var $this = jQuery(this), 13735             bar = $this.find('.vc_bar'), 13736             val = bar.data('percentage-value');          13737 setTimeout(function() {            13738 bar.css({ 13739 "width": val + '%' 13740 });          13741 }, index * 200);        13742 }); 13743 } 13744 }); 13745}; 13746uncode_progress_bar(); 13747 13748/*! 13749 * jquery.counterup.js 1.0 13750 * 13751 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 13752 * Released under the GPL v2 License 13753 * 13754 * Date: Nov 26, 2013 13755 */ 13756(function($) { 13757 "use strict"; 13758 $.fn.counterUp = function(options) { 13759 // Defaults 13760 var settings = $.extend({ 13761 'time': 400, 13762 'delay': 10 13763 }, options); 13764 return this.each(function() { 13765 // Store the object 13766 var $this = $(this); 13767 var $settings = settings; 13768 var counterUpper = function() { 13769 var nums = []; 13770 var divisions = $settings.time / $settings.delay; 13771 var numReal = $this.text(), 13772 num = numReal; 13773 var isComma = /[0-9]+,[0-9]+/.test(num); 13774 num = num.replace(/,/g, ''); 13775 var isInt = /^[0-9]+$/.test(num); 13776 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 13777 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 13778 // Generate list of incremental numbers to display 13779 for (var i = divisions; i >= 1; i--) { 13780 // Preserve as int if input was int 13781 var newNum = parseInt(num / divisions * i); 13782 // Preserve float if input was float 13783 if (isFloat) { 13784 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 13785 } 13786 // Preserve commas if input had commas 13787 if (isComma) { 13788 while (/(\d+)(\d{3})/.test(newNum.toString())) { 13789 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 13790 } 13791 } 13792 nums.unshift(newNum); 13793 } 13794 nums.push(numReal); 13795 $this.data('counterup-nums', nums); 13796 $this.text('0'); 13797 // Updates the number until we're done 13798 var f = function() { 13799 if ($this.data('counterup-nums') != null) { 13800 $this.text($this.data('counterup-nums').shift()); 13801 if ($this.data('counterup-nums').length) { 13802 setTimeout($this.data('counterup-func'), $settings.delay); 13803 } else { 13804 delete $this.data('counterup-nums'); 13805 $this.data('counterup-nums', null); 13806 $this.data('counterup-func', null); 13807 } 13808 } 13809 }; 13810 $this.data('counterup-func', f); 13811 // Start the count up 13812 setTimeout($this.data('counterup-func'), $settings.delay); 13813 }; 13814 // Perform counts when the element gets into view 13815 new Waypoint({ 13816 element: this, 13817 handler: function() { 13818 counterUpper(); 13819 this.destroy(); 13820 }, 13821 offset: '80%' 13822 }); 13823 }); 13824 }; 13825})(jQuery); 13826 13827/*! 13828 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 13829 * Copyright (c) 2014 Edson Hilios 13830 * 13831 * Permission is hereby granted, free of charge, to any person obtaining a copy of 13832 * this software and associated documentation files (the "Software"), to deal in 13833 * the Software without restriction, including without limitation the rights to 13834 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13835 * the Software, and to permit persons to whom the Software is furnished to do so, 13836 * subject to the following conditions: 13837 * 13838 * The above copyright notice and this permission notice shall be included in all 13839 * copies or substantial portions of the Software. 13840 * 13841 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13842 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13843 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13844 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13845 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 13846 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13847 */ 13848!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;
13848if(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])})}}); 13849 13850/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 13851* https://github.com/alexanderdickson/waitForImages 13852* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 13853;(function (factory) { 13854 if (typeof define === 'function' && define.amd) { 13855 // AMD. Register as an anonymous module. 13856 define(['jquery'], factory); 13857 } else if (typeof exports === 'object') { 13858 // CommonJS / nodejs module 13859 module.exports = factory(require('jquery')); 13860 } else { 13861 // Browser globals 13862 factory(jQuery); 13863 } 13864}(function ($) { 13865 // Namespace all events. 13866 var eventNamespace = 'waitForImages'; 13867 13868 // CSS properties which contain references to images. 13869 $.waitForImages = { 13870 hasImageProperties: [ 13871 'backgroundImage', 13872 'listStyleImage', 13873 'borderImage', 13874 'borderCornerImage', 13875 'cursor' 13876 ], 13877 hasImageAttributes: ['srcset'] 13878 }; 13879 13880 // Custom selector to find `img` elements that have a valid `src` 13881 // attribute and have not already loaded. 13882 $.expr[':'].uncached = function (obj) { 13883 // Ensure we are dealing with an `img` element with a valid 13884 // `src` attribute. 13885 if (!$(obj).is('img[src][src!=""]')) { 13886 return false;
13887 } 13888 13889 return !obj.complete; 13890 }; 13891 13892 $.fn.waitForImages = function () { 13893 13894 var allImgsLength = 0; 13895 var allImgsLoaded = 0; 13896 var deferred = $.Deferred(); 13897 13898 var finishedCallback; 13899 var eachCallback; 13900 var waitForAll; 13901 13902 // Handle options object (if passed). 13903 if ($.isPlainObject(arguments[0])) { 13904 13905 waitForAll = arguments[0].waitForAll; 13906 eachCallback = arguments[0].each; 13907 finishedCallback = arguments[0].finished; 13908 13909 } else { 13910 13911 // Handle if using deferred object and only one param was passed in. 13912 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 13913 waitForAll = arguments[0]; 13914 } else { 13915 finishedCallback = arguments[0]; 13916 eachCallback = arguments[1]; 13917 waitForAll = arguments[2]; 13918 } 13919 13920 } 13921 13922 // Handle missing callbacks. 13923 finishedCallback = finishedCallback || $.noop; 13924 eachCallback = eachCallback || $.noop; 13925 13926 // Convert waitForAll to Boolean 13927 waitForAll = !! waitForAll; 13928 13929 // Ensure callbacks are functions. 13930 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 13931 throw new TypeError('An invalid callback was supplied.'); 13932 } 13933 13934 this.each(function () { 13935 // Build a list of all imgs, dependent on what images will 13936 // be considered. 13937 var obj = $(this); 13938 var allImgs = []; 13939 // CSS properties which may contain an image. 13940 var hasImgProperties = $.waitForImages.hasImageProperties || []; 13941 // Element attributes which may contain an image. 13942 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 13943 // To match `url()` references. 13944 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 13945 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 13946 13947 if (waitForAll) { 13948 13949 // Get all elements (including the original), as any one of 13950 // them could have a background image. 13951 obj.find('*').addBack().each(function () { 13952 var element = $(this); 13953 13954 // If an `img` element, add it. But keep iterating in 13955 // case it has a background image too. 13956 if (element.is('img:uncached')) { 13957 allImgs.push({ 13958 src: element.attr('src'), 13959 element: element[0] 13960 }); 13961 } 13962 13963 $.each(hasImgProperties, function (i, property) { 13964 var propertyValue = element.css(property); 13965 var match; 13966 13967 // If it doesn't contain this property, skip. 13968 if (!propertyValue) { 13969 return true; 13970 } 13971 13972 // Get all url() of this element. 13973 while (match = matchUrl.exec(propertyValue)) { 13974 allImgs.push({ 13975 src: match[2], 13976 element: element[0] 13977 }); 13978 } 13979 }); 13980 13981 $.each(hasImageAttributes, function (i, attribute) { 13982 var attributeValue = element.attr(attribute); 13983 var attributeValues; 13984 13985 // If it doesn't contain this property, skip. 13986 if (!attributeValue) { 13987 return true; 13988 } 13989 13990 // Check for multiple comma separated images 13991 attributeValues = attributeValue.split(','); 13992 13993 $.each(attributeValues, function(i, value) { 13994 // Trim value and get string before first 13995 // whitespace (for use with srcset). 13996 value = $.trim(value).split(' ')[0]; 13997 allImgs.push({ 13998 src: value, 13999 element: element[0] 14000 }); 14001 }); 14002 }); 14003 }); 14004 } else { 14005 // For images only, the task is simpler. 14006 obj.find('img:uncached') 14007 .each(function () { 14008 allImgs.push({ 14009 src: this.src, 14010 element: this 14011 }); 14012 }); 14013 } 14014 14015 allImgsLength = allImgs.length; 14016 allImgsLoaded = 0; 14017 14018 // If no images found, don't bother. 14019 if (allImgsLength === 0) { 14020 finishedCallback.call(obj[0]); 14021 deferred.resolveWith(obj[0]); 14022 } 14023 14024 $.each(allImgs, function (i, img) { 14025 14026 var image = new Image(); 14027 var events = 14028 'load.' + eventNamespace + ' error.' + eventNamespace; 14029 14030 // Handle the image loading and error with the same callback. 14031 $(image).one(events, function me (event) { 14032 // If an error occurred with loading the image, set the 14033 // third argument accordingly. 14034 var eachArguments = [ 14035 allImgsLoaded, 14036 allImgsLength,
14037 event.type == 'load' 14038 ]; 14039 allImgsLoaded++; 14040 14041 eachCallback.apply(img.element, eachArguments); 14042 deferred.notifyWith(img.element, eachArguments); 14043 14044 // Unbind the event listeners. I use this in addition to 14045 // `one` as one of those events won't be called (either 14046 // 'load' or 'error' will be called). 14047 $(this).off(events, me); 14048 14049 if (allImgsLoaded == allImgsLength) { 14050 finishedCallback.call(obj[0]); 14051 deferred.resolveWith(obj[0]); 14052 return false; 14053 } 14054 14055 }); 14056 14057 image.src = img.src; 14058 }); 14059 }); 14060 14061 return deferred.promise(); 14062 14063 }; 14064})); 14065 14066/** 14067 * @preserve textfill 14068 * @name jquery.textfill.js 14069 * @author Russ Painter 14070 * @author Yu-Jie Lin 14071 * @author Alexandre Dantas 14072 * @version 0.6.0 14073 * @date 2014-08-19 14074 * @copyright (c) 2014 Alexandre Dantas 14075 * @copyright (c) 2012-2013 Yu-Jie Lin 14076 * @copyright (c) 2009 Russ Painter 14077 * @license MIT License 14078 * @homepage https://github.com/jquery-textfill/jquery-textfill 14079 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 14080 */ 14081; (function($) { 14082 14083 /** 14084 * Resizes an inner element's font so that the 14085 * inner element completely fills the outer element. 14086 * 14087 * @param {Object} options User options that take 14088 * higher precedence when 14089 * merging with the default ones. 14090 * 14091 * @return All outer elements processed 14092 */ 14093 $.fn.textfill = function(options) { 14094 14095 // ______ _______ _______ _______ _ _ _______ _______ 14096 // | \ |______ |______ |_____| | | | | |______ 14097 // |_____/ |______ | | | |_____| |_____ | ______| 14098 // 14099 // Merging user options with the default values 14100 14101 var defaults = { 14102 debug : false, 14103 maxFontPixels : 40, 14104 minFontPixels : 4, 14105 innerTag : 'span', 14106 widthOnly : false, 14107 success : null, // callback when a resizing is done 14108 callback : null, // callback when a resizing is done (deprecated, use success) 14109 fail : null, // callback when a resizing is failed 14110 complete : null, // callback when all is done 14111 explicitWidth : null, 14112 explicitHeight : null, 14113 changeLineHeight : false 14114 }; 14115 14116 var Opts = $.extend(defaults, options); 14117 14118 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 14119 // |______ | | | \ | | | | | | | \ | |______ 14120 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 14121 // 14122 // Predefining the awesomeness 14123 14124 // Output arguments to the Debug console 14125 // if "Debug Mode" is enabled 14126 function _debug() { 14127 if (!Opts.debug 14128 || typeof console == 'undefined' 14129 || typeof console.debug == 'undefined') { 14130 return; 14131 } 14132 console.debug.apply(console, arguments); 14133 } 14134 14135 // Output arguments to the Warning console 14136 function _warn() { 14137 if (typeof console == 'undefined' || 14138 typeof console.warn == 'undefined') { 14139 return; 14140 } 14141 console.warn.apply(console, arguments); 14142 } 14143 14144 // Outputs all information on the current sizing 14145 // of the font. 14146 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14147 14148 function _m(v1, v2) { 14149 14150 var marker = ' / '; 14151 14152 if (v1 > v2) 14153 marker = ' > '; 14154 14155 else if (v1 == v2) 14156 marker = ' = '; 14157 14158 return marker; 14159 } 14160 14161 _debug( 14162 '[TextFill] ' + prefix + ' { ' + 14163 'font-size: ' + ourText.css('font-size') + ',' +
14164 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 14165 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 14166 'minFontPixels: ' + minFontPixels + 'px, ' + 14167 'maxFontPixels: ' + maxFontPixels + 'px }' 14168 ); 14169 } 14170 14171 /** 14172 * Calculates which size the font can get resized, 14173 * according to constrains. 14174 * 14175 * @param {String} prefix Gets shown on the console before 14176 * all the arguments, if debug mode is on. 14177 * @param {Object} ourText The DOM element to resize, 14178 * that contains the text. 14179 * @param {function} func Function called on `ourText` that's 14180 * used to compare with `max`. 14181 * @param {number} max Maximum value, that gets compared with 14182 * `func` called on `ourText`. 14183 * @param {number} minFontPixels Minimum value the font can 14184 * get resized to (in pixels). 14185 * @param {number} maxFontPixels Maximum value the font can 14186 * get resized to (in pixels). 14187 * 14188 * @return Size (in pixels) that the font can be resized. 14189 */ 14190 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14191 14192 _debug_sizing( 14193 prefix, ourText, 14194 maxHeight, maxWidth, 14195 minFontPixels, maxFontPixels 14196 ); 14197 14198 // The kernel of the whole plugin, take most attention 14199 // on this part. 14200 // 14201 // This is a loop that keeps increasing the `font-size` 14202 // until it fits the parent element. 14203 // 14204 // - Start from the minimal allowed value (`minFontPixels`) 14205 // - Guesses an average font size (in pixels) for the font, 14206 // - Resizes the text and sees if its size is within the 14207 // boundaries (`minFontPixels` and `maxFontPixels`). 14208 // - If so, keep guessing until we break. 14209 // - If not, return the last calculated size. 14210 // 14211 // I understand this is not optimized and we should 14212 // consider implementing something akin to 14213 // Daniel Hoffmann's answer here: 14214 // 14215 // http://stackoverflow.com/a/17433451/1094964 14216 // 14217 14218 while (minFontPixels < (maxFontPixels - 1)) { 14219 14220 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 14221 ourText.css('font-size', fontSize); 14222 14223 if (func.call(ourText) <= max) { 14224 minFontPixels = fontSize; 14225 14226 if (func.call(ourText) == max) 14227 break; 14228 } 14229 else 14230 maxFontPixels = fontSize; 14231 14232 _debug_sizing( 14233 prefix, ourText, 14234 maxHeight, maxWidth, 14235 minFontPixels, maxFontPixels 14236 ); 14237 } 14238 14239 ourText.css('font-size', maxFontPixels); 14240 14241 if (func.call(ourText) <= max) { 14242 minFontPixels = maxFontPixels; 14243 14244 _debug_sizing( 14245 prefix + '* ', ourText, 14246 maxHeight, maxWidth, 14247 minFontPixels, maxFontPixels 14248 ); 14249 } 14250 return minFontPixels; 14251 } 14252 14253 // _______ _______ _______ ______ _______ 14254 // |______ | |_____| |_____/ | 14255 // ______| | | | | \_ | 14256 // 14257 // Let's get it started (yeah)! 14258 14259 _debug('[TextFill] Start Debug'); 14260 14261 this.each(function() { 14262 14263 // Contains the child element we will resize. 14264 // $(this) means the parent container 14265 var ourText = $(Opts.innerTag + ':visible:first', this); 14266 14267 // Will resize to this dimensions. 14268 // Use explicit dimensions when specified 14269 var maxHeight = Opts.explicitHeight || $(this).height(); 14270 var maxWidth = Opts.explicitWidth || $(this).width(); 14271 14272 var oldFontSize = ourText.css('font-size'); 14273 14274 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 14275 14276 _debug('[TextFill] Inner text: ' + ourText.text()); 14277 _debug('[TextFill] All options: ', Opts); 14278 _debug('[TextFill] Maximum sizes: { ' + 14279 'Height: ' + maxHeight + 'px, ' + 14280 'Width: ' + maxWidth + 'px' + ' }' 14281 ); 14282 14283 var minFontPixels = Opts.minFontPixels; 14284 14285 // Remember, if this `maxFontPixels` is negative, 14286 // the text will resize to as long as the container 14287 // can accomodate 14288 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 14289 maxHeight : 14290 Opts.maxFontPixels); 14291 14292 14293 // Let's start it all! 14294 14295 // 1. Calculate which `font-size` would 14296 // be best for the Height 14297 var fontSizeHeight = undefined; 14298 14299 if (! Opts.widthOnly) 14300 fontSizeHeight = _sizing( 14301 'Height', ourText, 14302 $.fn.height, maxHeight, 14303 maxHeight, maxWidth, 14304 minFontPixels, maxFontPixels 14305 ); 14306 14307 // 2. Calculate which `font-size` would 14308 // be best for the Width 14309 var fontSizeWidth = undefined; 14310 14311 fontSizeWidth = _sizing( 14312 'Width', ourText, 14313 $.fn.width, maxWidth, 14314 maxHeight, maxWidth, 14315 minFontPixels, maxFontPixels 14316 ); 14317 14318 // 3. Actually resize the text! 14319 14320 if (Opts.widthOnly) { 14321 ourText.css({ 14322 'font-size' : fontSizeWidth, 14323 'white-space': 'nowrap' 14324 }); 14325 14326 if (Opts.changeLineHeight) 14327 ourText.parent().css( 14328 'line-height', 14329 (lineHeight * fontSizeWidth + 'px') 14330 ); 14331 } 14332 else { 14333 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 14334 14335 ourText.css('font-size', fontSizeFinal); 14336 14337 if (Opts.changeLineHeight) 14338 ourText.parent().css( 14339 'line-height', 14340 (lineHeight * fontSizeFinal) + 'px' 14341 ); 14342 } 14343 14344 _debug( 14345 '[TextFill] Finished { ' + 14346 'Old font-size: ' + oldFontSize + ', ' + 14347 'New font-size: ' + ourText.css('font-size') + ' }' 14348 ); 14349 14350 // Oops, something wrong happened! 14351 // We weren't supposed to exceed the original size 14352 if ((ourText.width() > maxWidth) ||
14353 (ourText.height() > maxHeight && !Opts.widthOnly)) { 14354 14355 ourText.css('font-size', oldFontSize); 14356 14357 // Failure callback 14358 if (Opts.fail) 14359 Opts.fail(this); 14360 14361 _debug( 14362 '[TextFill] Failure { ' + 14363 'Current Width: ' + ourText.width() + ', ' + 14364 'Maximum Width: ' + maxWidth + ', ' + 14365 'Current Height: ' + ourText.height() + ', ' + 14366 'Maximum Height: ' + maxHeight + ' }' 14367 ); 14368 } 14369 else if (Opts.success) { 14370 Opts.success(this); 14371 } 14372 else if (Opts.callback) { 14373 _warn('callback is deprecated, use success, instead'); 14374 14375 // Success callback 14376 Opts.callback(this); 14377 } 14378 }); 14379 14380 // Complete callback 14381 if (Opts.complete) 14382 Opts.complete(this); 14383 14384 _debug('[TextFill] End Debug'); 14385 return this; 14386 }; 14387 14388})(window.jQuery); 14389 14390 14391!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; 14392function getStyles(config){ 14393 // 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;
14393left: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+"}" 14394}; 14395 var ShareUtils; 14396 14397if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 14398 Object.defineProperty(HTMLElement.prototype, "classList", { 14399 get: function() { 14400 var ret, self, update; 14401 update = function(fn) { 14402 return function(value) { 14403 var classes, index; 14404 classes = self.className.split(/\s+/); 14405 index = classes.indexOf(value); 14406 fn(classes, index, value); 14407 self.className = classes.join(" "); 14408 }; 14409 }; 14410 self = this; 14411 ret = { 14412 add: update(function(classes, index, value) { 14413 ~index || classes.push(value); 14414 }), 14415 remove: update(function(classes, index) { 14416 ~index && classes.splice(index, 1); 14417 }), 14418 toggle: update(function(classes, index, value) { 14419 if (~index) { 14420 classes.splice(index, 1); 14421 } else { 14422 classes.push(value); 14423 } 14424 }), 14425 contains: function(value) { 14426 return !!~self.className.split(/\s+/).indexOf(value); 14427 }, 14428 item: function(i) { 14429 return self.className.split(/\s+/)[i] || null; 14430 } 14431 }; 14432 Object.defineProperty(ret, "length", { 14433 get: function() { 14434 return self.className.split(/\s+/).length; 14435 } 14436 }); 14437 return ret; 14438 } 14439 }); 14440} 14441 14442String.prototype.to_rfc3986 = function() { 14443 var tmp; 14444 tmp = encodeURIComponent(this); 14445 return tmp.replace(/[!'()*]/g, function(c) { 14446 return "%" + c.charCodeAt(0).toString(16); 14447 }); 14448}; 14449 14450ShareUtils = (function() { 14451 function ShareUtils() {} 14452 14453 ShareUtils.prototype.extend = function(to, from, overwrite) { 14454 var hasProp, prop; 14455 for (prop in from) { 14456 hasProp = to[prop] !== undefined; 14457 if (hasProp && typeof from[prop] === "object") { 14458 this.extend(to[prop], from[prop], overwrite); 14459 } else { 14460 if (overwrite || !hasProp) { 14461 to[prop] = from[prop]; 14462 } 14463 } 14464 } 14465 }; 14466 14467 ShareUtils.prototype.hide = function(el) { 14468 return el.style.display = "none"; 14469 }; 14470 14471 ShareUtils.prototype.show = function(el) { 14472 return el.style.display = "block"; 14473 }; 14474 14475 ShareUtils.prototype.has_class = function(el, class_name) { 14476 return el.classList.contains(class_name); 14477 }; 14478 14479 ShareUtils.prototype.add_class = function(el, class_name) { 14480 return el.classList.add(class_name); 14481 }; 14482 14483 ShareUtils.prototype.remove_class = function(el, class_name) { 14484 return el.classList.remove(class_name); 14485 }; 14486 14487 ShareUtils.prototype.is_encoded = function(str) { 14488 str = str.to_rfc3986(); 14489 return decodeURIComponent(str) !== str; 14490 }; 14491 14492 ShareUtils.prototype.encode = function(str) { 14493 if (typeof str === "undefined" || this.is_encoded(str)) { 14494 return str; 14495 } else { 14496 return str.to_rfc3986(); 14497 } 14498 }; 14499 14500 ShareUtils.prototype.popup = function(url, params) { 14501 var k, popup, qs, v; 14502 if (params == null) { 14503 params = {}; 14504 } 14505 popup = { 14506 width: 500, 14507 height: 350 14508 }; 14509 popup.top = (screen.height / 2) - (popup.height / 2); 14510 popup.left = (screen.width / 2) - (popup.width / 2); 14511 qs = ((function() { 14512 var _results; 14513 _results = []; 14514 for (k in params) { 14515 v = params[k]; 14516 _results.push("" + k + "=" + (this.encode(v))); 14517 } 14518 return _results; 14519 }).call(this)).join('&'); 14520 if (qs) { 14521 qs = "?" + qs; 14522 } 14523 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="
14523+ popup.width + ",height=" + popup.height); 14524 }; 14525 14526 return ShareUtils; 14527 14528})(); 14529var Share, 14530 __hasProp = {}.hasOwnProperty, 14531 __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; }; 14532 14533Share = (function(_super) { 14534 __extends(Share, _super); 14535 14536 function Share(element, options) { 14537 this.element = element; 14538 this.el = { 14539 head: document.getElementsByTagName('head')[0], 14540 body: document.getElementsByTagName('body')[0] 14541 }; 14542 this.config = { 14543 enabled_networks: 0, 14544 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 14545 url: window.location.href, 14546 caption: null, 14547 title: this.default_title(), 14548 image: this.default_image(), 14549 description: this.default_description(), 14550 ui: { 14551 flyout: 'top center', 14552 button_text: 'Share', 14553 button_font: true, 14554 icon_font: true 14555 }, 14556 networks: { 14557 google_plus: { 14558 enabled: true, 14559 url: null 14560 }, 14561 twitter: { 14562 enabled: true, 14563 url: null, 14564 title: null, 14565 description: null 14566 }, 14567 facebook: { 14568 enabled: true, 14569 load_sdk: true, 14570 url: null, 14571 app_id: null, 14572 title: null, 14573 caption: null, 14574 description: null, 14575 image: null 14576 }, 14577 pinterest: { 14578 enabled: true, 14579 url: null, 14580 image: null, 14581 description: null 14582 }, 14583 reddit: { 14584 enabled: true, 14585 url: null, 14586 title: null 14587 }, 14588 linkedin: { 14589 enabled: true, 14590 url: null, 14591 title: null, 14592 description: null 14593 }, 14594 xing: { 14595 enabled: true, 14596 url: null, 14597 title: null, 14598 image: null, 14599 description: null 14600 }, 14601 whatsapp: { 14602 enabled: true, 14603 description: null, 14604 url: null 14605 }, 14606 email: { 14607 enabled: true, 14608 title: null, 14609 description: null, 14610 url: null 14611 } 14612 } 14613 }; 14614 this.setup(element, options); 14615 return this; 14616 } 14617 14618 Share.prototype.setup = function(element, opts) { 14619 var index, instance, instances, _i, _len; 14620 instances = document.querySelectorAll(element); 14621 this.extend(this.config, opts, true); 14622 this.set_global_configuration(); 14623 this.normalize_network_configuration(); 14624 if (this.config.ui.icon_font) { 14625 this.inject_icons(); 14626 } 14627 if (this.config.ui.button_font) { 14628 this.inject_fonts(); 14629 } 14630 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 14631 this.inject_facebook_sdk(); 14632 } 14633 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 14634 instance = instances[index]; 14635 this.setup_instance(element, index); 14636 } 14637 }; 14638 14639 Share.prototype.setup_instance = function(element, index) { 14640 var button, instance, label, network, networks, _i, _len, _results, 14641 _this = this; 14642 instance = document.querySelectorAll(element)[index]; 14643 this.hide(instance); 14644 this.add_class(instance, "sharer-" + index); 14645 instance = document.querySelectorAll(element)[index]; 14646 this.inject_css(instance); 14647 this.inject_html(instance); 14648 this.show(instance); 14649 label = instance.getElementsByTagName("label")[0]; 14650 button = instance.getElementsByClassName("social")[0]; 14651 networks = instance.getElementsByTagName('li'); 14652 this.add_class(button, "networks-" + this.config.enabled_networks); 14653 label.addEventListener("click", function() { 14654 return _this.event_toggle(button); 14655 }); 14656 _this = this; 14657 _results = []; 14658 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 14659 network = networks[index]; 14660 _results.push(network.addEventListener("click", function() { 14661 _this.event_network(instance, this); 14662 return _this.event_close(button); 14663 })); 14664 } 14665 return _results; 14666 }; 14667 14668 Share.prototype.event_toggle = function(button) { 14669 if (this.has_class(button, "active")) { 14670 return this.event_close(button); 14671 } else { 14672 return this.event_open(button); 14673 } 14674 }; 14675 14676 Share.prototype.event_open = function(button) { 14677 if (this.has_class(button, "load")) { 14678 this.remove_class(button, "load"); 14679 } 14680 return this.add_class(button, "active"); 14681 }; 14682 14683 Share.prototype.event_close = function(button) { 14684 return this.remove_class(button, "active"); 14685 }; 14686 14687 Share.prototype.event_network = function(instance, network) { 14688 var name; 14689 name = network.getAttribute("data-network"); 14690 this.hook("before", name, instance);
14691 this["network_" + name](); 14692 return this.hook("after", name, instance); 14693 }; 14694 14695 Share.prototype.open = function() { 14696 return this["public"]("open"); 14697 }; 14698 14699 Share.prototype.close = function() { 14700 return this["public"]("close"); 14701 }; 14702 14703 Share.prototype.toggle = function() { 14704 return this["public"]("toggle"); 14705 }; 14706 14707 Share.prototype["public"] = function(action) { 14708 var button, index, instance, _i, _len, _ref, _results; 14709 _ref = document.querySelectorAll(this.element); 14710 _results = []; 14711 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 14712 instance = _ref[index]; 14713 button = instance.getElementsByClassName("social")[0]; 14714 _results.push(this["event_" + action](button)); 14715 } 14716 return _results; 14717 }; 14718 14719 Share.prototype.network_facebook = function() { 14720 if (this.config.networks.facebook.load_sdk) { 14721 if (!window.FB) { 14722 return console.error("The Facebook JS SDK hasn't loaded yet."); 14723 } 14724 return FB.ui({ 14725 method: 'feed', 14726 name: this.config.networks.facebook.title, 14727 link: this.config.networks.facebook.url, 14728 picture: this.config.networks.facebook.image, 14729 caption: this.config.networks.facebook.caption, 14730 description: this.config.networks.facebook.description 14731 }); 14732 } else { 14733 return this.popup('https://www.facebook.com/sharer/sharer.php', { 14734 u: this.config.networks.facebook.url 14735 }); 14736 } 14737 }; 14738 14739 Share.prototype.network_twitter = function() { 14740 return this.popup('https://twitter.com/intent/tweet', { 14741 text: this.config.networks.twitter.title, 14742 url: this.config.networks.twitter.url 14743 }); 14744 }; 14745 14746 Share.prototype.network_google_plus = function() { 14747 return this.popup('https://plus.google.com/share', { 14748 url: this.config.networks.google_plus.url 14749 }); 14750 }; 14751 14752 Share.prototype.network_pinterest = function() { 14753 return this.popup('https://www.pinterest.com/pin/create/button', { 14754 url: this.config.networks.pinterest.url, 14755 media: this.config.networks.pinterest.image, 14756 description: this.config.networks.pinterest.description 14757 }); 14758 }; 14759 14760 Share.prototype.network_linkedin = function() { 14761 return this.popup('https://www.linkedin.com/shareArticle', { 14762 url: this.config.networks.linkedin.url, 14763 title: this.config.networks.linkedin.title, 14764 summary: this.config.networks.linkedin.description 14765 }); 14766 } 14767 14768 Share.prototype.network_xing = function() { 14769 return this.popup('https://www.xing.com/spi/shares/new', { 14770 url: this.config.networks.xing.url, 14771 image: this.config.networks.xing.image, 14772 title: this.config.networks.xing.title, 14773 summary: this.config.networks.xing.description 14774 }); 14775 } 14776 14777 Share.prototype.network_email = function() { 14778 return this.popup('mailto:', { 14779 subject: this.config.networks.email.title, 14780 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 14781 }); 14782 }; 14783 14784 Share.prototype.inject_icons = function() { 14785 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 14786 }; 14787 14788 Share.prototype.inject_fonts = function() { 14789 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 14790 }; 14791 14792 Share.prototype.inject_stylesheet = function(url) { 14793 var link; 14794 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 14795 link = document.createElement("link"); 14796 link.setAttribute("rel", "stylesheet"); 14797 link.setAttribute("href", url); 14798 return this.el.head.appendChild(link); 14799 } 14800 }; 14801 14802 Share.prototype.inject_css = function(instance) { 14803 var css, meta, selector, style; 14804 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 14805 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 14806 this.config.selector = selector; 14807 css = getStyles(this.config); 14808 style = document.createElement("style"); 14809 style.type = "text/css"; 14810 if (style.styleSheet) { 14811 style.styleSheet.cssText = css; 14812 } else { 14813 style.appendChild(document.createTextNode(css)); 14814 } 14815 this.el.head.appendChild(style); 14816 delete this.config.selector; 14817 meta = document.createElement("meta"); 14818 meta.setAttribute("name", "sharer" + selector); 14819 return this.el.head.appendChild(meta); 14820 } 14821 }; 14822 14823 Share.prototype.inject_html = function(instance) { 14824 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>"; 14825 }; 14826 14827 Share.prototype.inject_facebook_sdk = function() { 14828 var fb_root, script; 14829 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 14830 script = document.createElement("script"); 14831 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')"; 14832 fb_root = document.createElement("div"); 14833 fb_root.id = "fb-root"; 14834 this.el.body.appendChild(fb_root); 14835 return this.el.body.appendChild(script); 14836 } 14837 }; 14838 14839 Share.prototype.hook = function(type, network, instance) { 14840 var fn, opts; 14841 fn = this.config.networks[network][type]; 14842 if (typeof fn === "function") { 14843 opts = fn.call(this.config.networks[network], instance); 14844 if (opts !== void 0) { 14845 opts = this.normalize_filter_config_updates(opts); 14846 this.extend(this.config.networks[network], opts, true); 14847 this.normalize_network_configuration(); 14848 } 14849 } 14850 }; 14851 14852 Share.prototype.default_title = function() { 14853 var content; 14854 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 14855 return encodeURIComponent(content.getAttribute('content')); 14856 } else if (content = document.querySelector('title')) { 14857 return encodeURIComponent(content.innerText); 14858 } 14859 }; 14860 14861 Share.prototype.default_image = function() { 14862 var content; 14863 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 14864 return content.getAttribute('content'); 14865 } 14866 }; 14867 14868 Share.prototype.default_description = function() { 14869 var content; 14870 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 14871 return content.getAttribute('content'); 14872 } else { 14873 return ''; 14874 } 14875 }; 14876 14877 Share.prototype.set_global_configuration = function() { 14878 var display, network, option, options, _ref, _results; 14879 _ref = this.config.networks; 14880 _results = []; 14881 for (network in _ref) { 14882 options = _ref[network]; 14883 for (option in options) { 14884 if (this.config.networks[network][option] == null) { 14885 this.config.networks[network][option] = this.config[option]; 14886 } 14887 } 14888 if (this.config.networks[network].enabled) { 14889 display = 'block'; 14890 this.config.enabled_networks += 1; 14891 } else { 14892 display = 'none'; 14893 } 14894 _results.push(this.config.networks[network].display = display); 14895 } 14896 return _results; 14897 }; 14898 14899 Share.prototype.normalize_network_configuration = function() { 14900 if (!this.config.networks.facebook.app_id) { 14901 this.config.networks.facebook.load_sdk = false;
14902 } 14903 if (!this.is_encoded(this.config.networks.twitter.description)) { 14904 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 14905 } 14906 if (typeof this.config.networks.facebook.app_id === 'number') { 14907 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 14908 } 14909 }; 14910 14911 Share.prototype.normalize_filter_config_updates = function(opts) { 14912 if (this.config.networks.facebook.app_id !== opts.app_id) { 14913 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."); 14914 delete opts.app_id; 14915 } 14916 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 14917 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."); 14918 delete opts.app_id; 14919 } 14920 return opts; 14921 }; 14922 14923 return Share; 14924 14925})(ShareUtils); 14926 return Share; 14927}); 14928 14929 14930// Generated by CoffeeScript 1.9.2 14931 14932// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 14933 14934(function() { 14935 var $, win; 14936 14937 $ = this.jQuery || window.jQuery; 14938 14939 win = $(window); 14940 14941 $.fn.stick_in_parent = function(opts) { 14942 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 14943 if (opts == null) { 14944 opts = {}; 14945 } 14946 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; 14947 if (offset_top == null) { 14948 offset_top = 0; 14949 } 14950 if (parent_selector == null) { 14951 parent_selector = void 0; 14952 } 14953 if (inner_scrolling == null) { 14954 inner_scrolling = true; 14955 } 14956 if (sticky_class == null) { 14957 sticky_class = "is_stuck"; 14958 } 14959 doc = $(document); 14960 if (enable_bottoming == null) { 14961 enable_bottoming = true; 14962 } 14963 outer_width = function(el) { 14964 var _el, computed, w; 14965 if (window.getComputedStyle) { 14966 _el = el[0]; 14967 computed = window.getComputedStyle(el[0]); 14968 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 14969 if (computed.getPropertyValue("box-sizing") !== "border-box") { 14970 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 14971 } 14972 return w; 14973 } else { 14974 return el.outerWidth(true); 14975 } 14976 }; 14977 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 14978 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 14979 if (elm.data("sticky_kit")) { 14980 return; 14981 } 14982 elm.data("sticky_kit", true); 14983 last_scroll_height = doc.height(); 14984 parent = elm.parent(); 14985 if (parent_selector != null) { 14986 parent = parent.closest(parent_selector); 14987 } 14988 if (!parent.length) { 14989 throw "failed to find stick parent"; 14990 } 14991 fixed = false; 14992 bottomed = false; 14993 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 14994 if (spacer) { 14995 spacer.css('position', elm.css('position')); 14996 } 14997 recalc = function() { 14998 var border_top, padding_top, restore; 14999 if (detached) { 15000 return; 15001 } 15002 last_scroll_height = doc.height(); 15003 border_top = parseInt(parent.css("border-top-width"), 10); 15004 padding_top = parseInt(parent.css("padding-top"), 10); 15005 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 15006 parent_top = parent.offset().top + border_top + padding_top; 15007 parent_height = parent.height(); 15008 if (fixed) { 15009 fixed = false;
15010 bottomed = false; 15011 if (manual_spacer == null) { 15012 elm.insertAfter(spacer); 15013 spacer.detach(); 15014 } 15015 elm.css({ 15016 position: "", 15017 top: "", 15018 width: "", 15019 bottom: "" 15020 }).removeClass(sticky_class); 15021 restore = true; 15022 } 15023 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 15024 height = elm.outerHeight(true); 15025 el_float = elm.css("float"); 15026 if (spacer) { 15027 spacer.css({ 15028 width: outer_width(elm), 15029 height: height, 15030 display: elm.css("display"), 15031 "vertical-align": elm.css("vertical-align"), 15032 "float": el_float 15033 }); 15034 } 15035 if (restore) { 15036 return tick(); 15037 } 15038 }; 15039 recalc(); 15040 if (height === parent_height) { 15041 return; 15042 } 15043 last_pos = void 0; 15044 offset = offset_top; 15045 recalc_counter = recalc_every; 15046 tick = function() { 15047 var css, delta, recalced, scroll, will_bottom, win_height; 15048 if (detached) { 15049 return; 15050 } 15051 recalced = false; 15052 if (recalc_counter != null) { 15053 recalc_counter -= 1; 15054 if (recalc_counter <= 0) { 15055 recalc_counter = recalc_every; 15056 recalc(); 15057 recalced = true; 15058 } 15059 } 15060 if (!recalced && doc.height() !== last_scroll_height) { 15061 recalc(); 15062 recalced = true; 15063 } 15064 scroll = win.scrollTop(); 15065 if (last_pos != null) { 15066 delta = scroll - last_pos; 15067 } 15068 last_pos = scroll; 15069 if (fixed) { 15070 if (enable_bottoming) { 15071 will_bottom = scroll + height + offset > parent_height + parent_top; 15072 if (bottomed && !will_bottom) { 15073 bottomed = false; 15074 elm.css({ 15075 position: "fixed", 15076 bottom: "", 15077 top: offset 15078 }).trigger("sticky_kit:unbottom"); 15079 } 15080 } 15081 if (scroll < top) { 15082 fixed = false; 15083 offset = offset_top; 15084 if (manual_spacer == null) { 15085 if (el_float === "left" || el_float === "right") { 15086 elm.insertAfter(spacer); 15087 } 15088 spacer.detach(); 15089 } 15090 css = { 15091 position: "", 15092 width: "", 15093 top: "" 15094 }; 15095 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 15096 } 15097 if (inner_scrolling) { 15098 win_height = win.height(); 15099 if (height + offset_top > win_height) { 15100 if (!bottomed) { 15101 offset -= delta; 15102 offset = Math.max(win_height - height, offset); 15103 offset = Math.min(offset_top, offset); 15104 if (fixed) { 15105 elm.css({ 15106 top: offset + "px" 15107 }); 15108 } 15109 } 15110 } 15111 } 15112 } else { 15113 if (scroll > top) { 15114 fixed = true; 15115 css = { 15116 position: "fixed", 15117 top: offset 15118 }; 15119 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 15120 elm.css(css).addClass(sticky_class); 15121 if (manual_spacer == null) { 15122 elm.after(spacer); 15123 if (el_float === "left" || el_float === "right") { 15124 spacer.append(elm); 15125 } 15126 } 15127 elm.trigger("sticky_kit:stick"); 15128 } 15129 } 15130 if (fixed && enable_bottoming) { 15131 if (will_bottom == null) { 15132 will_bottom = scroll + height + offset > parent_height + parent_top; 15133 } 15134 if (!bottomed && will_bottom) { 15135 bottomed = true; 15136 if (parent.css("position") === "static") { 15137 parent.css({ 15138 position: "relative" 15139 }); 15140 } 15141 return elm.css({ 15142 position: "absolute", 15143 bottom: padding_bottom, 15144 top: "auto" 15145 }).trigger("sticky_kit:bottom"); 15146 } 15147 } 15148 }; 15149 recalc_and_tick = function() { 15150 recalc(); 15151 return tick(); 15152 }; 15153 detach = function() { 15154 detached = true; 15155 win.off("touchmove", tick); 15156 win.off("scroll", tick); 15157 win.off("resize", recalc_and_tick); 15158 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 15159 elm.off("sticky_kit:detach", detach); 15160 elm.removeData("sticky_kit"); 15161 elm.css({ 15162 position: "", 15163 bottom: "", 15164 top: "", 15165 width: "" 15166 }); 15167 parent.position("position", ""); 15168 if (fixed) { 15169 if (manual_spacer == null) { 15170 if (el_float === "left" || el_float === "right") { 15171 elm.insertAfter(spacer); 15172 } 15173 spacer.remove(); 15174 } 15175 return elm.removeClass(sticky_class); 15176 } 15177 }; 15178 win.on("touchmove", tick); 15179 win.on("scroll", tick); 15180 win.on("resize", recalc_and_tick); 15181 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 15182 elm.on("sticky_kit:detach", detach); 15183 return setTimeout(tick, 0); 15184 }; 15185 for (i = 0, len = this.length; i < len; i++) { 15186 elm = this[i]; 15187 fn($(elm)); 15188 } 15189 return this; 15190 }; 15191 15192}).call(this); 15193 15194 15195 15196/* ======================================================================== 15197 * Bootstrap: collapse.js v3.1.1 15198 * http://getbootstrap.com/javascript/#collapse 15199 * ======================================================================== 15200 * Copyright 2011-2014 Twitter, Inc. 15201 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15202 * ======================================================================== */ 15203 15204 15205+function ($) { 15206 'use strict'; 15207 15208 // COLLAPSE PUBLIC CLASS DEFINITION 15209 // ================================ 15210 15211 var Collapse = function (element, options) { 15212 this.$element = $(element) 15213 this.options = $.extend({}, Collapse.DEFAULTS, options) 15214 this.transitioning = null 15215 15216 if (this.options.parent) this.$parent = $(this.options.parent) 15217 if (this.options.toggle) this.toggle() 15218 } 15219 15220 Collapse.DEFAULTS = { 15221 toggle: true 15222 } 15223 15224 Collapse.prototype.dimension = function () { 15225 var hasWidth = this.$element.hasClass('width') 15226 return hasWidth ? 'width' : 'height' 15227 } 15228 15229 Collapse.prototype.show = function () { 15230 if (this.transitioning || this.$element.hasClass('in')) return 15231 15232 var startEvent = $.Event('show.bs.collapse') 15233 this.$element.trigger(startEvent) 15234 if (startEvent.isDefaultPrevented()) return 15235 15236 var actives = this.$parent && this.$parent.find('> .panel > .in') 15237 15238 if (actives && actives.length) { 15239 var hasData = actives.data('bs.collapse') 15240 if (hasData && hasData.transitioning) return 15241 actives.collapse('hide') 15242 hasData || actives.data('bs.collapse', null) 15243 } 15244 15245 var dimension = this.dimension() 15246 15247 this.$element 15248 .removeClass('collapse') 15249 .addClass('collapsing')[dimension](0) 15250 15251 this.transitioning = 1 15252 15253 var complete = function (e) { 15254 if (e && e.target != this.$element[0]) return 15255 this.$element 15256 .removeClass('collapsing') 15257 .addClass('collapse in')[dimension]('auto') 15258 this.transitioning = 0 15259 this.$element.trigger('shown.bs.collapse') 15260 } 15261 15262 if (!$.support.transition) return complete.call(this) 15263 15264 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 15265 15266 this.$element 15267 .one($.support.transition.end, $.proxy(complete, this)) 15268 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 15269 } 15270 15271 Collapse.prototype.hide = function () { 15272 if (this.transitioning || !this.$element.hasClass('in')) return 15273 15274 var startEvent = $.Event('hide.bs.collapse') 15275 this.$element.trigger(startEvent) 15276 if (startEvent.isDefaultPrevented()) return 15277 15278 var dimension = this.dimension() 15279 15280 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 15281 15282 this.$element 15283 .addClass('collapsing') 15284 .removeClass('collapse') 15285 .removeClass('in') 15286 15287 this.transitioning = 1 15288 15289 var complete = function (e) { 15290 if (e && e.target != this.$element[0]) return 15291 this.transitioning = 0 15292 this.$element 15293 .trigger('hidden.bs.collapse') 15294 .removeClass('collapsing') 15295 .addClass('collapse') 15296 } 15297 15298 if (!$.support.transition) return complete.call(this) 15299 15300 this.$element 15301 [dimension](0) 15302 .one($.support.transition.end, $.proxy(complete, this)) 15303 .emulateTransitionEnd(350) 15304 } 15305 15306 Collapse.prototype.toggle = function () { 15307 this[this.$element.hasClass('in') ? 'hide' : 'show']() 15308 } 15309 15310 15311 // COLLAPSE PLUGIN DEFINITION 15312 // ========================== 15313 15314 var old = $.fn.collapse 15315 15316 $.fn.collapse = function (option) { 15317 return this.each(function () { 15318 var $this = $(this) 15319 var data = $this.data('bs.collapse') 15320 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 15321 15322 if (!data && options.toggle && option == 'show') option = !option 15323 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 15324 if (typeof option == 'string') data[option]() 15325 }) 15326 } 15327 15328 $.fn.collapse.Constructor = Collapse 15329 15330 15331 // COLLAPSE NO CONFLICT 15332 // ==================== 15333 15334 $.fn.collapse.noConflict = function () { 15335 $.fn.collapse = old 15336 return this 15337 } 15338 15339 15340 // COLLAPSE DATA-API 15341 // ================= 15342 15343 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 15344 var $this = $(this), href 15345 var target = $this.attr('data-target') 15346 || e.preventDefault() 15347 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 15348 var $target = $(target) 15349 var data = $target.data('bs.collapse') 15350 var option = data ? 'toggle' : $this.data() 15351 var parent = $this.attr('data-parent') 15352 var $parent = parent && $(parent) 15353 15354 if (!data || !data.transitioning) { 15355 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 15356 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 15357 } 15358 15359 $target.collapse(option) 15360 }) 15361 15362}(jQuery); 15363 15364 15365/* ======================================================================== 15366 * Bootstrap: tab.js v3.1.1 15367 * http://getbootstrap.com/javascript/#tabs 15368 * ======================================================================== 15369 * Copyright 2011-2014 Twitter, Inc. 15370 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15371 * ======================================================================== */ 15372 15373 15374+function ($) { 15375 'use strict'; 15376 15377 // TAB CLASS DEFINITION 15378 // ==================== 15379 15380 var Tab = function (element) { 15381 this.element = $(element) 15382 } 15383 15384 Tab.prototype.show = function () { 15385 var $this = this.element 15386 var $ul = $this.closest('ul:not(.dropdown-menu)') 15387 var selector = $this.data('target') 15388 15389 if (!selector) { 15390 selector = $this.attr('href') 15391 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 15392 } 15393 15394 if ($this.parent('li').hasClass('active')) return 15395 15396 var previous = $ul.find('.active:last a')[0] 15397 var e = $.Event('show.bs.tab', { 15398 relatedTarget: previous 15399 }) 15400 15401 $this.trigger(e) 15402 15403 if (e.isDefaultPrevented()) return 15404 15405 var $target = $(selector) 15406 15407 this.activate($this.parent('li'), $ul) 15408 this.activate($target, $target.parent(), function () { 15409 $this.trigger({ 15410 type: 'shown.bs.tab', 15411 relatedTarget: previous 15412 }) 15413 }) 15414 } 15415 15416 Tab.prototype.activate = function (element, container, callback) { 15417 var $active = container.find('> .active') 15418 var transition = callback 15419 && $.support.transition 15420 && $active.hasClass('fade') 15421 15422 function next() { 15423 $active 15424 .removeClass('active') 15425 .find('> .dropdown-menu > .active') 15426 .removeClass('active') 15427 15428 element.addClass('active') 15429 15430 if (transition) { 15431 element[0].offsetWidth // reflow for transition 15432 element.addClass('in') 15433 } else { 15434 element.removeClass('fade') 15435 } 15436 15437 if (element.parent('.dropdown-menu')) { 15438 element.closest('li.dropdown').addClass('active') 15439 } 15440 15441 callback && callback() 15442 } 15443 15444 transition ? 15445 $active 15446 .one($.support.transition.end, next) 15447 .emulateTransitionEnd(150) : 15448 next() 15449 15450 $active.removeClass('in') 15451 } 15452 15453 15454 // TAB PLUGIN DEFINITION 15455 // ===================== 15456 15457 var old = $.fn.tab 15458 15459 $.fn.tab = function ( option ) { 15460 return this.each(function () { 15461 var $this = $(this) 15462 var data = $this.data('bs.tab') 15463 15464 if (!data) $this.data('bs.tab', (data = new Tab(this))) 15465 if (typeof option == 'string') data[option]() 15466 }) 15467 } 15468 15469 $.fn.tab.Constructor = Tab 15470 15471 15472 // TAB NO CONFLICT 15473 // =============== 15474 15475 $.fn.tab.noConflict = function () { 15476 $.fn.tab = old 15477 return this 15478 } 15479 15480 15481 // TAB DATA-API 15482 // ============ 15483 15484 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 15485 e.preventDefault() 15486 $(this).tab('show') 15487 }) 15488 15489}(jQuery); 15490 15491 15492/* ======================================================================== 15493 * Bootstrap: tooltip.js v3.1.1 15494 * http://getbootstrap.com/javascript/#tooltip 15495 * Inspired by the original jQuery.tipsy by Jason Frame 15496 * ======================================================================== 15497 * Copyright 2011-2014 Twitter, Inc. 15498 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15499 * ======================================================================== */ 15500 15501 15502+function ($) { 15503 'use strict'; 15504 15505 // TOOLTIP PUBLIC CLASS DEFINITION 15506 // =============================== 15507 15508 var Tooltip = function (element, options) { 15509 this.type = 15510 this.options = 15511 this.enabled = 15512 this.timeout = 15513 this.hoverState = 15514 this.$element = null 15515 15516 this.init('tooltip', element, options) 15517 } 15518 15519 Tooltip.DEFAULTS = { 15520 animation: true, 15521 placement: 'top', 15522 selector: false, 15523 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 15524 trigger: 'hover focus', 15525 title: '', 15526 delay: 0, 15527 html: false, 15528 container: false, 15529 viewport: { 15530 selector: 'body', 15531 padding: 0 15532 } 15533 } 15534 15535 Tooltip.prototype.init = function (type, element, options) { 15536 this.enabled = true 15537 this.type = type 15538 this.$element = $(element) 15539 this.options = this.getOptions(options) 15540 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 15541 15542 var triggers = this.options.trigger.split(' ') 15543 15544 for (var i = triggers.length; i--;) { 15545 var trigger = triggers[i] 15546 15547 if (trigger == 'click') { 15548 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 15549 } else if (trigger != 'manual') { 15550 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 15551 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 15552 15553 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 15554 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 15555 } 15556 } 15557 15558 this.options.selector ? 15559 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 15560 this.fixTitle() 15561 } 15562 15563 Tooltip.prototype.getDefaults = function () { 15564 return Tooltip.DEFAULTS 15565 } 15566 15567 Tooltip.prototype.getOptions = function (options) { 15568 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 15569 15570 if (options.delay && typeof options.delay == 'number') { 15571 options.delay = { 15572 show: options.delay, 15573 hide: options.delay 15574 } 15575 } 15576 15577 return options 15578 } 15579 15580 Tooltip.prototype.getDelegateOptions = function () { 15581 var options = {} 15582 var defaults = this.getDefaults() 15583 15584 this._options && $.each(this._options, function (key, value) { 15585 if (defaults[key] != value) options[key] = value 15586 }) 15587 15588 return options 15589 } 15590 15591 Tooltip.prototype.enter = function (obj) { 15592 var self = obj instanceof this.con
15592structor ? 15593 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 15594 15595 clearTimeout(self.timeout) 15596 15597 self.hoverState = 'in' 15598 15599 if (!self.options.delay || !self.options.delay.show) return self.show() 15600 15601 self.timeout = setTimeout(function () { 15602 if (self.hoverState == 'in') self.show() 15603 }, self.options.delay.show) 15604 } 15605 15606 Tooltip.prototype.leave = function (obj) { 15607 var self = obj instanceof this.constructor ? 15608 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 15609 15610 clearTimeout(self.timeout) 15611 15612 self.hoverState = 'out' 15613 15614 if (!self.options.delay || !self.options.delay.hide) return self.hide() 15615 15616 self.timeout = setTimeout(function () { 15617 if (self.hoverState == 'out') self.hide() 15618 }, self.options.delay.hide) 15619 } 15620 15621 Tooltip.prototype.show = function () { 15622 var e = $.Event('show.bs.' + this.type) 15623 15624 if (this.hasContent() && this.enabled) { 15625 this.$element.trigger(e) 15626 15627 if (e.isDefaultPrevented()) return 15628 var that = this; 15629 15630 var $tip = this.tip() 15631 15632 this.setContent() 15633 15634 if (this.options.animation) $tip.addClass('fade') 15635 15636 var placement = typeof this.options.placement == 'function' ? 15637 this.options.placement.call(this, $tip[0], this.$element[0]) : 15638 this.options.placement 15639 15640 var autoToken = /\s?auto?\s?/i 15641 var autoPlace = autoToken.test(placement) 15642 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 15643 15644 $tip 15645 .detach() 15646 .css({ top: 0, left: 0, display: 'block' }) 15647 .addClass(placement) 15648 15649 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 15650 15651 var pos = this.getPosition() 15652 var actualWidth = $tip[0].offsetWidth 15653 var actualHeight = $tip[0].offsetHeight 15654 15655 if (autoPlace) { 15656 var orgPlacement = placement 15657 var $parent = this.$element.parent() 15658 var parentDim = this.getPosition($parent) 15659 15660 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 15661 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 15662 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 15663 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 15664 placement 15665 15666 $tip 15667 .removeClass(orgPlacement) 15668 .addClass(placement) 15669 } 15670 15671 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 15672 15673 this.applyPlacement(calculatedOffset, placement) 15674 this.hoverState = null 15675 15676 var complete = function() { 15677 that.$element.trigger('shown.bs.' + that.type) 15678 } 15679 15680 $.support.transition && this.$tip.hasClass('fade') ? 15681 $tip 15682 .one($.support.transition.end, complete) 15683 .emulateTransitionEnd(150) : 15684 complete() 15685 } 15686 } 15687 15688 Tooltip.prototype.applyPlacement = function (offset, placement) { 15689 var $tip = this.tip() 15690 var width = $tip[0].offsetWidth 15691 var height = $tip[0].offsetHeight 15692 15693 // manually read margins because getBoundingClientRect includes difference 15694 var marginTop = parseInt($tip.css('margin-top'), 10) 15695 var marginLeft = parseInt($tip.css('margin-left'), 10) 15696 15697 // we must check for NaN for ie 8/9 15698 if (isNaN(marginTop)) marginTop = 0 15699 if (isNaN(marginLeft)) marginLeft = 0 15700 15701 offset.top = offset.top + marginTop 15702 offset.left = offset.left + marginLeft 15703 15704 // $.fn.offset doesn't round pixel values 15705 // so we use setOffset directly with our own function B-0 15706 $.offset.setOffset($tip[0], $.extend({ 15707 using: function (props) { 15708 $tip.css({ 15709 top: Math.round(props.top), 15710 left: Math.round(props.left) 15711 }) 15712 } 15713 }, offset), 0) 15714 15715 $tip.addClass('in') 15716 15717 // check to see if placing tip in new offset caused the tip to resize itself 15718 var actualWidth = $tip[0].offsetWidth 15719 var actualHeight = $tip[0].offsetHeight 15720 15721 if (placement == 'top' && actualHeight != height) { 15722 offset.top = offset.top + height - actualHeight 15723 } 15724 15725 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 15726 15727 if (delta.left) offset.left += delta.left 15728 else offset.top += delta.top 15729 15730 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 15731 var arrowPosition = delta.left ? 'left' : 'top' 15732 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 15733 15734 $tip.offset(offset) 15735 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 15736 } 15737 15738 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 15739 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 15740 } 15741 15742 Tooltip.prototype.setContent = function () { 15743 var $tip = this.tip() 15744 var title = this.getTitle() 15745 15746 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 15747 $tip.removeClass('fade in top bottom left right') 15748 } 15749 15750 Tooltip.prototype.hide = function () { 15751 var that = this 15752 var $tip = this.tip() 15753 var e = $.Event('hide.bs.' + this.type) 15754 15755 function complete() { 15756 if (that.hoverState != 'in') $tip.detach() 15757 that.$element.trigger('hidden.bs.' + that.type) 15758 } 15759 15760 this.$element.trigger(e) 15761 15762 if (e.isDefaultPrevented()) return 15763 15764 $tip.removeClass('in') 15765 15766 $.support.transition && this.$tip.hasClass('fade') ? 15767 $tip 15768 .one($.support.transition.end, complete) 15769 .emulateTransitionEnd(150) : 15770 complete() 15771 15772 this.hoverState = null 15773 15774 return this 15775 } 15776 15777 Tooltip.prototype.fixTitle = function () { 15778 var $e = this.$element 15779 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 15780 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 15781 } 15782 } 15783 15784 Tooltip.prototype.hasContent = function () { 15785 return this.getTitle() 15786 } 15787 15788 Tooltip.prototype.getPosition = function ($element) { 15789 $element = $element || this.$element 15790 var el = $element[0] 15791 var isBody = el.tagName == 'BODY' 15792 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 15793 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 15794 width: isBody ? $(window).width() : $element.outerWidth(), 15795 height: isBody ? $(window).height() : $element.outerHeight() 15796 }, isBody ? {top: 0, left: 0} : $element.offset()) 15797 } 15798 15799 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 15800 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 15801 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 15802 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 15803 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 15804 15805 } 15806 15807 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 15808 var delta = { top: 0, left: 0 } 15809 if (!this.$viewport) return delta 15810 15811 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 15812 var viewportDimensions = this.getPosition(this.$viewport) 15813 15814 if (/right|left/.test(placement)) { 15815 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 15816 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 15817 if (topEdgeOffset < viewportDimensions.top) { // top overflow 15818 delta.top = viewportDimensions.top - topEdgeOffset 15819 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 15820 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
15820EdgeOffset 15821 } 15822 } else { 15823 var leftEdgeOffset = pos.left - viewportPadding 15824 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 15825 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 15826 delta.left = viewportDimensions.left - leftEdgeOffset 15827 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 15828 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 15829 } 15830 } 15831 15832 return delta 15833 } 15834 15835 Tooltip.prototype.getTitle = function () { 15836 var title 15837 var $e = this.$element 15838 var o = this.options 15839 15840 title = $e.attr('data-original-title') 15841 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 15842 15843 return title 15844 } 15845 15846 Tooltip.prototype.tip = function () { 15847 return this.$tip = this.$tip || $(this.options.template) 15848 } 15849 15850 Tooltip.prototype.arrow = function () { 15851 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 15852 } 15853 15854 Tooltip.prototype.validate = function () { 15855 if (!this.$element[0].parentNode) { 15856 this.hide() 15857 this.$element = null 15858 this.options = null 15859 } 15860 } 15861 15862 Tooltip.prototype.enable = function () { 15863 this.enabled = true 15864 } 15865 15866 Tooltip.prototype.disable = function () { 15867 this.enabled = false 15868 } 15869 15870 Tooltip.prototype.toggleEnabled = function () { 15871 this.enabled = !this.enabled 15872 } 15873 15874 Tooltip.prototype.toggle = function (e) { 15875 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 15876 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 15877 } 15878 15879 Tooltip.prototype.destroy = function () { 15880 clearTimeout(this.timeout) 15881 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 15882 } 15883 15884 15885 // TOOLTIP PLUGIN DEFINITION 15886 // ========================= 15887 15888 var old = $.fn.tooltip 15889 15890 $.fn.tooltip = function (option) { 15891 return this.each(function () { 15892 var $this = $(this) 15893 var data = $this.data('bs.tooltip') 15894 var options = typeof option == 'object' && option 15895 15896 if (!data && option == 'destroy') return 15897 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 15898 if (typeof option == 'string') data[option]() 15899 }) 15900 } 15901 15902 $.fn.tooltip.Constructor = Tooltip 15903 15904 15905 // TOOLTIP NO CONFLICT 15906 // =================== 15907 15908 $.fn.tooltip.noConflict = function () { 15909 $.fn.tooltip = old 15910 return this 15911 } 15912 15913}(jQuery); 15914 15915 15916/* ======================================================================== 15917 * Bootstrap: transition.js v3.1.1 15918 * http://getbootstrap.com/javascript/#transitions 15919 * ======================================================================== 15920 * Copyright 2011-2014 Twitter, Inc. 15921 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15922 * ======================================================================== */ 15923 15924 15925+function ($) { 15926 'use strict'; 15927 15928 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 15929 // ============================================================ 15930 15931 function transitionEnd() { 15932 var el = document.createElement('bootstrap') 15933 15934 var transEndEventNames = { 15935 WebkitTransition : 'webkitTransitionEnd', 15936 MozTransition : 'transitionend', 15937 OTransition : 'oTransitionEnd otransitionend', 15938 transition : 'transitionend' 15939 } 15940 15941 for (var name in transEndEventNames) { 15942 if (el.style[name] !== undefined) { 15943 return { end: transEndEventNames[name] } 15944 } 15945 } 15946 15947 return false // explicit for ie8 ( ._.) 15948 } 15949 15950 // http://blog.alexmaccaw.com/css-transitions 15951 $.fn.emulateTransitionEnd = function (duration) { 15952 var called = false, $el = this 15953 $(this).one($.support.transition.end, function () { called = true }) 15954 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 15955 setTimeout(callback, duration) 15956 return this 15957 } 15958 15959 $(function () { 15960 $.support.transition = transitionEnd() 15961 }) 15962 15963}(jQuery); 15964 15965
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.