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-double').length ) { 6139 leftPos = '0px'; 6140 } else { 6141 if ( $('body.hmenu-center-split').length > 0 && !$sub.closest('.navbar-cta').length && ! $('body.hormenu-position-right').length ) { 6142 leftPos = - ($sub.closest('.menu-primary-inner')[0].offsetLeft) + 'px'; 6143 } else { 6144 if ( $sub.closest('.navbar-cta').length && !$('body.hmenu').length && !$('body.hmenu-center').length ) { 6145 leftPos = - ( parseFloat($sub.closest('.navbar-cta').offset().left) - parseFloat($sub.closest('.row-menu-inner').find('.logo-container').offset().left) ) + 'px'; 6146 } else if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0 && !$('body.hmenu-center-split').length) { 6147 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 6148 } else { 6149 leftPos = '0px'; 6150 } 6151 } 6152 } 6153 } else { 6154 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 6155 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 6156 } 6157 6158 $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) }); 6159 // IE iframe shim 6160 this.menuIframeShim($sub); 6161 if ($sub.dataSM('ie-shim')) { 6162 $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) }); 6163 } 6164 }, 6165 menuScroll: function($sub, up, wheel) { 6166 var y = parseFloat($sub.css('margin-top')), 6167 scroll = $sub.dataSM('scroll'), 6168 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 6169 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 6170 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 6171 y = parseFloat($sub.css('margin-top')); 6172 // show opposite arrow if appropriate 6173 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 6174 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 6175 } 6176 // accelerate when not using mousewheel to scroll 6177 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 6178 $sub.dataSM('scroll').step += 0.5; 6179 } 6180 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 6181 if (Math.abs(y - end) < 1) { 6182 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 6183 $sub.dataSM('scroll').step = 1; 6184 } else if (!wheel) { 6185 var self = this; 6186 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 6187 } 6188 }, 6189 menuScrollMousewheel: function($sub, e) { 6190 var $closestSub = $(e.target).closest('ul'); 6191 while ($closestSub.dataSM('in-mega')) { 6192 $closestSub = $closestSub.parent().closest('ul'); 6193 } 6194 if ($closestSub[0] == $sub[0]) { 6195 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 6196 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 6197 this.menuScroll($sub, up, true); 6198 } 6199 } 6200 e.preventDefault(); 6201 }, 6202 menuScrollOut: function($sub, e) { 6203 var reClass = /^scroll-(up|down)/, 6204 $closestSub = $(e.relatedTarget).closest('ul'); 6205 while ($closestSub.dataSM('in-mega')) { 6206 $closestSub = $closestSub.parent().closest('ul'); 6207 } 6208 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 6209 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 6210 } 6211 }, 6212 menuScrollOver: function($sub, e) { 6213 var reClass = /^scroll-(up|down)/, 6214 $closestSub = $(e.target).closest('ul'); 6215 while ($closestSub.dataSM('in-mega')) { 6216 $closestSub = $closestSub.parent().closest('ul'); 6217 } 6218 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 6219 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 6220 } 6221 }, 6222 menuScrollStop: function($sub) { 6223 if (this.scrollTimeout) { 6224 clearTimeout(this.scrollTimeout); 6225 this.scrollTimeout = 0; 6226 $sub.dataSM('scroll').step = 1; 6227 } 6228 }, 6229 menuShow: function($sub) { 6230 if (!$sub.dataSM('beforefirstshowfired')) { 6231 $sub.dataSM('beforefirstshowfired', true); 6232 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 6233 return; 6234 } 6235 } 6236 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 6237 return; 6238 } 6239 this.menuFixLayout($sub); 6240 $sub.stop(true, true); 6241 if (!$sub.is(':visible')) { 6242 // set z-index - for IE < 9 set it to the parent LI
6243 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 6244 if (IElt9) { 6245 $sub.parent().css('z-index', zIndex); 6246 } else { 6247 $sub.css('z-index', zIndex); 6248 } 6249 // highlight parent item 6250 if (this.opts.keepHighlighted || this.isCollapsible()) { 6251 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 6252 $sub.dataSM('parent-a').addClass('highlighted'); 6253 } 6254 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 6255 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 6256 if (!IElt8) { 6257 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6258 if (this.opts.subMenusMinWidth) { 6259 $sub.css('min-width', this.opts.subMenusMinWidth); 6260 } 6261 if (this.opts.subMenusMaxWidth) { 6262 var noMaxWidth = this.getWidth($sub); 6263 $sub.css('max-width', this.opts.subMenusMaxWidth); 6264 if (noMaxWidth > this.getWidth($sub)) { 6265 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6266 } 6267 } 6268 // IE6,7 6269 } else { 6270 $sub.children().css('styleFloat', 'none'); 6271 if (IE6) { 6272 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 6273 .children().children('a').css('white-space', 'nowrap'); 6274 } else { // IE7 6275 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6276 if (this.opts.subMenusMinWidth) { 6277 $sub.css('min-width', this.opts.subMenusMinWidth); 6278 } 6279 } 6280 if (this.opts.subMenusMaxWidth) { 6281 var noMaxWidth = $sub.width(); 6282 if (IE6) { 6283 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 6284 if (noMaxWidth > maxWidth) { 6285 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 6286 } else { 6287 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 6288 } 6289 } else { // IE7 6290 $sub.css('max-width', this.opts.subMenusMaxWidth); 6291 if (noMaxWidth > $sub.width()) { 6292 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6293 } else { 6294 $sub.width(noMaxWidth); 6295 } 6296 } 6297 } else { 6298 $sub.width($sub.width()); 6299 } 6300 $sub.children().css('styleFloat', 'left'); 6301 } 6302 } 6303 this.menuPosition($sub); 6304 // insert IE iframe shim 6305 if ($sub.dataSM('ie-shim')) { 6306 $sub.dataSM('ie-shim').insertBefore($sub); 6307 } 6308 var complete = function() { 6309 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 6310 $sub.css('overflow', ''); 6311 }; 6312 // if sub is collapsible (mobile view) 6313 if (this.isCollapsible()) { 6314 if (this.opts.collapsibleShowFunction) { 6315 this.opts.collapsibleShowFunction.call(this, $sub, complete); 6316 } else { 6317 $sub.show(this.opts.collapsibleShowDuration, complete); 6318 } 6319 } else { 6320 if (this.opts.showFunction) { 6321 this.opts.showFunction.call(this, $sub, complete); 6322 } else { 6323 $sub.show(this.opts.showDuration, complete); 6324 } 6325 } 6326 // save new sub menu for this level 6327 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 6328 this.$root.triggerHandler('show.smapi', $sub[0]); 6329 } 6330 }, 6331 popupHide: function(noHideTimeout) { 6332 if (this.hideTimeout) { 6333 clearTimeout(this.hideTimeout); 6334 this.hideTimeout = 0; 6335 } 6336 var self = this; 6337 this.hideTimeout = setTimeout(function() { 6338 self.menuHideAll(); 6339 }, noHideTimeout ? 1 : this.opts.hideTimeout); 6340 }, 6341 popupShow: function(left, top) { 6342 if (!this.opts.isPopup) { 6343 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 6344 return; 6345 } 6346 if (this.hideTimeout) { 6347 clearTimeout(this.hideTimeout); 6348 this.hideTimeout = 0; 6349 } 6350 this.menuFixLayout(this.$root); 6351 this.$root.stop(true, true); 6352 if (!this.$root.is(':visible')) { 6353 this.$root.css({ left: left, top: top }); 6354 // IE iframe shim 6355 this.menuIframeShim(this.$root); 6356 if (this.$root.dataSM('ie-shim')) { 6357 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6357: left, top: top }).insertBefore(this.$root); 6358 } 6359 // show menu 6360 if (this.opts.showFunction) { 6361 this.opts.showFunction.call(this, this.$root); 6362 } else { 6363 this.$root.show(this.opts.showDuration); 6364 } 6365 this.visibleSubMenus[0] = this.$root; 6366 } 6367 }, 6368 refresh: function() { 6369 this.menuHideAll(); 6370 this.$root.find('ul').each(function() { 6371 var $this = $(this); 6372 if ($this.dataSM('scroll-arrows')) { 6373 $this.dataSM('scroll-arrows').remove(); 6374 } 6375 }) 6376 .removeDataSM('in-mega') 6377 .removeDataSM('shown-before') 6378 .removeDataSM('ie-shim') 6379 .removeDataSM('scroll-arrows') 6380 .removeDataSM('parent-a') 6381 .removeDataSM('level') 6382 .removeDataSM('beforefirstshowfired'); 6383 this.$root.find('a.has-submenu').removeClass('has-submenu') 6384 .parent().removeDataSM('sub'); 6385 if (this.opts.subIndicators) { 6386 this.$root.find('span.sub-arrow').remove(); 6387 } 6388 if (this.opts.markCurrentItem) { 6389 this.$root.find('a.current').removeClass('current'); 6390 } 6391 this.subMenus = []; 6392 this.init(true); 6393 }, 6394 rootOut: function(e) { 6395 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6396 return; 6397 } 6398 if (this.hideTimeout) { 6399 clearTimeout(this.hideTimeout); 6400 this.hideTimeout = 0; 6401 } 6402 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 6403 var self = this; 6404 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 6405 } 6406 }, 6407 rootOver: function(e) { 6408 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6409 return; 6410 } 6411 if (this.hideTimeout) { 6412 clearTimeout(this.hideTimeout); 6413 this.hideTimeout = 0; 6414 } 6415 }, 6416 winResize: function(e) { 6417 if (!this.handleEvents()) { 6418 // we still need to resize the disable overlay if it's visible 6419 if (this.$disableOverlay) { 6420 var pos = this.$root.offset(); 6421 this.$disableOverlay.css({ 6422 top: pos.top, 6423 left: pos.left, 6424 width: this.$root.outerWidth(), 6425 height: this.$root.outerHeight() 6426 }); 6427 } 6428 return; 6429 } 6430 // hide sub menus on resize - on mobile do it only on orientation change 6431 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 6432 if (this.activatedItems.length) { 6433 this.activatedItems[this.activatedItems.length - 1][0].blur(); 6434 } 6435 this.menuHideAll(); 6436 } 6437 } 6438 } 6439 }); 6440 6441 $.fn.dataSM = function(key, val) { 6442 if (val) { 6443 return this.data(key + '_smartmenus', val); 6444 } 6445 return this.data(key + '_smartmenus'); 6446 } 6447 6448 $.fn.removeDataSM = function(key) { 6449 return this.removeData(key + '_smartmenus'); 6450 } 6451 6452 $.fn.smartmenus = function(options) { 6453 if (typeof options == 'string') { 6454 var args = arguments, 6455 method = options; 6456 Array.prototype.shift.call(args); 6457 return this.each(function() { 6458 var smartmenus = $(this).data('smartmenus'); 6459 if (smartmenus && smartmenus[method]) { 6460 smartmenus[method].apply(smartmenus, args); 6461 } 6462 }); 6463 } 6464 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 6465 return this.each(function() { 6466 new $.SmartMenus(this, opts); 6467 }); 6468 } 6469 6470 // default settings 6471 $.fn.smartmenus.defaults = { 6472 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 6473 mainMenuSubOffsetX: 0, // pixels offset from default position
6474 mainMenuSubOffsetY: 0, // pixels offset from default position 6475 subMenusSubOffsetX: 0, // pixels offset from default position 6476 subMenusSubOffsetY: 0, // pixels offset from default position 6477 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6478 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6479 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 6480 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 6481 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 6482 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 6483 scrollInterval: 30, // interval between each scrolling step 6484 scrollAccelerate: true, // accelerate scrolling or use a fixed step 6485 showTimeout: 250, // timeout before showing the sub menus 6486 hideTimeout: 500, // timeout before hiding the sub menus 6487 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 6488 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 6489 // don't forget to call complete() at the end of whatever you do 6490 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 6491 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 6492 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 6493 // don't forget to call complete() at the end of whatever you do 6494 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 6495 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 6496 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 6497 // (i.e. when mobile styles are used to make the sub menus collapsible) 6498 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 6499 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 6500 // (i.e. when mobile styles are used to make the sub menus collapsible) 6501 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 6502 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 6503 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 6504 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 6505 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 6506 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 6507 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 6508 bottomToTopSubMenus: false, // bottom to top display of the sub menus 6509 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 6510 }; 6511 6512})(jQuery); 6513 6514/* 6515 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 6516 * 6517 * Uses the built in easing capabilities added In jQuery 1.1 6518 * to offer multiple easing options 6519 * 6520 * TERMS OF USE - jQuery Easing 6521 * 6522 * Open source under the BSD License. 6523 * 6524 * Copyright © 2008 George McGinley Smith 6525 * All rights reserved. 6526 * 6527 * Redistribution and use in source and binary forms, with or without modification, 6528 * are permitted provided that the following conditions are met: 6529 * 6530 * Redistributions of source code must retain the above copyright notice, this list of 6531 * conditions and the following disclaimer. 6532 * Redistributions in binary form must reproduce the above copyright notice, this list 6533 * of conditions and the following disclaimer in the documentation and/or other materials 6534 * provided with the distribution. 6535 * 6536 * Neither the name of the author nor the names of contributors may be used to endorse 6537 * or promote products derived from this software without specific prior written permission. 6538 * 6539 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6540 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6541 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6542 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6543-6688
6543 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6544 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6545 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6546 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6547 * OF THE POSSIBILITY OF SUCH DAMAGE. 6548 * 6549*/ 6550 6551// t: current time, b: begInnIng value, c: change In value, d: duration 6552jQuery.easing['jswing'] = jQuery.easing['swing']; 6553 6554jQuery.extend( jQuery.easing, 6555{ 6556 def: 'easeOutQuad', 6557 swing: function (x, t, b, c, d) { 6558 //alert(jQuery.easing.default); 6559 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 6560 }, 6561 easeInQuad: function (x, t, b, c, d) { 6562 return c*(t/=d)*t + b; 6563 }, 6564 easeOutQuad: function (x, t, b, c, d) { 6565 return -c *(t/=d)*(t-2) + b; 6566 }, 6567 easeInOutQuad: function (x, t, b, c, d) { 6568 if ((t/=d/2) < 1) return c/2*t*t + b; 6569 return -c/2 * ((--t)*(t-2) - 1) + b; 6570 }, 6571 easeInCubic: function (x, t, b, c, d) { 6572 return c*(t/=d)*t*t + b; 6573 }, 6574 easeOutCubic: function (x, t, b, c, d) { 6575 return c*((t=t/d-1)*t*t + 1) + b; 6576 }, 6577 easeInOutCubic: function (x, t, b, c, d) { 6578 if ((t/=d/2) < 1) return c/2*t*t*t + b; 6579 return c/2*((t-=2)*t*t + 2) + b; 6580 }, 6581 easeInQuart: function (x, t, b, c, d) { 6582 return c*(t/=d)*t*t*t + b; 6583 }, 6584 easeOutQuart: function (x, t, b, c, d) { 6585 return -c * ((t=t/d-1)*t*t*t - 1) + b; 6586 }, 6587 easeInOutQuart: function (x, t, b, c, d) { 6588 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 6589 return -c/2 * ((t-=2)*t*t*t - 2) + b; 6590 }, 6591 easeInQuint: function (x, t, b, c, d) { 6592 return c*(t/=d)*t*t*t*t + b; 6593 }, 6594 easeOutQuint: function (x, t, b, c, d) { 6595 return c*((t=t/d-1)*t*t*t*t + 1) + b; 6596 }, 6597 easeInOutQuint: function (x, t, b, c, d) { 6598 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 6599 return c/2*((t-=2)*t*t*t*t + 2) + b; 6600 }, 6601 easeInSine: function (x, t, b, c, d) { 6602 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 6603 }, 6604 easeOutSine: function (x, t, b, c, d) { 6605 return c * Math.sin(t/d * (Math.PI/2)) + b; 6606 }, 6607 easeInOutSine: function (x, t, b, c, d) { 6608 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 6609 }, 6610 easeInExpo: function (x, t, b, c, d) { 6611 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 6612 }, 6613 easeOutExpo: function (x, t, b, c, d) { 6614 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 6615 }, 6616 easeInOutExpo: function (x, t, b, c, d) { 6617 if (t==0) return b; 6618 if (t==d) return b+c; 6619 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 6620 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 6621 }, 6622 easeInCirc: function (x, t, b, c, d) { 6623 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 6624 }, 6625 easeOutCirc: function (x, t, b, c, d) { 6626 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 6627 }, 6628 easeInOutCirc: function (x, t, b, c, d) { 6629 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 6630 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 6631 }, 6632 easeInElastic: function (x, t, b, c, d) { 6633 var s=1.70158;var p=0;var a=c; 6634 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6635 if (a < Math.abs(c)) { a=c; var s=p/4; } 6636 else var s = p/(2*Math.PI) * Math.asin (c/a); 6637 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6638 }, 6639 easeOutElastic: function (x, t, b, c, d) { 6640 var s=1.70158;var p=0;var a=c; 6641 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6642 if (a < Math.abs(c)) { a=c; var s=p/4; } 6643 else var s = p/(2*Math.PI) * Math.asin (c/a); 6644 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 6645 }, 6646 easeInOutElastic: function (x, t, b, c, d) { 6647 var s=1.70158;var p=0;var a=c; 6648 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 6649 if (a < Math.abs(c)) { a=c; var s=p/4; } 6650 else var s = p/(2*Math.PI) * Math.asin (c/a); 6651 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6652 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 6653 }, 6654 easeInBack: function (x, t, b, c, d, s) { 6655 if (s == undefined) s = 1.70158; 6656 return c*(t/=d)*t*((s+1)*t - s) + b; 6657 }, 6658 easeOutBack: function (x, t, b, c, d, s) { 6659 if (s == undefined) s = 1.70158; 6660 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 6661 }, 6662 easeInOutBack: function (x, t, b, c, d, s) { 6663 if (s == undefined) s = 1.70158; 6664 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 6665 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 6666 }, 6667 easeInBounce: function (x, t, b, c, d) { 6668 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 6669 }, 6670 easeOutBounce: function (x, t, b, c, d) { 6671 if ((t/=d) < (1/2.75)) { 6672 return c*(7.5625*t*t) + b; 6673 } else if (t < (2/2.75)) { 6674 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 6675 } else if (t < (2.5/2.75)) { 6676 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 6677 } else { 6678 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 6679 } 6680 }, 6681 easeInOutBounce: function (x, t, b, c, d) { 6682 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 6683 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 6684 } 6685}); 6686 6687/* 6688 *
6689 * TERMS OF USE - EASING EQUATIONS 6690 * 6691 * Open source under the BSD License. 6692 * 6693 * Copyright © 2001 Robert Penner 6694 * All rights reserved. 6695 * 6696 * Redistribution and use in source and binary forms, with or without modification, 6697 * are permitted provided that the following conditions are met: 6698 * 6699 * Redistributions of source code must retain the above copyright notice, this list of 6700 * conditions and the following disclaimer. 6701 * Redistributions in binary form must reproduce the above copyright notice, this list 6702 * of conditions and the following disclaimer in the documentation and/or other materials 6703 * provided with the distribution. 6704 * 6705 * Neither the name of the author nor the names of contributors may be used to endorse 6706 * or promote products derived from this software without specific prior written permission. 6707 * 6708 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6709 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6710 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6711 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 6712 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6713 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6714 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6715 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6716 * OF THE POSSIBILITY OF SUCH DAMAGE. 6717 * 6718 */ 6719 6720(function($, window, undefined) { 6721 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 6722 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 6723 6724 // requestAnimationFrame polyfill by Erik Möller 6725 // fixes from Paul Irish and Tino Zijdel 6726 6727 var lastTime = 0, 6728 running, 6729 animate = function (elem) { 6730 if (running) { 6731 window.requestAnimationFrame(animate, elem); 6732 jQuery.fx.tick(); 6733 } 6734 }, 6735 vendors = ['ms', 'moz', 'webkit', 'o']; 6736 6737 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 6738 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 6739 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 6740 || window[vendors[x]+'CancelRequestAnimationFrame']; 6741 } 6742 6743 if (!window.requestAnimationFrame) 6744 window.requestAnimationFrame = function(fn, element) { 6745 var currTime = new Date().getTime(), 6746 delta = currTime - lastTime, 6747 timeToCall = Math.max(0, 16 - delta); 6748 6749 var id = window.setTimeout(function() { 6750 fn(currTime + timeToCall); 6751 }, 6752 timeToCall 6753 ); 6754 6755 lastTime = currTime + timeToCall; 6756 6757 return id; 6758 }; 6759 6760 if (!window.cancelAnimationFrame) { 6761 window.cancelAnimationFrame = function(id) { 6762 clearTimeout(id); 6763 }; 6764 } 6765 6766 jQuery.fx.timer = function (timer) { 6767 if (timer() && jQuery.timers.push(timer) && !running) { 6768 running = true; 6769 animate(timer.elem); 6770 } 6771 }; 6772 6773 jQuery.fx.stop = function() { 6774 running = false; 6775 }; 6776 6777}(jQuery, this)); 6778 6779/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 6780 * Licensed under the MIT License (LICENSE.txt). 6781 * 6782 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 6783 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6784 * Thanks to: Seamus Leahy for adding deltaX and deltaY 6785 * 6786 * Version: 3.0.6 6787 * 6788 * Requires: 1.2.2+ 6789 */ 6790(function($) { 6791 var types = ['DOMMouseScroll', 'mousewheel']; 6792 if ($.event.fixHooks) { 6793 for (var i = types.length; i;) { 6794 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 6795 } 6796 } 6797 $.event.special.mousewheel = { 6798 setup: function() { 6799 if (this.addEventListener) { 6800 for (var i = types.length; i;) { 6801 this.addEventListener(types[--i], handler, false); 6802 } 6803 } else { 6804 this.onmousewheel = handler; 6805 } 6806 }, 6807 teardown: function() { 6808 if (this.removeEventListener) { 6809 for (var i = types.length; i;) { 6810 this.removeEventListener(types[--i], handler, false); 6811 } 6812 } else { 6813 this.onmousewheel = null; 6814 } 6815 } 6816 }; 6817 $.fn.extend({ 6818 mousewheel: function(fn) { 6819 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 6820 }, 6821 unmousewheel: function(fn) { 6822 return this.unbind("mousewheel", fn); 6823 } 6824 }); 6825 6826 function handler(event) { 6827 var orgEvent = event || window.event, 6828 args = [].slice.call(arguments, 1), 6829 delta = 0, 6830 returnValue = true, 6831 deltaX = 0, 6832 deltaY = 0; 6833 event = $.event.fix(orgEvent); 6834 event.type = "mousewheel"; 6835 // Old school scrollwheel delta 6836 if (orgEvent.wheelDelta) { 6837 delta = orgEvent.wheelDelta / 120; 6838 } 6839 if (orgEvent.detail) { 6840 delta = -orgEvent.detail / 3; 6841 } 6842 // New school multidimensional scroll (touchpads) deltas 6843 deltaY = delta; 6844 // Gecko 6845 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 6846 deltaY = 0; 6847 deltaX = -1 * delta; 6848 } 6849 // Webkit 6850 if (orgEvent.wheelDeltaY !== undefined) { 6851 deltaY = orgEvent.wheelDeltaY / 120; 6852 } 6853 if (orgEvent.wheelDeltaX !== undefined) { 6854 deltaX = -1 * orgEvent.wheelDeltaX / 120; 6855 } 6856 // Add event and delta to the front of the arguments 6857 args.unshift(event, delta, deltaX, deltaY); 6858 return ($.event.dispatch || $.event.handle).apply(this, args); 6859 } 6860})(jQuery); 6861 6862/** 6863 * jQuery iLightBox - Revolutionary Lightbox Plugin 6864 * http://www.ilightbox.net/ 6865 * 6866 * @version: 2.2.4 - October 14, 2017 6867 * 6868 * @author: iProDev (Hemn Chawroka) 6869 * http://www.iprodev.com/ 6870 * 6871 */ 6872(function($, window, undefined) { 6873 6874 var extensions = { 6875 flash: ['swf'], 6876 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 6877 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 6878 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 6879 }, 6880 6881 // Global DOM elements 6882 $win = $(window), 6883 $doc = $(document), 6884
6885 // Support indicators 6886 browser, 6887 transform, 6888 gpuAcceleration, 6889 fullScreenApi = '', 6890 userAgent = navigator.userAgent || navigator.vendor || window.opera, 6891 supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)), 6892 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)), 6893 6894 // Events 6895 clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox", 6896 touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 6897 touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 6898 touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 6899 6900 // Math shorthands 6901 abs = Math.abs, 6902 sqrt = Math.sqrt, 6903 round = Math.round, 6904 max = Math.max, 6905 min = Math.min, 6906 floor = Math.floor, 6907 random = Math.random, 6908 6909 pluginspages = { 6910 quicktime: 'http://www.apple.com/quicktime/download', 6911 flash: 'https://www.adobe.com/go/getflash' 6912 }, 6913 6914 iLightBox = function(el, options, items, instant) { 6915 var iL = this; 6916 6917 iL.options = options, 6918 iL.selector = el.selector || el, 6919 iL.context = el.context, 6920 iL.instant = instant; 6921 6922 if (items.length < 1) iL.attachItems(); 6923 else iL.items = items; 6924 6925 iL.vars = { 6926 total: iL.items.length, 6927 start: 0, 6928 current: null, 6929 next: null, 6930 prev: null, 6931 BODY: $('body'), 6932 loadRequests: 0, 6933 overlay: $('<div class="ilightbox-overlay"></div>'), 6934 loader: $('<div class="ilightbox-loader"><div></div></div>'), 6935 toolbar: $('<div class="ilightbox-toolbar"></div>'), 6936 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 6937 title: $('<div class="ilightbox-title"></div>'), 6938 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 6939 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 6940 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 6941 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 6942 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 6943 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6944 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6945 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6946 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 6947 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
6948 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>'), 6949 thumbs: false, 6950 nextLock: false, 6951 prevLock: false, 6952 hashLock: false, 6953 isMobile: false, 6954 mobileMaxWidth: 980, 6955 isInFullScreen: false, 6956 isSwipe: false, 6957 mouseID: 0, 6958 cycleID: 0, 6959 isPaused: 0, 6960 captionHeight: 39, 6961 }; 6962 6963 // Hideable elements with mousemove event 6964 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 6965 6966 iL.normalizeItems(); 6967 6968 //Check necessary plugins 6969 iL.availPlugins(); 6970 6971 //Set startFrom 6972 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 6973 6974 //If randomStart 6975 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 6976 iL.vars.start = iL.options.startFrom; 6977 6978 if (instant) iL.instantCall(); 6979 else iL.patchItemsEvents(); 6980 6981 if (iL.options.linkId) { 6982 iL.hashChangeHandler(); 6983 $win.iLightBoxHashChange(function() { 6984 iL.hashChangeHandler(); 6985 }); 6986 } 6987 6988 if (supportTouch) { 6989 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 6990 replace = "itap"; 6991 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 6992 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 6993 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 6994 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 6995 } 6996 6997 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 6998 $.extend(iL.options.styles, { 6999 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 7000 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 7001 nextOpacity: 0, 7002 prevOpacity: 0 7003 }); 7004 } 7005 }; 7006 7007 //iLightBox helpers 7008 iLightBox.prototype = { 7009 showLoader: function() { 7010 var iL = this; 7011 iL.vars.loadRequests += 1; 7012 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7013 //top: '-30px' 7014 opacity: '1' 7015 }, iL.options.show.speed, 'easeOutCirc'); 7016 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7017 //left: '-30px' 7018 opacity: '1' 7019 }, iL.options.show.speed, 'easeOutCirc'); 7020 }, 7021 7022 hideLoader: function() { 7023 var iL = this; 7024 iL.vars.loadRequests -= 1; 7025 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 7026 if (iL.options.path.toLowerCase() == "horizontal") { 7027 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7028 //top: '-192px' 7029 opacity: '0' 7030 }, iL.options.show.speed, 'easeInCirc'); 7031 } else { 7032 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7033 //left: '-192px' 7034 opacity: '0' 7035 }, iL.options.show.speed, 'easeInCirc'); 7036 } 7037 }, 7038 7039 createUI: function() { 7040 var iL = this; 7041 7042 iL.ui = { 7043 currentElement: iL.vars.holder, 7044 nextElement: iL.vars.nextPhoto, 7045 prevElement: iL.vars.prevPhoto, 7046 currentItem: iL.vars.current, 7047 nextItem: iL.vars.next, 7048 prevItem: iL.vars.prev, 7049 hide: function() { 7050 iL.closeAction(); 7051 }, 7052 refresh: function() { 7053 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7054 }, 7055 fullscreen: function() { 7056 iL.fullScreenAction(); 7057 } 7058 }; 7059 }, 7060 7061 attachItems: function() { 7062 var iL = this, 7063 itemsObject = new Array(), 7064 items = new Array(); 7065 7066 $(iL.selector, iL.context).each(function() { 7067 var t = $(this), 7068 URL = t.attr(iL.options.attr) || null, 7069 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 7070 caption = t.data('caption'), 7071 title = t.data('title'), 7072 type = t.data('type') || getTypeByExtension(URL), 7073 clone = t.data('lbox-clone') || false; 7074 7075 if (t.data('lbox-clone') != undefined) return; 7076 7077 //Uncode addition ##START## 7078 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 7079 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 7080 URL_i, 7081 URLS_LENGHT = ALBUM_URLS.length; 7082 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 7083 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 7084 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 7085 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 7086 items.push({ 7087 URL: ALBUM_URLS[URL_i].url, 7088 caption: ALBUM_URLS[URL_i].caption, 7089 title: ALBUM_URLS[URL_i].title, 7090 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 7091 options: item_opts, 7092 clone: clone 7093 }); 7094 var newT = t; 7095 newT.attr('href',ALBUM_URLS[URL_i].url); 7096 if (!iL.instant) itemsObject.push(newT); 7097 } 7098 } 7099 } else { 7100 //Uncode addition ##END## 7101 items.push({ 7102 URL: URL, 7103 caption: caption, 7104 title: title, 7105 type: type, 7106 options: options, 7107 clone: clone 7108 }); 7109 } 7110 7111 7112 if (iL.vars != undefined) iL.vars.total = items.length; 7113 7114 if (!iL.instant) itemsObject.push(t); 7115 }); 7116 7117 iL.items = items, 7118 iL.itemsObject = itemsObject; 7119 7120 }, 7121 7122 normalizeItems: function() { 7123 var iL = this, 7124 newItems = new Array(); 7125 7126 $.each(iL.items, function(key, val) { 7127 7128 if (typeof val == "string") val = { 7129 url: val 7130 }; 7131 7132 var URL = val.url || val.URL || null, 7133 options = val.options || {}, 7134 caption = val.caption || null, 7135 title = val.title || null, 7136 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 7137 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 7138 7139 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
7140 options.videoType = options.videoType || null, 7141 options.skin = options.skin || iL.options.skin, 7142 options.width = options.width || null, 7143 options.height = options.height || null, 7144 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 7145 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 7146 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 7147 7148 if (type == "video") { 7149 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 7150 7151 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 7152 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 7153 options.html5video.preload = options.html5video.preload || "metadata"; 7154 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 7155 //UNCODE addition 7156 options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false; 7157 } 7158 7159 if (!options.width || !options.height) { 7160 if (type == "video") options.width = 1280, options.height = 720; 7161 else if (type == "iframe") options.width = '100%', options.height = '90%'; 7162 else if (type == "flash") options.width = 1280, options.height = 720; 7163 } 7164 7165 delete val.url; 7166 val.index = key; 7167 val.URL = URL; 7168 val.caption = caption; 7169 val.title = title; 7170 val.type = type; 7171 val.options = options; 7172 val.ext = ext; 7173 7174 newItems.push(val); 7175 }); 7176 7177 iL.items = newItems; 7178 }, 7179 7180 instantCall: function() { 7181 var iL = this, 7182 key = iL.vars.start; 7183 7184 iL.vars.current = key; 7185 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 7186 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 7187 7188 iL.addContents(); 7189 iL.patchEvents(); 7190 }, 7191 7192 addContents: function() { 7193 var iL = this, 7194 vars = iL.vars, 7195 opts = iL.options, 7196 viewport = getViewport(), 7197 path = opts.path.toLowerCase(), 7198 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 7199 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 7200 }), 7201 needRecognition = recognizingItems.length > 0; 7202 7203 if (opts.mobileOptimizer && !opts.innerToolbar) 7204 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7205 7206 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 7207 7208 if (opts.linkId) 7209 vars.overlay[0].setAttribute('linkid', opts.linkId); 7210 7211 //Add Toolbar Buttons 7212 if (opts.controls.toolbar) { 7213 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 7214 if (opts.controls.fullscreen) 7215 vars.toolbar.append(vars.fullScreenButton); 7216 if (opts.controls.slideshow) 7217 vars.toolbar.append(vars.innerPlayButton); 7218 if (vars.total > 1) 7219 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 7220 } 7221 7222 //Append elements to body 7223 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 7224 7225 if (!opts.innerToolbar) 7226 vars.BODY.append(vars.toolbar); 7227 if (opts.controls.arrows) 7228 vars.BODY.append(vars.nextButton).append(vars.prevButton); 7229 7230 if (opts.controls.thumbnail && vars.total > 1) { 7231 vars.BODY.append(vars.thumbnails); 7232 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 7233 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 7234 vars.thumbs = true; 7235 } 7236 7237 //Configure loader and arrows 7238 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 7239 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 7240 } : { 7241 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 7242 }; 7243 vars.loader.addClass(opts.skin).css(loaderCss); 7244 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 7245 if (path == "horizontal") 7246 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 7247 7248 // Configure arrow buttons 7249 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7250 7251 if (!opts.infinite) { 7252 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 7253 7254 if (vars.current == 0) 7255 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 7256 if (vars.current >= vars.total - 1) 7257 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 7258 } 7259 7260 if (opts.show.effect) { 7261 vars.overlay.stop().fadeIn(opts.show.speed); 7262 vars.toolbar.stop().fadeIn(opts.show.speed); 7263 } else { 7264 vars.overlay.show(); 7265 vars.toolbar.show(); 7266 } 7267 7268 var length = recognizingItems.length; 7269 if (needRecognition) { 7270 iL.showLoader(); 7271 7272 $.each(recognizingItems, function(key, val) { 7273 var resultFnc = function(result) { 7274 var key = -1, 7275 filter = iL.items.filter(function(e, i, arr) { 7276 if (e.URL == result.url) 7277 key = i; 7278 7279 return e.URL == result.url; 7280 }), 7281 self = iL.items[key]; 7282 7283 if (result) 7284 $.extend(true, self, { 7285 URL: result.source, 7286 type: result.type, 7287 recognized: true, 7288 options: { 7289 html5video: result.html5video, 7290 width: (result.type == "image") ? 0 : (result.width || self.width), 7291 height: (result.type == "image") ? 0 : (result.height || self.height), 7292 thumbnail: self.options.thumbnail || result.thumbnail 7293 } 7294 }); 7295 7296 length--; 7297 7298 if (length == 0) { 7299 iL.hideLoader(); 7300 7301 vars.dontGenerateThumbs = false;
7302 iL.generateThumbnails(); 7303 7304 if (opts.show.effect) 7305 setTimeout(function() { 7306 iL.generateBoxes(); 7307 }, opts.show.speed); 7308 else 7309 iL.generateBoxes(); 7310 } 7311 }; 7312 7313 iL.ogpRecognition(this, resultFnc); 7314 }); 7315 } 7316 else { 7317 if (opts.show.effect) 7318 setTimeout(function() { 7319 iL.generateBoxes(); 7320 }, opts.show.speed); 7321 else 7322 iL.generateBoxes(); 7323 } 7324 7325 iL.createUI(); 7326 7327 window.iLightBox = { 7328 close: function() { 7329 iL.closeAction(); 7330 }, 7331 fullscreen: function() { 7332 iL.fullScreenAction(); 7333 }, 7334 moveNext: function() { 7335 iL.moveTo('next'); 7336 }, 7337 movePrev: function() { 7338 iL.moveTo('prev'); 7339 }, 7340 goTo: function(index) { 7341 iL.goTo(index); 7342 }, 7343 refresh: function() { 7344 iL.refresh(); 7345 }, 7346 reposition: function() { 7347 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7348 }, 7349 setOption: function(options) { 7350 iL.setOption(options); 7351 }, 7352 destroy: function() { 7353 iL.closeAction(); 7354 iL.dispatchItemsEvents(); 7355 } 7356 }; 7357 7358 if (opts.linkId) { 7359 vars.hashLock = true; 7360 window.location.hash = opts.linkId + '/' + vars.current; 7361 setTimeout(function() { 7362 vars.hashLock = false; 7363 }, 55); 7364 } 7365 7366 if (!opts.slideshow.startPaused) { 7367 iL.resume(); 7368 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 7369 } 7370 7371 //Trigger the onOpen callback 7372 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 7373 }, 7374 7375 loadContent: function(obj, opt, speed) { 7376 var iL = this, 7377 holder, item; 7378 7379 iL.createUI(); 7380 7381 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 7382 7383 if (opt == 'current') { 7384 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 7385 else iL.vars.lockWheel = false; 7386 7387 if (!obj.options.swipe) iL.vars.lockSwipe = true; 7388 else iL.vars.lockSwipe = false; 7389 } 7390 7391 switch (opt) { 7392 case 'current': 7393 holder = iL.vars.holder, item = iL.vars.current; 7394 break; 7395 case 'next': 7396 holder = iL.vars.nextPhoto, item = iL.vars.next; 7397 break; 7398 case 'prev': 7399 holder = iL.vars.prevPhoto, item = iL.vars.prev; 7400 break; 7401 } 7402 7403 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 7404 $('div.ilightbox-inner-toolbar', holder).remove(); 7405 7406 if (obj.title || iL.options.innerToolbar) { 7407 var innerToolbar = iL.vars.innerToolbar.clone(); 7408 if (obj.title && iL.options.show.title) { 7409 var title = iL.vars.title.clone(); 7410 title.empty().html(obj.title); 7411 innerToolbar.append(title); 7412 } 7413 if (iL.options.innerToolbar) { 7414 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 7415 } 7416 holder.prepend(innerToolbar); 7417 } 7418 7419 //console.warn('loadContent', arguments); 7420 7421 iL.loadSwitcher(obj, holder, item, opt); 7422 }, 7423 7424 loadSwitcher: function(obj, holder, item, opt) { 7425 var iL = this, 7426 opts = iL.options, 7427 api = { 7428 element: holder, 7429 position: item 7430 }; 7431 7432 switch (obj.type) { 7433 case 'image': 7434 //Trigger the onBeforeLoad callback 7435 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7436 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7437 7438 iL.loadImage(obj.URL, function(img) { 7439 //Trigger the onAfterLoad callback 7440 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7441 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7442 7443 var width = (img) ? img.width : 400, 7444 height = (img) ? img.height : 200; 7445 7446 holder.data({ 7447 naturalWidth: width, 7448 naturalHeight: height 7449 }); 7450 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 7451 7452 //Trigger the onRender callback 7453 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7454 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7455 7456 iL.configureHolder(obj, opt, holder); 7457 }); 7458 7459 break; 7460
7461 case 'video': 7462 holder.data({ 7463 naturalWidth: obj.options.width, 7464 naturalHeight: obj.options.height 7465 }); 7466 7467 if (opt === 'current') { 7468 iL.addContent(holder, obj); 7469 7470 //Trigger the onRender callback 7471 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7472 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7473 } else { 7474 $('div.ilightbox-container', holder).empty(); 7475 } 7476 7477 iL.configureHolder(obj, opt, holder); 7478 7479 break; 7480 7481 case 'iframe': 7482 //iL.showLoader(); 7483 holder.data({ 7484 naturalWidth: obj.options.width, 7485 naturalHeight: obj.options.height 7486 }); 7487 7488 iL.configureHolder(obj, opt, holder); 7489 7490 if (opt === 'current') { 7491 var el = iL.addContent(holder, obj); 7492 7493 //Trigger the onRender callback 7494 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7495 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7496 7497 //Trigger the onBeforeLoad callback 7498 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7499 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7500 7501 el.bind('load', function() { 7502 //Trigger the onAfterLoad callback 7503 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7504 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7505 7506 //iL.hideLoader(); 7507 el.unbind('load'); 7508 }); 7509 } else { 7510 $('div.ilightbox-container', holder).empty(); 7511 } 7512 7513 break; 7514 7515 case 'inline': 7516 var el = $(obj.URL), 7517 content = iL.addContent(holder, obj), 7518 images = findImageInElement(holder); 7519 7520 holder.data({ 7521 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7522 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7523 }); 7524 content.children().eq(0).show(); 7525 7526 //Trigger the onRender callback 7527 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7528 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7529 7530 //Trigger the onBeforeLoad callback 7531 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7532 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7533 7534 iL.loadImage(images, function() { 7535 //Trigger the onAfterLoad callback 7536 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7537 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7538 7539 iL.configureHolder(obj, opt, holder); 7540 }); 7541 7542 break; 7543 7544 case 'flash': 7545 var el = iL.addContent(holder, obj); 7546 7547 holder.data({ 7548 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7549 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7550 }); 7551 7552 //Trigger the onRender callback 7553 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7554 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7555 7556 iL.configureHolder(obj, opt, holder); 7557 7558 break; 7559 7560 case 'ajax': 7561 var ajax = obj.options.ajax || {}; 7562 //Trigger the onBeforeLoad callback 7563 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7564 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7565 7566 iL.showLoader(); 7567 $.ajax({ 7568 url: obj.URL || opts.ajaxSetup.url, 7569 data: ajax.data || null, 7570 dataType: ajax.dataType || "html", 7571 type: ajax.type || opts.ajaxSetup.type, 7572 cache: ajax.cache || opts.ajaxSetup.cache, 7573 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 7574 global: ajax.global || opts.ajaxSetup.global, 7575 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 7576 username: ajax.username || opts.ajaxSetup.username, 7577 password: ajax.password || opts.ajaxSetup.password, 7578 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 7579 complete: ajax.complete || opts.ajaxSetup.complete, 7580 success: function(data, textStatus, jqXHR) { 7581 iL.hideLoader(); 7582 7583 var el = $(data), 7584 container = $('div.ilightbox-container', holder), 7585 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 7586 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 7587 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 7588 'overflow': 'hidden' 7589 } : {}; 7590 7591 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 7592 holder.show().data({
7593 naturalWidth: (elWidth || container.outerWidth()), 7594 naturalHeight: (elHeight || container.outerHeight()) 7595 }).hide(); 7596 7597 //Trigger the onRender callback 7598 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7599 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7600 7601 var images = findImageInElement(holder); 7602 iL.loadImage(images, function() { 7603 //Trigger the onAfterLoad callback 7604 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7605 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7606 7607 iL.configureHolder(obj, opt, holder); 7608 }); 7609 7610 opts.ajaxSetup.success(data, textStatus, jqXHR); 7611 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 7612 }, 7613 error: function(jqXHR, textStatus, errorThrown) { 7614 //Trigger the onAfterLoad callback 7615 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7616 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7617 7618 iL.hideLoader(); 7619 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 7620 iL.configureHolder(obj, opt, holder); 7621 7622 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 7623 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 7624 } 7625 }); 7626 7627 break; 7628 7629 case 'html': 7630 var object = obj.URL, 7631 el 7632 container = $('div.ilightbox-container', holder); 7633 7634 if (object[0].nodeName) el = object.clone(); 7635 else { 7636 var dom = $(object); 7637 if (dom.selector) el = $('<div>' + dom + '</div>'); 7638 else el = dom; 7639 } 7640 7641 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 7642 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 7643 7644 iL.addContent(holder, obj); 7645 7646 el.appendTo(document.documentElement).hide(); 7647 7648 //Trigger the onRender callback 7649 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7650 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7651 7652 var images = findImageInElement(holder); 7653 7654 //Trigger the onBeforeLoad callback 7655 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7656 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7657 7658 iL.loadImage(images, function() { 7659 //Trigger the onAfterLoad callback 7660 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7661 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7662 7663 holder.show().data({ 7664 naturalWidth: (elWidth || container.outerWidth()), 7665 naturalHeight: (elHeight || container.outerHeight()) 7666 }).hide(); 7667 el.remove(); 7668 7669 iL.configureHolder(obj, opt, holder); 7670 }); 7671 7672 break; 7673 } 7674 }, 7675 7676 configureHolder: function(obj, opt, holder) { 7677 var iL = this, 7678 vars = iL.vars, 7679 opts = iL.options; 7680 7681 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 7682 7683 if (opt == "current") 7684 var item = vars.current; 7685 else if (opt == "next") 7686 var opacity = opts.styles.nextOpacity, 7687 item = vars.next; 7688 else 7689 var opacity = opts.styles.prevOpacity, 7690 item = vars.prev; 7691 7692 var api = { 7693 element: holder, 7694 position: item 7695 }; 7696 7697 iL.items[item].options.width = iL.items[item].options.width || 0, 7698 iL.items[item].options.height = iL.items[item].options.height || 0; 7699 7700 if (opt == "current") { 7701 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 7702 holder.css(transform, ''); 7703 if (obj.caption) { 7704 iL.setCaption(obj, holder); 7705 var caption = $('div.ilightbox-caption', holder), 7706 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 7707 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7707Speed); 7708 } 7709 7710 var social = obj.options.social; 7711 if (social) { 7712 iL.setSocial(social, obj.URL, holder); 7713 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 7714 } 7715 7716 //Generate thumbnails 7717 iL.generateThumbnails(); 7718 7719 //Trigger the onShow callback 7720 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7721 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7722 }); 7723 else { 7724 holder.show(); 7725 7726 //Generate thumbnails 7727 iL.generateThumbnails(); 7728 7729 //Trigger the onShow callback 7730 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7731 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7732 } 7733 } else { 7734 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 7735 if (opt == "next") vars.nextLock = false; 7736 else vars.prevLock = false; 7737 7738 //Generate thumbnails 7739 iL.generateThumbnails(); 7740 7741 //Trigger the onShow callback 7742 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7743 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7744 }); 7745 else { 7746 holder.css({ 7747 opacity: opacity 7748 }).show(); 7749 if (opt == "next") vars.nextLock = false; 7750 else vars.prevLock = false; 7751 7752 //Generate thumbnails 7753 iL.generateThumbnails(); 7754 7755 //Trigger the onShow callback 7756 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7757 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7758 } 7759 } 7760 7761 setTimeout(function() { 7762 iL.repositionPhoto(); 7763 }, 0); 7764 }, 7765 7766 generateBoxes: function() { 7767 var iL = this, 7768 vars = iL.vars, 7769 opts = iL.options; 7770 7771 if (opts.infinite && vars.total >= 3) { 7772 if (vars.current == vars.total - 1) vars.next = 0; 7773 if (vars.current == 0) vars.prev = vars.total - 1; 7774 } else opts.infinite = false; 7775 7776 //UNCODE addition 7777 if ( typeof iL.items[vars.current] == 'undefined' ) 7778 vars.current = 0; 7779 7780 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 7781 7782 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 7783 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 7784 }, 7785 7786 generateThumbnails: function() { 7787 var iL = this, 7788 vars = iL.vars, 7789 opts = iL.options, 7790 timeOut = null; 7791 7792 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 7793 var thumbnails = vars.thumbnails, 7794 container = $('div.ilightbox-thumbnails-container', thumbnails), 7795 grid = $('div.ilightbox-thumbnails-grid', container), 7796 i = 0; 7797 7798 grid.removeAttr('style').empty(); 7799 7800 $.each(iL.items, function(key, val) { 7801 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 7802 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 7803 thumb = val.options.thumbnail, 7804 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 7805 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 7806 7807 thumbnail.css({ 7808 opacity: 0 7809 }).addClass(isActive); 7810 7811 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 7812 icon.addClass('ilightbox-thumbnail-video'); 7813 thumbnail.append(icon); 7814 } else if (val.options.icon) { 7815 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 7816 thumbnail.append(icon); 7817 } 7818 7819 if (thumb) iL.loadImage(thumb, function(img) { 7820 i++; 7821 if (img) thumbnail.data({ 7822 naturalWidth: img.width, 7823 naturalHeight: img.height 7824 }).append('<img src="' + thumb + '" border="0" />'); 7825 else thumbnail.data({ 7826 naturalWidth: opts.thumbnails.maxWidth, 7827 naturalHeight: opts.thumbnails.maxHeight 7828 }); 7829 7830 clearTimeout(timeOut); 7831 timeOut = setTimeout(function() { 7832 iL.positionThumbnails(thumbnails, container, grid); 7833 }, 20); 7834 setTimeout(function() { 7835 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 7836 }, i * 20); 7837 }); 7838 7839 grid.append(thumbnail); 7840 }); 7841 iL.vars.dontGenerateThumbs = true; 7842 } 7843 }, 7844
7845 positionThumbnails: function(thumbnails, container, grid) { 7846 var iL = this, 7847 vars = iL.vars, 7848 opts = iL.options, 7849 viewport = getViewport(), 7850 path = opts.path.toLowerCase(); 7851 7852 if (!thumbnails) thumbnails = vars.thumbnails; 7853 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 7854 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 7855 7856 var thumbs = $('.ilightbox-thumbnail', grid), 7857 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 7858 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 7859 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 7860 gridHeight = (path == 'horizontal') ? heightAvail : 0, 7861 active = $('.ilightbox-active', grid), 7862 gridCss = {}, 7863 css = {}; 7864 7865 if (arguments.length < 3) { 7866 thumbs.css({ 7867 opacity: opts.thumbnails.normalOpacity 7868 }); 7869 active.css({ 7870 opacity: opts.thumbnails.activeOpacity 7871 }); 7872 } 7873 7874 thumbs.each(function(i) { 7875 var t = $(this), 7876 data = t.data(), 7877 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 7878 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 7879 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 7880 7881 t.css({ 7882 width: dims.width, 7883 height: dims.height 7884 }); 7885 if (path == 'horizontal') t.css({ 7886 'float': 'left' 7887 }); 7888 7889 (path == 'horizontal') ? ( 7890 gridWidth += t.outerWidth() 7891 ) : ( 7892 gridHeight += t.outerHeight() 7893 ); 7894 }); 7895 7896 gridCss = { 7897 width: gridWidth, 7898 height: gridHeight 7899 }; 7900 7901 grid.css(gridCss); 7902 7903 gridCss = {}; 7904 7905 var gridOffset = grid.offset(), 7906 activeOffset = (active.length) ? active.offset() : { 7907 top: parseInt(heightAvail / 2), 7908 left: parseInt(widthAvail / 2) 7909 }; 7910 7911 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 7912 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 7913 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 7914 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 7915 7916 (path == 'horizontal') ? ( 7917 gridCss.top = 0, 7918 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 7919 ) : ( 7920 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 7921 gridCss.left = 0 7922 ); 7923 7924 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 7925 else grid.css(gridCss); 7926 }, 7927 7928 loadImage: function(image, callback) { 7929 if (!$.isArray(image)) image = [image]; 7930 7931 var iL = this, 7932 length = image.length; 7933 7934 if (length > 0) { 7935 iL.showLoader(); 7936 $.each(image, function(index, value) { 7937 var img = new Image(); 7938 img.onload = function() { 7939 length -= 1; 7940 if (length == 0) { 7941 iL.hideLoader(); 7942 callback(img); 7943 } 7944 }; 7945 img.onerror = img.onabort = function() { 7946 length -= 1; 7947 if (length == 0) { 7948 iL.hideLoader(); 7949 callback(false); 7950 } 7951 }; 7952 img.src = image[index]; 7953 }); 7954 } else callback(false); 7955 }, 7956 7957 patchItemsEvents: function() { 7958 var iL = this, 7959 vars = iL.vars, 7960 clickEvent = supportTouch ? "itap.iL" : "click.iL", 7961 vEvent = supportTouch ? "click.iL" : "itap.iL"; 7962 7963 if (iL.context && iL.selector) { 7964 var $items = $(iL.selector, iL.context); 7965 7966 $(iL.context).on(clickEvent, iL.selector, function() { 7967 var $this = $(this), 7968 //UNCODE addition 7969 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 7970 if (UNCODE.isMobile) { 7971 var isCarousel = $this.closest('.owl-carousel'); 7972 if (isCarousel.length) { 7973 if (isCarousel.hasClass('owl-translating')) return false; 7974 } 7975 } 7976 7977 vars.current = key; 7978 vars.next = iL.items[key + 1] ? key + 1 : null; 7979 vars.prev = iL.items[key - 1] ? key - 1 : null; 7980 7981 //UNCODE addition 7982 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 7983 return false;
7984 7985 iL.addContents(); 7986 iL.patchEvents(); 7987 7988 return false; 7989 }).on(vEvent, iL.selector, function() { 7990 return false; 7991 }); 7992 } else 7993 $.each(iL.itemsObject, function(key, val) { 7994 val.on(clickEvent, function() { 7995 vars.current = key; 7996 vars.next = iL.items[key + 1] ? key + 1 : null; 7997 vars.prev = iL.items[key - 1] ? key - 1 : null; 7998 7999 iL.addContents(); 8000 iL.patchEvents(); 8001 8002 return false; 8003 }).on(vEvent, function() { 8004 return false; 8005 }); 8006 }); 8007 }, 8008 8009 dispatchItemsEvents: function() { 8010 var iL = this, 8011 vars = iL.vars, 8012 opts = iL.options; 8013 8014 if (iL.context && iL.selector) 8015 $(iL.context).off('.iL', iL.selector); 8016 else 8017 $.each(iL.itemsObject, function(key, val) { 8018 val.off('.iL'); 8019 }); 8020 }, 8021 8022 refresh: function() { 8023 var iL = this; 8024 8025 iL.dispatchItemsEvents(); 8026 iL.attachItems(); 8027 iL.normalizeItems(); 8028 iL.patchItemsEvents(); 8029 }, 8030 8031 patchEvents: function() { 8032 var iL = this, 8033 vars = iL.vars, 8034 opts = iL.options, 8035 path = opts.path.toLowerCase(), 8036 holders = $('.ilightbox-holder'), 8037 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 8038 durationThreshold = 1000, 8039 horizontalDistanceThreshold = 8040 verticalDistanceThreshold = 100, 8041 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 8042 8043 $win.bind('resize.iLightBox', function() { 8044 var viewport = getViewport(); 8045 8046 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 8047 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 8048 8049 iL.repositionPhoto(null); 8050 if (supportTouch) { 8051 clearTimeout(vars.setTime); 8052 vars.setTime = setTimeout(function() { 8053 var scrollTop = getScrollXY().y; 8054 window.scrollTo(0, scrollTop - 30); 8055 window.scrollTo(0, scrollTop + 30); 8056 window.scrollTo(0, scrollTop); 8057 }, 2000); 8058 } 8059 if (vars.thumbs) iL.positionThumbnails(); 8060 }).bind('keydown.iLightBox', function(event) { 8061 if (opts.controls.keyboard) { 8062 switch (event.keyCode) { 8063 case 13: 8064 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 8065 break; 8066 case 27: 8067 if (opts.keyboard.esc) iL.closeAction(); 8068 break; 8069 case 37: 8070 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 8071 break; 8072 case 38: 8073 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 8074 break; 8075 case 39: 8076 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 8077 break; 8078 case 40: 8079 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 8080 break; 8081 } 8082 } 8083 }); 8084 8085 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 8086 iL.doFullscreen(); 8087 }); 8088 8089 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 8090 return arr.lastIndexOf(e) === i; 8091 }), 8092 holderEvents = ""; 8093 8094 $.each(holderEventsArr, function(key, val) { 8095 if (key != 0) holderEvents += ' '; 8096 holderEvents += val; 8097 }); 8098 8099 $doc.on(clickEvent, '.ilightbox-overlay', function() { 8100 if (opts.overlay.blur) iL.closeAction(); 8101 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 8102 iL.moveTo('next'); 8103 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 8104 iL.moveTo('prev'); 8105 }).on(clickEvent, '.ilightbox-thumbnail', function() { 8106 var t = $(this), 8107 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 8108 index = thumbs.index(t); 8109 8110 if (index != vars.current) iL.goTo(index); 8111 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8112 var caption = $('div.ilightbox-caption', vars.holder), 8113 social = $('div.ilightbox-social', vars.holder), 8114 fadeSpeed = opts.effects.fadeSpeed; 8115 8116 if (vars.nextLock || vars.prevLock) { 8117 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 8118 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 8119 8120 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 8121 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 8122 } else { 8123 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 8124 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 8125 8126 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 8127 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 8128 } 8129 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 8130 if (e.type == 'mouseenter') vars.lockWheel = true; 8131 else vars.lockWheel = false;
8132 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 8133 var t = $(this); 8134 8135 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 8136 else if (t.hasClass('ilightbox-play')) { 8137 iL.resume(); 8138 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 8139 } else if (t.hasClass('ilightbox-pause')) { 8140 iL.pause(); 8141 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 8142 } else iL.closeAction(); 8143 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 8144 // prevent scrolling 8145 e.preventDefault(); 8146 }); 8147 8148 function mouseMoveHandler(e) { 8149 if (!vars.isMobile) { 8150 if (!vars.mouseID) { 8151 vars.hideableElements.show(); 8152 } 8153 8154 vars.mouseID = clearTimeout(vars.mouseID); 8155 8156 if (buttonsArray.indexOf(e.target) === -1) 8157 vars.mouseID = setTimeout(function() { 8158 vars.hideableElements.hide(); 8159 vars.mouseID = clearTimeout(vars.mouseID); 8160 }, 3000); 8161 } 8162 } 8163 8164 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 8165 8166 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8167 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 8168 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 8169 }); 8170 8171 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'); 8172 8173 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 8174 if (!vars.lockWheel) { 8175 event.preventDefault(); 8176 if (delta < 0) iL.moveTo('next'); 8177 else if (delta > 0) iL.moveTo('prev'); 8178 } 8179 }); 8180 8181 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 8182 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 8183 8184 vars.BODY.addClass('ilightbox-closedhand'); 8185 8186 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 8187 scrollTop = $doc.scrollTop(), 8188 scrollLeft = $doc.scrollLeft(), 8189 offsets = [ 8190 holders.eq(0).offset(), 8191 holders.eq(1).offset(), 8192 holders.eq(2).offset() 8193 ], 8194 offSet = [{ 8195 top: offsets[0].top - scrollTop, 8196 left: offsets[0].left - scrollLeft 8197 }, { 8198 top: offsets[1].top - scrollTop, 8199 left: offsets[1].left - scrollLeft 8200 }, { 8201 top: offsets[2].top - scrollTop, 8202 left: offsets[2].left - scrollLeft 8203 }], 8204 start = { 8205 time: (new Date()).getTime(), 8206 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8207 }, 8208 stop; 8209 8210 function moveEachHandler(i) { 8211 var t = $(this), 8212 offset = offSet[i], 8213 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 8214 8215 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 8216 } 8217 8218 function moveHandler(event) { 8219 8220 if (!start) return; 8221 8222 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 8223 8224 stop = { 8225 time: (new Date()).getTime(), 8226 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8227 }; 8228 8229 holders.each(moveEachHandler); 8230 8231 // prevent scrolling 8232 event.preventDefault(); 8233 } 8234 8235 function repositionHolders() { 8236 holders.each(function() { 8237 var t = $(this), 8238 offset = t.data('offset') || { 8239 top: t.offset().top - scrollTop, 8240 left: t.offset().left - scrollLeft 8241 }, 8242 top = offset.top, 8243 left = offset.left; 8244 8245 t.css(transform, gpuAcceleration).stop().animate({ 8246 top: top, 8247 left: left 8248 }, 500, 'easeOutCirc', function() { 8249 t.css(transform, ''); 8250 }); 8251 }); 8252 } 8253 8254 holders.bind(touchMoveEvent, moveHandler); 8255 $doc.one(touchStopEvent, function(event) { 8256 holders.unbind(touchMoveEvent, moveHandler); 8257 8258 vars.BODY.removeClass('ilightbox-closedhand'); 8259 8260 if (start && stop) { 8261 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 8262 if (start.coords[0] > stop.coords[0]) { 8263 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8264 else { 8265 vars.isSwipe = true; 8266 iL.moveTo('next'); 8267 } 8268 } else { 8269 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8270 else { 8271 vars.isSwipe = true; 8272 iL.moveTo('prev'); 8273 } 8274 } 8275 } 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) { 8276 if (start.coords[1] > stop.coords[1]) { 8277 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8278 else { 8279 vars.isSwipe = true; 8280 iL.moveTo('next'); 8281 } 8282 } else { 8283 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8284 else { 8285 vars.isSwipe = true; 8286 iL.moveTo('prev'); 8287 } 8288 } 8289 } else repositionHolders(); 8290 } 8291 start = stop = undefined; 8292 }); 8293 }); 8294 8295 }, 8296 8297 goTo: function(index) { 8298 var iL = this, 8299 vars = iL.vars, 8300 opts = iL.options, 8301 diff = (index - vars.current); 8302 8303 if (opts.infinite) { 8304 if (index == vars.total - 1 && vars.current == 0) diff = -1; 8305 if (vars.current == vars.total - 1 && index == 0) diff = 1; 8306 } 8307 8308 if (diff == 1) iL.moveTo('next'); 8309 else if (diff == -1) iL.moveTo('prev'); 8310 else { 8311 8312 if (vars.nextLock || vars.prevLock) return false;
8313 8314 //Trigger the onBeforeChange callback 8315 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 8316 8317 if (opts.linkId) { 8318 vars.hashLock = true; 8319 window.location.hash = opts.linkId + '/' + index; 8320 } 8321 8322 if (iL.items[index]) { 8323 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 8324 else iL.vars.lockWheel = false; 8325 8326 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 8327 else vars.lockSwipe = false; 8328 } 8329 8330 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 8331 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 8332 }); 8333 8334 vars.current = index; 8335 vars.next = index + 1; 8336 vars.prev = index - 1; 8337 8338 iL.createUI(); 8339 8340 setTimeout(function() { 8341 iL.generateBoxes(); 8342 }, opts.effects.loadedFadeSpeed + 50); 8343 8344 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 8345 iL.positionThumbnails(); 8346 8347 if (opts.linkId) setTimeout(function() { 8348 vars.hashLock = false; 8349 }, 55); 8350 8351 // Configure arrow buttons 8352 if (!opts.infinite) { 8353 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8354 8355 if (vars.current == 0) { 8356 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8357 } 8358 if (vars.current >= vars.total - 1) { 8359 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8360 } 8361 } 8362 8363 // Reset next cycle timeout 8364 iL.resetCycle(); 8365 8366 //Trigger the onAfterChange callback 8367 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 8368 } 8369 }, 8370 8371 moveTo: function(side) { 8372 var iL = this, 8373 vars = iL.vars, 8374 opts = iL.options, 8375 path = opts.path.toLowerCase(), 8376 viewport = getViewport(), 8377 switchSpeed = opts.effects.switchSpeed; 8378 8379 if (vars.nextLock || vars.prevLock) return false; 8380 else { 8381 8382 var item = (side == "next") ? vars.next : vars.prev; 8383 8384 if (opts.linkId) { 8385 vars.hashLock = true; 8386 window.location.hash = opts.linkId + '/' + item; 8387 } 8388 8389 if (side == "next") { 8390 if (!iL.items[item]) return false; 8391 var firstHolder = vars.nextPhoto, 8392 secondHolder = vars.holder, 8393 lastHolder = vars.prevPhoto, 8394 firstClass = 'ilightbox-prev', 8395 secondClass = 'ilightbox-next'; 8396 } else if (side == "prev") { 8397 if (!iL.items[item]) return false; 8398 var firstHolder = vars.prevPhoto, 8399 secondHolder = vars.holder, 8400 lastHolder = vars.nextPhoto, 8401 firstClass = 'ilightbox-next', 8402 secondClass = 'ilightbox-prev'; 8403 } 8404 8405 //Trigger the onBeforeChange callback 8406 if (typeof opts.callback.onBeforeChange == 'function') 8407 opts.callback.onBeforeChange.call(iL, iL.ui); 8408 8409 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 8410 8411 var captionFirst = $('div.ilightbox-caption', secondHolder), 8412 socialFirst = $('div.ilightbox-social', secondHolder); 8413 8414 if (captionFirst.length) 8415 captionFirst.stop().fadeOut(switchSpeed, function() { 8416 $(this).remove(); 8417 }); 8418 if (socialFirst.length) 8419 socialFirst.stop().fadeOut(switchSpeed, function() { 8420 $(this).remove(); 8421 }); 8422 8423 if (iL.items[item].caption) { 8424 iL.setCaption(iL.items[item], firstHolder); 8425 var caption = $('div.ilightbox-caption', firstHolder), 8426 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 8427 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 8428 } 8429 8430 var social = iL.items[item].options.social; 8431 if (social) { 8432 iL.setSocial(social, iL.items[item].URL, firstHolder); 8433 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 8434 } 8435 8436 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 8437 val.removeClass('ilightbox-next ilightbox-prev'); 8438 }); 8439 8440 var firstOffset = firstHolder.data('offset'), 8441 winW = (viewport.width - (opts.styles.pageOffsetX)), 8442 winH = (viewport.height - (opts.styles.pageOffsetY)), 8443 width = firstOffset.newDims.width, 8444 height = firstOffset.newDims.height, 8445 thumbsOffset = firstOffset.thumbsOffset, 8446 diff = firstOffset.diff, 8447 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8448 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8449 8450 var secondOffset = secondHolder.data('offset'), 8451 object = secondOffset.object; 8452 8453 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8454 var objRatio = width / height; 8455 height = height - vars.captionHeight; 8456 width = height * objRatio; 8457 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 8458 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8459 }*/ 8460 8461 firstHolder.show().css(transform, gpuAcceleration).animate({ 8462 top: top, 8463 left: left, 8464 opacity: 1 8465 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8466 firstHolder.css(transform, ''); 8467 }); 8468 8469 $('div.ilightbox-container', firstHolder).animate({ 8470 width: width, 8471 height: height 8472 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8473 8474 diff = secondOffset.diff; 8475 8476 width = secondOffset.newDims.width, 8477 height = secondOffset.newDims.height; 8478 8479 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8480 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8481 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 8482 8483 if (side == 'prev') 8484 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 8485 else { 8486 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 8487 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8488 } 8489 8490 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8491 var objRatio = width / height; 8492 height = height - vars.captionHeight; 8493 width = height * objRatio; 8494 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 8495 }*/ 8496 8497 $('div.ilightbox-container', secondHolder).animate({ 8498 width: width, 8499 height: height 8500 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8501 8502 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 8503 top: top, 8504 left: left, 8505 opacity: opts.styles.prevOpacity, 8506 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8507 secondHolder.css(transform, ''); 8508
8509 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 8510 iL.positionThumbnails(); 8511 8512 if (iL.items[item]) { 8513 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 8514 else vars.lockWheel = false; 8515 8516 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 8517 else vars.lockSwipe = false; 8518 } 8519 8520 vars.isSwipe = false; 8521 8522 // Remove iframe & video from previous slide 8523 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8524 $('div.ilightbox-container', secondHolder).empty(); 8525 } 8526 8527 if (side == "next") { 8528 vars.nextPhoto = lastHolder, 8529 vars.prevPhoto = secondHolder, 8530 vars.holder = firstHolder; 8531 8532 vars.nextPhoto.hide(); 8533 8534 vars.next = vars.next + 1, 8535 vars.prev = vars.current, 8536 vars.current = vars.current + 1; 8537 8538 if (opts.infinite) { 8539 if (vars.current > vars.total - 1) vars.current = 0; 8540 if (vars.current == vars.total - 1) vars.next = 0; 8541 if (vars.current == 0) vars.prev = vars.total - 1; 8542 } 8543 8544 iL.createUI(); 8545 8546 if (!iL.items[vars.next]) 8547 vars.nextLock = false; 8548 else 8549 iL.loadContent(iL.items[vars.next], 'next'); 8550 } else { 8551 vars.prevPhoto = lastHolder; 8552 vars.nextPhoto = secondHolder; 8553 vars.holder = firstHolder; 8554 8555 vars.prevPhoto.hide(); 8556 8557 vars.next = vars.current; 8558 vars.current = vars.prev; 8559 vars.prev = vars.current - 1; 8560 8561 if (opts.infinite) { 8562 if (vars.current == vars.total - 1) vars.next = 0; 8563 if (vars.current == 0) vars.prev = vars.total - 1; 8564 } 8565 8566 iL.createUI(); 8567 8568 if (!iL.items[vars.prev]) 8569 vars.prevLock = false; 8570 else 8571 iL.loadContent(iL.items[vars.prev], 'prev'); 8572 } 8573 8574 // Add iframe & video content for current slide 8575 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8576 iL.loadContent(iL.items[vars.current], 'current'); 8577 } 8578 8579 if (opts.linkId) setTimeout(function() { 8580 vars.hashLock = false; 8581 }, 55); 8582 8583 // Configure arrow buttons 8584 if (!opts.infinite) { 8585 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8586 8587 if (vars.current == 0) 8588 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8589 if (vars.current >= vars.total - 1) 8590 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8591 } 8592 8593 iL.repositionPhoto(); 8594 8595 // Reset next cycle timeout 8596 iL.resetCycle(); 8597 8598 //Trigger the onAfterChange callback 8599 if (typeof opts.callback.onAfterChange == 'function') 8600 opts.callback.onAfterChange.call(iL, iL.ui); 8601 }); 8602 8603 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 8604 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 8605 8606 lastHolder.css(transform, gpuAcceleration).animate({ 8607 top: top, 8608 left: left, 8609 opacity: opts.styles.nextOpacity 8610 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8611 lastHolder.css(transform, ''); 8612 }).addClass(secondClass); 8613 } 8614 }, 8615 8616 setCaption: function(obj, target) { 8617 var iL = this, 8618 caption = $('<div class="ilightbox-caption"></div>'); 8619 8620 if (obj.caption) { 8621 caption.html(obj.caption); 8622 $('div.ilightbox-container', target).append(caption); 8623 } 8624 }, 8625 8626 normalizeSocial: function(obj, url) { 8627 var iL = this, 8628 vars = iL.vars, 8629 opts = iL.options, 8630 baseURL = window.location.href; 8631 8632 $.each(obj, function(key, value) { 8633 if (!value) 8634 return true; 8635 8636 var item = key.toLowerCase(), 8637 source, text; 8638 8639 switch (item) { 8640 case 'facebook': 8641 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 8642 text = "Share on Facebook"; 8643 break; 8644 case 'twitter': 8645 source = "http://twitter.com/home?status={URL}", 8646 text = "Share on Twitter"; 8647 break; 8648 case 'googleplus': 8649 source = "https://plus.google.com/share?url={URL}", 8650 text = "Share on Google+"; 8651 break; 8652 case 'delicious': 8653 source = "http://delicious.com/post?url={URL}", 8654 text = "Share on Delicious"; 8655 break; 8656 case 'digg': 8657 source = "http://digg.com/submit?phase=2&url={URL}", 8658 text = "Share on Digg"; 8659 break; 8660 case 'reddit': 8661 source = "http://reddit.com/submit?url={URL}", 8662 text = "Share on reddit"; 8663 break; 8664 } 8665 8666 obj[key] = { 8667 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 8668 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 8669 text: value.text || text || "Share on " + key, 8670 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 8671 height: value.height || 360 8672 }; 8673 8674 }); 8675 8676 return obj; 8677 }, 8678 8679 setSocial: function(obj, url, target) { 8680 var iL = this, 8681 socialBar = $('<div class="ilightbox-social"></div>'), 8682 buttons = '<ul>'; 8683 8684 obj = iL.normalizeSocial(obj, url); 8685 8686 $.each(obj, function(key, value) { 8687 var item = key.toLowerCase(), 8688 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, '+')); 8689 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>'; 8690 }); 8691 8692 buttons += '</ul>'; 8693 8694 socialBar.html(buttons); 8695 $('div.ilightbox-container', target).append(socialBar); 8696 }, 8697 8698 fullScreenAction: function() { 8699 var iL = this, 8700 vars = iL.vars; 8701 8702 if (fullScreenApi.supportsFullScreen) { 8703 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 8704 else fullScreenApi.requestFullScreen(document.documentElement); 8705 } else { 8706 iL.doFullscreen(); 8707 } 8708 }, 8709 8710 doFullscreen: function() { 8711 var iL = this, 8712 vars = iL.vars, 8713 viewport = getViewport(), 8714 opts = iL.options; 8715 8716 if (opts.fullAlone) { 8717 var currentHolder = vars.holder, 8718 current = iL.items[vars.current], 8719 windowWidth = viewport.width, 8720 windowHeight = viewport.height, 8721 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 8722 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8723 8724 if (!vars.isInFullScreen) { 8725 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 8726 vars.overlay.css({ 8727 opacity: 1 8728 }); 8729 8730 $.each(hideElements, function(i, element) { 8731 element.hide(); 8732 }); 8733 8734 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 8735 8736 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8737 naturalWidthOld: currentHolder.data('naturalWidth'), 8738 naturalHeightOld: currentHolder.data('naturalHeight'), 8739 naturalWidth: windowWidth, 8740 naturalHeight: windowHeight 8741 }); 8742 else { 8743 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 8744 newWidth = windowWidth, 8745 newHeight = windowHeight, 8746 width = currentHolder.data('naturalWidth'), 8747 height = currentHolder.data('naturalHeight'); 8748 8749 if (viewport.toLowerCase() == 'fill') { 8750 newHeight = (newWidth / width) * height; 8751 8752 if (newHeight < windowHeight) { 8753 newWidth = (windowHeight / height) * width, 8754 newHeight = windowHeight; 8755 } 8756 } else if (viewport.toLowerCase() == 'fit') { 8757 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 8758 8759 newWidth = dims.width, 8760 newHeight = dims.height; 8761 } else if (viewport.toLowerCase() == 'stretch') { 8762 newWidth = newWidth, 8763 newHeight = newHeight; 8764 } else { 8765 var scale = (width > newWidth || height > newHeight) ? true : false, 8766 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 8767 newWidth = dims.width, 8768 newHeight = dims.height; 8769 } 8770 8771 currentHolder.data({ 8772 naturalWidthOld: currentHolder.data('naturalWidth'), 8773 naturalHeightOld: currentHolder.data('naturalHeight'), 8774 naturalWidth: newWidth, 8775 naturalHeight: newHeight 8776 }); 8777 } 8778 8779 $.each(elements, function(key, val) { 8780 val.addClass('ilightbox-fullscreen'); 8781 }); 8782 8783 //Trigger the onEnterFullScreen callback 8784 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 8785 } else { 8786 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 8787 vars.overlay.css({ 8788 opacity: iL.options.overlay.opacity 8789 }); 8790 8791 $.each(hideElements, function(i, element) { 8792 element.show(); 8793 }); 8794 8795 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 8796 8797 currentHolder.data({ 8798 naturalWidth: currentHolder.data('naturalWidthOld'), 8799 naturalHeight: currentHolder.data('naturalHeightOld'), 8800 naturalWidthOld: null, 8801 naturalHeightOld: null 8802 }); 8803 8804 $.each(elements, function(key, val) { 8805 val.removeClass('ilightbox-fullscreen'); 8806 }); 8807 8808 //Trigger the onExitFullScreen callback 8809 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 8810 } 8811 } else { 8812 if (!vars.isInFullScreen) vars.isInFullScreen = true; 8813 else vars.isInFullScreen = false; 8814 } 8815 iL.repositionPhoto(true); 8816 }, 8817 8818 closeAction: function() { 8819 var iL = this, 8820 vars = iL.vars, 8821 opts = iL.options; 8822 8823 $win.unbind('.iLightBox'); 8824 $doc.off('.iLightBox'); 8825 8826 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 8827 8828 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 8829 8830 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 8831 vars.overlay.remove(); 8832 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8833 }); 8834 else { 8835 vars.overlay.remove(); 8836 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8837 } 8838 8839 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8840 8841 $.each(fadeOuts, function(i, element) { 8842 element.removeAttr('style').remove(); 8843 }); 8844 8845 vars.dontGenerateThumbs = vars.isInFullScreen = false; 8846 8847 window.iLightBox = null; 8848 8849 if (opts.linkId) { 8850 vars.hashLock = true; 8851 removeHash(); 8852 setTimeout(function() { 8853 vars.hashLock = false; 8854 }, 55); 8855 } 8856 8857 //Trigger the onHide callback 8858 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 8859 }, 8860 8861 repositionPhoto: function() { 8862 var iL = this, 8863 vars = iL.vars, 8864 opts = iL.options, 8865 path = opts.path.toLowerCase(), 8866 viewport = getViewport(), 8867 winWidth = viewport.width, 8868 winHeight = viewport.height; 8869 8870 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 8871 8872 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 8873 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 8874 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 8875 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 8876 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, 8877 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))); 8878 8879 var elObject = { 8880 type: 'current', 8881 width: width, 8882 height: height, 8883 item: iL.items[vars.current], 8884 offsetW: offsetW, 8885 offsetH: offsetH,
8886 thumbsOffsetW: thumbsOffsetW, 8887 thumbsOffsetH: thumbsOffsetH, 8888 animate: arguments.length, 8889 holder: vars.holder 8890 }; 8891 8892 iL.repositionEl(elObject); 8893 8894 if (iL.items[vars.next]) { 8895 elObject = $.extend(elObject, { 8896 type: 'next', 8897 item: iL.items[vars.next], 8898 offsetX: opts.styles.nextOffsetX, 8899 offsetY: opts.styles.nextOffsetY, 8900 holder: vars.nextPhoto 8901 }); 8902 8903 iL.repositionEl(elObject); 8904 } 8905 8906 if (iL.items[vars.prev]) { 8907 elObject = $.extend(elObject, { 8908 type: 'prev', 8909 item: iL.items[vars.prev], 8910 offsetX: opts.styles.nextOffsetX, 8911 offsetY: opts.styles.prevOffsetY, 8912 holder: vars.prevPhoto 8913 }); 8914 8915 iL.repositionEl(elObject); 8916 } 8917 8918 var loaderCss = (path == "horizontal") ? { 8919 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 8920 } : { 8921 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 8922 }; 8923 vars.loader.css(loaderCss); 8924 }, 8925 8926 repositionEl: function(obj) { 8927 var iL = this, 8928 vars = iL.vars, 8929 opts = iL.options, 8930 path = opts.path.toLowerCase(), 8931 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 8932 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 8933 itemParent = obj.item, 8934 item = obj.item.options, 8935 holder = obj.holder, 8936 offsetX = obj.offsetX || 0, 8937 offsetY = obj.offsetY || 0, 8938 thumbsOffsetW = obj.thumbsOffsetW, 8939 thumbsOffsetH = obj.thumbsOffsetH; 8940 8941 if (obj.type == 'current') { 8942 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); 8943 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); 8944 } else { 8945 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 8946 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 8947 } 8948 8949 heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 8950 8951 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 8952 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 8953 8954 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 8955 width: width, 8956 height: height 8957 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 8958 newDims = $.extend({}, dims, {}); 8959 8960 if (obj.type == 'prev' || obj.type == 'next') 8961 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 8962 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 8963 else 8964 width = dims.width, 8965 height = dims.height; 8966 8967 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 8968 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); 8969 8970 switch (obj.type) { 8971 case 'current': 8972 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 8973 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8974 break; 8975
8976 case 'next': 8977 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 8978 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 8979 break; 8980 8981 case 'prev': 8982 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 8983 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8984 break; 8985 } 8986 8987 holder.data('offset', { 8988 top: top, 8989 left: left, 8990 newDims: newDims, 8991 diff: { 8992 W: widthDiff, 8993 H: heightDiff 8994 }, 8995 thumbsOffset: { 8996 W: thumbsOffsetW, 8997 H: thumbsOffsetH 8998 }, 8999 object: obj 9000 }); 9001 9002 var opacityMobile; 9003 if ( isMobile ) { 9004 opacityMobile = { 9005 opacity: 1, 9006 top: top, 9007 left: left 9008 }; 9009 } else { 9010 opacityMobile = { 9011 top: top, 9012 left: left 9013 }; 9014 } 9015 9016 if (obj.animate > 0 && opts.effects.reposition) { 9017 holder.css(transform, gpuAcceleration).stop().animate( 9018 opacityMobile, 9019 opts.effects.repositionSpeed, 'easeOutCirc', function() { 9020 holder.css(transform, ''); 9021 }); 9022 $('div.ilightbox-container', holder).stop().animate({ 9023 width: width, 9024 height: height 9025 }, opts.effects.repositionSpeed, 'easeOutCirc'); 9026 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 9027 width: width 9028 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 9029 $(this).css('overflow', 'visible'); 9030 }); 9031 } else { 9032 holder.css(opacityMobile); 9033 $('div.ilightbox-container', holder).css({ 9034 width: width, 9035 height: height 9036 }); 9037 $('div.ilightbox-inner-toolbar', holder).css({ 9038 width: width 9039 }); 9040 } 9041 }, 9042 9043 9044 resume: function(priority) { 9045 var iL = this, 9046 vars = iL.vars, 9047 opts = iL.options; 9048 9049 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 9050 return; 9051 } 9052 9053 vars.isPaused = 0; 9054 9055 if (vars.cycleID) { 9056 vars.cycleID = clearTimeout(vars.cycleID); 9057 } 9058 9059 vars.cycleID = setTimeout(function() { 9060 if (vars.current == vars.total - 1) iL.goTo(0); 9061 else iL.moveTo('next'); 9062 }, opts.slideshow.pauseTime); 9063 }, 9064 9065 pause: function(priority) { 9066 var iL = this, 9067 vars = iL.vars, 9068 opts = iL.options; 9069 9070 if (priority < vars.isPaused) { 9071 return; 9072 } 9073 9074 vars.isPaused = priority || 100; 9075 9076 if (vars.cycleID) { 9077 vars.cycleID = clearTimeout(vars.cycleID); 9078 } 9079 }, 9080 9081 resetCycle: function() { 9082 var iL = this, 9083 vars = iL.vars, 9084 opts = iL.options; 9085 9086 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 9087 iL.resume(); 9088 } 9089 }, 9090 9091 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 9092 var iL = this; 9093 9094 if (!width) factor = height / height_old; 9095 else if (!height) factor = width / width_old; 9096 else factor = min(width / width_old, height / height_old); 9097 9098 if (!thumb) { 9099 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 9100 else if (factor < iL.options.minScale) factor = iL.options.minScale; 9101 } 9102 9103 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 9104 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 9105 9106 return { 9107 width: final_width, 9108 height: final_height, 9109 ratio: factor 9110 }; 9111 }, 9112 9113 setOption: function(options) { 9114 var iL = this; 9115 9116 iL.options = $.extend(true, iL.options, options || {}); 9117 iL.refresh(); 9118 }, 9119 9120 availPlugins: function() { 9121 var iL = this, 9122 testEl = document.createElement("video"); 9123 9124 iL.plugins = { 9125 flash: !isMobile, 9126 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 9127 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 9128 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 9129 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 9130 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 9131 }; 9132 }, 9133 9134 addContent: function(element, obj) { 9135 var iL = this, 9136 el; 9137 9138 switch (obj.type) { 9139 case 'video': 9140 var HTML5 = false, 9141 videoType = obj.videoType, 9142 html5video = obj.options.html5video; 9143 9144 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 9145 obj.ext = 'mp4', 9146 obj.URL = html5video.h264 || obj.URL; 9147 else if (html5video.webm && iL.plugins.html5WebM) 9148 obj.ext = 'webm', 9149 obj.URL = html5video.webm || obj.URL; 9150 else if (html5video.ogg && iL.plugins.html5Vorbis) 9151 obj.ext = 'ogv', 9152 obj.URL = html5video.ogg || obj.URL; 9153 9154 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 9155 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 9156 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 9157 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 9158 9159 if (HTML5) { 9160 el = $('<video />
9160', { 9161 "width": "100%", 9162 "height": "100%", 9163 "preload": html5video.preload, 9164 "autoplay": html5video.autoplay, 9165 "loop": html5video.loop, 9166 "poster": html5video.poster, 9167 "controls": html5video.controls, 9168 "controlslist": "nodownload" 9169 }).append($('<source />', { 9170 "src": obj.URL, 9171 "type": videoType 9172 })); 9173 } else { 9174 if (!iL.plugins.quicktime) el = $('<span />', { 9175 "class": "ilightbox-alert", 9176 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 9177 }); 9178 else { 9179 9180 el = $('<object />', { 9181 "type": "video/quicktime", 9182 "pluginspage": pluginspages.quicktime 9183 }).attr({ 9184 "data": obj.URL, 9185 "width": "100%", 9186 "height": "100%" 9187 }).append($('<param />', { 9188 "name": "src", 9189 "value": obj.URL 9190 })).append($('<param />', { 9191 "name": "autoplay", 9192 "value": "false" 9193 })).append($('<param />', { 9194 "name": "loop", 9195 "value": "false" 9196 })).append($('<param />', { 9197 "name": "scale", 9198 "value": "tofit" 9199 })); 9200 9201 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 9202 } 9203 } 9204 9205 break; 9206 9207 case 'flash': 9208 if (!iL.plugins.flash) el = $('<span />', { 9209 "class": "ilightbox-alert", 9210 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 9211 }); 9212 else { 9213 var flashvars = "", 9214 i = 0; 9215 9216 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 9217 if (i != 0) flashvars += "&"; 9218 flashvars += k + "=" + encodeURIComponent(v); 9219 i++; 9220 }); 9221 else flashvars = null; 9222 9223 el = $('<embed />').attr({ 9224 "type": "application/x-shockwave-flash", 9225 "src": obj.URL, 9226 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9227 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9228 "quality": "high", 9229 "bgcolor": "#000000", 9230 "play": "true", 9231 "loop": "true", 9232 "menu": "true", 9233 "wmode": "transparent", 9234 "scale": "showall", 9235 "allowScriptAccess": "always", 9236 "allowFullScreen": "true", 9237 "flashvars": flashvars, 9238 "fullscreen": "yes" 9239 }); 9240 } 9241 9242 break; 9243 9244 case 'iframe': 9245 el = $('<iframe />').attr({ 9246 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9247 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9248 src: obj.URL, 9249 frameborder: 0, 9250 'hspace': 0, 9251 'vspace': 0, 9252 'scrolling': supportTouch ? 'auto' : 'scroll', 9253 'webkitAllowFullScreen': '', 9254 'mozallowfullscreen': '', 9255 'allowFullScreen': '' 9256 }); 9257 9258 break; 9259 9260 case 'inline': 9261 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 9262 9263 break; 9264 9265 case 'html': 9266 var object = obj.URL, 9267 el; 9268 9269 if (object[0].nodeName) { 9270 el = $('<div class="ilightbox-wrapper"></div>').html(object); 9271 } else { 9272 var dom = $(obj.URL), 9273 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 9274 el = $('<div class="ilightbox-wrapper"></div>').html(html); 9275 } 9276 9277 break; 9278 } 9279 9280 $('div.ilightbox-container', element).empty().html(el); 9281 9282 // For fixing Chrome about just playing the video for first time 9283 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 9284 var src = el[0].currentSrc + '?' + floor(random() * 30000); 9285 el[0].currentSrc = src; 9286 el[0].src = src; 9287 }); 9288 9289 return el; 9290 }, 9291 9292 ogpRecognition: function(obj, callback) { 9293 var iL = this, 9294 url = obj.URL; 9295 9296 iL.showLoader(); 9297 doAjax(url, function(data) { 9298 iL.hideLoader(); 9299 if (data) { 9300 var object = new Object(); 9301 9302 object.length = false, 9303 object.url = data.url; 9304 9305 if (data.status == 200) { 9306 var result = data.results, 9307 type = result.type, 9308 source = result.source; 9309 9310 object.source = source.src, 9311 object.width = source.width && parseInt(source.width) || 0, 9312 object.height = source.height && parseInt(source.height) || 0, 9313 object.type = type, 9314 object.thumbnail = source.thumbnail || result.images && result.images[0], 9315 object.html5video = result.html5video || {}, 9316 object.length = true; 9317 9318 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 9319 else if (source.type.indexOf("video/") != -1) object.type = "video"; 9320 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 9321 else if (source.type.indexOf("image/") != -1) object.type = "image"; 9322 9323 } else if (typeof data.response != 'undefined') 9324 throw data.response; 9325 9326 callback.call(this, object.length ? object : false); 9327 } 9328 }); 9329 }, 9330 9331 hashChangeHandler: function(url) { 9332 var iL = this, 9333 vars = iL.vars, 9334 opts = iL.options, 9335 URL = url || window.location.href, 9336 hash = parseURI(URL).hash, 9337 split = hash.split('/'), 9338 index = split[1]; 9339 9340 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 9341 9342 if (index) { 9343 var target = split[1] || 0; 9344 if (iL.items[target]) {
9345 var overlay = $('.ilightbox-overlay'); 9346 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 9347 iL.goTo(target); 9348 } else { 9349 iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click'); 9350 //iL.goTo(target); 9351 } 9352 } else { 9353 var overlay = $('.ilightbox-overlay'); 9354 if (overlay.length) iL.closeAction(); 9355 } 9356 } else { 9357 var overlay = $('.ilightbox-overlay'); 9358 if (overlay.length) iL.closeAction(); 9359 } 9360 } 9361 }; 9362 9363 /** 9364 * Parse style to pixels. 9365 * 9366 * @param {Object} $element jQuery object with element. 9367 * @param {Property} property CSS property to get the pixels from. 9368 * 9369 * @return {Int} 9370 */ 9371 function getPixel($element, property) { 9372 return parseInt($element.css(property), 10) || 0; 9373 } 9374 9375 /** 9376 * Make sure that number is within the limits. 9377 * 9378 * @param {Number} number 9379 * @param {Number} min 9380 * @param {Number} max 9381 * 9382 * @return {Number} 9383 */ 9384 function within(number, min, max) { 9385 return number < min ? min : number > max ? max : number; 9386 } 9387 9388 /** 9389 * Get viewport/window size (width and height). 9390 * 9391 * @return {Object} 9392 */ 9393 function getViewport() { 9394 var e = window, 9395 a = 'inner'; 9396 if (!('innerWidth' in window)) { 9397 a = 'client'; 9398 e = document.documentElement || document.body; 9399 } 9400 return { 9401 width: e[a + 'Width'], 9402 height: e[a + 'Height'] 9403 } 9404 } 9405 9406 /** 9407 * Remove hash tag from the URL 9408 * 9409 * @return {Void} 9410 */ 9411 function removeHash() { 9412 var scroll = getScrollXY(); 9413 9414 //UNCODE change 9415 //window.location.hash = ""; 9416 history.pushState("", document.title, window.location.pathname + window.location.search); 9417 9418 // Restore the scroll offset, should be flicker free 9419 window.scrollTo(scroll.x, scroll.y); 9420 } 9421 9422 /** 9423 * Do the ajax requests with callback. 9424 * 9425 * @param {String} url 9426 * @param {Function} callback 9427 * 9428 * @return {Void} 9429 */ 9430 function doAjax(url, callback) { 9431 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'); 9432 $.ajax({ 9433 url: url, 9434 dataType: 'jsonp' 9435 }); 9436 9437 iLCallback = function(data) { 9438 callback.call(this, data); 9439 }; 9440 } 9441 9442 /** 9443 * Find image from DOM elements 9444 * 9445 * @param {Element} element 9446 * 9447 * @return {Void} 9448 */ 9449 function findImageInElement(element) { 9450 var elements = $('*', element), 9451 imagesArr = new Array(); 9452 9453 elements.each(function() { 9454 var url = "", 9455 element = this; 9456 9457 if ($(element).css("background-image") != "none") { 9458 url = $(element).css("background-image"); 9459 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 9460 url = $(element).attr("src"); 9461 } 9462 9463 if (url.indexOf("gradient") == -1) { 9464 url = url.replace(/url\(\"/g, ""); 9465 url = url.replace(/url\(/g, ""); 9466 url = url.replace(/\"\)/g, ""); 9467 url = url.replace(/\)/g, ""); 9468 9469 var urls = url.split(","); 9470 9471 for (var i = 0; i < urls.length; i++) { 9472 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 9473 var extra = ""; 9474 if (browser.msie && browser.version < 9) { 9475 extra = "?" + floor(random() * 3000); 9476 } 9477 imagesArr.push(urls[i] + extra); 9478 } 9479 } 9480 } 9481 }); 9482 9483 return imagesArr; 9484 } 9485 9486 /** 9487 * Get file extension. 9488 * 9489 * @param {String} URL 9490 * 9491 * @return {String} 9492 */ 9493 function getExtension(URL) { 9494 if (URL !== null) { 9495 var ext = URL.split('.').pop().toLowerCase(), 9496 extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : ''; 9497 9498 //UNCODE: fix issue to detect media type with query strings 9499 ext = ext.replace('?'+extra, ''); 9500 9501 return ext.replace(extra, ''); 9502 } 9503 } 9504 9505 /** 9506 * Get type via extension. 9507 * 9508 * @param {String} URL 9509 * 9510 * @return {String} 9511 */ 9512 function getTypeByExtension(URL) { 9513 var type, 9514 ext = getExtension(URL); 9515 9516 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 9517 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 9518 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 9519 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 9520 else type = 'iframe'; 9521 9522 return type; 9523 } 9524 9525 /** 9526 * Return value from percent of a number. 9527 * 9528 * @param {Number} percent 9529 * @param {Number} total 9530 * 9531 * @return {Number} 9532 */ 9533 function percentToValue(percent, total) { 9534 return parseInt((total / 100) * percent); 9535 } 9536 9537 /** 9538 * A JavaScript equivalent of PHP’s parse_url. 9539 * 9540 * @param {String} url The URL to parse. 9541 * 9542 * @return {Mixed} 9543 */ 9544 function parseURI(url) { 9545 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 9546 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 9547 return (m ? { 9548 href: m[0] || '', 9549 protocol: m[1] || '', 9550 authority: m[2] || '', 9551 host: m[3] || '', 9552 hostname: m[4] || '', 9553 port: m[5] || '', 9554 pathname: m[6] || '', 9555 search: m[7] || '', 9556 hash: m[8] || '' 9557 } : null); 9558 } 9559 9560 /** 9561 * Gets the absolute URI. 9562 * 9563 * @param {String} href The relative URL. 9564 * @param {String} base The base URL. 9565 * 9566 * @return {String} The absolute URL. 9567 */ 9568 function absolutizeURI(base, href) { // RFC 3986 9569 var iL = this; 9570 9571 function removeDotSegments(input) { 9572 var output = []; 9573 input.replace(/^(\.\.?(\/|$))+/, '') 9574 .replace(/\/(\.(\/|$))+/g, '/') 9575 .replace(/\/\.\.$/, '/../') 9576 .replace(/\/?[^\/]*/g, function(p) { 9577 if (p === '/..') { 9578 output.pop(); 9579 } else { 9580 output.push(p); 9581 } 9582 }); 9583 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 9584 } 9585 9586 href = parseURI(href || ''); 9587 base = parseURI(base || ''); 9588 9589 return !href || !base ? null : (href.protocol || base.protocol) + 9590 (href.protocol || href.authority ? href.authority : base.authority) + 9591 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)) + 9592 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 9593 href.hash; 9594 } 9595 9596 /** 9597 * A JavaScript equivalent of PHP’s version_compare. 9598 * 9599 * @param {String} v1 9600 * @param {String} v2 9601 * @param {String} operator
9602 * 9603 * @return {Boolean} 9604 */ 9605 function version_compare(v1, v2, operator) { 9606 this.php_js = this.php_js || {}; 9607 this.php_js.ENV = this.php_js.ENV || {}; 9608 var i = 0, 9609 x = 0, 9610 compare = 0, 9611 vm = { 9612 'dev': -6, 9613 'alpha': -5, 9614 'a': -5, 9615 'beta': -4, 9616 'b': -4, 9617 'RC': -3, 9618 'rc': -3, 9619 '#': -2, 9620 'p': 1, 9621 'pl': 1 9622 }, 9623 prepVersion = function(v) { 9624 v = ('' + v).replace(/[_\-+]/g, '.'); 9625 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 9626 return (!v.length ? [-8] : v.split('.')); 9627 }, 9628 numVersion = function(v) { 9629 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 9630 }; 9631 v1 = prepVersion(v1); 9632 v2 = prepVersion(v2); 9633 x = max(v1.length, v2.length); 9634 for (i = 0; i < x; i++) { 9635 if (v1[i] == v2[i]) { 9636 continue; 9637 } 9638 v1[i] = numVersion(v1[i]); 9639 v2[i] = numVersion(v2[i]); 9640 if (v1[i] < v2[i]) { 9641 compare = -1; 9642 break; 9643 } else if (v1[i] > v2[i]) { 9644 compare = 1; 9645 break; 9646 } 9647 } 9648 if (!operator) { 9649 return compare; 9650 } 9651 9652 switch (operator) { 9653 case '>': 9654 case 'gt': 9655 return (compare > 0); 9656 case '>=': 9657 case 'ge': 9658 return (compare >= 0); 9659 case '<=': 9660 case 'le': 9661 return (compare <= 0); 9662 case '==': 9663 case '=': 9664 case 'eq': 9665 return (compare === 0); 9666 case '<>': 9667 case '!=': 9668 case 'ne': 9669 return (compare !== 0); 9670 case '': 9671 case '<': 9672 case 'lt': 9673 return (compare < 0); 9674 default: 9675 return null; 9676 } 9677 } 9678 9679 9680 // Begin the iLightBox plugin 9681 $.fn.iLightBox = function() { 9682 9683 var args = arguments, 9684 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 9685 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 9686 9687 if (!opt) opt = {}; 9688 9689 // Default options. Play carefully. 9690 var options = $.extend(true, { 9691 attr: 'href', 9692 path: 'vertical', 9693 skin: 'dark', 9694 linkId: false, 9695 infinite: false, 9696 startFrom: 0, 9697 randomStart: false, 9698 keepAspectRatio: true, 9699 maxScale: 1, 9700 minScale: .2, 9701 innerToolbar: false, 9702 smartRecognition: false, 9703 mobileOptimizer: true, 9704 fullAlone: true, 9705 fullViewPort: null, 9706 fullStretchTypes: 'flash, video', 9707 overlay: { 9708 blur: true, 9709 opacity: .85 9710 }, 9711 controls: { 9712 arrows: false, 9713 slideshow: false, 9714 toolbar: true, 9715 fullscreen: true, 9716 thumbnail: true, 9717 keyboard: true, 9718 mousewheel: true, 9719 swipe: true 9720 }, 9721 keyboard: { 9722 left: true, // previous 9723 right: true, // next 9724 up: true, // previous 9725 down: true, // next 9726 esc: true, // close 9727 shift_enter: true // fullscreen 9728 }, 9729 show: { 9730 effect: true, 9731 speed: 300, 9732 title: true 9733 }, 9734 hide: { 9735 effect: true, 9736 speed: 300 9737 }, 9738 caption: { 9739 start: true, 9740 show: 'mouseenter', 9741 hide: 'mouseleave' 9742 }, 9743 social: { 9744 start: true, 9745 show: 'mouseenter', 9746 hide: 'mouseleave',
9747 buttons: false 9748 }, 9749 styles: { 9750 pageOffsetX: 0, 9751 pageOffsetY: 0, 9752 nextOffsetX: 45, 9753 nextOffsetY: 0, 9754 nextOpacity: 1, 9755 nextScale: 1, 9756 prevOffsetX: 45, 9757 prevOffsetY: 0, 9758 prevOpacity: 1, 9759 prevScale: 1 9760 }, 9761 thumbnails: { 9762 maxWidth: 120, 9763 maxHeight: 80, 9764 normalOpacity: 1, 9765 activeOpacity: .6 9766 }, 9767 effects: { 9768 reposition: true, 9769 repositionSpeed: 200, 9770 switchSpeed: 500, 9771 loadedFadeSpeed: 180, 9772 fadeSpeed: 200 9773 }, 9774 slideshow: { 9775 pauseTime: 5000, 9776 pauseOnHover: false, 9777 startPaused: true 9778 }, 9779 text: { 9780 close: "Press Esc to close", 9781 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 9782 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 9783 slideShow: "Slideshow", 9784 next: "Next", 9785 previous: "Previous" 9786 }, 9787 errors: { 9788 loadImage: "An error occurred when trying to load photo.", 9789 loadContents: "An error occurred when trying to load contents.", 9790 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 9791 }, 9792 ajaxSetup: { 9793 url: '', 9794 beforeSend: function(jqXHR, settings) {}, 9795 cache: false, 9796 complete: function(jqXHR, textStatus) {}, 9797 crossDomain: false, 9798 error: function(jqXHR, textStatus, errorThrown) {}, 9799 success: function(data, textStatus, jqXHR) {}, 9800 global: true, 9801 ifModified: false, 9802 username: null, 9803 password: null, 9804 type: 'GET' 9805 }, 9806 callback: {} 9807 }, opt); 9808 9809 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 9810 9811 items = $.isArray(items) ? items : new Array(); 9812 9813 if (typeof args[0] == 'string') items[0] = args[0]; 9814 9815 if (version_compare($.fn.jquery, '1.8', '>=')) { 9816 var iLB = new iLightBox($(this), options, items, instant); 9817 return { 9818 close: function() { 9819 iLB.closeAction(); 9820 }, 9821 fullscreen: function() { 9822 iLB.fullScreenAction(); 9823 }, 9824 moveNext: function() { 9825 iLB.moveTo('next'); 9826 }, 9827 movePrev: function() { 9828 iLB.moveTo('prev'); 9829 }, 9830 goTo: function(index) { 9831 iLB.goTo(index); 9832 }, 9833 refresh: function() { 9834 iLB.refresh(); 9835 }, 9836 reposition: function() { 9837 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 9838 }, 9839 setOption: function(options) { 9840 iLB.setOption(options); 9841 }, 9842 destroy: function() { 9843 iLB.closeAction(); 9844 iLB.dispatchItemsEvents(); 9845 } 9846 }; 9847 } else { 9848 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 9849 } 9850 9851 }; 9852 9853 9854 $.iLightBox = function() { 9855 return $.fn.iLightBox(arguments[0], arguments[1]); 9856 }; 9857 9858 9859 $.extend($.easing, { 9860 easeInCirc: function(x, t, b, c, d) { 9861 return -c * (sqrt(1 - (t /= d) * t) - 1) + b; 9862 }, 9863 easeOutCirc: function(x, t, b, c, d) { 9864 return c * sqrt(1 - (t = t / d - 1) * t) + b; 9865 }, 9866 easeInOutCirc: function(x, t, b, c, d) { 9867 if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; 9868 return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b; 9869 } 9870 }); 9871 9872 function getScrollXY() { 9873 var scrOfX = 0, 9874 scrOfY = 0; 9875 if (typeof(window.pageYOffset) == 'number') { 9876 //Netscape compliant 9877 scrOfY = window.pageYOffset; 9878 scrOfX = window.pageXOffset; 9879 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 9880 //DOM compliant 9881 scrOfY = document.body.scrollTop; 9882 scrOfX = document.body.scrollLeft; 9883 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 9884 //IE6 standards compliant mode 9885 scrOfY = document.documentElement.scrollTop; 9886 scrOfX = document.documentElement.scrollLeft; 9887 } 9888 return { 9889 x: scrOfX, 9890 y: scrOfY 9891 }; 9892 } 9893 9894 (function() { 9895 // add new event shortcuts 9896 $.each(("touchstart touchmove touchend " + 9897 "tap taphold " + 9898 "swipe swipeleft swiperight " + 9899 "scrollstart scrollstop").split(" "), function(i, name) { 9900 9901 $.fn[name] = function(fn) { 9902 return fn ? this.bind(name, fn) : this.trigger(name); 9903 }; 9904 9905 // jQuery < 1.8 9906 // if ($.attrFn) { 9907 // $.attrFn[name] = true; 9908 // } 9909 }); 9910 9911 var tapSettings = { 9912 startEvent: 'touchstart.iTap', 9913 endEvent: 'touchend.iTap' 9914 }; 9915 9916 // tap Event: 9917 $.event.special.itap = { 9918 setup: function() { 9919 9920 var self = this, 9921 $self = $(this), 9922 start, stop; 9923 9924 $self.bind(tapSettings.startEvent, function(event) { 9925 start = getScrollXY(); 9926 9927 $self.one(tapSettings.endEvent, function(event) { 9928 stop = getScrollXY(); 9929 9930 var orgEvent = event || window.event; 9931 event = $.event.fix(orgEvent); 9932 event.type = "itap"; 9933 9934 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 9935 9936 start = stop = undefined; 9937 }); 9938 }); 9939 }, 9940 9941 teardown: function() { 9942 $(this).unbind(tapSettings.startEvent); 9943 } 9944 }; 9945 }()); 9946 9947 9948 //Fullscreen API 9949 (function() { 9950 fullScreenApi = { 9951 supportsFullScreen: false, 9952 isFullScreen: function() { 9953 return false;
9954 }, 9955 requestFullScreen: function() {}, 9956 cancelFullScreen: function() {}, 9957 fullScreenEventName: '', 9958 prefix: '' 9959 }, 9960 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 9961 9962 // check for native support 9963 if (typeof document.cancelFullScreen != 'undefined') { 9964 fullScreenApi.supportsFullScreen = true; 9965 } else { 9966 // check for fullscreen support by vendor prefix 9967 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 9968 fullScreenApi.prefix = browserPrefixes[i]; 9969 9970 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 9971 fullScreenApi.supportsFullScreen = true; 9972 9973 break; 9974 } 9975 } 9976 } 9977 9978 // update methods to do something useful 9979 if (fullScreenApi.supportsFullScreen) { 9980 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 9981 9982 fullScreenApi.isFullScreen = function() { 9983 switch (this.prefix) { 9984 case '': 9985 return document.fullScreen; 9986 case 'webkit': 9987 return document.webkitIsFullScreen; 9988 default: 9989 return document[this.prefix + 'FullScreen']; 9990 } 9991 } 9992 fullScreenApi.requestFullScreen = function(el) { 9993 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 9994 } 9995 fullScreenApi.cancelFullScreen = function(el) { 9996 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 9997 } 9998 } 9999 }()); 10000 10001 // Browser detect 10002 (function() { 10003 function uaMatch(ua) { 10004 ua = ua.toLowerCase(); 10005 10006 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 10007 /(webkit)[ \/]([\w.]+)/.exec(ua) || 10008 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 10009 /(msie) ([\w.]+)/.exec(ua) || 10010 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 10011 10012 return { 10013 browser: match[1] || "", 10014 version: match[2] || "0" 10015 }; 10016 } 10017 10018 var matched = uaMatch(navigator.userAgent); 10019 browser = {}; 10020 10021 if (matched.browser) { 10022 browser[matched.browser] = true; 10023 browser.version = matched.version; 10024 } 10025 10026 // Chrome is Webkit, but Webkit is also Safari. 10027 if (browser.chrome) { 10028 browser.webkit = true; 10029 } else if (browser.webkit) { 10030 browser.safari = true; 10031 } 10032 }()); 10033 10034 // Feature detects 10035 (function() { 10036 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 10037 var el = document.createElement('div'); 10038 10039 function testProp(prop) { 10040 for (var p = 0, pl = prefixes.length; p < pl; p++) { 10041 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 10042 if (el.style[prefixedProp] !== undefined) { 10043 return prefixedProp; 10044 } 10045 } 10046 } 10047 10048 // Global support indicators 10049 transform = testProp('transform') || ''; 10050 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 10051 }()); 10052 10053 10054 /* 10055 PluginDetect v0.7.9 10056 www.pinlady.net/PluginDetect/license/ 10057 [ getVersion onWindowLoaded BetterIE ] 10058 [ Flash QuickTime Shockwave ] 10059 */ 10060 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;
10060d++){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);
10060d.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)}
10060c.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;
10060if(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(); 10061 10062 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)}; 10063 10064 10065 /* 10066 jQuery hashchange event v1.3 10067 https://github.com/cowboy/jquery-hashchange 10068 Copyright (c) 2010 "Cowboy" Ben Alman 10069 Dual licensed under the MIT and GPL licenses. 10070 */ 10071 (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= 10072 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|| 10073 "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;
10073a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 10074 10075 if (!Array.prototype.filter) { 10076 Array.prototype.filter = function(fun /*, thisp */ ) { 10077 "use strict"; 10078 10079 if (this == null) 10080 throw new TypeError(); 10081 10082 var t = Object(this); 10083 var len = t.length >>> 0; 10084 if (typeof fun != "function") 10085 throw new TypeError(); 10086 10087 var res = []; 10088 var thisp = arguments[1]; 10089 for (var i = 0; i < len; i++) { 10090 if (i in t) { 10091 var val = t[i]; // in case fun mutates this 10092 if (fun.call(thisp, val, i, t)) 10093 res.push(val); 10094 } 10095 } 10096 10097 return res; 10098 }; 10099 } 10100 10101 if (!Array.prototype.indexOf) { 10102 Array.prototype.indexOf = function(searchElement, fromIndex) { 10103 var k; 10104 10105 if (this == null) { 10106 throw new TypeError('"this" is null or not defined'); 10107 } 10108 10109 var O = Object(this); 10110 10111 var len = O.length >>> 0; 10112 10113 if (len === 0) { 10114 return -1; 10115 } 10116 10117 var n = +fromIndex || 0; 10118 10119 if (abs(n) === Infinity) { 10120 n = 0; 10121 } 10122 10123 if (n >= len) { 10124 return -1; 10125 } 10126 10127 k = max(n >= 0 ? n : len - abs(n), 0); 10128 10129 while (k < len) { 10130 var kValue; 10131 if (k in O && O[k] === searchElement) { 10132 return k; 10133 } 10134 k++; 10135 } 10136 return -1; 10137 }; 10138 } 10139 10140 if (!Array.prototype.lastIndexOf) { 10141 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 10142 "use strict"; 10143 10144 if (this == null) 10145 throw new TypeError(); 10146 10147 var t = Object(this); 10148 var len = t.length >>> 0; 10149 if (len === 0) 10150 return -1; 10151 10152 var n = len; 10153 if (arguments.length > 1) { 10154 n = Number(arguments[1]); 10155 if (n != n) 10156 n = 0; 10157 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 10158 n = (n > 0 || -1) * floor(abs(n)); 10159 } 10160 10161 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 10162 10163 for (; k >= 0; k--) { 10164 if (k in t && t[k] === searchElement) 10165 return k; 10166 } 10167 return -1; 10168 }; 10169 } 10170})(jQuery, this); 10171 10172/** 10173 * Owl carousel
vendor: 12,109 bytes, lines 10174-10680
10174 * @version 2.0.0-beta.3 10175 * @author Bartosz Wojciechowski 10176 * @license The MIT License (MIT) 10177 * @todo Lazy Load Icon 10178 * @todo prevent animationend bubling 10179 * @todo itemsScaleUp 10180 * @todo Test Zepto 10181 * @todo stagePadding calculate wrong active classes 10182 */ 10183;(function($, window, document, undefined) { 10184 10185 /** 10186 * Creates a carousel. 10187 * @class The Owl Carousel. 10188 * @public 10189 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 10190 * @param {Object} [options] - The options 10191 */ 10192 function Owl(element, options) { 10193 10194 /** 10195 * Current settings for the carousel. 10196 * @public 10197 */ 10198 this.settings = null; 10199 10200 /** 10201 * Current options set by the caller including defaults. 10202 * @public 10203 */ 10204 this.options = $.extend({}, Owl.Defaults, options); 10205 10206 /** 10207 * Plugin element. 10208 * @public 10209 */ 10210 this.$element = $(element); 10211 10212 /** 10213 * Proxied event handlers. 10214 * @protected 10215 */ 10216 this._handlers = {}; 10217 10218 /** 10219 * References to the running plugins of this carousel. 10220 * @protected 10221 */ 10222 this._plugins = {}; 10223 10224 /** 10225 * Currently suppressed events to prevent them from beeing retriggered. 10226 * @protected 10227 */ 10228 this._supress = {}; 10229 10230 /** 10231 * Absolute current position. 10232 * @protected 10233 */ 10234 this._current = null; 10235 10236 /** 10237 * Animation speed in milliseconds. 10238 * @protected 10239 */ 10240 this._speed = null; 10241 10242 /** 10243 * Coordinates of all items in pixel. 10244 * @todo The name of this member is missleading. 10245 * @protected 10246 */ 10247 this._coordinates = []; 10248 10249 /** 10250 * Current breakpoint. 10251 * @todo Real media queries would be nice. 10252 * @protected 10253 */ 10254 this._breakpoint = null; 10255 10256 /** 10257 * Current width of the plugin element. 10258 */ 10259 this._width = null; 10260 10261 /** 10262 * All real items. 10263 * @protected 10264 */ 10265 this._items = []; 10266 10267 /** 10268 * All cloned items. 10269 * @protected 10270 */ 10271 this._clones = []; 10272 10273 /** 10274 * Merge values of all items. 10275 * @todo Maybe this could be part of a plugin. 10276 * @protected 10277 */ 10278 this._mergers = []; 10279 10280 /** 10281 * Widths of all items. 10282 */ 10283 this._widths = []; 10284 10285 /** 10286 * Invalidated parts within the update process. 10287 * @protected 10288 */ 10289 this._invalidated = {}; 10290 10291 /** 10292 * Ordered list of workers for the update process. 10293 * @protected 10294 */ 10295 this._pipe = []; 10296 10297 /** 10298 * Current state information for the drag operation. 10299 * @todo #261 10300 * @protected 10301 */ 10302 this._drag = { 10303 time: null, 10304 target: null, 10305 pointer: null, 10306 stage: { 10307 start: null, 10308 current: null 10309 }, 10310 direction: null 10311 }; 10312 10313 /** 10314 * Current state information and their tags. 10315 * @type {Object} 10316 * @protected 10317 */ 10318 this._states = { 10319 current: {}, 10320 tags: { 10321 'initializing': [ 'busy' ], 10322 'animating': [ 'busy' ], 10323 'dragging': [ 'interacting' ] 10324 } 10325 }; 10326 10327 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 10328 this._handlers[handler] = $.proxy(this[handler], this); 10329 }, this)); 10330 10331 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 10332 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 10333 = new plugin(this); 10334 }, this)); 10335 10336 $.each(Owl.Workers, $.proxy(function(priority, worker) { 10337 this._pipe.push({ 10338 'filter': worker.filter, 10339 'run': $.proxy(worker.run, this) 10340 }); 10341 }, this)); 10342 10343 this.setup(); 10344 this.initialize(); 10345 } 10346 10347 /** 10348 * Default options for the carousel. 10349 * @public 10350 */ 10351 Owl.Defaults = { 10352 items: 3, 10353 loop: false, 10354 center: false, 10355 rewind: false, 10356 10357 mouseDrag: true, 10358 touchDrag: true, 10359 pullDrag: true, 10360 freeDrag: false, 10361 10362 margin: 0, 10363 stagePadding: 0, 10364 10365 merge: false, 10366 mergeFit: true, 10367 autoWidth: false, 10368 10369 startPosition: 0, 10370 rtl: false, 10371 10372 smartSpeed: 250, 10373 fluidSpeed: false, 10374 dragEndSpeed: false, 10375 10376 responsive: {}, 10377 responsiveRefreshRate: 200, 10378 responsiveBaseElement: window, 10379 10380 fallbackEasing: 'swing', 10381 10382 info: false, 10383 10384 nestedItemSelector: false, 10385 itemElement: 'div', 10386 stageElement: 'div', 10387 10388 refreshClass: 'owl-refresh', 10389 loadedClass: 'owl-loaded', 10390 loadingClass: 'owl-loading', 10391 rtlClass: 'owl-rtl', 10392 responsiveClass: 'owl-responsive', 10393 dragClass: 'owl-drag', 10394 itemClass: 'owl-item', 10395 stageClass: 'owl-stage', 10396 stageOuterClass: 'owl-stage-outer', 10397 grabClass: 'owl-grab' 10398 }; 10399 10400 /** 10401 * Enumeration for width. 10402 * @public 10403 * @readonly 10404 * @enum {String} 10405 */ 10406 Owl.Width = { 10407 Default: 'default', 10408 Inner: 'inner', 10409 Outer: 'outer' 10410 }; 10411 10412 /** 10413 * Enumeration for types. 10414 * @public 10415 * @readonly 10416 * @enum {String} 10417 */ 10418 Owl.Type = { 10419 Event: 'event', 10420 State: 'state' 10421 }; 10422 10423 /** 10424 * Contains all registered plugins. 10425 * @public 10426 */ 10427 Owl.Plugins = {}; 10428 10429 /** 10430 * List of workers involved in the update process. 10431 */ 10432 Owl.Workers = [ { 10433 filter: [ 'width', 'settings' ], 10434 run: function() { 10435 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 10436 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 10437 } 10438 }, { 10439 filter: [ 'width', 'items', 'settings' ], 10440 run: function(cache) { 10441 cache.current = this._items && this._items[this.relative(this._current)]; 10442 } 10443 }, { 10444 filter: [ 'items', 'settings' ], 10445 run: function() { 10446 this.$stage.children('.cloned').remove(); 10447 } 10448 }, { 10449 filter: [ 'width', 'items', 'settings' ], 10450 run: function(cache) { 10451 var margin = this.settings.margin || '', 10452 grid = !this.settings.autoWidth, 10453 rtl = this.settings.rtl, 10454 css = { 10455 'width': 'auto', 10456 'margin-left': rtl ? margin : '', 10457 'margin-right': rtl ? '' : margin 10458 }; 10459 10460 !grid && this.$stage.children().css(css); 10461 10462 cache.css = css; 10463 } 10464 }, { 10465 filter: [ 'width', 'items', 'settings' ], 10466 run: function(cache) { 10467 //UNCODE edit to fix Chrome stage padding issue 10468 var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin), 10469 merge = null, 10470 iterator = this._items.length, 10471 grid = !this.settings.autoWidth, 10472 widths = []; 10473 10474 cache.items = { 10475 merge: false, 10476 width: width 10477 }; 10478 10479 while (iterator--) { 10480 merge = this._mergers[iterator]; 10481 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 10482 10483 cache.items.merge = merge > 1 || cache.items.merge; 10484 10485 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 10486 } 10487 10488 this._widths = widths; 10489 } 10490 }, { 10491 filter: [ 'items', 'settings' ], 10492 run: function() { 10493 var clones = [], 10494 items = this._items, 10495 settings = this.settings, 10496 view = Math.max(settings.items * 2, 4), 10497 size = Math.ceil(items.length / 2) * 2, 10498 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 10499 append = '', 10500 prepend = ''; 10501 10502 repeat /= 2; 10503 10504 while (repeat--) { 10505 clones.push(this.normalize(clones.length / 2, true)); 10506 append = append + items[clones[clones.length - 1]][0].outerHTML; 10507 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 10508 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 10509 } 10510 10511 this._clones = clones; 10512 10513 // var appendVideo = $(append).find('.uncode-video-container'); 10514 // if (appendVideo.length) { 10515 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 10516 // } 10517 // var prependVideo = $(prepend).find('.uncode-video-container'); 10518 // if (prependVideo.length) { 10519 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 10520 // } 10521 $(append).addClass('cloned').appendTo(this.$stage); 10522 $(prepend).addClass('cloned').prependTo(this.$stage); 10523 } 10524 }, { 10525 filter: [ 'width', 'items', 'settings' ], 10526 run: function() { 10527 var rtl = this.settings.rtl ? 1 : -1, 10528 size = this._clones.length + this._items.length, 10529 iterator = -1, 10530 previous = 0, 10531 current = 0, 10532 coordinates = []; 10533 10534 while (++iterator < size) { 10535 previous = coordinates[iterator - 1] || 0; 10536 current = this._widths[this.relative(iterator)] + this.settings.margin; 10537 coordinates.push(previous + current * rtl); 10538 } 10539 10540 this._coordinates = coordinates; 10541 } 10542 }, { 10543 filter: [ 'width', 'items', 'settings' ], 10544 run: function() { 10545 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10546 padding = stagePadding, 10547 coordinates = this._coordinates, 10548 css = { 10549 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 10550 'padding-left': padding || '', 10551 'padding-right': padding || '' 10552 }; 10553 10554 this.$stage.css(css); 10555 } 10556 }, { 10557 filter: [ 'width', 'items', 'settings' ], 10558 run: function(cache) { 10559 var iterator = this._coordinates.length, 10560 grid = !this.settings.autoWidth, 10561 items = this.$stage.children(); 10562 10563 if (grid && cache.items.merge) { 10564 while (iterator--) { 10565 cache.css.width = this._widths[this.relative(iterator)]; 10566 items.eq(iterator).css(cache.css); 10567 } 10568 } else if (grid) { 10569 cache.css.width = cache.items.width; 10570 items.css(cache.css); 10571 } 10572 } 10573 }, { 10574 filter: [ 'items' ], 10575 run: function() { 10576 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 10577 } 10578 }, { 10579 filter: [ 'width', 'items', 'settings' ], 10580 run: function(cache) { 10581 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 10582 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 10583 this.reset(cache.current); 10584 } 10585 }, { 10586 filter: [ 'position' ], 10587 run: function() { 10588 this.animate(this.coordinates(this._current)); 10589 } 10590 }, { 10591 filter: [ 'width', 'position', 'items', 'settings' ], 10592 run: function() { 10593 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10594 rtl = this.settings.rtl ? 1 : -1, 10595 padding = this.settings.stagePadding * 2, 10596 begin = this.coordinates(this.current()) + padding, 10597 end = begin + this.width() * rtl, 10598 inner, outer, matches = [], i, n; 10599 10600 for (i = 0, n = this._coordinates.length; i < n; i++) { 10601 inner = this._coordinates[i - 1] || 0; 10602 outer = Math.abs(this._coordinates[i]) + padding * rtl; 10603 10604 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 10605 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 10606 matches.push(i); 10607 } 10608 } 10609 10610 this.$stage.children('.active').removeClass('active'); 10611 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 10612 10613 if (this.settings.center) { 10614 this.$stage.children('.center').removeClass('center'); 10615 this.$stage.children().eq(this.current()).addClass('center'); 10616 } 10617 } 10618 } ]; 10619 10620 /** 10621 * Initializes the carousel. 10622 * @protected 10623 */ 10624 Owl.prototype.initialize = function() { 10625 this.enter('initializing'); 10626 this.trigger('initialize'); 10627 10628 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 10629 10630 if (this.settings.autoWidth && !this.is('pre-loading')) { 10631 var imgs, nestedSelector, width; 10632 imgs = this.$element.find('img'); 10633 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 10634 width = this.$element.children(nestedSelector).width(); 10635 10636 if (imgs.length && width <= 0) { 10637 this.preloadAutoWidthImages(imgs); 10638 } 10639 } 10640 10641 this.$element.addClass(this.options.loadingClass); 10642 10643 // create stage 10644 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 10645 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 10646 10647 // append stage 10648 this.$element.append(this.$stage.parent()); 10649 10650 // append content 10651 this.replace(this.$element.children().not(this.$stage.parent())); 10652 10653 // check visibility 10654 if (this.$element.is(':visible')) { 10655 // update view 10656 this.refresh(); 10657 } else { 10658 // invalidate width 10659 this.invalidate('width'); 10660 } 10661 10662 this.$element 10663 .removeClass(this.options.loadingClass) 10664 .addClass(this.options.loadedClass); 10665 10666 // register event handlers 10667 this.registerEventHandlers(); 10668 10669 this.leave('initializing'); 10670 this.trigger('initialized'); 10671 }; 10672 10673 /** 10674 * Setups the current settings. 10675 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 10676 * @todo Support for media queries by using `matchMedia` would be nice. 10677 * @public 10678 */ 10679 Owl.prototype.setup = function() { 10680 var viewport = this.viewport(),
10681 overwrites = this.options.responsive, 10682 match = -1, 10683 settings = null; 10684 10685 if (!overwrites) { 10686 settings = $.extend({}, this.options); 10687 } else { 10688 $.each(overwrites, function(breakpoint) { 10689 if (breakpoint <= viewport && breakpoint > match) { 10690 match = Number(breakpoint); 10691 } 10692 }); 10693 10694 settings = $.extend({}, this.options, overwrites[match]); 10695 delete settings.responsive; 10696 10697 // responsive class 10698 if (settings.responsiveClass) { 10699 this.$element.attr('class', 10700 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 10701 ); 10702 } 10703 } 10704 10705 if (this.settings === null || this._breakpoint !== match) { 10706 this.trigger('change', { property: { name: 'settings', value: settings } }); 10707 this._breakpoint = match; 10708 this.settings = settings; 10709 this.invalidate('settings'); 10710 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 10711 } 10712 }; 10713 10714 /** 10715 * Updates option logic if necessery. 10716 * @protected 10717 */ 10718 Owl.prototype.optionsLogic = function() { 10719 if (this.settings.autoWidth) { 10720 this.settings.stagePadding = false; 10721 this.settings.merge = false; 10722 } 10723 }; 10724 10725 /** 10726 * Prepares an item before add. 10727 * @todo Rename event parameter `content` to `item`. 10728 * @protected 10729 * @returns {jQuery|HTMLElement} - The item container. 10730 */ 10731 Owl.prototype.prepare = function(item, index) { 10732 var event = this.trigger('prepare', { content: item }); 10733 if (!event.data) { 10734 event.data = $('<' + this.settings.itemElement + '/>') 10735 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 10736 } 10737 10738 this.trigger('prepared', { content: event.data }); 10739 10740 return event.data; 10741 }; 10742 10743 /** 10744 * Updates the view. 10745 * @public 10746 */ 10747 Owl.prototype.update = function() { 10748 var i = 0, 10749 n = this._pipe.length, 10750 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 10751 cache = {}; 10752 10753 while (i < n) { 10754 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 10755 this._pipe[i].run(cache); 10756 } 10757 i++; 10758 } 10759 10760 this._invalidated = {}; 10761 10762 !this.is('valid') && this.enter('valid'); 10763 }; 10764 10765 /** 10766 * Gets the width of the view. 10767 * @public 10768 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 10769 * @returns {Number} - The width of the view in pixel. 10770 */ 10771 Owl.prototype.width = function(dimension) { 10772 dimension = dimension || Owl.Width.Default; 10773 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 10774 switch (dimension) { 10775 case Owl.Width.Inner: 10776 case Owl.Width.Outer: 10777 return this._width; 10778 default: 10779 return this._width - stagePadding * 2 + this.settings.margin; 10780 } 10781 }; 10782 10783 /** 10784 * Refreshes the carousel primarily for adaptive purposes. 10785 * @public 10786 */ 10787 Owl.prototype.refresh = function() { 10788 this.enter('refreshing'); 10789 this.trigger('refresh'); 10790 10791 this.setup(); 10792 10793 this.optionsLogic(); 10794 10795 this.$element.addClass(this.options.refreshClass); 10796 10797 this.update(); 10798 10799 this.$element.removeClass(this.options.refreshClass); 10800 10801 this.leave('refreshing'); 10802 this.trigger('refreshed'); 10803 }; 10804 10805 /** 10806 * Checks window `resize` event. 10807 * @protected 10808 */ 10809 Owl.prototype.onThrottledResize = function() { 10810 window.clearTimeout(this.resizeTimer); 10811 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 10812 }; 10813 10814 /** 10815 * Checks window `resize` event. 10816 * @protected 10817 */ 10818 Owl.prototype.onResize = function() { 10819 if (!this._items.length) { 10820 return false; 10821 } 10822 10823 if (this._width === this.$element.width()) { 10824 return false; 10825 } 10826 10827 if (!this.$element.is(':visible')) { 10828 return false; 10829 } 10830 10831 this.enter('resizing'); 10832 10833 if (this.trigger('resize').isDefaultPrevented()) { 10834 this.leave('resizing'); 10835 return false; 10836 } 10837 10838 this.invalidate('width'); 10839 10840 this.refresh(); 10841 10842 this.leave('resizing'); 10843 this.trigger('resized'); 10844 }; 10845 10846 /** 10847 * Registers event handlers. 10848 * @todo Check `msPointerEnabled` 10849 * @todo #261 10850 * @protected 10851 */ 10852 Owl.prototype.registerEventHandlers = function() { 10853 if ($.support.transition) { 10854 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 10855 } 10856 10857 if (this.settings.responsive !== false) { 10858 this.on(window, 'resize', this._handlers.onThrottledResize); 10859 } 10860 10861 if (this.settings.mouseDrag) { 10862 this.$element.addClass(this.options.dragClass); 10863 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 10864 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 10865 } 10866 10867 if (this.settings.touchDrag){ 10868 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 10869 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 10870 } 10871 }; 10872 10873 /** 10874 * Handles `touchstart` and `mousedown` events. 10875 * @todo Horizontal swipe threshold as option 10876 * @todo #261 10877 * @protected 10878 * @param {Event} event - The event arguments. 10879 */ 10880 Owl.prototype.onDragStart = function(event) { 10881 var stage = null; 10882 10883 if (event.which === 3) { 10884 return; 10885 } 10886
vendor: 9,106 bytes, lines 10887-11202
10887 if ($.support.transform) { 10888 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 10889 stage = { 10890 x: stage[stage.length === 16 ? 12 : 4], 10891 y: stage[stage.length === 16 ? 13 : 5] 10892 }; 10893 } else { 10894 stage = this.$stage.position(); 10895 stage = { 10896 x: this.settings.rtl ? 10897 stage.left + this.$stage.width() - this.width() + this.settings.margin : 10898 stage.left, 10899 y: stage.top 10900 }; 10901 } 10902 10903 if (this.is('animating')) { 10904 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 10905 this.invalidate('position'); 10906 } 10907 10908 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 10909 10910 this.speed(0); 10911 10912 this._drag.time = new Date().getTime(); 10913 this._drag.target = $(event.target); 10914 this._drag.stage.start = stage; 10915 this._drag.stage.current = stage; 10916 this._drag.pointer = this.pointer(event); 10917 10918 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 10919 10920 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 10921 var delta = this.difference(this._drag.pointer, this.pointer(event)); 10922 10923 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 10924 10925 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 10926 return; 10927 } 10928 10929 event.preventDefault(); 10930 10931 this.enter('dragging'); 10932 this.trigger('drag'); 10933 }, this)); 10934 }; 10935 10936 /** 10937 * Handles the `touchmove` and `mousemove` events. 10938 * @todo #261 10939 * @protected 10940 * @param {Event} event - The event arguments. 10941 */ 10942 Owl.prototype.onDragMove = function(event) { 10943 var minimum = null, 10944 maximum = null, 10945 pull = null, 10946 delta = this.difference(this._drag.pointer, this.pointer(event)), 10947 stage = this.difference(this._drag.stage.start, delta); 10948 10949 if (!this.is('dragging')) { 10950 return; 10951 } 10952 10953 event.preventDefault(); 10954 10955 if (this.settings.loop) { 10956 minimum = this.coordinates(this.minimum()); 10957 maximum = this.coordinates(this.maximum() + 1) - minimum; 10958 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 10959 } else { 10960 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 10961 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 10962 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 10963 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 10964 } 10965 10966 this._drag.stage.current = stage; 10967 10968 this.animate(stage.x); 10969 }; 10970 10971 /** 10972 * Handles the `touchend` and `mouseup` events. 10973 * @todo #261 10974 * @todo Threshold for click event 10975 * @protected 10976 * @param {Event} event - The event arguments. 10977 */ 10978 Owl.prototype.onDragEnd = function(event) { 10979 var delta = this.difference(this._drag.pointer, this.pointer(event)), 10980 stage = this._drag.stage.current, 10981 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 10982 10983 $(document).off('.owl.core'); 10984 10985 this.$element.removeClass(this.options.grabClass); 10986 10987 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 10988 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 10989 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 10990 this.invalidate('position'); 10991 this.update(); 10992 10993 this._drag.direction = direction; 10994 10995 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 10996 this._drag.target.one('click.owl.core', function() { return false; }); 10997 } 10998 } 10999 11000 if (!this.is('dragging')) { 11001 return; 11002 } 11003 11004 this.leave('dragging'); 11005 this.trigger('dragged'); 11006 }; 11007 11008 /** 11009 * Gets absolute position of the closest item for a coordinate. 11010 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 11011 * @protected 11012 * @param {Number} coordinate - The coordinate in pixel. 11013 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 11014 * @return {Number} - The absolute position of the closest item. 11015 */ 11016 Owl.prototype.closest = function(coordinate, direction) { 11017 var position = -1, 11018 pull = 30, 11019 width = this.width(), 11020 coordinates = this.coordinates(); 11021 11022 if (!this.settings.freeDrag) { 11023 // check closest item 11024 $.each(coordinates, $.proxy(function(index, value) { 11025 if (coordinate > value - pull && coordinate < value + pull) { 11026 position = index; 11027 } else if (this.op(coordinate, '<', value) 11028 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 11029 position = direction === 'left' ? index + 1 : index; 11030 } 11031 return position === -1; 11032 }, this)); 11033 } 11034 11035 if (!this.settings.loop) { 11036 // non loop boundries 11037 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 11038 position = coordinate = this.minimum(); 11039 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 11040 position = coordinate = this.maximum(); 11041 } 11042 } 11043 11044 return position; 11045 }; 11046 11047 /** 11048 * Animates the stage. 11049 * @todo #270 11050 * @public 11051 * @param {Number} coordinate - The coordinate in pixels. 11052 */ 11053 Owl.prototype.animate = function(coordinate) { 11054 var animate = this.speed() > 0; 11055 11056 this.is('animating') && this.onTransitionEnd(); 11057 11058 if (animate) { 11059 this.enter('animating'); 11060 this.trigger('translate'); 11061 } 11062 11063 if ($.support.transform3d && $.support.transition) { 11064 this.$stage.css({ 11065 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 11066 transition: (this.speed() / 1000) + 's' 11067 }); 11068 } else if (animate) { 11069 this.$stage.animate({ 11070 left: coordinate + 'px' 11071 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 11072 } else { 11073 this.$stage.css({ 11074 left: coordinate + 'px' 11075 }); 11076 } 11077 }; 11078 11079 /** 11080 * Checks whether the carousel is in a specific state or not. 11081 * @param {String} state - The state to check. 11082 * @returns {Boolean} - The flag which indicates if the carousel is busy. 11083 */ 11084 Owl.prototype.is = function(state) { 11085 return this._states.current[state] && this._states.current[state] > 0; 11086 }; 11087 11088 /** 11089 * Sets the absolute position of the current item. 11090 * @public 11091 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 11092 * @returns {Number} - The absolute position of the current item. 11093 */ 11094 Owl.prototype.current = function(position) { 11095 if (position === undefined) { 11096 return this._current; 11097 } 11098 11099 if (this._items.length === 0) { 11100 return undefined; 11101 } 11102 11103 position = this.normalize(position); 11104 11105 if (this._current !== position) { 11106 var event = this.trigger('change', { property: { name: 'position', value: position } }); 11107 11108 if (event.data !== undefined) { 11109 position = this.normalize(event.data); 11110 } 11111 11112 this._current = position; 11113 11114 this.invalidate('position'); 11115 11116 this.trigger('changed', { property: { name: 'position', value: this._current } }); 11117 } 11118 11119 return this._current; 11120 }; 11121 11122 /** 11123 * Invalidates the given part of the update routine. 11124 * @param {String} [part] - The part to invalidate. 11125 * @returns {Array.<String>} - The invalidated parts. 11126 */ 11127 Owl.prototype.invalidate = function(part) { 11128 if ($.type(part) === 'string') { 11129 this._invalidated[part] = true; 11130 this.is('valid') && this.leave('valid'); 11131 } 11132 return $.map(this._invalidated, function(v, i) { return i }); 11133 }; 11134 11135 /** 11136 * Resets the absolute position of the current item. 11137 * @public 11138 * @param {Number} position - The absolute position of the new item. 11139 */ 11140 Owl.prototype.reset = function(position) { 11141 position = this.normalize(position); 11142 11143 if (position === undefined) { 11144 return; 11145 } 11146 11147 this._speed = 0; 11148 this._current = position; 11149 11150 this.suppress([ 'translate', 'translated' ]); 11151 11152 this.animate(this.coordinates(position)); 11153 11154 this.release([ 'translate', 'translated' ]); 11155 }; 11156 11157 /** 11158 * Normalizes an absolute or a relative position of an item. 11159 * @public 11160 * @param {Number} position - The absolute or relative position to normalize. 11161 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 11162 * @returns {Number} - The normalized position. 11163 */ 11164 Owl.prototype.normalize = function(position, relative) { 11165 var n = this._items.length, 11166 m = relative ? 0 : this._clones.length; 11167 11168 if (!$.isNumeric(position) || n < 1) { 11169 position = undefined; 11170 } else if (position < 0 || position >= n + m) { 11171 position = ((position - m / 2) % n + n) % n + m / 2; 11172 } 11173 11174 return position; 11175 }; 11176 11177 /** 11178 * Converts an absolute position of an item into a relative one. 11179 * @public 11180 * @param {Number} position - The absolute position to convert. 11181 * @returns {Number} - The converted position. 11182 */ 11183 Owl.prototype.relative = function(position) { 11184 position -= this._clones.length / 2; 11185 return this.normalize(position, true); 11186 }; 11187 11188 /** 11189 * Gets the maximum position for the current item. 11190 * @public 11191 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11192 * @returns {Number} 11193 */ 11194 Owl.prototype.maximum = function(relative) { 11195 var settings = this.settings, 11196 maximum = this._coordinates.length, 11197 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 11198 i = -1, j; 11199 11200 if (settings.loop) { 11201 maximum = this._clones.length / 2 + this._items.length - 1; 11202 } else if (settings.autoWidth || settings.merge) {
11203 // binary search 11204 while (maximum - i > 1) { 11205 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 11206 ? i = j : maximum = j; 11207 } 11208 } else if (settings.center) { 11209 maximum = this._items.length - 1; 11210 } else { 11211 maximum = this._items.length - settings.items; 11212 } 11213 11214 if (relative) { 11215 maximum -= this._clones.length / 2; 11216 } 11217 11218 return Math.max(maximum, 0); 11219 }; 11220 11221 /** 11222 * Gets the minimum position for the current item. 11223 * @public 11224 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11225 * @returns {Number} 11226 */ 11227 Owl.prototype.minimum = function(relative) { 11228 return relative ? 0 : this._clones.length / 2; 11229 }; 11230 11231 /** 11232 * Gets an item at the specified relative position. 11233 * @public 11234 * @param {Number} [position] - The relative position of the item. 11235 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11236 */ 11237 Owl.prototype.items = function(position) { 11238 if (position === undefined) { 11239 return this._items.slice(); 11240 } 11241 11242 position = this.normalize(position, true); 11243 return this._items[position]; 11244 }; 11245 11246 /** 11247 * Gets an item at the specified relative position. 11248 * @public 11249 * @param {Number} [position] - The relative position of the item. 11250 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11251 */ 11252 Owl.prototype.mergers = function(position) { 11253 if (position === undefined) { 11254 return this._mergers.slice(); 11255 } 11256 11257 position = this.normalize(position, true); 11258 return this._mergers[position]; 11259 }; 11260 11261 /** 11262 * Gets the absolute positions of clones for an item. 11263 * @public 11264 * @param {Number} [position] - The relative position of the item. 11265 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 11266 */ 11267 Owl.prototype.clones = function(position) { 11268 var odd = this._clones.length / 2, 11269 even = odd + this._items.length, 11270 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 11271 11272 if (position === undefined) { 11273 return $.map(this._clones, function(v, i) { return map(i) }); 11274 } 11275 11276 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 11277 }; 11278 11279 /** 11280 * Sets the current animation speed. 11281 * @public 11282 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 11283 * @returns {Number} - The current animation speed in milliseconds. 11284 */ 11285 Owl.prototype.speed = function(speed) { 11286 if (speed !== undefined) { 11287 this._speed = speed; 11288 } 11289 11290 return this._speed; 11291 }; 11292 11293 /** 11294 * Gets the coordinate of an item. 11295 * @todo The name of this method is missleanding. 11296 * @public 11297 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 11298 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 11299 */ 11300 Owl.prototype.coordinates = function(position) { 11301 var coordinate = null; 11302 11303 if (position === undefined) { 11304 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 11305 return this.coordinates(index); 11306 }, this)); 11307 } 11308 11309 if (this.settings.center) { 11310 coordinate = this._coordinates[position]; 11311 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 11312 } else { 11313 coordinate = this._coordinates[position - 1] || 0; 11314 } 11315 11316 return coordinate; 11317 }; 11318 11319 /** 11320 * Calculates the speed for a translation. 11321 * @protected 11322 * @param {Number} from - The absolute position of the start item. 11323 * @param {Number} to - The absolute position of the target item. 11324 * @param {Number} [factor=undefined] - The time factor in milliseconds. 11325 * @returns {Number} - The time in milliseconds for the translation. 11326 */ 11327 Owl.prototype.duration = function(from, to, factor) { 11328 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 11329 }; 11330 11331 /** 11332 * Slides to the specified item. 11333 * @public 11334 * @param {Number} position - The position of the item. 11335 * @param {Number} [speed] - The time in milliseconds for the transition. 11336 */ 11337 Owl.prototype.to = function(position, speed) { 11338 var current = this.current(), 11339 revert = null, 11340 distance = position - this.relative(current), 11341 direction = (distance > 0) - (distance < 0), 11342 items = this._items.length, 11343 minimum = this.minimum(), 11344 maximum = this.maximum(); 11345 11346 if (this.settings.loop) { 11347 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 11348 distance += direction * -1 * items; 11349 } 11350 11351 position = current + distance; 11352 revert = ((position - minimum) % items + items) % items + minimum; 11353 11354 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 11355 current = revert - distance; 11356 position = revert; 11357 this.reset(current); 11358 } 11359 } else if (this.settings.rewind) { 11360 maximum += 1; 11361 position = (position % maximum + maximum) % maximum; 11362 } else { 11363 position = Math.max(minimum, Math.min(maximum, position)); 11364 } 11365 11366 this.speed(this.duration(current, position, speed)); 11367 this.current(position); 11368 11369 if (this.$element.is(':visible')) { 11370 this.update(); 11371 } 11372 }; 11373 11374 /** 11375 * Slides to the next item. 11376 * @public 11377 * @param {Number}
vendor: 12,284 bytes, lines 11377-11797
11377 [speed] - The time in milliseconds for the transition. 11378 */ 11379 Owl.prototype.next = function(speed) { 11380 speed = speed || false; 11381 this.to(this.relative(this.current()) + 1, speed); 11382 }; 11383 11384 /** 11385 * Slides to the previous item. 11386 * @public 11387 * @param {Number} [speed] - The time in milliseconds for the transition. 11388 */ 11389 Owl.prototype.prev = function(speed) { 11390 speed = speed || false; 11391 this.to(this.relative(this.current()) - 1, speed); 11392 }; 11393 11394 /** 11395 * Handles the end of an animation. 11396 * @protected 11397 * @param {Event} event - The event arguments. 11398 */ 11399 Owl.prototype.onTransitionEnd = function(event) { 11400 11401 // if css2 animation then event object is undefined 11402 if (event !== undefined) { 11403 event.stopPropagation(); 11404 11405 // Catch only owl-stage transitionEnd event 11406 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 11407 return false; 11408 } 11409 } 11410 11411 this.leave('animating'); 11412 this.trigger('translated'); 11413 }; 11414 11415 /** 11416 * Gets viewport width. 11417 * @protected 11418 * @return {Number} - The width in pixel. 11419 */ 11420 Owl.prototype.viewport = function() { 11421 var width; 11422 if (this.options.responsiveBaseElement !== window) { 11423 width = $(this.options.responsiveBaseElement).width(); 11424 } else if (window.innerWidth) { 11425 width = window.innerWidth; 11426 } else if (document.documentElement && document.documentElement.clientWidth) { 11427 width = document.documentElement.clientWidth; 11428 } else { 11429 throw 'Can not detect viewport width.'; 11430 } 11431 11432 return width; 11433 }; 11434 11435 /** 11436 * Replaces the current content. 11437 * @public 11438 * @param {HTMLElement|jQuery|String} content - The new content. 11439 */ 11440 Owl.prototype.replace = function(content) { 11441 this.$stage.empty(); 11442 this._items = []; 11443 11444 if (content) { 11445 content = (content instanceof jQuery) ? content : $(content); 11446 } 11447 11448 if (this.settings.nestedItemSelector) { 11449 content = content.find('.' + this.settings.nestedItemSelector); 11450 } 11451 11452 content.filter(function() { 11453 return this.nodeType === 1; 11454 }).each($.proxy(function(index, item) { 11455 item = this.prepare(item, index); 11456 this.$stage.append(item); 11457 this._items.push(item); 11458 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 11459 }, this)); 11460 11461 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 11462 11463 this.invalidate('items'); 11464 }; 11465 11466 /** 11467 * Adds an item. 11468 * @todo Use `item` instead of `content` for the event arguments. 11469 * @public 11470 * @param {HTMLElement|jQuery|String} content - The item content to add. 11471 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 11472 */ 11473 Owl.prototype.add = function(content, position) { 11474 var current = this.relative(this._current); 11475 11476 position = position === undefined ? this._items.length : this.normalize(position, true); 11477 content = content instanceof jQuery ? content : $(content); 11478 11479 this.trigger('add', { content: content, position: position }); 11480 11481 content = this.prepare(content, this._items[current].index()); 11482 11483 if (this._items.length === 0 || position === this._items.length) { 11484 this._items.length === 0 && this.$stage.append(content); 11485 this._items.length !== 0 && this._items[position - 1].after(content); 11486 this._items.push(content); 11487 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11488 } else { 11489 this._items[position].before(content); 11490 this._items.splice(position, 0, content); 11491 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11492 } 11493 11494 this._items[current] && this.reset(this._items[current].index()); 11495 11496 this.invalidate('items'); 11497 11498 this.trigger('added', { content: content, position: position }); 11499 }; 11500 11501 /** 11502 * Removes an item by its position. 11503 * @todo Use `item` instead of `content` for the event arguments. 11504 * @public 11505 * @param {Number} position - The relative position of the item to remove. 11506 */ 11507 Owl.prototype.remove = function(position) { 11508 position = this.normalize(position, true); 11509 11510 if (position === undefined) { 11511 return; 11512 } 11513 11514 this.trigger('remove', { content: this._items[position], position: position }); 11515 11516 this._items[position].remove(); 11517 this._items.splice(position, 1); 11518 this._mergers.splice(position, 1); 11519 11520 this.invalidate('items'); 11521 11522 this.trigger('removed', { content: null, position: position }); 11523 }; 11524 11525 /** 11526 * Preloads images with auto width. 11527 * @todo Replace by a more generic approach 11528 * @protected 11529 */ 11530 Owl.prototype.preloadAutoWidthImages = function(images) { 11531 images.each($.proxy(function(i, element) { 11532 this.enter('pre-loading'); 11533 element = $(element); 11534 $(new Image()).one('load', $.proxy(function(e) { 11535 element.attr('src', e.target.src); 11536 element.css('opacity', 1); 11537 this.leave('pre-loading'); 11538 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 11539 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 11540 }, this)); 11541 }; 11542 11543 /** 11544 * Destroys the carousel. 11545 * @public 11546 */ 11547 Owl.prototype.destroy = function() { 11548 11549 this.$element.off('.owl.core'); 11550 this.$stage.off('.owl.core'); 11551 $(document).off('.owl.core'); 11552 11553 if (this.settings.responsive !== false) { 11554 window.clearTimeout(this.resizeTimer); 11555 this.off(window, 'resize', this._handlers.onThrottledResize); 11556 } 11557 11558 for (var i in this._plugins) { 11559 this._plugins[i].destroy(); 11560 } 11561 11562 this.$stage.children('.cloned').remove(); 11563 11564 this.$stage.unwrap(); 11565 this.$stage.children().contents().unwrap(); 11566 this.$stage.children().unwrap(); 11567 11568 this.$element 11569 .removeClass(this.options.refreshClass) 11570 .removeClass(this.options.loadingClass) 11571 .removeClass(this.options.loadedClass) 11572 .removeClass(this.options.rtlClass) 11573 .removeClass(this.options.dragClass) 11574 .removeClass(this.options.grabClass) 11575 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 11576 .removeData('owl.carousel'); 11577 }; 11578 11579 /** 11580 * Operators to calculate right-to-left and left-to-right. 11581 * @protected 11582 * @param {Number} [a] - The left side operand. 11583 * @param {String} [o] - The operator. 11584 * @param {Number} [b] - The right side operand. 11585 */ 11586 Owl.prototype.op = function(a, o, b) { 11587 var rtl = this.settings.rtl; 11588 switch (o) { 11589 case '<': 11590 return rtl ? a > b : a < b; 11591 case '>': 11592 return rtl ? a < b : a > b; 11593 case '>=': 11594 return rtl ? a <= b : a >= b; 11595 case '<=': 11596 return rtl ? a >= b : a <= b; 11597 default: 11598 break; 11599 } 11600 }; 11601 11602 /** 11603 * Attaches to an internal event. 11604 * @protected 11605 * @param {HTMLElement} element - The event source. 11606 * @param {String} event - The event name. 11607 * @param {Function} listener - The event handler to attach. 11608 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 11609 */ 11610 Owl.prototype.on = function(element, event, listener, capture) { 11611 if (element.addEventListener) { 11612 element.addEventListener(event, listener, capture); 11613 } else if (element.attachEvent) { 11614 element.attachEvent('on' + event, listener); 11615 } 11616 }; 11617 11618 /** 11619 * Detaches from an internal event. 11620 * @protected 11621 * @param {HTMLElement} element - The event source. 11622 * @param {String} event - The event name. 11623 * @param {Function} listener - The attached event handler to detach. 11624 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 11625 */ 11626 Owl.prototype.off = function(element, event, listener, capture) { 11627 if (element.removeEventListener) { 11628 element.removeEventListener(event, listener, capture); 11629 } else if (element.detachEvent) { 11630 element.detachEvent('on' + event, listener); 11631 } 11632 }; 11633 11634 /** 11635 * Triggers a public event. 11636 * @todo Remove `status`, `relatedTarget` should be used instead. 11637 * @protected 11638 * @param {String} name - The event name. 11639 * @param {*} [data=null] - The event data. 11640 * @param {String} [namespace=carousel] - The event namespace. 11641 * @param {String} [state] - The state which is associated with the event. 11642 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 11643 * @returns {Event} - The event arguments. 11644 */ 11645 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 11646 var status = { 11647 item: { count: this._items.length, index: this.current() } 11648 }, handler = $.camelCase( 11649 $.grep([ 'on', name, namespace ], function(v) { return v }) 11650 .join('-').toLowerCase() 11651 ), event = $.Event( 11652 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 11653 $.extend({ relatedTarget: this }, status, data) 11654 ); 11655 11656 if (!this._supress[name]) { 11657 $.each(this._plugins, function(name, plugin) { 11658 if (plugin.onTrigger) { 11659 plugin.onTrigger(event); 11660 } 11661 }); 11662 11663 this.register({ type: Owl.Type.Event, name: name }); 11664 this.$element.trigger(event); 11665 11666 if (this.settings && typeof this.settings[handler] === 'function') { 11667 this.settings[handler].call(this, event); 11668 } 11669 } 11670 11671 return event; 11672 }; 11673 11674 /** 11675 * Enters a state. 11676 * @param name - The state name. 11677 */ 11678 Owl.prototype.enter = function(name) { 11679 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11680 if (this._states.current[name] === undefined) { 11681 this._states.current[name] = 0; 11682 } 11683 11684 this._states.current[name]++; 11685 }, this)); 11686 }; 11687 11688 /** 11689 * Leaves a state. 11690 * @param name - The state name. 11691 */ 11692 Owl.prototype.leave = function(name) { 11693 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11694 this._states.current[name]--; 11695 }, this)); 11696 }; 11697 11698 /** 11699 * Registers an event or state. 11700 * @public 11701 * @param {Object} object - The event or state to register. 11702 */ 11703 Owl.prototype.register = function(object) { 11704 if (object.type === Owl.Type.Event) { 11705 if (!$.event.special[object.name]) { 11706 $.event.special[object.name] = {}; 11707 } 11708 11709 if (!$.event.special[object.name].owl) { 11710 var _default = $.event.special[object.name]._default; 11711 $.event.special[object.name]._default = function(e) { 11712 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 11713 return _default.apply(this, arguments); 11714 } 11715 return e.namespace && e.namespace.indexOf('owl') > -1; 11716 }; 11717 $.event.special[object.name].owl = true; 11718 } 11719 } else if (object.type === Owl.Type.State) { 11720 if (!this._states.tags[object.name]) { 11721 this._states.tags[object.name] = object.tags; 11722 } else { 11723 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 11724 } 11725 11726 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 11727 return $.inArray(tag, this._states.tags[object.name]) === i; 11728 }, this)); 11729 } 11730 }; 11731 11732 /** 11733 * Suppresses events. 11734 * @protected 11735 * @param {Array.<String>} events - The events to suppress. 11736 */ 11737 Owl.prototype.suppress = function(events) { 11738 $.each(events, $.proxy(function(index, event) { 11739 this._supress[event] = true; 11740 }, this)); 11741 }; 11742 11743 /** 11744 * Releases suppressed events. 11745 * @protected 11746 * @param {Array.<String>} events - The events to release. 11747 */ 11748 Owl.prototype.release = function(events) { 11749 $.each(events, $.proxy(function(index, event) { 11750 delete this._supress[event]; 11751 }, this)); 11752 }; 11753 11754 /** 11755 * Gets unified pointer coordinates from event. 11756 * @todo #261 11757 * @protected 11758 * @param {Event} - The `mousedown` or `touchstart` event. 11759 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 11760 */ 11761 Owl.prototype.pointer = function(event) { 11762 var result = { x: null, y: null }; 11763 11764 event = event.originalEvent || event || window.event; 11765 11766 event = event.touches && event.touches.length ? 11767 event.touches[0] : event.changedTouches && event.changedTouches.length ? 11768 event.changedTouches[0] : event; 11769 11770 if (event.pageX) { 11771 result.x = event.pageX; 11772 result.y = event.pageY; 11773 } else { 11774 result.x = event.clientX; 11775 result.y = event.clientY; 11776 } 11777 11778 return result; 11779 }; 11780 11781 /** 11782 * Gets the difference of two vectors. 11783 * @todo #261 11784 * @protected 11785 * @param {Object} - The first vector. 11786 * @param {Object} - The second vector. 11787 * @returns {Object} - The difference. 11788 */ 11789 Owl.prototype.difference = function(first, second) { 11790 return { 11791 x: first.x - second.x, 11792 y: first.y - second.y 11793 }; 11794 }; 11795 11796 /** 11797 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 11798-13080
11798 * @todo Navigation plugin `next` and `prev` 11799 * @public 11800 */ 11801 $.fn.owlCarousel = function(option) { 11802 var args = Array.prototype.slice.call(arguments, 1); 11803 11804 return this.each(function() { 11805 var $this = $(this), 11806 data = $this.data('owl.carousel'); 11807 11808 if (!data) { 11809 data = new Owl(this, typeof option == 'object' && option); 11810 $this.data('owl.carousel', data); 11811 11812 $.each([ 11813 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 11814 ], function(i, event) { 11815 data.register({ type: Owl.Type.Event, name: event }); 11816 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 11817 if (e.namespace && e.relatedTarget !== this) { 11818 this.suppress([ event ]); 11819 data[event].apply(this, [].slice.call(arguments, 1)); 11820 this.release([ event ]); 11821 } 11822 }, data)); 11823 }); 11824 } 11825 11826 if (typeof option == 'string' && option.charAt(0) !== '_') { 11827 data[option].apply(data, args); 11828 } 11829 }); 11830 }; 11831 11832 /** 11833 * The constructor for the jQuery Plugin 11834 * @public 11835 */ 11836 $.fn.owlCarousel.Constructor = Owl; 11837 11838})(window.Zepto || window.jQuery, window, document); 11839 11840/** 11841 * AutoRefresh Plugin 11842 * @version 2.0.0-beta.3 11843 * @author Artus Kolanowski 11844 * @license The MIT License (MIT) 11845 */ 11846;(function($, window, document, undefined) { 11847 11848 /** 11849 * Creates the auto refresh plugin. 11850 * @class The Auto Refresh Plugin 11851 * @param {Owl} carousel - The Owl Carousel 11852 */ 11853 var AutoRefresh = function(carousel) { 11854 /** 11855 * Reference to the core. 11856 * @protected 11857 * @type {Owl} 11858 */ 11859 this._core = carousel; 11860 11861 /** 11862 * Refresh interval. 11863 * @protected 11864 * @type {number} 11865 */ 11866 this._interval = null; 11867 11868 /** 11869 * Whether the element is currently visible or not. 11870 * @protected 11871 * @type {Boolean} 11872 */ 11873 this._visible = null; 11874 11875 /** 11876 * All event handlers. 11877 * @protected 11878 * @type {Object} 11879 */ 11880 this._handlers = { 11881 'initialized.owl.carousel': $.proxy(function(e) { 11882 if (e.namespace && this._core.settings.autoRefresh) { 11883 this.watch(); 11884 } 11885 }, this) 11886 }; 11887 11888 // set default options 11889 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 11890 11891 // register event handlers 11892 this._core.$element.on(this._handlers); 11893 }; 11894 11895 /** 11896 * Default options. 11897 * @public 11898 */ 11899 AutoRefresh.Defaults = { 11900 autoRefresh: true, 11901 autoRefreshInterval: 500 11902 }; 11903 11904 /** 11905 * Watches the element. 11906 */ 11907 AutoRefresh.prototype.watch = function() { 11908 if (this._interval) { 11909 return; 11910 } 11911 11912 this._visible = this._core.$element.is(':visible'); 11913 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 11914 }; 11915 11916 /** 11917 * Refreshes the element. 11918 */ 11919 AutoRefresh.prototype.refresh = function() { 11920 if (this._core.$element.is(':visible') === this._visible) { 11921 return; 11922 } 11923 11924 this._visible = !this._visible; 11925 11926 this._core.$element.toggleClass('owl-hidden', !this._visible); 11927 11928 this._visible && (this._core.invalidate('width') && this._core.refresh()); 11929 }; 11930 11931 /** 11932 * Destroys the plugin. 11933 */ 11934 AutoRefresh.prototype.destroy = function() { 11935 var handler, property; 11936 11937 window.clearInterval(this._interval); 11938 11939 for (handler in this._handlers) { 11940 this._core.$element.off(handler, this._handlers[handler]); 11941 } 11942 for (property in Object.getOwnPropertyNames(this)) { 11943 typeof this[property] != 'function' && (this[property] = null); 11944 } 11945 }; 11946 11947 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 11948 11949})(window.Zepto || window.jQuery, window, document); 11950 11951/** 11952 * Lazy Plugin 11953 * @version 2.0.0-beta.3 11954 * @author Bartosz Wojciechowski 11955 * @license The MIT License (MIT) 11956 */ 11957;(function($, window, document, undefined) { 11958 11959 /** 11960 * Creates the lazy plugin. 11961 * @class The Lazy Plugin 11962 * @param {Owl} carousel - The Owl Carousel 11963 */ 11964 var Lazy = function(carousel) { 11965 11966 /** 11967 * Reference to the core. 11968 * @protected 11969 * @type {Owl} 11970 */ 11971 this._core = carousel; 11972 11973 /** 11974 * Already loaded items. 11975 * @protected 11976 * @type {Array.<jQuery>} 11977 */ 11978 this._loaded = []; 11979 11980 /** 11981 * Event handlers. 11982 * @protected 11983 * @type {Object} 11984 */ 11985 this._handlers = { 11986 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 11987 if (!e.namespace) { 11988 return; 11989 } 11990 11991 if (!this._core.settings || !this._core.settings.lazyLoad) { 11992 return; 11993 } 11994 11995 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 11996 var settings = this._core.settings, 11997 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 11998 i = ((settings.center && n * -1) || 0), 11999 position = ((e.property && e.property.value) || this._core.current()) + i, 12000 clones = this._core.clones().length, 12001 load = $.proxy(function(i, v) { this.load(v) }, this); 12002 12003 while (i++ < n) { 12004 this.load(clones / 2 + this._core.relative(position)); 12005 clones && $.each(this._core.clones(this._core.relative(position)), load); 12006 position++; 12007 } 12008 } 12009 }, this) 12010 }; 12011 12012 // set the default options 12013 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 12014 12015 // register event handler 12016 this._core.$element.on(this._handlers); 12017 } 12018 12019 /** 12020 * Default options. 12021 * @public 12022 */ 12023 Lazy.Defaults = { 12024 lazyLoad: false 12025 } 12026 12027 /** 12028 * Loads all resources of an item at the specified position. 12029 * @param {Number} position - The absolute position of the item. 12030 * @protected 12031 */ 12032 Lazy.prototype.load = function(position) { 12033 var $item = this._core.$stage.children().eq(position), 12034 $elements = $item && $item.find('.owl-lazy'); 12035 12036 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 12037 return; 12038 } 12039 12040 $elements.each($.proxy(function(index, element) { 12041 var $element = $(element), image, 12042 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 12043 12044 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 12045 12046 if ($element.is('img')) { 12047 $element.one('load.owl.lazy', $.proxy(function() { 12048 $element.css('opacity', 1); 12049 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12050 }, this)).attr('src', url); 12051 } else { 12052 image = new Image(); 12053 image.onload = $.proxy(function() { 12054 $element.css({ 12055 'background-image': 'url(' + url + ')', 12056 'opacity': '1' 12057 }); 12058 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12059 }, this); 12060 image.src = url; 12061 } 12062 }, this)); 12063 12064 this._loaded.push($item.get(0)); 12065 } 12066 12067 /** 12068 * Destroys the plugin. 12069 * @public 12070 */ 12071 Lazy.prototype.destroy = function() { 12072 var handler, property; 12073 12074 for (handler in this.handlers) { 12075 this._core.$element.off(handler, this.handlers[handler]); 12076 } 12077 for (property in Object.getOwnPropertyNames(this)) { 12078 typeof this[property] != 'function' && (this[property] = null); 12079 } 12080 }; 12081 12082 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 12083 12084})(window.Zepto || window.jQuery, window, document); 12085 12086/** 12087 * AutoHeight Plugin 12088 * @version 2.0.0-beta.3 12089 * @author Bartosz Wojciechowski 12090 * @license The MIT License (MIT) 12091 */ 12092;(function($, window, document, undefined) { 12093 12094 /** 12095 * Creates the auto height plugin. 12096 * @class The Auto Height Plugin 12097 * @param {Owl} carousel - The Owl Carousel 12098 */ 12099 var AutoHeight = function(carousel) { 12100 /** 12101 * Reference to the core. 12102 * @protected 12103 * @type {Owl} 12104 */ 12105 this._core = carousel; 12106 12107 /** 12108 * All event handlers. 12109 * @protected 12110 * @type {Object} 12111 */ 12112 this._handlers = { 12113 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 12114 if (e.namespace && this._core.settings.autoHeight) { 12115 this.update(); 12116 } 12117 }, this), 12118 'changed.owl.carousel': $.proxy(function(e) { 12119 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 12120 this.update(); 12121 } 12122 }, this), 12123 'loaded.owl.lazy': $.proxy(function(e) { 12124 if (e.namespace && this._core.settings.autoHeight 12125 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 12126 this.update(); 12127 } 12128 }, this) 12129 }; 12130 12131 // set default options 12132 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 12133 12134 // register event handlers 12135 this._core.$element.on(this._handlers); 12136 }; 12137 12138 /** 12139 * Default options. 12140 * @public 12141 */ 12142 AutoHeight.Defaults = { 12143 autoHeight: false, 12144 autoHeightClass: 'owl-height' 12145 }; 12146 12147 /** 12148 * Updates the view. 12149 */ 12150 AutoHeight.prototype.update = function() { 12151 var start = this._core._current, 12152 end = start + this._core.settings.items, 12153 visible = this._core.$stage.children().toArray().slice(start, end); 12154 heights = [], 12155 maxheight = 0; 12156 12157 $.each(visible, function(index, item) { 12158 heights.push($(item).height()); 12159 }); 12160 12161 maxheight = Math.max.apply(null, heights); 12162 12163 this._core.$stage.parent() 12164 .height(maxheight) 12165 .addClass(this._core.settings.autoHeightClass); 12166 }; 12167 12168 AutoHeight.prototype.destroy = function() { 12169 var handler, property; 12170 12171 for (handler in this._handlers) { 12172 this._core.$element.off(handler, this._handlers[handler]); 12173 } 12174 for (property in Object.getOwnPropertyNames(this)) { 12175 typeof this[property] != 'function' && (this[property] = null); 12176 } 12177 }; 12178 12179 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 12180 12181})(window.Zepto || window.jQuery, window, document); 12182 12183/** 12184 * Video Plugin 12185 * @version 2.0.0-beta.3 12186 * @author Bartosz Wojciechowski 12187 * @license The MIT License (MIT) 12188 */ 12189;(function($, window, document, undefined) { 12190 12191 /** 12192 * Creates the video plugin. 12193 * @class The Video Plugin 12194 * @param {Owl} carousel - The Owl Carousel 12195 */ 12196 var Video = function(carousel) { 12197 /** 12198 * Reference to the core. 12199 * @protected 12200 * @type {Owl} 12201 */ 12202 this._core = carousel; 12203 12204 /** 12205 * Cache all video URLs. 12206 * @protected 12207 * @type {Object} 12208 */ 12209 this._videos = {}; 12210 12211 /** 12212 * Current playing item. 12213 * @protected 12214 * @type {jQuery} 12215 */ 12216 this._playing = null; 12217 12218 /** 12219 * All event handlers. 12220 * @todo The cloned content removale is too late 12221 * @protected 12222 * @type {Object} 12223 */ 12224 this._handlers = { 12225 'initialized.owl.carousel': $.proxy(function(e) { 12226 if (e.namespace) { 12227 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 12228 } 12229 }, this), 12230 'resize.owl.carousel': $.proxy(function(e) { 12231 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 12232 e.preventDefault(); 12233 } 12234 }, this), 12235 'refreshed.owl.carousel': $.proxy(function(e) { 12236 if (e.namespace && this._core.is('resizing')) { 12237 this._core.$stage.find('.cloned .owl-video-frame').remove(); 12238 } 12239 }, this), 12240 'changed.owl.carousel': $.proxy(function(e) { 12241 if (e.namespace && e.property.name === 'position' && this._playing) { 12242 this.stop(); 12243 } 12244 }, this), 12245 'prepared.owl.carousel': $.proxy(function(e) { 12246 if (!e.namespace) { 12247 return; 12248 } 12249 12250 var $element = $(e.content).find('.owl-video'); 12251 12252 if ($element.length) { 12253 $element.css('display', 'none'); 12254 this.fetch($element, $(e.content)); 12255 } 12256 }, this) 12257 }; 12258 12259 // set default options 12260 this._core.options = $.extend({}, Video.Defaults, this._core.options); 12261 12262 // register event handlers 12263 this._core.$element.on(this._handlers); 12264 12265 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 12266 this.play(e); 12267 }, this)); 12268 }; 12269 12270 /** 12271 * Default options. 12272 * @public 12273 */ 12274 Video.Defaults = { 12275 video: false, 12276 videoHeight: false, 12277 videoWidth: false 12278 }; 12279 12280 /** 12281 * Gets the video ID and the type (YouTube/Vimeo only). 12282 * @protected 12283 * @param {jQuery} target - The target containing the video data. 12284 * @param {jQuery} item - The item containing the video. 12285 */ 12286 Video.prototype.fetch = function(target, item) { 12287 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 12288 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 12289 width = target.attr('data-width') || this._core.settings.videoWidth, 12290 height = target.attr('data-height') || this._core.settings.videoHeight, 12291 url = target.attr('href'); 12292 12293 if (url) { 12294 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+)?/); 12295 12296 if (id[3].indexOf('youtu') > -1) { 12297 type = 'youtube'; 12298 } else if (id[3].indexOf('vimeo') > -1) { 12299 type = 'vimeo'; 12300 } else { 12301 throw new Error('Video URL not supported.'); 12302 } 12303 id = id[6]; 12304 } else { 12305 throw new Error('Missing video URL.'); 12306 } 12307 12308 this._videos[url] = { 12309 type: type, 12310 id: id, 12311 width: width, 12312 height: height 12313 }; 12314 12315 item.attr('data-video', url); 12316 12317 this.thumbnail(target, this._videos[url]); 12318 }; 12319 12320 /** 12321 * Creates video thumbnail. 12322 * @protected 12323 * @param {jQuery} target - The target containing the video data. 12324 * @param {Object} info - The video info object. 12325 * @see `fetch` 12326 */ 12327 Video.prototype.thumbnail = function(target, video) { 12328 var tnLink, 12329 icon, 12330 path, 12331 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 12332 customTn = target.find('img'), 12333 srcType = 'src', 12334 lazyClass = '', 12335 settings = this._core.settings, 12336 create = function(path) { 12337 icon = '<div class="owl-video-play-icon"></div>'; 12338 12339 if (settings.lazyLoad) { 12340 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 12341 } else { 12342 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 12343 } 12344 target.after(tnLink); 12345 target.after(icon); 12346 }; 12347 12348 // wrap video content into owl-video-wrapper div 12349 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 12350 12351 if (this._core.settings.lazyLoad) { 12352 srcType = 'data-src'; 12353 lazyClass = 'owl-lazy'; 12354 } 12355 12356 // custom thumbnail 12357 if (customTn.length) { 12358 create(customTn.attr(srcType)); 12359 customTn.remove(); 12360 return false; 12361 } 12362 12363 if (video.type === 'youtube') { 12364 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 12365 create(path); 12366 } else if (video.type === 'vimeo') { 12367 $.ajax({ 12368 type: 'GET', 12369 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 12370 jsonp: 'callback', 12371 dataType: 'jsonp', 12372 success: function(data) { 12373 path = data[0].thumbnail_large; 12374 create(path); 12375 } 12376 }); 12377 } 12378 }; 12379 12380 /** 12381 * Stops the current video. 12382 * @public 12383 */ 12384 Video.prototype.stop = function() { 12385 this._core.trigger('stop', null, 'video'); 12386 this._playing.find('.owl-video-frame').remove(); 12387 this._playing.removeClass('owl-video-playing'); 12388 this._playing = null; 12389 this._core.leave('playing'); 12390 this._core.trigger('stopped', null, 'video'); 12391 }; 12392 12393 /** 12394 * Starts the current video. 12395 * @public 12396 * @param {Event} event - The event arguments. 12397 */ 12398 Video.prototype.play = function(event) { 12399 var target = $(event.target), 12400 item = target.closest('.' + this._core.settings.itemClass), 12401 video = this._videos[item.attr('data-video')], 12402 width = video.width || '100%', 12403 height = video.height || this._core.$stage.height(), 12404 html; 12405 12406 if (this._playing) { 12407 return; 12408 } 12409 12410 this._core.enter('playing'); 12411 this._core.trigger('play', null, 'video'); 12412 12413 item = this._core.items(this._core.relative(item.index())); 12414 12415 this._core.reset(item.index()); 12416 12417 if (video.type === 'youtube') { 12418 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 12419 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 12420 } else if (video.type === 'vimeo') { 12421 html = '<iframe src="//player.vimeo.com/video/' + video.id + 12422 '?autoplay=1" width="' + width + '" height="' + height + 12423 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 12424 } 12425 12426 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 12427 12428 this._playing = item.addClass('owl-video-playing'); 12429 }; 12430 12431 /** 12432 * Checks whether an video is currently in full screen mode or not. 12433 * @todo Bad style because looks like a readonly method but changes members. 12434 * @protected 12435 * @returns {Boolean} 12436 */ 12437 Video.prototype.isInFullScreen = function() { 12438 var element = document.fullscreenElement || document.mozFullScreenElement || 12439 document.webkitFullscreenElement; 12440 12441 return element && $(element).parent().hasClass('owl-video-frame'); 12442 }; 12443 12444 /** 12445 * Destroys the plugin. 12446 */ 12447 Video.prototype.destroy = function() { 12448 var handler, property; 12449 12450 this._core.$element.off('click.owl.video'); 12451 12452 for (handler in this._handlers) { 12453 this._core.$element.off(handler, this._handlers[handler]); 12454 } 12455 for (property in Object.getOwnPropertyNames(this)) { 12456 typeof this[property] != 'function' && (this[property] = null); 12457 } 12458 }; 12459 12460 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 12461 12462})(window.Zepto || window.jQuery, window, document); 12463 12464/** 12465 * Animate Plugin 12466 * @version 2.0.0-beta.3 12467 * @author Bartosz Wojciechowski 12468 * @license The MIT License (MIT) 12469 */ 12470;(function($, window, document, undefined) { 12471 12472 /** 12473 * Creates the animate plugin. 12474 * @class The Navigation Plugin 12475 * @param {Owl} scope - The Owl Carousel 12476 */ 12477 var Animate = function(scope) { 12478 this.core = scope; 12479 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 12480 this.swapping = true; 12481 this.previous = undefined; 12482 this.next = undefined; 12483 12484 this.handlers = { 12485 'change.owl.carousel': $.proxy(function(e) { 12486 if (e.namespace && e.property.name == 'position') { 12487 this.previous = this.core.current(); 12488 this.next = e.property.value; 12489 } 12490 }, this), 12491 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 12492 if (e.namespace) { 12493 this.swapping = e.type == 'translated'; 12494 } 12495 }, this), 12496 'translate.owl.carousel': $.proxy(function(e) { 12497 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 12498 this.swap(); 12499 } 12500 }, this) 12501 }; 12502 12503 this.core.$element.on(this.handlers); 12504 }; 12505 12506 /** 12507 * Default options. 12508 * @public 12509 */ 12510 Animate.Defaults = { 12511 animateOut: false, 12512 animateIn: false 12513 }; 12514 12515 /** 12516 * Toggles the animation classes whenever an translations starts. 12517 * @protected 12518 * @returns {Boolean|undefined} 12519 */ 12520 Animate.prototype.swap = function() { 12521 12522 if (this.core.settings.items !== 1) { 12523 return; 12524 } 12525 12526 if (!$.support.animation || !$.support.transition) { 12527 return; 12528 } 12529 12530 this.core.speed(0); 12531 12532 var left, 12533 clear = $.proxy(this.clear, this), 12534 previous = this.core.$stage.children().eq(this.previous), 12535 next = this.core.$stage.children().eq(this.next), 12536 incoming = this.core.settings.animateIn, 12537 outgoing = this.core.settings.animateOut; 12538 12539 if (this.core.current() === this.previous) { 12540 return; 12541 } 12542 12543 if (outgoing) { 12544 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 12545 previous.css( { 'left': left + 'px' } ) 12546 .addClass('animated owl-animated-out') 12547 .addClass(outgoing) 12548 .on($.support.animation.end, clear); 12549 } 12550 12551 if (incoming) { 12552 next.addClass('animated owl-animated-in') 12553 .addClass(incoming) 12554 .on($.support.animation.end, clear); 12555 } 12556 }; 12557 12558 Animate.prototype.clear = function(e) { 12559 if ($(e.target).hasClass('animated')) { 12560 $(e.target).css( { 'left': '' } ) 12561 .removeClass('animated owl-animated-out owl-animated-in') 12562 .removeClass(this.core.settings.animateIn) 12563 .removeClass(this.core.settings.animateOut); 12564 this.core.onTransitionEnd(); 12565 } 12566 }; 12567 12568 /** 12569 * Destroys the plugin. 12570 * @public 12571 */ 12572 Animate.prototype.destroy = function() { 12573 var handler, property; 12574 12575 for (handler in this.handlers) { 12576 this.core.$element.off(handler, this.handlers[handler]); 12577 } 12578 for (property in Object.getOwnPropertyNames(this)) { 12579 typeof this[property] != 'function' && (this[property] = null); 12580 } 12581 }; 12582 12583 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 12584 12585})(window.Zepto || window.jQuery, window, document); 12586 12587/** 12588 * Autoplay Plugin 12589 * @version 2.0.0-beta.3 12590 * @author Bartosz Wojciechowski 12591 * @author Artus Kolanowski 12592 * @license The MIT License (MIT) 12593 */ 12594;(function($, window, document, undefined) { 12595 12596 /** 12597 * Creates the autoplay plugin. 12598 * @class The Autoplay Plugin 12599 * @param {Owl} scope - The Owl Carousel 12600 */ 12601 var Autoplay = function(carousel) { 12602 /** 12603 * Reference to the core. 12604 * @protected 12605 * @type {Owl} 12606 */ 12607 this._core = carousel; 12608 12609 /** 12610 * The autoplay interval. 12611 * @type {Number} 12612 */ 12613 this._interval = null; 12614 12615 /** 12616 * Indicates whenever the autoplay is paused. 12617 * @type {Boolean} 12618 */ 12619 this._paused = false; 12620 12621 /** 12622 * All event handlers. 12623 * @protected 12624 * @type {Object} 12625 */ 12626 this._handlers = { 12627 'changed.owl.carousel': $.proxy(function(e) { 12628 if (e.namespace && e.property.name === 'settings') { 12629 if (this._core.settings.autoplay) { 12630 this.play(); 12631 } else { 12632 this.stop(); 12633 } 12634 } 12635 }, this), 12636 'initialized.owl.carousel': $.proxy(function(e) { 12637 if (e.namespace && this._core.settings.autoplay) { 12638 this.play(); 12639 } 12640 }, this), 12641 'play.owl.autoplay': $.proxy(function(e, t, s) { 12642 if (e.namespace) { 12643 this.play(t, s); 12644 } 12645 }, this), 12646 'stop.owl.autoplay': $.proxy(function(e) { 12647 if (e.namespace) { 12648 this.stop(); 12649 } 12650 }, this), 12651 'mouseover.owl.autoplay': $.proxy(function() { 12652 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12653 this.pause(); 12654 } 12655 }, this), 12656 'mouseleave.owl.autoplay': $.proxy(function() { 12657 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12658 this.play(); 12659 } 12660 }, this) 12661 }; 12662 12663 // register event handlers 12664 this._core.$element.on(this._handlers); 12665 12666 // set default options 12667 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 12668 }; 12669 12670 /** 12671 * Default options. 12672 * @public 12673 */ 12674 Autoplay.Defaults = { 12675 autoplay: false, 12676 autoplayTimeout: 5000, 12677 autoplayHoverPause: false, 12678 autoplaySpeed: false 12679 }; 12680 12681 /** 12682 * Starts the autoplay. 12683 * @public 12684 * @param {Number} [timeout] - The interval before the next animation starts. 12685 * @param {Number} [speed] - The animation speed for the animations. 12686 */ 12687 Autoplay.prototype.play = function(timeout, speed) { 12688 this._paused = false; 12689 12690 if (this._core.is('rotating')) { 12691 return; 12692 } 12693 12694 this._core.enter('rotating'); 12695 12696 this._interval = window.setInterval($.proxy(function() { 12697 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 12698 return; 12699 } 12700 this._core.next(speed || this._core.settings.autoplaySpeed); 12701 }, this), timeout || this._core.settings.autoplayTimeout); 12702 }; 12703 12704 /** 12705 * Stops the autoplay. 12706 * @public 12707 */ 12708 Autoplay.prototype.stop = function() { 12709 if (!this._core.is('rotating')) { 12710 return; 12711 } 12712 12713 window.clearInterval(this._interval); 12714 this._core.leave('rotating'); 12715 }; 12716 12717 /** 12718 * Stops the autoplay. 12719 * @public 12720 */ 12721 Autoplay.prototype.pause = function() { 12722 if (!this._core.is('rotating')) { 12723 return; 12724 } 12725 12726 this._paused = true; 12727 }; 12728 12729 /** 12730 * Destroys the plugin. 12731 */ 12732 Autoplay.prototype.destroy = function() { 12733 var handler, property; 12734 12735 this.stop(); 12736 12737 for (handler in this._handlers) { 12738 this._core.$element.off(handler, this._handlers[handler]); 12739 } 12740 for (property in Object.getOwnPropertyNames(this)) { 12741 typeof this[property] != 'function' && (this[property] = null); 12742 } 12743 }; 12744 12745 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 12746 12747})(window.Zepto || window.jQuery, window, document); 12748 12749/** 12750 * Navigation Plugin 12751 * @version 2.0.0-beta.3 12752 * @author Artus Kolanowski 12753 * @license The MIT License (MIT) 12754 */ 12755;(function($, window, document, undefined) { 12756 'use strict'; 12757 12758 /** 12759 * Creates the navigation plugin. 12760 * @class The Navigation Plugin 12761 * @param {Owl} carousel - The Owl Carousel. 12762 */ 12763 var Navigation = function(carousel) { 12764 /** 12765 * Reference to the core. 12766 * @protected 12767 * @type {Owl} 12768 */ 12769 this._core = carousel; 12770 12771 /** 12772 * Indicates whether the plugin is initialized or not. 12773 * @protected 12774 * @type {Boolean} 12775 */ 12776 this._initialized = false; 12777 12778 /** 12779 * The current paging indexes. 12780 * @protected 12781 * @type {Array} 12782 */ 12783 this._pages = []; 12784 12785 /** 12786 * All DOM elements of the user interface. 12787 * @protected 12788 * @type {Object} 12789 */ 12790 this._controls = {}; 12791 12792 /** 12793 * Markup for an indicator. 12794 * @protected 12795 * @type {Array.<String>} 12796 */ 12797 this._templates = []; 12798 12799 /** 12800 * The carousel element. 12801 * @type {jQuery} 12802 */ 12803 this.$element = this._core.$element; 12804 12805 /** 12806 * Overridden methods of the carousel. 12807 * @protected 12808 * @type {Object} 12809 */ 12810 this._overrides = { 12811 next: this._core.next, 12812 prev: this._core.prev, 12813 to: this._core.to 12814 }; 12815 12816 /** 12817 * All event handlers. 12818 * @protected 12819 * @type {Object} 12820 */ 12821 this._handlers = { 12822 'prepared.owl.carousel': $.proxy(function(e) { 12823 if (e.namespace && this._core.settings.dotsData) { 12824 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 12825 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 12826 } 12827 }, this), 12828 'added.owl.carousel': $.proxy(function(e) { 12829 if (e.namespace && this._core.settings.dotsData) { 12830 this._templates.splice(e.position, 0, this._templates.pop()); 12831 } 12832 }, this), 12833 'remove.owl.carousel': $.proxy(function(e) { 12834 if (e.namespace && this._core.settings.dotsData) { 12835 this._templates.splice(e.position, 1); 12836 } 12837 }, this), 12838 'changed.owl.carousel': $.proxy(function(e) { 12839 if (e.namespace && e.property.name == 'position') { 12840 this.draw(); 12841 } 12842 }, this), 12843 'initialized.owl.carousel': $.proxy(function(e) { 12844 if (e.namespace && !this._initialized) { 12845 this._core.trigger('initialize', null, 'navigation'); 12846 this.initialize(); 12847 this.update(); 12848 this.draw(); 12849 this._initialized = true; 12850 this._core.trigger('initialized', null, 'navigation'); 12851 } 12852 }, this), 12853 'refreshed.owl.carousel': $.proxy(function(e) { 12854 if (e.namespace && this._initialized) { 12855 this._core.trigger('refresh', null, 'navigation'); 12856 this.update(); 12857 this.draw(); 12858 this._core.trigger('refreshed', null, 'navigation'); 12859 } 12860 }, this) 12861 }; 12862 12863 // set default options 12864 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 12865 12866 // register event handlers 12867 this.$element.on(this._handlers); 12868 }; 12869 12870 /** 12871 * Default options. 12872 * @public 12873 * @todo Rename `slideBy` to `navBy` 12874 */ 12875 Navigation.Defaults = { 12876 nav: false, 12877 navText: [ 'prev', 'next' ], 12878 navSpeed: false, 12879 navElement: 'div', 12880 navContainer: false, 12881 navContainerClass: 'owl-nav', 12882 navClass: [ 'owl-prev', 'owl-next' ], 12883 slideBy: 1, 12884 dotClass: 'owl-dot', 12885 dotsClass: 'owl-dots', 12886 dots: true, 12887 dotsEach: false, 12888 dotsData: false, 12889 dotsSpeed: false, 12890 dotsContainer: false 12891 }; 12892 12893 /** 12894 * Initializes the layout of the plugin and extends the carousel. 12895 * @protected 12896 */ 12897 Navigation.prototype.initialize = function() { 12898 var override, 12899 settings = this._core.settings; 12900 12901 // create DOM structure for relative navigation 12902 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 12903 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 12904 12905 this._controls.$previous = $('<' + settings.navElement + '>') 12906 .addClass(settings.navClass[0]) 12907 .html(settings.navText[0]) 12908 .prependTo(this._controls.$relative) 12909 .on('click', $.proxy(function(e) { 12910 this.prev(settings.navSpeed); 12911 }, this)); 12912 this._controls.$next = $('<' + settings.navElement + '>') 12913 .addClass(settings.navClass[1]) 12914 .html(settings.navText[1]) 12915 .appendTo(this._controls.$relative) 12916 .on('click', $.proxy(function(e) { 12917 this.next(settings.navSpeed); 12918 }, this)); 12919 12920 // create DOM structure for absolute navigation 12921 if (!settings.dotsData) { 12922 this._templates = [ $('<div>') 12923 .addClass(settings.dotClass) 12924 .append($('<span>')) 12925 .prop('outerHTML') ]; 12926 } 12927 12928 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 12929 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 12930 12931 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 12932 var index = $(e.target).parent().is(this._controls.$absolute) 12933 ? $(e.target).index() : $(e.target).parent().index(); 12934 12935 e.preventDefault(); 12936 12937 this.to(index, settings.dotsSpeed); 12938 }, this)); 12939 12940 // override public methods of the carousel 12941 for (override in this._overrides) { 12942 this._core[override] = $.proxy(this[override], this); 12943 } 12944 }; 12945 12946 /** 12947 * Destroys the plugin. 12948 * @protected 12949 */ 12950 Navigation.prototype.destroy = function() { 12951 var handler, control, property, override; 12952 12953 for (handler in this._handlers) { 12954 this.$element.off(handler, this._handlers[handler]); 12955 } 12956 for (control in this._controls) { 12957 this._controls[control].remove(); 12958 } 12959 for (override in this.overides) { 12960 this._core[override] = this._overrides[override]; 12961 } 12962 for (property in Object.getOwnPropertyNames(this)) { 12963 typeof this[property] != 'function' && (this[property] = null); 12964 } 12965 }; 12966 12967 /** 12968 * Updates the internal state. 12969 * @protected 12970 */ 12971 Navigation.prototype.update = function() { 12972 var i, j, k, 12973 lower = this._core.clones().length / 2, 12974 upper = lower + this._core.items().length, 12975 maximum = this._core.maximum(true), 12976 settings = this._core.settings, 12977 size = settings.center || settings.autoWidth || settings.dotsData 12978 ? 1 : settings.dotsEach || settings.items; 12979 12980 if (settings.slideBy !== 'page') { 12981 settings.slideBy = Math.min(settings.slideBy, settings.items); 12982 } 12983 12984 if (settings.dots || settings.slideBy == 'page') { 12985 this._pages = []; 12986 12987 for (i = lower, j = 0, k = 0; i < upper; i++) { 12988 if (j >= size || j === 0) { 12989 this._pages.push({ 12990 start: Math.min(maximum, i - lower), 12991 end: i - lower + size - 1 12992 }); 12993 if (Math.min(maximum, i - lower) === maximum) { 12994 break; 12995 } 12996 j = 0, ++k; 12997 } 12998 j += this._core.mergers(this._core.relative(i)); 12999 } 13000 } 13001 }; 13002 13003 /** 13004 * Draws the user interface. 13005 * @todo The option `dotsData` wont work. 13006 * @protected 13007 */ 13008 Navigation.prototype.draw = function() { 13009 var difference, 13010 settings = this._core.settings, 13011 disabled = this._core.items().length <= settings.items, 13012 index = this._core.relative(this._core.current()), 13013 loop = settings.loop || settings.rewind; 13014 13015 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 13016 13017 if (settings.nav) { 13018 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 13019 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 13020 } 13021 13022 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 13023 13024 if (settings.dots) { 13025 difference = this._pages.length - this._controls.$absolute.children().length; 13026 13027 if (settings.dotsData && difference !== 0) { 13028 this._controls.$absolute.html(this._templates.join('')); 13029 } else if (difference > 0) { 13030 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 13031 } else if (difference < 0) { 13032 this._controls.$absolute.children().slice(difference).remove(); 13033 } 13034 13035 this._controls.$absolute.find('.active').removeClass('active'); 13036 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 13037 } 13038 }; 13039 13040 /** 13041 * Extends event data. 13042 * @protected 13043 * @param {Event} event - The event object which gets thrown. 13044 */ 13045 Navigation.prototype.onTrigger = function(event) { 13046 var settings = this._core.settings; 13047 13048 event.page = { 13049 index: $.inArray(this.current(), this._pages), 13050 count: this._pages.length, 13051 size: settings && (settings.center || settings.autoWidth || settings.dotsData 13052 ? 1 : settings.dotsEach || settings.items) 13053 }; 13054 }; 13055 13056 /** 13057 * Gets the current page position of the carousel. 13058 * @protected 13059 * @returns {Number} 13060 */ 13061 Navigation.prototype.current = function() { 13062 var current = this._core.relative(this._core.current()); 13063 return $.grep(this._pages, $.proxy(function(page, index) { 13064 return page.start <= current && page.end >= current; 13065 }, this)).pop(); 13066 }; 13067 13068 /** 13069 * Gets the current succesor/predecessor position. 13070 * @protected 13071 * @returns {Number} 13072 */ 13073 Navigation.prototype.getPosition = function(successor) { 13074 var position, length, 13075 settings = this._core.settings; 13076 13077 if (settings.slideBy == 'page') { 13078 position = $.inArray(this.current(), this._pages); 13079 length = this._pages.length; 13080 successor ? ++position : --position;
vendor: 5,678 bytes, lines 13081-13305
13081 position = this._pages[((position % length) + length) % length].start; 13082 } else { 13083 position = this._core.relative(this._core.current()); 13084 length = this._core.items().length; 13085 successor ? position += settings.slideBy : position -= settings.slideBy; 13086 } 13087 13088 return position; 13089 }; 13090 13091 /** 13092 * Slides to the next item or page. 13093 * @public 13094 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13095 */ 13096 Navigation.prototype.next = function(speed) { 13097 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 13098 }; 13099 13100 /** 13101 * Slides to the previous item or page. 13102 * @public 13103 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13104 */ 13105 Navigation.prototype.prev = function(speed) { 13106 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 13107 }; 13108 13109 /** 13110 * Slides to the specified item or page. 13111 * @public 13112 * @param {Number} position - The position of the item or page. 13113 * @param {Number} [speed] - The time in milliseconds for the transition. 13114 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 13115 */ 13116 Navigation.prototype.to = function(position, speed, standard) { 13117 var length; 13118 13119 if (!standard) { 13120 length = this._pages.length; 13121 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 13122 } else { 13123 $.proxy(this._overrides.to, this._core)(position, speed); 13124 } 13125 }; 13126 13127 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 13128 13129})(window.Zepto || window.jQuery, window, document); 13130 13131/** 13132 * Hash Plugin 13133 * @version 2.0.0-beta.3 13134 * @author Artus Kolanowski 13135 * @license The MIT License (MIT) 13136 */ 13137;(function($, window, document, undefined) { 13138 'use strict'; 13139 13140 /** 13141 * Creates the hash plugin. 13142 * @class The Hash Plugin 13143 * @param {Owl} carousel - The Owl Carousel 13144 */ 13145 var Hash = function(carousel) { 13146 /** 13147 * Reference to the core. 13148 * @protected 13149 * @type {Owl} 13150 */ 13151 this._core = carousel; 13152 13153 /** 13154 * Hash index for the items. 13155 * @protected 13156 * @type {Object} 13157 */ 13158 this._hashes = {}; 13159 13160 /** 13161 * The carousel element. 13162 * @type {jQuery} 13163 */ 13164 this.$element = this._core.$element; 13165 13166 /** 13167 * All event handlers. 13168 * @protected 13169 * @type {Object} 13170 */ 13171 this._handlers = { 13172 /*'initialized.owl.carousel': $.proxy(function(e) { 13173 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 13174 $(window).trigger('hashchange.owl.navigation'); 13175 } 13176 }, this),*/ 13177 'prepared.owl.carousel': $.proxy(function(e) { 13178 if (e.namespace) { 13179 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 13180 13181 if (!hash) { 13182 return; 13183 } 13184 13185 this._hashes[hash] = e.content; 13186 } 13187 }, this), 13188 'changed.owl.carousel': $.proxy(function(e) { 13189 if (e.namespace && e.property.name === 'position') { 13190 var current = this._core.items(this._core.relative(this._core.current())), 13191 hash = $.map(this._hashes, function(item, hash) { 13192 return item === current ? hash : null; 13193 }).join(); 13194 13195 if (!hash || window.location.hash.slice(1) === hash) { 13196 return; 13197 } 13198 13199 window.location.hash = hash; 13200 } 13201 }, this) 13202 }; 13203 13204 // set default options 13205 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 13206 13207 // register the event handlers 13208 this.$element.on(this._handlers); 13209 13210 // register event listener for hash navigation 13211 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 13212 var hash = window.location.hash.substring(1), 13213 items = this._core.$stage.children(), 13214 position = this._hashes[hash] && items.index(this._hashes[hash]); 13215 13216 if (position === undefined || position === this._core.current()) { 13217 return; 13218 } 13219 13220 this._core.to(this._core.relative(position), false, true); 13221 }, this));*/ 13222 }; 13223 13224 /** 13225 * Default options. 13226 * @public 13227 */ 13228 Hash.Defaults = { 13229 URLhashListener: false 13230 }; 13231 13232 /** 13233 * Destroys the plugin. 13234 * @public 13235 */ 13236 Hash.prototype.destroy = function() { 13237 var handler, property; 13238 13239 $(window).off('hashchange.owl.navigation'); 13240 13241 for (handler in this._handlers) { 13242 this._core.$element.off(handler, this._handlers[handler]); 13243 } 13244 for (property in Object.getOwnPropertyNames(this)) { 13245 typeof this[property] != 'function' && (this[property] = null); 13246 } 13247 }; 13248 13249 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 13250 13251})(window.Zepto || window.jQuery, window, document); 13252 13253/** 13254 * Support Plugin 13255 * 13256 * @version 2.0.0-beta.3 13257 * @author Vivid Planet Software GmbH 13258 * @author Artus Kolanowski 13259 * @license The MIT License (MIT) 13260 */ 13261;(function($, window, document, undefined) { 13262 13263 var style = $('<support>').get(0).style, 13264 prefixes = 'Webkit Moz O ms'.split(' '), 13265 events = { 13266 transition: { 13267 end: { 13268 WebkitTransition: 'webkitTransitionEnd', 13269 MozTransition: 'transitionend', 13270 OTransition: 'oTransitionEnd', 13271 transition: 'transitionend' 13272 } 13273 }, 13274 animation: { 13275 end: { 13276 WebkitAnimation: 'webkitAnimationEnd', 13277 MozAnimation: 'animationend', 13278 OAnimation: 'oAnimationEnd', 13279 animation: 'animationend' 13280 } 13281 } 13282 }, 13283 tests = { 13284 csstransforms: function() { 13285 return !!test('transform'); 13286 }, 13287 csstransforms3d: function() { 13288 return !!test('perspective'); 13289 }, 13290 csstransitions: function() { 13291 return !!test('transition'); 13292 }, 13293 cssanimations: function() { 13294 return !!test('animation'); 13295 } 13296 }; 13297 13298 function test(property, prefixed) { 13299 var result = false, 13300 upper = property.charAt(0).toUpperCase() + property.slice(1); 13301 13302 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 13303 if (style[property] !== undefined) { 13304 result = prefixed ? property : true; 13305 return false;
13306 } 13307 }); 13308 13309 return result; 13310 } 13311 13312 function prefixed(property) { 13313 return test(property, true); 13314 } 13315 13316 if (tests.csstransitions()) { 13317 /* jshint -W053 */ 13318 $.support.transition = new String(prefixed('transition')) 13319 $.support.transition.end = events.transition.end[ $.support.transition ]; 13320 } 13321 13322 if (tests.cssanimations()) { 13323 /* jshint -W053 */ 13324 $.support.animation = new String(prefixed('animation')) 13325 $.support.animation.end = events.animation.end[ $.support.animation ]; 13326 } 13327 13328 if (tests.csstransforms()) { 13329 /* jshint -W053 */ 13330 $.support.transform = new String(prefixed('transform')); 13331 $.support.transform3d = tests.csstransforms3d(); 13332 } 13333 13334})(window.Zepto || window.jQuery, window, document); 13335 13336(function(window, document, undefined) { 13337 13338 /** 13339 * Find the absolute position of an element 13340 */ 13341 var absPos = function(element) { 13342 var offsetLeft, offsetTop; 13343 offsetLeft = offsetTop = 0; 13344 if (element.offsetParent) { 13345 do { 13346 offsetLeft += element.offsetLeft; 13347 offsetTop += element.offsetTop; 13348 } while (element = element.offsetParent); 13349 } 13350 return [offsetLeft, offsetTop]; 13351 }; 13352 13353 /** 13354 * @constructor Progress Circle class 13355 * @param params.canvas Canvas on which the circles will be drawn. 13356 * @param params.minRadius Inner radius of the innermost circle, in px. 13357 * @param params.arcWidth Width of each circle(to be more accurate, ring). 13358 * @param params.gapWidth Space between each circle. 13359 * @param params.centerX X coordinate of the center of circles. 13360 * @param params.centerY Y coordinate of the center of circles. 13361 * @param params.infoLineBaseAngle Base angle of the info line. 13362 * @param params.infoLineAngleInterval Angles between the info lines. 13363 */ 13364 var ProgressCircle = function(params) { 13365 this.canvas = params.canvas; 13366 this.minRadius = params.minRadius || 15; 13367 this.arcWidth = params.arcWidth || 5; 13368 this.gapWidth = params.gapWidth || 3; 13369 this.centerX = params.centerX || this.canvas.width / 2; 13370 this.centerY = params.centerY || this.canvas.height / 2;
13371 this.infoLineLength = params.infoLineLength || 60; 13372 this.horizLineLength = params.horizLineLength || 10; 13373 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 13374 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 13375 13376 this.context = this.canvas.getContext('2d'); 13377 13378 this.width = this.canvas.width; 13379 this.height = this.canvas.height; 13380 13381 this.circles = []; 13382 this.runningCount = 0; 13383 }; 13384 13385 ProgressCircle.prototype = { 13386 constructor: ProgressCircle, 13387 13388 /** 13389 * @method Adds an progress monitor entry. 13390 * @param params.fillColor Color to fill in the circle. 13391 * @param params.outlineColor Color to outline the circle. 13392 * @param params.progressListener Callback function to fetch the progress. 13393 * @param params.infoListener Callback function to fetch the info. 13394 * @returns this 13395 */ 13396 addEntry: function(params) { 13397 this.circles.push(new Circle({ 13398 canvas: this.canvas, 13399 context: this.context, 13400 centerX: this.centerX, 13401 centerY: this.centerY, 13402 innerRadius: this.minRadius + this.circles.length * 13403 (this.gapWidth + this.arcWidth), 13404 arcWidth: this.arcWidth,
13405 infoLineLength: this.infoLineLength, 13406 horizLineLength: this.horizLineLength, 13407 13408 id: this.circles.length, 13409 fillColor: params.fillColor, 13410 outlineColor: params.outlineColor, 13411 progressListener: params.progressListener, 13412 infoListener: params.infoListener, 13413 infoLineAngle: this.infoLineBaseAngle + 13414 this.circles.length * this.infoLineAngleInterval, 13415 })); 13416 13417 return this; 13418 }, 13419 13420 /** 13421 * @method Starts the monitor and updates with the given interval. 13422 * @param interval Interval between updates, in millisecond. 13423 * @returns this 13424 */ 13425 start: function(interval) { 13426 var self = this; 13427 this.timer = setInterval(function() { 13428 self._update(); 13429 }, interval || 33); 13430 13431 return this; 13432 }, 13433 13434 /** 13435 * @method Stop the animation. 13436 */ 13437 stop: function() { 13438 clearTimeout(this.timer); 13439 }, 13440 13441 /** 13442 * @private 13443 * @method Call update on each circle and redraw them. 13444 * @returns this 13445 */ 13446 _update: function() { 13447 this._clear(); 13448 this.circles.forEach(function(circle, idx, array) { 13449 circle.update(); 13450 }); 13451 13452 return this; 13453 }, 13454 13455 /** 13456 * @private 13457 * @method Clear the canvas. 13458 * @returns this 13459 */ 13460 _clear: function() { 13461 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 13462 13463 return this; 13464 }, 13465 13466 }; 13467 13468 /** 13469 * @private 13470 * @class Individual progress circle. 13471 * @param params.canvas Canvas on which the circle will be drawn. 13472 * @param params.context Context of the canvas. 13473 * @param params.innerRadius Inner radius of the circle, in px. 13474 * @param params.arcWidth Width of each arc(circle). 13475 * @param params.gapWidth Distance between each arc. 13476 * @param params.centerX X coordinate of the center of circles. 13477 * @param params.centerY Y coordinate of the center of circles. 13478 * @param params.fillColor Color to fill in the circle. 13479 * @param params.outlineColor Color to outline the circle. 13480 * @param params.progressListener Callback function to fetch the progress. 13481 * @param params.infoListener Callback function to fetch the info. 13482 * @param params.infoLineAngle Angle of info line. 13483 */ 13484 var Circle = function(params) { 13485 this.id = params.id; 13486 this.canvas = params.canvas; 13487 this.context = params.context; 13488 this.centerX = params.centerX; 13489 this.centerY = params.centerY; 13490 this.arcWidth = params.arcWidth; 13491 this.innerRadius = params.innerRadius || 0; 13492 this.fillColor = params.fillColor || '#fff'; 13493 this.outlineColor = params.outlineColor || this.fillColor; 13494 this.progressListener = params.progressListener;
13495 this.infoLineLength = params.infoLineLength || 250; 13496 this.horizLineLength = params.horizLineLength || 50; 13497 this.infoListener = params.infoListener; 13498 this.infoLineAngle = params.infoLineAngle; 13499 13500 this.outerRadius = this.innerRadius + this.arcWidth; 13501 13502 // If the info listener is not registered, then don't calculate 13503 // the related coordinates 13504 if (!this.infoListener) return; 13505 13506 // calculate the info-line turning points 13507 var angle = this.infoLineAngle, 13508 arcDistance = (this.innerRadius + this.outerRadius) / 2, 13509 13510 sinA = Math.sin(angle), 13511 cosA = Math.cos(angle); 13512 13513 this.infoLineStartX = this.centerX + sinA * arcDistance; 13514 this.infoLineStartY = this.centerY - cosA * arcDistance; 13515 13516 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 13517 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 13518 13519 this.infoLineEndX = this.infoLineMidX + 13520 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 13521 this.infoLineEndY = this.infoLineMidY; 13522 13523 var infoText = document.createElement('div'), 13524 style = infoText.style; 13525 13526 style.color = this.fillColor; 13527 style.position = 'absolute'; 13528 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 13529 // style.top will be calculated in the `drawInfo` method. Since 13530 // user may want to change the size of the font, so the top offset 13531 // must be updated in each loop. 13532 infoText.className = 'ProgressCircleInfo'; // For css styling 13533 infoText.id = 'progress_circle_info_' + this.id; 13534 document.body.appendChild(infoText); 13535 this.infoText = infoText; 13536 }; 13537 13538 Circle.prototype = { 13539 constructor: Circle, 13540 13541 update: function() { 13542 this.progress = this.progressListener(); 13543 this._draw(); 13544 13545 if (this.infoListener) { 13546 this.info = this.infoListener(); 13547 this._drawInfo(); 13548 } 13549 }, 13550 13551 /** 13552 * @private 13553 * @method Draw the circle on the canvas. 13554 * @returns this 13555 */ 13556 _draw: function() { 13557 var ctx = this.context, 13558 13559 ANGLE_OFFSET = -Math.PI / 2, 13560 13561 startAngle = 0 + ANGLE_OFFSET, 13562 endAngle= startAngle + this.progress * Math.PI * 2, 13563 13564 x = this.centerX, 13565 y = this.centerY, 13566 13567 innerRadius = this.innerRadius - this.arcWidth - 1, 13568 outerRadius = this.outerRadius - this.arcWidth - 1; 13569 13570 ctx.fillStyle = this.fillColor; 13571 ctx.strokeStyle = this.outlineColor; 13572 13573 ctx.beginPath(); 13574 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 13575 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 13576 ctx.closePath(); 13577 ctx.stroke(); 13578 ctx.fill(); 13579 13580 return this; 13581 }, 13582 13583 /** 13584 * @private 13585 * @method Draw the info lines and info text. 13586 * @returns this 13587 */ 13588 _drawInfo: function() { 13589 13590 var pointList, lineHeight; 13591 13592 pointList = [ 13593 [this.infoLineStartX, this.infoLineStartY], 13594 [this.infoLineMidX, this.infoLineMidY], 13595 [this.infoLineEndX, this.infoLineEndY], 13596 ]; 13597 this._drawSegments(pointList, false); 13598 13599 this.infoText.innerHTML = this.info; 13600 13601 lineHeight = this.infoText.offsetHeight; 13602 this.infoText.style.top = this.infoLineEndY + 13603 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 13604 13605 return this; 13606 }, 13607 13608 /** 13609 * @private 13610 * @method Helper function to draw the segments 13611 * @param pointList An array of points in the form of [x, y]. 13612 * @param close Whether to connect the first and last point. 13613 */ 13614 _drawSegments: function(pointList, close) { 13615 var ctx = this.context; 13616 13617 ctx.beginPath(); 13618 ctx.moveTo(pointList[0][0], pointList[0][1]); 13619 for (var i = 1; i < pointList.length; ++i) { 13620 ctx.lineTo(pointList[i][0], pointList[i][1]); 13621 } 13622 13623 if (close) { 13624 ctx.closePath(); 13625 } 13626 ctx.stroke(); 13627 }, 13628 }; 13629 13630 window.ProgressCircle = ProgressCircle; 13631 13632})(window, document); 13633 13634 13635 13636 13637/* ========================================================= 13638 * jquery.vc_chart.js v1.0 13639 * ========================================================= 13640 * Copyright 2013 Wpbakery 13641 * 13642 * Jquery chart plugin for the Visual Composer.
13643 * ========================================================= */ 13644(function($){ 13645 /** 13646 * Pie chart animated. 13647 * @param element - DOM element 13648 * @param options - settings object. 13649 * @constructor 13650 */ 13651 var VcChart = function(element, options) { 13652 this.el = element; 13653 this.$el = $(this.el); 13654 this.options = $.extend({ 13655 color: 'wpb_button', 13656 units: '', 13657 width: '', 13658 label_selector: '.vc_pie_chart_value', 13659 back_selector: '.vc_pie_chart_back', 13660 responsive: true 13661 }, options); 13662 this.init(); 13663 }; 13664 VcChart.prototype = { 13665 constructor: VcChart, 13666 _progress_v: 0, 13667 animated: false, 13668 colors: { 13669 'wpb_button': 'rgba(247, 247, 247, 1)', 13670 'btn-primary': 'rgba(0, 136, 204, 1)', 13671 'btn-info': 'rgba(88, 185, 218, 1)', 13672 'btn-success': 'rgba(106, 177, 101, 1)', 13673 'btn-warning': 'rgba(255, 153, 0, 1)', 13674 'btn-danger': 'rgba(255, 103, 91, 1)', 13675 'btn-inverse': 'rgba(85, 85, 85, 1)' 13676 }, 13677 init: function() { 13678 this.setupColor(); 13679 this.value = this.$el.data('pie-value')/100; 13680 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 13681 this.$wrapper = $('.vc_pie_wrapper', this.$el); 13682 this.$label = $(this.options.label_selector, this.$el); 13683 this.$back = $(this.options.back_selector, this.$el); 13684 this.$canvas = this.$el.find('canvas'); 13685 this.arcWidth = this.$el.data('pie-width') * 2; 13686 this.draw(); 13687 this.setWayPoint(); 13688 if(this.options.responsive === true) this.setResponsive(); 13689 if (UNCODE.isMobile) this._progress_v = this.value; 13690 }, 13691 setupColor: function() { 13692 // if(typeof this.colors[this.options.color] !== 'undefined') { 13693 // this.color = this.colors[this.options.color]; 13694 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 13695 // this.color = this.options.color; 13696 // } else { 13697 // this.color = 'rgba(247, 247, 247, 0.2)'; 13698 // } 13699 if(typeof this.options.color !== 'undefined') { 13700 this.color = this.options.color; 13701 } else this.color = 'rgba(247, 247, 247, 0.2)'; 13702 13703 }, 13704 setResponsive: function() { 13705 var that = this; 13706 if (!UNCODE.isMobile) { 13707 $(window).resize(function(){ 13708 if(that.animated === true) that.circle.stop(); 13709 that.draw(true); 13710 }); 13711 } 13712 }, 13713 draw: function(redraw) { 13714 var w = this.$el.addClass('vc_ready').width() * 2, 13715 border_w = this.arcWidth, 13716 radius; 13717 if(!w) w = this.$el.parents(':visible').first().width()-2; 13718 //w = Math.round(w/100*80); 13719 //if (w < 250) w = 250; 13720 radius = w/2; 13721 this.$wrapper.css({"width" : (w / 2) + "px"}); 13722 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 13723 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 13724 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 13725 this.$el.addClass('vc_ready'); 13726 this.circle = new ProgressCircle({ 13727 canvas: this.$canvas.get(0), 13728 minRadius: radius, 13729 arcWidth: border_w 13730 }); 13731 if(redraw === true && this.animated === true) { 13732 this._progress_v = this.value; 13733 this.circle.addEntry({ 13734 fillColor: this.color, 13735 progressListener: $.proxy(this.setProgress, this) 13736 }).start(); 13737 } 13738 }, 13739 setProgress: function() { 13740 if (this._progress_v >= this.value) { 13741 this.circle.stop(); 13742 this.$label.html(this.label_value + this.options.units); 13743 return this._progress_v; 13744 } 13745 this._progress_v += 0.01; 13746 if (!isNaN(this.label_value)) { 13747 var label_value = this._progress_v/this.value*this.label_value; 13748 var val = Math.round(label_value) + this.options.units; 13749 this.$label.html(val); 13750 } else this.$label.html(this.label_value + this.options.units); 13751 return this._progress_v; 13752 }, 13753 animate: function() { 13754 if(this.animated !== true) { 13755 this.animated = true; 13756 this.circle.addEntry({ 13757 fillColor: this.color, 13758 progressListener: $.proxy(this.setProgress, this) 13759 }).start(5); 13760 } 13761 }, 13762 setWayPoint: function() { 13763 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 13764 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 13765 } else { 13766 this.animate(); 13767 } 13768 } 13769 }; 13770 /** 13771 * jQuery plugin 13772 * @param option - object with settings 13773 * @return {*} 13774 */ 13775 $.fn.vcChat = function(option, value) { 13776 return this.each(function () { 13777 var $this = $(this), 13778 data = $this.data('vc_chart'), 13779 options = typeof option === 'object' ? option : { 13780 color: $this.data('pie-color'), 13781 units: $this.data('pie-units') 13782 }; 13783 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 13784 if (typeof option == 'string') data[option](value); 13785 }); 13786 }; 13787 /** 13788 * Allows users to rewrite function inside theme. 13789 */ 13790 if ( typeof window['vc_pieChart'] !== 'function' ) { 13791 window.vc_pieChart = function() { 13792 $('.vc_pie_chart:visible').vcChat(); 13793 } 13794 } 13795 $(document).ready(function(){ 13796 !window.vc_iframe && vc_pieChart(); 13797 }); 13798 13799})(window.jQuery); 13800 13801 13802/* Progress bar 13803 ---------------------------------------------------------- */ 13804function uncode_progress_bar() {    13805 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 13806 if (!UNCODE.isMobile) { 13807 new Waypoint({ 13808 element: val, 13809 handler: function() { 13810 var element = jQuery(this.element); 13811 element.find('.vc_single_bar').each(function(index) {          13812 var $this = jQuery(this), 13813             bar = $this.find('.vc_bar'), 13814             val = bar.data('percentage-value');          13815 setTimeout(function() {            13816 bar.css({ 13817 "width": val + '%' 13818 });          13819 }, index * 200);        13820 }); 13821 }, 13822 offset: '80%' 13823 }); 13824 } else { 13825 var element = jQuery(val); 13826 element.find('.vc_single_bar').each(function(index) {          13827 var $this = jQuery(this), 13828             bar = $this.find('.vc_bar'), 13829             val = bar.data('percentage-value');          13830 setTimeout(function() {            13831 bar.css({ 13832 "width": val + '%' 13833 });          13834 }, index * 200);        13835 }); 13836 } 13837 }); 13838}; 13839uncode_progress_bar(); 13840 13841/*! 13842 * jquery.counterup.js 1.0 13843 * 13844 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 13845 * Released under the GPL v2 License 13846 * 13847 * Date: Nov 26, 2013 13848 */ 13849(function($) { 13850 "use strict"; 13851 $.fn.counterUp = function(options) { 13852 // Defaults 13853 var settings = $.extend({ 13854 'time': 400, 13855 'delay': 10 13856 }, options); 13857 return this.each(function() { 13858 // Store the object 13859 var $this = $(this); 13860 var $settings = settings; 13861 var counterUpper = function() { 13862 var nums = []; 13863 var divisions = $settings.time / $settings.delay; 13864 var numReal = $this.attr('data-val'), 13865 num = numReal; 13866 var isComma = /[0-9]+,[0-9]+/.test(num); 13867 num = num.replace(/,/g, ''); 13868 var isInt = /^[0-9]+$/.test(num); 13869 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 13870 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 13871 // Generate list of incremental numbers to display 13872 for (var i = divisions; i >= 1; i--) { 13873 // Preserve as int if input was int 13874 var newNum = parseInt(num / divisions * i); 13875 // Preserve float if input was float 13876 if (isFloat) { 13877 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 13878 } 13879 // Preserve commas if input had commas 13880 if (isComma) { 13881 while (/(\d+)(\d{3})/.test(newNum.toString())) { 13882 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 13883 } 13884 } 13885 nums.unshift(newNum); 13886 } 13887 nums.push(numReal); 13888 $this.data('counterup-nums', nums); 13889 $this.text('0'); 13890 // Updates the number until we're done 13891 var f = function() { 13892 if ($this.data('counterup-nums') != null) { 13893 $this.text($this.data('counterup-nums').shift()); 13894 if ($this.data('counterup-nums').length) { 13895 setTimeout($this.data('counterup-func'), $settings.delay); 13896 } else { 13897 delete $this.data('counterup-nums'); 13898 $this.data('counterup-nums', null); 13899 $this.data('counterup-func', null); 13900 } 13901 } 13902 }; 13903 $this.data('counterup-func', f); 13904 // Start the count up 13905 setTimeout($this.data('counterup-func'), $settings.delay); 13906 }; 13907 // Perform counts when the element gets into view 13908 new Waypoint({ 13909 element: this, 13910 handler: function() { 13911 counterUpper(); 13912 this.destroy(); 13913 }, 13914 offset: '100%' 13915 }); 13916 }); 13917 }; 13918})(jQuery); 13919 13920/*! 13921 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 13922 * Copyright (c) 2014 Edson Hilios 13923 * 13924 * Permission is hereby granted, free of charge, to any person obtaining a copy of 13925 * this software and associated documentation files (the "Software"), to deal in 13926 * the Software without restriction, including without limitation the rights to 13927 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13928 * the Software, and to permit persons to whom the Software is furnished to do so, 13929 * subject to the following conditions: 13930 * 13931 * The above copyright notice and this permission notice shall be included in all 13932 * copies or substantial portions of the Software. 13933 * 13934 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13935 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13936 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13937 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13938 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 13939 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13940 */ 13941!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;
13941if(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])})}}); 13942 13943/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 13944* https://github.com/alexanderdickson/waitForImages 13945* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 13946;(function (factory) { 13947 if (typeof define === 'function' && define.amd) { 13948 // AMD. Register as an anonymous module. 13949 define(['jquery'], factory); 13950 } else if (typeof exports === 'object') { 13951 // CommonJS / nodejs module 13952 module.exports = factory(require('jquery')); 13953 } else { 13954 // Browser globals 13955 factory(jQuery); 13956 } 13957}(function ($) { 13958 // Namespace all events. 13959 var eventNamespace = 'waitForImages'; 13960 13961 // CSS properties which contain references to images. 13962 $.waitForImages = { 13963 hasImageProperties: [ 13964 'backgroundImage', 13965 'listStyleImage', 13966 'borderImage', 13967 'borderCornerImage', 13968 'cursor' 13969 ], 13970 hasImageAttributes: ['srcset'] 13971 }; 13972 13973 // Custom selector to find `img` elements that have a valid `src` 13974 // attribute and have not already loaded. 13975 $.expr[':'].uncached = function (obj) { 13976 // Ensure we are dealing with an `img` element with a valid 13977 // `src` attribute. 13978 if (!$(obj).is('img[src][src!=""]')) { 13979 return false;
13980 } 13981 13982 return !obj.complete; 13983 }; 13984 13985 $.fn.waitForImages = function () { 13986 13987 var allImgsLength = 0; 13988 var allImgsLoaded = 0; 13989 var deferred = $.Deferred(); 13990 13991 var finishedCallback; 13992 var eachCallback; 13993 var waitForAll; 13994 13995 // Handle options object (if passed). 13996 if ($.isPlainObject(arguments[0])) { 13997 13998 waitForAll = arguments[0].waitForAll; 13999 eachCallback = arguments[0].each; 14000 finishedCallback = arguments[0].finished; 14001 14002 } else { 14003 14004 // Handle if using deferred object and only one param was passed in. 14005 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 14006 waitForAll = arguments[0]; 14007 } else { 14008 finishedCallback = arguments[0]; 14009 eachCallback = arguments[1]; 14010 waitForAll = arguments[2]; 14011 } 14012 14013 } 14014 14015 // Handle missing callbacks. 14016 finishedCallback = finishedCallback || $.noop; 14017 eachCallback = eachCallback || $.noop; 14018 14019 // Convert waitForAll to Boolean 14020 waitForAll = !! waitForAll; 14021 14022 // Ensure callbacks are functions. 14023 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 14024 throw new TypeError('An invalid callback was supplied.'); 14025 } 14026 14027 this.each(function () { 14028 // Build a list of all imgs, dependent on what images will 14029 // be considered. 14030 var obj = $(this); 14031 var allImgs = []; 14032 // CSS properties which may contain an image. 14033 var hasImgProperties = $.waitForImages.hasImageProperties || []; 14034 // Element attributes which may contain an image. 14035 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 14036 // To match `url()` references. 14037 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 14038 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 14039 14040 if (waitForAll) { 14041 14042 // Get all elements (including the original), as any one of 14043 // them could have a background image. 14044 obj.find('*').addBack().each(function () { 14045 var element = $(this); 14046 14047 // If an `img` element, add it. But keep iterating in 14048 // case it has a background image too. 14049 if (element.is('img:uncached')) { 14050 allImgs.push({ 14051 src: element.attr('src'), 14052 element: element[0] 14053 }); 14054 } 14055 14056 $.each(hasImgProperties, function (i, property) { 14057 var propertyValue = element.css(property); 14058 var match; 14059 14060 // If it doesn't contain this property, skip. 14061 if (!propertyValue) { 14062 return true; 14063 } 14064 14065 // Get all url() of this element. 14066 while (match = matchUrl.exec(propertyValue)) { 14067 allImgs.push({ 14068 src: match[2], 14069 element: element[0] 14070 }); 14071 } 14072 }); 14073 14074 $.each(hasImageAttributes, function (i, attribute) { 14075 var attributeValue = element.attr(attribute); 14076 var attributeValues; 14077 14078 // If it doesn't contain this property, skip. 14079 if (!attributeValue) { 14080 return true; 14081 } 14082 14083 // Check for multiple comma separated images 14084 attributeValues = attributeValue.split(','); 14085 14086 $.each(attributeValues, function(i, value) { 14087 // Trim value and get string before first 14088 // whitespace (for use with srcset). 14089 value = $.trim(value).split(' ')[0]; 14090 allImgs.push({ 14091 src: value, 14092 element: element[0] 14093 }); 14094 }); 14095 }); 14096 }); 14097 } else { 14098 // For images only, the task is simpler. 14099 obj.find('img:uncached') 14100 .each(function () { 14101 allImgs.push({ 14102 src: this.src, 14103 element: this 14104 }); 14105 }); 14106 } 14107 14108 allImgsLength = allImgs.length; 14109 allImgsLoaded = 0; 14110 14111 // If no images found, don't bother. 14112 if (allImgsLength === 0) { 14113 finishedCallback.call(obj[0]); 14114 deferred.resolveWith(obj[0]); 14115 } 14116 14117 $.each(allImgs, function (i, img) { 14118 14119 var image = new Image(); 14120 var events = 14121 'load.' + eventNamespace + ' error.' + eventNamespace; 14122 14123 // Handle the image loading and error with the same callback. 14124 $(image).one(events, function me (event) { 14125 // If an error occurred with loading the image, set the 14126 // third argument accordingly. 14127 var eachArguments = [ 14128 allImgsLoaded, 14129 allImgsLength,
14130 event.type == 'load' 14131 ]; 14132 allImgsLoaded++; 14133 14134 eachCallback.apply(img.element, eachArguments); 14135 deferred.notifyWith(img.element, eachArguments); 14136 14137 // Unbind the event listeners. I use this in addition to 14138 // `one` as one of those events won't be called (either 14139 // 'load' or 'error' will be called). 14140 $(this).off(events, me); 14141 14142 if (allImgsLoaded == allImgsLength) { 14143 finishedCallback.call(obj[0]); 14144 deferred.resolveWith(obj[0]); 14145 return false; 14146 } 14147 14148 }); 14149 14150 image.src = img.src; 14151 }); 14152 }); 14153 14154 return deferred.promise(); 14155 14156 }; 14157})); 14158 14159/** 14160 * @preserve textfill 14161 * @name jquery.textfill.js 14162 * @author Russ Painter 14163 * @author Yu-Jie Lin 14164 * @author Alexandre Dantas 14165 * @version 0.6.0 14166 * @date 2014-08-19 14167 * @copyright (c) 2014 Alexandre Dantas 14168 * @copyright (c) 2012-2013 Yu-Jie Lin 14169 * @copyright (c) 2009 Russ Painter 14170 * @license MIT License 14171 * @homepage https://github.com/jquery-textfill/jquery-textfill 14172 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 14173 */ 14174; (function($) { 14175 14176 /** 14177 * Resizes an inner element's font so that the 14178 * inner element completely fills the outer element. 14179 * 14180 * @param {Object} options User options that take 14181 * higher precedence when 14182 * merging with the default ones. 14183 * 14184 * @return All outer elements processed 14185 */ 14186 $.fn.textfill = function(options) { 14187 14188 // ______ _______ _______ _______ _ _ _______ _______ 14189 // | \ |______ |______ |_____| | | | | |______ 14190 // |_____/ |______ | | | |_____| |_____ | ______| 14191 // 14192 // Merging user options with the default values 14193 14194 var defaults = { 14195 debug : false, 14196 maxFontPixels : 40, 14197 minFontPixels : 4, 14198 innerTag : 'span', 14199 widthOnly : false, 14200 success : null, // callback when a resizing is done 14201 callback : null, // callback when a resizing is done (deprecated, use success) 14202 fail : null, // callback when a resizing is failed 14203 complete : null, // callback when all is done 14204 explicitWidth : null, 14205 explicitHeight : null, 14206 changeLineHeight : false 14207 }; 14208 14209 var Opts = $.extend(defaults, options); 14210 14211 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 14212 // |______ | | | \ | | | | | | | \ | |______ 14213 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 14214 // 14215 // Predefining the awesomeness 14216 14217 // Output arguments to the Debug console 14218 // if "Debug Mode" is enabled 14219 function _debug() { 14220 if (!Opts.debug 14221 || typeof console == 'undefined' 14222 || typeof console.debug == 'undefined') { 14223 return; 14224 } 14225 console.debug.apply(console, arguments); 14226 } 14227 14228 // Output arguments to the Warning console 14229 function _warn() { 14230 if (typeof console == 'undefined' || 14231 typeof console.warn == 'undefined') { 14232 return; 14233 } 14234 console.warn.apply(console, arguments); 14235 } 14236 14237 // Outputs all information on the current sizing 14238 // of the font. 14239 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14240 14241 function _m(v1, v2) { 14242 14243 var marker = ' / '; 14244 14245 if (v1 > v2) 14246 marker = ' > '; 14247 14248 else if (v1 == v2) 14249 marker = ' = '; 14250 14251 return marker; 14252 } 14253 14254 _debug( 14255 '[TextFill] ' + prefix + ' { ' + 14256 'font-size: ' + ourText.css('font-size') + ',' +
14257 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 14258 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 14259 'minFontPixels: ' + minFontPixels + 'px, ' + 14260 'maxFontPixels: ' + maxFontPixels + 'px }' 14261 ); 14262 } 14263 14264 /** 14265 * Calculates which size the font can get resized, 14266 * according to constrains. 14267 * 14268 * @param {String} prefix Gets shown on the console before 14269 * all the arguments, if debug mode is on. 14270 * @param {Object} ourText The DOM element to resize, 14271 * that contains the text. 14272 * @param {function} func Function called on `ourText` that's 14273 * used to compare with `max`. 14274 * @param {number} max Maximum value, that gets compared with 14275 * `func` called on `ourText`. 14276 * @param {number} minFontPixels Minimum value the font can 14277 * get resized to (in pixels). 14278 * @param {number} maxFontPixels Maximum value the font can 14279 * get resized to (in pixels). 14280 * 14281 * @return Size (in pixels) that the font can be resized. 14282 */ 14283 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14284 14285 _debug_sizing( 14286 prefix, ourText, 14287 maxHeight, maxWidth, 14288 minFontPixels, maxFontPixels 14289 ); 14290 14291 // The kernel of the whole plugin, take most attention 14292 // on this part. 14293 // 14294 // This is a loop that keeps increasing the `font-size` 14295 // until it fits the parent element. 14296 // 14297 // - Start from the minimal allowed value (`minFontPixels`) 14298 // - Guesses an average font size (in pixels) for the font, 14299 // - Resizes the text and sees if its size is within the 14300 // boundaries (`minFontPixels` and `maxFontPixels`). 14301 // - If so, keep guessing until we break. 14302 // - If not, return the last calculated size. 14303 // 14304 // I understand this is not optimized and we should 14305 // consider implementing something akin to 14306 // Daniel Hoffmann's answer here: 14307 // 14308 // http://stackoverflow.com/a/17433451/1094964 14309 // 14310 14311 while (minFontPixels < (maxFontPixels - 1)) { 14312 14313 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 14314 ourText.css('font-size', fontSize); 14315 14316 if (func.call(ourText) <= max) { 14317 minFontPixels = fontSize; 14318 14319 if (func.call(ourText) == max) 14320 break; 14321 } 14322 else 14323 maxFontPixels = fontSize; 14324 14325 _debug_sizing( 14326 prefix, ourText, 14327 maxHeight, maxWidth, 14328 minFontPixels, maxFontPixels 14329 ); 14330 } 14331 14332 ourText.css('font-size', maxFontPixels); 14333 14334 if (func.call(ourText) <= max) { 14335 minFontPixels = maxFontPixels; 14336 14337 _debug_sizing( 14338 prefix + '* ', ourText, 14339 maxHeight, maxWidth, 14340 minFontPixels, maxFontPixels 14341 ); 14342 } 14343 return minFontPixels; 14344 } 14345 14346 // _______ _______ _______ ______ _______ 14347 // |______ | |_____| |_____/ | 14348 // ______| | | | | \_ | 14349 // 14350 // Let's get it started (yeah)! 14351 14352 _debug('[TextFill] Start Debug'); 14353 14354 this.each(function() { 14355 14356 // Contains the child element we will resize. 14357 // $(this) means the parent container 14358 var ourText = $(Opts.innerTag + ':visible:first', this); 14359 14360 // Will resize to this dimensions. 14361 // Use explicit dimensions when specified 14362 var maxHeight = Opts.explicitHeight || $(this).height(); 14363 var maxWidth = Opts.explicitWidth || $(this).width(); 14364 14365 var oldFontSize = ourText.css('font-size'); 14366 14367 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 14368 14369 _debug('[TextFill] Inner text: ' + ourText.text()); 14370 _debug('[TextFill] All options: ', Opts); 14371 _debug('[TextFill] Maximum sizes: { ' + 14372 'Height: ' + maxHeight + 'px, ' + 14373 'Width: ' + maxWidth + 'px' + ' }' 14374 ); 14375 14376 var minFontPixels = Opts.minFontPixels; 14377 14378 // Remember, if this `maxFontPixels` is negative, 14379 // the text will resize to as long as the container 14380 // can accomodate 14381 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 14382 maxHeight : 14383 Opts.maxFontPixels); 14384 14385 14386 // Let's start it all! 14387 14388 // 1. Calculate which `font-size` would 14389 // be best for the Height 14390 var fontSizeHeight = undefined; 14391 14392 if (! Opts.widthOnly) 14393 fontSizeHeight = _sizing( 14394 'Height', ourText, 14395 $.fn.height, maxHeight, 14396 maxHeight, maxWidth, 14397 minFontPixels, maxFontPixels 14398 ); 14399 14400 // 2. Calculate which `font-size` would 14401 // be best for the Width 14402 var fontSizeWidth = undefined; 14403 14404 fontSizeWidth = _sizing( 14405 'Width', ourText, 14406 $.fn.width, maxWidth, 14407 maxHeight, maxWidth, 14408 minFontPixels, maxFontPixels 14409 ); 14410 14411 // 3. Actually resize the text! 14412 14413 if (Opts.widthOnly) { 14414 ourText.css({ 14415 'font-size' : fontSizeWidth, 14416 'white-space': 'nowrap' 14417 }); 14418 14419 if (Opts.changeLineHeight) 14420 ourText.parent().css( 14421 'line-height', 14422 (lineHeight * fontSizeWidth + 'px') 14423 ); 14424 } 14425 else { 14426 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 14427 14428 ourText.css('font-size', fontSizeFinal); 14429 14430 if (Opts.changeLineHeight) 14431 ourText.parent().css( 14432 'line-height', 14433 (lineHeight * fontSizeFinal) + 'px' 14434 ); 14435 } 14436 14437 _debug( 14438 '[TextFill] Finished { ' + 14439 'Old font-size: ' + oldFontSize + ', ' + 14440 'New font-size: ' + ourText.css('font-size') + ' }' 14441 ); 14442 14443 // Oops, something wrong happened! 14444 // We weren't supposed to exceed the original size 14445 if ((ourText.width() > maxWidth) ||
14446 (ourText.height() > maxHeight && !Opts.widthOnly)) { 14447 14448 ourText.css('font-size', oldFontSize); 14449 14450 // Failure callback 14451 if (Opts.fail) 14452 Opts.fail(this); 14453 14454 _debug( 14455 '[TextFill] Failure { ' + 14456 'Current Width: ' + ourText.width() + ', ' + 14457 'Maximum Width: ' + maxWidth + ', ' + 14458 'Current Height: ' + ourText.height() + ', ' + 14459 'Maximum Height: ' + maxHeight + ' }' 14460 ); 14461 } 14462 else if (Opts.success) { 14463 Opts.success(this); 14464 } 14465 else if (Opts.callback) { 14466 _warn('callback is deprecated, use success, instead'); 14467 14468 // Success callback 14469 Opts.callback(this); 14470 } 14471 }); 14472 14473 // Complete callback 14474 if (Opts.complete) 14475 Opts.complete(this); 14476 14477 _debug('[TextFill] End Debug'); 14478 return this; 14479 }; 14480 14481})(window.jQuery); 14482 14483 14484!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; 14485function getStyles(config){ 14486 // 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;
14486left: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+"}" 14487}; 14488 var ShareUtils; 14489 14490if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 14491 Object.defineProperty(HTMLElement.prototype, "classList", { 14492 get: function() { 14493 var ret, self, update; 14494 update = function(fn) { 14495 return function(value) { 14496 var classes, index; 14497 classes = self.className.split(/\s+/); 14498 index = classes.indexOf(value); 14499 fn(classes, index, value); 14500 self.className = classes.join(" "); 14501 }; 14502 }; 14503 self = this; 14504 ret = { 14505 add: update(function(classes, index, value) { 14506 ~index || classes.push(value); 14507 }), 14508 remove: update(function(classes, index) { 14509 ~index && classes.splice(index, 1); 14510 }), 14511 toggle: update(function(classes, index, value) { 14512 if (~index) { 14513 classes.splice(index, 1); 14514 } else { 14515 classes.push(value); 14516 } 14517 }), 14518 contains: function(value) { 14519 return !!~self.className.split(/\s+/).indexOf(value); 14520 }, 14521 item: function(i) { 14522 return self.className.split(/\s+/)[i] || null; 14523 } 14524 }; 14525 Object.defineProperty(ret, "length", { 14526 get: function() { 14527 return self.className.split(/\s+/).length; 14528 } 14529 }); 14530 return ret; 14531 } 14532 }); 14533} 14534 14535String.prototype.to_rfc3986 = function() { 14536 var tmp; 14537 tmp = encodeURIComponent(this); 14538 return tmp.replace(/[!'()*]/g, function(c) { 14539 return "%" + c.charCodeAt(0).toString(16); 14540 }); 14541}; 14542 14543ShareUtils = (function() { 14544 function ShareUtils() {} 14545 14546 ShareUtils.prototype.extend = function(to, from, overwrite) { 14547 var hasProp, prop; 14548 for (prop in from) { 14549 hasProp = to[prop] !== undefined; 14550 if (hasProp && typeof from[prop] === "object") { 14551 this.extend(to[prop], from[prop], overwrite); 14552 } else { 14553 if (overwrite || !hasProp) { 14554 to[prop] = from[prop]; 14555 } 14556 } 14557 } 14558 }; 14559 14560 ShareUtils.prototype.hide = function(el) { 14561 return el.style.display = "none"; 14562 }; 14563 14564 ShareUtils.prototype.show = function(el) { 14565 return el.style.display = "block"; 14566 }; 14567 14568 ShareUtils.prototype.has_class = function(el, class_name) { 14569 return el.classList.contains(class_name); 14570 }; 14571 14572 ShareUtils.prototype.add_class = function(el, class_name) { 14573 return el.classList.add(class_name); 14574 }; 14575 14576 ShareUtils.prototype.remove_class = function(el, class_name) { 14577 return el.classList.remove(class_name); 14578 }; 14579 14580 ShareUtils.prototype.is_encoded = function(str) { 14581 str = str.to_rfc3986(); 14582 return decodeURIComponent(str) !== str; 14583 }; 14584 14585 ShareUtils.prototype.encode = function(str) { 14586 if (typeof str === "undefined" || this.is_encoded(str)) { 14587 return str; 14588 } else { 14589 return str.to_rfc3986(); 14590 } 14591 }; 14592 14593 ShareUtils.prototype.popup = function(url, params) { 14594 var k, popup, qs, v; 14595 if (params == null) { 14596 params = {}; 14597 } 14598 popup = { 14599 width: 500, 14600 height: 350 14601 }; 14602 popup.top = (screen.height / 2) - (popup.height / 2); 14603 popup.left = (screen.width / 2) - (popup.width / 2); 14604 qs = ((function() { 14605 var _results; 14606 _results = []; 14607 for (k in params) { 14608 v = params[k]; 14609 _results.push("" + k + "=" + (this.encode(v))); 14610 } 14611 return _results; 14612 }).call(this)).join('&'); 14613 if (qs) { 14614 qs = "?" + qs; 14615 } 14616 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="
14616+ popup.width + ",height=" + popup.height); 14617 }; 14618 14619 return ShareUtils; 14620 14621})(); 14622var Share, 14623 __hasProp = {}.hasOwnProperty, 14624 __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; }; 14625 14626Share = (function(_super) { 14627 __extends(Share, _super); 14628 14629 function Share(element, options) { 14630 this.element = element; 14631 this.el = { 14632 head: document.getElementsByTagName('head')[0], 14633 body: document.getElementsByTagName('body')[0] 14634 }; 14635 this.config = { 14636 enabled_networks: 0, 14637 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 14638 url: window.location.href.replace("&", "%26"), 14639 caption: null, 14640 title: this.default_title(), 14641 image: this.default_image(), 14642 description: this.default_description(), 14643 ui: { 14644 flyout: 'top center', 14645 button_text: 'Share', 14646 button_font: true, 14647 icon_font: true 14648 }, 14649 networks: { 14650 google_plus: { 14651 enabled: true, 14652 url: null 14653 }, 14654 twitter: { 14655 enabled: true, 14656 url: null, 14657 title: null, 14658 description: null 14659 }, 14660 facebook: { 14661 enabled: true, 14662 load_sdk: true, 14663 url: null, 14664 app_id: null, 14665 title: null, 14666 caption: null, 14667 description: null, 14668 image: null 14669 }, 14670 pinterest: { 14671 enabled: true, 14672 url: null, 14673 image: null, 14674 description: null 14675 }, 14676 reddit: { 14677 enabled: true, 14678 url: null, 14679 title: null 14680 }, 14681 linkedin: { 14682 enabled: true, 14683 url: null, 14684 title: null, 14685 description: null 14686 }, 14687 xing: { 14688 enabled: true, 14689 url: null, 14690 title: null, 14691 image: null, 14692 description: null 14693 }, 14694 whatsapp: { 14695 enabled: true, 14696 description: null, 14697 url: null 14698 }, 14699 email: { 14700 enabled: true, 14701 title: null, 14702 description: null, 14703 url: null 14704 } 14705 } 14706 }; 14707 this.setup(element, options); 14708 return this; 14709 } 14710 14711 Share.prototype.setup = function(element, opts) { 14712 var index, instance, instances, _i, _len; 14713 instances = document.querySelectorAll(element); 14714 this.extend(this.config, opts, true); 14715 this.set_global_configuration(); 14716 this.normalize_network_configuration(); 14717 if (this.config.ui.icon_font) { 14718 this.inject_icons(); 14719 } 14720 if (this.config.ui.button_font) { 14721 this.inject_fonts(); 14722 } 14723 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 14724 this.inject_facebook_sdk(); 14725 } 14726 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 14727 instance = instances[index]; 14728 this.setup_instance(element, index); 14729 } 14730 }; 14731 14732 Share.prototype.setup_instance = function(element, index) { 14733 var button, instance, label, network, networks, _i, _len, _results, 14734 _this = this; 14735 instance = document.querySelectorAll(element)[index]; 14736 this.hide(instance); 14737 this.add_class(instance, "sharer-" + index); 14738 instance = document.querySelectorAll(element)[index]; 14739 this.inject_css(instance); 14740 this.inject_html(instance); 14741 this.show(instance); 14742 label = instance.getElementsByTagName("label")[0]; 14743 button = instance.getElementsByClassName("social")[0]; 14744 networks = instance.getElementsByTagName('li'); 14745 this.add_class(button, "networks-" + this.config.enabled_networks); 14746 label.addEventListener("click", function() { 14747 return _this.event_toggle(button); 14748 }); 14749 _this = this; 14750 _results = []; 14751 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 14752 network = networks[index]; 14753 _results.push(network.addEventListener("click", function() { 14754 _this.event_network(instance, this); 14755 return _this.event_close(button); 14756 })); 14757 } 14758 return _results; 14759 }; 14760 14761 Share.prototype.event_toggle = function(button) { 14762 if (this.has_class(button, "active")) { 14763 return this.event_close(button); 14764 } else { 14765 return this.event_open(button); 14766 } 14767 }; 14768 14769 Share.prototype.event_open = function(button) { 14770 if (this.has_class(button, "load")) { 14771 this.remove_class(button, "load"); 14772 } 14773 return this.add_class(button, "active"); 14774 }; 14775 14776 Share.prototype.event_close = function(button) { 14777 return this.remove_class(button, "active"); 14778 }; 14779 14780 Share.prototype.event_network = function(instance, network) { 14781 var name; 14782 name = network.getAttribute("data-network"); 14783 this.hook("before", name, instance);
14784 this["network_" + name](); 14785 return this.hook("after", name, instance); 14786 }; 14787 14788 Share.prototype.open = function() { 14789 return this["public"]("open"); 14790 }; 14791 14792 Share.prototype.close = function() { 14793 return this["public"]("close"); 14794 }; 14795 14796 Share.prototype.toggle = function() { 14797 return this["public"]("toggle"); 14798 }; 14799 14800 Share.prototype["public"] = function(action) { 14801 var button, index, instance, _i, _len, _ref, _results; 14802 _ref = document.querySelectorAll(this.element); 14803 _results = []; 14804 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 14805 instance = _ref[index]; 14806 button = instance.getElementsByClassName("social")[0]; 14807 _results.push(this["event_" + action](button)); 14808 } 14809 return _results; 14810 }; 14811 14812 Share.prototype.network_facebook = function() { 14813 if (this.config.networks.facebook.load_sdk) { 14814 if (!window.FB) { 14815 return console.error("The Facebook JS SDK hasn't loaded yet."); 14816 } 14817 return FB.ui({ 14818 method: 'feed', 14819 name: this.config.networks.facebook.title, 14820 link: this.config.networks.facebook.url, 14821 picture: this.config.networks.facebook.image, 14822 caption: this.config.networks.facebook.caption, 14823 description: this.config.networks.facebook.description 14824 }); 14825 } else { 14826 return this.popup('https://www.facebook.com/sharer/sharer.php', { 14827 u: this.config.networks.facebook.url 14828 }); 14829 } 14830 }; 14831 14832 Share.prototype.network_twitter = function() { 14833 return this.popup('https://twitter.com/intent/tweet', { 14834 text: this.config.networks.twitter.title, 14835 url: this.config.networks.twitter.url 14836 }); 14837 }; 14838 14839 Share.prototype.network_google_plus = function() { 14840 return this.popup('https://plus.google.com/share', { 14841 url: this.config.networks.google_plus.url 14842 }); 14843 }; 14844 14845 Share.prototype.network_pinterest = function() { 14846 return this.popup('https://www.pinterest.com/pin/create/button', { 14847 url: this.config.networks.pinterest.url, 14848 media: this.config.networks.pinterest.image, 14849 description: this.config.networks.pinterest.description 14850 }); 14851 }; 14852 14853 Share.prototype.network_linkedin = function() { 14854 return this.popup('https://www.linkedin.com/shareArticle', { 14855 url: this.config.networks.linkedin.url, 14856 title: this.config.networks.linkedin.title, 14857 summary: this.config.networks.linkedin.description 14858 }); 14859 } 14860 14861 Share.prototype.network_xing = function() { 14862 return this.popup('https://www.xing.com/spi/shares/new', { 14863 url: this.config.networks.xing.url, 14864 image: this.config.networks.xing.image, 14865 title: this.config.networks.xing.title, 14866 summary: this.config.networks.xing.description 14867 }); 14868 } 14869 14870 Share.prototype.network_email = function() { 14871 return this.popup('mailto:', { 14872 subject: this.config.networks.email.title, 14873 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 14874 }); 14875 }; 14876 14877 Share.prototype.inject_icons = function() { 14878 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 14879 }; 14880 14881 Share.prototype.inject_fonts = function() { 14882 // return this.inject_stylesheet("https://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 14883 }; 14884 14885 Share.prototype.inject_stylesheet = function(url) { 14886 var link; 14887 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 14888 link = document.createElement("link"); 14889 link.setAttribute("rel", "stylesheet"); 14890 link.setAttribute("href", url); 14891 return this.el.head.appendChild(link); 14892 } 14893 }; 14894 14895 Share.prototype.inject_css = function(instance) { 14896 var css, meta, selector, style; 14897 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 14898 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 14899 this.config.selector = selector; 14900 css = getStyles(this.config); 14901 style = document.createElement("style"); 14902 style.type = "text/css"; 14903 if (style.styleSheet) { 14904 style.styleSheet.cssText = css; 14905 } else { 14906 style.appendChild(document.createTextNode(css)); 14907 } 14908 this.el.head.appendChild(style); 14909 delete this.config.selector; 14910 meta = document.createElement("meta"); 14911 meta.setAttribute("name", "sharer" + selector); 14912 return this.el.head.appendChild(meta); 14913 } 14914 }; 14915 14916 Share.prototype.inject_html = function(instance) { 14917 //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>"; 14918 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-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>"; 14919 }; 14920 14921 Share.prototype.inject_facebook_sdk = function() { 14922 var fb_root, script; 14923 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 14924 script = document.createElement("script"); 14925 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')"; 14926 fb_root = document.createElement("div"); 14927 fb_root.id = "fb-root"; 14928 this.el.body.appendChild(fb_root); 14929 return this.el.body.appendChild(script); 14930 } 14931 }; 14932 14933 Share.prototype.hook = function(type, network, instance) { 14934 var fn, opts; 14935 fn = this.config.networks[network][type]; 14936 if (typeof fn === "function") { 14937 opts = fn.call(this.config.networks[network], instance); 14938 if (opts !== void 0) { 14939 opts = this.normalize_filter_config_updates(opts); 14940 this.extend(this.config.networks[network], opts, true); 14941 this.normalize_network_configuration(); 14942 } 14943 } 14944 }; 14945 14946 Share.prototype.default_title = function() { 14947 var content; 14948 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 14949 return encodeURIComponent(content.getAttribute('content')); 14950 } else if (content = document.querySelector('title')) { 14951 return encodeURIComponent(content.innerText); 14952 } 14953 }; 14954 14955 Share.prototype.default_image = function() { 14956 var content; 14957 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 14958 return content.getAttribute('content'); 14959 } 14960 }; 14961 14962 Share.prototype.default_description = function() { 14963 var content; 14964 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 14965 return encodeURIComponent(content.getAttribute('content')); 14966 } else { 14967 return ''; 14968 } 14969 }; 14970 14971 Share.prototype.set_global_configuration = function() { 14972 var display, network, option, options, _ref, _results; 14973 _ref = this.config.networks; 14974 _results = []; 14975 for (network in _ref) { 14976 options = _ref[network]; 14977 for (option in options) { 14978 if (this.config.networks[network][option] == null) { 14979 this.config.networks[network][option] = this.config[option]; 14980 } 14981 } 14982 if (this.config.networks[network].enabled) { 14983 display = 'block'; 14984 this.config.enabled_networks += 1; 14985 } else { 14986 display = 'none'; 14987 } 14988 _results.push(this.config.networks[network].display = display); 14989 } 14990 return _results; 14991 }; 14992 14993 Share.prototype.normalize_network_configuration = function() { 14994 if (!this.config.networks.facebook.app_id) { 14995 this.config.networks.facebook.load_sdk = false;
14996 } 14997 if (!this.is_encoded(this.config.networks.twitter.description)) { 14998 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 14999 } 15000 if (typeof this.config.networks.facebook.app_id === 'number') { 15001 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 15002 } 15003 }; 15004 15005 Share.prototype.normalize_filter_config_updates = function(opts) { 15006 if (this.config.networks.facebook.app_id !== opts.app_id) { 15007 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."); 15008 delete opts.app_id; 15009 } 15010 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 15011 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."); 15012 delete opts.app_id; 15013 } 15014 return opts; 15015 }; 15016 15017 return Share; 15018 15019})(ShareUtils); 15020 return Share; 15021}); 15022 15023 15024// Generated by CoffeeScript 1.9.2 15025 15026// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 15027 15028(function() { 15029 var $, win; 15030 15031 $ = this.jQuery || window.jQuery; 15032 15033 win = $(window); 15034 15035 $.fn.stick_in_parent = function(opts) { 15036 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 15037 if (opts == null) { 15038 opts = {}; 15039 } 15040 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; 15041 if (offset_top == null) { 15042 offset_top = 0; 15043 } 15044 if (parent_selector == null) { 15045 parent_selector = void 0; 15046 } 15047 if (inner_scrolling == null) { 15048 inner_scrolling = true; 15049 } 15050 if (sticky_class == null) { 15051 sticky_class = "is_stuck"; 15052 } 15053 doc = $(document); 15054 if (enable_bottoming == null) { 15055 enable_bottoming = true; 15056 } 15057 outer_width = function(el) { 15058 var _el, computed, w; 15059 if (window.getComputedStyle) { 15060 _el = el[0]; 15061 computed = window.getComputedStyle(el[0]); 15062 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 15063 if (computed.getPropertyValue("box-sizing") !== "border-box") { 15064 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 15065 } 15066 return w; 15067 } else { 15068 return el.outerWidth(true); 15069 } 15070 }; 15071 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 15072 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 15073 if (elm.data("sticky_kit")) { 15074 return; 15075 } 15076 elm.data("sticky_kit", true); 15077 last_scroll_height = doc.height(); 15078 parent = elm.parent(); 15079 if (parent_selector != null) { 15080 parent = parent.closest(parent_selector); 15081 } 15082 if (!parent.length) { 15083 throw "failed to find stick parent"; 15084 } 15085 fixed = false; 15086 bottomed = false; 15087 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 15088 if (spacer) { 15089 spacer.css('position', elm.css('position')); 15090 } 15091 recalc = function() { 15092 var border_top, padding_top, restore; 15093 if (detached) { 15094 return; 15095 } 15096 last_scroll_height = doc.height(); 15097 border_top = parseInt(parent.css("border-top-width"), 10); 15098 padding_top = parseInt(parent.css("padding-top"), 10); 15099 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 15100 parent_top = parent.offset().top + border_top + padding_top; 15101 parent_height = parent.height(); 15102 if (fixed) { 15103 fixed = false;
vendor: 6,069 bytes, lines 15104-15299
15104 bottomed = false; 15105 if (manual_spacer == null) { 15106 elm.insertAfter(spacer); 15107 spacer.detach(); 15108 } 15109 elm.css({ 15110 position: "", 15111 top: "", 15112 width: "", 15113 bottom: "" 15114 }).removeClass(sticky_class); 15115 restore = true; 15116 } 15117 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 15118 height = elm.outerHeight(true); 15119 el_float = elm.css("float"); 15120 if (spacer) { 15121 spacer.css({ 15122 width: outer_width(elm), 15123 height: height, 15124 display: elm.css("display"), 15125 "vertical-align": elm.css("vertical-align"), 15126 "float": el_float 15127 }); 15128 } 15129 if (restore) { 15130 return tick(); 15131 } 15132 }; 15133 recalc(); 15134 if (height === parent_height) { 15135 return; 15136 } 15137 last_pos = void 0; 15138 offset = offset_top; 15139 recalc_counter = recalc_every; 15140 tick = function() { 15141 var css, delta, recalced, scroll, will_bottom, win_height; 15142 if (detached) { 15143 return; 15144 } 15145 recalced = false; 15146 if (recalc_counter != null) { 15147 recalc_counter -= 1; 15148 if (recalc_counter <= 0) { 15149 recalc_counter = recalc_every; 15150 recalc(); 15151 recalced = true; 15152 } 15153 } 15154 if (!recalced && doc.height() !== last_scroll_height) { 15155 recalc(); 15156 recalced = true; 15157 } 15158 scroll = win.scrollTop(); 15159 if (last_pos != null) { 15160 delta = scroll - last_pos; 15161 } 15162 last_pos = scroll; 15163 if (fixed) { 15164 if (enable_bottoming) { 15165 will_bottom = scroll + height + offset > parent_height + parent_top; 15166 if (bottomed && !will_bottom) { 15167 bottomed = false; 15168 elm.css({ 15169 position: "fixed", 15170 bottom: "", 15171 top: offset 15172 }).trigger("sticky_kit:unbottom"); 15173 } 15174 } 15175 if (scroll < top) { 15176 fixed = false; 15177 offset = offset_top; 15178 if (manual_spacer == null) { 15179 if (el_float === "left" || el_float === "right") { 15180 elm.insertAfter(spacer); 15181 } 15182 spacer.detach(); 15183 } 15184 css = { 15185 position: "", 15186 width: "", 15187 top: "" 15188 }; 15189 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 15190 } 15191 if (inner_scrolling) { 15192 win_height = win.height(); 15193 if (height + offset_top > win_height) { 15194 if (!bottomed) { 15195 offset -= delta; 15196 offset = Math.max(win_height - height, offset); 15197 offset = Math.min(offset_top, offset); 15198 if (fixed) { 15199 elm.css({ 15200 top: offset + "px" 15201 }); 15202 } 15203 } 15204 } 15205 } 15206 } else { 15207 if (scroll > top) { 15208 fixed = true; 15209 css = { 15210 position: "fixed", 15211 top: offset 15212 }; 15213 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 15214 elm.css(css).addClass(sticky_class); 15215 if (manual_spacer == null) { 15216 elm.after(spacer); 15217 if (el_float === "left" || el_float === "right") { 15218 spacer.append(elm); 15219 } 15220 } 15221 elm.trigger("sticky_kit:stick"); 15222 } 15223 } 15224 if (fixed && enable_bottoming) { 15225 if (will_bottom == null) { 15226 will_bottom = scroll + height + offset > parent_height + parent_top; 15227 } 15228 if (!bottomed && will_bottom) { 15229 bottomed = true; 15230 if (parent.css("position") === "static") { 15231 parent.css({ 15232 position: "relative" 15233 }); 15234 } 15235 return elm.css({ 15236 position: "absolute", 15237 bottom: padding_bottom, 15238 top: "auto" 15239 }).trigger("sticky_kit:bottom"); 15240 } 15241 } 15242 }; 15243 recalc_and_tick = function() { 15244 recalc(); 15245 return tick(); 15246 }; 15247 detach = function() { 15248 detached = true; 15249 win.off("touchmove", tick); 15250 win.off("scroll", tick); 15251 win.off("resize", recalc_and_tick); 15252 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 15253 elm.off("sticky_kit:detach", detach); 15254 elm.removeData("sticky_kit"); 15255 elm.css({ 15256 position: "", 15257 bottom: "", 15258 top: "", 15259 width: "" 15260 }); 15261 parent.position("position", ""); 15262 if (fixed) { 15263 if (manual_spacer == null) { 15264 if (el_float === "left" || el_float === "right") { 15265 elm.insertAfter(spacer); 15266 } 15267 spacer.remove(); 15268 } 15269 return elm.removeClass(sticky_class); 15270 } 15271 }; 15272 win.on("touchmove", tick); 15273 win.on("scroll", tick); 15274 win.on("resize", recalc_and_tick); 15275 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 15276 elm.on("sticky_kit:detach", detach); 15277 return setTimeout(tick, 0); 15278 }; 15279 for (i = 0, len = this.length; i < len; i++) { 15280 elm = this[i]; 15281 fn($(elm)); 15282 } 15283 return this; 15284 }; 15285 15286}).call(this); 15287 15288/* ========================================================================== 15289 * bootstrap-tab-history.js 15290 * Author: Michael Narayan <[email protected]> 15291 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 15292 * ========================================================================== 15293 * Licensed under the Apache License, Version 2.0 (the "License"); you may 15294 * not use this file except in compliance with the License. You may obtain a 15295 * copy of the License at 15296 * 15297 * http://www.apache.org/licenses/LICENSE-2.0 15298 * 15299 * Unless required by applicable law or agreed to in writing, softw
15299are 15300 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15301 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15302 * License for the specific language governing permissions and limitations 15303 * under the License. 15304 * ========================================================================== */ 15305 15306/* ========================================================================== */ 15307/* JSHint directives */ 15308/* */ 15309/* global BootstrapTabHistory: true */ 15310/* */ 15311/* global document */ 15312/* global jQuery */ 15313/* global history */ 15314/* global window */ 15315/* ========================================================================== */ 15316 15317/** 15318 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 15319 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 15320 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 15321 * 15322 * See the README for additional information. 15323 * 15324 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 15325 */ 15326 15327BootstrapTabHistory = { 15328 options: { 15329 /** 15330 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 15331 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 15332 * 15333 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 15334 * 15335 * @public 15336 * @type {?number} 15337 */ 15338 defaultAnchorYOffset: 0, 15339 /** 15340 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 15341 * 15342 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 15343 * 15344 * @public 15345 * @type {string} 15346 */ 15347 defaultChanger: 'replace', 15348 /** 15349 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 15350 * `null` is passed as the third parameter to these calls. 15351 * 15352 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 15353 * 15354 * @public 15355 * @type {boolean} 15356 */ 15357 defaultUpdateURL: false, 15358 /** 15359 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 15360 * load. 15361 * 15362 * @public 15363 * @type {boolean} 15364 */ 15365 showTabsBasedOnAnchor: true 15366 } 15367}; 15368 15369(function () { 15370 'use strict'; 15371 15372 jQuery(function () { 15373 if(history && history.pushState && history.replaceState) { 15374 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15375 15376 if(bootstrapTabHistory) { 15377 showTabsBasedOnState(bootstrapTabHistory); 15378 } else { 15379 showTabsBasedOnAnchor(); 15380 } 15381 15382 backfillHistoryState(); 15383 15384 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 15385 jQuery(window).on('popstate', onPopState); 15386 } else { 15387 showTabsBasedOnAnchor(); 15388 } 15389 }); 15390 15391 /** 15392 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 15393 * 15394 * @type {boolean} 15395 */ 15396 var showingTabsBasedOnState = false; 15397 15398 /** 15399 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 15400 * `history.back` handling when `data-tab-history-update-url` is true. 15401 */ 15402 function backfillHistoryState() { 15403 var newState = null; 15404 15405 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 15406 var $activeTabElement = jQuery(this); 15407 var selector = getTabSelector($activeTabElement); 15408 15409 if(selector) { 15410 var tabGroup = getTabGroup($activeTabElement); 15411 15412 if(tabGroup) { 15413 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 15414 } 15415 } 15416 }); 15417 15418 if(newState) { 15419 history.replaceState(newState, '', null); 15420 } 15421 } 15422 15423 /** 15424 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 15425 * said bootstrapTabHistory attribute. 15426 * 15427 * @param {?object} existingState 15428 * @param {!string} tabGroup 15429 * @param {!string} selector 15430 * @returns {!object} 15431 */ 15432 function createNewHistoryState(existingState, tabGroup, selector) { 15433 // Clone history.state and ensure it has a bootstrapTabHistory entry. 15434 var newState = jQuery.extend(true, {}, existingState, { 15435 bootstrapTabHistory: {} 15436 }); 15437 15438 newState.bootstrapTabHistory[tabGroup] = selector; 15439 15440 return newState; 15441 } 15442 15443 /** 15444 * @param {jQuery} $tab
15445 * @returns {?string} 15446 */ 15447 function getTabGroup($tab) { 15448 return parseTruthyAttributeValue($tab.data('tab-history')); 15449 } 15450 15451 /** 15452 * @param {jQuery} $tab 15453 * @returns {?string} 15454 */ 15455 function getTabSelector($tab) { 15456 return $tab.data('target') || $tab.attr('href'); 15457 } 15458 15459 /** 15460 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 15461 * 15462 * @param {jQuery.Event} shownEvt 15463 */ 15464 function onShownTab(shownEvt) { 15465 if(!showingTabsBasedOnState) { 15466 var $activatedTab = jQuery(shownEvt.target); 15467 if ( $activatedTab.hasClass('panel-collapse') ) 15468 $activatedTab = $activatedTab.closest('.panel').find('a'); 15469 var selector = getTabSelector($activatedTab); 15470 15471 if(selector) { 15472 var tabGroup = getTabGroup($activatedTab); 15473 15474 if(tabGroup) { 15475 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 15476 var newState = createNewHistoryState(history.state, tabGroup, selector); 15477 var updateURL = (function ($activatedTab) { 15478 if(selector[0] === '#') { 15479 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 15480 15481 if(elementUpdateURLOption === undefined) { 15482 return BootstrapTabHistory.options.defaultUpdateURL; 15483 } else { 15484 return elementUpdateURLOption; 15485 } 15486 } else { 15487 return false; 15488 } 15489 })($activatedTab); 15490 15491 switch(historyChanger) { 15492 case 'push': 15493 history.pushState(newState, '', updateURL ? selector : null); 15494 break; 15495 case 'replace': 15496 history.replaceState(newState, '', updateURL ? selector : null); 15497 break; 15498 default: 15499 throw new Error('Unknown tab-history-changer: ' + historyChanger); 15500 } 15501 } 15502 } 15503 } 15504 } 15505 15506 /** 15507 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 15508 */ 15509 function onPopState() { 15510 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15511 15512 if(bootstrapTabHistory) { 15513 showTabsBasedOnState(bootstrapTabHistory); 15514 } 15515 } 15516 15517 /** 15518 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 15519 * 15520 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 15521 * 15522 * @param {*} value 15523 * @returns {*} 15524 */ 15525 function parseTruthyAttributeValue(value) { 15526 if(value) { 15527 return value; 15528 } else if(value === '') { 15529 return true; 15530 } else { 15531 return value; 15532 } 15533 } 15534 15535 /** 15536 * Show tabs based upon the anchor component of `window.location`. 15537 */ 15538 function showTabsBasedOnAnchor() { 15539 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 15540 var anchor = window.location && window.location.hash; 15541 15542 if(anchor) { 15543 var $tabElement = showTabForSelector(anchor); 15544 15545 if($tabElement && window.addEventListener && window.removeEventListener) { 15546 var anchorYOffset = (function ($tabElement) { 15547 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 15548 15549 if(elementSetting === undefined) { 15550 return BootstrapTabHistory.options.defaultAnchorYOffset; 15551 } else { 15552 return elementSetting; 15553 } 15554 })($tabElement); 15555 15556 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 15557 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 15558 // `history.state` object should have been used (unless the browser did not support the modern History API). 15559 if(anchorYOffset || anchorYOffset === 0) { 15560 var scrollListener = function resetAnchorScroll () { 15561 window.removeEventListener('scroll', scrollListener); 15562 window.scrollTo(0, anchorYOffset); 15563 }; 15564 15565 window.addEventListener('scroll', scrollListener); 15566 } 15567 } 15568 } 15569 } 15570 } 15571 15572 /** 15573 * Show a tab which corresponds to the provided selector. 15574 * 15575 * @param {string} selector - A CSS selector. 15576 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 15577 */ 15578 function showTabForSelector(selector) { 15579 var $tabElement = (function (selector) { 15580 var $ret = null; 15581 15582 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 15583 var $potentialTab = jQuery(this); 15584 15585 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 15586 $ret = $potentialTab; 15587 return false;
vendor: 4,523 bytes, lines 15588-15738
15588 } else { 15589 return null; 15590 } 15591 }); 15592 15593 return $ret; 15594 })(selector); 15595 15596 if($tabElement) { 15597 $tabElement.trigger('click'); 15598 //$tabElement.tab('show'); 15599 } 15600 15601 return $tabElement; 15602 } 15603 15604 /** 15605 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 15606 * 15607 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 15608 */ 15609 function showTabsBasedOnState(bootstrapTabHistory) { 15610 showingTabsBasedOnState = true; 15611 15612 try { 15613 for(var k in bootstrapTabHistory) { 15614 if(bootstrapTabHistory.hasOwnProperty(k)) { 15615 showTabForSelector(bootstrapTabHistory[k]); 15616 } 15617 } 15618 } finally { 15619 showingTabsBasedOnState = false; 15620 } 15621 } 15622})(); 15623 15624 15625/*! 15626 * Justified Gallery - v3.6.3 15627 * http://miromannino.github.io/Justified-Gallery/ 15628 * Copyright (c) 2016 Miro Mannino 15629 * Licensed under the MIT license. 15630 */ 15631(function($) { 15632 15633 function hasScrollBar() { 15634 return $("body").height() > $(window).height(); 15635 } 15636 /** 15637 * Justified Gallery controller constructor 15638 * 15639 * @param $gallery the gallery to build 15640 * @param settings the settings (the defaults are in $.fn.justifiedGallery.defaults) 15641 * @constructor 15642 */ 15643 var JustifiedGallery = function ($gallery, settings) { 15644 15645 this.settings = settings; 15646 this.checkSettings(); 15647 15648 this.imgAnalyzerTimeout = null; 15649 this.entries = null; 15650 this.buildingRow = { 15651 entriesBuff : [], 15652 width : 0, 15653 height : 0, 15654 aspectRatio : 0 15655 }; 15656 this.lastFetchedEntry = null; 15657 this.lastAnalyzedIndex = -1; 15658 this.yield = { 15659 every : 2, // do a flush every n flushes (must be greater than 1) 15660 flushed : 0 // flushed rows without a yield 15661 }; 15662 this.border = settings.border >= 0 ? settings.border : settings.margins; 15663 this.maxRowHeight = this.retrieveMaxRowHeight(); 15664 this.suffixRanges = this.retrieveSuffixRanges(); 15665 this.offY = this.border; 15666 this.rows = 0; 15667 this.spinner = { 15668 phase : 0, 15669 timeSlot : 150, 15670 $el : $('<div class="spinner"><span></span><span></span><span></span></div>'), 15671 intervalId : null 15672 }; 15673 this.checkWidthIntervalId = null; 15674 this.galleryWidth = $gallery.width(); 15675 this.$gallery = $gallery; 15676 15677 }; 15678 15679 /** @returns {String} the best suffix given the width and the height */ 15680 JustifiedGallery.prototype.getSuffix = function (width, height) { 15681 var longestSide, i; 15682 longestSide = (width > height) ? width : height; 15683 for (i = 0; i < this.suffixRanges.length; i++) { 15684 if (longestSide <= this.suffixRanges[i]) { 15685 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 15686 } 15687 } 15688 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 15689 }; 15690 15691 /** 15692 * Remove the suffix from the string 15693 * 15694 * @returns {string} a new string without the suffix 15695 */ 15696 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 15697 return str.substring(0, str.length - suffix.length); 15698 }; 15699 15700 /** 15701 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 15702 */ 15703 JustifiedGallery.prototype.endsWith = function (str, suffix) { 15704 return str.indexOf(suffix, str.length - suffix.length) !== -1; 15705 }; 15706 15707 /** 15708 * Get the used suffix of a particular url 15709 * 15710 * @param str 15711 * @returns {String} return the used suffix 15712 */ 15713 JustifiedGallery.prototype.getUsedSuffix = function (str) { 15714 for (var si in this.settings.sizeRangeSuffixes) { 15715 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 15716 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 15717 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 15718 } 15719 } 15720 return ''; 15721 }; 15722 15723 /** 15724 * Given an image src, with the width and the height, returns the new image src with the 15725 * best suffix to show the best quality thumbnail. 15726 * 15727 * @returns {String} the suffix to use 15728 */ 15729 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 15730 var newImageSrc; 15731 15732 if (this.settings.thumbnailPath) { 15733 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 15734 } else { 15735 var matchRes = imageSrc.match(this.settings.extension); 15736 var ext = (matchRes !== null) ? matchRes[0] : ''; 15737 newImageSrc = imageSrc.replace(this.settings.extension, ''); 15738 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
15739 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 15740 } 15741 15742 return newImageSrc; 15743 }; 15744 15745 /** 15746 * Shows the images that is in the given entry 15747 * 15748 * @param $entry the entry 15749 * @param callback the callback that is called when the show animation is finished 15750 */ 15751 JustifiedGallery.prototype.showImg = function ($entry, callback) { 15752 if (this.settings.cssAnimation) { 15753 $entry.addClass('entry-visible'); 15754 if (callback) callback(); 15755 } else { 15756 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15757 $entry.find('> img, > a > img').stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15758 } 15759 }; 15760 15761 /** 15762 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 15763 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 15764 * 15765 * @param $image the image to analyze 15766 * @returns {String} the extracted src 15767 */ 15768 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 15769 var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src'); 15770 $image.data('jg.originalSrc', imageSrc); 15771 return imageSrc; 15772 }; 15773 15774 /** @returns {jQuery} the image in the given entry */ 15775 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 15776 var $img = $entry.find('> img'); 15777 if ($img.length === 0) $img = $entry.find('> a > img'); 15778 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 15779 return $img.length === 0 ? null : $img; 15780 }; 15781 15782 /** @returns {jQuery} the caption in the given entry */ 15783 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 15784 var $caption = $entry.find('> .caption'); 15785 return $caption.length === 0 ? null : $caption; 15786 }; 15787 15788 /** 15789 * Display the entry 15790 * 15791 * @param {jQuery} $entry the entry to display 15792 * @param {int} x the x position where the entry must be positioned 15793 * @param y the y position where the entry must be positioned 15794 * @param imgWidth the image width 15795 * @param imgHeight the image height 15796 * @param rowHeight the row height of the row that owns the entry 15797 */ 15798 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 15799 $entry.width(imgWidth); 15800 $entry.height(Math.floor(rowHeight));//hacked by Uncode 15801 $entry.css('top', Math.floor(y));//hacked by Uncode 15802 $entry.css('left', x); 15803 15804 var $image = this.imgFromEntry($entry); 15805 if ($image !== null) { 15806 $image.css('width', imgWidth); 15807 $image.css('height', imgHeight); 15808 $image.css('margin-left', - imgWidth / 2); 15809 $image.css('margin-top', - imgHeight / 2); 15810 15811 // Image reloading for an high quality of thumbnails 15812 var imageSrc = $image.attr('src'); 15813 var newImageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 15814 15815 $image.one('error', function () { 15816 $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it. 15817 }); 15818 15819 var loadNewImage = function () { 15820 if (imageSrc !== newImageSrc) { //load the new image after the fadeIn 15821 $image.attr('src', newImageSrc); 15822 } 15823 }; 15824 15825 if ($entry.data('jg.loaded') === 'skipped') { 15826 this.onImageEvent(imageSrc, $.proxy(function() { 15827 this.showImg($entry, loadNewImage); 15828 $entry.data('jg.loaded', true); 15829 }, this)); 15830 } else { 15831 this.showImg($entry, loadNewImage); 15832 } 15833 15834 } else { 15835 this.showImg($entry); 15836 } 15837 15838 this.displayEntryCaption($entry); 15839 }; 15840 15841 /** 15842 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 15843 * or the 'title' attributes. 15844 * 15845 * @param {jQuery} $entry the entry to process 15846 */ 15847 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 15848 var $image = this.imgFromEntry($entry); 15849 if ($image !== null && this.settings.captions) { 15850 var $imgCaption = this.captionFromEntry($entry); 15851 15852 // Create it if it doesn't exists 15853 if ($imgCaption === null) { 15854 var caption = $image.attr('alt'); 15855 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 15856 if (this.isValidCaption(caption)) { // Create only we found something 15857 $imgCaption = $('<div class="caption">' + caption + '</div>'); 15858 $entry.append($imgCaption); 15859 $entry.data('jg.createdCaption', true); 15860 } 15861 } 15862 15863 // Create events (we check again the $imgCaption because it can be still inexistent) 15864 if ($imgCaption !== null) { 15865 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 15866 this.addCaptionEventsHandlers($entry); 15867 } 15868 } else { 15869 this.removeCaptionEventsHandlers($entry); 15870 } 15871 }; 15872 15873 /** 15874 * Validates the caption 15875 * 15876 * @param caption The caption that should be validated 15877 * @return {boolean} Validation result 15878 */ 15879 JustifiedGallery.prototype.isValidCaption = function (caption) { 15880 return (typeof caption !== 'undefined' && caption.length > 0); 15881 }; 15882 15883 /** 15884 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 15885 * It shows the caption using jQuery (or using CSS if it is configured so) 15886 * 15887 * @param {Event} eventObject the event object 15888 */ 15889 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 15890 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15891 if (this.settings.cssAnimation) { 15892 $caption.addClass('caption-visible').removeClass('caption-hidden'); 15893 } else { 15894 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15895 this.settings.captionSettings.visibleOpacity); 15896 } 15897 }; 15898 15899 /** 15900 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 15901 * It hides the caption using jQuery (or using CSS if it is configured so) 15902 * 15903 * @param {Event} eventObject the event object 15904 */ 15905 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 15906 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15907 if (this.settings.cssAnimation) { 15908 $caption.removeClass('caption-visible').removeClass('caption-hidden'); 15909 } else { 15910 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15911 this.settings.captionSettings.nonVisibleOpacity); 15912 } 15913 }; 15914 15915 /** 15916 * Add the handlers of the entry for the caption 15917 * 15918 * @param $entry the entry to modify 15919 */ 15920 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 15921 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15922 if (typeof captionMouseEvents === 'undefined') { 15923 captionMouseEvents = { 15924 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 15925 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 15926 }; 15927 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 15928 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 15929 $entry.data('jg.captionMouseEvents', captionMouseEvents); 15930 } 15931 }; 15932 15933 /** 15934 * Remove the handlers of the entry for the caption 15935 * 15936 * @param $entry the entry to modify 15937 */ 15938 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 15939 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15940 if (typeof captionMouseEvents !== 'undefined') { 15941 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 15942 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 15943 $entry.removeData('jg.captionMouseEvents'); 15944 } 15945 }; 15946 15947 /** 15948 * Justify the building row, preparing it to 15949 * 15950 * @param isLastRow 15951 * @returns a boolean to know if the row has been justified or not 15952 */ 15953 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow) { 15954 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 15955 var minHeight = 0; 15956 var availableWidth = this.galleryWidth - 2 * this.border - ( 15957 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 15958 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 15959 var defaultRowHeight = this.settings.rowHeight; 15960 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 15961 15962 //Skip the last row if we can't justify it and the lastRow == 'hide' 15963 if (isLastRow && this.settings.lastRow === 'hide' && !justifiable) { 15964 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15965 $entry = this.buildingRow.entriesBuff[i]; 15966 if (this.settings.cssAnimation) 15967 $entry.removeClass('entry-visible'); 15968 else { 15969 $entry.stop().fadeTo(0, 0.1); 15970 $entry.find('> img, > a > img').fadeTo(0, 0); 15971 } 15972 } 15973 return -1; 15974 } 15975 15976 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 15977 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 15978 justify = false;
15979 15980 if (this.rows > 0) { 15981 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 15982 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 15983 } 15984 } 15985 15986 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15987 $entry = this.buildingRow.entriesBuff[i]; 15988 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 15989 15990 if (justify) { 15991 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 15992 newImgH = rowHeight; 15993 } else { 15994 newImgW = defaultRowHeight * imgAspectRatio; 15995 newImgH = defaultRowHeight; 15996 } 15997 15998 availableWidth -= Math.round(newImgW); 15999 $entry.data('jg.jwidth', Math.round(newImgW)); 16000 $entry.data('jg.jheight', Math.ceil(newImgH)); 16001 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 16002 } 16003 16004 this.buildingRow.height = minHeight; 16005 return justify; 16006 }; 16007 16008 /** 16009 * Clear the building row data to be used for a new row 16010 */ 16011 JustifiedGallery.prototype.clearBuildingRow = function () { 16012 this.buildingRow.entriesBuff = []; 16013 this.buildingRow.aspectRatio = 0; 16014 this.buildingRow.width = 0; 16015 }; 16016 16017 /** 16018 * Flush a row: justify it, modify the gallery height accordingly to the row height 16019 * 16020 * @param isLastRow 16021 */ 16022 JustifiedGallery.prototype.flushRow = function (isLastRow) { 16023 var settings = this.settings; 16024 var $entry, buildingRowRes, offX = this.border, i; 16025 16026 buildingRowRes = this.prepareBuildingRow(isLastRow); 16027 if (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1) { 16028 this.clearBuildingRow(); 16029 return; 16030 } 16031 16032 if (this.maxRowHeight) { 16033 if (this.maxRowHeight.isPercentage && this.maxRowHeight.value * settings.rowHeight < this.buildingRow.height) { 16034 this.buildingRow.height = this.maxRowHeight.value * settings.rowHeight; 16035 } else if (this.maxRowHeight.value >= settings.rowHeight && this.maxRowHeight.value < this.buildingRow.height) { 16036 this.buildingRow.height = this.maxRowHeight.value; 16037 } 16038 } 16039 16040 //Align last (unjustified) row 16041 if (settings.lastRow === 'center' || settings.lastRow === 'right') { 16042 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 16043 16044 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16045 $entry = this.buildingRow.entriesBuff[i]; 16046 availableWidth -= $entry.data('jg.jwidth'); 16047 } 16048 16049 if (settings.lastRow === 'center') 16050 offX += availableWidth / 2; 16051 else if (settings.lastRow === 'right') 16052 offX += availableWidth; 16053 } 16054 16055 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16056 $entry = this.buildingRow.entriesBuff[i]; 16057 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 16058 offX += $entry.data('jg.jwidth') + settings.margins; 16059 } 16060 16061 //Gallery Height 16062 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 16063 this.$gallery.height(this.galleryHeightToSet + this.getSpinnerHeight()); 16064 16065 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 16066 //Ready for a new row 16067 this.offY += this.buildingRow.height + settings.margins; 16068 this.rows += 1; 16069 this.clearBuildingRow(); 16070 this.$gallery.trigger('jg.rowflush'); 16071 } 16072 }; 16073 16074 /** 16075 * Checks the width of the gallery container, to know if a new justification is needed 16076 */ 16077 var scrollBarOn = false; 16078 JustifiedGallery.prototype.checkWidth = function () { 16079 this.checkWidthIntervalId = setInterval($.proxy(function () { 16080 var galleryWidth = parseFloat(this.$gallery.width()); 16081 if (hasScrollBar() === scrollBarOn) { 16082 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 16083 this.galleryWidth = galleryWidth; 16084 this.rewind(); 16085 16086 // Restart to analyze 16087 this.startImgAnalyzer(true); 16088 } 16089 } else { 16090 scrollBarOn = hasScrollBar(); 16091 this.galleryWidth = galleryWidth; 16092 } 16093 }, this), this.settings.refreshTime); 16094 }; 16095 16096 /** 16097 * @returns {boolean} a boolean saying if the spinner is active or not 16098 */ 16099 JustifiedGallery.prototype.isSpinnerActive = function () { 16100 return this.spinner.intervalId !== null; 16101 }; 16102 16103 /** 16104 * @returns {int} the spinner height 16105 */ 16106 JustifiedGallery.prototype.getSpinnerHeight = function () {
16107 return this.spinner.$el.innerHeight(); 16108 }; 16109 16110 /** 16111 * Stops the spinner animation and modify the gallery height to exclude the spinner 16112 */ 16113 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 16114 clearInterval(this.spinner.intervalId); 16115 this.spinner.intervalId = null; 16116 this.$gallery.height(this.$gallery.height() - this.getSpinnerHeight()); 16117 this.spinner.$el.detach(); 16118 }; 16119 16120 /** 16121 * Starts the spinner animation 16122 */ 16123 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 16124 var spinnerContext = this.spinner; 16125 var $spinnerPoints = spinnerContext.$el.find('span'); 16126 clearInterval(spinnerContext.intervalId); 16127 this.$gallery.append(spinnerContext.$el); 16128 this.$gallery.height(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 16129 spinnerContext.intervalId = setInterval(function () { 16130 if (spinnerContext.phase < $spinnerPoints.length) { 16131 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 16132 } else {
vendor: 4,333 bytes, lines 16133-16277
16133 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 16134 } 16135 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 16136 }, spinnerContext.timeSlot); 16137 }; 16138 16139 /** 16140 * Rewind the image analysis to start from the first entry. 16141 */ 16142 JustifiedGallery.prototype.rewind = function () { 16143 this.lastFetchedEntry = null; 16144 this.lastAnalyzedIndex = -1; 16145 this.offY = this.border; 16146 this.rows = 0; 16147 this.clearBuildingRow(); 16148 }; 16149 16150 /** 16151 * Update the entries searching it from the justified gallery HTML element 16152 * 16153 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 16154 * @returns {boolean} true if some entries has been founded 16155 */ 16156 JustifiedGallery.prototype.updateEntries = function (norewind) { 16157 var newEntries; 16158 16159 if (norewind && this.lastFetchedEntry != null) { 16160 newEntries = $(this.lastFetchedEntry).nextAll(this.settings.selector).toArray(); 16161 } else { 16162 this.entries = []; 16163 newEntries = this.$gallery.children(this.settings.selector).toArray(); 16164 } 16165 16166 if (newEntries.length > 0) { 16167 16168 // Sort or randomize 16169 if ($.isFunction(this.settings.sort)) { 16170 newEntries = this.sortArray(newEntries); 16171 } else if (this.settings.randomize) { 16172 newEntries = this.shuffleArray(newEntries); 16173 } 16174 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 16175 16176 // Filter 16177 if (this.settings.filter) { 16178 newEntries = this.filterArray(newEntries); 16179 } else { 16180 this.resetFilters(newEntries); 16181 } 16182 16183 } 16184 16185 this.entries = this.entries.concat(newEntries); 16186 return true; 16187 }; 16188 16189 /** 16190 * Apply the entries order to the DOM, iterating the entries and appending the images 16191 * 16192 * @param entries the entries that has been modified and that must be re-ordered in the DOM 16193 */ 16194 JustifiedGallery.prototype.insertToGallery = function (entries) { 16195 var that = this; 16196 $.each(entries, function () { 16197 $(this).appendTo(that.$gallery); 16198 }); 16199 }; 16200 16201 /** 16202 * Shuffle the array using the Fisher-Yates shuffle algorithm 16203 * 16204 * @param a the array to shuffle 16205 * @return the shuffled array 16206 */ 16207 JustifiedGallery.prototype.shuffleArray = function (a) { 16208 var i, j, temp; 16209 for (i = a.length - 1; i > 0; i--) { 16210 j = Math.floor(Math.random() * (i + 1)); 16211 temp = a[i]; 16212 a[i] = a[j]; 16213 a[j] = temp; 16214 } 16215 this.insertToGallery(a); 16216 return a; 16217 }; 16218 16219 /** 16220 * Sort the array using settings.comparator as comparator 16221 * 16222 * @param a the array to sort (it is sorted) 16223 * @return the sorted array 16224 */ 16225 JustifiedGallery.prototype.sortArray = function (a) { 16226 a.sort(this.settings.sort); 16227 this.insertToGallery(a); 16228 return a; 16229 }; 16230 16231 /** 16232 * Reset the filters removing the 'jg-filtered' class from all the entries 16233 * 16234 * @param a the array to reset 16235 */ 16236 JustifiedGallery.prototype.resetFilters = function (a) { 16237 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 16238 }; 16239 16240 /** 16241 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 16242 * 16243 * @param a the array to filter 16244 * @return the filtered array 16245 */ 16246 JustifiedGallery.prototype.filterArray = function (a) { 16247 var settings = this.settings; 16248 if ($.type(settings.filter) === 'string') { 16249 // Filter only keeping the entries passed in the string 16250 return a.filter(function (el) { 16251 var $el = $(el); 16252 if ($el.is(settings.filter)) { 16253 $el.removeClass('jg-filtered'); 16254 return true; 16255 } else { 16256 $el.addClass('jg-filtered').removeClass('jg-visible'); 16257 return false; 16258 } 16259 }); 16260 } else if ($.isFunction(settings.filter)) { 16261 // Filter using the passed function 16262 var filteredArr = a.filter(settings.filter); 16263 for (var i = 0; i < a.length; i++) { 16264 if (filteredArr.indexOf(a[i]) == -1) { 16265 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 16266 } else { 16267 $(a[i]).removeClass('jg-filtered'); 16268 } 16269 } 16270 return filteredArr; 16271 } 16272 }; 16273 16274 /** 16275 * Destroy the Justified Gallery instance. 16276 * 16277 * It clears all the css properties added in the style attributes. We doesn't backup the original
16278 * values for those css attributes, because it costs (performance) and because in general one 16279 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 16280 * classes). Creating a backup is also difficult because JG could be called multiple times and 16281 * with different style attributes. 16282 */ 16283 JustifiedGallery.prototype.destroy = function () { 16284 clearInterval(this.checkWidthIntervalId); 16285 16286 $.each(this.entries, $.proxy(function(_, entry) { 16287 var $entry = $(entry); 16288 16289 // Reset entry style 16290 $entry.css('width', ''); 16291 $entry.css('height', ''); 16292 $entry.css('top', ''); 16293 $entry.css('left', ''); 16294 $entry.data('jg.loaded', undefined); 16295 $entry.removeClass('jg-entry'); 16296 16297 // Reset image style 16298 var $img = this.imgFromEntry($entry); 16299 $img.css('width', ''); 16300 $img.css('height', ''); 16301 $img.css('margin-left', ''); 16302 $img.css('margin-top', ''); 16303 $img.attr('src', $img.data('jg.originalSrc')); 16304 $img.data('jg.originalSrc', undefined); 16305 16306 // Remove caption 16307 this.removeCaptionEventsHandlers($entry); 16308 var $caption = this.captionFromEntry($entry); 16309 if ($entry.data('jg.createdCaption')) { 16310 // remove also the caption element (if created by jg) 16311 $entry.data('jg.createdCaption', undefined); 16312 if ($caption !== null) $caption.remove(); 16313 } else { 16314 if ($caption !== null) $caption.fadeTo(0, 1); 16315 } 16316 16317 }, this)); 16318 16319 this.$gallery.css('height', ''); 16320 this.$gallery.removeClass('justified-gallery'); 16321 this.$gallery.data('jg.controller', undefined); 16322 }; 16323 16324 /** 16325 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 16326 * 16327 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 16328 */ 16329 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 16330 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 16331 var $entry = $(this.entries[i]); 16332 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 16333 var availableWidth = this.galleryWidth - 2 * this.border - ( 16334 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 16335 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 16336 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 16337 this.flushRow(false); 16338 if(++this.yield.flushed >= this.yield.every) { 16339 this.startImgAnalyzer(isForResize); 16340 return; 16341 } 16342 } 16343 16344 this.buildingRow.entriesBuff.push($entry); 16345 this.buildingRow.aspectRatio += imgAspectRatio; 16346 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 16347 this.lastAnalyzedIndex = i; 16348 16349 } else if ($entry.data('jg.loaded') !== 'error') { 16350 return; 16351 } 16352 } 16353 16354 // Last row flush (the row is not full) 16355 if (this.buildingRow.entriesBuff.length > 0) this.flushRow(true); 16356 16357 if (this.isSpinnerActive()) { 16358 this.stopLoadingSpinnerAnimation(); 16359 } 16360 16361 /* Stop, if there is, the timeout to start the analyzeImages. 16362 This is because an image can be set loaded, and the timeout can be set, 16363 but this image can be analyzed yet. 16364 */ 16365 this.stopImgAnalyzerStarter(); 16366 16367 //On complete callback 16368 this.$gallery.trigger(isForResize ? 'jg.resize' : 'jg.complete'); 16369 this.$gallery.height(this.galleryHeightToSet); 16370 }; 16371 16372 /** 16373 * Stops any ImgAnalyzer starter (that has an assigned timeout) 16374 */ 16375 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 16376 this.yield.flushed = 0; 16377 if (this.imgAnalyzerTimeout !== null) clearTimeout(this.imgAnalyzerTimeout); 16378 }; 16379 16380 /** 16381 * Starts the image analyzer. It is not immediately called to let the browser to update the view 16382 * 16383 * @param isForResize specifies if the image analyzer must be called for resizing or not 16384 */ 16385 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 16386 var that = this; 16387 this.stopImgAnalyzerStarter(); 16388 this.imgAnalyzerTimeout = setTimeout(function () { 16389 that.analyzeImages(isForResize); 16390 }, 0.001); // we can't start it immediately due to a IE different behaviour 16391 }; 16392 16393 /** 16394 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 16395 * because some browsers, with a 404 set complete = true. 16396 * 16397 * @param imageSrc the image src to load 16398 * @param onLoad callback that is called when the image has been loaded
vendor: 13,320 bytes, lines 16399-16749
16399 * @param onError callback that is called in case of an error 16400 */ 16401 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 16402 if (!onLoad && !onError) return; 16403 16404 var memImage = new Image(); 16405 var $memImage = $(memImage); 16406 if (onLoad) { 16407 $memImage.one('load', function () { 16408 $memImage.off('load error'); 16409 onLoad(memImage); 16410 }); 16411 } 16412 if (onError) { 16413 $memImage.one('error', function() { 16414 $memImage.off('load error'); 16415 onError(memImage); 16416 }); 16417 } 16418 memImage.src = imageSrc; 16419 }; 16420 16421 /** 16422 * Init of Justified Gallery controlled 16423 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 16424 */ 16425 JustifiedGallery.prototype.init = function () { 16426 var imagesToLoad = false, skippedImages = false, that = this; 16427 $.each(this.entries, function (index, entry) { 16428 var $entry = $(entry); 16429 var $image = that.imgFromEntry($entry); 16430 16431 $entry.addClass('jg-entry'); 16432 16433 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 16434 16435 // Link Rel global overwrite 16436 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 16437 16438 // Link Target global overwrite 16439 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 16440 16441 if ($image !== null) { 16442 16443 // Image src 16444 var imageSrc = that.extractImgSrcFromImage($image); 16445 $image.attr('src', imageSrc); 16446 16447 /* If we have the height and the width, we don't wait that the image is loaded, but we start directly 16448 * with the justification */ 16449 if (that.settings.waitThumbnailsLoad === false) { 16450 var width = parseFloat($image.attr('width')); 16451 var height = parseFloat($image.attr('height')); 16452 if (!isNaN(width) && !isNaN(height)) { 16453 $entry.data('jg.width', width); 16454 $entry.data('jg.height', height); 16455 $entry.data('jg.loaded', 'skipped'); 16456 skippedImages = true; 16457 that.startImgAnalyzer(false); 16458 return true; // continue 16459 } 16460 } 16461 16462 $entry.data('jg.loaded', false); 16463 imagesToLoad = true; 16464 16465 // Spinner start 16466 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 16467 16468 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 16469 $entry.data('jg.width', loadImg.width); 16470 $entry.data('jg.height', loadImg.height); 16471 $entry.data('jg.loaded', true); 16472 that.startImgAnalyzer(false); 16473 }, function () { // image load error 16474 $entry.data('jg.loaded', 'error'); 16475 that.startImgAnalyzer(false); 16476 }); 16477 16478 } else { 16479 $entry.data('jg.loaded', true); 16480 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 16481 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 16482 } 16483 16484 } 16485 16486 }); 16487 16488 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 16489 this.checkWidth(); 16490 }; 16491 16492 /** 16493 * Checks that it is a valid number. If a string is passed it is converted to a number 16494 * 16495 * @param settingContainer the object that contains the setting (to allow the conversion) 16496 * @param settingName the setting name 16497 */ 16498 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 16499 if ($.type(settingContainer[settingName]) === 'string') { 16500 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 16501 } 16502 16503 if ($.type(settingContainer[settingName]) === 'number') { 16504 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 16505 } else { 16506 throw settingName + ' must be a number'; 16507 } 16508 }; 16509 16510 /** 16511 * Checks the sizeRangeSuffixes and, if necessary, converts 16512 * its keys from string (e.g. old settings with 'lt100') to int. 16513 */ 16514 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 16515 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 16516 throw 'sizeRangeSuffixes must be defined and must be an object'; 16517 } 16518 16519 var suffixRanges = []; 16520 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16521 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 16522 } 16523 16524 var newSizeRngSuffixes = {0: ''}; 16525 for (var i = 0; i < suffixRanges.length; i++) { 16526 if ($.type(suffixRanges[i]) === 'string') { 16527 try { 16528 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 16529 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16530 } catch (e) { 16531 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 16532 } 16533 } else { 16534 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16535 } 16536 } 16537 16538 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 16539 }; 16540 16541 /** 16542 * check and convert the maxRowHeight setting 16543 */ 16544 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 16545 var newMaxRowHeight = { }; 16546 16547 if ($.type(this.settings.maxRowHeight) === 'string') { 16548 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 16549 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 16550 newMaxRowHeight.isPercentage = false; 16551 } else { 16552 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight); 16553 newMaxRowHeight.isPercentage = true; 16554 } 16555 } else if ($.type(this.settings.maxRowHeight) === 'number') { 16556 newMaxRowHeight.value = this.settings.maxRowHeight; 16557 newMaxRowHeight.isPercentage = false; 16558 } else if (this.settings.maxRowHeight === false || 16559 this.settings.maxRowHeight === null || 16560 typeof this.settings.maxRowHeight == 'undefined') { 16561 return null; 16562 } else { 16563 throw 'maxRowHeight must be a number or a percentage'; 16564 } 16565 16566 // check if the converted value is not a number 16567 if (isNaN(newMaxRowHeight.value)) throw 'invalid number for maxRowHeight'; 16568 16569 // check values 16570 if (newMaxRowHeight.isPercentage) { 16571 if (newMaxRowHeight.value < 100) newMaxRowHeight.value = 100; 16572 } 16573 16574 return newMaxRowHeight; 16575 }; 16576 16577 /** 16578 * Checks the settings 16579 */ 16580 JustifiedGallery.prototype.checkSettings = function () { 16581 this.checkSizeRangesSuffixes(); 16582 16583 this.checkOrConvertNumber(this.settings, 'rowHeight'); 16584 this.checkOrConvertNumber(this.settings, 'margins'); 16585 this.checkOrConvertNumber(this.settings, 'border'); 16586 16587 var lastRowModes = [ 16588 'justify', 16589 'nojustify', 16590 'left', 16591 'center', 16592 'right', 16593 'hide' 16594 ]; 16595 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 16596 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 16597 } 16598 16599 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 16600 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 16601 throw 'justifyThreshold must be in the interval [0,1]'; 16602 } 16603 if ($.type(this.settings.cssAnimation) !== 'boolean') { 16604 throw 'cssAnimation must be a boolean'; 16605 } 16606 16607 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 16608 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 16609 16610 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 16611 if (this.settings.captionSettings.visibleOpacity < 0 || 16612 this.settings.captionSettings.visibleOpacity > 1) { 16613 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 16614 } 16615 16616 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 16617 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 16618 this.settings.captionSettings.nonVisibleOpacity > 1) { 16619 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 16620 } 16621 16622 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 16623 this.checkOrConvertNumber(this.settings, 'refreshTime'); 16624 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 16625 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 16626 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 16627 16628 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 16629 throw 'sort must be false or a comparison function'; 16630 } 16631 16632 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 16633 $.type(this.settings.filter) !== 'string') { 16634 throw 'filter must be false, a string or a filter function'; 16635 } 16636 }; 16637 16638 /** 16639 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 16640 * @returns {Array} sorted suffix ranges 16641 */ 16642 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 16643 var suffixRanges = []; 16644 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16645 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 16646 } 16647 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 16648 return suffixRanges; 16649 }; 16650 16651 /** 16652 * Update the existing settings only changing some of them 16653 * 16654 * @param newSettings the new settings (or a subgroup of them) 16655 */ 16656 JustifiedGallery.prototype.updateSettings = function (newSettings) { 16657 // In this case Justified Gallery has been called again changing only some options 16658 this.settings = $.extend({}, this.settings, newSettings); 16659 this.checkSettings(); 16660 16661 // As reported in the settings: negative value = same as margins, 0 = disabled 16662 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 16663 16664 this.maxRowHeight = this.retrieveMaxRowHeight(); 16665 this.suffixRanges = this.retrieveSuffixRanges(); 16666 }; 16667 16668 /** 16669 * Justified Gallery plugin for jQuery 16670 * 16671 * Events 16672 * - jg.complete : called when all the gallery has been created 16673 * - jg.resize : called when the gallery has been resized 16674 * - jg.rowflush : when a new row appears 16675 * 16676 * @param arg the action (or the settings) passed when the plugin is called 16677 * @returns {*} the object itself 16678 */ 16679 $.fn.justifiedGallery = function (arg) { 16680 return this.each(function (index, gallery) { 16681 16682 var $gallery = $(gallery); 16683 $gallery.addClass('justified-gallery'); 16684 16685 var controller = $gallery.data('jg.controller'); 16686 if (typeof controller === 'undefined') { 16687 // Create controller and assign it to the object data 16688 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 16689 if (arg === 'destroy') return; // Just a call to an unexisting object 16690 throw 'The argument must be an object'; 16691 } 16692 controller = new JustifiedGallery($gallery, $.extend({}, $.fn.justifiedGallery.defaults, arg)); 16693 $gallery.data('jg.controller', controller); 16694 } else if (arg === 'norewind') { 16695 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 16696 // ... left to be more readable 16697 } else if (arg === 'destroy') { 16698 controller.destroy(); 16699 return; 16700 } else { 16701 // In this case Justified Gallery has been called again changing only some options 16702 controller.updateSettings(arg); 16703 controller.rewind(); 16704 } 16705 16706 // Update the entries list 16707 if (!controller.updateEntries(arg === 'norewind')) return; 16708 16709 // Init justified gallery 16710 controller.init(); 16711 16712 }); 16713 }; 16714 16715 // Default options 16716 $.fn.justifiedGallery.defaults = { 16717 sizeRangeSuffixes: { }, /* e.g. Flickr configuration 16718 { 16719 100: '_t', // used when longest is less than 100px 16720 240: '_m', // used when longest is between 101px and 240px 16721 320: '_n', // ... 16722 500: '', 16723 640: '_z', 16724 1024: '_b' // used as else case because it is the last 16725 } 16726 */ 16727 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 16728 path relative to a specific thumbnail size. The function should accept respectively three arguments: 16729 current path, width and height */ 16730 rowHeight: 120, 16731 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 16732 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 16733 // can't exceed 3 * rowHeight) 16734 margins: 1, 16735 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 16736 16737 lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 16738 16739 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 16740 * (i.e. lastRow setting is not considered) */ 16741 waitThumbnailsLoad: true, 16742 captions: true, 16743 cssAnimation: true, 16744 imagesAnimationDuration: 500, // ignored with css animations 16745 captionSettings: { // ignored with css animations 16746 animationDuration: 500, 16747 visibleOpacity: 0.7, 16748 nonVisibleOpacity: 0.0 16749 },
vendor: 5,760 bytes, lines 16750-16893
16750 rel: null, // rewrite the rel of each analyzed links 16751 target: null, // rewrite the target of all links 16752 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 16753 refreshTime: 200, // time interval (in ms) to check if the page changes its width 16754 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 16755 randomize: false, 16756 sort: false, /* 16757 - false: to do not sort 16758 - function: to sort them using the function as comparator (see Array.prototype.sort()) 16759 */ 16760 filter: false, /* 16761 - false, null or undefined: for a disabled filter 16762 - a string: an entry is kept if entry.is(filter string) returns true 16763 see jQuery's .is() function for further information 16764 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 16765 It follows the specifications of the Array.prototype.filter() function of JavaScript. 16766 */ 16767 selector: 'a, div:not(.spinner)' // The selector that is used to know what are the entries of the gallery 16768 }; 16769 16770}(jQuery)); 16771 16772/*! 16773* Customized version of iScroll.js 0.0.1 16774* It fixes bugs affecting its integration with fullpage.js 16775*/ 16776/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 16777(function (window, document, Math) { 16778var rAF = window.requestAnimationFrame || 16779 window.webkitRequestAnimationFrame || 16780 window.mozRequestAnimationFrame || 16781 window.oRequestAnimationFrame || 16782 window.msRequestAnimationFrame || 16783 function (callback) { window.setTimeout(callback, 1000 / 60); }; 16784 16785var utils = (function () { 16786 var me = {}; 16787 16788 var _elementStyle = document.createElement('div').style; 16789 var _vendor = (function () { 16790 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 16791 transform, 16792 i = 0, 16793 l = vendors.length; 16794 16795 for ( ; i < l; i++ ) { 16796 transform = vendors[i] + 'ransform'; 16797 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 16798 } 16799 16800 return false; 16801 })(); 16802 16803 function _prefixStyle (style) { 16804 if ( _vendor === false ) return false; 16805 if ( _vendor === '' ) return style; 16806 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 16807 } 16808 16809 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 16810 16811 me.extend = function (target, obj) { 16812 for ( var i in obj ) { 16813 target[i] = obj[i]; 16814 } 16815 }; 16816 16817 me.addEvent = function (el, type, fn, capture) { 16818 el.addEventListener(type, fn, !!capture); 16819 }; 16820 16821 me.removeEvent = function (el, type, fn, capture) { 16822 el.removeEventListener(type, fn, !!capture); 16823 }; 16824 16825 me.prefixPointerEvent = function (pointerEvent) { 16826 return window.MSPointerEvent ? 16827 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 16828 pointerEvent; 16829 }; 16830 16831 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 16832 var distance = current - start, 16833 speed = Math.abs(distance) / time, 16834 destination, 16835 duration; 16836 16837 deceleration = deceleration === undefined ? 0.0006 : deceleration; 16838 16839 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 16840 duration = speed / deceleration; 16841 16842 if ( destination < lowerMargin ) { 16843 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 16844 distance = Math.abs(destination - current); 16845 duration = distance / speed; 16846 } else if ( destination > 0 ) { 16847 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 16848 distance = Math.abs(current) + destination; 16849 duration = distance / speed; 16850 } 16851 16852 return { 16853 destination: Math.round(destination), 16854 duration: duration 16855 }; 16856 }; 16857 16858 var _transform = _prefixStyle('transform'); 16859 16860 me.extend(me, { 16861 hasTransform: _transform !== false, 16862 hasPerspective: _prefixStyle('perspective') in _elementStyle, 16863 hasTouch: 'ontouchstart' in window, 16864 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 16865 hasTransition: _prefixStyle('transition') in _elementStyle 16866 }); 16867 16868 /* 16869 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 16870 - galaxy S2 is ok 16871 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 16872 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16873 - galaxy S3 is badAndroid (stock brower, webview) 16874 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16875 - galaxy S4 is badAndroid (stock brower, webview) 16876 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16877 - galaxy S5 is OK 16878 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16879 - galaxy S6 is OK 16880 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16881 */ 16882 me.isBadAndroid = (function() { 16883 var appVersion = window.navigator.appVersion; 16884 // Android browser is not a chrome browser. 16885 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 16886 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 16887 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 16888 return parseFloat(safariVersion[1]) < 535.19; 16889 } else { 16890 return true; 16891 } 16892 } else { 16893 return false;
vendor: 5,536 bytes, lines 16894-17086
16894 } 16895 })(); 16896 16897 me.extend(me.style = {}, { 16898 transform: _transform, 16899 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 16900 transitionDuration: _prefixStyle('transitionDuration'), 16901 transitionDelay: _prefixStyle('transitionDelay'), 16902 transformOrigin: _prefixStyle('transformOrigin') 16903 }); 16904 16905 me.hasClass = function (e, c) { 16906 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 16907 return re.test(e.className); 16908 }; 16909 16910 me.addClass = function (e, c) { 16911 if ( me.hasClass(e, c) ) { 16912 return; 16913 } 16914 16915 var newclass = e.className.split(' '); 16916 newclass.push(c); 16917 e.className = newclass.join(' '); 16918 }; 16919 16920 me.removeClass = function (e, c) { 16921 if ( !me.hasClass(e, c) ) { 16922 return; 16923 } 16924 16925 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 16926 e.className = e.className.replace(re, ' '); 16927 }; 16928 16929 me.offset = function (el) { 16930 var left = -el.offsetLeft, 16931 top = -el.offsetTop; 16932 16933 // jshint -W084 16934 while (el = el.offsetParent) { 16935 left -= el.offsetLeft; 16936 top -= el.offsetTop; 16937 } 16938 // jshint +W084 16939 16940 return { 16941 left: left, 16942 top: top 16943 }; 16944 }; 16945 16946 me.preventDefaultException = function (el, exceptions) { 16947 for ( var i in exceptions ) { 16948 if ( exceptions[i].test(el[i]) ) { 16949 return true; 16950 } 16951 } 16952 16953 return false; 16954 }; 16955 16956 me.extend(me.eventType = {}, { 16957 touchstart: 1, 16958 touchmove: 1, 16959 touchend: 1, 16960 16961 mousedown: 2, 16962 mousemove: 2, 16963 mouseup: 2, 16964 16965 pointerdown: 3, 16966 pointermove: 3, 16967 pointerup: 3, 16968 16969 MSPointerDown: 3, 16970 MSPointerMove: 3, 16971 MSPointerUp: 3 16972 }); 16973 16974 me.extend(me.ease = {}, { 16975 quadratic: { 16976 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 16977 fn: function (k) { 16978 return k * ( 2 - k ); 16979 } 16980 }, 16981 circular: { 16982 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) 16983 fn: function (k) { 16984 return Math.sqrt( 1 - ( --k * k ) ); 16985 } 16986 }, 16987 back: { 16988 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 16989 fn: function (k) { 16990 var b = 4; 16991 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 16992 } 16993 }, 16994 bounce: { 16995 style: '', 16996 fn: function (k) { 16997 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 16998 return 7.5625 * k * k; 16999 } else if ( k < ( 2 / 2.75 ) ) { 17000 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 17001 } else if ( k < ( 2.5 / 2.75 ) ) { 17002 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 17003 } else { 17004 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 17005 } 17006 } 17007 }, 17008 elastic: { 17009 style: '', 17010 fn: function (k) { 17011 var f = 0.22, 17012 e = 0.4; 17013 17014 if ( k === 0 ) { return 0; } 17015 if ( k == 1 ) { return 1; } 17016 17017 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 17018 } 17019 } 17020 }); 17021 17022 me.tap = function (e, eventName) { 17023 var ev = document.createEvent('Event'); 17024 ev.initEvent(eventName, true, true); 17025 ev.pageX = e.pageX; 17026 ev.pageY = e.pageY; 17027 e.target.dispatchEvent(ev); 17028 }; 17029 17030 me.click = function (e) { 17031 var target = e.target, 17032 ev; 17033 17034 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 17035 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 17036 // initMouseEvent is deprecated. 17037 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 17038 ev.initEvent('click', true, true); 17039 ev.view = e.view || window; 17040 ev.detail = 1; 17041 ev.screenX = target.screenX || 0; 17042 ev.screenY = target.screenY || 0; 17043 ev.clientX = target.clientX || 0; 17044 ev.clientY = target.clientY || 0; 17045 ev.ctrlKey = !!e.ctrlKey; 17046 ev.altKey = !!e.altKey; 17047 ev.shiftKey = !!e.shiftKey; 17048 ev.metaKey = !!e.metaKey; 17049 ev.button = 0; 17050 ev.relatedTarget = null; 17051 ev._constructed = true; 17052 target.dispatchEvent(ev); 17053 } 17054 }; 17055 17056 return me; 17057})(); 17058function IScroll (el, options) { 17059 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 17060 this.scroller = this.wrapper.children[0]; 17061 this.scrollerStyle = this.scroller.style; // cache style for better performance 17062 17063 this.options = { 17064 17065 resizeScrollbars: true, 17066 17067 mouseWheelSpeed: 20, 17068 17069 snapThreshold: 0.334, 17070 17071// INSERT POINT: OPTIONS 17072 disablePointer : !utils.hasPointer, 17073 disableTouch : utils.hasPointer || !utils.hasTouch, 17074 disableMouse : utils.hasPointer || utils.hasTouch, 17075 startX: 0, 17076 startY: 0, 17077 scrollY: true, 17078 directionLockThreshold: 5, 17079 momentum: true, 17080 17081 bounce: true, 17082 bounceTime: 600, 17083 bounceEasing: '', 17084 17085 preventDefault: true, 17086 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|
vendor: 4,420 bytes, lines 17086-17230
17086SELECT|LABEL)$/ }, 17087 17088 HWCompositing: true, 17089 useTransition: true, 17090 useTransform: true, 17091 bindToWrapper: typeof window.onmousedown === "undefined" 17092 }; 17093 17094 for ( var i in options ) { 17095 this.options[i] = options[i]; 17096 } 17097 17098 // Normalize options 17099 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 17100 17101 this.options.useTransition = utils.hasTransition && this.options.useTransition; 17102 this.options.useTransform = utils.hasTransform && this.options.useTransform; 17103 17104 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 17105 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 17106 17107 // If you want eventPassthrough I have to lock one of the axes 17108 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 17109 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 17110 17111 // With eventPassthrough we also need lockDirection mechanism 17112 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 17113 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 17114 17115 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 17116 17117 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 17118 17119 if ( this.options.tap === true ) { 17120 this.options.tap = 'tap'; 17121 } 17122 17123 // https://github.com/cubiq/iscroll/issues/1029 17124 if (!this.options.useTransition && !this.options.useTransform) { 17125 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 17126 this.scrollerStyle.position = "relative"; 17127 } 17128 } 17129 17130 if ( this.options.shrinkScrollbars == 'scale' ) { 17131 this.options.useTransition = false; 17132 } 17133 17134 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 17135 17136// INSERT POINT: NORMALIZATION 17137 17138 // Some defaults 17139 this.x = 0; 17140 this.y = 0; 17141 this.directionX = 0; 17142 this.directionY = 0; 17143 this._events = {}; 17144 17145// INSERT POINT: DEFAULTS 17146 17147 this._init(); 17148 this.refresh(); 17149 17150 this.scrollTo(this.options.startX, this.options.startY); 17151 this.enable(); 17152} 17153 17154IScroll.prototype = { 17155 version: '5.2.0', 17156 17157 _init: function () { 17158 this._initEvents(); 17159 17160 if ( this.options.scrollbars || this.options.indicators ) { 17161 this._initIndicators(); 17162 } 17163 17164 if ( this.options.mouseWheel ) { 17165 this._initWheel(); 17166 } 17167 17168 if ( this.options.snap ) { 17169 this._initSnap(); 17170 } 17171 17172 if ( this.options.keyBindings ) { 17173 this._initKeys(); 17174 } 17175 17176// INSERT POINT: _init 17177 17178 }, 17179 17180 destroy: function () { 17181 this._initEvents(true); 17182 clearTimeout(this.resizeTimeout); 17183 this.resizeTimeout = null; 17184 this._execEvent('destroy'); 17185 }, 17186 17187 _transitionEnd: function (e) { 17188 if ( e.target != this.scroller || !this.isInTransition ) { 17189 return; 17190 } 17191 17192 this._transitionTime(); 17193 if ( !this.resetPosition(this.options.bounceTime) ) { 17194 this.isInTransition = false; 17195 this._execEvent('scrollEnd'); 17196 } 17197 }, 17198 17199 _start: function (e) { 17200 // React to left mouse button only 17201 if ( utils.eventType[e.type] != 1 ) { 17202 // for button property 17203 // http://unixpapa.com/js/mouse.html 17204 var button; 17205 if (!e.which) { 17206 /* IE case */ 17207 button = (e.button < 2) ? 0 : 17208 ((e.button == 4) ? 1 : 2); 17209 } else { 17210 /* All others */ 17211 button = e.button; 17212 } 17213 if ( button !== 0 ) { 17214 return; 17215 } 17216 } 17217 17218 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 17219 return; 17220 } 17221 17222 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17223 e.preventDefault(); 17224 } 17225 17226 var point = e.touches ? e.touches[0] : e, 17227 pos; 17228 17229 this.initiated = utils.eventType[e.type]; 17230 this.moved = false;
vendor: 5,928 bytes, lines 17231-17409
17231 this.distX = 0; 17232 this.distY = 0; 17233 this.directionX = 0; 17234 this.directionY = 0; 17235 this.directionLocked = 0; 17236 17237 this.startTime = utils.getTime(); 17238 17239 if ( this.options.useTransition && this.isInTransition ) { 17240 this._transitionTime(); 17241 this.isInTransition = false; 17242 pos = this.getComputedPosition(); 17243 this._translate(Math.round(pos.x), Math.round(pos.y)); 17244 this._execEvent('scrollEnd'); 17245 } else if ( !this.options.useTransition && this.isAnimating ) { 17246 this.isAnimating = false; 17247 this._execEvent('scrollEnd'); 17248 } 17249 17250 this.startX = this.x; 17251 this.startY = this.y; 17252 this.absStartX = this.x; 17253 this.absStartY = this.y; 17254 this.pointX = point.pageX; 17255 this.pointY = point.pageY; 17256 17257 this._execEvent('beforeScrollStart'); 17258 }, 17259 17260 _move: function (e) { 17261 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17262 return; 17263 } 17264 17265 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 17266 e.preventDefault(); 17267 } 17268 17269 var point = e.touches ? e.touches[0] : e, 17270 deltaX = point.pageX - this.pointX, 17271 deltaY = point.pageY - this.pointY, 17272 timestamp = utils.getTime(), 17273 newX, newY, 17274 absDistX, absDistY; 17275 17276 this.pointX = point.pageX; 17277 this.pointY = point.pageY; 17278 17279 this.distX += deltaX; 17280 this.distY += deltaY; 17281 absDistX = Math.abs(this.distX); 17282 absDistY = Math.abs(this.distY); 17283 17284 // We need to move at least 10 pixels for the scrolling to initiate 17285 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 17286 return; 17287 } 17288 17289 // If you are scrolling in one direction lock the other 17290 if ( !this.directionLocked && !this.options.freeScroll ) { 17291 if ( absDistX > absDistY + this.options.directionLockThreshold ) { 17292 this.directionLocked = 'h'; // lock horizontally 17293 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 17294 this.directionLocked = 'v'; // lock vertically 17295 } else { 17296 this.directionLocked = 'n'; // no lock 17297 } 17298 } 17299 17300 if ( this.directionLocked == 'h' ) { 17301 if ( this.options.eventPassthrough == 'vertical' ) { 17302 e.preventDefault(); 17303 } else if ( this.options.eventPassthrough == 'horizontal' ) { 17304 this.initiated = false; 17305 return; 17306 } 17307 17308 deltaY = 0; 17309 } else if ( this.directionLocked == 'v' ) { 17310 if ( this.options.eventPassthrough == 'horizontal' ) { 17311 e.preventDefault(); 17312 } else if ( this.options.eventPassthrough == 'vertical' ) { 17313 this.initiated = false; 17314 return; 17315 } 17316 17317 deltaX = 0; 17318 } 17319 17320 deltaX = this.hasHorizontalScroll ? deltaX : 0; 17321 deltaY = this.hasVerticalScroll ? deltaY : 0; 17322 17323 newX = this.x + deltaX; 17324 newY = this.y + deltaY; 17325 17326 // Slow down if outside of the boundaries 17327 if ( newX > 0 || newX < this.maxScrollX ) { 17328 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 17329 } 17330 if ( newY > 0 || newY < this.maxScrollY ) { 17331 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 17332 } 17333 17334 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 17335 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 17336 17337 if ( !this.moved ) { 17338 this._execEvent('scrollStart'); 17339 } 17340 17341 this.moved = true; 17342 17343 this._translate(newX, newY); 17344 17345/* REPLACE START: _move */ 17346 17347 if ( timestamp - this.startTime > 300 ) { 17348 this.startTime = timestamp; 17349 this.startX = this.x; 17350 this.startY = this.y; 17351 } 17352 17353/* REPLACE END: _move */ 17354 17355 }, 17356 17357 _end: function (e) { 17358 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17359 return; 17360 } 17361 17362 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17363 e.preventDefault(); 17364 } 17365 17366 var point = e.changedTouches ? e.changedTouches[0] : e, 17367 momentumX, 17368 momentumY, 17369 duration = utils.getTime() - this.startTime, 17370 newX = Math.round(this.x), 17371 newY = Math.round(this.y), 17372 distanceX = Math.abs(newX - this.startX), 17373 distanceY = Math.abs(newY - this.startY), 17374 time = 0, 17375 easing = ''; 17376 17377 this.isInTransition = 0; 17378 this.initiated = 0; 17379 this.endTime = utils.getTime(); 17380 17381 // reset if we are outside of the boundaries 17382 if ( this.resetPosition(this.options.bounceTime) ) { 17383 return; 17384 } 17385 17386 this.scrollTo(newX, newY); // ensures that the last position is rounded 17387 17388 // we scrolled less than 10 pixels 17389 if ( !this.moved ) { 17390 if ( this.options.tap ) { 17391 utils.tap(e, this.options.tap); 17392 } 17393 17394 if ( this.options.click ) { 17395 utils.click(e); 17396 } 17397 17398 this._execEvent('scrollCancel'); 17399 return; 17400 } 17401 17402 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 17403 this._execEvent('flick'); 17404 return; 17405 } 17406 17407 // start momentum animation if needed 17408 if ( this.options.momentum && duration < 300 ) { 17409 momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperW
vendor: 7,740 bytes, lines 17409-17682
17409idth : 0, this.options.deceleration) : { destination: newX, duration: 0 }; 17410 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 }; 17411 newX = momentumX.destination; 17412 newY = momentumY.destination; 17413 time = Math.max(momentumX.duration, momentumY.duration); 17414 this.isInTransition = 1; 17415 } 17416 17417 17418 if ( this.options.snap ) { 17419 var snap = this._nearestSnap(newX, newY); 17420 this.currentPage = snap; 17421 time = this.options.snapSpeed || Math.max( 17422 Math.max( 17423 Math.min(Math.abs(newX - snap.x), 1000), 17424 Math.min(Math.abs(newY - snap.y), 1000) 17425 ), 300); 17426 newX = snap.x; 17427 newY = snap.y; 17428 17429 this.directionX = 0; 17430 this.directionY = 0; 17431 easing = this.options.bounceEasing; 17432 } 17433 17434// INSERT POINT: _end 17435 17436 if ( newX != this.x || newY != this.y ) { 17437 // change easing function when scroller goes out of the boundaries 17438 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 17439 easing = utils.ease.quadratic; 17440 } 17441 17442 this.scrollTo(newX, newY, time, easing); 17443 return; 17444 } 17445 17446 this._execEvent('scrollEnd'); 17447 }, 17448 17449 _resize: function () { 17450 var that = this; 17451 17452 clearTimeout(this.resizeTimeout); 17453 17454 this.resizeTimeout = setTimeout(function () { 17455 that.refresh(); 17456 }, this.options.resizePolling); 17457 }, 17458 17459 resetPosition: function (time) { 17460 var x = this.x, 17461 y = this.y; 17462 17463 time = time || 0; 17464 17465 if ( !this.hasHorizontalScroll || this.x > 0 ) { 17466 x = 0; 17467 } else if ( this.x < this.maxScrollX ) { 17468 x = this.maxScrollX; 17469 } 17470 17471 if ( !this.hasVerticalScroll || this.y > 0 ) { 17472 y = 0; 17473 } else if ( this.y < this.maxScrollY ) { 17474 y = this.maxScrollY; 17475 } 17476 17477 if ( x == this.x && y == this.y ) { 17478 return false; 17479 } 17480 17481 this.scrollTo(x, y, time, this.options.bounceEasing); 17482 17483 return true; 17484 }, 17485 17486 disable: function () { 17487 this.enabled = false; 17488 }, 17489 17490 enable: function () { 17491 this.enabled = true; 17492 }, 17493 17494 refresh: function () { 17495 var rf = this.wrapper.offsetHeight; // Force reflow 17496 17497 this.wrapperWidth = this.wrapper.clientWidth; 17498 this.wrapperHeight = this.wrapper.clientHeight; 17499 17500/* REPLACE START: refresh */ 17501 17502 this.scrollerWidth = this.scroller.offsetWidth; 17503 this.scrollerHeight = this.scroller.offsetHeight; 17504 17505 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 17506 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 17507 17508/* REPLACE END: refresh */ 17509 17510 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 17511 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 17512 17513 if ( !this.hasHorizontalScroll ) { 17514 this.maxScrollX = 0; 17515 this.scrollerWidth = this.wrapperWidth; 17516 } 17517 17518 if ( !this.hasVerticalScroll ) { 17519 this.maxScrollY = 0; 17520 this.scrollerHeight = this.wrapperHeight; 17521 } 17522 17523 this.endTime = 0; 17524 this.directionX = 0; 17525 this.directionY = 0; 17526 17527 this.wrapperOffset = utils.offset(this.wrapper); 17528 17529 this._execEvent('refresh'); 17530 17531 this.resetPosition(); 17532 17533// INSERT POINT: _refresh 17534 17535 }, 17536 17537 on: function (type, fn) { 17538 if ( !this._events[type] ) { 17539 this._events[type] = []; 17540 } 17541 17542 this._events[type].push(fn); 17543 }, 17544 17545 off: function (type, fn) { 17546 if ( !this._events[type] ) { 17547 return; 17548 } 17549 17550 var index = this._events[type].indexOf(fn); 17551 17552 if ( index > -1 ) { 17553 this._events[type].splice(index, 1); 17554 } 17555 }, 17556 17557 _execEvent: function (type) { 17558 if ( !this._events[type] ) { 17559 return; 17560 } 17561 17562 var i = 0, 17563 l = this._events[type].length; 17564 17565 if ( !l ) { 17566 return; 17567 } 17568 17569 for ( ; i < l; i++ ) { 17570 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 17571 } 17572 }, 17573 17574 scrollBy: function (x, y, time, easing) { 17575 x = this.x + x; 17576 y = this.y + y; 17577 time = time || 0; 17578 17579 this.scrollTo(x, y, time, easing); 17580 }, 17581 17582 scrollTo: function (x, y, time, easing) { 17583 easing = easing || utils.ease.circular; 17584 17585 this.isInTransition = this.options.useTransition && time > 0; 17586 var transitionType = this.options.useTransition && easing.style; 17587 if ( !time || transitionType ) { 17588 if(transitionType) { 17589 this._transitionTimingFunction(easing.style); 17590 this._transitionTime(time); 17591 } 17592 this._translate(x, y); 17593 } else { 17594 this._animate(x, y, time, easing.fn); 17595 } 17596 }, 17597 17598 scrollToElement: function (el, time, offsetX, offsetY, easing) { 17599 el = el.nodeType ? el : this.scroller.querySelector(el); 17600 17601 if ( !el ) { 17602 return; 17603 } 17604 17605 var pos = utils.offset(el); 17606 17607 pos.left -= this.wrapperOffset.left; 17608 pos.top -= this.wrapperOffset.top; 17609 17610 // if offsetX/Y are true we center the element to the screen 17611 if ( offsetX === true ) { 17612 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 17613 } 17614 if ( offsetY === true ) { 17615 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 17616 } 17617 17618 pos.left -= offsetX || 0; 17619 pos.top -= offsetY || 0; 17620 17621 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 17622 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 17623 17624 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 17625 17626 this.scrollTo(pos.left, pos.top, time, easing); 17627 }, 17628 17629 _transitionTime: function (time) { 17630 if (!this.options.useTransition) { 17631 return; 17632 } 17633 time = time || 0; 17634 var durationProp = utils.style.transitionDuration; 17635 if(!durationProp) { 17636 return; 17637 } 17638 17639 this.scrollerStyle[durationProp] = time + 'ms'; 17640 17641 if ( !time && utils.isBadAndroid ) { 17642 this.scrollerStyle[durationProp] = '0.0001ms'; 17643 // remove 0.0001ms 17644 var self = this; 17645 rAF(function() { 17646 if(self.scrollerStyle[durationProp] === '0.0001ms') { 17647 self.scrollerStyle[durationProp] = '0s'; 17648 } 17649 }); 17650 } 17651 17652 17653 if ( this.indicators ) { 17654 for ( var i = this.indicators.length; i--; ) { 17655 this.indicators[i].transitionTime(time); 17656 } 17657 } 17658 17659 17660// INSERT POINT: _transitionTime 17661 17662 }, 17663 17664 _transitionTimingFunction: function (easing) { 17665 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 17666 17667 17668 if ( this.indicators ) { 17669 for ( var i = this.indicators.length; i--; ) { 17670 this.indicators[i].transitionTimingFunction(easing); 17671 } 17672 } 17673 17674 17675// INSERT POINT: _transitionTimingFunction 17676 17677 }, 17678 17679 _translate: function (x, y) { 17680 //Uncode addition 17681 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 17682 return false;
vendor: 9,946 bytes, lines 17683-17994
17683 17684 if ( this.options.useTransform ) { 17685 17686/* REPLACE START: _translate */ 17687 17688 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 17689 17690/* REPLACE END: _translate */ 17691 17692 } else { 17693 x = Math.round(x); 17694 y = Math.round(y); 17695 this.scrollerStyle.left = x + 'px'; 17696 this.scrollerStyle.top = y + 'px'; 17697 } 17698 17699 this.x = x; 17700 this.y = y; 17701 17702 17703 if ( this.indicators ) { 17704 for ( var i = this.indicators.length; i--; ) { 17705 this.indicators[i].updatePosition(); 17706 } 17707 } 17708 17709 //Uncode addition 17710 var uncodevent = new CustomEvent('fp-slide-scroll'); 17711 window.dispatchEvent(uncodevent); 17712 17713// INSERT POINT: _translate 17714 17715 }, 17716 17717 _initEvents: function (remove) { 17718 var eventType = remove ? utils.removeEvent : utils.addEvent, 17719 target = this.options.bindToWrapper ? this.wrapper : window; 17720 17721 eventType(window, 'orientationchange', this); 17722 eventType(window, 'resize', this); 17723 17724 if ( this.options.click ) { 17725 eventType(this.wrapper, 'click', this, true); 17726 } 17727 17728 if ( !this.options.disableMouse ) { 17729 eventType(this.wrapper, 'mousedown', this); 17730 eventType(target, 'mousemove', this); 17731 eventType(target, 'mousecancel', this); 17732 eventType(target, 'mouseup', this); 17733 } 17734 17735 if ( utils.hasPointer && !this.options.disablePointer ) { 17736 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 17737 eventType(target, utils.prefixPointerEvent('pointermove'), this); 17738 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 17739 eventType(target, utils.prefixPointerEvent('pointerup'), this); 17740 } 17741 17742 if ( utils.hasTouch && !this.options.disableTouch ) { 17743 eventType(this.wrapper, 'touchstart', this); 17744 eventType(target, 'touchmove', this); 17745 eventType(target, 'touchcancel', this); 17746 eventType(target, 'touchend', this); 17747 } 17748 17749 eventType(this.scroller, 'transitionend', this); 17750 eventType(this.scroller, 'webkitTransitionEnd', this); 17751 eventType(this.scroller, 'oTransitionEnd', this); 17752 eventType(this.scroller, 'MSTransitionEnd', this); 17753 }, 17754 17755 getComputedPosition: function () { 17756 var matrix = window.getComputedStyle(this.scroller, null), 17757 x, y; 17758 17759 if ( this.options.useTransform ) { 17760 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 17761 x = +(matrix[12] || matrix[4]); 17762 y = +(matrix[13] || matrix[5]); 17763 } else { 17764 x = +matrix.left.replace(/[^-\d.]/g, ''); 17765 y = +matrix.top.replace(/[^-\d.]/g, ''); 17766 } 17767 17768 return { x: x, y: y }; 17769 }, 17770 _initIndicators: function () { 17771 var interactive = this.options.interactiveScrollbars, 17772 customStyle = typeof this.options.scrollbars != 'string', 17773 indicators = [], 17774 indicator; 17775 17776 var that = this; 17777 17778 this.indicators = []; 17779 17780 if ( this.options.scrollbars ) { 17781 // Vertical scrollbar 17782 if ( this.options.scrollY ) { 17783 indicator = { 17784 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 17785 interactive: interactive, 17786 defaultScrollbars: true, 17787 customStyle: customStyle, 17788 resize: this.options.resizeScrollbars, 17789 shrink: this.options.shrinkScrollbars, 17790 fade: this.options.fadeScrollbars, 17791 listenX: false 17792 }; 17793 17794 this.wrapper.appendChild(indicator.el); 17795 indicators.push(indicator); 17796 } 17797 17798 // Horizontal scrollbar 17799 if ( this.options.scrollX ) { 17800 indicator = { 17801 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 17802 interactive: interactive, 17803 defaultScrollbars: true, 17804 customStyle: customStyle, 17805 resize: this.options.resizeScrollbars, 17806 shrink: this.options.shrinkScrollbars, 17807 fade: this.options.fadeScrollbars, 17808 listenY: false 17809 }; 17810 17811 this.wrapper.appendChild(indicator.el); 17812 indicators.push(indicator); 17813 } 17814 } 17815 17816 if ( this.options.indicators ) { 17817 // TODO: check concat compatibility 17818 indicators = indicators.concat(this.options.indicators); 17819 } 17820 17821 for ( var i = indicators.length; i--; ) { 17822 this.indicators.push( new Indicator(this, indicators[i]) ); 17823 } 17824 17825 // TODO: check if we can use array.map (wide compatibility and performance issues) 17826 function _indicatorsMap (fn) { 17827 if (that.indicators) { 17828 for ( var i = that.indicators.length; i--; ) { 17829 fn.call(that.indicators[i]); 17830 } 17831 } 17832 } 17833 17834 if ( this.options.fadeScrollbars ) { 17835 this.on('scrollEnd', function () { 17836 _indicatorsMap(function () { 17837 this.fade(); 17838 }); 17839 }); 17840 17841 this.on('scrollCancel', function () { 17842 _indicatorsMap(function () { 17843 this.fade(); 17844 }); 17845 }); 17846 17847 this.on('scrollStart', function () { 17848 _indicatorsMap(function () { 17849 this.fade(1); 17850 }); 17851 }); 17852 17853 this.on('beforeScrollStart', function () { 17854 _indicatorsMap(function () { 17855 this.fade(1, true); 17856 }); 17857 }); 17858 } 17859 17860 17861 this.on('refresh', function () { 17862 _indicatorsMap(function () { 17863 this.refresh(); 17864 }); 17865 }); 17866 17867 this.on('destroy', function () { 17868 _indicatorsMap(function () { 17869 this.destroy(); 17870 }); 17871 17872 delete this.indicators; 17873 }); 17874 }, 17875 17876 _initWheel: function () { 17877 utils.addEvent(this.wrapper, 'wheel', this); 17878 utils.addEvent(this.wrapper, 'mousewheel', this); 17879 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 17880 17881 this.on('destroy', function () { 17882 clearTimeout(this.wheelTimeout); 17883 this.wheelTimeout = null; 17884 utils.removeEvent(this.wrapper, 'wheel', this); 17885 utils.removeEvent(this.wrapper, 'mousewheel', this); 17886 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 17887 }); 17888 }, 17889 17890 _wheel: function (e) { 17891 if ( !this.enabled ) { 17892 return; 17893 } 17894 17895 var wheelDeltaX, wheelDeltaY, 17896 newX, newY, 17897 that = this; 17898 17899 if ( this.wheelTimeout === undefined ) { 17900 that._execEvent('scrollStart'); 17901 } 17902 17903 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 17904 clearTimeout(this.wheelTimeout); 17905 this.wheelTimeout = setTimeout(function () { 17906 if(!that.options.snap) { 17907 that._execEvent('scrollEnd'); 17908 } 17909 that.wheelTimeout = undefined; 17910 }, 400); 17911 17912 if ( 'deltaX' in e ) { 17913 if (e.deltaMode === 1) { 17914 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 17915 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 17916 } else { 17917 wheelDeltaX = -e.deltaX; 17918 wheelDeltaY = -e.deltaY; 17919 } 17920 } else if ( 'wheelDeltaX' in e ) { 17921 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 17922 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 17923 } else if ( 'wheelDelta' in e ) { 17924 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 17925 } else if ( 'detail' in e ) { 17926 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 17927 } else { 17928 return; 17929 } 17930 17931 wheelDeltaX *= this.options.invertWheelDirection; 17932 wheelDeltaY *= this.options.invertWheelDirection; 17933 17934 if ( !this.hasVerticalScroll ) { 17935 wheelDeltaX = wheelDeltaY; 17936 wheelDeltaY = 0; 17937 } 17938 17939 if ( this.options.snap ) { 17940 newX = this.currentPage.pageX; 17941 newY = this.currentPage.pageY; 17942 17943 if ( wheelDeltaX > 0 ) { 17944 newX--; 17945 } else if ( wheelDeltaX < 0 ) { 17946 newX++; 17947 } 17948 17949 if ( wheelDeltaY > 0 ) { 17950 newY--; 17951 } else if ( wheelDeltaY < 0 ) { 17952 newY++; 17953 } 17954 17955 this.goToPage(newX, newY); 17956 17957 return; 17958 } 17959 17960 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 17961 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 17962 17963 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 17964 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 17965 17966 if ( newX > 0 ) { 17967 newX = 0; 17968 } else if ( newX < this.maxScrollX ) { 17969 newX = this.maxScrollX; 17970 } 17971 17972 if ( newY > 0 ) { 17973 newY = 0; 17974 } else if ( newY < this.maxScrollY ) { 17975 newY = this.maxScrollY; 17976 } 17977 17978 this.scrollTo(newX, newY, 0); 17979 17980// INSERT POINT: _wheel 17981 }, 17982 17983 _initSnap: function () { 17984 this.currentPage = {}; 17985 17986 if ( typeof this.options.snap == 'string' ) { 17987 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 17988 } 17989 17990 this.on('refresh', function () { 17991 var i = 0, l, 17992 m = 0, n, 17993 cx, cy, 17994 x = 0, y,
vendor: 7,339 bytes, lines 17995-18248
17995 stepX = this.options.snapStepX || this.wrapperWidth, 17996 stepY = this.options.snapStepY || this.wrapperHeight, 17997 el; 17998 17999 this.pages = []; 18000 18001 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 18002 return; 18003 } 18004 18005 if ( this.options.snap === true ) { 18006 cx = Math.round( stepX / 2 ); 18007 cy = Math.round( stepY / 2 ); 18008 18009 while ( x > -this.scrollerWidth ) { 18010 this.pages[i] = []; 18011 l = 0; 18012 y = 0; 18013 18014 while ( y > -this.scrollerHeight ) { 18015 this.pages[i][l] = { 18016 x: Math.max(x, this.maxScrollX), 18017 y: Math.max(y, this.maxScrollY), 18018 width: stepX, 18019 height: stepY, 18020 cx: x - cx, 18021 cy: y - cy 18022 }; 18023 18024 y -= stepY; 18025 l++; 18026 } 18027 18028 x -= stepX; 18029 i++; 18030 } 18031 } else { 18032 el = this.options.snap; 18033 l = el.length; 18034 n = -1; 18035 18036 for ( ; i < l; i++ ) { 18037 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 18038 m = 0; 18039 n++; 18040 } 18041 18042 if ( !this.pages[m] ) { 18043 this.pages[m] = []; 18044 } 18045 18046 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 18047 y = Math.max(-el[i].offsetTop, this.maxScrollY); 18048 cx = x - Math.round(el[i].offsetWidth / 2); 18049 cy = y - Math.round(el[i].offsetHeight / 2); 18050 18051 this.pages[m][n] = { 18052 x: x, 18053 y: y, 18054 width: el[i].offsetWidth, 18055 height: el[i].offsetHeight, 18056 cx: cx, 18057 cy: cy 18058 }; 18059 18060 if ( x > this.maxScrollX ) { 18061 m++; 18062 } 18063 } 18064 } 18065 18066 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 18067 18068 // Update snap threshold if needed 18069 if ( this.options.snapThreshold % 1 === 0 ) { 18070 this.snapThresholdX = this.options.snapThreshold; 18071 this.snapThresholdY = this.options.snapThreshold; 18072 } else { 18073 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 18074 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 18075 } 18076 }); 18077 18078 this.on('flick', function () { 18079 var time = this.options.snapSpeed || Math.max( 18080 Math.max( 18081 Math.min(Math.abs(this.x - this.startX), 1000), 18082 Math.min(Math.abs(this.y - this.startY), 1000) 18083 ), 300); 18084 18085 this.goToPage( 18086 this.currentPage.pageX + this.directionX, 18087 this.currentPage.pageY + this.directionY, 18088 time 18089 ); 18090 }); 18091 }, 18092 18093 _nearestSnap: function (x, y) { 18094 if ( !this.pages.length ) { 18095 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 18096 } 18097 18098 var i = 0, 18099 l = this.pages.length, 18100 m = 0; 18101 18102 // Check if we exceeded the snap threshold 18103 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 18104 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 18105 return this.currentPage; 18106 } 18107 18108 if ( x > 0 ) { 18109 x = 0; 18110 } else if ( x < this.maxScrollX ) { 18111 x = this.maxScrollX; 18112 } 18113 18114 if ( y > 0 ) { 18115 y = 0; 18116 } else if ( y < this.maxScrollY ) { 18117 y = this.maxScrollY; 18118 } 18119 18120 for ( ; i < l; i++ ) { 18121 if ( x >= this.pages[i][0].cx ) { 18122 x = this.pages[i][0].x; 18123 break; 18124 } 18125 } 18126 18127 l = this.pages[i].length; 18128 18129 for ( ; m < l; m++ ) { 18130 if ( y >= this.pages[0][m].cy ) { 18131 y = this.pages[0][m].y; 18132 break; 18133 } 18134 } 18135 18136 if ( i == this.currentPage.pageX ) { 18137 i += this.directionX; 18138 18139 if ( i < 0 ) { 18140 i = 0; 18141 } else if ( i >= this.pages.length ) { 18142 i = this.pages.length - 1; 18143 } 18144 18145 x = this.pages[i][0].x; 18146 } 18147 18148 if ( m == this.currentPage.pageY ) { 18149 m += this.directionY; 18150 18151 if ( m < 0 ) { 18152 m = 0; 18153 } else if ( m >= this.pages[0].length ) { 18154 m = this.pages[0].length - 1; 18155 } 18156 18157 y = this.pages[0][m].y; 18158 } 18159 18160 return { 18161 x: x, 18162 y: y, 18163 pageX: i, 18164 pageY: m 18165 }; 18166 }, 18167 18168 goToPage: function (x, y, time, easing) { 18169 easing = easing || this.options.bounceEasing; 18170 18171 if ( x >= this.pages.length ) { 18172 x = this.pages.length - 1; 18173 } else if ( x < 0 ) { 18174 x = 0; 18175 } 18176 18177 if ( y >= this.pages[x].length ) { 18178 y = this.pages[x].length - 1; 18179 } else if ( y < 0 ) { 18180 y = 0; 18181 } 18182 18183 var posX = this.pages[x][y].x, 18184 posY = this.pages[x][y].y; 18185 18186 time = time === undefined ? this.options.snapSpeed || Math.max( 18187 Math.max( 18188 Math.min(Math.abs(posX - this.x), 1000), 18189 Math.min(Math.abs(posY - this.y), 1000) 18190 ), 300) : time; 18191 18192 this.currentPage = { 18193 x: posX, 18194 y: posY, 18195 pageX: x, 18196 pageY: y 18197 }; 18198 18199 this.scrollTo(posX, posY, time, easing); 18200 }, 18201 18202 next: function (time, easing) { 18203 var x = this.currentPage.pageX, 18204 y = this.currentPage.pageY; 18205 18206 x++; 18207 18208 if ( x >= this.pages.length && this.hasVerticalScroll ) { 18209 x = 0; 18210 y++; 18211 } 18212 18213 this.goToPage(x, y, time, easing); 18214 }, 18215 18216 prev: function (time, easing) { 18217 var x = this.currentPage.pageX, 18218 y = this.currentPage.pageY; 18219 18220 x--; 18221 18222 if ( x < 0 && this.hasVerticalScroll ) { 18223 x = 0; 18224 y--; 18225 } 18226 18227 this.goToPage(x, y, time, easing); 18228 }, 18229 18230 _initKeys: function (e) { 18231 // default key bindings 18232 var keys = { 18233 pageUp: 33, 18234 pageDown: 34, 18235 end: 35, 18236 home: 36, 18237 left: 37, 18238 up: 38, 18239 right: 39, 18240 down: 40 18241 }; 18242 var i; 18243 18244 // if you give me characters I give you keycode 18245 if ( typeof this.options.keyBindings == 'object' ) { 18246 for ( i in this.options.keyBindings ) { 18247 if ( typeof this.options.keyBindings[i] == 'string' ) { 18248 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 18248-18601
18248deAt(0); 18249 } 18250 } 18251 } else { 18252 this.options.keyBindings = {}; 18253 } 18254 18255 for ( i in keys ) { 18256 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 18257 } 18258 18259 utils.addEvent(window, 'keydown', this); 18260 18261 this.on('destroy', function () { 18262 utils.removeEvent(window, 'keydown', this); 18263 }); 18264 }, 18265 18266 _key: function (e) { 18267 if ( !this.enabled ) { 18268 return; 18269 } 18270 18271 var snap = this.options.snap, // we are using this alot, better to cache it 18272 newX = snap ? this.currentPage.pageX : this.x, 18273 newY = snap ? this.currentPage.pageY : this.y, 18274 now = utils.getTime(), 18275 prevTime = this.keyTime || 0, 18276 acceleration = 0.250, 18277 pos; 18278 18279 if ( this.options.useTransition && this.isInTransition ) { 18280 pos = this.getComputedPosition(); 18281 18282 this._translate(Math.round(pos.x), Math.round(pos.y)); 18283 this.isInTransition = false; 18284 } 18285 18286 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 18287 18288 switch ( e.keyCode ) { 18289 case this.options.keyBindings.pageUp: 18290 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18291 newX += snap ? 1 : this.wrapperWidth; 18292 } else { 18293 newY += snap ? 1 : this.wrapperHeight; 18294 } 18295 break; 18296 case this.options.keyBindings.pageDown: 18297 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18298 newX -= snap ? 1 : this.wrapperWidth; 18299 } else { 18300 newY -= snap ? 1 : this.wrapperHeight; 18301 } 18302 break; 18303 case this.options.keyBindings.end: 18304 newX = snap ? this.pages.length-1 : this.maxScrollX; 18305 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 18306 break; 18307 case this.options.keyBindings.home: 18308 newX = 0; 18309 newY = 0; 18310 break; 18311 case this.options.keyBindings.left: 18312 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 18313 break; 18314 case this.options.keyBindings.up: 18315 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 18316 break; 18317 case this.options.keyBindings.right: 18318 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 18319 break; 18320 case this.options.keyBindings.down: 18321 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 18322 break; 18323 default: 18324 return; 18325 } 18326 18327 if ( snap ) { 18328 this.goToPage(newX, newY); 18329 return; 18330 } 18331 18332 if ( newX > 0 ) { 18333 newX = 0; 18334 this.keyAcceleration = 0; 18335 } else if ( newX < this.maxScrollX ) { 18336 newX = this.maxScrollX; 18337 this.keyAcceleration = 0; 18338 } 18339 18340 if ( newY > 0 ) { 18341 newY = 0; 18342 this.keyAcceleration = 0; 18343 } else if ( newY < this.maxScrollY ) { 18344 newY = this.maxScrollY; 18345 this.keyAcceleration = 0; 18346 } 18347 18348 this.scrollTo(newX, newY, 0); 18349 18350 this.keyTime = now; 18351 }, 18352 18353 _animate: function (destX, destY, duration, easingFn) { 18354 var that = this, 18355 startX = this.x, 18356 startY = this.y, 18357 startTime = utils.getTime(), 18358 destTime = startTime + duration; 18359 18360 function step () { 18361 var now = utils.getTime(), 18362 newX, newY, 18363 easing; 18364 18365 if ( now >= destTime ) { 18366 that.isAnimating = false; 18367 that._translate(destX, destY); 18368 18369 if ( !that.resetPosition(that.options.bounceTime) ) { 18370 that._execEvent('scrollEnd'); 18371 } 18372 18373 return; 18374 } 18375 18376 now = ( now - startTime ) / duration; 18377 easing = easingFn(now); 18378 newX = ( destX - startX ) * easing + startX; 18379 newY = ( destY - startY ) * easing + startY; 18380 that._translate(newX, newY); 18381 18382 if ( that.isAnimating ) { 18383 rAF(step); 18384 } 18385 } 18386 18387 this.isAnimating = true; 18388 step(); 18389 }, 18390 handleEvent: function (e) { 18391 switch ( e.type ) { 18392 case 'touchstart': 18393 case 'pointerdown': 18394 case 'MSPointerDown': 18395 case 'mousedown': 18396 this._start(e); 18397 break; 18398 case 'touchmove': 18399 case 'pointermove': 18400 case 'MSPointerMove': 18401 case 'mousemove': 18402 this._move(e); 18403 break; 18404 case 'touchend': 18405 case 'pointerup': 18406 case 'MSPointerUp': 18407 case 'mouseup': 18408 case 'touchcancel': 18409 case 'pointercancel': 18410 case 'MSPointerCancel': 18411 case 'mousecancel': 18412 this._end(e); 18413 break; 18414 case 'orientationchange': 18415 case 'resize': 18416 this._resize(); 18417 break; 18418 case 'transitionend': 18419 case 'webkitTransitionEnd': 18420 case 'oTransitionEnd': 18421 case 'MSTransitionEnd': 18422 this._transitionEnd(e); 18423 break; 18424 case 'wheel': 18425 case 'DOMMouseScroll': 18426 case 'mousewheel': 18427 this._wheel(e); 18428 break; 18429 case 'keydown': 18430 this._key(e); 18431 break; 18432 case 'click': 18433 if ( this.enabled && !e._constructed ) { 18434 e.preventDefault(); 18435 e.stopPropagation(); 18436 } 18437 break; 18438 } 18439 } 18440}; 18441function createDefaultScrollbar (direction, interactive, type) { 18442 var scrollbar = document.createElement('div'), 18443 indicator = document.createElement('div'); 18444 18445 if ( type === true ) { 18446 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 18447 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'; 18448 } 18449 18450 indicator.className = 'iScrollIndicator'; 18451 18452 if ( direction == 'h' ) { 18453 if ( type === true ) { 18454 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 18455 indicator.style.height = '100%'; 18456 } 18457 scrollbar.className = 'iScrollHorizontalScrollbar'; 18458 } else { 18459 if ( type === true ) { 18460 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 18461 indicator.style.width = '100%'; 18462 } 18463 scrollbar.className = 'iScrollVerticalScrollbar'; 18464 } 18465 18466 scrollbar.style.cssText += ';overflow:hidden'; 18467 18468 if ( !interactive ) { 18469 scrollbar.style.pointerEvents = 'none'; 18470 } 18471 18472 scrollbar.appendChild(indicator); 18473 18474 return scrollbar; 18475} 18476 18477function Indicator (scroller, options) { 18478 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 18479 this.wrapperStyle = this.wrapper.style; 18480 this.indicator = this.wrapper.children[0]; 18481 this.indicatorStyle = this.indicator.style; 18482 this.scroller = scroller; 18483 18484 this.options = { 18485 listenX: true, 18486 listenY: true, 18487 interactive: false, 18488 resize: true, 18489 defaultScrollbars: false, 18490 shrink: false, 18491 fade: false, 18492 speedRatioX: 0, 18493 speedRatioY: 0 18494 }; 18495 18496 for ( var i in options ) { 18497 this.options[i] = options[i]; 18498 } 18499 18500 this.sizeRatioX = 1; 18501 this.sizeRatioY = 1; 18502 this.maxPosX = 0; 18503 this.maxPosY = 0; 18504 18505 if ( this.options.interactive ) { 18506 if ( !this.options.disableTouch ) { 18507 utils.addEvent(this.indicator, 'touchstart', this); 18508 utils.addEvent(window, 'touchend', this); 18509 } 18510 if ( !this.options.disablePointer ) { 18511 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18512 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 18513 } 18514 if ( !this.options.disableMouse ) { 18515 utils.addEvent(this.indicator, 'mousedown', this); 18516 utils.addEvent(window, 'mouseup', this); 18517 } 18518 } 18519 18520 if ( this.options.fade ) { 18521 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 18522 var durationProp = utils.style.transitionDuration; 18523 if(!durationProp) { 18524 return; 18525 } 18526 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 18527 // remove 0.0001ms 18528 var self = this; 18529 if(utils.isBadAndroid) { 18530 rAF(function() { 18531 if(self.wrapperStyle[durationProp] === '0.0001ms') { 18532 self.wrapperStyle[durationProp] = '0s'; 18533 } 18534 }); 18535 } 18536 this.wrapperStyle.opacity = '0'; 18537 } 18538} 18539 18540Indicator.prototype = { 18541 handleEvent: function (e) { 18542 switch ( e.type ) { 18543 case 'touchstart': 18544 case 'pointerdown': 18545 case 'MSPointerDown': 18546 case 'mousedown': 18547 this._start(e); 18548 break; 18549 case 'touchmove': 18550 case 'pointermove': 18551 case 'MSPointerMove': 18552 case 'mousemove': 18553 this._move(e); 18554 break; 18555 case 'touchend': 18556 case 'pointerup': 18557 case 'MSPointerUp': 18558 case 'mouseup': 18559 case 'touchcancel': 18560 case 'pointercancel': 18561 case 'MSPointerCancel': 18562 case 'mousecancel': 18563 this._end(e); 18564 break; 18565 } 18566 }, 18567 18568 destroy: function () { 18569 if ( this.options.fadeScrollbars ) { 18570 clearTimeout(this.fadeTimeout); 18571 this.fadeTimeout = null; 18572 } 18573 if ( this.options.interactive ) { 18574 utils.removeEvent(this.indicator, 'touchstart', this); 18575 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18576 utils.removeEvent(this.indicator, 'mousedown', this); 18577 18578 utils.removeEvent(window, 'touchmove', this); 18579 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18580 utils.removeEvent(window, 'mousemove', this); 18581 18582 utils.removeEvent(window, 'touchend', this); 18583 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 18584 utils.removeEvent(window, 'mouseup', this); 18585 } 18586 18587 if ( this.options.defaultScrollbars ) { 18588 this.wrapper.parentNode.removeChild(this.wrapper); 18589 } 18590 }, 18591 18592 _start: function (e) { 18593 var point = e.touches ? e.touches[0] : e; 18594 18595 e.preventDefault(); 18596 e.stopPropagation(); 18597 18598 this.transitionTime(); 18599 18600 this.initiated = true; 18601 this.moved = false;
vendor: 9,615 bytes, lines 18602-18860
18602 this.lastPointX = point.pageX; 18603 this.lastPointY = point.pageY; 18604 18605 this.startTime = utils.getTime(); 18606 18607 if ( !this.options.disableTouch ) { 18608 utils.addEvent(window, 'touchmove', this); 18609 } 18610 if ( !this.options.disablePointer ) { 18611 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 18612 } 18613 if ( !this.options.disableMouse ) { 18614 utils.addEvent(window, 'mousemove', this); 18615 } 18616 18617 this.scroller._execEvent('beforeScrollStart'); 18618 }, 18619 18620 _move: function (e) { 18621 var point = e.touches ? e.touches[0] : e, 18622 deltaX, deltaY, 18623 newX, newY, 18624 timestamp = utils.getTime(); 18625 18626 if ( !this.moved ) { 18627 this.scroller._execEvent('scrollStart'); 18628 } 18629 18630 this.moved = true; 18631 18632 deltaX = point.pageX - this.lastPointX; 18633 this.lastPointX = point.pageX; 18634 18635 deltaY = point.pageY - this.lastPointY; 18636 this.lastPointY = point.pageY; 18637 18638 newX = this.x + deltaX; 18639 newY = this.y + deltaY; 18640 18641 this._pos(newX, newY); 18642 18643// INSERT POINT: indicator._move 18644 18645 e.preventDefault(); 18646 e.stopPropagation(); 18647 }, 18648 18649 _end: function (e) { 18650 if ( !this.initiated ) { 18651 return; 18652 } 18653 18654 this.initiated = false; 18655 18656 e.preventDefault(); 18657 e.stopPropagation(); 18658 18659 utils.removeEvent(window, 'touchmove', this); 18660 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18661 utils.removeEvent(window, 'mousemove', this); 18662 18663 if ( this.scroller.options.snap ) { 18664 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 18665 18666 var time = this.options.snapSpeed || Math.max( 18667 Math.max( 18668 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 18669 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 18670 ), 300); 18671 18672 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 18673 this.scroller.directionX = 0; 18674 this.scroller.directionY = 0; 18675 this.scroller.currentPage = snap; 18676 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 18677 } 18678 } 18679 18680 if ( this.moved ) { 18681 this.scroller._execEvent('scrollEnd'); 18682 } 18683 }, 18684 18685 transitionTime: function (time) { 18686 time = time || 0; 18687 var durationProp = utils.style.transitionDuration; 18688 if(!durationProp) { 18689 return; 18690 } 18691 18692 this.indicatorStyle[durationProp] = time + 'ms'; 18693 18694 if ( !time && utils.isBadAndroid ) { 18695 this.indicatorStyle[durationProp] = '0.0001ms'; 18696 // remove 0.0001ms 18697 var self = this; 18698 rAF(function() { 18699 if(self.indicatorStyle[durationProp] === '0.0001ms') { 18700 self.indicatorStyle[durationProp] = '0s'; 18701 } 18702 }); 18703 } 18704 }, 18705 18706 transitionTimingFunction: function (easing) { 18707 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 18708 }, 18709 18710 refresh: function () { 18711 this.transitionTime(); 18712 18713 if ( this.options.listenX && !this.options.listenY ) { 18714 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 18715 } else if ( this.options.listenY && !this.options.listenX ) { 18716 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 18717 } else { 18718 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 18719 } 18720 18721 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 18722 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 18723 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 18724 18725 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18726 if ( this.options.listenX ) { 18727 this.wrapper.style.right = '8px'; 18728 } else { 18729 this.wrapper.style.bottom = '8px'; 18730 } 18731 } 18732 } else { 18733 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 18734 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 18735 18736 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18737 if ( this.options.listenX ) { 18738 this.wrapper.style.right = '2px'; 18739 } else { 18740 this.wrapper.style.bottom = '2px'; 18741 } 18742 } 18743 } 18744 18745 var r = this.wrapper.offsetHeight; // force refresh 18746 18747 if ( this.options.listenX ) { 18748 this.wrapperWidth = this.wrapper.clientWidth; 18749 if ( this.options.resize ) { 18750 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 18751 this.indicatorStyle.width = this.indicatorWidth + 'px'; 18752 } else { 18753 this.indicatorWidth = this.indicator.clientWidth; 18754 } 18755 18756 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 18757 18758 if ( this.options.shrink == 'clip' ) { 18759 this.minBoundaryX = -this.indicatorWidth + 8; 18760 this.maxBoundaryX = this.wrapperWidth - 8; 18761 } else { 18762 this.minBoundaryX = 0; 18763 this.maxBoundaryX = this.maxPosX; 18764 } 18765 18766 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 18767 } 18768 18769 if ( this.options.listenY ) { 18770 this.wrapperHeight = this.wrapper.clientHeight; 18771 if ( this.options.resize ) { 18772 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 18773 this.indicatorStyle.height = this.indicatorHeight + 'px'; 18774 } else { 18775 this.indicatorHeight = this.indicator.clientHeight; 18776 } 18777 18778 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18779 18780 if ( this.options.shrink == 'clip' ) { 18781 this.minBoundaryY = -this.indicatorHeight + 8; 18782 this.maxBoundaryY = this.wrapperHeight - 8; 18783 } else { 18784 this.minBoundaryY = 0; 18785 this.maxBoundaryY = this.maxPosY; 18786 } 18787 18788 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18789 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 18790 } 18791 18792 this.updatePosition(); 18793 }, 18794 18795 updatePosition: function () { 18796 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 18797 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 18798 18799 if ( !this.options.ignoreBoundaries ) { 18800 if ( x < this.minBoundaryX ) { 18801 if ( this.options.shrink == 'scale' ) { 18802 this.width = Math.max(this.indicatorWidth + x, 8); 18803 this.indicatorStyle.width = this.width + 'px'; 18804 } 18805 x = this.minBoundaryX; 18806 } else if ( x > this.maxBoundaryX ) { 18807 if ( this.options.shrink == 'scale' ) { 18808 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 18809 this.indicatorStyle.width = this.width + 'px'; 18810 x = this.maxPosX + this.indicatorWidth - this.width; 18811 } else { 18812 x = this.maxBoundaryX; 18813 } 18814 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 18815 this.width = this.indicatorWidth; 18816 this.indicatorStyle.width = this.width + 'px'; 18817 } 18818 18819 if ( y < this.minBoundaryY ) { 18820 if ( this.options.shrink == 'scale' ) { 18821 this.height = Math.max(this.indicatorHeight + y * 3, 8); 18822 this.indicatorStyle.height = this.height + 'px'; 18823 } 18824 y = this.minBoundaryY; 18825 } else if ( y > this.maxBoundaryY ) { 18826 if ( this.options.shrink == 'scale' ) { 18827 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 18828 this.indicatorStyle.height = this.height + 'px'; 18829 y = this.maxPosY + this.indicatorHeight - this.height; 18830 } else { 18831 y = this.maxBoundaryY; 18832 } 18833 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 18834 this.height = this.indicatorHeight; 18835 this.indicatorStyle.height = this.height + 'px'; 18836 } 18837 } 18838 18839 this.x = x; 18840 this.y = y; 18841 18842 if ( this.scroller.options.useTransform ) { 18843 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 18844 } else { 18845 this.indicatorStyle.left = x + 'px'; 18846 this.indicatorStyle.top = y + 'px'; 18847 } 18848 }, 18849 18850 _pos: function (x, y) { 18851 if ( x < 0 ) { 18852 x = 0; 18853 } else if ( x > this.maxPosX ) { 18854 x = this.maxPosX; 18855 } 18856 18857 if ( y < 0 ) { 18858 y = 0; 18859 } else if ( y > this.maxPosY ) { 18860 y = this.maxPosY;
18861 } 18862 18863 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 18864 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 18865 18866 this.scroller.scrollTo(x, y); 18867 }, 18868 18869 fade: function (val, hold) { 18870 if ( hold && !this.visible ) { 18871 return; 18872 } 18873 18874 clearTimeout(this.fadeTimeout); 18875 this.fadeTimeout = null; 18876 18877 var time = val ? 250 : 500, 18878 delay = val ? 0 : 300; 18879 18880 val = val ? '1' : '0'; 18881 18882 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 18883 18884 this.fadeTimeout = setTimeout((function (val) { 18885 this.wrapperStyle.opacity = val; 18886 this.visible = +val; 18887 }).bind(this, val), delay); 18888 } 18889}; 18890 18891IScroll.utils = utils; 18892 18893if ( typeof module != 'undefined' && module.exports ) { 18894 module.exports = IScroll; 18895} else if ( typeof define == 'function' && define.amd ) { 18896 define( function () { return IScroll; } ); 18897} else { 18898 window.IScroll = IScroll; 18899} 18900 18901})(window, document, Math); 18902/*! 18903 * fullPage 2.9.4 18904 * https://github.com/alvarotrigo/fullPage.js 18905 * @license MIT licensed 18906 * 18907 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 18908 */ 18909(function(global, factory) { 18910 'use strict'; 18911 if (typeof define === 'function' && define.amd) { 18912 define(['jquery'], function($) { 18913 return factory($, global, global.document, global.Math); 18914 }); 18915 } else if (typeof exports === "object" && exports) { 18916 module.exports = factory(require('jquery'), global, global.document, global.Math); 18917 } else { 18918 factory(jQuery, global, global.document, global.Math); 18919 } 18920})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 18921 'use strict'; 18922 18923 // keeping central set of classnames and selectors 18924 var WRAPPER = 'fullpage-wrapper'; 18925 var WRAPPER_SEL = '.' + WRAPPER; 18926 18927 // slimscroll 18928 var SCROLLABLE = 'fp-scrollable'; 18929 var SCROLLABLE_SEL = '.' + SCROLLABLE; 18930 18931 // util 18932 var RESPONSIVE = 'fp-responsive'; 18933 var NO_TRANSITION = 'fp-notransition'; 18934 var DESTROYED = 'fp-destroyed'; 18935 var ENABLED = 'fp-enabled'; 18936 var VIEWING_PREFIX = 'fp-viewing'; 18937 var ACTIVE = 'active'; 18938 var ACTIVE_SEL = '.' + ACTIVE; 18939 var COMPLETELY = 'fp-completely'; 18940 var COMPLETELY_SEL = '.' + COMPLETELY; 18941 18942 // section 18943 var SECTION_DEFAULT_SEL = '.section'; 18944 var SECTION = 'fp-section'; 18945 var SECTION_SEL = '.' + SECTION; 18946 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 18947 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 18948 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 18949 var TABLE_CELL = 'fp-tableCell'; 18950 var TABLE_CELL_SEL = '.' + TABLE_CELL; 18951 var AUTO_HEIGHT = 'fp-auto-height'; 18952 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 18953 var NORMAL_SCROLL = 'fp-normal-scroll'; 18954 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 18955 18956 // section nav 18957 var SECTION_NAV = 'fp-nav'; 18958 var SECTION_NAV_SEL = '#' + SECTION_NAV; 18959 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 18960 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 18961 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 18962 18963 // slide 18964 var SLIDE_DEFAULT_SEL = '.slide'; 18965 var SLIDE = 'fp-slide'; 18966 var SLIDE_SEL = '.' + SLIDE; 18967 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 18968 var SLIDES_WRAPPER = 'fp-slides'; 18969 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 18970 var SLIDES_CONTAINER = 'fp-slidesContainer'; 18971 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 18972 var TABLE = 'fp-table'; 18973 18974 // slide nav 18975 var SLIDES_NAV = 'fp-slidesNav'; 18976 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 18977 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 18978 var SLIDES_ARROW = 'fp-controlArrow'; 18979 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 18980 var SLIDES_PREV = 'fp-prev'; 18981 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 18982 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 18983 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 18984 var SLIDES_NEXT = 'fp-next';
18985 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 18986 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 18987 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 18988 18989 var $window = $(window); 18990 var $document = $(document); 18991 18992 // Default options for iScroll.js used when using scrollOverflow 18993 var iscrollOptions = { 18994 scrollbars: true, 18995 mouseWheel: true, 18996 hideScrollbars: false, 18997 fadeScrollbars: false, 18998 disableMouse: true, 18999 interactiveScrollbars: true, 19000 bounce: false, 19001 }; 19002 19003 $.fn.fullpage = function(options) { 19004 //only once my friend! 19005 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 19006 19007 // common jQuery objects 19008 var $htmlBody = $('html, body'); 19009 var $body = $('body'); 19010 19011 var FP = $.fn.fullpage; 19012 19013 // Creating some defaults, extending them with any options that were provided 19014 options = $.extend({ 19015 //navigation 19016 menu: false, 19017 anchors:[], 19018 lockAnchors: false, 19019 navigation: false, 19020 navigationPosition: 'right', 19021 navigationTooltips: [], 19022 showActiveTooltip: false, 19023 slidesNavigation: false, 19024 slidesNavPosition: 'bottom', 19025 scrollBar: false, 19026 hybrid: false, 19027 19028 //scrolling 19029 css3: true, 19030 scrollingSpeed: 700, 19031 autoScrolling: true, 19032 fitToSection: true, 19033 fitToSectionDelay: 1000, 19034 easing: 'easeInOutCubic', 19035 easingcss3: 'ease', 19036 loopBottom: false, 19037 loopTop: false, 19038 loopHorizontal: true, 19039 continuousVertical: false, 19040 continuousHorizontal: false, 19041 scrollHorizontally: false, 19042 interlockedSlides: false, 19043 dragAndMove: false, 19044 offsetSections: false, 19045 resetSliders: false, 19046 fadingEffect: false, 19047 normalScrollElements: null, 19048 scrollOverflow: false, 19049 scrollOverflowReset: false, 19050 scrollOverflowHandler: iscrollHandler, 19051 scrollOverflowOptions: null, 19052 touchSensitivity: 5, 19053 normalScrollElementTouchThreshold: 5, 19054 bigSectionsDestination: null, 19055 19056 //Accessibility 19057 keyboardScrolling: true, 19058 animateAnchor: true, 19059 recordHistory: true, 19060 19061 //design 19062 controlArrows: true, 19063 controlArrowColor: '#fff', 19064 verticalCentered: true, 19065 sectionsColor : [], 19066 paddingTop: 0, 19067 paddingBottom: 0, 19068 fixedElements: null, 19069 responsive: 0, //backwards compabitility with responsiveWiddth 19070 responsiveWidth: 0, 19071 responsiveHeight: 0, 19072 responsiveSlides: false, 19073 parallax: false, 19074 parallaxOptions: { 19075 type: 'reveal', 19076 percentage: 62, 19077 property: 'translate' 19078 }, 19079 19080 //Custom selectors 19081 sectionSelector: SECTION_DEFAULT_SEL, 19082 slideSelector: SLIDE_DEFAULT_SEL, 19083 19084 //events 19085 afterLoad: null, 19086 onLeave: null, 19087 afterRender: null, 19088 afterResize: null, 19089 afterReBuild: null, 19090 afterSlideLoad: null, 19091 onSlideLeave: null, 19092 afterResponsive: null, 19093 19094 lazyLoading: true 19095 }, options); 19096 19097 //flag to avoid very fast sliding for landscape sliders 19098 var slideMoving = false; 19099 19100 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 19101 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 19102 var container = $(this); 19103 var windowsHeight = $window.height(); 19104 var isResizing = false; 19105 var isWindowFocused = true; 19106 var lastScrolledDestiny; 19107 var lastScrolledSlide; 19108 var canScroll = true; 19109 var scrollings = []; 19110 var controlPressed; 19111 var startingSection; 19112 var isScrollAllowed = {}; 19113 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 19114 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 19115 var MSPointer = getMSPointer(); 19116 var events = { 19117 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 19118 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 19119 }; 19120 19121 //timeouts 19122 var resizeId; 19123 var afterSectionLoadsId; 19124 var afterSlideLoadsId; 19125 var scrollId; 19126 var scrollId2;
19127 var keydownId; 19128 var originals = $.extend(true, {}, options); //deep copy 19129 19130 //Uncode addition 19131 var $masthead = $('#masthead'); 19132 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 19133 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 19134 var bodyBorder = UNCODE.bodyBorder; 19135 var adminBarHeight = UNCODE.adminBarHeight; 19136 19137 displayWarnings(); 19138 19139 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 19140 iscrollOptions.click = isTouch; // see #2035 19141 19142 //extending iScroll options with the user custom ones 19143 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 19144 19145 //easeInOutCubic animation included in the plugin 19146 $.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;}}); 19147 19148 /** 19149 * Sets the autoScroll option. 19150 * It changes the scroll bar visibility and the history of the site as a result. 19151 */ 19152 function setAutoScrolling(value, type){ 19153 //removing the transformation 19154 if(!value){ 19155 silentScroll(0); 19156 } 19157 19158 setVariableState('autoScrolling', value, type); 19159 19160 var element = $(SECTION_ACTIVE_SEL); 19161 19162 if(options.autoScrolling && !options.scrollBar){ 19163 $htmlBody.css({ 19164 'overflow' : 'hidden !important', 19165 'height' : '100%' 19166 }); 19167 19168 //Uncode addition 19169 //setRecordHistory(originals.recordHistory, 'internal'); 19170 19171 //for IE touch devices 19172 container.css({ 19173 '-ms-touch-action': 'none', 19174 'touch-action': 'none' 19175 }); 19176 19177 if(element.length){ 19178 //moving the container up 19179 silentScroll(element.position().top); 19180 } 19181 19182 }else{ 19183 $htmlBody.css({ 19184 'overflow' : 'visible !important', 19185 'height' : 'initial' 19186 }); 19187 19188 //Uncode addition 19189 //setRecordHistory(false, 'internal'); 19190 19191 //for IE touch devices 19192 container.css({ 19193 '-ms-touch-action': '', 19194 'touch-action': '' 19195 }); 19196 19197 //scrolling the page to the section with no animation 19198 if (element.length) { 19199 $htmlBody.scrollTop(element.position().top); 19200 } 19201 } 19202 } 19203 19204 /** 19205 * Defines wheter to record the history for each hash change in the URL. 19206 */ 19207 function setRecordHistory(value, type){ 19208 setVariableState('recordHistory', value, type); 19209 } 19210 19211 /** 19212 * Defines the scrolling speed 19213 */ 19214 function setScrollingSpeed(value, type){ 19215 setVariableState('scrollingSpeed', value, type); 19216 } 19217 19218 /** 19219 * Sets fitToSection 19220 */ 19221 function setFitToSection(value, type){ 19222 setVariableState('fitToSection', value, type); 19223 } 19224 19225 /** 19226 * Sets lockAnchors 19227 */ 19228 function setLockAnchors(value){ 19229 options.lockAnchors = value; 19230 } 19231 19232 /** 19233 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 19234 */ 19235 function setMouseWheelScrolling(value){ 19236 if(value){ 19237 addMouseWheelHandler(); 19238 addMiddleWheelHandler(); 19239 }else{ 19240 removeMouseWheelHandler(); 19241 removeMiddleWheelHandler(); 19242 } 19243 } 19244 19245 /** 19246 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 19247 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 19248 * 19249 * @param directions string containing the direction or directions separated by comma. 19250 */ 19251 function setAllowScrolling(value, directions){ 19252 if(typeof directions !== 'undefined'){ 19253 directions = directions.replace(/ /g,'').split(','); 19254 19255 $.each(directions, function (index, direction){ 19256 setIsScrollAllowed(value, direction, 'm'); 19257 }); 19258 } 19259 else if(value){ 19260 setMouseWheelScrolling(true); 19261 addTouchHandler(); 19262 }else{ 19263 setMouseWheelScrolling(false); 19264 removeTouchHandler(); 19265 } 19266 } 19267 19268 /** 19269 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 19270 */ 19271 function setKeyboardScrolling(value, directions){ 19272 if(typeof directions !== 'undefined'){ 19273 directions = directions.replace(/ /g,'').split(','); 19274 19275 $.each(directions, function (index, direction){ 19276 setIsScrollAllowed(value, direction, 'k'); 19277 }); 19278 }else{ 19279 options.keyboardScrolling = value; 19280 } 19281 } 19282 19283 /** 19284 * Moves the page up one section. 19285 */ 19286 function moveSectionUp(){ 19287 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 19288 19289 //looping to the bottom if there's no more sections above 19290 if (!prev.length && (options.loopTop || options.continuousVertical)) {
19291 prev = $(SECTION_SEL).last(); 19292 } 19293 19294 if (prev.length) { 19295 scrollPage(prev, null, true); 19296 } 19297 } 19298 19299 /** 19300 * Moves the page down one section. 19301 */ 19302 function moveSectionDown(){ 19303 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 19304 19305 //looping to the top if there's no more sections below 19306 if(!next.length && 19307 (options.loopBottom || options.continuousVertical)){ 19308 next = $(SECTION_SEL).first(); 19309 } 19310 19311 if(next.length){ 19312 scrollPage(next, null, false); 19313 } 19314 } 19315 19316 /** 19317 * Moves the page to the given section and slide with no animation. 19318 * Anchors or index positions can be used as params. 19319 */ 19320 function silentMoveTo(sectionAnchor, slideAnchor){ 19321 setScrollingSpeed (0, 'internal'); 19322 moveTo(sectionAnchor, slideAnchor); 19323 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 19324 } 19325 19326 /** 19327 * Moves the page to the given section and slide. 19328 * Anchors or index positions can be used as params. 19329 */ 19330 function moveTo(sectionAnchor, slideAnchor){ 19331 var destiny = getSectionByAnchor(sectionAnchor); 19332 19333 if (typeof slideAnchor !== 'undefined'){ 19334 scrollPageAndSlide(sectionAnchor, slideAnchor); 19335 }else if(destiny.length > 0){ 19336 scrollPage(destiny); 19337 } 19338 } 19339 19340 /** 19341 * Slides right the slider of the active section. 19342 * Optional `section` param. 19343 */ 19344 function moveSlideRight(section){ 19345 moveSlide('right', section); 19346 } 19347 19348 /** 19349 * Slides left the slider of the active section. 19350 * Optional `section` param. 19351 */ 19352 function moveSlideLeft(section){ 19353 moveSlide('left', section); 19354 } 19355 19356 /** 19357 * When resizing is finished, we adjust the slides sizes and positions 19358 */ 19359 function reBuild(resizing){ 19360 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 19361 19362 isResizing = true; 19363 19364 windowsHeight = $window.height(); //updating global var 19365 19366 $(SECTION_SEL).each(function(){ 19367 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 19368 var slides = $(this).find(SLIDE_SEL); 19369 19370 //adjusting the height of the table-cell for IE and Firefox 19371 if(options.verticalCentered){ 19372 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 19373 } 19374 19375 $(this).css('height', windowsHeight + 'px'); 19376 19377 //resizing the scrolling divs 19378 if(options.scrollOverflow){ 19379 if(slides.length){ 19380 slides.each(function(){ 19381 createScrollBar($(this)); 19382 }); 19383 }else{ 19384 createScrollBar($(this)); 19385 } 19386 } 19387 19388 //adjusting the position fo the FULL WIDTH slides... 19389 if (slides.length > 1) { 19390 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 19391 } 19392 }); 19393 19394 var activeSection = $(SECTION_ACTIVE_SEL); 19395 var sectionIndex = activeSection.index(SECTION_SEL); 19396 19397 //isn't it the first section? 19398 if(sectionIndex){ 19399 //adjusting the position for the current section 19400 silentMoveTo(sectionIndex + 1); 19401 } 19402 19403 isResizing = false; 19404 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 19405 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 19406 } 19407 19408 /** 19409 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 19410 * are smaller than the set limit values. 19411 */ 19412 function setResponsive(active){ 19413 var isResponsive = $body.hasClass(RESPONSIVE); 19414 19415 if(active){ 19416 if(!isResponsive){ 19417 setAutoScrolling(false, 'internal'); 19418 setFitToSection(false, 'internal'); 19419 $(SECTION_NAV_SEL).hide(); 19420 $body.addClass(RESPONSIVE); 19421 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19422 } 19423 } 19424 else if(isResponsive){ 19425 setAutoScrolling(originals.autoScrolling, 'internal'); 19426 setFitToSection(originals.autoScrolling, 'internal'); 19427 $(SECTION_NAV_SEL).show(); 19428 $body.removeClass(RESPONSIVE); 19429 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19430 } 19431 } 19432 19433 if($(this).length){ 19434 //public functions 19435 FP.setAutoScrolling = setAutoScrolling; 19436 FP.setRecordHistory = setRecordHistory; 19437 FP.setScrollingSpeed = setScrollingSpeed; 19438 FP.setFitToSection = setFitToSection; 19439 FP.setLockAnchors = setLockAnchors; 19440 FP.setMouseWheelScrolling = setMouseWheelScrolling; 19441 FP.setAllowScrolling = setAllowScrolling; 19442 FP.setKeyboardScrolling = setKeyboardScrolling; 19443 FP.moveSectionUp = moveSectionUp; 19444 FP.moveSectionDown = moveSectionDown; 19445 FP.silentMoveTo = silentMoveTo; 19446 FP.moveTo = moveTo; 19447 FP.moveSlideRight = moveSlideRight; 19448 FP.moveSlideLeft = moveSlideLeft; 19449 FP.fitToSection = fitToSection; 19450 FP.reBuild = reBuild; 19451 FP.setResponsive = setResponsive; 19452 FP.destroy = destroy; 19453 19454 init(); 19455 19456 bindEvents(); 19457 } 19458
19459 function init(){ 19460 //if css3 is not supported, it will use jQuery animations 19461 if(options.css3){ 19462 options.css3 = support3d(); 19463 } 19464 19465 options.scrollBar = options.scrollBar || options.hybrid; 19466 19467 setOptionsFromDOM(); 19468 prepareDom(); 19469 setAllowScrolling(true); 19470 setAutoScrolling(options.autoScrolling, 'internal'); 19471 responsive(); 19472 19473 //setting the class for the body element 19474 setBodyClass(); 19475 19476 //Uncode addition 19477 // if(document.readyState === 'complete'){ 19478 // scrollToAnchor(); 19479 // } 19480 // $window.on('load', scrollToAnchor); 19481 } 19482 19483 function bindEvents(){ 19484 $window 19485 //when scrolling... 19486 //.on('scroll', scrollHandler) 19487 19488 //detecting any change on the URL to scroll to the given anchor link 19489 //(a way to detect back history button as we play with the hashes on the URL) 19490 .on('hashchange', hashChangeHandler) 19491 19492 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 19493 .blur(blurHandler) 19494 19495 //when resizing the site, we adjust the heights of the sections, slimScroll... 19496 .resize(resizeHandler); 19497 19498 $document 19499 //Sliding with arrow keys, both, vertical and horizontal 19500 .keydown(keydownHandler) 19501 19502 //to prevent scrolling while zooming 19503 .keyup(keyUpHandler) 19504 19505 //Scrolls to the section when clicking the navigation bullet 19506 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 19507 19508 //Scrolls the slider to the given slide destination for the given section 19509 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 19510 19511 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 19512 19513 //Scrolling horizontally when clicking on the slider controls. 19514 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 19515 19516 /** 19517 * Applying normalScroll elements. 19518 * Ignoring the scrolls over the specified selectors. 19519 */ 19520 if(options.normalScrollElements){ 19521 $document.on('mouseenter', options.normalScrollElements, function () { 19522 setMouseWheelScrolling(false); 19523 }); 19524 19525 $document.on('mouseleave', options.normalScrollElements, function(){ 19526 setMouseWheelScrolling(true); 19527 }); 19528 } 19529 } 19530 19531 /** 19532 * Setting options from DOM elements if they are not provided. 19533 */ 19534 function setOptionsFromDOM(){ 19535 var sections = container.find(options.sectionSelector); 19536 19537 //no anchors option? Checking for them in the DOM attributes 19538 if(!options.anchors.length){ 19539 options.anchors = sections.filter('[data-anchor]').map(function(){ 19540 return $(this).data('anchor').toString(); 19541 }).get(); 19542 } 19543 19544 //no tooltips option? Checking for them in the DOM attributes 19545 if(!options.navigationTooltips.length){ 19546 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 19547 return $(this).data('tooltip').toString(); 19548 }).get(); 19549 } 19550 } 19551 19552 /** 19553 * Works over the DOM structure to set it up for the current fullpage options. 19554 */ 19555 function prepareDom(){ 19556 container.css({ 19557 'height': '100%', 19558 'position': 'relative' 19559 }); 19560 19561 //adding a class to recognize the container internally in the code 19562 container.addClass(WRAPPER); 19563 $('html').addClass(ENABLED); 19564 19565 windowsHeight = $window.height(); 19566 19567 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 19568 19569 addInternalSelectors(); 19570 19571 //styling the sections / slides / menu 19572 $(SECTION_SEL).each(function(index){ 19573 var section = $(this); 19574 var slides = section.find(SLIDE_SEL); 19575 var numSlides = slides.length; 19576 19577 styleSection(section, index); 19578 styleMenu(section, index); 19579 19580 // if there's any slide 19581 if (numSlides > 0) { 19582 styleSlides(section, slides, numSlides); 19583 }else{ 19584 if(options.verticalCentered){ 19585 addTableClass(section); 19586 } 19587 } 19588 }); 19589 19590 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 19591 if(options.fixedElements && options.css3){ 19592 $(options.fixedElements).appendTo($body); 19593 } 19594 19595 //vertical centered of the navigation + active bullet 19596 if(options.navigation){ 19597 addVerticalNavigation(); 19598 } 19599 19600 enableYoutubeAPI(); 19601 19602 if(options.scrollOverflow){ 19603 if(document.readyState === 'complete'){ 19604 createScrollBarHandler(); 19605 } 19606 //after DOM and images are loaded 19607 $window.on('load', createScrollBarHandler); 19608 }else{ 19609 afterRenderActions(); 19610 } 19611 } 19612 19613 /** 19614 * Styles the horizontal slides for a section. 19615 */ 19616 function styleSlides(section, slides, numSlides){ 19617 var sliderWidth = numSlides * 100; 19618 var slideWidth = 100 / numSlides; 19619 19620 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 19621 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 19622 19623 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 19624 19625 if(numSlides > 1){ 19626 if(options.controlArrows){ 19627 createSlideArrows(section); 19628 } 19629 19630 if(options.slidesNavigation){ 19631 addSlidesNavigation(section, numSlides); 19632 } 19633 } 19634 19635 slides.each(function(index) { 19636 $(this).css('width', slideWidth + '%'); 19637 19638 if(options.verticalCentered){ 19639 addTableClass($(this)); 19640 } 19641 }); 19642 19643 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 19644 19645 //if the slide won't be an starting point, the default will be the first one 19646 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
19646ide by default. 19647 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 19648 silentLandscapeScroll(startingSlide, 'internal'); 19649 }else{ 19650 slides.eq(0).addClass(ACTIVE); 19651 } 19652 } 19653 19654 /** 19655 * Styling vertical sections 19656 */ 19657 function styleSection(section, index){ 19658 //if no active section is defined, the 1st one will be the default one 19659 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 19660 section.addClass(ACTIVE); 19661 } 19662 startingSection = $(SECTION_ACTIVE_SEL); 19663 19664 section.css('height', windowsHeight + 'px'); 19665 19666 if(options.paddingTop){ 19667 section.css('padding-top', options.paddingTop); 19668 } 19669 19670 if(options.paddingBottom){ 19671 section.css('padding-bottom', options.paddingBottom); 19672 } 19673 19674 if (typeof options.sectionsColor[index] !== 'undefined') { 19675 section.css('background-color', options.sectionsColor[index]); 19676 } 19677 19678 if (typeof options.anchors[index] !== 'undefined') { 19679 section.attr('data-anchor', options.anchors[index]); 19680 } 19681 } 19682 19683 /** 19684 * Sets the data-anchor attributes to the menu elements and activates the current one. 19685 */ 19686 function styleMenu(section, index){ 19687 if (typeof options.anchors[index] !== 'undefined') { 19688 //activating the menu / nav element on load 19689 if(section.hasClass(ACTIVE)){ 19690 activateMenuAndNav(options.anchors[index], index); 19691 } 19692 } 19693 19694 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 19695 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 19696 $(options.menu).appendTo($body); 19697 } 19698 } 19699 19700 /** 19701 * Adds internal classes to be able to provide customizable selectors 19702 * keeping the link with the style sheet. 19703 */ 19704 function addInternalSelectors(){ 19705 container.find(options.sectionSelector).addClass(SECTION); 19706 container.find(options.slideSelector).addClass(SLIDE); 19707 } 19708 19709 /** 19710 * Creates the control arrows for the given section 19711 */ 19712 function createSlideArrows(section){ 19713 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 19714 19715 if(options.controlArrowColor!='#fff'){ 19716 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 19717 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 19718 } 19719 19720 if(!options.loopHorizontal){ 19721 section.find(SLIDES_ARROW_PREV_SEL).hide(); 19722 } 19723 } 19724 19725 /** 19726 * Creates a vertical navigation bar. 19727 */ 19728 function addVerticalNavigation(){ 19729 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 19730 var nav = $(SECTION_NAV_SEL); 19731 19732 nav.addClass(function() { 19733 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 19734 }); 19735 19736 for (var i = 0; i < $(SECTION_SEL).length; i++) { 19737 var link = ''; 19738 if (options.anchors.length) { 19739 link = options.anchors[i]; 19740 } 19741 19742 var li = '<li><a href="#' + link + '"><span></span></a>'; 19743 19744 // Only add tooltip if needed (defined by user) 19745 var tooltip = options.navigationTooltips[i]; 19746 19747 if (typeof tooltip !== 'undefined' && tooltip !== '') { 19748 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 19749 } 19750 19751 li += '</li>'; 19752 19753 nav.find('ul').append(li); 19754 } 19755 19756 //centering it vertically 19757 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 19758 19759 //activating the current active section 19760 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 19761 } 19762 19763 /** 19764 * Creates the slim scroll scrollbar for the sections and slides inside them. 19765 */ 19766 function createScrollBarHandler(){ 19767 $(SECTION_SEL).each(function(){ 19768 var slides = $(this).find(SLIDE_SEL); 19769 19770 if(slides.length){ 19771 slides.each(function(){ 19772 createScrollBar($(this)); 19773 }); 19774 }else{ 19775 createScrollBar($(this)); 19776 } 19777 19778 }); 19779 afterRenderActions(); 19780 } 19781 19782 /*
19783 * Enables the Youtube videos API so we can control their flow if necessary. 19784 */ 19785 function enableYoutubeAPI(){ 19786 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 19787 addURLParam($(this), 'enablejsapi=1'); 19788 }); 19789 } 19790 19791 /** 19792 * Adds a new parameter and its value to the `src` of a given element 19793 */ 19794 function addURLParam(element, newParam){ 19795 var originalSrc = element.attr('src'); 19796 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 19797 } 19798 19799 /* 19800 * Returns the prefix sign to use for a new parameter in an existen URL. 19801 * 19802 * @return {String} ? | & 19803 */ 19804 function getUrlParamSign(url){ 19805 return ( !/\?/.test( url ) ) ? '?' : '&'; 19806 } 19807 19808 /** 19809 * Actions and callbacks to fire afterRender 19810 */ 19811 function afterRenderActions(){ 19812 var section = $(SECTION_ACTIVE_SEL); 19813 19814 section.addClass(COMPLETELY); 19815 19816 if(options.scrollOverflowHandler.afterRender){ 19817 options.scrollOverflowHandler.afterRender(section); 19818 } 19819 lazyLoad(section); 19820 playMedia(section); 19821 options.scrollOverflowHandler.afterLoad(); 19822 19823 if(isDestinyTheStartingSection()){ 19824 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 19825 } 19826 19827 $.isFunction( options.afterRender ) && options.afterRender.call(container); 19828 } 19829 19830 /** 19831 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 19832 */ 19833 function isDestinyTheStartingSection(){ 19834 var anchors = window.location.hash.replace('#', '').split('/'); 19835 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 19836 19837 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 19838 } 19839 19840 19841 var isScrolling = false; 19842 var lastScroll = 0; 19843 19844 //when scrolling... 19845 function scrollHandler(){ 19846 var currentSection; 19847 19848 if(!options.autoScrolling || options.scrollBar){ 19849 var currentScroll = $window.scrollTop(); 19850 var scrollDirection = getScrollDirection(currentScroll); 19851 var visibleSectionIndex = 0; 19852 var screen_mid = currentScroll + ($window.height() / 2.0); 19853 var isAtBottom = $body.height() - $window.height() === currentScroll; 19854 var sections = document.querySelectorAll(SECTION_SEL); 19855 19856 //when using `auto-height` for a small last section it won't be centered in the viewport 19857 if(isAtBottom){ 19858 visibleSectionIndex = sections.length - 1; 19859 } 19860 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 19861 else if(!currentScroll){ 19862 visibleSectionIndex = 0; 19863 } 19864 19865 //taking the section which is showing more content in the viewport 19866 else{ 19867 for (var i = 0; i < sections.length; ++i) { 19868 var section = sections[i]; 19869 19870 // Pick the the last section which passes the middle line of the screen. 19871 if (section.offsetTop <= screen_mid) 19872 { 19873 visibleSectionIndex = i; 19874 } 19875 } 19876 } 19877 19878 if(isCompletelyInViewPort(scrollDirection)){ 19879 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 19880 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 19881 } 19882 } 19883 19884 //geting the last one, the current one on the screen 19885 currentSection = $(sections).eq(visibleSectionIndex); 19886 19887 //setting the visible section as active when manually scrolling 19888 //executing only once the first time we reach the section 19889 if(!currentSection.hasClass(ACTIVE)){ 19890 isScrolling = true; 19891 var leavingSection = $(SECTION_ACTIVE_SEL); 19892 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 19893 var yMovement = getYmovement(currentSection); 19894 var anchorLink = currentSection.data('anchor'); 19895 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 19896 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 19897 var slideIndex; 19898 var slideAnchorLink; 19899 19900 if(activeSlide.length){ 19901 slideAnchorLink = activeSlide.data('anchor'); 19902 slideIndex = activeSlide.index(); 19903 } 19904 19905 if(canScroll){ 19906 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 19907 19908 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 19909 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 19910 19911 stopMedia(leavingSection); 19912 lazyLoad(currentSection); 19913 playMedia(currentSection); 19914 19915 activateMenuAndNav(anchorLink, sectionIndex - 1); 19916 19917 if(options.anchors.length){ 19918 //needed to enter in hashChange event when using the menu with anchor links 19919 lastScrolledDestiny = anchorLink; 19920 } 19921 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 19922 } 19923 19924 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 19925 clearTimeout(scrollId); 19926 scrollId = setTimeout(function(){ 19927 isScrolling = false;
19928 }, 100); 19929 } 19930 19931 if(options.fitToSection){ 19932 //for the auto adjust of the viewport to fit a whole section 19933 clearTimeout(scrollId2); 19934 19935 scrollId2 = setTimeout(function(){ 19936 //checking it again in case it changed during the delay 19937 if(options.fitToSection){ 19938 fitToSection(); 19939 } 19940 }, options.fitToSectionDelay); 19941 } 19942 } 19943 } 19944 19945 /** 19946 * Fits the site to the nearest active section 19947 */ 19948 function fitToSection(){ 19949 //checking fitToSection again in case it was set to false before the timeout delay 19950 if(canScroll){ 19951 //allows to scroll to an active section and 19952 //if the section is already active, we prevent firing callbacks 19953 isResizing = true; 19954 19955 scrollPage($(SECTION_ACTIVE_SEL)); 19956 isResizing = false; 19957 } 19958 } 19959 19960 /** 19961 * Determines whether the active section has seen in its whole or not. 19962 */ 19963 function isCompletelyInViewPort(movement){ 19964 var top = $(SECTION_ACTIVE_SEL).position().top; 19965 var bottom = top + $window.height(); 19966 19967 if(movement == 'up'){ 19968 return bottom >= ($window.scrollTop() + $window.height()); 19969 } 19970 return top <= $window.scrollTop(); 19971 } 19972 19973 /** 19974 * Gets the directon of the the scrolling fired by the scroll event. 19975 */ 19976 function getScrollDirection(currentScroll){ 19977 var direction = currentScroll > lastScroll ? 'down' : 'up'; 19978 19979 lastScroll = currentScroll; 19980 19981 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 19982 previousDestTop = currentScroll; 19983 19984 return direction; 19985 } 19986 19987 /** 19988 * Determines the way of scrolling up or down: 19989 * by 'automatically' scrolling a section or by using the default and normal scrolling. 19990 */ 19991 function scrolling(type, scrollable){ 19992 if (!isScrollAllowed.m[type]){ 19993 return; 19994 } 19995 var check = (type === 'down') ? 'bottom' : 'top'; 19996 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 19997 19998 if(scrollable.length > 0 ){ 19999 //is the scrollbar at the start/end of the scroll? 20000 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 20001 scrollSection(); 20002 }else{ 20003 return true; 20004 } 20005 }else{ 20006 // moved up/down 20007 scrollSection(); 20008 } 20009 } 20010 20011 /* 20012 * Preventing bouncing in iOS #2285 20013 */ 20014 function preventBouncing(event){ 20015 var e = event.originalEvent; 20016 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e)){ 20017 //preventing the easing on iOS devices 20018 event.preventDefault(); 20019 } 20020 } 20021 20022 var touchStartY = 0; 20023 var touchStartX = 0; 20024 var touchEndY = 0; 20025 var touchEndX = 0; 20026 20027 /* Detecting touch events 20028 20029 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 20030 * This way, the touchstart and the touch moves shows an small difference between them which is the 20031 * used one to determine the direction. 20032 */ 20033 function touchMoveHandler(event){ 20034 var e = event.originalEvent; 20035 var activeSection = $(e.target).closest(SECTION_SEL); 20036 20037 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 20038 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 20039 20040 if(options.autoScrolling){ 20041 //preventing the easing on iOS devices 20042 event.preventDefault(); 20043 } 20044 20045 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20046 var touchEvents = getEventsPage(e); 20047 20048 touchEndY = touchEvents.y; 20049 touchEndX = touchEvents.x; 20050 20051 //if movement in the X axys is greater than in the Y and the currect section has slides... 20052 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 20053 20054 //is the movement greater than the minimum resistance to scroll? 20055 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 20056 if (touchStartX > touchEndX) { 20057 if(isScrollAllowed.m.right){ 20058 moveSlideRight(activeSection); //next 20059 } 20060 } else { 20061 if(isScrollAllowed.m.left){ 20062 moveSlideLeft(activeSection); //prev 20063 } 20064 } 20065 } 20066 } 20067 20068 //vertical scrolling (only when autoScrolling is enabled) 20069 else if(options.autoScrolling && canScroll){ 20070 20071 //is the movement greater than the minimum resistance to scroll? 20072 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 20073 if (touchStartY > touchEndY) { 20074 scrolling('down', scrollable); 20075 } else if (touchEndY > touchStartY) { 20076 scrolling('up', scrollable); 20077 } 20078 } 20079 } 20080 } 20081 } 20082 20083 /** 20084 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 20085 * Currently works well for iOS - Android might need some testing 20086 * @param {Element} el target element / jquery selector (in subsequent nodes) 20087 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 20088 * @return {boolean} true if there is a match to options.normalScrollElements 20089 */ 20090 function checkParentForNormalScrollElement (el, hop) { 20091 hop = hop || 0; 20092 var parent = $(el).parent(); 20093 20094 if (hop < options.normalScrollElementTouchThreshold && 20095 parent.is(options.normalScrollElements) ) { 20096 return true; 20097 } else if (hop == options.normalScrollElementTouchThreshold) { 20098 return false;
20099 } else { 20100 return checkParentForNormalScrollElement(parent, ++hop); 20101 } 20102 } 20103 20104 /** 20105 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 20106 * this way we make sure that is really a touch event what IE is detecting. 20107 */ 20108 function isReallyTouch(e){ 20109 //if is not IE || IE is detecting `touch` or `pen` 20110 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 20111 } 20112 20113 /** 20114 * Handler for the touch start event. 20115 */ 20116 function touchStartHandler(event){ 20117 var e = event.originalEvent; 20118 20119 //stopping the auto scroll to adjust to a section 20120 if(options.fitToSection){ 20121 $htmlBody.stop(); 20122 } 20123 20124 if(isReallyTouch(e)){ 20125 var touchEvents = getEventsPage(e); 20126 touchStartY = touchEvents.y; 20127 touchStartX = touchEvents.x; 20128 } 20129 } 20130 20131 /** 20132 * Gets the average of the last `number` elements of the given array. 20133 */ 20134 function getAverage(elements, number){ 20135 var sum = 0; 20136 20137 //taking `number` elements from the end to make the average, if there are not enought, 1 20138 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 20139 20140 for(var i = 0; i < lastElements.length; i++){ 20141 sum = sum + lastElements[i]; 20142 } 20143 20144 return Math.ceil(sum/number); 20145 } 20146 20147 /** 20148 * Detecting mousewheel scrolling 20149 * 20150 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 20151 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 20152 */ 20153 var prevTime = new Date().getTime(); 20154 20155 function MouseWheelHandler(e) { 20156 var curTime = new Date().getTime(); 20157 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 20158 20159 //autoscrolling and not zooming? 20160 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 20161 // cross-browser wheel delta 20162 e = e || window.event; 20163 var value = e.wheelDelta || -e.deltaY || -e.detail; 20164 var delta = Math.max(-1, Math.min(1, value)); 20165 20166 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 20167 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 20168 20169 //Limiting the array to 150 (lets not waste memory!) 20170 if(scrollings.length > 149){ 20171 scrollings.shift(); 20172 } 20173 20174 //keeping record of the previous scrollings 20175 scrollings.push(Math.abs(value)); 20176 20177 //preventing to scroll the site on mouse wheel when scrollbar is present 20178 if(options.scrollBar){ 20179 e.preventDefault ? e.preventDefault() : e.returnValue = false; 20180 } 20181 20182 var activeSection = $(SECTION_ACTIVE_SEL); 20183 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20184 20185 //time difference between the last scroll and the current one 20186 var timeDiff = curTime-prevTime; 20187 prevTime = curTime; 20188 20189 //haven't they scrolled in a while? 20190 //(enough to be consider a different scrolling action to scroll another section) 20191 if(timeDiff > 200){ 20192 //emptying the array, we dont care about old scrollings for our averages 20193 scrollings = []; 20194 } 20195 20196 if(canScroll){ 20197 var averageEnd = getAverage(scrollings, 10); 20198 var averageMiddle = getAverage(scrollings, 70); 20199 var isAccelerating = averageEnd >= averageMiddle; 20200 20201 //to avoid double swipes... 20202 if(isAccelerating && isScrollingVertically){ 20203 //scrolling down? 20204 if (delta < 0) { 20205 scrolling('down', scrollable); 20206 20207 //scrolling up? 20208 }else { 20209 scrolling('up', scrollable); 20210 } 20211 } 20212 } 20213 20214 return false;
20215 } 20216 20217 if(options.fitToSection){ 20218 //stopping the auto scroll to adjust to a section 20219 $htmlBody.stop(); 20220 } 20221 } 20222 20223 /** 20224 * Slides a slider to the given direction. 20225 * Optional `section` param. 20226 */ 20227 function moveSlide(direction, section){ 20228 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 20229 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 20230 var numSlides = slides.find(SLIDE_SEL).length; 20231 20232 // more than one slide needed and nothing should be sliding 20233 if (!slides.length || slideMoving || numSlides < 2) { 20234 return; 20235 } 20236 20237 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 20238 var destiny = null; 20239 20240 if(direction === 'left'){ 20241 destiny = currentSlide.prev(SLIDE_SEL); 20242 }else{ 20243 destiny = currentSlide.next(SLIDE_SEL); 20244 } 20245 20246 //isn't there a next slide in the secuence? 20247 if(!destiny.length){ 20248 //respect loopHorizontal settin 20249 if (!options.loopHorizontal) return; 20250 20251 if(direction === 'left'){ 20252 destiny = currentSlide.siblings(':last'); 20253 }else{ 20254 destiny = currentSlide.siblings(':first'); 20255 } 20256 } 20257 20258 slideMoving = true; 20259 20260 landscapeScroll(slides, destiny, direction); 20261 } 20262 20263 /** 20264 * Maintains the active slides in the viewport 20265 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 20266 */ 20267 function keepSlidesPosition(){ 20268 $(SLIDE_ACTIVE_SEL).each(function(){ 20269 silentLandscapeScroll($(this), 'internal'); 20270 }); 20271 } 20272 20273 var previousDestTop = 0; 20274 /** 20275 * Returns the destination Y position based on the scrolling direction and 20276 * the height of the section. 20277 */ 20278 function getDestinationPosition(element){ 20279 var elemPosition = element.position(); 20280 20281 //top of the desination will be at the top of the viewport 20282 var position = elemPosition.top; 20283 var isScrollingDown = elemPosition.top > previousDestTop; 20284 var sectionBottom = position - windowsHeight + element.outerHeight(); 20285 var bigSectionsDestination = options.bigSectionsDestination; 20286 20287 //Uncode addition 20288 var containerH = container.outerHeight(); 20289 var containerPosition = container.offset(); 20290 20291 //########### Commented by Uncode - START ########### 20292 //is the destination element bigger than the viewport? 20293 // if(element.outerHeight() > windowsHeight){ 20294 // //scrolling up? 20295 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 20296 // position = sectionBottom; 20297 // } 20298 // } 20299 20300 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 20301 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 20302 // //The bottom of the destination will be at the bottom of the viewport 20303 // position = sectionBottom; 20304 // } 20305 //########### Commented by Uncode - END ########### 20306 20307 //Uncode addition 20308 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 20309 position += 18; 20310 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 20311 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 20312 } 20313 20314 /* 20315 Keeping record of the last scrolled position to determine the scrolling direction. 20316 No conventional methods can be used as the scroll bar might not be present 20317 AND the section might not be active if it is auto-height and didnt reach the middle 20318 of the viewport. 20319 */ 20320 previousDestTop = position; 20321 return position; 20322 } 20323 20324 /** 20325 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 20326 */ 20327 function scrollPage(element, callback, isMovementUp){ 20328 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 20329 20330 var dtop = getDestinationPosition(element); 20331 var slideAnchorLink; 20332 var slideIndex; 20333 20334 //local variables 20335 var v = { 20336 element: element, 20337 callback: callback, 20338 isMovementUp: isMovementUp, 20339 dtop: dtop, 20340 yMovement: getYmovement(element), 20341 anchorLink: element.data('anchor'), 20342 sectionIndex: element.index(SECTION_SEL), 20343 activeSlide: element.find(SLIDE_ACTIVE_SEL), 20344 activeSection: $(SECTION_ACTIVE_SEL), 20345 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 20346 20347 //caching the value of isResizing at the momment the function is called 20348 //because it will be checked later inside a setTimeout and the value might change 20349 localIsResizing: isResizing 20350 }; 20351 20352 //quiting when destination scroll is the same as the current one 20353 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 20354 20355 if(v.activeSlide.length){ 20356 slideAnchorLink = v.activeSlide.data('anchor'); 20357 slideIndex = v.activeSlide.index(); 20358 } 20359 20360 // If continuousVertical && we need to wrap around 20361 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 20362 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 20363 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 20364 20365 v = createInfiniteSections(v); 20366 } 20367 20368 //callback (onLeave) if the site is not just resizing and readjusting the slides 20369 if($.isFunction(options.onLeave) && !v.localIsResizing){ 20370 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 20371 return; 20372 } 20373 } 20374 20375 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 20376 if(!v.localIsResizing){ 20377 stopMedia(v.activeSection); 20378 } 20379 20380 options.scrollOverflowHandler.beforeLeave(); 20381 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20382 lazyLoad(element); 20383 options.scrollOverflowHandler.onLeave(); 20384 20385 20386 //preventing from activating the MouseWheelHandler event 20387 //more than once if the page is scrolling 20388 canScroll = false;
20389 20390 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 20391 20392 performMovement(v); 20393 20394 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 20395 lastScrolledDestiny = v.anchorLink; 20396 20397 //avoid firing it twice (as it does also on scroll) 20398 activateMenuAndNav(v.anchorLink, v.sectionIndex); 20399 } 20400 20401 /** 20402 * Performs the vertical movement (by CSS3 or by jQuery) 20403 */ 20404 function performMovement(v){ 20405 // using CSS3 translate functionality 20406 if (options.css3 && options.autoScrolling && !options.scrollBar) { 20407 20408 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 20409 // that's why we round it to 0. 20410 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 20411 transformContainer(translate3d, true); 20412 20413 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 20414 //scrollingSpeed to change in case of using silentMoveTo(); 20415 if(options.scrollingSpeed){ 20416 clearTimeout(afterSectionLoadsId); 20417 afterSectionLoadsId = setTimeout(function () { 20418 afterSectionLoads(v); 20419 }, options.scrollingSpeed); 20420 }else{ 20421 afterSectionLoads(v); 20422 } 20423 } 20424 20425 // using jQuery animate 20426 else{ 20427 var scrollSettings = getScrollSettings(v); 20428 20429 $(scrollSettings.element).animate( 20430 scrollSettings.options, 20431 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 20432 if(options.scrollBar){ 20433 20434 /* Hack! 20435 The timeout prevents setting the most dominant section in the viewport as "active" when the user 20436 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 20437 20438 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 20439 */ 20440 setTimeout(function(){ 20441 afterSectionLoads(v); 20442 },30); 20443 }else{ 20444 afterSectionLoads(v); 20445 } 20446 }); 20447 } 20448 } 20449 20450 /** 20451 * Gets the scrolling settings depending on the plugin autoScrolling option 20452 */ 20453 function getScrollSettings(v){ 20454 var scroll = {}; 20455 20456 if(options.autoScrolling && !options.scrollBar){ 20457 scroll.options = { 'top': -v.dtop}; 20458 scroll.element = WRAPPER_SEL; 20459 }else{ 20460 scroll.options = { 'scrollTop': v.dtop}; 20461 scroll.element = 'html, body'; 20462 } 20463 20464 return scroll; 20465 } 20466 20467 /** 20468 * Adds sections before or after the current one to create the infinite effect. 20469 */ 20470 function createInfiniteSections(v){ 20471 // Scrolling down 20472 if (!v.isMovementUp) { 20473 // Move all previous sections to after the active section 20474 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 20475 } 20476 else { // Scrolling up 20477 // Move all next sections to before the active section 20478 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 20479 } 20480 20481 // Maintain the displayed position (now that we changed the element order) 20482 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20483 20484 // Maintain the active slides visible in the viewport 20485 keepSlidesPosition(); 20486 20487 // save for later the elements that still need to be reordered 20488 v.wrapAroundElements = v.activeSection; 20489 20490 // Recalculate animation variables 20491 v.dtop = v.element.position().top; 20492 v.yMovement = getYmovement(v.element); 20493 20494 return v; 20495 } 20496 20497 /** 20498 * Fix section order after continuousVertical changes have been animated 20499 */ 20500 function continuousVerticalFixSectionOrder (v) {
20501 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 20502 // finish moving the elements around so the direct navigation will function more simply 20503 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 20504 return; 20505 } 20506 20507 if (v.isMovementUp) { 20508 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 20509 } 20510 else { 20511 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 20512 } 20513 20514 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20515 20516 // Maintain the active slides visible in the viewport 20517 keepSlidesPosition(); 20518 } 20519 20520 20521 /** 20522 * Actions to do once the section is loaded. 20523 */ 20524 function afterSectionLoads (v){ 20525 continuousVerticalFixSectionOrder(v); 20526 20527 //callback (afterLoad) if the site is not just resizing and readjusting the slides 20528 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 20529 options.scrollOverflowHandler.afterLoad(); 20530 20531 if(!v.localIsResizing){ 20532 playMedia(v.element); 20533 } 20534 20535 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 20536 20537 canScroll = true; 20538 20539 $.isFunction(v.callback) && v.callback.call(this); 20540 } 20541 20542 /** 20543 * Sets the value for the given attribute from the `data-` attribute with the same suffix 20544 * ie: data-srcset ==> srcset | data-src ==> src 20545 */ 20546 function setSrc(element, attribute){ 20547 element 20548 .attr(attribute, element.data(attribute)) 20549 .removeAttr('data-' + attribute); 20550 } 20551 20552 /** 20553 * Lazy loads image, video and audio elements. 20554 */ 20555 function lazyLoad(destiny){ 20556 if (!options.lazyLoading){ 20557 return; 20558 } 20559 20560 var panel = getSlideOrSection(destiny); 20561 var element; 20562 20563 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 20564 element = $(this); 20565 20566 $.each(['src', 'srcset'], function(index, type){ 20567 var attribute = element.attr('data-' + type); 20568 if(typeof attribute !== 'undefined' && attribute){ 20569 setSrc(element, type); 20570 } 20571 }); 20572 20573 if(element.is('source')){ 20574 element.closest('video').get(0).load(); 20575 } 20576 }); 20577 } 20578 20579 /** 20580 * Plays video and audio elements. 20581 */ 20582 function playMedia(destiny){ 20583 var panel = getSlideOrSection(destiny); 20584 20585 //playing HTML5 media elements 20586 panel.find('video, audio').each(function(){ 20587 var element = $(this).get(0); 20588 20589 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 20590 element.play(); 20591 } 20592 }); 20593 20594 //youtube videos 20595 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20596 var element = $(this).get(0); 20597 20598 if ( element.hasAttribute('data-autoplay') ){ 20599 playYoutube(element); 20600 } 20601 20602 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 20603 element.onload = function() { 20604 if ( element.hasAttribute('data-autoplay') ){ 20605 playYoutube(element); 20606 } 20607 }; 20608 }); 20609 } 20610 20611 /** 20612 * Plays a youtube video 20613 */ 20614 function playYoutube(element){ 20615 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 20616 } 20617 20618 /** 20619 * Stops video and audio elements. 20620 */ 20621 function stopMedia(destiny){ 20622 var panel = getSlideOrSection(destiny); 20623 20624 //stopping HTML5 media elements 20625 panel.find('video, audio').each(function(){ 20626 var element = $(this).get(0); 20627 20628 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 20629 element.pause(); 20630 } 20631 }); 20632 20633 //youtube videos 20634 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20635 var element = $(this).get(0); 20636 20637 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 20638 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 20639 } 20640 }); 20641 } 20642 20643 /** 20644 * Gets the active slide (or section) for the given section 20645 */ 20646 function getSlideOrSection(destiny){ 20647 var slide = destiny.find(SLIDE_ACTIVE_SEL); 20648 if( slide.length ) { 20649 destiny = $(slide); 20650 } 20651 20652 return destiny; 20653 } 20654 20655 /**
20656 * Scrolls to the anchor in the URL when loading the site 20657 */ 20658 function scrollToAnchor(){ 20659 //getting the anchor link in the URL and deleting the `#` 20660 var value = window.location.hash.replace('#', '').split('/'); 20661 var sectionAnchor = decodeURIComponent(value[0]); 20662 var slideAnchor = decodeURIComponent(value[1]); 20663 20664 if(sectionAnchor){ //if theres any # 20665 if(options.animateAnchor){ 20666 scrollPageAndSlide(sectionAnchor, slideAnchor); 20667 }else{ 20668 silentMoveTo(sectionAnchor, slideAnchor); 20669 } 20670 } 20671 } 20672 20673 /** 20674 * Detecting any change on the URL to scroll to the given anchor link 20675 * (a way to detect back history button as we play with the hashes on the URL) 20676 */ 20677 function hashChangeHandler(){ 20678 if(!isScrolling && !options.lockAnchors){ 20679 var value = window.location.hash.replace('#', '').split('/'); 20680 var sectionAnchor = decodeURIComponent(value[0]); 20681 var slideAnchor = decodeURIComponent(value[1]); 20682 20683 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 20684 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 20685 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 20686 20687 20688 if(sectionAnchor.length){ 20689 /*in order to call scrollpage() only once for each destination at a time 20690 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 20691 event is fired on every scroll too.*/ 20692 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 20693 scrollPageAndSlide(sectionAnchor, slideAnchor); 20694 } 20695 } 20696 } 20697 } 20698 20699 //Sliding with arrow keys, both, vertical and horizontal 20700 function keydownHandler(e) { 20701 20702 clearTimeout(keydownId); 20703 20704 var activeElement = $(':focus'); 20705 20706 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 20707 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 20708 options.keyboardScrolling && options.autoScrolling){ 20709 var keyCode = e.which; 20710 20711 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 20712 var keyControls = [40, 38, 32, 33, 34]; 20713 if($.inArray(keyCode, keyControls) > -1){ 20714 e.preventDefault(); 20715 } 20716 20717 controlPressed = e.ctrlKey; 20718 20719 keydownId = setTimeout(function(){ 20720 onkeydown(e); 20721 },150); 20722 } 20723 } 20724 20725 function tooltipTextHandler(){ 20726 $(this).prev().trigger('click'); 20727 } 20728 20729 //to prevent scrolling while zooming 20730 function keyUpHandler(e){ 20731 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 20732 controlPressed = e.ctrlKey; 20733 } 20734 } 20735 20736 //binding the mousemove when the mouse's middle button is released 20737 function mouseDownHandler(e){ 20738 //middle button 20739 if (e.which == 2){ 20740 oldPageY = e.pageY; 20741 container.on('mousemove', mouseMoveHandler); 20742 } 20743 } 20744 20745 //unbinding the mousemove when the mouse's middle button is released 20746 function mouseUpHandler(e){ 20747 //middle button 20748 if (e.which == 2){ 20749 container.off('mousemove'); 20750 } 20751 } 20752 20753 //Scrolling horizontally when clicking on the slider controls. 20754 function slideArrowHandler(){ 20755 var section = $(this).closest(SECTION_SEL); 20756 20757 if ($(this).hasClass(SLIDES_PREV)) { 20758 if(isScrollAllowed.m.left){ 20759 moveSlideLeft(section); 20760 } 20761 } else { 20762 if(isScrollAllowed.m.right){ 20763 moveSlideRight(section); 20764 } 20765 } 20766 } 20767 20768 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 20769 function blurHandler(){ 20770 isWindowFocused = false;
20771 controlPressed = false; 20772 } 20773 20774 //Scrolls to the section when clicking the navigation bullet 20775 function sectionBulletHandler(e){ 20776 e.preventDefault(); 20777 var index = $(this).parent().index(); 20778 scrollPage($(SECTION_SEL).eq(index)); 20779 } 20780 20781 //Scrolls the slider to the given slide destination for the given section 20782 function slideBulletHandler(e){ 20783 e.preventDefault(); 20784 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 20785 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 20786 20787 landscapeScroll(slides, destiny); 20788 } 20789 20790 /** 20791 * Keydown event 20792 */ 20793 function onkeydown(e){ 20794 var shiftPressed = e.shiftKey; 20795 20796 //do nothing if we can not scroll or we are not using horizotnal key arrows. 20797 if(!canScroll && [37,39].indexOf(e.which) < 0){ 20798 return; 20799 } 20800 20801 switch (e.which) { 20802 //up 20803 case 38: 20804 case 33: 20805 if(isScrollAllowed.k.up){ 20806 moveSectionUp(); 20807 } 20808 break; 20809 20810 //down 20811 case 32: //spacebar 20812 if(shiftPressed && isScrollAllowed.k.up){ 20813 moveSectionUp(); 20814 break; 20815 } 20816 /* falls through */ 20817 case 40: 20818 case 34: 20819 if(isScrollAllowed.k.down){ 20820 moveSectionDown(); 20821 } 20822 break; 20823 20824 //Home 20825 case 36: 20826 if(isScrollAllowed.k.up){ 20827 moveTo(1); 20828 } 20829 break; 20830 20831 //End 20832 case 35: 20833 if(isScrollAllowed.k.down){ 20834 moveTo( $(SECTION_SEL).length ); 20835 } 20836 break; 20837 20838 //left 20839 case 37: 20840 if(isScrollAllowed.k.left){ 20841 moveSlideLeft(); 20842 } 20843 break; 20844 20845 //right 20846 case 39: 20847 if(isScrollAllowed.k.right){ 20848 moveSlideRight(); 20849 } 20850 break; 20851 20852 default: 20853 return; // exit this handler for other keys 20854 } 20855 } 20856 20857 /** 20858 * Detecting the direction of the mouse movement. 20859 * Used only for the middle button of the mouse. 20860 */ 20861 var oldPageY = 0; 20862 function mouseMoveHandler(e){ 20863 if(canScroll){ 20864 // moving up 20865 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 20866 moveSectionUp(); 20867 } 20868 20869 // moving down 20870 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 20871 moveSectionDown(); 20872 } 20873 } 20874 oldPageY = e.pageY; 20875 } 20876 20877 /** 20878 * Scrolls horizontal sliders. 20879 */ 20880 function landscapeScroll(slides, destiny, direction){ 20881 var section = slides.closest(SECTION_SEL); 20882 var v = { 20883 slides: slides, 20884 destiny: destiny, 20885 direction: direction, 20886 destinyPos: destiny.position(), 20887 slideIndex: destiny.index(), 20888 section: section, 20889 sectionIndex: section.index(SECTION_SEL), 20890 anchorLink: section.data('anchor'), 20891 slidesNav: section.find(SLIDES_NAV_SEL), 20892 slideAnchor: getAnchor(destiny), 20893 prevSlide: section.find(SLIDE_ACTIVE_SEL), 20894 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 20895 20896 //caching the value of isResizing at the momment the function is called 20897 //because it will be checked later inside a setTimeout and the value might change 20898 localIsResizing: isResizing 20899 }; 20900 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 20901 20902 //important!! Only do it when not resizing 20903 if(!v.localIsResizing){ 20904 //preventing from scrolling to the next/prev section when using scrollHorizontally 20905 canScroll = false;
20906 } 20907 20908 if(options.onSlideLeave){ 20909 20910 //if the site is not just resizing and readjusting the slides 20911 if(!v.localIsResizing && v.xMovement!=='none'){ 20912 if($.isFunction( options.onSlideLeave )){ 20913 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 20914 slideMoving = false; 20915 return; 20916 } 20917 } 20918 } 20919 } 20920 20921 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20922 20923 if(!v.localIsResizing){ 20924 stopMedia(v.prevSlide); 20925 lazyLoad(destiny); 20926 } 20927 20928 if(!options.loopHorizontal && options.controlArrows){ 20929 //hidding it for the fist slide, showing for the rest 20930 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 20931 20932 //hidding it for the last slide, showing for the rest 20933 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 20934 } 20935 20936 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 20937 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 20938 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 20939 } 20940 20941 performHorizontalMove(slides, v, true); 20942 } 20943 20944 20945 function afterSlideLoads(v){ 20946 activeSlidesNavigation(v.slidesNav, v.slideIndex); 20947 20948 //if the site is not just resizing and readjusting the slides 20949 if(!v.localIsResizing){ 20950 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 20951 20952 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 20953 //and to prevent double scroll right after a windows resize 20954 canScroll = true; 20955 20956 playMedia(v.destiny); 20957 } 20958 20959 //letting them slide again 20960 slideMoving = false; 20961 } 20962 20963 /** 20964 * Performs the horizontal movement. (CSS3 or jQuery) 20965 * 20966 * @param fireCallback {Bool} - determines whether or not to fire the callback 20967 */ 20968 function performHorizontalMove(slides, v, fireCallback){ 20969 var destinyPos = v.destinyPos; 20970 20971 if(options.css3){ 20972 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 20973 20974 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 20975 20976 afterSlideLoadsId = setTimeout(function(){ 20977 fireCallback && afterSlideLoads(v); 20978 }, options.scrollingSpeed, options.easing); 20979 }else{ 20980 slides.animate({ 20981 scrollLeft : Math.round(destinyPos.left) 20982 }, options.scrollingSpeed, options.easing, function() { 20983 20984 fireCallback && afterSlideLoads(v); 20985 }); 20986 } 20987 } 20988 20989 /** 20990 * Sets the state for the horizontal bullet navigations. 20991 */ 20992 function activeSlidesNavigation(slidesNav, slideIndex){ 20993 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 20994 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 20995 } 20996 20997 var previousHeight = windowsHeight; 20998 20999 //when resizing the site, we adjust the heights of the sections, slimScroll... 21000 function resizeHandler(){ 21001 //checking if it needs to get responsive 21002 responsive(); 21003 21004 // rebuild immediately on touch devices 21005 if (isTouchDevice) { 21006 var activeElement = $(document.activeElement); 21007 21008 //if the keyboard is NOT visible 21009 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 21010 var currentHeight = $window.height(); 21011 21012 //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) 21013 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 21014 reBuild(true); 21015 previousHeight = currentHeight; 21016 } 21017 } 21018 }else{ 21019 //in order to call the functions only when the resize is finished 21020 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 21021 clearTimeout(resizeId); 21022 21023 resizeId = setTimeout(function(){ 21024 reBuild(true); 21025 }, 350); 21026 } 21027 } 21028 21029 /** 21030 * Checks if the site needs to get responsive and disables autoScrolling if so. 21031 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 21032 */ 21033 function responsive(){ 21034 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 21035 var heightLimit = options.responsiveHeight; 21036 21037 //only calculating what we need. Remember its called on the resize event. 21038 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 21039 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 21040 21041 if(widthLimit && heightLimit){ 21042 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 21043 } 21044 else if(widthLimit){ 21045 setResponsive(isBreakingPointWidth); 21046 } 21047 else if(heightLimit){ 21048 setResponsive(isBreakingPointHeight); 21049 } 21050 } 21051 21052 /** 21053 * Adds transition animations for the given element 21054 */ 21055 function addAnimation(container, element){ 21056 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 21057 21058 container.removeClass(NO_TRANSITION); 21059 return container.css({
21060 '-webkit-transition': transition, 21061 'transition': transition 21062 }); 21063 } 21064 21065 /** 21066 * Remove transition animations for the given element 21067 */ 21068 function removeAnimation(element){ 21069 return element.addClass(NO_TRANSITION); 21070 } 21071 21072 /** 21073 * Activating the vertical navigation bullets according to the given slide name. 21074 */ 21075 function activateNavDots(name, sectionIndex){ 21076 if(options.navigation){ 21077 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 21078 if(name){ 21079 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 21080 }else{ 21081 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 21082 } 21083 } 21084 } 21085 21086 /** 21087 * Activating the website main menu elements according to the given slide name. 21088 */ 21089 function activateMenuElement(name){ 21090 if(options.menu){ 21091 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 21092 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 21093 } 21094 } 21095 21096 /** 21097 * Sets to active the current menu and vertical nav items. 21098 */ 21099 function activateMenuAndNav(anchor, index){ 21100 activateMenuElement(anchor); 21101 activateNavDots(anchor, index); 21102 } 21103 21104 /** 21105 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 21106 * from the current section. 21107 */ 21108 function getYmovement(destiny){ 21109 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 21110 var toIndex = destiny.index(SECTION_SEL); 21111 if( fromIndex == toIndex){ 21112 return 'none'; 21113 } 21114 if(fromIndex > toIndex){ 21115 return 'up'; 21116 } 21117 return 'down'; 21118 } 21119 21120 /** 21121 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 21122 * from the current slide. 21123 */ 21124 function getXmovement(fromIndex, toIndex){ 21125 if( fromIndex == toIndex){ 21126 return 'none'; 21127 } 21128 if(fromIndex > toIndex){ 21129 return 'left'; 21130 } 21131 return 'right'; 21132 } 21133 21134 /** 21135 * Checks if the element needs scrollbar and if the user wants to apply it. 21136 * If so it creates it. 21137 * 21138 * @param {Object} element jQuery object of the section or slide 21139 */ 21140 function createScrollBar(element){ 21141 //User doesn't want scrollbar here? Sayonara baby! 21142 if(element.hasClass('fp-noscroll')) return; 21143 21144 //needed to make `scrollHeight` work under Opera 12 21145 element.css('overflow', 'hidden'); 21146 21147 var scrollOverflowHandler = options.scrollOverflowHandler; 21148 var wrap = scrollOverflowHandler.wrapContent(); 21149 //in case element is a slide 21150 var section = element.closest(SECTION_SEL); 21151 var scrollable = scrollOverflowHandler.scrollable(element); 21152 var contentHeight; 21153 21154 //if there was scroll, the contentHeight will be the one in the scrollable section 21155 if(scrollable.length){ 21156 contentHeight = scrollOverflowHandler.scrollHeight(element); 21157 }else{ 21158 contentHeight = element.get(0).scrollHeight; 21159 if(options.verticalCentered){ 21160 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 21161 } 21162 } 21163 21164 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 21165 //Uncode addition 21166 scrollHeight -= UNCODE.bodyBorder*2 + UNCODE.adminBarHeight; 21167 21168 //needs scroll? 21169 if ( contentHeight > scrollHeight) { 21170 //did we already have an scrollbar ? Updating it 21171 if(scrollable.length){ 21172 scrollOverflowHandler.update(element, scrollHeight); 21173 } 21174 //creating the scrolling 21175 else{ 21176 if(options.verticalCentered){ 21177 element.find(TABLE_CELL_SEL).wrapInner(wrap); 21178 }else{ 21179 element.wrapInner(wrap); 21180 } 21181 scrollOverflowHandler.create(element, scrollHeight); 21182 } 21183 } 21184 //removing the scrolling when it is not necessary anymore 21185 else{ 21186 scrollOverflowHandler.remove(element); 21187 } 21188 21189 //undo 21190 element.css('overflow', ''); 21191 } 21192 21193 function addTableClass(element){ 21194 //In case we are styling for the 2nd time as in with reponsiveSlides 21195 if(!element.hasClass(TABLE)){ 21196 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 21197 } 21198 } 21199 21200 function getTableHeight(element){ 21201 var sectionHeight = windowsHeight; 21202 21203 if(options.paddingTop || options.paddingBottom){ 21204 var section = element; 21205 if(!section.hasClass(SECTION)){ 21206 section = element.closest(SECTION_SEL); 21207 } 21208 21209 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 21210 sectionHeight = (windowsHeight - paddings); 21211 } 21212 21213 return sectionHeight; 21214 } 21215 21216 /** 21217 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 21218 */ 21219 function transformContainer(translate3d, animated){ 21220 if(animated){ 21221 addAnimation(container); 21222 }else{ 21223 removeAnimation(container); 21224 } 21225 21226 container.css(getTransforms(translate3d)); 21227 21228 //syncronously removing the class after the animation has been applied. 21229 setTimeout(function(){ 21230 container.removeClass(NO_TRANSITION); 21231 },10); 21232 } 21233 21234 /** 21235 * Gets a section by its anchor / index 21236 */ 21237 function getSectionByAnchor(sectionAnchor){ 21238 if(!sectionAnchor) return []; 21239 21240 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 21241 if(!section.length){ 21242 section = $(SECTION_SEL).eq( sectionAnchor -1); 21243 } 21244 21245 return section; 21246 } 21247 21248 /** 21249 * Gets a slide inside a given section by its anchor / index 21250 */ 21251 function getSlideByAnchor(slideAnchor, section){ 21252 var slides = section.find(SLIDES_WRAPPER_SEL); 21253 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 21254
21255 if(!slide.length){ 21256 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 21257 } 21258 21259 return slide; 21260 } 21261 21262 /** 21263 * Scrolls to the given section and slide anchors 21264 */ 21265 function scrollPageAndSlide(destiny, slide){ 21266 var section = getSectionByAnchor(destiny); 21267 21268 //do nothing if there's no section with the given anchor name 21269 if(!section.length) return; 21270 21271 //default slide 21272 if (typeof slide === 'undefined') { 21273 slide = 0; 21274 } 21275 21276 //we need to scroll to the section and then to the slide 21277 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 21278 scrollPage(section, function(){ 21279 scrollSlider(section, slide); 21280 }); 21281 } 21282 //if we were already in the section 21283 else{ 21284 scrollSlider(section, slide); 21285 } 21286 } 21287 21288 /** 21289 * Scrolls the slider to the given slide destination for the given section 21290 */ 21291 function scrollSlider(section, slideAnchor){ 21292 if(typeof slideAnchor !== 'undefined'){ 21293 var slides = section.find(SLIDES_WRAPPER_SEL); 21294 var destiny = getSlideByAnchor(slideAnchor, section); 21295 21296 if(destiny.length){ 21297 landscapeScroll(slides, destiny); 21298 } 21299 } 21300 } 21301 21302 /** 21303 * Creates a landscape navigation bar with dots for horizontal sliders. 21304 */ 21305 function addSlidesNavigation(section, numSlides){ 21306 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 21307 var nav = section.find(SLIDES_NAV_SEL); 21308 21309 //top or bottom 21310 nav.addClass(options.slidesNavPosition); 21311 21312 for(var i=0; i< numSlides; i++){ 21313 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 21314 } 21315 21316 //centering it 21317 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 21318 21319 nav.find('li').first().find('a').addClass(ACTIVE); 21320 } 21321 21322 21323 /** 21324 * Sets the state of the website depending on the active section/slide. 21325 * It changes the URL hash when needed and updates the body class. 21326 */ 21327 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 21328 var sectionHash = ''; 21329 21330 if(options.anchors.length && !options.lockAnchors){ 21331 21332 //isn't it the first slide? 21333 if(slideIndex){ 21334 if(typeof anchorLink !== 'undefined'){ 21335 sectionHash = anchorLink; 21336 } 21337 21338 //slide without anchor link? We take the index instead. 21339 if(typeof slideAnchor === 'undefined'){ 21340 slideAnchor = slideIndex; 21341 } 21342 21343 lastScrolledSlide = slideAnchor; 21344 setUrlHash(sectionHash + '/' + slideAnchor); 21345 21346 //first slide won't have slide anchor, just the section one 21347 }else if(typeof slideIndex !== 'undefined'){ 21348 lastScrolledSlide = slideAnchor; 21349 setUrlHash(anchorLink); 21350 } 21351 21352 //section without slides 21353 else{ 21354 setUrlHash(anchorLink); 21355 } 21356 } 21357 21358 setBodyClass(); 21359 } 21360 21361 /** 21362 * Sets the URL hash. 21363 */ 21364 function setUrlHash(url){ 21365 //Uncode addition 21366 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 21367 return false; 21368 21369 if(options.recordHistory){ 21370 location.hash = url; 21371 }else{ 21372 //Uncode addition 21373 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 21374 // if(isTouchDevice || isTouch){ 21375 // window.history.replaceState(undefined, undefined, '#' + url); 21376 // }else{ 21377 // var baseUrl = window.location.href.split('#')[0]; 21378 // window.location.replace( baseUrl + '#' + url ); 21379 // } 21380 return false;
21381 } 21382 } 21383 21384 /** 21385 * Gets the anchor for the given slide / section. Its index will be used if there's none. 21386 */ 21387 function getAnchor(element){ 21388 var anchor = element.data('anchor'); 21389 var index = element.index(); 21390 21391 //Slide without anchor link? We take the index instead. 21392 if(typeof anchor === 'undefined'){ 21393 anchor = index; 21394 } 21395 21396 return anchor; 21397 } 21398 21399 /** 21400 * Sets a class for the body of the page depending on the active section / slide 21401 */ 21402 function setBodyClass(){ 21403 var section = $(SECTION_ACTIVE_SEL); 21404 var slide = section.find(SLIDE_ACTIVE_SEL); 21405 21406 var sectionAnchor = getAnchor(section); 21407 var slideAnchor = getAnchor(slide); 21408 21409 var text = String(sectionAnchor); 21410 21411 if(slide.length){ 21412 text = text + '-' + slideAnchor; 21413 } 21414 21415 //changing slash for dash to make it a valid CSS style 21416 text = text.replace('/', '-').replace('#',''); 21417 21418 //removing previous anchor classes 21419 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 21420 $body[0].className = $body[0].className.replace(classRe, ''); 21421 21422 //adding the current anchor 21423 $body.addClass(VIEWING_PREFIX + '-' + text); 21424 } 21425 21426 /** 21427 * Checks for translate3d support 21428 * @return boolean 21429 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 21430 */ 21431 function support3d() { 21432 var el = document.createElement('p'), 21433 has3d, 21434 transforms = { 21435 'webkitTransform':'-webkit-transform', 21436 'OTransform':'-o-transform', 21437 'msTransform':'-ms-transform', 21438 'MozTransform':'-moz-transform', 21439 'transform':'transform' 21440 }; 21441 21442 // Add it to the body to get the computed style. 21443 document.body.insertBefore(el, null); 21444 21445 for (var t in transforms) { 21446 if (el.style[t] !== undefined) { 21447 el.style[t] = 'translate3d(1px,1px,1px)'; 21448 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 21449 } 21450 } 21451 21452 document.body.removeChild(el); 21453 21454 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 21455 } 21456 21457 /** 21458 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 21459 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 21460 */ 21461 function removeMouseWheelHandler(){ 21462 if (document.addEventListener) { 21463 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 21464 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 21465 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 21466 } else { 21467 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 21468 } 21469 } 21470 21471 /** 21472 * Adds the auto scrolling action for the mouse wheel and trackpad. 21473 * After this function is called, the mousewheel and trackpad movements will scroll through sections 21474 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 21475 */ 21476 function addMouseWheelHandler(){ 21477 var prefix = ''; 21478 var _addEventListener; 21479 21480 if (window.addEventListener){ 21481 _addEventListener = "addEventListener"; 21482 }else{ 21483 _addEventListener = "attachEvent"; 21484 prefix = 'on'; 21485 } 21486 21487 // detect available wheel event 21488 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 21489 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 21490 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 21491 21492 21493 if(support == 'DOMMouseScroll'){ 21494 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false); 21495 } 21496 21497 //handle MozMousePixelScroll in older Firefox 21498 else{ 21499 document[ _addEventListener ](prefix + support, MouseWheelHandler, false); 21500 } 21501 } 21502 21503 /** 21504 * Binding the mousemove when the mouse's middle button is pressed 21505 */ 21506 function addMiddleWheelHandler(){ 21507 container 21508 .on('mousedown', mouseDownHandler) 21509 .on('mouseup', mouseUpHandler); 21510 } 21511 21512 /** 21513 * Unbinding the mousemove when the mouse's middle button is released 21514 */ 21515 function removeMiddleWheelHandler(){ 21516 container 21517 .off('mousedown', mouseDownHandler) 21518 .off('mouseup', mouseUpHandler); 21519 } 21520 21521 /** 21522 * Adds the possibility to auto scroll through sections on touch devices. 21523 */ 21524 function addTouchHandler(){ 21525 if(isTouchDevice || isTouch){ 21526 if(options.autoScrolling){ 21527 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 21528 } 21529 21530 $(WRAPPER_SEL) 21531 .off(events.touchstart).on(events.touchstart, touchStartHandler) 21532 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 21533 } 21534 } 21535 21536 /** 21537 * Removes the auto scrolling for touch devices. 21538 */ 21539 function removeTouchHandler(){ 21540 if(isTouchDevice || isTouch){ 21541 $(WRAPPER_SEL) 21542 .off(events.touchstart) 21543 .off(events.touchmove); 21544 } 21545 } 21546 21547 /* 21548 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
21549 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 21550 */ 21551 function getMSPointer(){ 21552 var pointer; 21553 21554 //IE >= 11 & rest of browsers 21555 if(window.PointerEvent){ 21556 pointer = { down: 'pointerdown', move: 'pointermove'}; 21557 } 21558 21559 //IE < 11 21560 else{ 21561 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 21562 } 21563 21564 return pointer; 21565 } 21566 21567 /** 21568 * Gets the pageX and pageY properties depending on the browser. 21569 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 21570 */ 21571 function getEventsPage(e){ 21572 var events = []; 21573 21574 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 21575 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 21576 21577 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 21578 if(isTouch && isReallyTouch(e) && options.scrollBar){ 21579 events.y = e.touches[0].pageY; 21580 events.x = e.touches[0].pageX; 21581 } 21582 21583 return events; 21584 } 21585 21586 /** 21587 * Slides silently (with no animation) the active slider to the given slide. 21588 * @param noCallback {bool} true or defined -> no callbacks 21589 */ 21590 function silentLandscapeScroll(activeSlide, noCallbacks){ 21591 setScrollingSpeed (0, 'internal'); 21592 21593 if(typeof noCallbacks !== 'undefined'){ 21594 //preventing firing callbacks afterSlideLoad etc. 21595 isResizing = true; 21596 } 21597 21598 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 21599 21600 if(typeof noCallbacks !== 'undefined'){ 21601 isResizing = false; 21602 } 21603 21604 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 21605 } 21606 21607 /** 21608 * Scrolls silently (with no animation) the page to the given Y position. 21609 */ 21610 function silentScroll(top){ 21611 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 21612 // that's why we round it to 0. 21613 var roundedTop = Math.round(top); 21614 21615 if (options.css3 && options.autoScrolling && !options.scrollBar){ 21616 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 21617 transformContainer(translate3d, false); 21618 } 21619 else if(options.autoScrolling && !options.scrollBar){ 21620 container.css('top', -roundedTop); 21621 } 21622 else{ 21623 $htmlBody.scrollTop(roundedTop); 21624 } 21625 } 21626 21627 /** 21628 * Returns the cross-browser transform string. 21629 */ 21630 function getTransforms(translate3d){ 21631 return { 21632 '-webkit-transform': translate3d, 21633 '-moz-transform': translate3d, 21634 '-ms-transform':translate3d, 21635 'transform': translate3d 21636 }; 21637 } 21638 21639 /** 21640 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 21641 * @type m (mouse) or k (keyboard) 21642 */ 21643 function setIsScrollAllowed(value, direction, type){ 21644 switch (direction){ 21645 case 'up': isScrollAllowed[type].up = value; break; 21646 case 'down': isScrollAllowed[type].down = value; break; 21647 case 'left': isScrollAllowed[type].left = value; break; 21648 case 'right': isScrollAllowed[type].right = value; break; 21649 case 'all': 21650 if(type == 'm'){ 21651 setAllowScrolling(value); 21652 }else{ 21653 setKeyboardScrolling(value); 21654 } 21655 } 21656 } 21657 21658 /* 21659 * Destroys fullpage.js plugin events and optinally its html markup and styles 21660 */ 21661 function destroy(all){ 21662 setAutoScrolling(false, 'internal'); 21663 setAllowScrolling(false); 21664 setKeyboardScrolling(false); 21665 container.addClass(DESTROYED); 21666 21667 clearTimeout(afterSlideLoadsId); 21668 clearTimeout(afterSectionLoadsId); 21669 clearTimeout(resizeId); 21670 clearTimeout(scrollId); 21671 clearTimeout(scrollId2); 21672 21673 $window 21674 .off('scroll', scrollHandler) 21675 .off('hashchange', hashChangeHandler) 21676 .off('resize', resizeHandler); 21677 21678 $document 21679 .off('click touchstart', SECTION_NAV_SEL + ' a') 21680 .off('mouseenter', SECTION_NAV_SEL + ' li') 21681 .off('mouseleave', SECTION_NAV_SEL + ' li') 21682 .off('click touchstart', SLIDES_NAV_LINK_SEL) 21683 .off('mouseover', options.normalScrollElements) 21684 .off('mouseout', options.normalScrollElements); 21685 21686 $(SECTION_SEL) 21687 .off('click touchstart', SLIDES_ARROW_SEL); 21688 21689 clearTimeout(afterSlideLoadsId); 21690 clearTimeout(afterSectionLoadsId); 21691 21692 //lets make a mess! 21693 if(all){ 21694 destroyStructure(); 21695 } 21696 } 21697 21698 /* 21699 * Removes inline styles added by fullpage.js 21700 */ 21701 function destroyStructure(){ 21702 //reseting the `top` or `translate` properties to 0 21703 silentScroll(0); 21704 21705 //loading all the lazy load content 21706 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 21707 setSrc($(this), 'src'); 21708 }); 21709 21710 container.find('img[data-srcset]').each(function(){ 21711 setSrc($(this), 'srcset'); 21712 }); 21713 21714 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 21715 21716 //removing inline styles 21717 $(SECTION_SEL).css( { 21718 'height': '', 21719 'background-color' : '', 21720 'padding': '' 21721 }); 21722 21723 $(SLIDE_SEL).css( { 21724 'width': '' 21725 }); 21726 21727 container.css({ 21728 'height': '', 21729 'position': '',
21730 '-ms-touch-action': '', 21731 'touch-action': '' 21732 }); 21733 21734 $htmlBody.css({ 21735 'overflow': '', 21736 'height': '' 21737 }); 21738 21739 // remove .fp-enabled class 21740 $('html').removeClass(ENABLED); 21741 21742 // remove .fp-responsive class 21743 $body.removeClass(RESPONSIVE); 21744 21745 // remove all of the .fp-viewing- classes 21746 $.each($body.get(0).className.split(/\s+/), function (index, className) { 21747 if (className.indexOf(VIEWING_PREFIX) === 0) { 21748 $body.removeClass(className); 21749 } 21750 }); 21751 21752 //removing added classes 21753 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 21754 options.scrollOverflowHandler.remove($(this)); 21755 $(this).removeClass(TABLE + ' ' + ACTIVE); 21756 }); 21757 21758 removeAnimation(container); 21759 21760 //Unwrapping content 21761 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 21762 //unwrap not being use in case there's no child element inside and its just text 21763 $(this).replaceWith(this.childNodes); 21764 }); 21765 21766 //removing the applied transition from the fullpage wrapper 21767 container.css({ 21768 '-webkit-transition': 'none', 21769 'transition': 'none' 21770 }); 21771 21772 //scrolling the page to the top with no animation 21773 $htmlBody.scrollTop(0); 21774 21775 //removing selectors 21776 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 21777 $.each(usedSelectors, function(index, value){ 21778 $('.' + value).removeClass(value); 21779 }); 21780 } 21781 21782 /* 21783 * Sets the state for a variable with multiple states (original, and temporal) 21784 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 21785 * This function is used to keep track of both states, the original and the temporal one. 21786 * If type is not 'internal', then we assume the user is globally changing the variable. 21787 */ 21788 function setVariableState(variable, value, type){ 21789 options[variable] = value; 21790 if(type !== 'internal'){ 21791 originals[variable] = value; 21792 } 21793 } 21794 21795 /** 21796 * Displays warnings 21797 */ 21798 function displayWarnings(){ 21799 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 21800 //UNCODE.addition 21801 // if($('html').hasClass(ENABLED)){ 21802 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 21803 // return; 21804 // } 21805 21806 // Disable mutually exclusive settings 21807 //UNCODE.addition 21808 // if (options.continuousVertical && 21809 // (options.loopTop || options.loopBottom)) { 21810 // options.continuousVertical = false;
21811 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21812 // } 21813 21814 // if(options.scrollBar && options.scrollOverflow){ 21815 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 21816 // } 21817 21818 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 21819 // options.continuousVertical = false; 21820 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21821 // } 21822 21823 //using extensions? Wrong file! 21824 $.each(extensions, function(index, extension){ 21825 //is the option set to true? 21826 if(options[extension]){ 21827 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 21828 } 21829 }); 21830 21831 //anchors can not have the same value as any element ID or NAME 21832 $.each(options.anchors, function(index, name){ 21833 21834 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 21835 var nameAttr = $document.find('[name]').filter(function() { 21836 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 21837 }); 21838 21839 var idAttr = $document.find('[id]').filter(function() { 21840 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 21841 }); 21842 21843 if(idAttr.length || nameAttr.length ){ 21844 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 21845 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 21846 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 21847 } 21848 }); 21849 } 21850 21851 /** 21852 * Shows a message in the console of the given type. 21853 */ 21854 function showError(type, text){ 21855 console && console[type] && console[type]('fullPage: ' + text); 21856 } 21857 21858 }; //end of $.fn.fullpage 21859 21860 if(typeof IScroll !== 'undefined'){ 21861 /* 21862 * Turns iScroll `mousewheel` option off dynamically 21863 * https://github.com/cubiq/iscroll/issues/1036 21864 */ 21865 IScroll.prototype.wheelOn = function () { 21866 this.wrapper.addEventListener('wheel', this); 21867 this.wrapper.addEventListener('mousewheel', this); 21868 this.wrapper.addEventListener('DOMMouseScroll', this); 21869 }; 21870 21871 /* 21872 * Turns iScroll `mousewheel` option on dynamically 21873 * https://github.com/cubiq/iscroll/issues/1036 21874 */ 21875 IScroll.prototype.wheelOff = function () { 21876 this.wrapper.removeEventListener('wheel', this); 21877 this.wrapper.removeEventListener('mousewheel', this); 21878 this.wrapper.removeEventListener('DOMMouseScroll', this); 21879 }; 21880 } 21881 21882 /** 21883 * An object to handle overflow scrolling. 21884 * This uses jquery.slimScroll to accomplish overflow scrolling. 21885 * It is possible to pass in an alternate scrollOverflowHandler 21886 * to the fullpage.js option that implements the same functions 21887 * as this handler. 21888 * 21889 * @type {Object} 21890 */ 21891 var iscrollHandler = { 21892 refreshId: null, 21893 iScrollInstances: [], 21894 21895 // Enables or disables the mouse wheel for the active section or all slides in it 21896 toggleWheel: function(value){ 21897 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 21898 scrollable.each(function(){ 21899 var iScrollInstance = $(this).data('iscrollInstance'); 21900 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 21901 if(value){ 21902 iScrollInstance.wheelOn(); 21903 } 21904 else{ 21905 iScrollInstance.wheelOff(); 21906 } 21907 } 21908 }); 21909 }, 21910 21911 /** 21912 * Turns off iScroll for the destination section. 21913 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
21914 * scroll the destination section/slide before the sections animations ends. 21915 */ 21916 onLeave: function(){ 21917 iscrollHandler.toggleWheel(false); 21918 }, 21919 21920 // Turns off iScroll for the leaving section 21921 beforeLeave: function(){ 21922 iscrollHandler.onLeave() 21923 }, 21924 21925 // Turns on iScroll on section load 21926 afterLoad: function(){ 21927 iscrollHandler.toggleWheel(true); 21928 }, 21929 21930 /** 21931 * Called when overflow scrolling is needed for a section. 21932 * 21933 * @param {Object} element jQuery object containing current section 21934 * @param {Number} scrollHeight Current window height in pixels 21935 */ 21936 create: function(element, scrollHeight) { 21937 var scrollable = element.find(SCROLLABLE_SEL); 21938 21939 scrollable.height(scrollHeight); 21940 scrollable.each(function() { 21941 var $this = $(this); 21942 var iScrollInstance = $this.data('iscrollInstance'); 21943 if (iScrollInstance) { 21944 $.each(iscrollHandler.iScrollInstances, function(){ 21945 $(this).destroy(); 21946 }); 21947 } 21948 21949 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 21950 iscrollHandler.iScrollInstances.push(iScrollInstance); 21951 21952 //off by default until the section gets active 21953 iScrollInstance.wheelOff(); 21954 21955 $this.data('iscrollInstance', iScrollInstance); 21956 }); 21957 }, 21958 21959 /** 21960 * Return a boolean depending on whether the scrollable element is a 21961 * the end or at the start of the scrolling depending on the given type. 21962 * 21963 * @param {String} type Either 'top' or 'bottom' 21964 * @param {Object} scrollable jQuery object for the scrollable element 21965 * @return {Boolean} 21966 */ 21967 isScrolled: function(type, scrollable) { 21968 var scroller = scrollable.data('iscrollInstance'); 21969 21970 //no scroller? 21971 if (!scroller) { 21972 return true; 21973 } 21974 21975 if (type === 'top') { 21976 return scroller.y >= 0 && !scrollable.scrollTop(); 21977 } else if (type === 'bottom') { 21978 return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight; 21979 } 21980 }, 21981 21982 /** 21983 * Returns the scrollable element for the given section. 21984 * If there are landscape slides, will only return a scrollable element 21985 * if it is in the active slide. 21986 * 21987 * @param {Object} activeSection jQuery object containing current section 21988 * @return {Boolean} 21989 */ 21990 scrollable: function(activeSection){ 21991 // if there are landscape slides, we check if the scrolling bar is in the current one or not 21992 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 21993 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 21994 } 21995 return activeSection.find(SCROLLABLE_SEL); 21996 }, 21997 21998 /** 21999 * Returns the scroll height of the wrapped content. 22000 * If this is larger than the window height minus section padding, 22001 * overflow scrolling is needed. 22002 * 22003 * @param {Object} element jQuery object containing current section 22004 * @return {Number} 22005 */ 22006 scrollHeight: function(element) { 22007 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 22008 }, 22009 22010 /** 22011 * Called when overflow scrolling is no longer needed for a section. 22012 * 22013 * @param {Object} element jQuery object containing current section 22014 */ 22015 remove: function(element) { 22016 var scrollable = element.find(SCROLLABLE_SEL); 22017 if (scrollable.length) { 22018 var iScrollInstance = scrollable.data('iscrollInstance'); 22019 iScrollInstance.destroy(); 22020 22021 scrollable.data('iscrollInstance', null); 22022 } 22023 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 22024 }, 22025 22026 /** 22027 * Called when overflow scrolling has already been setup but the 22028 * window height has potentially changed. 22029 * 22030 * @param {Object}
vendor: 16,384 bytes, lines 22030-22577
22030 element jQuery object containing current section 22031 * @param {Number} scrollHeight Current window height in pixels 22032 */ 22033 update: function(element, scrollHeight) { 22034 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 22035 //short period of time. 22036 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 22037 clearTimeout(iscrollHandler.refreshId); 22038 iscrollHandler.refreshId = setTimeout(function(){ 22039 $.each(iscrollHandler.iScrollInstances, function(){ 22040 $(this).get(0).refresh(); 22041 }); 22042 }, 150); 22043 22044 //updating the wrappers height 22045 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 22046 }, 22047 22048 /** 22049 * Called to get any additional elements needed to wrap the section 22050 * content in order to facilitate overflow scrolling. 22051 * 22052 * @return {String|Object} Can be a string containing HTML, 22053 * a DOM element, or jQuery object. 22054 */ 22055 wrapContent: function() { 22056 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 22057 } 22058 }; 22059}); 22060 22061 22062 22063/* ======================================================================== 22064 * Bootstrap: collapse.js v3.1.1 22065 * http://getbootstrap.com/javascript/#collapse 22066 * ======================================================================== 22067 * Copyright 2011-2014 Twitter, Inc. 22068 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22069 * ======================================================================== */ 22070 22071 22072+function ($) { 22073 'use strict'; 22074 22075 // COLLAPSE PUBLIC CLASS DEFINITION 22076 // ================================ 22077 22078 var Collapse = function (element, options) { 22079 this.$element = $(element) 22080 this.options = $.extend({}, Collapse.DEFAULTS, options) 22081 this.transitioning = null 22082 22083 if (this.options.parent) this.$parent = $(this.options.parent) 22084 if (this.options.toggle) this.toggle() 22085 } 22086 22087 Collapse.DEFAULTS = { 22088 toggle: true 22089 } 22090 22091 Collapse.prototype.dimension = function () { 22092 var hasWidth = this.$element.hasClass('width') 22093 return hasWidth ? 'width' : 'height' 22094 } 22095 22096 Collapse.prototype.show = function () { 22097 if (this.transitioning || this.$element.hasClass('in')) return 22098 22099 var startEvent = $.Event('show.bs.collapse') 22100 this.$element.trigger(startEvent) 22101 if (startEvent.isDefaultPrevented()) return 22102 22103 var actives = this.$parent && this.$parent.find('> .panel > .in') 22104 22105 if (actives && actives.length) { 22106 var hasData = actives.data('bs.collapse') 22107 if (hasData && hasData.transitioning) return 22108 actives.collapse('hide') 22109 hasData || actives.data('bs.collapse', null) 22110 } 22111 22112 var dimension = this.dimension() 22113 22114 this.$element 22115 .removeClass('collapse') 22116 .addClass('collapsing')[dimension](0) 22117 22118 this.transitioning = 1 22119 22120 var complete = function (e) { 22121 if (e && e.target != this.$element[0]) return 22122 this.$element 22123 .removeClass('collapsing') 22124 .addClass('collapse in')[dimension]('auto') 22125 this.transitioning = 0 22126 this.$element.trigger('shown.bs.collapse') 22127 } 22128 22129 if (!$.support.transition) return complete.call(this) 22130 22131 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 22132 22133 this.$element 22134 .one($.support.transition.end, $.proxy(complete, this)) 22135 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 22136 } 22137 22138 Collapse.prototype.hide = function () { 22139 if (this.transitioning || !this.$element.hasClass('in')) return 22140 22141 var startEvent = $.Event('hide.bs.collapse') 22142 this.$element.trigger(startEvent) 22143 if (startEvent.isDefaultPrevented()) return 22144 22145 var dimension = this.dimension() 22146 22147 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 22148 22149 this.$element 22150 .addClass('collapsing') 22151 .removeClass('collapse') 22152 .removeClass('in') 22153 22154 this.transitioning = 1 22155 22156 var complete = function (e) { 22157 if (e && e.target != this.$element[0]) return 22158 this.transitioning = 0 22159 this.$element 22160 .trigger('hidden.bs.collapse') 22161 .removeClass('collapsing') 22162 .addClass('collapse') 22163 } 22164 22165 if (!$.support.transition) return complete.call(this) 22166 22167 this.$element 22168 [dimension](0) 22169 .one($.support.transition.end, $.proxy(complete, this)) 22170 .emulateTransitionEnd(350) 22171 } 22172 22173 Collapse.prototype.toggle = function () { 22174 this[this.$element.hasClass('in') ? 'hide' : 'show']() 22175 } 22176 22177 22178 // COLLAPSE PLUGIN DEFINITION 22179 // ========================== 22180 22181 var old = $.fn.collapse 22182 22183 $.fn.collapse = function (option) { 22184 return this.each(function () { 22185 var $this = $(this) 22186 var data = $this.data('bs.collapse') 22187 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 22188 22189 if (!data && options.toggle && option == 'show') option = !option 22190 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 22191 if (typeof option == 'string') data[option]() 22192 }) 22193 } 22194 22195 $.fn.collapse.Constructor = Collapse 22196 22197 22198 // COLLAPSE NO CONFLICT 22199 // ==================== 22200 22201 $.fn.collapse.noConflict = function () { 22202 $.fn.collapse = old 22203 return this 22204 } 22205 22206 22207 // COLLAPSE DATA-API 22208 // ================= 22209 22210 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 22211 var $this = $(this), href 22212 var target = $this.attr('data-target') 22213 || e.preventDefault() 22214 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 22215 //Edited by Uncode to replace ID in panel [START] 22216 var _target = href.replace(/^#/, ""); 22217 if ( $('[data-id="' + _target + '"]').length ) { 22218 var $target = $('[data-id="' + _target + '"]') 22219 } else { 22220 var $target = $(target) 22221 } 22222 //Edited by Uncode to replace ID in panel [END] 22223 var data = $target.data('bs.collapse') 22224 var option = data ? 'toggle' : $this.data() 22225 var parent = $this.attr('data-parent') 22226 var $parent = parent && $(parent) 22227 22228 if (!data || !data.transitioning) { 22229 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 22230 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 22231 } 22232 22233 $target.collapse(option) 22234 }) 22235 22236}(jQuery); 22237 22238 22239/* ======================================================================== 22240 * Bootstrap: tab.js v3.1.1 22241 * http://getbootstrap.com/javascript/#tabs 22242 * ======================================================================== 22243 * Copyright 2011-2014 Twitter, Inc. 22244 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22245 * ======================================================================== */ 22246 22247 22248+function ($) { 22249 'use strict'; 22250 22251 // TAB CLASS DEFINITION 22252 // ==================== 22253 22254 var Tab = function (element) { 22255 this.element = $(element) 22256 } 22257 22258 Tab.prototype.show = function () { 22259 var $this = this.element 22260 var $ul = $this.closest('ul:not(.dropdown-menu)') 22261 var selector = $this.data('target') 22262 22263 if (!selector) { 22264 selector = $this.attr('href') 22265 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 22266 } 22267 22268 if ($this.parent('li').hasClass('active')) return 22269 22270 var previous = $ul.find('.active:last a')[0] 22271 var e = $.Event('show.bs.tab', { 22272 relatedTarget: previous 22273 }) 22274 22275 $this.trigger(e) 22276 22277 if (e.isDefaultPrevented()) return 22278 22279 //Edited by Uncode to replace ID in panel [START] 22280 var _target = selector.replace(/^#/, ""); 22281 if ( $('[data-id="' + _target + '"]').length ) 22282 var $target = $('[data-id="' + _target + '"]') 22283 else 22284 var $target = $(selector) 22285 //Edited by Uncode to replace ID in panel [END] 22286 22287 this.activate($this.parent('li'), $ul) 22288 this.activate($target, $target.parent(), function () { 22289 $this.trigger({ 22290 type: 'shown.bs.tab', 22291 relatedTarget: previous 22292 }) 22293 }) 22294 } 22295 22296 Tab.prototype.activate = function (element, container, callback) { 22297 var $active = container.find('> .active') 22298 var transition = callback 22299 && $.support.transition 22300 && $active.hasClass('fade') 22301 22302 function next() { 22303 $active 22304 .removeClass('active') 22305 .find('> .dropdown-menu > .active') 22306 .removeClass('active') 22307 22308 element.addClass('active') 22309 22310 if (transition) { 22311 element[0].offsetWidth // reflow for transition 22312 element.addClass('in') 22313 } else { 22314 element.removeClass('fade') 22315 } 22316 22317 if (element.parent('.dropdown-menu')) { 22318 element.closest('li.dropdown').addClass('active') 22319 } 22320 22321 callback && callback() 22322 } 22323 22324 transition ? 22325 $active 22326 .one($.support.transition.end, next) 22327 .emulateTransitionEnd(150) : 22328 next() 22329 22330 $active.removeClass('in') 22331 } 22332 22333 22334 // TAB PLUGIN DEFINITION 22335 // ===================== 22336 22337 var old = $.fn.tab 22338 22339 $.fn.tab = function ( option ) { 22340 return this.each(function () { 22341 var $this = $(this) 22342 var data = $this.data('bs.tab') 22343 22344 if (!data) $this.data('bs.tab', (data = new Tab(this))) 22345 if (typeof option == 'string') data[option]() 22346 }) 22347 } 22348 22349 $.fn.tab.Constructor = Tab 22350 22351 22352 // TAB NO CONFLICT 22353 // =============== 22354 22355 $.fn.tab.noConflict = function () { 22356 $.fn.tab = old 22357 return this 22358 } 22359 22360 22361 // TAB DATA-API 22362 // ============ 22363 22364 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 22365 e.preventDefault() 22366 $(this).tab('show') 22367 }) 22368 22369}(jQuery); 22370 22371 22372/* ======================================================================== 22373 * Bootstrap: tooltip.js v3.1.1 22374 * http://getbootstrap.com/javascript/#tooltip 22375 * Inspired by the original jQuery.tipsy by Jason Frame 22376 * ======================================================================== 22377 * Copyright 2011-2014 Twitter, Inc. 22378 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22379 * ======================================================================== */ 22380 22381 22382+function ($) { 22383 'use strict'; 22384 22385 // TOOLTIP PUBLIC CLASS DEFINITION 22386 // =============================== 22387 22388 var Tooltip = function (element, options) { 22389 this.type = 22390 this.options = 22391 this.enabled = 22392 this.timeout = 22393 this.hoverState = 22394 this.$element = null 22395 22396 this.init('tooltip', element, options) 22397 } 22398 22399 Tooltip.DEFAULTS = { 22400 animation: true, 22401 placement: 'top', 22402 selector: false, 22403 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 22404 trigger: 'hover focus', 22405 title: '', 22406 delay: 0, 22407 html: false, 22408 container: false, 22409 viewport: { 22410 selector: 'body', 22411 padding: 0 22412 } 22413 } 22414 22415 Tooltip.prototype.init = function (type, element, options) { 22416 this.enabled = true 22417 this.type = type 22418 this.$element = $(element) 22419 this.options = this.getOptions(options) 22420 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 22421 22422 var triggers = this.options.trigger.split(' ') 22423 22424 for (var i = triggers.length; i--;) { 22425 var trigger = triggers[i] 22426 22427 if (trigger == 'click') { 22428 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 22429 } else if (trigger != 'manual') { 22430 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 22431 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 22432 22433 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 22434 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 22435 } 22436 } 22437 22438 this.options.selector ? 22439 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 22440 this.fixTitle() 22441 } 22442 22443 Tooltip.prototype.getDefaults = function () { 22444 return Tooltip.DEFAULTS 22445 } 22446 22447 Tooltip.prototype.getOptions = function (options) { 22448 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 22449 22450 if (options.delay && typeof options.delay == 'number') { 22451 options.delay = { 22452 show: options.delay, 22453 hide: options.delay 22454 } 22455 } 22456 22457 return options 22458 } 22459 22460 Tooltip.prototype.getDelegateOptions = function () { 22461 var options = {} 22462 var defaults = this.getDefaults() 22463 22464 this._options && $.each(this._options, function (key, value) { 22465 if (defaults[key] != value) options[key] = value 22466 }) 22467 22468 return options 22469 } 22470 22471 Tooltip.prototype.enter = function (obj) { 22472 var self = obj instanceof this.constructor ? 22473 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22474 22475 clearTimeout(self.timeout) 22476 22477 self.hoverState = 'in' 22478 22479 if (!self.options.delay || !self.options.delay.show) return self.show() 22480 22481 self.timeout = setTimeout(function () { 22482 if (self.hoverState == 'in') self.show() 22483 }, self.options.delay.show) 22484 } 22485 22486 Tooltip.prototype.leave = function (obj) { 22487 var self = obj instanceof this.constructor ? 22488 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22489 22490 clearTimeout(self.timeout) 22491 22492 self.hoverState = 'out' 22493 22494 if (!self.options.delay || !self.options.delay.hide) return self.hide() 22495 22496 self.timeout = setTimeout(function () { 22497 if (self.hoverState == 'out') self.hide() 22498 }, self.options.delay.hide) 22499 } 22500 22501 Tooltip.prototype.show = function () { 22502 var e = $.Event('show.bs.' + this.type) 22503 22504 if (this.hasContent() && this.enabled) { 22505 this.$element.trigger(e) 22506 22507 if (e.isDefaultPrevented()) return 22508 var that = this; 22509 22510 var $tip = this.tip() 22511 22512 this.setContent() 22513 22514 if (this.options.animation) $tip.addClass('fade') 22515 22516 var placement = typeof this.options.placement == 'function' ? 22517 this.options.placement.call(this, $tip[0], this.$element[0]) : 22518 this.options.placement 22519 22520 var autoToken = /\s?auto?\s?/i 22521 var autoPlace = autoToken.test(placement) 22522 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 22523 22524 $tip 22525 .detach() 22526 .css({ top: 0, left: 0, display: 'block' }) 22527 .addClass(placement) 22528 22529 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 22530 22531 var pos = this.getPosition() 22532 var actualWidth = $tip[0].offsetWidth 22533 var actualHeight = $tip[0].offsetHeight 22534 22535 if (autoPlace) { 22536 var orgPlacement = placement 22537 var $parent = this.$element.parent() 22538 var parentDim = this.getPosition($parent) 22539 22540 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 22541 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 22542 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 22543 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 22544 placement 22545 22546 $tip 22547 .removeClass(orgPlacement) 22548 .addClass(placement) 22549 } 22550 22551 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 22552 22553 this.applyPlacement(calculatedOffset, placement) 22554 this.hoverState = null 22555 22556 var complete = function() { 22557 that.$element.trigger('shown.bs.' + that.type) 22558 } 22559 22560 $.support.transition && this.$tip.hasClass('fade') ? 22561 $tip 22562 .one($.support.transition.end, complete) 22563 .emulateTransitionEnd(150) : 22564 complete() 22565 } 22566 } 22567 22568 Tooltip.prototype.applyPlacement = function (offset, placement) { 22569 var $tip = this.tip() 22570 var width = $tip[0].offsetWidth 22571 var height = $tip[0].offsetHeight 22572 22573 // manually read margins because getBoundingClientRect includes difference 22574 var marginTop = parseInt($tip.css('margin-top'), 10) 22575 var marginLeft = parseInt($tip.css('margin-left'), 10) 22576 22577 // we must check for NaN for i
22577e 8/9 22578 if (isNaN(marginTop)) marginTop = 0 22579 if (isNaN(marginLeft)) marginLeft = 0 22580 22581 offset.top = offset.top + marginTop 22582 offset.left = offset.left + marginLeft 22583 22584 // $.fn.offset doesn't round pixel values 22585 // so we use setOffset directly with our own function B-0 22586 $.offset.setOffset($tip[0], $.extend({ 22587 using: function (props) { 22588 $tip.css({ 22589 top: Math.round(props.top), 22590 left: Math.round(props.left) 22591 }) 22592 } 22593 }, offset), 0) 22594 22595 $tip.addClass('in') 22596 22597 // check to see if placing tip in new offset caused the tip to resize itself 22598 var actualWidth = $tip[0].offsetWidth 22599 var actualHeight = $tip[0].offsetHeight 22600 22601 if (placement == 'top' && actualHeight != height) { 22602 offset.top = offset.top + height - actualHeight 22603 } 22604 22605 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 22606 22607 if (delta.left) offset.left += delta.left 22608 else offset.top += delta.top 22609 22610 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 22611 var arrowPosition = delta.left ? 'left' : 'top' 22612 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 22613 22614 $tip.offset(offset) 22615 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 22616 } 22617 22618 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 22619 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 22620 } 22621 22622 Tooltip.prototype.setContent = function () { 22623 var $tip = this.tip() 22624 var title = this.getTitle() 22625 22626 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 22627 $tip.removeClass('fade in top bottom left right') 22628 } 22629 22630 Tooltip.prototype.hide = function () { 22631 var that = this 22632 var $tip = this.tip() 22633 var e = $.Event('hide.bs.' + this.type) 22634 22635 function complete() { 22636 if (that.hoverState != 'in') $tip.detach() 22637 that.$element.trigger('hidden.bs.' + that.type) 22638 } 22639 22640 this.$element.trigger(e) 22641 22642 if (e.isDefaultPrevented()) return 22643 22644 $tip.removeClass('in') 22645 22646 $.support.transition && this.$tip.hasClass('fade') ? 22647 $tip 22648 .one($.support.transition.end, complete) 22649 .emulateTransitionEnd(150) : 22650 complete() 22651 22652 this.hoverState = null 22653 22654 return this 22655 } 22656 22657 Tooltip.prototype.fixTitle = function () { 22658 var $e = this.$element 22659 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 22660 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 22661 } 22662 } 22663 22664 Tooltip.prototype.hasContent = function () { 22665 return this.getTitle() 22666 } 22667 22668 Tooltip.prototype.getPosition = function ($element) { 22669 $element = $element || this.$element 22670 var el = $element[0] 22671 var isBody = el.tagName == 'BODY' 22672 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 22673 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 22674 width: isBody ? $(window).width() : $element.outerWidth(), 22675 height: isBody ? $(window).height() : $element.outerHeight() 22676 }, isBody ? {top: 0, left: 0} : $element.offset()) 22677 } 22678 22679 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 22680 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22681 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22682 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 22683 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 22684 22685 } 22686 22687 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 22688 var delta = { top: 0, left: 0 } 22689 if (!this.$viewport) return delta 22690 22691 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 22692 var viewportDimensions = this.getPosition(this.$viewport) 22693 22694 if (/right|left/.test(placement)) { 22695 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 22696 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 22697 if (topEdgeOffset < viewportDimensions.top) { // top overflow 22698 delta.top = viewportDimensions.top - topEdgeOffset 22699 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 22700 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
22700EdgeOffset 22701 } 22702 } else { 22703 var leftEdgeOffset = pos.left - viewportPadding 22704 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 22705 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 22706 delta.left = viewportDimensions.left - leftEdgeOffset 22707 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 22708 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 22709 } 22710 } 22711 22712 return delta 22713 } 22714 22715 Tooltip.prototype.getTitle = function () { 22716 var title 22717 var $e = this.$element 22718 var o = this.options 22719 22720 title = $e.attr('data-original-title') 22721 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 22722 22723 return title 22724 } 22725 22726 Tooltip.prototype.tip = function () { 22727 return this.$tip = this.$tip || $(this.options.template) 22728 } 22729 22730 Tooltip.prototype.arrow = function () { 22731 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 22732 } 22733 22734 Tooltip.prototype.validate = function () { 22735 if (!this.$element[0].parentNode) { 22736 this.hide() 22737 this.$element = null 22738 this.options = null 22739 } 22740 } 22741 22742 Tooltip.prototype.enable = function () { 22743 this.enabled = true 22744 } 22745 22746 Tooltip.prototype.disable = function () { 22747 this.enabled = false 22748 } 22749 22750 Tooltip.prototype.toggleEnabled = function () { 22751 this.enabled = !this.enabled 22752 } 22753 22754 Tooltip.prototype.toggle = function (e) { 22755 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 22756 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 22757 } 22758 22759 Tooltip.prototype.destroy = function () { 22760 clearTimeout(this.timeout) 22761 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 22762 } 22763 22764 22765 // TOOLTIP PLUGIN DEFINITION 22766 // ========================= 22767 22768 var old = $.fn.tooltip 22769 22770 $.fn.tooltip = function (option) { 22771 return this.each(function () { 22772 var $this = $(this) 22773 var data = $this.data('bs.tooltip') 22774 var options = typeof option == 'object' && option 22775 22776 if (!data && option == 'destroy') return 22777 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 22778 if (typeof option == 'string') data[option]() 22779 }) 22780 } 22781 22782 $.fn.tooltip.Constructor = Tooltip 22783 22784 22785 // TOOLTIP NO CONFLICT 22786 // =================== 22787 22788 $.fn.tooltip.noConflict = function () { 22789 $.fn.tooltip = old 22790 return this 22791 } 22792 22793}(jQuery); 22794 22795 22796/* ======================================================================== 22797 * Bootstrap: transition.js v3.1.1 22798 * http://getbootstrap.com/javascript/#transitions 22799 * ======================================================================== 22800 * Copyright 2011-2014 Twitter, Inc. 22801 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22802 * ======================================================================== */ 22803 22804 22805+function ($) { 22806 'use strict'; 22807 22808 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 22809 // ============================================================ 22810 22811 function transitionEnd() { 22812 var el = document.createElement('bootstrap') 22813 22814 var transEndEventNames = { 22815 WebkitTransition : 'webkitTransitionEnd', 22816 MozTransition : 'transitionend', 22817 OTransition : 'oTransitionEnd otransitionend', 22818 transition : 'transitionend' 22819 } 22820 22821 for (var name in transEndEventNames) { 22822 if (el.style[name] !== undefined) { 22823 return { end: transEndEventNames[name] } 22824 } 22825 } 22826 22827 return false // explicit for ie8 ( ._.) 22828 } 22829 22830 // http://blog.alexmaccaw.com/css-transitions 22831 $.fn.emulateTransitionEnd = function (duration) { 22832 var called = false, $el = this 22833 $(this).one($.support.transition.end, function () { called = true }) 22834 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 22835 setTimeout(callback, duration) 22836 return this 22837 } 22838 22839 $(function () { 22840 $.support.transition = transitionEnd() 22841 }) 22842 22843}(jQuery); 22844 22845
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.