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 v2.0.1 4552 * sub-classes Packery 4553 */ 4554 4555!function(a,b){"function"==typeof define&&define.amd?define("packery/js/rect",b):"object"==typeof module&&module.exports?module.exports=b():(a.Packery=a.Packery||{},a.Packery.Rect=b())}(window,function(){function a(b){for(var c in a.defaults)this[c]=a.defaults[c];for(c in b)this[c]=b[c]}a.defaults={x:0,y:0,width:0,height:0};var b=a.prototype;return b.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},b.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},b.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},b.canFit=function(a){return this.width>=a.width&&this.height>=a.height},a}),function(a,b){if("function"==typeof define&&define.amd)define("packery/js/packer",["./rect"],b);else if("object"==typeof module&&module.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){this.width=a||0,this.height=b||0,this.sortDirection=c||"downwardLeftToRight",this.reset()}var c=b.prototype;c.reset=function(){this.spaces=[];var b=new a({x:0,y:0,width:this.width,height:this.height});this.spaces.push(b),this.sorter=d[this.sortDirection]||d.downwardLeftToRight},c.pack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b];if(c.canFit(a)){this.placeInSpace(a,c);break}}},c.columnPack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b],d=c.x<=a.x&&c.x+c.width>=a.x+a.width&&c.height>=a.height-.01;if(d){a.y=c.y,this.placed(a);break}}},c.rowPack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b],d=c.y<=a.y&&c.y+c.height>=a.y+a.height&&c.width>=a.width-.01;if(d){a.x=c.x,this.placed(a);break}}},c.placeInSpace=function(a,b){a.x=b.x,a.y=b.y,this.placed(a)},c.placed=function(a){for(var b=[],c=0;c<this.spaces.length;c++){var d=this.spaces[c],e=d.getMaximalFreeRects(a);
vendor: 8,438 bytes, line 4555
4555e?b.push.apply(b,e):b.push(d)}this.spaces=b,this.mergeSortSpaces()},c.mergeSortSpaces=function(){b.mergeRects(this.spaces),this.spaces.sort(this.sorter)},c.addSpace=function(a){this.spaces.push(a),this.mergeSortSpaces()},b.mergeRects=function(a){var b=0,c=a[b];a:for(;c;){for(var d=0,e=a[b+d];e;){if(e==c)d++;else{if(e.contains(c)){a.splice(b,1),c=a[b];continue a}c.contains(e)?a.splice(b+d,1):d++}e=a[b+d]}b++,c=a[b]}return a};var d={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}),function(a,b){"function"==typeof define&&define.amd?define("packery/js/item",["outlayer/outlayer","./rect"],b):"object"==typeof module&&module.exports?module.exports=b(require("outlayer"),require("./rect")):a.Packery.Item=b(a.Outlayer,a.Packery.Rect)}(window,function(a,b){var c=document.documentElement.style,d="string"==typeof c.transform?"transform":"WebkitTransform",e=function(){a.Item.apply(this,arguments)},f=e.prototype=Object.create(a.Item.prototype),g=f._create;f._create=function(){g.call(this),this.rect=new b};var h=f.moveTo;return f.moveTo=function(a,b){var c=Math.abs(this.position.x-a),d=Math.abs(this.position.y-b),e=this.layout.dragItemCount&&!this.isPlacing&&!this.isTransitioning&&1>c&&1>d;return e?void this.goTo(a,b):void h.apply(this,arguments)},f.enablePlacing=function(){this.removeTransitionStyles(),this.isTransitioning&&d&&(this.element.style[d]="none"),this.isTransitioning=!1,this.getSize(),this.layout._setRectSize(this.element,this.rect),this.isPlacing=!0},f.disablePlacing=function(){this.isPlacing=!1},f.removeElem=function(){this.element.parentNode.removeChild(this.element),this.layout.packer.addSpace(this.rect),this.emitEvent("remove",[this])},f.showDropPlaceholder=function(){var a=this.dropPlaceholder;a||(a=this.dropPlaceholder=document.createElement("div"),a.className="packery-drop-placeholder",a.style.position="absolute"),a.style.width=this.size.width+"px",a.style.height=this.size.height+"px",this.positionDropPlaceholder(),this.layout.element.appendChild(a)},f.positionDropPlaceholder=function(){this.dropPlaceholder.style[d]="translate("+this.rect.x+"px, "+this.rect.y+"px)"},f.hideDropPlaceholder=function(){this.layout.element.removeChild(this.dropPlaceholder)},e}),function(a,b){"function"==typeof define&&define.amd?define("packery/js/packery",["get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],b):"object"==typeof module&&module.exports?module.exports=b(require("get-size"),require("outlayer"),require("./rect"),require("./packer"),require("./item")):a.Packery=b(a.getSize,a.Outlayer,a.Packery.Rect,a.Packery.Packer,a.Packery.Item)}(window,function(a,b,c,d,e){function f(a,b){return a.position.y-b.position.y||a.position.x-b.position.x}function g(a,b){return a.position.x-b.position.x||a.position.y-b.position.y}function h(a,b){var c=b.x-a.x,d=b.y-a.y;return Math.sqrt(c*c+d*d)}c.prototype.canFit=function(a){return this.width>=a.width-1&&this.height>=a.height-1};var i=b.create("packery");i.Item=e;var j=i.prototype;j._create=function(){b.prototype._create.call(this),this.packer=new d,this.shiftPacker=new d,this.isEnabled=!0,this.dragItemCount=0;var a=this;this.handleDraggabilly={dragStart:function(){a.itemDragStart(this.element)},dragMove:function(){a.itemDragMove(this.element,this.position.x,this.position.y)},dragEnd:function(){a.itemDragEnd(this.element)}},this.handleUIDraggable={start:function(b,c){c&&a.itemDragStart(b.currentTarget)},drag:function(b,c){c&&a.itemDragMove(b.currentTarget,c.position.left,c.position.top)},stop:function(b,c){c&&a.itemDragEnd(b.currentTarget)}}},j._resetLayout=function(){this.getSize(),this._getMeasurements();var a,b,c;this._getOption("horizontal")?(a=1/0,b=this.size.innerHeight+this.gutter,c="rightwardTopToBottom"):(a=this.size.innerWidth+this.gutter,b=1/0,c="downwardLeftToRight"),this.packer.width=this.shiftPacker.width=a,this.packer.height=this.shiftPacker.height=b,this.packer.sortDirection=this.shiftPacker.sortDirection=c,this.packer.reset(),this.maxY=0,this.maxX=0},j._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},j._getItemLayoutPosition=function(a){if(this._setRectSize(a.element,a.rect),this.isShifting||this.dragItemCount>0){var b=this._getPackMethod();this.packer[b](a.rect)}else this.packer.pack(a.rect);return this._setMaxXY(a.rect),a.rect},j.shiftLayout=function(){this.isShifting=!0,this.layout(),delete this.isShifting},j._getPackMethod=function(){return this._getOption("horizontal")?"rowPack":"columnPack"},j._setMaxXY=function(a){this.maxX=Math.max(a.x+a.width,this.maxX),this.maxY=Math.max(a.y+a.height,this.maxY)},j._setRectSize=function(b,c){var d=a(b),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)},j._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},j._getContainerSize=function(){return this._getOption("horizontal")?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},j._manageStamp=function(a){var b,d=this.getItem(a);if(d&&d.isPlacing)b=d.rect;else{var e=this._getElementOffset(a);b=new c({x:this._getOption("originLeft")?e.left:e.right,y:this._getOption("originTop")?e.top:e.bottom})}this._setRectSize(a,b),this.packer.placed(b),this._setMaxXY(b)},j.sortItemsByPosition=function(){var a=this._getOption("horizontal")?g:f;this.items.sort(a)},j.fit=function(a,b,c){var d=this.getItem(a);d&&(this.stamp(d.element),d.enablePlacing(),this.updateShiftTargets(d),b=void 0===b?d.rect.x:b,c=void 0===c?d.rect.y:c,this.shift(d,b,c),this._bindFitEvents(d),d.moveTo(d.rect.x,d.rect.y),this.shiftLayout(),this.unstamp(d.element),this.sortItemsByPosition(),d.disablePlacing())},j._bindFitEvents=function(a){function b(){d++,2==d&&c.dispatchEvent("fitComplete",null,[a])}var c=this,d=0;a.once("layout",b),this.once("layoutComplete",b)},j.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&(this.options.shiftPercentResize?this.resizeShiftPercentLayout():this.layout())},j.needsResizeLayout=function(){var b=a(this.element),c=this._getOption("horizontal")?"innerHeight":"innerWidth";return b[c]!=this.size[c]},j.resizeShiftPercentLayout=function(){var b=this._getItemsForLayout(this.items),c=this._getOption("horizontal"),d=c?"y":"x",e=c?"height":"width",f=c?"rowHeight":"columnWidth",g=c?"innerHeight":"innerWidth",h=this[f];if(h=h&&h+this.gutter){this._getMeasurements();var i=this[f]+this.gutter;b.forEach(function(a){var b=Math.round(a.rect[d]/h);a.rect[d]=b*i})}else{var j=a(this.element)[g]+this.gutter,k=this.packer[e];b.forEach(function(a){a.rect[d]=a.rect[d]/k*j})}this.shiftLayout()},j.itemDragStart=function(a){if(this.isEnabled){this.stamp(a);var b=this.getItem(a);b&&(b.enablePlacing(),b.showDropPlaceholder(),this.dragItemCount++,this.updateShiftTargets(b))}},j.updateShiftTargets=function(a){this.shiftPacker.reset(),this._getBoundingRect();var b=this._getOption("originLeft"),d=this._getOption("originTop");this.stamps.forEach(function(a){var e=this.getItem(a);if(!e||!e.isPlacing){var f=this._getElementOffset(a),g=new c({x:b?f.left:f.right,y:d?f.top:f.bottom});this._setRectSize(a,g),this.shiftPacker.placed(g)}},this);var e=this._getOption("horizontal"),f=e?"rowHeight":"columnWidth",g=e?"height":"width";this.shiftTargetKeys=[],this.shiftTargets=[];var h,i=this[f];if(i=i&&i+this.gutter){var j=Math.ceil(a.rect[g]/i),k=Math.floor((this.shiftPacker[g]+this.gutter)/i);h=(k-j)*i;for(var l=0;k>l;l++)this._addShiftTarget(l*i,0,h)}else h=this.shiftPacker[g]+this.gutter-a.rect[g],this._addShiftTarget(0,0,h);var m=this._getItemsForLayout(this.items),n=this._getPackMethod();m.forEach(function(a){var b=a.rect;this._setRectSize(a.element,b),this.shiftPacker[n](b),this._addShiftTarget(b.x,b.y,h);var c=e?b.x+b.width:b.x,d=e?b.y:b.y+b.height;if(this._addShiftTarget(c,d,h),i)for(var f=Math.round(b[g]/i),j=1;f>j;j++){var k=e?c:b.x+i*j,l=e?b.y+i*j:d;this._addShiftTarget(k,l,h)}},this)},j._addShiftTarget=function(a,b,c){var d=this._getOption("horizontal")?b:a;if(!(0!==d&&d>c)){var e=a+","+b,f=-1!=this.shiftTargetKeys.indexOf(e);f||(this.shiftTargetKeys.push(e),this.shiftTargets.push({x:a,y:b}))}},j.shift=function(a,b,c){var d,e=1/0,f={x:b,y:c};
4555this.shiftTargets.forEach(function(a){var b=h(a,f);e>b&&(d=a,e=b)}),a.rect.x=d.x,a.rect.y=d.y};var k=120;j.itemDragMove=function(a,b,c){function d(){f.shift(e,b,c),e.positionDropPlaceholder(),f.layout()}var e=this.isEnabled&&this.getItem(a);if(e){b-=this.size.paddingLeft,c-=this.size.paddingTop;var f=this,g=new Date;this._itemDragTime&&g-this._itemDragTime<k?(clearTimeout(this.dragTimeout),this.dragTimeout=setTimeout(d,k)):(d(),this._itemDragTime=g)}},j.itemDragEnd=function(a){function b(){d++,2==d&&(c.element.classList.remove("is-positioning-post-drag"),c.hideDropPlaceholder(),e.dispatchEvent("dragItemPositioned",null,[c]))}var c=this.isEnabled&&this.getItem(a);if(c){clearTimeout(this.dragTimeout),c.element.classList.add("is-positioning-post-drag");var d=0,e=this;c.once("layout",b),this.once("layoutComplete",b),c.moveTo(c.rect.x,c.rect.y),this.layout(),this.dragItemCount=Math.max(0,this.dragItemCount-1),this.sortItemsByPosition(),c.disablePlacing(),this.unstamp(c.element)}},j.bindDraggabillyEvents=function(a){this._bindDraggabillyEvents(a,"on")},j.unbindDraggabillyEvents=function(a){this._bindDraggabillyEvents(a,"off")},j._bindDraggabillyEvents=function(a,b){var c=this.handleDraggabilly;a[b]("dragStart",c.dragStart),a[b]("dragMove",c.dragMove),a[b]("dragEnd",c.dragEnd)},j.bindUIDraggableEvents=function(a){this._bindUIDraggableEvents(a,"on")},j.unbindUIDraggableEvents=function(a){this._bindUIDraggableEvents(a,"off")},j._bindUIDraggableEvents=function(a,b){var c=this.handleUIDraggable;a[b]("dragstart",c.start)[b]("drag",c.drag)[b]("dragstop",c.stop)};var l=j.destroy;return j.destroy=function(){l.apply(this,arguments),this.isEnabled=!1},i.Rect=c,i.Packer=d,i}),function(a,b){"function"==typeof define&&define.amd?define(["isotope-layout/js/layout-mode","packery/js/packery"],b):"object"==typeof module&&module.exports?module.exports=b(require("isotope-layout/js/layout-mode"),require("packery")):b(a.Isotope.LayoutMode,a.Packery)}(window,function(a,b){var c=a.create("packery"),d=c.prototype,e={_getElementOffset:!0,_getMeasurement:!0};for(var f in b.prototype)e[f]||(d[f]=b.prototype[f]);var g=d._resetLayout;d._resetLayout=function(){this.packer=this.packer||new b.Packer,this.shiftPacker=this.shiftPacker||new b.Packer,g.apply(this,arguments)};var h=d._getItemLayoutPosition;d._getItemLayoutPosition=function(a){return a.rect=a.rect||new b.Rect,h.call(this,a)};var i=d.needsResizeLayout;d.needsResizeLayout=function(){return this._getOption("horizontal")?this.needsVerticalResizeLayout():i.call(this)};var j=d._getOption;return d._getOption=function(a){return"horizontal"==a?void 0!==this.options.isHorizontal?this.options.isHorizontal:this.options.horizontal:j.apply(this.isotope,arguments)},c}); 4556 4557/*! 4558 * cellsByRows layout mode for Isotope 4559 * v1.1.3 4560 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 4561 */ 4562 4563/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 4564 4565( function( window, factory ) { 4566 // universal module definition 4567 /* jshint strict: false */ /*globals define, module, require */ 4568 if ( typeof define === 'function' && define.amd ) { 4569 // AMD 4570 define( [ 4571 'isotope/js/layout-mode' 4572 ], 4573 factory ); 4574 } else if ( typeof exports === 'object' ) { 4575 // CommonJS 4576 module.exports = factory( 4577 require('isotope-layout/js/layout-mode') 4578 ); 4579 } else { 4580 // browser global 4581 factory( 4582 window.Isotope.LayoutMode 4583 ); 4584 } 4585 4586}( window, function factory( LayoutMode ) { 4587 'use strict'; 4588 4589 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 4590 var proto = CellsByRow.prototype; 4591 4592 proto._resetLayout = function() { 4593 // reset properties 4594 this.itemIndex = 0; 4595 // measurements 4596 this.getColumnWidth(); 4597 this.getRowHeight(); 4598 // set cols 4599 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 4600 this.cols = Math.max( this.cols, 1 ); 4601 }; 4602 4603 proto._getItemLayoutPosition = function( item ) { 4604 item.getSize(); 4605 var col = this.itemIndex % this.cols; 4606 var row = Math.floor( this.itemIndex / this.cols ); 4607 // center item within cell 4608 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 4609 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 4610 this.itemIndex++; 4611 return { x: x, y: y }; 4612 }; 4613 4614 proto._getContainerSize = function() { 4615 return {
4616 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 4617 }; 4618 }; 4619 4620 return CellsByRow; 4621 4622})); 4623 4624/*! 4625 -------------------------------- 4626 Infinite Scroll 4627 -------------------------------- 4628 + https://github.com/paulirish/infinite-scroll 4629 + version 2.1.0 4630 + Copyright 2011/12 Paul Irish & Luke Shumard 4631 + Licensed under the MIT license 4632 4633 + Documentation: http://infinite-scroll.com/ 4634*/ 4635;(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;base64,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/fDuFh
4635ohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSHMzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
4635iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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
4635ing"){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;
4635r.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";
4635switch(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"])}}); 4636 4637/*!
4638Waypoints - 4.0.1 4639Copyright © 2011-2016 Caleb Troughton 4640Licensed under the MIT license. 4641https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 4642*/ 4643(function() { 4644 'use strict' 4645 4646 var keyCounter = 0 4647 var allWaypoints = {} 4648 4649 /* http://imakewebthings.com/waypoints/api/waypoint */ 4650 function Waypoint(options) { 4651 if (!options) { 4652 throw new Error('No options passed to Waypoint constructor') 4653 } 4654 if (!options.element) { 4655 throw new Error('No element option passed to Waypoint constructor') 4656 } 4657 if (!options.handler) { 4658 throw new Error('No handler option passed to Waypoint constructor') 4659 } 4660 4661 this.key = 'waypoint-' + keyCounter 4662 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 4663 this.element = this.options.element 4664 this.adapter = new Waypoint.Adapter(this.element) 4665 this.callback = options.handler 4666 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 4667 this.enabled = this.options.enabled 4668 this.triggerPoint = null 4669 this.group = Waypoint.Group.findOrCreate({ 4670 name: this.options.group, 4671 axis: this.axis 4672 }) 4673 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 4674 4675 if (Waypoint.offsetAliases[this.options.offset]) { 4676 this.options.offset = Waypoint.offsetAliases[this.options.offset] 4677 } 4678 this.group.add(this) 4679 this.context.add(this) 4680 allWaypoints[this.key] = this 4681 keyCounter += 1 4682 } 4683 4684 /* Private */ 4685 Waypoint.prototype.queueTrigger = function(direction) { 4686 this.group.queueTrigger(this, direction) 4687 } 4688 4689 /* Private */ 4690 Waypoint.prototype.trigger = function(args) { 4691 if (!this.enabled) { 4692 return 4693 } 4694 if (this.callback) { 4695 this.callback.apply(this, args) 4696 } 4697 } 4698 4699 /* Public */ 4700 /* http://imakewebthings.com/waypoints/api/destroy */ 4701 Waypoint.prototype.destroy = function() { 4702 this.context.remove(this) 4703 this.group.remove(this) 4704 delete allWaypoints[this.key] 4705 } 4706 4707 /* Public */ 4708 /* http://imakewebthings.com/waypoints/api/disable */ 4709 Waypoint.prototype.disable = function() { 4710 this.enabled = false 4711 return this 4712 } 4713 4714 /* Public */ 4715 /* http://imakewebthings.com/waypoints/api/enable */ 4716 Waypoint.prototype.enable = function() { 4717 this.context.refresh() 4718 this.enabled = true 4719 return this 4720 } 4721 4722 /* Public */ 4723 /* http://imakewebthings.com/waypoints/api/next */ 4724 Waypoint.prototype.next = function() { 4725 return this.group.next(this) 4726 } 4727 4728 /* Public */ 4729 /* http://imakewebthings.com/waypoints/api/previous */ 4730 Waypoint.prototype.previous = function() { 4731 return this.group.previous(this) 4732 } 4733 4734 /* Private */ 4735 Waypoint.invokeAll = function(method) { 4736 var allWaypointsArray = []
4737 for (var waypointKey in allWaypoints) { 4738 allWaypointsArray.push(allWaypoints[waypointKey]) 4739 } 4740 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 4741 allWaypointsArray[i][method]() 4742 } 4743 } 4744 4745 /* Public */ 4746 /* http://imakewebthings.com/waypoints/api/destroy-all */ 4747 Waypoint.destroyAll = function() { 4748 Waypoint.invokeAll('destroy') 4749 } 4750 4751 /* Public */ 4752 /* http://imakewebthings.com/waypoints/api/disable-all */ 4753 Waypoint.disableAll = function() { 4754 Waypoint.invokeAll('disable') 4755 } 4756 4757 /* Public */ 4758 /* http://imakewebthings.com/waypoints/api/enable-all */ 4759 Waypoint.enableAll = function() { 4760 Waypoint.Context.refreshAll() 4761 for (var waypointKey in allWaypoints) { 4762 allWaypoints[waypointKey].enabled = true 4763 } 4764 return this 4765 } 4766 4767 /* Public */ 4768 /* http://imakewebthings.com/waypoints/api/refresh-all */ 4769 Waypoint.refreshAll = function() { 4770 Waypoint.Context.refreshAll() 4771 } 4772 4773 /* Public */ 4774 /* http://imakewebthings.com/waypoints/api/viewport-height */ 4775 Waypoint.viewportHeight = function() { 4776 return window.innerHeight || document.documentElement.clientHeight 4777 } 4778 4779 /* Public */ 4780 /* http://imakewebthings.com/waypoints/api/viewport-width */ 4781 Waypoint.viewportWidth = function() { 4782 return document.documentElement.clientWidth 4783 } 4784 4785 Waypoint.adapters = [] 4786 4787 Waypoint.defaults = { 4788 context: window, 4789 continuous: true, 4790 enabled: true, 4791 group: 'default', 4792 horizontal: false, 4793 offset: 0 4794 } 4795 4796 Waypoint.offsetAliases = { 4797 'bottom-in-view': function() { 4798 return this.context.innerHeight() - this.adapter.outerHeight() 4799 }, 4800 'right-in-view': function() { 4801 return this.context.innerWidth() - this.adapter.outerWidth() 4802 } 4803 } 4804 4805 window.Waypoint = Waypoint 4806}()) 4807;(function() { 4808 'use strict' 4809 4810 function requestAnimationFrameShim(callback) { 4811 window.setTimeout(callback, 1000 / 60) 4812 } 4813 4814 var keyCounter = 0 4815 var contexts = {} 4816 var Waypoint = window.Waypoint 4817 var oldWindowLoad = window.onload 4818 4819 /* http://imakewebthings.com/waypoints/api/context */ 4820 function Context(element) { 4821 this.element = element 4822 this.Adapter = Waypoint.Adapter 4823 this.adapter = new this.Adapter(element) 4824 this.key = 'waypoint-context-' + keyCounter 4825 this.didScroll = false 4826 this.didResize = false 4827 this.oldScroll = { 4828 x: this.adapter.scrollLeft(), 4829 y: this.adapter.scrollTop() 4830 } 4831 this.waypoints = { 4832 vertical: {}, 4833 horizontal: {} 4834 } 4835 4836 element.waypointContextKey = this.key 4837 contexts[element.waypointContextKey] = this 4838 keyCounter += 1 4839 if (!Waypoint.windowContext) { 4840 Waypoint.windowContext = true 4841 Waypoint.windowContext = new Context(window) 4842 } 4843 4844 this.createThrottledScrollHandler() 4845 this.createThrottledResizeHandler() 4846 } 4847 4848 /* Private */ 4849 Context.prototype.add = function(waypoint) { 4850 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 4851 this.waypoints[axis][waypoint.key] = waypoint 4852 this.refresh() 4853 } 4854 4855 /* Private */ 4856 Context.prototype.checkEmpty = function() { 4857 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 4858 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 4859 var isWindow = this.element == this.element.window 4860 if (horizontalEmpty && verticalEmpty && !isWindow) { 4861 this.adapter.off('.waypoints') 4862 delete contexts[this.key] 4863 } 4864 } 4865 4866 /* Private */ 4867 Context.prototype.createThrottledResizeHandler = function() { 4868 var self = this 4869 4870 function resizeHandler() { 4871 self.handleResize() 4872 self.didResize = false 4873 } 4874 4875 this.adapter.on('resize.waypoints', function() { 4876 if (!self.didResize) { 4877 self.didResize = true 4878 Waypoint.requestAnimationFrame(resizeHandler) 4879 } 4880 }) 4881 } 4882 4883 /* Private */ 4884 Context.prototype.createThrottledScrollHandler = function() { 4885 var self = this 4886 function scrollHandler() { 4887 self.handleScroll() 4888 self.didScroll = false 4889 } 4890 4891 this.adapter.on('scroll.waypoints', function() { 4892 if (!self.didScroll || Waypoint.isTouch) { 4893 self.didScroll = true 4894 Waypoint.requestAnimationFrame(scrollHandler) 4895 } 4896 }) 4897 } 4898 4899 /* Private */ 4900 Context.prototype.handleResize = function() { 4901 Waypoint.Context.refreshAll() 4902 } 4903 4904 /* Private */ 4905 Context.prototype.handleScroll = function() { 4906 var triggeredGroups = {} 4907 var axes = { 4908 horizontal: { 4909 newScroll: this.adapter.scrollLeft(), 4910 oldScroll: this.oldScroll.x, 4911 forward: 'right', 4912 backward: 'left' 4913 }, 4914 vertical: { 4915 newScroll: this.adapter.scrollTop(), 4916 oldScroll: this.oldScroll.y, 4917 forward: 'down', 4918 backward: 'up' 4919 } 4920 } 4921 4922 for (var axisKey in axes) { 4923 var axis = axes[axisKey] 4924 var isForward = axis.newScroll > axis.oldScroll 4925 var direction = isForward ? axis.forward : axis.backward 4926
4927 for (var waypointKey in this.waypoints[axisKey]) { 4928 var waypoint = this.waypoints[axisKey][waypointKey] 4929 if (waypoint.triggerPoint === null) { 4930 continue 4931 } 4932 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 4933 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 4934 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 4935 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 4936 if (crossedForward || crossedBackward) { 4937 waypoint.queueTrigger(direction) 4938 triggeredGroups[waypoint.group.id] = waypoint.group 4939 } 4940 } 4941 } 4942 4943 for (var groupKey in triggeredGroups) { 4944 triggeredGroups[groupKey].flushTriggers() 4945 } 4946 4947 this.oldScroll = { 4948 x: axes.horizontal.newScroll, 4949 y: axes.vertical.newScroll 4950 } 4951 } 4952 4953 /* Private */ 4954 Context.prototype.innerHeight = function() { 4955 /*eslint-disable eqeqeq */ 4956 if (this.element == this.element.window) { 4957 return Waypoint.viewportHeight() 4958 } 4959 /*eslint-enable eqeqeq */ 4960 return this.adapter.innerHeight() 4961 } 4962 4963 /* Private */ 4964 Context.prototype.remove = function(waypoint) { 4965 delete this.waypoints[waypoint.axis][waypoint.key] 4966 this.checkEmpty() 4967 } 4968 4969 /* Private */ 4970 Context.prototype.innerWidth = function() { 4971 /*eslint-disable eqeqeq */ 4972 if (this.element == this.element.window) { 4973 return Waypoint.viewportWidth() 4974 } 4975 /*eslint-enable eqeqeq */ 4976 return this.adapter.innerWidth() 4977 } 4978 4979 /* Public */ 4980 /* http://imakewebthings.com/waypoints/api/context-destroy */ 4981 Context.prototype.destroy = function() { 4982 var allWaypoints = [] 4983 for (var axis in this.waypoints) {
4984 for (var waypointKey in this.waypoints[axis]) { 4985 allWaypoints.push(this.waypoints[axis][waypointKey]) 4986 } 4987 } 4988 for (var i = 0, end = allWaypoints.length; i < end; i++) { 4989 allWaypoints[i].destroy() 4990 } 4991 } 4992 4993 /* Public */ 4994 /* http://imakewebthings.com/waypoints/api/context-refresh */ 4995 Context.prototype.refresh = function() { 4996 /*eslint-disable eqeqeq */ 4997 var isWindow = this.element == this.element.window 4998 /*eslint-enable eqeqeq */ 4999 var contextOffset = isWindow ? undefined : this.adapter.offset() 5000 var triggeredGroups = {} 5001 var axes 5002 5003 this.handleScroll() 5004 axes = { 5005 horizontal: { 5006 contextOffset: isWindow ? 0 : contextOffset.left, 5007 contextScroll: isWindow ? 0 : this.oldScroll.x, 5008 contextDimension: this.innerWidth(), 5009 oldScroll: this.oldScroll.x, 5010 forward: 'right', 5011 backward: 'left', 5012 offsetProp: 'left' 5013 }, 5014 vertical: { 5015 contextOffset: isWindow ? 0 : contextOffset.top, 5016 contextScroll: isWindow ? 0 : this.oldScroll.y, 5017 contextDimension: this.innerHeight(), 5018 oldScroll: this.oldScroll.y, 5019 forward: 'down', 5020 backward: 'up', 5021 offsetProp: 'top' 5022 } 5023 } 5024 5025 for (var axisKey in axes) { 5026 var axis = axes[axisKey]
5027 for (var waypointKey in this.waypoints[axisKey]) { 5028 var waypoint = this.waypoints[axisKey][waypointKey] 5029 var adjustment = waypoint.options.offset 5030 var oldTriggerPoint = waypoint.triggerPoint 5031 var elementOffset = 0 5032 var freshWaypoint = oldTriggerPoint == null 5033 var contextModifier, wasBeforeScroll, nowAfterScroll 5034 var triggeredBackward, triggeredForward 5035 5036 if (waypoint.element !== waypoint.element.window) { 5037 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 5038 } 5039 5040 if (typeof adjustment === 'function') { 5041 adjustment = adjustment.apply(waypoint) 5042 } 5043 else if (typeof adjustment === 'string') { 5044 adjustment = parseFloat(adjustment) 5045 if (waypoint.options.offset.indexOf('%') > - 1) { 5046 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 5047 } 5048 } 5049 5050 contextModifier = axis.contextScroll - axis.contextOffset 5051 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 5052 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 5053 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 5054 triggeredBackward = wasBeforeScroll && nowAfterScroll 5055 triggeredForward = !wasBeforeScroll && !nowAfterScroll 5056 5057 if (!freshWaypoint && triggeredBackward) { 5058 waypoint.queueTrigger(axis.backward) 5059 triggeredGroups[waypoint.group.id] = waypoint.group 5060 } 5061 else if (!freshWaypoint && triggeredForward) { 5062 waypoint.queueTrigger(axis.forward) 5063 triggeredGroups[waypoint.group.id] = waypoint.group 5064 } 5065 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 5066 waypoint.queueTrigger(axis.forward) 5067 triggeredGroups[waypoint.group.id] = waypoint.group 5068 } 5069 } 5070 } 5071 5072 Waypoint.requestAnimationFrame(function() { 5073 for (var groupKey in triggeredGroups) { 5074 triggeredGroups[groupKey].flushTriggers() 5075 } 5076 }) 5077 5078 return this 5079 } 5080 5081 /* Private */ 5082 Context.findOrCreateByElement = function(element) { 5083 return Context.findByElement(element) || new Context(element) 5084 } 5085 5086 /* Private */ 5087 Context.refreshAll = function() { 5088 for (var contextId in contexts) { 5089 contexts[contextId].refresh() 5090 } 5091 } 5092 5093 /* Public */ 5094 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 5095 Context.findByElement = function(element) { 5096 return contexts[element.waypointContextKey] 5097 } 5098 5099 window.onload = function() { 5100 if (oldWindowLoad) { 5101 oldWindowLoad() 5102 } 5103 Context.refreshAll() 5104 } 5105 5106 5107 Waypoint.requestAnimationFrame = function(callback) { 5108 var requestFn = window.requestAnimationFrame || 5109 window.mozRequestAnimationFrame || 5110 window.webkitRequestAnimationFrame || 5111 requestAnimationFrameShim 5112 requestFn.call(window, callback) 5113 } 5114 Waypoint.Context = Context 5115}()) 5116;(function() { 5117 'use strict' 5118 5119 function byTriggerPoint(a, b) { 5120 return a.triggerPoint - b.triggerPoint 5121 } 5122 5123 function byReverseTriggerPoint(a, b) { 5124 return b.triggerPoint - a.triggerPoint 5125 } 5126 5127 var groups = { 5128 vertical: {}, 5129 horizontal: {} 5130 } 5131 var Waypoint = window.Waypoint 5132 5133 /* http://imakewebthings.com/waypoints/api/group */ 5134 function Group(options) { 5135 this.name = options.name 5136 this.axis = options.axis 5137 this.id = this.name + '-' + this.axis 5138 this.waypoints = [] 5139 this.clearTriggerQueues() 5140 groups[this.axis][this.name] = this 5141 } 5142 5143 /* Private */ 5144 Group.prototype.add = function(waypoint) { 5145 this.waypoints.push(waypoint) 5146 } 5147 5148 /* Private */ 5149 Group.prototype.clearTriggerQueues = function() { 5150 this.triggerQueues = { 5151 up: [], 5152 down: [], 5153 left: [], 5154 right: [] 5155 } 5156 } 5157 5158 /* Private */ 5159 Group.prototype.flushTriggers = function() { 5160 for (var direction in this.triggerQueues) { 5161 var waypoints = this.triggerQueues[direction] 5162 var reverse = direction === 'up' || direction === 'left' 5163 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 5164 for (var i = 0, end = waypoints.length; i < end; i += 1) { 5165 var waypoint = waypoints[i] 5166 if (waypoint.options.continuous || i === waypoints.length - 1) { 5167 waypoint.trigger([direction]) 5168 } 5169 } 5170 } 5171 this.clearTriggerQueues() 5172 } 5173 5174 /* Private */ 5175 Group.prototype.next = function(waypoint) { 5176 this.waypoints.sort(byTriggerPoint) 5177 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5178 var isLast = index === this.waypoints.length - 1 5179 return isLast ? null : this.waypoints[index + 1] 5180 } 5181 5182 /* Private */ 5183 Group.prototype.previous = function(waypoint) { 5184 this.waypoints.sort(byTriggerPoint) 5185 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5186 return index ? this.waypoints[index - 1] : null 5187 } 5188 5189 /* Private */ 5190 Group.prototype.queueTrigger = function(waypoint, direction) { 5191 this.triggerQueues[direction].push(waypoint) 5192 } 5193 5194 /* Private */ 5195 Group.prototype.remove = function(waypoint) { 5196 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5197 if (index > -1) { 5198 this.waypoints.splice(index, 1) 5199 } 5200 } 5201 5202 /* Public */ 5203 /* http://imakewebthings.com/waypoints/api/first */ 5204 Group.prototype.first = function() { 5205 return this.waypoints[0] 5206 } 5207 5208 /* Public */ 5209 /* http://imakewebthings.com/waypoints/api/last */ 5210 Group.prototype.last = function() { 5211 return this.waypoints[this.waypoints.length - 1] 5212 } 5213 5214 /* Private */ 5215 Group.findOrCreate = function(options) { 5216 return groups[options.axis][options.name] || new Group(options) 5217 } 5218 5219 Waypoint.Group = Group 5220}()) 5221;(function() { 5222 'use strict' 5223 5224 var $ = window.jQuery 5225 var Waypoint = window.Waypoint 5226 5227 function JQueryAdapter(element) { 5228 this.$element = $(element) 5229 } 5230 5231 $.each([
5232 'innerHeight', 5233 'innerWidth', 5234 'off', 5235 'offset', 5236 'on', 5237 'outerHeight', 5238 'outerWidth', 5239 'scrollLeft', 5240 'scrollTop' 5241 ], function(i, method) { 5242 JQueryAdapter.prototype[method] = function() { 5243 var args = Array.prototype.slice.call(arguments) 5244 return this.$element[method].apply(this.$element, args) 5245 } 5246 }) 5247 5248 $.each([ 5249 'extend', 5250 'inArray', 5251 'isEmptyObject' 5252 ], function(i, method) { 5253 JQueryAdapter[method] = $[method] 5254 }) 5255 5256 Waypoint.adapters.push({ 5257 name: 'jquery', 5258 Adapter: JQueryAdapter 5259 }) 5260 Waypoint.Adapter = JQueryAdapter 5261}()) 5262;(function() { 5263 'use strict' 5264 5265 var Waypoint = window.Waypoint 5266 5267 function createExtension(framework) { 5268 return function() { 5269 var waypoints = [] 5270 var overrides = arguments[0] 5271 5272 if (framework.isFunction(arguments[0])) { 5273 overrides = framework.extend({}, arguments[1]) 5274 overrides.handler = arguments[0] 5275 } 5276 5277 this.each(function() { 5278 var options = framework.extend({}, overrides, { 5279 element: this 5280 }) 5281 if (typeof options.context === 'string') { 5282 options.context = framework(this).closest(options.context)[0] 5283 } 5284 waypoints.push(new Waypoint(options)) 5285 }) 5286 5287 return waypoints 5288 } 5289 } 5290 5291 if (window.jQuery) { 5292 window.jQuery.fn.waypoint = createExtension(window.jQuery) 5293 } 5294 if (window.Zepto) { 5295 window.Zepto.fn.waypoint = createExtension(window.Zepto) 5296 } 5297}()) 5298; 5299 5300/*! 5301Waypoints Inview Shortcut - 4.0.1 5302Copyright © 2011-2016 Caleb Troughton 5303Licensed under the MIT license. 5304https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 5305*/ 5306(function() { 5307 'use strict' 5308 5309 function noop() {} 5310 5311 var Waypoint = window.Waypoint 5312 5313 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 5314 function Inview(options) { 5315 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 5316 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 5317 this.waypoints = [] 5318 this.element = this.options.element 5319 this.createWaypoints() 5320 } 5321 5322 /* Private */ 5323 Inview.prototype.createWaypoints = function() { 5324 var configs = { 5325 vertical: [{ 5326 down: 'enter', 5327 up: 'exited', 5328 offset: '100%' 5329 }, { 5330 down: 'entered', 5331 up: 'exit', 5332 offset: 'bottom-in-view' 5333 }, { 5334 down: 'exit', 5335 up: 'entered', 5336 offset: 0 5337 }, { 5338 down: 'exited', 5339 up: 'enter', 5340 offset: function() { 5341 return -this.adapter.outerHeight() 5342 } 5343 }], 5344 horizontal: [{ 5345 right: 'enter', 5346 left: 'exited', 5347 offset: '100%' 5348 }, { 5349 right: 'entered', 5350 left: 'exit', 5351 offset: 'right-in-view' 5352 }, { 5353 right: 'exit', 5354 left: 'entered', 5355 offset: 0 5356 }, { 5357 right: 'exited', 5358 left: 'enter', 5359 offset: function() { 5360 return -this.adapter.outerWidth() 5361 } 5362 }] 5363 } 5364 5365 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 5366 var config = configs[this.axis][i] 5367 this.createWaypoint(config) 5368 } 5369 } 5370 5371 /* Private */ 5372 Inview.prototype.createWaypoint = function(config) { 5373 var self = this 5374 this.waypoints.push(new Waypoint({ 5375 context: this.options.context, 5376 element: this.options.element, 5377 enabled: this.options.enabled, 5378 handler: (function(config) { 5379 return function(direction) { 5380 self.options[config[direction]].call(self, direction) 5381 } 5382 }(config)), 5383 offset: config.offset, 5384 horizontal: this.options.horizontal 5385 })) 5386 } 5387 5388 /* Public */ 5389 Inview.prototype.destroy = function() { 5390 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5391 this.waypoints[i].destroy() 5392 } 5393 this.waypoints = [] 5394 } 5395 5396 Inview.prototype.disable = function() { 5397 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5398 this.waypoints[i].disable() 5399 } 5400 } 5401 5402 Inview.prototype.enable = function() { 5403 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5404 this.waypoints[i].enable() 5405 } 5406 } 5407 5408 Inview.defaults = { 5409 context: window, 5410 enabled: true, 5411 enter: noop, 5412 entered: noop,
5413 exit: noop, 5414 exited: noop 5415 } 5416 5417 Waypoint.Inview = Inview 5418}()) 5419; 5420 5421/* 5422 * SmartMenus jQuery v0.9.6 5423 * http://www.smartmenus.org/ 5424 * 5425 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 5426 * http://vadikom.com/ 5427 * 5428 * Released under the MIT license: 5429 * http://www.opensource.org/licenses/MIT 5430 */ 5431 5432(function($) { 5433 5434 var menuTrees = [], 5435 IE = !!window.createPopup, // we need to detect it, unfortunately 5436 IElt9 = IE && !document.defaultView, 5437 IElt8 = IE && !document.querySelector, 5438 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 5439 mouse = false, // optimize for touch by default - we will detect for mouse input 5440 mouseDetectionEnabled = false; 5441 5442 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 5443 function initMouseDetection(disable) { 5444 if (!mouseDetectionEnabled && !disable) { 5445 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 5446 // 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) 5447 var firstTime = true, 5448 lastMove = null; 5449 $(document).bind({ 5450 'mousemove.smartmenus_mouse': function(e) { 5451 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 5452 if (lastMove) { 5453 var deltaX = Math.abs(lastMove.x - thisMove.x), 5454 deltaY = Math.abs(lastMove.y - thisMove.y); 5455 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 5456 mouse = true; 5457 // 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 5458 if (firstTime) { 5459 var $a = $(e.target).closest('a'); 5460 if ($a.is('a')) { 5461 $.each(menuTrees, function() { 5462 if ($.contains(this.$root[0], $a[0])) { 5463 this.itemEnter({ currentTarget: $a[0] }); 5464 return false; 5465 } 5466 }); 5467 } 5468 firstTime = false; 5469 } 5470 } 5471 } 5472 lastMove = thisMove; 5473 }, 5474 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 5475 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 5476 mouse = false; 5477 } 5478 } 5479 }); 5480 mouseDetectionEnabled = true; 5481 } else if (mouseDetectionEnabled && disable) { 5482 $(document).unbind('.smartmenus_mouse'); 5483 mouseDetectionEnabled = false; 5484 } 5485 }; 5486 5487 $.SmartMenus = function(elm, options) { 5488 this.$root = $(elm); 5489 this.opts = options; 5490 this.rootId = ''; // internal 5491 this.$subArrow = null; 5492 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) 5493 this.activatedItems = []; // stores last activated A's for each level 5494 this.visibleSubMenus = []; // stores visible sub menus UL's 5495 this.showTimeout = 0; 5496 this.hideTimeout = 0; 5497 this.scrollTimeout = 0; 5498 this.clickActivated = false; 5499 this.zIndexInc = 0; 5500 this.$firstLink = null; // we'll use these for some tests 5501 this.$firstSub = null; // at runtime so we'll cache them 5502 this.disabled = false; 5503 this.$disableOverlay = null; 5504 this.init(); 5505 }; 5506 5507 $.extend($.SmartMenus, { 5508 hideAll: function() { 5509 $.each(menuTrees, function() { 5510 this.menuHideAll(); 5511 }); 5512 }, 5513 destroy: function() { 5514 while (menuTrees.length) { 5515 menuTrees[0].destroy(); 5516 } 5517 initMouseDetection(true); 5518 }, 5519 prototype: { 5520 init: function(refresh) { 5521 var self = this; 5522 5523 if (!refresh) { 5524 menuTrees.push(this); 5525 5526 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 5527 5528 if (this.$root.hasClass('sm-rtl')) { 5529 this.opts.rightToLeftSubMenus = true; 5530 } 5531 5532 // init root (main menu) 5533 this.$root 5534 .data('smartmenus', this) 5535 .attr('data-smartmenus-id', this.rootId) 5536 .dataSM('level', 1) 5537 .bind({ 5538 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
5539 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 5540 }) 5541 .delegate('a', { 5542 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 5543 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 5544 'mousedown.smartmenus': $.proxy(this.itemDown, this), 5545 'focus.smartmenus': $.proxy(this.itemFocus, this), 5546 'blur.smartmenus': $.proxy(this.itemBlur, this), 5547 'click.smartmenus': $.proxy(this.itemClick, this), 5548 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 5549 }); 5550 5551 var eNamespace = '.smartmenus' + this.rootId; 5552 // hide menus on tap or click outside the root UL 5553 if (this.opts.hideOnClick) { 5554 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 5555 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 5556 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 5557 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 5558 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 5559 } 5560 // hide sub menus on resize 5561 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5562 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5563 5564 if (this.opts.subIndicators) { 5565 this.$subArrow = $('<span/>').addClass('sub-arrow'); 5566 if (this.opts.subIndicatorsText) { 5567 this.$subArrow.html(this.opts.subIndicatorsText); 5568 } 5569 } 5570 5571 // make sure mouse detection is enabled 5572 initMouseDetection(); 5573 } 5574 5575 // init sub menus 5576 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 5577 5578 this.$firstLink = this.$root.find('a').eq(0); 5579 5580 // find current item 5581 if (this.opts.markCurrentItem) { 5582 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 5583 reHash = /#.*/, 5584 locHref = window.location.href.replace(reDefaultDoc, ''), 5585 locHrefNoHash = locHref.replace(reHash, ''); 5586 this.$root.find('a').each(function() { 5587 var href = this.href.replace(reDefaultDoc, ''), 5588 $this = $(this); 5589 if (href == locHref || href == locHrefNoHash) { 5590 $this.addClass('current'); 5591 if (self.opts.markCurrentTree) { 5592 $this.parents('li').each(function() { 5593 var $this = $(this); 5594 if ($this.dataSM('sub')) { 5595 $this.children('a').addClass('current'); 5596 } 5597 }); 5598 } 5599 } 5600 }); 5601 } 5602 }, 5603 destroy: function() { 5604 this.menuHideAll(); 5605 this.$root 5606 .removeData('smartmenus') 5607 .removeAttr('data-smartmenus-id') 5608 .removeDataSM('level') 5609 .unbind('.smartmenus') 5610 .undelegate('.smartmenus'); 5611 var eNamespace = '.smartmenus' + this.rootId; 5612 $(document).unbind(eNamespace); 5613 $(window).unbind(eNamespace); 5614 if (this.opts.subIndicators) { 5615 this.$subArrow = null; 5616 } 5617 var self = this; 5618 $.each(this.subMenus, function() { 5619 if (this.hasClass('mega-menu')) { 5620 this.find('ul').removeDataSM('in-mega'); 5621 } 5622 if (this.dataSM('shown-before')) { 5623 if (IElt8) { 5624 this.children().css({ styleFloat: '', width: '' }); 5625 } 5626 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 5627 if (!IE6) { 5628 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 5629 } else { 5630 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 5631 } 5632 } 5633 if (this.dataSM('scroll-arrows')) { 5634 this.dataSM('scroll-arrows').remove(); 5635 } 5636 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 5637 } 5638 if (self.opts.subIndicators) { 5639 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 5640 } 5641 this.removeDataSM('shown-before') 5642 .removeDataSM('ie-shim') 5643 .removeDataSM('scroll-arrows') 5644 .removeDataSM('parent-a') 5645 .removeDataSM('level') 5646 .removeDataSM('beforefirstshowfired') 5647 .parent().removeDataSM('sub'); 5648 }); 5649 if (this.opts.markCurrentItem) { 5650 this.$root.find('a.current').removeClass('current'); 5651 } 5652 this.$root = null; 5653 this.$firstLink = null; 5654 this.$firstSub = null; 5655 if (this.$disableOverlay) { 5656 this.$disableOverlay.remove(); 5657 this.$disableOverlay = null; 5658 } 5659 menuTrees.splice($.inArray(this, menuTrees), 1); 5660 }, 5661 disable: function(noOverlay) { 5662 if (!this.disabled) { 5663 this.menuHideAll(); 5664 // display overlay over the menu to prevent interaction 5665 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 5666 var pos = this.$root.offset(); 5667 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 5668 position: 'absolute', 5669 top: pos.top, 5670 left: pos.left, 5671 width: this.$root.outerWidth(), 5672 height: this.$root.outerHeight(),
5673 zIndex: this.getStartZIndex() + 1, 5674 opacity: 0 5675 }).appendTo(document.body); 5676 } 5677 this.disabled = true; 5678 } 5679 }, 5680 docClick: function(e) { 5681 // hide on any click outside the menu or on a menu link 5682 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 5683 this.menuHideAll($(e.target)); 5684 } 5685 }, 5686 docTouchEnd: function(e) { 5687 if (!this.lastTouch) { 5688 return; 5689 } 5690 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))) { 5691 if (this.hideTimeout) { 5692 clearTimeout(this.hideTimeout); 5693 this.hideTimeout = 0; 5694 } 5695 // hide with a delay to prevent triggering accidental unwanted click on some page element 5696 var self = this; 5697 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 5698 } 5699 this.lastTouch = null; 5700 }, 5701 docTouchMove: function(e) { 5702 if (!this.lastTouch) { 5703 return; 5704 } 5705 var touchPoint = e.originalEvent.touches[0]; 5706 this.lastTouch.x2 = touchPoint.pageX; 5707 this.lastTouch.y2 = touchPoint.pageY; 5708 }, 5709 docTouchStart: function(e) { 5710 var touchPoint = e.originalEvent.touches[0]; 5711 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 5712 }, 5713 enable: function() { 5714 if (this.disabled) { 5715 if (this.$disableOverlay) { 5716 this.$disableOverlay.remove(); 5717 this.$disableOverlay = null; 5718 } 5719 this.disabled = false; 5720 } 5721 }, 5722 getHeight: function($elm) { 5723 return this.getOffset($elm, true); 5724 }, 5725 // returns precise width/height float values in IE9+, FF4+, recent WebKit 5726 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 5727 getOffset: function($elm, height) { 5728 var old; 5729 if ($elm.css('display') == 'none') { 5730 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 5731 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 5732 } 5733 var defaultView = $elm[0].ownerDocument.defaultView, 5734 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 5735 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 5736 if (val) { 5737 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 5738 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 5739 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 5740 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 5741 } else { 5742 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 5743 } 5744 if (old) { 5745 $elm.hide().css(old); 5746 } 5747 return val; 5748 }, 5749 getWidth: function($elm) { 5750 return this.getOffset($elm); 5751 }, 5752 getStartZIndex: function() { 5753 var zIndex = parseInt(this.$root.css('z-index')); 5754 return !isNaN(zIndex) ? zIndex : 1; 5755 }, 5756 handleEvents: function() { 5757 return !this.disabled && this.isCSSOn(); 5758 }, 5759 handleItemEvents: function($a) { 5760 return this.handleEvents() && !this.isLinkInMegaMenu($a); 5761 }, 5762 isCollapsible: function() { 5763 return this.$firstSub.css('position') == 'static'; 5764 }, 5765 isCSSOn: function() { 5766 return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'inline'; 5767 }, 5768 isFixed: function() { 5769 return this.$root.css('position') == 'fixed'; 5770 }, 5771 isLinkInMegaMenu: function($a) { 5772 return !$a.parent().parent().dataSM('level'); 5773 }, 5774 isTouchMode: function() { 5775 return !mouse || this.isCollapsible(); 5776 }, 5777 itemActivate: function($a) { 5778 var $li = $a.parent(), 5779 $ul = $li.parent(), 5780 level = $ul.dataSM('level'); 5781 // 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 5782 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 5783 var self = this; 5784 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 5785 self.itemActivate($(this).dataSM('parent-a')); 5786 }); 5787 } 5788 // hide any visible deeper level sub menus 5789 if (this.visibleSubMenus.length > level) { 5790 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--) { 5791 this.menuHide(this.visibleSubMenus[i]); 5792 } 5793 } 5794 // save new active item and sub menu for this level 5795 this.activatedItems[level - 1] = $a; 5796 this.visibleSubMenus[level - 1] = $ul; 5797 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 5798 return; 5799 } 5800 // show the sub menu if this item has one 5801 var $sub = $li.dataSM('sub'); 5802 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 5803 this.menuShow($sub); 5804 } 5805 }, 5806 itemBlur: function(e) { 5807 var $a = $(e.currentTarget); 5808 if (!this.handleItemEvents($a)) { 5809 return; 5810 } 5811 this.$root.triggerHandler('blur.smapi', $a[0]); 5812 }, 5813 itemClick: function(e) { 5814 var $a = $(e.currentTarget); 5815 5816 if (!this.handleItemEvents($a)) { 5817 return; 5818 } 5819 $a.removeDataSM('mousedown'); 5820 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 5821 return false;
5822 } 5823 var $sub = $a.parent().dataSM('sub'); 5824 if (this.isTouchMode()) { 5825 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 5826 if ($a.dataSM('href')) { 5827 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 5828 } 5829 // if the sub is not visible 5830 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5831 // try to activate the item and show the sub 5832 this.itemActivate($a); 5833 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 5834 // 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 5835 if ($sub.is(':visible')) { 5836 return false; 5837 } 5838 } 5839 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 5840 this.clickActivated = true; 5841 this.menuShow($sub); 5842 return false; 5843 } 5844 if ($a.hasClass('disabled')) { 5845 return false; 5846 } 5847 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 5848 return false; 5849 } 5850 }, 5851 itemDown: function(e) { 5852 var $a = $(e.currentTarget); 5853 if (!this.handleItemEvents($a)) { 5854 return; 5855 } 5856 $a.dataSM('mousedown', true); 5857 }, 5858 itemEnter: function(e) { 5859 var $a = $(e.currentTarget); 5860 if (!this.handleItemEvents($a)) { 5861 return; 5862 } 5863 if (!this.isTouchMode()) { 5864 if (this.showTimeout) { 5865 clearTimeout(this.showTimeout); 5866 this.showTimeout = 0; 5867 } 5868 var self = this; 5869 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 5870 } 5871 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 5872 }, 5873 itemFocus: function(e) { 5874 var $a = $(e.currentTarget); 5875 if (!this.handleItemEvents($a)) { 5876 return; 5877 } 5878 // 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 5879 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 5880 this.itemActivate($a); 5881 } 5882 this.$root.triggerHandler('focus.smapi', $a[0]); 5883 }, 5884 itemLeave: function(e) { 5885 var $a = $(e.currentTarget); 5886 if (!this.handleItemEvents($a)) { 5887 return; 5888 } 5889 if (!this.isTouchMode()) { 5890 if ($a[0].blur) { 5891 $a[0].blur(); 5892 } 5893 if (this.showTimeout) { 5894 clearTimeout(this.showTimeout); 5895 this.showTimeout = 0; 5896 } 5897 } 5898 $a.removeDataSM('mousedown'); 5899 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 5900 }, 5901 itemTouchEnd: function(e) { 5902 var $a = $(e.currentTarget); 5903 if (!this.handleItemEvents($a)) { 5904 return; 5905 } 5906 // prevent the address bar on iPhone from sliding down when expanding a sub menu 5907 var $sub = $a.parent().dataSM('sub'); 5908 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5909 $a.dataSM('href', $a.attr('href')); 5910 $a.attr('href', '#'); 5911 } 5912 }, 5913 menuFixLayout: function($ul) { 5914 // fixes a menu that is being shown for the first time 5915 if (!$ul.dataSM('shown-before')) { 5916 $ul.hide().dataSM('shown-before', true); 5917 // fix the layout of the items in IE<8 5918 if (IElt8) { 5919 $ul.children().css({ styleFloat: 'left', width: '100%' }); 5920 } 5921 } 5922 }, 5923 menuHide: function($sub) { 5924 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 5925 return; 5926 } 5927 $sub.stop(true, true); 5928 if ($sub.is(':visible')) { 5929 var complete = function() { 5930 // unset z-index 5931 if (IElt9) { 5932 $sub.parent().css('z-index', ''); 5933 } else { 5934 $sub.css('z-index', ''); 5935 } 5936 }; 5937 // if sub is collapsible (mobile view) 5938 if (this.isCollapsible()) { 5939 if (this.opts.collapsibleHideFunction) { 5940 this.opts.collapsibleHideFunction.call(this, $sub, complete); 5941 } else { 5942 $sub.hide(this.opts.collapsibleHideDuration, complete); 5943 } 5944 } else { 5945 if (this.opts.hideFunction) { 5946 this.opts.hideFunction.call(this, $sub, complete); 5947 } else { 5948 $sub.hide(this.opts.hideDuration, complete); 5949 } 5950 } 5951 // remove IE iframe shim 5952 if ($sub.dataSM('ie-shim')) { 5953 $sub.dataSM('ie-shim').remove(); 5954 } 5955 // deactivate scrolling if it is activated for this sub 5956 if ($sub.dataSM('scroll')) { 5957 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 5958 } 5959 // unhighlight parent item 5960 $sub.dataSM('parent-a').removeClass('highlighted'); 5961 var level = $sub.dataSM('level'); 5962 this.activatedItems.splice(level - 1, 1); 5963 this.visibleSubMenus.splice(level - 1, 1); 5964 this.$root.triggerHandler('hide.smapi', $sub[0]); 5965 } 5966 }, 5967 menuHideAll: function($item) { 5968 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 5969 if (this.showTimeout) { 5970 clearTimeout(this.showTimeout); 5971 this.showTimeout = 0; 5972 } 5973 // hide all subs 5974 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 5975 this.menuHide(this.visibleSubMenus[i]); 5976 } 5977 // hide root if it's popup 5978 if (this.opts.isPopup) { 5979 this.$root.stop(true, true); 5980 if (this.$root.is(':visible')) { 5981 if (this.opts.hideFunction) { 5982 this.opts.hideFunction.call(this, this.$root); 5983 } else { 5984 this.$root.hide(this.opts.hideDuration); 5985 } 5986 // remove IE iframe shim 5987 if (this.$root.dataSM('ie-shim')) { 5988 this.$root.dataSM('ie-shim').remove(); 5989 } 5990 } 5991 } 5992 this.activatedItems = []; 5993 this.visibleSubMenus = []; 5994 this.clickActivated = false;
5995 // reset z-index increment 5996 this.zIndexInc = 0; 5997 }, 5998 menuIframeShim: function($ul) { 5999 // create iframe shim for the menu 6000 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 6001 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 6002 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 6003 ); 6004 } 6005 }, 6006 menuInit: function($ul) { 6007 if (!$ul.dataSM('in-mega')) { 6008 this.subMenus.push($ul); 6009 // mark UL's in mega drop downs (if any) so we can neglect them 6010 if ($ul.hasClass('mega-menu')) { 6011 $ul.find('ul').dataSM('in-mega', true); 6012 } 6013 // get level (much faster than, for example, using parentsUntil) 6014 var level = 2, 6015 par = $ul[0]; 6016 while ((par = par.parentNode.parentNode) != this.$root[0]) { 6017 level++; 6018 } 6019 // cache stuff 6020 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 6021 .dataSM('level', level) 6022 .parent().dataSM('sub', $ul); 6023 // add sub indicator to parent item 6024 if (this.opts.subIndicators) { 6025 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 6026 } 6027 } 6028 }, 6029 menuPosition: function($sub) { 6030 var fixIE = $('html.ie').length; 6031 // if (fixIE) { 6032 // var $rowParent = $($sub).closest('.main-menu-container'); 6033 // $rowParent.height($rowParent.height()); 6034 // } 6035 var $a = $sub.dataSM('parent-a'), 6036 $li = $sub.parent(), 6037 $ul = $sub.parent().parent(), 6038 $container = $ul.closest('.row-menu-inner'), 6039 level = $sub.dataSM('level'), 6040 subW = this.getWidth($sub), 6041 subH = this.getHeight($sub), 6042 itemOffset = $a.offset(), 6043 itemX = itemOffset.left, 6044 itemY = itemOffset.top, 6045 itemW = this.getWidth($a), 6046 itemH = this.getHeight($a), 6047 $win = $(window), 6048 winX = $win.scrollLeft(), 6049 winY = $win.scrollTop(), 6050 winW = $win.width(), 6051 winH = $win.height(), 6052 containerW = $container.width(), 6053 containerOffsetX = containerW + ((winW - containerW) / 2), 6054 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 6055 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 6056 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 6057 x, y, leftPos; 6058 if (horizontalParent) { 6059 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 6060 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 6061 } else { 6062 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX; 6063 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 6064 } 6065 if (this.opts.keepInViewport && !this.isCollapsible()) { 6066 if (this.isFixed()) { 6067 itemX -= winX; 6068 itemY -= winY; 6069 winX = winY = 0; 6070 } 6071 var absX = itemX + x, 6072 absY = itemY + y; 6073 if (this.opts.rightToLeftSubMenus && absX < winX) { 6074 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 6075 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 6076 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 6077 } 6078 if (!horizontalParent) { 6079 if (subH < winH && absY + subH > winY + winH) { 6080 y += winY + winH - subH - absY; 6081 } else if (subH >= winH || absY < winY) { 6082 y += winY - absY; 6083 } 6084 } 6085 // do we need scrolling? 6086 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 6087 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 6088 var self = this; 6089 if (!$sub.dataSM('scroll-arrows')) { 6090 $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]]) 6091 .bind({ 6092 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 6093 mouseleave: function(e) { 6094 self.menuScrollStop($sub); 6095 self.menuScrollOut($sub, e); 6096 }, 6097 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 6098 }) 6099 .insertAfter($sub) 6100 ); 6101 } 6102 // bind events to show/hide arrows on hover and save scrolling data for this sub 6103 var vportY = winY - (itemY + itemH); 6104 $sub.dataSM('scroll', { 6105 vportY: vportY, 6106 subH: subH, 6107 winH: winH, 6108 step: 1 6109 }) 6110 .bind({ 6111 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 6112 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 6113 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 6114 }) 6115 .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
6115StartZIndex() + this.zIndexInc }) 6116 .eq(0).css('margin-top', vportY).end() 6117 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 6118 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 6119 } 6120 } 6121 // if ($sub.hasClass('mega-menu-inner')) { 6122 // if ($('.menu-wrapper .megamenu-diff').length > 0) { 6123 // leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth()); 6124 // leftPos = -leftPos; 6125 // } else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft')); 6126 6127 // if ($('body.header-full-width').length > 0) { 6128 // $sub.css({ width: $('.box-container').width()}); 6129 // leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft'))); 6130 // } else $sub.css({ width: containerW}); 6131 // leftPos = leftPos + 'px'; 6132 6133 // } else { 6134 // leftPos = $li.position().left + 'px'; 6135 // } 6136 if ($sub.hasClass('mega-menu-inner')) { 6137 $sub.css({ width: containerW}); 6138 if ($('body.hmenu-center-split').length > 0 && !$sub.closest('.navbar-cta').length ) { 6139 leftPos = - ($sub.closest('.menu-primary-inner')[0].offsetLeft) + 'px'; 6140 } else { 6141 if ( $sub.closest('.navbar-cta').length && !$('body.hmenu').length && !$('body.hmenu-center').length ) { 6142 leftPos = - ( parseFloat($sub.closest('.navbar-cta').offset().left) - parseFloat($sub.closest('.row-menu-inner').find('.logo-container').offset().left) ) + 'px'; 6143 } else if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0 && !$('body.hmenu-center-split').length) { 6144 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 6145 } else { 6146 leftPos = '0px'; 6147 } 6148 } 6149 } else { 6150 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 6151 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 6152 } 6153 6154 $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) }); 6155 // IE iframe shim 6156 this.menuIframeShim($sub); 6157 if ($sub.dataSM('ie-shim')) { 6158 $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) }); 6159 } 6160 }, 6161 menuScroll: function($sub, up, wheel) { 6162 var y = parseFloat($sub.css('margin-top')), 6163 scroll = $sub.dataSM('scroll'), 6164 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 6165 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 6166 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 6167 y = parseFloat($sub.css('margin-top')); 6168 // show opposite arrow if appropriate 6169 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 6170 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 6171 } 6172 // accelerate when not using mousewheel to scroll 6173 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 6174 $sub.dataSM('scroll').step += 0.5; 6175 } 6176 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 6177 if (Math.abs(y - end) < 1) { 6178 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 6179 $sub.dataSM('scroll').step = 1; 6180 } else if (!wheel) { 6181 var self = this; 6182 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 6183 } 6184 }, 6185 menuScrollMousewheel: function($sub, e) { 6186 var $closestSub = $(e.target).closest('ul'); 6187 while ($closestSub.dataSM('in-mega')) { 6188 $closestSub = $closestSub.parent().closest('ul'); 6189 } 6190 if ($closestSub[0] == $sub[0]) { 6191 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 6192 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 6193 this.menuScroll($sub, up, true); 6194 } 6195 } 6196 e.preventDefault(); 6197 }, 6198 menuScrollOut: function($sub, e) { 6199 var reClass = /^scroll-(up|down)/, 6200 $closestSub = $(e.relatedTarget).closest('ul'); 6201 while ($closestSub.dataSM('in-mega')) { 6202 $closestSub = $closestSub.parent().closest('ul'); 6203 } 6204 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 6205 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 6206 } 6207 }, 6208 menuScrollOver: function($sub, e) { 6209 var reClass = /^scroll-(up|down)/, 6210 $closestSub = $(e.target).closest('ul'); 6211 while ($closestSub.dataSM('in-mega')) { 6212 $closestSub = $closestSub.parent().closest('ul'); 6213 } 6214 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 6215 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 6216 } 6217 }, 6218 menuScrollStop: function($sub) { 6219 if (this.scrollTimeout) { 6220 clearTimeout(this.scrollTimeout); 6221 this.scrollTimeout = 0; 6222 $sub.dataSM('scroll').step = 1; 6223 } 6224 }, 6225 menuShow: function($sub) { 6226 if (!$sub.dataSM('beforefirstshowfired')) { 6227 $sub.dataSM('beforefirstshowfired', true); 6228 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 6229 return; 6230 } 6231 } 6232 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 6233 return; 6234 } 6235 this.menuFixLayout($sub); 6236 $sub.stop(true, true); 6237 if (!$sub.is(':visible')) { 6238 // set z-index - for IE < 9 set it to the parent LI
6239 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 6240 if (IElt9) { 6241 $sub.parent().css('z-index', zIndex); 6242 } else { 6243 $sub.css('z-index', zIndex); 6244 } 6245 // highlight parent item 6246 if (this.opts.keepHighlighted || this.isCollapsible()) { 6247 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 6248 $sub.dataSM('parent-a').addClass('highlighted'); 6249 } 6250 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 6251 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 6252 if (!IElt8) { 6253 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6254 if (this.opts.subMenusMinWidth) { 6255 $sub.css('min-width', this.opts.subMenusMinWidth); 6256 } 6257 if (this.opts.subMenusMaxWidth) { 6258 var noMaxWidth = this.getWidth($sub); 6259 $sub.css('max-width', this.opts.subMenusMaxWidth); 6260 if (noMaxWidth > this.getWidth($sub)) { 6261 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6262 } 6263 } 6264 // IE6,7 6265 } else { 6266 $sub.children().css('styleFloat', 'none'); 6267 if (IE6) { 6268 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 6269 .children().children('a').css('white-space', 'nowrap'); 6270 } else { // IE7 6271 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6272 if (this.opts.subMenusMinWidth) { 6273 $sub.css('min-width', this.opts.subMenusMinWidth); 6274 } 6275 } 6276 if (this.opts.subMenusMaxWidth) { 6277 var noMaxWidth = $sub.width(); 6278 if (IE6) { 6279 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 6280 if (noMaxWidth > maxWidth) { 6281 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 6282 } else { 6283 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 6284 } 6285 } else { // IE7 6286 $sub.css('max-width', this.opts.subMenusMaxWidth); 6287 if (noMaxWidth > $sub.width()) { 6288 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6289 } else { 6290 $sub.width(noMaxWidth); 6291 } 6292 } 6293 } else { 6294 $sub.width($sub.width()); 6295 } 6296 $sub.children().css('styleFloat', 'left'); 6297 } 6298 } 6299 this.menuPosition($sub); 6300 // insert IE iframe shim 6301 if ($sub.dataSM('ie-shim')) { 6302 $sub.dataSM('ie-shim').insertBefore($sub); 6303 } 6304 var complete = function() { 6305 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 6306 $sub.css('overflow', ''); 6307 }; 6308 // if sub is collapsible (mobile view) 6309 if (this.isCollapsible()) { 6310 if (this.opts.collapsibleShowFunction) { 6311 this.opts.collapsibleShowFunction.call(this, $sub, complete); 6312 } else { 6313 $sub.show(this.opts.collapsibleShowDuration, complete); 6314 } 6315 } else { 6316 if (this.opts.showFunction) { 6317 this.opts.showFunction.call(this, $sub, complete); 6318 } else { 6319 $sub.show(this.opts.showDuration, complete); 6320 } 6321 } 6322 // save new sub menu for this level 6323 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 6324 this.$root.triggerHandler('show.smapi', $sub[0]); 6325 } 6326 }, 6327 popupHide: function(noHideTimeout) { 6328 if (this.hideTimeout) { 6329 clearTimeout(this.hideTimeout); 6330 this.hideTimeout = 0; 6331 } 6332 var self = this; 6333 this.hideTimeout = setTimeout(function() { 6334 self.menuHideAll(); 6335 }, noHideTimeout ? 1 : this.opts.hideTimeout); 6336 }, 6337 popupShow: function(left, top) { 6338 if (!this.opts.isPopup) { 6339 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 6340 return; 6341 } 6342 if (this.hideTimeout) { 6343 clearTimeout(this.hideTimeout); 6344 this.hideTimeout = 0; 6345 } 6346 this.menuFixLayout(this.$root); 6347 this.$root.stop(true, true); 6348 if (!this.$root.is(':visible')) { 6349 this.$root.css({ left: left, top: top }); 6350 // IE iframe shim 6351 this.menuIframeShim(this.$root); 6352 if (this.$root.dataSM('ie-shim')) { 6353 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6353: left, top: top }).insertBefore(this.$root); 6354 } 6355 // show menu 6356 if (this.opts.showFunction) { 6357 this.opts.showFunction.call(this, this.$root); 6358 } else { 6359 this.$root.show(this.opts.showDuration); 6360 } 6361 this.visibleSubMenus[0] = this.$root; 6362 } 6363 }, 6364 refresh: function() { 6365 this.menuHideAll(); 6366 this.$root.find('ul').each(function() { 6367 var $this = $(this); 6368 if ($this.dataSM('scroll-arrows')) { 6369 $this.dataSM('scroll-arrows').remove(); 6370 } 6371 }) 6372 .removeDataSM('in-mega') 6373 .removeDataSM('shown-before') 6374 .removeDataSM('ie-shim') 6375 .removeDataSM('scroll-arrows') 6376 .removeDataSM('parent-a') 6377 .removeDataSM('level') 6378 .removeDataSM('beforefirstshowfired'); 6379 this.$root.find('a.has-submenu').removeClass('has-submenu') 6380 .parent().removeDataSM('sub'); 6381 if (this.opts.subIndicators) { 6382 this.$root.find('span.sub-arrow').remove(); 6383 } 6384 if (this.opts.markCurrentItem) { 6385 this.$root.find('a.current').removeClass('current'); 6386 } 6387 this.subMenus = []; 6388 this.init(true); 6389 }, 6390 rootOut: function(e) { 6391 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6392 return; 6393 } 6394 if (this.hideTimeout) { 6395 clearTimeout(this.hideTimeout); 6396 this.hideTimeout = 0; 6397 } 6398 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 6399 var self = this; 6400 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 6401 } 6402 }, 6403 rootOver: function(e) { 6404 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6405 return; 6406 } 6407 if (this.hideTimeout) { 6408 clearTimeout(this.hideTimeout); 6409 this.hideTimeout = 0; 6410 } 6411 }, 6412 winResize: function(e) { 6413 if (!this.handleEvents()) { 6414 // we still need to resize the disable overlay if it's visible 6415 if (this.$disableOverlay) { 6416 var pos = this.$root.offset(); 6417 this.$disableOverlay.css({ 6418 top: pos.top, 6419 left: pos.left, 6420 width: this.$root.outerWidth(), 6421 height: this.$root.outerHeight() 6422 }); 6423 } 6424 return; 6425 } 6426 // hide sub menus on resize - on mobile do it only on orientation change 6427 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 6428 if (this.activatedItems.length) { 6429 this.activatedItems[this.activatedItems.length - 1][0].blur(); 6430 } 6431 this.menuHideAll(); 6432 } 6433 } 6434 } 6435 }); 6436 6437 $.fn.dataSM = function(key, val) { 6438 if (val) { 6439 return this.data(key + '_smartmenus', val); 6440 } 6441 return this.data(key + '_smartmenus'); 6442 } 6443 6444 $.fn.removeDataSM = function(key) { 6445 return this.removeData(key + '_smartmenus'); 6446 } 6447 6448 $.fn.smartmenus = function(options) { 6449 if (typeof options == 'string') { 6450 var args = arguments, 6451 method = options; 6452 Array.prototype.shift.call(args); 6453 return this.each(function() { 6454 var smartmenus = $(this).data('smartmenus'); 6455 if (smartmenus && smartmenus[method]) { 6456 smartmenus[method].apply(smartmenus, args); 6457 } 6458 }); 6459 } 6460 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 6461 return this.each(function() { 6462 new $.SmartMenus(this, opts); 6463 }); 6464 } 6465 6466 // default settings 6467 $.fn.smartmenus.defaults = { 6468 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 6469 mainMenuSubOffsetX: 0, // pixels offset from default position
6470 mainMenuSubOffsetY: 0, // pixels offset from default position 6471 subMenusSubOffsetX: 0, // pixels offset from default position 6472 subMenusSubOffsetY: 0, // pixels offset from default position 6473 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6474 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6475 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 6476 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 6477 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 6478 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 6479 scrollInterval: 30, // interval between each scrolling step 6480 scrollAccelerate: true, // accelerate scrolling or use a fixed step 6481 showTimeout: 250, // timeout before showing the sub menus 6482 hideTimeout: 500, // timeout before hiding the sub menus 6483 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 6484 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 6485 // don't forget to call complete() at the end of whatever you do 6486 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 6487 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 6488 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 6489 // don't forget to call complete() at the end of whatever you do 6490 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 6491 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 6492 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 6493 // (i.e. when mobile styles are used to make the sub menus collapsible) 6494 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 6495 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 6496 // (i.e. when mobile styles are used to make the sub menus collapsible) 6497 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 6498 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 6499 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 6500 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 6501 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 6502 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 6503 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 6504 bottomToTopSubMenus: false, // bottom to top display of the sub menus 6505 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 6506 }; 6507 6508})(jQuery); 6509 6510/* 6511 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 6512 * 6513 * Uses the built in easing capabilities added In jQuery 1.1 6514 * to offer multiple easing options 6515 * 6516 * TERMS OF USE - jQuery Easing 6517 * 6518 * Open source under the BSD License. 6519 * 6520 * Copyright © 2008 George McGinley Smith 6521 * All rights reserved. 6522 * 6523 * Redistribution and use in source and binary forms, with or without modification, 6524 * are permitted provided that the following conditions are met: 6525 * 6526 * Redistributions of source code must retain the above copyright notice, this list of 6527 * conditions and the following disclaimer. 6528 * Redistributions in binary form must reproduce the above copyright notice, this list 6529 * of conditions and the following disclaimer in the documentation and/or other materials 6530 * provided with the distribution. 6531 * 6532 * Neither the name of the author nor the names of contributors may be used to endorse 6533 * or promote products derived from this software without specific prior written permission. 6534 * 6535 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6536 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6537 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6538 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6539-6684
6539 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6540 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6541 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6542 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6543 * OF THE POSSIBILITY OF SUCH DAMAGE. 6544 * 6545*/ 6546 6547// t: current time, b: begInnIng value, c: change In value, d: duration 6548jQuery.easing['jswing'] = jQuery.easing['swing']; 6549 6550jQuery.extend( jQuery.easing, 6551{ 6552 def: 'easeOutQuad', 6553 swing: function (x, t, b, c, d) { 6554 //alert(jQuery.easing.default); 6555 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 6556 }, 6557 easeInQuad: function (x, t, b, c, d) { 6558 return c*(t/=d)*t + b; 6559 }, 6560 easeOutQuad: function (x, t, b, c, d) { 6561 return -c *(t/=d)*(t-2) + b; 6562 }, 6563 easeInOutQuad: function (x, t, b, c, d) { 6564 if ((t/=d/2) < 1) return c/2*t*t + b; 6565 return -c/2 * ((--t)*(t-2) - 1) + b; 6566 }, 6567 easeInCubic: function (x, t, b, c, d) { 6568 return c*(t/=d)*t*t + b; 6569 }, 6570 easeOutCubic: function (x, t, b, c, d) { 6571 return c*((t=t/d-1)*t*t + 1) + b; 6572 }, 6573 easeInOutCubic: function (x, t, b, c, d) { 6574 if ((t/=d/2) < 1) return c/2*t*t*t + b; 6575 return c/2*((t-=2)*t*t + 2) + b; 6576 }, 6577 easeInQuart: function (x, t, b, c, d) { 6578 return c*(t/=d)*t*t*t + b; 6579 }, 6580 easeOutQuart: function (x, t, b, c, d) { 6581 return -c * ((t=t/d-1)*t*t*t - 1) + b; 6582 }, 6583 easeInOutQuart: function (x, t, b, c, d) { 6584 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 6585 return -c/2 * ((t-=2)*t*t*t - 2) + b; 6586 }, 6587 easeInQuint: function (x, t, b, c, d) { 6588 return c*(t/=d)*t*t*t*t + b; 6589 }, 6590 easeOutQuint: function (x, t, b, c, d) { 6591 return c*((t=t/d-1)*t*t*t*t + 1) + b; 6592 }, 6593 easeInOutQuint: function (x, t, b, c, d) { 6594 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 6595 return c/2*((t-=2)*t*t*t*t + 2) + b; 6596 }, 6597 easeInSine: function (x, t, b, c, d) { 6598 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 6599 }, 6600 easeOutSine: function (x, t, b, c, d) { 6601 return c * Math.sin(t/d * (Math.PI/2)) + b; 6602 }, 6603 easeInOutSine: function (x, t, b, c, d) { 6604 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 6605 }, 6606 easeInExpo: function (x, t, b, c, d) { 6607 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 6608 }, 6609 easeOutExpo: function (x, t, b, c, d) { 6610 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 6611 }, 6612 easeInOutExpo: function (x, t, b, c, d) { 6613 if (t==0) return b; 6614 if (t==d) return b+c; 6615 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 6616 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 6617 }, 6618 easeInCirc: function (x, t, b, c, d) { 6619 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 6620 }, 6621 easeOutCirc: function (x, t, b, c, d) { 6622 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 6623 }, 6624 easeInOutCirc: function (x, t, b, c, d) { 6625 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 6626 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 6627 }, 6628 easeInElastic: function (x, t, b, c, d) { 6629 var s=1.70158;var p=0;var a=c; 6630 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6631 if (a < Math.abs(c)) { a=c; var s=p/4; } 6632 else var s = p/(2*Math.PI) * Math.asin (c/a); 6633 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6634 }, 6635 easeOutElastic: function (x, t, b, c, d) { 6636 var s=1.70158;var p=0;var a=c; 6637 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6638 if (a < Math.abs(c)) { a=c; var s=p/4; } 6639 else var s = p/(2*Math.PI) * Math.asin (c/a); 6640 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 6641 }, 6642 easeInOutElastic: function (x, t, b, c, d) { 6643 var s=1.70158;var p=0;var a=c; 6644 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 6645 if (a < Math.abs(c)) { a=c; var s=p/4; } 6646 else var s = p/(2*Math.PI) * Math.asin (c/a); 6647 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6648 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 6649 }, 6650 easeInBack: function (x, t, b, c, d, s) { 6651 if (s == undefined) s = 1.70158; 6652 return c*(t/=d)*t*((s+1)*t - s) + b; 6653 }, 6654 easeOutBack: function (x, t, b, c, d, s) { 6655 if (s == undefined) s = 1.70158; 6656 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 6657 }, 6658 easeInOutBack: function (x, t, b, c, d, s) { 6659 if (s == undefined) s = 1.70158; 6660 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 6661 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 6662 }, 6663 easeInBounce: function (x, t, b, c, d) { 6664 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 6665 }, 6666 easeOutBounce: function (x, t, b, c, d) { 6667 if ((t/=d) < (1/2.75)) { 6668 return c*(7.5625*t*t) + b; 6669 } else if (t < (2/2.75)) { 6670 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 6671 } else if (t < (2.5/2.75)) { 6672 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 6673 } else { 6674 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 6675 } 6676 }, 6677 easeInOutBounce: function (x, t, b, c, d) { 6678 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 6679 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 6680 } 6681}); 6682 6683/* 6684 *
6685 * TERMS OF USE - EASING EQUATIONS 6686 * 6687 * Open source under the BSD License. 6688 * 6689 * Copyright © 2001 Robert Penner 6690 * All rights reserved. 6691 * 6692 * Redistribution and use in source and binary forms, with or without modification, 6693 * are permitted provided that the following conditions are met: 6694 * 6695 * Redistributions of source code must retain the above copyright notice, this list of 6696 * conditions and the following disclaimer. 6697 * Redistributions in binary form must reproduce the above copyright notice, this list 6698 * of conditions and the following disclaimer in the documentation and/or other materials 6699 * provided with the distribution. 6700 * 6701 * Neither the name of the author nor the names of contributors may be used to endorse 6702 * or promote products derived from this software without specific prior written permission. 6703 * 6704 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6705 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6706 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6707 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 6708 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6709 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6710 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6711 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6712 * OF THE POSSIBILITY OF SUCH DAMAGE. 6713 * 6714 */ 6715 6716(function($, window, undefined) { 6717 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 6718 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 6719 6720 // requestAnimationFrame polyfill by Erik Möller 6721 // fixes from Paul Irish and Tino Zijdel 6722 6723 var lastTime = 0, 6724 running, 6725 animate = function (elem) { 6726 if (running) { 6727 window.requestAnimationFrame(animate, elem); 6728 jQuery.fx.tick(); 6729 } 6730 }, 6731 vendors = ['ms', 'moz', 'webkit', 'o']; 6732 6733 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 6734 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 6735 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 6736 || window[vendors[x]+'CancelRequestAnimationFrame']; 6737 } 6738 6739 if (!window.requestAnimationFrame) 6740 window.requestAnimationFrame = function(fn, element) { 6741 var currTime = new Date().getTime(), 6742 delta = currTime - lastTime, 6743 timeToCall = Math.max(0, 16 - delta); 6744 6745 var id = window.setTimeout(function() { 6746 fn(currTime + timeToCall); 6747 }, 6748 timeToCall 6749 ); 6750 6751 lastTime = currTime + timeToCall; 6752 6753 return id; 6754 }; 6755 6756 if (!window.cancelAnimationFrame) { 6757 window.cancelAnimationFrame = function(id) { 6758 clearTimeout(id); 6759 }; 6760 } 6761 6762 jQuery.fx.timer = function (timer) { 6763 if (timer() && jQuery.timers.push(timer) && !running) { 6764 running = true; 6765 animate(timer.elem); 6766 } 6767 }; 6768 6769 jQuery.fx.stop = function() { 6770 running = false; 6771 }; 6772 6773}(jQuery, this)); 6774 6775/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 6776 * Licensed under the MIT License (LICENSE.txt). 6777 * 6778 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 6779 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6780 * Thanks to: Seamus Leahy for adding deltaX and deltaY 6781 * 6782 * Version: 3.0.6 6783 * 6784 * Requires: 1.2.2+ 6785 */ 6786(function($) { 6787 var types = ['DOMMouseScroll', 'mousewheel']; 6788 if ($.event.fixHooks) { 6789 for (var i = types.length; i;) { 6790 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 6791 } 6792 } 6793 $.event.special.mousewheel = { 6794 setup: function() { 6795 if (this.addEventListener) { 6796 for (var i = types.length; i;) { 6797 this.addEventListener(types[--i], handler, false); 6798 } 6799 } else { 6800 this.onmousewheel = handler; 6801 } 6802 }, 6803 teardown: function() { 6804 if (this.removeEventListener) { 6805 for (var i = types.length; i;) { 6806 this.removeEventListener(types[--i], handler, false); 6807 } 6808 } else { 6809 this.onmousewheel = null; 6810 } 6811 } 6812 }; 6813 $.fn.extend({ 6814 mousewheel: function(fn) { 6815 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 6816 }, 6817 unmousewheel: function(fn) { 6818 return this.unbind("mousewheel", fn); 6819 } 6820 }); 6821 6822 function handler(event) { 6823 var orgEvent = event || window.event, 6824 args = [].slice.call(arguments, 1), 6825 delta = 0, 6826 returnValue = true, 6827 deltaX = 0, 6828 deltaY = 0; 6829 event = $.event.fix(orgEvent); 6830 event.type = "mousewheel"; 6831 // Old school scrollwheel delta 6832 if (orgEvent.wheelDelta) { 6833 delta = orgEvent.wheelDelta / 120; 6834 } 6835 if (orgEvent.detail) { 6836 delta = -orgEvent.detail / 3; 6837 } 6838 // New school multidimensional scroll (touchpads) deltas 6839 deltaY = delta; 6840 // Gecko 6841 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 6842 deltaY = 0; 6843 deltaX = -1 * delta; 6844 } 6845 // Webkit 6846 if (orgEvent.wheelDeltaY !== undefined) { 6847 deltaY = orgEvent.wheelDeltaY / 120; 6848 } 6849 if (orgEvent.wheelDeltaX !== undefined) { 6850 deltaX = -1 * orgEvent.wheelDeltaX / 120; 6851 } 6852 // Add event and delta to the front of the arguments 6853 args.unshift(event, delta, deltaX, deltaY); 6854 return ($.event.dispatch || $.event.handle).apply(this, args); 6855 } 6856})(jQuery); 6857 6858/** 6859 * jQuery iLightBox - Revolutionary Lightbox Plugin 6860 * http://www.ilightbox.net/ 6861 * 6862 * @version: 2.2.4 - October 14, 2017 6863 * 6864 * @author: iProDev (Hemn Chawroka) 6865 * http://www.iprodev.com/ 6866 * 6867 */ 6868(function($, window, undefined) { 6869 6870 var extensions = { 6871 flash: ['swf'], 6872 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 6873 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 6874 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 6875 }, 6876 6877 // Global DOM elements 6878 $win = $(window), 6879 $doc = $(document), 6880
6881 // Support indicators 6882 browser, 6883 transform, 6884 gpuAcceleration, 6885 fullScreenApi = '', 6886 userAgent = navigator.userAgent || navigator.vendor || window.opera, 6887 supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)), 6888 isMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4)), 6889 6890 // Events 6891 clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox", 6892 touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 6893 touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 6894 touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 6895 6896 // Math shorthands 6897 abs = Math.abs, 6898 sqrt = Math.sqrt, 6899 round = Math.round, 6900 max = Math.max, 6901 min = Math.min, 6902 floor = Math.floor, 6903 random = Math.random, 6904 6905 pluginspages = { 6906 quicktime: 'http://www.apple.com/quicktime/download', 6907 flash: 'http://www.adobe.com/go/getflash' 6908 }, 6909 6910 iLightBox = function(el, options, items, instant) { 6911 var iL = this; 6912 6913 iL.options = options, 6914 iL.selector = el.selector || el, 6915 iL.context = el.context, 6916 iL.instant = instant; 6917 6918 if (items.length < 1) iL.attachItems(); 6919 else iL.items = items; 6920 6921 iL.vars = { 6922 total: iL.items.length, 6923 start: 0, 6924 current: null, 6925 next: null, 6926 prev: null, 6927 BODY: $('body'), 6928 loadRequests: 0, 6929 overlay: $('<div class="ilightbox-overlay"></div>'), 6930 loader: $('<div class="ilightbox-loader"><div></div></div>'), 6931 toolbar: $('<div class="ilightbox-toolbar"></div>'), 6932 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 6933 title: $('<div class="ilightbox-title"></div>'), 6934 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 6935 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 6936 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 6937 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 6938 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 6939 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6940 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6941 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6942 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 6943 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
6944 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>'), 6945 thumbs: false, 6946 nextLock: false, 6947 prevLock: false, 6948 hashLock: false, 6949 isMobile: false, 6950 mobileMaxWidth: 980, 6951 isInFullScreen: false, 6952 isSwipe: false, 6953 mouseID: 0, 6954 cycleID: 0, 6955 isPaused: 0, 6956 captionHeight: 39, 6957 }; 6958 6959 // Hideable elements with mousemove event 6960 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 6961 6962 iL.normalizeItems(); 6963 6964 //Check necessary plugins 6965 iL.availPlugins(); 6966 6967 //Set startFrom 6968 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 6969 6970 //If randomStart 6971 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 6972 iL.vars.start = iL.options.startFrom; 6973 6974 if (instant) iL.instantCall(); 6975 else iL.patchItemsEvents(); 6976 6977 if (iL.options.linkId) { 6978 iL.hashChangeHandler(); 6979 $win.iLightBoxHashChange(function() { 6980 iL.hashChangeHandler(); 6981 }); 6982 } 6983 6984 if (supportTouch) { 6985 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 6986 replace = "itap"; 6987 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 6988 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 6989 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 6990 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 6991 } 6992 6993 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 6994 $.extend(iL.options.styles, { 6995 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6996 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6997 nextOpacity: 0, 6998 prevOpacity: 0 6999 }); 7000 } 7001 }; 7002 7003 //iLightBox helpers 7004 iLightBox.prototype = { 7005 showLoader: function() { 7006 var iL = this; 7007 iL.vars.loadRequests += 1; 7008 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7009 //top: '-30px' 7010 opacity: '1' 7011 }, iL.options.show.speed, 'easeOutCirc'); 7012 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7013 //left: '-30px' 7014 opacity: '1' 7015 }, iL.options.show.speed, 'easeOutCirc'); 7016 }, 7017 7018 hideLoader: function() { 7019 var iL = this; 7020 iL.vars.loadRequests -= 1; 7021 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 7022 if (iL.options.path.toLowerCase() == "horizontal") { 7023 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7024 //top: '-192px' 7025 opacity: '0' 7026 }, iL.options.show.speed, 'easeInCirc'); 7027 } else { 7028 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7029 //left: '-192px' 7030 opacity: '0' 7031 }, iL.options.show.speed, 'easeInCirc'); 7032 } 7033 }, 7034 7035 createUI: function() { 7036 var iL = this; 7037 7038 iL.ui = { 7039 currentElement: iL.vars.holder, 7040 nextElement: iL.vars.nextPhoto, 7041 prevElement: iL.vars.prevPhoto, 7042 currentItem: iL.vars.current, 7043 nextItem: iL.vars.next, 7044 prevItem: iL.vars.prev, 7045 hide: function() { 7046 iL.closeAction(); 7047 }, 7048 refresh: function() { 7049 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7050 }, 7051 fullscreen: function() { 7052 iL.fullScreenAction(); 7053 } 7054 }; 7055 }, 7056 7057 attachItems: function() { 7058 var iL = this, 7059 itemsObject = new Array(), 7060 items = new Array(); 7061 7062 $(iL.selector, iL.context).each(function() { 7063 var t = $(this), 7064 URL = t.attr(iL.options.attr) || null, 7065 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 7066 caption = t.data('caption'), 7067 title = t.data('title'), 7068 type = t.data('type') || getTypeByExtension(URL), 7069 clone = t.data('lbox-clone') || false; 7070 7071 if (t.data('lbox-clone') != undefined) return; 7072 7073 //Uncode addition ##START## 7074 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 7075 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 7076 URL_i, 7077 URLS_LENGHT = ALBUM_URLS.length; 7078 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 7079 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 7080 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 7081 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 7082 items.push({ 7083 URL: ALBUM_URLS[URL_i].url, 7084 caption: ALBUM_URLS[URL_i].caption, 7085 title: ALBUM_URLS[URL_i].title, 7086 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 7087 options: item_opts, 7088 clone: clone 7089 }); 7090 var newT = t; 7091 newT.attr('href',ALBUM_URLS[URL_i].url); 7092 if (!iL.instant) itemsObject.push(newT); 7093 } 7094 } 7095 } else { 7096 //Uncode addition ##END## 7097 items.push({ 7098 URL: URL, 7099 caption: caption, 7100 title: title, 7101 type: type, 7102 options: options, 7103 clone: clone 7104 }); 7105 } 7106 7107 7108 if (iL.vars != undefined) iL.vars.total = items.length; 7109 7110 if (!iL.instant) itemsObject.push(t); 7111 }); 7112 7113 iL.items = items, 7114 iL.itemsObject = itemsObject; 7115 7116 }, 7117 7118 normalizeItems: function() { 7119 var iL = this, 7120 newItems = new Array(); 7121 7122 $.each(iL.items, function(key, val) { 7123 7124 if (typeof val == "string") val = { 7125 url: val 7126 }; 7127 7128 var URL = val.url || val.URL || null, 7129 options = val.options || {}, 7130 caption = val.caption || null, 7131 title = val.title || null, 7132 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 7133 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 7134 7135 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
7136 options.videoType = options.videoType || null, 7137 options.skin = options.skin || iL.options.skin, 7138 options.width = options.width || null, 7139 options.height = options.height || null, 7140 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 7141 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 7142 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 7143 7144 if (type == "video") { 7145 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 7146 7147 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 7148 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 7149 options.html5video.preload = options.html5video.preload || "metadata"; 7150 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 7151 } 7152 7153 if (!options.width || !options.height) { 7154 if (type == "video") options.width = 1280, options.height = 720; 7155 else if (type == "iframe") options.width = '100%', options.height = '90%'; 7156 else if (type == "flash") options.width = 1280, options.height = 720; 7157 } 7158 7159 delete val.url; 7160 val.index = key; 7161 val.URL = URL; 7162 val.caption = caption; 7163 val.title = title; 7164 val.type = type; 7165 val.options = options; 7166 val.ext = ext; 7167 7168 newItems.push(val); 7169 }); 7170 7171 iL.items = newItems; 7172 }, 7173 7174 instantCall: function() { 7175 var iL = this, 7176 key = iL.vars.start; 7177 7178 iL.vars.current = key; 7179 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 7180 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 7181 7182 iL.addContents(); 7183 iL.patchEvents(); 7184 }, 7185 7186 addContents: function() { 7187 var iL = this, 7188 vars = iL.vars, 7189 opts = iL.options, 7190 viewport = getViewport(), 7191 path = opts.path.toLowerCase(), 7192 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 7193 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 7194 }), 7195 needRecognition = recognizingItems.length > 0; 7196 7197 if (opts.mobileOptimizer && !opts.innerToolbar) 7198 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7199 7200 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 7201 7202 if (opts.linkId) 7203 vars.overlay[0].setAttribute('linkid', opts.linkId); 7204 7205 //Add Toolbar Buttons 7206 if (opts.controls.toolbar) { 7207 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 7208 if (opts.controls.fullscreen) 7209 vars.toolbar.append(vars.fullScreenButton); 7210 if (opts.controls.slideshow) 7211 vars.toolbar.append(vars.innerPlayButton); 7212 if (vars.total > 1) 7213 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 7214 } 7215 7216 //Append elements to body 7217 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 7218 7219 if (!opts.innerToolbar) 7220 vars.BODY.append(vars.toolbar); 7221 if (opts.controls.arrows) 7222 vars.BODY.append(vars.nextButton).append(vars.prevButton); 7223 7224 if (opts.controls.thumbnail && vars.total > 1) { 7225 vars.BODY.append(vars.thumbnails); 7226 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 7227 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 7228 vars.thumbs = true; 7229 } 7230 7231 //Configure loader and arrows 7232 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 7233 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 7234 } : { 7235 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 7236 }; 7237 vars.loader.addClass(opts.skin).css(loaderCss); 7238 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 7239 if (path == "horizontal") 7240 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 7241 7242 // Configure arrow buttons 7243 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7244 7245 if (!opts.infinite) { 7246 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 7247 7248 if (vars.current == 0) 7249 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 7250 if (vars.current >= vars.total - 1) 7251 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 7252 } 7253 7254 if (opts.show.effect) { 7255 vars.overlay.stop().fadeIn(opts.show.speed); 7256 vars.toolbar.stop().fadeIn(opts.show.speed); 7257 } else { 7258 vars.overlay.show(); 7259 vars.toolbar.show(); 7260 } 7261 7262 var length = recognizingItems.length; 7263 if (needRecognition) { 7264 iL.showLoader(); 7265 7266 $.each(recognizingItems, function(key, val) { 7267 var resultFnc = function(result) { 7268 var key = -1, 7269 filter = iL.items.filter(function(e, i, arr) { 7270 if (e.URL == result.url) 7271 key = i; 7272 7273 return e.URL == result.url; 7274 }), 7275 self = iL.items[key]; 7276 7277 if (result) 7278 $.extend(true, self, { 7279 URL: result.source, 7280 type: result.type, 7281 recognized: true, 7282 options: { 7283 html5video: result.html5video, 7284 width: (result.type == "image") ? 0 : (result.width || self.width), 7285 height: (result.type == "image") ? 0 : (result.height || self.height), 7286 thumbnail: self.options.thumbnail || result.thumbnail 7287 } 7288 }); 7289 7290 length--; 7291 7292 if (length == 0) { 7293 iL.hideLoader(); 7294 7295 vars.dontGenerateThumbs = false;
7296 iL.generateThumbnails(); 7297 7298 if (opts.show.effect) 7299 setTimeout(function() { 7300 iL.generateBoxes(); 7301 }, opts.show.speed); 7302 else 7303 iL.generateBoxes(); 7304 } 7305 }; 7306 7307 iL.ogpRecognition(this, resultFnc); 7308 }); 7309 } 7310 else { 7311 if (opts.show.effect) 7312 setTimeout(function() { 7313 iL.generateBoxes(); 7314 }, opts.show.speed); 7315 else 7316 iL.generateBoxes(); 7317 } 7318 7319 iL.createUI(); 7320 7321 window.iLightBox = { 7322 close: function() { 7323 iL.closeAction(); 7324 }, 7325 fullscreen: function() { 7326 iL.fullScreenAction(); 7327 }, 7328 moveNext: function() { 7329 iL.moveTo('next'); 7330 }, 7331 movePrev: function() { 7332 iL.moveTo('prev'); 7333 }, 7334 goTo: function(index) { 7335 iL.goTo(index); 7336 }, 7337 refresh: function() { 7338 iL.refresh(); 7339 }, 7340 reposition: function() { 7341 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7342 }, 7343 setOption: function(options) { 7344 iL.setOption(options); 7345 }, 7346 destroy: function() { 7347 iL.closeAction(); 7348 iL.dispatchItemsEvents(); 7349 } 7350 }; 7351 7352 if (opts.linkId) { 7353 vars.hashLock = true; 7354 window.location.hash = opts.linkId + '/' + vars.current; 7355 setTimeout(function() { 7356 vars.hashLock = false; 7357 }, 55); 7358 } 7359 7360 if (!opts.slideshow.startPaused) { 7361 iL.resume(); 7362 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 7363 } 7364 7365 //Trigger the onOpen callback 7366 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 7367 }, 7368 7369 loadContent: function(obj, opt, speed) { 7370 var iL = this, 7371 holder, item; 7372 7373 iL.createUI(); 7374 7375 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 7376 7377 if (opt == 'current') { 7378 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 7379 else iL.vars.lockWheel = false; 7380 7381 if (!obj.options.swipe) iL.vars.lockSwipe = true; 7382 else iL.vars.lockSwipe = false; 7383 } 7384 7385 switch (opt) { 7386 case 'current': 7387 holder = iL.vars.holder, item = iL.vars.current; 7388 break; 7389 case 'next': 7390 holder = iL.vars.nextPhoto, item = iL.vars.next; 7391 break; 7392 case 'prev': 7393 holder = iL.vars.prevPhoto, item = iL.vars.prev; 7394 break; 7395 } 7396 7397 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 7398 $('div.ilightbox-inner-toolbar', holder).remove(); 7399 7400 if (obj.title || iL.options.innerToolbar) { 7401 var innerToolbar = iL.vars.innerToolbar.clone(); 7402 if (obj.title && iL.options.show.title) { 7403 var title = iL.vars.title.clone(); 7404 title.empty().html(obj.title); 7405 innerToolbar.append(title); 7406 } 7407 if (iL.options.innerToolbar) { 7408 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 7409 } 7410 holder.prepend(innerToolbar); 7411 } 7412 7413 //console.warn('loadContent', arguments); 7414 7415 iL.loadSwitcher(obj, holder, item, opt); 7416 }, 7417 7418 loadSwitcher: function(obj, holder, item, opt) { 7419 var iL = this, 7420 opts = iL.options, 7421 api = { 7422 element: holder, 7423 position: item 7424 }; 7425 7426 switch (obj.type) { 7427 case 'image': 7428 //Trigger the onBeforeLoad callback 7429 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7430 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7431 7432 iL.loadImage(obj.URL, function(img) { 7433 //Trigger the onAfterLoad callback 7434 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7435 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7436 7437 var width = (img) ? img.width : 400, 7438 height = (img) ? img.height : 200; 7439 7440 holder.data({ 7441 naturalWidth: width, 7442 naturalHeight: height 7443 }); 7444 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 7445 7446 //Trigger the onRender callback 7447 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7448 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7449 7450 iL.configureHolder(obj, opt, holder); 7451 }); 7452 7453 break; 7454
7455 case 'video': 7456 holder.data({ 7457 naturalWidth: obj.options.width, 7458 naturalHeight: obj.options.height 7459 }); 7460 7461 if (opt === 'current') { 7462 iL.addContent(holder, obj); 7463 7464 //Trigger the onRender callback 7465 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7466 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7467 } else { 7468 $('div.ilightbox-container', holder).empty(); 7469 } 7470 7471 iL.configureHolder(obj, opt, holder); 7472 7473 break; 7474 7475 case 'iframe': 7476 //iL.showLoader(); 7477 holder.data({ 7478 naturalWidth: obj.options.width, 7479 naturalHeight: obj.options.height 7480 }); 7481 7482 iL.configureHolder(obj, opt, holder); 7483 7484 if (opt === 'current') { 7485 var el = iL.addContent(holder, obj); 7486 7487 //Trigger the onRender callback 7488 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7489 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7490 7491 //Trigger the onBeforeLoad callback 7492 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7493 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7494 7495 el.bind('load', function() { 7496 //Trigger the onAfterLoad callback 7497 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7498 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7499 7500 //iL.hideLoader(); 7501 el.unbind('load'); 7502 }); 7503 } else { 7504 $('div.ilightbox-container', holder).empty(); 7505 } 7506 7507 break; 7508 7509 case 'inline': 7510 var el = $(obj.URL), 7511 content = iL.addContent(holder, obj), 7512 images = findImageInElement(holder); 7513 7514 holder.data({ 7515 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7516 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7517 }); 7518 content.children().eq(0).show(); 7519 7520 //Trigger the onRender callback 7521 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7522 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7523 7524 //Trigger the onBeforeLoad callback 7525 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7526 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7527 7528 iL.loadImage(images, function() { 7529 //Trigger the onAfterLoad callback 7530 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7531 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7532 7533 iL.configureHolder(obj, opt, holder); 7534 }); 7535 7536 break; 7537 7538 case 'flash': 7539 var el = iL.addContent(holder, obj); 7540 7541 holder.data({ 7542 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7543 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7544 }); 7545 7546 //Trigger the onRender callback 7547 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7548 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7549 7550 iL.configureHolder(obj, opt, holder); 7551 7552 break; 7553 7554 case 'ajax': 7555 var ajax = obj.options.ajax || {}; 7556 //Trigger the onBeforeLoad callback 7557 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7558 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7559 7560 iL.showLoader(); 7561 $.ajax({ 7562 url: obj.URL || opts.ajaxSetup.url, 7563 data: ajax.data || null, 7564 dataType: ajax.dataType || "html", 7565 type: ajax.type || opts.ajaxSetup.type, 7566 cache: ajax.cache || opts.ajaxSetup.cache, 7567 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 7568 global: ajax.global || opts.ajaxSetup.global, 7569 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 7570 username: ajax.username || opts.ajaxSetup.username, 7571 password: ajax.password || opts.ajaxSetup.password, 7572 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 7573 complete: ajax.complete || opts.ajaxSetup.complete, 7574 success: function(data, textStatus, jqXHR) { 7575 iL.hideLoader(); 7576 7577 var el = $(data), 7578 container = $('div.ilightbox-container', holder), 7579 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 7580 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 7581 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 7582 'overflow': 'hidden' 7583 } : {}; 7584 7585 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 7586 holder.show().data({
7587 naturalWidth: (elWidth || container.outerWidth()), 7588 naturalHeight: (elHeight || container.outerHeight()) 7589 }).hide(); 7590 7591 //Trigger the onRender callback 7592 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7593 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7594 7595 var images = findImageInElement(holder); 7596 iL.loadImage(images, function() { 7597 //Trigger the onAfterLoad callback 7598 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7599 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7600 7601 iL.configureHolder(obj, opt, holder); 7602 }); 7603 7604 opts.ajaxSetup.success(data, textStatus, jqXHR); 7605 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 7606 }, 7607 error: function(jqXHR, textStatus, errorThrown) { 7608 //Trigger the onAfterLoad callback 7609 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7610 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7611 7612 iL.hideLoader(); 7613 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 7614 iL.configureHolder(obj, opt, holder); 7615 7616 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 7617 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 7618 } 7619 }); 7620 7621 break; 7622 7623 case 'html': 7624 var object = obj.URL, 7625 el 7626 container = $('div.ilightbox-container', holder); 7627 7628 if (object[0].nodeName) el = object.clone(); 7629 else { 7630 var dom = $(object); 7631 if (dom.selector) el = $('<div>' + dom + '</div>'); 7632 else el = dom; 7633 } 7634 7635 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 7636 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 7637 7638 iL.addContent(holder, obj); 7639 7640 el.appendTo(document.documentElement).hide(); 7641 7642 //Trigger the onRender callback 7643 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7644 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7645 7646 var images = findImageInElement(holder); 7647 7648 //Trigger the onBeforeLoad callback 7649 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7650 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7651 7652 iL.loadImage(images, function() { 7653 //Trigger the onAfterLoad callback 7654 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7655 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7656 7657 holder.show().data({ 7658 naturalWidth: (elWidth || container.outerWidth()), 7659 naturalHeight: (elHeight || container.outerHeight()) 7660 }).hide(); 7661 el.remove(); 7662 7663 iL.configureHolder(obj, opt, holder); 7664 }); 7665 7666 break; 7667 } 7668 }, 7669 7670 configureHolder: function(obj, opt, holder) { 7671 var iL = this, 7672 vars = iL.vars, 7673 opts = iL.options; 7674 7675 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 7676 7677 if (opt == "current") 7678 var item = vars.current; 7679 else if (opt == "next") 7680 var opacity = opts.styles.nextOpacity, 7681 item = vars.next; 7682 else 7683 var opacity = opts.styles.prevOpacity, 7684 item = vars.prev; 7685 7686 var api = { 7687 element: holder, 7688 position: item 7689 }; 7690 7691 iL.items[item].options.width = iL.items[item].options.width || 0, 7692 iL.items[item].options.height = iL.items[item].options.height || 0; 7693 7694 if (opt == "current") { 7695 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 7696 holder.css(transform, ''); 7697 if (obj.caption) { 7698 iL.setCaption(obj, holder); 7699 var caption = $('div.ilightbox-caption', holder), 7700 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 7701 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7701Speed); 7702 } 7703 7704 var social = obj.options.social; 7705 if (social) { 7706 iL.setSocial(social, obj.URL, holder); 7707 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 7708 } 7709 7710 //Generate thumbnails 7711 iL.generateThumbnails(); 7712 7713 //Trigger the onShow callback 7714 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7715 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7716 }); 7717 else { 7718 holder.show(); 7719 7720 //Generate thumbnails 7721 iL.generateThumbnails(); 7722 7723 //Trigger the onShow callback 7724 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7725 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7726 } 7727 } else { 7728 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 7729 if (opt == "next") vars.nextLock = false; 7730 else vars.prevLock = false; 7731 7732 //Generate thumbnails 7733 iL.generateThumbnails(); 7734 7735 //Trigger the onShow callback 7736 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7737 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7738 }); 7739 else { 7740 holder.css({ 7741 opacity: opacity 7742 }).show(); 7743 if (opt == "next") vars.nextLock = false; 7744 else vars.prevLock = false; 7745 7746 //Generate thumbnails 7747 iL.generateThumbnails(); 7748 7749 //Trigger the onShow callback 7750 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7751 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7752 } 7753 } 7754 7755 setTimeout(function() { 7756 iL.repositionPhoto(); 7757 }, 0); 7758 }, 7759 7760 generateBoxes: function() { 7761 var iL = this, 7762 vars = iL.vars, 7763 opts = iL.options; 7764 7765 if (opts.infinite && vars.total >= 3) { 7766 if (vars.current == vars.total - 1) vars.next = 0; 7767 if (vars.current == 0) vars.prev = vars.total - 1; 7768 } else opts.infinite = false; 7769 7770 //UNCODE addition 7771 if ( typeof iL.items[vars.current] == 'undefined' ) 7772 vars.current = 0; 7773 7774 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 7775 7776 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 7777 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 7778 }, 7779 7780 generateThumbnails: function() { 7781 var iL = this, 7782 vars = iL.vars, 7783 opts = iL.options, 7784 timeOut = null; 7785 7786 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 7787 var thumbnails = vars.thumbnails, 7788 container = $('div.ilightbox-thumbnails-container', thumbnails), 7789 grid = $('div.ilightbox-thumbnails-grid', container), 7790 i = 0; 7791 7792 grid.removeAttr('style').empty(); 7793 7794 $.each(iL.items, function(key, val) { 7795 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 7796 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 7797 thumb = val.options.thumbnail, 7798 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 7799 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 7800 7801 thumbnail.css({ 7802 opacity: 0 7803 }).addClass(isActive); 7804 7805 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 7806 icon.addClass('ilightbox-thumbnail-video'); 7807 thumbnail.append(icon); 7808 } else if (val.options.icon) { 7809 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 7810 thumbnail.append(icon); 7811 } 7812 7813 if (thumb) iL.loadImage(thumb, function(img) { 7814 i++; 7815 if (img) thumbnail.data({ 7816 naturalWidth: img.width, 7817 naturalHeight: img.height 7818 }).append('<img src="' + thumb + '" border="0" />'); 7819 else thumbnail.data({ 7820 naturalWidth: opts.thumbnails.maxWidth, 7821 naturalHeight: opts.thumbnails.maxHeight 7822 }); 7823 7824 clearTimeout(timeOut); 7825 timeOut = setTimeout(function() { 7826 iL.positionThumbnails(thumbnails, container, grid); 7827 }, 20); 7828 setTimeout(function() { 7829 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 7830 }, i * 20); 7831 }); 7832 7833 grid.append(thumbnail); 7834 }); 7835 iL.vars.dontGenerateThumbs = true; 7836 } 7837 }, 7838
7839 positionThumbnails: function(thumbnails, container, grid) { 7840 var iL = this, 7841 vars = iL.vars, 7842 opts = iL.options, 7843 viewport = getViewport(), 7844 path = opts.path.toLowerCase(); 7845 7846 if (!thumbnails) thumbnails = vars.thumbnails; 7847 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 7848 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 7849 7850 var thumbs = $('.ilightbox-thumbnail', grid), 7851 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 7852 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 7853 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 7854 gridHeight = (path == 'horizontal') ? heightAvail : 0, 7855 active = $('.ilightbox-active', grid), 7856 gridCss = {}, 7857 css = {}; 7858 7859 if (arguments.length < 3) { 7860 thumbs.css({ 7861 opacity: opts.thumbnails.normalOpacity 7862 }); 7863 active.css({ 7864 opacity: opts.thumbnails.activeOpacity 7865 }); 7866 } 7867 7868 thumbs.each(function(i) { 7869 var t = $(this), 7870 data = t.data(), 7871 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 7872 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 7873 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 7874 7875 t.css({ 7876 width: dims.width, 7877 height: dims.height 7878 }); 7879 if (path == 'horizontal') t.css({ 7880 'float': 'left' 7881 }); 7882 7883 (path == 'horizontal') ? ( 7884 gridWidth += t.outerWidth() 7885 ) : ( 7886 gridHeight += t.outerHeight() 7887 ); 7888 }); 7889 7890 gridCss = { 7891 width: gridWidth, 7892 height: gridHeight 7893 }; 7894 7895 grid.css(gridCss); 7896 7897 gridCss = {}; 7898 7899 var gridOffset = grid.offset(), 7900 activeOffset = (active.length) ? active.offset() : { 7901 top: parseInt(heightAvail / 2), 7902 left: parseInt(widthAvail / 2) 7903 }; 7904 7905 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 7906 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 7907 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 7908 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 7909 7910 (path == 'horizontal') ? ( 7911 gridCss.top = 0, 7912 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 7913 ) : ( 7914 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 7915 gridCss.left = 0 7916 ); 7917 7918 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 7919 else grid.css(gridCss); 7920 }, 7921 7922 loadImage: function(image, callback) { 7923 if (!$.isArray(image)) image = [image]; 7924 7925 var iL = this, 7926 length = image.length; 7927 7928 if (length > 0) { 7929 iL.showLoader(); 7930 $.each(image, function(index, value) { 7931 var img = new Image(); 7932 img.onload = function() { 7933 length -= 1; 7934 if (length == 0) { 7935 iL.hideLoader(); 7936 callback(img); 7937 } 7938 }; 7939 img.onerror = img.onabort = function() { 7940 length -= 1; 7941 if (length == 0) { 7942 iL.hideLoader(); 7943 callback(false); 7944 } 7945 }; 7946 img.src = image[index]; 7947 }); 7948 } else callback(false); 7949 }, 7950 7951 patchItemsEvents: function() { 7952 var iL = this, 7953 vars = iL.vars, 7954 clickEvent = supportTouch ? "itap.iL" : "click.iL", 7955 vEvent = supportTouch ? "click.iL" : "itap.iL"; 7956 7957 if (iL.context && iL.selector) { 7958 var $items = $(iL.selector, iL.context); 7959 7960 $(iL.context).on(clickEvent, iL.selector, function() { 7961 var $this = $(this), 7962 //UNCODE addition 7963 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 7964 if (UNCODE.isMobile) { 7965 var isCarousel = $this.closest('.owl-carousel'); 7966 if (isCarousel.length) { 7967 if (isCarousel.hasClass('owl-translating')) return false; 7968 } 7969 } 7970 7971 vars.current = key; 7972 vars.next = iL.items[key + 1] ? key + 1 : null; 7973 vars.prev = iL.items[key - 1] ? key - 1 : null; 7974 7975 //UNCODE addition 7976 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 7977 return false;
7978 7979 iL.addContents(); 7980 iL.patchEvents(); 7981 7982 return false; 7983 }).on(vEvent, iL.selector, function() { 7984 return false; 7985 }); 7986 } else 7987 $.each(iL.itemsObject, function(key, val) { 7988 val.on(clickEvent, function() { 7989 vars.current = key; 7990 vars.next = iL.items[key + 1] ? key + 1 : null; 7991 vars.prev = iL.items[key - 1] ? key - 1 : null; 7992 7993 iL.addContents(); 7994 iL.patchEvents(); 7995 7996 return false; 7997 }).on(vEvent, function() { 7998 return false; 7999 }); 8000 }); 8001 }, 8002 8003 dispatchItemsEvents: function() { 8004 var iL = this, 8005 vars = iL.vars, 8006 opts = iL.options; 8007 8008 if (iL.context && iL.selector) 8009 $(iL.context).off('.iL', iL.selector); 8010 else 8011 $.each(iL.itemsObject, function(key, val) { 8012 val.off('.iL'); 8013 }); 8014 }, 8015 8016 refresh: function() { 8017 var iL = this; 8018 8019 iL.dispatchItemsEvents(); 8020 iL.attachItems(); 8021 iL.normalizeItems(); 8022 iL.patchItemsEvents(); 8023 }, 8024 8025 patchEvents: function() { 8026 var iL = this, 8027 vars = iL.vars, 8028 opts = iL.options, 8029 path = opts.path.toLowerCase(), 8030 holders = $('.ilightbox-holder'), 8031 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 8032 durationThreshold = 1000, 8033 horizontalDistanceThreshold = 8034 verticalDistanceThreshold = 100, 8035 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 8036 8037 $win.bind('resize.iLightBox', function() { 8038 var viewport = getViewport(); 8039 8040 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 8041 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 8042 8043 iL.repositionPhoto(null); 8044 if (supportTouch) { 8045 clearTimeout(vars.setTime); 8046 vars.setTime = setTimeout(function() { 8047 var scrollTop = getScrollXY().y; 8048 window.scrollTo(0, scrollTop - 30); 8049 window.scrollTo(0, scrollTop + 30); 8050 window.scrollTo(0, scrollTop); 8051 }, 2000); 8052 } 8053 if (vars.thumbs) iL.positionThumbnails(); 8054 }).bind('keydown.iLightBox', function(event) { 8055 if (opts.controls.keyboard) { 8056 switch (event.keyCode) { 8057 case 13: 8058 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 8059 break; 8060 case 27: 8061 if (opts.keyboard.esc) iL.closeAction(); 8062 break; 8063 case 37: 8064 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 8065 break; 8066 case 38: 8067 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 8068 break; 8069 case 39: 8070 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 8071 break; 8072 case 40: 8073 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 8074 break; 8075 } 8076 } 8077 }); 8078 8079 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 8080 iL.doFullscreen(); 8081 }); 8082 8083 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 8084 return arr.lastIndexOf(e) === i; 8085 }), 8086 holderEvents = ""; 8087 8088 $.each(holderEventsArr, function(key, val) { 8089 if (key != 0) holderEvents += ' '; 8090 holderEvents += val; 8091 }); 8092 8093 $doc.on(clickEvent, '.ilightbox-overlay', function() { 8094 if (opts.overlay.blur) iL.closeAction(); 8095 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 8096 iL.moveTo('next'); 8097 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 8098 iL.moveTo('prev'); 8099 }).on(clickEvent, '.ilightbox-thumbnail', function() { 8100 var t = $(this), 8101 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 8102 index = thumbs.index(t); 8103 8104 if (index != vars.current) iL.goTo(index); 8105 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8106 var caption = $('div.ilightbox-caption', vars.holder), 8107 social = $('div.ilightbox-social', vars.holder), 8108 fadeSpeed = opts.effects.fadeSpeed; 8109 8110 if (vars.nextLock || vars.prevLock) { 8111 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 8112 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 8113 8114 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 8115 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 8116 } else { 8117 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 8118 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 8119 8120 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 8121 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 8122 } 8123 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 8124 if (e.type == 'mouseenter') vars.lockWheel = true; 8125 else vars.lockWheel = false;
8126 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 8127 var t = $(this); 8128 8129 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 8130 else if (t.hasClass('ilightbox-play')) { 8131 iL.resume(); 8132 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 8133 } else if (t.hasClass('ilightbox-pause')) { 8134 iL.pause(); 8135 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 8136 } else iL.closeAction(); 8137 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 8138 // prevent scrolling 8139 e.preventDefault(); 8140 }); 8141 8142 function mouseMoveHandler(e) { 8143 if (!vars.isMobile) { 8144 if (!vars.mouseID) { 8145 vars.hideableElements.show(); 8146 } 8147 8148 vars.mouseID = clearTimeout(vars.mouseID); 8149 8150 if (buttonsArray.indexOf(e.target) === -1) 8151 vars.mouseID = setTimeout(function() { 8152 vars.hideableElements.hide(); 8153 vars.mouseID = clearTimeout(vars.mouseID); 8154 }, 3000); 8155 } 8156 } 8157 8158 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 8159 8160 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8161 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 8162 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 8163 }); 8164 8165 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'); 8166 8167 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 8168 if (!vars.lockWheel) { 8169 event.preventDefault(); 8170 if (delta < 0) iL.moveTo('next'); 8171 else if (delta > 0) iL.moveTo('prev'); 8172 } 8173 }); 8174 8175 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 8176 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 8177 8178 vars.BODY.addClass('ilightbox-closedhand'); 8179 8180 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 8181 scrollTop = $doc.scrollTop(), 8182 scrollLeft = $doc.scrollLeft(), 8183 offsets = [ 8184 holders.eq(0).offset(), 8185 holders.eq(1).offset(), 8186 holders.eq(2).offset() 8187 ], 8188 offSet = [{ 8189 top: offsets[0].top - scrollTop, 8190 left: offsets[0].left - scrollLeft 8191 }, { 8192 top: offsets[1].top - scrollTop, 8193 left: offsets[1].left - scrollLeft 8194 }, { 8195 top: offsets[2].top - scrollTop, 8196 left: offsets[2].left - scrollLeft 8197 }], 8198 start = { 8199 time: (new Date()).getTime(), 8200 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8201 }, 8202 stop; 8203 8204 function moveEachHandler(i) { 8205 var t = $(this), 8206 offset = offSet[i], 8207 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 8208 8209 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 8210 } 8211 8212 function moveHandler(event) { 8213 8214 if (!start) return; 8215 8216 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 8217 8218 stop = { 8219 time: (new Date()).getTime(), 8220 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8221 }; 8222 8223 holders.each(moveEachHandler); 8224 8225 // prevent scrolling 8226 event.preventDefault(); 8227 } 8228 8229 function repositionHolders() { 8230 holders.each(function() { 8231 var t = $(this), 8232 offset = t.data('offset') || { 8233 top: t.offset().top - scrollTop, 8234 left: t.offset().left - scrollLeft 8235 }, 8236 top = offset.top, 8237 left = offset.left; 8238 8239 t.css(transform, gpuAcceleration).stop().animate({ 8240 top: top, 8241 left: left 8242 }, 500, 'easeOutCirc', function() { 8243 t.css(transform, ''); 8244 }); 8245 }); 8246 } 8247 8248 holders.bind(touchMoveEvent, moveHandler); 8249 $doc.one(touchStopEvent, function(event) { 8250 holders.unbind(touchMoveEvent, moveHandler); 8251 8252 vars.BODY.removeClass('ilightbox-closedhand'); 8253 8254 if (start && stop) { 8255 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 8256 if (start.coords[0] > stop.coords[0]) { 8257 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8258 else { 8259 vars.isSwipe = true; 8260 iL.moveTo('next'); 8261 } 8262 } else { 8263 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8264 else { 8265 vars.isSwipe = true; 8266 iL.moveTo('prev'); 8267 } 8268 } 8269 } 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) { 8270 if (start.coords[1] > stop.coords[1]) { 8271 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8272 else { 8273 vars.isSwipe = true; 8274 iL.moveTo('next'); 8275 } 8276 } else { 8277 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8278 else { 8279 vars.isSwipe = true; 8280 iL.moveTo('prev'); 8281 } 8282 } 8283 } else repositionHolders(); 8284 } 8285 start = stop = undefined; 8286 }); 8287 }); 8288 8289 }, 8290 8291 goTo: function(index) { 8292 var iL = this, 8293 vars = iL.vars, 8294 opts = iL.options, 8295 diff = (index - vars.current); 8296 8297 if (opts.infinite) { 8298 if (index == vars.total - 1 && vars.current == 0) diff = -1; 8299 if (vars.current == vars.total - 1 && index == 0) diff = 1; 8300 } 8301 8302 if (diff == 1) iL.moveTo('next'); 8303 else if (diff == -1) iL.moveTo('prev'); 8304 else { 8305 8306 if (vars.nextLock || vars.prevLock) return false;
8307 8308 //Trigger the onBeforeChange callback 8309 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 8310 8311 if (opts.linkId) { 8312 vars.hashLock = true; 8313 window.location.hash = opts.linkId + '/' + index; 8314 } 8315 8316 if (iL.items[index]) { 8317 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 8318 else iL.vars.lockWheel = false; 8319 8320 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 8321 else vars.lockSwipe = false; 8322 } 8323 8324 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 8325 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 8326 }); 8327 8328 vars.current = index; 8329 vars.next = index + 1; 8330 vars.prev = index - 1; 8331 8332 iL.createUI(); 8333 8334 setTimeout(function() { 8335 iL.generateBoxes(); 8336 }, opts.effects.loadedFadeSpeed + 50); 8337 8338 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 8339 iL.positionThumbnails(); 8340 8341 if (opts.linkId) setTimeout(function() { 8342 vars.hashLock = false; 8343 }, 55); 8344 8345 // Configure arrow buttons 8346 if (!opts.infinite) { 8347 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8348 8349 if (vars.current == 0) { 8350 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8351 } 8352 if (vars.current >= vars.total - 1) { 8353 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8354 } 8355 } 8356 8357 // Reset next cycle timeout 8358 iL.resetCycle(); 8359 8360 //Trigger the onAfterChange callback 8361 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 8362 } 8363 }, 8364 8365 moveTo: function(side) { 8366 var iL = this, 8367 vars = iL.vars, 8368 opts = iL.options, 8369 path = opts.path.toLowerCase(), 8370 viewport = getViewport(), 8371 switchSpeed = opts.effects.switchSpeed; 8372 8373 if (vars.nextLock || vars.prevLock) return false; 8374 else { 8375 8376 var item = (side == "next") ? vars.next : vars.prev; 8377 8378 if (opts.linkId) { 8379 vars.hashLock = true; 8380 window.location.hash = opts.linkId + '/' + item; 8381 } 8382 8383 if (side == "next") { 8384 if (!iL.items[item]) return false; 8385 var firstHolder = vars.nextPhoto, 8386 secondHolder = vars.holder, 8387 lastHolder = vars.prevPhoto, 8388 firstClass = 'ilightbox-prev', 8389 secondClass = 'ilightbox-next'; 8390 } else if (side == "prev") { 8391 if (!iL.items[item]) return false; 8392 var firstHolder = vars.prevPhoto, 8393 secondHolder = vars.holder, 8394 lastHolder = vars.nextPhoto, 8395 firstClass = 'ilightbox-next', 8396 secondClass = 'ilightbox-prev'; 8397 } 8398 8399 //Trigger the onBeforeChange callback 8400 if (typeof opts.callback.onBeforeChange == 'function') 8401 opts.callback.onBeforeChange.call(iL, iL.ui); 8402 8403 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 8404 8405 var captionFirst = $('div.ilightbox-caption', secondHolder), 8406 socialFirst = $('div.ilightbox-social', secondHolder); 8407 8408 if (captionFirst.length) 8409 captionFirst.stop().fadeOut(switchSpeed, function() { 8410 $(this).remove(); 8411 }); 8412 if (socialFirst.length) 8413 socialFirst.stop().fadeOut(switchSpeed, function() { 8414 $(this).remove(); 8415 }); 8416 8417 if (iL.items[item].caption) { 8418 iL.setCaption(iL.items[item], firstHolder); 8419 var caption = $('div.ilightbox-caption', firstHolder), 8420 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 8421 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 8422 } 8423 8424 var social = iL.items[item].options.social; 8425 if (social) { 8426 iL.setSocial(social, iL.items[item].URL, firstHolder); 8427 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 8428 } 8429 8430 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 8431 val.removeClass('ilightbox-next ilightbox-prev'); 8432 }); 8433 8434 var firstOffset = firstHolder.data('offset'), 8435 winW = (viewport.width - (opts.styles.pageOffsetX)), 8436 winH = (viewport.height - (opts.styles.pageOffsetY)), 8437 width = firstOffset.newDims.width, 8438 height = firstOffset.newDims.height, 8439 thumbsOffset = firstOffset.thumbsOffset, 8440 diff = firstOffset.diff, 8441 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8442 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8443 8444 var secondOffset = secondHolder.data('offset'), 8445 object = secondOffset.object; 8446 8447 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8448 var objRatio = width / height; 8449 height = height - vars.captionHeight; 8450 width = height * objRatio; 8451 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 8452 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8453 }*/ 8454 8455 firstHolder.show().css(transform, gpuAcceleration).animate({ 8456 top: top, 8457 left: left, 8458 opacity: 1 8459 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8460 firstHolder.css(transform, ''); 8461 }); 8462 8463 $('div.ilightbox-container', firstHolder).animate({ 8464 width: width, 8465 height: height 8466 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8467 8468 diff = secondOffset.diff; 8469 8470 width = secondOffset.newDims.width, 8471 height = secondOffset.newDims.height; 8472 8473 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8474 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8475 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 8476 8477 if (side == 'prev') 8478 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 8479 else { 8480 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 8481 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8482 } 8483 8484 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8485 var objRatio = width / height; 8486 height = height - vars.captionHeight; 8487 width = height * objRatio; 8488 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 8489 }*/ 8490 8491 $('div.ilightbox-container', secondHolder).animate({ 8492 width: width, 8493 height: height 8494 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8495 8496 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 8497 top: top, 8498 left: left, 8499 opacity: opts.styles.prevOpacity, 8500 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8501 secondHolder.css(transform, ''); 8502
8503 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 8504 iL.positionThumbnails(); 8505 8506 if (iL.items[item]) { 8507 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 8508 else vars.lockWheel = false; 8509 8510 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 8511 else vars.lockSwipe = false; 8512 } 8513 8514 vars.isSwipe = false; 8515 8516 // Remove iframe & video from previous slide 8517 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8518 $('div.ilightbox-container', secondHolder).empty(); 8519 } 8520 8521 if (side == "next") { 8522 vars.nextPhoto = lastHolder, 8523 vars.prevPhoto = secondHolder, 8524 vars.holder = firstHolder; 8525 8526 vars.nextPhoto.hide(); 8527 8528 vars.next = vars.next + 1, 8529 vars.prev = vars.current, 8530 vars.current = vars.current + 1; 8531 8532 if (opts.infinite) { 8533 if (vars.current > vars.total - 1) vars.current = 0; 8534 if (vars.current == vars.total - 1) vars.next = 0; 8535 if (vars.current == 0) vars.prev = vars.total - 1; 8536 } 8537 8538 iL.createUI(); 8539 8540 if (!iL.items[vars.next]) 8541 vars.nextLock = false; 8542 else 8543 iL.loadContent(iL.items[vars.next], 'next'); 8544 } else { 8545 vars.prevPhoto = lastHolder; 8546 vars.nextPhoto = secondHolder; 8547 vars.holder = firstHolder; 8548 8549 vars.prevPhoto.hide(); 8550 8551 vars.next = vars.current; 8552 vars.current = vars.prev; 8553 vars.prev = vars.current - 1; 8554 8555 if (opts.infinite) { 8556 if (vars.current == vars.total - 1) vars.next = 0; 8557 if (vars.current == 0) vars.prev = vars.total - 1; 8558 } 8559 8560 iL.createUI(); 8561 8562 if (!iL.items[vars.prev]) 8563 vars.prevLock = false; 8564 else 8565 iL.loadContent(iL.items[vars.prev], 'prev'); 8566 } 8567 8568 // Add iframe & video content for current slide 8569 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8570 iL.loadContent(iL.items[vars.current], 'current'); 8571 } 8572 8573 if (opts.linkId) setTimeout(function() { 8574 vars.hashLock = false; 8575 }, 55); 8576 8577 // Configure arrow buttons 8578 if (!opts.infinite) { 8579 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8580 8581 if (vars.current == 0) 8582 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8583 if (vars.current >= vars.total - 1) 8584 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8585 } 8586 8587 iL.repositionPhoto(); 8588 8589 // Reset next cycle timeout 8590 iL.resetCycle(); 8591 8592 //Trigger the onAfterChange callback 8593 if (typeof opts.callback.onAfterChange == 'function') 8594 opts.callback.onAfterChange.call(iL, iL.ui); 8595 }); 8596 8597 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 8598 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 8599 8600 lastHolder.css(transform, gpuAcceleration).animate({ 8601 top: top, 8602 left: left, 8603 opacity: opts.styles.nextOpacity 8604 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8605 lastHolder.css(transform, ''); 8606 }).addClass(secondClass); 8607 } 8608 }, 8609 8610 setCaption: function(obj, target) { 8611 var iL = this, 8612 caption = $('<div class="ilightbox-caption"></div>'); 8613 8614 if (obj.caption) { 8615 caption.html(obj.caption); 8616 $('div.ilightbox-container', target).append(caption); 8617 } 8618 }, 8619 8620 normalizeSocial: function(obj, url) { 8621 var iL = this, 8622 vars = iL.vars, 8623 opts = iL.options, 8624 baseURL = window.location.href; 8625 8626 $.each(obj, function(key, value) { 8627 if (!value) 8628 return true; 8629 8630 var item = key.toLowerCase(), 8631 source, text; 8632 8633 switch (item) { 8634 case 'facebook': 8635 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 8636 text = "Share on Facebook"; 8637 break; 8638 case 'twitter': 8639 source = "http://twitter.com/home?status={URL}", 8640 text = "Share on Twitter"; 8641 break; 8642 case 'googleplus': 8643 source = "https://plus.google.com/share?url={URL}", 8644 text = "Share on Google+"; 8645 break; 8646 case 'delicious': 8647 source = "http://delicious.com/post?url={URL}", 8648 text = "Share on Delicious"; 8649 break; 8650 case 'digg': 8651 source = "http://digg.com/submit?phase=2&url={URL}", 8652 text = "Share on Digg"; 8653 break; 8654 case 'reddit': 8655 source = "http://reddit.com/submit?url={URL}", 8656 text = "Share on reddit"; 8657 break; 8658 } 8659 8660 obj[key] = { 8661 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 8662 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 8663 text: value.text || text || "Share on " + key, 8664 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 8665 height: value.height || 360 8666 }; 8667 8668 }); 8669 8670 return obj; 8671 }, 8672 8673 setSocial: function(obj, url, target) { 8674 var iL = this, 8675 socialBar = $('<div class="ilightbox-social"></div>'), 8676 buttons = '<ul>'; 8677 8678 obj = iL.normalizeSocial(obj, url); 8679 8680 $.each(obj, function(key, value) { 8681 var item = key.toLowerCase(), 8682 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, '+')); 8683 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>'; 8684 }); 8685 8686 buttons += '</ul>'; 8687 8688 socialBar.html(buttons); 8689 $('div.ilightbox-container', target).append(socialBar); 8690 }, 8691 8692 fullScreenAction: function() { 8693 var iL = this, 8694 vars = iL.vars; 8695 8696 if (fullScreenApi.supportsFullScreen) { 8697 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 8698 else fullScreenApi.requestFullScreen(document.documentElement); 8699 } else { 8700 iL.doFullscreen(); 8701 } 8702 }, 8703 8704 doFullscreen: function() { 8705 var iL = this, 8706 vars = iL.vars, 8707 viewport = getViewport(), 8708 opts = iL.options; 8709 8710 if (opts.fullAlone) { 8711 var currentHolder = vars.holder, 8712 current = iL.items[vars.current], 8713 windowWidth = viewport.width, 8714 windowHeight = viewport.height, 8715 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 8716 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8717 8718 if (!vars.isInFullScreen) { 8719 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 8720 vars.overlay.css({ 8721 opacity: 1 8722 }); 8723 8724 $.each(hideElements, function(i, element) { 8725 element.hide(); 8726 }); 8727 8728 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 8729 8730 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8731 naturalWidthOld: currentHolder.data('naturalWidth'), 8732 naturalHeightOld: currentHolder.data('naturalHeight'), 8733 naturalWidth: windowWidth, 8734 naturalHeight: windowHeight 8735 }); 8736 else { 8737 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 8738 newWidth = windowWidth, 8739 newHeight = windowHeight, 8740 width = currentHolder.data('naturalWidth'), 8741 height = currentHolder.data('naturalHeight'); 8742 8743 if (viewport.toLowerCase() == 'fill') { 8744 newHeight = (newWidth / width) * height; 8745 8746 if (newHeight < windowHeight) { 8747 newWidth = (windowHeight / height) * width, 8748 newHeight = windowHeight; 8749 } 8750 } else if (viewport.toLowerCase() == 'fit') { 8751 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 8752 8753 newWidth = dims.width, 8754 newHeight = dims.height; 8755 } else if (viewport.toLowerCase() == 'stretch') { 8756 newWidth = newWidth, 8757 newHeight = newHeight; 8758 } else { 8759 var scale = (width > newWidth || height > newHeight) ? true : false, 8760 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 8761 newWidth = dims.width, 8762 newHeight = dims.height; 8763 } 8764 8765 currentHolder.data({ 8766 naturalWidthOld: currentHolder.data('naturalWidth'), 8767 naturalHeightOld: currentHolder.data('naturalHeight'), 8768 naturalWidth: newWidth, 8769 naturalHeight: newHeight 8770 }); 8771 } 8772 8773 $.each(elements, function(key, val) { 8774 val.addClass('ilightbox-fullscreen'); 8775 }); 8776 8777 //Trigger the onEnterFullScreen callback 8778 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 8779 } else { 8780 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 8781 vars.overlay.css({ 8782 opacity: iL.options.overlay.opacity 8783 }); 8784 8785 $.each(hideElements, function(i, element) { 8786 element.show(); 8787 }); 8788 8789 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 8790 8791 currentHolder.data({ 8792 naturalWidth: currentHolder.data('naturalWidthOld'), 8793 naturalHeight: currentHolder.data('naturalHeightOld'), 8794 naturalWidthOld: null, 8795 naturalHeightOld: null 8796 }); 8797 8798 $.each(elements, function(key, val) { 8799 val.removeClass('ilightbox-fullscreen'); 8800 }); 8801 8802 //Trigger the onExitFullScreen callback 8803 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 8804 } 8805 } else { 8806 if (!vars.isInFullScreen) vars.isInFullScreen = true; 8807 else vars.isInFullScreen = false; 8808 } 8809 iL.repositionPhoto(true); 8810 }, 8811 8812 closeAction: function() { 8813 var iL = this, 8814 vars = iL.vars, 8815 opts = iL.options; 8816 8817 $win.unbind('.iLightBox'); 8818 $doc.off('.iLightBox'); 8819 8820 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 8821 8822 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 8823 8824 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 8825 vars.overlay.remove(); 8826 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8827 }); 8828 else { 8829 vars.overlay.remove(); 8830 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8831 } 8832 8833 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8834 8835 $.each(fadeOuts, function(i, element) { 8836 element.removeAttr('style').remove(); 8837 }); 8838 8839 vars.dontGenerateThumbs = vars.isInFullScreen = false; 8840 8841 window.iLightBox = null; 8842 8843 if (opts.linkId) { 8844 vars.hashLock = true; 8845 removeHash(); 8846 setTimeout(function() { 8847 vars.hashLock = false; 8848 }, 55); 8849 } 8850 8851 //Trigger the onHide callback 8852 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 8853 }, 8854 8855 repositionPhoto: function() { 8856 var iL = this, 8857 vars = iL.vars, 8858 opts = iL.options, 8859 path = opts.path.toLowerCase(), 8860 viewport = getViewport(), 8861 winWidth = viewport.width, 8862 winHeight = viewport.height; 8863 8864 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 8865 8866 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 8867 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 8868 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 8869 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 8870 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, 8871 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))); 8872 8873 var elObject = { 8874 type: 'current', 8875 width: width, 8876 height: height, 8877 item: iL.items[vars.current], 8878 offsetW: offsetW, 8879 offsetH: offsetH,
8880 thumbsOffsetW: thumbsOffsetW, 8881 thumbsOffsetH: thumbsOffsetH, 8882 animate: arguments.length, 8883 holder: vars.holder 8884 }; 8885 8886 iL.repositionEl(elObject); 8887 8888 if (iL.items[vars.next]) { 8889 elObject = $.extend(elObject, { 8890 type: 'next', 8891 item: iL.items[vars.next], 8892 offsetX: opts.styles.nextOffsetX, 8893 offsetY: opts.styles.nextOffsetY, 8894 holder: vars.nextPhoto 8895 }); 8896 8897 iL.repositionEl(elObject); 8898 } 8899 8900 if (iL.items[vars.prev]) { 8901 elObject = $.extend(elObject, { 8902 type: 'prev', 8903 item: iL.items[vars.prev], 8904 offsetX: opts.styles.nextOffsetX, 8905 offsetY: opts.styles.prevOffsetY, 8906 holder: vars.prevPhoto 8907 }); 8908 8909 iL.repositionEl(elObject); 8910 } 8911 8912 var loaderCss = (path == "horizontal") ? { 8913 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 8914 } : { 8915 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 8916 }; 8917 vars.loader.css(loaderCss); 8918 }, 8919 8920 repositionEl: function(obj) { 8921 var iL = this, 8922 vars = iL.vars, 8923 opts = iL.options, 8924 path = opts.path.toLowerCase(), 8925 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 8926 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 8927 itemParent = obj.item, 8928 item = obj.item.options, 8929 holder = obj.holder, 8930 offsetX = obj.offsetX || 0, 8931 offsetY = obj.offsetY || 0, 8932 thumbsOffsetW = obj.thumbsOffsetW, 8933 thumbsOffsetH = obj.thumbsOffsetH; 8934 8935 if (obj.type == 'current') { 8936 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); 8937 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); 8938 } else { 8939 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 8940 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 8941 } 8942 8943 heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 8944 8945 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 8946 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 8947 8948 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 8949 width: width, 8950 height: height 8951 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 8952 newDims = $.extend({}, dims, {}); 8953 8954 if (obj.type == 'prev' || obj.type == 'next') 8955 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 8956 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 8957 else 8958 width = dims.width, 8959 height = dims.height; 8960 8961 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 8962 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() || 0)) / 2); 8963 8964 switch (obj.type) { 8965 case 'current': 8966 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 8967 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8968 break; 8969
8970 case 'next': 8971 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 8972 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 8973 break; 8974 8975 case 'prev': 8976 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 8977 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8978 break; 8979 } 8980 8981 holder.data('offset', { 8982 top: top, 8983 left: left, 8984 newDims: newDims, 8985 diff: { 8986 W: widthDiff, 8987 H: heightDiff 8988 }, 8989 thumbsOffset: { 8990 W: thumbsOffsetW, 8991 H: thumbsOffsetH 8992 }, 8993 object: obj 8994 }); 8995 8996 var opacityMobile; 8997 if ( isMobile ) { 8998 opacityMobile = { 8999 opacity: 1, 9000 top: top, 9001 left: left 9002 }; 9003 } else { 9004 opacityMobile = { 9005 top: top, 9006 left: left 9007 }; 9008 } 9009 9010 if (obj.animate > 0 && opts.effects.reposition) { 9011 holder.css(transform, gpuAcceleration).stop().animate( 9012 opacityMobile, 9013 opts.effects.repositionSpeed, 'easeOutCirc', function() { 9014 holder.css(transform, ''); 9015 }); 9016 $('div.ilightbox-container', holder).stop().animate({ 9017 width: width, 9018 height: height 9019 }, opts.effects.repositionSpeed, 'easeOutCirc'); 9020 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 9021 width: width 9022 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 9023 $(this).css('overflow', 'visible'); 9024 }); 9025 } else { 9026 holder.css(opacityMobile); 9027 $('div.ilightbox-container', holder).css({ 9028 width: width, 9029 height: height 9030 }); 9031 $('div.ilightbox-inner-toolbar', holder).css({ 9032 width: width 9033 }); 9034 } 9035 }, 9036 9037 9038 resume: function(priority) { 9039 var iL = this, 9040 vars = iL.vars, 9041 opts = iL.options; 9042 9043 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 9044 return; 9045 } 9046 9047 vars.isPaused = 0; 9048 9049 if (vars.cycleID) { 9050 vars.cycleID = clearTimeout(vars.cycleID); 9051 } 9052 9053 vars.cycleID = setTimeout(function() { 9054 if (vars.current == vars.total - 1) iL.goTo(0); 9055 else iL.moveTo('next'); 9056 }, opts.slideshow.pauseTime); 9057 }, 9058 9059 pause: function(priority) { 9060 var iL = this, 9061 vars = iL.vars, 9062 opts = iL.options; 9063 9064 if (priority < vars.isPaused) { 9065 return; 9066 } 9067 9068 vars.isPaused = priority || 100; 9069 9070 if (vars.cycleID) { 9071 vars.cycleID = clearTimeout(vars.cycleID); 9072 } 9073 }, 9074 9075 resetCycle: function() { 9076 var iL = this, 9077 vars = iL.vars, 9078 opts = iL.options; 9079 9080 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 9081 iL.resume(); 9082 } 9083 }, 9084 9085 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 9086 var iL = this; 9087 9088 if (!width) factor = height / height_old; 9089 else if (!height) factor = width / width_old; 9090 else factor = min(width / width_old, height / height_old); 9091 9092 if (!thumb) { 9093 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 9094 else if (factor < iL.options.minScale) factor = iL.options.minScale; 9095 } 9096 9097 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 9098 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 9099 9100 return { 9101 width: final_width, 9102 height: final_height, 9103 ratio: factor 9104 }; 9105 }, 9106 9107 setOption: function(options) { 9108 var iL = this; 9109 9110 iL.options = $.extend(true, iL.options, options || {}); 9111 iL.refresh(); 9112 }, 9113 9114 availPlugins: function() { 9115 var iL = this, 9116 testEl = document.createElement("video"); 9117 9118 iL.plugins = { 9119 flash: !isMobile, 9120 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 9121 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 9122 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 9123 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 9124 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 9125 }; 9126 }, 9127 9128 addContent: function(element, obj) { 9129 var iL = this, 9130 el; 9131 9132 switch (obj.type) { 9133 case 'video': 9134 var HTML5 = false, 9135 videoType = obj.videoType, 9136 html5video = obj.options.html5video; 9137 9138 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 9139 obj.ext = 'mp4', 9140 obj.URL = html5video.h264 || obj.URL; 9141 else if (html5video.webm && iL.plugins.html5WebM) 9142 obj.ext = 'webm', 9143 obj.URL = html5video.webm || obj.URL; 9144 else if (html5video.ogg && iL.plugins.html5Vorbis) 9145 obj.ext = 'ogv', 9146 obj.URL = html5video.ogg || obj.URL; 9147 9148 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 9149 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 9150 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 9151 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 9152 9153 if (HTML5) { 9154 el = $('<video />
9154', { 9155 "width": "100%", 9156 "height": "100%", 9157 "preload": html5video.preload, 9158 "autoplay": html5video.autoplay, 9159 "poster": html5video.poster, 9160 "controls": html5video.controls 9161 }).append($('<source />', { 9162 "src": obj.URL, 9163 "type": videoType 9164 })); 9165 } else { 9166 if (!iL.plugins.quicktime) el = $('<span />', { 9167 "class": "ilightbox-alert", 9168 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 9169 }); 9170 else { 9171 9172 el = $('<object />', { 9173 "type": "video/quicktime", 9174 "pluginspage": pluginspages.quicktime 9175 }).attr({ 9176 "data": obj.URL, 9177 "width": "100%", 9178 "height": "100%" 9179 }).append($('<param />', { 9180 "name": "src", 9181 "value": obj.URL 9182 })).append($('<param />', { 9183 "name": "autoplay", 9184 "value": "false" 9185 })).append($('<param />', { 9186 "name": "loop", 9187 "value": "false" 9188 })).append($('<param />', { 9189 "name": "scale", 9190 "value": "tofit" 9191 })); 9192 9193 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 9194 } 9195 } 9196 9197 break; 9198 9199 case 'flash': 9200 if (!iL.plugins.flash) el = $('<span />', { 9201 "class": "ilightbox-alert", 9202 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 9203 }); 9204 else { 9205 var flashvars = "", 9206 i = 0; 9207 9208 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 9209 if (i != 0) flashvars += "&"; 9210 flashvars += k + "=" + encodeURIComponent(v); 9211 i++; 9212 }); 9213 else flashvars = null; 9214 9215 el = $('<embed />').attr({ 9216 "type": "application/x-shockwave-flash", 9217 "src": obj.URL, 9218 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9219 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9220 "quality": "high", 9221 "bgcolor": "#000000", 9222 "play": "true", 9223 "loop": "true", 9224 "menu": "true", 9225 "wmode": "transparent", 9226 "scale": "showall", 9227 "allowScriptAccess": "always", 9228 "allowFullScreen": "true", 9229 "flashvars": flashvars, 9230 "fullscreen": "yes" 9231 }); 9232 } 9233 9234 break; 9235 9236 case 'iframe': 9237 el = $('<iframe />').attr({ 9238 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9239 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9240 src: obj.URL, 9241 frameborder: 0, 9242 'hspace': 0, 9243 'vspace': 0, 9244 'scrolling': supportTouch ? 'auto' : 'scroll', 9245 'webkitAllowFullScreen': '', 9246 'mozallowfullscreen': '', 9247 'allowFullScreen': '' 9248 }); 9249 9250 break; 9251 9252 case 'inline': 9253 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 9254 9255 break; 9256 9257 case 'html': 9258 var object = obj.URL, 9259 el; 9260 9261 if (object[0].nodeName) { 9262 el = $('<div class="ilightbox-wrapper"></div>').html(object); 9263 } else { 9264 var dom = $(obj.URL), 9265 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 9266 el = $('<div class="ilightbox-wrapper"></div>').html(html); 9267 } 9268 9269 break; 9270 } 9271 9272 $('div.ilightbox-container', element).empty().html(el); 9273 9274 // For fixing Chrome about just playing the video for first time 9275 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 9276 var src = el[0].currentSrc + '?' + floor(random() * 30000); 9277 el[0].currentSrc = src; 9278 el[0].src = src; 9279 }); 9280 9281 return el; 9282 }, 9283 9284 ogpRecognition: function(obj, callback) { 9285 var iL = this, 9286 url = obj.URL; 9287 9288 iL.showLoader(); 9289 doAjax(url, function(data) { 9290 iL.hideLoader(); 9291 if (data) { 9292 var object = new Object(); 9293 9294 object.length = false, 9295 object.url = data.url; 9296 9297 if (data.status == 200) { 9298 var result = data.results, 9299 type = result.type, 9300 source = result.source; 9301 9302 object.source = source.src, 9303 object.width = source.width && parseInt(source.width) || 0, 9304 object.height = source.height && parseInt(source.height) || 0, 9305 object.type = type, 9306 object.thumbnail = source.thumbnail || result.images && result.images[0], 9307 object.html5video = result.html5video || {}, 9308 object.length = true; 9309 9310 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 9311 else if (source.type.indexOf("video/") != -1) object.type = "video"; 9312 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 9313 else if (source.type.indexOf("image/") != -1) object.type = "image"; 9314 9315 } else if (typeof data.response != 'undefined') 9316 throw data.response; 9317 9318 callback.call(this, object.length ? object : false); 9319 } 9320 }); 9321 }, 9322 9323 hashChangeHandler: function(url) { 9324 var iL = this, 9325 vars = iL.vars, 9326 opts = iL.options, 9327 URL = url || window.location.href, 9328 hash = parseURI(URL).hash, 9329 split = hash.split('/'), 9330 index = split[1]; 9331 9332 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 9333 9334 if (index) { 9335 var target = split[1] || 0; 9336 if (iL.items[target]) {
9337 var overlay = $('.ilightbox-overlay'); 9338 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 9339 iL.goTo(target); 9340 } else { 9341 iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click'); 9342 //iL.goTo(target); 9343 } 9344 } else { 9345 var overlay = $('.ilightbox-overlay'); 9346 if (overlay.length) iL.closeAction(); 9347 } 9348 } else { 9349 var overlay = $('.ilightbox-overlay'); 9350 if (overlay.length) iL.closeAction(); 9351 } 9352 } 9353 }; 9354 9355 /** 9356 * Parse style to pixels. 9357 * 9358 * @param {Object} $element jQuery object with element. 9359 * @param {Property} property CSS property to get the pixels from. 9360 * 9361 * @return {Int} 9362 */ 9363 function getPixel($element, property) { 9364 return parseInt($element.css(property), 10) || 0; 9365 } 9366 9367 /** 9368 * Make sure that number is within the limits. 9369 * 9370 * @param {Number} number 9371 * @param {Number} min 9372 * @param {Number} max 9373 * 9374 * @return {Number} 9375 */ 9376 function within(number, min, max) { 9377 return number < min ? min : number > max ? max : number; 9378 } 9379 9380 /** 9381 * Get viewport/window size (width and height). 9382 * 9383 * @return {Object} 9384 */ 9385 function getViewport() { 9386 var e = window, 9387 a = 'inner'; 9388 if (!('innerWidth' in window)) { 9389 a = 'client'; 9390 e = document.documentElement || document.body; 9391 } 9392 return { 9393 width: e[a + 'Width'], 9394 height: e[a + 'Height'] 9395 } 9396 } 9397 9398 /** 9399 * Remove hash tag from the URL 9400 * 9401 * @return {Void} 9402 */ 9403 function removeHash() { 9404 var scroll = getScrollXY(); 9405 9406 //UNCODE change 9407 //window.location.hash = ""; 9408 history.pushState("", document.title, window.location.pathname + window.location.search); 9409 9410 // Restore the scroll offset, should be flicker free 9411 window.scrollTo(scroll.x, scroll.y); 9412 } 9413 9414 /** 9415 * Do the ajax requests with callback. 9416 * 9417 * @param {String} url 9418 * @param {Function} callback 9419 * 9420 * @return {Void} 9421 */ 9422 function doAjax(url, callback) { 9423 var url = "//ilightbox.net/getSource/jsonp.php?url=" + encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A'); 9424 $.ajax({ 9425 url: url, 9426 dataType: 'jsonp' 9427 }); 9428 9429 iLCallback = function(data) { 9430 callback.call(this, data); 9431 }; 9432 } 9433 9434 /** 9435 * Find image from DOM elements 9436 * 9437 * @param {Element} element 9438 * 9439 * @return {Void} 9440 */ 9441 function findImageInElement(element) { 9442 var elements = $('*', element), 9443 imagesArr = new Array(); 9444 9445 elements.each(function() { 9446 var url = "", 9447 element = this; 9448 9449 if ($(element).css("background-image") != "none") { 9450 url = $(element).css("background-image"); 9451 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 9452 url = $(element).attr("src"); 9453 } 9454 9455 if (url.indexOf("gradient") == -1) { 9456 url = url.replace(/url\(\"/g, ""); 9457 url = url.replace(/url\(/g, ""); 9458 url = url.replace(/\"\)/g, ""); 9459 url = url.replace(/\)/g, ""); 9460 9461 var urls = url.split(","); 9462 9463 for (var i = 0; i < urls.length; i++) { 9464 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 9465 var extra = ""; 9466 if (browser.msie && browser.version < 9) { 9467 extra = "?" + floor(random() * 3000); 9468 } 9469 imagesArr.push(urls[i] + extra); 9470 } 9471 } 9472 } 9473 }); 9474 9475 return imagesArr; 9476 } 9477 9478 /** 9479 * Get file extension. 9480 * 9481 * @param {String} URL 9482 * 9483 * @return {String} 9484 */ 9485 function getExtension(URL) { 9486 if (URL !== null) { 9487 var ext = URL.split('.').pop().toLowerCase(), 9488 extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : ''; 9489 9490 return ext.replace(extra, ''); 9491 } 9492 } 9493 9494 /** 9495 * Get type via extension. 9496 * 9497 * @param {String} URL 9498 * 9499 * @return {String} 9500 */ 9501 function getTypeByExtension(URL) { 9502 var type, 9503 ext = getExtension(URL); 9504 9505 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 9506 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 9507 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 9508 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 9509 else type = 'iframe'; 9510 9511 return type; 9512 } 9513 9514 /** 9515 * Return value from percent of a number. 9516 * 9517 * @param {Number} percent 9518 * @param {Number} total 9519 * 9520 * @return {Number} 9521 */ 9522 function percentToValue(percent, total) { 9523 return parseInt((total / 100) * percent); 9524 } 9525 9526 /** 9527 * A JavaScript equivalent of PHP’s parse_url. 9528 * 9529 * @param {String} url The URL to parse. 9530 * 9531 * @return {Mixed} 9532 */ 9533 function parseURI(url) { 9534 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 9535 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 9536 return (m ? { 9537 href: m[0] || '', 9538 protocol: m[1] || '', 9539 authority: m[2] || '', 9540 host: m[3] || '', 9541 hostname: m[4] || '', 9542 port: m[5] || '', 9543 pathname: m[6] || '', 9544 search: m[7] || '', 9545 hash: m[8] || '' 9546 } : null); 9547 } 9548 9549 /** 9550 * Gets the absolute URI. 9551 * 9552 * @param {String} href The relative URL. 9553 * @param {String} base The base URL. 9554 * 9555 * @return {String} The absolute URL. 9556 */ 9557 function absolutizeURI(base, href) { // RFC 3986 9558 var iL = this; 9559 9560 function removeDotSegments(input) { 9561 var output = []; 9562 input.replace(/^(\.\.?(\/|$))+/, '') 9563 .replace(/\/(\.(\/|$))+/g, '/') 9564 .replace(/\/\.\.$/, '/../') 9565 .replace(/\/?[^\/]*/g, function(p) { 9566 if (p === '/..') { 9567 output.pop(); 9568 } else { 9569 output.push(p); 9570 } 9571 }); 9572 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 9573 } 9574 9575 href = parseURI(href || ''); 9576 base = parseURI(base || ''); 9577 9578 return !href || !base ? null : (href.protocol || base.protocol) + 9579 (href.protocol || href.authority ? href.authority : base.authority) + 9580 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)) + 9581 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 9582 href.hash; 9583 } 9584 9585 /** 9586 * A JavaScript equivalent of PHP’s version_compare. 9587 * 9588 * @param {String} v1 9589 * @param {String} v2 9590 * @param {String} operator
9591 * 9592 * @return {Boolean} 9593 */ 9594 function version_compare(v1, v2, operator) { 9595 this.php_js = this.php_js || {}; 9596 this.php_js.ENV = this.php_js.ENV || {}; 9597 var i = 0, 9598 x = 0, 9599 compare = 0, 9600 vm = { 9601 'dev': -6, 9602 'alpha': -5, 9603 'a': -5, 9604 'beta': -4, 9605 'b': -4, 9606 'RC': -3, 9607 'rc': -3, 9608 '#': -2, 9609 'p': 1, 9610 'pl': 1 9611 }, 9612 prepVersion = function(v) { 9613 v = ('' + v).replace(/[_\-+]/g, '.'); 9614 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 9615 return (!v.length ? [-8] : v.split('.')); 9616 }, 9617 numVersion = function(v) { 9618 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 9619 }; 9620 v1 = prepVersion(v1); 9621 v2 = prepVersion(v2); 9622 x = max(v1.length, v2.length); 9623 for (i = 0; i < x; i++) { 9624 if (v1[i] == v2[i]) { 9625 continue; 9626 } 9627 v1[i] = numVersion(v1[i]); 9628 v2[i] = numVersion(v2[i]); 9629 if (v1[i] < v2[i]) { 9630 compare = -1; 9631 break; 9632 } else if (v1[i] > v2[i]) { 9633 compare = 1; 9634 break; 9635 } 9636 } 9637 if (!operator) { 9638 return compare; 9639 } 9640 9641 switch (operator) { 9642 case '>': 9643 case 'gt': 9644 return (compare > 0); 9645 case '>=': 9646 case 'ge': 9647 return (compare >= 0); 9648 case '<=': 9649 case 'le': 9650 return (compare <= 0); 9651 case '==': 9652 case '=': 9653 case 'eq': 9654 return (compare === 0); 9655 case '<>': 9656 case '!=': 9657 case 'ne': 9658 return (compare !== 0); 9659 case '': 9660 case '<': 9661 case 'lt': 9662 return (compare < 0); 9663 default: 9664 return null; 9665 } 9666 } 9667 9668 9669 // Begin the iLightBox plugin 9670 $.fn.iLightBox = function() { 9671 9672 var args = arguments, 9673 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 9674 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 9675 9676 if (!opt) opt = {}; 9677 9678 // Default options. Play carefully. 9679 var options = $.extend(true, { 9680 attr: 'href', 9681 path: 'vertical', 9682 skin: 'dark', 9683 linkId: false, 9684 infinite: false, 9685 startFrom: 0, 9686 randomStart: false, 9687 keepAspectRatio: true, 9688 maxScale: 1, 9689 minScale: .2, 9690 innerToolbar: false, 9691 smartRecognition: false, 9692 mobileOptimizer: true, 9693 fullAlone: true, 9694 fullViewPort: null, 9695 fullStretchTypes: 'flash, video', 9696 overlay: { 9697 blur: true, 9698 opacity: .85 9699 }, 9700 controls: { 9701 arrows: false, 9702 slideshow: false, 9703 toolbar: true, 9704 fullscreen: true, 9705 thumbnail: true, 9706 keyboard: true, 9707 mousewheel: true, 9708 swipe: true 9709 }, 9710 keyboard: { 9711 left: true, // previous 9712 right: true, // next 9713 up: true, // previous 9714 down: true, // next 9715 esc: true, // close 9716 shift_enter: true // fullscreen 9717 }, 9718 show: { 9719 effect: true, 9720 speed: 300, 9721 title: true 9722 }, 9723 hide: { 9724 effect: true, 9725 speed: 300 9726 }, 9727 caption: { 9728 start: true, 9729 show: 'mouseenter', 9730 hide: 'mouseleave' 9731 }, 9732 social: { 9733 start: true, 9734 show: 'mouseenter', 9735 hide: 'mouseleave',
9736 buttons: false 9737 }, 9738 styles: { 9739 pageOffsetX: 0, 9740 pageOffsetY: 0, 9741 nextOffsetX: 45, 9742 nextOffsetY: 0, 9743 nextOpacity: 1, 9744 nextScale: 1, 9745 prevOffsetX: 45, 9746 prevOffsetY: 0, 9747 prevOpacity: 1, 9748 prevScale: 1 9749 }, 9750 thumbnails: { 9751 maxWidth: 120, 9752 maxHeight: 80, 9753 normalOpacity: 1, 9754 activeOpacity: .6 9755 }, 9756 effects: { 9757 reposition: true, 9758 repositionSpeed: 200, 9759 switchSpeed: 500, 9760 loadedFadeSpeed: 180, 9761 fadeSpeed: 200 9762 }, 9763 slideshow: { 9764 pauseTime: 5000, 9765 pauseOnHover: false, 9766 startPaused: true 9767 }, 9768 text: { 9769 close: "Press Esc to close", 9770 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 9771 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 9772 slideShow: "Slideshow", 9773 next: "Next", 9774 previous: "Previous" 9775 }, 9776 errors: { 9777 loadImage: "An error occurred when trying to load photo.", 9778 loadContents: "An error occurred when trying to load contents.", 9779 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 9780 }, 9781 ajaxSetup: { 9782 url: '', 9783 beforeSend: function(jqXHR, settings) {}, 9784 cache: false, 9785 complete: function(jqXHR, textStatus) {}, 9786 crossDomain: false, 9787 error: function(jqXHR, textStatus, errorThrown) {}, 9788 success: function(data, textStatus, jqXHR) {}, 9789 global: true, 9790 ifModified: false, 9791 username: null, 9792 password: null, 9793 type: 'GET' 9794 }, 9795 callback: {} 9796 }, opt); 9797 9798 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 9799 9800 items = $.isArray(items) ? items : new Array(); 9801 9802 if (typeof args[0] == 'string') items[0] = args[0]; 9803 9804 if (version_compare($.fn.jquery, '1.8', '>=')) { 9805 var iLB = new iLightBox($(this), options, items, instant); 9806 return { 9807 close: function() { 9808 iLB.closeAction(); 9809 }, 9810 fullscreen: function() { 9811 iLB.fullScreenAction(); 9812 }, 9813 moveNext: function() { 9814 iLB.moveTo('next'); 9815 }, 9816 movePrev: function() { 9817 iLB.moveTo('prev'); 9818 }, 9819 goTo: function(index) { 9820 iLB.goTo(index); 9821 }, 9822 refresh: function() { 9823 iLB.refresh(); 9824 }, 9825 reposition: function() { 9826 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 9827 }, 9828 setOption: function(options) { 9829 iLB.setOption(options); 9830 }, 9831 destroy: function() { 9832 iLB.closeAction(); 9833 iLB.dispatchItemsEvents(); 9834 } 9835 }; 9836 } else { 9837 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 9838 } 9839 9840 }; 9841 9842 9843 $.iLightBox = function() { 9844 return $.fn.iLightBox(arguments[0], arguments[1]); 9845 }; 9846 9847 9848 $.extend($.easing, { 9849 easeInCirc: function(x, t, b, c, d) { 9850 return -c * (sqrt(1 - (t /= d) * t) - 1) + b; 9851 }, 9852 easeOutCirc: function(x, t, b, c, d) { 9853 return c * sqrt(1 - (t = t / d - 1) * t) + b; 9854 }, 9855 easeInOutCirc: function(x, t, b, c, d) { 9856 if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; 9857 return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b; 9858 } 9859 }); 9860 9861 function getScrollXY() { 9862 var scrOfX = 0, 9863 scrOfY = 0; 9864 if (typeof(window.pageYOffset) == 'number') { 9865 //Netscape compliant 9866 scrOfY = window.pageYOffset; 9867 scrOfX = window.pageXOffset; 9868 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 9869 //DOM compliant 9870 scrOfY = document.body.scrollTop; 9871 scrOfX = document.body.scrollLeft; 9872 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 9873 //IE6 standards compliant mode 9874 scrOfY = document.documentElement.scrollTop; 9875 scrOfX = document.documentElement.scrollLeft; 9876 } 9877 return { 9878 x: scrOfX, 9879 y: scrOfY 9880 }; 9881 } 9882 9883 (function() { 9884 // add new event shortcuts 9885 $.each(("touchstart touchmove touchend " + 9886 "tap taphold " + 9887 "swipe swipeleft swiperight " + 9888 "scrollstart scrollstop").split(" "), function(i, name) { 9889 9890 $.fn[name] = function(fn) { 9891 return fn ? this.bind(name, fn) : this.trigger(name); 9892 }; 9893 9894 // jQuery < 1.8 9895 // if ($.attrFn) { 9896 // $.attrFn[name] = true; 9897 // } 9898 }); 9899 9900 var tapSettings = { 9901 startEvent: 'touchstart.iTap', 9902 endEvent: 'touchend.iTap' 9903 }; 9904 9905 // tap Event: 9906 $.event.special.itap = { 9907 setup: function() { 9908 9909 var self = this, 9910 $self = $(this), 9911 start, stop; 9912 9913 $self.bind(tapSettings.startEvent, function(event) { 9914 start = getScrollXY(); 9915 9916 $self.one(tapSettings.endEvent, function(event) { 9917 stop = getScrollXY(); 9918 9919 var orgEvent = event || window.event; 9920 event = $.event.fix(orgEvent); 9921 event.type = "itap"; 9922 9923 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 9924 9925 start = stop = undefined; 9926 }); 9927 }); 9928 }, 9929 9930 teardown: function() { 9931 $(this).unbind(tapSettings.startEvent); 9932 } 9933 }; 9934 }()); 9935 9936 9937 //Fullscreen API 9938 (function() { 9939 fullScreenApi = { 9940 supportsFullScreen: false, 9941 isFullScreen: function() { 9942 return false;
9943 }, 9944 requestFullScreen: function() {}, 9945 cancelFullScreen: function() {}, 9946 fullScreenEventName: '', 9947 prefix: '' 9948 }, 9949 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 9950 9951 // check for native support 9952 if (typeof document.cancelFullScreen != 'undefined') { 9953 fullScreenApi.supportsFullScreen = true; 9954 } else { 9955 // check for fullscreen support by vendor prefix 9956 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 9957 fullScreenApi.prefix = browserPrefixes[i]; 9958 9959 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 9960 fullScreenApi.supportsFullScreen = true; 9961 9962 break; 9963 } 9964 } 9965 } 9966 9967 // update methods to do something useful 9968 if (fullScreenApi.supportsFullScreen) { 9969 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 9970 9971 fullScreenApi.isFullScreen = function() { 9972 switch (this.prefix) { 9973 case '': 9974 return document.fullScreen; 9975 case 'webkit': 9976 return document.webkitIsFullScreen; 9977 default: 9978 return document[this.prefix + 'FullScreen']; 9979 } 9980 } 9981 fullScreenApi.requestFullScreen = function(el) { 9982 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 9983 } 9984 fullScreenApi.cancelFullScreen = function(el) { 9985 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 9986 } 9987 } 9988 }()); 9989 9990 // Browser detect 9991 (function() { 9992 function uaMatch(ua) { 9993 ua = ua.toLowerCase(); 9994 9995 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 9996 /(webkit)[ \/]([\w.]+)/.exec(ua) || 9997 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 9998 /(msie) ([\w.]+)/.exec(ua) || 9999 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 10000 10001 return { 10002 browser: match[1] || "", 10003 version: match[2] || "0" 10004 }; 10005 } 10006 10007 var matched = uaMatch(navigator.userAgent); 10008 browser = {}; 10009 10010 if (matched.browser) { 10011 browser[matched.browser] = true; 10012 browser.version = matched.version; 10013 } 10014 10015 // Chrome is Webkit, but Webkit is also Safari. 10016 if (browser.chrome) { 10017 browser.webkit = true; 10018 } else if (browser.webkit) { 10019 browser.safari = true; 10020 } 10021 }()); 10022 10023 // Feature detects 10024 (function() { 10025 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 10026 var el = document.createElement('div'); 10027 10028 function testProp(prop) { 10029 for (var p = 0, pl = prefixes.length; p < pl; p++) { 10030 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 10031 if (el.style[prefixedProp] !== undefined) { 10032 return prefixedProp; 10033 } 10034 } 10035 } 10036 10037 // Global support indicators 10038 transform = testProp('transform') || ''; 10039 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 10040 }()); 10041 10042 10043 /* 10044 PluginDetect v0.7.9 10045 www.pinlady.net/PluginDetect/license/ 10046 [ getVersion onWindowLoaded BetterIE ] 10047 [ Flash QuickTime Shockwave ] 10048 */ 10049 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;
10049d++){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);
10049d.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)}
10049c.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;
10049if(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(); 10050 10051 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)}; 10052 10053 10054 /* 10055 jQuery hashchange event v1.3 10056 https://github.com/cowboy/jquery-hashchange 10057 Copyright (c) 2010 "Cowboy" Ben Alman 10058 Dual licensed under the MIT and GPL licenses. 10059 */ 10060 (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= 10061 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|| 10062 "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;
10062a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 10063 10064 if (!Array.prototype.filter) { 10065 Array.prototype.filter = function(fun /*, thisp */ ) { 10066 "use strict"; 10067 10068 if (this == null) 10069 throw new TypeError(); 10070 10071 var t = Object(this); 10072 var len = t.length >>> 0; 10073 if (typeof fun != "function") 10074 throw new TypeError(); 10075 10076 var res = []; 10077 var thisp = arguments[1]; 10078 for (var i = 0; i < len; i++) { 10079 if (i in t) { 10080 var val = t[i]; // in case fun mutates this 10081 if (fun.call(thisp, val, i, t)) 10082 res.push(val); 10083 } 10084 } 10085 10086 return res; 10087 }; 10088 } 10089 10090 if (!Array.prototype.indexOf) { 10091 Array.prototype.indexOf = function(searchElement, fromIndex) { 10092 var k; 10093 10094 if (this == null) { 10095 throw new TypeError('"this" is null or not defined'); 10096 } 10097 10098 var O = Object(this); 10099 10100 var len = O.length >>> 0; 10101 10102 if (len === 0) { 10103 return -1; 10104 } 10105 10106 var n = +fromIndex || 0; 10107 10108 if (abs(n) === Infinity) { 10109 n = 0; 10110 } 10111 10112 if (n >= len) { 10113 return -1; 10114 } 10115 10116 k = max(n >= 0 ? n : len - abs(n), 0); 10117 10118 while (k < len) { 10119 var kValue; 10120 if (k in O && O[k] === searchElement) { 10121 return k; 10122 } 10123 k++; 10124 } 10125 return -1; 10126 }; 10127 } 10128 10129 if (!Array.prototype.lastIndexOf) { 10130 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 10131 "use strict"; 10132 10133 if (this == null) 10134 throw new TypeError(); 10135 10136 var t = Object(this); 10137 var len = t.length >>> 0; 10138 if (len === 0) 10139 return -1; 10140 10141 var n = len; 10142 if (arguments.length > 1) { 10143 n = Number(arguments[1]); 10144 if (n != n) 10145 n = 0; 10146 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 10147 n = (n > 0 || -1) * floor(abs(n)); 10148 } 10149 10150 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 10151 10152 for (; k >= 0; k--) { 10153 if (k in t && t[k] === searchElement) 10154 return k; 10155 } 10156 return -1; 10157 }; 10158 } 10159})(jQuery, this); 10160 10161/** 10162 * Owl carousel
vendor: 12,045 bytes, lines 10163-10668
10163 * @version 2.0.0-beta.3 10164 * @author Bartosz Wojciechowski 10165 * @license The MIT License (MIT) 10166 * @todo Lazy Load Icon 10167 * @todo prevent animationend bubling 10168 * @todo itemsScaleUp 10169 * @todo Test Zepto 10170 * @todo stagePadding calculate wrong active classes 10171 */ 10172;(function($, window, document, undefined) { 10173 10174 /** 10175 * Creates a carousel. 10176 * @class The Owl Carousel. 10177 * @public 10178 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 10179 * @param {Object} [options] - The options 10180 */ 10181 function Owl(element, options) { 10182 10183 /** 10184 * Current settings for the carousel. 10185 * @public 10186 */ 10187 this.settings = null; 10188 10189 /** 10190 * Current options set by the caller including defaults. 10191 * @public 10192 */ 10193 this.options = $.extend({}, Owl.Defaults, options); 10194 10195 /** 10196 * Plugin element. 10197 * @public 10198 */ 10199 this.$element = $(element); 10200 10201 /** 10202 * Proxied event handlers. 10203 * @protected 10204 */ 10205 this._handlers = {}; 10206 10207 /** 10208 * References to the running plugins of this carousel. 10209 * @protected 10210 */ 10211 this._plugins = {}; 10212 10213 /** 10214 * Currently suppressed events to prevent them from beeing retriggered. 10215 * @protected 10216 */ 10217 this._supress = {}; 10218 10219 /** 10220 * Absolute current position. 10221 * @protected 10222 */ 10223 this._current = null; 10224 10225 /** 10226 * Animation speed in milliseconds. 10227 * @protected 10228 */ 10229 this._speed = null; 10230 10231 /** 10232 * Coordinates of all items in pixel. 10233 * @todo The name of this member is missleading. 10234 * @protected 10235 */ 10236 this._coordinates = []; 10237 10238 /** 10239 * Current breakpoint. 10240 * @todo Real media queries would be nice. 10241 * @protected 10242 */ 10243 this._breakpoint = null; 10244 10245 /** 10246 * Current width of the plugin element. 10247 */ 10248 this._width = null; 10249 10250 /** 10251 * All real items. 10252 * @protected 10253 */ 10254 this._items = []; 10255 10256 /** 10257 * All cloned items. 10258 * @protected 10259 */ 10260 this._clones = []; 10261 10262 /** 10263 * Merge values of all items. 10264 * @todo Maybe this could be part of a plugin. 10265 * @protected 10266 */ 10267 this._mergers = []; 10268 10269 /** 10270 * Widths of all items. 10271 */ 10272 this._widths = []; 10273 10274 /** 10275 * Invalidated parts within the update process. 10276 * @protected 10277 */ 10278 this._invalidated = {}; 10279 10280 /** 10281 * Ordered list of workers for the update process. 10282 * @protected 10283 */ 10284 this._pipe = []; 10285 10286 /** 10287 * Current state information for the drag operation. 10288 * @todo #261 10289 * @protected 10290 */ 10291 this._drag = { 10292 time: null, 10293 target: null, 10294 pointer: null, 10295 stage: { 10296 start: null, 10297 current: null 10298 }, 10299 direction: null 10300 }; 10301 10302 /** 10303 * Current state information and their tags. 10304 * @type {Object} 10305 * @protected 10306 */ 10307 this._states = { 10308 current: {}, 10309 tags: { 10310 'initializing': [ 'busy' ], 10311 'animating': [ 'busy' ], 10312 'dragging': [ 'interacting' ] 10313 } 10314 }; 10315 10316 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 10317 this._handlers[handler] = $.proxy(this[handler], this); 10318 }, this)); 10319 10320 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 10321 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 10322 = new plugin(this); 10323 }, this)); 10324 10325 $.each(Owl.Workers, $.proxy(function(priority, worker) { 10326 this._pipe.push({ 10327 'filter': worker.filter, 10328 'run': $.proxy(worker.run, this) 10329 }); 10330 }, this)); 10331 10332 this.setup(); 10333 this.initialize(); 10334 } 10335 10336 /** 10337 * Default options for the carousel. 10338 * @public 10339 */ 10340 Owl.Defaults = { 10341 items: 3, 10342 loop: false, 10343 center: false, 10344 rewind: false, 10345 10346 mouseDrag: true, 10347 touchDrag: true, 10348 pullDrag: true, 10349 freeDrag: false, 10350 10351 margin: 0, 10352 stagePadding: 0, 10353 10354 merge: false, 10355 mergeFit: true, 10356 autoWidth: false, 10357 10358 startPosition: 0, 10359 rtl: false, 10360 10361 smartSpeed: 250, 10362 fluidSpeed: false, 10363 dragEndSpeed: false, 10364 10365 responsive: {}, 10366 responsiveRefreshRate: 200, 10367 responsiveBaseElement: window, 10368 10369 fallbackEasing: 'swing', 10370 10371 info: false, 10372 10373 nestedItemSelector: false, 10374 itemElement: 'div', 10375 stageElement: 'div', 10376 10377 refreshClass: 'owl-refresh', 10378 loadedClass: 'owl-loaded', 10379 loadingClass: 'owl-loading', 10380 rtlClass: 'owl-rtl', 10381 responsiveClass: 'owl-responsive', 10382 dragClass: 'owl-drag', 10383 itemClass: 'owl-item', 10384 stageClass: 'owl-stage', 10385 stageOuterClass: 'owl-stage-outer', 10386 grabClass: 'owl-grab' 10387 }; 10388 10389 /** 10390 * Enumeration for width. 10391 * @public 10392 * @readonly 10393 * @enum {String} 10394 */ 10395 Owl.Width = { 10396 Default: 'default', 10397 Inner: 'inner', 10398 Outer: 'outer' 10399 }; 10400 10401 /** 10402 * Enumeration for types. 10403 * @public 10404 * @readonly 10405 * @enum {String} 10406 */ 10407 Owl.Type = { 10408 Event: 'event', 10409 State: 'state' 10410 }; 10411 10412 /** 10413 * Contains all registered plugins. 10414 * @public 10415 */ 10416 Owl.Plugins = {}; 10417 10418 /** 10419 * List of workers involved in the update process. 10420 */ 10421 Owl.Workers = [ { 10422 filter: [ 'width', 'settings' ], 10423 run: function() { 10424 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 10425 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 10426 } 10427 }, { 10428 filter: [ 'width', 'items', 'settings' ], 10429 run: function(cache) { 10430 cache.current = this._items && this._items[this.relative(this._current)]; 10431 } 10432 }, { 10433 filter: [ 'items', 'settings' ], 10434 run: function() { 10435 this.$stage.children('.cloned').remove(); 10436 } 10437 }, { 10438 filter: [ 'width', 'items', 'settings' ], 10439 run: function(cache) { 10440 var margin = this.settings.margin || '', 10441 grid = !this.settings.autoWidth, 10442 rtl = this.settings.rtl, 10443 css = { 10444 'width': 'auto', 10445 'margin-left': rtl ? margin : '', 10446 'margin-right': rtl ? '' : margin 10447 }; 10448 10449 !grid && this.$stage.children().css(css); 10450 10451 cache.css = css; 10452 } 10453 }, { 10454 filter: [ 'width', 'items', 'settings' ], 10455 run: function(cache) { 10456 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 10457 merge = null, 10458 iterator = this._items.length, 10459 grid = !this.settings.autoWidth, 10460 widths = []; 10461 10462 cache.items = { 10463 merge: false, 10464 width: width 10465 }; 10466 10467 while (iterator--) { 10468 merge = this._mergers[iterator]; 10469 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 10470 10471 cache.items.merge = merge > 1 || cache.items.merge; 10472 10473 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 10474 } 10475 10476 this._widths = widths; 10477 } 10478 }, { 10479 filter: [ 'items', 'settings' ], 10480 run: function() { 10481 var clones = [], 10482 items = this._items, 10483 settings = this.settings, 10484 view = Math.max(settings.items * 2, 4), 10485 size = Math.ceil(items.length / 2) * 2, 10486 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 10487 append = '', 10488 prepend = ''; 10489 10490 repeat /= 2; 10491 10492 while (repeat--) { 10493 clones.push(this.normalize(clones.length / 2, true)); 10494 append = append + items[clones[clones.length - 1]][0].outerHTML; 10495 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 10496 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 10497 } 10498 10499 this._clones = clones; 10500 10501 // var appendVideo = $(append).find('.uncode-video-container'); 10502 // if (appendVideo.length) { 10503 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 10504 // } 10505 // var prependVideo = $(prepend).find('.uncode-video-container'); 10506 // if (prependVideo.length) { 10507 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 10508 // } 10509 $(append).addClass('cloned').appendTo(this.$stage); 10510 $(prepend).addClass('cloned').prependTo(this.$stage); 10511 } 10512 }, { 10513 filter: [ 'width', 'items', 'settings' ], 10514 run: function() { 10515 var rtl = this.settings.rtl ? 1 : -1, 10516 size = this._clones.length + this._items.length, 10517 iterator = -1, 10518 previous = 0, 10519 current = 0, 10520 coordinates = []; 10521 10522 while (++iterator < size) { 10523 previous = coordinates[iterator - 1] || 0; 10524 current = this._widths[this.relative(iterator)] + this.settings.margin; 10525 coordinates.push(previous + current * rtl); 10526 } 10527 10528 this._coordinates = coordinates; 10529 } 10530 }, { 10531 filter: [ 'width', 'items', 'settings' ], 10532 run: function() { 10533 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10534 padding = stagePadding, 10535 coordinates = this._coordinates, 10536 css = { 10537 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 10538 'padding-left': padding || '', 10539 'padding-right': padding || '' 10540 }; 10541 10542 this.$stage.css(css); 10543 } 10544 }, { 10545 filter: [ 'width', 'items', 'settings' ], 10546 run: function(cache) { 10547 var iterator = this._coordinates.length, 10548 grid = !this.settings.autoWidth, 10549 items = this.$stage.children(); 10550 10551 if (grid && cache.items.merge) { 10552 while (iterator--) { 10553 cache.css.width = this._widths[this.relative(iterator)]; 10554 items.eq(iterator).css(cache.css); 10555 } 10556 } else if (grid) { 10557 cache.css.width = cache.items.width; 10558 items.css(cache.css); 10559 } 10560 } 10561 }, { 10562 filter: [ 'items' ], 10563 run: function() { 10564 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 10565 } 10566 }, { 10567 filter: [ 'width', 'items', 'settings' ], 10568 run: function(cache) { 10569 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 10570 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 10571 this.reset(cache.current); 10572 } 10573 }, { 10574 filter: [ 'position' ], 10575 run: function() { 10576 this.animate(this.coordinates(this._current)); 10577 } 10578 }, { 10579 filter: [ 'width', 'position', 'items', 'settings' ], 10580 run: function() { 10581 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10582 rtl = this.settings.rtl ? 1 : -1, 10583 padding = this.settings.stagePadding * 2, 10584 begin = this.coordinates(this.current()) + padding, 10585 end = begin + this.width() * rtl, 10586 inner, outer, matches = [], i, n; 10587 10588 for (i = 0, n = this._coordinates.length; i < n; i++) { 10589 inner = this._coordinates[i - 1] || 0; 10590 outer = Math.abs(this._coordinates[i]) + padding * rtl; 10591 10592 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 10593 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 10594 matches.push(i); 10595 } 10596 } 10597 10598 this.$stage.children('.active').removeClass('active'); 10599 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 10600 10601 if (this.settings.center) { 10602 this.$stage.children('.center').removeClass('center'); 10603 this.$stage.children().eq(this.current()).addClass('center'); 10604 } 10605 } 10606 } ]; 10607 10608 /** 10609 * Initializes the carousel. 10610 * @protected 10611 */ 10612 Owl.prototype.initialize = function() { 10613 this.enter('initializing'); 10614 this.trigger('initialize'); 10615 10616 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 10617 10618 if (this.settings.autoWidth && !this.is('pre-loading')) { 10619 var imgs, nestedSelector, width; 10620 imgs = this.$element.find('img'); 10621 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 10622 width = this.$element.children(nestedSelector).width(); 10623 10624 if (imgs.length && width <= 0) { 10625 this.preloadAutoWidthImages(imgs); 10626 } 10627 } 10628 10629 this.$element.addClass(this.options.loadingClass); 10630 10631 // create stage 10632 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 10633 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 10634 10635 // append stage 10636 this.$element.append(this.$stage.parent()); 10637 10638 // append content 10639 this.replace(this.$element.children().not(this.$stage.parent())); 10640 10641 // check visibility 10642 if (this.$element.is(':visible')) { 10643 // update view 10644 this.refresh(); 10645 } else { 10646 // invalidate width 10647 this.invalidate('width'); 10648 } 10649 10650 this.$element 10651 .removeClass(this.options.loadingClass) 10652 .addClass(this.options.loadedClass); 10653 10654 // register event handlers 10655 this.registerEventHandlers(); 10656 10657 this.leave('initializing'); 10658 this.trigger('initialized'); 10659 }; 10660 10661 /** 10662 * Setups the current settings. 10663 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 10664 * @todo Support for media queries by using `matchMedia` would be nice. 10665 * @public 10666 */ 10667 Owl.prototype.setup = function() { 10668 var viewport = this.viewport(),
10669 overwrites = this.options.responsive, 10670 match = -1, 10671 settings = null; 10672 10673 if (!overwrites) { 10674 settings = $.extend({}, this.options); 10675 } else { 10676 $.each(overwrites, function(breakpoint) { 10677 if (breakpoint <= viewport && breakpoint > match) { 10678 match = Number(breakpoint); 10679 } 10680 }); 10681 10682 settings = $.extend({}, this.options, overwrites[match]); 10683 delete settings.responsive; 10684 10685 // responsive class 10686 if (settings.responsiveClass) { 10687 this.$element.attr('class', 10688 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 10689 ); 10690 } 10691 } 10692 10693 if (this.settings === null || this._breakpoint !== match) { 10694 this.trigger('change', { property: { name: 'settings', value: settings } }); 10695 this._breakpoint = match; 10696 this.settings = settings; 10697 this.invalidate('settings'); 10698 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 10699 } 10700 }; 10701 10702 /** 10703 * Updates option logic if necessery. 10704 * @protected 10705 */ 10706 Owl.prototype.optionsLogic = function() { 10707 if (this.settings.autoWidth) { 10708 this.settings.stagePadding = false; 10709 this.settings.merge = false; 10710 } 10711 }; 10712 10713 /** 10714 * Prepares an item before add. 10715 * @todo Rename event parameter `content` to `item`. 10716 * @protected 10717 * @returns {jQuery|HTMLElement} - The item container. 10718 */ 10719 Owl.prototype.prepare = function(item, index) { 10720 var event = this.trigger('prepare', { content: item }); 10721 if (!event.data) { 10722 event.data = $('<' + this.settings.itemElement + '/>') 10723 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 10724 } 10725 10726 this.trigger('prepared', { content: event.data }); 10727 10728 return event.data; 10729 }; 10730 10731 /** 10732 * Updates the view. 10733 * @public 10734 */ 10735 Owl.prototype.update = function() { 10736 var i = 0, 10737 n = this._pipe.length, 10738 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 10739 cache = {}; 10740 10741 while (i < n) { 10742 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 10743 this._pipe[i].run(cache); 10744 } 10745 i++; 10746 } 10747 10748 this._invalidated = {}; 10749 10750 !this.is('valid') && this.enter('valid'); 10751 }; 10752 10753 /** 10754 * Gets the width of the view. 10755 * @public 10756 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 10757 * @returns {Number} - The width of the view in pixel. 10758 */ 10759 Owl.prototype.width = function(dimension) { 10760 dimension = dimension || Owl.Width.Default; 10761 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 10762 switch (dimension) { 10763 case Owl.Width.Inner: 10764 case Owl.Width.Outer: 10765 return this._width; 10766 default: 10767 return this._width - stagePadding * 2 + this.settings.margin; 10768 } 10769 }; 10770 10771 /** 10772 * Refreshes the carousel primarily for adaptive purposes. 10773 * @public 10774 */ 10775 Owl.prototype.refresh = function() { 10776 this.enter('refreshing'); 10777 this.trigger('refresh'); 10778 10779 this.setup(); 10780 10781 this.optionsLogic(); 10782 10783 this.$element.addClass(this.options.refreshClass); 10784 10785 this.update(); 10786 10787 this.$element.removeClass(this.options.refreshClass); 10788 10789 this.leave('refreshing'); 10790 this.trigger('refreshed'); 10791 }; 10792 10793 /** 10794 * Checks window `resize` event. 10795 * @protected 10796 */ 10797 Owl.prototype.onThrottledResize = function() { 10798 window.clearTimeout(this.resizeTimer); 10799 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 10800 }; 10801 10802 /** 10803 * Checks window `resize` event. 10804 * @protected 10805 */ 10806 Owl.prototype.onResize = function() { 10807 if (!this._items.length) { 10808 return false; 10809 } 10810 10811 if (this._width === this.$element.width()) { 10812 return false; 10813 } 10814 10815 if (!this.$element.is(':visible')) { 10816 return false; 10817 } 10818 10819 this.enter('resizing'); 10820 10821 if (this.trigger('resize').isDefaultPrevented()) { 10822 this.leave('resizing'); 10823 return false; 10824 } 10825 10826 this.invalidate('width'); 10827 10828 this.refresh(); 10829 10830 this.leave('resizing'); 10831 this.trigger('resized'); 10832 }; 10833 10834 /** 10835 * Registers event handlers. 10836 * @todo Check `msPointerEnabled` 10837 * @todo #261 10838 * @protected 10839 */ 10840 Owl.prototype.registerEventHandlers = function() { 10841 if ($.support.transition) { 10842 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 10843 } 10844 10845 if (this.settings.responsive !== false) { 10846 this.on(window, 'resize', this._handlers.onThrottledResize); 10847 } 10848 10849 if (this.settings.mouseDrag) { 10850 this.$element.addClass(this.options.dragClass); 10851 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 10852 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 10853 } 10854 10855 if (this.settings.touchDrag){ 10856 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 10857 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 10858 } 10859 }; 10860 10861 /** 10862 * Handles `touchstart` and `mousedown` events. 10863 * @todo Horizontal swipe threshold as option 10864 * @todo #261 10865 * @protected 10866 * @param {Event} event - The event arguments. 10867 */ 10868 Owl.prototype.onDragStart = function(event) { 10869 var stage = null; 10870 10871 if (event.which === 3) { 10872 return; 10873 } 10874
vendor: 9,106 bytes, lines 10875-11190
10875 if ($.support.transform) { 10876 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 10877 stage = { 10878 x: stage[stage.length === 16 ? 12 : 4], 10879 y: stage[stage.length === 16 ? 13 : 5] 10880 }; 10881 } else { 10882 stage = this.$stage.position(); 10883 stage = { 10884 x: this.settings.rtl ? 10885 stage.left + this.$stage.width() - this.width() + this.settings.margin : 10886 stage.left, 10887 y: stage.top 10888 }; 10889 } 10890 10891 if (this.is('animating')) { 10892 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 10893 this.invalidate('position'); 10894 } 10895 10896 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 10897 10898 this.speed(0); 10899 10900 this._drag.time = new Date().getTime(); 10901 this._drag.target = $(event.target); 10902 this._drag.stage.start = stage; 10903 this._drag.stage.current = stage; 10904 this._drag.pointer = this.pointer(event); 10905 10906 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 10907 10908 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 10909 var delta = this.difference(this._drag.pointer, this.pointer(event)); 10910 10911 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 10912 10913 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 10914 return; 10915 } 10916 10917 event.preventDefault(); 10918 10919 this.enter('dragging'); 10920 this.trigger('drag'); 10921 }, this)); 10922 }; 10923 10924 /** 10925 * Handles the `touchmove` and `mousemove` events. 10926 * @todo #261 10927 * @protected 10928 * @param {Event} event - The event arguments. 10929 */ 10930 Owl.prototype.onDragMove = function(event) { 10931 var minimum = null, 10932 maximum = null, 10933 pull = null, 10934 delta = this.difference(this._drag.pointer, this.pointer(event)), 10935 stage = this.difference(this._drag.stage.start, delta); 10936 10937 if (!this.is('dragging')) { 10938 return; 10939 } 10940 10941 event.preventDefault(); 10942 10943 if (this.settings.loop) { 10944 minimum = this.coordinates(this.minimum()); 10945 maximum = this.coordinates(this.maximum() + 1) - minimum; 10946 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 10947 } else { 10948 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 10949 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 10950 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 10951 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 10952 } 10953 10954 this._drag.stage.current = stage; 10955 10956 this.animate(stage.x); 10957 }; 10958 10959 /** 10960 * Handles the `touchend` and `mouseup` events. 10961 * @todo #261 10962 * @todo Threshold for click event 10963 * @protected 10964 * @param {Event} event - The event arguments. 10965 */ 10966 Owl.prototype.onDragEnd = function(event) { 10967 var delta = this.difference(this._drag.pointer, this.pointer(event)), 10968 stage = this._drag.stage.current, 10969 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 10970 10971 $(document).off('.owl.core'); 10972 10973 this.$element.removeClass(this.options.grabClass); 10974 10975 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 10976 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 10977 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 10978 this.invalidate('position'); 10979 this.update(); 10980 10981 this._drag.direction = direction; 10982 10983 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 10984 this._drag.target.one('click.owl.core', function() { return false; }); 10985 } 10986 } 10987 10988 if (!this.is('dragging')) { 10989 return; 10990 } 10991 10992 this.leave('dragging'); 10993 this.trigger('dragged'); 10994 }; 10995 10996 /** 10997 * Gets absolute position of the closest item for a coordinate. 10998 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 10999 * @protected 11000 * @param {Number} coordinate - The coordinate in pixel. 11001 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 11002 * @return {Number} - The absolute position of the closest item. 11003 */ 11004 Owl.prototype.closest = function(coordinate, direction) { 11005 var position = -1, 11006 pull = 30, 11007 width = this.width(), 11008 coordinates = this.coordinates(); 11009 11010 if (!this.settings.freeDrag) { 11011 // check closest item 11012 $.each(coordinates, $.proxy(function(index, value) { 11013 if (coordinate > value - pull && coordinate < value + pull) { 11014 position = index; 11015 } else if (this.op(coordinate, '<', value) 11016 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 11017 position = direction === 'left' ? index + 1 : index; 11018 } 11019 return position === -1; 11020 }, this)); 11021 } 11022 11023 if (!this.settings.loop) { 11024 // non loop boundries 11025 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 11026 position = coordinate = this.minimum(); 11027 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 11028 position = coordinate = this.maximum(); 11029 } 11030 } 11031 11032 return position; 11033 }; 11034 11035 /** 11036 * Animates the stage. 11037 * @todo #270 11038 * @public 11039 * @param {Number} coordinate - The coordinate in pixels. 11040 */ 11041 Owl.prototype.animate = function(coordinate) { 11042 var animate = this.speed() > 0; 11043 11044 this.is('animating') && this.onTransitionEnd(); 11045 11046 if (animate) { 11047 this.enter('animating'); 11048 this.trigger('translate'); 11049 } 11050 11051 if ($.support.transform3d && $.support.transition) { 11052 this.$stage.css({ 11053 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 11054 transition: (this.speed() / 1000) + 's' 11055 }); 11056 } else if (animate) { 11057 this.$stage.animate({ 11058 left: coordinate + 'px' 11059 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 11060 } else { 11061 this.$stage.css({ 11062 left: coordinate + 'px' 11063 }); 11064 } 11065 }; 11066 11067 /** 11068 * Checks whether the carousel is in a specific state or not. 11069 * @param {String} state - The state to check. 11070 * @returns {Boolean} - The flag which indicates if the carousel is busy. 11071 */ 11072 Owl.prototype.is = function(state) { 11073 return this._states.current[state] && this._states.current[state] > 0; 11074 }; 11075 11076 /** 11077 * Sets the absolute position of the current item. 11078 * @public 11079 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 11080 * @returns {Number} - The absolute position of the current item. 11081 */ 11082 Owl.prototype.current = function(position) { 11083 if (position === undefined) { 11084 return this._current; 11085 } 11086 11087 if (this._items.length === 0) { 11088 return undefined; 11089 } 11090 11091 position = this.normalize(position); 11092 11093 if (this._current !== position) { 11094 var event = this.trigger('change', { property: { name: 'position', value: position } }); 11095 11096 if (event.data !== undefined) { 11097 position = this.normalize(event.data); 11098 } 11099 11100 this._current = position; 11101 11102 this.invalidate('position'); 11103 11104 this.trigger('changed', { property: { name: 'position', value: this._current } }); 11105 } 11106 11107 return this._current; 11108 }; 11109 11110 /** 11111 * Invalidates the given part of the update routine. 11112 * @param {String} [part] - The part to invalidate. 11113 * @returns {Array.<String>} - The invalidated parts. 11114 */ 11115 Owl.prototype.invalidate = function(part) { 11116 if ($.type(part) === 'string') { 11117 this._invalidated[part] = true; 11118 this.is('valid') && this.leave('valid'); 11119 } 11120 return $.map(this._invalidated, function(v, i) { return i }); 11121 }; 11122 11123 /** 11124 * Resets the absolute position of the current item. 11125 * @public 11126 * @param {Number} position - The absolute position of the new item. 11127 */ 11128 Owl.prototype.reset = function(position) { 11129 position = this.normalize(position); 11130 11131 if (position === undefined) { 11132 return; 11133 } 11134 11135 this._speed = 0; 11136 this._current = position; 11137 11138 this.suppress([ 'translate', 'translated' ]); 11139 11140 this.animate(this.coordinates(position)); 11141 11142 this.release([ 'translate', 'translated' ]); 11143 }; 11144 11145 /** 11146 * Normalizes an absolute or a relative position of an item. 11147 * @public 11148 * @param {Number} position - The absolute or relative position to normalize. 11149 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 11150 * @returns {Number} - The normalized position. 11151 */ 11152 Owl.prototype.normalize = function(position, relative) { 11153 var n = this._items.length, 11154 m = relative ? 0 : this._clones.length; 11155 11156 if (!$.isNumeric(position) || n < 1) { 11157 position = undefined; 11158 } else if (position < 0 || position >= n + m) { 11159 position = ((position - m / 2) % n + n) % n + m / 2; 11160 } 11161 11162 return position; 11163 }; 11164 11165 /** 11166 * Converts an absolute position of an item into a relative one. 11167 * @public 11168 * @param {Number} position - The absolute position to convert. 11169 * @returns {Number} - The converted position. 11170 */ 11171 Owl.prototype.relative = function(position) { 11172 position -= this._clones.length / 2; 11173 return this.normalize(position, true); 11174 }; 11175 11176 /** 11177 * Gets the maximum position for the current item. 11178 * @public 11179 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11180 * @returns {Number} 11181 */ 11182 Owl.prototype.maximum = function(relative) { 11183 var settings = this.settings, 11184 maximum = this._coordinates.length, 11185 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 11186 i = -1, j; 11187 11188 if (settings.loop) { 11189 maximum = this._clones.length / 2 + this._items.length - 1; 11190 } else if (settings.autoWidth || settings.merge) {
11191 // binary search 11192 while (maximum - i > 1) { 11193 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 11194 ? i = j : maximum = j; 11195 } 11196 } else if (settings.center) { 11197 maximum = this._items.length - 1; 11198 } else { 11199 maximum = this._items.length - settings.items; 11200 } 11201 11202 if (relative) { 11203 maximum -= this._clones.length / 2; 11204 } 11205 11206 return Math.max(maximum, 0); 11207 }; 11208 11209 /** 11210 * Gets the minimum position for the current item. 11211 * @public 11212 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11213 * @returns {Number} 11214 */ 11215 Owl.prototype.minimum = function(relative) { 11216 return relative ? 0 : this._clones.length / 2; 11217 }; 11218 11219 /** 11220 * Gets an item at the specified relative position. 11221 * @public 11222 * @param {Number} [position] - The relative position of the item. 11223 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11224 */ 11225 Owl.prototype.items = function(position) { 11226 if (position === undefined) { 11227 return this._items.slice(); 11228 } 11229 11230 position = this.normalize(position, true); 11231 return this._items[position]; 11232 }; 11233 11234 /** 11235 * Gets an item at the specified relative position. 11236 * @public 11237 * @param {Number} [position] - The relative position of the item. 11238 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11239 */ 11240 Owl.prototype.mergers = function(position) { 11241 if (position === undefined) { 11242 return this._mergers.slice(); 11243 } 11244 11245 position = this.normalize(position, true); 11246 return this._mergers[position]; 11247 }; 11248 11249 /** 11250 * Gets the absolute positions of clones for an item. 11251 * @public 11252 * @param {Number} [position] - The relative position of the item. 11253 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 11254 */ 11255 Owl.prototype.clones = function(position) { 11256 var odd = this._clones.length / 2, 11257 even = odd + this._items.length, 11258 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 11259 11260 if (position === undefined) { 11261 return $.map(this._clones, function(v, i) { return map(i) }); 11262 } 11263 11264 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 11265 }; 11266 11267 /** 11268 * Sets the current animation speed. 11269 * @public 11270 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 11271 * @returns {Number} - The current animation speed in milliseconds. 11272 */ 11273 Owl.prototype.speed = function(speed) { 11274 if (speed !== undefined) { 11275 this._speed = speed; 11276 } 11277 11278 return this._speed; 11279 }; 11280 11281 /** 11282 * Gets the coordinate of an item. 11283 * @todo The name of this method is missleanding. 11284 * @public 11285 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 11286 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 11287 */ 11288 Owl.prototype.coordinates = function(position) { 11289 var coordinate = null; 11290 11291 if (position === undefined) { 11292 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 11293 return this.coordinates(index); 11294 }, this)); 11295 } 11296 11297 if (this.settings.center) { 11298 coordinate = this._coordinates[position]; 11299 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 11300 } else { 11301 coordinate = this._coordinates[position - 1] || 0; 11302 } 11303 11304 return coordinate; 11305 }; 11306 11307 /** 11308 * Calculates the speed for a translation. 11309 * @protected 11310 * @param {Number} from - The absolute position of the start item. 11311 * @param {Number} to - The absolute position of the target item. 11312 * @param {Number} [factor=undefined] - The time factor in milliseconds. 11313 * @returns {Number} - The time in milliseconds for the translation. 11314 */ 11315 Owl.prototype.duration = function(from, to, factor) { 11316 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 11317 }; 11318 11319 /** 11320 * Slides to the specified item. 11321 * @public 11322 * @param {Number} position - The position of the item. 11323 * @param {Number} [speed] - The time in milliseconds for the transition. 11324 */ 11325 Owl.prototype.to = function(position, speed) { 11326 var current = this.current(), 11327 revert = null, 11328 distance = position - this.relative(current), 11329 direction = (distance > 0) - (distance < 0), 11330 items = this._items.length, 11331 minimum = this.minimum(), 11332 maximum = this.maximum(); 11333 11334 if (this.settings.loop) { 11335 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 11336 distance += direction * -1 * items; 11337 } 11338 11339 position = current + distance; 11340 revert = ((position - minimum) % items + items) % items + minimum; 11341 11342 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 11343 current = revert - distance; 11344 position = revert; 11345 this.reset(current); 11346 } 11347 } else if (this.settings.rewind) { 11348 maximum += 1; 11349 position = (position % maximum + maximum) % maximum; 11350 } else { 11351 position = Math.max(minimum, Math.min(maximum, position)); 11352 } 11353 11354 this.speed(this.duration(current, position, speed)); 11355 this.current(position); 11356 11357 if (this.$element.is(':visible')) { 11358 this.update(); 11359 } 11360 }; 11361 11362 /** 11363 * Slides to the next item. 11364 * @public 11365 * @param {Number}
vendor: 12,284 bytes, lines 11365-11785
11365 [speed] - The time in milliseconds for the transition. 11366 */ 11367 Owl.prototype.next = function(speed) { 11368 speed = speed || false; 11369 this.to(this.relative(this.current()) + 1, speed); 11370 }; 11371 11372 /** 11373 * Slides to the previous item. 11374 * @public 11375 * @param {Number} [speed] - The time in milliseconds for the transition. 11376 */ 11377 Owl.prototype.prev = function(speed) { 11378 speed = speed || false; 11379 this.to(this.relative(this.current()) - 1, speed); 11380 }; 11381 11382 /** 11383 * Handles the end of an animation. 11384 * @protected 11385 * @param {Event} event - The event arguments. 11386 */ 11387 Owl.prototype.onTransitionEnd = function(event) { 11388 11389 // if css2 animation then event object is undefined 11390 if (event !== undefined) { 11391 event.stopPropagation(); 11392 11393 // Catch only owl-stage transitionEnd event 11394 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 11395 return false; 11396 } 11397 } 11398 11399 this.leave('animating'); 11400 this.trigger('translated'); 11401 }; 11402 11403 /** 11404 * Gets viewport width. 11405 * @protected 11406 * @return {Number} - The width in pixel. 11407 */ 11408 Owl.prototype.viewport = function() { 11409 var width; 11410 if (this.options.responsiveBaseElement !== window) { 11411 width = $(this.options.responsiveBaseElement).width(); 11412 } else if (window.innerWidth) { 11413 width = window.innerWidth; 11414 } else if (document.documentElement && document.documentElement.clientWidth) { 11415 width = document.documentElement.clientWidth; 11416 } else { 11417 throw 'Can not detect viewport width.'; 11418 } 11419 11420 return width; 11421 }; 11422 11423 /** 11424 * Replaces the current content. 11425 * @public 11426 * @param {HTMLElement|jQuery|String} content - The new content. 11427 */ 11428 Owl.prototype.replace = function(content) { 11429 this.$stage.empty(); 11430 this._items = []; 11431 11432 if (content) { 11433 content = (content instanceof jQuery) ? content : $(content); 11434 } 11435 11436 if (this.settings.nestedItemSelector) { 11437 content = content.find('.' + this.settings.nestedItemSelector); 11438 } 11439 11440 content.filter(function() { 11441 return this.nodeType === 1; 11442 }).each($.proxy(function(index, item) { 11443 item = this.prepare(item, index); 11444 this.$stage.append(item); 11445 this._items.push(item); 11446 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 11447 }, this)); 11448 11449 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 11450 11451 this.invalidate('items'); 11452 }; 11453 11454 /** 11455 * Adds an item. 11456 * @todo Use `item` instead of `content` for the event arguments. 11457 * @public 11458 * @param {HTMLElement|jQuery|String} content - The item content to add. 11459 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 11460 */ 11461 Owl.prototype.add = function(content, position) { 11462 var current = this.relative(this._current); 11463 11464 position = position === undefined ? this._items.length : this.normalize(position, true); 11465 content = content instanceof jQuery ? content : $(content); 11466 11467 this.trigger('add', { content: content, position: position }); 11468 11469 content = this.prepare(content, this._items[current].index()); 11470 11471 if (this._items.length === 0 || position === this._items.length) { 11472 this._items.length === 0 && this.$stage.append(content); 11473 this._items.length !== 0 && this._items[position - 1].after(content); 11474 this._items.push(content); 11475 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11476 } else { 11477 this._items[position].before(content); 11478 this._items.splice(position, 0, content); 11479 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11480 } 11481 11482 this._items[current] && this.reset(this._items[current].index()); 11483 11484 this.invalidate('items'); 11485 11486 this.trigger('added', { content: content, position: position }); 11487 }; 11488 11489 /** 11490 * Removes an item by its position. 11491 * @todo Use `item` instead of `content` for the event arguments. 11492 * @public 11493 * @param {Number} position - The relative position of the item to remove. 11494 */ 11495 Owl.prototype.remove = function(position) { 11496 position = this.normalize(position, true); 11497 11498 if (position === undefined) { 11499 return; 11500 } 11501 11502 this.trigger('remove', { content: this._items[position], position: position }); 11503 11504 this._items[position].remove(); 11505 this._items.splice(position, 1); 11506 this._mergers.splice(position, 1); 11507 11508 this.invalidate('items'); 11509 11510 this.trigger('removed', { content: null, position: position }); 11511 }; 11512 11513 /** 11514 * Preloads images with auto width. 11515 * @todo Replace by a more generic approach 11516 * @protected 11517 */ 11518 Owl.prototype.preloadAutoWidthImages = function(images) { 11519 images.each($.proxy(function(i, element) { 11520 this.enter('pre-loading'); 11521 element = $(element); 11522 $(new Image()).one('load', $.proxy(function(e) { 11523 element.attr('src', e.target.src); 11524 element.css('opacity', 1); 11525 this.leave('pre-loading'); 11526 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 11527 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 11528 }, this)); 11529 }; 11530 11531 /** 11532 * Destroys the carousel. 11533 * @public 11534 */ 11535 Owl.prototype.destroy = function() { 11536 11537 this.$element.off('.owl.core'); 11538 this.$stage.off('.owl.core'); 11539 $(document).off('.owl.core'); 11540 11541 if (this.settings.responsive !== false) { 11542 window.clearTimeout(this.resizeTimer); 11543 this.off(window, 'resize', this._handlers.onThrottledResize); 11544 } 11545 11546 for (var i in this._plugins) { 11547 this._plugins[i].destroy(); 11548 } 11549 11550 this.$stage.children('.cloned').remove(); 11551 11552 this.$stage.unwrap(); 11553 this.$stage.children().contents().unwrap(); 11554 this.$stage.children().unwrap(); 11555 11556 this.$element 11557 .removeClass(this.options.refreshClass) 11558 .removeClass(this.options.loadingClass) 11559 .removeClass(this.options.loadedClass) 11560 .removeClass(this.options.rtlClass) 11561 .removeClass(this.options.dragClass) 11562 .removeClass(this.options.grabClass) 11563 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 11564 .removeData('owl.carousel'); 11565 }; 11566 11567 /** 11568 * Operators to calculate right-to-left and left-to-right. 11569 * @protected 11570 * @param {Number} [a] - The left side operand. 11571 * @param {String} [o] - The operator. 11572 * @param {Number} [b] - The right side operand. 11573 */ 11574 Owl.prototype.op = function(a, o, b) { 11575 var rtl = this.settings.rtl; 11576 switch (o) { 11577 case '<': 11578 return rtl ? a > b : a < b; 11579 case '>': 11580 return rtl ? a < b : a > b; 11581 case '>=': 11582 return rtl ? a <= b : a >= b; 11583 case '<=': 11584 return rtl ? a >= b : a <= b; 11585 default: 11586 break; 11587 } 11588 }; 11589 11590 /** 11591 * Attaches to an internal event. 11592 * @protected 11593 * @param {HTMLElement} element - The event source. 11594 * @param {String} event - The event name. 11595 * @param {Function} listener - The event handler to attach. 11596 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 11597 */ 11598 Owl.prototype.on = function(element, event, listener, capture) { 11599 if (element.addEventListener) { 11600 element.addEventListener(event, listener, capture); 11601 } else if (element.attachEvent) { 11602 element.attachEvent('on' + event, listener); 11603 } 11604 }; 11605 11606 /** 11607 * Detaches from an internal event. 11608 * @protected 11609 * @param {HTMLElement} element - The event source. 11610 * @param {String} event - The event name. 11611 * @param {Function} listener - The attached event handler to detach. 11612 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 11613 */ 11614 Owl.prototype.off = function(element, event, listener, capture) { 11615 if (element.removeEventListener) { 11616 element.removeEventListener(event, listener, capture); 11617 } else if (element.detachEvent) { 11618 element.detachEvent('on' + event, listener); 11619 } 11620 }; 11621 11622 /** 11623 * Triggers a public event. 11624 * @todo Remove `status`, `relatedTarget` should be used instead. 11625 * @protected 11626 * @param {String} name - The event name. 11627 * @param {*} [data=null] - The event data. 11628 * @param {String} [namespace=carousel] - The event namespace. 11629 * @param {String} [state] - The state which is associated with the event. 11630 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 11631 * @returns {Event} - The event arguments. 11632 */ 11633 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 11634 var status = { 11635 item: { count: this._items.length, index: this.current() } 11636 }, handler = $.camelCase( 11637 $.grep([ 'on', name, namespace ], function(v) { return v }) 11638 .join('-').toLowerCase() 11639 ), event = $.Event( 11640 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 11641 $.extend({ relatedTarget: this }, status, data) 11642 ); 11643 11644 if (!this._supress[name]) { 11645 $.each(this._plugins, function(name, plugin) { 11646 if (plugin.onTrigger) { 11647 plugin.onTrigger(event); 11648 } 11649 }); 11650 11651 this.register({ type: Owl.Type.Event, name: name }); 11652 this.$element.trigger(event); 11653 11654 if (this.settings && typeof this.settings[handler] === 'function') { 11655 this.settings[handler].call(this, event); 11656 } 11657 } 11658 11659 return event; 11660 }; 11661 11662 /** 11663 * Enters a state. 11664 * @param name - The state name. 11665 */ 11666 Owl.prototype.enter = function(name) { 11667 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11668 if (this._states.current[name] === undefined) { 11669 this._states.current[name] = 0; 11670 } 11671 11672 this._states.current[name]++; 11673 }, this)); 11674 }; 11675 11676 /** 11677 * Leaves a state. 11678 * @param name - The state name. 11679 */ 11680 Owl.prototype.leave = function(name) { 11681 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11682 this._states.current[name]--; 11683 }, this)); 11684 }; 11685 11686 /** 11687 * Registers an event or state. 11688 * @public 11689 * @param {Object} object - The event or state to register. 11690 */ 11691 Owl.prototype.register = function(object) { 11692 if (object.type === Owl.Type.Event) { 11693 if (!$.event.special[object.name]) { 11694 $.event.special[object.name] = {}; 11695 } 11696 11697 if (!$.event.special[object.name].owl) { 11698 var _default = $.event.special[object.name]._default; 11699 $.event.special[object.name]._default = function(e) { 11700 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 11701 return _default.apply(this, arguments); 11702 } 11703 return e.namespace && e.namespace.indexOf('owl') > -1; 11704 }; 11705 $.event.special[object.name].owl = true; 11706 } 11707 } else if (object.type === Owl.Type.State) { 11708 if (!this._states.tags[object.name]) { 11709 this._states.tags[object.name] = object.tags; 11710 } else { 11711 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 11712 } 11713 11714 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 11715 return $.inArray(tag, this._states.tags[object.name]) === i; 11716 }, this)); 11717 } 11718 }; 11719 11720 /** 11721 * Suppresses events. 11722 * @protected 11723 * @param {Array.<String>} events - The events to suppress. 11724 */ 11725 Owl.prototype.suppress = function(events) { 11726 $.each(events, $.proxy(function(index, event) { 11727 this._supress[event] = true; 11728 }, this)); 11729 }; 11730 11731 /** 11732 * Releases suppressed events. 11733 * @protected 11734 * @param {Array.<String>} events - The events to release. 11735 */ 11736 Owl.prototype.release = function(events) { 11737 $.each(events, $.proxy(function(index, event) { 11738 delete this._supress[event]; 11739 }, this)); 11740 }; 11741 11742 /** 11743 * Gets unified pointer coordinates from event. 11744 * @todo #261 11745 * @protected 11746 * @param {Event} - The `mousedown` or `touchstart` event. 11747 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 11748 */ 11749 Owl.prototype.pointer = function(event) { 11750 var result = { x: null, y: null }; 11751 11752 event = event.originalEvent || event || window.event; 11753 11754 event = event.touches && event.touches.length ? 11755 event.touches[0] : event.changedTouches && event.changedTouches.length ? 11756 event.changedTouches[0] : event; 11757 11758 if (event.pageX) { 11759 result.x = event.pageX; 11760 result.y = event.pageY; 11761 } else { 11762 result.x = event.clientX; 11763 result.y = event.clientY; 11764 } 11765 11766 return result; 11767 }; 11768 11769 /** 11770 * Gets the difference of two vectors. 11771 * @todo #261 11772 * @protected 11773 * @param {Object} - The first vector. 11774 * @param {Object} - The second vector. 11775 * @returns {Object} - The difference. 11776 */ 11777 Owl.prototype.difference = function(first, second) { 11778 return { 11779 x: first.x - second.x, 11780 y: first.y - second.y 11781 }; 11782 }; 11783 11784 /** 11785 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 11786-13068
11786 * @todo Navigation plugin `next` and `prev` 11787 * @public 11788 */ 11789 $.fn.owlCarousel = function(option) { 11790 var args = Array.prototype.slice.call(arguments, 1); 11791 11792 return this.each(function() { 11793 var $this = $(this), 11794 data = $this.data('owl.carousel'); 11795 11796 if (!data) { 11797 data = new Owl(this, typeof option == 'object' && option); 11798 $this.data('owl.carousel', data); 11799 11800 $.each([ 11801 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 11802 ], function(i, event) { 11803 data.register({ type: Owl.Type.Event, name: event }); 11804 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 11805 if (e.namespace && e.relatedTarget !== this) { 11806 this.suppress([ event ]); 11807 data[event].apply(this, [].slice.call(arguments, 1)); 11808 this.release([ event ]); 11809 } 11810 }, data)); 11811 }); 11812 } 11813 11814 if (typeof option == 'string' && option.charAt(0) !== '_') { 11815 data[option].apply(data, args); 11816 } 11817 }); 11818 }; 11819 11820 /** 11821 * The constructor for the jQuery Plugin 11822 * @public 11823 */ 11824 $.fn.owlCarousel.Constructor = Owl; 11825 11826})(window.Zepto || window.jQuery, window, document); 11827 11828/** 11829 * AutoRefresh Plugin 11830 * @version 2.0.0-beta.3 11831 * @author Artus Kolanowski 11832 * @license The MIT License (MIT) 11833 */ 11834;(function($, window, document, undefined) { 11835 11836 /** 11837 * Creates the auto refresh plugin. 11838 * @class The Auto Refresh Plugin 11839 * @param {Owl} carousel - The Owl Carousel 11840 */ 11841 var AutoRefresh = function(carousel) { 11842 /** 11843 * Reference to the core. 11844 * @protected 11845 * @type {Owl} 11846 */ 11847 this._core = carousel; 11848 11849 /** 11850 * Refresh interval. 11851 * @protected 11852 * @type {number} 11853 */ 11854 this._interval = null; 11855 11856 /** 11857 * Whether the element is currently visible or not. 11858 * @protected 11859 * @type {Boolean} 11860 */ 11861 this._visible = null; 11862 11863 /** 11864 * All event handlers. 11865 * @protected 11866 * @type {Object} 11867 */ 11868 this._handlers = { 11869 'initialized.owl.carousel': $.proxy(function(e) { 11870 if (e.namespace && this._core.settings.autoRefresh) { 11871 this.watch(); 11872 } 11873 }, this) 11874 }; 11875 11876 // set default options 11877 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 11878 11879 // register event handlers 11880 this._core.$element.on(this._handlers); 11881 }; 11882 11883 /** 11884 * Default options. 11885 * @public 11886 */ 11887 AutoRefresh.Defaults = { 11888 autoRefresh: true, 11889 autoRefreshInterval: 500 11890 }; 11891 11892 /** 11893 * Watches the element. 11894 */ 11895 AutoRefresh.prototype.watch = function() { 11896 if (this._interval) { 11897 return; 11898 } 11899 11900 this._visible = this._core.$element.is(':visible'); 11901 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 11902 }; 11903 11904 /** 11905 * Refreshes the element. 11906 */ 11907 AutoRefresh.prototype.refresh = function() { 11908 if (this._core.$element.is(':visible') === this._visible) { 11909 return; 11910 } 11911 11912 this._visible = !this._visible; 11913 11914 this._core.$element.toggleClass('owl-hidden', !this._visible); 11915 11916 this._visible && (this._core.invalidate('width') && this._core.refresh()); 11917 }; 11918 11919 /** 11920 * Destroys the plugin. 11921 */ 11922 AutoRefresh.prototype.destroy = function() { 11923 var handler, property; 11924 11925 window.clearInterval(this._interval); 11926 11927 for (handler in this._handlers) { 11928 this._core.$element.off(handler, this._handlers[handler]); 11929 } 11930 for (property in Object.getOwnPropertyNames(this)) { 11931 typeof this[property] != 'function' && (this[property] = null); 11932 } 11933 }; 11934 11935 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 11936 11937})(window.Zepto || window.jQuery, window, document); 11938 11939/** 11940 * Lazy Plugin 11941 * @version 2.0.0-beta.3 11942 * @author Bartosz Wojciechowski 11943 * @license The MIT License (MIT) 11944 */ 11945;(function($, window, document, undefined) { 11946 11947 /** 11948 * Creates the lazy plugin. 11949 * @class The Lazy Plugin 11950 * @param {Owl} carousel - The Owl Carousel 11951 */ 11952 var Lazy = function(carousel) { 11953 11954 /** 11955 * Reference to the core. 11956 * @protected 11957 * @type {Owl} 11958 */ 11959 this._core = carousel; 11960 11961 /** 11962 * Already loaded items. 11963 * @protected 11964 * @type {Array.<jQuery>} 11965 */ 11966 this._loaded = []; 11967 11968 /** 11969 * Event handlers. 11970 * @protected 11971 * @type {Object} 11972 */ 11973 this._handlers = { 11974 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 11975 if (!e.namespace) { 11976 return; 11977 } 11978 11979 if (!this._core.settings || !this._core.settings.lazyLoad) { 11980 return; 11981 } 11982 11983 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 11984 var settings = this._core.settings, 11985 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 11986 i = ((settings.center && n * -1) || 0), 11987 position = ((e.property && e.property.value) || this._core.current()) + i, 11988 clones = this._core.clones().length, 11989 load = $.proxy(function(i, v) { this.load(v) }, this); 11990 11991 while (i++ < n) { 11992 this.load(clones / 2 + this._core.relative(position)); 11993 clones && $.each(this._core.clones(this._core.relative(position)), load); 11994 position++; 11995 } 11996 } 11997 }, this) 11998 }; 11999 12000 // set the default options 12001 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 12002 12003 // register event handler 12004 this._core.$element.on(this._handlers); 12005 } 12006 12007 /** 12008 * Default options. 12009 * @public 12010 */ 12011 Lazy.Defaults = { 12012 lazyLoad: false 12013 } 12014 12015 /** 12016 * Loads all resources of an item at the specified position. 12017 * @param {Number} position - The absolute position of the item. 12018 * @protected 12019 */ 12020 Lazy.prototype.load = function(position) { 12021 var $item = this._core.$stage.children().eq(position), 12022 $elements = $item && $item.find('.owl-lazy'); 12023 12024 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 12025 return; 12026 } 12027 12028 $elements.each($.proxy(function(index, element) { 12029 var $element = $(element), image, 12030 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 12031 12032 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 12033 12034 if ($element.is('img')) { 12035 $element.one('load.owl.lazy', $.proxy(function() { 12036 $element.css('opacity', 1); 12037 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12038 }, this)).attr('src', url); 12039 } else { 12040 image = new Image(); 12041 image.onload = $.proxy(function() { 12042 $element.css({ 12043 'background-image': 'url(' + url + ')', 12044 'opacity': '1' 12045 }); 12046 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12047 }, this); 12048 image.src = url; 12049 } 12050 }, this)); 12051 12052 this._loaded.push($item.get(0)); 12053 } 12054 12055 /** 12056 * Destroys the plugin. 12057 * @public 12058 */ 12059 Lazy.prototype.destroy = function() { 12060 var handler, property; 12061 12062 for (handler in this.handlers) { 12063 this._core.$element.off(handler, this.handlers[handler]); 12064 } 12065 for (property in Object.getOwnPropertyNames(this)) { 12066 typeof this[property] != 'function' && (this[property] = null); 12067 } 12068 }; 12069 12070 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 12071 12072})(window.Zepto || window.jQuery, window, document); 12073 12074/** 12075 * AutoHeight Plugin 12076 * @version 2.0.0-beta.3 12077 * @author Bartosz Wojciechowski 12078 * @license The MIT License (MIT) 12079 */ 12080;(function($, window, document, undefined) { 12081 12082 /** 12083 * Creates the auto height plugin. 12084 * @class The Auto Height Plugin 12085 * @param {Owl} carousel - The Owl Carousel 12086 */ 12087 var AutoHeight = function(carousel) { 12088 /** 12089 * Reference to the core. 12090 * @protected 12091 * @type {Owl} 12092 */ 12093 this._core = carousel; 12094 12095 /** 12096 * All event handlers. 12097 * @protected 12098 * @type {Object} 12099 */ 12100 this._handlers = { 12101 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 12102 if (e.namespace && this._core.settings.autoHeight) { 12103 this.update(); 12104 } 12105 }, this), 12106 'changed.owl.carousel': $.proxy(function(e) { 12107 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 12108 this.update(); 12109 } 12110 }, this), 12111 'loaded.owl.lazy': $.proxy(function(e) { 12112 if (e.namespace && this._core.settings.autoHeight 12113 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 12114 this.update(); 12115 } 12116 }, this) 12117 }; 12118 12119 // set default options 12120 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 12121 12122 // register event handlers 12123 this._core.$element.on(this._handlers); 12124 }; 12125 12126 /** 12127 * Default options. 12128 * @public 12129 */ 12130 AutoHeight.Defaults = { 12131 autoHeight: false, 12132 autoHeightClass: 'owl-height' 12133 }; 12134 12135 /** 12136 * Updates the view. 12137 */ 12138 AutoHeight.prototype.update = function() { 12139 var start = this._core._current, 12140 end = start + this._core.settings.items, 12141 visible = this._core.$stage.children().toArray().slice(start, end); 12142 heights = [], 12143 maxheight = 0; 12144 12145 $.each(visible, function(index, item) { 12146 heights.push($(item).height()); 12147 }); 12148 12149 maxheight = Math.max.apply(null, heights); 12150 12151 this._core.$stage.parent() 12152 .height(maxheight) 12153 .addClass(this._core.settings.autoHeightClass); 12154 }; 12155 12156 AutoHeight.prototype.destroy = function() { 12157 var handler, property; 12158 12159 for (handler in this._handlers) { 12160 this._core.$element.off(handler, this._handlers[handler]); 12161 } 12162 for (property in Object.getOwnPropertyNames(this)) { 12163 typeof this[property] != 'function' && (this[property] = null); 12164 } 12165 }; 12166 12167 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 12168 12169})(window.Zepto || window.jQuery, window, document); 12170 12171/** 12172 * Video Plugin 12173 * @version 2.0.0-beta.3 12174 * @author Bartosz Wojciechowski 12175 * @license The MIT License (MIT) 12176 */ 12177;(function($, window, document, undefined) { 12178 12179 /** 12180 * Creates the video plugin. 12181 * @class The Video Plugin 12182 * @param {Owl} carousel - The Owl Carousel 12183 */ 12184 var Video = function(carousel) { 12185 /** 12186 * Reference to the core. 12187 * @protected 12188 * @type {Owl} 12189 */ 12190 this._core = carousel; 12191 12192 /** 12193 * Cache all video URLs. 12194 * @protected 12195 * @type {Object} 12196 */ 12197 this._videos = {}; 12198 12199 /** 12200 * Current playing item. 12201 * @protected 12202 * @type {jQuery} 12203 */ 12204 this._playing = null; 12205 12206 /** 12207 * All event handlers. 12208 * @todo The cloned content removale is too late 12209 * @protected 12210 * @type {Object} 12211 */ 12212 this._handlers = { 12213 'initialized.owl.carousel': $.proxy(function(e) { 12214 if (e.namespace) { 12215 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 12216 } 12217 }, this), 12218 'resize.owl.carousel': $.proxy(function(e) { 12219 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 12220 e.preventDefault(); 12221 } 12222 }, this), 12223 'refreshed.owl.carousel': $.proxy(function(e) { 12224 if (e.namespace && this._core.is('resizing')) { 12225 this._core.$stage.find('.cloned .owl-video-frame').remove(); 12226 } 12227 }, this), 12228 'changed.owl.carousel': $.proxy(function(e) { 12229 if (e.namespace && e.property.name === 'position' && this._playing) { 12230 this.stop(); 12231 } 12232 }, this), 12233 'prepared.owl.carousel': $.proxy(function(e) { 12234 if (!e.namespace) { 12235 return; 12236 } 12237 12238 var $element = $(e.content).find('.owl-video'); 12239 12240 if ($element.length) { 12241 $element.css('display', 'none'); 12242 this.fetch($element, $(e.content)); 12243 } 12244 }, this) 12245 }; 12246 12247 // set default options 12248 this._core.options = $.extend({}, Video.Defaults, this._core.options); 12249 12250 // register event handlers 12251 this._core.$element.on(this._handlers); 12252 12253 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 12254 this.play(e); 12255 }, this)); 12256 }; 12257 12258 /** 12259 * Default options. 12260 * @public 12261 */ 12262 Video.Defaults = { 12263 video: false, 12264 videoHeight: false, 12265 videoWidth: false 12266 }; 12267 12268 /** 12269 * Gets the video ID and the type (YouTube/Vimeo only). 12270 * @protected 12271 * @param {jQuery} target - The target containing the video data. 12272 * @param {jQuery} item - The item containing the video. 12273 */ 12274 Video.prototype.fetch = function(target, item) { 12275 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 12276 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 12277 width = target.attr('data-width') || this._core.settings.videoWidth, 12278 height = target.attr('data-height') || this._core.settings.videoHeight, 12279 url = target.attr('href'); 12280 12281 if (url) { 12282 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+)?/); 12283 12284 if (id[3].indexOf('youtu') > -1) { 12285 type = 'youtube'; 12286 } else if (id[3].indexOf('vimeo') > -1) { 12287 type = 'vimeo'; 12288 } else { 12289 throw new Error('Video URL not supported.'); 12290 } 12291 id = id[6]; 12292 } else { 12293 throw new Error('Missing video URL.'); 12294 } 12295 12296 this._videos[url] = { 12297 type: type, 12298 id: id, 12299 width: width, 12300 height: height 12301 }; 12302 12303 item.attr('data-video', url); 12304 12305 this.thumbnail(target, this._videos[url]); 12306 }; 12307 12308 /** 12309 * Creates video thumbnail. 12310 * @protected 12311 * @param {jQuery} target - The target containing the video data. 12312 * @param {Object} info - The video info object. 12313 * @see `fetch` 12314 */ 12315 Video.prototype.thumbnail = function(target, video) { 12316 var tnLink, 12317 icon, 12318 path, 12319 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 12320 customTn = target.find('img'), 12321 srcType = 'src', 12322 lazyClass = '', 12323 settings = this._core.settings, 12324 create = function(path) { 12325 icon = '<div class="owl-video-play-icon"></div>'; 12326 12327 if (settings.lazyLoad) { 12328 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 12329 } else { 12330 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 12331 } 12332 target.after(tnLink); 12333 target.after(icon); 12334 }; 12335 12336 // wrap video content into owl-video-wrapper div 12337 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 12338 12339 if (this._core.settings.lazyLoad) { 12340 srcType = 'data-src'; 12341 lazyClass = 'owl-lazy'; 12342 } 12343 12344 // custom thumbnail 12345 if (customTn.length) { 12346 create(customTn.attr(srcType)); 12347 customTn.remove(); 12348 return false; 12349 } 12350 12351 if (video.type === 'youtube') { 12352 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 12353 create(path); 12354 } else if (video.type === 'vimeo') { 12355 $.ajax({ 12356 type: 'GET', 12357 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 12358 jsonp: 'callback', 12359 dataType: 'jsonp', 12360 success: function(data) { 12361 path = data[0].thumbnail_large; 12362 create(path); 12363 } 12364 }); 12365 } 12366 }; 12367 12368 /** 12369 * Stops the current video. 12370 * @public 12371 */ 12372 Video.prototype.stop = function() { 12373 this._core.trigger('stop', null, 'video'); 12374 this._playing.find('.owl-video-frame').remove(); 12375 this._playing.removeClass('owl-video-playing'); 12376 this._playing = null; 12377 this._core.leave('playing'); 12378 this._core.trigger('stopped', null, 'video'); 12379 }; 12380 12381 /** 12382 * Starts the current video. 12383 * @public 12384 * @param {Event} event - The event arguments. 12385 */ 12386 Video.prototype.play = function(event) { 12387 var target = $(event.target), 12388 item = target.closest('.' + this._core.settings.itemClass), 12389 video = this._videos[item.attr('data-video')], 12390 width = video.width || '100%', 12391 height = video.height || this._core.$stage.height(), 12392 html; 12393 12394 if (this._playing) { 12395 return; 12396 } 12397 12398 this._core.enter('playing'); 12399 this._core.trigger('play', null, 'video'); 12400 12401 item = this._core.items(this._core.relative(item.index())); 12402 12403 this._core.reset(item.index()); 12404 12405 if (video.type === 'youtube') { 12406 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 12407 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 12408 } else if (video.type === 'vimeo') { 12409 html = '<iframe src="//player.vimeo.com/video/' + video.id + 12410 '?autoplay=1" width="' + width + '" height="' + height + 12411 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 12412 } 12413 12414 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 12415 12416 this._playing = item.addClass('owl-video-playing'); 12417 }; 12418 12419 /** 12420 * Checks whether an video is currently in full screen mode or not. 12421 * @todo Bad style because looks like a readonly method but changes members. 12422 * @protected 12423 * @returns {Boolean} 12424 */ 12425 Video.prototype.isInFullScreen = function() { 12426 var element = document.fullscreenElement || document.mozFullScreenElement || 12427 document.webkitFullscreenElement; 12428 12429 return element && $(element).parent().hasClass('owl-video-frame'); 12430 }; 12431 12432 /** 12433 * Destroys the plugin. 12434 */ 12435 Video.prototype.destroy = function() { 12436 var handler, property; 12437 12438 this._core.$element.off('click.owl.video'); 12439 12440 for (handler in this._handlers) { 12441 this._core.$element.off(handler, this._handlers[handler]); 12442 } 12443 for (property in Object.getOwnPropertyNames(this)) { 12444 typeof this[property] != 'function' && (this[property] = null); 12445 } 12446 }; 12447 12448 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 12449 12450})(window.Zepto || window.jQuery, window, document); 12451 12452/** 12453 * Animate Plugin 12454 * @version 2.0.0-beta.3 12455 * @author Bartosz Wojciechowski 12456 * @license The MIT License (MIT) 12457 */ 12458;(function($, window, document, undefined) { 12459 12460 /** 12461 * Creates the animate plugin. 12462 * @class The Navigation Plugin 12463 * @param {Owl} scope - The Owl Carousel 12464 */ 12465 var Animate = function(scope) { 12466 this.core = scope; 12467 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 12468 this.swapping = true; 12469 this.previous = undefined; 12470 this.next = undefined; 12471 12472 this.handlers = { 12473 'change.owl.carousel': $.proxy(function(e) { 12474 if (e.namespace && e.property.name == 'position') { 12475 this.previous = this.core.current(); 12476 this.next = e.property.value; 12477 } 12478 }, this), 12479 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 12480 if (e.namespace) { 12481 this.swapping = e.type == 'translated'; 12482 } 12483 }, this), 12484 'translate.owl.carousel': $.proxy(function(e) { 12485 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 12486 this.swap(); 12487 } 12488 }, this) 12489 }; 12490 12491 this.core.$element.on(this.handlers); 12492 }; 12493 12494 /** 12495 * Default options. 12496 * @public 12497 */ 12498 Animate.Defaults = { 12499 animateOut: false, 12500 animateIn: false 12501 }; 12502 12503 /** 12504 * Toggles the animation classes whenever an translations starts. 12505 * @protected 12506 * @returns {Boolean|undefined} 12507 */ 12508 Animate.prototype.swap = function() { 12509 12510 if (this.core.settings.items !== 1) { 12511 return; 12512 } 12513 12514 if (!$.support.animation || !$.support.transition) { 12515 return; 12516 } 12517 12518 this.core.speed(0); 12519 12520 var left, 12521 clear = $.proxy(this.clear, this), 12522 previous = this.core.$stage.children().eq(this.previous), 12523 next = this.core.$stage.children().eq(this.next), 12524 incoming = this.core.settings.animateIn, 12525 outgoing = this.core.settings.animateOut; 12526 12527 if (this.core.current() === this.previous) { 12528 return; 12529 } 12530 12531 if (outgoing) { 12532 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 12533 previous.css( { 'left': left + 'px' } ) 12534 .addClass('animated owl-animated-out') 12535 .addClass(outgoing) 12536 .on($.support.animation.end, clear); 12537 } 12538 12539 if (incoming) { 12540 next.addClass('animated owl-animated-in') 12541 .addClass(incoming) 12542 .on($.support.animation.end, clear); 12543 } 12544 }; 12545 12546 Animate.prototype.clear = function(e) { 12547 if ($(e.target).hasClass('animated')) { 12548 $(e.target).css( { 'left': '' } ) 12549 .removeClass('animated owl-animated-out owl-animated-in') 12550 .removeClass(this.core.settings.animateIn) 12551 .removeClass(this.core.settings.animateOut); 12552 this.core.onTransitionEnd(); 12553 } 12554 }; 12555 12556 /** 12557 * Destroys the plugin. 12558 * @public 12559 */ 12560 Animate.prototype.destroy = function() { 12561 var handler, property; 12562 12563 for (handler in this.handlers) { 12564 this.core.$element.off(handler, this.handlers[handler]); 12565 } 12566 for (property in Object.getOwnPropertyNames(this)) { 12567 typeof this[property] != 'function' && (this[property] = null); 12568 } 12569 }; 12570 12571 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 12572 12573})(window.Zepto || window.jQuery, window, document); 12574 12575/** 12576 * Autoplay Plugin 12577 * @version 2.0.0-beta.3 12578 * @author Bartosz Wojciechowski 12579 * @author Artus Kolanowski 12580 * @license The MIT License (MIT) 12581 */ 12582;(function($, window, document, undefined) { 12583 12584 /** 12585 * Creates the autoplay plugin. 12586 * @class The Autoplay Plugin 12587 * @param {Owl} scope - The Owl Carousel 12588 */ 12589 var Autoplay = function(carousel) { 12590 /** 12591 * Reference to the core. 12592 * @protected 12593 * @type {Owl} 12594 */ 12595 this._core = carousel; 12596 12597 /** 12598 * The autoplay interval. 12599 * @type {Number} 12600 */ 12601 this._interval = null; 12602 12603 /** 12604 * Indicates whenever the autoplay is paused. 12605 * @type {Boolean} 12606 */ 12607 this._paused = false; 12608 12609 /** 12610 * All event handlers. 12611 * @protected 12612 * @type {Object} 12613 */ 12614 this._handlers = { 12615 'changed.owl.carousel': $.proxy(function(e) { 12616 if (e.namespace && e.property.name === 'settings') { 12617 if (this._core.settings.autoplay) { 12618 this.play(); 12619 } else { 12620 this.stop(); 12621 } 12622 } 12623 }, this), 12624 'initialized.owl.carousel': $.proxy(function(e) { 12625 if (e.namespace && this._core.settings.autoplay) { 12626 this.play(); 12627 } 12628 }, this), 12629 'play.owl.autoplay': $.proxy(function(e, t, s) { 12630 if (e.namespace) { 12631 this.play(t, s); 12632 } 12633 }, this), 12634 'stop.owl.autoplay': $.proxy(function(e) { 12635 if (e.namespace) { 12636 this.stop(); 12637 } 12638 }, this), 12639 'mouseover.owl.autoplay': $.proxy(function() { 12640 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12641 this.pause(); 12642 } 12643 }, this), 12644 'mouseleave.owl.autoplay': $.proxy(function() { 12645 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12646 this.play(); 12647 } 12648 }, this) 12649 }; 12650 12651 // register event handlers 12652 this._core.$element.on(this._handlers); 12653 12654 // set default options 12655 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 12656 }; 12657 12658 /** 12659 * Default options. 12660 * @public 12661 */ 12662 Autoplay.Defaults = { 12663 autoplay: false, 12664 autoplayTimeout: 5000, 12665 autoplayHoverPause: false, 12666 autoplaySpeed: false 12667 }; 12668 12669 /** 12670 * Starts the autoplay. 12671 * @public 12672 * @param {Number} [timeout] - The interval before the next animation starts. 12673 * @param {Number} [speed] - The animation speed for the animations. 12674 */ 12675 Autoplay.prototype.play = function(timeout, speed) { 12676 this._paused = false; 12677 12678 if (this._core.is('rotating')) { 12679 return; 12680 } 12681 12682 this._core.enter('rotating'); 12683 12684 this._interval = window.setInterval($.proxy(function() { 12685 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 12686 return; 12687 } 12688 this._core.next(speed || this._core.settings.autoplaySpeed); 12689 }, this), timeout || this._core.settings.autoplayTimeout); 12690 }; 12691 12692 /** 12693 * Stops the autoplay. 12694 * @public 12695 */ 12696 Autoplay.prototype.stop = function() { 12697 if (!this._core.is('rotating')) { 12698 return; 12699 } 12700 12701 window.clearInterval(this._interval); 12702 this._core.leave('rotating'); 12703 }; 12704 12705 /** 12706 * Stops the autoplay. 12707 * @public 12708 */ 12709 Autoplay.prototype.pause = function() { 12710 if (!this._core.is('rotating')) { 12711 return; 12712 } 12713 12714 this._paused = true; 12715 }; 12716 12717 /** 12718 * Destroys the plugin. 12719 */ 12720 Autoplay.prototype.destroy = function() { 12721 var handler, property; 12722 12723 this.stop(); 12724 12725 for (handler in this._handlers) { 12726 this._core.$element.off(handler, this._handlers[handler]); 12727 } 12728 for (property in Object.getOwnPropertyNames(this)) { 12729 typeof this[property] != 'function' && (this[property] = null); 12730 } 12731 }; 12732 12733 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 12734 12735})(window.Zepto || window.jQuery, window, document); 12736 12737/** 12738 * Navigation Plugin 12739 * @version 2.0.0-beta.3 12740 * @author Artus Kolanowski 12741 * @license The MIT License (MIT) 12742 */ 12743;(function($, window, document, undefined) { 12744 'use strict'; 12745 12746 /** 12747 * Creates the navigation plugin. 12748 * @class The Navigation Plugin 12749 * @param {Owl} carousel - The Owl Carousel. 12750 */ 12751 var Navigation = function(carousel) { 12752 /** 12753 * Reference to the core. 12754 * @protected 12755 * @type {Owl} 12756 */ 12757 this._core = carousel; 12758 12759 /** 12760 * Indicates whether the plugin is initialized or not. 12761 * @protected 12762 * @type {Boolean} 12763 */ 12764 this._initialized = false; 12765 12766 /** 12767 * The current paging indexes. 12768 * @protected 12769 * @type {Array} 12770 */ 12771 this._pages = []; 12772 12773 /** 12774 * All DOM elements of the user interface. 12775 * @protected 12776 * @type {Object} 12777 */ 12778 this._controls = {}; 12779 12780 /** 12781 * Markup for an indicator. 12782 * @protected 12783 * @type {Array.<String>} 12784 */ 12785 this._templates = []; 12786 12787 /** 12788 * The carousel element. 12789 * @type {jQuery} 12790 */ 12791 this.$element = this._core.$element; 12792 12793 /** 12794 * Overridden methods of the carousel. 12795 * @protected 12796 * @type {Object} 12797 */ 12798 this._overrides = { 12799 next: this._core.next, 12800 prev: this._core.prev, 12801 to: this._core.to 12802 }; 12803 12804 /** 12805 * All event handlers. 12806 * @protected 12807 * @type {Object} 12808 */ 12809 this._handlers = { 12810 'prepared.owl.carousel': $.proxy(function(e) { 12811 if (e.namespace && this._core.settings.dotsData) { 12812 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 12813 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 12814 } 12815 }, this), 12816 'added.owl.carousel': $.proxy(function(e) { 12817 if (e.namespace && this._core.settings.dotsData) { 12818 this._templates.splice(e.position, 0, this._templates.pop()); 12819 } 12820 }, this), 12821 'remove.owl.carousel': $.proxy(function(e) { 12822 if (e.namespace && this._core.settings.dotsData) { 12823 this._templates.splice(e.position, 1); 12824 } 12825 }, this), 12826 'changed.owl.carousel': $.proxy(function(e) { 12827 if (e.namespace && e.property.name == 'position') { 12828 this.draw(); 12829 } 12830 }, this), 12831 'initialized.owl.carousel': $.proxy(function(e) { 12832 if (e.namespace && !this._initialized) { 12833 this._core.trigger('initialize', null, 'navigation'); 12834 this.initialize(); 12835 this.update(); 12836 this.draw(); 12837 this._initialized = true; 12838 this._core.trigger('initialized', null, 'navigation'); 12839 } 12840 }, this), 12841 'refreshed.owl.carousel': $.proxy(function(e) { 12842 if (e.namespace && this._initialized) { 12843 this._core.trigger('refresh', null, 'navigation'); 12844 this.update(); 12845 this.draw(); 12846 this._core.trigger('refreshed', null, 'navigation'); 12847 } 12848 }, this) 12849 }; 12850 12851 // set default options 12852 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 12853 12854 // register event handlers 12855 this.$element.on(this._handlers); 12856 }; 12857 12858 /** 12859 * Default options. 12860 * @public 12861 * @todo Rename `slideBy` to `navBy` 12862 */ 12863 Navigation.Defaults = { 12864 nav: false, 12865 navText: [ 'prev', 'next' ], 12866 navSpeed: false, 12867 navElement: 'div', 12868 navContainer: false, 12869 navContainerClass: 'owl-nav', 12870 navClass: [ 'owl-prev', 'owl-next' ], 12871 slideBy: 1, 12872 dotClass: 'owl-dot', 12873 dotsClass: 'owl-dots', 12874 dots: true, 12875 dotsEach: false, 12876 dotsData: false, 12877 dotsSpeed: false, 12878 dotsContainer: false 12879 }; 12880 12881 /** 12882 * Initializes the layout of the plugin and extends the carousel. 12883 * @protected 12884 */ 12885 Navigation.prototype.initialize = function() { 12886 var override, 12887 settings = this._core.settings; 12888 12889 // create DOM structure for relative navigation 12890 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 12891 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 12892 12893 this._controls.$previous = $('<' + settings.navElement + '>') 12894 .addClass(settings.navClass[0]) 12895 .html(settings.navText[0]) 12896 .prependTo(this._controls.$relative) 12897 .on('click', $.proxy(function(e) { 12898 this.prev(settings.navSpeed); 12899 }, this)); 12900 this._controls.$next = $('<' + settings.navElement + '>') 12901 .addClass(settings.navClass[1]) 12902 .html(settings.navText[1]) 12903 .appendTo(this._controls.$relative) 12904 .on('click', $.proxy(function(e) { 12905 this.next(settings.navSpeed); 12906 }, this)); 12907 12908 // create DOM structure for absolute navigation 12909 if (!settings.dotsData) { 12910 this._templates = [ $('<div>') 12911 .addClass(settings.dotClass) 12912 .append($('<span>')) 12913 .prop('outerHTML') ]; 12914 } 12915 12916 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 12917 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 12918 12919 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 12920 var index = $(e.target).parent().is(this._controls.$absolute) 12921 ? $(e.target).index() : $(e.target).parent().index(); 12922 12923 e.preventDefault(); 12924 12925 this.to(index, settings.dotsSpeed); 12926 }, this)); 12927 12928 // override public methods of the carousel 12929 for (override in this._overrides) { 12930 this._core[override] = $.proxy(this[override], this); 12931 } 12932 }; 12933 12934 /** 12935 * Destroys the plugin. 12936 * @protected 12937 */ 12938 Navigation.prototype.destroy = function() { 12939 var handler, control, property, override; 12940 12941 for (handler in this._handlers) { 12942 this.$element.off(handler, this._handlers[handler]); 12943 } 12944 for (control in this._controls) { 12945 this._controls[control].remove(); 12946 } 12947 for (override in this.overides) { 12948 this._core[override] = this._overrides[override]; 12949 } 12950 for (property in Object.getOwnPropertyNames(this)) { 12951 typeof this[property] != 'function' && (this[property] = null); 12952 } 12953 }; 12954 12955 /** 12956 * Updates the internal state. 12957 * @protected 12958 */ 12959 Navigation.prototype.update = function() { 12960 var i, j, k, 12961 lower = this._core.clones().length / 2, 12962 upper = lower + this._core.items().length, 12963 maximum = this._core.maximum(true), 12964 settings = this._core.settings, 12965 size = settings.center || settings.autoWidth || settings.dotsData 12966 ? 1 : settings.dotsEach || settings.items; 12967 12968 if (settings.slideBy !== 'page') { 12969 settings.slideBy = Math.min(settings.slideBy, settings.items); 12970 } 12971 12972 if (settings.dots || settings.slideBy == 'page') { 12973 this._pages = []; 12974 12975 for (i = lower, j = 0, k = 0; i < upper; i++) { 12976 if (j >= size || j === 0) { 12977 this._pages.push({ 12978 start: Math.min(maximum, i - lower), 12979 end: i - lower + size - 1 12980 }); 12981 if (Math.min(maximum, i - lower) === maximum) { 12982 break; 12983 } 12984 j = 0, ++k; 12985 } 12986 j += this._core.mergers(this._core.relative(i)); 12987 } 12988 } 12989 }; 12990 12991 /** 12992 * Draws the user interface. 12993 * @todo The option `dotsData` wont work. 12994 * @protected 12995 */ 12996 Navigation.prototype.draw = function() { 12997 var difference, 12998 settings = this._core.settings, 12999 disabled = this._core.items().length <= settings.items, 13000 index = this._core.relative(this._core.current()), 13001 loop = settings.loop || settings.rewind; 13002 13003 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 13004 13005 if (settings.nav) { 13006 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 13007 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 13008 } 13009 13010 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 13011 13012 if (settings.dots) { 13013 difference = this._pages.length - this._controls.$absolute.children().length; 13014 13015 if (settings.dotsData && difference !== 0) { 13016 this._controls.$absolute.html(this._templates.join('')); 13017 } else if (difference > 0) { 13018 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 13019 } else if (difference < 0) { 13020 this._controls.$absolute.children().slice(difference).remove(); 13021 } 13022 13023 this._controls.$absolute.find('.active').removeClass('active'); 13024 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 13025 } 13026 }; 13027 13028 /** 13029 * Extends event data. 13030 * @protected 13031 * @param {Event} event - The event object which gets thrown. 13032 */ 13033 Navigation.prototype.onTrigger = function(event) { 13034 var settings = this._core.settings; 13035 13036 event.page = { 13037 index: $.inArray(this.current(), this._pages), 13038 count: this._pages.length, 13039 size: settings && (settings.center || settings.autoWidth || settings.dotsData 13040 ? 1 : settings.dotsEach || settings.items) 13041 }; 13042 }; 13043 13044 /** 13045 * Gets the current page position of the carousel. 13046 * @protected 13047 * @returns {Number} 13048 */ 13049 Navigation.prototype.current = function() { 13050 var current = this._core.relative(this._core.current()); 13051 return $.grep(this._pages, $.proxy(function(page, index) { 13052 return page.start <= current && page.end >= current; 13053 }, this)).pop(); 13054 }; 13055 13056 /** 13057 * Gets the current succesor/predecessor position. 13058 * @protected 13059 * @returns {Number} 13060 */ 13061 Navigation.prototype.getPosition = function(successor) { 13062 var position, length, 13063 settings = this._core.settings; 13064 13065 if (settings.slideBy == 'page') { 13066 position = $.inArray(this.current(), this._pages); 13067 length = this._pages.length; 13068 successor ? ++position : --position;
vendor: 5,678 bytes, lines 13069-13293
13069 position = this._pages[((position % length) + length) % length].start; 13070 } else { 13071 position = this._core.relative(this._core.current()); 13072 length = this._core.items().length; 13073 successor ? position += settings.slideBy : position -= settings.slideBy; 13074 } 13075 13076 return position; 13077 }; 13078 13079 /** 13080 * Slides to the next item or page. 13081 * @public 13082 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13083 */ 13084 Navigation.prototype.next = function(speed) { 13085 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 13086 }; 13087 13088 /** 13089 * Slides to the previous item or page. 13090 * @public 13091 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13092 */ 13093 Navigation.prototype.prev = function(speed) { 13094 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 13095 }; 13096 13097 /** 13098 * Slides to the specified item or page. 13099 * @public 13100 * @param {Number} position - The position of the item or page. 13101 * @param {Number} [speed] - The time in milliseconds for the transition. 13102 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 13103 */ 13104 Navigation.prototype.to = function(position, speed, standard) { 13105 var length; 13106 13107 if (!standard) { 13108 length = this._pages.length; 13109 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 13110 } else { 13111 $.proxy(this._overrides.to, this._core)(position, speed); 13112 } 13113 }; 13114 13115 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 13116 13117})(window.Zepto || window.jQuery, window, document); 13118 13119/** 13120 * Hash Plugin 13121 * @version 2.0.0-beta.3 13122 * @author Artus Kolanowski 13123 * @license The MIT License (MIT) 13124 */ 13125;(function($, window, document, undefined) { 13126 'use strict'; 13127 13128 /** 13129 * Creates the hash plugin. 13130 * @class The Hash Plugin 13131 * @param {Owl} carousel - The Owl Carousel 13132 */ 13133 var Hash = function(carousel) { 13134 /** 13135 * Reference to the core. 13136 * @protected 13137 * @type {Owl} 13138 */ 13139 this._core = carousel; 13140 13141 /** 13142 * Hash index for the items. 13143 * @protected 13144 * @type {Object} 13145 */ 13146 this._hashes = {}; 13147 13148 /** 13149 * The carousel element. 13150 * @type {jQuery} 13151 */ 13152 this.$element = this._core.$element; 13153 13154 /** 13155 * All event handlers. 13156 * @protected 13157 * @type {Object} 13158 */ 13159 this._handlers = { 13160 /*'initialized.owl.carousel': $.proxy(function(e) { 13161 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 13162 $(window).trigger('hashchange.owl.navigation'); 13163 } 13164 }, this),*/ 13165 'prepared.owl.carousel': $.proxy(function(e) { 13166 if (e.namespace) { 13167 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 13168 13169 if (!hash) { 13170 return; 13171 } 13172 13173 this._hashes[hash] = e.content; 13174 } 13175 }, this), 13176 'changed.owl.carousel': $.proxy(function(e) { 13177 if (e.namespace && e.property.name === 'position') { 13178 var current = this._core.items(this._core.relative(this._core.current())), 13179 hash = $.map(this._hashes, function(item, hash) { 13180 return item === current ? hash : null; 13181 }).join(); 13182 13183 if (!hash || window.location.hash.slice(1) === hash) { 13184 return; 13185 } 13186 13187 window.location.hash = hash; 13188 } 13189 }, this) 13190 }; 13191 13192 // set default options 13193 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 13194 13195 // register the event handlers 13196 this.$element.on(this._handlers); 13197 13198 // register event listener for hash navigation 13199 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 13200 var hash = window.location.hash.substring(1), 13201 items = this._core.$stage.children(), 13202 position = this._hashes[hash] && items.index(this._hashes[hash]); 13203 13204 if (position === undefined || position === this._core.current()) { 13205 return; 13206 } 13207 13208 this._core.to(this._core.relative(position), false, true); 13209 }, this));*/ 13210 }; 13211 13212 /** 13213 * Default options. 13214 * @public 13215 */ 13216 Hash.Defaults = { 13217 URLhashListener: false 13218 }; 13219 13220 /** 13221 * Destroys the plugin. 13222 * @public 13223 */ 13224 Hash.prototype.destroy = function() { 13225 var handler, property; 13226 13227 $(window).off('hashchange.owl.navigation'); 13228 13229 for (handler in this._handlers) { 13230 this._core.$element.off(handler, this._handlers[handler]); 13231 } 13232 for (property in Object.getOwnPropertyNames(this)) { 13233 typeof this[property] != 'function' && (this[property] = null); 13234 } 13235 }; 13236 13237 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 13238 13239})(window.Zepto || window.jQuery, window, document); 13240 13241/** 13242 * Support Plugin 13243 * 13244 * @version 2.0.0-beta.3 13245 * @author Vivid Planet Software GmbH 13246 * @author Artus Kolanowski 13247 * @license The MIT License (MIT) 13248 */ 13249;(function($, window, document, undefined) { 13250 13251 var style = $('<support>').get(0).style, 13252 prefixes = 'Webkit Moz O ms'.split(' '), 13253 events = { 13254 transition: { 13255 end: { 13256 WebkitTransition: 'webkitTransitionEnd', 13257 MozTransition: 'transitionend', 13258 OTransition: 'oTransitionEnd', 13259 transition: 'transitionend' 13260 } 13261 }, 13262 animation: { 13263 end: { 13264 WebkitAnimation: 'webkitAnimationEnd', 13265 MozAnimation: 'animationend', 13266 OAnimation: 'oAnimationEnd', 13267 animation: 'animationend' 13268 } 13269 } 13270 }, 13271 tests = { 13272 csstransforms: function() { 13273 return !!test('transform'); 13274 }, 13275 csstransforms3d: function() { 13276 return !!test('perspective'); 13277 }, 13278 csstransitions: function() { 13279 return !!test('transition'); 13280 }, 13281 cssanimations: function() { 13282 return !!test('animation'); 13283 } 13284 }; 13285 13286 function test(property, prefixed) { 13287 var result = false, 13288 upper = property.charAt(0).toUpperCase() + property.slice(1); 13289 13290 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 13291 if (style[property] !== undefined) { 13292 result = prefixed ? property : true; 13293 return false;
13294 } 13295 }); 13296 13297 return result; 13298 } 13299 13300 function prefixed(property) { 13301 return test(property, true); 13302 } 13303 13304 if (tests.csstransitions()) { 13305 /* jshint -W053 */ 13306 $.support.transition = new String(prefixed('transition')) 13307 $.support.transition.end = events.transition.end[ $.support.transition ]; 13308 } 13309 13310 if (tests.cssanimations()) { 13311 /* jshint -W053 */ 13312 $.support.animation = new String(prefixed('animation')) 13313 $.support.animation.end = events.animation.end[ $.support.animation ]; 13314 } 13315 13316 if (tests.csstransforms()) { 13317 /* jshint -W053 */ 13318 $.support.transform = new String(prefixed('transform')); 13319 $.support.transform3d = tests.csstransforms3d(); 13320 } 13321 13322})(window.Zepto || window.jQuery, window, document); 13323 13324(function(window, document, undefined) { 13325 13326 /** 13327 * Find the absolute position of an element 13328 */ 13329 var absPos = function(element) { 13330 var offsetLeft, offsetTop; 13331 offsetLeft = offsetTop = 0; 13332 if (element.offsetParent) { 13333 do { 13334 offsetLeft += element.offsetLeft; 13335 offsetTop += element.offsetTop; 13336 } while (element = element.offsetParent); 13337 } 13338 return [offsetLeft, offsetTop]; 13339 }; 13340 13341 /** 13342 * @constructor Progress Circle class 13343 * @param params.canvas Canvas on which the circles will be drawn. 13344 * @param params.minRadius Inner radius of the innermost circle, in px. 13345 * @param params.arcWidth Width of each circle(to be more accurate, ring). 13346 * @param params.gapWidth Space between each circle. 13347 * @param params.centerX X coordinate of the center of circles. 13348 * @param params.centerY Y coordinate of the center of circles. 13349 * @param params.infoLineBaseAngle Base angle of the info line. 13350 * @param params.infoLineAngleInterval Angles between the info lines. 13351 */ 13352 var ProgressCircle = function(params) { 13353 this.canvas = params.canvas; 13354 this.minRadius = params.minRadius || 15; 13355 this.arcWidth = params.arcWidth || 5; 13356 this.gapWidth = params.gapWidth || 3; 13357 this.centerX = params.centerX || this.canvas.width / 2; 13358 this.centerY = params.centerY || this.canvas.height / 2;
13359 this.infoLineLength = params.infoLineLength || 60; 13360 this.horizLineLength = params.horizLineLength || 10; 13361 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 13362 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 13363 13364 this.context = this.canvas.getContext('2d'); 13365 13366 this.width = this.canvas.width; 13367 this.height = this.canvas.height; 13368 13369 this.circles = []; 13370 this.runningCount = 0; 13371 }; 13372 13373 ProgressCircle.prototype = { 13374 constructor: ProgressCircle, 13375 13376 /** 13377 * @method Adds an progress monitor entry. 13378 * @param params.fillColor Color to fill in the circle. 13379 * @param params.outlineColor Color to outline the circle. 13380 * @param params.progressListener Callback function to fetch the progress. 13381 * @param params.infoListener Callback function to fetch the info. 13382 * @returns this 13383 */ 13384 addEntry: function(params) { 13385 this.circles.push(new Circle({ 13386 canvas: this.canvas, 13387 context: this.context, 13388 centerX: this.centerX, 13389 centerY: this.centerY, 13390 innerRadius: this.minRadius + this.circles.length * 13391 (this.gapWidth + this.arcWidth), 13392 arcWidth: this.arcWidth,
13393 infoLineLength: this.infoLineLength, 13394 horizLineLength: this.horizLineLength, 13395 13396 id: this.circles.length, 13397 fillColor: params.fillColor, 13398 outlineColor: params.outlineColor, 13399 progressListener: params.progressListener, 13400 infoListener: params.infoListener, 13401 infoLineAngle: this.infoLineBaseAngle + 13402 this.circles.length * this.infoLineAngleInterval, 13403 })); 13404 13405 return this; 13406 }, 13407 13408 /** 13409 * @method Starts the monitor and updates with the given interval. 13410 * @param interval Interval between updates, in millisecond. 13411 * @returns this 13412 */ 13413 start: function(interval) { 13414 var self = this; 13415 this.timer = setInterval(function() { 13416 self._update(); 13417 }, interval || 33); 13418 13419 return this; 13420 }, 13421 13422 /** 13423 * @method Stop the animation. 13424 */ 13425 stop: function() { 13426 clearTimeout(this.timer); 13427 }, 13428 13429 /** 13430 * @private 13431 * @method Call update on each circle and redraw them. 13432 * @returns this 13433 */ 13434 _update: function() { 13435 this._clear(); 13436 this.circles.forEach(function(circle, idx, array) { 13437 circle.update(); 13438 }); 13439 13440 return this; 13441 }, 13442 13443 /** 13444 * @private 13445 * @method Clear the canvas. 13446 * @returns this 13447 */ 13448 _clear: function() { 13449 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 13450 13451 return this; 13452 }, 13453 13454 }; 13455 13456 /** 13457 * @private 13458 * @class Individual progress circle. 13459 * @param params.canvas Canvas on which the circle will be drawn. 13460 * @param params.context Context of the canvas. 13461 * @param params.innerRadius Inner radius of the circle, in px. 13462 * @param params.arcWidth Width of each arc(circle). 13463 * @param params.gapWidth Distance between each arc. 13464 * @param params.centerX X coordinate of the center of circles. 13465 * @param params.centerY Y coordinate of the center of circles. 13466 * @param params.fillColor Color to fill in the circle. 13467 * @param params.outlineColor Color to outline the circle. 13468 * @param params.progressListener Callback function to fetch the progress. 13469 * @param params.infoListener Callback function to fetch the info. 13470 * @param params.infoLineAngle Angle of info line. 13471 */ 13472 var Circle = function(params) { 13473 this.id = params.id; 13474 this.canvas = params.canvas; 13475 this.context = params.context; 13476 this.centerX = params.centerX; 13477 this.centerY = params.centerY; 13478 this.arcWidth = params.arcWidth; 13479 this.innerRadius = params.innerRadius || 0; 13480 this.fillColor = params.fillColor || '#fff'; 13481 this.outlineColor = params.outlineColor || this.fillColor; 13482 this.progressListener = params.progressListener;
13483 this.infoLineLength = params.infoLineLength || 250; 13484 this.horizLineLength = params.horizLineLength || 50; 13485 this.infoListener = params.infoListener; 13486 this.infoLineAngle = params.infoLineAngle; 13487 13488 this.outerRadius = this.innerRadius + this.arcWidth; 13489 13490 // If the info listener is not registered, then don't calculate 13491 // the related coordinates 13492 if (!this.infoListener) return; 13493 13494 // calculate the info-line turning points 13495 var angle = this.infoLineAngle, 13496 arcDistance = (this.innerRadius + this.outerRadius) / 2, 13497 13498 sinA = Math.sin(angle), 13499 cosA = Math.cos(angle); 13500 13501 this.infoLineStartX = this.centerX + sinA * arcDistance; 13502 this.infoLineStartY = this.centerY - cosA * arcDistance; 13503 13504 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 13505 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 13506 13507 this.infoLineEndX = this.infoLineMidX + 13508 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 13509 this.infoLineEndY = this.infoLineMidY; 13510 13511 var infoText = document.createElement('div'), 13512 style = infoText.style; 13513 13514 style.color = this.fillColor; 13515 style.position = 'absolute'; 13516 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 13517 // style.top will be calculated in the `drawInfo` method. Since 13518 // user may want to change the size of the font, so the top offset 13519 // must be updated in each loop. 13520 infoText.className = 'ProgressCircleInfo'; // For css styling 13521 infoText.id = 'progress_circle_info_' + this.id; 13522 document.body.appendChild(infoText); 13523 this.infoText = infoText; 13524 }; 13525 13526 Circle.prototype = { 13527 constructor: Circle, 13528 13529 update: function() { 13530 this.progress = this.progressListener(); 13531 this._draw(); 13532 13533 if (this.infoListener) { 13534 this.info = this.infoListener(); 13535 this._drawInfo(); 13536 } 13537 }, 13538 13539 /** 13540 * @private 13541 * @method Draw the circle on the canvas. 13542 * @returns this 13543 */ 13544 _draw: function() { 13545 var ctx = this.context, 13546 13547 ANGLE_OFFSET = -Math.PI / 2, 13548 13549 startAngle = 0 + ANGLE_OFFSET, 13550 endAngle= startAngle + this.progress * Math.PI * 2, 13551 13552 x = this.centerX, 13553 y = this.centerY, 13554 13555 innerRadius = this.innerRadius - this.arcWidth - 1, 13556 outerRadius = this.outerRadius - this.arcWidth - 1; 13557 13558 ctx.fillStyle = this.fillColor; 13559 ctx.strokeStyle = this.outlineColor; 13560 13561 ctx.beginPath(); 13562 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 13563 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 13564 ctx.closePath(); 13565 ctx.stroke(); 13566 ctx.fill(); 13567 13568 return this; 13569 }, 13570 13571 /** 13572 * @private 13573 * @method Draw the info lines and info text. 13574 * @returns this 13575 */ 13576 _drawInfo: function() { 13577 13578 var pointList, lineHeight; 13579 13580 pointList = [ 13581 [this.infoLineStartX, this.infoLineStartY], 13582 [this.infoLineMidX, this.infoLineMidY], 13583 [this.infoLineEndX, this.infoLineEndY], 13584 ]; 13585 this._drawSegments(pointList, false); 13586 13587 this.infoText.innerHTML = this.info; 13588 13589 lineHeight = this.infoText.offsetHeight; 13590 this.infoText.style.top = this.infoLineEndY + 13591 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 13592 13593 return this; 13594 }, 13595 13596 /** 13597 * @private 13598 * @method Helper function to draw the segments 13599 * @param pointList An array of points in the form of [x, y]. 13600 * @param close Whether to connect the first and last point. 13601 */ 13602 _drawSegments: function(pointList, close) { 13603 var ctx = this.context; 13604 13605 ctx.beginPath(); 13606 ctx.moveTo(pointList[0][0], pointList[0][1]); 13607 for (var i = 1; i < pointList.length; ++i) { 13608 ctx.lineTo(pointList[i][0], pointList[i][1]); 13609 } 13610 13611 if (close) { 13612 ctx.closePath(); 13613 } 13614 ctx.stroke(); 13615 }, 13616 }; 13617 13618 window.ProgressCircle = ProgressCircle; 13619 13620})(window, document); 13621 13622 13623 13624 13625/* ========================================================= 13626 * jquery.vc_chart.js v1.0 13627 * ========================================================= 13628 * Copyright 2013 Wpbakery 13629 * 13630 * Jquery chart plugin for the Visual Composer.
13631 * ========================================================= */ 13632(function($){ 13633 /** 13634 * Pie chart animated. 13635 * @param element - DOM element 13636 * @param options - settings object. 13637 * @constructor 13638 */ 13639 var VcChart = function(element, options) { 13640 this.el = element; 13641 this.$el = $(this.el); 13642 this.options = $.extend({ 13643 color: 'wpb_button', 13644 units: '', 13645 width: '', 13646 label_selector: '.vc_pie_chart_value', 13647 back_selector: '.vc_pie_chart_back', 13648 responsive: true 13649 }, options); 13650 this.init(); 13651 }; 13652 VcChart.prototype = { 13653 constructor: VcChart, 13654 _progress_v: 0, 13655 animated: false, 13656 colors: { 13657 'wpb_button': 'rgba(247, 247, 247, 1)', 13658 'btn-primary': 'rgba(0, 136, 204, 1)', 13659 'btn-info': 'rgba(88, 185, 218, 1)', 13660 'btn-success': 'rgba(106, 177, 101, 1)', 13661 'btn-warning': 'rgba(255, 153, 0, 1)', 13662 'btn-danger': 'rgba(255, 103, 91, 1)', 13663 'btn-inverse': 'rgba(85, 85, 85, 1)' 13664 }, 13665 init: function() { 13666 this.setupColor(); 13667 this.value = this.$el.data('pie-value')/100; 13668 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 13669 this.$wrapper = $('.vc_pie_wrapper', this.$el); 13670 this.$label = $(this.options.label_selector, this.$el); 13671 this.$back = $(this.options.back_selector, this.$el); 13672 this.$canvas = this.$el.find('canvas'); 13673 this.arcWidth = this.$el.data('pie-width') * 2; 13674 this.draw(); 13675 this.setWayPoint(); 13676 if(this.options.responsive === true) this.setResponsive(); 13677 if (UNCODE.isMobile) this._progress_v = this.value; 13678 }, 13679 setupColor: function() { 13680 // if(typeof this.colors[this.options.color] !== 'undefined') { 13681 // this.color = this.colors[this.options.color]; 13682 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 13683 // this.color = this.options.color; 13684 // } else { 13685 // this.color = 'rgba(247, 247, 247, 0.2)'; 13686 // } 13687 if(typeof this.options.color !== 'undefined') { 13688 this.color = this.options.color; 13689 } else this.color = 'rgba(247, 247, 247, 0.2)'; 13690 13691 }, 13692 setResponsive: function() { 13693 var that = this; 13694 if (!UNCODE.isMobile) { 13695 $(window).resize(function(){ 13696 if(that.animated === true) that.circle.stop(); 13697 that.draw(true); 13698 }); 13699 } 13700 }, 13701 draw: function(redraw) { 13702 var w = this.$el.addClass('vc_ready').width() * 2, 13703 border_w = this.arcWidth, 13704 radius; 13705 if(!w) w = this.$el.parents(':visible').first().width()-2; 13706 //w = Math.round(w/100*80); 13707 //if (w < 250) w = 250; 13708 radius = w/2; 13709 this.$wrapper.css({"width" : (w / 2) + "px"}); 13710 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 13711 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 13712 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 13713 this.$el.addClass('vc_ready'); 13714 this.circle = new ProgressCircle({ 13715 canvas: this.$canvas.get(0), 13716 minRadius: radius, 13717 arcWidth: border_w 13718 }); 13719 if(redraw === true && this.animated === true) { 13720 this._progress_v = this.value; 13721 this.circle.addEntry({ 13722 fillColor: this.color, 13723 progressListener: $.proxy(this.setProgress, this) 13724 }).start(); 13725 } 13726 }, 13727 setProgress: function() { 13728 if (this._progress_v >= this.value) { 13729 this.circle.stop(); 13730 this.$label.html(this.label_value + this.options.units); 13731 return this._progress_v; 13732 } 13733 this._progress_v += 0.01; 13734 if (!isNaN(this.label_value)) { 13735 var label_value = this._progress_v/this.value*this.label_value; 13736 var val = Math.round(label_value) + this.options.units; 13737 this.$label.html(val); 13738 } else this.$label.html(this.label_value + this.options.units); 13739 return this._progress_v; 13740 }, 13741 animate: function() { 13742 if(this.animated !== true) { 13743 this.animated = true; 13744 this.circle.addEntry({ 13745 fillColor: this.color, 13746 progressListener: $.proxy(this.setProgress, this) 13747 }).start(5); 13748 } 13749 }, 13750 setWayPoint: function() { 13751 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 13752 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 13753 } else { 13754 this.animate(); 13755 } 13756 } 13757 }; 13758 /** 13759 * jQuery plugin 13760 * @param option - object with settings 13761 * @return {*} 13762 */ 13763 $.fn.vcChat = function(option, value) { 13764 return this.each(function () { 13765 var $this = $(this), 13766 data = $this.data('vc_chart'), 13767 options = typeof option === 'object' ? option : { 13768 color: $this.data('pie-color'), 13769 units: $this.data('pie-units') 13770 }; 13771 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 13772 if (typeof option == 'string') data[option](value); 13773 }); 13774 }; 13775 /** 13776 * Allows users to rewrite function inside theme. 13777 */ 13778 if ( typeof window['vc_pieChart'] !== 'function' ) { 13779 window.vc_pieChart = function() { 13780 $('.vc_pie_chart:visible').vcChat(); 13781 } 13782 } 13783 $(document).ready(function(){ 13784 !window.vc_iframe && vc_pieChart(); 13785 }); 13786 13787})(window.jQuery); 13788 13789 13790/* Progress bar 13791 ---------------------------------------------------------- */ 13792function uncode_progress_bar() {    13793 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 13794 if (!UNCODE.isMobile) { 13795 new Waypoint({ 13796 element: val, 13797 handler: function() { 13798 var element = jQuery(this.element); 13799 element.find('.vc_single_bar').each(function(index) {          13800 var $this = jQuery(this), 13801             bar = $this.find('.vc_bar'), 13802             val = bar.data('percentage-value');          13803 setTimeout(function() {            13804 bar.css({ 13805 "width": val + '%' 13806 });          13807 }, index * 200);        13808 }); 13809 }, 13810 offset: '80%' 13811 }); 13812 } else { 13813 var element = jQuery(val); 13814 element.find('.vc_single_bar').each(function(index) {          13815 var $this = jQuery(this), 13816             bar = $this.find('.vc_bar'), 13817             val = bar.data('percentage-value');          13818 setTimeout(function() {            13819 bar.css({ 13820 "width": val + '%' 13821 });          13822 }, index * 200);        13823 }); 13824 } 13825 }); 13826}; 13827uncode_progress_bar(); 13828 13829/*! 13830 * jquery.counterup.js 1.0 13831 * 13832 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 13833 * Released under the GPL v2 License 13834 * 13835 * Date: Nov 26, 2013 13836 */ 13837(function($) { 13838 "use strict"; 13839 $.fn.counterUp = function(options) { 13840 // Defaults 13841 var settings = $.extend({ 13842 'time': 400, 13843 'delay': 10 13844 }, options); 13845 return this.each(function() { 13846 // Store the object 13847 var $this = $(this); 13848 var $settings = settings; 13849 var counterUpper = function() { 13850 var nums = []; 13851 var divisions = $settings.time / $settings.delay; 13852 var numReal = $this.text(), 13853 num = numReal; 13854 var isComma = /[0-9]+,[0-9]+/.test(num); 13855 num = num.replace(/,/g, ''); 13856 var isInt = /^[0-9]+$/.test(num); 13857 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 13858 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 13859 // Generate list of incremental numbers to display 13860 for (var i = divisions; i >= 1; i--) { 13861 // Preserve as int if input was int 13862 var newNum = parseInt(num / divisions * i); 13863 // Preserve float if input was float 13864 if (isFloat) { 13865 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 13866 } 13867 // Preserve commas if input had commas 13868 if (isComma) { 13869 while (/(\d+)(\d{3})/.test(newNum.toString())) { 13870 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 13871 } 13872 } 13873 nums.unshift(newNum); 13874 } 13875 nums.push(numReal); 13876 $this.data('counterup-nums', nums); 13877 $this.text('0'); 13878 // Updates the number until we're done 13879 var f = function() { 13880 if ($this.data('counterup-nums') != null) { 13881 $this.text($this.data('counterup-nums').shift()); 13882 if ($this.data('counterup-nums').length) { 13883 setTimeout($this.data('counterup-func'), $settings.delay); 13884 } else { 13885 delete $this.data('counterup-nums'); 13886 $this.data('counterup-nums', null); 13887 $this.data('counterup-func', null); 13888 } 13889 } 13890 }; 13891 $this.data('counterup-func', f); 13892 // Start the count up 13893 setTimeout($this.data('counterup-func'), $settings.delay); 13894 }; 13895 // Perform counts when the element gets into view 13896 new Waypoint({ 13897 element: this, 13898 handler: function() { 13899 counterUpper(); 13900 this.destroy(); 13901 }, 13902 offset: '80%' 13903 }); 13904 }); 13905 }; 13906})(jQuery); 13907 13908/*! 13909 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 13910 * Copyright (c) 2014 Edson Hilios 13911 * 13912 * Permission is hereby granted, free of charge, to any person obtaining a copy of 13913 * this software and associated documentation files (the "Software"), to deal in 13914 * the Software without restriction, including without limitation the rights to 13915 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13916 * the Software, and to permit persons to whom the Software is furnished to do so, 13917 * subject to the following conditions: 13918 * 13919 * The above copyright notice and this permission notice shall be included in all 13920 * copies or substantial portions of the Software. 13921 * 13922 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13923 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13924 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13925 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13926 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 13927 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13928 */ 13929!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;
13929if(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])})}}); 13930 13931/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 13932* https://github.com/alexanderdickson/waitForImages 13933* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 13934;(function (factory) { 13935 if (typeof define === 'function' && define.amd) { 13936 // AMD. Register as an anonymous module. 13937 define(['jquery'], factory); 13938 } else if (typeof exports === 'object') { 13939 // CommonJS / nodejs module 13940 module.exports = factory(require('jquery')); 13941 } else { 13942 // Browser globals 13943 factory(jQuery); 13944 } 13945}(function ($) { 13946 // Namespace all events. 13947 var eventNamespace = 'waitForImages'; 13948 13949 // CSS properties which contain references to images. 13950 $.waitForImages = { 13951 hasImageProperties: [ 13952 'backgroundImage', 13953 'listStyleImage', 13954 'borderImage', 13955 'borderCornerImage', 13956 'cursor' 13957 ], 13958 hasImageAttributes: ['srcset'] 13959 }; 13960 13961 // Custom selector to find `img` elements that have a valid `src` 13962 // attribute and have not already loaded. 13963 $.expr[':'].uncached = function (obj) { 13964 // Ensure we are dealing with an `img` element with a valid 13965 // `src` attribute. 13966 if (!$(obj).is('img[src][src!=""]')) { 13967 return false;
13968 } 13969 13970 return !obj.complete; 13971 }; 13972 13973 $.fn.waitForImages = function () { 13974 13975 var allImgsLength = 0; 13976 var allImgsLoaded = 0; 13977 var deferred = $.Deferred(); 13978 13979 var finishedCallback; 13980 var eachCallback; 13981 var waitForAll; 13982 13983 // Handle options object (if passed). 13984 if ($.isPlainObject(arguments[0])) { 13985 13986 waitForAll = arguments[0].waitForAll; 13987 eachCallback = arguments[0].each; 13988 finishedCallback = arguments[0].finished; 13989 13990 } else { 13991 13992 // Handle if using deferred object and only one param was passed in. 13993 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 13994 waitForAll = arguments[0]; 13995 } else { 13996 finishedCallback = arguments[0]; 13997 eachCallback = arguments[1]; 13998 waitForAll = arguments[2]; 13999 } 14000 14001 } 14002 14003 // Handle missing callbacks. 14004 finishedCallback = finishedCallback || $.noop; 14005 eachCallback = eachCallback || $.noop; 14006 14007 // Convert waitForAll to Boolean 14008 waitForAll = !! waitForAll; 14009 14010 // Ensure callbacks are functions. 14011 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 14012 throw new TypeError('An invalid callback was supplied.'); 14013 } 14014 14015 this.each(function () { 14016 // Build a list of all imgs, dependent on what images will 14017 // be considered. 14018 var obj = $(this); 14019 var allImgs = []; 14020 // CSS properties which may contain an image. 14021 var hasImgProperties = $.waitForImages.hasImageProperties || []; 14022 // Element attributes which may contain an image. 14023 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 14024 // To match `url()` references. 14025 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 14026 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 14027 14028 if (waitForAll) { 14029 14030 // Get all elements (including the original), as any one of 14031 // them could have a background image. 14032 obj.find('*').addBack().each(function () { 14033 var element = $(this); 14034 14035 // If an `img` element, add it. But keep iterating in 14036 // case it has a background image too. 14037 if (element.is('img:uncached')) { 14038 allImgs.push({ 14039 src: element.attr('src'), 14040 element: element[0] 14041 }); 14042 } 14043 14044 $.each(hasImgProperties, function (i, property) { 14045 var propertyValue = element.css(property); 14046 var match; 14047 14048 // If it doesn't contain this property, skip. 14049 if (!propertyValue) { 14050 return true; 14051 } 14052 14053 // Get all url() of this element. 14054 while (match = matchUrl.exec(propertyValue)) { 14055 allImgs.push({ 14056 src: match[2], 14057 element: element[0] 14058 }); 14059 } 14060 }); 14061 14062 $.each(hasImageAttributes, function (i, attribute) { 14063 var attributeValue = element.attr(attribute); 14064 var attributeValues; 14065 14066 // If it doesn't contain this property, skip. 14067 if (!attributeValue) { 14068 return true; 14069 } 14070 14071 // Check for multiple comma separated images 14072 attributeValues = attributeValue.split(','); 14073 14074 $.each(attributeValues, function(i, value) { 14075 // Trim value and get string before first 14076 // whitespace (for use with srcset). 14077 value = $.trim(value).split(' ')[0]; 14078 allImgs.push({ 14079 src: value, 14080 element: element[0] 14081 }); 14082 }); 14083 }); 14084 }); 14085 } else { 14086 // For images only, the task is simpler. 14087 obj.find('img:uncached') 14088 .each(function () { 14089 allImgs.push({ 14090 src: this.src, 14091 element: this 14092 }); 14093 }); 14094 } 14095 14096 allImgsLength = allImgs.length; 14097 allImgsLoaded = 0; 14098 14099 // If no images found, don't bother. 14100 if (allImgsLength === 0) { 14101 finishedCallback.call(obj[0]); 14102 deferred.resolveWith(obj[0]); 14103 } 14104 14105 $.each(allImgs, function (i, img) { 14106 14107 var image = new Image(); 14108 var events = 14109 'load.' + eventNamespace + ' error.' + eventNamespace; 14110 14111 // Handle the image loading and error with the same callback. 14112 $(image).one(events, function me (event) { 14113 // If an error occurred with loading the image, set the 14114 // third argument accordingly. 14115 var eachArguments = [ 14116 allImgsLoaded, 14117 allImgsLength,
14118 event.type == 'load' 14119 ]; 14120 allImgsLoaded++; 14121 14122 eachCallback.apply(img.element, eachArguments); 14123 deferred.notifyWith(img.element, eachArguments); 14124 14125 // Unbind the event listeners. I use this in addition to 14126 // `one` as one of those events won't be called (either 14127 // 'load' or 'error' will be called). 14128 $(this).off(events, me); 14129 14130 if (allImgsLoaded == allImgsLength) { 14131 finishedCallback.call(obj[0]); 14132 deferred.resolveWith(obj[0]); 14133 return false; 14134 } 14135 14136 }); 14137 14138 image.src = img.src; 14139 }); 14140 }); 14141 14142 return deferred.promise(); 14143 14144 }; 14145})); 14146 14147/** 14148 * @preserve textfill 14149 * @name jquery.textfill.js 14150 * @author Russ Painter 14151 * @author Yu-Jie Lin 14152 * @author Alexandre Dantas 14153 * @version 0.6.0 14154 * @date 2014-08-19 14155 * @copyright (c) 2014 Alexandre Dantas 14156 * @copyright (c) 2012-2013 Yu-Jie Lin 14157 * @copyright (c) 2009 Russ Painter 14158 * @license MIT License 14159 * @homepage https://github.com/jquery-textfill/jquery-textfill 14160 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 14161 */ 14162; (function($) { 14163 14164 /** 14165 * Resizes an inner element's font so that the 14166 * inner element completely fills the outer element. 14167 * 14168 * @param {Object} options User options that take 14169 * higher precedence when 14170 * merging with the default ones. 14171 * 14172 * @return All outer elements processed 14173 */ 14174 $.fn.textfill = function(options) { 14175 14176 // ______ _______ _______ _______ _ _ _______ _______ 14177 // | \ |______ |______ |_____| | | | | |______ 14178 // |_____/ |______ | | | |_____| |_____ | ______| 14179 // 14180 // Merging user options with the default values 14181 14182 var defaults = { 14183 debug : false, 14184 maxFontPixels : 40, 14185 minFontPixels : 4, 14186 innerTag : 'span', 14187 widthOnly : false, 14188 success : null, // callback when a resizing is done 14189 callback : null, // callback when a resizing is done (deprecated, use success) 14190 fail : null, // callback when a resizing is failed 14191 complete : null, // callback when all is done 14192 explicitWidth : null, 14193 explicitHeight : null, 14194 changeLineHeight : false 14195 }; 14196 14197 var Opts = $.extend(defaults, options); 14198 14199 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 14200 // |______ | | | \ | | | | | | | \ | |______ 14201 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 14202 // 14203 // Predefining the awesomeness 14204 14205 // Output arguments to the Debug console 14206 // if "Debug Mode" is enabled 14207 function _debug() { 14208 if (!Opts.debug 14209 || typeof console == 'undefined' 14210 || typeof console.debug == 'undefined') { 14211 return; 14212 } 14213 console.debug.apply(console, arguments); 14214 } 14215 14216 // Output arguments to the Warning console 14217 function _warn() { 14218 if (typeof console == 'undefined' || 14219 typeof console.warn == 'undefined') { 14220 return; 14221 } 14222 console.warn.apply(console, arguments); 14223 } 14224 14225 // Outputs all information on the current sizing 14226 // of the font. 14227 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14228 14229 function _m(v1, v2) { 14230 14231 var marker = ' / '; 14232 14233 if (v1 > v2) 14234 marker = ' > '; 14235 14236 else if (v1 == v2) 14237 marker = ' = '; 14238 14239 return marker; 14240 } 14241 14242 _debug( 14243 '[TextFill] ' + prefix + ' { ' + 14244 'font-size: ' + ourText.css('font-size') + ',' +
14245 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 14246 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 14247 'minFontPixels: ' + minFontPixels + 'px, ' + 14248 'maxFontPixels: ' + maxFontPixels + 'px }' 14249 ); 14250 } 14251 14252 /** 14253 * Calculates which size the font can get resized, 14254 * according to constrains. 14255 * 14256 * @param {String} prefix Gets shown on the console before 14257 * all the arguments, if debug mode is on. 14258 * @param {Object} ourText The DOM element to resize, 14259 * that contains the text. 14260 * @param {function} func Function called on `ourText` that's 14261 * used to compare with `max`. 14262 * @param {number} max Maximum value, that gets compared with 14263 * `func` called on `ourText`. 14264 * @param {number} minFontPixels Minimum value the font can 14265 * get resized to (in pixels). 14266 * @param {number} maxFontPixels Maximum value the font can 14267 * get resized to (in pixels). 14268 * 14269 * @return Size (in pixels) that the font can be resized. 14270 */ 14271 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14272 14273 _debug_sizing( 14274 prefix, ourText, 14275 maxHeight, maxWidth, 14276 minFontPixels, maxFontPixels 14277 ); 14278 14279 // The kernel of the whole plugin, take most attention 14280 // on this part. 14281 // 14282 // This is a loop that keeps increasing the `font-size` 14283 // until it fits the parent element. 14284 // 14285 // - Start from the minimal allowed value (`minFontPixels`) 14286 // - Guesses an average font size (in pixels) for the font, 14287 // - Resizes the text and sees if its size is within the 14288 // boundaries (`minFontPixels` and `maxFontPixels`). 14289 // - If so, keep guessing until we break. 14290 // - If not, return the last calculated size. 14291 // 14292 // I understand this is not optimized and we should 14293 // consider implementing something akin to 14294 // Daniel Hoffmann's answer here: 14295 // 14296 // http://stackoverflow.com/a/17433451/1094964 14297 // 14298 14299 while (minFontPixels < (maxFontPixels - 1)) { 14300 14301 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 14302 ourText.css('font-size', fontSize); 14303 14304 if (func.call(ourText) <= max) { 14305 minFontPixels = fontSize; 14306 14307 if (func.call(ourText) == max) 14308 break; 14309 } 14310 else 14311 maxFontPixels = fontSize; 14312 14313 _debug_sizing( 14314 prefix, ourText, 14315 maxHeight, maxWidth, 14316 minFontPixels, maxFontPixels 14317 ); 14318 } 14319 14320 ourText.css('font-size', maxFontPixels); 14321 14322 if (func.call(ourText) <= max) { 14323 minFontPixels = maxFontPixels; 14324 14325 _debug_sizing( 14326 prefix + '* ', ourText, 14327 maxHeight, maxWidth, 14328 minFontPixels, maxFontPixels 14329 ); 14330 } 14331 return minFontPixels; 14332 } 14333 14334 // _______ _______ _______ ______ _______ 14335 // |______ | |_____| |_____/ | 14336 // ______| | | | | \_ | 14337 // 14338 // Let's get it started (yeah)! 14339 14340 _debug('[TextFill] Start Debug'); 14341 14342 this.each(function() { 14343 14344 // Contains the child element we will resize. 14345 // $(this) means the parent container 14346 var ourText = $(Opts.innerTag + ':visible:first', this); 14347 14348 // Will resize to this dimensions. 14349 // Use explicit dimensions when specified 14350 var maxHeight = Opts.explicitHeight || $(this).height(); 14351 var maxWidth = Opts.explicitWidth || $(this).width(); 14352 14353 var oldFontSize = ourText.css('font-size'); 14354 14355 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 14356 14357 _debug('[TextFill] Inner text: ' + ourText.text()); 14358 _debug('[TextFill] All options: ', Opts); 14359 _debug('[TextFill] Maximum sizes: { ' + 14360 'Height: ' + maxHeight + 'px, ' + 14361 'Width: ' + maxWidth + 'px' + ' }' 14362 ); 14363 14364 var minFontPixels = Opts.minFontPixels; 14365 14366 // Remember, if this `maxFontPixels` is negative, 14367 // the text will resize to as long as the container 14368 // can accomodate 14369 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 14370 maxHeight : 14371 Opts.maxFontPixels); 14372 14373 14374 // Let's start it all! 14375 14376 // 1. Calculate which `font-size` would 14377 // be best for the Height 14378 var fontSizeHeight = undefined; 14379 14380 if (! Opts.widthOnly) 14381 fontSizeHeight = _sizing( 14382 'Height', ourText, 14383 $.fn.height, maxHeight, 14384 maxHeight, maxWidth, 14385 minFontPixels, maxFontPixels 14386 ); 14387 14388 // 2. Calculate which `font-size` would 14389 // be best for the Width 14390 var fontSizeWidth = undefined; 14391 14392 fontSizeWidth = _sizing( 14393 'Width', ourText, 14394 $.fn.width, maxWidth, 14395 maxHeight, maxWidth, 14396 minFontPixels, maxFontPixels 14397 ); 14398 14399 // 3. Actually resize the text! 14400 14401 if (Opts.widthOnly) { 14402 ourText.css({ 14403 'font-size' : fontSizeWidth, 14404 'white-space': 'nowrap' 14405 }); 14406 14407 if (Opts.changeLineHeight) 14408 ourText.parent().css( 14409 'line-height', 14410 (lineHeight * fontSizeWidth + 'px') 14411 ); 14412 } 14413 else { 14414 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 14415 14416 ourText.css('font-size', fontSizeFinal); 14417 14418 if (Opts.changeLineHeight) 14419 ourText.parent().css( 14420 'line-height', 14421 (lineHeight * fontSizeFinal) + 'px' 14422 ); 14423 } 14424 14425 _debug( 14426 '[TextFill] Finished { ' + 14427 'Old font-size: ' + oldFontSize + ', ' + 14428 'New font-size: ' + ourText.css('font-size') + ' }' 14429 ); 14430 14431 // Oops, something wrong happened! 14432 // We weren't supposed to exceed the original size 14433 if ((ourText.width() > maxWidth) ||
14434 (ourText.height() > maxHeight && !Opts.widthOnly)) { 14435 14436 ourText.css('font-size', oldFontSize); 14437 14438 // Failure callback 14439 if (Opts.fail) 14440 Opts.fail(this); 14441 14442 _debug( 14443 '[TextFill] Failure { ' + 14444 'Current Width: ' + ourText.width() + ', ' + 14445 'Maximum Width: ' + maxWidth + ', ' + 14446 'Current Height: ' + ourText.height() + ', ' + 14447 'Maximum Height: ' + maxHeight + ' }' 14448 ); 14449 } 14450 else if (Opts.success) { 14451 Opts.success(this); 14452 } 14453 else if (Opts.callback) { 14454 _warn('callback is deprecated, use success, instead'); 14455 14456 // Success callback 14457 Opts.callback(this); 14458 } 14459 }); 14460 14461 // Complete callback 14462 if (Opts.complete) 14463 Opts.complete(this); 14464 14465 _debug('[TextFill] End Debug'); 14466 return this; 14467 }; 14468 14469})(window.jQuery); 14470 14471 14472!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; 14473function getStyles(config){ 14474 // 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;
14474left: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+"}" 14475}; 14476 var ShareUtils; 14477 14478if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 14479 Object.defineProperty(HTMLElement.prototype, "classList", { 14480 get: function() { 14481 var ret, self, update; 14482 update = function(fn) { 14483 return function(value) { 14484 var classes, index; 14485 classes = self.className.split(/\s+/); 14486 index = classes.indexOf(value); 14487 fn(classes, index, value); 14488 self.className = classes.join(" "); 14489 }; 14490 }; 14491 self = this; 14492 ret = { 14493 add: update(function(classes, index, value) { 14494 ~index || classes.push(value); 14495 }), 14496 remove: update(function(classes, index) { 14497 ~index && classes.splice(index, 1); 14498 }), 14499 toggle: update(function(classes, index, value) { 14500 if (~index) { 14501 classes.splice(index, 1); 14502 } else { 14503 classes.push(value); 14504 } 14505 }), 14506 contains: function(value) { 14507 return !!~self.className.split(/\s+/).indexOf(value); 14508 }, 14509 item: function(i) { 14510 return self.className.split(/\s+/)[i] || null; 14511 } 14512 }; 14513 Object.defineProperty(ret, "length", { 14514 get: function() { 14515 return self.className.split(/\s+/).length; 14516 } 14517 }); 14518 return ret; 14519 } 14520 }); 14521} 14522 14523String.prototype.to_rfc3986 = function() { 14524 var tmp; 14525 tmp = encodeURIComponent(this); 14526 return tmp.replace(/[!'()*]/g, function(c) { 14527 return "%" + c.charCodeAt(0).toString(16); 14528 }); 14529}; 14530 14531ShareUtils = (function() { 14532 function ShareUtils() {} 14533 14534 ShareUtils.prototype.extend = function(to, from, overwrite) { 14535 var hasProp, prop; 14536 for (prop in from) { 14537 hasProp = to[prop] !== undefined; 14538 if (hasProp && typeof from[prop] === "object") { 14539 this.extend(to[prop], from[prop], overwrite); 14540 } else { 14541 if (overwrite || !hasProp) { 14542 to[prop] = from[prop]; 14543 } 14544 } 14545 } 14546 }; 14547 14548 ShareUtils.prototype.hide = function(el) { 14549 return el.style.display = "none"; 14550 }; 14551 14552 ShareUtils.prototype.show = function(el) { 14553 return el.style.display = "block"; 14554 }; 14555 14556 ShareUtils.prototype.has_class = function(el, class_name) { 14557 return el.classList.contains(class_name); 14558 }; 14559 14560 ShareUtils.prototype.add_class = function(el, class_name) { 14561 return el.classList.add(class_name); 14562 }; 14563 14564 ShareUtils.prototype.remove_class = function(el, class_name) { 14565 return el.classList.remove(class_name); 14566 }; 14567 14568 ShareUtils.prototype.is_encoded = function(str) { 14569 str = str.to_rfc3986(); 14570 return decodeURIComponent(str) !== str; 14571 }; 14572 14573 ShareUtils.prototype.encode = function(str) { 14574 if (typeof str === "undefined" || this.is_encoded(str)) { 14575 return str; 14576 } else { 14577 return str.to_rfc3986(); 14578 } 14579 }; 14580 14581 ShareUtils.prototype.popup = function(url, params) { 14582 var k, popup, qs, v; 14583 if (params == null) { 14584 params = {}; 14585 } 14586 popup = { 14587 width: 500, 14588 height: 350 14589 }; 14590 popup.top = (screen.height / 2) - (popup.height / 2); 14591 popup.left = (screen.width / 2) - (popup.width / 2); 14592 qs = ((function() { 14593 var _results; 14594 _results = []; 14595 for (k in params) { 14596 v = params[k]; 14597 _results.push("" + k + "=" + (this.encode(v))); 14598 } 14599 return _results; 14600 }).call(this)).join('&'); 14601 if (qs) { 14602 qs = "?" + qs; 14603 } 14604 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="
14604+ popup.width + ",height=" + popup.height); 14605 }; 14606 14607 return ShareUtils; 14608 14609})(); 14610var Share, 14611 __hasProp = {}.hasOwnProperty, 14612 __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; }; 14613 14614Share = (function(_super) { 14615 __extends(Share, _super); 14616 14617 function Share(element, options) { 14618 this.element = element; 14619 this.el = { 14620 head: document.getElementsByTagName('head')[0], 14621 body: document.getElementsByTagName('body')[0] 14622 }; 14623 this.config = { 14624 enabled_networks: 0, 14625 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 14626 url: window.location.href.replace("&", "%26"), 14627 caption: null, 14628 title: this.default_title(), 14629 image: this.default_image(), 14630 description: this.default_description(), 14631 ui: { 14632 flyout: 'top center', 14633 button_text: 'Share', 14634 button_font: true, 14635 icon_font: true 14636 }, 14637 networks: { 14638 google_plus: { 14639 enabled: true, 14640 url: null 14641 }, 14642 twitter: { 14643 enabled: true, 14644 url: null, 14645 title: null, 14646 description: null 14647 }, 14648 facebook: { 14649 enabled: true, 14650 load_sdk: true, 14651 url: null, 14652 app_id: null, 14653 title: null, 14654 caption: null, 14655 description: null, 14656 image: null 14657 }, 14658 pinterest: { 14659 enabled: true, 14660 url: null, 14661 image: null, 14662 description: null 14663 }, 14664 reddit: { 14665 enabled: true, 14666 url: null, 14667 title: null 14668 }, 14669 linkedin: { 14670 enabled: true, 14671 url: null, 14672 title: null, 14673 description: null 14674 }, 14675 xing: { 14676 enabled: true, 14677 url: null, 14678 title: null, 14679 image: null, 14680 description: null 14681 }, 14682 whatsapp: { 14683 enabled: true, 14684 description: null, 14685 url: null 14686 }, 14687 email: { 14688 enabled: true, 14689 title: null, 14690 description: null, 14691 url: null 14692 } 14693 } 14694 }; 14695 this.setup(element, options); 14696 return this; 14697 } 14698 14699 Share.prototype.setup = function(element, opts) { 14700 var index, instance, instances, _i, _len; 14701 instances = document.querySelectorAll(element); 14702 this.extend(this.config, opts, true); 14703 this.set_global_configuration(); 14704 this.normalize_network_configuration(); 14705 if (this.config.ui.icon_font) { 14706 this.inject_icons(); 14707 } 14708 if (this.config.ui.button_font) { 14709 this.inject_fonts(); 14710 } 14711 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 14712 this.inject_facebook_sdk(); 14713 } 14714 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 14715 instance = instances[index]; 14716 this.setup_instance(element, index); 14717 } 14718 }; 14719 14720 Share.prototype.setup_instance = function(element, index) { 14721 var button, instance, label, network, networks, _i, _len, _results, 14722 _this = this; 14723 instance = document.querySelectorAll(element)[index]; 14724 this.hide(instance); 14725 this.add_class(instance, "sharer-" + index); 14726 instance = document.querySelectorAll(element)[index]; 14727 this.inject_css(instance); 14728 this.inject_html(instance); 14729 this.show(instance); 14730 label = instance.getElementsByTagName("label")[0]; 14731 button = instance.getElementsByClassName("social")[0]; 14732 networks = instance.getElementsByTagName('li'); 14733 this.add_class(button, "networks-" + this.config.enabled_networks); 14734 label.addEventListener("click", function() { 14735 return _this.event_toggle(button); 14736 }); 14737 _this = this; 14738 _results = []; 14739 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 14740 network = networks[index]; 14741 _results.push(network.addEventListener("click", function() { 14742 _this.event_network(instance, this); 14743 return _this.event_close(button); 14744 })); 14745 } 14746 return _results; 14747 }; 14748 14749 Share.prototype.event_toggle = function(button) { 14750 if (this.has_class(button, "active")) { 14751 return this.event_close(button); 14752 } else { 14753 return this.event_open(button); 14754 } 14755 }; 14756 14757 Share.prototype.event_open = function(button) { 14758 if (this.has_class(button, "load")) { 14759 this.remove_class(button, "load"); 14760 } 14761 return this.add_class(button, "active"); 14762 }; 14763 14764 Share.prototype.event_close = function(button) { 14765 return this.remove_class(button, "active"); 14766 }; 14767 14768 Share.prototype.event_network = function(instance, network) { 14769 var name; 14770 name = network.getAttribute("data-network"); 14771 this.hook("before", name, instance);
14772 this["network_" + name](); 14773 return this.hook("after", name, instance); 14774 }; 14775 14776 Share.prototype.open = function() { 14777 return this["public"]("open"); 14778 }; 14779 14780 Share.prototype.close = function() { 14781 return this["public"]("close"); 14782 }; 14783 14784 Share.prototype.toggle = function() { 14785 return this["public"]("toggle"); 14786 }; 14787 14788 Share.prototype["public"] = function(action) { 14789 var button, index, instance, _i, _len, _ref, _results; 14790 _ref = document.querySelectorAll(this.element); 14791 _results = []; 14792 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 14793 instance = _ref[index]; 14794 button = instance.getElementsByClassName("social")[0]; 14795 _results.push(this["event_" + action](button)); 14796 } 14797 return _results; 14798 }; 14799 14800 Share.prototype.network_facebook = function() { 14801 if (this.config.networks.facebook.load_sdk) { 14802 if (!window.FB) { 14803 return console.error("The Facebook JS SDK hasn't loaded yet."); 14804 } 14805 return FB.ui({ 14806 method: 'feed', 14807 name: this.config.networks.facebook.title, 14808 link: this.config.networks.facebook.url, 14809 picture: this.config.networks.facebook.image, 14810 caption: this.config.networks.facebook.caption, 14811 description: this.config.networks.facebook.description 14812 }); 14813 } else { 14814 return this.popup('https://www.facebook.com/sharer/sharer.php', { 14815 u: this.config.networks.facebook.url 14816 }); 14817 } 14818 }; 14819 14820 Share.prototype.network_twitter = function() { 14821 return this.popup('https://twitter.com/intent/tweet', { 14822 text: this.config.networks.twitter.title, 14823 url: this.config.networks.twitter.url 14824 }); 14825 }; 14826 14827 Share.prototype.network_google_plus = function() { 14828 return this.popup('https://plus.google.com/share', { 14829 url: this.config.networks.google_plus.url 14830 }); 14831 }; 14832 14833 Share.prototype.network_pinterest = function() { 14834 return this.popup('https://www.pinterest.com/pin/create/button', { 14835 url: this.config.networks.pinterest.url, 14836 media: this.config.networks.pinterest.image, 14837 description: this.config.networks.pinterest.description 14838 }); 14839 }; 14840 14841 Share.prototype.network_linkedin = function() { 14842 return this.popup('https://www.linkedin.com/shareArticle', { 14843 url: this.config.networks.linkedin.url, 14844 title: this.config.networks.linkedin.title, 14845 summary: this.config.networks.linkedin.description 14846 }); 14847 } 14848 14849 Share.prototype.network_xing = function() { 14850 return this.popup('https://www.xing.com/spi/shares/new', { 14851 url: this.config.networks.xing.url, 14852 image: this.config.networks.xing.image, 14853 title: this.config.networks.xing.title, 14854 summary: this.config.networks.xing.description 14855 }); 14856 } 14857 14858 Share.prototype.network_email = function() { 14859 return this.popup('mailto:', { 14860 subject: this.config.networks.email.title, 14861 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 14862 }); 14863 }; 14864 14865 Share.prototype.inject_icons = function() { 14866 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 14867 }; 14868 14869 Share.prototype.inject_fonts = function() { 14870 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 14871 }; 14872 14873 Share.prototype.inject_stylesheet = function(url) { 14874 var link; 14875 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 14876 link = document.createElement("link"); 14877 link.setAttribute("rel", "stylesheet"); 14878 link.setAttribute("href", url); 14879 return this.el.head.appendChild(link); 14880 } 14881 }; 14882 14883 Share.prototype.inject_css = function(instance) { 14884 var css, meta, selector, style; 14885 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 14886 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 14887 this.config.selector = selector; 14888 css = getStyles(this.config); 14889 style = document.createElement("style"); 14890 style.type = "text/css"; 14891 if (style.styleSheet) { 14892 style.styleSheet.cssText = css; 14893 } else { 14894 style.appendChild(document.createTextNode(css)); 14895 } 14896 this.el.head.appendChild(style); 14897 delete this.config.selector; 14898 meta = document.createElement("meta"); 14899 meta.setAttribute("name", "sharer" + selector); 14900 return this.el.head.appendChild(meta); 14901 } 14902 }; 14903 14904 Share.prototype.inject_html = function(instance) { 14905 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>"; 14906 }; 14907 14908 Share.prototype.inject_facebook_sdk = function() { 14909 var fb_root, script; 14910 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 14911 script = document.createElement("script"); 14912 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')"; 14913 fb_root = document.createElement("div"); 14914 fb_root.id = "fb-root"; 14915 this.el.body.appendChild(fb_root); 14916 return this.el.body.appendChild(script); 14917 } 14918 }; 14919 14920 Share.prototype.hook = function(type, network, instance) { 14921 var fn, opts; 14922 fn = this.config.networks[network][type]; 14923 if (typeof fn === "function") { 14924 opts = fn.call(this.config.networks[network], instance); 14925 if (opts !== void 0) { 14926 opts = this.normalize_filter_config_updates(opts); 14927 this.extend(this.config.networks[network], opts, true); 14928 this.normalize_network_configuration(); 14929 } 14930 } 14931 }; 14932 14933 Share.prototype.default_title = function() { 14934 var content; 14935 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 14936 return encodeURIComponent(content.getAttribute('content')); 14937 } else if (content = document.querySelector('title')) { 14938 return encodeURIComponent(content.innerText); 14939 } 14940 }; 14941 14942 Share.prototype.default_image = function() { 14943 var content; 14944 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 14945 return content.getAttribute('content'); 14946 } 14947 }; 14948 14949 Share.prototype.default_description = function() { 14950 var content; 14951 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 14952 return encodeURIComponent(content.getAttribute('content')); 14953 } else { 14954 return ''; 14955 } 14956 }; 14957 14958 Share.prototype.set_global_configuration = function() { 14959 var display, network, option, options, _ref, _results; 14960 _ref = this.config.networks; 14961 _results = []; 14962 for (network in _ref) { 14963 options = _ref[network]; 14964 for (option in options) { 14965 if (this.config.networks[network][option] == null) { 14966 this.config.networks[network][option] = this.config[option]; 14967 } 14968 } 14969 if (this.config.networks[network].enabled) { 14970 display = 'block'; 14971 this.config.enabled_networks += 1; 14972 } else { 14973 display = 'none'; 14974 } 14975 _results.push(this.config.networks[network].display = display); 14976 } 14977 return _results; 14978 }; 14979 14980 Share.prototype.normalize_network_configuration = function() { 14981 if (!this.config.networks.facebook.app_id) { 14982 this.config.networks.facebook.load_sdk = false;
14983 } 14984 if (!this.is_encoded(this.config.networks.twitter.description)) { 14985 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 14986 } 14987 if (typeof this.config.networks.facebook.app_id === 'number') { 14988 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 14989 } 14990 }; 14991 14992 Share.prototype.normalize_filter_config_updates = function(opts) { 14993 if (this.config.networks.facebook.app_id !== opts.app_id) { 14994 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."); 14995 delete opts.app_id; 14996 } 14997 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 14998 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."); 14999 delete opts.app_id; 15000 } 15001 return opts; 15002 }; 15003 15004 return Share; 15005 15006})(ShareUtils); 15007 return Share; 15008}); 15009 15010 15011// Generated by CoffeeScript 1.9.2 15012 15013// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 15014 15015(function() { 15016 var $, win; 15017 15018 $ = this.jQuery || window.jQuery; 15019 15020 win = $(window); 15021 15022 $.fn.stick_in_parent = function(opts) { 15023 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 15024 if (opts == null) { 15025 opts = {}; 15026 } 15027 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; 15028 if (offset_top == null) { 15029 offset_top = 0; 15030 } 15031 if (parent_selector == null) { 15032 parent_selector = void 0; 15033 } 15034 if (inner_scrolling == null) { 15035 inner_scrolling = true; 15036 } 15037 if (sticky_class == null) { 15038 sticky_class = "is_stuck"; 15039 } 15040 doc = $(document); 15041 if (enable_bottoming == null) { 15042 enable_bottoming = true; 15043 } 15044 outer_width = function(el) { 15045 var _el, computed, w; 15046 if (window.getComputedStyle) { 15047 _el = el[0]; 15048 computed = window.getComputedStyle(el[0]); 15049 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 15050 if (computed.getPropertyValue("box-sizing") !== "border-box") { 15051 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 15052 } 15053 return w; 15054 } else { 15055 return el.outerWidth(true); 15056 } 15057 }; 15058 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 15059 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 15060 if (elm.data("sticky_kit")) { 15061 return; 15062 } 15063 elm.data("sticky_kit", true); 15064 last_scroll_height = doc.height(); 15065 parent = elm.parent(); 15066 if (parent_selector != null) { 15067 parent = parent.closest(parent_selector); 15068 } 15069 if (!parent.length) { 15070 throw "failed to find stick parent"; 15071 } 15072 fixed = false; 15073 bottomed = false; 15074 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 15075 if (spacer) { 15076 spacer.css('position', elm.css('position')); 15077 } 15078 recalc = function() { 15079 var border_top, padding_top, restore; 15080 if (detached) { 15081 return; 15082 } 15083 last_scroll_height = doc.height(); 15084 border_top = parseInt(parent.css("border-top-width"), 10); 15085 padding_top = parseInt(parent.css("padding-top"), 10); 15086 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 15087 parent_top = parent.offset().top + border_top + padding_top; 15088 parent_height = parent.height(); 15089 if (fixed) { 15090 fixed = false;
vendor: 6,069 bytes, lines 15091-15286
15091 bottomed = false; 15092 if (manual_spacer == null) { 15093 elm.insertAfter(spacer); 15094 spacer.detach(); 15095 } 15096 elm.css({ 15097 position: "", 15098 top: "", 15099 width: "", 15100 bottom: "" 15101 }).removeClass(sticky_class); 15102 restore = true; 15103 } 15104 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 15105 height = elm.outerHeight(true); 15106 el_float = elm.css("float"); 15107 if (spacer) { 15108 spacer.css({ 15109 width: outer_width(elm), 15110 height: height, 15111 display: elm.css("display"), 15112 "vertical-align": elm.css("vertical-align"), 15113 "float": el_float 15114 }); 15115 } 15116 if (restore) { 15117 return tick(); 15118 } 15119 }; 15120 recalc(); 15121 if (height === parent_height) { 15122 return; 15123 } 15124 last_pos = void 0; 15125 offset = offset_top; 15126 recalc_counter = recalc_every; 15127 tick = function() { 15128 var css, delta, recalced, scroll, will_bottom, win_height; 15129 if (detached) { 15130 return; 15131 } 15132 recalced = false; 15133 if (recalc_counter != null) { 15134 recalc_counter -= 1; 15135 if (recalc_counter <= 0) { 15136 recalc_counter = recalc_every; 15137 recalc(); 15138 recalced = true; 15139 } 15140 } 15141 if (!recalced && doc.height() !== last_scroll_height) { 15142 recalc(); 15143 recalced = true; 15144 } 15145 scroll = win.scrollTop(); 15146 if (last_pos != null) { 15147 delta = scroll - last_pos; 15148 } 15149 last_pos = scroll; 15150 if (fixed) { 15151 if (enable_bottoming) { 15152 will_bottom = scroll + height + offset > parent_height + parent_top; 15153 if (bottomed && !will_bottom) { 15154 bottomed = false; 15155 elm.css({ 15156 position: "fixed", 15157 bottom: "", 15158 top: offset 15159 }).trigger("sticky_kit:unbottom"); 15160 } 15161 } 15162 if (scroll < top) { 15163 fixed = false; 15164 offset = offset_top; 15165 if (manual_spacer == null) { 15166 if (el_float === "left" || el_float === "right") { 15167 elm.insertAfter(spacer); 15168 } 15169 spacer.detach(); 15170 } 15171 css = { 15172 position: "", 15173 width: "", 15174 top: "" 15175 }; 15176 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 15177 } 15178 if (inner_scrolling) { 15179 win_height = win.height(); 15180 if (height + offset_top > win_height) { 15181 if (!bottomed) { 15182 offset -= delta; 15183 offset = Math.max(win_height - height, offset); 15184 offset = Math.min(offset_top, offset); 15185 if (fixed) { 15186 elm.css({ 15187 top: offset + "px" 15188 }); 15189 } 15190 } 15191 } 15192 } 15193 } else { 15194 if (scroll > top) { 15195 fixed = true; 15196 css = { 15197 position: "fixed", 15198 top: offset 15199 }; 15200 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 15201 elm.css(css).addClass(sticky_class); 15202 if (manual_spacer == null) { 15203 elm.after(spacer); 15204 if (el_float === "left" || el_float === "right") { 15205 spacer.append(elm); 15206 } 15207 } 15208 elm.trigger("sticky_kit:stick"); 15209 } 15210 } 15211 if (fixed && enable_bottoming) { 15212 if (will_bottom == null) { 15213 will_bottom = scroll + height + offset > parent_height + parent_top; 15214 } 15215 if (!bottomed && will_bottom) { 15216 bottomed = true; 15217 if (parent.css("position") === "static") { 15218 parent.css({ 15219 position: "relative" 15220 }); 15221 } 15222 return elm.css({ 15223 position: "absolute", 15224 bottom: padding_bottom, 15225 top: "auto" 15226 }).trigger("sticky_kit:bottom"); 15227 } 15228 } 15229 }; 15230 recalc_and_tick = function() { 15231 recalc(); 15232 return tick(); 15233 }; 15234 detach = function() { 15235 detached = true; 15236 win.off("touchmove", tick); 15237 win.off("scroll", tick); 15238 win.off("resize", recalc_and_tick); 15239 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 15240 elm.off("sticky_kit:detach", detach); 15241 elm.removeData("sticky_kit"); 15242 elm.css({ 15243 position: "", 15244 bottom: "", 15245 top: "", 15246 width: "" 15247 }); 15248 parent.position("position", ""); 15249 if (fixed) { 15250 if (manual_spacer == null) { 15251 if (el_float === "left" || el_float === "right") { 15252 elm.insertAfter(spacer); 15253 } 15254 spacer.remove(); 15255 } 15256 return elm.removeClass(sticky_class); 15257 } 15258 }; 15259 win.on("touchmove", tick); 15260 win.on("scroll", tick); 15261 win.on("resize", recalc_and_tick); 15262 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 15263 elm.on("sticky_kit:detach", detach); 15264 return setTimeout(tick, 0); 15265 }; 15266 for (i = 0, len = this.length; i < len; i++) { 15267 elm = this[i]; 15268 fn($(elm)); 15269 } 15270 return this; 15271 }; 15272 15273}).call(this); 15274 15275/* ========================================================================== 15276 * bootstrap-tab-history.js 15277 * Author: Michael Narayan <[email protected]> 15278 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 15279 * ========================================================================== 15280 * Licensed under the Apache License, Version 2.0 (the "License"); you may 15281 * not use this file except in compliance with the License. You may obtain a 15282 * copy of the License at 15283 * 15284 * http://www.apache.org/licenses/LICENSE-2.0 15285 * 15286 * Unless required by applicable law or agreed to in writing, softw
15286are 15287 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15288 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15289 * License for the specific language governing permissions and limitations 15290 * under the License. 15291 * ========================================================================== */ 15292 15293/* ========================================================================== */ 15294/* JSHint directives */ 15295/* */ 15296/* global BootstrapTabHistory: true */ 15297/* */ 15298/* global document */ 15299/* global jQuery */ 15300/* global history */ 15301/* global window */ 15302/* ========================================================================== */ 15303 15304/** 15305 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 15306 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 15307 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 15308 * 15309 * See the README for additional information. 15310 * 15311 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 15312 */ 15313 15314BootstrapTabHistory = { 15315 options: { 15316 /** 15317 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 15318 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 15319 * 15320 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 15321 * 15322 * @public 15323 * @type {?number} 15324 */ 15325 defaultAnchorYOffset: 0, 15326 /** 15327 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 15328 * 15329 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 15330 * 15331 * @public 15332 * @type {string} 15333 */ 15334 defaultChanger: 'replace', 15335 /** 15336 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 15337 * `null` is passed as the third parameter to these calls. 15338 * 15339 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 15340 * 15341 * @public 15342 * @type {boolean} 15343 */ 15344 defaultUpdateURL: false, 15345 /** 15346 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 15347 * load. 15348 * 15349 * @public 15350 * @type {boolean} 15351 */ 15352 showTabsBasedOnAnchor: true 15353 } 15354}; 15355 15356(function () { 15357 'use strict'; 15358 15359 jQuery(function () { 15360 if(history && history.pushState && history.replaceState) { 15361 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15362 15363 if(bootstrapTabHistory) { 15364 showTabsBasedOnState(bootstrapTabHistory); 15365 } else { 15366 showTabsBasedOnAnchor(); 15367 } 15368 15369 backfillHistoryState(); 15370 15371 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 15372 jQuery(window).on('popstate', onPopState); 15373 } else { 15374 showTabsBasedOnAnchor(); 15375 } 15376 }); 15377 15378 /** 15379 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 15380 * 15381 * @type {boolean} 15382 */ 15383 var showingTabsBasedOnState = false; 15384 15385 /** 15386 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 15387 * `history.back` handling when `data-tab-history-update-url` is true. 15388 */ 15389 function backfillHistoryState() { 15390 var newState = null; 15391 15392 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 15393 var $activeTabElement = jQuery(this); 15394 var selector = getTabSelector($activeTabElement); 15395 15396 if(selector) { 15397 var tabGroup = getTabGroup($activeTabElement); 15398 15399 if(tabGroup) { 15400 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 15401 } 15402 } 15403 }); 15404 15405 if(newState) { 15406 history.replaceState(newState, '', null); 15407 } 15408 } 15409 15410 /** 15411 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 15412 * said bootstrapTabHistory attribute. 15413 * 15414 * @param {?object} existingState 15415 * @param {!string} tabGroup 15416 * @param {!string} selector 15417 * @returns {!object} 15418 */ 15419 function createNewHistoryState(existingState, tabGroup, selector) { 15420 // Clone history.state and ensure it has a bootstrapTabHistory entry. 15421 var newState = jQuery.extend(true, {}, existingState, { 15422 bootstrapTabHistory: {} 15423 }); 15424 15425 newState.bootstrapTabHistory[tabGroup] = selector; 15426 15427 return newState; 15428 } 15429 15430 /** 15431 * @param {jQuery} $tab
15432 * @returns {?string} 15433 */ 15434 function getTabGroup($tab) { 15435 return parseTruthyAttributeValue($tab.data('tab-history')); 15436 } 15437 15438 /** 15439 * @param {jQuery} $tab 15440 * @returns {?string} 15441 */ 15442 function getTabSelector($tab) { 15443 return $tab.data('target') || $tab.attr('href'); 15444 } 15445 15446 /** 15447 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 15448 * 15449 * @param {jQuery.Event} shownEvt 15450 */ 15451 function onShownTab(shownEvt) { 15452 if(!showingTabsBasedOnState) { 15453 var $activatedTab = jQuery(shownEvt.target); 15454 if ( $activatedTab.hasClass('panel-collapse') ) 15455 $activatedTab = $activatedTab.closest('.panel').find('a'); 15456 var selector = getTabSelector($activatedTab); 15457 15458 if(selector) { 15459 var tabGroup = getTabGroup($activatedTab); 15460 15461 if(tabGroup) { 15462 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 15463 var newState = createNewHistoryState(history.state, tabGroup, selector); 15464 var updateURL = (function ($activatedTab) { 15465 if(selector[0] === '#') { 15466 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 15467 15468 if(elementUpdateURLOption === undefined) { 15469 return BootstrapTabHistory.options.defaultUpdateURL; 15470 } else { 15471 return elementUpdateURLOption; 15472 } 15473 } else { 15474 return false; 15475 } 15476 })($activatedTab); 15477 15478 switch(historyChanger) { 15479 case 'push': 15480 history.pushState(newState, '', updateURL ? selector : null); 15481 break; 15482 case 'replace': 15483 history.replaceState(newState, '', updateURL ? selector : null); 15484 break; 15485 default: 15486 throw new Error('Unknown tab-history-changer: ' + historyChanger); 15487 } 15488 } 15489 } 15490 } 15491 } 15492 15493 /** 15494 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 15495 */ 15496 function onPopState() { 15497 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15498 15499 if(bootstrapTabHistory) { 15500 showTabsBasedOnState(bootstrapTabHistory); 15501 } 15502 } 15503 15504 /** 15505 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 15506 * 15507 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 15508 * 15509 * @param {*} value 15510 * @returns {*} 15511 */ 15512 function parseTruthyAttributeValue(value) { 15513 if(value) { 15514 return value; 15515 } else if(value === '') { 15516 return true; 15517 } else { 15518 return value; 15519 } 15520 } 15521 15522 /** 15523 * Show tabs based upon the anchor component of `window.location`. 15524 */ 15525 function showTabsBasedOnAnchor() { 15526 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 15527 var anchor = window.location && window.location.hash; 15528 15529 if(anchor) { 15530 var $tabElement = showTabForSelector(anchor); 15531 15532 if($tabElement && window.addEventListener && window.removeEventListener) { 15533 var anchorYOffset = (function ($tabElement) { 15534 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 15535 15536 if(elementSetting === undefined) { 15537 return BootstrapTabHistory.options.defaultAnchorYOffset; 15538 } else { 15539 return elementSetting; 15540 } 15541 })($tabElement); 15542 15543 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 15544 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 15545 // `history.state` object should have been used (unless the browser did not support the modern History API). 15546 if(anchorYOffset || anchorYOffset === 0) { 15547 var scrollListener = function resetAnchorScroll () { 15548 window.removeEventListener('scroll', scrollListener); 15549 window.scrollTo(0, anchorYOffset); 15550 }; 15551 15552 window.addEventListener('scroll', scrollListener); 15553 } 15554 } 15555 } 15556 } 15557 } 15558 15559 /** 15560 * Show a tab which corresponds to the provided selector. 15561 * 15562 * @param {string} selector - A CSS selector. 15563 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 15564 */ 15565 function showTabForSelector(selector) { 15566 var $tabElement = (function (selector) { 15567 var $ret = null; 15568 15569 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 15570 var $potentialTab = jQuery(this); 15571 15572 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 15573 $ret = $potentialTab; 15574 return false;
vendor: 4,523 bytes, lines 15575-15725
15575 } else { 15576 return null; 15577 } 15578 }); 15579 15580 return $ret; 15581 })(selector); 15582 15583 if($tabElement) { 15584 $tabElement.trigger('click'); 15585 //$tabElement.tab('show'); 15586 } 15587 15588 return $tabElement; 15589 } 15590 15591 /** 15592 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 15593 * 15594 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 15595 */ 15596 function showTabsBasedOnState(bootstrapTabHistory) { 15597 showingTabsBasedOnState = true; 15598 15599 try { 15600 for(var k in bootstrapTabHistory) { 15601 if(bootstrapTabHistory.hasOwnProperty(k)) { 15602 showTabForSelector(bootstrapTabHistory[k]); 15603 } 15604 } 15605 } finally { 15606 showingTabsBasedOnState = false; 15607 } 15608 } 15609})(); 15610 15611 15612/*! 15613 * Justified Gallery - v3.6.3 15614 * http://miromannino.github.io/Justified-Gallery/ 15615 * Copyright (c) 2016 Miro Mannino 15616 * Licensed under the MIT license. 15617 */ 15618(function($) { 15619 15620 function hasScrollBar() { 15621 return $("body").height() > $(window).height(); 15622 } 15623 /** 15624 * Justified Gallery controller constructor 15625 * 15626 * @param $gallery the gallery to build 15627 * @param settings the settings (the defaults are in $.fn.justifiedGallery.defaults) 15628 * @constructor 15629 */ 15630 var JustifiedGallery = function ($gallery, settings) { 15631 15632 this.settings = settings; 15633 this.checkSettings(); 15634 15635 this.imgAnalyzerTimeout = null; 15636 this.entries = null; 15637 this.buildingRow = { 15638 entriesBuff : [], 15639 width : 0, 15640 height : 0, 15641 aspectRatio : 0 15642 }; 15643 this.lastFetchedEntry = null; 15644 this.lastAnalyzedIndex = -1; 15645 this.yield = { 15646 every : 2, // do a flush every n flushes (must be greater than 1) 15647 flushed : 0 // flushed rows without a yield 15648 }; 15649 this.border = settings.border >= 0 ? settings.border : settings.margins; 15650 this.maxRowHeight = this.retrieveMaxRowHeight(); 15651 this.suffixRanges = this.retrieveSuffixRanges(); 15652 this.offY = this.border; 15653 this.rows = 0; 15654 this.spinner = { 15655 phase : 0, 15656 timeSlot : 150, 15657 $el : $('<div class="spinner"><span></span><span></span><span></span></div>'), 15658 intervalId : null 15659 }; 15660 this.checkWidthIntervalId = null; 15661 this.galleryWidth = $gallery.width(); 15662 this.$gallery = $gallery; 15663 15664 }; 15665 15666 /** @returns {String} the best suffix given the width and the height */ 15667 JustifiedGallery.prototype.getSuffix = function (width, height) { 15668 var longestSide, i; 15669 longestSide = (width > height) ? width : height; 15670 for (i = 0; i < this.suffixRanges.length; i++) { 15671 if (longestSide <= this.suffixRanges[i]) { 15672 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 15673 } 15674 } 15675 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 15676 }; 15677 15678 /** 15679 * Remove the suffix from the string 15680 * 15681 * @returns {string} a new string without the suffix 15682 */ 15683 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 15684 return str.substring(0, str.length - suffix.length); 15685 }; 15686 15687 /** 15688 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 15689 */ 15690 JustifiedGallery.prototype.endsWith = function (str, suffix) { 15691 return str.indexOf(suffix, str.length - suffix.length) !== -1; 15692 }; 15693 15694 /** 15695 * Get the used suffix of a particular url 15696 * 15697 * @param str 15698 * @returns {String} return the used suffix 15699 */ 15700 JustifiedGallery.prototype.getUsedSuffix = function (str) { 15701 for (var si in this.settings.sizeRangeSuffixes) { 15702 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 15703 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 15704 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 15705 } 15706 } 15707 return ''; 15708 }; 15709 15710 /** 15711 * Given an image src, with the width and the height, returns the new image src with the 15712 * best suffix to show the best quality thumbnail. 15713 * 15714 * @returns {String} the suffix to use 15715 */ 15716 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 15717 var newImageSrc; 15718 15719 if (this.settings.thumbnailPath) { 15720 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 15721 } else { 15722 var matchRes = imageSrc.match(this.settings.extension); 15723 var ext = (matchRes !== null) ? matchRes[0] : ''; 15724 newImageSrc = imageSrc.replace(this.settings.extension, ''); 15725 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
15726 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 15727 } 15728 15729 return newImageSrc; 15730 }; 15731 15732 /** 15733 * Shows the images that is in the given entry 15734 * 15735 * @param $entry the entry 15736 * @param callback the callback that is called when the show animation is finished 15737 */ 15738 JustifiedGallery.prototype.showImg = function ($entry, callback) { 15739 if (this.settings.cssAnimation) { 15740 $entry.addClass('entry-visible'); 15741 if (callback) callback(); 15742 } else { 15743 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15744 $entry.find('> img, > a > img').stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15745 } 15746 }; 15747 15748 /** 15749 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 15750 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 15751 * 15752 * @param $image the image to analyze 15753 * @returns {String} the extracted src 15754 */ 15755 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 15756 var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src'); 15757 $image.data('jg.originalSrc', imageSrc); 15758 return imageSrc; 15759 }; 15760 15761 /** @returns {jQuery} the image in the given entry */ 15762 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 15763 var $img = $entry.find('> img'); 15764 if ($img.length === 0) $img = $entry.find('> a > img'); 15765 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 15766 return $img.length === 0 ? null : $img; 15767 }; 15768 15769 /** @returns {jQuery} the caption in the given entry */ 15770 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 15771 var $caption = $entry.find('> .caption'); 15772 return $caption.length === 0 ? null : $caption; 15773 }; 15774 15775 /** 15776 * Display the entry 15777 * 15778 * @param {jQuery} $entry the entry to display 15779 * @param {int} x the x position where the entry must be positioned 15780 * @param y the y position where the entry must be positioned 15781 * @param imgWidth the image width 15782 * @param imgHeight the image height 15783 * @param rowHeight the row height of the row that owns the entry 15784 */ 15785 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 15786 $entry.width(imgWidth); 15787 $entry.height(Math.floor(rowHeight));//hacked by Uncode 15788 $entry.css('top', Math.floor(y));//hacked by Uncode 15789 $entry.css('left', x); 15790 15791 var $image = this.imgFromEntry($entry); 15792 if ($image !== null) { 15793 $image.css('width', imgWidth); 15794 $image.css('height', imgHeight); 15795 $image.css('margin-left', - imgWidth / 2); 15796 $image.css('margin-top', - imgHeight / 2); 15797 15798 // Image reloading for an high quality of thumbnails 15799 var imageSrc = $image.attr('src'); 15800 var newImageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 15801 15802 $image.one('error', function () { 15803 $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it. 15804 }); 15805 15806 var loadNewImage = function () { 15807 if (imageSrc !== newImageSrc) { //load the new image after the fadeIn 15808 $image.attr('src', newImageSrc); 15809 } 15810 }; 15811 15812 if ($entry.data('jg.loaded') === 'skipped') { 15813 this.onImageEvent(imageSrc, $.proxy(function() { 15814 this.showImg($entry, loadNewImage); 15815 $entry.data('jg.loaded', true); 15816 }, this)); 15817 } else { 15818 this.showImg($entry, loadNewImage); 15819 } 15820 15821 } else { 15822 this.showImg($entry); 15823 } 15824 15825 this.displayEntryCaption($entry); 15826 }; 15827 15828 /** 15829 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 15830 * or the 'title' attributes. 15831 * 15832 * @param {jQuery} $entry the entry to process 15833 */ 15834 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 15835 var $image = this.imgFromEntry($entry); 15836 if ($image !== null && this.settings.captions) { 15837 var $imgCaption = this.captionFromEntry($entry); 15838 15839 // Create it if it doesn't exists 15840 if ($imgCaption === null) { 15841 var caption = $image.attr('alt'); 15842 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 15843 if (this.isValidCaption(caption)) { // Create only we found something 15844 $imgCaption = $('<div class="caption">' + caption + '</div>'); 15845 $entry.append($imgCaption); 15846 $entry.data('jg.createdCaption', true); 15847 } 15848 } 15849 15850 // Create events (we check again the $imgCaption because it can be still inexistent) 15851 if ($imgCaption !== null) { 15852 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 15853 this.addCaptionEventsHandlers($entry); 15854 } 15855 } else { 15856 this.removeCaptionEventsHandlers($entry); 15857 } 15858 }; 15859 15860 /** 15861 * Validates the caption 15862 * 15863 * @param caption The caption that should be validated 15864 * @return {boolean} Validation result 15865 */ 15866 JustifiedGallery.prototype.isValidCaption = function (caption) { 15867 return (typeof caption !== 'undefined' && caption.length > 0); 15868 }; 15869 15870 /** 15871 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 15872 * It shows the caption using jQuery (or using CSS if it is configured so) 15873 * 15874 * @param {Event} eventObject the event object 15875 */ 15876 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 15877 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15878 if (this.settings.cssAnimation) { 15879 $caption.addClass('caption-visible').removeClass('caption-hidden'); 15880 } else { 15881 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15882 this.settings.captionSettings.visibleOpacity); 15883 } 15884 }; 15885 15886 /** 15887 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 15888 * It hides the caption using jQuery (or using CSS if it is configured so) 15889 * 15890 * @param {Event} eventObject the event object 15891 */ 15892 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 15893 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15894 if (this.settings.cssAnimation) { 15895 $caption.removeClass('caption-visible').removeClass('caption-hidden'); 15896 } else { 15897 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15898 this.settings.captionSettings.nonVisibleOpacity); 15899 } 15900 }; 15901 15902 /** 15903 * Add the handlers of the entry for the caption 15904 * 15905 * @param $entry the entry to modify 15906 */ 15907 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 15908 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15909 if (typeof captionMouseEvents === 'undefined') { 15910 captionMouseEvents = { 15911 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 15912 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 15913 }; 15914 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 15915 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 15916 $entry.data('jg.captionMouseEvents', captionMouseEvents); 15917 } 15918 }; 15919 15920 /** 15921 * Remove the handlers of the entry for the caption 15922 * 15923 * @param $entry the entry to modify 15924 */ 15925 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 15926 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15927 if (typeof captionMouseEvents !== 'undefined') { 15928 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 15929 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 15930 $entry.removeData('jg.captionMouseEvents'); 15931 } 15932 }; 15933 15934 /** 15935 * Justify the building row, preparing it to 15936 * 15937 * @param isLastRow 15938 * @returns a boolean to know if the row has been justified or not 15939 */ 15940 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow) { 15941 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 15942 var minHeight = 0; 15943 var availableWidth = this.galleryWidth - 2 * this.border - ( 15944 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 15945 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 15946 var defaultRowHeight = this.settings.rowHeight; 15947 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 15948 15949 //Skip the last row if we can't justify it and the lastRow == 'hide' 15950 if (isLastRow && this.settings.lastRow === 'hide' && !justifiable) { 15951 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15952 $entry = this.buildingRow.entriesBuff[i]; 15953 if (this.settings.cssAnimation) 15954 $entry.removeClass('entry-visible'); 15955 else { 15956 $entry.stop().fadeTo(0, 0.1); 15957 $entry.find('> img, > a > img').fadeTo(0, 0); 15958 } 15959 } 15960 return -1; 15961 } 15962 15963 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 15964 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 15965 justify = false;
15966 15967 if (this.rows > 0) { 15968 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 15969 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 15970 } 15971 } 15972 15973 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15974 $entry = this.buildingRow.entriesBuff[i]; 15975 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 15976 15977 if (justify) { 15978 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 15979 newImgH = rowHeight; 15980 } else { 15981 newImgW = defaultRowHeight * imgAspectRatio; 15982 newImgH = defaultRowHeight; 15983 } 15984 15985 availableWidth -= Math.round(newImgW); 15986 $entry.data('jg.jwidth', Math.round(newImgW)); 15987 $entry.data('jg.jheight', Math.ceil(newImgH)); 15988 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 15989 } 15990 15991 this.buildingRow.height = minHeight; 15992 return justify; 15993 }; 15994 15995 /** 15996 * Clear the building row data to be used for a new row 15997 */ 15998 JustifiedGallery.prototype.clearBuildingRow = function () { 15999 this.buildingRow.entriesBuff = []; 16000 this.buildingRow.aspectRatio = 0; 16001 this.buildingRow.width = 0; 16002 }; 16003 16004 /** 16005 * Flush a row: justify it, modify the gallery height accordingly to the row height 16006 * 16007 * @param isLastRow 16008 */ 16009 JustifiedGallery.prototype.flushRow = function (isLastRow) { 16010 var settings = this.settings; 16011 var $entry, buildingRowRes, offX = this.border, i; 16012 16013 buildingRowRes = this.prepareBuildingRow(isLastRow); 16014 if (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1) { 16015 this.clearBuildingRow(); 16016 return; 16017 } 16018 16019 if (this.maxRowHeight) { 16020 if (this.maxRowHeight.isPercentage && this.maxRowHeight.value * settings.rowHeight < this.buildingRow.height) { 16021 this.buildingRow.height = this.maxRowHeight.value * settings.rowHeight; 16022 } else if (this.maxRowHeight.value >= settings.rowHeight && this.maxRowHeight.value < this.buildingRow.height) { 16023 this.buildingRow.height = this.maxRowHeight.value; 16024 } 16025 } 16026 16027 //Align last (unjustified) row 16028 if (settings.lastRow === 'center' || settings.lastRow === 'right') { 16029 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 16030 16031 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16032 $entry = this.buildingRow.entriesBuff[i]; 16033 availableWidth -= $entry.data('jg.jwidth'); 16034 } 16035 16036 if (settings.lastRow === 'center') 16037 offX += availableWidth / 2; 16038 else if (settings.lastRow === 'right') 16039 offX += availableWidth; 16040 } 16041 16042 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16043 $entry = this.buildingRow.entriesBuff[i]; 16044 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 16045 offX += $entry.data('jg.jwidth') + settings.margins; 16046 } 16047 16048 //Gallery Height 16049 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 16050 this.$gallery.height(this.galleryHeightToSet + this.getSpinnerHeight()); 16051 16052 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 16053 //Ready for a new row 16054 this.offY += this.buildingRow.height + settings.margins; 16055 this.rows += 1; 16056 this.clearBuildingRow(); 16057 this.$gallery.trigger('jg.rowflush'); 16058 } 16059 }; 16060 16061 /** 16062 * Checks the width of the gallery container, to know if a new justification is needed 16063 */ 16064 var scrollBarOn = false; 16065 JustifiedGallery.prototype.checkWidth = function () { 16066 this.checkWidthIntervalId = setInterval($.proxy(function () { 16067 var galleryWidth = parseFloat(this.$gallery.width()); 16068 if (hasScrollBar() === scrollBarOn) { 16069 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 16070 this.galleryWidth = galleryWidth; 16071 this.rewind(); 16072 16073 // Restart to analyze 16074 this.startImgAnalyzer(true); 16075 } 16076 } else { 16077 scrollBarOn = hasScrollBar(); 16078 this.galleryWidth = galleryWidth; 16079 } 16080 }, this), this.settings.refreshTime); 16081 }; 16082 16083 /** 16084 * @returns {boolean} a boolean saying if the spinner is active or not 16085 */ 16086 JustifiedGallery.prototype.isSpinnerActive = function () { 16087 return this.spinner.intervalId !== null; 16088 }; 16089 16090 /** 16091 * @returns {int} the spinner height 16092 */ 16093 JustifiedGallery.prototype.getSpinnerHeight = function () {
16094 return this.spinner.$el.innerHeight(); 16095 }; 16096 16097 /** 16098 * Stops the spinner animation and modify the gallery height to exclude the spinner 16099 */ 16100 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 16101 clearInterval(this.spinner.intervalId); 16102 this.spinner.intervalId = null; 16103 this.$gallery.height(this.$gallery.height() - this.getSpinnerHeight()); 16104 this.spinner.$el.detach(); 16105 }; 16106 16107 /** 16108 * Starts the spinner animation 16109 */ 16110 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 16111 var spinnerContext = this.spinner; 16112 var $spinnerPoints = spinnerContext.$el.find('span'); 16113 clearInterval(spinnerContext.intervalId); 16114 this.$gallery.append(spinnerContext.$el); 16115 this.$gallery.height(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 16116 spinnerContext.intervalId = setInterval(function () { 16117 if (spinnerContext.phase < $spinnerPoints.length) { 16118 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 16119 } else {
vendor: 4,333 bytes, lines 16120-16264
16120 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 16121 } 16122 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 16123 }, spinnerContext.timeSlot); 16124 }; 16125 16126 /** 16127 * Rewind the image analysis to start from the first entry. 16128 */ 16129 JustifiedGallery.prototype.rewind = function () { 16130 this.lastFetchedEntry = null; 16131 this.lastAnalyzedIndex = -1; 16132 this.offY = this.border; 16133 this.rows = 0; 16134 this.clearBuildingRow(); 16135 }; 16136 16137 /** 16138 * Update the entries searching it from the justified gallery HTML element 16139 * 16140 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 16141 * @returns {boolean} true if some entries has been founded 16142 */ 16143 JustifiedGallery.prototype.updateEntries = function (norewind) { 16144 var newEntries; 16145 16146 if (norewind && this.lastFetchedEntry != null) { 16147 newEntries = $(this.lastFetchedEntry).nextAll(this.settings.selector).toArray(); 16148 } else { 16149 this.entries = []; 16150 newEntries = this.$gallery.children(this.settings.selector).toArray(); 16151 } 16152 16153 if (newEntries.length > 0) { 16154 16155 // Sort or randomize 16156 if ($.isFunction(this.settings.sort)) { 16157 newEntries = this.sortArray(newEntries); 16158 } else if (this.settings.randomize) { 16159 newEntries = this.shuffleArray(newEntries); 16160 } 16161 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 16162 16163 // Filter 16164 if (this.settings.filter) { 16165 newEntries = this.filterArray(newEntries); 16166 } else { 16167 this.resetFilters(newEntries); 16168 } 16169 16170 } 16171 16172 this.entries = this.entries.concat(newEntries); 16173 return true; 16174 }; 16175 16176 /** 16177 * Apply the entries order to the DOM, iterating the entries and appending the images 16178 * 16179 * @param entries the entries that has been modified and that must be re-ordered in the DOM 16180 */ 16181 JustifiedGallery.prototype.insertToGallery = function (entries) { 16182 var that = this; 16183 $.each(entries, function () { 16184 $(this).appendTo(that.$gallery); 16185 }); 16186 }; 16187 16188 /** 16189 * Shuffle the array using the Fisher-Yates shuffle algorithm 16190 * 16191 * @param a the array to shuffle 16192 * @return the shuffled array 16193 */ 16194 JustifiedGallery.prototype.shuffleArray = function (a) { 16195 var i, j, temp; 16196 for (i = a.length - 1; i > 0; i--) { 16197 j = Math.floor(Math.random() * (i + 1)); 16198 temp = a[i]; 16199 a[i] = a[j]; 16200 a[j] = temp; 16201 } 16202 this.insertToGallery(a); 16203 return a; 16204 }; 16205 16206 /** 16207 * Sort the array using settings.comparator as comparator 16208 * 16209 * @param a the array to sort (it is sorted) 16210 * @return the sorted array 16211 */ 16212 JustifiedGallery.prototype.sortArray = function (a) { 16213 a.sort(this.settings.sort); 16214 this.insertToGallery(a); 16215 return a; 16216 }; 16217 16218 /** 16219 * Reset the filters removing the 'jg-filtered' class from all the entries 16220 * 16221 * @param a the array to reset 16222 */ 16223 JustifiedGallery.prototype.resetFilters = function (a) { 16224 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 16225 }; 16226 16227 /** 16228 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 16229 * 16230 * @param a the array to filter 16231 * @return the filtered array 16232 */ 16233 JustifiedGallery.prototype.filterArray = function (a) { 16234 var settings = this.settings; 16235 if ($.type(settings.filter) === 'string') { 16236 // Filter only keeping the entries passed in the string 16237 return a.filter(function (el) { 16238 var $el = $(el); 16239 if ($el.is(settings.filter)) { 16240 $el.removeClass('jg-filtered'); 16241 return true; 16242 } else { 16243 $el.addClass('jg-filtered').removeClass('jg-visible'); 16244 return false; 16245 } 16246 }); 16247 } else if ($.isFunction(settings.filter)) { 16248 // Filter using the passed function 16249 var filteredArr = a.filter(settings.filter); 16250 for (var i = 0; i < a.length; i++) { 16251 if (filteredArr.indexOf(a[i]) == -1) { 16252 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 16253 } else { 16254 $(a[i]).removeClass('jg-filtered'); 16255 } 16256 } 16257 return filteredArr; 16258 } 16259 }; 16260 16261 /** 16262 * Destroy the Justified Gallery instance. 16263 * 16264 * It clears all the css properties added in the style attributes. We doesn't backup the original
16265 * values for those css attributes, because it costs (performance) and because in general one 16266 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 16267 * classes). Creating a backup is also difficult because JG could be called multiple times and 16268 * with different style attributes. 16269 */ 16270 JustifiedGallery.prototype.destroy = function () { 16271 clearInterval(this.checkWidthIntervalId); 16272 16273 $.each(this.entries, $.proxy(function(_, entry) { 16274 var $entry = $(entry); 16275 16276 // Reset entry style 16277 $entry.css('width', ''); 16278 $entry.css('height', ''); 16279 $entry.css('top', ''); 16280 $entry.css('left', ''); 16281 $entry.data('jg.loaded', undefined); 16282 $entry.removeClass('jg-entry'); 16283 16284 // Reset image style 16285 var $img = this.imgFromEntry($entry); 16286 $img.css('width', ''); 16287 $img.css('height', ''); 16288 $img.css('margin-left', ''); 16289 $img.css('margin-top', ''); 16290 $img.attr('src', $img.data('jg.originalSrc')); 16291 $img.data('jg.originalSrc', undefined); 16292 16293 // Remove caption 16294 this.removeCaptionEventsHandlers($entry); 16295 var $caption = this.captionFromEntry($entry); 16296 if ($entry.data('jg.createdCaption')) { 16297 // remove also the caption element (if created by jg) 16298 $entry.data('jg.createdCaption', undefined); 16299 if ($caption !== null) $caption.remove(); 16300 } else { 16301 if ($caption !== null) $caption.fadeTo(0, 1); 16302 } 16303 16304 }, this)); 16305 16306 this.$gallery.css('height', ''); 16307 this.$gallery.removeClass('justified-gallery'); 16308 this.$gallery.data('jg.controller', undefined); 16309 }; 16310 16311 /** 16312 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 16313 * 16314 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 16315 */ 16316 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 16317 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 16318 var $entry = $(this.entries[i]); 16319 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 16320 var availableWidth = this.galleryWidth - 2 * this.border - ( 16321 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 16322 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 16323 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 16324 this.flushRow(false); 16325 if(++this.yield.flushed >= this.yield.every) { 16326 this.startImgAnalyzer(isForResize); 16327 return; 16328 } 16329 } 16330 16331 this.buildingRow.entriesBuff.push($entry); 16332 this.buildingRow.aspectRatio += imgAspectRatio; 16333 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 16334 this.lastAnalyzedIndex = i; 16335 16336 } else if ($entry.data('jg.loaded') !== 'error') { 16337 return; 16338 } 16339 } 16340 16341 // Last row flush (the row is not full) 16342 if (this.buildingRow.entriesBuff.length > 0) this.flushRow(true); 16343 16344 if (this.isSpinnerActive()) { 16345 this.stopLoadingSpinnerAnimation(); 16346 } 16347 16348 /* Stop, if there is, the timeout to start the analyzeImages. 16349 This is because an image can be set loaded, and the timeout can be set, 16350 but this image can be analyzed yet. 16351 */ 16352 this.stopImgAnalyzerStarter(); 16353 16354 //On complete callback 16355 this.$gallery.trigger(isForResize ? 'jg.resize' : 'jg.complete'); 16356 this.$gallery.height(this.galleryHeightToSet); 16357 }; 16358 16359 /** 16360 * Stops any ImgAnalyzer starter (that has an assigned timeout) 16361 */ 16362 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 16363 this.yield.flushed = 0; 16364 if (this.imgAnalyzerTimeout !== null) clearTimeout(this.imgAnalyzerTimeout); 16365 }; 16366 16367 /** 16368 * Starts the image analyzer. It is not immediately called to let the browser to update the view 16369 * 16370 * @param isForResize specifies if the image analyzer must be called for resizing or not 16371 */ 16372 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 16373 var that = this; 16374 this.stopImgAnalyzerStarter(); 16375 this.imgAnalyzerTimeout = setTimeout(function () { 16376 that.analyzeImages(isForResize); 16377 }, 0.001); // we can't start it immediately due to a IE different behaviour 16378 }; 16379 16380 /** 16381 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 16382 * because some browsers, with a 404 set complete = true. 16383 * 16384 * @param imageSrc the image src to load 16385 * @param onLoad callback that is called when the image has been loaded
vendor: 13,320 bytes, lines 16386-16736
16386 * @param onError callback that is called in case of an error 16387 */ 16388 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 16389 if (!onLoad && !onError) return; 16390 16391 var memImage = new Image(); 16392 var $memImage = $(memImage); 16393 if (onLoad) { 16394 $memImage.one('load', function () { 16395 $memImage.off('load error'); 16396 onLoad(memImage); 16397 }); 16398 } 16399 if (onError) { 16400 $memImage.one('error', function() { 16401 $memImage.off('load error'); 16402 onError(memImage); 16403 }); 16404 } 16405 memImage.src = imageSrc; 16406 }; 16407 16408 /** 16409 * Init of Justified Gallery controlled 16410 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 16411 */ 16412 JustifiedGallery.prototype.init = function () { 16413 var imagesToLoad = false, skippedImages = false, that = this; 16414 $.each(this.entries, function (index, entry) { 16415 var $entry = $(entry); 16416 var $image = that.imgFromEntry($entry); 16417 16418 $entry.addClass('jg-entry'); 16419 16420 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 16421 16422 // Link Rel global overwrite 16423 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 16424 16425 // Link Target global overwrite 16426 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 16427 16428 if ($image !== null) { 16429 16430 // Image src 16431 var imageSrc = that.extractImgSrcFromImage($image); 16432 $image.attr('src', imageSrc); 16433 16434 /* If we have the height and the width, we don't wait that the image is loaded, but we start directly 16435 * with the justification */ 16436 if (that.settings.waitThumbnailsLoad === false) { 16437 var width = parseFloat($image.attr('width')); 16438 var height = parseFloat($image.attr('height')); 16439 if (!isNaN(width) && !isNaN(height)) { 16440 $entry.data('jg.width', width); 16441 $entry.data('jg.height', height); 16442 $entry.data('jg.loaded', 'skipped'); 16443 skippedImages = true; 16444 that.startImgAnalyzer(false); 16445 return true; // continue 16446 } 16447 } 16448 16449 $entry.data('jg.loaded', false); 16450 imagesToLoad = true; 16451 16452 // Spinner start 16453 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 16454 16455 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 16456 $entry.data('jg.width', loadImg.width); 16457 $entry.data('jg.height', loadImg.height); 16458 $entry.data('jg.loaded', true); 16459 that.startImgAnalyzer(false); 16460 }, function () { // image load error 16461 $entry.data('jg.loaded', 'error'); 16462 that.startImgAnalyzer(false); 16463 }); 16464 16465 } else { 16466 $entry.data('jg.loaded', true); 16467 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 16468 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 16469 } 16470 16471 } 16472 16473 }); 16474 16475 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 16476 this.checkWidth(); 16477 }; 16478 16479 /** 16480 * Checks that it is a valid number. If a string is passed it is converted to a number 16481 * 16482 * @param settingContainer the object that contains the setting (to allow the conversion) 16483 * @param settingName the setting name 16484 */ 16485 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 16486 if ($.type(settingContainer[settingName]) === 'string') { 16487 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 16488 } 16489 16490 if ($.type(settingContainer[settingName]) === 'number') { 16491 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 16492 } else { 16493 throw settingName + ' must be a number'; 16494 } 16495 }; 16496 16497 /** 16498 * Checks the sizeRangeSuffixes and, if necessary, converts 16499 * its keys from string (e.g. old settings with 'lt100') to int. 16500 */ 16501 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 16502 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 16503 throw 'sizeRangeSuffixes must be defined and must be an object'; 16504 } 16505 16506 var suffixRanges = []; 16507 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16508 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 16509 } 16510 16511 var newSizeRngSuffixes = {0: ''}; 16512 for (var i = 0; i < suffixRanges.length; i++) { 16513 if ($.type(suffixRanges[i]) === 'string') { 16514 try { 16515 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 16516 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16517 } catch (e) { 16518 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 16519 } 16520 } else { 16521 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16522 } 16523 } 16524 16525 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 16526 }; 16527 16528 /** 16529 * check and convert the maxRowHeight setting 16530 */ 16531 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 16532 var newMaxRowHeight = { }; 16533 16534 if ($.type(this.settings.maxRowHeight) === 'string') { 16535 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 16536 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 16537 newMaxRowHeight.isPercentage = false; 16538 } else { 16539 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight); 16540 newMaxRowHeight.isPercentage = true; 16541 } 16542 } else if ($.type(this.settings.maxRowHeight) === 'number') { 16543 newMaxRowHeight.value = this.settings.maxRowHeight; 16544 newMaxRowHeight.isPercentage = false; 16545 } else if (this.settings.maxRowHeight === false || 16546 this.settings.maxRowHeight === null || 16547 typeof this.settings.maxRowHeight == 'undefined') { 16548 return null; 16549 } else { 16550 throw 'maxRowHeight must be a number or a percentage'; 16551 } 16552 16553 // check if the converted value is not a number 16554 if (isNaN(newMaxRowHeight.value)) throw 'invalid number for maxRowHeight'; 16555 16556 // check values 16557 if (newMaxRowHeight.isPercentage) { 16558 if (newMaxRowHeight.value < 100) newMaxRowHeight.value = 100; 16559 } 16560 16561 return newMaxRowHeight; 16562 }; 16563 16564 /** 16565 * Checks the settings 16566 */ 16567 JustifiedGallery.prototype.checkSettings = function () { 16568 this.checkSizeRangesSuffixes(); 16569 16570 this.checkOrConvertNumber(this.settings, 'rowHeight'); 16571 this.checkOrConvertNumber(this.settings, 'margins'); 16572 this.checkOrConvertNumber(this.settings, 'border'); 16573 16574 var lastRowModes = [ 16575 'justify', 16576 'nojustify', 16577 'left', 16578 'center', 16579 'right', 16580 'hide' 16581 ]; 16582 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 16583 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 16584 } 16585 16586 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 16587 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 16588 throw 'justifyThreshold must be in the interval [0,1]'; 16589 } 16590 if ($.type(this.settings.cssAnimation) !== 'boolean') { 16591 throw 'cssAnimation must be a boolean'; 16592 } 16593 16594 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 16595 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 16596 16597 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 16598 if (this.settings.captionSettings.visibleOpacity < 0 || 16599 this.settings.captionSettings.visibleOpacity > 1) { 16600 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 16601 } 16602 16603 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 16604 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 16605 this.settings.captionSettings.nonVisibleOpacity > 1) { 16606 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 16607 } 16608 16609 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 16610 this.checkOrConvertNumber(this.settings, 'refreshTime'); 16611 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 16612 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 16613 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 16614 16615 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 16616 throw 'sort must be false or a comparison function'; 16617 } 16618 16619 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 16620 $.type(this.settings.filter) !== 'string') { 16621 throw 'filter must be false, a string or a filter function'; 16622 } 16623 }; 16624 16625 /** 16626 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 16627 * @returns {Array} sorted suffix ranges 16628 */ 16629 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 16630 var suffixRanges = []; 16631 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16632 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 16633 } 16634 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 16635 return suffixRanges; 16636 }; 16637 16638 /** 16639 * Update the existing settings only changing some of them 16640 * 16641 * @param newSettings the new settings (or a subgroup of them) 16642 */ 16643 JustifiedGallery.prototype.updateSettings = function (newSettings) { 16644 // In this case Justified Gallery has been called again changing only some options 16645 this.settings = $.extend({}, this.settings, newSettings); 16646 this.checkSettings(); 16647 16648 // As reported in the settings: negative value = same as margins, 0 = disabled 16649 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 16650 16651 this.maxRowHeight = this.retrieveMaxRowHeight(); 16652 this.suffixRanges = this.retrieveSuffixRanges(); 16653 }; 16654 16655 /** 16656 * Justified Gallery plugin for jQuery 16657 * 16658 * Events 16659 * - jg.complete : called when all the gallery has been created 16660 * - jg.resize : called when the gallery has been resized 16661 * - jg.rowflush : when a new row appears 16662 * 16663 * @param arg the action (or the settings) passed when the plugin is called 16664 * @returns {*} the object itself 16665 */ 16666 $.fn.justifiedGallery = function (arg) { 16667 return this.each(function (index, gallery) { 16668 16669 var $gallery = $(gallery); 16670 $gallery.addClass('justified-gallery'); 16671 16672 var controller = $gallery.data('jg.controller'); 16673 if (typeof controller === 'undefined') { 16674 // Create controller and assign it to the object data 16675 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 16676 if (arg === 'destroy') return; // Just a call to an unexisting object 16677 throw 'The argument must be an object'; 16678 } 16679 controller = new JustifiedGallery($gallery, $.extend({}, $.fn.justifiedGallery.defaults, arg)); 16680 $gallery.data('jg.controller', controller); 16681 } else if (arg === 'norewind') { 16682 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 16683 // ... left to be more readable 16684 } else if (arg === 'destroy') { 16685 controller.destroy(); 16686 return; 16687 } else { 16688 // In this case Justified Gallery has been called again changing only some options 16689 controller.updateSettings(arg); 16690 controller.rewind(); 16691 } 16692 16693 // Update the entries list 16694 if (!controller.updateEntries(arg === 'norewind')) return; 16695 16696 // Init justified gallery 16697 controller.init(); 16698 16699 }); 16700 }; 16701 16702 // Default options 16703 $.fn.justifiedGallery.defaults = { 16704 sizeRangeSuffixes: { }, /* e.g. Flickr configuration 16705 { 16706 100: '_t', // used when longest is less than 100px 16707 240: '_m', // used when longest is between 101px and 240px 16708 320: '_n', // ... 16709 500: '', 16710 640: '_z', 16711 1024: '_b' // used as else case because it is the last 16712 } 16713 */ 16714 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 16715 path relative to a specific thumbnail size. The function should accept respectively three arguments: 16716 current path, width and height */ 16717 rowHeight: 120, 16718 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 16719 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 16720 // can't exceed 3 * rowHeight) 16721 margins: 1, 16722 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 16723 16724 lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 16725 16726 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 16727 * (i.e. lastRow setting is not considered) */ 16728 waitThumbnailsLoad: true, 16729 captions: true, 16730 cssAnimation: true, 16731 imagesAnimationDuration: 500, // ignored with css animations 16732 captionSettings: { // ignored with css animations 16733 animationDuration: 500, 16734 visibleOpacity: 0.7, 16735 nonVisibleOpacity: 0.0 16736 },
vendor: 9,476 bytes, lines 16737-17007
16737 rel: null, // rewrite the rel of each analyzed links 16738 target: null, // rewrite the target of all links 16739 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 16740 refreshTime: 200, // time interval (in ms) to check if the page changes its width 16741 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 16742 randomize: false, 16743 sort: false, /* 16744 - false: to do not sort 16745 - function: to sort them using the function as comparator (see Array.prototype.sort()) 16746 */ 16747 filter: false, /* 16748 - false, null or undefined: for a disabled filter 16749 - a string: an entry is kept if entry.is(filter string) returns true 16750 see jQuery's .is() function for further information 16751 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 16752 It follows the specifications of the Array.prototype.filter() function of JavaScript. 16753 */ 16754 selector: 'a, div:not(.spinner)' // The selector that is used to know what are the entries of the gallery 16755 }; 16756 16757}(jQuery)); 16758 16759/*! 16760* Customized version of iScroll.js 0.0.1 16761* It fixes bugs affecting its integration with fullpage.js 16762*/ 16763/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 16764(function (window, document, Math) { 16765var rAF = window.requestAnimationFrame || 16766 window.webkitRequestAnimationFrame || 16767 window.mozRequestAnimationFrame || 16768 window.oRequestAnimationFrame || 16769 window.msRequestAnimationFrame || 16770 function (callback) { window.setTimeout(callback, 1000 / 60); }; 16771 16772var utils = (function () { 16773 var me = {}; 16774 16775 var _elementStyle = document.createElement('div').style; 16776 var _vendor = (function () { 16777 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 16778 transform, 16779 i = 0, 16780 l = vendors.length; 16781 16782 for ( ; i < l; i++ ) { 16783 transform = vendors[i] + 'ransform'; 16784 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 16785 } 16786 16787 return false; 16788 })(); 16789 16790 function _prefixStyle (style) { 16791 if ( _vendor === false ) return false; 16792 if ( _vendor === '' ) return style; 16793 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 16794 } 16795 16796 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 16797 16798 me.extend = function (target, obj) { 16799 for ( var i in obj ) { 16800 target[i] = obj[i]; 16801 } 16802 }; 16803 16804 me.addEvent = function (el, type, fn, capture) { 16805 el.addEventListener(type, fn, !!capture); 16806 }; 16807 16808 me.removeEvent = function (el, type, fn, capture) { 16809 el.removeEventListener(type, fn, !!capture); 16810 }; 16811 16812 me.prefixPointerEvent = function (pointerEvent) { 16813 return window.MSPointerEvent ? 16814 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 16815 pointerEvent; 16816 }; 16817 16818 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 16819 var distance = current - start, 16820 speed = Math.abs(distance) / time, 16821 destination, 16822 duration; 16823 16824 deceleration = deceleration === undefined ? 0.0006 : deceleration; 16825 16826 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 16827 duration = speed / deceleration; 16828 16829 if ( destination < lowerMargin ) { 16830 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 16831 distance = Math.abs(destination - current); 16832 duration = distance / speed; 16833 } else if ( destination > 0 ) { 16834 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 16835 distance = Math.abs(current) + destination; 16836 duration = distance / speed; 16837 } 16838 16839 return { 16840 destination: Math.round(destination), 16841 duration: duration 16842 }; 16843 }; 16844 16845 var _transform = _prefixStyle('transform'); 16846 16847 me.extend(me, { 16848 hasTransform: _transform !== false, 16849 hasPerspective: _prefixStyle('perspective') in _elementStyle, 16850 hasTouch: 'ontouchstart' in window, 16851 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 16852 hasTransition: _prefixStyle('transition') in _elementStyle 16853 }); 16854 16855 /* 16856 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 16857 - galaxy S2 is ok 16858 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 16859 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16860 - galaxy S3 is badAndroid (stock brower, webview) 16861 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16862 - galaxy S4 is badAndroid (stock brower, webview) 16863 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16864 - galaxy S5 is OK 16865 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16866 - galaxy S6 is OK 16867 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16868 */ 16869 me.isBadAndroid = (function() { 16870 var appVersion = window.navigator.appVersion; 16871 // Android browser is not a chrome browser. 16872 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 16873 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 16874 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 16875 return parseFloat(safariVersion[1]) < 535.19; 16876 } else { 16877 return true; 16878 } 16879 } else { 16880 return false; 16881 } 16882 })(); 16883 16884 me.extend(me.style = {}, { 16885 transform: _transform, 16886 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 16887 transitionDuration: _prefixStyle('transitionDuration'), 16888 transitionDelay: _prefixStyle('transitionDelay'), 16889 transformOrigin: _prefixStyle('transformOrigin') 16890 }); 16891 16892 me.hasClass = function (e, c) { 16893 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 16894 return re.test(e.className); 16895 }; 16896 16897 me.addClass = function (e, c) { 16898 if ( me.hasClass(e, c) ) { 16899 return; 16900 } 16901 16902 var newclass = e.className.split(' '); 16903 newclass.push(c); 16904 e.className = newclass.join(' '); 16905 }; 16906 16907 me.removeClass = function (e, c) { 16908 if ( !me.hasClass(e, c) ) { 16909 return; 16910 } 16911 16912 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 16913 e.className = e.className.replace(re, ' '); 16914 }; 16915 16916 me.offset = function (el) { 16917 var left = -el.offsetLeft, 16918 top = -el.offsetTop; 16919 16920 // jshint -W084 16921 while (el = el.offsetParent) { 16922 left -= el.offsetLeft; 16923 top -= el.offsetTop; 16924 } 16925 // jshint +W084 16926 16927 return { 16928 left: left, 16929 top: top 16930 }; 16931 }; 16932 16933 me.preventDefaultException = function (el, exceptions) { 16934 for ( var i in exceptions ) { 16935 if ( exceptions[i].test(el[i]) ) { 16936 return true; 16937 } 16938 } 16939 16940 return false; 16941 }; 16942 16943 me.extend(me.eventType = {}, { 16944 touchstart: 1, 16945 touchmove: 1, 16946 touchend: 1, 16947 16948 mousedown: 2, 16949 mousemove: 2, 16950 mouseup: 2, 16951 16952 pointerdown: 3, 16953 pointermove: 3, 16954 pointerup: 3, 16955 16956 MSPointerDown: 3, 16957 MSPointerMove: 3, 16958 MSPointerUp: 3 16959 }); 16960 16961 me.extend(me.ease = {}, { 16962 quadratic: { 16963 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 16964 fn: function (k) { 16965 return k * ( 2 - k ); 16966 } 16967 }, 16968 circular: { 16969 style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1) 16970 fn: function (k) { 16971 return Math.sqrt( 1 - ( --k * k ) ); 16972 } 16973 }, 16974 back: { 16975 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 16976 fn: function (k) { 16977 var b = 4; 16978 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 16979 } 16980 }, 16981 bounce: { 16982 style: '', 16983 fn: function (k) { 16984 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 16985 return 7.5625 * k * k; 16986 } else if ( k < ( 2 / 2.75 ) ) { 16987 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 16988 } else if ( k < ( 2.5 / 2.75 ) ) { 16989 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 16990 } else { 16991 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 16992 } 16993 } 16994 }, 16995 elastic: { 16996 style: '', 16997 fn: function (k) { 16998 var f = 0.22, 16999 e = 0.4; 17000 17001 if ( k === 0 ) { return 0; } 17002 if ( k == 1 ) { return 1; } 17003 17004 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 17005 } 17006 } 17007 });
17008 17009 me.tap = function (e, eventName) { 17010 var ev = document.createEvent('Event'); 17011 ev.initEvent(eventName, true, true); 17012 ev.pageX = e.pageX; 17013 ev.pageY = e.pageY; 17014 e.target.dispatchEvent(ev); 17015 }; 17016 17017 me.click = function (e) { 17018 var target = e.target, 17019 ev; 17020 17021 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 17022 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 17023 // initMouseEvent is deprecated. 17024 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 17025 ev.initEvent('click', true, true); 17026 ev.view = e.view || window; 17027 ev.detail = 1; 17028 ev.screenX = target.screenX || 0; 17029 ev.screenY = target.screenY || 0; 17030 ev.clientX = target.clientX || 0; 17031 ev.clientY = target.clientY || 0; 17032 ev.ctrlKey = !!e.ctrlKey; 17033 ev.altKey = !!e.altKey; 17034 ev.shiftKey = !!e.shiftKey; 17035 ev.metaKey = !!e.metaKey; 17036 ev.button = 0; 17037 ev.relatedTarget = null; 17038 ev._constructed = true; 17039 target.dispatchEvent(ev); 17040 } 17041 }; 17042 17043 return me; 17044})(); 17045function IScroll (el, options) { 17046 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 17047 this.scroller = this.wrapper.children[0]; 17048 this.scrollerStyle = this.scroller.style; // cache style for better performance 17049 17050 this.options = { 17051 17052 resizeScrollbars: true, 17053 17054 mouseWheelSpeed: 20, 17055 17056 snapThreshold: 0.334, 17057 17058// INSERT POINT: OPTIONS 17059 disablePointer : !utils.hasPointer, 17060 disableTouch : utils.hasPointer || !utils.hasTouch, 17061 disableMouse : utils.hasPointer || utils.hasTouch, 17062 startX: 0, 17063 startY: 0, 17064 scrollY: true, 17065 directionLockThreshold: 5, 17066 momentum: true, 17067 17068 bounce: true, 17069 bounceTime: 600, 17070 bounceEasing: '', 17071 17072 preventDefault: true, 17073 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ }, 17074 17075 HWCompositing: true, 17076 useTransition: true, 17077 useTransform: true, 17078 bindToWrapper: typeof window.onmousedown === "undefined" 17079 }; 17080 17081 for ( var i in options ) { 17082 this.options[i] = options[i]; 17083 } 17084 17085 // Normalize options 17086 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 17087 17088 this.options.useTransition = utils.hasTransition && this.options.useTransition; 17089 this.options.useTransform = utils.hasTransform && this.options.useTransform; 17090 17091 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 17092 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 17093 17094 // If you want eventPassthrough I have to lock one of the axes 17095 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 17096 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 17097 17098 // With eventPassthrough we also need lockDirection mechanism 17099 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 17100 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 17101 17102 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 17103 17104 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 17105 17106 if ( this.options.tap === true ) { 17107 this.options.tap = 'tap'; 17108 } 17109 17110 // https://github.com/cubiq/iscroll/issues/1029 17111 if (!this.options.useTransition && !this.options.useTransform) { 17112 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 17113 this.scrollerStyle.position = "relative"; 17114 } 17115 } 17116 17117 if ( this.options.shrinkScrollbars == 'scale' ) { 17118 this.options.useTransition = false; 17119 } 17120 17121 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 17122 17123// INSERT POINT: NORMALIZATION 17124 17125 // Some defaults 17126 this.x = 0; 17127 this.y = 0; 17128 this.directionX = 0; 17129 this.directionY = 0; 17130 this._events = {}; 17131 17132// INSERT POINT: DEFAULTS 17133 17134 this._init(); 17135 this.refresh();
vendor: 4,317 bytes, lines 17136-17278
17136 17137 this.scrollTo(this.options.startX, this.options.startY); 17138 this.enable(); 17139} 17140 17141IScroll.prototype = { 17142 version: '5.2.0', 17143 17144 _init: function () { 17145 this._initEvents(); 17146 17147 if ( this.options.scrollbars || this.options.indicators ) { 17148 this._initIndicators(); 17149 } 17150 17151 if ( this.options.mouseWheel ) { 17152 this._initWheel(); 17153 } 17154 17155 if ( this.options.snap ) { 17156 this._initSnap(); 17157 } 17158 17159 if ( this.options.keyBindings ) { 17160 this._initKeys(); 17161 } 17162 17163// INSERT POINT: _init 17164 17165 }, 17166 17167 destroy: function () { 17168 this._initEvents(true); 17169 clearTimeout(this.resizeTimeout); 17170 this.resizeTimeout = null; 17171 this._execEvent('destroy'); 17172 }, 17173 17174 _transitionEnd: function (e) { 17175 if ( e.target != this.scroller || !this.isInTransition ) { 17176 return; 17177 } 17178 17179 this._transitionTime(); 17180 if ( !this.resetPosition(this.options.bounceTime) ) { 17181 this.isInTransition = false; 17182 this._execEvent('scrollEnd'); 17183 } 17184 }, 17185 17186 _start: function (e) { 17187 // React to left mouse button only 17188 if ( utils.eventType[e.type] != 1 ) { 17189 // for button property 17190 // http://unixpapa.com/js/mouse.html 17191 var button; 17192 if (!e.which) { 17193 /* IE case */ 17194 button = (e.button < 2) ? 0 : 17195 ((e.button == 4) ? 1 : 2); 17196 } else { 17197 /* All others */ 17198 button = e.button; 17199 } 17200 if ( button !== 0 ) { 17201 return; 17202 } 17203 } 17204 17205 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 17206 return; 17207 } 17208 17209 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17210 e.preventDefault(); 17211 } 17212 17213 var point = e.touches ? e.touches[0] : e, 17214 pos; 17215 17216 this.initiated = utils.eventType[e.type]; 17217 this.moved = false; 17218 this.distX = 0; 17219 this.distY = 0; 17220 this.directionX = 0; 17221 this.directionY = 0; 17222 this.directionLocked = 0; 17223 17224 this.startTime = utils.getTime(); 17225 17226 if ( this.options.useTransition && this.isInTransition ) { 17227 this._transitionTime(); 17228 this.isInTransition = false; 17229 pos = this.getComputedPosition(); 17230 this._translate(Math.round(pos.x), Math.round(pos.y)); 17231 this._execEvent('scrollEnd'); 17232 } else if ( !this.options.useTransition && this.isAnimating ) { 17233 this.isAnimating = false; 17234 this._execEvent('scrollEnd'); 17235 } 17236 17237 this.startX = this.x; 17238 this.startY = this.y; 17239 this.absStartX = this.x; 17240 this.absStartY = this.y; 17241 this.pointX = point.pageX; 17242 this.pointY = point.pageY; 17243 17244 this._execEvent('beforeScrollStart'); 17245 }, 17246 17247 _move: function (e) { 17248 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17249 return; 17250 } 17251 17252 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 17253 e.preventDefault(); 17254 } 17255 17256 var point = e.touches ? e.touches[0] : e, 17257 deltaX = point.pageX - this.pointX, 17258 deltaY = point.pageY - this.pointY, 17259 timestamp = utils.getTime(), 17260 newX, newY, 17261 absDistX, absDistY; 17262 17263 this.pointX = point.pageX; 17264 this.pointY = point.pageY; 17265 17266 this.distX += deltaX; 17267 this.distY += deltaY; 17268 absDistX = Math.abs(this.distX); 17269 absDistY = Math.abs(this.distY); 17270 17271 // We need to move at least 10 pixels for the scrolling to initiate 17272 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 17273 return; 17274 } 17275 17276 // If you are scrolling in one direction lock the other 17277 if ( !this.directionLocked && !this.options.freeScroll ) { 17278 if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 5,654 bytes, lines 17279-17442
17279 this.directionLocked = 'h'; // lock horizontally 17280 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 17281 this.directionLocked = 'v'; // lock vertically 17282 } else { 17283 this.directionLocked = 'n'; // no lock 17284 } 17285 } 17286 17287 if ( this.directionLocked == 'h' ) { 17288 if ( this.options.eventPassthrough == 'vertical' ) { 17289 e.preventDefault(); 17290 } else if ( this.options.eventPassthrough == 'horizontal' ) { 17291 this.initiated = false; 17292 return; 17293 } 17294 17295 deltaY = 0; 17296 } else if ( this.directionLocked == 'v' ) { 17297 if ( this.options.eventPassthrough == 'horizontal' ) { 17298 e.preventDefault(); 17299 } else if ( this.options.eventPassthrough == 'vertical' ) { 17300 this.initiated = false; 17301 return; 17302 } 17303 17304 deltaX = 0; 17305 } 17306 17307 deltaX = this.hasHorizontalScroll ? deltaX : 0; 17308 deltaY = this.hasVerticalScroll ? deltaY : 0; 17309 17310 newX = this.x + deltaX; 17311 newY = this.y + deltaY; 17312 17313 // Slow down if outside of the boundaries 17314 if ( newX > 0 || newX < this.maxScrollX ) { 17315 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 17316 } 17317 if ( newY > 0 || newY < this.maxScrollY ) { 17318 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 17319 } 17320 17321 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 17322 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 17323 17324 if ( !this.moved ) { 17325 this._execEvent('scrollStart'); 17326 } 17327 17328 this.moved = true; 17329 17330 this._translate(newX, newY); 17331 17332/* REPLACE START: _move */ 17333 17334 if ( timestamp - this.startTime > 300 ) { 17335 this.startTime = timestamp; 17336 this.startX = this.x; 17337 this.startY = this.y; 17338 } 17339 17340/* REPLACE END: _move */ 17341 17342 }, 17343 17344 _end: function (e) { 17345 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17346 return; 17347 } 17348 17349 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17350 e.preventDefault(); 17351 } 17352 17353 var point = e.changedTouches ? e.changedTouches[0] : e, 17354 momentumX, 17355 momentumY, 17356 duration = utils.getTime() - this.startTime, 17357 newX = Math.round(this.x), 17358 newY = Math.round(this.y), 17359 distanceX = Math.abs(newX - this.startX), 17360 distanceY = Math.abs(newY - this.startY), 17361 time = 0, 17362 easing = ''; 17363 17364 this.isInTransition = 0; 17365 this.initiated = 0; 17366 this.endTime = utils.getTime(); 17367 17368 // reset if we are outside of the boundaries 17369 if ( this.resetPosition(this.options.bounceTime) ) { 17370 return; 17371 } 17372 17373 this.scrollTo(newX, newY); // ensures that the last position is rounded 17374 17375 // we scrolled less than 10 pixels 17376 if ( !this.moved ) { 17377 if ( this.options.tap ) { 17378 utils.tap(e, this.options.tap); 17379 } 17380 17381 if ( this.options.click ) { 17382 utils.click(e); 17383 } 17384 17385 this._execEvent('scrollCancel'); 17386 return; 17387 } 17388 17389 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 17390 this._execEvent('flick'); 17391 return; 17392 } 17393 17394 // start momentum animation if needed 17395 if ( this.options.momentum && duration < 300 ) { 17396 momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 }; 17397 momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 }; 17398 newX = momentumX.destination; 17399 newY = momentumY.destination; 17400 time = Math.max(momentumX.duration, momentumY.duration); 17401 this.isInTransition = 1; 17402 } 17403 17404 17405 if ( this.options.snap ) { 17406 var snap = this._nearestSnap(newX, newY); 17407 this.currentPage = snap; 17408 time = this.options.snapSpeed || Math.max( 17409 Math.max( 17410 Math.min(Math.abs(newX - snap.x), 1000), 17411 Math.min(Math.abs(newY - snap.y), 1000) 17412 ), 300); 17413 newX = snap.x; 17414 newY = snap.y; 17415 17416 this.directionX = 0; 17417 this.directionY = 0; 17418 easing = this.options.bounceEasing; 17419 } 17420 17421// INSERT POINT: _end 17422 17423 if ( newX != this.x || newY != this.y ) { 17424 // change easing function when scroller goes out of the boundaries 17425 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 17426 easing = utils.ease.quadratic; 17427 } 17428 17429 this.scrollTo(newX, newY, time, easing); 17430 return; 17431 } 17432 17433 this._execEvent('scrollEnd'); 17434 }, 17435 17436 _resize: function () { 17437 var that = this; 17438 17439 clearTimeout(this.resizeTimeout); 17440 17441 this.resizeTimeout = setTimeout(function () { 17442 that.refresh();
vendor: 12,140 bytes, lines 17443-17836
17443 }, this.options.resizePolling); 17444 }, 17445 17446 resetPosition: function (time) { 17447 var x = this.x, 17448 y = this.y; 17449 17450 time = time || 0; 17451 17452 if ( !this.hasHorizontalScroll || this.x > 0 ) { 17453 x = 0; 17454 } else if ( this.x < this.maxScrollX ) { 17455 x = this.maxScrollX; 17456 } 17457 17458 if ( !this.hasVerticalScroll || this.y > 0 ) { 17459 y = 0; 17460 } else if ( this.y < this.maxScrollY ) { 17461 y = this.maxScrollY; 17462 } 17463 17464 if ( x == this.x && y == this.y ) { 17465 return false; 17466 } 17467 17468 this.scrollTo(x, y, time, this.options.bounceEasing); 17469 17470 return true; 17471 }, 17472 17473 disable: function () { 17474 this.enabled = false; 17475 }, 17476 17477 enable: function () { 17478 this.enabled = true; 17479 }, 17480 17481 refresh: function () { 17482 var rf = this.wrapper.offsetHeight; // Force reflow 17483 17484 this.wrapperWidth = this.wrapper.clientWidth; 17485 this.wrapperHeight = this.wrapper.clientHeight; 17486 17487/* REPLACE START: refresh */ 17488 17489 this.scrollerWidth = this.scroller.offsetWidth; 17490 this.scrollerHeight = this.scroller.offsetHeight; 17491 17492 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 17493 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 17494 17495/* REPLACE END: refresh */ 17496 17497 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 17498 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 17499 17500 if ( !this.hasHorizontalScroll ) { 17501 this.maxScrollX = 0; 17502 this.scrollerWidth = this.wrapperWidth; 17503 } 17504 17505 if ( !this.hasVerticalScroll ) { 17506 this.maxScrollY = 0; 17507 this.scrollerHeight = this.wrapperHeight; 17508 } 17509 17510 this.endTime = 0; 17511 this.directionX = 0; 17512 this.directionY = 0; 17513 17514 this.wrapperOffset = utils.offset(this.wrapper); 17515 17516 this._execEvent('refresh'); 17517 17518 this.resetPosition(); 17519 17520// INSERT POINT: _refresh 17521 17522 }, 17523 17524 on: function (type, fn) { 17525 if ( !this._events[type] ) { 17526 this._events[type] = []; 17527 } 17528 17529 this._events[type].push(fn); 17530 }, 17531 17532 off: function (type, fn) { 17533 if ( !this._events[type] ) { 17534 return; 17535 } 17536 17537 var index = this._events[type].indexOf(fn); 17538 17539 if ( index > -1 ) { 17540 this._events[type].splice(index, 1); 17541 } 17542 }, 17543 17544 _execEvent: function (type) { 17545 if ( !this._events[type] ) { 17546 return; 17547 } 17548 17549 var i = 0, 17550 l = this._events[type].length; 17551 17552 if ( !l ) { 17553 return; 17554 } 17555 17556 for ( ; i < l; i++ ) { 17557 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 17558 } 17559 }, 17560 17561 scrollBy: function (x, y, time, easing) { 17562 x = this.x + x; 17563 y = this.y + y; 17564 time = time || 0; 17565 17566 this.scrollTo(x, y, time, easing); 17567 }, 17568 17569 scrollTo: function (x, y, time, easing) { 17570 easing = easing || utils.ease.circular; 17571 17572 this.isInTransition = this.options.useTransition && time > 0; 17573 var transitionType = this.options.useTransition && easing.style; 17574 if ( !time || transitionType ) { 17575 if(transitionType) { 17576 this._transitionTimingFunction(easing.style); 17577 this._transitionTime(time); 17578 } 17579 this._translate(x, y); 17580 } else { 17581 this._animate(x, y, time, easing.fn); 17582 } 17583 }, 17584 17585 scrollToElement: function (el, time, offsetX, offsetY, easing) { 17586 el = el.nodeType ? el : this.scroller.querySelector(el); 17587 17588 if ( !el ) { 17589 return; 17590 } 17591 17592 var pos = utils.offset(el); 17593 17594 pos.left -= this.wrapperOffset.left; 17595 pos.top -= this.wrapperOffset.top; 17596 17597 // if offsetX/Y are true we center the element to the screen 17598 if ( offsetX === true ) { 17599 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 17600 } 17601 if ( offsetY === true ) { 17602 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 17603 } 17604 17605 pos.left -= offsetX || 0; 17606 pos.top -= offsetY || 0; 17607 17608 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 17609 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 17610 17611 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 17612 17613 this.scrollTo(pos.left, pos.top, time, easing); 17614 }, 17615 17616 _transitionTime: function (time) { 17617 if (!this.options.useTransition) { 17618 return; 17619 } 17620 time = time || 0; 17621 var durationProp = utils.style.transitionDuration; 17622 if(!durationProp) { 17623 return; 17624 } 17625 17626 this.scrollerStyle[durationProp] = time + 'ms'; 17627 17628 if ( !time && utils.isBadAndroid ) { 17629 this.scrollerStyle[durationProp] = '0.0001ms'; 17630 // remove 0.0001ms 17631 var self = this; 17632 rAF(function() { 17633 if(self.scrollerStyle[durationProp] === '0.0001ms') { 17634 self.scrollerStyle[durationProp] = '0s'; 17635 } 17636 }); 17637 } 17638 17639 17640 if ( this.indicators ) { 17641 for ( var i = this.indicators.length; i--; ) { 17642 this.indicators[i].transitionTime(time); 17643 } 17644 } 17645 17646 17647// INSERT POINT: _transitionTime 17648 17649 }, 17650 17651 _transitionTimingFunction: function (easing) { 17652 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 17653 17654 17655 if ( this.indicators ) { 17656 for ( var i = this.indicators.length; i--; ) { 17657 this.indicators[i].transitionTimingFunction(easing); 17658 } 17659 } 17660 17661 17662// INSERT POINT: _transitionTimingFunction 17663 17664 }, 17665 17666 _translate: function (x, y) { 17667 //Uncode addition 17668 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 17669 return false; 17670 17671 if ( this.options.useTransform ) { 17672 17673/* REPLACE START: _translate */ 17674 17675 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 17676 17677/* REPLACE END: _translate */ 17678 17679 } else { 17680 x = Math.round(x); 17681 y = Math.round(y); 17682 this.scrollerStyle.left = x + 'px'; 17683 this.scrollerStyle.top = y + 'px'; 17684 } 17685 17686 this.x = x; 17687 this.y = y; 17688 17689 17690 if ( this.indicators ) { 17691 for ( var i = this.indicators.length; i--; ) { 17692 this.indicators[i].updatePosition(); 17693 } 17694 } 17695 17696 //Uncode addition 17697 var uncodevent = new CustomEvent('fp-slide-scroll'); 17698 window.dispatchEvent(uncodevent); 17699 17700// INSERT POINT: _translate 17701 17702 }, 17703 17704 _initEvents: function (remove) { 17705 var eventType = remove ? utils.removeEvent : utils.addEvent, 17706 target = this.options.bindToWrapper ? this.wrapper : window; 17707 17708 eventType(window, 'orientationchange', this); 17709 eventType(window, 'resize', this); 17710 17711 if ( this.options.click ) { 17712 eventType(this.wrapper, 'click', this, true); 17713 } 17714 17715 if ( !this.options.disableMouse ) { 17716 eventType(this.wrapper, 'mousedown', this); 17717 eventType(target, 'mousemove', this); 17718 eventType(target, 'mousecancel', this); 17719 eventType(target, 'mouseup', this); 17720 } 17721 17722 if ( utils.hasPointer && !this.options.disablePointer ) { 17723 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 17724 eventType(target, utils.prefixPointerEvent('pointermove'), this); 17725 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 17726 eventType(target, utils.prefixPointerEvent('pointerup'), this); 17727 } 17728 17729 if ( utils.hasTouch && !this.options.disableTouch ) { 17730 eventType(this.wrapper, 'touchstart', this); 17731 eventType(target, 'touchmove', this); 17732 eventType(target, 'touchcancel', this); 17733 eventType(target, 'touchend', this); 17734 } 17735 17736 eventType(this.scroller, 'transitionend', this); 17737 eventType(this.scroller, 'webkitTransitionEnd', this); 17738 eventType(this.scroller, 'oTransitionEnd', this); 17739 eventType(this.scroller, 'MSTransitionEnd', this); 17740 }, 17741 17742 getComputedPosition: function () { 17743 var matrix = window.getComputedStyle(this.scroller, null), 17744 x, y; 17745 17746 if ( this.options.useTransform ) { 17747 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 17748 x = +(matrix[12] || matrix[4]); 17749 y = +(matrix[13] || matrix[5]); 17750 } else { 17751 x = +matrix.left.replace(/[^-\d.]/g, ''); 17752 y = +matrix.top.replace(/[^-\d.]/g, ''); 17753 } 17754 17755 return { x: x, y: y }; 17756 }, 17757 _initIndicators: function () { 17758 var interactive = this.options.interactiveScrollbars, 17759 customStyle = typeof this.options.scrollbars != 'string', 17760 indicators = [], 17761 indicator; 17762 17763 var that = this; 17764 17765 this.indicators = []; 17766 17767 if ( this.options.scrollbars ) { 17768 // Vertical scrollbar 17769 if ( this.options.scrollY ) { 17770 indicator = { 17771 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 17772 interactive: interactive, 17773 defaultScrollbars: true, 17774 customStyle: customStyle, 17775 resize: this.options.resizeScrollbars, 17776 shrink: this.options.shrinkScrollbars, 17777 fade: this.options.fadeScrollbars, 17778 listenX: false 17779 }; 17780 17781 this.wrapper.appendChild(indicator.el); 17782 indicators.push(indicator); 17783 } 17784 17785 // Horizontal scrollbar 17786 if ( this.options.scrollX ) { 17787 indicator = { 17788 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 17789 interactive: interactive, 17790 defaultScrollbars: true, 17791 customStyle: customStyle, 17792 resize: this.options.resizeScrollbars, 17793 shrink: this.options.shrinkScrollbars, 17794 fade: this.options.fadeScrollbars, 17795 listenY: false 17796 }; 17797 17798 this.wrapper.appendChild(indicator.el); 17799 indicators.push(indicator); 17800 } 17801 } 17802 17803 if ( this.options.indicators ) { 17804 // TODO: check concat compatibility 17805 indicators = indicators.concat(this.options.indicators); 17806 } 17807 17808 for ( var i = indicators.length; i--; ) { 17809 this.indicators.push( new Indicator(this, indicators[i]) ); 17810 } 17811 17812 // TODO: check if we can use array.map (wide compatibility and performance issues) 17813 function _indicatorsMap (fn) { 17814 if (that.indicators) { 17815 for ( var i = that.indicators.length; i--; ) { 17816 fn.call(that.indicators[i]); 17817 } 17818 } 17819 } 17820 17821 if ( this.options.fadeScrollbars ) { 17822 this.on('scrollEnd', function () { 17823 _indicatorsMap(function () { 17824 this.fade(); 17825 }); 17826 }); 17827 17828 this.on('scrollCancel', function () { 17829 _indicatorsMap(function () { 17830 this.fade(); 17831 }); 17832 }); 17833 17834 this.on('scrollStart', function () { 17835 _indicatorsMap(function () { 17836 this.fade(1);
vendor: 4,420 bytes, lines 17837-17981
17837 }); 17838 }); 17839 17840 this.on('beforeScrollStart', function () { 17841 _indicatorsMap(function () { 17842 this.fade(1, true); 17843 }); 17844 }); 17845 } 17846 17847 17848 this.on('refresh', function () { 17849 _indicatorsMap(function () { 17850 this.refresh(); 17851 }); 17852 }); 17853 17854 this.on('destroy', function () { 17855 _indicatorsMap(function () { 17856 this.destroy(); 17857 }); 17858 17859 delete this.indicators; 17860 }); 17861 }, 17862 17863 _initWheel: function () { 17864 utils.addEvent(this.wrapper, 'wheel', this); 17865 utils.addEvent(this.wrapper, 'mousewheel', this); 17866 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 17867 17868 this.on('destroy', function () { 17869 clearTimeout(this.wheelTimeout); 17870 this.wheelTimeout = null; 17871 utils.removeEvent(this.wrapper, 'wheel', this); 17872 utils.removeEvent(this.wrapper, 'mousewheel', this); 17873 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 17874 }); 17875 }, 17876 17877 _wheel: function (e) { 17878 if ( !this.enabled ) { 17879 return; 17880 } 17881 17882 var wheelDeltaX, wheelDeltaY, 17883 newX, newY, 17884 that = this; 17885 17886 if ( this.wheelTimeout === undefined ) { 17887 that._execEvent('scrollStart'); 17888 } 17889 17890 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 17891 clearTimeout(this.wheelTimeout); 17892 this.wheelTimeout = setTimeout(function () { 17893 if(!that.options.snap) { 17894 that._execEvent('scrollEnd'); 17895 } 17896 that.wheelTimeout = undefined; 17897 }, 400); 17898 17899 if ( 'deltaX' in e ) { 17900 if (e.deltaMode === 1) { 17901 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 17902 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 17903 } else { 17904 wheelDeltaX = -e.deltaX; 17905 wheelDeltaY = -e.deltaY; 17906 } 17907 } else if ( 'wheelDeltaX' in e ) { 17908 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 17909 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 17910 } else if ( 'wheelDelta' in e ) { 17911 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 17912 } else if ( 'detail' in e ) { 17913 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 17914 } else { 17915 return; 17916 } 17917 17918 wheelDeltaX *= this.options.invertWheelDirection; 17919 wheelDeltaY *= this.options.invertWheelDirection; 17920 17921 if ( !this.hasVerticalScroll ) { 17922 wheelDeltaX = wheelDeltaY; 17923 wheelDeltaY = 0; 17924 } 17925 17926 if ( this.options.snap ) { 17927 newX = this.currentPage.pageX; 17928 newY = this.currentPage.pageY; 17929 17930 if ( wheelDeltaX > 0 ) { 17931 newX--; 17932 } else if ( wheelDeltaX < 0 ) { 17933 newX++; 17934 } 17935 17936 if ( wheelDeltaY > 0 ) { 17937 newY--; 17938 } else if ( wheelDeltaY < 0 ) { 17939 newY++; 17940 } 17941 17942 this.goToPage(newX, newY); 17943 17944 return; 17945 } 17946 17947 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 17948 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 17949 17950 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 17951 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 17952 17953 if ( newX > 0 ) { 17954 newX = 0; 17955 } else if ( newX < this.maxScrollX ) { 17956 newX = this.maxScrollX; 17957 } 17958 17959 if ( newY > 0 ) { 17960 newY = 0; 17961 } else if ( newY < this.maxScrollY ) { 17962 newY = this.maxScrollY; 17963 } 17964 17965 this.scrollTo(newX, newY, 0); 17966 17967// INSERT POINT: _wheel 17968 }, 17969 17970 _initSnap: function () { 17971 this.currentPage = {}; 17972 17973 if ( typeof this.options.snap == 'string' ) { 17974 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 17975 } 17976 17977 this.on('refresh', function () { 17978 var i = 0, l, 17979 m = 0, n, 17980 cx, cy, 17981 x = 0, y,
vendor: 7,592 bytes, lines 17982-18235
17982 stepX = this.options.snapStepX || this.wrapperWidth, 17983 stepY = this.options.snapStepY || this.wrapperHeight, 17984 el; 17985 17986 this.pages = []; 17987 17988 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 17989 return; 17990 } 17991 17992 if ( this.options.snap === true ) { 17993 cx = Math.round( stepX / 2 ); 17994 cy = Math.round( stepY / 2 ); 17995 17996 while ( x > -this.scrollerWidth ) { 17997 this.pages[i] = []; 17998 l = 0; 17999 y = 0; 18000 18001 while ( y > -this.scrollerHeight ) { 18002 this.pages[i][l] = { 18003 x: Math.max(x, this.maxScrollX), 18004 y: Math.max(y, this.maxScrollY), 18005 width: stepX, 18006 height: stepY, 18007 cx: x - cx, 18008 cy: y - cy 18009 }; 18010 18011 y -= stepY; 18012 l++; 18013 } 18014 18015 x -= stepX; 18016 i++; 18017 } 18018 } else { 18019 el = this.options.snap; 18020 l = el.length; 18021 n = -1; 18022 18023 for ( ; i < l; i++ ) { 18024 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 18025 m = 0; 18026 n++; 18027 } 18028 18029 if ( !this.pages[m] ) { 18030 this.pages[m] = []; 18031 } 18032 18033 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 18034 y = Math.max(-el[i].offsetTop, this.maxScrollY); 18035 cx = x - Math.round(el[i].offsetWidth / 2); 18036 cy = y - Math.round(el[i].offsetHeight / 2); 18037 18038 this.pages[m][n] = { 18039 x: x, 18040 y: y, 18041 width: el[i].offsetWidth, 18042 height: el[i].offsetHeight, 18043 cx: cx, 18044 cy: cy 18045 }; 18046 18047 if ( x > this.maxScrollX ) { 18048 m++; 18049 } 18050 } 18051 } 18052 18053 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 18054 18055 // Update snap threshold if needed 18056 if ( this.options.snapThreshold % 1 === 0 ) { 18057 this.snapThresholdX = this.options.snapThreshold; 18058 this.snapThresholdY = this.options.snapThreshold; 18059 } else { 18060 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 18061 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 18062 } 18063 }); 18064 18065 this.on('flick', function () { 18066 var time = this.options.snapSpeed || Math.max( 18067 Math.max( 18068 Math.min(Math.abs(this.x - this.startX), 1000), 18069 Math.min(Math.abs(this.y - this.startY), 1000) 18070 ), 300); 18071 18072 this.goToPage( 18073 this.currentPage.pageX + this.directionX, 18074 this.currentPage.pageY + this.directionY, 18075 time 18076 ); 18077 }); 18078 }, 18079 18080 _nearestSnap: function (x, y) { 18081 if ( !this.pages.length ) { 18082 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 18083 } 18084 18085 var i = 0, 18086 l = this.pages.length, 18087 m = 0; 18088 18089 // Check if we exceeded the snap threshold 18090 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 18091 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 18092 return this.currentPage; 18093 } 18094 18095 if ( x > 0 ) { 18096 x = 0; 18097 } else if ( x < this.maxScrollX ) { 18098 x = this.maxScrollX; 18099 } 18100 18101 if ( y > 0 ) { 18102 y = 0; 18103 } else if ( y < this.maxScrollY ) { 18104 y = this.maxScrollY; 18105 } 18106 18107 for ( ; i < l; i++ ) { 18108 if ( x >= this.pages[i][0].cx ) { 18109 x = this.pages[i][0].x; 18110 break; 18111 } 18112 } 18113 18114 l = this.pages[i].length; 18115 18116 for ( ; m < l; m++ ) { 18117 if ( y >= this.pages[0][m].cy ) { 18118 y = this.pages[0][m].y; 18119 break; 18120 } 18121 } 18122 18123 if ( i == this.currentPage.pageX ) { 18124 i += this.directionX; 18125 18126 if ( i < 0 ) { 18127 i = 0; 18128 } else if ( i >= this.pages.length ) { 18129 i = this.pages.length - 1; 18130 } 18131 18132 x = this.pages[i][0].x; 18133 } 18134 18135 if ( m == this.currentPage.pageY ) { 18136 m += this.directionY; 18137 18138 if ( m < 0 ) { 18139 m = 0; 18140 } else if ( m >= this.pages[0].length ) { 18141 m = this.pages[0].length - 1; 18142 } 18143 18144 y = this.pages[0][m].y; 18145 } 18146 18147 return { 18148 x: x, 18149 y: y, 18150 pageX: i, 18151 pageY: m 18152 }; 18153 }, 18154 18155 goToPage: function (x, y, time, easing) { 18156 easing = easing || this.options.bounceEasing; 18157 18158 if ( x >= this.pages.length ) { 18159 x = this.pages.length - 1; 18160 } else if ( x < 0 ) { 18161 x = 0; 18162 } 18163 18164 if ( y >= this.pages[x].length ) { 18165 y = this.pages[x].length - 1; 18166 } else if ( y < 0 ) { 18167 y = 0; 18168 } 18169 18170 var posX = this.pages[x][y].x, 18171 posY = this.pages[x][y].y; 18172 18173 time = time === undefined ? this.options.snapSpeed || Math.max( 18174 Math.max( 18175 Math.min(Math.abs(posX - this.x), 1000), 18176 Math.min(Math.abs(posY - this.y), 1000) 18177 ), 300) : time; 18178 18179 this.currentPage = { 18180 x: posX, 18181 y: posY, 18182 pageX: x, 18183 pageY: y 18184 }; 18185 18186 this.scrollTo(posX, posY, time, easing); 18187 }, 18188 18189 next: function (time, easing) { 18190 var x = this.currentPage.pageX, 18191 y = this.currentPage.pageY; 18192 18193 x++; 18194 18195 if ( x >= this.pages.length && this.hasVerticalScroll ) { 18196 x = 0; 18197 y++; 18198 } 18199 18200 this.goToPage(x, y, time, easing); 18201 }, 18202 18203 prev: function (time, easing) { 18204 var x = this.currentPage.pageX, 18205 y = this.currentPage.pageY; 18206 18207 x--; 18208 18209 if ( x < 0 && this.hasVerticalScroll ) { 18210 x = 0; 18211 y--; 18212 } 18213 18214 this.goToPage(x, y, time, easing); 18215 }, 18216 18217 _initKeys: function (e) { 18218 // default key bindings 18219 var keys = { 18220 pageUp: 33, 18221 pageDown: 34, 18222 end: 35, 18223 home: 36, 18224 left: 37, 18225 up: 38, 18226 right: 39, 18227 down: 40 18228 }; 18229 var i; 18230 18231 // if you give me characters I give you keycode 18232 if ( typeof this.options.keyBindings == 'object' ) { 18233 for ( i in this.options.keyBindings ) { 18234 if ( typeof this.options.keyBindings[i] == 'string' ) { 18235 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 16,384 bytes, lines 18235-18735
18235deAt(0); 18236 } 18237 } 18238 } else { 18239 this.options.keyBindings = {}; 18240 } 18241 18242 for ( i in keys ) { 18243 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 18244 } 18245 18246 utils.addEvent(window, 'keydown', this); 18247 18248 this.on('destroy', function () { 18249 utils.removeEvent(window, 'keydown', this); 18250 }); 18251 }, 18252 18253 _key: function (e) { 18254 if ( !this.enabled ) { 18255 return; 18256 } 18257 18258 var snap = this.options.snap, // we are using this alot, better to cache it 18259 newX = snap ? this.currentPage.pageX : this.x, 18260 newY = snap ? this.currentPage.pageY : this.y, 18261 now = utils.getTime(), 18262 prevTime = this.keyTime || 0, 18263 acceleration = 0.250, 18264 pos; 18265 18266 if ( this.options.useTransition && this.isInTransition ) { 18267 pos = this.getComputedPosition(); 18268 18269 this._translate(Math.round(pos.x), Math.round(pos.y)); 18270 this.isInTransition = false; 18271 } 18272 18273 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 18274 18275 switch ( e.keyCode ) { 18276 case this.options.keyBindings.pageUp: 18277 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18278 newX += snap ? 1 : this.wrapperWidth; 18279 } else { 18280 newY += snap ? 1 : this.wrapperHeight; 18281 } 18282 break; 18283 case this.options.keyBindings.pageDown: 18284 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18285 newX -= snap ? 1 : this.wrapperWidth; 18286 } else { 18287 newY -= snap ? 1 : this.wrapperHeight; 18288 } 18289 break; 18290 case this.options.keyBindings.end: 18291 newX = snap ? this.pages.length-1 : this.maxScrollX; 18292 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 18293 break; 18294 case this.options.keyBindings.home: 18295 newX = 0; 18296 newY = 0; 18297 break; 18298 case this.options.keyBindings.left: 18299 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 18300 break; 18301 case this.options.keyBindings.up: 18302 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 18303 break; 18304 case this.options.keyBindings.right: 18305 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 18306 break; 18307 case this.options.keyBindings.down: 18308 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 18309 break; 18310 default: 18311 return; 18312 } 18313 18314 if ( snap ) { 18315 this.goToPage(newX, newY); 18316 return; 18317 } 18318 18319 if ( newX > 0 ) { 18320 newX = 0; 18321 this.keyAcceleration = 0; 18322 } else if ( newX < this.maxScrollX ) { 18323 newX = this.maxScrollX; 18324 this.keyAcceleration = 0; 18325 } 18326 18327 if ( newY > 0 ) { 18328 newY = 0; 18329 this.keyAcceleration = 0; 18330 } else if ( newY < this.maxScrollY ) { 18331 newY = this.maxScrollY; 18332 this.keyAcceleration = 0; 18333 } 18334 18335 this.scrollTo(newX, newY, 0); 18336 18337 this.keyTime = now; 18338 }, 18339 18340 _animate: function (destX, destY, duration, easingFn) { 18341 var that = this, 18342 startX = this.x, 18343 startY = this.y, 18344 startTime = utils.getTime(), 18345 destTime = startTime + duration; 18346 18347 function step () { 18348 var now = utils.getTime(), 18349 newX, newY, 18350 easing; 18351 18352 if ( now >= destTime ) { 18353 that.isAnimating = false; 18354 that._translate(destX, destY); 18355 18356 if ( !that.resetPosition(that.options.bounceTime) ) { 18357 that._execEvent('scrollEnd'); 18358 } 18359 18360 return; 18361 } 18362 18363 now = ( now - startTime ) / duration; 18364 easing = easingFn(now); 18365 newX = ( destX - startX ) * easing + startX; 18366 newY = ( destY - startY ) * easing + startY; 18367 that._translate(newX, newY); 18368 18369 if ( that.isAnimating ) { 18370 rAF(step); 18371 } 18372 } 18373 18374 this.isAnimating = true; 18375 step(); 18376 }, 18377 handleEvent: function (e) { 18378 switch ( e.type ) { 18379 case 'touchstart': 18380 case 'pointerdown': 18381 case 'MSPointerDown': 18382 case 'mousedown': 18383 this._start(e); 18384 break; 18385 case 'touchmove': 18386 case 'pointermove': 18387 case 'MSPointerMove': 18388 case 'mousemove': 18389 this._move(e); 18390 break; 18391 case 'touchend': 18392 case 'pointerup': 18393 case 'MSPointerUp': 18394 case 'mouseup': 18395 case 'touchcancel': 18396 case 'pointercancel': 18397 case 'MSPointerCancel': 18398 case 'mousecancel': 18399 this._end(e); 18400 break; 18401 case 'orientationchange': 18402 case 'resize': 18403 this._resize(); 18404 break; 18405 case 'transitionend': 18406 case 'webkitTransitionEnd': 18407 case 'oTransitionEnd': 18408 case 'MSTransitionEnd': 18409 this._transitionEnd(e); 18410 break; 18411 case 'wheel': 18412 case 'DOMMouseScroll': 18413 case 'mousewheel': 18414 this._wheel(e); 18415 break; 18416 case 'keydown': 18417 this._key(e); 18418 break; 18419 case 'click': 18420 if ( this.enabled && !e._constructed ) { 18421 e.preventDefault(); 18422 e.stopPropagation(); 18423 } 18424 break; 18425 } 18426 } 18427}; 18428function createDefaultScrollbar (direction, interactive, type) { 18429 var scrollbar = document.createElement('div'), 18430 indicator = document.createElement('div'); 18431 18432 if ( type === true ) { 18433 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 18434 indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px'; 18435 } 18436 18437 indicator.className = 'iScrollIndicator'; 18438 18439 if ( direction == 'h' ) { 18440 if ( type === true ) { 18441 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 18442 indicator.style.height = '100%'; 18443 } 18444 scrollbar.className = 'iScrollHorizontalScrollbar'; 18445 } else { 18446 if ( type === true ) { 18447 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 18448 indicator.style.width = '100%'; 18449 } 18450 scrollbar.className = 'iScrollVerticalScrollbar'; 18451 } 18452 18453 scrollbar.style.cssText += ';overflow:hidden'; 18454 18455 if ( !interactive ) { 18456 scrollbar.style.pointerEvents = 'none'; 18457 } 18458 18459 scrollbar.appendChild(indicator); 18460 18461 return scrollbar; 18462} 18463 18464function Indicator (scroller, options) { 18465 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 18466 this.wrapperStyle = this.wrapper.style; 18467 this.indicator = this.wrapper.children[0]; 18468 this.indicatorStyle = this.indicator.style; 18469 this.scroller = scroller; 18470 18471 this.options = { 18472 listenX: true, 18473 listenY: true, 18474 interactive: false, 18475 resize: true, 18476 defaultScrollbars: false, 18477 shrink: false, 18478 fade: false, 18479 speedRatioX: 0, 18480 speedRatioY: 0 18481 }; 18482 18483 for ( var i in options ) { 18484 this.options[i] = options[i]; 18485 } 18486 18487 this.sizeRatioX = 1; 18488 this.sizeRatioY = 1; 18489 this.maxPosX = 0; 18490 this.maxPosY = 0; 18491 18492 if ( this.options.interactive ) { 18493 if ( !this.options.disableTouch ) { 18494 utils.addEvent(this.indicator, 'touchstart', this); 18495 utils.addEvent(window, 'touchend', this); 18496 } 18497 if ( !this.options.disablePointer ) { 18498 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18499 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 18500 } 18501 if ( !this.options.disableMouse ) { 18502 utils.addEvent(this.indicator, 'mousedown', this); 18503 utils.addEvent(window, 'mouseup', this); 18504 } 18505 } 18506 18507 if ( this.options.fade ) { 18508 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 18509 var durationProp = utils.style.transitionDuration; 18510 if(!durationProp) { 18511 return; 18512 } 18513 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 18514 // remove 0.0001ms 18515 var self = this; 18516 if(utils.isBadAndroid) { 18517 rAF(function() { 18518 if(self.wrapperStyle[durationProp] === '0.0001ms') { 18519 self.wrapperStyle[durationProp] = '0s'; 18520 } 18521 }); 18522 } 18523 this.wrapperStyle.opacity = '0'; 18524 } 18525} 18526 18527Indicator.prototype = { 18528 handleEvent: function (e) { 18529 switch ( e.type ) { 18530 case 'touchstart': 18531 case 'pointerdown': 18532 case 'MSPointerDown': 18533 case 'mousedown': 18534 this._start(e); 18535 break; 18536 case 'touchmove': 18537 case 'pointermove': 18538 case 'MSPointerMove': 18539 case 'mousemove': 18540 this._move(e); 18541 break; 18542 case 'touchend': 18543 case 'pointerup': 18544 case 'MSPointerUp': 18545 case 'mouseup': 18546 case 'touchcancel': 18547 case 'pointercancel': 18548 case 'MSPointerCancel': 18549 case 'mousecancel': 18550 this._end(e); 18551 break; 18552 } 18553 }, 18554 18555 destroy: function () { 18556 if ( this.options.fadeScrollbars ) { 18557 clearTimeout(this.fadeTimeout); 18558 this.fadeTimeout = null; 18559 } 18560 if ( this.options.interactive ) { 18561 utils.removeEvent(this.indicator, 'touchstart', this); 18562 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18563 utils.removeEvent(this.indicator, 'mousedown', this); 18564 18565 utils.removeEvent(window, 'touchmove', this); 18566 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18567 utils.removeEvent(window, 'mousemove', this); 18568 18569 utils.removeEvent(window, 'touchend', this); 18570 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 18571 utils.removeEvent(window, 'mouseup', this); 18572 } 18573 18574 if ( this.options.defaultScrollbars ) { 18575 this.wrapper.parentNode.removeChild(this.wrapper); 18576 } 18577 }, 18578 18579 _start: function (e) { 18580 var point = e.touches ? e.touches[0] : e; 18581 18582 e.preventDefault(); 18583 e.stopPropagation(); 18584 18585 this.transitionTime(); 18586 18587 this.initiated = true; 18588 this.moved = false; 18589 this.lastPointX = point.pageX; 18590 this.lastPointY = point.pageY; 18591 18592 this.startTime = utils.getTime(); 18593 18594 if ( !this.options.disableTouch ) { 18595 utils.addEvent(window, 'touchmove', this); 18596 } 18597 if ( !this.options.disablePointer ) { 18598 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 18599 } 18600 if ( !this.options.disableMouse ) { 18601 utils.addEvent(window, 'mousemove', this); 18602 } 18603 18604 this.scroller._execEvent('beforeScrollStart'); 18605 }, 18606 18607 _move: function (e) { 18608 var point = e.touches ? e.touches[0] : e, 18609 deltaX, deltaY, 18610 newX, newY, 18611 timestamp = utils.getTime(); 18612 18613 if ( !this.moved ) { 18614 this.scroller._execEvent('scrollStart'); 18615 } 18616 18617 this.moved = true; 18618 18619 deltaX = point.pageX - this.lastPointX; 18620 this.lastPointX = point.pageX; 18621 18622 deltaY = point.pageY - this.lastPointY; 18623 this.lastPointY = point.pageY; 18624 18625 newX = this.x + deltaX; 18626 newY = this.y + deltaY; 18627 18628 this._pos(newX, newY); 18629 18630// INSERT POINT: indicator._move 18631 18632 e.preventDefault(); 18633 e.stopPropagation(); 18634 }, 18635 18636 _end: function (e) { 18637 if ( !this.initiated ) { 18638 return; 18639 } 18640 18641 this.initiated = false; 18642 18643 e.preventDefault(); 18644 e.stopPropagation(); 18645 18646 utils.removeEvent(window, 'touchmove', this); 18647 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18648 utils.removeEvent(window, 'mousemove', this); 18649 18650 if ( this.scroller.options.snap ) { 18651 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 18652 18653 var time = this.options.snapSpeed || Math.max( 18654 Math.max( 18655 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 18656 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 18657 ), 300); 18658 18659 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 18660 this.scroller.directionX = 0; 18661 this.scroller.directionY = 0; 18662 this.scroller.currentPage = snap; 18663 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 18664 } 18665 } 18666 18667 if ( this.moved ) { 18668 this.scroller._execEvent('scrollEnd'); 18669 } 18670 }, 18671 18672 transitionTime: function (time) { 18673 time = time || 0; 18674 var durationProp = utils.style.transitionDuration; 18675 if(!durationProp) { 18676 return; 18677 } 18678 18679 this.indicatorStyle[durationProp] = time + 'ms'; 18680 18681 if ( !time && utils.isBadAndroid ) { 18682 this.indicatorStyle[durationProp] = '0.0001ms'; 18683 // remove 0.0001ms 18684 var self = this; 18685 rAF(function() { 18686 if(self.indicatorStyle[durationProp] === '0.0001ms') { 18687 self.indicatorStyle[durationProp] = '0s'; 18688 } 18689 }); 18690 } 18691 }, 18692 18693 transitionTimingFunction: function (easing) { 18694 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 18695 }, 18696 18697 refresh: function () { 18698 this.transitionTime(); 18699 18700 if ( this.options.listenX && !this.options.listenY ) { 18701 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 18702 } else if ( this.options.listenY && !this.options.listenX ) { 18703 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 18704 } else { 18705 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 18706 } 18707 18708 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 18709 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 18710 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 18711 18712 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18713 if ( this.options.listenX ) { 18714 this.wrapper.style.right = '8px'; 18715 } else { 18716 this.wrapper.style.bottom = '8px'; 18717 } 18718 } 18719 } else { 18720 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 18721 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 18722 18723 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18724 if ( this.options.listenX ) { 18725 this.wrapper.style.right = '2px'; 18726 } else { 18727 this.wrapper.style.bottom = '2px'; 18728 } 18729 } 18730 } 18731 18732 var r = this.wrapper.offsetHeight; // force refresh 18733 18734 if ( this.options.listenX ) { 18735
vendor: 5,401 bytes, lines 18735-18864
18735 this.wrapperWidth = this.wrapper.clientWidth; 18736 if ( this.options.resize ) { 18737 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 18738 this.indicatorStyle.width = this.indicatorWidth + 'px'; 18739 } else { 18740 this.indicatorWidth = this.indicator.clientWidth; 18741 } 18742 18743 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 18744 18745 if ( this.options.shrink == 'clip' ) { 18746 this.minBoundaryX = -this.indicatorWidth + 8; 18747 this.maxBoundaryX = this.wrapperWidth - 8; 18748 } else { 18749 this.minBoundaryX = 0; 18750 this.maxBoundaryX = this.maxPosX; 18751 } 18752 18753 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 18754 } 18755 18756 if ( this.options.listenY ) { 18757 this.wrapperHeight = this.wrapper.clientHeight; 18758 if ( this.options.resize ) { 18759 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 18760 this.indicatorStyle.height = this.indicatorHeight + 'px'; 18761 } else { 18762 this.indicatorHeight = this.indicator.clientHeight; 18763 } 18764 18765 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18766 18767 if ( this.options.shrink == 'clip' ) { 18768 this.minBoundaryY = -this.indicatorHeight + 8; 18769 this.maxBoundaryY = this.wrapperHeight - 8; 18770 } else { 18771 this.minBoundaryY = 0; 18772 this.maxBoundaryY = this.maxPosY; 18773 } 18774 18775 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18776 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 18777 } 18778 18779 this.updatePosition(); 18780 }, 18781 18782 updatePosition: function () { 18783 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 18784 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 18785 18786 if ( !this.options.ignoreBoundaries ) { 18787 if ( x < this.minBoundaryX ) { 18788 if ( this.options.shrink == 'scale' ) { 18789 this.width = Math.max(this.indicatorWidth + x, 8); 18790 this.indicatorStyle.width = this.width + 'px'; 18791 } 18792 x = this.minBoundaryX; 18793 } else if ( x > this.maxBoundaryX ) { 18794 if ( this.options.shrink == 'scale' ) { 18795 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 18796 this.indicatorStyle.width = this.width + 'px'; 18797 x = this.maxPosX + this.indicatorWidth - this.width; 18798 } else { 18799 x = this.maxBoundaryX; 18800 } 18801 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 18802 this.width = this.indicatorWidth; 18803 this.indicatorStyle.width = this.width + 'px'; 18804 } 18805 18806 if ( y < this.minBoundaryY ) { 18807 if ( this.options.shrink == 'scale' ) { 18808 this.height = Math.max(this.indicatorHeight + y * 3, 8); 18809 this.indicatorStyle.height = this.height + 'px'; 18810 } 18811 y = this.minBoundaryY; 18812 } else if ( y > this.maxBoundaryY ) { 18813 if ( this.options.shrink == 'scale' ) { 18814 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 18815 this.indicatorStyle.height = this.height + 'px'; 18816 y = this.maxPosY + this.indicatorHeight - this.height; 18817 } else { 18818 y = this.maxBoundaryY; 18819 } 18820 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 18821 this.height = this.indicatorHeight; 18822 this.indicatorStyle.height = this.height + 'px'; 18823 } 18824 } 18825 18826 this.x = x; 18827 this.y = y; 18828 18829 if ( this.scroller.options.useTransform ) { 18830 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 18831 } else { 18832 this.indicatorStyle.left = x + 'px'; 18833 this.indicatorStyle.top = y + 'px'; 18834 } 18835 }, 18836 18837 _pos: function (x, y) { 18838 if ( x < 0 ) { 18839 x = 0; 18840 } else if ( x > this.maxPosX ) { 18841 x = this.maxPosX; 18842 } 18843 18844 if ( y < 0 ) { 18845 y = 0; 18846 } else if ( y > this.maxPosY ) { 18847 y = this.maxPosY; 18848 } 18849 18850 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 18851 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 18852 18853 this.scroller.scrollTo(x, y); 18854 }, 18855 18856 fade: function (val, hold) { 18857 if ( hold && !this.visible ) { 18858 return; 18859 } 18860 18861 clearTimeout(this.fadeTimeout); 18862 this.fadeTimeout = null; 18863 18864 var time = val ? 250 : 500,
18865 delay = val ? 0 : 300; 18866 18867 val = val ? '1' : '0'; 18868 18869 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 18870 18871 this.fadeTimeout = setTimeout((function (val) { 18872 this.wrapperStyle.opacity = val; 18873 this.visible = +val; 18874 }).bind(this, val), delay); 18875 } 18876}; 18877 18878IScroll.utils = utils; 18879 18880if ( typeof module != 'undefined' && module.exports ) { 18881 module.exports = IScroll; 18882} else if ( typeof define == 'function' && define.amd ) { 18883 define( function () { return IScroll; } ); 18884} else { 18885 window.IScroll = IScroll; 18886} 18887 18888})(window, document, Math); 18889/*! 18890 * fullPage 2.9.4 18891 * https://github.com/alvarotrigo/fullPage.js 18892 * @license MIT licensed 18893 * 18894 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 18895 */ 18896(function(global, factory) { 18897 'use strict'; 18898 if (typeof define === 'function' && define.amd) { 18899 define(['jquery'], function($) { 18900 return factory($, global, global.document, global.Math); 18901 }); 18902 } else if (typeof exports === "object" && exports) { 18903 module.exports = factory(require('jquery'), global, global.document, global.Math); 18904 } else { 18905 factory(jQuery, global, global.document, global.Math); 18906 } 18907})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 18908 'use strict'; 18909 18910 // keeping central set of classnames and selectors 18911 var WRAPPER = 'fullpage-wrapper'; 18912 var WRAPPER_SEL = '.' + WRAPPER; 18913 18914 // slimscroll 18915 var SCROLLABLE = 'fp-scrollable'; 18916 var SCROLLABLE_SEL = '.' + SCROLLABLE; 18917 18918 // util 18919 var RESPONSIVE = 'fp-responsive'; 18920 var NO_TRANSITION = 'fp-notransition'; 18921 var DESTROYED = 'fp-destroyed'; 18922 var ENABLED = 'fp-enabled'; 18923 var VIEWING_PREFIX = 'fp-viewing'; 18924 var ACTIVE = 'active'; 18925 var ACTIVE_SEL = '.' + ACTIVE; 18926 var COMPLETELY = 'fp-completely'; 18927 var COMPLETELY_SEL = '.' + COMPLETELY; 18928 18929 // section 18930 var SECTION_DEFAULT_SEL = '.section'; 18931 var SECTION = 'fp-section'; 18932 var SECTION_SEL = '.' + SECTION; 18933 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 18934 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 18935 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 18936 var TABLE_CELL = 'fp-tableCell'; 18937 var TABLE_CELL_SEL = '.' + TABLE_CELL; 18938 var AUTO_HEIGHT = 'fp-auto-height'; 18939 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 18940 var NORMAL_SCROLL = 'fp-normal-scroll'; 18941 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 18942 18943 // section nav 18944 var SECTION_NAV = 'fp-nav'; 18945 var SECTION_NAV_SEL = '#' + SECTION_NAV; 18946 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 18947 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 18948 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 18949 18950 // slide 18951 var SLIDE_DEFAULT_SEL = '.slide'; 18952 var SLIDE = 'fp-slide'; 18953 var SLIDE_SEL = '.' + SLIDE; 18954 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 18955 var SLIDES_WRAPPER = 'fp-slides'; 18956 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 18957 var SLIDES_CONTAINER = 'fp-slidesContainer'; 18958 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 18959 var TABLE = 'fp-table'; 18960 18961 // slide nav 18962 var SLIDES_NAV = 'fp-slidesNav'; 18963 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 18964 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 18965 var SLIDES_ARROW = 'fp-controlArrow'; 18966 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 18967 var SLIDES_PREV = 'fp-prev'; 18968 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 18969 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 18970 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 18971 var SLIDES_NEXT = 'fp-next'; 18972 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 18973 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 18974 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 18975 18976 var $window = $(window); 18977 var $document = $(document); 18978 18979 // Default options for iScroll.js used when using scrollOverflow 18980 var iscrollOptions = { 18981 scrollbars: true, 18982 mouseWheel: true, 18983 hideScrollbars: false, 18984 fadeScrollbars: false, 18985 disableMouse: true, 18986 interactiveScrollbars: true, 18987 bounce: false, 18988 }; 18989 18990 $.fn.fullpage = function(options) { 18991 //only once my friend! 18992 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 18993 18994 // common jQuery objects 18995 var $htmlBody = $('html, body'); 18996 var $body = $('body'); 18997 18998 var FP = $.fn.fullpage; 18999 19000 // Creating some defaults, extending them with any options that were provided 19001 options = $.extend({ 19002 //navigation 19003 menu: false, 19004 anchors:[], 19005 lockAnchors: false, 19006 navigation: false, 19007 navigationPosition: 'right', 19008 navigationTooltips: [], 19009 showActiveTooltip: false, 19010 slidesNavigation: false, 19011 slidesNavPosition: 'bottom', 19012 scrollBar: false, 19013 hybrid: false, 19014 19015 //scrolling 19016 css3: true, 19017 scrollingSpeed: 700, 19018 autoScrolling: true, 19019 fitToSection: true, 19020 fitToSectionDelay: 1000, 19021 easing: 'easeInOutCubic', 19022 easingcss3: 'ease', 19023 loopBottom: false, 19024 loopTop: false, 19025 loopHorizontal: true, 19026 continuousVertical: false, 19027 continuousHorizontal: false, 19028 scrollHorizontally: false, 19029 interlockedSlides: false, 19030 dragAndMove: false, 19031 offsetSections: false, 19032 resetSliders: false, 19033 fadingEffect: false, 19034 normalScrollElements: null, 19035 scrollOverflow: false, 19036 scrollOverflowReset: false, 19037 scrollOverflowHandler: iscrollHandler, 19038 scrollOverflowOptions: null, 19039 touchSensitivity: 5, 19040 normalScrollElementTouchThreshold: 5, 19041 bigSectionsDestination: null, 19042 19043 //Accessibility 19044 keyboardScrolling: true, 19045 animateAnchor: true, 19046 recordHistory: true, 19047 19048 //design 19049 controlArrows: true, 19050 controlArrowColor: '#fff', 19051 verticalCentered: true, 19052 sectionsColor : [], 19053 paddingTop: 0, 19054 paddingBottom: 0, 19055 fixedElements: null, 19056 responsive: 0, //backwards compabitility with responsiveWiddth 19057 responsiveWidth: 0, 19058 responsiveHeight: 0, 19059 responsiveSlides: false, 19060 parallax: false, 19061 parallaxOptions: { 19062 type: 'reveal', 19063 percentage: 62, 19064 property: 'translate' 19065 }, 19066 19067 //Custom selectors 19068 sectionSelector: SECTION_DEFAULT_SEL, 19069 slideSelector: SLIDE_DEFAULT_SEL, 19070 19071 //events 19072 afterLoad: null, 19073 onLeave: null, 19074 afterRender: null, 19075 afterResize: null, 19076 afterReBuild: null, 19077 afterSlideLoad: null, 19078 onSlideLeave: null, 19079 afterResponsive: null, 19080 19081 lazyLoading: true 19082 }, options); 19083 19084 //flag to avoid very fast sliding for landscape sliders 19085 var slideMoving = false; 19086 19087 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 19088 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 19089 var container = $(this); 19090 var windowsHeight = $window.height(); 19091 var isResizing = false; 19092 var isWindowFocused = true; 19093 var lastScrolledDestiny; 19094 var lastScrolledSlide; 19095 var canScroll = true; 19096 var scrollings = []; 19097 var controlPressed; 19098 var startingSection; 19099 var isScrollAllowed = {}; 19100 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 19101 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 19102 var MSPointer = getMSPointer(); 19103 var events = { 19104 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 19105 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 19106 }; 19107 19108 //timeouts 19109 var resizeId; 19110 var afterSectionLoadsId; 19111 var afterSlideLoadsId; 19112 var scrollId; 19113 var scrollId2;
19114 var keydownId; 19115 var originals = $.extend(true, {}, options); //deep copy 19116 19117 //Uncode addition 19118 var $masthead = $('#masthead'); 19119 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 19120 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 19121 var bodyBorder = UNCODE.bodyBorder; 19122 var adminBarHeight = UNCODE.adminBarHeight; 19123 19124 displayWarnings(); 19125 19126 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 19127 iscrollOptions.click = isTouch; // see #2035 19128 19129 //extending iScroll options with the user custom ones 19130 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 19131 19132 //easeInOutCubic animation included in the plugin 19133 $.extend($.easing,{ easeInOutCubic: function (x, t, b, c, d) {if ((t/=d/2) < 1) return c/2*t*t*t + b;return c/2*((t-=2)*t*t + 2) + b;}}); 19134 19135 /** 19136 * Sets the autoScroll option. 19137 * It changes the scroll bar visibility and the history of the site as a result. 19138 */ 19139 function setAutoScrolling(value, type){ 19140 //removing the transformation 19141 if(!value){ 19142 silentScroll(0); 19143 } 19144 19145 setVariableState('autoScrolling', value, type); 19146 19147 var element = $(SECTION_ACTIVE_SEL); 19148 19149 if(options.autoScrolling && !options.scrollBar){ 19150 $htmlBody.css({ 19151 'overflow' : 'hidden !important', 19152 'height' : '100%' 19153 }); 19154 19155 //Uncode addition 19156 //setRecordHistory(originals.recordHistory, 'internal'); 19157 19158 //for IE touch devices 19159 container.css({ 19160 '-ms-touch-action': 'none', 19161 'touch-action': 'none' 19162 }); 19163 19164 if(element.length){ 19165 //moving the container up 19166 silentScroll(element.position().top); 19167 } 19168 19169 }else{ 19170 $htmlBody.css({ 19171 'overflow' : 'visible !important', 19172 'height' : 'initial' 19173 }); 19174 19175 //Uncode addition 19176 //setRecordHistory(false, 'internal'); 19177 19178 //for IE touch devices 19179 container.css({ 19180 '-ms-touch-action': '', 19181 'touch-action': '' 19182 }); 19183 19184 //scrolling the page to the section with no animation 19185 if (element.length) { 19186 $htmlBody.scrollTop(element.position().top); 19187 } 19188 } 19189 } 19190 19191 /** 19192 * Defines wheter to record the history for each hash change in the URL. 19193 */ 19194 function setRecordHistory(value, type){ 19195 setVariableState('recordHistory', value, type); 19196 } 19197 19198 /** 19199 * Defines the scrolling speed 19200 */ 19201 function setScrollingSpeed(value, type){ 19202 setVariableState('scrollingSpeed', value, type); 19203 } 19204 19205 /** 19206 * Sets fitToSection 19207 */ 19208 function setFitToSection(value, type){ 19209 setVariableState('fitToSection', value, type); 19210 } 19211 19212 /** 19213 * Sets lockAnchors 19214 */ 19215 function setLockAnchors(value){ 19216 options.lockAnchors = value; 19217 } 19218 19219 /** 19220 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 19221 */ 19222 function setMouseWheelScrolling(value){ 19223 if(value){ 19224 addMouseWheelHandler(); 19225 addMiddleWheelHandler(); 19226 }else{ 19227 removeMouseWheelHandler(); 19228 removeMiddleWheelHandler(); 19229 } 19230 } 19231 19232 /** 19233 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 19234 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 19235 * 19236 * @param directions string containing the direction or directions separated by comma. 19237 */ 19238 function setAllowScrolling(value, directions){ 19239 if(typeof directions !== 'undefined'){ 19240 directions = directions.replace(/ /g,'').split(','); 19241 19242 $.each(directions, function (index, direction){ 19243 setIsScrollAllowed(value, direction, 'm'); 19244 }); 19245 } 19246 else if(value){ 19247 setMouseWheelScrolling(true); 19248 addTouchHandler(); 19249 }else{ 19250 setMouseWheelScrolling(false); 19251 removeTouchHandler(); 19252 } 19253 } 19254 19255 /** 19256 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 19257 */ 19258 function setKeyboardScrolling(value, directions){ 19259 if(typeof directions !== 'undefined'){ 19260 directions = directions.replace(/ /g,'').split(','); 19261 19262 $.each(directions, function (index, direction){ 19263 setIsScrollAllowed(value, direction, 'k'); 19264 }); 19265 }else{ 19266 options.keyboardScrolling = value; 19267 } 19268 } 19269 19270 /** 19271 * Moves the page up one section. 19272 */ 19273 function moveSectionUp(){ 19274 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 19275 19276 //looping to the bottom if there's no more sections above 19277 if (!prev.length && (options.loopTop || options.continuousVertical)) {
19278 prev = $(SECTION_SEL).last(); 19279 } 19280 19281 if (prev.length) { 19282 scrollPage(prev, null, true); 19283 } 19284 } 19285 19286 /** 19287 * Moves the page down one section. 19288 */ 19289 function moveSectionDown(){ 19290 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 19291 19292 //looping to the top if there's no more sections below 19293 if(!next.length && 19294 (options.loopBottom || options.continuousVertical)){ 19295 next = $(SECTION_SEL).first(); 19296 } 19297 19298 if(next.length){ 19299 scrollPage(next, null, false); 19300 } 19301 } 19302 19303 /** 19304 * Moves the page to the given section and slide with no animation. 19305 * Anchors or index positions can be used as params. 19306 */ 19307 function silentMoveTo(sectionAnchor, slideAnchor){ 19308 setScrollingSpeed (0, 'internal'); 19309 moveTo(sectionAnchor, slideAnchor); 19310 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 19311 } 19312 19313 /** 19314 * Moves the page to the given section and slide. 19315 * Anchors or index positions can be used as params. 19316 */ 19317 function moveTo(sectionAnchor, slideAnchor){ 19318 var destiny = getSectionByAnchor(sectionAnchor); 19319 19320 if (typeof slideAnchor !== 'undefined'){ 19321 scrollPageAndSlide(sectionAnchor, slideAnchor); 19322 }else if(destiny.length > 0){ 19323 scrollPage(destiny); 19324 } 19325 } 19326 19327 /** 19328 * Slides right the slider of the active section. 19329 * Optional `section` param. 19330 */ 19331 function moveSlideRight(section){ 19332 moveSlide('right', section); 19333 } 19334 19335 /** 19336 * Slides left the slider of the active section. 19337 * Optional `section` param. 19338 */ 19339 function moveSlideLeft(section){ 19340 moveSlide('left', section); 19341 } 19342 19343 /** 19344 * When resizing is finished, we adjust the slides sizes and positions 19345 */ 19346 function reBuild(resizing){ 19347 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 19348 19349 isResizing = true; 19350 19351 windowsHeight = $window.height(); //updating global var 19352 19353 $(SECTION_SEL).each(function(){ 19354 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 19355 var slides = $(this).find(SLIDE_SEL); 19356 19357 //adjusting the height of the table-cell for IE and Firefox 19358 if(options.verticalCentered){ 19359 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 19360 } 19361 19362 $(this).css('height', windowsHeight + 'px'); 19363 19364 //resizing the scrolling divs 19365 if(options.scrollOverflow){ 19366 if(slides.length){ 19367 slides.each(function(){ 19368 createScrollBar($(this)); 19369 }); 19370 }else{ 19371 createScrollBar($(this)); 19372 } 19373 } 19374 19375 //adjusting the position fo the FULL WIDTH slides... 19376 if (slides.length > 1) { 19377 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 19378 } 19379 }); 19380 19381 var activeSection = $(SECTION_ACTIVE_SEL); 19382 var sectionIndex = activeSection.index(SECTION_SEL); 19383 19384 //isn't it the first section? 19385 if(sectionIndex){ 19386 //adjusting the position for the current section 19387 silentMoveTo(sectionIndex + 1); 19388 } 19389 19390 isResizing = false; 19391 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 19392 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 19393 } 19394 19395 /** 19396 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 19397 * are smaller than the set limit values. 19398 */ 19399 function setResponsive(active){ 19400 var isResponsive = $body.hasClass(RESPONSIVE); 19401 19402 if(active){ 19403 if(!isResponsive){ 19404 setAutoScrolling(false, 'internal'); 19405 setFitToSection(false, 'internal'); 19406 $(SECTION_NAV_SEL).hide(); 19407 $body.addClass(RESPONSIVE); 19408 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19409 } 19410 } 19411 else if(isResponsive){ 19412 setAutoScrolling(originals.autoScrolling, 'internal'); 19413 setFitToSection(originals.autoScrolling, 'internal'); 19414 $(SECTION_NAV_SEL).show(); 19415 $body.removeClass(RESPONSIVE); 19416 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19417 } 19418 } 19419 19420 if($(this).length){ 19421 //public functions 19422 FP.setAutoScrolling = setAutoScrolling; 19423 FP.setRecordHistory = setRecordHistory;
19424 FP.setScrollingSpeed = setScrollingSpeed; 19425 FP.setFitToSection = setFitToSection; 19426 FP.setLockAnchors = setLockAnchors; 19427 FP.setMouseWheelScrolling = setMouseWheelScrolling; 19428 FP.setAllowScrolling = setAllowScrolling; 19429 FP.setKeyboardScrolling = setKeyboardScrolling; 19430 FP.moveSectionUp = moveSectionUp; 19431 FP.moveSectionDown = moveSectionDown; 19432 FP.silentMoveTo = silentMoveTo; 19433 FP.moveTo = moveTo; 19434 FP.moveSlideRight = moveSlideRight; 19435 FP.moveSlideLeft = moveSlideLeft; 19436 FP.fitToSection = fitToSection; 19437 FP.reBuild = reBuild; 19438 FP.setResponsive = setResponsive; 19439 FP.destroy = destroy; 19440 19441 init(); 19442 19443 bindEvents(); 19444 } 19445 19446 function init(){ 19447 //if css3 is not supported, it will use jQuery animations 19448 if(options.css3){ 19449 options.css3 = support3d(); 19450 } 19451 19452 options.scrollBar = options.scrollBar || options.hybrid; 19453 19454 setOptionsFromDOM(); 19455 prepareDom(); 19456 setAllowScrolling(true); 19457 setAutoScrolling(options.autoScrolling, 'internal'); 19458 responsive(); 19459 19460 //setting the class for the body element 19461 setBodyClass(); 19462 19463 //Uncode addition 19464 // if(document.readyState === 'complete'){ 19465 // scrollToAnchor(); 19466 // } 19467 // $window.on('load', scrollToAnchor); 19468 } 19469 19470 function bindEvents(){ 19471 $window 19472 //when scrolling... 19473 //.on('scroll', scrollHandler) 19474 19475 //detecting any change on the URL to scroll to the given anchor link 19476 //(a way to detect back history button as we play with the hashes on the URL) 19477 .on('hashchange', hashChangeHandler) 19478 19479 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 19480 .blur(blurHandler) 19481 19482 //when resizing the site, we adjust the heights of the sections, slimScroll... 19483 .resize(resizeHandler); 19484 19485 $document 19486 //Sliding with arrow keys, both, vertical and horizontal 19487 .keydown(keydownHandler) 19488 19489 //to prevent scrolling while zooming 19490 .keyup(keyUpHandler) 19491 19492 //Scrolls to the section when clicking the navigation bullet 19493 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 19494 19495 //Scrolls the slider to the given slide destination for the given section 19496 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 19497 19498 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 19499 19500 //Scrolling horizontally when clicking on the slider controls. 19501 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 19502 19503 /** 19504 * Applying normalScroll elements. 19505 * Ignoring the scrolls over the specified selectors. 19506 */ 19507 if(options.normalScrollElements){ 19508 $document.on('mouseenter', options.normalScrollElements, function () { 19509 setMouseWheelScrolling(false); 19510 }); 19511 19512 $document.on('mouseleave', options.normalScrollElements, function(){ 19513 setMouseWheelScrolling(true); 19514 }); 19515 } 19516 } 19517 19518 /** 19519 * Setting options from DOM elements if they are not provided. 19520 */ 19521 function setOptionsFromDOM(){ 19522 var sections = container.find(options.sectionSelector); 19523 19524 //no anchors option? Checking for them in the DOM attributes 19525 if(!options.anchors.length){ 19526 options.anchors = sections.filter('[data-anchor]').map(function(){ 19527 return $(this).data('anchor').toString(); 19528 }).get(); 19529 } 19530 19531 //no tooltips option? Checking for them in the DOM attributes 19532 if(!options.navigationTooltips.length){ 19533 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 19534 return $(this).data('tooltip').toString(); 19535 }).get(); 19536 } 19537 } 19538 19539 /** 19540 * Works over the DOM structure to set it up for the current fullpage options. 19541 */ 19542 function prepareDom(){ 19543 container.css({ 19544 'height': '100%', 19545 'position': 'relative' 19546 }); 19547 19548 //adding a class to recognize the container internally in the code 19549 container.addClass(WRAPPER); 19550 $('html').addClass(ENABLED); 19551 19552 windowsHeight = $window.height(); 19553 19554 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 19555 19556 addInternalSelectors(); 19557 19558 //styling the sections / slides / menu 19559 $(SECTION_SEL).each(function(index){ 19560 var section = $(this); 19561 var slides = section.find(SLIDE_SEL); 19562 var numSlides = slides.length; 19563 19564 styleSection(section, index); 19565 styleMenu(section, index); 19566 19567 // if there's any slide 19568 if (numSlides > 0) { 19569 styleSlides(section, slides, numSlides); 19570 }else{ 19571 if(options.verticalCentered){ 19572 addTableClass(section); 19573 } 19574 } 19575 }); 19576 19577 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 19578 if(options.fixedElements && options.css3){ 19579 $(options.fixedElements).appendTo($body); 19580 } 19581 19582 //vertical centered of the navigation + active bullet 19583 if(options.navigation){ 19584 addVerticalNavigation(); 19585 } 19586 19587 enableYoutubeAPI(); 19588 19589 if(options.scrollOverflow){ 19590 if(document.readyState === 'complete'){ 19591 createScrollBarHandler(); 19592 } 19593 //after DOM and images are loaded 19594 $window.on('load', createScrollBarHandler); 19595 }else{ 19596 afterRenderActions(); 19597 } 19598 } 19599 19600 /** 19601 * Styles the horizontal slides for a section. 19602 */ 19603 function styleSlides(section, slides, numSlides){ 19604 var sliderWidth = numSlides * 100; 19605 var slideWidth = 100 / numSlides; 19606 19607 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 19608 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 19609 19610 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 19611 19612 if(numSlides > 1){ 19613 if(options.controlArrows){ 19614 createSlideArrows(section); 19615 } 19616 19617 if(options.slidesNavigation){ 19618 addSlidesNavigation(section, numSlides); 19619 } 19620 } 19621 19622 slides.each(function(index) { 19623 $(this).css('width', slideWidth + '%'); 19624 19625 if(options.verticalCentered){ 19626 addTableClass($(this)); 19627 } 19628 }); 19629 19630 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 19631 19632 //if the slide won't be an starting point, the default will be the first one 19633 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
19633ide by default. 19634 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 19635 silentLandscapeScroll(startingSlide, 'internal'); 19636 }else{ 19637 slides.eq(0).addClass(ACTIVE); 19638 } 19639 } 19640 19641 /** 19642 * Styling vertical sections 19643 */ 19644 function styleSection(section, index){ 19645 //if no active section is defined, the 1st one will be the default one 19646 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 19647 section.addClass(ACTIVE); 19648 } 19649 startingSection = $(SECTION_ACTIVE_SEL); 19650 19651 section.css('height', windowsHeight + 'px'); 19652 19653 if(options.paddingTop){ 19654 section.css('padding-top', options.paddingTop); 19655 } 19656 19657 if(options.paddingBottom){ 19658 section.css('padding-bottom', options.paddingBottom); 19659 } 19660 19661 if (typeof options.sectionsColor[index] !== 'undefined') { 19662 section.css('background-color', options.sectionsColor[index]); 19663 } 19664 19665 if (typeof options.anchors[index] !== 'undefined') { 19666 section.attr('data-anchor', options.anchors[index]); 19667 } 19668 } 19669 19670 /** 19671 * Sets the data-anchor attributes to the menu elements and activates the current one. 19672 */ 19673 function styleMenu(section, index){ 19674 if (typeof options.anchors[index] !== 'undefined') { 19675 //activating the menu / nav element on load 19676 if(section.hasClass(ACTIVE)){ 19677 activateMenuAndNav(options.anchors[index], index); 19678 } 19679 } 19680 19681 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 19682 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 19683 $(options.menu).appendTo($body); 19684 } 19685 } 19686 19687 /** 19688 * Adds internal classes to be able to provide customizable selectors 19689 * keeping the link with the style sheet. 19690 */ 19691 function addInternalSelectors(){ 19692 container.find(options.sectionSelector).addClass(SECTION); 19693 container.find(options.slideSelector).addClass(SLIDE); 19694 } 19695 19696 /** 19697 * Creates the control arrows for the given section 19698 */ 19699 function createSlideArrows(section){ 19700 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 19701 19702 if(options.controlArrowColor!='#fff'){ 19703 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 19704 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 19705 } 19706 19707 if(!options.loopHorizontal){ 19708 section.find(SLIDES_ARROW_PREV_SEL).hide(); 19709 } 19710 } 19711 19712 /** 19713 * Creates a vertical navigation bar. 19714 */ 19715 function addVerticalNavigation(){ 19716 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 19717 var nav = $(SECTION_NAV_SEL); 19718 19719 nav.addClass(function() { 19720 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 19721 }); 19722 19723 for (var i = 0; i < $(SECTION_SEL).length; i++) { 19724 var link = ''; 19725 if (options.anchors.length) { 19726 link = options.anchors[i]; 19727 } 19728 19729 var li = '<li><a href="#' + link + '"><span></span></a>'; 19730 19731 // Only add tooltip if needed (defined by user) 19732 var tooltip = options.navigationTooltips[i]; 19733 19734 if (typeof tooltip !== 'undefined' && tooltip !== '') { 19735 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 19736 } 19737 19738 li += '</li>'; 19739 19740 nav.find('ul').append(li); 19741 } 19742 19743 //centering it vertically 19744 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 19745 19746 //activating the current active section 19747 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 19748 } 19749 19750 /** 19751 * Creates the slim scroll scrollbar for the sections and slides inside them. 19752 */ 19753 function createScrollBarHandler(){ 19754 $(SECTION_SEL).each(function(){ 19755 var slides = $(this).find(SLIDE_SEL); 19756 19757 if(slides.length){ 19758 slides.each(function(){ 19759 createScrollBar($(this)); 19760 }); 19761 }else{ 19762 createScrollBar($(this)); 19763 } 19764 19765 }); 19766 afterRenderActions(); 19767 } 19768 19769 /*
19770 * Enables the Youtube videos API so we can control their flow if necessary. 19771 */ 19772 function enableYoutubeAPI(){ 19773 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 19774 addURLParam($(this), 'enablejsapi=1'); 19775 }); 19776 } 19777 19778 /** 19779 * Adds a new parameter and its value to the `src` of a given element 19780 */ 19781 function addURLParam(element, newParam){ 19782 var originalSrc = element.attr('src'); 19783 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 19784 } 19785 19786 /* 19787 * Returns the prefix sign to use for a new parameter in an existen URL. 19788 * 19789 * @return {String} ? | & 19790 */ 19791 function getUrlParamSign(url){ 19792 return ( !/\?/.test( url ) ) ? '?' : '&'; 19793 } 19794 19795 /** 19796 * Actions and callbacks to fire afterRender 19797 */ 19798 function afterRenderActions(){ 19799 var section = $(SECTION_ACTIVE_SEL); 19800 19801 section.addClass(COMPLETELY); 19802 19803 if(options.scrollOverflowHandler.afterRender){ 19804 options.scrollOverflowHandler.afterRender(section); 19805 } 19806 lazyLoad(section); 19807 playMedia(section); 19808 options.scrollOverflowHandler.afterLoad(); 19809 19810 if(isDestinyTheStartingSection()){ 19811 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 19812 } 19813 19814 $.isFunction( options.afterRender ) && options.afterRender.call(container); 19815 } 19816 19817 /** 19818 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 19819 */ 19820 function isDestinyTheStartingSection(){ 19821 var anchors = window.location.hash.replace('#', '').split('/'); 19822 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 19823 19824 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 19825 } 19826 19827 19828 var isScrolling = false; 19829 var lastScroll = 0; 19830 19831 //when scrolling... 19832 function scrollHandler(){ 19833 var currentSection; 19834 19835 if(!options.autoScrolling || options.scrollBar){ 19836 var currentScroll = $window.scrollTop(); 19837 var scrollDirection = getScrollDirection(currentScroll); 19838 var visibleSectionIndex = 0; 19839 var screen_mid = currentScroll + ($window.height() / 2.0); 19840 var isAtBottom = $body.height() - $window.height() === currentScroll; 19841 var sections = document.querySelectorAll(SECTION_SEL); 19842 19843 //when using `auto-height` for a small last section it won't be centered in the viewport 19844 if(isAtBottom){ 19845 visibleSectionIndex = sections.length - 1; 19846 } 19847 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 19848 else if(!currentScroll){ 19849 visibleSectionIndex = 0; 19850 } 19851 19852 //taking the section which is showing more content in the viewport 19853 else{ 19854 for (var i = 0; i < sections.length; ++i) { 19855 var section = sections[i]; 19856 19857 // Pick the the last section which passes the middle line of the screen. 19858 if (section.offsetTop <= screen_mid) 19859 { 19860 visibleSectionIndex = i; 19861 } 19862 } 19863 } 19864 19865 if(isCompletelyInViewPort(scrollDirection)){ 19866 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 19867 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 19868 } 19869 } 19870 19871 //geting the last one, the current one on the screen 19872 currentSection = $(sections).eq(visibleSectionIndex); 19873 19874 //setting the visible section as active when manually scrolling 19875 //executing only once the first time we reach the section 19876 if(!currentSection.hasClass(ACTIVE)){ 19877 isScrolling = true; 19878 var leavingSection = $(SECTION_ACTIVE_SEL); 19879 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 19880 var yMovement = getYmovement(currentSection); 19881 var anchorLink = currentSection.data('anchor'); 19882 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 19883 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 19884 var slideIndex; 19885 var slideAnchorLink; 19886 19887 if(activeSlide.length){ 19888 slideAnchorLink = activeSlide.data('anchor'); 19889 slideIndex = activeSlide.index(); 19890 } 19891 19892 if(canScroll){ 19893 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 19894 19895 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 19896 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 19897 19898 stopMedia(leavingSection); 19899 lazyLoad(currentSection); 19900 playMedia(currentSection); 19901 19902 activateMenuAndNav(anchorLink, sectionIndex - 1); 19903 19904 if(options.anchors.length){ 19905 //needed to enter in hashChange event when using the menu with anchor links 19906 lastScrolledDestiny = anchorLink; 19907 } 19908 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 19909 } 19910 19911 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 19912 clearTimeout(scrollId); 19913 scrollId = setTimeout(function(){ 19914 isScrolling = false; 19915 }, 100); 19916 } 19917 19918 if(options.fitToSection){ 19919 //for the auto adjust of the viewport to fit a whole section 19920 clearTimeout(scrollId2); 19921 19922 scrollId2 = setTimeout(function(){ 19923 //checking it again in case it changed during the delay 19924 if(options.fitToSection){ 19925 fitToSection(); 19926 } 19927 }, options.fitToSectionDelay); 19928 } 19929 } 19930 } 19931 19932 /** 19933 * Fits the site to the nearest active section 19934 */ 19935 function fitToSection(){ 19936 //checking fitToSection again in case it was set to false before the timeout delay 19937 if(canScroll){ 19938 //allows to scroll to an active section and 19939 //if the section is already active, we prevent firing callbacks 19940 isResizing = true; 19941 19942 scrollPage($(SECTION_ACTIVE_SEL)); 19943 isResizing = false; 19944 } 19945 } 19946 19947 /** 19948 * Determines whether the active section has seen in its whole or not. 19949 */ 19950 function isCompletelyInViewPort(movement){ 19951 var top = $(SECTION_ACTIVE_SEL).position().top; 19952 var bottom = top + $window.height(); 19953 19954 if(movement == 'up'){ 19955 return bottom >= ($window.scrollTop() + $window.height()); 19956 } 19957 return top <= $window.scrollTop(); 19958 } 19959 19960 /** 19961 * Gets the directon of the the scrolling fired by the scroll event. 19962 */ 19963 function getScrollDirection(currentScroll){ 19964 var direction = currentScroll > lastScroll ? 'down' : 'up'; 19965 19966 lastScroll = currentScroll; 19967 19968 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 19969 previousDestTop = currentScroll; 19970 19971 return direction; 19972 } 19973 19974 /** 19975 * Determines the way of scrolling up or down: 19976 * by 'automatically' scrolling a section or by using the default and n
19976ormal scrolling. 19977 */ 19978 function scrolling(type, scrollable){ 19979 if (!isScrollAllowed.m[type]){ 19980 return; 19981 } 19982 var check = (type === 'down') ? 'bottom' : 'top'; 19983 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 19984 19985 if(scrollable.length > 0 ){ 19986 //is the scrollbar at the start/end of the scroll? 19987 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 19988 scrollSection(); 19989 }else{ 19990 return true; 19991 } 19992 }else{ 19993 // moved up/down 19994 scrollSection(); 19995 } 19996 } 19997 19998 /* 19999 * Preventing bouncing in iOS #2285 20000 */ 20001 function preventBouncing(event){ 20002 var e = event.originalEvent; 20003 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e)){ 20004 //preventing the easing on iOS devices 20005 event.preventDefault(); 20006 } 20007 } 20008 20009 var touchStartY = 0; 20010 var touchStartX = 0; 20011 var touchEndY = 0; 20012 var touchEndX = 0; 20013 20014 /* Detecting touch events 20015 20016 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 20017 * This way, the touchstart and the touch moves shows an small difference between them which is the 20018 * used one to determine the direction. 20019 */ 20020 function touchMoveHandler(event){ 20021 var e = event.originalEvent; 20022 var activeSection = $(e.target).closest(SECTION_SEL); 20023 20024 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 20025 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 20026 20027 if(options.autoScrolling){ 20028 //preventing the easing on iOS devices 20029 event.preventDefault(); 20030 } 20031 20032 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20033 var touchEvents = getEventsPage(e); 20034 20035 touchEndY = touchEvents.y; 20036 touchEndX = touchEvents.x; 20037 20038 //if movement in the X axys is greater than in the Y and the currect section has slides... 20039 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 20040 20041 //is the movement greater than the minimum resistance to scroll? 20042 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 20043 if (touchStartX > touchEndX) { 20044 if(isScrollAllowed.m.right){ 20045 moveSlideRight(activeSection); //next 20046 } 20047 } else { 20048 if(isScrollAllowed.m.left){ 20049 moveSlideLeft(activeSection); //prev 20050 } 20051 } 20052 } 20053 } 20054 20055 //vertical scrolling (only when autoScrolling is enabled) 20056 else if(options.autoScrolling && canScroll){ 20057 20058 //is the movement greater than the minimum resistance to scroll? 20059 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 20060 if (touchStartY > touchEndY) { 20061 scrolling('down', scrollable); 20062 } else if (touchEndY > touchStartY) { 20063 scrolling('up', scrollable); 20064 } 20065 } 20066 } 20067 } 20068 } 20069 20070 /** 20071 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 20072 * Currently works well for iOS - Android might need some testing 20073 * @param {Element} el target element / jquery selector (in subsequent nodes) 20074 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 20075 * @return {boolean} true if there is a match to options.normalScrollElements 20076 */ 20077 function checkParentForNormalScrollElement (el, hop) { 20078 hop = hop || 0; 20079 var parent = $(el).parent(); 20080 20081 if (hop < options.normalScrollElementTouchThreshold && 20082 parent.is(options.normalScrollElements) ) { 20083 return true; 20084 } else if (hop == options.normalScrollElementTouchThreshold) { 20085 return false; 20086 } else { 20087 return checkParentForNormalScrollElement(parent, ++hop); 20088 } 20089 } 20090 20091 /** 20092 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 20093 * this way we make sure that is really a touch event what IE is detecting. 20094 */ 20095 function isReallyTouch(e){ 20096 //if is not IE || IE is detecting `touch` or `pen` 20097 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 20098 } 20099 20100 /** 20101 * Handler for the touch start event. 20102 */ 20103 function touchStartHandler(event){ 20104 var e = event.originalEvent; 20105 20106 //stopping the auto scroll to adjust to a section 20107 if(options.fitToSection){ 20108 $htmlBody.stop(); 20109 } 20110 20111 if(isReallyTouch(e)){ 20112 var touchEvents = getEventsPage(e); 20113 touchStartY = touchEvents.y; 20114 touchStartX = touchEvents.x; 20115 } 20116 } 20117 20118 /** 20119 * Gets the average of the last `number` elements of the given array. 20120 */ 20121 function getAverage(elements, number){
20122 var sum = 0; 20123 20124 //taking `number` elements from the end to make the average, if there are not enought, 1 20125 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 20126 20127 for(var i = 0; i < lastElements.length; i++){ 20128 sum = sum + lastElements[i]; 20129 } 20130 20131 return Math.ceil(sum/number); 20132 } 20133 20134 /** 20135 * Detecting mousewheel scrolling 20136 * 20137 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 20138 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 20139 */ 20140 var prevTime = new Date().getTime(); 20141 20142 function MouseWheelHandler(e) { 20143 var curTime = new Date().getTime(); 20144 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 20145 20146 //autoscrolling and not zooming? 20147 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 20148 // cross-browser wheel delta 20149 e = e || window.event; 20150 var value = e.wheelDelta || -e.deltaY || -e.detail; 20151 var delta = Math.max(-1, Math.min(1, value)); 20152 20153 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 20154 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 20155 20156 //Limiting the array to 150 (lets not waste memory!) 20157 if(scrollings.length > 149){ 20158 scrollings.shift(); 20159 } 20160 20161 //keeping record of the previous scrollings 20162 scrollings.push(Math.abs(value)); 20163 20164 //preventing to scroll the site on mouse wheel when scrollbar is present 20165 if(options.scrollBar){ 20166 e.preventDefault ? e.preventDefault() : e.returnValue = false; 20167 } 20168 20169 var activeSection = $(SECTION_ACTIVE_SEL); 20170 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20171 20172 //time difference between the last scroll and the current one 20173 var timeDiff = curTime-prevTime; 20174 prevTime = curTime; 20175 20176 //haven't they scrolled in a while? 20177 //(enough to be consider a different scrolling action to scroll another section) 20178 if(timeDiff > 200){ 20179 //emptying the array, we dont care about old scrollings for our averages 20180 scrollings = []; 20181 } 20182 20183 if(canScroll){ 20184 var averageEnd = getAverage(scrollings, 10); 20185 var averageMiddle = getAverage(scrollings, 70); 20186 var isAccelerating = averageEnd >= averageMiddle; 20187 20188 //to avoid double swipes... 20189 if(isAccelerating && isScrollingVertically){ 20190 //scrolling down? 20191 if (delta < 0) { 20192 scrolling('down', scrollable); 20193 20194 //scrolling up? 20195 }else { 20196 scrolling('up', scrollable); 20197 } 20198 } 20199 } 20200 20201 return false; 20202 } 20203 20204 if(options.fitToSection){ 20205 //stopping the auto scroll to adjust to a section 20206 $htmlBody.stop(); 20207 } 20208 } 20209 20210 /** 20211 * Slides a slider to the given direction. 20212 * Optional `section` param. 20213 */ 20214 function moveSlide(direction, section){ 20215 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 20216 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 20217 var numSlides = slides.find(SLIDE_SEL).length; 20218 20219 // more than one slide needed and nothing should be sliding 20220 if (!slides.length || slideMoving || numSlides < 2) { 20221 return; 20222 } 20223 20224 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 20225 var destiny = null; 20226 20227 if(direction === 'left'){ 20228 destiny = currentSlide.prev(SLIDE_SEL); 20229 }else{ 20230 destiny = currentSlide.next(SLIDE_SEL); 20231 } 20232 20233 //isn't there a next slide in the secuence? 20234 if(!destiny.length){ 20235 //respect loopHorizontal settin 20236 if (!options.loopHorizontal) return; 20237 20238 if(direction === 'left'){ 20239 destiny = currentSlide.siblings(':last'); 20240 }else{ 20241 destiny = currentSlide.siblings(':first'); 20242 } 20243 } 20244 20245 slideMoving = true; 20246
20247 landscapeScroll(slides, destiny, direction); 20248 } 20249 20250 /** 20251 * Maintains the active slides in the viewport 20252 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 20253 */ 20254 function keepSlidesPosition(){ 20255 $(SLIDE_ACTIVE_SEL).each(function(){ 20256 silentLandscapeScroll($(this), 'internal'); 20257 }); 20258 } 20259 20260 var previousDestTop = 0; 20261 /** 20262 * Returns the destination Y position based on the scrolling direction and 20263 * the height of the section. 20264 */ 20265 function getDestinationPosition(element){ 20266 var elemPosition = element.position(); 20267 20268 //top of the desination will be at the top of the viewport 20269 var position = elemPosition.top; 20270 var isScrollingDown = elemPosition.top > previousDestTop; 20271 var sectionBottom = position - windowsHeight + element.outerHeight(); 20272 var bigSectionsDestination = options.bigSectionsDestination; 20273 20274 //Uncode addition 20275 var containerH = container.outerHeight(); 20276 var containerPosition = container.offset(); 20277 20278 //########### Commented by Uncode - START ########### 20279 //is the destination element bigger than the viewport? 20280 // if(element.outerHeight() > windowsHeight){ 20281 // //scrolling up? 20282 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 20283 // position = sectionBottom; 20284 // } 20285 // } 20286 20287 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 20288 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 20289 // //The bottom of the destination will be at the bottom of the viewport 20290 // position = sectionBottom; 20291 // } 20292 //########### Commented by Uncode - END ########### 20293 20294 //Uncode addition 20295 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 20296 position += 18; 20297 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 20298 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 20299 } 20300 20301 /* 20302 Keeping record of the last scrolled position to determine the scrolling direction. 20303 No conventional methods can be used as the scroll bar might not be present 20304 AND the section might not be active if it is auto-height and didnt reach the middle 20305 of the viewport. 20306 */ 20307 previousDestTop = position; 20308 return position; 20309 } 20310 20311 /** 20312 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 20313 */ 20314 function scrollPage(element, callback, isMovementUp){ 20315 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 20316 20317 var dtop = getDestinationPosition(element); 20318 var slideAnchorLink; 20319 var slideIndex; 20320 20321 //local variables 20322 var v = { 20323 element: element, 20324 callback: callback, 20325 isMovementUp: isMovementUp, 20326 dtop: dtop, 20327 yMovement: getYmovement(element), 20328 anchorLink: element.data('anchor'), 20329 sectionIndex: element.index(SECTION_SEL), 20330 activeSlide: element.find(SLIDE_ACTIVE_SEL), 20331 activeSection: $(SECTION_ACTIVE_SEL), 20332 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 20333 20334 //caching the value of isResizing at the momment the function is called 20335 //because it will be checked later inside a setTimeout and the value might change 20336 localIsResizing: isResizing 20337 }; 20338 20339 //quiting when destination scroll is the same as the current one 20340 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 20341 20342 if(v.activeSlide.length){ 20343 slideAnchorLink = v.activeSlide.data('anchor'); 20344 slideIndex = v.activeSlide.index(); 20345 } 20346 20347 // If continuousVertical && we need to wrap around 20348 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 20349 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 20350 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 20351 20352 v = createInfiniteSections(v); 20353 } 20354 20355 //callback (onLeave) if the site is not just resizing and readjusting the slides 20356 if($.isFunction(options.onLeave) && !v.localIsResizing){ 20357 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 20358 return; 20359 } 20360 } 20361 20362 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 20363 if(!v.localIsResizing){ 20364 stopMedia(v.activeSection); 20365 } 20366 20367 options.scrollOverflowHandler.beforeLeave(); 20368 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20369 lazyLoad(element); 20370 options.scrollOverflowHandler.onLeave(); 20371 20372 20373 //preventing from activating the MouseWheelHandler event 20374 //more than once if the page is scrolling 20375 canScroll = false; 20376 20377 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 20378 20379 performMovement(v); 20380 20381 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 20382 lastScrolledDestiny = v.anchorLink; 20383 20384 //avoid firing it twice (as it does also on scroll) 20385 activateMenuAndNav(v.anchorLink, v.sectionIndex); 20386 } 20387 20388 /** 20389 * Performs the vertical movement (by CSS3 or by jQuery) 20390 */ 20391 function performMovement(v){ 20392 // using CSS3 translate functionality 20393 if (options.css3 && options.autoScrolling && !options.scrollBar) { 20394 20395 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 20396 // that's why we round it to 0. 20397 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 20398 transformContainer(translate3d, true); 20399 20400 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 20401 //scrollingSpeed to change in case of using silentMoveTo(); 20402 if(options.scrollingSpeed){ 20403 clearTimeout(afterSectionLoadsId); 20404 afterSectionLoadsId = setTimeout(function () { 20405 afterSectionLoads(v); 20406 }, options.scrollingSpeed); 20407 }else{ 20408 afterSectionLoads(v); 20409 } 20410 } 20411 20412 // using jQuery animate 20413 else{ 20414 var scrollSettings = getScrollSettings(v); 20415 20416 $(scrollSettings.element).animate( 20417 scrollSettings.options, 20418 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 20419 if(options.scrollBar){ 20420 20421 /* Hack! 20422 The timeout prevents setting the most dominant section in the viewport as "active" when the user 20423 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 20424 20425 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 20426 */ 20427 setTimeout(function(){ 20428 afterSectionLoads(v); 20429 },30); 20430 }else{ 20431 afterSectionLoads(v); 20432 } 20433 }); 20434 } 20435 } 20436 20437 /** 20438 * Gets the scrolling settings depending on the plugin autoScrolling option 20439 */ 20440 function getScrollSettings(v){ 20441 var scroll = {}; 20442 20443 if(options.autoScrolling && !options.scrollBar){ 20444 scroll.options = { 'top': -v.dtop}; 20445 scroll.element = WRAPPER_SEL; 20446 }else{ 20447 scroll.options = { 'scrollTop': v.dtop}; 20448 scroll.element = 'html, body'; 20449 } 20450 20451 return scroll; 20452 } 20453 20454 /** 20455 * Adds sections before or after the current one to create the infinite effect. 20456 */ 20457 function createInfiniteSections(v){ 20458 // Scrolling down 20459 if (!v.isMovementUp) { 20460 // Move all previous sections to after the active section 20461 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 20462 } 20463 else { // Scrolling up 20464 // Move all next sections to before the active section 20465 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 20466 } 20467 20468 // Maintain the displayed position (now that we changed the element order) 20469 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20470 20471 // Maintain the active slides visible in the viewport 20472 keepSlidesPosition(); 20473 20474 // save for later the elements that still need to be reordered 20475 v.wrapAroundElements = v.activeSection; 20476 20477 // Recalculate animation variables 20478 v.dtop = v.element.position().top; 20479 v.yMovement = getYmovement(v.element); 20480 20481 return v; 20482 } 20483 20484 /** 20485 * Fix section order after continuousVertical changes have been animated 20486 */ 20487 function continuousVerticalFixSectionOrder (v) {
20488 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 20489 // finish moving the elements around so the direct navigation will function more simply 20490 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 20491 return; 20492 } 20493 20494 if (v.isMovementUp) { 20495 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 20496 } 20497 else { 20498 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 20499 } 20500 20501 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20502 20503 // Maintain the active slides visible in the viewport 20504 keepSlidesPosition(); 20505 } 20506 20507 20508 /** 20509 * Actions to do once the section is loaded. 20510 */ 20511 function afterSectionLoads (v){ 20512 continuousVerticalFixSectionOrder(v); 20513 20514 //callback (afterLoad) if the site is not just resizing and readjusting the slides 20515 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 20516 options.scrollOverflowHandler.afterLoad(); 20517 20518 if(!v.localIsResizing){ 20519 playMedia(v.element); 20520 } 20521 20522 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 20523 20524 canScroll = true; 20525 20526 $.isFunction(v.callback) && v.callback.call(this); 20527 } 20528 20529 /** 20530 * Sets the value for the given attribute from the `data-` attribute with the same suffix 20531 * ie: data-srcset ==> srcset | data-src ==> src 20532 */ 20533 function setSrc(element, attribute){ 20534 element 20535 .attr(attribute, element.data(attribute)) 20536 .removeAttr('data-' + attribute); 20537 } 20538 20539 /** 20540 * Lazy loads image, video and audio elements. 20541 */ 20542 function lazyLoad(destiny){ 20543 if (!options.lazyLoading){ 20544 return; 20545 } 20546 20547 var panel = getSlideOrSection(destiny); 20548 var element; 20549 20550 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 20551 element = $(this); 20552 20553 $.each(['src', 'srcset'], function(index, type){ 20554 var attribute = element.attr('data-' + type); 20555 if(typeof attribute !== 'undefined' && attribute){ 20556 setSrc(element, type); 20557 } 20558 }); 20559 20560 if(element.is('source')){ 20561 element.closest('video').get(0).load(); 20562 } 20563 }); 20564 } 20565 20566 /** 20567 * Plays video and audio elements. 20568 */ 20569 function playMedia(destiny){ 20570 var panel = getSlideOrSection(destiny); 20571 20572 //playing HTML5 media elements 20573 panel.find('video, audio').each(function(){ 20574 var element = $(this).get(0); 20575 20576 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 20577 element.play(); 20578 } 20579 }); 20580 20581 //youtube videos 20582 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20583 var element = $(this).get(0); 20584 20585 if ( element.hasAttribute('data-autoplay') ){ 20586 playYoutube(element); 20587 } 20588 20589 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 20590 element.onload = function() { 20591 if ( element.hasAttribute('data-autoplay') ){ 20592 playYoutube(element); 20593 } 20594 }; 20595 }); 20596 } 20597 20598 /** 20599 * Plays a youtube video 20600 */ 20601 function playYoutube(element){ 20602 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 20603 } 20604 20605 /** 20606 * Stops video and audio elements. 20607 */ 20608 function stopMedia(destiny){ 20609 var panel = getSlideOrSection(destiny); 20610 20611 //stopping HTML5 media elements 20612 panel.find('video, audio').each(function(){ 20613 var element = $(this).get(0); 20614 20615 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 20616 element.pause(); 20617 } 20618 }); 20619 20620 //youtube videos 20621 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20622 var element = $(this).get(0); 20623 20624 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 20625 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 20626 } 20627 }); 20628 } 20629 20630 /** 20631 * Gets the active slide (or section) for the given section 20632 */ 20633 function getSlideOrSection(destiny){ 20634 var slide = destiny.find(SLIDE_ACTIVE_SEL); 20635 if( slide.length ) { 20636 destiny = $(slide); 20637 } 20638 20639 return destiny; 20640 } 20641 20642 /**
20643 * Scrolls to the anchor in the URL when loading the site 20644 */ 20645 function scrollToAnchor(){ 20646 //getting the anchor link in the URL and deleting the `#` 20647 var value = window.location.hash.replace('#', '').split('/'); 20648 var sectionAnchor = decodeURIComponent(value[0]); 20649 var slideAnchor = decodeURIComponent(value[1]); 20650 20651 if(sectionAnchor){ //if theres any # 20652 if(options.animateAnchor){ 20653 scrollPageAndSlide(sectionAnchor, slideAnchor); 20654 }else{ 20655 silentMoveTo(sectionAnchor, slideAnchor); 20656 } 20657 } 20658 } 20659 20660 /** 20661 * Detecting any change on the URL to scroll to the given anchor link 20662 * (a way to detect back history button as we play with the hashes on the URL) 20663 */ 20664 function hashChangeHandler(){ 20665 if(!isScrolling && !options.lockAnchors){ 20666 var value = window.location.hash.replace('#', '').split('/'); 20667 var sectionAnchor = decodeURIComponent(value[0]); 20668 var slideAnchor = decodeURIComponent(value[1]); 20669 20670 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 20671 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 20672 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 20673 20674 20675 if(sectionAnchor.length){ 20676 /*in order to call scrollpage() only once for each destination at a time 20677 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 20678 event is fired on every scroll too.*/ 20679 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 20680 scrollPageAndSlide(sectionAnchor, slideAnchor); 20681 } 20682 } 20683 } 20684 } 20685 20686 //Sliding with arrow keys, both, vertical and horizontal 20687 function keydownHandler(e) { 20688 20689 clearTimeout(keydownId); 20690 20691 var activeElement = $(':focus'); 20692 20693 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 20694 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 20695 options.keyboardScrolling && options.autoScrolling){ 20696 var keyCode = e.which; 20697 20698 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 20699 var keyControls = [40, 38, 32, 33, 34]; 20700 if($.inArray(keyCode, keyControls) > -1){ 20701 e.preventDefault(); 20702 } 20703 20704 controlPressed = e.ctrlKey; 20705 20706 keydownId = setTimeout(function(){ 20707 onkeydown(e); 20708 },150); 20709 } 20710 } 20711 20712 function tooltipTextHandler(){ 20713 $(this).prev().trigger('click'); 20714 } 20715 20716 //to prevent scrolling while zooming 20717 function keyUpHandler(e){ 20718 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 20719 controlPressed = e.ctrlKey; 20720 } 20721 } 20722 20723 //binding the mousemove when the mouse's middle button is released 20724 function mouseDownHandler(e){ 20725 //middle button 20726 if (e.which == 2){ 20727 oldPageY = e.pageY; 20728 container.on('mousemove', mouseMoveHandler); 20729 } 20730 } 20731 20732 //unbinding the mousemove when the mouse's middle button is released 20733 function mouseUpHandler(e){ 20734 //middle button 20735 if (e.which == 2){ 20736 container.off('mousemove'); 20737 } 20738 } 20739 20740 //Scrolling horizontally when clicking on the slider controls. 20741 function slideArrowHandler(){ 20742 var section = $(this).closest(SECTION_SEL); 20743 20744 if ($(this).hasClass(SLIDES_PREV)) { 20745 if(isScrollAllowed.m.left){ 20746 moveSlideLeft(section); 20747 } 20748 } else { 20749 if(isScrollAllowed.m.right){ 20750 moveSlideRight(section); 20751 } 20752 } 20753 } 20754 20755 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 20756 function blurHandler(){ 20757 isWindowFocused = false; 20758 controlPressed = false; 20759 } 20760 20761 //Scrolls to the section when clicking the navigation bullet 20762 function sectionBulletHandler(e){ 20763 e.preventDefault(); 20764 var index = $(this).parent().index(); 20765 scrollPage($(SECTION_SEL).eq(index)); 20766 } 20767 20768 //Scrolls the slider to the given slide destination for the given section 20769 function slideBulletHandler(e){ 20770 e.preventDefault(); 20771 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 20772 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 20773
20774 landscapeScroll(slides, destiny); 20775 } 20776 20777 /** 20778 * Keydown event 20779 */ 20780 function onkeydown(e){ 20781 var shiftPressed = e.shiftKey; 20782 20783 //do nothing if we can not scroll or we are not using horizotnal key arrows. 20784 if(!canScroll && [37,39].indexOf(e.which) < 0){ 20785 return; 20786 } 20787 20788 switch (e.which) { 20789 //up 20790 case 38: 20791 case 33: 20792 if(isScrollAllowed.k.up){ 20793 moveSectionUp(); 20794 } 20795 break; 20796 20797 //down 20798 case 32: //spacebar 20799 if(shiftPressed && isScrollAllowed.k.up){ 20800 moveSectionUp(); 20801 break; 20802 } 20803 /* falls through */ 20804 case 40: 20805 case 34: 20806 if(isScrollAllowed.k.down){ 20807 moveSectionDown(); 20808 } 20809 break; 20810 20811 //Home 20812 case 36: 20813 if(isScrollAllowed.k.up){ 20814 moveTo(1); 20815 } 20816 break; 20817 20818 //End 20819 case 35: 20820 if(isScrollAllowed.k.down){ 20821 moveTo( $(SECTION_SEL).length ); 20822 } 20823 break; 20824 20825 //left 20826 case 37: 20827 if(isScrollAllowed.k.left){ 20828 moveSlideLeft(); 20829 } 20830 break; 20831 20832 //right 20833 case 39: 20834 if(isScrollAllowed.k.right){ 20835 moveSlideRight(); 20836 } 20837 break; 20838 20839 default: 20840 return; // exit this handler for other keys 20841 } 20842 } 20843 20844 /** 20845 * Detecting the direction of the mouse movement. 20846 * Used only for the middle button of the mouse. 20847 */ 20848 var oldPageY = 0; 20849 function mouseMoveHandler(e){ 20850 if(canScroll){ 20851 // moving up 20852 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 20853 moveSectionUp(); 20854 } 20855 20856 // moving down 20857 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 20858 moveSectionDown(); 20859 } 20860 } 20861 oldPageY = e.pageY; 20862 } 20863 20864 /** 20865 * Scrolls horizontal sliders. 20866 */ 20867 function landscapeScroll(slides, destiny, direction){ 20868 var section = slides.closest(SECTION_SEL); 20869 var v = { 20870 slides: slides, 20871 destiny: destiny, 20872 direction: direction, 20873 destinyPos: destiny.position(), 20874 slideIndex: destiny.index(), 20875 section: section, 20876 sectionIndex: section.index(SECTION_SEL), 20877 anchorLink: section.data('anchor'), 20878 slidesNav: section.find(SLIDES_NAV_SEL), 20879 slideAnchor: getAnchor(destiny), 20880 prevSlide: section.find(SLIDE_ACTIVE_SEL), 20881 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 20882 20883 //caching the value of isResizing at the momment the function is called 20884 //because it will be checked later inside a setTimeout and the value might change 20885 localIsResizing: isResizing 20886 }; 20887 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 20888 20889 //important!! Only do it when not resizing 20890 if(!v.localIsResizing){ 20891 //preventing from scrolling to the next/prev section when using scrollHorizontally 20892 canScroll = false; 20893 } 20894 20895 if(options.onSlideLeave){ 20896 20897 //if the site is not just resizing and readjusting the slides 20898 if(!v.localIsResizing && v.xMovement!=='none'){ 20899 if($.isFunction( options.onSlideLeave )){ 20900 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 20901 slideMoving = false; 20902 return; 20903 } 20904 } 20905 } 20906 } 20907 20908 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20909 20910 if(!v.localIsResizing){ 20911 stopMedia(v.prevSlide); 20912 lazyLoad(destiny); 20913 } 20914 20915 if(!options.loopHorizontal && options.controlArrows){ 20916 //hidding it for the fist slide, showing for the rest 20917 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 20918 20919 //hidding it for the last slide, showing for the rest 20920 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 20921 } 20922 20923 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 20924 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 20925 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 20926 } 20927 20928 performHorizontalMove(slides, v, true); 20929 } 20930 20931 20932 function afterSlideLoads(v){ 20933 activeSlidesNavigation(v.slidesNav, v.slideIndex); 20934 20935 //if the site is not just resizing and readjusting the slides 20936 if(!v.localIsResizing){ 20937 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 20938 20939 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 20940 //and to prevent double scroll right after a windows resize 20941 canScroll = true; 20942 20943 playMedia(v.destiny); 20944 } 20945 20946 //letting them slide again 20947 slideMoving = false; 20948 } 20949 20950 /** 20951 * Performs the horizontal movement. (CSS3 or jQuery) 20952 * 20953 * @param fireCallback {Bool} - determines whether or not to fire the callback 20954 */ 20955 function performHorizontalMove(slides, v, fireCallback){ 20956 var destinyPos = v.destinyPos; 20957 20958 if(options.css3){ 20959 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 20960 20961 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 20962 20963 afterSlideLoadsId = setTimeout(function(){ 20964 fireCallback && afterSlideLoads(v); 20965 }, options.scrollingSpeed, options.easing); 20966 }else{ 20967 slides.animate({ 20968 scrollLeft : Math.round(destinyPos.left) 20969 }, options.scrollingSpeed, options.easing, function() { 20970 20971 fireCallback && afterSlideLoads(v); 20972 }); 20973 } 20974 } 20975 20976 /** 20977 * Sets the state for the horizontal bullet navigations. 20978 */ 20979 function activeSlidesNavigation(slidesNav, slideIndex){ 20980 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 20981 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 20982 } 20983 20984 var previousHeight = windowsHeight; 20985 20986 //when resizing the site, we adjust the heights of the sections, slimScroll... 20987 function resizeHandler(){ 20988 //checking if it needs to get responsive 20989 responsive(); 20990 20991 // rebuild immediately on touch devices 20992 if (isTouchDevice) { 20993 var activeElement = $(document.activeElement); 20994 20995 //if the keyboard is NOT visible 20996 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 20997 var currentHeight = $window.height(); 20998 20999 //making sure the change in the viewport size is enough to force a rebuild. (20 % of the window to avoid problems when hidding scroll bars) 21000 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 21001 reBuild(true); 21002 previousHeight = currentHeight; 21003 } 21004 } 21005 }else{ 21006 //in order to call the functions only when the resize is finished 21007 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 21008 clearTimeout(resizeId); 21009 21010 resizeId = setTimeout(function(){ 21011 reBuild(true); 21012 }, 350); 21013 } 21014 } 21015 21016 /** 21017 * Checks if the site needs to get responsive and disables autoScrolling if so. 21018 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 21019 */ 21020 function responsive(){ 21021 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 21022 var heightLimit = options.responsiveHeight; 21023 21024 //only calculating what we need. Remember its called on the resize event. 21025 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 21026 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 21027 21028 if(widthLimit && heightLimit){ 21029 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 21030 } 21031 else if(widthLimit){ 21032 setResponsive(isBreakingPointWidth);
21033 } 21034 else if(heightLimit){ 21035 setResponsive(isBreakingPointHeight); 21036 } 21037 } 21038 21039 /** 21040 * Adds transition animations for the given element 21041 */ 21042 function addAnimation(container, element){ 21043 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 21044 21045 container.removeClass(NO_TRANSITION); 21046 return container.css({ 21047 '-webkit-transition': transition, 21048 'transition': transition 21049 }); 21050 } 21051 21052 /** 21053 * Remove transition animations for the given element 21054 */ 21055 function removeAnimation(element){ 21056 return element.addClass(NO_TRANSITION); 21057 } 21058 21059 /** 21060 * Activating the vertical navigation bullets according to the given slide name. 21061 */ 21062 function activateNavDots(name, sectionIndex){ 21063 if(options.navigation){ 21064 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 21065 if(name){ 21066 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 21067 }else{ 21068 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 21069 } 21070 } 21071 } 21072 21073 /** 21074 * Activating the website main menu elements according to the given slide name. 21075 */ 21076 function activateMenuElement(name){ 21077 if(options.menu){ 21078 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 21079 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 21080 } 21081 } 21082 21083 /** 21084 * Sets to active the current menu and vertical nav items. 21085 */ 21086 function activateMenuAndNav(anchor, index){ 21087 activateMenuElement(anchor); 21088 activateNavDots(anchor, index); 21089 } 21090 21091 /** 21092 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 21093 * from the current section. 21094 */ 21095 function getYmovement(destiny){ 21096 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 21097 var toIndex = destiny.index(SECTION_SEL); 21098 if( fromIndex == toIndex){ 21099 return 'none'; 21100 } 21101 if(fromIndex > toIndex){ 21102 return 'up'; 21103 } 21104 return 'down'; 21105 } 21106 21107 /** 21108 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 21109 * from the current slide. 21110 */ 21111 function getXmovement(fromIndex, toIndex){ 21112 if( fromIndex == toIndex){ 21113 return 'none'; 21114 } 21115 if(fromIndex > toIndex){ 21116 return 'left'; 21117 } 21118 return 'right'; 21119 } 21120 21121 /** 21122 * Checks if the element needs scrollbar and if the user wants to apply it. 21123 * If so it creates it. 21124 * 21125 * @param {Object} element jQuery object of the section or slide 21126 */ 21127 function createScrollBar(element){ 21128 //User doesn't want scrollbar here? Sayonara baby! 21129 if(element.hasClass('fp-noscroll')) return; 21130 21131 //needed to make `scrollHeight` work under Opera 12 21132 element.css('overflow', 'hidden'); 21133 21134 var scrollOverflowHandler = options.scrollOverflowHandler; 21135 var wrap = scrollOverflowHandler.wrapContent(); 21136 //in case element is a slide 21137 var section = element.closest(SECTION_SEL); 21138 var scrollable = scrollOverflowHandler.scrollable(element); 21139 var contentHeight; 21140 21141 //if there was scroll, the contentHeight will be the one in the scrollable section 21142 if(scrollable.length){ 21143 contentHeight = scrollOverflowHandler.scrollHeight(element); 21144 }else{ 21145 contentHeight = element.get(0).scrollHeight; 21146 if(options.verticalCentered){ 21147 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 21148 } 21149 } 21150 21151 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 21152 //Uncode addition
21153 scrollHeight -= UNCODE.bodyBorder*2 + UNCODE.adminBarHeight; 21154 21155 //needs scroll? 21156 if ( contentHeight > scrollHeight) { 21157 //did we already have an scrollbar ? Updating it 21158 if(scrollable.length){ 21159 scrollOverflowHandler.update(element, scrollHeight); 21160 } 21161 //creating the scrolling 21162 else{ 21163 if(options.verticalCentered){ 21164 element.find(TABLE_CELL_SEL).wrapInner(wrap); 21165 }else{ 21166 element.wrapInner(wrap); 21167 } 21168 scrollOverflowHandler.create(element, scrollHeight); 21169 } 21170 } 21171 //removing the scrolling when it is not necessary anymore 21172 else{ 21173 scrollOverflowHandler.remove(element); 21174 } 21175 21176 //undo 21177 element.css('overflow', ''); 21178 } 21179 21180 function addTableClass(element){ 21181 //In case we are styling for the 2nd time as in with reponsiveSlides 21182 if(!element.hasClass(TABLE)){ 21183 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 21184 } 21185 } 21186 21187 function getTableHeight(element){ 21188 var sectionHeight = windowsHeight; 21189 21190 if(options.paddingTop || options.paddingBottom){ 21191 var section = element; 21192 if(!section.hasClass(SECTION)){ 21193 section = element.closest(SECTION_SEL); 21194 } 21195 21196 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 21197 sectionHeight = (windowsHeight - paddings); 21198 } 21199 21200 return sectionHeight; 21201 } 21202 21203 /** 21204 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 21205 */ 21206 function transformContainer(translate3d, animated){ 21207 if(animated){ 21208 addAnimation(container); 21209 }else{ 21210 removeAnimation(container); 21211 } 21212 21213 container.css(getTransforms(translate3d)); 21214 21215 //syncronously removing the class after the animation has been applied. 21216 setTimeout(function(){ 21217 container.removeClass(NO_TRANSITION); 21218 },10); 21219 } 21220 21221 /** 21222 * Gets a section by its anchor / index 21223 */ 21224 function getSectionByAnchor(sectionAnchor){ 21225 if(!sectionAnchor) return []; 21226 21227 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 21228 if(!section.length){ 21229 section = $(SECTION_SEL).eq( sectionAnchor -1); 21230 } 21231 21232 return section; 21233 } 21234 21235 /** 21236 * Gets a slide inside a given section by its anchor / index 21237 */ 21238 function getSlideByAnchor(slideAnchor, section){ 21239 var slides = section.find(SLIDES_WRAPPER_SEL); 21240 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 21241 21242 if(!slide.length){ 21243 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 21244 } 21245 21246 return slide; 21247 } 21248 21249 /** 21250 * Scrolls to the given section and slide anchors 21251 */ 21252 function scrollPageAndSlide(destiny, slide){ 21253 var section = getSectionByAnchor(destiny); 21254 21255 //do nothing if there's no section with the given anchor name 21256 if(!section.length) return; 21257 21258 //default slide 21259 if (typeof slide === 'undefined') { 21260 slide = 0; 21261 } 21262 21263 //we need to scroll to the section and then to the slide 21264 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 21265 scrollPage(section, function(){ 21266 scrollSlider(section, slide); 21267 }); 21268 } 21269 //if we were already in the section 21270 else{ 21271 scrollSlider(section, slide); 21272 } 21273 } 21274 21275 /** 21276 * Scrolls the slider to the given slide destination for the given section 21277 */ 21278 function scrollSlider(section, slideAnchor){ 21279 if(typeof slideAnchor !== 'undefined'){ 21280 var slides = section.find(SLIDES_WRAPPER_SEL); 21281 var destiny = getSlideByAnchor(slideAnchor, section); 21282 21283 if(destiny.length){
21284 landscapeScroll(slides, destiny); 21285 } 21286 } 21287 } 21288 21289 /** 21290 * Creates a landscape navigation bar with dots for horizontal sliders. 21291 */ 21292 function addSlidesNavigation(section, numSlides){ 21293 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 21294 var nav = section.find(SLIDES_NAV_SEL); 21295 21296 //top or bottom 21297 nav.addClass(options.slidesNavPosition); 21298 21299 for(var i=0; i< numSlides; i++){ 21300 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 21301 } 21302 21303 //centering it 21304 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 21305 21306 nav.find('li').first().find('a').addClass(ACTIVE); 21307 } 21308 21309 21310 /** 21311 * Sets the state of the website depending on the active section/slide. 21312 * It changes the URL hash when needed and updates the body class. 21313 */ 21314 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 21315 var sectionHash = ''; 21316 21317 if(options.anchors.length && !options.lockAnchors){ 21318 21319 //isn't it the first slide? 21320 if(slideIndex){ 21321 if(typeof anchorLink !== 'undefined'){ 21322 sectionHash = anchorLink; 21323 } 21324 21325 //slide without anchor link? We take the index instead. 21326 if(typeof slideAnchor === 'undefined'){ 21327 slideAnchor = slideIndex; 21328 } 21329 21330 lastScrolledSlide = slideAnchor; 21331 setUrlHash(sectionHash + '/' + slideAnchor); 21332 21333 //first slide won't have slide anchor, just the section one 21334 }else if(typeof slideIndex !== 'undefined'){ 21335 lastScrolledSlide = slideAnchor; 21336 setUrlHash(anchorLink); 21337 } 21338 21339 //section without slides 21340 else{ 21341 setUrlHash(anchorLink); 21342 } 21343 } 21344 21345 setBodyClass(); 21346 } 21347 21348 /** 21349 * Sets the URL hash. 21350 */ 21351 function setUrlHash(url){ 21352 //Uncode addition 21353 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 21354 return false; 21355 21356 if(options.recordHistory){ 21357 location.hash = url; 21358 }else{ 21359 //Uncode addition 21360 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 21361 // if(isTouchDevice || isTouch){ 21362 // window.history.replaceState(undefined, undefined, '#' + url); 21363 // }else{ 21364 // var baseUrl = window.location.href.split('#')[0]; 21365 // window.location.replace( baseUrl + '#' + url ); 21366 // } 21367 return false; 21368 } 21369 } 21370 21371 /** 21372 * Gets the anchor for the given slide / section. Its index will be used if there's none. 21373 */ 21374 function getAnchor(element){ 21375 var anchor = element.data('anchor'); 21376 var index = element.index(); 21377 21378 //Slide without anchor link? We take the index instead. 21379 if(typeof anchor === 'undefined'){ 21380 anchor = index; 21381 } 21382 21383 return anchor; 21384 } 21385 21386 /** 21387 * Sets a class for the body of the page depending on the active section / slide 21388 */ 21389 function setBodyClass(){ 21390 var section = $(SECTION_ACTIVE_SEL); 21391 var slide = section.find(SLIDE_ACTIVE_SEL); 21392 21393 var sectionAnchor = getAnchor(section); 21394 var slideAnchor = getAnchor(slide); 21395 21396 var text = String(sectionAnchor); 21397 21398 if(slide.length){ 21399 text = text + '-' + slideAnchor; 21400 } 21401 21402 //changing slash for dash to make it a valid CSS style 21403 text = text.replace('/', '-').replace('#',''); 21404 21405 //removing previous anchor classes 21406 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 21407 $body[0].className = $body[0].className.replace(classRe, ''); 21408 21409 //adding the current anchor 21410 $body.addClass(VIEWING_PREFIX + '-' + text); 21411 } 21412 21413 /** 21414 * Checks for translate3d support 21415 * @return boolean 21416 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 21417 */ 21418 function support3d() { 21419 var el = document.createElement('p'), 21420 has3d, 21421 transforms = { 21422 'webkitTransform':'-webkit-transform',
21423 'OTransform':'-o-transform', 21424 'msTransform':'-ms-transform', 21425 'MozTransform':'-moz-transform', 21426 'transform':'transform' 21427 }; 21428 21429 // Add it to the body to get the computed style. 21430 document.body.insertBefore(el, null); 21431 21432 for (var t in transforms) { 21433 if (el.style[t] !== undefined) { 21434 el.style[t] = 'translate3d(1px,1px,1px)'; 21435 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 21436 } 21437 } 21438 21439 document.body.removeChild(el); 21440 21441 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 21442 } 21443 21444 /** 21445 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 21446 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 21447 */ 21448 function removeMouseWheelHandler(){ 21449 if (document.addEventListener) { 21450 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 21451 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 21452 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 21453 } else { 21454 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 21455 } 21456 } 21457 21458 /** 21459 * Adds the auto scrolling action for the mouse wheel and trackpad. 21460 * After this function is called, the mousewheel and trackpad movements will scroll through sections 21461 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 21462 */ 21463 function addMouseWheelHandler(){ 21464 var prefix = ''; 21465 var _addEventListener; 21466 21467 if (window.addEventListener){ 21468 _addEventListener = "addEventListener"; 21469 }else{ 21470 _addEventListener = "attachEvent"; 21471 prefix = 'on'; 21472 } 21473 21474 // detect available wheel event 21475 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 21476 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 21477 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 21478 21479 21480 if(support == 'DOMMouseScroll'){ 21481 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false); 21482 } 21483 21484 //handle MozMousePixelScroll in older Firefox 21485 else{ 21486 document[ _addEventListener ](prefix + support, MouseWheelHandler, false); 21487 } 21488 } 21489 21490 /** 21491 * Binding the mousemove when the mouse's middle button is pressed 21492 */ 21493 function addMiddleWheelHandler(){ 21494 container 21495 .on('mousedown', mouseDownHandler) 21496 .on('mouseup', mouseUpHandler); 21497 } 21498 21499 /** 21500 * Unbinding the mousemove when the mouse's middle button is released 21501 */ 21502 function removeMiddleWheelHandler(){ 21503 container 21504 .off('mousedown', mouseDownHandler) 21505 .off('mouseup', mouseUpHandler); 21506 } 21507 21508 /** 21509 * Adds the possibility to auto scroll through sections on touch devices. 21510 */ 21511 function addTouchHandler(){ 21512 if(isTouchDevice || isTouch){ 21513 if(options.autoScrolling){ 21514 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 21515 } 21516 21517 $(WRAPPER_SEL) 21518 .off(events.touchstart).on(events.touchstart, touchStartHandler) 21519 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 21520 } 21521 } 21522 21523 /** 21524 * Removes the auto scrolling for touch devices. 21525 */ 21526 function removeTouchHandler(){ 21527 if(isTouchDevice || isTouch){ 21528 $(WRAPPER_SEL) 21529 .off(events.touchstart) 21530 .off(events.touchmove); 21531 } 21532 } 21533 21534 /* 21535 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
21536 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 21537 */ 21538 function getMSPointer(){ 21539 var pointer; 21540 21541 //IE >= 11 & rest of browsers 21542 if(window.PointerEvent){ 21543 pointer = { down: 'pointerdown', move: 'pointermove'}; 21544 } 21545 21546 //IE < 11 21547 else{ 21548 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 21549 } 21550 21551 return pointer; 21552 } 21553 21554 /** 21555 * Gets the pageX and pageY properties depending on the browser. 21556 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 21557 */ 21558 function getEventsPage(e){ 21559 var events = []; 21560 21561 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 21562 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 21563 21564 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 21565 if(isTouch && isReallyTouch(e) && options.scrollBar){ 21566 events.y = e.touches[0].pageY; 21567 events.x = e.touches[0].pageX; 21568 } 21569 21570 return events; 21571 } 21572 21573 /** 21574 * Slides silently (with no animation) the active slider to the given slide. 21575 * @param noCallback {bool} true or defined -> no callbacks 21576 */ 21577 function silentLandscapeScroll(activeSlide, noCallbacks){ 21578 setScrollingSpeed (0, 'internal'); 21579 21580 if(typeof noCallbacks !== 'undefined'){ 21581 //preventing firing callbacks afterSlideLoad etc. 21582 isResizing = true; 21583 } 21584 21585 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 21586 21587 if(typeof noCallbacks !== 'undefined'){ 21588 isResizing = false; 21589 } 21590 21591 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 21592 } 21593 21594 /** 21595 * Scrolls silently (with no animation) the page to the given Y position. 21596 */ 21597 function silentScroll(top){ 21598 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 21599 // that's why we round it to 0. 21600 var roundedTop = Math.round(top); 21601 21602 if (options.css3 && options.autoScrolling && !options.scrollBar){ 21603 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 21604 transformContainer(translate3d, false); 21605 } 21606 else if(options.autoScrolling && !options.scrollBar){ 21607 container.css('top', -roundedTop); 21608 } 21609 else{ 21610 $htmlBody.scrollTop(roundedTop); 21611 } 21612 } 21613 21614 /** 21615 * Returns the cross-browser transform string. 21616 */ 21617 function getTransforms(translate3d){ 21618 return { 21619 '-webkit-transform': translate3d, 21620 '-moz-transform': translate3d, 21621 '-ms-transform':translate3d, 21622 'transform': translate3d 21623 }; 21624 } 21625 21626 /** 21627 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 21628 * @type m (mouse) or k (keyboard) 21629 */ 21630 function setIsScrollAllowed(value, direction, type){ 21631 switch (direction){ 21632 case 'up': isScrollAllowed[type].up = value; break; 21633 case 'down': isScrollAllowed[type].down = value; break; 21634 case 'left': isScrollAllowed[type].left = value; break; 21635 case 'right': isScrollAllowed[type].right = value; break; 21636 case 'all': 21637 if(type == 'm'){ 21638 setAllowScrolling(value); 21639 }else{ 21640 setKeyboardScrolling(value); 21641 } 21642 } 21643 } 21644 21645 /* 21646 * Destroys fullpage.js plugin events and optinally its html markup and styles 21647 */ 21648 function destroy(all){ 21649 setAutoScrolling(false, 'internal'); 21650 setAllowScrolling(false); 21651 setKeyboardScrolling(false); 21652 container.addClass(DESTROYED); 21653 21654 clearTimeout(afterSlideLoadsId); 21655 clearTimeout(afterSectionLoadsId); 21656 clearTimeout(resizeId); 21657 clearTimeout(scrollId); 21658 clearTimeout(scrollId2); 21659 21660 $window 21661 .off('scroll', scrollHandler) 21662 .off('hashchange', hashChangeHandler) 21663 .off('resize', resizeHandler); 21664 21665 $document 21666 .off('click touchstart', SECTION_NAV_SEL + ' a') 21667 .off('mouseenter', SECTION_NAV_SEL + ' li') 21668 .off('mouseleave', SECTION_NAV_SEL + ' li') 21669 .off('click touchstart', SLIDES_NAV_LINK_SEL) 21670 .off('mouseover', options.normalScrollElements) 21671 .off('mouseout', options.normalScrollElements); 21672 21673 $(SECTION_SEL) 21674 .off('click touchstart', SLIDES_ARROW_SEL);
21675 21676 clearTimeout(afterSlideLoadsId); 21677 clearTimeout(afterSectionLoadsId); 21678 21679 //lets make a mess! 21680 if(all){ 21681 destroyStructure(); 21682 } 21683 } 21684 21685 /* 21686 * Removes inline styles added by fullpage.js 21687 */ 21688 function destroyStructure(){ 21689 //reseting the `top` or `translate` properties to 0 21690 silentScroll(0); 21691 21692 //loading all the lazy load content 21693 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 21694 setSrc($(this), 'src'); 21695 }); 21696 21697 container.find('img[data-srcset]').each(function(){ 21698 setSrc($(this), 'srcset'); 21699 }); 21700 21701 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 21702 21703 //removing inline styles 21704 $(SECTION_SEL).css( { 21705 'height': '', 21706 'background-color' : '', 21707 'padding': '' 21708 }); 21709 21710 $(SLIDE_SEL).css( { 21711 'width': '' 21712 }); 21713 21714 container.css({ 21715 'height': '', 21716 'position': '', 21717 '-ms-touch-action': '', 21718 'touch-action': '' 21719 }); 21720 21721 $htmlBody.css({ 21722 'overflow': '', 21723 'height': '' 21724 }); 21725 21726 // remove .fp-enabled class 21727 $('html').removeClass(ENABLED); 21728 21729 // remove .fp-responsive class 21730 $body.removeClass(RESPONSIVE); 21731 21732 // remove all of the .fp-viewing- classes 21733 $.each($body.get(0).className.split(/\s+/), function (index, className) { 21734 if (className.indexOf(VIEWING_PREFIX) === 0) { 21735 $body.removeClass(className); 21736 } 21737 }); 21738 21739 //removing added classes 21740 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 21741 options.scrollOverflowHandler.remove($(this)); 21742 $(this).removeClass(TABLE + ' ' + ACTIVE); 21743 }); 21744 21745 removeAnimation(container); 21746 21747 //Unwrapping content 21748 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 21749 //unwrap not being use in case there's no child element inside and its just text 21750 $(this).replaceWith(this.childNodes); 21751 }); 21752 21753 //removing the applied transition from the fullpage wrapper 21754 container.css({ 21755 '-webkit-transition': 'none', 21756 'transition': 'none' 21757 }); 21758 21759 //scrolling the page to the top with no animation 21760 $htmlBody.scrollTop(0); 21761 21762 //removing selectors 21763 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 21764 $.each(usedSelectors, function(index, value){ 21765 $('.' + value).removeClass(value); 21766 }); 21767 } 21768 21769 /* 21770 * Sets the state for a variable with multiple states (original, and temporal) 21771 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 21772 * This function is used to keep track of both states, the original and the temporal one. 21773 * If type is not 'internal', then we assume the user is globally changing the variable. 21774 */ 21775 function setVariableState(variable, value, type){ 21776 options[variable] = value; 21777 if(type !== 'internal'){ 21778 originals[variable] = value; 21779 } 21780 } 21781 21782 /** 21783 * Displays warnings 21784 */ 21785 function displayWarnings(){ 21786 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 21787 //UNCODE.addition 21788 // if($('html').hasClass(ENABLED)){ 21789 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 21790 // return; 21791 // } 21792 21793 // Disable mutually exclusive settings 21794 //UNCODE.addition 21795 // if (options.continuousVertical && 21796 // (options.loopTop || options.loopBottom)) { 21797 // options.continuousVertical = false; 21798 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21799 // } 21800 21801 // if(options.scrollBar && options.scrollOverflow){ 21802 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 21803 // } 21804 21805 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 21806 // options.continuousVertical = false; 21807 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21808 // } 21809 21810 //using extensions? Wrong file! 21811 $.each(extensions, function(index, extension){ 21812 //is the option set to true? 21813 if(options[extension]){ 21814 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 21815 } 21816 }); 21817 21818 //anchors can not have the same value as any element ID or NAME 21819 $.each(options.anchors, function(index, name){ 21820 21821 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 21822 var nameAttr = $document.find('[name]').filter(function() { 21823 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 21824 }); 21825 21826 var idAttr = $document.find('[id]').filter(function() { 21827 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 21828 }); 21829 21830 if(idAttr.length || nameAttr.length ){ 21831 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
21832 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 21833 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 21834 } 21835 }); 21836 } 21837 21838 /** 21839 * Shows a message in the console of the given type. 21840 */ 21841 function showError(type, text){ 21842 console && console[type] && console[type]('fullPage: ' + text); 21843 } 21844 21845 }; //end of $.fn.fullpage 21846 21847 if(typeof IScroll !== 'undefined'){ 21848 /* 21849 * Turns iScroll `mousewheel` option off dynamically 21850 * https://github.com/cubiq/iscroll/issues/1036 21851 */ 21852 IScroll.prototype.wheelOn = function () { 21853 this.wrapper.addEventListener('wheel', this); 21854 this.wrapper.addEventListener('mousewheel', this); 21855 this.wrapper.addEventListener('DOMMouseScroll', this); 21856 }; 21857 21858 /* 21859 * Turns iScroll `mousewheel` option on dynamically 21860 * https://github.com/cubiq/iscroll/issues/1036 21861 */ 21862 IScroll.prototype.wheelOff = function () { 21863 this.wrapper.removeEventListener('wheel', this); 21864 this.wrapper.removeEventListener('mousewheel', this); 21865 this.wrapper.removeEventListener('DOMMouseScroll', this); 21866 }; 21867 } 21868 21869 /** 21870 * An object to handle overflow scrolling. 21871 * This uses jquery.slimScroll to accomplish overflow scrolling. 21872 * It is possible to pass in an alternate scrollOverflowHandler 21873 * to the fullpage.js option that implements the same functions 21874 * as this handler. 21875 * 21876 * @type {Object} 21877 */ 21878 var iscrollHandler = { 21879 refreshId: null, 21880 iScrollInstances: [], 21881 21882 // Enables or disables the mouse wheel for the active section or all slides in it 21883 toggleWheel: function(value){ 21884 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 21885 scrollable.each(function(){ 21886 var iScrollInstance = $(this).data('iscrollInstance'); 21887 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 21888 if(value){ 21889 iScrollInstance.wheelOn(); 21890 } 21891 else{ 21892 iScrollInstance.wheelOff(); 21893 } 21894 } 21895 }); 21896 }, 21897 21898 /** 21899 * Turns off iScroll for the destination section. 21900 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would 21901 * scroll the destination section/slide before the sections animations ends. 21902 */ 21903 onLeave: function(){ 21904 iscrollHandler.toggleWheel(false); 21905 }, 21906 21907 // Turns off iScroll for the leaving section 21908 beforeLeave: function(){ 21909 iscrollHandler.onLeave() 21910 }, 21911 21912 // Turns on iScroll on section load 21913 afterLoad: function(){ 21914 iscrollHandler.toggleWheel(true); 21915 }, 21916 21917 /** 21918 * Called when overflow scrolling is needed for a section. 21919 * 21920 * @param {Object} element jQuery object containing current section 21921 * @param {Number} scrollHeight Current window height in pixels 21922 */ 21923 create: function(element, scrollHeight) { 21924 var scrollable = element.find(SCROLLABLE_SEL); 21925 21926 scrollable.height(scrollHeight); 21927 scrollable.each(function() { 21928 var $this = $(this); 21929 var iScrollInstance = $this.data('iscrollInstance'); 21930 if (iScrollInstance) { 21931 $.each(iscrollHandler.iScrollInstances, function(){ 21932 $(this).destroy(); 21933 }); 21934 } 21935 21936 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 21937 iscrollHandler.iScrollInstances.push(iScrollInstance); 21938 21939 //off by default until the section gets active 21940 iScrollInstance.wheelOff(); 21941 21942 $this.data('iscrollInstance', iScrollInstance); 21943 }); 21944 }, 21945 21946 /** 21947 * Return a boolean depending on whether the scrollable element is a 21948 * the end or at the start of the scrolling depending on the given type. 21949 * 21950 * @param {String} type Either 'top' or 'bottom' 21951 * @param {Object} scrollable jQuery object for the scrollable element 21952 * @return {Boolean} 21953 */ 21954 isScrolled: function(type, scrollable) { 21955 var scroller = scrollable.data('iscrollInstance'); 21956 21957 //no scroller? 21958 if (!scroller) { 21959 return true; 21960 } 21961 21962 if (type === 'top') { 21963 return scroller.y >= 0 && !scrollable.scrollTop(); 21964 } else if (type === 'bottom') { 21965 return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHe
vendor: 16,384 bytes, lines 21965-22509
21965ight() >= scrollable[0].scrollHeight; 21966 } 21967 }, 21968 21969 /** 21970 * Returns the scrollable element for the given section. 21971 * If there are landscape slides, will only return a scrollable element 21972 * if it is in the active slide. 21973 * 21974 * @param {Object} activeSection jQuery object containing current section 21975 * @return {Boolean} 21976 */ 21977 scrollable: function(activeSection){ 21978 // if there are landscape slides, we check if the scrolling bar is in the current one or not 21979 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 21980 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 21981 } 21982 return activeSection.find(SCROLLABLE_SEL); 21983 }, 21984 21985 /** 21986 * Returns the scroll height of the wrapped content. 21987 * If this is larger than the window height minus section padding, 21988 * overflow scrolling is needed. 21989 * 21990 * @param {Object} element jQuery object containing current section 21991 * @return {Number} 21992 */ 21993 scrollHeight: function(element) { 21994 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 21995 }, 21996 21997 /** 21998 * Called when overflow scrolling is no longer needed for a section. 21999 * 22000 * @param {Object} element jQuery object containing current section 22001 */ 22002 remove: function(element) { 22003 var scrollable = element.find(SCROLLABLE_SEL); 22004 if (scrollable.length) { 22005 var iScrollInstance = scrollable.data('iscrollInstance'); 22006 iScrollInstance.destroy(); 22007 22008 scrollable.data('iscrollInstance', null); 22009 } 22010 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 22011 }, 22012 22013 /** 22014 * Called when overflow scrolling has already been setup but the 22015 * window height has potentially changed. 22016 * 22017 * @param {Object} element jQuery object containing current section 22018 * @param {Number} scrollHeight Current window height in pixels 22019 */ 22020 update: function(element, scrollHeight) { 22021 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 22022 //short period of time. 22023 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 22024 clearTimeout(iscrollHandler.refreshId); 22025 iscrollHandler.refreshId = setTimeout(function(){ 22026 $.each(iscrollHandler.iScrollInstances, function(){ 22027 $(this).get(0).refresh(); 22028 }); 22029 }, 150); 22030 22031 //updating the wrappers height 22032 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 22033 }, 22034 22035 /** 22036 * Called to get any additional elements needed to wrap the section 22037 * content in order to facilitate overflow scrolling. 22038 * 22039 * @return {String|Object} Can be a string containing HTML, 22040 * a DOM element, or jQuery object. 22041 */ 22042 wrapContent: function() { 22043 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 22044 } 22045 }; 22046}); 22047 22048 22049 22050/* ======================================================================== 22051 * Bootstrap: collapse.js v3.1.1 22052 * http://getbootstrap.com/javascript/#collapse 22053 * ======================================================================== 22054 * Copyright 2011-2014 Twitter, Inc. 22055 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22056 * ======================================================================== */ 22057 22058 22059+function ($) { 22060 'use strict'; 22061 22062 // COLLAPSE PUBLIC CLASS DEFINITION 22063 // ================================ 22064 22065 var Collapse = function (element, options) { 22066 this.$element = $(element) 22067 this.options = $.extend({}, Collapse.DEFAULTS, options) 22068 this.transitioning = null 22069 22070 if (this.options.parent) this.$parent = $(this.options.parent) 22071 if (this.options.toggle) this.toggle() 22072 } 22073 22074 Collapse.DEFAULTS = { 22075 toggle: true 22076 } 22077 22078 Collapse.prototype.dimension = function () { 22079 var hasWidth = this.$element.hasClass('width') 22080 return hasWidth ? 'width' : 'height' 22081 } 22082 22083 Collapse.prototype.show = function () { 22084 if (this.transitioning || this.$element.hasClass('in')) return 22085 22086 var startEvent = $.Event('show.bs.collapse') 22087 this.$element.trigger(startEvent) 22088 if (startEvent.isDefaultPrevented()) return 22089 22090 var actives = this.$parent && this.$parent.find('> .panel > .in') 22091 22092 if (actives && actives.length) { 22093 var hasData = actives.data('bs.collapse') 22094 if (hasData && hasData.transitioning) return 22095 actives.collapse('hide') 22096 hasData || actives.data('bs.collapse', null) 22097 } 22098 22099 var dimension = this.dimension() 22100 22101 this.$element 22102 .removeClass('collapse') 22103 .addClass('collapsing')[dimension](0) 22104 22105 this.transitioning = 1 22106 22107 var complete = function (e) { 22108 if (e && e.target != this.$element[0]) return 22109 this.$element 22110 .removeClass('collapsing') 22111 .addClass('collapse in')[dimension]('auto') 22112 this.transitioning = 0 22113 this.$element.trigger('shown.bs.collapse') 22114 } 22115 22116 if (!$.support.transition) return complete.call(this) 22117 22118 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 22119 22120 this.$element 22121 .one($.support.transition.end, $.proxy(complete, this)) 22122 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 22123 } 22124 22125 Collapse.prototype.hide = function () { 22126 if (this.transitioning || !this.$element.hasClass('in')) return 22127 22128 var startEvent = $.Event('hide.bs.collapse') 22129 this.$element.trigger(startEvent) 22130 if (startEvent.isDefaultPrevented()) return 22131 22132 var dimension = this.dimension() 22133 22134 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 22135 22136 this.$element 22137 .addClass('collapsing') 22138 .removeClass('collapse') 22139 .removeClass('in') 22140 22141 this.transitioning = 1 22142 22143 var complete = function (e) { 22144 if (e && e.target != this.$element[0]) return 22145 this.transitioning = 0 22146 this.$element 22147 .trigger('hidden.bs.collapse') 22148 .removeClass('collapsing') 22149 .addClass('collapse') 22150 } 22151 22152 if (!$.support.transition) return complete.call(this) 22153 22154 this.$element 22155 [dimension](0) 22156 .one($.support.transition.end, $.proxy(complete, this)) 22157 .emulateTransitionEnd(350) 22158 } 22159 22160 Collapse.prototype.toggle = function () { 22161 this[this.$element.hasClass('in') ? 'hide' : 'show']() 22162 } 22163 22164 22165 // COLLAPSE PLUGIN DEFINITION 22166 // ========================== 22167 22168 var old = $.fn.collapse 22169 22170 $.fn.collapse = function (option) { 22171 return this.each(function () { 22172 var $this = $(this) 22173 var data = $this.data('bs.collapse') 22174 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 22175 22176 if (!data && options.toggle && option == 'show') option = !option 22177 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 22178 if (typeof option == 'string') data[option]() 22179 }) 22180 } 22181 22182 $.fn.collapse.Constructor = Collapse 22183 22184 22185 // COLLAPSE NO CONFLICT 22186 // ==================== 22187 22188 $.fn.collapse.noConflict = function () { 22189 $.fn.collapse = old 22190 return this 22191 } 22192 22193 22194 // COLLAPSE DATA-API 22195 // ================= 22196 22197 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 22198 var $this = $(this), href 22199 var target = $this.attr('data-target') 22200 || e.preventDefault() 22201 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 22202 //Edited by Uncode to replace ID in panel [START] 22203 var _target = href.replace(/^#/, ""); 22204 if ( $('[data-id="' + _target + '"]').length ) { 22205 var $target = $('[data-id="' + _target + '"]') 22206 } else { 22207 var $target = $(target) 22208 } 22209 //Edited by Uncode to replace ID in panel [END] 22210 var data = $target.data('bs.collapse') 22211 var option = data ? 'toggle' : $this.data() 22212 var parent = $this.attr('data-parent') 22213 var $parent = parent && $(parent) 22214 22215 if (!data || !data.transitioning) { 22216 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 22217 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 22218 } 22219 22220 $target.collapse(option) 22221 }) 22222 22223}(jQuery); 22224 22225 22226/* ======================================================================== 22227 * Bootstrap: tab.js v3.1.1 22228 * http://getbootstrap.com/javascript/#tabs 22229 * ======================================================================== 22230 * Copyright 2011-2014 Twitter, Inc. 22231 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22232 * ======================================================================== */ 22233 22234 22235+function ($) { 22236 'use strict'; 22237 22238 // TAB CLASS DEFINITION 22239 // ==================== 22240 22241 var Tab = function (element) { 22242 this.element = $(element) 22243 } 22244 22245 Tab.prototype.show = function () { 22246 var $this = this.element 22247 var $ul = $this.closest('ul:not(.dropdown-menu)') 22248 var selector = $this.data('target') 22249 22250 if (!selector) { 22251 selector = $this.attr('href') 22252 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 22253 } 22254 22255 if ($this.parent('li').hasClass('active')) return 22256 22257 var previous = $ul.find('.active:last a')[0] 22258 var e = $.Event('show.bs.tab', { 22259 relatedTarget: previous 22260 }) 22261 22262 $this.trigger(e) 22263 22264 if (e.isDefaultPrevented()) return 22265 22266 //Edited by Uncode to replace ID in panel [START] 22267 var _target = selector.replace(/^#/, ""); 22268 if ( $('[data-id="' + _target + '"]').length ) 22269 var $target = $('[data-id="' + _target + '"]') 22270 else 22271 var $target = $(selector) 22272 //Edited by Uncode to replace ID in panel [END] 22273 22274 this.activate($this.parent('li'), $ul) 22275 this.activate($target, $target.parent(), function () { 22276 $this.trigger({ 22277 type: 'shown.bs.tab', 22278 relatedTarget: previous 22279 }) 22280 }) 22281 } 22282 22283 Tab.prototype.activate = function (element, container, callback) { 22284 var $active = container.find('> .active') 22285 var transition = callback 22286 && $.support.transition 22287 && $active.hasClass('fade') 22288 22289 function next() { 22290 $active 22291 .removeClass('active') 22292 .find('> .dropdown-menu > .active') 22293 .removeClass('active') 22294 22295 element.addClass('active') 22296 22297 if (transition) { 22298 element[0].offsetWidth // reflow for transition 22299 element.addClass('in') 22300 } else { 22301 element.removeClass('fade') 22302 } 22303 22304 if (element.parent('.dropdown-menu')) { 22305 element.closest('li.dropdown').addClass('active') 22306 } 22307 22308 callback && callback() 22309 } 22310 22311 transition ? 22312 $active 22313 .one($.support.transition.end, next) 22314 .emulateTransitionEnd(150) : 22315 next() 22316 22317 $active.removeClass('in') 22318 } 22319 22320 22321 // TAB PLUGIN DEFINITION 22322 // ===================== 22323 22324 var old = $.fn.tab 22325 22326 $.fn.tab = function ( option ) { 22327 return this.each(function () { 22328 var $this = $(this) 22329 var data = $this.data('bs.tab') 22330 22331 if (!data) $this.data('bs.tab', (data = new Tab(this))) 22332 if (typeof option == 'string') data[option]() 22333 }) 22334 } 22335 22336 $.fn.tab.Constructor = Tab 22337 22338 22339 // TAB NO CONFLICT 22340 // =============== 22341 22342 $.fn.tab.noConflict = function () { 22343 $.fn.tab = old 22344 return this 22345 } 22346 22347 22348 // TAB DATA-API 22349 // ============ 22350 22351 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 22352 e.preventDefault() 22353 $(this).tab('show') 22354 }) 22355 22356}(jQuery); 22357 22358 22359/* ======================================================================== 22360 * Bootstrap: tooltip.js v3.1.1 22361 * http://getbootstrap.com/javascript/#tooltip 22362 * Inspired by the original jQuery.tipsy by Jason Frame 22363 * ======================================================================== 22364 * Copyright 2011-2014 Twitter, Inc. 22365 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22366 * ======================================================================== */ 22367 22368 22369+function ($) { 22370 'use strict'; 22371 22372 // TOOLTIP PUBLIC CLASS DEFINITION 22373 // =============================== 22374 22375 var Tooltip = function (element, options) { 22376 this.type = 22377 this.options = 22378 this.enabled = 22379 this.timeout = 22380 this.hoverState = 22381 this.$element = null 22382 22383 this.init('tooltip', element, options) 22384 } 22385 22386 Tooltip.DEFAULTS = { 22387 animation: true, 22388 placement: 'top', 22389 selector: false, 22390 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 22391 trigger: 'hover focus', 22392 title: '', 22393 delay: 0, 22394 html: false, 22395 container: false, 22396 viewport: { 22397 selector: 'body', 22398 padding: 0 22399 } 22400 } 22401 22402 Tooltip.prototype.init = function (type, element, options) { 22403 this.enabled = true 22404 this.type = type 22405 this.$element = $(element) 22406 this.options = this.getOptions(options) 22407 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 22408 22409 var triggers = this.options.trigger.split(' ') 22410 22411 for (var i = triggers.length; i--;) { 22412 var trigger = triggers[i] 22413 22414 if (trigger == 'click') { 22415 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 22416 } else if (trigger != 'manual') { 22417 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 22418 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 22419 22420 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 22421 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 22422 } 22423 } 22424 22425 this.options.selector ? 22426 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 22427 this.fixTitle() 22428 } 22429 22430 Tooltip.prototype.getDefaults = function () { 22431 return Tooltip.DEFAULTS 22432 } 22433 22434 Tooltip.prototype.getOptions = function (options) { 22435 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 22436 22437 if (options.delay && typeof options.delay == 'number') { 22438 options.delay = { 22439 show: options.delay, 22440 hide: options.delay 22441 } 22442 } 22443 22444 return options 22445 } 22446 22447 Tooltip.prototype.getDelegateOptions = function () { 22448 var options = {} 22449 var defaults = this.getDefaults() 22450 22451 this._options && $.each(this._options, function (key, value) { 22452 if (defaults[key] != value) options[key] = value 22453 }) 22454 22455 return options 22456 } 22457 22458 Tooltip.prototype.enter = function (obj) { 22459 var self = obj instanceof this.constructor ? 22460 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22461 22462 clearTimeout(self.timeout) 22463 22464 self.hoverState = 'in' 22465 22466 if (!self.options.delay || !self.options.delay.show) return self.show() 22467 22468 self.timeout = setTimeout(function () { 22469 if (self.hoverState == 'in') self.show() 22470 }, self.options.delay.show) 22471 } 22472 22473 Tooltip.prototype.leave = function (obj) { 22474 var self = obj instanceof this.constructor ? 22475 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22476 22477 clearTimeout(self.timeout) 22478 22479 self.hoverState = 'out' 22480 22481 if (!self.options.delay || !self.options.delay.hide) return self.hide() 22482 22483 self.timeout = setTimeout(function () { 22484 if (self.hoverState == 'out') self.hide() 22485 }, self.options.delay.hide) 22486 } 22487 22488 Tooltip.prototype.show = function () { 22489 var e = $.Event('show.bs.' + this.type) 22490 22491 if (this.hasContent() && this.enabled) { 22492 this.$element.trigger(e) 22493 22494 if (e.isDefaultPrevented()) return 22495 var that = this; 22496 22497 var $tip = this.tip() 22498 22499 this.setContent() 22500 22501 if (this.options.animation) $tip.addClass('fade') 22502 22503 var placement = typeof this.options.placement == 'function' ? 22504 this.options.placement.call(this, $tip[0], this.$element[0]) : 22505 this.options.placement 22506 22507 var autoToken = /\s?auto?\s?/i 22508 var autoPlace = autoToken.test(placement) 22509 if (autoPlace) placement =
22509 placement.replace(autoToken, '') || 'top' 22510 22511 $tip 22512 .detach() 22513 .css({ top: 0, left: 0, display: 'block' }) 22514 .addClass(placement) 22515 22516 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 22517 22518 var pos = this.getPosition() 22519 var actualWidth = $tip[0].offsetWidth 22520 var actualHeight = $tip[0].offsetHeight 22521 22522 if (autoPlace) { 22523 var orgPlacement = placement 22524 var $parent = this.$element.parent() 22525 var parentDim = this.getPosition($parent) 22526 22527 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 22528 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 22529 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 22530 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 22531 placement 22532 22533 $tip 22534 .removeClass(orgPlacement) 22535 .addClass(placement) 22536 } 22537 22538 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 22539 22540 this.applyPlacement(calculatedOffset, placement) 22541 this.hoverState = null 22542 22543 var complete = function() { 22544 that.$element.trigger('shown.bs.' + that.type) 22545 } 22546 22547 $.support.transition && this.$tip.hasClass('fade') ? 22548 $tip 22549 .one($.support.transition.end, complete) 22550 .emulateTransitionEnd(150) : 22551 complete() 22552 } 22553 } 22554 22555 Tooltip.prototype.applyPlacement = function (offset, placement) { 22556 var $tip = this.tip() 22557 var width = $tip[0].offsetWidth 22558 var height = $tip[0].offsetHeight 22559 22560 // manually read margins because getBoundingClientRect includes difference 22561 var marginTop = parseInt($tip.css('margin-top'), 10) 22562 var marginLeft = parseInt($tip.css('margin-left'), 10) 22563 22564 // we must check for NaN for ie 8/9 22565 if (isNaN(marginTop)) marginTop = 0 22566 if (isNaN(marginLeft)) marginLeft = 0 22567 22568 offset.top = offset.top + marginTop 22569 offset.left = offset.left + marginLeft 22570 22571 // $.fn.offset doesn't round pixel values 22572 // so we use setOffset directly with our own function B-0 22573 $.offset.setOffset($tip[0], $.extend({ 22574 using: function (props) { 22575 $tip.css({ 22576 top: Math.round(props.top), 22577 left: Math.round(props.left) 22578 }) 22579 } 22580 }, offset), 0) 22581 22582 $tip.addClass('in') 22583 22584 // check to see if placing tip in new offset caused the tip to resize itself 22585 var actualWidth = $tip[0].offsetWidth 22586 var actualHeight = $tip[0].offsetHeight 22587 22588 if (placement == 'top' && actualHeight != height) { 22589 offset.top = offset.top + height - actualHeight 22590 } 22591 22592 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 22593 22594 if (delta.left) offset.left += delta.left 22595 else offset.top += delta.top 22596 22597 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 22598 var arrowPosition = delta.left ? 'left' : 'top' 22599 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 22600 22601 $tip.offset(offset) 22602 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 22603 } 22604 22605 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 22606 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 22607 } 22608 22609 Tooltip.prototype.setContent = function () { 22610 var $tip = this.tip() 22611 var title = this.getTitle() 22612 22613 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 22614 $tip.removeClass('fade in top bottom left right') 22615 } 22616 22617 Tooltip.prototype.hide = function () { 22618 var that = this 22619 var $tip = this.tip() 22620 var e = $.Event('hide.bs.' + this.type) 22621 22622 function complete() { 22623 if (that.hoverState != 'in') $tip.detach() 22624 that.$element.trigger('hidden.bs.' + that.type) 22625 } 22626 22627 this.$element.trigger(e) 22628 22629 if (e.isDefaultPrevented()) return 22630 22631 $tip.removeClass('in') 22632 22633 $.support.transition && this.$tip.hasClass('fade') ? 22634 $tip 22635 .one($.support.transition.end, complete) 22636 .emulateTransitionEnd(150) : 22637 complete() 22638 22639 this.hoverState = null 22640 22641 return this 22642 } 22643 22644 Tooltip.prototype.fixTitle = function () { 22645 var $e = this.$element 22646 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 22647 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 22648 } 22649 } 22650 22651 Tooltip.prototype.hasContent = function () { 22652 return this.getTitle() 22653 } 22654 22655 Tooltip.prototype.getPosition = function ($element) { 22656 $element = $element || this.$element 22657 var el = $element[0] 22658 var isBody = el.tagName == 'BODY' 22659 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 22660 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 22661 width: isBody ? $(window).width() : $element.outerWidth(), 22662 height: isBody ? $(window).height() : $element.outerHeight() 22663 }, isBody ? {top: 0, left: 0} : $element.offset()) 22664 } 22665 22666 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 22667 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22668 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22669 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 22670 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 22671 22672 } 22673 22674 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 22675 var delta = { top: 0, left: 0 } 22676 if (!this.$viewport) return delta 22677 22678 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 22679 var viewportDimensions = this.getPosition(this.$viewport) 22680 22681 if (/right|left/.test(placement)) { 22682 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 22683 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 22684 if (topEdgeOffset < viewportDimensions.top) { // top overflow 22685 delta.top = viewportDimensions.top - topEdgeOffset 22686 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 22687 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
22687EdgeOffset 22688 } 22689 } else { 22690 var leftEdgeOffset = pos.left - viewportPadding 22691 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 22692 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 22693 delta.left = viewportDimensions.left - leftEdgeOffset 22694 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 22695 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 22696 } 22697 } 22698 22699 return delta 22700 } 22701 22702 Tooltip.prototype.getTitle = function () { 22703 var title 22704 var $e = this.$element 22705 var o = this.options 22706 22707 title = $e.attr('data-original-title') 22708 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 22709 22710 return title 22711 } 22712 22713 Tooltip.prototype.tip = function () { 22714 return this.$tip = this.$tip || $(this.options.template) 22715 } 22716 22717 Tooltip.prototype.arrow = function () { 22718 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 22719 } 22720 22721 Tooltip.prototype.validate = function () { 22722 if (!this.$element[0].parentNode) { 22723 this.hide() 22724 this.$element = null 22725 this.options = null 22726 } 22727 } 22728 22729 Tooltip.prototype.enable = function () { 22730 this.enabled = true 22731 } 22732 22733 Tooltip.prototype.disable = function () { 22734 this.enabled = false 22735 } 22736 22737 Tooltip.prototype.toggleEnabled = function () { 22738 this.enabled = !this.enabled 22739 } 22740 22741 Tooltip.prototype.toggle = function (e) { 22742 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 22743 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 22744 } 22745 22746 Tooltip.prototype.destroy = function () { 22747 clearTimeout(this.timeout) 22748 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 22749 } 22750 22751 22752 // TOOLTIP PLUGIN DEFINITION 22753 // ========================= 22754 22755 var old = $.fn.tooltip 22756 22757 $.fn.tooltip = function (option) { 22758 return this.each(function () { 22759 var $this = $(this) 22760 var data = $this.data('bs.tooltip') 22761 var options = typeof option == 'object' && option 22762 22763 if (!data && option == 'destroy') return 22764 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 22765 if (typeof option == 'string') data[option]() 22766 }) 22767 } 22768 22769 $.fn.tooltip.Constructor = Tooltip 22770 22771 22772 // TOOLTIP NO CONFLICT 22773 // =================== 22774 22775 $.fn.tooltip.noConflict = function () { 22776 $.fn.tooltip = old 22777 return this 22778 } 22779 22780}(jQuery); 22781 22782 22783/* ======================================================================== 22784 * Bootstrap: transition.js v3.1.1 22785 * http://getbootstrap.com/javascript/#transitions 22786 * ======================================================================== 22787 * Copyright 2011-2014 Twitter, Inc. 22788 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22789 * ======================================================================== */ 22790 22791 22792+function ($) { 22793 'use strict'; 22794 22795 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 22796 // ============================================================ 22797 22798 function transitionEnd() { 22799 var el = document.createElement('bootstrap') 22800 22801 var transEndEventNames = { 22802 WebkitTransition : 'webkitTransitionEnd', 22803 MozTransition : 'transitionend', 22804 OTransition : 'oTransitionEnd otransitionend', 22805 transition : 'transitionend' 22806 } 22807 22808 for (var name in transEndEventNames) { 22809 if (el.style[name] !== undefined) { 22810 return { end: transEndEventNames[name] } 22811 } 22812 } 22813 22814 return false // explicit for ie8 ( ._.) 22815 } 22816 22817 // http://blog.alexmaccaw.com/css-transitions 22818 $.fn.emulateTransitionEnd = function (duration) { 22819 var called = false, $el = this 22820 $(this).one($.support.transition.end, function () { called = true }) 22821 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 22822 setTimeout(callback, duration) 22823 return this 22824 } 22825 22826 $(function () { 22827 $.support.transition = transitionEnd() 22828 }) 22829 22830}(jQuery); 22831 22832
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.