1/* ---------------------------------------------------------- 2 * Plugins 3 * ---------------------------------------------------------- */ 4 5(function(window, $) { 6 'use strict'; 7 var counter = 0, 8 $headCache = $('head'), 9 oldBigText = window.BigText, 10 oldjQueryMethod = $.fn.bigtext, 11 BigText = { 12 DEBUG_MODE: false, 13 DEFAULT_MIN_FONT_SIZE_PX: null, 14 DEFAULT_MAX_FONT_SIZE_PX: 528, 15 GLOBAL_STYLE_ID: 'bigtext-style', 16 STYLE_ID: 'bigtext-id', 17 LINE_CLASS_PREFIX: 'bigtext-line', 18 EXEMPT_CLASS: 'bigtext-exempt', 19 noConflict: function(restore) 20 { 21 if(restore) { 22 $.fn.bigtext = oldjQueryMethod; 23 window.BigText = oldBigText; 24 } 25 return BigText; 26 }, 27 supports: { 28 wholeNumberFontSizeOnly: (function() { 29 if( !( 'getComputedStyle' in window ) ) { 30 return true; 31 } 32 var test = $('<div/>').css({ 33 position: 'absolute', 34 'font-size': '14.1px' 35 }).insertBefore( $('script').eq(0) ), 36 computedStyle = window.getComputedStyle( test[0], null ); 37 38 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 39 test.remove(); 40 return ret; 41 })() 42 }, 43 init: function() { 44 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 45 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 46 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 47 } 48 }, 49 bindResize: function(eventName, resizeFunction) { 50 var timeoutId; 51 $(window).unbind(eventName).bind(eventName, function() { 52 if( timeoutId ) { 53 clearTimeout( timeoutId ); 54 } 55 timeoutId = setTimeout( resizeFunction, 300 ); 56 }); 57 }, 58 getStyleId: function(id) 59 { 60 return BigText.STYLE_ID + '-' + id; 61 }, 62 generateStyleTag: function(id, css) 63 { 64 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 65 }, 66 clearCss: function(id) 67 { 68 var styleId = BigText.getStyleId(id); 69 $('#' + styleId).remove(); 70 }, 71 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 72 { 73 var css = []; 74 75 BigText.clearCss(id); 76 77 for(var j=0, k=linesFontSizes.length; j<k; j++) { 78 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 79 (minFontSizes[j] ? ' white-space: normal;' : '') + 80 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 81 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 82 '}'); 83 } 84 85 return BigText.generateStyleTag(BigText.getStyleId(id), css); 86 }, 87 jQueryMethod: function(options) 88 { 89 BigText.init(); 90 91 options = $.extend({ 92 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 93 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 94 childSelector: '', 95 resize: true 96 }, options || {}); 97 98 this.each(function() 99 { 100 var $t = $(this).addClass('bigtext'), 101 maxWidth = $t.width(), 102 id = $t.attr('id'), 103 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 104 105 if(!id) { 106 id = 'bigtext-id' + (counter++); 107 $t.attr('id', id); 108 } 109 110 if(options.resize) { 111 BigText.bindResize('resize.bigtext-event-' + id, function() 112 { 113 // TODO only call this if the width has changed. 114 BigText.jQueryMethod.call($('#' + id), options); 115 }); 116 } 117 118 BigText.clearCss(id); 119 120 $children.addClass(function(lineNumber, className) 121 { 122 // remove existing line classes. 123 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 124 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 125 }); 126 127 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 128 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 129 }); 130 131 return this.trigger('bigtext:complete'); 132 } 133 }; 134 135 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 136 { 137 var width; 138 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 139 $line.css(property, size + units); 140 141 width = $line.width(); 142 143 if(width >= maxWidth) { 144 145 $line.css(property, ''); 146 147 if(width === maxWidth) { 148 return { 149 match: 'exact', 150 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 151 }; 152 } 153 154 // Since this is an estimate, we calculate how far over the width we went with the new value. 155 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 156 // Otherwise, we revert to the underestimate. 157 var under = maxWidth - previousWidth, 158 over = width - maxWidth; 159 160 return { 161 match: 'estimate', 162 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 163 }; 164 } 165 166 return width; 167 } 168 169 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 170 { 171 var $c = $t.clone(true) 172 .addClass('bigtext-cloned') 173 .css({ 174 fontFamily: $t.css('font-family'), 175 textTransform: $t.css('text-transform'), 176 wordSpacing: $t.css('word-spacing'), 177 letterSpacing: $t.css('letter-spacing'), 178 position: 'absolute', 179 left: BigText.DEBUG_MODE ? 0 : -9999, 180 top: BigText.DEBUG_MODE ? 0 : -9999
181 }) 182 .appendTo(document.body); 183 184 // font-size isn't the only thing we can modify, we can also mess with: 185 // word-spacing and letter-spacing. WebKit does not respect subpixel 186 // letter-spacing, word-spacing, or font-size. 187 // TODO try -webkit-transform: scale() as a workaround. 188 var fontSizes = [], 189 wordSpacings = [], 190 minFontSizes = [], 191 ratios = []; 192 193 $children.css('float', 'left').each(function() { 194 var $line = $(this), 195 // TODO replace 8, 4 with a proportional size to the calculated font-size. 196 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 197 lineMax, 198 newFontSize; 199 200 if($line.hasClass(BigText.EXEMPT_CLASS)) { 201 fontSizes.push(null); 202 ratios.push(null); 203 minFontSizes.push(false); 204 return; 205 } 206 207 // TODO we can cache this ratio? 208 var autoGuessSubtraction = 32, // font size in px 209 currentFontSize = parseFloat($line.css('font-size')), 210 ratio = ( $line.width() / currentFontSize ).toFixed(6); 211 212 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 213 214 outer: for(var m=0, n=intervals.length; m<n; m++) { 215 inner: for(var j=1, k=10; j<=k; j++) { 216 if(newFontSize + j*intervals[m] > maxFontSize) { 217 newFontSize = maxFontSize; 218 break outer; 219 } 220 221 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 222 if(typeof lineMax !== 'number') { 223 newFontSize = lineMax.size; 224 225 if(lineMax.match === 'exact') { 226 break outer; 227 } 228 break inner; 229 } 230 } 231 } 232 233 ratios.push(maxWidth / newFontSize); 234 235 if(newFontSize > maxFontSize) { 236 fontSizes.push(maxFontSize); 237 minFontSizes.push(false); 238 } else if(!!minFontSize && newFontSize < minFontSize) { 239 fontSizes.push(minFontSize); 240 minFontSizes.push(true); 241 } else { 242 fontSizes.push(newFontSize); 243 minFontSizes.push(false); 244 } 245 }).each(function(lineNumber) { 246 var $line = $(this), 247 wordSpacing = 0, 248 interval = 1, 249 maxWordSpacing; 250 251 if($line.hasClass(BigText.EXEMPT_CLASS)) { 252 wordSpacings.push(null); 253 return; 254 } 255 256 // must re-use font-size, even though it was removed above. 257 $line.css('font-size', fontSizes[lineNumber] + 'px'); 258 259 for(var m=1, n=3; m<n; m+=interval) { 260 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 261 if(typeof maxWordSpacing !== 'number') { 262 wordSpacing = maxWordSpacing.size; 263 break; 264 } 265 } 266 267 $line.css('font-size', ''); 268 wordSpacings.push(wordSpacing); 269 }).removeAttr('style'); 270 271 if( !BigText.DEBUG_MODE ) { 272 $c.remove(); 273 } else { 274 $c.css({ 275 'background-color': 'rgba(255,255,255,.4)' 276 }); 277 } 278 279 return { 280 fontSizes: fontSizes, 281 wordSpacings: wordSpacings, 282 ratios: ratios, 283 minFontSizes: minFontSizes 284 }; 285 } 286 287 $.fn.bigtext = BigText.jQueryMethod; 288 window.BigText = BigText; 289 290})(this, jQuery); 291 292/*! 293 * Isotope PACKAGED v2.2.2 294 * 295 * Licensed GPLv3 for open source use 296 * or Isotope Commercial License for commercial use 297 * 298 * http://isotope.metafizzy.co 299 * Copyright 2015 Metafizzy 300 */ 301 302/** 303 * Bridget makes jQuery widgets 304 * v1.1.0 305 * MIT license 306 */ 307 308( function( window ) { 309 310 311 312// -------------------------- utils -------------------------- // 313 314var slice = Array.prototype.slice; 315 316function noop() {} 317 318// -------------------------- definition -------------------------- // 319 320function defineBridget( $ ) { 321 322// bail if no jQuery 323if ( !$ ) { 324 return; 325} 326 327// -------------------------- addOptionMethod -------------------------- // 328 329/** 330 * adds option method -> $().plugin('option', {...}) 331 * @param {Function} PluginClass - constructor class 332 */ 333function addOptionMethod( PluginClass ) { 334 // don't overwrite original option method 335 if ( PluginClass.prototype.option ) { 336 return; 337 } 338 339 // option setter 340 PluginClass.prototype.option = function( opts ) { 341 // bail out if not an object 342 if ( !$.isPlainObject( opts ) ){ 343 return; 344 } 345 this.options = $.extend( true, this.options, opts ); 346 }; 347} 348 349// -------------------------- plugin bridge -------------------------- // 350 351// helper function for logging errors 352// $.error breaks jQuery chaining 353var logError = typeof console === 'undefined' ? noop : 354 function( message ) { 355 console.error( message ); 356 }; 357 358/** 359 * jQuery plugin bridge, access methods like $elem.plugin('method') 360 * @param {String} namespace - plugin name 361 * @param {Function} PluginClass - constructor class 362 */ 363function bridge( namespace, PluginClass ) { 364 // add to jQuery fn namespace 365 $.fn[ namespace ] = function( options ) { 366 if ( typeof options === 'string' ) { 367 // call plugin method when first argument is a string 368 // get arguments for method 369 var args = slice.call( arguments, 1 ); 370 371 for ( var i=0, len = this.length; i < len; i++ ) { 372 var elem = this[i]; 373 var instance = $.data( elem, namespace ); 374 if ( !instance ) { 375 logError( "cannot call methods on " + namespace + " prior to initialization; " + 376 "attempted to call '" + options + "'" ); 377 continue; 378 } 379 if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { 380 logError( "no such method '" + options + "' for " + namespace + " instance" ); 381 continue; 382 } 383 384 // trigger method with arguments 385 var returnValue = instance[ options ].apply( instance, args ); 386 387 // break look and return first value if provided 388 if ( returnValue !== undefined ) { 389 return returnValue; 390 } 391 } 392 // return this if no return value 393 return this; 394 } else { 395 return this.each( function() { 396 var instance = $.data( this, namespace ); 397 if ( instance ) { 398 // apply options & init 399 instance.option( options ); 400 instance._init(); 401 } else { 402 // initialize new instance 403 instance = new PluginClass( this, options ); 404 $.data( this, namespace, instance ); 405 } 406 }); 407 } 408 }; 409 410} 411 412// -------------------------- bridget -------------------------- // 413 414/** 415 * converts a Prototypical class into a proper jQuery plugin 416 * the class must have a ._init method 417 * @param {String} namespace - plugin name, used in $().pluginName 418 * @param {Function} PluginClass - constructor class 419 */ 420$.bridget = function( namespace, PluginClass ) { 421 addOptionMethod( PluginClass ); 422 bridge( namespace, PluginClass ); 423}; 424 425return $.bridget; 426 427} 428 429// transport 430if ( typeof define === 'function' && define.amd ) { 431 // AMD 432 define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget ); 433} else if ( typeof exports === 'object' ) { 434 defineBridget( require('jquery') ); 435} else { 436 // get jquery from browser global 437 defineBridget( window.jQuery ); 438} 439 440})( window ); 441 442/*! 443 * eventie v1.0.6 444 * event binding helper 445 * eventie.bind( elem, 'click', myFn ) 446 * eventie.unbind( elem, 'click', myFn ) 447 * MIT license 448 */ 449 450/*jshint browser: true, undef: true, unused: true */ 451/*global define: false, module: false */ 452 453( function( window ) { 454 455 456 457var docElem = document.documentElement; 458 459var bind = function() {}; 460 461function getIEEvent( obj ) { 462 var event = window.event; 463 // add event.target 464 event.target = event.target || event.srcElement || obj; 465 return event; 466} 467 468if ( docElem.addEventListener ) { 469 bind = function( obj, type, fn ) { 470 obj.addEventListener( type, fn, false ); 471 }; 472} else if ( docElem.attachEvent ) { 473 bind = function( obj, type, fn ) { 474 obj[ type + fn ] = fn.handleEvent ? 475 function() { 476 var event = getIEEvent( obj ); 477 fn.handleEvent.call( fn, event ); 478 } : 479 function() { 480 var event = getIEEvent( obj ); 481 fn.call( obj, event ); 482 }; 483 obj.attachEvent( "on" + type, obj[ type + fn ] ); 484 }; 485} 486 487var unbind = function() {}; 488 489if ( docElem.removeEventListener ) { 490 unbind = function( obj, type, fn ) { 491 obj.removeEventListener( type, fn, false ); 492 }; 493} else if ( docElem.detachEvent ) { 494 unbind = function( obj, type, fn ) { 495 obj.detachEvent( "on" + type, obj[ type + fn ] ); 496 try { 497 delete obj[ type + fn ]; 498 } catch ( err ) { 499 // can't delete window object properties 500 obj[ type + fn ] = undefined; 501 } 502 }; 503} 504 505var eventie = { 506 bind: bind, 507 unbind: unbind 508}; 509 510// ----- module definition ----- // 511 512if ( typeof define === 'function' && define.amd ) { 513 // AMD 514 define( 'eventie/eventie',eventie ); 515} else if ( typeof exports === 'object' ) { 516 // CommonJS 517 module.exports = eventie; 518} else { 519 // browser global 520 window.eventie = eventie; 521} 522 523})( window ); 524 525/*! 526 * EventEmitter v4.2.11 - git.io/ee 527 * Unlicense - http://unlicense.org/ 528 * Oliver Caldwell - http://oli.me.uk/ 529 * @preserve 530 */ 531 532;(function () { 533 'use strict'; 534 535 /** 536 * Class for managing events. 537 * Can be extended to provide event functionality in other classes. 538 * 539 * @class EventEmitter Manages event registering and emitting. 540 */ 541 function EventEmitter() {} 542 543 // Shortcuts to improve speed and size 544 var proto = EventEmitter.prototype; 545 var exports = this; 546 var originalGlobalValue = exports.EventEmitter; 547 548 /** 549 * Finds the index of the listener for the event in its storage array. 550 * 551 * @param {Function[]} listeners Array of listeners to search through. 552 * @param {Function} listener Method to look for. 553 * @return {Number} Index of the specified listener, -1 if not found 554 * @api private 555 */ 556 function indexOfListener(listeners, listener) { 557 var i = listeners.length; 558 while (i--) { 559 if (listeners[i].listener === listener) { 560 return i; 561 } 562 } 563 564 return -1; 565 } 566 567 /** 568 * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 568-971
568writing of target method. 569 * 570 * @param {String} name The name of the target method. 571 * @return {Function} The aliased method 572 * @api private 573 */ 574 function alias(name) { 575 return function aliasClosure() { 576 return this[name].apply(this, arguments); 577 }; 578 } 579 580 /** 581 * Returns the listener array for the specified event. 582 * Will initialise the event object and listener arrays if required. 583 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. 584 * Each property in the object response is an array of listener functions. 585 * 586 * @param {String|RegExp} evt Name of the event to return the listeners from. 587 * @return {Function[]|Object} All listener functions for the event. 588 */ 589 proto.getListeners = function getListeners(evt) { 590 var events = this._getEvents(); 591 var response; 592 var key; 593 594 // Return a concatenated array of all matching events if 595 // the selector is a regular expression. 596 if (evt instanceof RegExp) { 597 response = {}; 598 for (key in events) { 599 if (events.hasOwnProperty(key) && evt.test(key)) { 600 response[key] = events[key]; 601 } 602 } 603 } 604 else { 605 response = events[evt] || (events[evt] = []); 606 } 607 608 return response; 609 }; 610 611 /** 612 * Takes a list of listener objects and flattens it into a list of listener functions. 613 * 614 * @param {Object[]} listeners Raw listener objects. 615 * @return {Function[]} Just the listener functions. 616 */ 617 proto.flattenListeners = function flattenListeners(listeners) { 618 var flatListeners = []; 619 var i; 620 621 for (i = 0; i < listeners.length; i += 1) { 622 flatListeners.push(listeners[i].listener); 623 } 624 625 return flatListeners; 626 }; 627 628 /** 629 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. 630 * 631 * @param {String|RegExp} evt Name of the event to return the listeners from. 632 * @return {Object} All listener functions for an event in an object. 633 */ 634 proto.getListenersAsObject = function getListenersAsObject(evt) { 635 var listeners = this.getListeners(evt); 636 var response; 637 638 if (listeners instanceof Array) { 639 response = {}; 640 response[evt] = listeners; 641 } 642 643 return response || listeners; 644 }; 645 646 /** 647 * Adds a listener function to the specified event. 648 * The listener will not be added if it is a duplicate. 649 * If the listener returns true then it will be removed after it is called. 650 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 651 * 652 * @param {String|RegExp} evt Name of the event to attach the listener to. 653 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 654 * @return {Object} Current instance of EventEmitter for chaining. 655 */ 656 proto.addListener = function addListener(evt, listener) { 657 var listeners = this.getListenersAsObject(evt); 658 var listenerIsWrapped = typeof listener === 'object'; 659 var key; 660 661 for (key in listeners) { 662 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 663 listeners[key].push(listenerIsWrapped ? listener : { 664 listener: listener, 665 once: false 666 }); 667 } 668 } 669 670 return this; 671 }; 672 673 /** 674 * Alias of addListener 675 */ 676 proto.on = alias('addListener'); 677 678 /** 679 * Semi-alias of addListener. It will add a listener that will be 680 * automatically removed after its first execution. 681 * 682 * @param {String|RegExp} evt Name of the event to attach the listener to. 683 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 684 * @return {Object} Current instance of EventEmitter for chaining. 685 */ 686 proto.addOnceListener = function addOnceListener(evt, listener) { 687 return this.addListener(evt, { 688 listener: listener, 689 once: true 690 }); 691 }; 692 693 /** 694 * Alias of addOnceListener. 695 */ 696 proto.once = alias('addOnceListener'); 697 698 /** 699 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. 700 * You need to tell it what event names should be matched by a regex. 701 * 702 * @param {String} evt Name of the event to create. 703 * @return {Object} Current instance of EventEmitter for chaining. 704 */ 705 proto.defineEvent = function defineEvent(evt) { 706 this.getListeners(evt); 707 return this; 708 }; 709 710 /** 711 * Uses defineEvent to define multiple events. 712 * 713 * @param {String[]} evts An array of event names to define. 714 * @return {Object} Current instance of EventEmitter for chaining. 715 */ 716 proto.defineEvents = function defineEvents(evts) { 717 for (var i = 0; i < evts.length; i += 1) { 718 this.defineEvent(evts[i]); 719 } 720 return this; 721 }; 722 723 /** 724 * Removes a listener function from the specified event. 725 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 726 * 727 * @param {String|RegExp} evt Name of the event to remove the listener from. 728 * @param {Function} listener Method to remove from the event. 729 * @return {Object} Current instance of EventEmitter for chaining. 730 */ 731 proto.removeListener = function removeListener(evt, listener) { 732 var listeners = this.getListenersAsObject(evt); 733 var index; 734 var key; 735 736 for (key in listeners) { 737 if (listeners.hasOwnProperty(key)) { 738 index = indexOfListener(listeners[key], listener); 739 740 if (index !== -1) { 741 listeners[key].splice(index, 1); 742 } 743 } 744 } 745 746 return this; 747 }; 748 749 /** 750 * Alias of removeListener 751 */ 752 proto.off = alias('removeListener'); 753 754 /** 755 * Adds listeners in bulk using the manipulateListeners method. 756 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. 757 * You can also pass it a regular expression to add the array of listeners to all events that match it. 758 * Yeah, this function does quite a bit. That's probably a bad thing. 759 * 760 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. 761 * @param {Function[]} [listeners] An optional array of listener functions to add. 762 * @return {Object} Current instance of EventEmitter for chaining. 763 */ 764 proto.addListeners = function addListeners(evt, listeners) { 765 // Pass through to manipulateListeners 766 return this.manipulateListeners(false, evt, listeners); 767 }; 768 769 /** 770 * Removes listeners in bulk using the manipulateListeners method. 771 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 772 * You can also pass it an event name and an array of listeners to be removed. 773 * You can also pass it a regular expression to remove the listeners from all events that match it. 774 * 775 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. 776 * @param {Function[]} [listeners] An optional array of listener functions to remove. 777 * @return {Object} Current instance of EventEmitter for chaining. 778 */ 779 proto.removeListeners = function removeListeners(evt, listeners) { 780 // Pass through to manipulateListeners 781 return this.manipulateListeners(true, evt, listeners); 782 }; 783 784 /** 785 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. 786 * The first argument will determine if the listeners are removed (true) or added (false). 787 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 788 * You can also pass it an event name and an array of listeners to be added/removed. 789 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 790 * 791 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 792 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. 793 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 794 * @return {Object} Current instance of EventEmitter for chaining. 795 */ 796 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 797 var i; 798 var value; 799 var single = remove ? this.removeListener : this.addListener; 800 var multiple = remove ? this.removeListeners : this.addListeners; 801 802 // If evt is an object then pass each of its properties to this method 803 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 804 for (i in evt) { 805 if (evt.hasOwnProperty(i) && (value = evt[i])) { 806 // Pass the single listener straight through to the singular method 807 if (typeof value === 'function') { 808 single.call(this, i, value); 809 } 810 else { 811 // Otherwise pass back to the multiple function 812 multiple.call(this, i, value); 813 } 814 } 815 } 816 } 817 else { 818 // So evt must be a string 819 // And listeners must be an array of listeners 820 // Loop over it and pass each one to the multiple method 821 i = listeners.length; 822 while (i--) { 823 single.call(this, evt, listeners[i]); 824 } 825 } 826 827 return this; 828 }; 829 830 /** 831 * Removes all listeners from a specified event. 832 * If you do not specify an event then all listeners will be removed. 833 * That means every event will be emptied. 834 * You can also pass a regex to remove all events that match it. 835 * 836 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 837 * @return {Object} Current instance of EventEmitter for chaining. 838 */ 839 proto.removeEvent = function removeEvent(evt) { 840 var type = typeof evt; 841 var events = this._getEvents(); 842 var key; 843 844 // Remove different things depending on the state of evt 845 if (type === 'string') { 846 // Remove all listeners for the specified event 847 delete events[evt]; 848 } 849 else if (evt instanceof RegExp) { 850 // Remove all events matching the regex. 851 for (key in events) { 852 if (events.hasOwnProperty(key) && evt.test(key)) { 853 delete events[key]; 854 } 855 } 856 } 857 else { 858 // Remove all listeners in all events 859 delete this._events; 860 } 861 862 return this; 863 }; 864 865 /** 866 * Alias of removeEvent. 867 * 868 * Added to mirror the node API. 869 */ 870 proto.removeAllListeners = alias('removeEvent'); 871 872 /** 873 * Emits an event of your choice. 874 * When emitted, every listener attached to that event will be executed. 875 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 876 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. 877 * So they will not arrive within the array on the other side, they will be separate. 878 * You can also pass a regular expression to emit to all events that match it. 879 * 880 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 881 * @param {Array} [args] Optional array of arguments to be passed to each listener. 882 * @return {Object} Current instance of EventEmitter for chaining. 883 */ 884 proto.emitEvent = function emitEvent(evt, args) { 885 var listeners = this.getListenersAsObject(evt); 886 var listener; 887 var i; 888 var key; 889 var response; 890 891 for (key in listeners) { 892 if (listeners.hasOwnProperty(key)) { 893 i = listeners[key].length; 894 895 while (i--) { 896 // If the listener returns true then it shall be removed from the event 897 // The function is executed either with a basic call or an apply if there is an args array 898 listener = listeners[key][i]; 899 900 if (listener.once === true) { 901 this.removeListener(evt, listener.listener); 902 } 903 904 response = listener.listener.apply(this, args || []); 905 906 if (response === this._getOnceReturnValue()) { 907 this.removeListener(evt, listener.listener); 908 } 909 } 910 } 911 } 912 913 return this; 914 }; 915 916 /** 917 * Alias of emitEvent 918 */ 919 proto.trigger = alias('emitEvent'); 920 921 /** 922 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. 923 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 924 * 925 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 926 * @param {...*} Optional additional arguments to be passed to each listener. 927 * @return {Object} Current instance of EventEmitter for chaining. 928 */ 929 proto.emit = function emit(evt) { 930 var args = Array.prototype.slice.call(arguments, 1); 931 return this.emitEvent(evt, args); 932 }; 933 934 /** 935 * Sets the current value to check against when executing listeners. If a 936 * listeners return value matches the one set here then it will be removed 937 * after execution. This value defaults to true. 938 * 939 * @param {*} value The new value to check for when executing listeners. 940 * @return {Object} Current instance of EventEmitter for chaining. 941 */ 942 proto.setOnceReturnValue = function setOnceReturnValue(value) { 943 this._onceReturnValue = value; 944 return this; 945 }; 946 947 /** 948 * Fetches the current value to check against when executing listeners. If 949 * the listeners return value matches this one then it should be removed 950 * automatically. It will return true by default. 951 * 952 * @return {*|Boolean} The current value to check for or the default, true. 953 * @api private 954 */ 955 proto._getOnceReturnValue = function _getOnceReturnValue() { 956 if (this.hasOwnProperty('_onceReturnValue')) { 957 return this._onceReturnValue; 958 } 959 else { 960 return true; 961 } 962 }; 963 964 /** 965 * Fetches the events object and creates one if required. 966 * 967 * @return {Object} The events storage object. 968 * @api private 969 */ 970 proto._getEvents = function _getEvents() { 971 return this._events || (this
971._events = {}); 972 }; 973 974 /** 975 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. 976 * 977 * @return {Function} Non conflicting EventEmitter class. 978 */ 979 EventEmitter.noConflict = function noConflict() { 980 exports.EventEmitter = originalGlobalValue; 981 return EventEmitter; 982 }; 983 984 // Expose the class either via AMD, CommonJS or the global object 985 if (typeof define === 'function' && define.amd) { 986 define('eventEmitter/EventEmitter',[],function () { 987 return EventEmitter; 988 }); 989 } 990 else if (typeof module === 'object' && module.exports){ 991 module.exports = EventEmitter; 992 } 993 else { 994 exports.EventEmitter = EventEmitter; 995 } 996}.call(this)); 997 998/*! 999 * getStyleProperty v1.0.4 1000 * original by kangax 1001 * http://perfectionkills.com/feature-testing-css-properties/ 1002 * MIT license 1003 */ 1004 1005/*jshint browser: true, strict: true, undef: true */ 1006/*global define: false, exports: false, module: false */ 1007 1008( function( window ) { 1009 1010 1011 1012var prefixes = 'Webkit Moz ms Ms O'.split(' '); 1013var docElemStyle = document.documentElement.style; 1014 1015function getStyleProperty( propName ) { 1016 if ( !propName ) { 1017 return; 1018 } 1019 1020 // test standard property first 1021 if ( typeof docElemStyle[ propName ] === 'string' ) { 1022 return propName; 1023 } 1024 1025 // capitalize 1026 propName = propName.charAt(0).toUpperCase() + propName.slice(1); 1027 1028 // test vendor specific properties 1029 var prefixed; 1030 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1031 prefixed = prefixes[i] + propName; 1032 if ( typeof docElemStyle[ prefixed ] === 'string' ) { 1033 return prefixed; 1034 } 1035 } 1036} 1037 1038// transport 1039if ( typeof define === 'function' && define.amd ) { 1040 // AMD 1041 define( 'get-style-property/get-style-property',[],function() { 1042 return getStyleProperty; 1043 }); 1044} else if ( typeof exports === 'object' ) { 1045 // CommonJS for Component 1046 module.exports = getStyleProperty; 1047} else { 1048 // browser global 1049 window.getStyleProperty = getStyleProperty; 1050} 1051 1052})( window ); 1053 1054/*! 1055 * getSize v1.2.2 1056 * measure size of elements 1057 * MIT license 1058 */ 1059 1060/*jshint browser: true, strict: true, undef: true, unused: true */ 1061/*global define: false, exports: false, require: false, module: false, console: false */ 1062 1063( function( window, undefined ) { 1064 1065 1066 1067// -------------------------- helpers -------------------------- // 1068 1069// get a number from a string, not a percentage 1070function getStyleSize( value ) { 1071 var num = parseFloat( value ); 1072 // not a percent like '100%', and a number 1073 var isValid = value.indexOf('%') === -1 && !isNaN( num ); 1074 return isValid && num; 1075} 1076 1077function noop() {} 1078 1079var logError = typeof console === 'undefined' ? noop : 1080 function( message ) { 1081 console.error( message ); 1082 }; 1083 1084// -------------------------- measurements -------------------------- // 1085 1086var measurements = [ 1087 'paddingLeft', 1088 'paddingRight', 1089 'paddingTop', 1090 'paddingBottom', 1091 'marginLeft', 1092 'marginRight', 1093 'marginTop', 1094 'marginBottom', 1095 'borderLeftWidth', 1096 'borderRightWidth', 1097 'borderTopWidth', 1098 'borderBottomWidth' 1099]; 1100 1101function getZeroSize() { 1102 var size = { 1103 width: 0, 1104 height: 0, 1105 innerWidth: 0, 1106 innerHeight: 0, 1107 outerWidth: 0, 1108 outerHeight: 0 1109 }; 1110 for ( var i=0, len = measurements.length; i < len; i++ ) { 1111 var measurement = measurements[i]; 1112 size[ measurement ] = 0; 1113 } 1114 return size; 1115} 1116 1117 1118 1119function defineGetSize( getStyleProperty ) { 1120 1121// -------------------------- setup -------------------------- // 1122 1123var isSetup = false; 1124 1125var getStyle, boxSizingProp, isBoxSizeOuter; 1126 1127/** 1128 * setup vars and functions 1129 * do it on initial getSize(), rather than on script load 1130 * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397 1131 */ 1132function setup() { 1133 // setup once 1134 if ( isSetup ) { 1135 return; 1136 } 1137 isSetup = true; 1138 1139 var getComputedStyle = window.getComputedStyle; 1140 getStyle = ( function() { 1141 var getStyleFn = getComputedStyle ? 1142 function( elem ) { 1143 return getComputedStyle( elem, null ); 1144 } : 1145 function( elem ) { 1146 return elem.currentStyle; 1147 }; 1148 1149 return function getStyle( elem ) { 1150 var style = getStyleFn( elem ); 1151 if ( !style ) { 1152 logError( 'Style returned ' + style + 1153 '. Are you running this code in a hidden iframe on Firefox? ' + 1154 'See http://bit.ly/getsizebug1' ); 1155 } 1156 return style; 1157 }; 1158 })(); 1159 1160 // -------------------------- box sizing -------------------------- // 1161 1162 boxSizingProp = getStyleProperty('boxSizing'); 1163 1164 /** 1165 * WebKit measures the outer-width on style.width on border-box elems 1166 * IE & Firefox measures the inner-width 1167 */ 1168 if ( boxSizingProp ) { 1169 var div = document.createElement('div'); 1170 div.style.width = '200px'; 1171 div.style.padding = '1px 2px 3px 4px'; 1172 div.style.borderStyle = 'solid'; 1173 div.style.borderWidth = '1px 2px 3px 4px'; 1174 div.style[ boxSizingProp ] = 'border-box'; 1175 1176 var body = document.body || document.documentElement; 1177 body.appendChild( div ); 1178 var style = getStyle( div ); 1179 1180 isBoxSizeOuter = getStyleSize( style.width ) === 200; 1181 body.removeChild( div ); 1182 } 1183 1184} 1185 1186// -------------------------- getSize -------------------------- // 1187 1188function getSize( elem ) { 1189 setup(); 1190 1191 // use querySeletor if elem is string 1192 if ( typeof elem === 'string' ) { 1193 elem = document.querySelector( elem ); 1194 } 1195 1196 // do not proceed on non-objects 1197 if ( !elem || typeof elem !== 'object' || !elem.nodeType ) { 1198 return; 1199 } 1200 1201 var style = getStyle( elem ); 1202 1203 // if hidden, everything is 0 1204 if ( style.display === 'none' ) { 1205 return getZeroSize(); 1206 } 1207 1208 var size = {}; 1209 size.width = elem.offsetWidth; 1210 size.height = elem.offsetHeight; 1211 1212 var isBorderBox = size.isBorderBox = !!( boxSizingProp && 1213 style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' ); 1214 1215 // get all measurements 1216 for ( var i=0, len = measurements.length; i < len; i++ ) { 1217 var measurement = measurements[i]; 1218 var value = style[ measurement ]; 1219 value = mungeNonPixel( elem, value ); 1220 var num = parseFloat( value ); 1221 // any 'auto', 'medium' value will be 0 1222 size[ measurement ] = !isNaN( num ) ? num : 0; 1223 } 1224 1225 var paddingWidth = size.paddingLeft + size.paddingRight; 1226 var paddingHeight = size.paddingTop + size.paddingBottom; 1227 var marginWidth = size.marginLeft + size.marginRight; 1228 var marginHeight = size.marginTop + size.marginBottom; 1229 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 1230 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 1231 1232 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 1233 1234 // overwrite width and height if we can get it from style 1235 var styleWidth = getStyleSize( style.width ); 1236 if ( styleWidth !== false ) { 1237 size.width = styleWidth + 1238 // add padding and border unless it's already including it 1239 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 1240 } 1241 1242 var styleHeight = getStyleSize( style.height ); 1243 if ( styleHeight !== false ) { 1244 size.height = styleHeight + 1245 // add padding and border unless it's already including it 1246 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 1247 } 1248 1249 size.innerWidth = size.width - ( paddingWidth + borderWidth );
1250 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 1251 1252 size.outerWidth = size.width + marginWidth; 1253 size.outerHeight = size.height + marginHeight; 1254 1255 return size; 1256} 1257 1258// IE8 returns percent values, not pixels 1259// taken from jQuery's curCSS 1260function mungeNonPixel( elem, value ) { 1261 // IE8 and has percent value 1262 if ( window.getComputedStyle || value.indexOf('%') === -1 ) { 1263 return value; 1264 } 1265 var style = elem.style; 1266 // Remember the original values 1267 var left = style.left; 1268 var rs = elem.runtimeStyle; 1269 var rsLeft = rs && rs.left; 1270 1271 // Put in the new values to get a computed value out 1272 if ( rsLeft ) { 1273 rs.left = elem.currentStyle.left; 1274 } 1275 style.left = value; 1276 value = style.pixelLeft; 1277 1278 // Revert the changed values 1279 style.left = left; 1280 if ( rsLeft ) { 1281 rs.left = rsLeft; 1282 } 1283 1284 return value; 1285} 1286 1287return getSize; 1288 1289} 1290 1291// transport 1292if ( typeof define === 'function' && define.amd ) { 1293 // AMD for RequireJS 1294 define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize ); 1295} else if ( typeof exports === 'object' ) { 1296 // CommonJS for Component 1297 module.exports = defineGetSize( require('desandro-get-style-property') ); 1298} else { 1299 // browser global 1300 window.getSize = defineGetSize( window.getStyleProperty ); 1301} 1302 1303})( window ); 1304 1305/*! 1306 * docReady v1.0.4 1307 * Cross browser DOMContentLoaded event emitter 1308 * MIT license 1309 */ 1310 1311/*jshint browser: true, strict: true, undef: true, unused: true*/ 1312/*global define: false, require: false, module: false */ 1313 1314( function( window ) { 1315 1316 1317 1318var document = window.document; 1319// collection of functions to be triggered on ready 1320var queue = []; 1321 1322function docReady( fn ) { 1323 // throw out non-functions 1324 if ( typeof fn !== 'function' ) { 1325 return; 1326 } 1327 1328 if ( docReady.isReady ) { 1329 // ready now, hit it 1330 fn(); 1331 } else { 1332 // queue function when ready 1333 queue.push( fn ); 1334 } 1335} 1336 1337docReady.isReady = false; 1338 1339// triggered on various doc ready events 1340function onReady( event ) { 1341 // bail if already triggered or IE8 document is not ready just yet 1342 var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete'; 1343 if ( docReady.isReady || isIE8NotReady ) { 1344 return; 1345 } 1346 1347 trigger(); 1348} 1349 1350function trigger() { 1351 docReady.isReady = true; 1352 // process queue 1353 for ( var i=0, len = queue.length; i < len; i++ ) { 1354 var fn = queue[i]; 1355 fn(); 1356 } 1357} 1358 1359function defineDocReady( eventie ) { 1360 // trigger ready if page is ready 1361 if ( document.readyState === 'complete' ) { 1362 trigger(); 1363 } else { 1364 // listen for events 1365 eventie.bind( document, 'DOMContentLoaded', onReady ); 1366 eventie.bind( document, 'readystatechange', onReady ); 1367 eventie.bind( window, 'load', onReady ); 1368 } 1369 1370 return docReady; 1371} 1372 1373// transport 1374if ( typeof define === 'function' && define.amd ) { 1375 // AMD 1376 define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady ); 1377} else if ( typeof exports === 'object' ) { 1378 module.exports = defineDocReady( require('eventie') ); 1379} else { 1380 // browser global 1381 window.docReady = defineDocReady( window.eventie ); 1382} 1383 1384})( window ); 1385 1386/** 1387 * matchesSelector v1.0.3 1388 * matchesSelector( element, '.selector' ) 1389 * MIT license 1390 */ 1391 1392/*jshint browser: true, strict: true, undef: true, unused: true */ 1393/*global define: false, module: false */ 1394 1395( function( ElemProto ) { 1396 1397 'use strict'; 1398 1399 var matchesMethod = ( function() { 1400 // check for the standard method name first 1401 if ( ElemProto.matches ) { 1402 return 'matches'; 1403 } 1404 // check un-prefixed 1405 if ( ElemProto.matchesSelector ) { 1406 return 'matchesSelector'; 1407 } 1408 // check vendor prefixes 1409 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 1410 1411 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1412 var prefix = prefixes[i]; 1413 var method = prefix + 'MatchesSelector'; 1414 if ( ElemProto[ method ] ) { 1415 return method; 1416 } 1417 } 1418 })(); 1419 1420 // ----- match ----- // 1421 1422 function match( elem, selector ) { 1423 return elem[ matchesMethod ]( selector ); 1424 } 1425 1426 // ----- appendToFragment ----- // 1427 1428 function checkParent( elem ) { 1429 // not needed if already has parent 1430 if ( elem.parentNode ) { 1431 return; 1432 } 1433 var fragment = document.createDocumentFragment(); 1434 fragment.appendChild( elem ); 1435 } 1436 1437 // ----- query ----- // 1438 1439 // fall back to using QSA 1440 // thx @jonathantneal https://gist.github.com/3062955 1441 function query( elem, selector ) { 1442 // append to fragment if no parent 1443 checkParent( elem ); 1444 1445 // match elem with all selected elems of parent 1446 var elems = elem.parentNode.querySelectorAll( selector ); 1447 for ( var i=0, len = elems.length; i < len; i++ ) { 1448 // return true if match 1449 if ( elems[i] === elem ) { 1450 return true; 1451 } 1452 } 1453 // otherwise return false 1454 return false;
1455 } 1456 1457 // ----- matchChild ----- // 1458 1459 function matchChild( elem, selector ) { 1460 checkParent( elem ); 1461 return match( elem, selector ); 1462 } 1463 1464 // ----- matchesSelector ----- // 1465 1466 var matchesSelector; 1467 1468 if ( matchesMethod ) { 1469 // IE9 supports matchesSelector, but doesn't work on orphaned elems 1470 // check for that 1471 var div = document.createElement('div'); 1472 var supportsOrphans = match( div, 'div' ); 1473 matchesSelector = supportsOrphans ? match : matchChild; 1474 } else { 1475 matchesSelector = query; 1476 } 1477 1478 // transport 1479 if ( typeof define === 'function' && define.amd ) { 1480 // AMD 1481 define( 'matches-selector/matches-selector',[],function() { 1482 return matchesSelector; 1483 }); 1484 } else if ( typeof exports === 'object' ) { 1485 module.exports = matchesSelector; 1486 } 1487 else { 1488 // browser global 1489 window.matchesSelector = matchesSelector; 1490 } 1491 1492})( Element.prototype ); 1493 1494/** 1495 * Fizzy UI utils v1.0.1 1496 * MIT license 1497 */ 1498 1499/*jshint browser: true, undef: true, unused: true, strict: true */ 1500 1501( function( window, factory ) { 1502 /*global define: false, module: false, require: false */ 1503 'use strict'; 1504 // universal module definition 1505 1506 if ( typeof define == 'function' && define.amd ) { 1507 // AMD 1508 define( 'fizzy-ui-utils/utils',[ 1509 'doc-ready/doc-ready', 1510 'matches-selector/matches-selector' 1511 ], function( docReady, matchesSelector ) { 1512 return factory( window, docReady, matchesSelector ); 1513 }); 1514 } else if ( typeof exports == 'object' ) { 1515 // CommonJS 1516 module.exports = factory( 1517 window, 1518 require('doc-ready'), 1519 require('desandro-matches-selector') 1520 ); 1521 } else { 1522 // browser global 1523 window.fizzyUIUtils = factory( 1524 window, 1525 window.docReady, 1526 window.matchesSelector 1527 ); 1528 } 1529 1530}( window, function factory( window, docReady, matchesSelector ) { 1531 1532 1533 1534var utils = {}; 1535 1536// ----- extend ----- // 1537 1538// extends objects 1539utils.extend = function( a, b ) { 1540 for ( var prop in b ) { 1541 a[ prop ] = b[ prop ]; 1542 } 1543 return a; 1544}; 1545 1546// ----- modulo ----- // 1547 1548utils.modulo = function( num, div ) { 1549 return ( ( num % div ) + div ) % div; 1550}; 1551 1552// ----- isArray ----- // 1553 1554var objToString = Object.prototype.toString; 1555utils.isArray = function( obj ) { 1556 return objToString.call( obj ) == '[object Array]'; 1557}; 1558 1559// ----- makeArray ----- // 1560 1561// turn element or nodeList into an array 1562utils.makeArray = function( obj ) { 1563 var ary = []; 1564 if ( utils.isArray( obj ) ) { 1565 // use object if already an array 1566 ary = obj; 1567 } else if ( obj && typeof obj.length == 'number' ) { 1568 // convert nodeList to array 1569 for ( var i=0, len = obj.length; i < len; i++ ) { 1570 ary.push( obj[i] ); 1571 } 1572 } else { 1573 // array of single index 1574 ary.push( obj ); 1575 } 1576 return ary; 1577}; 1578 1579// ----- indexOf ----- // 1580 1581// index of helper cause IE8 1582utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) { 1583 return ary.indexOf( obj ); 1584 } : function( ary, obj ) { 1585 for ( var i=0, len = ary.length; i < len; i++ ) { 1586 if ( ary[i] === obj ) { 1587 return i; 1588 } 1589 } 1590 return -1; 1591 }; 1592 1593// ----- removeFrom ----- // 1594 1595utils.removeFrom = function( ary, obj ) { 1596 var index = utils.indexOf( ary, obj ); 1597 if ( index != -1 ) { 1598 ary.splice( index, 1 ); 1599 } 1600}; 1601 1602// ----- isElement ----- // 1603 1604// http://stackoverflow.com/a/384380/182183 1605utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ? 1606 function isElementDOM2( obj ) { 1607 return obj instanceof HTMLElement; 1608 } : 1609 function isElementQuirky( obj ) { 1610 return obj && typeof obj == 'object' && 1611 obj.nodeType == 1 && typeof obj.nodeName == 'string'; 1612 }; 1613 1614// ----- setText ----- // 1615 1616utils.setText = ( function() { 1617 var setTextProperty; 1618 function setText( elem, text ) { 1619 // only check setTextProperty once 1620 setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' ); 1621 elem[ setTextProperty ] = text; 1622 } 1623 return setText; 1624})(); 1625 1626// ----- getParent ----- // 1627 1628utils.getParent = function( elem, selector ) { 1629 while ( elem != document.body ) { 1630 elem = elem.parentNode; 1631 if ( matchesSelector( elem, selector ) ) { 1632 return elem; 1633 } 1634 } 1635}; 1636 1637// ----- getQueryElement ----- // 1638 1639// use element as selector string 1640utils.getQueryElement = function( elem ) { 1641 if ( typeof elem == 'string' ) { 1642 return document.querySelector( elem ); 1643 } 1644 return elem; 1645}; 1646 1647// ----- handleEvent ----- // 1648 1649// enable .ontype to trigger from .addEventListener( elem, 'type' ) 1650utils.handleEvent = function( event ) { 1651 var method = 'on' + event.type; 1652 if ( this[ method ] ) { 1653 this[ method ]( event ); 1654 } 1655}; 1656 1657// ----- filterFindElements ----- // 1658 1659utils.filterFindElements = function( elems, selector ) { 1660 // make array of elems 1661 elems = utils.makeArray( elems ); 1662 var ffElems = []; 1663 1664 for ( var i=0, len = elems.length; i < len; i++ ) { 1665 var elem = elems[i]; 1666 // check that elem is an actual element 1667 if ( !utils.isElement( elem ) ) { 1668 continue; 1669 } 1670 // filter & find items if we have a selector 1671 if ( selector ) { 1672 // filter siblings 1673 if ( matchesSelector( elem, selector ) ) { 1674 ffElems.push( elem ); 1675 } 1676 // find children 1677 var childElems = elem.querySelectorAll( selector ); 1678 // concat childElems to filterFound array 1679 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 1680 ffElems.push( childElems[j] ); 1681 } 1682 } else { 1683 ffElems.push( elem ); 1684 } 1685 } 1686 1687 return ffElems; 1688}; 1689 1690// ----- debounceMethod ----- // 1691 1692utils.debounceMethod = function( _class, methodName, threshold ) { 1693 // original method 1694 var method = _class.prototype[ methodName ]; 1695 var timeoutName = methodName + 'Timeout'; 1696 1697 _class.prototype[ methodName ] = function() { 1698 var timeout = this[ timeoutName ]; 1699 if ( timeout ) { 1700 clearTimeout( timeout ); 1701 } 1702 var args = arguments; 1703 1704 var _this = this; 1705 this[ timeoutName ] = setTimeout( function() { 1706 method.apply( _this, args ); 1707 delete _this[ timeoutName ]; 1708 }, threshold || 100 ); 1709 }; 1710}; 1711 1712// ----- htmlInit ----- // 1713 1714// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 1715utils.toDashed = function( str ) { 1716 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 1717 return $1 + '-' + $2; 1718 }).toLowerCase(); 1719}; 1720
1721var console = window.console; 1722/** 1723 * allow user to initialize classes via .js-namespace class 1724 * htmlInit( Widget, 'widgetName' ) 1725 * options are parsed from data-namespace-option attribute 1726 */ 1727utils.htmlInit = function( WidgetClass, namespace ) { 1728 docReady( function() { 1729 var dashedNamespace = utils.toDashed( namespace ); 1730 var elems = document.querySelectorAll( '.js-' + dashedNamespace ); 1731 var dataAttr = 'data-' + dashedNamespace + '-options'; 1732 1733 for ( var i=0, len = elems.length; i < len; i++ ) { 1734 var elem = elems[i]; 1735 var attr = elem.getAttribute( dataAttr ); 1736 var options; 1737 try { 1738 options = attr && JSON.parse( attr ); 1739 } catch ( error ) { 1740 // log error, do not initialize 1741 if ( console ) { 1742 console.error( 'Error parsing ' + dataAttr + ' on ' + 1743 elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' + 1744 error ); 1745 } 1746 continue; 1747 } 1748 // initialize 1749 var instance = new WidgetClass( elem, options ); 1750 // make available via $().data('layoutname') 1751 var jQuery = window.jQuery; 1752 if ( jQuery ) { 1753 jQuery.data( elem, namespace, instance ); 1754 } 1755 } 1756 }); 1757}; 1758 1759// ----- ----- // 1760 1761return utils; 1762 1763})); 1764 1765/** 1766 * Outlayer Item 1767 */ 1768 1769( function( window, factory ) { 1770 'use strict'; 1771 // universal module definition 1772 if ( typeof define === 'function' && define.amd ) { 1773 // AMD 1774 define( 'outlayer/item',[ 1775 'eventEmitter/EventEmitter', 1776 'get-size/get-size', 1777 'get-style-property/get-style-property', 1778 'fizzy-ui-utils/utils' 1779 ], 1780 function( EventEmitter, getSize, getStyleProperty, utils ) { 1781 return factory( window, EventEmitter, getSize, getStyleProperty, utils ); 1782 } 1783 ); 1784 } else if (typeof exports === 'object') { 1785 // CommonJS 1786 module.exports = factory( 1787 window, 1788 require('wolfy87-eventemitter'), 1789 require('get-size'), 1790 require('desandro-get-style-property'), 1791 require('fizzy-ui-utils') 1792 ); 1793 } else { 1794 // browser global 1795 window.Outlayer = {}; 1796 window.Outlayer.Item = factory( 1797 window, 1798 window.EventEmitter, 1799 window.getSize, 1800 window.getStyleProperty, 1801 window.fizzyUIUtils 1802 ); 1803 } 1804 1805}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) { 1806'use strict'; 1807 1808// ----- helpers ----- // 1809 1810var getComputedStyle = window.getComputedStyle; 1811var getStyle = getComputedStyle ? 1812 function( elem ) { 1813 return getComputedStyle( elem, null ); 1814 } : 1815 function( elem ) { 1816 return elem.currentStyle; 1817 }; 1818 1819 1820function isEmptyObj( obj ) { 1821 for ( var prop in obj ) { 1822 return false; 1823 } 1824 prop = null; 1825 return true; 1826} 1827 1828// -------------------------- CSS3 support -------------------------- // 1829 1830var transitionProperty = getStyleProperty('transition'); 1831var transformProperty = getStyleProperty('transform'); 1832var supportsCSS3 = transitionProperty && transformProperty; 1833var is3d = !!getStyleProperty('perspective'); 1834 1835var transitionEndEvent = { 1836 WebkitTransition: 'webkitTransitionEnd', 1837 MozTransition: 'transitionend', 1838 OTransition: 'otransitionend', 1839 transition: 'transitionend' 1840}[ transitionProperty ]; 1841 1842// properties that could have vendor prefix 1843var prefixableProperties = [ 1844 'transform', 1845 'transition', 1846 'transitionDuration', 1847 'transitionProperty' 1848]; 1849 1850// cache all vendor properties 1851var vendorProperties = ( function() { 1852 var cache = {}; 1853 for ( var i=0, len = prefixableProperties.length; i < len; i++ ) { 1854 var prop = prefixableProperties[i]; 1855 var supportedProp = getStyleProperty( prop ); 1856 if ( supportedProp && supportedProp !== prop ) { 1857 cache[ prop ] = supportedProp; 1858 } 1859 } 1860 return cache; 1861})(); 1862 1863// -------------------------- Item -------------------------- // 1864 1865function Item( element, layout ) { 1866 if ( !element ) { 1867 return; 1868 } 1869 1870 this.element = element; 1871 // parent layout class, i.e. Masonry, Isotope, or Packery 1872 this.layout = layout; 1873 this.position = { 1874 x: 0, 1875 y: 0 1876 }; 1877 1878 this._create(); 1879} 1880 1881// inherit EventEmitter 1882utils.extend( Item.prototype, EventEmitter.prototype ); 1883 1884Item.prototype._create = function() { 1885 // transition objects 1886 this._transn = { 1887 ingProperties: {}, 1888 clean: {}, 1889 onEnd: {} 1890 }; 1891 1892 this.css({ 1893 position: 'absolute' 1894 }); 1895}; 1896 1897// trigger specified handler for event type 1898Item.prototype.handleEvent = function( event ) { 1899 var method = 'on' + event.type; 1900 if ( this[ method ] ) { 1901 this[ method ]( event ); 1902 } 1903}; 1904 1905Item.prototype.getSize = function() { 1906 this.size = getSize( this.element ); 1907}; 1908 1909/** 1910 * apply CSS styles to element 1911 * @param {Object} style 1912 */ 1913Item.prototype.css = function( style ) { 1914 var elemStyle = this.element.style; 1915 1916 for ( var prop in style ) { 1917 // use vendor property if available
1918 var supportedProp = vendorProperties[ prop ] || prop; 1919 elemStyle[ supportedProp ] = style[ prop ]; 1920 } 1921}; 1922 1923 // measure position, and sets it 1924Item.prototype.getPosition = function() { 1925 var style = getStyle( this.element ); 1926 var layoutOptions = this.layout.options; 1927 var isOriginLeft = layoutOptions.isOriginLeft; 1928 var isOriginTop = layoutOptions.isOriginTop; 1929 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 1930 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 1931 // convert percent to pixels 1932 var layoutSize = this.layout.size; 1933 var x = xValue.indexOf('%') != -1 ? 1934 ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 ); 1935 var y = yValue.indexOf('%') != -1 ? 1936 ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 ); 1937 1938 // clean up 'auto' or other non-integer values 1939 x = isNaN( x ) ? 0 : x; 1940 y = isNaN( y ) ? 0 : y; 1941 // remove padding from measurement 1942 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 1943 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 1944 1945 this.position.x = x; 1946 this.position.y = y; 1947}; 1948 1949// set settled position, apply padding 1950Item.prototype.layoutPosition = function() { 1951 var layoutSize = this.layout.size; 1952 var layoutOptions = this.layout.options; 1953 var style = {}; 1954 1955 // x 1956 var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight'; 1957 var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right'; 1958 var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left'; 1959 1960 var x = this.position.x + layoutSize[ xPadding ]; 1961 // set in percentage or pixels 1962 style[ xProperty ] = this.getXValue( x ); 1963 // reset other property 1964 style[ xResetProperty ] = ''; 1965 1966 // y 1967 var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom'; 1968 var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom'; 1969 var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top'; 1970 1971 var y = this.position.y + layoutSize[ yPadding ]; 1972 // set in percentage or pixels 1973 style[ yProperty ] = this.getYValue( y ); 1974 // reset other property 1975 style[ yResetProperty ] = ''; 1976 1977 this.css( style ); 1978 this.emitEvent( 'layout', [ this ] ); 1979}; 1980 1981Item.prototype.getXValue = function( x ) { 1982 var layoutOptions = this.layout.options; 1983 return layoutOptions.percentPosition && !layoutOptions.isHorizontal ? 1984 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 1985}; 1986 1987Item.prototype.getYValue = function( y ) { 1988 var layoutOptions = this.layout.options; 1989 return layoutOptions.percentPosition && layoutOptions.isHorizontal ? 1990 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 1991}; 1992 1993 1994Item.prototype._transitionTo = function( x, y ) { 1995 this.getPosition(); 1996 // get current x & y from top/left 1997 var curX = this.position.x; 1998 var curY = this.position.y; 1999 2000 var compareX = parseInt( x, 10 ); 2001 var compareY = parseInt( y, 10 ); 2002 var didNotMove = compareX === this.position.x && compareY === this.position.y; 2003 2004 // save end position 2005 this.setPosition( x, y ); 2006 2007 // if did not move and not transitioning, just go to layout 2008 if ( didNotMove && !this.isTransitioning ) { 2009 this.layoutPosition(); 2010 return; 2011 } 2012 2013 var transX = x - curX; 2014 var transY = y - curY; 2015 var transitionStyle = {}; 2016 transitionStyle.transform = this.getTranslate( transX, transY ); 2017 2018 this.transition({ 2019 to: transitionStyle, 2020 onTransitionEnd: { 2021 transform: this.layoutPosition 2022 }, 2023 isCleaning: true 2024 }); 2025}; 2026 2027Item.prototype.getTranslate = function( x, y ) { 2028 // flip cooridinates if origin on right or bottom 2029 var layoutOptions = this.layout.options; 2030 x = layoutOptions.isOriginLeft ? x : -x; 2031 y = layoutOptions.isOriginTop ? y : -y; 2032 2033 if ( is3d ) { 2034 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 2035 } 2036 2037 return 'translate(' + x + 'px, ' + y + 'px)'; 2038}; 2039 2040// non transition + transform support 2041Item.prototype.goTo = function( x, y ) { 2042 this.setPosition( x, y ); 2043 this.layoutPosition(); 2044}; 2045 2046// use transition and transforms if supported 2047Item.prototype.moveTo = supportsCSS3 ? 2048 Item.prototype._transitionTo : Item.prototype.goTo; 2049 2050Item.prototype.setPosition = function( x, y ) { 2051 this.position.x = parseInt( x, 10 ); 2052 this.position.y = parseInt( y, 10 ); 2053}; 2054 2055// ----- transition ----- // 2056 2057/** 2058 * @param {Object} style - CSS 2059 * @param {Function} onTransitionEnd 2060 */ 2061 2062// non transition, just trigger callback 2063Item.prototype._nonTransition = function( args ) { 2064 this.css( args.to ); 2065 if ( args.isCleaning ) { 2066 this._removeStyles( args.to ); 2067 } 2068 for ( var prop in args.onTransitionEnd ) { 2069 args.onTransitionEnd[ prop ].call( this ); 2070 } 2071}; 2072 2073/** 2074 * proper transition 2075 * @param {Object} args - arguments 2076 * @param {Object} to - style to transition to 2077 * @param {Object} from - style to start transition from 2078 * @param {Boolean} isCleaning - removes transition styles after transition 2079 * @param {Function} onTransitionEnd - callback 2080 */ 2081Item.prototype._transition = function( args ) { 2082 // redirect to nonTransition if no transition duration 2083 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 2084 this._nonTransition( args ); 2085 return; 2086 } 2087 2088 var _transition = this._transn; 2089 // keep track of onTransitionEnd callback by css property 2090 for ( var prop in args.onTransitionEnd ) { 2091 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 2092 } 2093 // keep track of properties that are transitioning 2094 for ( prop in args.to ) { 2095 _transition.ingProperties[ prop ] = true; 2096 // keep track of properties to clean up when transition is done 2097 if ( args.isCleaning ) { 2098 _transition.clean[ prop ] = true; 2099 } 2100 } 2101 2102 // set from styles 2103 if ( args.from ) { 2104 this.css( args.from ); 2105 // force redraw. http://blog.alexmaccaw.com/css-transitions 2106 var h = this.element.offsetHeight; 2107 // hack for JSHint to hush about unused var 2108 h = null; 2109 } 2110 // enable transition 2111 this.enableTransition( args.to ); 2112 // set styles that are transitioning 2113 this.css( args.to ); 2114 2115 this.isTransitioning = true; 2116 2117}; 2118 2119// dash before all cap letters, including first for 2120// WebkitTransform => -webkit-transform 2121function toDashedAll( str ) { 2122 return str.replace( /([A-Z])/g, function( $1 ) { 2123 return '-' + $1.toLowerCase(); 2124 }); 2125} 2126 2127var transitionProps = 'opacity,' +
vendor: 11,190 bytes, lines 2128-2574
2128 toDashedAll( vendorProperties.transform || 'transform' ); 2129 2130Item.prototype.enableTransition = function(/* style */) { 2131 // HACK changing transitionProperty during a transition 2132 // will cause transition to jump 2133 if ( this.isTransitioning ) { 2134 return; 2135 } 2136 2137 // make `transition: foo, bar, baz` from style object 2138 // HACK un-comment this when enableTransition can work 2139 // while a transition is happening 2140 // var transitionValues = []; 2141 // for ( var prop in style ) { 2142 // // dash-ify camelCased properties like WebkitTransition 2143 // prop = vendorProperties[ prop ] || prop; 2144 // transitionValues.push( toDashedAll( prop ) ); 2145 // } 2146 // enable transition styles 2147 this.css({ 2148 transitionProperty: transitionProps, 2149 transitionDuration: this.layout.options.transitionDuration 2150 }); 2151 // listen for transition end event 2152 this.element.addEventListener( transitionEndEvent, this, false ); 2153}; 2154 2155Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ]; 2156 2157// ----- events ----- // 2158 2159Item.prototype.onwebkitTransitionEnd = function( event ) { 2160 this.ontransitionend( event ); 2161}; 2162 2163Item.prototype.onotransitionend = function( event ) { 2164 this.ontransitionend( event ); 2165}; 2166 2167// properties that I munge to make my life easier 2168var dashedVendorProperties = { 2169 '-webkit-transform': 'transform', 2170 '-moz-transform': 'transform', 2171 '-o-transform': 'transform' 2172}; 2173 2174Item.prototype.ontransitionend = function( event ) { 2175 // disregard bubbled events from children 2176 if ( event.target !== this.element ) { 2177 return; 2178 } 2179 var _transition = this._transn; 2180 // get property name of transitioned property, convert to prefix-free 2181 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 2182 2183 // remove property that has completed transitioning 2184 delete _transition.ingProperties[ propertyName ]; 2185 // check if any properties are still transitioning 2186 if ( isEmptyObj( _transition.ingProperties ) ) { 2187 // all properties have completed transitioning 2188 this.disableTransition(); 2189 } 2190 // clean style 2191 if ( propertyName in _transition.clean ) { 2192 // clean up style 2193 this.element.style[ event.propertyName ] = ''; 2194 delete _transition.clean[ propertyName ]; 2195 } 2196 // trigger onTransitionEnd callback 2197 if ( propertyName in _transition.onEnd ) { 2198 var onTransitionEnd = _transition.onEnd[ propertyName ]; 2199 onTransitionEnd.call( this ); 2200 delete _transition.onEnd[ propertyName ]; 2201 } 2202 2203 this.emitEvent( 'transitionEnd', [ this ] ); 2204}; 2205 2206Item.prototype.disableTransition = function() { 2207 this.removeTransitionStyles(); 2208 this.element.removeEventListener( transitionEndEvent, this, false ); 2209 this.isTransitioning = false; 2210}; 2211 2212/** 2213 * removes style property from element 2214 * @param {Object} style 2215**/ 2216Item.prototype._removeStyles = function( style ) { 2217 // clean up transition styles 2218 var cleanStyle = {}; 2219 for ( var prop in style ) { 2220 cleanStyle[ prop ] = ''; 2221 } 2222 this.css( cleanStyle ); 2223}; 2224 2225var cleanTransitionStyle = { 2226 transitionProperty: '', 2227 transitionDuration: '' 2228}; 2229 2230Item.prototype.removeTransitionStyles = function() { 2231 // remove transition 2232 this.css( cleanTransitionStyle ); 2233}; 2234 2235// ----- show/hide/remove ----- // 2236 2237// remove element from DOM 2238Item.prototype.removeElem = function() { 2239 this.element.parentNode.removeChild( this.element ); 2240 // remove display: none 2241 this.css({ display: '' }); 2242 this.emitEvent( 'remove', [ this ] ); 2243}; 2244 2245Item.prototype.remove = function() { 2246 // just remove element if no transition support or no transition 2247 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 2248 this.removeElem(); 2249 return; 2250 } 2251 2252 // start transition 2253 var _this = this; 2254 this.once( 'transitionEnd', function() { 2255 _this.removeElem(); 2256 }); 2257 this.hide(); 2258}; 2259 2260Item.prototype.reveal = function() { 2261 delete this.isHidden; 2262 // remove display: none 2263 this.css({ display: '' }); 2264 2265 var options = this.layout.options; 2266 2267 var onTransitionEnd = {}; 2268 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 2269 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 2270 2271 this.transition({ 2272 from: options.hiddenStyle, 2273 to: options.visibleStyle, 2274 isCleaning: true, 2275 onTransitionEnd: onTransitionEnd 2276 }); 2277}; 2278 2279Item.prototype.onRevealTransitionEnd = function() { 2280 // check if still visible 2281 // during transition, item may have been hidden 2282 if ( !this.isHidden ) { 2283 this.emitEvent('reveal'); 2284 } 2285}; 2286 2287/** 2288 * get style property use for hide/reveal transition end 2289 * @param {String} styleProperty - hiddenStyle/visibleStyle 2290 * @returns {String} 2291 */ 2292Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) { 2293 var optionStyle = this.layout.options[ styleProperty ]; 2294 // use opacity 2295 if ( optionStyle.opacity ) { 2296 return 'opacity'; 2297 } 2298 // get first property 2299 for ( var prop in optionStyle ) { 2300 return prop; 2301 } 2302}; 2303 2304Item.prototype.hide = function() { 2305 // set flag 2306 this.isHidden = true; 2307 // remove display: none 2308 this.css({ display: '' }); 2309 2310 var options = this.layout.options; 2311 2312 var onTransitionEnd = {}; 2313 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 2314 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 2315 2316 this.transition({ 2317 from: options.visibleStyle, 2318 to: options.hiddenStyle, 2319 // keep hidden stuff hidden 2320 isCleaning: true, 2321 onTransitionEnd: onTransitionEnd 2322 }); 2323}; 2324 2325Item.prototype.onHideTransitionEnd = function() { 2326 // check if still hidden 2327 // during transition, item may have been un-hidden 2328 if ( this.isHidden ) { 2329 this.css({ display: 'none' }); 2330 this.emitEvent('hide'); 2331 } 2332}; 2333 2334Item.prototype.destroy = function() { 2335 this.css({ 2336 position: '', 2337 left: '', 2338 right: '', 2339 top: '', 2340 bottom: '', 2341 transition: '', 2342 transform: '' 2343 }); 2344}; 2345 2346return Item; 2347 2348})); 2349 2350/*! 2351 * Outlayer v1.4.2 2352 * the brains and guts of a layout library 2353 * MIT license 2354 */ 2355 2356( function( window, factory ) { 2357 'use strict'; 2358 // universal module definition 2359 2360 if ( typeof define == 'function' && define.amd ) { 2361 // AMD 2362 define( 'outlayer/outlayer',[ 2363 'eventie/eventie', 2364 'eventEmitter/EventEmitter', 2365 'get-size/get-size', 2366 'fizzy-ui-utils/utils', 2367 './item' 2368 ], 2369 function( eventie, EventEmitter, getSize, utils, Item ) { 2370 return factory( window, eventie, EventEmitter, getSize, utils, Item); 2371 } 2372 ); 2373 } else if ( typeof exports == 'object' ) { 2374 // CommonJS 2375 module.exports = factory( 2376 window, 2377 require('eventie'), 2378 require('wolfy87-eventemitter'), 2379 require('get-size'), 2380 require('fizzy-ui-utils'), 2381 require('./item') 2382 ); 2383 } else { 2384 // browser global 2385 window.Outlayer = factory( 2386 window, 2387 window.eventie, 2388 window.EventEmitter, 2389 window.getSize, 2390 window.fizzyUIUtils, 2391 window.Outlayer.Item 2392 ); 2393 } 2394 2395}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) { 2396'use strict'; 2397 2398// ----- vars ----- // 2399 2400var console = window.console; 2401var jQuery = window.jQuery; 2402var noop = function() {}; 2403 2404// -------------------------- Outlayer -------------------------- // 2405 2406// globally unique identifiers 2407var GUID = 0; 2408// internal store of all Outlayer intances 2409var instances = {}; 2410 2411 2412/** 2413 * @param {Element, String} element 2414 * @param {Object} options 2415 * @constructor 2416 */ 2417function Outlayer( element, options ) { 2418 var queryElement = utils.getQueryElement( element ); 2419 if ( !queryElement ) { 2420 if ( console ) { 2421 console.error( 'Bad element for ' + this.constructor.namespace + 2422 ': ' + ( queryElement || element ) ); 2423 } 2424 return; 2425 } 2426 this.element = queryElement; 2427 // add jQuery 2428 if ( jQuery ) { 2429 this.$element = jQuery( this.element ); 2430 } 2431 2432 // options 2433 this.options = utils.extend( {}, this.constructor.defaults ); 2434 this.option( options ); 2435 2436 // add id for Outlayer.getFromElement 2437 var id = ++GUID; 2438 this.element.outlayerGUID = id; // expando 2439 instances[ id ] = this; // associate via id 2440 2441 // kick it off 2442 this._create(); 2443 2444 if ( this.options.isInitLayout ) { 2445 this.layout(); 2446 } 2447} 2448 2449// settings are for internal use only 2450Outlayer.namespace = 'outlayer'; 2451Outlayer.Item = Item; 2452 2453// default options 2454Outlayer.defaults = { 2455 containerStyle: { 2456 position: 'relative' 2457 }, 2458 isInitLayout: true, 2459 isOriginLeft: true, 2460 isOriginTop: true, 2461 isResizeBound: true, 2462 isResizingContainer: true, 2463 // item options 2464 transitionDuration: '0.4s', 2465 hiddenStyle: { 2466 opacity: 0, 2467 transform: 'scale(0.001)' 2468 }, 2469 visibleStyle: { 2470 opacity: 1, 2471 transform: 'scale(1)' 2472 } 2473}; 2474 2475// inherit EventEmitter 2476utils.extend( Outlayer.prototype, EventEmitter.prototype ); 2477 2478/** 2479 * set options 2480 * @param {Object} opts 2481 */ 2482Outlayer.prototype.option = function( opts ) { 2483 utils.extend( this.options, opts ); 2484}; 2485 2486Outlayer.prototype._create = function() { 2487 // get items from children 2488 this.reloadItems(); 2489 // elements that affect layout, but are not laid out 2490 this.stamps = []; 2491 this.stamp( this.options.stamp ); 2492 // set container style 2493 utils.extend( this.element.style, this.options.containerStyle ); 2494 2495 // bind resize method 2496 if ( this.options.isResizeBound ) { 2497 this.bindResize(); 2498 } 2499}; 2500 2501// goes through all children again and gets bricks in proper order 2502Outlayer.prototype.reloadItems = function() { 2503 // collection of item elements 2504 this.items = this._itemize( this.element.children ); 2505}; 2506 2507 2508/** 2509 * turn elements into Outlayer.Items to be used in layout 2510 * @param {Array or NodeList or HTMLElement} elems 2511 * @returns {Array} items - collection of new Outlayer Items 2512 */ 2513Outlayer.prototype._itemize = function( elems ) { 2514 2515 var itemElems = this._filterFindItemElements( elems ); 2516 var Item = this.constructor.Item; 2517 2518 // create new Outlayer Items for collection 2519 var items = []; 2520 for ( var i=0, len = itemElems.length; i < len; i++ ) { 2521 var elem = itemElems[i]; 2522 var item = new Item( elem, this ); 2523 items.push( item ); 2524 } 2525 2526 return items; 2527}; 2528 2529/** 2530 * get item elements to be used in layout 2531 * @param {Array or NodeList or HTMLElement} elems 2532 * @returns {Array} items - item elements 2533 */ 2534Outlayer.prototype._filterFindItemElements = function( elems ) { 2535 return utils.filterFindElements( elems, this.options.itemSelector ); 2536}; 2537 2538/** 2539 * getter method for getting item elements 2540 * @returns {Array} elems - collection of item elements 2541 */ 2542Outlayer.prototype.getItemElements = function() { 2543 var elems = []; 2544 for ( var i=0, len = this.items.length; i < len; i++ ) { 2545 elems.push( this.items[i].element ); 2546 } 2547 return elems; 2548}; 2549 2550// ----- init & layout ----- // 2551 2552/** 2553 * lays out all items 2554 */ 2555Outlayer.prototype.layout = function() { 2556 this._resetLayout(); 2557 this._manageStamps(); 2558 2559 // don't animate first layout 2560 var isInstant = this.options.isLayoutInstant !== undefined ? 2561 this.options.isLayoutInstant : !this._isLayoutInited; 2562 this.layoutItems( this.items, isInstant ); 2563 2564 // flag for initalized 2565 this._isLayoutInited = true; 2566}; 2567 2568// _init is alias for layout 2569Outlayer.prototype._init = Outlayer.prototype.layout; 2570 2571/** 2572 * logic before any new layout 2573 */ 2574Outlayer.prototype._resetLayout = function() {
2575 this.getSize(); 2576}; 2577 2578 2579Outlayer.prototype.getSize = function() { 2580 this.size = getSize( this.element ); 2581}; 2582 2583/** 2584 * get measurement from option, for columnWidth, rowHeight, gutter 2585 * if option is String -> get element from selector string, & get size of element 2586 * if option is Element -> get size of element 2587 * else use option as a number 2588 * 2589 * @param {String} measurement 2590 * @param {String} size - width or height 2591 * @private 2592 */ 2593Outlayer.prototype._getMeasurement = function( measurement, size ) { 2594 var option = this.options[ measurement ]; 2595 var elem; 2596 if ( !option ) { 2597 // default to 0 2598 this[ measurement ] = 0; 2599 } else { 2600 // use option as an element 2601 if ( typeof option === 'string' ) { 2602 elem = this.element.querySelector( option ); 2603 } else if ( utils.isElement( option ) ) { 2604 elem = option; 2605 } 2606 // use size of element, if element 2607 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 2608 } 2609}; 2610 2611/** 2612 * layout a collection of item elements 2613 * @api public 2614 */ 2615Outlayer.prototype.layoutItems = function( items, isInstant ) { 2616 items = this._getItemsForLayout( items ); 2617 2618 this._layoutItems( items, isInstant ); 2619 2620 this._postLayout(); 2621}; 2622 2623/** 2624 * get the items to be laid out 2625 * you may want to skip over some items 2626 * @param {Array} items 2627 * @returns {Array} items 2628 */ 2629Outlayer.prototype._getItemsForLayout = function( items ) { 2630 var layoutItems = []; 2631 for ( var i=0, len = items.length; i < len; i++ ) { 2632 var item = items[i]; 2633 if ( !item.isIgnored ) { 2634 layoutItems.push( item ); 2635 } 2636 } 2637 return layoutItems; 2638}; 2639 2640/** 2641 * layout items 2642 * @param {Array} items 2643 * @param {Boolean} isInstant 2644 */ 2645Outlayer.prototype._layoutItems = function( items, isInstant ) { 2646 this._emitCompleteOnItems( 'layout', items ); 2647 2648 if ( !items || !items.length ) { 2649 // no items, emit event with empty array 2650 return; 2651 } 2652 2653 var queue = []; 2654 2655 for ( var i=0, len = items.length; i < len; i++ ) { 2656 var item = items[i]; 2657 // get x/y object from method 2658 var position = this._getItemLayoutPosition( item ); 2659 // enqueue 2660 position.item = item; 2661 position.isInstant = isInstant || item.isLayoutInstant; 2662 queue.push( position ); 2663 } 2664 2665 this._processLayoutQueue( queue ); 2666}; 2667 2668/** 2669 * get item layout position 2670 * @param {Outlayer.Item} item 2671 * @returns {Object} x and y position 2672 */ 2673Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) { 2674 return { 2675 x: 0, 2676 y: 0 2677 }; 2678}; 2679 2680/** 2681 * iterate over array and position each item 2682 * Reason being - separating this logic prevents 'layout invalidation' 2683 * thx @paul_irish 2684 * @param {Array} queue 2685 */ 2686Outlayer.prototype._processLayoutQueue = function( queue ) { 2687 for ( var i=0, len = queue.length; i < len; i++ ) { 2688 var obj = queue[i]; 2689 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant ); 2690 } 2691}; 2692 2693/** 2694 * Sets position of item in DOM 2695 * @param {Outlayer.Item} item 2696 * @param {Number} x - horizontal position 2697 * @param {Number} y - vertical position 2698 * @param {Boolean} isInstant - disables transitions 2699 */ 2700Outlayer.prototype._positionItem = function( item, x, y, isInstant ) { 2701 if ( isInstant ) { 2702 // if not transition, just set CSS 2703 item.goTo( x, y ); 2704 } else { 2705 item.moveTo( x, y ); 2706 } 2707}; 2708 2709/** 2710 * Any logic you want to do after each layout, 2711 * i.e. size the container 2712 */ 2713Outlayer.prototype._postLayout = function() { 2714 this.resizeContainer(); 2715}; 2716 2717Outlayer.prototype.resizeContainer = function() { 2718 if ( !this.options.isResizingContainer ) { 2719 return; 2720 } 2721 var size = this._getContainerSize(); 2722 if ( size ) { 2723 this._setContainerMeasure( size.width, true ); 2724 this._setContainerMeasure( size.height, false ); 2725 } 2726}; 2727 2728/** 2729 * Sets width or height of container if returned 2730 * @returns {Object} size 2731 * @param {Number} width 2732 * @param {Number} height 2733 */ 2734Outlayer.prototype._getContainerSize = noop; 2735 2736/** 2737 * @param {Number} measure - size of width or height 2738 * @param {Boolean} isWidth 2739 */ 2740Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) { 2741 if ( measure === undefined ) { 2742 return; 2743 } 2744 2745 var elemSize = this.size; 2746 // add padding and border width if border box 2747 if ( elemSize.isBorderBox ) { 2748 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 2749 elemSize.borderLeftWidth + elemSize.borderRightWidth : 2750 elemSize.paddingBottom + elemSize.paddingTop + 2751 elemSize.borderTopWidth + elemSize.borderBottomWidth; 2752 } 2753 2754 measure = Math.max( measure, 0 ); 2755 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 2756}; 2757 2758/** 2759 * emit eventComplete on a collection of items events 2760 * @param {String} eventName 2761 * @param {Array} items - Outlayer.Items 2762 */ 2763Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) { 2764 var _this = this; 2765 function onComplete() { 2766 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 2767 } 2768 2769 var count = items.length; 2770 if ( !items || !count ) { 2771 onComplete(); 2772 return; 2773 } 2774 2775 var doneCount = 0; 2776 function tick() { 2777 doneCount++; 2778 if ( doneCount === count ) { 2779 onComplete(); 2780 } 2781 } 2782 2783 // bind callback 2784 for ( var i=0, len = items.length; i < len; i++ ) { 2785 var item = items[i]; 2786 item.once( eventName, tick ); 2787 } 2788}; 2789 2790/** 2791 * emits events via eventEmitter and jQuery events 2792 * @param {String} type - name of event 2793 * @param {Event} event - original event 2794 * @param {Array} args - extra arguments 2795 */ 2796Outlayer.prototype.dispatchEvent = function( type, event, args ) { 2797 // add original event to arguments 2798 var emitArgs = event ? [ event ].concat( args ) : args; 2799 this.emitEvent( type, emitArgs ); 2800 2801 if ( jQuery ) { 2802 // set this.$element 2803 this.$element = this.$element || jQuery( this.element ); 2804 if ( event ) { 2805 // create jQuery event 2806 var $event = jQuery.Event( event ); 2807 $event.type = type; 2808 this.$element.trigger( $event, args ); 2809 } else { 2810 // just trigger with type if no event available 2811 this.$element.trigger( type, args ); 2812 } 2813 } 2814}; 2815 2816// -------------------------- ignore & stamps -------------------------- // 2817 2818 2819/** 2820 * keep item in collection, but do not lay it out 2821 * ignored items do not get skipped in layout 2822 * @param {Element} elem 2823 */ 2824Outlayer.prototype.ignore = function( elem ) { 2825 var item = this.getItem( elem ); 2826 if ( item ) { 2827 item.isIgnored = true; 2828 } 2829}; 2830 2831/** 2832 * return item to layout collection 2833 * @param {Element} elem 2834 */ 2835Outlayer.prototype.unignore = function( elem ) { 2836 var item = this.getItem( elem ); 2837 if ( item ) { 2838 delete item.isIgnored; 2839 } 2840}; 2841 2842/** 2843 * adds elements to stamps 2844 * @param {NodeList, Array, Element, or String} elems 2845 */ 2846Outlayer.prototype.stamp = function( elems ) { 2847 elems = this._find( elems ); 2848 if ( !elems ) { 2849 return; 2850 } 2851
2852 this.stamps = this.stamps.concat( elems ); 2853 // ignore 2854 for ( var i=0, len = elems.length; i < len; i++ ) { 2855 var elem = elems[i]; 2856 this.ignore( elem ); 2857 } 2858}; 2859 2860/** 2861 * removes elements to stamps 2862 * @param {NodeList, Array, or Element} elems 2863 */ 2864Outlayer.prototype.unstamp = function( elems ) { 2865 elems = this._find( elems ); 2866 if ( !elems ){ 2867 return; 2868 } 2869 2870 for ( var i=0, len = elems.length; i < len; i++ ) { 2871 var elem = elems[i]; 2872 // filter out removed stamp elements 2873 utils.removeFrom( this.stamps, elem ); 2874 this.unignore( elem ); 2875 } 2876 2877}; 2878 2879/** 2880 * finds child elements 2881 * @param {NodeList, Array, Element, or String} elems 2882 * @returns {Array} elems 2883 */ 2884Outlayer.prototype._find = function( elems ) { 2885 if ( !elems ) { 2886 return; 2887 } 2888 // if string, use argument as selector string 2889 if ( typeof elems === 'string' ) { 2890 elems = this.element.querySelectorAll( elems ); 2891 } 2892 elems = utils.makeArray( elems ); 2893 return elems; 2894}; 2895 2896Outlayer.prototype._manageStamps = function() { 2897 if ( !this.stamps || !this.stamps.length ) { 2898 return; 2899 } 2900 2901 this._getBoundingRect(); 2902 2903 for ( var i=0, len = this.stamps.length; i < len; i++ ) { 2904 var stamp = this.stamps[i]; 2905 this._manageStamp( stamp ); 2906 } 2907}; 2908 2909// update boundingLeft / Top 2910Outlayer.prototype._getBoundingRect = function() { 2911 // get bounding rect for container element 2912 var boundingRect = this.element.getBoundingClientRect(); 2913 var size = this.size; 2914 this._boundingRect = { 2915 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 2916 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 2917 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 2918 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 2919 }; 2920}; 2921 2922/** 2923 * @param {Element} stamp 2924**/ 2925Outlayer.prototype._manageStamp = noop; 2926 2927/** 2928 * get x/y position of element relative to container element 2929 * @param {Element} elem 2930 * @returns {Object} offset - has left, top, right, bottom 2931 */ 2932Outlayer.prototype._getElementOffset = function( elem ) { 2933 var boundingRect = elem.getBoundingClientRect(); 2934 var thisRect = this._boundingRect; 2935 var size = getSize( elem ); 2936 var offset = { 2937 left: boundingRect.left - thisRect.left - size.marginLeft, 2938 top: boundingRect.top - thisRect.top - size.marginTop, 2939 right: thisRect.right - boundingRect.right - size.marginRight, 2940 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 2941 }; 2942 return offset; 2943}; 2944 2945// -------------------------- resize -------------------------- // 2946 2947// enable event handlers for listeners 2948// i.e. resize -> onresize 2949Outlayer.prototype.handleEvent = function( event ) { 2950 var method = 'on' + event.type; 2951 if ( this[ method ] ) { 2952 this[ method ]( event ); 2953 } 2954}; 2955 2956/** 2957 * Bind layout to window resizing 2958 */ 2959Outlayer.prototype.bindResize = function() { 2960 // bind just one listener 2961 if ( this.isResizeBound ) { 2962 return; 2963 } 2964 eventie.bind( window, 'resize', this ); 2965 this.isResizeBound = true; 2966}; 2967 2968/** 2969 * Unbind layout to window resizing 2970 */ 2971Outlayer.prototype.unbindResize = function() { 2972 if ( this.isResizeBound ) { 2973 eventie.unbind( window, 'resize', this ); 2974 } 2975 this.isResizeBound = false; 2976}; 2977 2978// original debounce by John Hann 2979// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 2980 2981// this fires every resize 2982Outlayer.prototype.onresize = function() { 2983 if ( this.resizeTimeout ) { 2984 clearTimeout( this.resizeTimeout ); 2985 } 2986 2987 var _this = this; 2988 function delayed() { 2989 _this.resize(); 2990 delete _this.resizeTimeout; 2991 } 2992 2993 this.resizeTimeout = setTimeout( delayed, 100 ); 2994}; 2995 2996// debounced, layout on resize 2997Outlayer.prototype.resize = function() { 2998 // don't trigger if size did not change 2999 // or if resize was unbound. See #9 3000 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 3001 return; 3002 } 3003 3004 this.layout(); 3005}; 3006 3007/** 3008 * check if layout is needed post layout 3009 * @returns Boolean 3010 */ 3011Outlayer.prototype.needsResizeLayout = function() { 3012 var size = getSize( this.element ); 3013 // check that this.size and size are there 3014 // IE8 triggers resize on body size change, so they might not be 3015 var hasSizes = this.size && size; 3016 return hasSizes && size.innerWidth !== this.size.innerWidth; 3017}; 3018 3019// -------------------------- methods -------------------------- // 3020 3021/** 3022 * add items to Outlayer instance 3023 * @param {Array or NodeList or Element} elems 3024 * @returns {Array} items - Outlayer.Items 3025**/ 3026Outlayer.prototype.addItems = function( elems ) { 3027 var items = this._itemize( elems ); 3028 // add items to collection 3029 if ( items.length ) { 3030 this.items = this.items.concat( items ); 3031 } 3032 return items; 3033}; 3034 3035/** 3036 * Layout newly-appended item elements 3037 * @param {Array or NodeList or Element} elems 3038 */ 3039Outlayer.prototype.appended = function( elems ) { 3040 var items = this.addItems( elems ); 3041 if ( !items.length ) { 3042 return; 3043 } 3044 // layout and reveal just the new items 3045 this.layoutItems( items, true ); 3046 this.reveal( items ); 3047}; 3048 3049/** 3050 * Layout prepended elements 3051 * @param {Array or NodeList or Element} elems 3052 */ 3053Outlayer.prototype.prepended = function( elems ) { 3054 var items = this._itemize( elems ); 3055 if ( !items.length ) { 3056 return; 3057 } 3058 // add items to beginning of collection 3059 var previousItems = this.items.slice(0); 3060 this.items = items.concat( previousItems ); 3061 // start new layout 3062 this._resetLayout(); 3063 this._manageStamps(); 3064 // layout new stuff without transition 3065 this.layoutItems( items, true ); 3066 this.reveal( items ); 3067 // layout previous items 3068 this.layoutItems( previousItems ); 3069}; 3070 3071/** 3072 * reveal a collection of items 3073 * @param {Array of Outlayer.Items} items 3074 */ 3075Outlayer.prototype.reveal = function( items ) { 3076 this._emitCompleteOnItems( 'reveal', items ); 3077 3078 var len = items && items.length; 3079 for ( var i=0; len && i < len; i++ ) { 3080 var item = items[i]; 3081 item.reveal(); 3082 } 3083}; 3084 3085/** 3086 * hide a collection of items 3087 * @param {Array of Outlayer.Items} items 3088 */ 3089Outlayer.prototype.hide = function( items ) { 3090 this._emitCompleteOnItems( 'hide', items ); 3091 3092 var len = items && items.length; 3093 for ( var i=0; len && i < len; i++ ) { 3094 var item = items[i]; 3095 item.hide(); 3096 } 3097}; 3098 3099/** 3100 * reveal item elements 3101 * @param {Array}, {Element}, {NodeList} items 3102 */ 3103Outlayer.prototype.revealItemElements = function( elems ) { 3104 var items = this.getItems( elems ); 3105 this.reveal( items ); 3106}; 3107 3108/** 3109 * hide item elements 3110 * @param {Array}, {Element}, {NodeList} items 3111 */ 3112Outlayer.prototype.hideItemElements = function( elems ) { 3113 var items = this.getItems( elems ); 3114 this.hide( items ); 3115}; 3116 3117/** 3118 * get Outlayer.Item, given an Element 3119 * @param {Element} elem 3120 * @param {Function} callback 3121 * @returns {Outlayer.Item} item 3122 */ 3123Outlayer.prototype.getItem = function( elem ) { 3124 // loop through items to get the one that matches 3125 for ( var i=0, len = this.items.length; i < len; i++ ) { 3126 var item = this.items[i]; 3127 if ( item.element === elem ) { 3128 // return item 3129 return item; 3130 } 3131 } 3132}; 3133 3134/** 3135 * get collection of Outlayer.Items, given Elements 3136 * @param {Array} elems 3137 * @returns {Array} items - Outlayer.Items 3138 */ 3139Outlayer.prototype.getItems = function( elems ) { 3140 elems = utils.makeArray( elems ); 3141 var items = []; 3142 for ( var i=0, len = elems.length; i < len; i++ ) { 3143 var elem = elems[i]; 3144 var item = this.getItem( elem ); 3145 if ( item ) { 3146 items.push( item ); 3147 } 3148 } 3149 3150 return items; 3151}; 3152 3153/**
3154 * remove element(s) from instance and DOM 3155 * @param {Array or NodeList or Element} elems 3156 */ 3157Outlayer.prototype.remove = function( elems ) { 3158 var removeItems = this.getItems( elems ); 3159 3160 this._emitCompleteOnItems( 'remove', removeItems ); 3161 3162 // bail if no items to remove 3163 if ( !removeItems || !removeItems.length ) { 3164 return; 3165 } 3166 3167 for ( var i=0, len = removeItems.length; i < len; i++ ) { 3168 var item = removeItems[i]; 3169 item.remove(); 3170 // remove item from collection 3171 utils.removeFrom( this.items, item ); 3172 } 3173}; 3174 3175// ----- destroy ----- // 3176 3177// remove and disable Outlayer instance 3178Outlayer.prototype.destroy = function() { 3179 // clean up dynamic styles 3180 var style = this.element.style; 3181 style.height = ''; 3182 style.position = ''; 3183 style.width = ''; 3184 // destroy items 3185 for ( var i=0, len = this.items.length; i < len; i++ ) { 3186 var item = this.items[i]; 3187 item.destroy(); 3188 } 3189 3190 this.unbindResize(); 3191 3192 var id = this.element.outlayerGUID; 3193 delete instances[ id ]; // remove reference to instance by id 3194 delete this.element.outlayerGUID; 3195 // remove data for jQuery 3196 if ( jQuery ) { 3197 jQuery.removeData( this.element, this.constructor.namespace ); 3198 } 3199 3200}; 3201 3202// -------------------------- data -------------------------- // 3203 3204/** 3205 * get Outlayer instance from element 3206 * @param {Element} elem 3207 * @returns {Outlayer} 3208 */ 3209Outlayer.data = function( elem ) { 3210 elem = utils.getQueryElement( elem ); 3211 var id = elem && elem.outlayerGUID; 3212 return id && instances[ id ]; 3213}; 3214 3215 3216// -------------------------- create Outlayer class -------------------------- // 3217 3218/** 3219 * create a layout class 3220 * @param {String} namespace 3221 */ 3222Outlayer.create = function( namespace, options ) { 3223 // sub-class Outlayer 3224 function Layout() { 3225 Outlayer.apply( this, arguments ); 3226 } 3227 // inherit Outlayer prototype, use Object.create if there 3228 if ( Object.create ) { 3229 Layout.prototype = Object.create( Outlayer.prototype ); 3230 } else { 3231 utils.extend( Layout.prototype, Outlayer.prototype ); 3232 } 3233 // set contructor, used for namespace and Item 3234 Layout.prototype.constructor = Layout; 3235 3236 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 3237 // apply new options 3238 utils.extend( Layout.defaults, options ); 3239 // keep prototype.settings for backwards compatibility (Packery v1.2.0) 3240 Layout.prototype.settings = {}; 3241 3242 Layout.namespace = namespace; 3243 3244 Layout.data = Outlayer.data; 3245 3246 // sub-class Item 3247 Layout.Item = function LayoutItem() { 3248 Item.apply( this, arguments ); 3249 }; 3250 3251 Layout.Item.prototype = new Item(); 3252 3253 // -------------------------- declarative -------------------------- // 3254 3255 utils.htmlInit( Layout, namespace ); 3256 3257 // -------------------------- jQuery bridge -------------------------- // 3258 3259 // make into jQuery plugin 3260 if ( jQuery && jQuery.bridget ) { 3261 jQuery.bridget( namespace, Layout ); 3262 } 3263 3264 return Layout; 3265}; 3266 3267// ----- fin ----- // 3268 3269// back in global 3270Outlayer.Item = Item; 3271 3272return Outlayer; 3273 3274})); 3275 3276 3277/** 3278 * Isotope Item 3279**/ 3280 3281( function( window, factory ) { 3282'use strict'; 3283 // universal module definition 3284 if ( typeof define == 'function' && define.amd ) { 3285 // AMD 3286 define( 'isotope/js/item',[ 3287 'outlayer/outlayer' 3288 ], 3289 factory ); 3290 } else if ( typeof exports == 'object' ) { 3291 // CommonJS 3292 module.exports = factory( 3293 require('outlayer') 3294 ); 3295 } else { 3296 // browser global 3297 window.Isotope = window.Isotope || {}; 3298 window.Isotope.Item = factory( 3299 window.Outlayer 3300 ); 3301 } 3302 3303}( window, function factory( Outlayer ) { 3304'use strict'; 3305 3306// -------------------------- Item -------------------------- // 3307 3308// sub-class Outlayer Item 3309function Item() { 3310 Outlayer.Item.apply( this, arguments ); 3311} 3312 3313Item.prototype = new Outlayer.Item(); 3314 3315Item.prototype._create = function() { 3316 // assign id, used for original-order sorting 3317 this.id = this.layout.itemGUID++; 3318 Outlayer.Item.prototype._create.call( this ); 3319 this.sortData = {}; 3320}; 3321 3322Item.prototype.updateSortData = function() { 3323 if ( this.isIgnored ) { 3324 return; 3325 } 3326 // default sorters 3327 this.sortData.id = this.id; 3328 // for backward compatibility 3329 this.sortData['original-order'] = this.id; 3330 this.sortData.random = Math.random(); 3331 // go thru getSortData obj and apply the sorters 3332 var getSortData = this.layout.options.getSortData; 3333 var sorters = this.layout._sorters; 3334 for ( var key in getSortData ) { 3335 var sorter = sorters[ key ]; 3336 this.sortData[ key ] = sorter( this.element, this ); 3337 } 3338}; 3339 3340var _destroy = Item.prototype.destroy; 3341Item.prototype.destroy = function() { 3342 // call super 3343 _destroy.apply( this, arguments ); 3344 // reset display, #741 3345 this.css({ 3346 display: '' 3347 }); 3348}; 3349 3350return Item; 3351 3352})); 3353 3354/** 3355 * Isotope LayoutMode 3356 */ 3357 3358( function( window, factory ) { 3359 'use strict'; 3360 // universal module definition 3361 3362 if ( typeof define == 'function' && define.amd ) { 3363 // AMD 3364 define( 'isotope/js/layout-mode',[ 3365 'get-size/get-size', 3366 'outlayer/outlayer' 3367 ], 3368 factory ); 3369 } else if ( typeof exports == 'object' ) { 3370 // CommonJS 3371 module.exports = factory( 3372 require('get-size'), 3373 require('outlayer') 3374 ); 3375 } else { 3376 // browser global 3377 window.Isotope = window.Isotope || {}; 3378 window.Isotope.LayoutMode = factory( 3379 window.getSize, 3380 window.Outlayer 3381 ); 3382 } 3383 3384}( window, function factory( getSize, Outlayer ) { 3385 'use strict'; 3386 3387 // layout mode class 3388 function LayoutMode( isotope ) { 3389 this.isotope = isotope; 3390 // link properties 3391 if ( isotope ) { 3392 this.options = isotope.options[ this.namespace ]; 3393 this.element = isotope.element; 3394 this.items = isotope.filteredItems; 3395 this.size = isotope.size; 3396 } 3397 } 3398 3399 /** 3400 * some methods should just defer to default Outlayer method 3401 * and reference the Isotope instance as `this` 3402 **/ 3403 ( function() { 3404 var facadeMethods = [ 3405 '_resetLayout', 3406 '_getItemLayoutPosition', 3407 '_manageStamp', 3408 '_getContainerSize', 3409 '_getElementOffset', 3410 'needsResizeLayout' 3411 ]; 3412 3413 for ( var i=0, len = facadeMethods.length; i < len; i++ ) { 3414 var methodName = facadeMethods[i]; 3415 LayoutMode.prototype[ methodName ] = getOutlayerMethod( methodName ); 3416 } 3417 3418 function getOutlayerMethod( methodName ) { 3419 return function() { 3420 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 3421 }; 3422 } 3423 })(); 3424 3425 // ----- ----- // 3426 3427 // for horizontal layout modes, check vertical size 3428 LayoutMode.prototype.needsVerticalResizeLayout = function() {
vendor: 20,029 bytes, lines 3429-4164
3429 // don't trigger if size did not change 3430 var size = getSize( this.isotope.element ); 3431 // check that this.size and size are there 3432 // IE8 triggers resize on body size change, so they might not be 3433 var hasSizes = this.isotope.size && size; 3434 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 3435 }; 3436 3437 // ----- measurements ----- // 3438 3439 LayoutMode.prototype._getMeasurement = function() { 3440 this.isotope._getMeasurement.apply( this, arguments ); 3441 }; 3442 3443 LayoutMode.prototype.getColumnWidth = function() { 3444 this.getSegmentSize( 'column', 'Width' ); 3445 }; 3446 3447 LayoutMode.prototype.getRowHeight = function() { 3448 this.getSegmentSize( 'row', 'Height' ); 3449 }; 3450 3451 /** 3452 * get columnWidth or rowHeight 3453 * segment: 'column' or 'row' 3454 * size 'Width' or 'Height' 3455 **/ 3456 LayoutMode.prototype.getSegmentSize = function( segment, size ) { 3457 var segmentName = segment + size; 3458 var outerSize = 'outer' + size; 3459 // columnWidth / outerWidth // rowHeight / outerHeight 3460 this._getMeasurement( segmentName, outerSize ); 3461 // got rowHeight or columnWidth, we can chill 3462 if ( this[ segmentName ] ) { 3463 return; 3464 } 3465 // fall back to item of first element 3466 var firstItemSize = this.getFirstItemSize(); 3467 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 3468 // or size of container 3469 this.isotope.size[ 'inner' + size ]; 3470 }; 3471 3472 LayoutMode.prototype.getFirstItemSize = function() { 3473 var firstItem = this.isotope.filteredItems[0]; 3474 return firstItem && firstItem.element && getSize( firstItem.element ); 3475 }; 3476 3477 // ----- methods that should reference isotope ----- // 3478 3479 LayoutMode.prototype.layout = function() { 3480 this.isotope.layout.apply( this.isotope, arguments ); 3481 }; 3482 3483 LayoutMode.prototype.getSize = function() { 3484 this.isotope.getSize(); 3485 this.size = this.isotope.size; 3486 }; 3487 3488 // -------------------------- create -------------------------- // 3489 3490 LayoutMode.modes = {}; 3491 3492 LayoutMode.create = function( namespace, options ) { 3493 3494 function Mode() { 3495 LayoutMode.apply( this, arguments ); 3496 } 3497 3498 Mode.prototype = new LayoutMode(); 3499 3500 // default options 3501 if ( options ) { 3502 Mode.options = options; 3503 } 3504 3505 Mode.prototype.namespace = namespace; 3506 // register in Isotope 3507 LayoutMode.modes[ namespace ] = Mode; 3508 3509 return Mode; 3510 }; 3511 3512 return LayoutMode; 3513 3514})); 3515 3516/*! 3517 * Masonry v3.3.1 3518 * Cascading grid layout library 3519 * http://masonry.desandro.com 3520 * MIT License 3521 * by David DeSandro 3522 */ 3523 3524( function( window, factory ) { 3525 'use strict'; 3526 // universal module definition 3527 if ( typeof define === 'function' && define.amd ) { 3528 // AMD 3529 define( 'masonry/masonry',[ 3530 'outlayer/outlayer', 3531 'get-size/get-size', 3532 'fizzy-ui-utils/utils' 3533 ], 3534 factory ); 3535 } else if ( typeof exports === 'object' ) { 3536 // CommonJS 3537 module.exports = factory( 3538 require('outlayer'), 3539 require('get-size'), 3540 require('fizzy-ui-utils') 3541 ); 3542 } else { 3543 // browser global 3544 window.Masonry = factory( 3545 window.Outlayer, 3546 window.getSize, 3547 window.fizzyUIUtils 3548 ); 3549 } 3550 3551}( window, function factory( Outlayer, getSize, utils ) { 3552 3553 3554 3555// -------------------------- masonryDefinition -------------------------- // 3556 3557 // create an Outlayer layout class 3558 var Masonry = Outlayer.create('masonry'); 3559 3560 Masonry.prototype._resetLayout = function() { 3561 this.getSize(); 3562 this._getMeasurement( 'columnWidth', 'outerWidth' ); 3563 this._getMeasurement( 'gutter', 'outerWidth' ); 3564 this.measureColumns(); 3565 3566 // reset column Y 3567 var i = this.cols; 3568 this.colYs = []; 3569 while (i--) { 3570 this.colYs.push( 0 ); 3571 } 3572 3573 this.maxY = 0; 3574 }; 3575 3576 Masonry.prototype.measureColumns = function() { 3577 this.getContainerWidth(); 3578 // if columnWidth is 0, default to outerWidth of first item 3579 if ( !this.columnWidth ) { 3580 var firstItem = this.items[0]; 3581 var firstItemElem = firstItem && firstItem.element; 3582 // columnWidth fall back to item of first element 3583 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 3584 // if first elem has no width, default to size of container 3585 this.containerWidth; 3586 } 3587 3588 var columnWidth = this.columnWidth += this.gutter; 3589 3590 // calculate columns 3591 var containerWidth = this.containerWidth + this.gutter; 3592 var cols = containerWidth / columnWidth; 3593 // fix rounding errors, typically with gutters 3594 var excess = columnWidth - containerWidth % columnWidth; 3595 // if overshoot is less than a pixel, round up, otherwise floor it 3596 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 3597 cols = Math[ mathMethod ]( cols ); 3598 this.cols = Math.max( cols, 1 ); 3599 }; 3600 3601 Masonry.prototype.getContainerWidth = function() { 3602 // container is parent if fit width 3603 var container = this.options.isFitWidth ? this.element.parentNode : this.element; 3604 // check that this.size and size are there 3605 // IE8 triggers resize on body size change, so they might not be 3606 var size = getSize( container ); 3607 this.containerWidth = size && size.innerWidth; 3608 }; 3609 3610 Masonry.prototype._getItemLayoutPosition = function( item ) { 3611 item.getSize(); 3612 // how many columns does this brick span 3613 var remainder = item.size.outerWidth % this.columnWidth; 3614 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 3615 // round if off by 1 pixel, otherwise use ceil 3616 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 3617 colSpan = Math.min( colSpan, this.cols ); 3618 3619 var colGroup = this._getColGroup( colSpan ); 3620 // get the minimum Y value from the columns 3621 var minimumY = Math.min.apply( Math, colGroup ); 3622 var shortColIndex = utils.indexOf( colGroup, minimumY ); 3623 3624 // position the brick 3625 var position = { 3626 x: this.columnWidth * shortColIndex, 3627 y: minimumY 3628 }; 3629 3630 // apply setHeight to necessary columns 3631 var setHeight = minimumY + item.size.outerHeight; 3632 var setSpan = this.cols + 1 - colGroup.length; 3633 for ( var i = 0; i < setSpan; i++ ) { 3634 this.colYs[ shortColIndex + i ] = setHeight; 3635 } 3636 3637 return position; 3638 }; 3639 3640 /** 3641 * @param {Number} colSpan - number of columns the element spans 3642 * @returns {Array} colGroup 3643 */ 3644 Masonry.prototype._getColGroup = function( colSpan ) { 3645 if ( colSpan < 2 ) { 3646 // if brick spans only one column, use all the column Ys 3647 return this.colYs; 3648 } 3649 3650 var colGroup = []; 3651 // how many different places could this brick fit horizontally 3652 var groupCount = this.cols + 1 - colSpan; 3653 // for each group potential horizontal position 3654 for ( var i = 0; i < groupCount; i++ ) { 3655 // make an array of colY values for that one group 3656 var groupColYs = this.colYs.slice( i, i + colSpan ); 3657 // and get the max value of the array 3658 colGroup[i] = Math.max.apply( Math, groupColYs ); 3659 } 3660 return colGroup; 3661 }; 3662 3663 Masonry.prototype._manageStamp = function( stamp ) { 3664 var stampSize = getSize( stamp ); 3665 var offset = this._getElementOffset( stamp ); 3666 // get the columns that this stamp affects 3667 var firstX = this.options.isOriginLeft ? offset.left : offset.right; 3668 var lastX = firstX + stampSize.outerWidth; 3669 var firstCol = Math.floor( firstX / this.columnWidth ); 3670 firstCol = Math.max( 0, firstCol ); 3671 var lastCol = Math.floor( lastX / this.columnWidth ); 3672 // lastCol should not go over if multiple of columnWidth #425 3673 lastCol -= lastX % this.columnWidth ? 0 : 1; 3674 lastCol = Math.min( this.cols - 1, lastCol ); 3675 // set colYs to bottom of the stamp 3676 var stampMaxY = ( this.options.isOriginTop ? offset.top : offset.bottom ) + 3677 stampSize.outerHeight; 3678 for ( var i = firstCol; i <= lastCol; i++ ) { 3679 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 3680 } 3681 }; 3682 3683 Masonry.prototype._getContainerSize = function() { 3684 this.maxY = Math.max.apply( Math, this.colYs ); 3685 var size = { 3686 height: this.maxY 3687 }; 3688 3689 if ( this.options.isFitWidth ) { 3690 size.width = this._getContainerFitWidth(); 3691 } 3692 3693 return size; 3694 }; 3695 3696 Masonry.prototype._getContainerFitWidth = function() { 3697 var unusedCols = 0; 3698 // count unused columns 3699 var i = this.cols; 3700 while ( --i ) { 3701 if ( this.colYs[i] !== 0 ) { 3702 break; 3703 } 3704 unusedCols++; 3705 } 3706 // fit container to columns that have been used 3707 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 3708 }; 3709 3710 Masonry.prototype.needsResizeLayout = function() { 3711 var previousWidth = this.containerWidth; 3712 this.getContainerWidth(); 3713 return previousWidth !== this.containerWidth; 3714 }; 3715 3716 return Masonry; 3717 3718})); 3719 3720/*! 3721 * Masonry layout mode 3722 * sub-classes Masonry 3723 * http://masonry.desandro.com 3724 */ 3725 3726( function( window, factory ) { 3727 'use strict'; 3728 // universal module definition 3729 if ( typeof define == 'function' && define.amd ) { 3730 // AMD 3731 define( 'isotope/js/layout-modes/masonry',[ 3732 '../layout-mode', 3733 'masonry/masonry' 3734 ], 3735 factory ); 3736 } else if ( typeof exports == 'object' ) { 3737 // CommonJS 3738 module.exports = factory( 3739 require('../layout-mode'), 3740 require('masonry-layout') 3741 ); 3742 } else { 3743 // browser global 3744 factory( 3745 window.Isotope.LayoutMode, 3746 window.Masonry 3747 ); 3748 } 3749 3750}( window, function factory( LayoutMode, Masonry ) { 3751'use strict'; 3752 3753// -------------------------- helpers -------------------------- // 3754 3755// extend objects 3756function extend( a, b ) { 3757 for ( var prop in b ) { 3758 a[ prop ] = b[ prop ]; 3759 } 3760 return a; 3761} 3762 3763// -------------------------- masonryDefinition -------------------------- // 3764 3765 // create an Outlayer layout class 3766 var MasonryMode = LayoutMode.create('masonry'); 3767 3768 // save on to these methods 3769 var _getElementOffset = MasonryMode.prototype._getElementOffset; 3770 var layout = MasonryMode.prototype.layout; 3771 var _getMeasurement = MasonryMode.prototype._getMeasurement; 3772 3773 // sub-class Masonry 3774 extend( MasonryMode.prototype, Masonry.prototype ); 3775 3776 // set back, as it was overwritten by Masonry 3777 MasonryMode.prototype._getElementOffset = _getElementOffset; 3778 MasonryMode.prototype.layout = layout; 3779 MasonryMode.prototype._getMeasurement = _getMeasurement; 3780 3781 var measureColumns = MasonryMode.prototype.measureColumns; 3782 MasonryMode.prototype.measureColumns = function() { 3783 // set items, used if measuring first item 3784 this.items = this.isotope.filteredItems; 3785 measureColumns.call( this ); 3786 }; 3787 3788 // HACK copy over isOriginLeft/Top options 3789 var _manageStamp = MasonryMode.prototype._manageStamp; 3790 MasonryMode.prototype._manageStamp = function() { 3791 this.options.isOriginLeft = this.isotope.options.isOriginLeft; 3792 this.options.isOriginTop = this.isotope.options.isOriginTop; 3793 _manageStamp.apply( this, arguments ); 3794 }; 3795 3796 return MasonryMode; 3797 3798})); 3799 3800/** 3801 * fitRows layout mode 3802 */ 3803 3804( function( window, factory ) { 3805 'use strict'; 3806 // universal module definition 3807 if ( typeof define == 'function' && define.amd ) { 3808 // AMD 3809 define( 'isotope/js/layout-modes/fit-rows',[ 3810 '../layout-mode' 3811 ], 3812 factory ); 3813 } else if ( typeof exports == 'object' ) { 3814 // CommonJS 3815 module.exports = factory( 3816 require('../layout-mode') 3817 ); 3818 } else { 3819 // browser global 3820 factory( 3821 window.Isotope.LayoutMode 3822 ); 3823 } 3824 3825}( window, function factory( LayoutMode ) { 3826'use strict'; 3827 3828var FitRows = LayoutMode.create('fitRows'); 3829 3830FitRows.prototype._resetLayout = function() { 3831 this.x = 0; 3832 this.y = 0; 3833 this.maxY = 0; 3834 this._getMeasurement( 'gutter', 'outerWidth' ); 3835}; 3836 3837FitRows.prototype._getItemLayoutPosition = function( item ) { 3838 item.getSize(); 3839 3840 var itemWidth = item.size.outerWidth + this.gutter; 3841 // if this element cannot fit in the current row 3842 var containerWidth = this.isotope.size.innerWidth + this.gutter; 3843 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 3844 this.x = 0; 3845 this.y = this.maxY; 3846 } 3847 3848 var position = { 3849 x: this.x, 3850 y: this.y 3851 }; 3852 3853 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 3854 this.x += itemWidth; 3855 3856 return position; 3857}; 3858 3859FitRows.prototype._getContainerSize = function() { 3860 return { height: this.maxY }; 3861}; 3862 3863return FitRows; 3864 3865})); 3866 3867/** 3868 * vertical layout mode 3869 */ 3870 3871( function( window, factory ) { 3872 'use strict'; 3873 // universal module definition 3874 if ( typeof define == 'function' && define.amd ) { 3875 // AMD 3876 define( 'isotope/js/layout-modes/vertical',[ 3877 '../layout-mode' 3878 ], 3879 factory ); 3880 } else if ( typeof exports == 'object' ) { 3881 // CommonJS 3882 module.exports = factory( 3883 require('../layout-mode') 3884 ); 3885 } else { 3886 // browser global 3887 factory( 3888 window.Isotope.LayoutMode 3889 ); 3890 } 3891 3892}( window, function factory( LayoutMode ) { 3893'use strict'; 3894 3895var Vertical = LayoutMode.create( 'vertical', { 3896 horizontalAlignment: 0 3897}); 3898 3899Vertical.prototype._resetLayout = function() { 3900 this.y = 0; 3901}; 3902 3903Vertical.prototype._getItemLayoutPosition = function( item ) { 3904 item.getSize(); 3905 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 3906 this.options.horizontalAlignment; 3907 var y = this.y; 3908 this.y += item.size.outerHeight; 3909 return { x: x, y: y }; 3910}; 3911 3912Vertical.prototype._getContainerSize = function() { 3913 return { height: this.y }; 3914}; 3915 3916return Vertical; 3917 3918})); 3919 3920/*! 3921 * Isotope v2.2.2 3922 * 3923 * Licensed GPLv3 for open source use 3924 * or Isotope Commercial License for commercial use 3925 * 3926 * http://isotope.metafizzy.co 3927 * Copyright 2015 Metafizzy 3928 */ 3929 3930( function( window, factory ) { 3931 'use strict'; 3932 // universal module definition 3933 3934 if ( typeof define == 'function' && define.amd ) { 3935 // AMD 3936 define( [ 3937 'outlayer/outlayer', 3938 'get-size/get-size', 3939 'matches-selector/matches-selector', 3940 'fizzy-ui-utils/utils', 3941 'isotope/js/item', 3942 'isotope/js/layout-mode', 3943 // include default layout modes 3944 'isotope/js/layout-modes/masonry', 3945 'isotope/js/layout-modes/fit-rows', 3946 'isotope/js/layout-modes/vertical' 3947 ], 3948 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 3949 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 3950 }); 3951 } else if ( typeof exports == 'object' ) { 3952 // CommonJS 3953 module.exports = factory( 3954 window, 3955 require('outlayer'), 3956 require('get-size'), 3957 require('desandro-matches-selector'), 3958 require('fizzy-ui-utils'), 3959 require('./item'), 3960 require('./layout-mode'), 3961 // include default layout modes 3962 require('./layout-modes/masonry'), 3963 require('./layout-modes/fit-rows'), 3964 require('./layout-modes/vertical') 3965 ); 3966 } else { 3967 // browser global 3968 window.Isotope = factory( 3969 window, 3970 window.Outlayer, 3971 window.getSize, 3972 window.matchesSelector, 3973 window.fizzyUIUtils, 3974 window.Isotope.Item, 3975 window.Isotope.LayoutMode 3976 ); 3977 } 3978 3979}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 3980 Item, LayoutMode ) { 3981 3982 3983 3984// -------------------------- vars -------------------------- // 3985 3986var jQuery = window.jQuery; 3987 3988// -------------------------- helpers -------------------------- // 3989 3990var trim = String.prototype.trim ? 3991 function( str ) { 3992 return str.trim(); 3993 } : 3994 function( str ) { 3995 return str.replace( /^\s+|\s+$/g, '' ); 3996 }; 3997 3998var docElem = document.documentElement; 3999 4000var getText = docElem.textContent ? 4001 function( elem ) { 4002 return elem.textContent; 4003 } : 4004 function( elem ) { 4005 return elem.innerText; 4006 }; 4007 4008// -------------------------- isotopeDefinition -------------------------- // 4009 4010 // create an Outlayer layout class 4011 var Isotope = Outlayer.create( 'isotope', { 4012 layoutMode: "masonry", 4013 isJQueryFiltering: true, 4014 sortAscending: true 4015 }); 4016 4017 Isotope.Item = Item; 4018 Isotope.LayoutMode = LayoutMode; 4019 4020 Isotope.prototype._create = function() { 4021 this.itemGUID = 0; 4022 // functions that sort items 4023 this._sorters = {}; 4024 this._getSorters(); 4025 // call super 4026 Outlayer.prototype._create.call( this ); 4027 4028 // create layout modes 4029 this.modes = {}; 4030 // start filteredItems with all items 4031 this.filteredItems = this.items; 4032 // keep of track of sortBys 4033 this.sortHistory = [ 'original-order' ]; 4034 // create from registered layout modes 4035 for ( var name in LayoutMode.modes ) { 4036 this._initLayoutMode( name ); 4037 } 4038 }; 4039 4040 Isotope.prototype.reloadItems = function() { 4041 // reset item ID counter 4042 this.itemGUID = 0; 4043 // call super 4044 Outlayer.prototype.reloadItems.call( this ); 4045 }; 4046 4047 Isotope.prototype._itemize = function() { 4048 var items = Outlayer.prototype._itemize.apply( this, arguments ); 4049 // assign ID for original-order 4050 for ( var i=0, len = items.length; i < len; i++ ) { 4051 var item = items[i]; 4052 item.id = this.itemGUID++; 4053 } 4054 this._updateItemsSortData( items ); 4055 return items; 4056 }; 4057 4058 4059 // -------------------------- layout -------------------------- // 4060 4061 Isotope.prototype._initLayoutMode = function( name ) { 4062 var Mode = LayoutMode.modes[ name ]; 4063 // set mode options 4064 // HACK extend initial options, back-fill in default options 4065 var initialOpts = this.options[ name ] || {}; 4066 this.options[ name ] = Mode.options ? 4067 utils.extend( Mode.options, initialOpts ) : initialOpts; 4068 // init layout mode instance 4069 this.modes[ name ] = new Mode( this ); 4070 }; 4071 4072 4073 Isotope.prototype.layout = function() { 4074 // if first time doing layout, do all magic 4075 if ( !this._isLayoutInited && this.options.isInitLayout ) { 4076 this.arrange(); 4077 return; 4078 } 4079 this._layout(); 4080 }; 4081 4082 // private method to be used in layout() & magic() 4083 Isotope.prototype._layout = function() { 4084 // don't animate first layout 4085 var isInstant = this._getIsInstant(); 4086 // layout flow 4087 this._resetLayout(); 4088 this._manageStamps(); 4089 this.layoutItems( this.filteredItems, isInstant ); 4090 4091 // flag for initalized 4092 this._isLayoutInited = true; 4093 }; 4094 4095 // filter + sort + layout 4096 Isotope.prototype.arrange = function( opts ) { 4097 // set any options pass 4098 this.option( opts ); 4099 this._getIsInstant(); 4100 // filter, sort, and layout 4101 4102 // filter 4103 var filtered = this._filter( this.items ); 4104 this.filteredItems = filtered.matches; 4105 4106 var _this = this; 4107 function hideReveal() { 4108 _this.reveal( filtered.needReveal ); 4109 _this.hide( filtered.needHide ); 4110 } 4111 4112 this._bindArrangeComplete(); 4113 4114 if ( this._isInstant ) { 4115 this._noTransition( hideReveal ); 4116 } else { 4117 hideReveal(); 4118 } 4119 4120 this._sort(); 4121 this._layout(); 4122 }; 4123 // alias to _init for main plugin method 4124 Isotope.prototype._init = Isotope.prototype.arrange; 4125 4126 // HACK 4127 // Don't animate/transition first layout 4128 // Or don't animate/transition other layouts 4129 Isotope.prototype._getIsInstant = function() { 4130 var isInstant = this.options.isLayoutInstant !== undefined ? 4131 this.options.isLayoutInstant : !this._isLayoutInited; 4132 this._isInstant = isInstant; 4133 return isInstant; 4134 }; 4135 4136 // listen for layoutComplete, hideComplete and revealComplete 4137 // to trigger arrangeComplete 4138 Isotope.prototype._bindArrangeComplete = function() { 4139 // listen for 3 events to trigger arrangeComplete 4140 var isLayoutComplete, isHideComplete, isRevealComplete; 4141 var _this = this; 4142 function arrangeParallelCallback() { 4143 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 4144 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 4145 } 4146 } 4147 this.once( 'layoutComplete', function() { 4148 isLayoutComplete = true; 4149 arrangeParallelCallback(); 4150 }); 4151 this.once( 'hideComplete', function() { 4152 isHideComplete = true; 4153 arrangeParallelCallback(); 4154 }); 4155 this.once( 'revealComplete', function() { 4156 isRevealComplete = true; 4157 arrangeParallelCallback(); 4158 }); 4159 }; 4160 4161 // -------------------------- filter -------------------------- // 4162 4163 Isotope.prototype._filter = function( items ) { 4164 var filter = this.options.filter;
4165 filter = filter || '*'; 4166 var matches = []; 4167 var hiddenMatched = []; 4168 var visibleUnmatched = []; 4169 4170 var test = this._getFilterTest( filter ); 4171 4172 // test each item 4173 for ( var i=0, len = items.length; i < len; i++ ) { 4174 var item = items[i]; 4175 if ( item.isIgnored ) { 4176 continue; 4177 } 4178 // add item to either matched or unmatched group 4179 var isMatched = test( item ); 4180 // item.isFilterMatched = isMatched; 4181 // add to matches if its a match 4182 if ( isMatched ) { 4183 matches.push( item ); 4184 } 4185 // add to additional group if item needs to be hidden or revealed 4186 if ( isMatched && item.isHidden ) { 4187 hiddenMatched.push( item ); 4188 } else if ( !isMatched && !item.isHidden ) { 4189 visibleUnmatched.push( item ); 4190 } 4191 } 4192 4193 // return collections of items to be manipulated 4194 return { 4195 matches: matches, 4196 needReveal: hiddenMatched, 4197 needHide: visibleUnmatched 4198 }; 4199 }; 4200 4201 // get a jQuery, function, or a matchesSelector test given the filter 4202 Isotope.prototype._getFilterTest = function( filter ) { 4203 if ( jQuery && this.options.isJQueryFiltering ) { 4204 // use jQuery 4205 return function( item ) { 4206 return jQuery( item.element ).is( filter ); 4207 }; 4208 } 4209 if ( typeof filter == 'function' ) { 4210 // use filter as function 4211 return function( item ) { 4212 return filter( item.element ); 4213 }; 4214 } 4215 // default, use filter as selector string 4216 return function( item ) { 4217 return matchesSelector( item.element, filter ); 4218 }; 4219 }; 4220 4221 // -------------------------- sorting -------------------------- // 4222 4223 /** 4224 * @params {Array} elems 4225 * @public 4226 */ 4227 Isotope.prototype.updateSortData = function( elems ) { 4228 // get items 4229 var items; 4230 if ( elems ) { 4231 elems = utils.makeArray( elems ); 4232 items = this.getItems( elems ); 4233 } else { 4234 // update all items if no elems provided 4235 items = this.items; 4236 } 4237 4238 this._getSorters(); 4239 this._updateItemsSortData( items ); 4240 }; 4241 4242 Isotope.prototype._getSorters = function() { 4243 var getSortData = this.options.getSortData; 4244 for ( var key in getSortData ) { 4245 var sorter = getSortData[ key ]; 4246 this._sorters[ key ] = mungeSorter( sorter ); 4247 } 4248 }; 4249 4250 /** 4251 * @params {Array} items - of Isotope.Items 4252 * @private 4253 */ 4254 Isotope.prototype._updateItemsSortData = function( items ) { 4255 // do not update if no items 4256 var len = items && items.length; 4257 4258 for ( var i=0; len && i < len; i++ ) { 4259 var item = items[i]; 4260 item.updateSortData(); 4261 } 4262 }; 4263 4264 // ----- munge sorter ----- // 4265 4266 // encapsulate this, as we just need mungeSorter 4267 // other functions in here are just for munging 4268 var mungeSorter = ( function() { 4269 // add a magic layer to sorters for convienent shorthands 4270 // `.foo-bar` will use the text of .foo-bar querySelector 4271 // `[foo-bar]` will use attribute 4272 // you can also add parser 4273 // `.foo-bar parseInt` will parse that as a number 4274 function mungeSorter( sorter ) { 4275 // if not a string, return function or whatever it is 4276 if ( typeof sorter != 'string' ) { 4277 return sorter; 4278 } 4279 // parse the sorter string 4280 var args = trim( sorter ).split(' '); 4281 var query = args[0]; 4282 // check if query looks like [an-attribute] 4283 var attrMatch = query.match( /^\[(.+)\]$/ ); 4284 var attr = attrMatch && attrMatch[1]; 4285 var getValue = getValueGetter( attr, query ); 4286 // use second argument as a parser 4287 var parser = Isotope.sortDataParsers[ args[1] ]; 4288 // parse the value, if there was a parser 4289 sorter = parser ? function( elem ) { 4290 return elem && parser( getValue( elem ) ); 4291 } : 4292 // otherwise just return value 4293 function( elem ) { 4294 return elem && getValue( elem ); 4295 }; 4296 4297 return sorter; 4298 } 4299 4300 // get an attribute getter, or get text of the querySelector 4301 function getValueGetter( attr, query ) { 4302 var getValue; 4303 // if query looks like [foo-bar], get attribute 4304 if ( attr ) { 4305 getValue = function( elem ) { 4306 return elem.getAttribute( attr ); 4307 }; 4308 } else { 4309 // otherwise, assume its a querySelector, and get its text 4310 getValue = function( elem ) { 4311 var child = elem.querySelector( query ); 4312 return child && getText( child ); 4313 }; 4314 } 4315 return getValue; 4316 } 4317 4318 return mungeSorter; 4319 })(); 4320 4321 // parsers used in getSortData shortcut strings 4322 Isotope.sortDataParsers = { 4323 'parseInt': function( val ) { 4324 return parseInt( val, 10 ); 4325 }, 4326 'parseFloat': function( val ) { 4327 return parseFloat( val ); 4328 } 4329 }; 4330 4331 // ----- sort method ----- // 4332 4333 // sort filteredItem order 4334 Isotope.prototype._sort = function() { 4335 var sortByOpt = this.options.sortBy; 4336 if ( !sortByOpt ) { 4337 return; 4338 } 4339 // concat all sortBy and sortHistory 4340 var sortBys = [].concat.apply( sortByOpt, this.sortHistory ); 4341 // sort magic 4342 var itemSorter = getItemSorter( sortBys, this.options.sortAscending ); 4343 this.filteredItems.sort( itemSorter ); 4344 // keep track of sortBy History 4345 if ( sortByOpt != this.sortHistory[0] ) { 4346 // add to front, oldest goes in last 4347 this.sortHistory.unshift( sortByOpt ); 4348 } 4349 }; 4350 4351 // returns a function used for sorting 4352 function getItemSorter( sortBys, sortAsc ) { 4353 return function sorter( itemA, itemB ) { 4354 // cycle through all sortKeys 4355 for ( var i = 0, len = sortBys.length; i < len; i++ ) { 4356 var sortBy = sortBys[i]; 4357 var a = itemA.sortData[ sortBy ]; 4358 var b = itemB.sortData[ sortBy ]; 4359 if ( a > b || a < b ) { 4360 // if sortAsc is an object, use the value given the sortBy key
4361 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 4362 var direction = isAscending ? 1 : -1; 4363 return ( a > b ? 1 : -1 ) * direction; 4364 } 4365 } 4366 return 0; 4367 }; 4368 } 4369 4370 // -------------------------- methods -------------------------- // 4371 4372 // get layout mode 4373 Isotope.prototype._mode = function() { 4374 var layoutMode = this.options.layoutMode; 4375 var mode = this.modes[ layoutMode ]; 4376 if ( !mode ) { 4377 // TODO console.error 4378 throw new Error( 'No layout mode: ' + layoutMode ); 4379 } 4380 // HACK sync mode's options 4381 // any options set after init for layout mode need to be synced 4382 mode.options = this.options[ layoutMode ]; 4383 return mode; 4384 }; 4385 4386 Isotope.prototype._resetLayout = function() { 4387 // trigger original reset layout 4388 Outlayer.prototype._resetLayout.call( this ); 4389 this._mode()._resetLayout(); 4390 }; 4391 4392 Isotope.prototype._getItemLayoutPosition = function( item ) { 4393 return this._mode()._getItemLayoutPosition( item ); 4394 }; 4395 4396 Isotope.prototype._manageStamp = function( stamp ) { 4397 this._mode()._manageStamp( stamp ); 4398 }; 4399 4400 Isotope.prototype._getContainerSize = function() { 4401 return this._mode()._getContainerSize(); 4402 }; 4403 4404 Isotope.prototype.needsResizeLayout = function() { 4405 return this._mode().needsResizeLayout(); 4406 }; 4407 4408 // -------------------------- adding & removing -------------------------- // 4409 4410 // HEADS UP overwrites default Outlayer appended 4411 Isotope.prototype.appended = function( elems ) { 4412 var items = this.addItems( elems ); 4413 if ( !items.length ) { 4414 return; 4415 } 4416 // filter, layout, reveal new items 4417 var filteredItems = this._filterRevealAdded( items ); 4418 // add to filteredItems 4419 this.filteredItems = this.filteredItems.concat( filteredItems ); 4420 }; 4421 4422 // HEADS UP overwrites default Outlayer prepended 4423 Isotope.prototype.prepended = function( elems ) { 4424 var items = this._itemize( elems ); 4425 if ( !items.length ) { 4426 return; 4427 } 4428 // start new layout 4429 this._resetLayout(); 4430 this._manageStamps(); 4431 // filter, layout, reveal new items 4432 var filteredItems = this._filterRevealAdded( items ); 4433 // layout previous items 4434 this.layoutItems( this.filteredItems ); 4435 // add to items and filteredItems 4436 this.filteredItems = filteredItems.concat( this.filteredItems ); 4437 this.items = items.concat( this.items ); 4438 }; 4439 4440 Isotope.prototype._filterRevealAdded = function( items ) { 4441 var filtered = this._filter( items ); 4442 this.hide( filtered.needHide ); 4443 // reveal all new items 4444 this.reveal( filtered.matches ); 4445 // layout new items, no transition 4446 this.layoutItems( filtered.matches, true ); 4447 return filtered.matches; 4448 }; 4449 4450 /** 4451 * Filter, sort, and layout newly-appended item elements 4452 * @param {Array or NodeList or Element} elems 4453 */ 4454 Isotope.prototype.insert = function( elems ) { 4455 var items = this.addItems( elems ); 4456 if ( !items.length ) { 4457 return; 4458 } 4459 // append item elements 4460 var i, item; 4461 var len = items.length; 4462 for ( i=0; i < len; i++ ) { 4463 item = items[i]; 4464 this.element.appendChild( item.element ); 4465 } 4466 // filter new stuff 4467 var filteredInsertItems = this._filter( items ).matches; 4468 // set flag 4469 for ( i=0; i < len; i++ ) { 4470 items[i].isLayoutInstant = true; 4471 } 4472 this.arrange(); 4473 // reset flag 4474 for ( i=0; i < len; i++ ) { 4475 delete items[i].isLayoutInstant; 4476 } 4477 this.reveal( filteredInsertItems ); 4478 }; 4479 4480 var _remove = Isotope.prototype.remove; 4481 Isotope.prototype.remove = function( elems ) { 4482 elems = utils.makeArray( elems ); 4483 var removeItems = this.getItems( elems ); 4484 // do regular thing 4485 _remove.call( this, elems ); 4486 // bail if no items to remove 4487 var len = removeItems && removeItems.length; 4488 if ( !len ) { 4489 return; 4490 } 4491 // remove elems from filteredItems 4492 for ( var i=0; i < len; i++ ) { 4493 var item = removeItems[i]; 4494 // remove item from collection 4495 utils.removeFrom( this.filteredItems, item ); 4496 } 4497 }; 4498 4499 Isotope.prototype.shuffle = function() { 4500 // update random sortData 4501 for ( var i=0, len = this.items.length; i < len; i++ ) { 4502 var item = this.items[i]; 4503 item.sortData.random = Math.random(); 4504 } 4505 this.options.sortBy = 'random'; 4506 this._sort(); 4507 this._layout(); 4508 }; 4509 4510 /** 4511 * trigger fn without transition 4512 * kind of hacky to have this in the first place 4513 * @param {Function} fn 4514 * @returns ret 4515 * @private 4516 */ 4517 Isotope.prototype._noTransition = function( fn ) { 4518 // save transitionDuration before disabling 4519 var transitionDuration = this.options.transitionDuration; 4520 // disable transition 4521 this.options.transitionDuration = 0; 4522 // do it 4523 var returnValue = fn.call( this ); 4524 // re-enable transition for reveal 4525 this.options.transitionDuration = transitionDuration; 4526 return returnValue; 4527 }; 4528 4529 // ----- helper methods ----- // 4530 4531 /** 4532 * getter method for getting filtered item elements 4533 * @returns {Array} elems - collection of item elements 4534 */ 4535 Isotope.prototype.getFilteredItemElements = function() { 4536 var elems = []; 4537 for ( var i=0, len = this.filteredItems.length; i < len; i++ ) { 4538 elems.push( this.filteredItems[i].element ); 4539 } 4540 return elems; 4541 }; 4542 4543 // ----- ----- // 4544 4545 return Isotope; 4546 4547})); 4548 4549 4550/*! 4551 * Packery layout mode PACKAGED v2.0.1 4552 * sub-classes Packery 4553 */ 4554 4555!function(a,b){"function"==typeof define&&define.amd?define("packery/js/rect",b):"object"==typeof module&&module.exports?module.exports=b():(a.Packery=a.Packery||{},a.Packery.Rect=b())}(window,function(){function a(b){for(var c in a.defaults)this[c]=a.defaults[c];for(c in b)this[c]=b[c]}a.defaults={x:0,y:0,width:0,height:0};var b=a.prototype;return b.contains=function(a){var b=a.width||0,c=a.height||0;return this.x<=a.x&&this.y<=a.y&&this.x+this.width>=a.x+b&&this.y+this.height>=a.y+c},b.overlaps=function(a){var b=this.x+this.width,c=this.y+this.height,d=a.x+a.width,e=a.y+a.height;return this.x<d&&b>a.x&&this.y<e&&c>a.y},b.getMaximalFreeRects=function(b){if(!this.overlaps(b))return!1;var c,d=[],e=this.x+this.width,f=this.y+this.height,g=b.x+b.width,h=b.y+b.height;return this.y<b.y&&(c=new a({x:this.x,y:this.y,width:this.width,height:b.y-this.y}),d.push(c)),e>g&&(c=new a({x:g,y:this.y,width:e-g,height:this.height}),d.push(c)),f>h&&(c=new a({x:this.x,y:h,width:this.width,height:f-h}),d.push(c)),this.x<b.x&&(c=new a({x:this.x,y:this.y,width:b.x-this.x,height:this.height}),d.push(c)),d},b.canFit=function(a){return this.width>=a.width&&this.height>=a.height},a}),function(a,b){if("function"==typeof define&&define.amd)define("packery/js/packer",["./rect"],b);else if("object"==typeof module&&module.exports)module.exports=b(require("./rect"));else{var c=a.Packery=a.Packery||{};c.Packer=b(c.Rect)}}(window,function(a){function b(a,b,c){this.width=a||0,this.height=b||0,this.sortDirection=c||"downwardLeftToRight",this.reset()}var c=b.prototype;c.reset=function(){this.spaces=[];var b=new a({x:0,y:0,width:this.width,height:this.height});this.spaces.push(b),this.sorter=d[this.sortDirection]||d.downwardLeftToRight},c.pack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b];if(c.canFit(a)){this.placeInSpace(a,c);break}}},c.columnPack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b],d=c.x<=a.x&&c.x+c.width>=a.x+a.width&&c.height>=a.height-.01;if(d){a.y=c.y,this.placed(a);break}}},c.rowPack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b],d=c.y<=a.y&&c.y+c.height>=a.y+a.height&&c.width>=a.width-.01;if(d){a.x=c.x,this.placed(a);break}}},c.placeInSpace=function(a,b){a.x=b.x,a.y=b.y,this.placed(a)},c.placed=function(a){for(var b=[],c=0;c<this.spaces.length;c++){var d=this.spaces[c],e=d.getMaximalFreeRects(a);
vendor: 8,438 bytes, line 4555
4555e?b.push.apply(b,e):b.push(d)}this.spaces=b,this.mergeSortSpaces()},c.mergeSortSpaces=function(){b.mergeRects(this.spaces),this.spaces.sort(this.sorter)},c.addSpace=function(a){this.spaces.push(a),this.mergeSortSpaces()},b.mergeRects=function(a){var b=0,c=a[b];a:for(;c;){for(var d=0,e=a[b+d];e;){if(e==c)d++;else{if(e.contains(c)){a.splice(b,1),c=a[b];continue a}c.contains(e)?a.splice(b+d,1):d++}e=a[b+d]}b++,c=a[b]}return a};var d={downwardLeftToRight:function(a,b){return a.y-b.y||a.x-b.x},rightwardTopToBottom:function(a,b){return a.x-b.x||a.y-b.y}};return b}),function(a,b){"function"==typeof define&&define.amd?define("packery/js/item",["outlayer/outlayer","./rect"],b):"object"==typeof module&&module.exports?module.exports=b(require("outlayer"),require("./rect")):a.Packery.Item=b(a.Outlayer,a.Packery.Rect)}(window,function(a,b){var c=document.documentElement.style,d="string"==typeof c.transform?"transform":"WebkitTransform",e=function(){a.Item.apply(this,arguments)},f=e.prototype=Object.create(a.Item.prototype),g=f._create;f._create=function(){g.call(this),this.rect=new b};var h=f.moveTo;return f.moveTo=function(a,b){var c=Math.abs(this.position.x-a),d=Math.abs(this.position.y-b),e=this.layout.dragItemCount&&!this.isPlacing&&!this.isTransitioning&&1>c&&1>d;return e?void this.goTo(a,b):void h.apply(this,arguments)},f.enablePlacing=function(){this.removeTransitionStyles(),this.isTransitioning&&d&&(this.element.style[d]="none"),this.isTransitioning=!1,this.getSize(),this.layout._setRectSize(this.element,this.rect),this.isPlacing=!0},f.disablePlacing=function(){this.isPlacing=!1},f.removeElem=function(){this.element.parentNode.removeChild(this.element),this.layout.packer.addSpace(this.rect),this.emitEvent("remove",[this])},f.showDropPlaceholder=function(){var a=this.dropPlaceholder;a||(a=this.dropPlaceholder=document.createElement("div"),a.className="packery-drop-placeholder",a.style.position="absolute"),a.style.width=this.size.width+"px",a.style.height=this.size.height+"px",this.positionDropPlaceholder(),this.layout.element.appendChild(a)},f.positionDropPlaceholder=function(){this.dropPlaceholder.style[d]="translate("+this.rect.x+"px, "+this.rect.y+"px)"},f.hideDropPlaceholder=function(){this.layout.element.removeChild(this.dropPlaceholder)},e}),function(a,b){"function"==typeof define&&define.amd?define("packery/js/packery",["get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],b):"object"==typeof module&&module.exports?module.exports=b(require("get-size"),require("outlayer"),require("./rect"),require("./packer"),require("./item")):a.Packery=b(a.getSize,a.Outlayer,a.Packery.Rect,a.Packery.Packer,a.Packery.Item)}(window,function(a,b,c,d,e){function f(a,b){return a.position.y-b.position.y||a.position.x-b.position.x}function g(a,b){return a.position.x-b.position.x||a.position.y-b.position.y}function h(a,b){var c=b.x-a.x,d=b.y-a.y;return Math.sqrt(c*c+d*d)}c.prototype.canFit=function(a){return this.width>=a.width-1&&this.height>=a.height-1};var i=b.create("packery");i.Item=e;var j=i.prototype;j._create=function(){b.prototype._create.call(this),this.packer=new d,this.shiftPacker=new d,this.isEnabled=!0,this.dragItemCount=0;var a=this;this.handleDraggabilly={dragStart:function(){a.itemDragStart(this.element)},dragMove:function(){a.itemDragMove(this.element,this.position.x,this.position.y)},dragEnd:function(){a.itemDragEnd(this.element)}},this.handleUIDraggable={start:function(b,c){c&&a.itemDragStart(b.currentTarget)},drag:function(b,c){c&&a.itemDragMove(b.currentTarget,c.position.left,c.position.top)},stop:function(b,c){c&&a.itemDragEnd(b.currentTarget)}}},j._resetLayout=function(){this.getSize(),this._getMeasurements();var a,b,c;this._getOption("horizontal")?(a=1/0,b=this.size.innerHeight+this.gutter,c="rightwardTopToBottom"):(a=this.size.innerWidth+this.gutter,b=1/0,c="downwardLeftToRight"),this.packer.width=this.shiftPacker.width=a,this.packer.height=this.shiftPacker.height=b,this.packer.sortDirection=this.shiftPacker.sortDirection=c,this.packer.reset(),this.maxY=0,this.maxX=0},j._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},j._getItemLayoutPosition=function(a){if(this._setRectSize(a.element,a.rect),this.isShifting||this.dragItemCount>0){var b=this._getPackMethod();this.packer[b](a.rect)}else this.packer.pack(a.rect);return this._setMaxXY(a.rect),a.rect},j.shiftLayout=function(){this.isShifting=!0,this.layout(),delete this.isShifting},j._getPackMethod=function(){return this._getOption("horizontal")?"rowPack":"columnPack"},j._setMaxXY=function(a){this.maxX=Math.max(a.x+a.width,this.maxX),this.maxY=Math.max(a.y+a.height,this.maxY)},j._setRectSize=function(b,c){var d=a(b),e=d.outerWidth,f=d.outerHeight;(e||f)&&(e=this._applyGridGutter(e,this.columnWidth),f=this._applyGridGutter(f,this.rowHeight)),c.width=Math.min(e,this.packer.width),c.height=Math.min(f,this.packer.height)},j._applyGridGutter=function(a,b){if(!b)return a+this.gutter;b+=this.gutter;var c=a%b,d=c&&1>c?"round":"ceil";return a=Math[d](a/b)*b},j._getContainerSize=function(){return this._getOption("horizontal")?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},j._manageStamp=function(a){var b,d=this.getItem(a);if(d&&d.isPlacing)b=d.rect;else{var e=this._getElementOffset(a);b=new c({x:this._getOption("originLeft")?e.left:e.right,y:this._getOption("originTop")?e.top:e.bottom})}this._setRectSize(a,b),this.packer.placed(b),this._setMaxXY(b)},j.sortItemsByPosition=function(){var a=this._getOption("horizontal")?g:f;this.items.sort(a)},j.fit=function(a,b,c){var d=this.getItem(a);d&&(this.stamp(d.element),d.enablePlacing(),this.updateShiftTargets(d),b=void 0===b?d.rect.x:b,c=void 0===c?d.rect.y:c,this.shift(d,b,c),this._bindFitEvents(d),d.moveTo(d.rect.x,d.rect.y),this.shiftLayout(),this.unstamp(d.element),this.sortItemsByPosition(),d.disablePlacing())},j._bindFitEvents=function(a){function b(){d++,2==d&&c.dispatchEvent("fitComplete",null,[a])}var c=this,d=0;a.once("layout",b),this.once("layoutComplete",b)},j.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&(this.options.shiftPercentResize?this.resizeShiftPercentLayout():this.layout())},j.needsResizeLayout=function(){var b=a(this.element),c=this._getOption("horizontal")?"innerHeight":"innerWidth";return b[c]!=this.size[c]},j.resizeShiftPercentLayout=function(){var b=this._getItemsForLayout(this.items),c=this._getOption("horizontal"),d=c?"y":"x",e=c?"height":"width",f=c?"rowHeight":"columnWidth",g=c?"innerHeight":"innerWidth",h=this[f];if(h=h&&h+this.gutter){this._getMeasurements();var i=this[f]+this.gutter;b.forEach(function(a){var b=Math.round(a.rect[d]/h);a.rect[d]=b*i})}else{var j=a(this.element)[g]+this.gutter,k=this.packer[e];b.forEach(function(a){a.rect[d]=a.rect[d]/k*j})}this.shiftLayout()},j.itemDragStart=function(a){if(this.isEnabled){this.stamp(a);var b=this.getItem(a);b&&(b.enablePlacing(),b.showDropPlaceholder(),this.dragItemCount++,this.updateShiftTargets(b))}},j.updateShiftTargets=function(a){this.shiftPacker.reset(),this._getBoundingRect();var b=this._getOption("originLeft"),d=this._getOption("originTop");this.stamps.forEach(function(a){var e=this.getItem(a);if(!e||!e.isPlacing){var f=this._getElementOffset(a),g=new c({x:b?f.left:f.right,y:d?f.top:f.bottom});this._setRectSize(a,g),this.shiftPacker.placed(g)}},this);var e=this._getOption("horizontal"),f=e?"rowHeight":"columnWidth",g=e?"height":"width";this.shiftTargetKeys=[],this.shiftTargets=[];var h,i=this[f];if(i=i&&i+this.gutter){var j=Math.ceil(a.rect[g]/i),k=Math.floor((this.shiftPacker[g]+this.gutter)/i);h=(k-j)*i;for(var l=0;k>l;l++)this._addShiftTarget(l*i,0,h)}else h=this.shiftPacker[g]+this.gutter-a.rect[g],this._addShiftTarget(0,0,h);var m=this._getItemsForLayout(this.items),n=this._getPackMethod();m.forEach(function(a){var b=a.rect;this._setRectSize(a.element,b),this.shiftPacker[n](b),this._addShiftTarget(b.x,b.y,h);var c=e?b.x+b.width:b.x,d=e?b.y:b.y+b.height;if(this._addShiftTarget(c,d,h),i)for(var f=Math.round(b[g]/i),j=1;f>j;j++){var k=e?c:b.x+i*j,l=e?b.y+i*j:d;this._addShiftTarget(k,l,h)}},this)},j._addShiftTarget=function(a,b,c){var d=this._getOption("horizontal")?b:a;if(!(0!==d&&d>c)){var e=a+","+b,f=-1!=this.shiftTargetKeys.indexOf(e);f||(this.shiftTargetKeys.push(e),this.shiftTargets.push({x:a,y:b}))}},j.shift=function(a,b,c){var d,e=1/0,f={x:b,y:c};
4555this.shiftTargets.forEach(function(a){var b=h(a,f);e>b&&(d=a,e=b)}),a.rect.x=d.x,a.rect.y=d.y};var k=120;j.itemDragMove=function(a,b,c){function d(){f.shift(e,b,c),e.positionDropPlaceholder(),f.layout()}var e=this.isEnabled&&this.getItem(a);if(e){b-=this.size.paddingLeft,c-=this.size.paddingTop;var f=this,g=new Date;this._itemDragTime&&g-this._itemDragTime<k?(clearTimeout(this.dragTimeout),this.dragTimeout=setTimeout(d,k)):(d(),this._itemDragTime=g)}},j.itemDragEnd=function(a){function b(){d++,2==d&&(c.element.classList.remove("is-positioning-post-drag"),c.hideDropPlaceholder(),e.dispatchEvent("dragItemPositioned",null,[c]))}var c=this.isEnabled&&this.getItem(a);if(c){clearTimeout(this.dragTimeout),c.element.classList.add("is-positioning-post-drag");var d=0,e=this;c.once("layout",b),this.once("layoutComplete",b),c.moveTo(c.rect.x,c.rect.y),this.layout(),this.dragItemCount=Math.max(0,this.dragItemCount-1),this.sortItemsByPosition(),c.disablePlacing(),this.unstamp(c.element)}},j.bindDraggabillyEvents=function(a){this._bindDraggabillyEvents(a,"on")},j.unbindDraggabillyEvents=function(a){this._bindDraggabillyEvents(a,"off")},j._bindDraggabillyEvents=function(a,b){var c=this.handleDraggabilly;a[b]("dragStart",c.dragStart),a[b]("dragMove",c.dragMove),a[b]("dragEnd",c.dragEnd)},j.bindUIDraggableEvents=function(a){this._bindUIDraggableEvents(a,"on")},j.unbindUIDraggableEvents=function(a){this._bindUIDraggableEvents(a,"off")},j._bindUIDraggableEvents=function(a,b){var c=this.handleUIDraggable;a[b]("dragstart",c.start)[b]("drag",c.drag)[b]("dragstop",c.stop)};var l=j.destroy;return j.destroy=function(){l.apply(this,arguments),this.isEnabled=!1},i.Rect=c,i.Packer=d,i}),function(a,b){"function"==typeof define&&define.amd?define(["isotope-layout/js/layout-mode","packery/js/packery"],b):"object"==typeof module&&module.exports?module.exports=b(require("isotope-layout/js/layout-mode"),require("packery")):b(a.Isotope.LayoutMode,a.Packery)}(window,function(a,b){var c=a.create("packery"),d=c.prototype,e={_getElementOffset:!0,_getMeasurement:!0};for(var f in b.prototype)e[f]||(d[f]=b.prototype[f]);var g=d._resetLayout;d._resetLayout=function(){this.packer=this.packer||new b.Packer,this.shiftPacker=this.shiftPacker||new b.Packer,g.apply(this,arguments)};var h=d._getItemLayoutPosition;d._getItemLayoutPosition=function(a){return a.rect=a.rect||new b.Rect,h.call(this,a)};var i=d.needsResizeLayout;d.needsResizeLayout=function(){return this._getOption("horizontal")?this.needsVerticalResizeLayout():i.call(this)};var j=d._getOption;return d._getOption=function(a){return"horizontal"==a?void 0!==this.options.isHorizontal?this.options.isHorizontal:this.options.horizontal:j.apply(this.isotope,arguments)},c}); 4556 4557/*! 4558 * cellsByRows layout mode for Isotope 4559 * v1.1.3 4560 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 4561 */ 4562 4563/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 4564 4565( function( window, factory ) { 4566 // universal module definition 4567 /* jshint strict: false */ /*globals define, module, require */ 4568 if ( typeof define === 'function' && define.amd ) { 4569 // AMD 4570 define( [ 4571 'isotope/js/layout-mode' 4572 ], 4573 factory ); 4574 } else if ( typeof exports === 'object' ) { 4575 // CommonJS 4576 module.exports = factory( 4577 require('isotope-layout/js/layout-mode') 4578 ); 4579 } else { 4580 // browser global 4581 factory( 4582 window.Isotope.LayoutMode 4583 ); 4584 } 4585 4586}( window, function factory( LayoutMode ) { 4587 'use strict'; 4588 4589 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 4590 var proto = CellsByRow.prototype; 4591 4592 proto._resetLayout = function() { 4593 // reset properties 4594 this.itemIndex = 0; 4595 // measurements 4596 this.getColumnWidth(); 4597 this.getRowHeight(); 4598 // set cols 4599 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 4600 this.cols = Math.max( this.cols, 1 ); 4601 }; 4602 4603 proto._getItemLayoutPosition = function( item ) { 4604 item.getSize(); 4605 var col = this.itemIndex % this.cols; 4606 var row = Math.floor( this.itemIndex / this.cols ); 4607 // center item within cell 4608 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 4609 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 4610 this.itemIndex++; 4611 return { x: x, y: y }; 4612 }; 4613 4614 proto._getContainerSize = function() { 4615 return {
4616 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 4617 }; 4618 }; 4619 4620 return CellsByRow; 4621 4622})); 4623 4624/*! 4625 -------------------------------- 4626 Infinite Scroll 4627 -------------------------------- 4628 + https://github.com/paulirish/infinite-scroll 4629 + version 2.1.0 4630 + Copyright 2011/12 Paul Irish & Luke Shumard 4631 + Licensed under the MIT license 4632 4633 + Documentation: http://infinite-scroll.com/ 4634*/ 4635;(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(jQuery)}})(function(e,t){"use strict";e.infinitescroll=function(n,r,i){this.element=e(i);if(!this._create(n,r)){this.failed=true}};e.infinitescroll.defaults={loading:{finished:t,finishedMsg:"<em>Congratulations, you've reached the end of the internet.</em>",img:"data:image/gif;base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oXHlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFh
4635ohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSHMzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2G
4635iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7",msg:null,msgText:"<em>Loading the next set of posts...</em>",selector:null,speed:"fast",start:t},state:{isDuringAjax:false,isInvalidPage:false,isDestroyed:false,isDone:false,isPaused:false,isBeyondMaxPage:false,currPage:1},debug:false,behavior:t,binder:e(window),nextSelector:"div.navigation a:first",navSelector:"div.navigation",contentSelector:null,extraScrollPx:150,itemSelector:"div.post",animate:false,pathParse:t,dataType:"html",appendCallback:true,bufferPx:40,errorCallback:function(){},infid:0,pixelsFromNavToBottom:t,path:t,prefill:false,maxPage:t};e.infinitescroll.prototype={_binding:function(n){var r=this,i=r.options;i.v="2.0b2.120520";if(!!i.behavior&&this["_binding_"+i.behavior]!==t){this["_binding_"+i.behavior].call(this);return}if(n!=="bind"&&n!=="unbind"){this._debug("Binding value "+n+" not valid");return false}if(n==="unbind"){this.options.binder.unbind("smartscroll.infscr."+r.options.infid)}else{this.options.binder[n]("smartscroll.infscr."+r.options.infid,function(){r.scroll()})}this._debug("Binding",n)},_create:function(r,i){var s=e.extend(true,{},e.infinitescroll.defaults,r);this.options=s;var o=e(window);var u=this;if(!u._validate(r)){return false}var a=e(s.nextSelector).attr("href");if(!a){this._debug("Navigation selector not found");return false}s.path=s.path||this._determinepath(a);s.contentSelector=s.contentSelector||this.element;s.loading.selector=s.loading.selector||s.contentSelector;s.loading.msg=s.loading.msg||e('<div id="infscr-loading"><img alt="Loading..." src="'+s.loading.img+'" /><div>'+s.loading.msgText+"</div></div>");(new Image).src=s.loading.img;if(s.pixelsFromNavToBottom===t){s.pixelsFromNavToBottom=e(document).height()-e(s.navSelector).offset().top;this._debug("pixelsFromNavToBottom: "+s.pixelsFromNavToBottom)}var f=this;s.loading.start=s.loading.start||function(){e(s.navSelector).hide();s.loading.msg.appendTo(s.loading.selector).show(s.loading.speed,e.proxy(function(){this.beginAjax(s)},f))};s.loading.finished=s.loading.finished||function(){if(!s.state.isBeyondMaxPage)s.loading.msg.fadeOut(s.loading.speed)};s.callback=function(n,r,u){if(!!s.behavior&&n["_callback_"+s.behavior]!==t){n["_callback_"+s.behavior].call(e(s.contentSelector)[0],r,u)}if(i){i.call(e(s.contentSelector)[0],r,s,u)}if(s.prefill){o.bind("resize.infinite-scroll",n._prefill)}};if(r.debug){if(Function.prototype.bind&&(typeof console==="object"||typeof console==="function")&&typeof console.log==="object"){["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function(e){console[e]=this.call(console[e],console)},Function.prototype.bind)}}this._setup();if(s.prefill){this._prefill()}return true},_prefill:function(){function i(){return e(n.options.contentSelector).height()<=r.height()}var n=this;var r=e(window);this._prefill=function(){if(i()){n.scroll()}r.bind("resize.infinite-scroll",function(){if(i()){r.unbind("resize.infinite-scroll");n.scroll()}})};this._prefill()},_debug:function(){if(true!==this.options.debug){return}if(typeof console!=="undefined"&&typeof console.log==="function"){if(Array.prototype.slice.call(arguments).length===1&&typeof Array.prototype.slice.call(arguments)[0]==="str
4635ing"){console.log(Array.prototype.slice.call(arguments).toString())}else{console.log(Array.prototype.slice.call(arguments))}}else if(!Function.prototype.bind&&typeof console!=="undefined"&&typeof console.log==="object"){Function.prototype.call.call(console.log,console,Array.prototype.slice.call(arguments))}},_determinepath:function(n){var r=this.options;if(!!r.behavior&&this["_determinepath_"+r.behavior]!==t){return this["_determinepath_"+r.behavior].call(this,n)}if(!!r.pathParse){this._debug("pathParse manual");return r.pathParse(n,this.options.state.currPage+1)}else if(n.match(/^(.*?)\b2\b(.*?$)/)){n=n.match(/^(.*?)\b2\b(.*?$)/).slice(1)}else if(n.match(/^(.*?)2(.*?$)/)){if(n.match(/^(.*?page=)2(\/.*|$)/)){n=n.match(/^(.*?page=)2(\/.*|$)/).slice(1);return n}n=n.match(/^(.*?)2(.*?$)/).slice(1)}else{if(n.match(/^(.*?page=)1(\/.*|$)/)){n=n.match(/^(.*?page=)1(\/.*|$)/).slice(1);return n}else{this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.");r.state.isInvalidPage=true}}this._debug("determinePath",n);return n},_error:function(n){var r=this.options;if(!!r.behavior&&this["_error_"+r.behavior]!==t){this["_error_"+r.behavior].call(this,n);return}if(n!=="destroy"&&n!=="end"){n="unknown"}this._debug("Error",n);if(n==="end"||r.state.isBeyondMaxPage){this._showdonemsg()}r.state.isDone=true;r.state.currPage=1;
4635r.state.isPaused=false;r.state.isBeyondMaxPage=false;this._binding("unbind")},_loadcallback:function(r,i,s){var o=this.options,u=this.options.callback,a=o.state.isDone?"done":!o.appendCallback?"no-append":"append",f;if(!!o.behavior&&this["_loadcallback_"+o.behavior]!==t){this["_loadcallback_"+o.behavior].call(this,r,i);return}switch(a){case"done":this._showdonemsg();return false;case"no-append":if(o.dataType==="html"){i="<div>"+i+"</div>";i=e(i).find(o.itemSelector)}if(i.length===0){return this._error("end")}break;case"append":var l=r.children();if(l.length===0){return this._error("end")}f=document.createDocumentFragment();while(r[0].firstChild){f.appendChild(r[0].firstChild)}this._debug("contentSelector",e(o.contentSelector)[0]);e(o.contentSelector)[0].appendChild(f);i=l.get();break}o.loading.finished.call(e(o.contentSelector)[0],o);if(o.animate){var c=e(window).scrollTop()+e(o.loading.msg).height()+o.extraScrollPx+"px";e("html,body").animate({scrollTop:c},800,function(){o.state.isDuringAjax=false})}if(!o.animate){o.state.isDuringAjax=false}u(this,i,s);if(o.prefill){this._prefill()}},_nearbottom:function(){var r=this.options,i=0+e(document).height()-r.binder.scrollTop()-e(window).height();if(!!r.behavior&&this["_nearbottom_"+r.behavior]!==t){return this["_nearbottom_"+r.behavior].call(this)}this._debug("math:",i,r.pixelsFromNavToBottom);return i-r.bufferPx<r.pixelsFromNavToBottom},_pausing:function(n){var r=this.options;if(!!r.behavior&&this["_pausing_"+r.behavior]!==t){this["_pausing_"+r.behavior].call(this,n);return}if(n!=="pause"&&n!=="resume"&&n!==null){this._debug("Invalid argument. Toggling pause value instead")}n=n&&(n==="pause"||n==="resume")?n:"toggle";
4635switch(n){case"pause":r.state.isPaused=true;break;case"resume":r.state.isPaused=false;break;case"toggle":r.state.isPaused=!r.state.isPaused;break}this._debug("Paused",r.state.isPaused);return false},_setup:function(){var n=this.options;if(!!n.behavior&&this["_setup_"+n.behavior]!==t){this["_setup_"+n.behavior].call(this);return}this._binding("bind");return false},_showdonemsg:function(){var r=this.options;if(!!r.behavior&&this["_showdonemsg_"+r.behavior]!==t){this["_showdonemsg_"+r.behavior].call(this);return}r.loading.msg.find("img").hide().parent().find("div").html(r.loading.finishedMsg).animate({opacity:1},2e3,function(){e(this).parent().fadeOut(r.loading.speed)});r.errorCallback.call(e(r.contentSelector)[0],"done")},_validate:function(n){for(var r in n){if(r.indexOf&&r.indexOf("Selector")>-1&&e(n[r]).length===0){this._debug("Your "+r+" found no elements.");return false}}return true},bind:function(){this._binding("bind")},destroy:function(){this.options.state.isDestroyed=true;this.options.loading.finished();return this._error("destroy")},pause:function(){this._pausing("pause")},resume:function(){this._pausing("resume")},beginAjax:function(r){var i=this,s=r.path,o,u,a,f;r.state.currPage++;if(r.maxPage!==t&&r.state.currPage>r.maxPage){r.state.isBeyondMaxPage=true;this.destroy();return}o=e(r.contentSelector).is("table, tbody")?e("<tbody/>"):e("<div/>");u=typeof s==="function"?s(r.state.currPage):s.join(r.state.currPage);i._debug("heading into ajax",u);a=r.dataType==="html"||r.dataType==="json"?r.dataType:"html+callback";if(r.appendCallback&&r.dataType==="html"){a+="+callback"}switch(a){case"html+callback":i._debug("Using HTML via .load() method");o.load(u+" "+r.itemSelector,t,function(t){i._loadcallback(o,t,u)});break;case"html":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({url:u,dataType:r.dataType,complete:function(t,n){f=typeof t.isResolved!=="undefined"?t.isResolved():n==="success"||n==="notmodified";if(f){i._loadcallback(o,t.responseText,u)}else{i._error("end")}}});break;case"json":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({dataType:"json",type:"GET",url:u,success:function(e,n,s){f=typeof s.isResolved!=="undefined"?s.isResolved():n==="success"||n==="notmodified";if(r.appendCallback){if(r.template!==t){var a=r.template(e);o.append(a);if(f){i._loadcallback(o,a)}else{i._error("end")}}else{i._debug("template must be defined.");i._error("end")}}else{if(f){i._loadcallback(o,e,u)}else{i._error("end")}}},error:function(){i._debug("JSON ajax request failed.");i._error("end")}});break}},retrieve:function(r){r=r||null;var i=this,s=i.options;if(!!s.behavior&&this["retrieve_"+s.behavior]!==t){this["retrieve_"+s.behavior].call(this,r);return}if(s.state.isDestroyed){this._debug("Instance is destroyed");return false}s.state.isDuringAjax=true;s.loading.start.call(e(s.contentSelector)[0],s)},scroll:function(){var n=this.options,r=n.state;if(!!n.behavior&&this["scroll_"+n.behavior]!==t){this["scroll_"+n.behavior].call(this);return}if(r.isDuringAjax||r.isInvalidPage||r.isDone||r.isDestroyed||r.isPaused){return}if(!this._nearbottom()){return}this.retrieve()},toggle:function(){this._pausing()},unbind:function(){this._binding("unbind")},update:function(n){if(e.isPlainObject(n)){this.options=e.extend(true,this.options,n)}}};e.fn.infinitescroll=function(n,r){var i=typeof n;switch(i){case"string":var s=Array.prototype.slice.call(arguments,1);this.each(function(){var t=e.data(this,"infinitescroll");if(!t){return false}if(!e.isFunction(t[n])||n.charAt(0)==="_"){return false}t[n].apply(t,s)});break;case"object":this.each(function(){var t=e.data(this,"infinitescroll");if(t){t.update(n)}else{t=new e.infinitescroll(n,r,this);if(!t.failed){e.data(this,"infinitescroll",t)}}});break}return this};var n=e.event,r;n.special.smartscroll={setup:function(){e(this).bind("scroll",n.special.smartscroll.handler)},teardown:function(){e(this).unbind("scroll",n.special.smartscroll.handler)},handler:function(t,n){var i=this,s=arguments;t.type="smartscroll";if(r){clearTimeout(r)}r=setTimeout(function(){e(i).trigger("smartscroll",s)},n==="execAsap"?0:100)}};e.fn.smartscroll=function(e){return e?this.bind("smartscroll",e):this.trigger("smartscroll",["execAsap"])}}); 4636 4637/*!
4638Waypoints - 4.0.1 4639Copyright © 2011-2016 Caleb Troughton 4640Licensed under the MIT license. 4641https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 4642*/ 4643(function() { 4644 'use strict' 4645 4646 var keyCounter = 0 4647 var allWaypoints = {} 4648 4649 /* http://imakewebthings.com/waypoints/api/waypoint */ 4650 function Waypoint(options) { 4651 if (!options) { 4652 throw new Error('No options passed to Waypoint constructor') 4653 } 4654 if (!options.element) { 4655 throw new Error('No element option passed to Waypoint constructor') 4656 } 4657 if (!options.handler) { 4658 throw new Error('No handler option passed to Waypoint constructor') 4659 } 4660 4661 this.key = 'waypoint-' + keyCounter 4662 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 4663 this.element = this.options.element 4664 this.adapter = new Waypoint.Adapter(this.element) 4665 this.callback = options.handler 4666 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 4667 this.enabled = this.options.enabled 4668 this.triggerPoint = null 4669 this.group = Waypoint.Group.findOrCreate({ 4670 name: this.options.group, 4671 axis: this.axis 4672 }) 4673 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 4674 4675 if (Waypoint.offsetAliases[this.options.offset]) { 4676 this.options.offset = Waypoint.offsetAliases[this.options.offset] 4677 } 4678 this.group.add(this) 4679 this.context.add(this) 4680 allWaypoints[this.key] = this 4681 keyCounter += 1 4682 } 4683 4684 /* Private */ 4685 Waypoint.prototype.queueTrigger = function(direction) { 4686 this.group.queueTrigger(this, direction) 4687 } 4688 4689 /* Private */ 4690 Waypoint.prototype.trigger = function(args) { 4691 if (!this.enabled) { 4692 return 4693 } 4694 if (this.callback) { 4695 this.callback.apply(this, args) 4696 } 4697 } 4698 4699 /* Public */ 4700 /* http://imakewebthings.com/waypoints/api/destroy */ 4701 Waypoint.prototype.destroy = function() { 4702 this.context.remove(this) 4703 this.group.remove(this) 4704 delete allWaypoints[this.key] 4705 } 4706 4707 /* Public */ 4708 /* http://imakewebthings.com/waypoints/api/disable */ 4709 Waypoint.prototype.disable = function() { 4710 this.enabled = false 4711 return this 4712 } 4713 4714 /* Public */ 4715 /* http://imakewebthings.com/waypoints/api/enable */ 4716 Waypoint.prototype.enable = function() { 4717 this.context.refresh() 4718 this.enabled = true 4719 return this 4720 } 4721 4722 /* Public */ 4723 /* http://imakewebthings.com/waypoints/api/next */ 4724 Waypoint.prototype.next = function() { 4725 return this.group.next(this) 4726 } 4727 4728 /* Public */ 4729 /* http://imakewebthings.com/waypoints/api/previous */ 4730 Waypoint.prototype.previous = function() { 4731 return this.group.previous(this) 4732 } 4733 4734 /* Private */ 4735 Waypoint.invokeAll = function(method) { 4736 var allWaypointsArray = []
4737 for (var waypointKey in allWaypoints) { 4738 allWaypointsArray.push(allWaypoints[waypointKey]) 4739 } 4740 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 4741 allWaypointsArray[i][method]() 4742 } 4743 } 4744 4745 /* Public */ 4746 /* http://imakewebthings.com/waypoints/api/destroy-all */ 4747 Waypoint.destroyAll = function() { 4748 Waypoint.invokeAll('destroy') 4749 } 4750 4751 /* Public */ 4752 /* http://imakewebthings.com/waypoints/api/disable-all */ 4753 Waypoint.disableAll = function() { 4754 Waypoint.invokeAll('disable') 4755 } 4756 4757 /* Public */ 4758 /* http://imakewebthings.com/waypoints/api/enable-all */ 4759 Waypoint.enableAll = function() { 4760 Waypoint.Context.refreshAll() 4761 for (var waypointKey in allWaypoints) { 4762 allWaypoints[waypointKey].enabled = true 4763 } 4764 return this 4765 } 4766 4767 /* Public */ 4768 /* http://imakewebthings.com/waypoints/api/refresh-all */ 4769 Waypoint.refreshAll = function() { 4770 Waypoint.Context.refreshAll() 4771 } 4772 4773 /* Public */ 4774 /* http://imakewebthings.com/waypoints/api/viewport-height */ 4775 Waypoint.viewportHeight = function() { 4776 return window.innerHeight || document.documentElement.clientHeight 4777 } 4778 4779 /* Public */ 4780 /* http://imakewebthings.com/waypoints/api/viewport-width */ 4781 Waypoint.viewportWidth = function() { 4782 return document.documentElement.clientWidth 4783 } 4784 4785 Waypoint.adapters = [] 4786 4787 Waypoint.defaults = { 4788 context: window, 4789 continuous: true, 4790 enabled: true, 4791 group: 'default', 4792 horizontal: false, 4793 offset: 0 4794 } 4795 4796 Waypoint.offsetAliases = { 4797 'bottom-in-view': function() { 4798 return this.context.innerHeight() - this.adapter.outerHeight() 4799 }, 4800 'right-in-view': function() { 4801 return this.context.innerWidth() - this.adapter.outerWidth() 4802 } 4803 } 4804 4805 window.Waypoint = Waypoint 4806}()) 4807;(function() { 4808 'use strict' 4809 4810 function requestAnimationFrameShim(callback) { 4811 window.setTimeout(callback, 1000 / 60) 4812 } 4813 4814 var keyCounter = 0 4815 var contexts = {} 4816 var Waypoint = window.Waypoint 4817 var oldWindowLoad = window.onload 4818 4819 /* http://imakewebthings.com/waypoints/api/context */ 4820 function Context(element) { 4821 this.element = element 4822 this.Adapter = Waypoint.Adapter 4823 this.adapter = new this.Adapter(element) 4824 this.key = 'waypoint-context-' + keyCounter 4825 this.didScroll = false 4826 this.didResize = false 4827 this.oldScroll = { 4828 x: this.adapter.scrollLeft(), 4829 y: this.adapter.scrollTop() 4830 } 4831 this.waypoints = { 4832 vertical: {}, 4833 horizontal: {} 4834 } 4835 4836 element.waypointContextKey = this.key 4837 contexts[element.waypointContextKey] = this 4838 keyCounter += 1 4839 if (!Waypoint.windowContext) { 4840 Waypoint.windowContext = true 4841 Waypoint.windowContext = new Context(window) 4842 } 4843 4844 this.createThrottledScrollHandler() 4845 this.createThrottledResizeHandler() 4846 } 4847 4848 /* Private */ 4849 Context.prototype.add = function(waypoint) { 4850 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 4851 this.waypoints[axis][waypoint.key] = waypoint 4852 this.refresh() 4853 } 4854 4855 /* Private */ 4856 Context.prototype.checkEmpty = function() { 4857 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 4858 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 4859 var isWindow = this.element == this.element.window 4860 if (horizontalEmpty && verticalEmpty && !isWindow) { 4861 this.adapter.off('.waypoints') 4862 delete contexts[this.key] 4863 } 4864 } 4865 4866 /* Private */ 4867 Context.prototype.createThrottledResizeHandler = function() { 4868 var self = this 4869 4870 function resizeHandler() { 4871 self.handleResize() 4872 self.didResize = false 4873 } 4874 4875 this.adapter.on('resize.waypoints', function() { 4876 if (!self.didResize) { 4877 self.didResize = true 4878 Waypoint.requestAnimationFrame(resizeHandler) 4879 } 4880 }) 4881 } 4882 4883 /* Private */ 4884 Context.prototype.createThrottledScrollHandler = function() { 4885 var self = this 4886 function scrollHandler() { 4887 self.handleScroll() 4888 self.didScroll = false 4889 } 4890 4891 this.adapter.on('scroll.waypoints', function() { 4892 if (!self.didScroll || Waypoint.isTouch) { 4893 self.didScroll = true 4894 Waypoint.requestAnimationFrame(scrollHandler) 4895 } 4896 }) 4897 } 4898 4899 /* Private */ 4900 Context.prototype.handleResize = function() { 4901 Waypoint.Context.refreshAll() 4902 } 4903 4904 /* Private */ 4905 Context.prototype.handleScroll = function() { 4906 var triggeredGroups = {} 4907 var axes = { 4908 horizontal: { 4909 newScroll: this.adapter.scrollLeft(), 4910 oldScroll: this.oldScroll.x, 4911 forward: 'right', 4912 backward: 'left' 4913 }, 4914 vertical: { 4915 newScroll: this.adapter.scrollTop(), 4916 oldScroll: this.oldScroll.y, 4917 forward: 'down', 4918 backward: 'up' 4919 } 4920 } 4921 4922 for (var axisKey in axes) { 4923 var axis = axes[axisKey] 4924 var isForward = axis.newScroll > axis.oldScroll 4925 var direction = isForward ? axis.forward : axis.backward 4926
4927 for (var waypointKey in this.waypoints[axisKey]) { 4928 var waypoint = this.waypoints[axisKey][waypointKey] 4929 if (waypoint.triggerPoint === null) { 4930 continue 4931 } 4932 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 4933 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 4934 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 4935 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 4936 if (crossedForward || crossedBackward) { 4937 waypoint.queueTrigger(direction) 4938 triggeredGroups[waypoint.group.id] = waypoint.group 4939 } 4940 } 4941 } 4942 4943 for (var groupKey in triggeredGroups) { 4944 triggeredGroups[groupKey].flushTriggers() 4945 } 4946 4947 this.oldScroll = { 4948 x: axes.horizontal.newScroll, 4949 y: axes.vertical.newScroll 4950 } 4951 } 4952 4953 /* Private */ 4954 Context.prototype.innerHeight = function() { 4955 /*eslint-disable eqeqeq */ 4956 if (this.element == this.element.window) { 4957 return Waypoint.viewportHeight() 4958 } 4959 /*eslint-enable eqeqeq */ 4960 return this.adapter.innerHeight() 4961 } 4962 4963 /* Private */ 4964 Context.prototype.remove = function(waypoint) { 4965 delete this.waypoints[waypoint.axis][waypoint.key] 4966 this.checkEmpty() 4967 } 4968 4969 /* Private */ 4970 Context.prototype.innerWidth = function() { 4971 /*eslint-disable eqeqeq */ 4972 if (this.element == this.element.window) { 4973 return Waypoint.viewportWidth() 4974 } 4975 /*eslint-enable eqeqeq */ 4976 return this.adapter.innerWidth() 4977 } 4978 4979 /* Public */ 4980 /* http://imakewebthings.com/waypoints/api/context-destroy */ 4981 Context.prototype.destroy = function() { 4982 var allWaypoints = [] 4983 for (var axis in this.waypoints) {
4984 for (var waypointKey in this.waypoints[axis]) { 4985 allWaypoints.push(this.waypoints[axis][waypointKey]) 4986 } 4987 } 4988 for (var i = 0, end = allWaypoints.length; i < end; i++) { 4989 allWaypoints[i].destroy() 4990 } 4991 } 4992 4993 /* Public */ 4994 /* http://imakewebthings.com/waypoints/api/context-refresh */ 4995 Context.prototype.refresh = function() { 4996 /*eslint-disable eqeqeq */ 4997 var isWindow = this.element == this.element.window 4998 /*eslint-enable eqeqeq */ 4999 var contextOffset = isWindow ? undefined : this.adapter.offset() 5000 var triggeredGroups = {} 5001 var axes 5002 5003 this.handleScroll() 5004 axes = { 5005 horizontal: { 5006 contextOffset: isWindow ? 0 : contextOffset.left, 5007 contextScroll: isWindow ? 0 : this.oldScroll.x, 5008 contextDimension: this.innerWidth(), 5009 oldScroll: this.oldScroll.x, 5010 forward: 'right', 5011 backward: 'left', 5012 offsetProp: 'left' 5013 }, 5014 vertical: { 5015 contextOffset: isWindow ? 0 : contextOffset.top, 5016 contextScroll: isWindow ? 0 : this.oldScroll.y, 5017 contextDimension: this.innerHeight(), 5018 oldScroll: this.oldScroll.y, 5019 forward: 'down', 5020 backward: 'up', 5021 offsetProp: 'top' 5022 } 5023 } 5024 5025 for (var axisKey in axes) { 5026 var axis = axes[axisKey]
5027 for (var waypointKey in this.waypoints[axisKey]) { 5028 var waypoint = this.waypoints[axisKey][waypointKey] 5029 var adjustment = waypoint.options.offset 5030 var oldTriggerPoint = waypoint.triggerPoint 5031 var elementOffset = 0 5032 var freshWaypoint = oldTriggerPoint == null 5033 var contextModifier, wasBeforeScroll, nowAfterScroll 5034 var triggeredBackward, triggeredForward 5035 5036 if (waypoint.element !== waypoint.element.window) { 5037 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 5038 } 5039 5040 if (typeof adjustment === 'function') { 5041 adjustment = adjustment.apply(waypoint) 5042 } 5043 else if (typeof adjustment === 'string') { 5044 adjustment = parseFloat(adjustment) 5045 if (waypoint.options.offset.indexOf('%') > - 1) { 5046 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 5047 } 5048 } 5049 5050 contextModifier = axis.contextScroll - axis.contextOffset 5051 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 5052 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 5053 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 5054 triggeredBackward = wasBeforeScroll && nowAfterScroll 5055 triggeredForward = !wasBeforeScroll && !nowAfterScroll 5056 5057 if (!freshWaypoint && triggeredBackward) { 5058 waypoint.queueTrigger(axis.backward) 5059 triggeredGroups[waypoint.group.id] = waypoint.group 5060 } 5061 else if (!freshWaypoint && triggeredForward) { 5062 waypoint.queueTrigger(axis.forward) 5063 triggeredGroups[waypoint.group.id] = waypoint.group 5064 } 5065 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 5066 waypoint.queueTrigger(axis.forward) 5067 triggeredGroups[waypoint.group.id] = waypoint.group 5068 } 5069 } 5070 } 5071 5072 Waypoint.requestAnimationFrame(function() { 5073 for (var groupKey in triggeredGroups) { 5074 triggeredGroups[groupKey].flushTriggers() 5075 } 5076 }) 5077 5078 return this 5079 } 5080 5081 /* Private */ 5082 Context.findOrCreateByElement = function(element) { 5083 return Context.findByElement(element) || new Context(element) 5084 } 5085 5086 /* Private */ 5087 Context.refreshAll = function() { 5088 for (var contextId in contexts) { 5089 contexts[contextId].refresh() 5090 } 5091 } 5092 5093 /* Public */ 5094 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 5095 Context.findByElement = function(element) { 5096 return contexts[element.waypointContextKey] 5097 } 5098 5099 window.onload = function() { 5100 if (oldWindowLoad) { 5101 oldWindowLoad() 5102 } 5103 Context.refreshAll() 5104 } 5105 5106 5107 Waypoint.requestAnimationFrame = function(callback) { 5108 var requestFn = window.requestAnimationFrame || 5109 window.mozRequestAnimationFrame || 5110 window.webkitRequestAnimationFrame || 5111 requestAnimationFrameShim 5112 requestFn.call(window, callback) 5113 } 5114 Waypoint.Context = Context 5115}()) 5116;(function() { 5117 'use strict' 5118 5119 function byTriggerPoint(a, b) { 5120 return a.triggerPoint - b.triggerPoint 5121 } 5122 5123 function byReverseTriggerPoint(a, b) { 5124 return b.triggerPoint - a.triggerPoint 5125 } 5126 5127 var groups = { 5128 vertical: {}, 5129 horizontal: {} 5130 } 5131 var Waypoint = window.Waypoint 5132 5133 /* http://imakewebthings.com/waypoints/api/group */ 5134 function Group(options) { 5135 this.name = options.name 5136 this.axis = options.axis 5137 this.id = this.name + '-' + this.axis 5138 this.waypoints = [] 5139 this.clearTriggerQueues() 5140 groups[this.axis][this.name] = this 5141 } 5142 5143 /* Private */ 5144 Group.prototype.add = function(waypoint) { 5145 this.waypoints.push(waypoint) 5146 } 5147 5148 /* Private */ 5149 Group.prototype.clearTriggerQueues = function() { 5150 this.triggerQueues = { 5151 up: [], 5152 down: [], 5153 left: [], 5154 right: [] 5155 } 5156 } 5157 5158 /* Private */ 5159 Group.prototype.flushTriggers = function() { 5160 for (var direction in this.triggerQueues) { 5161 var waypoints = this.triggerQueues[direction] 5162 var reverse = direction === 'up' || direction === 'left' 5163 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 5164 for (var i = 0, end = waypoints.length; i < end; i += 1) { 5165 var waypoint = waypoints[i] 5166 if (waypoint.options.continuous || i === waypoints.length - 1) { 5167 waypoint.trigger([direction]) 5168 } 5169 } 5170 } 5171 this.clearTriggerQueues() 5172 } 5173 5174 /* Private */ 5175 Group.prototype.next = function(waypoint) { 5176 this.waypoints.sort(byTriggerPoint) 5177 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5178 var isLast = index === this.waypoints.length - 1 5179 return isLast ? null : this.waypoints[index + 1] 5180 } 5181 5182 /* Private */ 5183 Group.prototype.previous = function(waypoint) { 5184 this.waypoints.sort(byTriggerPoint) 5185 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5186 return index ? this.waypoints[index - 1] : null 5187 } 5188 5189 /* Private */ 5190 Group.prototype.queueTrigger = function(waypoint, direction) { 5191 this.triggerQueues[direction].push(waypoint) 5192 } 5193 5194 /* Private */ 5195 Group.prototype.remove = function(waypoint) { 5196 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5197 if (index > -1) { 5198 this.waypoints.splice(index, 1) 5199 } 5200 } 5201 5202 /* Public */ 5203 /* http://imakewebthings.com/waypoints/api/first */ 5204 Group.prototype.first = function() { 5205 return this.waypoints[0] 5206 } 5207 5208 /* Public */ 5209 /* http://imakewebthings.com/waypoints/api/last */ 5210 Group.prototype.last = function() { 5211 return this.waypoints[this.waypoints.length - 1] 5212 } 5213 5214 /* Private */ 5215 Group.findOrCreate = function(options) { 5216 return groups[options.axis][options.name] || new Group(options) 5217 } 5218 5219 Waypoint.Group = Group 5220}()) 5221;(function() { 5222 'use strict' 5223 5224 var $ = window.jQuery 5225 var Waypoint = window.Waypoint 5226 5227 function JQueryAdapter(element) { 5228 this.$element = $(element) 5229 } 5230 5231 $.each([
5232 'innerHeight', 5233 'innerWidth', 5234 'off', 5235 'offset', 5236 'on', 5237 'outerHeight', 5238 'outerWidth', 5239 'scrollLeft', 5240 'scrollTop' 5241 ], function(i, method) { 5242 JQueryAdapter.prototype[method] = function() { 5243 var args = Array.prototype.slice.call(arguments) 5244 return this.$element[method].apply(this.$element, args) 5245 } 5246 }) 5247 5248 $.each([ 5249 'extend', 5250 'inArray', 5251 'isEmptyObject' 5252 ], function(i, method) { 5253 JQueryAdapter[method] = $[method] 5254 }) 5255 5256 Waypoint.adapters.push({ 5257 name: 'jquery', 5258 Adapter: JQueryAdapter 5259 }) 5260 Waypoint.Adapter = JQueryAdapter 5261}()) 5262;(function() { 5263 'use strict' 5264 5265 var Waypoint = window.Waypoint 5266 5267 function createExtension(framework) { 5268 return function() { 5269 var waypoints = [] 5270 var overrides = arguments[0] 5271 5272 if (framework.isFunction(arguments[0])) { 5273 overrides = framework.extend({}, arguments[1]) 5274 overrides.handler = arguments[0] 5275 } 5276 5277 this.each(function() { 5278 var options = framework.extend({}, overrides, { 5279 element: this 5280 }) 5281 if (typeof options.context === 'string') { 5282 options.context = framework(this).closest(options.context)[0] 5283 } 5284 waypoints.push(new Waypoint(options)) 5285 }) 5286 5287 return waypoints 5288 } 5289 } 5290 5291 if (window.jQuery) { 5292 window.jQuery.fn.waypoint = createExtension(window.jQuery) 5293 } 5294 if (window.Zepto) { 5295 window.Zepto.fn.waypoint = createExtension(window.Zepto) 5296 } 5297}()) 5298; 5299 5300/*! 5301Waypoints Inview Shortcut - 4.0.1 5302Copyright © 2011-2016 Caleb Troughton 5303Licensed under the MIT license. 5304https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 5305*/ 5306(function() { 5307 'use strict' 5308 5309 function noop() {} 5310 5311 var Waypoint = window.Waypoint 5312 5313 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 5314 function Inview(options) { 5315 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 5316 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 5317 this.waypoints = [] 5318 this.element = this.options.element 5319 this.createWaypoints() 5320 } 5321 5322 /* Private */ 5323 Inview.prototype.createWaypoints = function() { 5324 var configs = { 5325 vertical: [{ 5326 down: 'enter', 5327 up: 'exited', 5328 offset: '100%' 5329 }, { 5330 down: 'entered', 5331 up: 'exit', 5332 offset: 'bottom-in-view' 5333 }, { 5334 down: 'exit', 5335 up: 'entered', 5336 offset: 0 5337 }, { 5338 down: 'exited', 5339 up: 'enter', 5340 offset: function() { 5341 return -this.adapter.outerHeight() 5342 } 5343 }], 5344 horizontal: [{ 5345 right: 'enter', 5346 left: 'exited', 5347 offset: '100%' 5348 }, { 5349 right: 'entered', 5350 left: 'exit', 5351 offset: 'right-in-view' 5352 }, { 5353 right: 'exit', 5354 left: 'entered', 5355 offset: 0 5356 }, { 5357 right: 'exited', 5358 left: 'enter', 5359 offset: function() { 5360 return -this.adapter.outerWidth() 5361 } 5362 }] 5363 } 5364 5365 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 5366 var config = configs[this.axis][i] 5367 this.createWaypoint(config) 5368 } 5369 } 5370 5371 /* Private */ 5372 Inview.prototype.createWaypoint = function(config) { 5373 var self = this 5374 this.waypoints.push(new Waypoint({ 5375 context: this.options.context, 5376 element: this.options.element, 5377 enabled: this.options.enabled, 5378 handler: (function(config) { 5379 return function(direction) { 5380 self.options[config[direction]].call(self, direction) 5381 } 5382 }(config)), 5383 offset: config.offset, 5384 horizontal: this.options.horizontal 5385 })) 5386 } 5387 5388 /* Public */ 5389 Inview.prototype.destroy = function() { 5390 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5391 this.waypoints[i].destroy() 5392 } 5393 this.waypoints = [] 5394 } 5395 5396 Inview.prototype.disable = function() { 5397 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5398 this.waypoints[i].disable() 5399 } 5400 } 5401 5402 Inview.prototype.enable = function() { 5403 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5404 this.waypoints[i].enable() 5405 } 5406 } 5407 5408 Inview.defaults = { 5409 context: window, 5410 enabled: true, 5411 enter: noop, 5412 entered: noop,
5413 exit: noop, 5414 exited: noop 5415 } 5416 5417 Waypoint.Inview = Inview 5418}()) 5419; 5420 5421/* 5422 * SmartMenus jQuery v0.9.6 5423 * http://www.smartmenus.org/ 5424 * 5425 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 5426 * http://vadikom.com/ 5427 * 5428 * Released under the MIT license: 5429 * http://www.opensource.org/licenses/MIT 5430 */ 5431 5432(function($) { 5433 5434 var menuTrees = [], 5435 IE = !!window.createPopup, // we need to detect it, unfortunately 5436 IElt9 = IE && !document.defaultView, 5437 IElt8 = IE && !document.querySelector, 5438 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 5439 mouse = false, // optimize for touch by default - we will detect for mouse input 5440 mouseDetectionEnabled = false; 5441 5442 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 5443 function initMouseDetection(disable) { 5444 if (!mouseDetectionEnabled && !disable) { 5445 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 5446 // in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events) 5447 var firstTime = true, 5448 lastMove = null; 5449 $(document).bind({ 5450 'mousemove.smartmenus_mouse': function(e) { 5451 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 5452 if (lastMove) { 5453 var deltaX = Math.abs(lastMove.x - thisMove.x), 5454 deltaY = Math.abs(lastMove.y - thisMove.y); 5455 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 5456 mouse = true; 5457 // if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes 5458 if (firstTime) { 5459 var $a = $(e.target).closest('a'); 5460 if ($a.is('a')) { 5461 $.each(menuTrees, function() { 5462 if ($.contains(this.$root[0], $a[0])) { 5463 this.itemEnter({ currentTarget: $a[0] }); 5464 return false; 5465 } 5466 }); 5467 } 5468 firstTime = false; 5469 } 5470 } 5471 } 5472 lastMove = thisMove; 5473 }, 5474 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 5475 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 5476 mouse = false; 5477 } 5478 } 5479 }); 5480 mouseDetectionEnabled = true; 5481 } else if (mouseDetectionEnabled && disable) { 5482 $(document).unbind('.smartmenus_mouse'); 5483 mouseDetectionEnabled = false; 5484 } 5485 }; 5486 5487 $.SmartMenus = function(elm, options) { 5488 this.$root = $(elm); 5489 this.opts = options; 5490 this.rootId = ''; // internal 5491 this.$subArrow = null; 5492 this.subMenus = []; // all sub menus in the tree (UL elms) in no particular order (only real - e.g. UL's in mega sub menus won't be counted) 5493 this.activatedItems = []; // stores last activated A's for each level 5494 this.visibleSubMenus = []; // stores visible sub menus UL's 5495 this.showTimeout = 0; 5496 this.hideTimeout = 0; 5497 this.scrollTimeout = 0; 5498 this.clickActivated = false; 5499 this.zIndexInc = 0; 5500 this.$firstLink = null; // we'll use these for some tests 5501 this.$firstSub = null; // at runtime so we'll cache them 5502 this.disabled = false; 5503 this.$disableOverlay = null; 5504 this.init(); 5505 }; 5506 5507 $.extend($.SmartMenus, { 5508 hideAll: function() { 5509 $.each(menuTrees, function() { 5510 this.menuHideAll(); 5511 }); 5512 }, 5513 destroy: function() { 5514 while (menuTrees.length) { 5515 menuTrees[0].destroy(); 5516 } 5517 initMouseDetection(true); 5518 }, 5519 prototype: { 5520 init: function(refresh) { 5521 var self = this; 5522 5523 if (!refresh) { 5524 menuTrees.push(this); 5525 5526 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 5527 5528 if (this.$root.hasClass('sm-rtl')) { 5529 this.opts.rightToLeftSubMenus = true; 5530 } 5531 5532 // init root (main menu) 5533 this.$root 5534 .data('smartmenus', this) 5535 .attr('data-smartmenus-id', this.rootId) 5536 .dataSM('level', 1) 5537 .bind({ 5538 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
5539 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 5540 }) 5541 .delegate('a', { 5542 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 5543 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 5544 'mousedown.smartmenus': $.proxy(this.itemDown, this), 5545 'focus.smartmenus': $.proxy(this.itemFocus, this), 5546 'blur.smartmenus': $.proxy(this.itemBlur, this), 5547 'click.smartmenus': $.proxy(this.itemClick, this), 5548 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 5549 }); 5550 5551 var eNamespace = '.smartmenus' + this.rootId; 5552 // hide menus on tap or click outside the root UL 5553 if (this.opts.hideOnClick) { 5554 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 5555 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 5556 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 5557 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 5558 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 5559 } 5560 // hide sub menus on resize 5561 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5562 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5563 5564 if (this.opts.subIndicators) { 5565 this.$subArrow = $('<span/>').addClass('sub-arrow'); 5566 if (this.opts.subIndicatorsText) { 5567 this.$subArrow.html(this.opts.subIndicatorsText); 5568 } 5569 } 5570 5571 // make sure mouse detection is enabled 5572 initMouseDetection(); 5573 } 5574 5575 // init sub menus 5576 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 5577 5578 this.$firstLink = this.$root.find('a').eq(0); 5579 5580 // find current item 5581 if (this.opts.markCurrentItem) { 5582 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 5583 reHash = /#.*/, 5584 locHref = window.location.href.replace(reDefaultDoc, ''), 5585 locHrefNoHash = locHref.replace(reHash, ''); 5586 this.$root.find('a').each(function() { 5587 var href = this.href.replace(reDefaultDoc, ''), 5588 $this = $(this); 5589 if (href == locHref || href == locHrefNoHash) { 5590 $this.addClass('current'); 5591 if (self.opts.markCurrentTree) { 5592 $this.parents('li').each(function() { 5593 var $this = $(this); 5594 if ($this.dataSM('sub')) { 5595 $this.children('a').addClass('current'); 5596 } 5597 }); 5598 } 5599 } 5600 }); 5601 } 5602 }, 5603 destroy: function() { 5604 this.menuHideAll(); 5605 this.$root 5606 .removeData('smartmenus') 5607 .removeAttr('data-smartmenus-id') 5608 .removeDataSM('level') 5609 .unbind('.smartmenus') 5610 .undelegate('.smartmenus'); 5611 var eNamespace = '.smartmenus' + this.rootId; 5612 $(document).unbind(eNamespace); 5613 $(window).unbind(eNamespace); 5614 if (this.opts.subIndicators) { 5615 this.$subArrow = null; 5616 } 5617 var self = this; 5618 $.each(this.subMenus, function() { 5619 if (this.hasClass('mega-menu')) { 5620 this.find('ul').removeDataSM('in-mega'); 5621 } 5622 if (this.dataSM('shown-before')) { 5623 if (IElt8) { 5624 this.children().css({ styleFloat: '', width: '' }); 5625 } 5626 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 5627 if (!IE6) { 5628 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 5629 } else { 5630 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 5631 } 5632 } 5633 if (this.dataSM('scroll-arrows')) { 5634 this.dataSM('scroll-arrows').remove(); 5635 } 5636 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 5637 } 5638 if (self.opts.subIndicators) { 5639 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 5640 } 5641 this.removeDataSM('shown-before') 5642 .removeDataSM('ie-shim') 5643 .removeDataSM('scroll-arrows') 5644 .removeDataSM('parent-a') 5645 .removeDataSM('level') 5646 .removeDataSM('beforefirstshowfired') 5647 .parent().removeDataSM('sub'); 5648 }); 5649 if (this.opts.markCurrentItem) { 5650 this.$root.find('a.current').removeClass('current'); 5651 } 5652 this.$root = null; 5653 this.$firstLink = null; 5654 this.$firstSub = null; 5655 if (this.$disableOverlay) { 5656 this.$disableOverlay.remove(); 5657 this.$disableOverlay = null; 5658 } 5659 menuTrees.splice($.inArray(this, menuTrees), 1); 5660 }, 5661 disable: function(noOverlay) { 5662 if (!this.disabled) { 5663 this.menuHideAll(); 5664 // display overlay over the menu to prevent interaction 5665 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 5666 var pos = this.$root.offset(); 5667 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 5668 position: 'absolute', 5669 top: pos.top, 5670 left: pos.left, 5671 width: this.$root.outerWidth(), 5672 height: this.$root.outerHeight(),
5673 zIndex: this.getStartZIndex() + 1, 5674 opacity: 0 5675 }).appendTo(document.body); 5676 } 5677 this.disabled = true; 5678 } 5679 }, 5680 docClick: function(e) { 5681 // hide on any click outside the menu or on a menu link 5682 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 5683 this.menuHideAll($(e.target)); 5684 } 5685 }, 5686 docTouchEnd: function(e) { 5687 if (!this.lastTouch) { 5688 return; 5689 } 5690 if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) { 5691 if (this.hideTimeout) { 5692 clearTimeout(this.hideTimeout); 5693 this.hideTimeout = 0; 5694 } 5695 // hide with a delay to prevent triggering accidental unwanted click on some page element 5696 var self = this; 5697 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 5698 } 5699 this.lastTouch = null; 5700 }, 5701 docTouchMove: function(e) { 5702 if (!this.lastTouch) { 5703 return; 5704 } 5705 var touchPoint = e.originalEvent.touches[0]; 5706 this.lastTouch.x2 = touchPoint.pageX; 5707 this.lastTouch.y2 = touchPoint.pageY; 5708 }, 5709 docTouchStart: function(e) { 5710 var touchPoint = e.originalEvent.touches[0]; 5711 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 5712 }, 5713 enable: function() { 5714 if (this.disabled) { 5715 if (this.$disableOverlay) { 5716 this.$disableOverlay.remove(); 5717 this.$disableOverlay = null; 5718 } 5719 this.disabled = false; 5720 } 5721 }, 5722 getHeight: function($elm) { 5723 return this.getOffset($elm, true); 5724 }, 5725 // returns precise width/height float values in IE9+, FF4+, recent WebKit 5726 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 5727 getOffset: function($elm, height) { 5728 var old; 5729 if ($elm.css('display') == 'none') { 5730 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 5731 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 5732 } 5733 var defaultView = $elm[0].ownerDocument.defaultView, 5734 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 5735 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 5736 if (val) { 5737 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 5738 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 5739 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 5740 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 5741 } else { 5742 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 5743 } 5744 if (old) { 5745 $elm.hide().css(old); 5746 } 5747 return val; 5748 }, 5749 getWidth: function($elm) { 5750 return this.getOffset($elm); 5751 }, 5752 getStartZIndex: function() { 5753 var zIndex = parseInt(this.$root.css('z-index')); 5754 return !isNaN(zIndex) ? zIndex : 1; 5755 }, 5756 handleEvents: function() { 5757 return !this.disabled && this.isCSSOn(); 5758 }, 5759 handleItemEvents: function($a) { 5760 return this.handleEvents() && !this.isLinkInMegaMenu($a); 5761 }, 5762 isCollapsible: function() { 5763 return this.$firstSub.css('position') == 'static'; 5764 }, 5765 isCSSOn: function() { 5766 return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'inline'; 5767 }, 5768 isFixed: function() { 5769 return this.$root.css('position') == 'fixed'; 5770 }, 5771 isLinkInMegaMenu: function($a) { 5772 return !$a.parent().parent().dataSM('level'); 5773 }, 5774 isTouchMode: function() { 5775 return !mouse || this.isCollapsible(); 5776 }, 5777 itemActivate: function($a) { 5778 var $li = $a.parent(), 5779 $ul = $li.parent(), 5780 level = $ul.dataSM('level'); 5781 // if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first 5782 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 5783 var self = this; 5784 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 5785 self.itemActivate($(this).dataSM('parent-a')); 5786 }); 5787 } 5788 // hide any visible deeper level sub menus 5789 if (this.visibleSubMenus.length > level) { 5790 for (var i = this.visibleSubMenus.length - 1, l = !this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level; i > l; i--) { 5791 this.menuHide(this.visibleSubMenus[i]); 5792 } 5793 } 5794 // save new active item and sub menu for this level 5795 this.activatedItems[level - 1] = $a; 5796 this.visibleSubMenus[level - 1] = $ul; 5797 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 5798 return; 5799 } 5800 // show the sub menu if this item has one 5801 var $sub = $li.dataSM('sub'); 5802 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 5803 this.menuShow($sub); 5804 } 5805 }, 5806 itemBlur: function(e) { 5807 var $a = $(e.currentTarget); 5808 if (!this.handleItemEvents($a)) { 5809 return; 5810 } 5811 this.$root.triggerHandler('blur.smapi', $a[0]); 5812 }, 5813 itemClick: function(e) { 5814 var $a = $(e.currentTarget); 5815 5816 if (!this.handleItemEvents($a)) { 5817 return; 5818 } 5819 $a.removeDataSM('mousedown'); 5820 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 5821 return false;
5822 } 5823 var $sub = $a.parent().dataSM('sub'); 5824 if (this.isTouchMode()) { 5825 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 5826 if ($a.dataSM('href')) { 5827 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 5828 } 5829 // if the sub is not visible 5830 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5831 // try to activate the item and show the sub 5832 this.itemActivate($a); 5833 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 5834 // if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded 5835 if ($sub.is(':visible')) { 5836 return false; 5837 } 5838 } 5839 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 5840 this.clickActivated = true; 5841 this.menuShow($sub); 5842 return false; 5843 } 5844 if ($a.hasClass('disabled')) { 5845 return false; 5846 } 5847 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 5848 return false; 5849 } 5850 }, 5851 itemDown: function(e) { 5852 var $a = $(e.currentTarget); 5853 if (!this.handleItemEvents($a)) { 5854 return; 5855 } 5856 $a.dataSM('mousedown', true); 5857 }, 5858 itemEnter: function(e) { 5859 var $a = $(e.currentTarget); 5860 if (!this.handleItemEvents($a)) { 5861 return; 5862 } 5863 if (!this.isTouchMode()) { 5864 if (this.showTimeout) { 5865 clearTimeout(this.showTimeout); 5866 this.showTimeout = 0; 5867 } 5868 var self = this; 5869 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 5870 } 5871 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 5872 }, 5873 itemFocus: function(e) { 5874 var $a = $(e.currentTarget); 5875 if (!this.handleItemEvents($a)) { 5876 return; 5877 } 5878 // fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus 5879 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 5880 this.itemActivate($a); 5881 } 5882 this.$root.triggerHandler('focus.smapi', $a[0]); 5883 }, 5884 itemLeave: function(e) { 5885 var $a = $(e.currentTarget); 5886 if (!this.handleItemEvents($a)) { 5887 return; 5888 } 5889 if (!this.isTouchMode()) { 5890 if ($a[0].blur) { 5891 $a[0].blur(); 5892 } 5893 if (this.showTimeout) { 5894 clearTimeout(this.showTimeout); 5895 this.showTimeout = 0; 5896 } 5897 } 5898 $a.removeDataSM('mousedown'); 5899 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 5900 }, 5901 itemTouchEnd: function(e) { 5902 var $a = $(e.currentTarget); 5903 if (!this.handleItemEvents($a)) { 5904 return; 5905 } 5906 // prevent the address bar on iPhone from sliding down when expanding a sub menu 5907 var $sub = $a.parent().dataSM('sub'); 5908 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5909 $a.dataSM('href', $a.attr('href')); 5910 $a.attr('href', '#'); 5911 } 5912 }, 5913 menuFixLayout: function($ul) { 5914 // fixes a menu that is being shown for the first time 5915 if (!$ul.dataSM('shown-before')) { 5916 $ul.hide().dataSM('shown-before', true); 5917 // fix the layout of the items in IE<8 5918 if (IElt8) { 5919 $ul.children().css({ styleFloat: 'left', width: '100%' }); 5920 } 5921 } 5922 }, 5923 menuHide: function($sub) { 5924 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 5925 return; 5926 } 5927 $sub.stop(true, true); 5928 if ($sub.is(':visible')) { 5929 var complete = function() { 5930 // unset z-index 5931 if (IElt9) { 5932 $sub.parent().css('z-index', ''); 5933 } else { 5934 $sub.css('z-index', ''); 5935 } 5936 }; 5937 // if sub is collapsible (mobile view) 5938 if (this.isCollapsible()) { 5939 if (this.opts.collapsibleHideFunction) { 5940 this.opts.collapsibleHideFunction.call(this, $sub, complete); 5941 } else { 5942 $sub.hide(this.opts.collapsibleHideDuration, complete); 5943 } 5944 } else { 5945 if (this.opts.hideFunction) { 5946 this.opts.hideFunction.call(this, $sub, complete); 5947 } else { 5948 $sub.hide(this.opts.hideDuration, complete); 5949 } 5950 } 5951 // remove IE iframe shim 5952 if ($sub.dataSM('ie-shim')) { 5953 $sub.dataSM('ie-shim').remove(); 5954 } 5955 // deactivate scrolling if it is activated for this sub 5956 if ($sub.dataSM('scroll')) { 5957 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 5958 } 5959 // unhighlight parent item 5960 $sub.dataSM('parent-a').removeClass('highlighted'); 5961 var level = $sub.dataSM('level'); 5962 this.activatedItems.splice(level - 1, 1); 5963 this.visibleSubMenus.splice(level - 1, 1); 5964 this.$root.triggerHandler('hide.smapi', $sub[0]); 5965 } 5966 }, 5967 menuHideAll: function($item) { 5968 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 5969 if (this.showTimeout) { 5970 clearTimeout(this.showTimeout); 5971 this.showTimeout = 0; 5972 } 5973 // hide all subs 5974 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 5975 this.menuHide(this.visibleSubMenus[i]); 5976 } 5977 // hide root if it's popup 5978 if (this.opts.isPopup) { 5979 this.$root.stop(true, true); 5980 if (this.$root.is(':visible')) { 5981 if (this.opts.hideFunction) { 5982 this.opts.hideFunction.call(this, this.$root); 5983 } else { 5984 this.$root.hide(this.opts.hideDuration); 5985 } 5986 // remove IE iframe shim 5987 if (this.$root.dataSM('ie-shim')) { 5988 this.$root.dataSM('ie-shim').remove(); 5989 } 5990 } 5991 } 5992 this.activatedItems = []; 5993 this.visibleSubMenus = []; 5994 this.clickActivated = false;
5995 // reset z-index increment 5996 this.zIndexInc = 0; 5997 }, 5998 menuIframeShim: function($ul) { 5999 // create iframe shim for the menu 6000 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 6001 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 6002 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 6003 ); 6004 } 6005 }, 6006 menuInit: function($ul) { 6007 if (!$ul.dataSM('in-mega')) { 6008 this.subMenus.push($ul); 6009 // mark UL's in mega drop downs (if any) so we can neglect them 6010 if ($ul.hasClass('mega-menu')) { 6011 $ul.find('ul').dataSM('in-mega', true); 6012 } 6013 // get level (much faster than, for example, using parentsUntil) 6014 var level = 2, 6015 par = $ul[0]; 6016 while ((par = par.parentNode.parentNode) != this.$root[0]) { 6017 level++; 6018 } 6019 // cache stuff 6020 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 6021 .dataSM('level', level) 6022 .parent().dataSM('sub', $ul); 6023 // add sub indicator to parent item 6024 if (this.opts.subIndicators) { 6025 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 6026 } 6027 } 6028 }, 6029 menuPosition: function($sub) { 6030 var fixIE = $('html.ie').length; 6031 // if (fixIE) { 6032 // var $rowParent = $($sub).closest('.main-menu-container'); 6033 // $rowParent.height($rowParent.height()); 6034 // } 6035 var $a = $sub.dataSM('parent-a'), 6036 $li = $sub.parent(), 6037 $ul = $sub.parent().parent(), 6038 $container = $ul.closest('.row-menu-inner'), 6039 level = $sub.dataSM('level'), 6040 subW = this.getWidth($sub), 6041 subH = this.getHeight($sub), 6042 itemOffset = $a.offset(), 6043 itemX = itemOffset.left, 6044 itemY = itemOffset.top, 6045 itemW = this.getWidth($a), 6046 itemH = this.getHeight($a), 6047 $win = $(window), 6048 winX = $win.scrollLeft(), 6049 winY = $win.scrollTop(), 6050 winW = $win.width(), 6051 winH = $win.height(), 6052 containerW = $container.width(), 6053 containerOffsetX = containerW + ((winW - containerW) / 2), 6054 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 6055 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 6056 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 6057 x, y, leftPos; 6058 if (horizontalParent) { 6059 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 6060 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 6061 } else { 6062 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX; 6063 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 6064 } 6065 if (this.opts.keepInViewport && !this.isCollapsible()) { 6066 if (this.isFixed()) { 6067 itemX -= winX; 6068 itemY -= winY; 6069 winX = winY = 0; 6070 } 6071 var absX = itemX + x, 6072 absY = itemY + y; 6073 if (this.opts.rightToLeftSubMenus && absX < winX) { 6074 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 6075 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 6076 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 6077 } 6078 if (!horizontalParent) { 6079 if (subH < winH && absY + subH > winY + winH) { 6080 y += winY + winH - subH - absY; 6081 } else if (subH >= winH || absY < winY) { 6082 y += winY - absY; 6083 } 6084 } 6085 // do we need scrolling? 6086 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 6087 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 6088 var self = this; 6089 if (!$sub.dataSM('scroll-arrows')) { 6090 $sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]) 6091 .bind({ 6092 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 6093 mouseleave: function(e) { 6094 self.menuScrollStop($sub); 6095 self.menuScrollOut($sub, e); 6096 }, 6097 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 6098 }) 6099 .insertAfter($sub) 6100 ); 6101 } 6102 // bind events to show/hide arrows on hover and save scrolling data for this sub 6103 var vportY = winY - (itemY + itemH); 6104 $sub.dataSM('scroll', { 6105 vportY: vportY, 6106 subH: subH, 6107 winH: winH, 6108 step: 1 6109 }) 6110 .bind({ 6111 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 6112 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 6113 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 6114 }) 6115 .dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: this.getWidth($sub) - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: this.get
6115StartZIndex() + this.zIndexInc }) 6116 .eq(0).css('margin-top', vportY).end() 6117 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 6118 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 6119 } 6120 } 6121 // if ($sub.hasClass('mega-menu-inner')) { 6122 // if ($('.menu-wrapper .megamenu-diff').length > 0) { 6123 // leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth()); 6124 // leftPos = -leftPos; 6125 // } else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft')); 6126 6127 // if ($('body.header-full-width').length > 0) { 6128 // $sub.css({ width: $('.box-container').width()}); 6129 // leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft'))); 6130 // } else $sub.css({ width: containerW}); 6131 // leftPos = leftPos + 'px'; 6132 6133 // } else { 6134 // leftPos = $li.position().left + 'px'; 6135 // } 6136 if ($sub.hasClass('mega-menu-inner')) { 6137 $sub.css({ width: containerW}); 6138 if ($('body.hmenu-center-split').length > 0) { 6139 leftPos = - ($sub.closest('.menu-primary-inner')[0].offsetLeft) + 'px'; 6140 } else { 6141 if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0) { 6142 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 6143 } else { 6144 leftPos = '0px'; 6145 } 6146 } 6147 } else { 6148 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 6149 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 6150 } 6151 6152 $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) }); 6153 // IE iframe shim 6154 this.menuIframeShim($sub); 6155 if ($sub.dataSM('ie-shim')) { 6156 $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) }); 6157 } 6158 }, 6159 menuScroll: function($sub, up, wheel) { 6160 var y = parseFloat($sub.css('margin-top')), 6161 scroll = $sub.dataSM('scroll'), 6162 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 6163 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 6164 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 6165 y = parseFloat($sub.css('margin-top')); 6166 // show opposite arrow if appropriate 6167 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 6168 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 6169 } 6170 // accelerate when not using mousewheel to scroll 6171 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 6172 $sub.dataSM('scroll').step += 0.5; 6173 } 6174 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 6175 if (Math.abs(y - end) < 1) { 6176 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 6177 $sub.dataSM('scroll').step = 1; 6178 } else if (!wheel) { 6179 var self = this; 6180 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 6181 } 6182 }, 6183 menuScrollMousewheel: function($sub, e) { 6184 var $closestSub = $(e.target).closest('ul'); 6185 while ($closestSub.dataSM('in-mega')) { 6186 $closestSub = $closestSub.parent().closest('ul'); 6187 } 6188 if ($closestSub[0] == $sub[0]) { 6189 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 6190 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 6191 this.menuScroll($sub, up, true); 6192 } 6193 } 6194 e.preventDefault(); 6195 }, 6196 menuScrollOut: function($sub, e) { 6197 var reClass = /^scroll-(up|down)/, 6198 $closestSub = $(e.relatedTarget).closest('ul'); 6199 while ($closestSub.dataSM('in-mega')) { 6200 $closestSub = $closestSub.parent().closest('ul'); 6201 } 6202 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 6203 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 6204 } 6205 }, 6206 menuScrollOver: function($sub, e) { 6207 var reClass = /^scroll-(up|down)/, 6208 $closestSub = $(e.target).closest('ul'); 6209 while ($closestSub.dataSM('in-mega')) { 6210 $closestSub = $closestSub.parent().closest('ul'); 6211 } 6212 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 6213 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 6214 } 6215 }, 6216 menuScrollStop: function($sub) { 6217 if (this.scrollTimeout) { 6218 clearTimeout(this.scrollTimeout); 6219 this.scrollTimeout = 0; 6220 $sub.dataSM('scroll').step = 1; 6221 } 6222 }, 6223 menuShow: function($sub) { 6224 if (!$sub.dataSM('beforefirstshowfired')) { 6225 $sub.dataSM('beforefirstshowfired', true); 6226 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 6227 return; 6228 } 6229 } 6230 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 6231 return; 6232 } 6233 this.menuFixLayout($sub); 6234 $sub.stop(true, true); 6235 if (!$sub.is(':visible')) { 6236 // set z-index - for IE < 9 set it to the parent LI
6237 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 6238 if (IElt9) { 6239 $sub.parent().css('z-index', zIndex); 6240 } else { 6241 $sub.css('z-index', zIndex); 6242 } 6243 // highlight parent item 6244 if (this.opts.keepHighlighted || this.isCollapsible()) { 6245 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 6246 $sub.dataSM('parent-a').addClass('highlighted'); 6247 } 6248 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 6249 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 6250 if (!IElt8) { 6251 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6252 if (this.opts.subMenusMinWidth) { 6253 $sub.css('min-width', this.opts.subMenusMinWidth); 6254 } 6255 if (this.opts.subMenusMaxWidth) { 6256 var noMaxWidth = this.getWidth($sub); 6257 $sub.css('max-width', this.opts.subMenusMaxWidth); 6258 if (noMaxWidth > this.getWidth($sub)) { 6259 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6260 } 6261 } 6262 // IE6,7 6263 } else { 6264 $sub.children().css('styleFloat', 'none'); 6265 if (IE6) { 6266 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 6267 .children().children('a').css('white-space', 'nowrap'); 6268 } else { // IE7 6269 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6270 if (this.opts.subMenusMinWidth) { 6271 $sub.css('min-width', this.opts.subMenusMinWidth); 6272 } 6273 } 6274 if (this.opts.subMenusMaxWidth) { 6275 var noMaxWidth = $sub.width(); 6276 if (IE6) { 6277 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 6278 if (noMaxWidth > maxWidth) { 6279 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 6280 } else { 6281 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 6282 } 6283 } else { // IE7 6284 $sub.css('max-width', this.opts.subMenusMaxWidth); 6285 if (noMaxWidth > $sub.width()) { 6286 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6287 } else { 6288 $sub.width(noMaxWidth); 6289 } 6290 } 6291 } else { 6292 $sub.width($sub.width()); 6293 } 6294 $sub.children().css('styleFloat', 'left'); 6295 } 6296 } 6297 this.menuPosition($sub); 6298 // insert IE iframe shim 6299 if ($sub.dataSM('ie-shim')) { 6300 $sub.dataSM('ie-shim').insertBefore($sub); 6301 } 6302 var complete = function() { 6303 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 6304 $sub.css('overflow', ''); 6305 }; 6306 // if sub is collapsible (mobile view) 6307 if (this.isCollapsible()) { 6308 if (this.opts.collapsibleShowFunction) { 6309 this.opts.collapsibleShowFunction.call(this, $sub, complete); 6310 } else { 6311 $sub.show(this.opts.collapsibleShowDuration, complete); 6312 } 6313 } else { 6314 if (this.opts.showFunction) { 6315 this.opts.showFunction.call(this, $sub, complete); 6316 } else { 6317 $sub.show(this.opts.showDuration, complete); 6318 } 6319 } 6320 // save new sub menu for this level 6321 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 6322 this.$root.triggerHandler('show.smapi', $sub[0]); 6323 } 6324 }, 6325 popupHide: function(noHideTimeout) { 6326 if (this.hideTimeout) { 6327 clearTimeout(this.hideTimeout); 6328 this.hideTimeout = 0; 6329 } 6330 var self = this; 6331 this.hideTimeout = setTimeout(function() { 6332 self.menuHideAll(); 6333 }, noHideTimeout ? 1 : this.opts.hideTimeout); 6334 }, 6335 popupShow: function(left, top) { 6336 if (!this.opts.isPopup) { 6337 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 6338 return; 6339 } 6340 if (this.hideTimeout) { 6341 clearTimeout(this.hideTimeout); 6342 this.hideTimeout = 0; 6343 } 6344 this.menuFixLayout(this.$root); 6345 this.$root.stop(true, true); 6346 if (!this.$root.is(':visible')) { 6347 this.$root.css({ left: left, top: top }); 6348 // IE iframe shim 6349 this.menuIframeShim(this.$root); 6350 if (this.$root.dataSM('ie-shim')) { 6351 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6351: left, top: top }).insertBefore(this.$root); 6352 } 6353 // show menu 6354 if (this.opts.showFunction) { 6355 this.opts.showFunction.call(this, this.$root); 6356 } else { 6357 this.$root.show(this.opts.showDuration); 6358 } 6359 this.visibleSubMenus[0] = this.$root; 6360 } 6361 }, 6362 refresh: function() { 6363 this.menuHideAll(); 6364 this.$root.find('ul').each(function() { 6365 var $this = $(this); 6366 if ($this.dataSM('scroll-arrows')) { 6367 $this.dataSM('scroll-arrows').remove(); 6368 } 6369 }) 6370 .removeDataSM('in-mega') 6371 .removeDataSM('shown-before') 6372 .removeDataSM('ie-shim') 6373 .removeDataSM('scroll-arrows') 6374 .removeDataSM('parent-a') 6375 .removeDataSM('level') 6376 .removeDataSM('beforefirstshowfired'); 6377 this.$root.find('a.has-submenu').removeClass('has-submenu') 6378 .parent().removeDataSM('sub'); 6379 if (this.opts.subIndicators) { 6380 this.$root.find('span.sub-arrow').remove(); 6381 } 6382 if (this.opts.markCurrentItem) { 6383 this.$root.find('a.current').removeClass('current'); 6384 } 6385 this.subMenus = []; 6386 this.init(true); 6387 }, 6388 rootOut: function(e) { 6389 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6390 return; 6391 } 6392 if (this.hideTimeout) { 6393 clearTimeout(this.hideTimeout); 6394 this.hideTimeout = 0; 6395 } 6396 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 6397 var self = this; 6398 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 6399 } 6400 }, 6401 rootOver: function(e) { 6402 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6403 return; 6404 } 6405 if (this.hideTimeout) { 6406 clearTimeout(this.hideTimeout); 6407 this.hideTimeout = 0; 6408 } 6409 }, 6410 winResize: function(e) { 6411 if (!this.handleEvents()) { 6412 // we still need to resize the disable overlay if it's visible 6413 if (this.$disableOverlay) { 6414 var pos = this.$root.offset(); 6415 this.$disableOverlay.css({ 6416 top: pos.top, 6417 left: pos.left, 6418 width: this.$root.outerWidth(), 6419 height: this.$root.outerHeight() 6420 }); 6421 } 6422 return; 6423 } 6424 // hide sub menus on resize - on mobile do it only on orientation change 6425 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 6426 if (this.activatedItems.length) { 6427 this.activatedItems[this.activatedItems.length - 1][0].blur(); 6428 } 6429 this.menuHideAll(); 6430 } 6431 } 6432 } 6433 }); 6434 6435 $.fn.dataSM = function(key, val) { 6436 if (val) { 6437 return this.data(key + '_smartmenus', val); 6438 } 6439 return this.data(key + '_smartmenus'); 6440 } 6441 6442 $.fn.removeDataSM = function(key) { 6443 return this.removeData(key + '_smartmenus'); 6444 } 6445 6446 $.fn.smartmenus = function(options) { 6447 if (typeof options == 'string') { 6448 var args = arguments, 6449 method = options; 6450 Array.prototype.shift.call(args); 6451 return this.each(function() { 6452 var smartmenus = $(this).data('smartmenus'); 6453 if (smartmenus && smartmenus[method]) { 6454 smartmenus[method].apply(smartmenus, args); 6455 } 6456 }); 6457 } 6458 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 6459 return this.each(function() { 6460 new $.SmartMenus(this, opts); 6461 }); 6462 } 6463 6464 // default settings 6465 $.fn.smartmenus.defaults = { 6466 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 6467 mainMenuSubOffsetX: 0, // pixels offset from default position
6468 mainMenuSubOffsetY: 0, // pixels offset from default position 6469 subMenusSubOffsetX: 0, // pixels offset from default position 6470 subMenusSubOffsetY: 0, // pixels offset from default position 6471 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6472 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6473 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 6474 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 6475 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 6476 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 6477 scrollInterval: 30, // interval between each scrolling step 6478 scrollAccelerate: true, // accelerate scrolling or use a fixed step 6479 showTimeout: 250, // timeout before showing the sub menus 6480 hideTimeout: 500, // timeout before hiding the sub menus 6481 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 6482 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 6483 // don't forget to call complete() at the end of whatever you do 6484 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 6485 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 6486 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 6487 // don't forget to call complete() at the end of whatever you do 6488 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 6489 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 6490 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 6491 // (i.e. when mobile styles are used to make the sub menus collapsible) 6492 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 6493 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 6494 // (i.e. when mobile styles are used to make the sub menus collapsible) 6495 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 6496 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 6497 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 6498 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 6499 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 6500 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 6501 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 6502 bottomToTopSubMenus: false, // bottom to top display of the sub menus 6503 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 6504 }; 6505 6506})(jQuery); 6507 6508/* 6509 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 6510 * 6511 * Uses the built in easing capabilities added In jQuery 1.1 6512 * to offer multiple easing options 6513 * 6514 * TERMS OF USE - jQuery Easing 6515 * 6516 * Open source under the BSD License. 6517 * 6518 * Copyright © 2008 George McGinley Smith 6519 * All rights reserved. 6520 * 6521 * Redistribution and use in source and binary forms, with or without modification, 6522 * are permitted provided that the following conditions are met: 6523 * 6524 * Redistributions of source code must retain the above copyright notice, this list of 6525 * conditions and the following disclaimer. 6526 * Redistributions in binary form must reproduce the above copyright notice, this list 6527 * of conditions and the following disclaimer in the documentation and/or other materials 6528 * provided with the distribution. 6529 * 6530 * Neither the name of the author nor the names of contributors may be used to endorse 6531 * or promote products derived from this software without specific prior written permission. 6532 * 6533 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6534 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6535 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6536 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6537-6682
6537 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6538 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6539 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6540 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6541 * OF THE POSSIBILITY OF SUCH DAMAGE. 6542 * 6543*/ 6544 6545// t: current time, b: begInnIng value, c: change In value, d: duration 6546jQuery.easing['jswing'] = jQuery.easing['swing']; 6547 6548jQuery.extend( jQuery.easing, 6549{ 6550 def: 'easeOutQuad', 6551 swing: function (x, t, b, c, d) { 6552 //alert(jQuery.easing.default); 6553 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 6554 }, 6555 easeInQuad: function (x, t, b, c, d) { 6556 return c*(t/=d)*t + b; 6557 }, 6558 easeOutQuad: function (x, t, b, c, d) { 6559 return -c *(t/=d)*(t-2) + b; 6560 }, 6561 easeInOutQuad: function (x, t, b, c, d) { 6562 if ((t/=d/2) < 1) return c/2*t*t + b; 6563 return -c/2 * ((--t)*(t-2) - 1) + b; 6564 }, 6565 easeInCubic: function (x, t, b, c, d) { 6566 return c*(t/=d)*t*t + b; 6567 }, 6568 easeOutCubic: function (x, t, b, c, d) { 6569 return c*((t=t/d-1)*t*t + 1) + b; 6570 }, 6571 easeInOutCubic: function (x, t, b, c, d) { 6572 if ((t/=d/2) < 1) return c/2*t*t*t + b; 6573 return c/2*((t-=2)*t*t + 2) + b; 6574 }, 6575 easeInQuart: function (x, t, b, c, d) { 6576 return c*(t/=d)*t*t*t + b; 6577 }, 6578 easeOutQuart: function (x, t, b, c, d) { 6579 return -c * ((t=t/d-1)*t*t*t - 1) + b; 6580 }, 6581 easeInOutQuart: function (x, t, b, c, d) { 6582 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 6583 return -c/2 * ((t-=2)*t*t*t - 2) + b; 6584 }, 6585 easeInQuint: function (x, t, b, c, d) { 6586 return c*(t/=d)*t*t*t*t + b; 6587 }, 6588 easeOutQuint: function (x, t, b, c, d) { 6589 return c*((t=t/d-1)*t*t*t*t + 1) + b; 6590 }, 6591 easeInOutQuint: function (x, t, b, c, d) { 6592 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 6593 return c/2*((t-=2)*t*t*t*t + 2) + b; 6594 }, 6595 easeInSine: function (x, t, b, c, d) { 6596 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 6597 }, 6598 easeOutSine: function (x, t, b, c, d) { 6599 return c * Math.sin(t/d * (Math.PI/2)) + b; 6600 }, 6601 easeInOutSine: function (x, t, b, c, d) { 6602 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 6603 }, 6604 easeInExpo: function (x, t, b, c, d) { 6605 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 6606 }, 6607 easeOutExpo: function (x, t, b, c, d) { 6608 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 6609 }, 6610 easeInOutExpo: function (x, t, b, c, d) { 6611 if (t==0) return b; 6612 if (t==d) return b+c; 6613 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 6614 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 6615 }, 6616 easeInCirc: function (x, t, b, c, d) { 6617 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 6618 }, 6619 easeOutCirc: function (x, t, b, c, d) { 6620 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 6621 }, 6622 easeInOutCirc: function (x, t, b, c, d) { 6623 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 6624 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 6625 }, 6626 easeInElastic: function (x, t, b, c, d) { 6627 var s=1.70158;var p=0;var a=c; 6628 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6629 if (a < Math.abs(c)) { a=c; var s=p/4; } 6630 else var s = p/(2*Math.PI) * Math.asin (c/a); 6631 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6632 }, 6633 easeOutElastic: function (x, t, b, c, d) { 6634 var s=1.70158;var p=0;var a=c; 6635 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6636 if (a < Math.abs(c)) { a=c; var s=p/4; } 6637 else var s = p/(2*Math.PI) * Math.asin (c/a); 6638 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 6639 }, 6640 easeInOutElastic: function (x, t, b, c, d) { 6641 var s=1.70158;var p=0;var a=c; 6642 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 6643 if (a < Math.abs(c)) { a=c; var s=p/4; } 6644 else var s = p/(2*Math.PI) * Math.asin (c/a); 6645 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6646 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 6647 }, 6648 easeInBack: function (x, t, b, c, d, s) { 6649 if (s == undefined) s = 1.70158; 6650 return c*(t/=d)*t*((s+1)*t - s) + b; 6651 }, 6652 easeOutBack: function (x, t, b, c, d, s) { 6653 if (s == undefined) s = 1.70158; 6654 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 6655 }, 6656 easeInOutBack: function (x, t, b, c, d, s) { 6657 if (s == undefined) s = 1.70158; 6658 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 6659 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 6660 }, 6661 easeInBounce: function (x, t, b, c, d) { 6662 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 6663 }, 6664 easeOutBounce: function (x, t, b, c, d) { 6665 if ((t/=d) < (1/2.75)) { 6666 return c*(7.5625*t*t) + b; 6667 } else if (t < (2/2.75)) { 6668 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 6669 } else if (t < (2.5/2.75)) { 6670 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 6671 } else { 6672 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 6673 } 6674 }, 6675 easeInOutBounce: function (x, t, b, c, d) { 6676 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 6677 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 6678 } 6679}); 6680 6681/* 6682 *
6683 * TERMS OF USE - EASING EQUATIONS 6684 * 6685 * Open source under the BSD License. 6686 * 6687 * Copyright © 2001 Robert Penner 6688 * All rights reserved. 6689 * 6690 * Redistribution and use in source and binary forms, with or without modification, 6691 * are permitted provided that the following conditions are met: 6692 * 6693 * Redistributions of source code must retain the above copyright notice, this list of 6694 * conditions and the following disclaimer. 6695 * Redistributions in binary form must reproduce the above copyright notice, this list 6696 * of conditions and the following disclaimer in the documentation and/or other materials 6697 * provided with the distribution. 6698 * 6699 * Neither the name of the author nor the names of contributors may be used to endorse 6700 * or promote products derived from this software without specific prior written permission. 6701 * 6702 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6703 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6704 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6705 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 6706 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6707 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6708 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6709 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6710 * OF THE POSSIBILITY OF SUCH DAMAGE. 6711 * 6712 */ 6713 6714(function($, window, undefined) { 6715 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 6716 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 6717 6718 // requestAnimationFrame polyfill by Erik Möller 6719 // fixes from Paul Irish and Tino Zijdel 6720 6721 var lastTime = 0, 6722 running, 6723 animate = function (elem) { 6724 if (running) { 6725 window.requestAnimationFrame(animate, elem); 6726 jQuery.fx.tick(); 6727 } 6728 }, 6729 vendors = ['ms', 'moz', 'webkit', 'o']; 6730 6731 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 6732 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 6733 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 6734 || window[vendors[x]+'CancelRequestAnimationFrame']; 6735 } 6736 6737 if (!window.requestAnimationFrame) 6738 window.requestAnimationFrame = function(fn, element) { 6739 var currTime = new Date().getTime(), 6740 delta = currTime - lastTime, 6741 timeToCall = Math.max(0, 16 - delta); 6742 6743 var id = window.setTimeout(function() { 6744 fn(currTime + timeToCall); 6745 }, 6746 timeToCall 6747 ); 6748 6749 lastTime = currTime + timeToCall; 6750 6751 return id; 6752 }; 6753 6754 if (!window.cancelAnimationFrame) { 6755 window.cancelAnimationFrame = function(id) { 6756 clearTimeout(id); 6757 }; 6758 } 6759 6760 jQuery.fx.timer = function (timer) { 6761 if (timer() && jQuery.timers.push(timer) && !running) { 6762 running = true; 6763 animate(timer.elem); 6764 } 6765 }; 6766 6767 jQuery.fx.stop = function() { 6768 running = false; 6769 }; 6770 6771}(jQuery, this)); 6772 6773/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 6774 * Licensed under the MIT License (LICENSE.txt). 6775 * 6776 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 6777 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6778 * Thanks to: Seamus Leahy for adding deltaX and deltaY 6779 * 6780 * Version: 3.0.6 6781 * 6782 * Requires: 1.2.2+ 6783 */ 6784(function($) { 6785 var types = ['DOMMouseScroll', 'mousewheel']; 6786 if ($.event.fixHooks) { 6787 for (var i = types.length; i;) { 6788 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 6789 } 6790 } 6791 $.event.special.mousewheel = { 6792 setup: function() { 6793 if (this.addEventListener) { 6794 for (var i = types.length; i;) { 6795 this.addEventListener(types[--i], handler, false); 6796 } 6797 } else { 6798 this.onmousewheel = handler; 6799 } 6800 }, 6801 teardown: function() { 6802 if (this.removeEventListener) { 6803 for (var i = types.length; i;) { 6804 this.removeEventListener(types[--i], handler, false); 6805 } 6806 } else { 6807 this.onmousewheel = null; 6808 } 6809 } 6810 }; 6811 $.fn.extend({ 6812 mousewheel: function(fn) { 6813 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 6814 }, 6815 unmousewheel: function(fn) { 6816 return this.unbind("mousewheel", fn); 6817 } 6818 }); 6819 6820 function handler(event) { 6821 var orgEvent = event || window.event, 6822 args = [].slice.call(arguments, 1), 6823 delta = 0, 6824 returnValue = true, 6825 deltaX = 0, 6826 deltaY = 0; 6827 event = $.event.fix(orgEvent); 6828 event.type = "mousewheel"; 6829 // Old school scrollwheel delta 6830 if (orgEvent.wheelDelta) { 6831 delta = orgEvent.wheelDelta / 120; 6832 } 6833 if (orgEvent.detail) { 6834 delta = -orgEvent.detail / 3; 6835 } 6836 // New school multidimensional scroll (touchpads) deltas 6837 deltaY = delta; 6838 // Gecko 6839 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 6840 deltaY = 0; 6841 deltaX = -1 * delta; 6842 } 6843 // Webkit 6844 if (orgEvent.wheelDeltaY !== undefined) { 6845 deltaY = orgEvent.wheelDeltaY / 120; 6846 } 6847 if (orgEvent.wheelDeltaX !== undefined) { 6848 deltaX = -1 * orgEvent.wheelDeltaX / 120; 6849 } 6850 // Add event and delta to the front of the arguments 6851 args.unshift(event, delta, deltaX, deltaY); 6852 return ($.event.dispatch || $.event.handle).apply(this, args); 6853 } 6854})(jQuery); 6855 6856/** 6857 * jQuery iLightBox - Revolutionary Lightbox Plugin 6858 * http://www.ilightbox.net/ 6859 * 6860 * @version: 2.2.4 - October 14, 2017 6861 * 6862 * @author: iProDev (Hemn Chawroka) 6863 * http://www.iprodev.com/ 6864 * 6865 */ 6866(function($, window, undefined) { 6867 6868 var extensions = { 6869 flash: ['swf'], 6870 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 6871 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 6872 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 6873 }, 6874 6875 // Global DOM elements 6876 $win = $(window), 6877 $doc = $(document), 6878
6879 // Support indicators 6880 browser, 6881 transform, 6882 gpuAcceleration, 6883 fullScreenApi = '', 6884 userAgent = navigator.userAgent || navigator.vendor || window.opera, 6885 supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)), 6886 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)), 6887 6888 // Events 6889 clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox", 6890 touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 6891 touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 6892 touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 6893 6894 // Math shorthands 6895 abs = Math.abs, 6896 sqrt = Math.sqrt, 6897 round = Math.round, 6898 max = Math.max, 6899 min = Math.min, 6900 floor = Math.floor, 6901 random = Math.random, 6902 6903 pluginspages = { 6904 quicktime: 'http://www.apple.com/quicktime/download', 6905 flash: 'http://www.adobe.com/go/getflash' 6906 }, 6907 6908 iLightBox = function(el, options, items, instant) { 6909 var iL = this; 6910 6911 iL.options = options, 6912 iL.selector = el.selector || el, 6913 iL.context = el.context, 6914 iL.instant = instant; 6915 6916 if (items.length < 1) iL.attachItems(); 6917 else iL.items = items; 6918 6919 iL.vars = { 6920 total: iL.items.length, 6921 start: 0, 6922 current: null, 6923 next: null, 6924 prev: null, 6925 BODY: $('body'), 6926 loadRequests: 0, 6927 overlay: $('<div class="ilightbox-overlay"></div>'), 6928 loader: $('<div class="ilightbox-loader"><div></div></div>'), 6929 toolbar: $('<div class="ilightbox-toolbar"></div>'), 6930 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 6931 title: $('<div class="ilightbox-title"></div>'), 6932 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 6933 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 6934 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 6935 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 6936 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 6937 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6938 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6939 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6940 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 6941 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
6942 thumbnails: $('<div class="ilightbox-thumbnails" ondragstart="return false;"><div class="ilightbox-thumbnails-container"><a class="ilightbox-thumbnails-dragger"></a><div class="ilightbox-thumbnails-grid"></div></div></div>'), 6943 thumbs: false, 6944 nextLock: false, 6945 prevLock: false, 6946 hashLock: false, 6947 isMobile: false, 6948 mobileMaxWidth: 980, 6949 isInFullScreen: false, 6950 isSwipe: false, 6951 mouseID: 0, 6952 cycleID: 0, 6953 isPaused: 0, 6954 captionHeight: 39, 6955 }; 6956 6957 // Hideable elements with mousemove event 6958 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 6959 6960 iL.normalizeItems(); 6961 6962 //Check necessary plugins 6963 iL.availPlugins(); 6964 6965 //Set startFrom 6966 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 6967 6968 //If randomStart 6969 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 6970 iL.vars.start = iL.options.startFrom; 6971 6972 if (instant) iL.instantCall(); 6973 else iL.patchItemsEvents(); 6974 6975 if (iL.options.linkId) { 6976 iL.hashChangeHandler(); 6977 $win.iLightBoxHashChange(function() { 6978 iL.hashChangeHandler(); 6979 }); 6980 } 6981 6982 if (supportTouch) { 6983 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 6984 replace = "itap"; 6985 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 6986 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 6987 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 6988 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 6989 } 6990 6991 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 6992 $.extend(iL.options.styles, { 6993 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6994 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6995 nextOpacity: 0, 6996 prevOpacity: 0 6997 }); 6998 } 6999 }; 7000 7001 //iLightBox helpers 7002 iLightBox.prototype = { 7003 showLoader: function() { 7004 var iL = this; 7005 iL.vars.loadRequests += 1; 7006 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7007 //top: '-30px' 7008 opacity: '1' 7009 }, iL.options.show.speed, 'easeOutCirc'); 7010 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7011 //left: '-30px' 7012 opacity: '1' 7013 }, iL.options.show.speed, 'easeOutCirc'); 7014 }, 7015 7016 hideLoader: function() { 7017 var iL = this; 7018 iL.vars.loadRequests -= 1; 7019 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 7020 if (iL.options.path.toLowerCase() == "horizontal") { 7021 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7022 //top: '-192px' 7023 opacity: '0' 7024 }, iL.options.show.speed, 'easeInCirc'); 7025 } else { 7026 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7027 //left: '-192px' 7028 opacity: '0' 7029 }, iL.options.show.speed, 'easeInCirc'); 7030 } 7031 }, 7032 7033 createUI: function() { 7034 var iL = this; 7035 7036 iL.ui = { 7037 currentElement: iL.vars.holder, 7038 nextElement: iL.vars.nextPhoto, 7039 prevElement: iL.vars.prevPhoto, 7040 currentItem: iL.vars.current, 7041 nextItem: iL.vars.next, 7042 prevItem: iL.vars.prev, 7043 hide: function() { 7044 iL.closeAction(); 7045 }, 7046 refresh: function() { 7047 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7048 }, 7049 fullscreen: function() { 7050 iL.fullScreenAction(); 7051 } 7052 }; 7053 }, 7054 7055 attachItems: function() { 7056 var iL = this, 7057 itemsObject = new Array(), 7058 items = new Array(); 7059 7060 $(iL.selector, iL.context).each(function() { 7061 var t = $(this), 7062 URL = t.attr(iL.options.attr) || null, 7063 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 7064 caption = t.data('caption'), 7065 title = t.data('title'), 7066 type = t.data('type') || getTypeByExtension(URL), 7067 clone = t.data('lbox-clone') || false; 7068 7069 if (t.data('lbox-clone') != undefined) return; 7070 7071 //Uncode addition ##START## 7072 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 7073 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 7074 URL_i, 7075 URLS_LENGHT = ALBUM_URLS.length; 7076 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 7077 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 7078 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 7079 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 7080 items.push({ 7081 URL: ALBUM_URLS[URL_i].url, 7082 caption: ALBUM_URLS[URL_i].caption, 7083 title: ALBUM_URLS[URL_i].title, 7084 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 7085 options: item_opts, 7086 clone: clone 7087 }); 7088 var newT = t; 7089 newT.attr('href',ALBUM_URLS[URL_i].url); 7090 if (!iL.instant) itemsObject.push(newT); 7091 } 7092 } 7093 } else { 7094 //Uncode addition ##END## 7095 items.push({ 7096 URL: URL, 7097 caption: caption, 7098 title: title, 7099 type: type, 7100 options: options, 7101 clone: clone 7102 }); 7103 } 7104 7105 7106 if (iL.vars != undefined) iL.vars.total = items.length; 7107 7108 if (!iL.instant) itemsObject.push(t); 7109 }); 7110 7111 iL.items = items, 7112 iL.itemsObject = itemsObject; 7113 7114 }, 7115 7116 normalizeItems: function() { 7117 var iL = this, 7118 newItems = new Array(); 7119 7120 $.each(iL.items, function(key, val) { 7121 7122 if (typeof val == "string") val = { 7123 url: val 7124 }; 7125 7126 var URL = val.url || val.URL || null, 7127 options = val.options || {}, 7128 caption = val.caption || null, 7129 title = val.title || null, 7130 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 7131 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 7132 7133 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
7134 options.videoType = options.videoType || null, 7135 options.skin = options.skin || iL.options.skin, 7136 options.width = options.width || null, 7137 options.height = options.height || null, 7138 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 7139 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 7140 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 7141 7142 if (type == "video") { 7143 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 7144 7145 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 7146 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 7147 options.html5video.preload = options.html5video.preload || "metadata"; 7148 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 7149 } 7150 7151 if (!options.width || !options.height) { 7152 if (type == "video") options.width = 1280, options.height = 720; 7153 else if (type == "iframe") options.width = '100%', options.height = '90%'; 7154 else if (type == "flash") options.width = 1280, options.height = 720; 7155 } 7156 7157 delete val.url; 7158 val.index = key; 7159 val.URL = URL; 7160 val.caption = caption; 7161 val.title = title; 7162 val.type = type; 7163 val.options = options; 7164 val.ext = ext; 7165 7166 newItems.push(val); 7167 }); 7168 7169 iL.items = newItems; 7170 }, 7171 7172 instantCall: function() { 7173 var iL = this, 7174 key = iL.vars.start; 7175 7176 iL.vars.current = key; 7177 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 7178 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 7179 7180 iL.addContents(); 7181 iL.patchEvents(); 7182 }, 7183 7184 addContents: function() { 7185 var iL = this, 7186 vars = iL.vars, 7187 opts = iL.options, 7188 viewport = getViewport(), 7189 path = opts.path.toLowerCase(), 7190 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 7191 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 7192 }), 7193 needRecognition = recognizingItems.length > 0; 7194 7195 if (opts.mobileOptimizer && !opts.innerToolbar) 7196 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7197 7198 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 7199 7200 if (opts.linkId) 7201 vars.overlay[0].setAttribute('linkid', opts.linkId); 7202 7203 //Add Toolbar Buttons 7204 if (opts.controls.toolbar) { 7205 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 7206 if (opts.controls.fullscreen) 7207 vars.toolbar.append(vars.fullScreenButton); 7208 if (opts.controls.slideshow) 7209 vars.toolbar.append(vars.innerPlayButton); 7210 if (vars.total > 1) 7211 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 7212 } 7213 7214 //Append elements to body 7215 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 7216 7217 if (!opts.innerToolbar) 7218 vars.BODY.append(vars.toolbar); 7219 if (opts.controls.arrows) 7220 vars.BODY.append(vars.nextButton).append(vars.prevButton); 7221 7222 if (opts.controls.thumbnail && vars.total > 1) { 7223 vars.BODY.append(vars.thumbnails); 7224 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 7225 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 7226 vars.thumbs = true; 7227 } 7228 7229 //Configure loader and arrows 7230 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 7231 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 7232 } : { 7233 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 7234 }; 7235 vars.loader.addClass(opts.skin).css(loaderCss); 7236 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 7237 if (path == "horizontal") 7238 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 7239 7240 // Configure arrow buttons 7241 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7242 7243 if (!opts.infinite) { 7244 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 7245 7246 if (vars.current == 0) 7247 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 7248 if (vars.current >= vars.total - 1) 7249 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 7250 } 7251 7252 if (opts.show.effect) { 7253 vars.overlay.stop().fadeIn(opts.show.speed); 7254 vars.toolbar.stop().fadeIn(opts.show.speed); 7255 } else { 7256 vars.overlay.show(); 7257 vars.toolbar.show(); 7258 } 7259 7260 var length = recognizingItems.length; 7261 if (needRecognition) { 7262 iL.showLoader(); 7263 7264 $.each(recognizingItems, function(key, val) { 7265 var resultFnc = function(result) { 7266 var key = -1, 7267 filter = iL.items.filter(function(e, i, arr) { 7268 if (e.URL == result.url) 7269 key = i; 7270 7271 return e.URL == result.url; 7272 }), 7273 self = iL.items[key]; 7274 7275 if (result) 7276 $.extend(true, self, { 7277 URL: result.source, 7278 type: result.type, 7279 recognized: true, 7280 options: { 7281 html5video: result.html5video, 7282 width: (result.type == "image") ? 0 : (result.width || self.width), 7283 height: (result.type == "image") ? 0 : (result.height || self.height), 7284 thumbnail: self.options.thumbnail || result.thumbnail 7285 } 7286 }); 7287 7288 length--; 7289 7290 if (length == 0) { 7291 iL.hideLoader(); 7292 7293 vars.dontGenerateThumbs = false;
7294 iL.generateThumbnails(); 7295 7296 if (opts.show.effect) 7297 setTimeout(function() { 7298 iL.generateBoxes(); 7299 }, opts.show.speed); 7300 else 7301 iL.generateBoxes(); 7302 } 7303 }; 7304 7305 iL.ogpRecognition(this, resultFnc); 7306 }); 7307 } 7308 else { 7309 if (opts.show.effect) 7310 setTimeout(function() { 7311 iL.generateBoxes(); 7312 }, opts.show.speed); 7313 else 7314 iL.generateBoxes(); 7315 } 7316 7317 iL.createUI(); 7318 7319 window.iLightBox = { 7320 close: function() { 7321 iL.closeAction(); 7322 }, 7323 fullscreen: function() { 7324 iL.fullScreenAction(); 7325 }, 7326 moveNext: function() { 7327 iL.moveTo('next'); 7328 }, 7329 movePrev: function() { 7330 iL.moveTo('prev'); 7331 }, 7332 goTo: function(index) { 7333 iL.goTo(index); 7334 }, 7335 refresh: function() { 7336 iL.refresh(); 7337 }, 7338 reposition: function() { 7339 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7340 }, 7341 setOption: function(options) { 7342 iL.setOption(options); 7343 }, 7344 destroy: function() { 7345 iL.closeAction(); 7346 iL.dispatchItemsEvents(); 7347 } 7348 }; 7349 7350 if (opts.linkId) { 7351 vars.hashLock = true; 7352 window.location.hash = opts.linkId + '/' + vars.current; 7353 setTimeout(function() { 7354 vars.hashLock = false; 7355 }, 55); 7356 } 7357 7358 if (!opts.slideshow.startPaused) { 7359 iL.resume(); 7360 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 7361 } 7362 7363 //Trigger the onOpen callback 7364 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 7365 }, 7366 7367 loadContent: function(obj, opt, speed) { 7368 var iL = this, 7369 holder, item; 7370 7371 iL.createUI(); 7372 7373 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 7374 7375 if (opt == 'current') { 7376 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 7377 else iL.vars.lockWheel = false; 7378 7379 if (!obj.options.swipe) iL.vars.lockSwipe = true; 7380 else iL.vars.lockSwipe = false; 7381 } 7382 7383 switch (opt) { 7384 case 'current': 7385 holder = iL.vars.holder, item = iL.vars.current; 7386 break; 7387 case 'next': 7388 holder = iL.vars.nextPhoto, item = iL.vars.next; 7389 break; 7390 case 'prev': 7391 holder = iL.vars.prevPhoto, item = iL.vars.prev; 7392 break; 7393 } 7394 7395 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 7396 $('div.ilightbox-inner-toolbar', holder).remove(); 7397 7398 if (obj.title || iL.options.innerToolbar) { 7399 var innerToolbar = iL.vars.innerToolbar.clone(); 7400 if (obj.title && iL.options.show.title) { 7401 var title = iL.vars.title.clone(); 7402 title.empty().html(obj.title); 7403 innerToolbar.append(title); 7404 } 7405 if (iL.options.innerToolbar) { 7406 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 7407 } 7408 holder.prepend(innerToolbar); 7409 } 7410 7411 //console.warn('loadContent', arguments); 7412 7413 iL.loadSwitcher(obj, holder, item, opt); 7414 }, 7415 7416 loadSwitcher: function(obj, holder, item, opt) { 7417 var iL = this, 7418 opts = iL.options, 7419 api = { 7420 element: holder, 7421 position: item 7422 }; 7423 7424 switch (obj.type) { 7425 case 'image': 7426 //Trigger the onBeforeLoad callback 7427 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7428 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7429 7430 iL.loadImage(obj.URL, function(img) { 7431 //Trigger the onAfterLoad callback 7432 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7433 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7434 7435 var width = (img) ? img.width : 400, 7436 height = (img) ? img.height : 200; 7437 7438 holder.data({ 7439 naturalWidth: width, 7440 naturalHeight: height 7441 }); 7442 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 7443 7444 //Trigger the onRender callback 7445 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7446 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7447 7448 iL.configureHolder(obj, opt, holder); 7449 }); 7450 7451 break; 7452
7453 case 'video': 7454 holder.data({ 7455 naturalWidth: obj.options.width, 7456 naturalHeight: obj.options.height 7457 }); 7458 7459 if (opt === 'current') { 7460 iL.addContent(holder, obj); 7461 7462 //Trigger the onRender callback 7463 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7464 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7465 } else { 7466 $('div.ilightbox-container', holder).empty(); 7467 } 7468 7469 iL.configureHolder(obj, opt, holder); 7470 7471 break; 7472 7473 case 'iframe': 7474 //iL.showLoader(); 7475 holder.data({ 7476 naturalWidth: obj.options.width, 7477 naturalHeight: obj.options.height 7478 }); 7479 7480 iL.configureHolder(obj, opt, holder); 7481 7482 if (opt === 'current') { 7483 var el = iL.addContent(holder, obj); 7484 7485 //Trigger the onRender callback 7486 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7487 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7488 7489 //Trigger the onBeforeLoad callback 7490 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7491 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7492 7493 el.bind('load', function() { 7494 //Trigger the onAfterLoad callback 7495 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7496 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7497 7498 //iL.hideLoader(); 7499 el.unbind('load'); 7500 }); 7501 } else { 7502 $('div.ilightbox-container', holder).empty(); 7503 } 7504 7505 break; 7506 7507 case 'inline': 7508 var el = $(obj.URL), 7509 content = iL.addContent(holder, obj), 7510 images = findImageInElement(holder); 7511 7512 holder.data({ 7513 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7514 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7515 }); 7516 content.children().eq(0).show(); 7517 7518 //Trigger the onRender callback 7519 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7520 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7521 7522 //Trigger the onBeforeLoad callback 7523 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7524 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7525 7526 iL.loadImage(images, function() { 7527 //Trigger the onAfterLoad callback 7528 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7529 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7530 7531 iL.configureHolder(obj, opt, holder); 7532 }); 7533 7534 break; 7535 7536 case 'flash': 7537 var el = iL.addContent(holder, obj); 7538 7539 holder.data({ 7540 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7541 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7542 }); 7543 7544 //Trigger the onRender callback 7545 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7546 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7547 7548 iL.configureHolder(obj, opt, holder); 7549 7550 break; 7551 7552 case 'ajax': 7553 var ajax = obj.options.ajax || {}; 7554 //Trigger the onBeforeLoad callback 7555 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7556 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7557 7558 iL.showLoader(); 7559 $.ajax({ 7560 url: obj.URL || opts.ajaxSetup.url, 7561 data: ajax.data || null, 7562 dataType: ajax.dataType || "html", 7563 type: ajax.type || opts.ajaxSetup.type, 7564 cache: ajax.cache || opts.ajaxSetup.cache, 7565 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 7566 global: ajax.global || opts.ajaxSetup.global, 7567 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 7568 username: ajax.username || opts.ajaxSetup.username, 7569 password: ajax.password || opts.ajaxSetup.password, 7570 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 7571 complete: ajax.complete || opts.ajaxSetup.complete, 7572 success: function(data, textStatus, jqXHR) { 7573 iL.hideLoader(); 7574 7575 var el = $(data), 7576 container = $('div.ilightbox-container', holder), 7577 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 7578 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 7579 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 7580 'overflow': 'hidden' 7581 } : {}; 7582 7583 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 7584 holder.show().data({
7585 naturalWidth: (elWidth || container.outerWidth()), 7586 naturalHeight: (elHeight || container.outerHeight()) 7587 }).hide(); 7588 7589 //Trigger the onRender callback 7590 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7591 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7592 7593 var images = findImageInElement(holder); 7594 iL.loadImage(images, function() { 7595 //Trigger the onAfterLoad callback 7596 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7597 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7598 7599 iL.configureHolder(obj, opt, holder); 7600 }); 7601 7602 opts.ajaxSetup.success(data, textStatus, jqXHR); 7603 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 7604 }, 7605 error: function(jqXHR, textStatus, errorThrown) { 7606 //Trigger the onAfterLoad callback 7607 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7608 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7609 7610 iL.hideLoader(); 7611 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 7612 iL.configureHolder(obj, opt, holder); 7613 7614 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 7615 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 7616 } 7617 }); 7618 7619 break; 7620 7621 case 'html': 7622 var object = obj.URL, 7623 el 7624 container = $('div.ilightbox-container', holder); 7625 7626 if (object[0].nodeName) el = object.clone(); 7627 else { 7628 var dom = $(object); 7629 if (dom.selector) el = $('<div>' + dom + '</div>'); 7630 else el = dom; 7631 } 7632 7633 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 7634 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 7635 7636 iL.addContent(holder, obj); 7637 7638 el.appendTo(document.documentElement).hide(); 7639 7640 //Trigger the onRender callback 7641 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7642 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7643 7644 var images = findImageInElement(holder); 7645 7646 //Trigger the onBeforeLoad callback 7647 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7648 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7649 7650 iL.loadImage(images, function() { 7651 //Trigger the onAfterLoad callback 7652 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7653 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7654 7655 holder.show().data({ 7656 naturalWidth: (elWidth || container.outerWidth()), 7657 naturalHeight: (elHeight || container.outerHeight()) 7658 }).hide(); 7659 el.remove(); 7660 7661 iL.configureHolder(obj, opt, holder); 7662 }); 7663 7664 break; 7665 } 7666 }, 7667 7668 configureHolder: function(obj, opt, holder) { 7669 var iL = this, 7670 vars = iL.vars, 7671 opts = iL.options; 7672 7673 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 7674 7675 if (opt == "current") 7676 var item = vars.current; 7677 else if (opt == "next") 7678 var opacity = opts.styles.nextOpacity, 7679 item = vars.next; 7680 else 7681 var opacity = opts.styles.prevOpacity, 7682 item = vars.prev; 7683 7684 var api = { 7685 element: holder, 7686 position: item 7687 }; 7688 7689 iL.items[item].options.width = iL.items[item].options.width || 0, 7690 iL.items[item].options.height = iL.items[item].options.height || 0; 7691 7692 if (opt == "current") { 7693 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 7694 holder.css(transform, ''); 7695 if (obj.caption) { 7696 iL.setCaption(obj, holder); 7697 var caption = $('div.ilightbox-caption', holder), 7698 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 7699 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7699Speed); 7700 } 7701 7702 var social = obj.options.social; 7703 if (social) { 7704 iL.setSocial(social, obj.URL, holder); 7705 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 7706 } 7707 7708 //Generate thumbnails 7709 iL.generateThumbnails(); 7710 7711 //Trigger the onShow callback 7712 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7713 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7714 }); 7715 else { 7716 holder.show(); 7717 7718 //Generate thumbnails 7719 iL.generateThumbnails(); 7720 7721 //Trigger the onShow callback 7722 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7723 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7724 } 7725 } else { 7726 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 7727 if (opt == "next") vars.nextLock = false; 7728 else vars.prevLock = false; 7729 7730 //Generate thumbnails 7731 iL.generateThumbnails(); 7732 7733 //Trigger the onShow callback 7734 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7735 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7736 }); 7737 else { 7738 holder.css({ 7739 opacity: opacity 7740 }).show(); 7741 if (opt == "next") vars.nextLock = false; 7742 else vars.prevLock = false; 7743 7744 //Generate thumbnails 7745 iL.generateThumbnails(); 7746 7747 //Trigger the onShow callback 7748 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7749 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7750 } 7751 } 7752 7753 setTimeout(function() { 7754 iL.repositionPhoto(); 7755 }, 0); 7756 }, 7757 7758 generateBoxes: function() { 7759 var iL = this, 7760 vars = iL.vars, 7761 opts = iL.options; 7762 7763 if (opts.infinite && vars.total >= 3) { 7764 if (vars.current == vars.total - 1) vars.next = 0; 7765 if (vars.current == 0) vars.prev = vars.total - 1; 7766 } else opts.infinite = false; 7767 7768 //UNCODE addition 7769 if ( typeof iL.items[vars.current] == 'undefined' ) 7770 vars.current = 0; 7771 7772 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 7773 7774 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 7775 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 7776 }, 7777 7778 generateThumbnails: function() { 7779 var iL = this, 7780 vars = iL.vars, 7781 opts = iL.options, 7782 timeOut = null; 7783 7784 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 7785 var thumbnails = vars.thumbnails, 7786 container = $('div.ilightbox-thumbnails-container', thumbnails), 7787 grid = $('div.ilightbox-thumbnails-grid', container), 7788 i = 0; 7789 7790 grid.removeAttr('style').empty(); 7791 7792 $.each(iL.items, function(key, val) { 7793 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 7794 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 7795 thumb = val.options.thumbnail, 7796 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 7797 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 7798 7799 thumbnail.css({ 7800 opacity: 0 7801 }).addClass(isActive); 7802 7803 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 7804 icon.addClass('ilightbox-thumbnail-video'); 7805 thumbnail.append(icon); 7806 } else if (val.options.icon) { 7807 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 7808 thumbnail.append(icon); 7809 } 7810 7811 if (thumb) iL.loadImage(thumb, function(img) { 7812 i++; 7813 if (img) thumbnail.data({ 7814 naturalWidth: img.width, 7815 naturalHeight: img.height 7816 }).append('<img src="' + thumb + '" border="0" />'); 7817 else thumbnail.data({ 7818 naturalWidth: opts.thumbnails.maxWidth, 7819 naturalHeight: opts.thumbnails.maxHeight 7820 }); 7821 7822 clearTimeout(timeOut); 7823 timeOut = setTimeout(function() { 7824 iL.positionThumbnails(thumbnails, container, grid); 7825 }, 20); 7826 setTimeout(function() { 7827 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 7828 }, i * 20); 7829 }); 7830 7831 grid.append(thumbnail); 7832 }); 7833 iL.vars.dontGenerateThumbs = true; 7834 } 7835 }, 7836
7837 positionThumbnails: function(thumbnails, container, grid) { 7838 var iL = this, 7839 vars = iL.vars, 7840 opts = iL.options, 7841 viewport = getViewport(), 7842 path = opts.path.toLowerCase(); 7843 7844 if (!thumbnails) thumbnails = vars.thumbnails; 7845 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 7846 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 7847 7848 var thumbs = $('.ilightbox-thumbnail', grid), 7849 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 7850 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 7851 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 7852 gridHeight = (path == 'horizontal') ? heightAvail : 0, 7853 active = $('.ilightbox-active', grid), 7854 gridCss = {}, 7855 css = {}; 7856 7857 if (arguments.length < 3) { 7858 thumbs.css({ 7859 opacity: opts.thumbnails.normalOpacity 7860 }); 7861 active.css({ 7862 opacity: opts.thumbnails.activeOpacity 7863 }); 7864 } 7865 7866 thumbs.each(function(i) { 7867 var t = $(this), 7868 data = t.data(), 7869 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 7870 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 7871 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 7872 7873 t.css({ 7874 width: dims.width, 7875 height: dims.height 7876 }); 7877 if (path == 'horizontal') t.css({ 7878 'float': 'left' 7879 }); 7880 7881 (path == 'horizontal') ? ( 7882 gridWidth += t.outerWidth() 7883 ) : ( 7884 gridHeight += t.outerHeight() 7885 ); 7886 }); 7887 7888 gridCss = { 7889 width: gridWidth, 7890 height: gridHeight 7891 }; 7892 7893 grid.css(gridCss); 7894 7895 gridCss = {}; 7896 7897 var gridOffset = grid.offset(), 7898 activeOffset = (active.length) ? active.offset() : { 7899 top: parseInt(heightAvail / 2), 7900 left: parseInt(widthAvail / 2) 7901 }; 7902 7903 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 7904 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 7905 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 7906 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 7907 7908 (path == 'horizontal') ? ( 7909 gridCss.top = 0, 7910 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 7911 ) : ( 7912 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 7913 gridCss.left = 0 7914 ); 7915 7916 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 7917 else grid.css(gridCss); 7918 }, 7919 7920 loadImage: function(image, callback) { 7921 if (!$.isArray(image)) image = [image]; 7922 7923 var iL = this, 7924 length = image.length; 7925 7926 if (length > 0) { 7927 iL.showLoader(); 7928 $.each(image, function(index, value) { 7929 var img = new Image(); 7930 img.onload = function() { 7931 length -= 1; 7932 if (length == 0) { 7933 iL.hideLoader(); 7934 callback(img); 7935 } 7936 }; 7937 img.onerror = img.onabort = function() { 7938 length -= 1; 7939 if (length == 0) { 7940 iL.hideLoader(); 7941 callback(false); 7942 } 7943 }; 7944 img.src = image[index]; 7945 }); 7946 } else callback(false); 7947 }, 7948 7949 patchItemsEvents: function() { 7950 var iL = this, 7951 vars = iL.vars, 7952 clickEvent = supportTouch ? "itap.iL" : "click.iL", 7953 vEvent = supportTouch ? "click.iL" : "itap.iL"; 7954 7955 if (iL.context && iL.selector) { 7956 var $items = $(iL.selector, iL.context); 7957 7958 $(iL.context).on(clickEvent, iL.selector, function() { 7959 var $this = $(this), 7960 //UNCODE addition 7961 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 7962 if (UNCODE.isMobile) { 7963 var isCarousel = $this.closest('.owl-carousel'); 7964 if (isCarousel.length) { 7965 if (isCarousel.hasClass('owl-translating')) return false; 7966 } 7967 } 7968 7969 vars.current = key; 7970 vars.next = iL.items[key + 1] ? key + 1 : null; 7971 vars.prev = iL.items[key - 1] ? key - 1 : null; 7972 7973 iL.addContents(); 7974 iL.patchEvents(); 7975 7976 return false;
7977 }).on(vEvent, iL.selector, function() { 7978 return false; 7979 }); 7980 } else 7981 $.each(iL.itemsObject, function(key, val) { 7982 val.on(clickEvent, function() { 7983 vars.current = key; 7984 vars.next = iL.items[key + 1] ? key + 1 : null; 7985 vars.prev = iL.items[key - 1] ? key - 1 : null; 7986 7987 iL.addContents(); 7988 iL.patchEvents(); 7989 7990 return false; 7991 }).on(vEvent, function() { 7992 return false; 7993 }); 7994 }); 7995 }, 7996 7997 dispatchItemsEvents: function() { 7998 var iL = this, 7999 vars = iL.vars, 8000 opts = iL.options; 8001 8002 if (iL.context && iL.selector) 8003 $(iL.context).off('.iL', iL.selector); 8004 else 8005 $.each(iL.itemsObject, function(key, val) { 8006 val.off('.iL'); 8007 }); 8008 }, 8009 8010 refresh: function() { 8011 var iL = this; 8012 8013 iL.dispatchItemsEvents(); 8014 iL.attachItems(); 8015 iL.normalizeItems(); 8016 iL.patchItemsEvents(); 8017 }, 8018 8019 patchEvents: function() { 8020 var iL = this, 8021 vars = iL.vars, 8022 opts = iL.options, 8023 path = opts.path.toLowerCase(), 8024 holders = $('.ilightbox-holder'), 8025 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 8026 durationThreshold = 1000, 8027 horizontalDistanceThreshold = 8028 verticalDistanceThreshold = 100, 8029 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 8030 8031 $win.bind('resize.iLightBox', function() { 8032 var viewport = getViewport(); 8033 8034 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 8035 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 8036 8037 iL.repositionPhoto(null); 8038 if (supportTouch) { 8039 clearTimeout(vars.setTime); 8040 vars.setTime = setTimeout(function() { 8041 var scrollTop = getScrollXY().y; 8042 window.scrollTo(0, scrollTop - 30); 8043 window.scrollTo(0, scrollTop + 30); 8044 window.scrollTo(0, scrollTop); 8045 }, 2000); 8046 } 8047 if (vars.thumbs) iL.positionThumbnails(); 8048 }).bind('keydown.iLightBox', function(event) { 8049 if (opts.controls.keyboard) { 8050 switch (event.keyCode) { 8051 case 13: 8052 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 8053 break; 8054 case 27: 8055 if (opts.keyboard.esc) iL.closeAction(); 8056 break; 8057 case 37: 8058 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 8059 break; 8060 case 38: 8061 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 8062 break; 8063 case 39: 8064 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 8065 break; 8066 case 40: 8067 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 8068 break; 8069 } 8070 } 8071 }); 8072 8073 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 8074 iL.doFullscreen(); 8075 }); 8076 8077 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 8078 return arr.lastIndexOf(e) === i; 8079 }), 8080 holderEvents = ""; 8081 8082 $.each(holderEventsArr, function(key, val) { 8083 if (key != 0) holderEvents += ' '; 8084 holderEvents += val; 8085 }); 8086 8087 $doc.on(clickEvent, '.ilightbox-overlay', function() { 8088 if (opts.overlay.blur) iL.closeAction(); 8089 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 8090 iL.moveTo('next'); 8091 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 8092 iL.moveTo('prev'); 8093 }).on(clickEvent, '.ilightbox-thumbnail', function() { 8094 var t = $(this), 8095 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 8096 index = thumbs.index(t); 8097 8098 if (index != vars.current) iL.goTo(index); 8099 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8100 var caption = $('div.ilightbox-caption', vars.holder), 8101 social = $('div.ilightbox-social', vars.holder), 8102 fadeSpeed = opts.effects.fadeSpeed; 8103 8104 if (vars.nextLock || vars.prevLock) { 8105 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 8106 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 8107 8108 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 8109 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 8110 } else { 8111 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 8112 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 8113 8114 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 8115 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 8116 } 8117 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 8118 if (e.type == 'mouseenter') vars.lockWheel = true; 8119 else vars.lockWheel = false;
8120 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 8121 var t = $(this); 8122 8123 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 8124 else if (t.hasClass('ilightbox-play')) { 8125 iL.resume(); 8126 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 8127 } else if (t.hasClass('ilightbox-pause')) { 8128 iL.pause(); 8129 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 8130 } else iL.closeAction(); 8131 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 8132 // prevent scrolling 8133 e.preventDefault(); 8134 }); 8135 8136 function mouseMoveHandler(e) { 8137 if (!vars.isMobile) { 8138 if (!vars.mouseID) { 8139 vars.hideableElements.show(); 8140 } 8141 8142 vars.mouseID = clearTimeout(vars.mouseID); 8143 8144 if (buttonsArray.indexOf(e.target) === -1) 8145 vars.mouseID = setTimeout(function() { 8146 vars.hideableElements.hide(); 8147 vars.mouseID = clearTimeout(vars.mouseID); 8148 }, 3000); 8149 } 8150 } 8151 8152 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 8153 8154 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8155 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 8156 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 8157 }); 8158 8159 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'); 8160 8161 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 8162 if (!vars.lockWheel) { 8163 event.preventDefault(); 8164 if (delta < 0) iL.moveTo('next'); 8165 else if (delta > 0) iL.moveTo('prev'); 8166 } 8167 }); 8168 8169 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 8170 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 8171 8172 vars.BODY.addClass('ilightbox-closedhand'); 8173 8174 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 8175 scrollTop = $doc.scrollTop(), 8176 scrollLeft = $doc.scrollLeft(), 8177 offsets = [ 8178 holders.eq(0).offset(), 8179 holders.eq(1).offset(), 8180 holders.eq(2).offset() 8181 ], 8182 offSet = [{ 8183 top: offsets[0].top - scrollTop, 8184 left: offsets[0].left - scrollLeft 8185 }, { 8186 top: offsets[1].top - scrollTop, 8187 left: offsets[1].left - scrollLeft 8188 }, { 8189 top: offsets[2].top - scrollTop, 8190 left: offsets[2].left - scrollLeft 8191 }], 8192 start = { 8193 time: (new Date()).getTime(), 8194 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8195 }, 8196 stop; 8197 8198 function moveEachHandler(i) { 8199 var t = $(this), 8200 offset = offSet[i], 8201 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 8202 8203 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 8204 } 8205 8206 function moveHandler(event) { 8207 8208 if (!start) return; 8209 8210 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 8211 8212 stop = { 8213 time: (new Date()).getTime(), 8214 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8215 }; 8216 8217 holders.each(moveEachHandler); 8218 8219 // prevent scrolling 8220 event.preventDefault(); 8221 } 8222 8223 function repositionHolders() { 8224 holders.each(function() { 8225 var t = $(this), 8226 offset = t.data('offset') || { 8227 top: t.offset().top - scrollTop, 8228 left: t.offset().left - scrollLeft 8229 }, 8230 top = offset.top, 8231 left = offset.left; 8232 8233 t.css(transform, gpuAcceleration).stop().animate({ 8234 top: top, 8235 left: left 8236 }, 500, 'easeOutCirc', function() { 8237 t.css(transform, ''); 8238 }); 8239 }); 8240 } 8241 8242 holders.bind(touchMoveEvent, moveHandler); 8243 $doc.one(touchStopEvent, function(event) { 8244 holders.unbind(touchMoveEvent, moveHandler); 8245 8246 vars.BODY.removeClass('ilightbox-closedhand'); 8247 8248 if (start && stop) { 8249 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 8250 if (start.coords[0] > stop.coords[0]) { 8251 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8252 else { 8253 vars.isSwipe = true; 8254 iL.moveTo('next'); 8255 } 8256 } else { 8257 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8258 else { 8259 vars.isSwipe = true; 8260 iL.moveTo('prev'); 8261 } 8262 } 8263 } 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) { 8264 if (start.coords[1] > stop.coords[1]) { 8265 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8266 else { 8267 vars.isSwipe = true; 8268 iL.moveTo('next'); 8269 } 8270 } else { 8271 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8272 else { 8273 vars.isSwipe = true; 8274 iL.moveTo('prev'); 8275 } 8276 } 8277 } else repositionHolders(); 8278 } 8279 start = stop = undefined; 8280 }); 8281 }); 8282 8283 }, 8284 8285 goTo: function(index) { 8286 var iL = this, 8287 vars = iL.vars, 8288 opts = iL.options, 8289 diff = (index - vars.current); 8290 8291 if (opts.infinite) { 8292 if (index == vars.total - 1 && vars.current == 0) diff = -1; 8293 if (vars.current == vars.total - 1 && index == 0) diff = 1; 8294 } 8295 8296 if (diff == 1) iL.moveTo('next'); 8297 else if (diff == -1) iL.moveTo('prev'); 8298 else { 8299 8300 if (vars.nextLock || vars.prevLock) return false;
8301 8302 //Trigger the onBeforeChange callback 8303 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 8304 8305 if (opts.linkId) { 8306 vars.hashLock = true; 8307 window.location.hash = opts.linkId + '/' + index; 8308 } 8309 8310 if (iL.items[index]) { 8311 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 8312 else iL.vars.lockWheel = false; 8313 8314 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 8315 else vars.lockSwipe = false; 8316 } 8317 8318 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 8319 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 8320 }); 8321 8322 vars.current = index; 8323 vars.next = index + 1; 8324 vars.prev = index - 1; 8325 8326 iL.createUI(); 8327 8328 setTimeout(function() { 8329 iL.generateBoxes(); 8330 }, opts.effects.loadedFadeSpeed + 50); 8331 8332 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 8333 iL.positionThumbnails(); 8334 8335 if (opts.linkId) setTimeout(function() { 8336 vars.hashLock = false; 8337 }, 55); 8338 8339 // Configure arrow buttons 8340 if (!opts.infinite) { 8341 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8342 8343 if (vars.current == 0) { 8344 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8345 } 8346 if (vars.current >= vars.total - 1) { 8347 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8348 } 8349 } 8350 8351 // Reset next cycle timeout 8352 iL.resetCycle(); 8353 8354 //Trigger the onAfterChange callback 8355 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 8356 } 8357 }, 8358 8359 moveTo: function(side) { 8360 var iL = this, 8361 vars = iL.vars, 8362 opts = iL.options, 8363 path = opts.path.toLowerCase(), 8364 viewport = getViewport(), 8365 switchSpeed = opts.effects.switchSpeed; 8366 8367 if (vars.nextLock || vars.prevLock) return false; 8368 else { 8369 8370 var item = (side == "next") ? vars.next : vars.prev; 8371 8372 if (opts.linkId) { 8373 vars.hashLock = true; 8374 window.location.hash = opts.linkId + '/' + item; 8375 } 8376 8377 if (side == "next") { 8378 if (!iL.items[item]) return false; 8379 var firstHolder = vars.nextPhoto, 8380 secondHolder = vars.holder, 8381 lastHolder = vars.prevPhoto, 8382 firstClass = 'ilightbox-prev', 8383 secondClass = 'ilightbox-next'; 8384 } else if (side == "prev") { 8385 if (!iL.items[item]) return false; 8386 var firstHolder = vars.prevPhoto, 8387 secondHolder = vars.holder, 8388 lastHolder = vars.nextPhoto, 8389 firstClass = 'ilightbox-next', 8390 secondClass = 'ilightbox-prev'; 8391 } 8392 8393 //Trigger the onBeforeChange callback 8394 if (typeof opts.callback.onBeforeChange == 'function') 8395 opts.callback.onBeforeChange.call(iL, iL.ui); 8396 8397 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 8398 8399 var captionFirst = $('div.ilightbox-caption', secondHolder), 8400 socialFirst = $('div.ilightbox-social', secondHolder); 8401 8402 if (captionFirst.length) 8403 captionFirst.stop().fadeOut(switchSpeed, function() { 8404 $(this).remove(); 8405 }); 8406 if (socialFirst.length) 8407 socialFirst.stop().fadeOut(switchSpeed, function() { 8408 $(this).remove(); 8409 }); 8410 8411 if (iL.items[item].caption) { 8412 iL.setCaption(iL.items[item], firstHolder); 8413 var caption = $('div.ilightbox-caption', firstHolder), 8414 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 8415 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 8416 } 8417 8418 var social = iL.items[item].options.social; 8419 if (social) { 8420 iL.setSocial(social, iL.items[item].URL, firstHolder); 8421 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 8422 } 8423 8424 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 8425 val.removeClass('ilightbox-next ilightbox-prev'); 8426 }); 8427 8428 var firstOffset = firstHolder.data('offset'), 8429 winW = (viewport.width - (opts.styles.pageOffsetX)), 8430 winH = (viewport.height - (opts.styles.pageOffsetY)), 8431 width = firstOffset.newDims.width, 8432 height = firstOffset.newDims.height, 8433 thumbsOffset = firstOffset.thumbsOffset, 8434 diff = firstOffset.diff, 8435 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8436 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8437 8438 var secondOffset = secondHolder.data('offset'), 8439 object = secondOffset.object; 8440 8441 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8442 var objRatio = width / height; 8443 height = height - vars.captionHeight; 8444 width = height * objRatio; 8445 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 8446 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8447 }*/ 8448 8449 firstHolder.show().css(transform, gpuAcceleration).animate({ 8450 top: top, 8451 left: left, 8452 opacity: 1 8453 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8454 firstHolder.css(transform, ''); 8455 }); 8456 8457 $('div.ilightbox-container', firstHolder).animate({ 8458 width: width, 8459 height: height 8460 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8461 8462 diff = secondOffset.diff; 8463 8464 width = secondOffset.newDims.width, 8465 height = secondOffset.newDims.height; 8466 8467 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8468 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8469 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 8470 8471 if (side == 'prev') 8472 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 8473 else { 8474 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 8475 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8476 } 8477 8478 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8479 var objRatio = width / height; 8480 height = height - vars.captionHeight; 8481 width = height * objRatio; 8482 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 8483 }*/ 8484 8485 $('div.ilightbox-container', secondHolder).animate({ 8486 width: width, 8487 height: height 8488 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8489 8490 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 8491 top: top, 8492 left: left, 8493 opacity: opts.styles.prevOpacity, 8494 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8495 secondHolder.css(transform, ''); 8496
8497 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 8498 iL.positionThumbnails(); 8499 8500 if (iL.items[item]) { 8501 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 8502 else vars.lockWheel = false; 8503 8504 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 8505 else vars.lockSwipe = false; 8506 } 8507 8508 vars.isSwipe = false; 8509 8510 // Remove iframe & video from previous slide 8511 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8512 $('div.ilightbox-container', secondHolder).empty(); 8513 } 8514 8515 if (side == "next") { 8516 vars.nextPhoto = lastHolder, 8517 vars.prevPhoto = secondHolder, 8518 vars.holder = firstHolder; 8519 8520 vars.nextPhoto.hide(); 8521 8522 vars.next = vars.next + 1, 8523 vars.prev = vars.current, 8524 vars.current = vars.current + 1; 8525 8526 if (opts.infinite) { 8527 if (vars.current > vars.total - 1) vars.current = 0; 8528 if (vars.current == vars.total - 1) vars.next = 0; 8529 if (vars.current == 0) vars.prev = vars.total - 1; 8530 } 8531 8532 iL.createUI(); 8533 8534 if (!iL.items[vars.next]) 8535 vars.nextLock = false; 8536 else 8537 iL.loadContent(iL.items[vars.next], 'next'); 8538 } else { 8539 vars.prevPhoto = lastHolder; 8540 vars.nextPhoto = secondHolder; 8541 vars.holder = firstHolder; 8542 8543 vars.prevPhoto.hide(); 8544 8545 vars.next = vars.current; 8546 vars.current = vars.prev; 8547 vars.prev = vars.current - 1; 8548 8549 if (opts.infinite) { 8550 if (vars.current == vars.total - 1) vars.next = 0; 8551 if (vars.current == 0) vars.prev = vars.total - 1; 8552 } 8553 8554 iL.createUI(); 8555 8556 if (!iL.items[vars.prev]) 8557 vars.prevLock = false; 8558 else 8559 iL.loadContent(iL.items[vars.prev], 'prev'); 8560 } 8561 8562 // Add iframe & video content for current slide 8563 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8564 iL.loadContent(iL.items[vars.current], 'current'); 8565 } 8566 8567 if (opts.linkId) setTimeout(function() { 8568 vars.hashLock = false; 8569 }, 55); 8570 8571 // Configure arrow buttons 8572 if (!opts.infinite) { 8573 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8574 8575 if (vars.current == 0) 8576 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8577 if (vars.current >= vars.total - 1) 8578 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8579 } 8580 8581 iL.repositionPhoto(); 8582 8583 // Reset next cycle timeout 8584 iL.resetCycle(); 8585 8586 //Trigger the onAfterChange callback 8587 if (typeof opts.callback.onAfterChange == 'function') 8588 opts.callback.onAfterChange.call(iL, iL.ui); 8589 }); 8590 8591 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 8592 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 8593 8594 lastHolder.css(transform, gpuAcceleration).animate({ 8595 top: top, 8596 left: left, 8597 opacity: opts.styles.nextOpacity 8598 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8599 lastHolder.css(transform, ''); 8600 }).addClass(secondClass); 8601 } 8602 }, 8603 8604 setCaption: function(obj, target) { 8605 var iL = this, 8606 caption = $('<div class="ilightbox-caption"></div>'); 8607 8608 if (obj.caption) { 8609 caption.html(obj.caption); 8610 $('div.ilightbox-container', target).append(caption); 8611 } 8612 }, 8613 8614 normalizeSocial: function(obj, url) { 8615 var iL = this, 8616 vars = iL.vars, 8617 opts = iL.options, 8618 baseURL = window.location.href; 8619 8620 $.each(obj, function(key, value) { 8621 if (!value) 8622 return true; 8623 8624 var item = key.toLowerCase(), 8625 source, text; 8626 8627 switch (item) { 8628 case 'facebook': 8629 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 8630 text = "Share on Facebook"; 8631 break; 8632 case 'twitter': 8633 source = "http://twitter.com/home?status={URL}", 8634 text = "Share on Twitter"; 8635 break; 8636 case 'googleplus': 8637 source = "https://plus.google.com/share?url={URL}", 8638 text = "Share on Google+"; 8639 break; 8640 case 'delicious': 8641 source = "http://delicious.com/post?url={URL}", 8642 text = "Share on Delicious"; 8643 break; 8644 case 'digg': 8645 source = "http://digg.com/submit?phase=2&url={URL}", 8646 text = "Share on Digg"; 8647 break; 8648 case 'reddit': 8649 source = "http://reddit.com/submit?url={URL}", 8650 text = "Share on reddit"; 8651 break; 8652 } 8653 8654 obj[key] = { 8655 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 8656 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 8657 text: value.text || text || "Share on " + key, 8658 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 8659 height: value.height || 360 8660 }; 8661 8662 }); 8663 8664 return obj; 8665 }, 8666 8667 setSocial: function(obj, url, target) { 8668 var iL = this, 8669 socialBar = $('<div class="ilightbox-social"></div>'), 8670 buttons = '<ul>'; 8671 8672 obj = iL.normalizeSocial(obj, url); 8673 8674 $.each(obj, function(key, value) { 8675 var item = key.toLowerCase(), 8676 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, '+')); 8677 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>'; 8678 }); 8679 8680 buttons += '</ul>'; 8681 8682 socialBar.html(buttons); 8683 $('div.ilightbox-container', target).append(socialBar); 8684 }, 8685 8686 fullScreenAction: function() { 8687 var iL = this, 8688 vars = iL.vars; 8689 8690 if (fullScreenApi.supportsFullScreen) { 8691 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 8692 else fullScreenApi.requestFullScreen(document.documentElement); 8693 } else { 8694 iL.doFullscreen(); 8695 } 8696 }, 8697 8698 doFullscreen: function() { 8699 var iL = this, 8700 vars = iL.vars, 8701 viewport = getViewport(), 8702 opts = iL.options; 8703 8704 if (opts.fullAlone) { 8705 var currentHolder = vars.holder, 8706 current = iL.items[vars.current], 8707 windowWidth = viewport.width, 8708 windowHeight = viewport.height, 8709 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 8710 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8711 8712 if (!vars.isInFullScreen) { 8713 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 8714 vars.overlay.css({ 8715 opacity: 1 8716 }); 8717 8718 $.each(hideElements, function(i, element) { 8719 element.hide(); 8720 }); 8721 8722 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 8723 8724 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8725 naturalWidthOld: currentHolder.data('naturalWidth'), 8726 naturalHeightOld: currentHolder.data('naturalHeight'), 8727 naturalWidth: windowWidth, 8728 naturalHeight: windowHeight 8729 }); 8730 else { 8731 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 8732 newWidth = windowWidth, 8733 newHeight = windowHeight, 8734 width = currentHolder.data('naturalWidth'), 8735 height = currentHolder.data('naturalHeight'); 8736 8737 if (viewport.toLowerCase() == 'fill') { 8738 newHeight = (newWidth / width) * height; 8739 8740 if (newHeight < windowHeight) { 8741 newWidth = (windowHeight / height) * width, 8742 newHeight = windowHeight; 8743 } 8744 } else if (viewport.toLowerCase() == 'fit') { 8745 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 8746 8747 newWidth = dims.width, 8748 newHeight = dims.height; 8749 } else if (viewport.toLowerCase() == 'stretch') { 8750 newWidth = newWidth, 8751 newHeight = newHeight; 8752 } else { 8753 var scale = (width > newWidth || height > newHeight) ? true : false, 8754 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 8755 newWidth = dims.width, 8756 newHeight = dims.height; 8757 } 8758 8759 currentHolder.data({ 8760 naturalWidthOld: currentHolder.data('naturalWidth'), 8761 naturalHeightOld: currentHolder.data('naturalHeight'), 8762 naturalWidth: newWidth, 8763 naturalHeight: newHeight 8764 }); 8765 } 8766 8767 $.each(elements, function(key, val) { 8768 val.addClass('ilightbox-fullscreen'); 8769 }); 8770 8771 //Trigger the onEnterFullScreen callback 8772 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 8773 } else { 8774 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 8775 vars.overlay.css({ 8776 opacity: iL.options.overlay.opacity 8777 }); 8778 8779 $.each(hideElements, function(i, element) { 8780 element.show(); 8781 }); 8782 8783 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 8784 8785 currentHolder.data({ 8786 naturalWidth: currentHolder.data('naturalWidthOld'), 8787 naturalHeight: currentHolder.data('naturalHeightOld'), 8788 naturalWidthOld: null, 8789 naturalHeightOld: null 8790 }); 8791 8792 $.each(elements, function(key, val) { 8793 val.removeClass('ilightbox-fullscreen'); 8794 }); 8795 8796 //Trigger the onExitFullScreen callback 8797 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 8798 } 8799 } else { 8800 if (!vars.isInFullScreen) vars.isInFullScreen = true; 8801 else vars.isInFullScreen = false; 8802 } 8803 iL.repositionPhoto(true); 8804 }, 8805 8806 closeAction: function() { 8807 var iL = this, 8808 vars = iL.vars, 8809 opts = iL.options; 8810 8811 $win.unbind('.iLightBox'); 8812 $doc.off('.iLightBox'); 8813 8814 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 8815 8816 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 8817 8818 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 8819 vars.overlay.remove(); 8820 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8821 }); 8822 else { 8823 vars.overlay.remove(); 8824 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8825 } 8826 8827 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8828 8829 $.each(fadeOuts, function(i, element) { 8830 element.removeAttr('style').remove(); 8831 }); 8832 8833 vars.dontGenerateThumbs = vars.isInFullScreen = false; 8834 8835 window.iLightBox = null; 8836 8837 if (opts.linkId) { 8838 vars.hashLock = true; 8839 removeHash(); 8840 setTimeout(function() { 8841 vars.hashLock = false; 8842 }, 55); 8843 } 8844 8845 //Trigger the onHide callback 8846 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 8847 }, 8848 8849 repositionPhoto: function() { 8850 var iL = this, 8851 vars = iL.vars, 8852 opts = iL.options, 8853 path = opts.path.toLowerCase(), 8854 viewport = getViewport(), 8855 winWidth = viewport.width, 8856 winHeight = viewport.height; 8857 8858 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 8859 8860 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 8861 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 8862 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 8863 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 8864 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, 8865 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))); 8866 8867 var elObject = { 8868 type: 'current', 8869 width: width, 8870 height: height, 8871 item: iL.items[vars.current], 8872 offsetW: offsetW, 8873 offsetH: offsetH,
8874 thumbsOffsetW: thumbsOffsetW, 8875 thumbsOffsetH: thumbsOffsetH, 8876 animate: arguments.length, 8877 holder: vars.holder 8878 }; 8879 8880 iL.repositionEl(elObject); 8881 8882 if (iL.items[vars.next]) { 8883 elObject = $.extend(elObject, { 8884 type: 'next', 8885 item: iL.items[vars.next], 8886 offsetX: opts.styles.nextOffsetX, 8887 offsetY: opts.styles.nextOffsetY, 8888 holder: vars.nextPhoto 8889 }); 8890 8891 iL.repositionEl(elObject); 8892 } 8893 8894 if (iL.items[vars.prev]) { 8895 elObject = $.extend(elObject, { 8896 type: 'prev', 8897 item: iL.items[vars.prev], 8898 offsetX: opts.styles.nextOffsetX, 8899 offsetY: opts.styles.prevOffsetY, 8900 holder: vars.prevPhoto 8901 }); 8902 8903 iL.repositionEl(elObject); 8904 } 8905 8906 var loaderCss = (path == "horizontal") ? { 8907 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 8908 } : { 8909 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 8910 }; 8911 vars.loader.css(loaderCss); 8912 }, 8913 8914 repositionEl: function(obj) { 8915 var iL = this, 8916 vars = iL.vars, 8917 opts = iL.options, 8918 path = opts.path.toLowerCase(), 8919 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 8920 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 8921 itemParent = obj.item, 8922 item = obj.item.options, 8923 holder = obj.holder, 8924 offsetX = obj.offsetX || 0, 8925 offsetY = obj.offsetY || 0, 8926 thumbsOffsetW = obj.thumbsOffsetW, 8927 thumbsOffsetH = obj.thumbsOffsetH; 8928 8929 if (obj.type == 'current') { 8930 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); 8931 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); 8932 } else { 8933 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 8934 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 8935 } 8936 8937 heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 8938 8939 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 8940 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 8941 8942 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 8943 width: width, 8944 height: height 8945 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 8946 newDims = $.extend({}, dims, {}); 8947 8948 if (obj.type == 'prev' || obj.type == 'next') 8949 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 8950 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 8951 else 8952 width = dims.width, 8953 height = dims.height; 8954 8955 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 8956 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); 8957 8958 switch (obj.type) { 8959 case 'current': 8960 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 8961 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8962 break; 8963
8964 case 'next': 8965 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 8966 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 8967 break; 8968 8969 case 'prev': 8970 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 8971 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8972 break; 8973 } 8974 8975 holder.data('offset', { 8976 top: top, 8977 left: left, 8978 newDims: newDims, 8979 diff: { 8980 W: widthDiff, 8981 H: heightDiff 8982 }, 8983 thumbsOffset: { 8984 W: thumbsOffsetW, 8985 H: thumbsOffsetH 8986 }, 8987 object: obj 8988 }); 8989 8990 var opacityMobile; 8991 if ( isMobile ) { 8992 opacityMobile = { 8993 opacity: 1, 8994 top: top, 8995 left: left 8996 }; 8997 } else { 8998 opacityMobile = { 8999 top: top, 9000 left: left 9001 }; 9002 } 9003 9004 if (obj.animate > 0 && opts.effects.reposition) { 9005 holder.css(transform, gpuAcceleration).stop().animate( 9006 opacityMobile, 9007 opts.effects.repositionSpeed, 'easeOutCirc', function() { 9008 holder.css(transform, ''); 9009 }); 9010 $('div.ilightbox-container', holder).stop().animate({ 9011 width: width, 9012 height: height 9013 }, opts.effects.repositionSpeed, 'easeOutCirc'); 9014 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 9015 width: width 9016 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 9017 $(this).css('overflow', 'visible'); 9018 }); 9019 } else { 9020 holder.css(opacityMobile); 9021 $('div.ilightbox-container', holder).css({ 9022 width: width, 9023 height: height 9024 }); 9025 $('div.ilightbox-inner-toolbar', holder).css({ 9026 width: width 9027 }); 9028 } 9029 }, 9030 9031 9032 resume: function(priority) { 9033 var iL = this, 9034 vars = iL.vars, 9035 opts = iL.options; 9036 9037 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 9038 return; 9039 } 9040 9041 vars.isPaused = 0; 9042 9043 if (vars.cycleID) { 9044 vars.cycleID = clearTimeout(vars.cycleID); 9045 } 9046 9047 vars.cycleID = setTimeout(function() { 9048 if (vars.current == vars.total - 1) iL.goTo(0); 9049 else iL.moveTo('next'); 9050 }, opts.slideshow.pauseTime); 9051 }, 9052 9053 pause: function(priority) { 9054 var iL = this, 9055 vars = iL.vars, 9056 opts = iL.options; 9057 9058 if (priority < vars.isPaused) { 9059 return; 9060 } 9061 9062 vars.isPaused = priority || 100; 9063 9064 if (vars.cycleID) { 9065 vars.cycleID = clearTimeout(vars.cycleID); 9066 } 9067 }, 9068 9069 resetCycle: function() { 9070 var iL = this, 9071 vars = iL.vars, 9072 opts = iL.options; 9073 9074 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 9075 iL.resume(); 9076 } 9077 }, 9078 9079 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 9080 var iL = this; 9081 9082 if (!width) factor = height / height_old; 9083 else if (!height) factor = width / width_old; 9084 else factor = min(width / width_old, height / height_old); 9085 9086 if (!thumb) { 9087 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 9088 else if (factor < iL.options.minScale) factor = iL.options.minScale; 9089 } 9090 9091 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 9092 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 9093 9094 return { 9095 width: final_width, 9096 height: final_height, 9097 ratio: factor 9098 }; 9099 }, 9100 9101 setOption: function(options) { 9102 var iL = this; 9103 9104 iL.options = $.extend(true, iL.options, options || {}); 9105 iL.refresh(); 9106 }, 9107 9108 availPlugins: function() { 9109 var iL = this, 9110 testEl = document.createElement("video"); 9111 9112 iL.plugins = { 9113 flash: !isMobile, 9114 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 9115 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 9116 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 9117 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 9118 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 9119 }; 9120 }, 9121 9122 addContent: function(element, obj) { 9123 var iL = this, 9124 el; 9125 9126 switch (obj.type) { 9127 case 'video': 9128 var HTML5 = false, 9129 videoType = obj.videoType, 9130 html5video = obj.options.html5video; 9131 9132 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 9133 obj.ext = 'mp4', 9134 obj.URL = html5video.h264 || obj.URL; 9135 else if (html5video.webm && iL.plugins.html5WebM) 9136 obj.ext = 'webm', 9137 obj.URL = html5video.webm || obj.URL; 9138 else if (html5video.ogg && iL.plugins.html5Vorbis) 9139 obj.ext = 'ogv', 9140 obj.URL = html5video.ogg || obj.URL; 9141 9142 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 9143 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 9144 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 9145 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 9146 9147 if (HTML5) { 9148 el = $('<video />
9148', { 9149 "width": "100%", 9150 "height": "100%", 9151 "preload": html5video.preload, 9152 "autoplay": html5video.autoplay, 9153 "poster": html5video.poster, 9154 "controls": html5video.controls 9155 }).append($('<source />', { 9156 "src": obj.URL, 9157 "type": videoType 9158 })); 9159 } else { 9160 if (!iL.plugins.quicktime) el = $('<span />', { 9161 "class": "ilightbox-alert", 9162 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 9163 }); 9164 else { 9165 9166 el = $('<object />', { 9167 "type": "video/quicktime", 9168 "pluginspage": pluginspages.quicktime 9169 }).attr({ 9170 "data": obj.URL, 9171 "width": "100%", 9172 "height": "100%" 9173 }).append($('<param />', { 9174 "name": "src", 9175 "value": obj.URL 9176 })).append($('<param />', { 9177 "name": "autoplay", 9178 "value": "false" 9179 })).append($('<param />', { 9180 "name": "loop", 9181 "value": "false" 9182 })).append($('<param />', { 9183 "name": "scale", 9184 "value": "tofit" 9185 })); 9186 9187 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 9188 } 9189 } 9190 9191 break; 9192 9193 case 'flash': 9194 if (!iL.plugins.flash) el = $('<span />', { 9195 "class": "ilightbox-alert", 9196 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 9197 }); 9198 else { 9199 var flashvars = "", 9200 i = 0; 9201 9202 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 9203 if (i != 0) flashvars += "&"; 9204 flashvars += k + "=" + encodeURIComponent(v); 9205 i++; 9206 }); 9207 else flashvars = null; 9208 9209 el = $('<embed />').attr({ 9210 "type": "application/x-shockwave-flash", 9211 "src": obj.URL, 9212 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9213 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9214 "quality": "high", 9215 "bgcolor": "#000000", 9216 "play": "true", 9217 "loop": "true", 9218 "menu": "true", 9219 "wmode": "transparent", 9220 "scale": "showall", 9221 "allowScriptAccess": "always", 9222 "allowFullScreen": "true", 9223 "flashvars": flashvars, 9224 "fullscreen": "yes" 9225 }); 9226 } 9227 9228 break; 9229 9230 case 'iframe': 9231 el = $('<iframe />').attr({ 9232 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9233 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9234 src: obj.URL, 9235 frameborder: 0, 9236 'hspace': 0, 9237 'vspace': 0, 9238 'scrolling': supportTouch ? 'auto' : 'scroll', 9239 'webkitAllowFullScreen': '', 9240 'mozallowfullscreen': '', 9241 'allowFullScreen': '' 9242 }); 9243 9244 break; 9245 9246 case 'inline': 9247 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 9248 9249 break; 9250 9251 case 'html': 9252 var object = obj.URL, 9253 el; 9254 9255 if (object[0].nodeName) { 9256 el = $('<div class="ilightbox-wrapper"></div>').html(object); 9257 } else { 9258 var dom = $(obj.URL), 9259 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 9260 el = $('<div class="ilightbox-wrapper"></div>').html(html); 9261 } 9262 9263 break; 9264 } 9265 9266 $('div.ilightbox-container', element).empty().html(el); 9267 9268 // For fixing Chrome about just playing the video for first time 9269 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 9270 var src = el[0].currentSrc + '?' + floor(random() * 30000); 9271 el[0].currentSrc = src; 9272 el[0].src = src; 9273 }); 9274 9275 return el; 9276 }, 9277 9278 ogpRecognition: function(obj, callback) { 9279 var iL = this, 9280 url = obj.URL; 9281 9282 iL.showLoader(); 9283 doAjax(url, function(data) { 9284 iL.hideLoader(); 9285 if (data) { 9286 var object = new Object(); 9287 9288 object.length = false, 9289 object.url = data.url; 9290 9291 if (data.status == 200) { 9292 var result = data.results, 9293 type = result.type, 9294 source = result.source; 9295 9296 object.source = source.src, 9297 object.width = source.width && parseInt(source.width) || 0, 9298 object.height = source.height && parseInt(source.height) || 0, 9299 object.type = type, 9300 object.thumbnail = source.thumbnail || result.images && result.images[0], 9301 object.html5video = result.html5video || {}, 9302 object.length = true; 9303 9304 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 9305 else if (source.type.indexOf("video/") != -1) object.type = "video"; 9306 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 9307 else if (source.type.indexOf("image/") != -1) object.type = "image"; 9308 9309 } else if (typeof data.response != 'undefined') 9310 throw data.response; 9311 9312 callback.call(this, object.length ? object : false); 9313 } 9314 }); 9315 }, 9316 9317 hashChangeHandler: function(url) { 9318 var iL = this, 9319 vars = iL.vars, 9320 opts = iL.options, 9321 URL = url || window.location.href, 9322 hash = parseURI(URL).hash, 9323 split = hash.split('/'), 9324 index = split[1]; 9325 9326 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 9327 9328 if (index) { 9329 var target = split[1] || 0; 9330 if (iL.items[target]) {
9331 var overlay = $('.ilightbox-overlay'); 9332 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 9333 iL.goTo(target); 9334 } else { 9335 iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click'); 9336 iL.goTo(target); 9337 } 9338 } else { 9339 var overlay = $('.ilightbox-overlay'); 9340 if (overlay.length) iL.closeAction(); 9341 } 9342 } else { 9343 var overlay = $('.ilightbox-overlay'); 9344 if (overlay.length) iL.closeAction(); 9345 } 9346 } 9347 }; 9348 9349 /** 9350 * Parse style to pixels. 9351 * 9352 * @param {Object} $element jQuery object with element. 9353 * @param {Property} property CSS property to get the pixels from. 9354 * 9355 * @return {Int} 9356 */ 9357 function getPixel($element, property) { 9358 return parseInt($element.css(property), 10) || 0; 9359 } 9360 9361 /** 9362 * Make sure that number is within the limits. 9363 * 9364 * @param {Number} number 9365 * @param {Number} min 9366 * @param {Number} max 9367 * 9368 * @return {Number} 9369 */ 9370 function within(number, min, max) { 9371 return number < min ? min : number > max ? max : number; 9372 } 9373 9374 /** 9375 * Get viewport/window size (width and height). 9376 * 9377 * @return {Object} 9378 */ 9379 function getViewport() { 9380 var e = window, 9381 a = 'inner'; 9382 if (!('innerWidth' in window)) { 9383 a = 'client'; 9384 e = document.documentElement || document.body; 9385 } 9386 return { 9387 width: e[a + 'Width'], 9388 height: e[a + 'Height'] 9389 } 9390 } 9391 9392 /** 9393 * Remove hash tag from the URL 9394 * 9395 * @return {Void} 9396 */ 9397 function removeHash() { 9398 var scroll = getScrollXY(); 9399 9400 window.location.hash = ""; 9401 9402 // Restore the scroll offset, should be flicker free 9403 window.scrollTo(scroll.x, scroll.y); 9404 } 9405 9406 /** 9407 * Do the ajax requests with callback. 9408 * 9409 * @param {String} url 9410 * @param {Function} callback 9411 * 9412 * @return {Void} 9413 */ 9414 function doAjax(url, callback) { 9415 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'); 9416 $.ajax({ 9417 url: url, 9418 dataType: 'jsonp' 9419 }); 9420 9421 iLCallback = function(data) { 9422 callback.call(this, data); 9423 }; 9424 } 9425 9426 /** 9427 * Find image from DOM elements 9428 * 9429 * @param {Element} element 9430 * 9431 * @return {Void} 9432 */ 9433 function findImageInElement(element) { 9434 var elements = $('*', element), 9435 imagesArr = new Array(); 9436 9437 elements.each(function() { 9438 var url = "", 9439 element = this; 9440 9441 if ($(element).css("background-image") != "none") { 9442 url = $(element).css("background-image"); 9443 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 9444 url = $(element).attr("src"); 9445 } 9446 9447 if (url.indexOf("gradient") == -1) { 9448 url = url.replace(/url\(\"/g, ""); 9449 url = url.replace(/url\(/g, ""); 9450 url = url.replace(/\"\)/g, ""); 9451 url = url.replace(/\)/g, ""); 9452 9453 var urls = url.split(","); 9454 9455 for (var i = 0; i < urls.length; i++) { 9456 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 9457 var extra = ""; 9458 if (browser.msie && browser.version < 9) { 9459 extra = "?" + floor(random() * 3000); 9460 } 9461 imagesArr.push(urls[i] + extra); 9462 } 9463 } 9464 } 9465 }); 9466 9467 return imagesArr; 9468 } 9469 9470 /** 9471 * Get file extension. 9472 * 9473 * @param {String} URL 9474 * 9475 * @return {String} 9476 */ 9477 function getExtension(URL) { 9478 if (URL !== null) { 9479 var ext = URL.split('.').pop().toLowerCase(), 9480 extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : ''; 9481 9482 return ext.replace(extra, ''); 9483 } 9484 } 9485 9486 /** 9487 * Get type via extension. 9488 * 9489 * @param {String} URL 9490 * 9491 * @return {String} 9492 */ 9493 function getTypeByExtension(URL) { 9494 var type, 9495 ext = getExtension(URL); 9496 9497 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 9498 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 9499 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 9500 else type = 'iframe'; 9501 9502 return type; 9503 } 9504 9505 /** 9506 * Return value from percent of a number. 9507 * 9508 * @param {Number} percent 9509 * @param {Number} total 9510 * 9511 * @return {Number} 9512 */ 9513 function percentToValue(percent, total) { 9514 return parseInt((total / 100) * percent); 9515 } 9516 9517 /** 9518 * A JavaScript equivalent of PHP’s parse_url. 9519 * 9520 * @param {String} url The URL to parse. 9521 * 9522 * @return {Mixed} 9523 */ 9524 function parseURI(url) { 9525 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 9526 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 9527 return (m ? { 9528 href: m[0] || '', 9529 protocol: m[1] || '', 9530 authority: m[2] || '', 9531 host: m[3] || '', 9532 hostname: m[4] || '', 9533 port: m[5] || '', 9534 pathname: m[6] || '', 9535 search: m[7] || '', 9536 hash: m[8] || '' 9537 } : null); 9538 } 9539 9540 /** 9541 * Gets the absolute URI. 9542 * 9543 * @param {String} href The relative URL. 9544 * @param {String} base The base URL. 9545 * 9546 * @return {String} The absolute URL. 9547 */ 9548 function absolutizeURI(base, href) { // RFC 3986 9549 var iL = this; 9550 9551 function removeDotSegments(input) { 9552 var output = []; 9553 input.replace(/^(\.\.?(\/|$))+/, '') 9554 .replace(/\/(\.(\/|$))+/g, '/') 9555 .replace(/\/\.\.$/, '/../') 9556 .replace(/\/?[^\/]*/g, function(p) { 9557 if (p === '/..') { 9558 output.pop(); 9559 } else { 9560 output.push(p); 9561 } 9562 }); 9563 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 9564 } 9565 9566 href = parseURI(href || ''); 9567 base = parseURI(base || ''); 9568 9569 return !href || !base ? null : (href.protocol || base.protocol) + 9570 (href.protocol || href.authority ? href.authority : base.authority) + 9571 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)) + 9572 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 9573 href.hash; 9574 } 9575 9576 /** 9577 * A JavaScript equivalent of PHP’s version_compare. 9578 * 9579 * @param {String} v1 9580 * @param {String} v2 9581 * @param {String} operator
9582 * 9583 * @return {Boolean} 9584 */ 9585 function version_compare(v1, v2, operator) { 9586 this.php_js = this.php_js || {}; 9587 this.php_js.ENV = this.php_js.ENV || {}; 9588 var i = 0, 9589 x = 0, 9590 compare = 0, 9591 vm = { 9592 'dev': -6, 9593 'alpha': -5, 9594 'a': -5, 9595 'beta': -4, 9596 'b': -4, 9597 'RC': -3, 9598 'rc': -3, 9599 '#': -2, 9600 'p': 1, 9601 'pl': 1 9602 }, 9603 prepVersion = function(v) { 9604 v = ('' + v).replace(/[_\-+]/g, '.'); 9605 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 9606 return (!v.length ? [-8] : v.split('.')); 9607 }, 9608 numVersion = function(v) { 9609 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 9610 }; 9611 v1 = prepVersion(v1); 9612 v2 = prepVersion(v2); 9613 x = max(v1.length, v2.length); 9614 for (i = 0; i < x; i++) { 9615 if (v1[i] == v2[i]) { 9616 continue; 9617 } 9618 v1[i] = numVersion(v1[i]); 9619 v2[i] = numVersion(v2[i]); 9620 if (v1[i] < v2[i]) { 9621 compare = -1; 9622 break; 9623 } else if (v1[i] > v2[i]) { 9624 compare = 1; 9625 break; 9626 } 9627 } 9628 if (!operator) { 9629 return compare; 9630 } 9631 9632 switch (operator) { 9633 case '>': 9634 case 'gt': 9635 return (compare > 0); 9636 case '>=': 9637 case 'ge': 9638 return (compare >= 0); 9639 case '<=': 9640 case 'le': 9641 return (compare <= 0); 9642 case '==': 9643 case '=': 9644 case 'eq': 9645 return (compare === 0); 9646 case '<>': 9647 case '!=': 9648 case 'ne': 9649 return (compare !== 0); 9650 case '': 9651 case '<': 9652 case 'lt': 9653 return (compare < 0); 9654 default: 9655 return null; 9656 } 9657 } 9658 9659 9660 // Begin the iLightBox plugin 9661 $.fn.iLightBox = function() { 9662 9663 var args = arguments, 9664 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 9665 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 9666 9667 if (!opt) opt = {}; 9668 9669 // Default options. Play carefully. 9670 var options = $.extend(true, { 9671 attr: 'href', 9672 path: 'vertical', 9673 skin: 'dark', 9674 linkId: false, 9675 infinite: false, 9676 startFrom: 0, 9677 randomStart: false, 9678 keepAspectRatio: true, 9679 maxScale: 1, 9680 minScale: .2, 9681 innerToolbar: false, 9682 smartRecognition: false, 9683 mobileOptimizer: true, 9684 fullAlone: true, 9685 fullViewPort: null, 9686 fullStretchTypes: 'flash, video', 9687 overlay: { 9688 blur: true, 9689 opacity: .85 9690 }, 9691 controls: { 9692 arrows: false, 9693 slideshow: false, 9694 toolbar: true, 9695 fullscreen: true, 9696 thumbnail: true, 9697 keyboard: true, 9698 mousewheel: true, 9699 swipe: true 9700 }, 9701 keyboard: { 9702 left: true, // previous 9703 right: true, // next 9704 up: true, // previous 9705 down: true, // next 9706 esc: true, // close 9707 shift_enter: true // fullscreen 9708 }, 9709 show: { 9710 effect: true, 9711 speed: 300, 9712 title: true 9713 }, 9714 hide: { 9715 effect: true, 9716 speed: 300 9717 }, 9718 caption: { 9719 start: true, 9720 show: 'mouseenter', 9721 hide: 'mouseleave' 9722 }, 9723 social: { 9724 start: true, 9725 show: 'mouseenter', 9726 hide: 'mouseleave',
9727 buttons: false 9728 }, 9729 styles: { 9730 pageOffsetX: 0, 9731 pageOffsetY: 0, 9732 nextOffsetX: 45, 9733 nextOffsetY: 0, 9734 nextOpacity: 1, 9735 nextScale: 1, 9736 prevOffsetX: 45, 9737 prevOffsetY: 0, 9738 prevOpacity: 1, 9739 prevScale: 1 9740 }, 9741 thumbnails: { 9742 maxWidth: 120, 9743 maxHeight: 80, 9744 normalOpacity: 1, 9745 activeOpacity: .6 9746 }, 9747 effects: { 9748 reposition: true, 9749 repositionSpeed: 200, 9750 switchSpeed: 500, 9751 loadedFadeSpeed: 180, 9752 fadeSpeed: 200 9753 }, 9754 slideshow: { 9755 pauseTime: 5000, 9756 pauseOnHover: false, 9757 startPaused: true 9758 }, 9759 text: { 9760 close: "Press Esc to close", 9761 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 9762 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 9763 slideShow: "Slideshow", 9764 next: "Next", 9765 previous: "Previous" 9766 }, 9767 errors: { 9768 loadImage: "An error occurred when trying to load photo.", 9769 loadContents: "An error occurred when trying to load contents.", 9770 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 9771 }, 9772 ajaxSetup: { 9773 url: '', 9774 beforeSend: function(jqXHR, settings) {}, 9775 cache: false, 9776 complete: function(jqXHR, textStatus) {}, 9777 crossDomain: false, 9778 error: function(jqXHR, textStatus, errorThrown) {}, 9779 success: function(data, textStatus, jqXHR) {}, 9780 global: true, 9781 ifModified: false, 9782 username: null, 9783 password: null, 9784 type: 'GET' 9785 }, 9786 callback: {} 9787 }, opt); 9788 9789 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 9790 9791 items = $.isArray(items) ? items : new Array(); 9792 9793 if (typeof args[0] == 'string') items[0] = args[0]; 9794 9795 if (version_compare($.fn.jquery, '1.8', '>=')) { 9796 var iLB = new iLightBox($(this), options, items, instant); 9797 return { 9798 close: function() { 9799 iLB.closeAction(); 9800 }, 9801 fullscreen: function() { 9802 iLB.fullScreenAction(); 9803 }, 9804 moveNext: function() { 9805 iLB.moveTo('next'); 9806 }, 9807 movePrev: function() { 9808 iLB.moveTo('prev'); 9809 }, 9810 goTo: function(index) { 9811 iLB.goTo(index); 9812 }, 9813 refresh: function() { 9814 iLB.refresh(); 9815 }, 9816 reposition: function() { 9817 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 9818 }, 9819 setOption: function(options) { 9820 iLB.setOption(options); 9821 }, 9822 destroy: function() { 9823 iLB.closeAction(); 9824 iLB.dispatchItemsEvents(); 9825 } 9826 }; 9827 } else { 9828 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 9829 } 9830 9831 }; 9832 9833 9834 $.iLightBox = function() { 9835 return $.fn.iLightBox(arguments[0], arguments[1]); 9836 }; 9837 9838 9839 $.extend($.easing, { 9840 easeInCirc: function(x, t, b, c, d) { 9841 return -c * (sqrt(1 - (t /= d) * t) - 1) + b; 9842 }, 9843 easeOutCirc: function(x, t, b, c, d) { 9844 return c * sqrt(1 - (t = t / d - 1) * t) + b; 9845 }, 9846 easeInOutCirc: function(x, t, b, c, d) { 9847 if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; 9848 return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b; 9849 } 9850 }); 9851 9852 function getScrollXY() { 9853 var scrOfX = 0, 9854 scrOfY = 0; 9855 if (typeof(window.pageYOffset) == 'number') { 9856 //Netscape compliant 9857 scrOfY = window.pageYOffset; 9858 scrOfX = window.pageXOffset; 9859 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 9860 //DOM compliant 9861 scrOfY = document.body.scrollTop; 9862 scrOfX = document.body.scrollLeft; 9863 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 9864 //IE6 standards compliant mode 9865 scrOfY = document.documentElement.scrollTop; 9866 scrOfX = document.documentElement.scrollLeft; 9867 } 9868 return { 9869 x: scrOfX, 9870 y: scrOfY 9871 }; 9872 } 9873 9874 (function() { 9875 // add new event shortcuts 9876 $.each(("touchstart touchmove touchend " + 9877 "tap taphold " + 9878 "swipe swipeleft swiperight " + 9879 "scrollstart scrollstop").split(" "), function(i, name) { 9880 9881 $.fn[name] = function(fn) { 9882 return fn ? this.bind(name, fn) : this.trigger(name); 9883 }; 9884 9885 // jQuery < 1.8 9886 // if ($.attrFn) { 9887 // $.attrFn[name] = true; 9888 // } 9889 }); 9890 9891 var tapSettings = { 9892 startEvent: 'touchstart.iTap', 9893 endEvent: 'touchend.iTap' 9894 }; 9895 9896 // tap Event: 9897 $.event.special.itap = { 9898 setup: function() { 9899 9900 var self = this, 9901 $self = $(this), 9902 start, stop; 9903 9904 $self.bind(tapSettings.startEvent, function(event) { 9905 start = getScrollXY(); 9906 9907 $self.one(tapSettings.endEvent, function(event) { 9908 stop = getScrollXY(); 9909 9910 var orgEvent = event || window.event; 9911 event = $.event.fix(orgEvent); 9912 event.type = "itap"; 9913 9914 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 9915 9916 start = stop = undefined; 9917 }); 9918 }); 9919 }, 9920 9921 teardown: function() { 9922 $(this).unbind(tapSettings.startEvent); 9923 } 9924 }; 9925 }()); 9926 9927 9928 //Fullscreen API 9929 (function() { 9930 fullScreenApi = { 9931 supportsFullScreen: false, 9932 isFullScreen: function() { 9933 return false;
9934 }, 9935 requestFullScreen: function() {}, 9936 cancelFullScreen: function() {}, 9937 fullScreenEventName: '', 9938 prefix: '' 9939 }, 9940 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 9941 9942 // check for native support 9943 if (typeof document.cancelFullScreen != 'undefined') { 9944 fullScreenApi.supportsFullScreen = true; 9945 } else { 9946 // check for fullscreen support by vendor prefix 9947 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 9948 fullScreenApi.prefix = browserPrefixes[i]; 9949 9950 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 9951 fullScreenApi.supportsFullScreen = true; 9952 9953 break; 9954 } 9955 } 9956 } 9957 9958 // update methods to do something useful 9959 if (fullScreenApi.supportsFullScreen) { 9960 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 9961 9962 fullScreenApi.isFullScreen = function() { 9963 switch (this.prefix) { 9964 case '': 9965 return document.fullScreen; 9966 case 'webkit': 9967 return document.webkitIsFullScreen; 9968 default: 9969 return document[this.prefix + 'FullScreen']; 9970 } 9971 } 9972 fullScreenApi.requestFullScreen = function(el) { 9973 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 9974 } 9975 fullScreenApi.cancelFullScreen = function(el) { 9976 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 9977 } 9978 } 9979 }()); 9980 9981 // Browser detect 9982 (function() { 9983 function uaMatch(ua) { 9984 ua = ua.toLowerCase(); 9985 9986 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 9987 /(webkit)[ \/]([\w.]+)/.exec(ua) || 9988 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 9989 /(msie) ([\w.]+)/.exec(ua) || 9990 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 9991 9992 return { 9993 browser: match[1] || "", 9994 version: match[2] || "0" 9995 }; 9996 } 9997 9998 var matched = uaMatch(navigator.userAgent); 9999 browser = {}; 10000 10001 if (matched.browser) { 10002 browser[matched.browser] = true; 10003 browser.version = matched.version; 10004 } 10005 10006 // Chrome is Webkit, but Webkit is also Safari. 10007 if (browser.chrome) { 10008 browser.webkit = true; 10009 } else if (browser.webkit) { 10010 browser.safari = true; 10011 } 10012 }()); 10013 10014 // Feature detects 10015 (function() { 10016 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 10017 var el = document.createElement('div'); 10018 10019 function testProp(prop) { 10020 for (var p = 0, pl = prefixes.length; p < pl; p++) { 10021 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 10022 if (el.style[prefixedProp] !== undefined) { 10023 return prefixedProp; 10024 } 10025 } 10026 } 10027 10028 // Global support indicators 10029 transform = testProp('transform') || ''; 10030 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 10031 }()); 10032 10033 10034 /* 10035 PluginDetect v0.7.9 10036 www.pinlady.net/PluginDetect/license/ 10037 [ getVersion onWindowLoaded BetterIE ] 10038 [ Flash QuickTime Shockwave ] 10039 */ 10040 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;
10040d++){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);
10040d.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)}
10040c.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;
10040if(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(); 10041 10042 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)}; 10043 10044 10045 /* 10046 jQuery hashchange event v1.3 10047 https://github.com/cowboy/jquery-hashchange 10048 Copyright (c) 2010 "Cowboy" Ben Alman 10049 Dual licensed under the MIT and GPL licenses. 10050 */ 10051 (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= 10052 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|| 10053 "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;
10053a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 10054 10055 if (!Array.prototype.filter) { 10056 Array.prototype.filter = function(fun /*, thisp */ ) { 10057 "use strict"; 10058 10059 if (this == null) 10060 throw new TypeError(); 10061 10062 var t = Object(this); 10063 var len = t.length >>> 0; 10064 if (typeof fun != "function") 10065 throw new TypeError(); 10066 10067 var res = []; 10068 var thisp = arguments[1]; 10069 for (var i = 0; i < len; i++) { 10070 if (i in t) { 10071 var val = t[i]; // in case fun mutates this 10072 if (fun.call(thisp, val, i, t)) 10073 res.push(val); 10074 } 10075 } 10076 10077 return res; 10078 }; 10079 } 10080 10081 if (!Array.prototype.indexOf) { 10082 Array.prototype.indexOf = function(searchElement, fromIndex) { 10083 var k; 10084 10085 if (this == null) { 10086 throw new TypeError('"this" is null or not defined'); 10087 } 10088 10089 var O = Object(this); 10090 10091 var len = O.length >>> 0; 10092 10093 if (len === 0) { 10094 return -1; 10095 } 10096 10097 var n = +fromIndex || 0; 10098 10099 if (abs(n) === Infinity) { 10100 n = 0; 10101 } 10102 10103 if (n >= len) { 10104 return -1; 10105 } 10106 10107 k = max(n >= 0 ? n : len - abs(n), 0); 10108 10109 while (k < len) { 10110 var kValue; 10111 if (k in O && O[k] === searchElement) { 10112 return k; 10113 } 10114 k++; 10115 } 10116 return -1; 10117 }; 10118 } 10119 10120 if (!Array.prototype.lastIndexOf) { 10121 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 10122 "use strict"; 10123 10124 if (this == null) 10125 throw new TypeError(); 10126 10127 var t = Object(this); 10128 var len = t.length >>> 0; 10129 if (len === 0) 10130 return -1; 10131 10132 var n = len; 10133 if (arguments.length > 1) { 10134 n = Number(arguments[1]); 10135 if (n != n) 10136 n = 0; 10137 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 10138 n = (n > 0 || -1) * floor(abs(n)); 10139 } 10140 10141 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 10142 10143 for (; k >= 0; k--) { 10144 if (k in t && t[k] === searchElement) 10145 return k; 10146 } 10147 return -1; 10148 }; 10149 } 10150})(jQuery, this); 10151 10152/** 10153 * Owl carousel
vendor: 12,045 bytes, lines 10154-10659
10154 * @version 2.0.0-beta.3 10155 * @author Bartosz Wojciechowski 10156 * @license The MIT License (MIT) 10157 * @todo Lazy Load Icon 10158 * @todo prevent animationend bubling 10159 * @todo itemsScaleUp 10160 * @todo Test Zepto 10161 * @todo stagePadding calculate wrong active classes 10162 */ 10163;(function($, window, document, undefined) { 10164 10165 /** 10166 * Creates a carousel. 10167 * @class The Owl Carousel. 10168 * @public 10169 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 10170 * @param {Object} [options] - The options 10171 */ 10172 function Owl(element, options) { 10173 10174 /** 10175 * Current settings for the carousel. 10176 * @public 10177 */ 10178 this.settings = null; 10179 10180 /** 10181 * Current options set by the caller including defaults. 10182 * @public 10183 */ 10184 this.options = $.extend({}, Owl.Defaults, options); 10185 10186 /** 10187 * Plugin element. 10188 * @public 10189 */ 10190 this.$element = $(element); 10191 10192 /** 10193 * Proxied event handlers. 10194 * @protected 10195 */ 10196 this._handlers = {}; 10197 10198 /** 10199 * References to the running plugins of this carousel. 10200 * @protected 10201 */ 10202 this._plugins = {}; 10203 10204 /** 10205 * Currently suppressed events to prevent them from beeing retriggered. 10206 * @protected 10207 */ 10208 this._supress = {}; 10209 10210 /** 10211 * Absolute current position. 10212 * @protected 10213 */ 10214 this._current = null; 10215 10216 /** 10217 * Animation speed in milliseconds. 10218 * @protected 10219 */ 10220 this._speed = null; 10221 10222 /** 10223 * Coordinates of all items in pixel. 10224 * @todo The name of this member is missleading. 10225 * @protected 10226 */ 10227 this._coordinates = []; 10228 10229 /** 10230 * Current breakpoint. 10231 * @todo Real media queries would be nice. 10232 * @protected 10233 */ 10234 this._breakpoint = null; 10235 10236 /** 10237 * Current width of the plugin element. 10238 */ 10239 this._width = null; 10240 10241 /** 10242 * All real items. 10243 * @protected 10244 */ 10245 this._items = []; 10246 10247 /** 10248 * All cloned items. 10249 * @protected 10250 */ 10251 this._clones = []; 10252 10253 /** 10254 * Merge values of all items. 10255 * @todo Maybe this could be part of a plugin. 10256 * @protected 10257 */ 10258 this._mergers = []; 10259 10260 /** 10261 * Widths of all items. 10262 */ 10263 this._widths = []; 10264 10265 /** 10266 * Invalidated parts within the update process. 10267 * @protected 10268 */ 10269 this._invalidated = {}; 10270 10271 /** 10272 * Ordered list of workers for the update process. 10273 * @protected 10274 */ 10275 this._pipe = []; 10276 10277 /** 10278 * Current state information for the drag operation. 10279 * @todo #261 10280 * @protected 10281 */ 10282 this._drag = { 10283 time: null, 10284 target: null, 10285 pointer: null, 10286 stage: { 10287 start: null, 10288 current: null 10289 }, 10290 direction: null 10291 }; 10292 10293 /** 10294 * Current state information and their tags. 10295 * @type {Object} 10296 * @protected 10297 */ 10298 this._states = { 10299 current: {}, 10300 tags: { 10301 'initializing': [ 'busy' ], 10302 'animating': [ 'busy' ], 10303 'dragging': [ 'interacting' ] 10304 } 10305 }; 10306 10307 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 10308 this._handlers[handler] = $.proxy(this[handler], this); 10309 }, this)); 10310 10311 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 10312 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 10313 = new plugin(this); 10314 }, this)); 10315 10316 $.each(Owl.Workers, $.proxy(function(priority, worker) { 10317 this._pipe.push({ 10318 'filter': worker.filter, 10319 'run': $.proxy(worker.run, this) 10320 }); 10321 }, this)); 10322 10323 this.setup(); 10324 this.initialize(); 10325 } 10326 10327 /** 10328 * Default options for the carousel. 10329 * @public 10330 */ 10331 Owl.Defaults = { 10332 items: 3, 10333 loop: false, 10334 center: false, 10335 rewind: false, 10336 10337 mouseDrag: true, 10338 touchDrag: true, 10339 pullDrag: true, 10340 freeDrag: false, 10341 10342 margin: 0, 10343 stagePadding: 0, 10344 10345 merge: false, 10346 mergeFit: true, 10347 autoWidth: false, 10348 10349 startPosition: 0, 10350 rtl: false, 10351 10352 smartSpeed: 250, 10353 fluidSpeed: false, 10354 dragEndSpeed: false, 10355 10356 responsive: {}, 10357 responsiveRefreshRate: 200, 10358 responsiveBaseElement: window, 10359 10360 fallbackEasing: 'swing', 10361 10362 info: false, 10363 10364 nestedItemSelector: false, 10365 itemElement: 'div', 10366 stageElement: 'div', 10367 10368 refreshClass: 'owl-refresh', 10369 loadedClass: 'owl-loaded', 10370 loadingClass: 'owl-loading', 10371 rtlClass: 'owl-rtl', 10372 responsiveClass: 'owl-responsive', 10373 dragClass: 'owl-drag', 10374 itemClass: 'owl-item', 10375 stageClass: 'owl-stage', 10376 stageOuterClass: 'owl-stage-outer', 10377 grabClass: 'owl-grab' 10378 }; 10379 10380 /** 10381 * Enumeration for width. 10382 * @public 10383 * @readonly 10384 * @enum {String} 10385 */ 10386 Owl.Width = { 10387 Default: 'default', 10388 Inner: 'inner', 10389 Outer: 'outer' 10390 }; 10391 10392 /** 10393 * Enumeration for types. 10394 * @public 10395 * @readonly 10396 * @enum {String} 10397 */ 10398 Owl.Type = { 10399 Event: 'event', 10400 State: 'state' 10401 }; 10402 10403 /** 10404 * Contains all registered plugins. 10405 * @public 10406 */ 10407 Owl.Plugins = {}; 10408 10409 /** 10410 * List of workers involved in the update process. 10411 */ 10412 Owl.Workers = [ { 10413 filter: [ 'width', 'settings' ], 10414 run: function() { 10415 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 10416 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 10417 } 10418 }, { 10419 filter: [ 'width', 'items', 'settings' ], 10420 run: function(cache) { 10421 cache.current = this._items && this._items[this.relative(this._current)]; 10422 } 10423 }, { 10424 filter: [ 'items', 'settings' ], 10425 run: function() { 10426 this.$stage.children('.cloned').remove(); 10427 } 10428 }, { 10429 filter: [ 'width', 'items', 'settings' ], 10430 run: function(cache) { 10431 var margin = this.settings.margin || '', 10432 grid = !this.settings.autoWidth, 10433 rtl = this.settings.rtl, 10434 css = { 10435 'width': 'auto', 10436 'margin-left': rtl ? margin : '', 10437 'margin-right': rtl ? '' : margin 10438 }; 10439 10440 !grid && this.$stage.children().css(css); 10441 10442 cache.css = css; 10443 } 10444 }, { 10445 filter: [ 'width', 'items', 'settings' ], 10446 run: function(cache) { 10447 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 10448 merge = null, 10449 iterator = this._items.length, 10450 grid = !this.settings.autoWidth, 10451 widths = []; 10452 10453 cache.items = { 10454 merge: false, 10455 width: width 10456 }; 10457 10458 while (iterator--) { 10459 merge = this._mergers[iterator]; 10460 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 10461 10462 cache.items.merge = merge > 1 || cache.items.merge; 10463 10464 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 10465 } 10466 10467 this._widths = widths; 10468 } 10469 }, { 10470 filter: [ 'items', 'settings' ], 10471 run: function() { 10472 var clones = [], 10473 items = this._items, 10474 settings = this.settings, 10475 view = Math.max(settings.items * 2, 4), 10476 size = Math.ceil(items.length / 2) * 2, 10477 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 10478 append = '', 10479 prepend = ''; 10480 10481 repeat /= 2; 10482 10483 while (repeat--) { 10484 clones.push(this.normalize(clones.length / 2, true)); 10485 append = append + items[clones[clones.length - 1]][0].outerHTML; 10486 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 10487 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 10488 } 10489 10490 this._clones = clones; 10491 10492 // var appendVideo = $(append).find('.uncode-video-container'); 10493 // if (appendVideo.length) { 10494 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 10495 // } 10496 // var prependVideo = $(prepend).find('.uncode-video-container'); 10497 // if (prependVideo.length) { 10498 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 10499 // } 10500 $(append).addClass('cloned').appendTo(this.$stage); 10501 $(prepend).addClass('cloned').prependTo(this.$stage); 10502 } 10503 }, { 10504 filter: [ 'width', 'items', 'settings' ], 10505 run: function() { 10506 var rtl = this.settings.rtl ? 1 : -1, 10507 size = this._clones.length + this._items.length, 10508 iterator = -1, 10509 previous = 0, 10510 current = 0, 10511 coordinates = []; 10512 10513 while (++iterator < size) { 10514 previous = coordinates[iterator - 1] || 0; 10515 current = this._widths[this.relative(iterator)] + this.settings.margin; 10516 coordinates.push(previous + current * rtl); 10517 } 10518 10519 this._coordinates = coordinates; 10520 } 10521 }, { 10522 filter: [ 'width', 'items', 'settings' ], 10523 run: function() { 10524 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10525 padding = stagePadding, 10526 coordinates = this._coordinates, 10527 css = { 10528 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 10529 'padding-left': padding || '', 10530 'padding-right': padding || '' 10531 }; 10532 10533 this.$stage.css(css); 10534 } 10535 }, { 10536 filter: [ 'width', 'items', 'settings' ], 10537 run: function(cache) { 10538 var iterator = this._coordinates.length, 10539 grid = !this.settings.autoWidth, 10540 items = this.$stage.children(); 10541 10542 if (grid && cache.items.merge) { 10543 while (iterator--) { 10544 cache.css.width = this._widths[this.relative(iterator)]; 10545 items.eq(iterator).css(cache.css); 10546 } 10547 } else if (grid) { 10548 cache.css.width = cache.items.width; 10549 items.css(cache.css); 10550 } 10551 } 10552 }, { 10553 filter: [ 'items' ], 10554 run: function() { 10555 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 10556 } 10557 }, { 10558 filter: [ 'width', 'items', 'settings' ], 10559 run: function(cache) { 10560 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 10561 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 10562 this.reset(cache.current); 10563 } 10564 }, { 10565 filter: [ 'position' ], 10566 run: function() { 10567 this.animate(this.coordinates(this._current)); 10568 } 10569 }, { 10570 filter: [ 'width', 'position', 'items', 'settings' ], 10571 run: function() { 10572 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10573 rtl = this.settings.rtl ? 1 : -1, 10574 padding = this.settings.stagePadding * 2, 10575 begin = this.coordinates(this.current()) + padding, 10576 end = begin + this.width() * rtl, 10577 inner, outer, matches = [], i, n; 10578 10579 for (i = 0, n = this._coordinates.length; i < n; i++) { 10580 inner = this._coordinates[i - 1] || 0; 10581 outer = Math.abs(this._coordinates[i]) + padding * rtl; 10582 10583 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 10584 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 10585 matches.push(i); 10586 } 10587 } 10588 10589 this.$stage.children('.active').removeClass('active'); 10590 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 10591 10592 if (this.settings.center) { 10593 this.$stage.children('.center').removeClass('center'); 10594 this.$stage.children().eq(this.current()).addClass('center'); 10595 } 10596 } 10597 } ]; 10598 10599 /** 10600 * Initializes the carousel. 10601 * @protected 10602 */ 10603 Owl.prototype.initialize = function() { 10604 this.enter('initializing'); 10605 this.trigger('initialize'); 10606 10607 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 10608 10609 if (this.settings.autoWidth && !this.is('pre-loading')) { 10610 var imgs, nestedSelector, width; 10611 imgs = this.$element.find('img'); 10612 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 10613 width = this.$element.children(nestedSelector).width(); 10614 10615 if (imgs.length && width <= 0) { 10616 this.preloadAutoWidthImages(imgs); 10617 } 10618 } 10619 10620 this.$element.addClass(this.options.loadingClass); 10621 10622 // create stage 10623 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 10624 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 10625 10626 // append stage 10627 this.$element.append(this.$stage.parent()); 10628 10629 // append content 10630 this.replace(this.$element.children().not(this.$stage.parent())); 10631 10632 // check visibility 10633 if (this.$element.is(':visible')) { 10634 // update view 10635 this.refresh(); 10636 } else { 10637 // invalidate width 10638 this.invalidate('width'); 10639 } 10640 10641 this.$element 10642 .removeClass(this.options.loadingClass) 10643 .addClass(this.options.loadedClass); 10644 10645 // register event handlers 10646 this.registerEventHandlers(); 10647 10648 this.leave('initializing'); 10649 this.trigger('initialized'); 10650 }; 10651 10652 /** 10653 * Setups the current settings. 10654 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 10655 * @todo Support for media queries by using `matchMedia` would be nice. 10656 * @public 10657 */ 10658 Owl.prototype.setup = function() { 10659 var viewport = this.viewport(),
10660 overwrites = this.options.responsive, 10661 match = -1, 10662 settings = null; 10663 10664 if (!overwrites) { 10665 settings = $.extend({}, this.options); 10666 } else { 10667 $.each(overwrites, function(breakpoint) { 10668 if (breakpoint <= viewport && breakpoint > match) { 10669 match = Number(breakpoint); 10670 } 10671 }); 10672 10673 settings = $.extend({}, this.options, overwrites[match]); 10674 delete settings.responsive; 10675 10676 // responsive class 10677 if (settings.responsiveClass) { 10678 this.$element.attr('class', 10679 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 10680 ); 10681 } 10682 } 10683 10684 if (this.settings === null || this._breakpoint !== match) { 10685 this.trigger('change', { property: { name: 'settings', value: settings } }); 10686 this._breakpoint = match; 10687 this.settings = settings; 10688 this.invalidate('settings'); 10689 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 10690 } 10691 }; 10692 10693 /** 10694 * Updates option logic if necessery. 10695 * @protected 10696 */ 10697 Owl.prototype.optionsLogic = function() { 10698 if (this.settings.autoWidth) { 10699 this.settings.stagePadding = false; 10700 this.settings.merge = false; 10701 } 10702 }; 10703 10704 /** 10705 * Prepares an item before add. 10706 * @todo Rename event parameter `content` to `item`. 10707 * @protected 10708 * @returns {jQuery|HTMLElement} - The item container. 10709 */ 10710 Owl.prototype.prepare = function(item, index) { 10711 var event = this.trigger('prepare', { content: item }); 10712 if (!event.data) { 10713 event.data = $('<' + this.settings.itemElement + '/>') 10714 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 10715 } 10716 10717 this.trigger('prepared', { content: event.data }); 10718 10719 return event.data; 10720 }; 10721 10722 /** 10723 * Updates the view. 10724 * @public 10725 */ 10726 Owl.prototype.update = function() { 10727 var i = 0, 10728 n = this._pipe.length, 10729 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 10730 cache = {}; 10731 10732 while (i < n) { 10733 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 10734 this._pipe[i].run(cache); 10735 } 10736 i++; 10737 } 10738 10739 this._invalidated = {}; 10740 10741 !this.is('valid') && this.enter('valid'); 10742 }; 10743 10744 /** 10745 * Gets the width of the view. 10746 * @public 10747 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 10748 * @returns {Number} - The width of the view in pixel. 10749 */ 10750 Owl.prototype.width = function(dimension) { 10751 dimension = dimension || Owl.Width.Default; 10752 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 10753 switch (dimension) { 10754 case Owl.Width.Inner: 10755 case Owl.Width.Outer: 10756 return this._width; 10757 default: 10758 return this._width - stagePadding * 2 + this.settings.margin; 10759 } 10760 }; 10761 10762 /** 10763 * Refreshes the carousel primarily for adaptive purposes. 10764 * @public 10765 */ 10766 Owl.prototype.refresh = function() { 10767 this.enter('refreshing'); 10768 this.trigger('refresh'); 10769 10770 this.setup(); 10771 10772 this.optionsLogic(); 10773 10774 this.$element.addClass(this.options.refreshClass); 10775 10776 this.update(); 10777 10778 this.$element.removeClass(this.options.refreshClass); 10779 10780 this.leave('refreshing'); 10781 this.trigger('refreshed'); 10782 }; 10783 10784 /** 10785 * Checks window `resize` event. 10786 * @protected 10787 */ 10788 Owl.prototype.onThrottledResize = function() { 10789 window.clearTimeout(this.resizeTimer); 10790 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 10791 }; 10792 10793 /** 10794 * Checks window `resize` event. 10795 * @protected 10796 */ 10797 Owl.prototype.onResize = function() { 10798 if (!this._items.length) { 10799 return false; 10800 } 10801 10802 if (this._width === this.$element.width()) { 10803 return false; 10804 } 10805 10806 if (!this.$element.is(':visible')) { 10807 return false; 10808 } 10809 10810 this.enter('resizing'); 10811 10812 if (this.trigger('resize').isDefaultPrevented()) { 10813 this.leave('resizing'); 10814 return false; 10815 } 10816 10817 this.invalidate('width'); 10818 10819 this.refresh(); 10820 10821 this.leave('resizing'); 10822 this.trigger('resized'); 10823 }; 10824 10825 /** 10826 * Registers event handlers. 10827 * @todo Check `msPointerEnabled` 10828 * @todo #261 10829 * @protected 10830 */ 10831 Owl.prototype.registerEventHandlers = function() { 10832 if ($.support.transition) { 10833 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 10834 } 10835 10836 if (this.settings.responsive !== false) { 10837 this.on(window, 'resize', this._handlers.onThrottledResize); 10838 } 10839 10840 if (this.settings.mouseDrag) { 10841 this.$element.addClass(this.options.dragClass); 10842 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 10843 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 10844 } 10845 10846 if (this.settings.touchDrag){ 10847 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 10848 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 10849 } 10850 }; 10851 10852 /** 10853 * Handles `touchstart` and `mousedown` events. 10854 * @todo Horizontal swipe threshold as option 10855 * @todo #261 10856 * @protected 10857 * @param {Event} event - The event arguments. 10858 */ 10859 Owl.prototype.onDragStart = function(event) { 10860 var stage = null; 10861 10862 if (event.which === 3) { 10863 return; 10864 } 10865
vendor: 9,106 bytes, lines 10866-11181
10866 if ($.support.transform) { 10867 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 10868 stage = { 10869 x: stage[stage.length === 16 ? 12 : 4], 10870 y: stage[stage.length === 16 ? 13 : 5] 10871 }; 10872 } else { 10873 stage = this.$stage.position(); 10874 stage = { 10875 x: this.settings.rtl ? 10876 stage.left + this.$stage.width() - this.width() + this.settings.margin : 10877 stage.left, 10878 y: stage.top 10879 }; 10880 } 10881 10882 if (this.is('animating')) { 10883 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 10884 this.invalidate('position'); 10885 } 10886 10887 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 10888 10889 this.speed(0); 10890 10891 this._drag.time = new Date().getTime(); 10892 this._drag.target = $(event.target); 10893 this._drag.stage.start = stage; 10894 this._drag.stage.current = stage; 10895 this._drag.pointer = this.pointer(event); 10896 10897 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 10898 10899 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 10900 var delta = this.difference(this._drag.pointer, this.pointer(event)); 10901 10902 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 10903 10904 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 10905 return; 10906 } 10907 10908 event.preventDefault(); 10909 10910 this.enter('dragging'); 10911 this.trigger('drag'); 10912 }, this)); 10913 }; 10914 10915 /** 10916 * Handles the `touchmove` and `mousemove` events. 10917 * @todo #261 10918 * @protected 10919 * @param {Event} event - The event arguments. 10920 */ 10921 Owl.prototype.onDragMove = function(event) { 10922 var minimum = null, 10923 maximum = null, 10924 pull = null, 10925 delta = this.difference(this._drag.pointer, this.pointer(event)), 10926 stage = this.difference(this._drag.stage.start, delta); 10927 10928 if (!this.is('dragging')) { 10929 return; 10930 } 10931 10932 event.preventDefault(); 10933 10934 if (this.settings.loop) { 10935 minimum = this.coordinates(this.minimum()); 10936 maximum = this.coordinates(this.maximum() + 1) - minimum; 10937 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 10938 } else { 10939 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 10940 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 10941 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 10942 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 10943 } 10944 10945 this._drag.stage.current = stage; 10946 10947 this.animate(stage.x); 10948 }; 10949 10950 /** 10951 * Handles the `touchend` and `mouseup` events. 10952 * @todo #261 10953 * @todo Threshold for click event 10954 * @protected 10955 * @param {Event} event - The event arguments. 10956 */ 10957 Owl.prototype.onDragEnd = function(event) { 10958 var delta = this.difference(this._drag.pointer, this.pointer(event)), 10959 stage = this._drag.stage.current, 10960 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 10961 10962 $(document).off('.owl.core'); 10963 10964 this.$element.removeClass(this.options.grabClass); 10965 10966 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 10967 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 10968 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 10969 this.invalidate('position'); 10970 this.update(); 10971 10972 this._drag.direction = direction; 10973 10974 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 10975 this._drag.target.one('click.owl.core', function() { return false; }); 10976 } 10977 } 10978 10979 if (!this.is('dragging')) { 10980 return; 10981 } 10982 10983 this.leave('dragging'); 10984 this.trigger('dragged'); 10985 }; 10986 10987 /** 10988 * Gets absolute position of the closest item for a coordinate. 10989 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 10990 * @protected 10991 * @param {Number} coordinate - The coordinate in pixel. 10992 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 10993 * @return {Number} - The absolute position of the closest item. 10994 */ 10995 Owl.prototype.closest = function(coordinate, direction) { 10996 var position = -1, 10997 pull = 30, 10998 width = this.width(), 10999 coordinates = this.coordinates(); 11000 11001 if (!this.settings.freeDrag) { 11002 // check closest item 11003 $.each(coordinates, $.proxy(function(index, value) { 11004 if (coordinate > value - pull && coordinate < value + pull) { 11005 position = index; 11006 } else if (this.op(coordinate, '<', value) 11007 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 11008 position = direction === 'left' ? index + 1 : index; 11009 } 11010 return position === -1; 11011 }, this)); 11012 } 11013 11014 if (!this.settings.loop) { 11015 // non loop boundries 11016 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 11017 position = coordinate = this.minimum(); 11018 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 11019 position = coordinate = this.maximum(); 11020 } 11021 } 11022 11023 return position; 11024 }; 11025 11026 /** 11027 * Animates the stage. 11028 * @todo #270 11029 * @public 11030 * @param {Number} coordinate - The coordinate in pixels. 11031 */ 11032 Owl.prototype.animate = function(coordinate) { 11033 var animate = this.speed() > 0; 11034 11035 this.is('animating') && this.onTransitionEnd(); 11036 11037 if (animate) { 11038 this.enter('animating'); 11039 this.trigger('translate'); 11040 } 11041 11042 if ($.support.transform3d && $.support.transition) { 11043 this.$stage.css({ 11044 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 11045 transition: (this.speed() / 1000) + 's' 11046 }); 11047 } else if (animate) { 11048 this.$stage.animate({ 11049 left: coordinate + 'px' 11050 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 11051 } else { 11052 this.$stage.css({ 11053 left: coordinate + 'px' 11054 }); 11055 } 11056 }; 11057 11058 /** 11059 * Checks whether the carousel is in a specific state or not. 11060 * @param {String} state - The state to check. 11061 * @returns {Boolean} - The flag which indicates if the carousel is busy. 11062 */ 11063 Owl.prototype.is = function(state) { 11064 return this._states.current[state] && this._states.current[state] > 0; 11065 }; 11066 11067 /** 11068 * Sets the absolute position of the current item. 11069 * @public 11070 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 11071 * @returns {Number} - The absolute position of the current item. 11072 */ 11073 Owl.prototype.current = function(position) { 11074 if (position === undefined) { 11075 return this._current; 11076 } 11077 11078 if (this._items.length === 0) { 11079 return undefined; 11080 } 11081 11082 position = this.normalize(position); 11083 11084 if (this._current !== position) { 11085 var event = this.trigger('change', { property: { name: 'position', value: position } }); 11086 11087 if (event.data !== undefined) { 11088 position = this.normalize(event.data); 11089 } 11090 11091 this._current = position; 11092 11093 this.invalidate('position'); 11094 11095 this.trigger('changed', { property: { name: 'position', value: this._current } }); 11096 } 11097 11098 return this._current; 11099 }; 11100 11101 /** 11102 * Invalidates the given part of the update routine. 11103 * @param {String} [part] - The part to invalidate. 11104 * @returns {Array.<String>} - The invalidated parts. 11105 */ 11106 Owl.prototype.invalidate = function(part) { 11107 if ($.type(part) === 'string') { 11108 this._invalidated[part] = true; 11109 this.is('valid') && this.leave('valid'); 11110 } 11111 return $.map(this._invalidated, function(v, i) { return i }); 11112 }; 11113 11114 /** 11115 * Resets the absolute position of the current item. 11116 * @public 11117 * @param {Number} position - The absolute position of the new item. 11118 */ 11119 Owl.prototype.reset = function(position) { 11120 position = this.normalize(position); 11121 11122 if (position === undefined) { 11123 return; 11124 } 11125 11126 this._speed = 0; 11127 this._current = position; 11128 11129 this.suppress([ 'translate', 'translated' ]); 11130 11131 this.animate(this.coordinates(position)); 11132 11133 this.release([ 'translate', 'translated' ]); 11134 }; 11135 11136 /** 11137 * Normalizes an absolute or a relative position of an item. 11138 * @public 11139 * @param {Number} position - The absolute or relative position to normalize. 11140 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 11141 * @returns {Number} - The normalized position. 11142 */ 11143 Owl.prototype.normalize = function(position, relative) { 11144 var n = this._items.length, 11145 m = relative ? 0 : this._clones.length; 11146 11147 if (!$.isNumeric(position) || n < 1) { 11148 position = undefined; 11149 } else if (position < 0 || position >= n + m) { 11150 position = ((position - m / 2) % n + n) % n + m / 2; 11151 } 11152 11153 return position; 11154 }; 11155 11156 /** 11157 * Converts an absolute position of an item into a relative one. 11158 * @public 11159 * @param {Number} position - The absolute position to convert. 11160 * @returns {Number} - The converted position. 11161 */ 11162 Owl.prototype.relative = function(position) { 11163 position -= this._clones.length / 2; 11164 return this.normalize(position, true); 11165 }; 11166 11167 /** 11168 * Gets the maximum position for the current item. 11169 * @public 11170 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11171 * @returns {Number} 11172 */ 11173 Owl.prototype.maximum = function(relative) { 11174 var settings = this.settings, 11175 maximum = this._coordinates.length, 11176 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 11177 i = -1, j; 11178 11179 if (settings.loop) { 11180 maximum = this._clones.length / 2 + this._items.length - 1; 11181 } else if (settings.autoWidth || settings.merge) {
11182 // binary search 11183 while (maximum - i > 1) { 11184 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 11185 ? i = j : maximum = j; 11186 } 11187 } else if (settings.center) { 11188 maximum = this._items.length - 1; 11189 } else { 11190 maximum = this._items.length - settings.items; 11191 } 11192 11193 if (relative) { 11194 maximum -= this._clones.length / 2; 11195 } 11196 11197 return Math.max(maximum, 0); 11198 }; 11199 11200 /** 11201 * Gets the minimum position for the current item. 11202 * @public 11203 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11204 * @returns {Number} 11205 */ 11206 Owl.prototype.minimum = function(relative) { 11207 return relative ? 0 : this._clones.length / 2; 11208 }; 11209 11210 /** 11211 * Gets an item at the specified relative position. 11212 * @public 11213 * @param {Number} [position] - The relative position of the item. 11214 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11215 */ 11216 Owl.prototype.items = function(position) { 11217 if (position === undefined) { 11218 return this._items.slice(); 11219 } 11220 11221 position = this.normalize(position, true); 11222 return this._items[position]; 11223 }; 11224 11225 /** 11226 * Gets an item at the specified relative position. 11227 * @public 11228 * @param {Number} [position] - The relative position of the item. 11229 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11230 */ 11231 Owl.prototype.mergers = function(position) { 11232 if (position === undefined) { 11233 return this._mergers.slice(); 11234 } 11235 11236 position = this.normalize(position, true); 11237 return this._mergers[position]; 11238 }; 11239 11240 /** 11241 * Gets the absolute positions of clones for an item. 11242 * @public 11243 * @param {Number} [position] - The relative position of the item. 11244 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 11245 */ 11246 Owl.prototype.clones = function(position) { 11247 var odd = this._clones.length / 2, 11248 even = odd + this._items.length, 11249 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 11250 11251 if (position === undefined) { 11252 return $.map(this._clones, function(v, i) { return map(i) }); 11253 } 11254 11255 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 11256 }; 11257 11258 /** 11259 * Sets the current animation speed. 11260 * @public 11261 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 11262 * @returns {Number} - The current animation speed in milliseconds. 11263 */ 11264 Owl.prototype.speed = function(speed) { 11265 if (speed !== undefined) { 11266 this._speed = speed; 11267 } 11268 11269 return this._speed; 11270 }; 11271 11272 /** 11273 * Gets the coordinate of an item. 11274 * @todo The name of this method is missleanding. 11275 * @public 11276 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 11277 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 11278 */ 11279 Owl.prototype.coordinates = function(position) { 11280 var coordinate = null; 11281 11282 if (position === undefined) { 11283 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 11284 return this.coordinates(index); 11285 }, this)); 11286 } 11287 11288 if (this.settings.center) { 11289 coordinate = this._coordinates[position]; 11290 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 11291 } else { 11292 coordinate = this._coordinates[position - 1] || 0; 11293 } 11294 11295 return coordinate; 11296 }; 11297 11298 /** 11299 * Calculates the speed for a translation. 11300 * @protected 11301 * @param {Number} from - The absolute position of the start item. 11302 * @param {Number} to - The absolute position of the target item. 11303 * @param {Number} [factor=undefined] - The time factor in milliseconds. 11304 * @returns {Number} - The time in milliseconds for the translation. 11305 */ 11306 Owl.prototype.duration = function(from, to, factor) { 11307 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 11308 }; 11309 11310 /** 11311 * Slides to the specified item. 11312 * @public 11313 * @param {Number} position - The position of the item. 11314 * @param {Number} [speed] - The time in milliseconds for the transition. 11315 */ 11316 Owl.prototype.to = function(position, speed) { 11317 var current = this.current(), 11318 revert = null, 11319 distance = position - this.relative(current), 11320 direction = (distance > 0) - (distance < 0), 11321 items = this._items.length, 11322 minimum = this.minimum(), 11323 maximum = this.maximum(); 11324 11325 if (this.settings.loop) { 11326 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 11327 distance += direction * -1 * items; 11328 } 11329 11330 position = current + distance; 11331 revert = ((position - minimum) % items + items) % items + minimum; 11332 11333 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 11334 current = revert - distance; 11335 position = revert; 11336 this.reset(current); 11337 } 11338 } else if (this.settings.rewind) { 11339 maximum += 1; 11340 position = (position % maximum + maximum) % maximum; 11341 } else { 11342 position = Math.max(minimum, Math.min(maximum, position)); 11343 } 11344 11345 this.speed(this.duration(current, position, speed)); 11346 this.current(position); 11347 11348 if (this.$element.is(':visible')) { 11349 this.update(); 11350 } 11351 }; 11352 11353 /** 11354 * Slides to the next item. 11355 * @public 11356 * @param {Number}
vendor: 12,284 bytes, lines 11356-11776
11356 [speed] - The time in milliseconds for the transition. 11357 */ 11358 Owl.prototype.next = function(speed) { 11359 speed = speed || false; 11360 this.to(this.relative(this.current()) + 1, speed); 11361 }; 11362 11363 /** 11364 * Slides to the previous item. 11365 * @public 11366 * @param {Number} [speed] - The time in milliseconds for the transition. 11367 */ 11368 Owl.prototype.prev = function(speed) { 11369 speed = speed || false; 11370 this.to(this.relative(this.current()) - 1, speed); 11371 }; 11372 11373 /** 11374 * Handles the end of an animation. 11375 * @protected 11376 * @param {Event} event - The event arguments. 11377 */ 11378 Owl.prototype.onTransitionEnd = function(event) { 11379 11380 // if css2 animation then event object is undefined 11381 if (event !== undefined) { 11382 event.stopPropagation(); 11383 11384 // Catch only owl-stage transitionEnd event 11385 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 11386 return false; 11387 } 11388 } 11389 11390 this.leave('animating'); 11391 this.trigger('translated'); 11392 }; 11393 11394 /** 11395 * Gets viewport width. 11396 * @protected 11397 * @return {Number} - The width in pixel. 11398 */ 11399 Owl.prototype.viewport = function() { 11400 var width; 11401 if (this.options.responsiveBaseElement !== window) { 11402 width = $(this.options.responsiveBaseElement).width(); 11403 } else if (window.innerWidth) { 11404 width = window.innerWidth; 11405 } else if (document.documentElement && document.documentElement.clientWidth) { 11406 width = document.documentElement.clientWidth; 11407 } else { 11408 throw 'Can not detect viewport width.'; 11409 } 11410 11411 return width; 11412 }; 11413 11414 /** 11415 * Replaces the current content. 11416 * @public 11417 * @param {HTMLElement|jQuery|String} content - The new content. 11418 */ 11419 Owl.prototype.replace = function(content) { 11420 this.$stage.empty(); 11421 this._items = []; 11422 11423 if (content) { 11424 content = (content instanceof jQuery) ? content : $(content); 11425 } 11426 11427 if (this.settings.nestedItemSelector) { 11428 content = content.find('.' + this.settings.nestedItemSelector); 11429 } 11430 11431 content.filter(function() { 11432 return this.nodeType === 1; 11433 }).each($.proxy(function(index, item) { 11434 item = this.prepare(item, index); 11435 this.$stage.append(item); 11436 this._items.push(item); 11437 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 11438 }, this)); 11439 11440 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 11441 11442 this.invalidate('items'); 11443 }; 11444 11445 /** 11446 * Adds an item. 11447 * @todo Use `item` instead of `content` for the event arguments. 11448 * @public 11449 * @param {HTMLElement|jQuery|String} content - The item content to add. 11450 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 11451 */ 11452 Owl.prototype.add = function(content, position) { 11453 var current = this.relative(this._current); 11454 11455 position = position === undefined ? this._items.length : this.normalize(position, true); 11456 content = content instanceof jQuery ? content : $(content); 11457 11458 this.trigger('add', { content: content, position: position }); 11459 11460 content = this.prepare(content, this._items[current].index()); 11461 11462 if (this._items.length === 0 || position === this._items.length) { 11463 this._items.length === 0 && this.$stage.append(content); 11464 this._items.length !== 0 && this._items[position - 1].after(content); 11465 this._items.push(content); 11466 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11467 } else { 11468 this._items[position].before(content); 11469 this._items.splice(position, 0, content); 11470 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11471 } 11472 11473 this._items[current] && this.reset(this._items[current].index()); 11474 11475 this.invalidate('items'); 11476 11477 this.trigger('added', { content: content, position: position }); 11478 }; 11479 11480 /** 11481 * Removes an item by its position. 11482 * @todo Use `item` instead of `content` for the event arguments. 11483 * @public 11484 * @param {Number} position - The relative position of the item to remove. 11485 */ 11486 Owl.prototype.remove = function(position) { 11487 position = this.normalize(position, true); 11488 11489 if (position === undefined) { 11490 return; 11491 } 11492 11493 this.trigger('remove', { content: this._items[position], position: position }); 11494 11495 this._items[position].remove(); 11496 this._items.splice(position, 1); 11497 this._mergers.splice(position, 1); 11498 11499 this.invalidate('items'); 11500 11501 this.trigger('removed', { content: null, position: position }); 11502 }; 11503 11504 /** 11505 * Preloads images with auto width. 11506 * @todo Replace by a more generic approach 11507 * @protected 11508 */ 11509 Owl.prototype.preloadAutoWidthImages = function(images) { 11510 images.each($.proxy(function(i, element) { 11511 this.enter('pre-loading'); 11512 element = $(element); 11513 $(new Image()).one('load', $.proxy(function(e) { 11514 element.attr('src', e.target.src); 11515 element.css('opacity', 1); 11516 this.leave('pre-loading'); 11517 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 11518 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 11519 }, this)); 11520 }; 11521 11522 /** 11523 * Destroys the carousel. 11524 * @public 11525 */ 11526 Owl.prototype.destroy = function() { 11527 11528 this.$element.off('.owl.core'); 11529 this.$stage.off('.owl.core'); 11530 $(document).off('.owl.core'); 11531 11532 if (this.settings.responsive !== false) { 11533 window.clearTimeout(this.resizeTimer); 11534 this.off(window, 'resize', this._handlers.onThrottledResize); 11535 } 11536 11537 for (var i in this._plugins) { 11538 this._plugins[i].destroy(); 11539 } 11540 11541 this.$stage.children('.cloned').remove(); 11542 11543 this.$stage.unwrap(); 11544 this.$stage.children().contents().unwrap(); 11545 this.$stage.children().unwrap(); 11546 11547 this.$element 11548 .removeClass(this.options.refreshClass) 11549 .removeClass(this.options.loadingClass) 11550 .removeClass(this.options.loadedClass) 11551 .removeClass(this.options.rtlClass) 11552 .removeClass(this.options.dragClass) 11553 .removeClass(this.options.grabClass) 11554 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 11555 .removeData('owl.carousel'); 11556 }; 11557 11558 /** 11559 * Operators to calculate right-to-left and left-to-right. 11560 * @protected 11561 * @param {Number} [a] - The left side operand. 11562 * @param {String} [o] - The operator. 11563 * @param {Number} [b] - The right side operand. 11564 */ 11565 Owl.prototype.op = function(a, o, b) { 11566 var rtl = this.settings.rtl; 11567 switch (o) { 11568 case '<': 11569 return rtl ? a > b : a < b; 11570 case '>': 11571 return rtl ? a < b : a > b; 11572 case '>=': 11573 return rtl ? a <= b : a >= b; 11574 case '<=': 11575 return rtl ? a >= b : a <= b; 11576 default: 11577 break; 11578 } 11579 }; 11580 11581 /** 11582 * Attaches to an internal event. 11583 * @protected 11584 * @param {HTMLElement} element - The event source. 11585 * @param {String} event - The event name. 11586 * @param {Function} listener - The event handler to attach. 11587 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 11588 */ 11589 Owl.prototype.on = function(element, event, listener, capture) { 11590 if (element.addEventListener) { 11591 element.addEventListener(event, listener, capture); 11592 } else if (element.attachEvent) { 11593 element.attachEvent('on' + event, listener); 11594 } 11595 }; 11596 11597 /** 11598 * Detaches from an internal event. 11599 * @protected 11600 * @param {HTMLElement} element - The event source. 11601 * @param {String} event - The event name. 11602 * @param {Function} listener - The attached event handler to detach. 11603 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 11604 */ 11605 Owl.prototype.off = function(element, event, listener, capture) { 11606 if (element.removeEventListener) { 11607 element.removeEventListener(event, listener, capture); 11608 } else if (element.detachEvent) { 11609 element.detachEvent('on' + event, listener); 11610 } 11611 }; 11612 11613 /** 11614 * Triggers a public event. 11615 * @todo Remove `status`, `relatedTarget` should be used instead. 11616 * @protected 11617 * @param {String} name - The event name. 11618 * @param {*} [data=null] - The event data. 11619 * @param {String} [namespace=carousel] - The event namespace. 11620 * @param {String} [state] - The state which is associated with the event. 11621 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 11622 * @returns {Event} - The event arguments. 11623 */ 11624 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 11625 var status = { 11626 item: { count: this._items.length, index: this.current() } 11627 }, handler = $.camelCase( 11628 $.grep([ 'on', name, namespace ], function(v) { return v }) 11629 .join('-').toLowerCase() 11630 ), event = $.Event( 11631 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 11632 $.extend({ relatedTarget: this }, status, data) 11633 ); 11634 11635 if (!this._supress[name]) { 11636 $.each(this._plugins, function(name, plugin) { 11637 if (plugin.onTrigger) { 11638 plugin.onTrigger(event); 11639 } 11640 }); 11641 11642 this.register({ type: Owl.Type.Event, name: name }); 11643 this.$element.trigger(event); 11644 11645 if (this.settings && typeof this.settings[handler] === 'function') { 11646 this.settings[handler].call(this, event); 11647 } 11648 } 11649 11650 return event; 11651 }; 11652 11653 /** 11654 * Enters a state. 11655 * @param name - The state name. 11656 */ 11657 Owl.prototype.enter = function(name) { 11658 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11659 if (this._states.current[name] === undefined) { 11660 this._states.current[name] = 0; 11661 } 11662 11663 this._states.current[name]++; 11664 }, this)); 11665 }; 11666 11667 /** 11668 * Leaves a state. 11669 * @param name - The state name. 11670 */ 11671 Owl.prototype.leave = function(name) { 11672 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11673 this._states.current[name]--; 11674 }, this)); 11675 }; 11676 11677 /** 11678 * Registers an event or state. 11679 * @public 11680 * @param {Object} object - The event or state to register. 11681 */ 11682 Owl.prototype.register = function(object) { 11683 if (object.type === Owl.Type.Event) { 11684 if (!$.event.special[object.name]) { 11685 $.event.special[object.name] = {}; 11686 } 11687 11688 if (!$.event.special[object.name].owl) { 11689 var _default = $.event.special[object.name]._default; 11690 $.event.special[object.name]._default = function(e) { 11691 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 11692 return _default.apply(this, arguments); 11693 } 11694 return e.namespace && e.namespace.indexOf('owl') > -1; 11695 }; 11696 $.event.special[object.name].owl = true; 11697 } 11698 } else if (object.type === Owl.Type.State) { 11699 if (!this._states.tags[object.name]) { 11700 this._states.tags[object.name] = object.tags; 11701 } else { 11702 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 11703 } 11704 11705 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 11706 return $.inArray(tag, this._states.tags[object.name]) === i; 11707 }, this)); 11708 } 11709 }; 11710 11711 /** 11712 * Suppresses events. 11713 * @protected 11714 * @param {Array.<String>} events - The events to suppress. 11715 */ 11716 Owl.prototype.suppress = function(events) { 11717 $.each(events, $.proxy(function(index, event) { 11718 this._supress[event] = true; 11719 }, this)); 11720 }; 11721 11722 /** 11723 * Releases suppressed events. 11724 * @protected 11725 * @param {Array.<String>} events - The events to release. 11726 */ 11727 Owl.prototype.release = function(events) { 11728 $.each(events, $.proxy(function(index, event) { 11729 delete this._supress[event]; 11730 }, this)); 11731 }; 11732 11733 /** 11734 * Gets unified pointer coordinates from event. 11735 * @todo #261 11736 * @protected 11737 * @param {Event} - The `mousedown` or `touchstart` event. 11738 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 11739 */ 11740 Owl.prototype.pointer = function(event) { 11741 var result = { x: null, y: null }; 11742 11743 event = event.originalEvent || event || window.event; 11744 11745 event = event.touches && event.touches.length ? 11746 event.touches[0] : event.changedTouches && event.changedTouches.length ? 11747 event.changedTouches[0] : event; 11748 11749 if (event.pageX) { 11750 result.x = event.pageX; 11751 result.y = event.pageY; 11752 } else { 11753 result.x = event.clientX; 11754 result.y = event.clientY; 11755 } 11756 11757 return result; 11758 }; 11759 11760 /** 11761 * Gets the difference of two vectors. 11762 * @todo #261 11763 * @protected 11764 * @param {Object} - The first vector. 11765 * @param {Object} - The second vector. 11766 * @returns {Object} - The difference. 11767 */ 11768 Owl.prototype.difference = function(first, second) { 11769 return { 11770 x: first.x - second.x, 11771 y: first.y - second.y 11772 }; 11773 }; 11774 11775 /** 11776 * The jQuery Plugin for the Owl Carousel
vendor: 32,236 bytes, lines 11777-13059
11777 * @todo Navigation plugin `next` and `prev` 11778 * @public 11779 */ 11780 $.fn.owlCarousel = function(option) { 11781 var args = Array.prototype.slice.call(arguments, 1); 11782 11783 return this.each(function() { 11784 var $this = $(this), 11785 data = $this.data('owl.carousel'); 11786 11787 if (!data) { 11788 data = new Owl(this, typeof option == 'object' && option); 11789 $this.data('owl.carousel', data); 11790 11791 $.each([ 11792 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 11793 ], function(i, event) { 11794 data.register({ type: Owl.Type.Event, name: event }); 11795 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 11796 if (e.namespace && e.relatedTarget !== this) { 11797 this.suppress([ event ]); 11798 data[event].apply(this, [].slice.call(arguments, 1)); 11799 this.release([ event ]); 11800 } 11801 }, data)); 11802 }); 11803 } 11804 11805 if (typeof option == 'string' && option.charAt(0) !== '_') { 11806 data[option].apply(data, args); 11807 } 11808 }); 11809 }; 11810 11811 /** 11812 * The constructor for the jQuery Plugin 11813 * @public 11814 */ 11815 $.fn.owlCarousel.Constructor = Owl; 11816 11817})(window.Zepto || window.jQuery, window, document); 11818 11819/** 11820 * AutoRefresh Plugin 11821 * @version 2.0.0-beta.3 11822 * @author Artus Kolanowski 11823 * @license The MIT License (MIT) 11824 */ 11825;(function($, window, document, undefined) { 11826 11827 /** 11828 * Creates the auto refresh plugin. 11829 * @class The Auto Refresh Plugin 11830 * @param {Owl} carousel - The Owl Carousel 11831 */ 11832 var AutoRefresh = function(carousel) { 11833 /** 11834 * Reference to the core. 11835 * @protected 11836 * @type {Owl} 11837 */ 11838 this._core = carousel; 11839 11840 /** 11841 * Refresh interval. 11842 * @protected 11843 * @type {number} 11844 */ 11845 this._interval = null; 11846 11847 /** 11848 * Whether the element is currently visible or not. 11849 * @protected 11850 * @type {Boolean} 11851 */ 11852 this._visible = null; 11853 11854 /** 11855 * All event handlers. 11856 * @protected 11857 * @type {Object} 11858 */ 11859 this._handlers = { 11860 'initialized.owl.carousel': $.proxy(function(e) { 11861 if (e.namespace && this._core.settings.autoRefresh) { 11862 this.watch(); 11863 } 11864 }, this) 11865 }; 11866 11867 // set default options 11868 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 11869 11870 // register event handlers 11871 this._core.$element.on(this._handlers); 11872 }; 11873 11874 /** 11875 * Default options. 11876 * @public 11877 */ 11878 AutoRefresh.Defaults = { 11879 autoRefresh: true, 11880 autoRefreshInterval: 500 11881 }; 11882 11883 /** 11884 * Watches the element. 11885 */ 11886 AutoRefresh.prototype.watch = function() { 11887 if (this._interval) { 11888 return; 11889 } 11890 11891 this._visible = this._core.$element.is(':visible'); 11892 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 11893 }; 11894 11895 /** 11896 * Refreshes the element. 11897 */ 11898 AutoRefresh.prototype.refresh = function() { 11899 if (this._core.$element.is(':visible') === this._visible) { 11900 return; 11901 } 11902 11903 this._visible = !this._visible; 11904 11905 this._core.$element.toggleClass('owl-hidden', !this._visible); 11906 11907 this._visible && (this._core.invalidate('width') && this._core.refresh()); 11908 }; 11909 11910 /** 11911 * Destroys the plugin. 11912 */ 11913 AutoRefresh.prototype.destroy = function() { 11914 var handler, property; 11915 11916 window.clearInterval(this._interval); 11917 11918 for (handler in this._handlers) { 11919 this._core.$element.off(handler, this._handlers[handler]); 11920 } 11921 for (property in Object.getOwnPropertyNames(this)) { 11922 typeof this[property] != 'function' && (this[property] = null); 11923 } 11924 }; 11925 11926 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 11927 11928})(window.Zepto || window.jQuery, window, document); 11929 11930/** 11931 * Lazy Plugin 11932 * @version 2.0.0-beta.3 11933 * @author Bartosz Wojciechowski 11934 * @license The MIT License (MIT) 11935 */ 11936;(function($, window, document, undefined) { 11937 11938 /** 11939 * Creates the lazy plugin. 11940 * @class The Lazy Plugin 11941 * @param {Owl} carousel - The Owl Carousel 11942 */ 11943 var Lazy = function(carousel) { 11944 11945 /** 11946 * Reference to the core. 11947 * @protected 11948 * @type {Owl} 11949 */ 11950 this._core = carousel; 11951 11952 /** 11953 * Already loaded items. 11954 * @protected 11955 * @type {Array.<jQuery>} 11956 */ 11957 this._loaded = []; 11958 11959 /** 11960 * Event handlers. 11961 * @protected 11962 * @type {Object} 11963 */ 11964 this._handlers = { 11965 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 11966 if (!e.namespace) { 11967 return; 11968 } 11969 11970 if (!this._core.settings || !this._core.settings.lazyLoad) { 11971 return; 11972 } 11973 11974 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 11975 var settings = this._core.settings, 11976 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 11977 i = ((settings.center && n * -1) || 0), 11978 position = ((e.property && e.property.value) || this._core.current()) + i, 11979 clones = this._core.clones().length, 11980 load = $.proxy(function(i, v) { this.load(v) }, this); 11981 11982 while (i++ < n) { 11983 this.load(clones / 2 + this._core.relative(position)); 11984 clones && $.each(this._core.clones(this._core.relative(position)), load); 11985 position++; 11986 } 11987 } 11988 }, this) 11989 }; 11990 11991 // set the default options 11992 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 11993 11994 // register event handler 11995 this._core.$element.on(this._handlers); 11996 } 11997 11998 /** 11999 * Default options. 12000 * @public 12001 */ 12002 Lazy.Defaults = { 12003 lazyLoad: false 12004 } 12005 12006 /** 12007 * Loads all resources of an item at the specified position. 12008 * @param {Number} position - The absolute position of the item. 12009 * @protected 12010 */ 12011 Lazy.prototype.load = function(position) { 12012 var $item = this._core.$stage.children().eq(position), 12013 $elements = $item && $item.find('.owl-lazy'); 12014 12015 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 12016 return; 12017 } 12018 12019 $elements.each($.proxy(function(index, element) { 12020 var $element = $(element), image, 12021 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 12022 12023 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 12024 12025 if ($element.is('img')) { 12026 $element.one('load.owl.lazy', $.proxy(function() { 12027 $element.css('opacity', 1); 12028 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12029 }, this)).attr('src', url); 12030 } else { 12031 image = new Image(); 12032 image.onload = $.proxy(function() { 12033 $element.css({ 12034 'background-image': 'url(' + url + ')', 12035 'opacity': '1' 12036 }); 12037 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12038 }, this); 12039 image.src = url; 12040 } 12041 }, this)); 12042 12043 this._loaded.push($item.get(0)); 12044 } 12045 12046 /** 12047 * Destroys the plugin. 12048 * @public 12049 */ 12050 Lazy.prototype.destroy = function() { 12051 var handler, property; 12052 12053 for (handler in this.handlers) { 12054 this._core.$element.off(handler, this.handlers[handler]); 12055 } 12056 for (property in Object.getOwnPropertyNames(this)) { 12057 typeof this[property] != 'function' && (this[property] = null); 12058 } 12059 }; 12060 12061 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 12062 12063})(window.Zepto || window.jQuery, window, document); 12064 12065/** 12066 * AutoHeight Plugin 12067 * @version 2.0.0-beta.3 12068 * @author Bartosz Wojciechowski 12069 * @license The MIT License (MIT) 12070 */ 12071;(function($, window, document, undefined) { 12072 12073 /** 12074 * Creates the auto height plugin. 12075 * @class The Auto Height Plugin 12076 * @param {Owl} carousel - The Owl Carousel 12077 */ 12078 var AutoHeight = function(carousel) { 12079 /** 12080 * Reference to the core. 12081 * @protected 12082 * @type {Owl} 12083 */ 12084 this._core = carousel; 12085 12086 /** 12087 * All event handlers. 12088 * @protected 12089 * @type {Object} 12090 */ 12091 this._handlers = { 12092 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 12093 if (e.namespace && this._core.settings.autoHeight) { 12094 this.update(); 12095 } 12096 }, this), 12097 'changed.owl.carousel': $.proxy(function(e) { 12098 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 12099 this.update(); 12100 } 12101 }, this), 12102 'loaded.owl.lazy': $.proxy(function(e) { 12103 if (e.namespace && this._core.settings.autoHeight 12104 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 12105 this.update(); 12106 } 12107 }, this) 12108 }; 12109 12110 // set default options 12111 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 12112 12113 // register event handlers 12114 this._core.$element.on(this._handlers); 12115 }; 12116 12117 /** 12118 * Default options. 12119 * @public 12120 */ 12121 AutoHeight.Defaults = { 12122 autoHeight: false, 12123 autoHeightClass: 'owl-height' 12124 }; 12125 12126 /** 12127 * Updates the view. 12128 */ 12129 AutoHeight.prototype.update = function() { 12130 var start = this._core._current, 12131 end = start + this._core.settings.items, 12132 visible = this._core.$stage.children().toArray().slice(start, end); 12133 heights = [], 12134 maxheight = 0; 12135 12136 $.each(visible, function(index, item) { 12137 heights.push($(item).height()); 12138 }); 12139 12140 maxheight = Math.max.apply(null, heights); 12141 12142 this._core.$stage.parent() 12143 .height(maxheight) 12144 .addClass(this._core.settings.autoHeightClass); 12145 }; 12146 12147 AutoHeight.prototype.destroy = function() { 12148 var handler, property; 12149 12150 for (handler in this._handlers) { 12151 this._core.$element.off(handler, this._handlers[handler]); 12152 } 12153 for (property in Object.getOwnPropertyNames(this)) { 12154 typeof this[property] != 'function' && (this[property] = null); 12155 } 12156 }; 12157 12158 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 12159 12160})(window.Zepto || window.jQuery, window, document); 12161 12162/** 12163 * Video Plugin 12164 * @version 2.0.0-beta.3 12165 * @author Bartosz Wojciechowski 12166 * @license The MIT License (MIT) 12167 */ 12168;(function($, window, document, undefined) { 12169 12170 /** 12171 * Creates the video plugin. 12172 * @class The Video Plugin 12173 * @param {Owl} carousel - The Owl Carousel 12174 */ 12175 var Video = function(carousel) { 12176 /** 12177 * Reference to the core. 12178 * @protected 12179 * @type {Owl} 12180 */ 12181 this._core = carousel; 12182 12183 /** 12184 * Cache all video URLs. 12185 * @protected 12186 * @type {Object} 12187 */ 12188 this._videos = {}; 12189 12190 /** 12191 * Current playing item. 12192 * @protected 12193 * @type {jQuery} 12194 */ 12195 this._playing = null; 12196 12197 /** 12198 * All event handlers. 12199 * @todo The cloned content removale is too late 12200 * @protected 12201 * @type {Object} 12202 */ 12203 this._handlers = { 12204 'initialized.owl.carousel': $.proxy(function(e) { 12205 if (e.namespace) { 12206 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 12207 } 12208 }, this), 12209 'resize.owl.carousel': $.proxy(function(e) { 12210 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 12211 e.preventDefault(); 12212 } 12213 }, this), 12214 'refreshed.owl.carousel': $.proxy(function(e) { 12215 if (e.namespace && this._core.is('resizing')) { 12216 this._core.$stage.find('.cloned .owl-video-frame').remove(); 12217 } 12218 }, this), 12219 'changed.owl.carousel': $.proxy(function(e) { 12220 if (e.namespace && e.property.name === 'position' && this._playing) { 12221 this.stop(); 12222 } 12223 }, this), 12224 'prepared.owl.carousel': $.proxy(function(e) { 12225 if (!e.namespace) { 12226 return; 12227 } 12228 12229 var $element = $(e.content).find('.owl-video'); 12230 12231 if ($element.length) { 12232 $element.css('display', 'none'); 12233 this.fetch($element, $(e.content)); 12234 } 12235 }, this) 12236 }; 12237 12238 // set default options 12239 this._core.options = $.extend({}, Video.Defaults, this._core.options); 12240 12241 // register event handlers 12242 this._core.$element.on(this._handlers); 12243 12244 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 12245 this.play(e); 12246 }, this)); 12247 }; 12248 12249 /** 12250 * Default options. 12251 * @public 12252 */ 12253 Video.Defaults = { 12254 video: false, 12255 videoHeight: false, 12256 videoWidth: false 12257 }; 12258 12259 /** 12260 * Gets the video ID and the type (YouTube/Vimeo only). 12261 * @protected 12262 * @param {jQuery} target - The target containing the video data. 12263 * @param {jQuery} item - The item containing the video. 12264 */ 12265 Video.prototype.fetch = function(target, item) { 12266 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 12267 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 12268 width = target.attr('data-width') || this._core.settings.videoWidth, 12269 height = target.attr('data-height') || this._core.settings.videoHeight, 12270 url = target.attr('href'); 12271 12272 if (url) { 12273 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+)?/); 12274 12275 if (id[3].indexOf('youtu') > -1) { 12276 type = 'youtube'; 12277 } else if (id[3].indexOf('vimeo') > -1) { 12278 type = 'vimeo'; 12279 } else { 12280 throw new Error('Video URL not supported.'); 12281 } 12282 id = id[6]; 12283 } else { 12284 throw new Error('Missing video URL.'); 12285 } 12286 12287 this._videos[url] = { 12288 type: type, 12289 id: id, 12290 width: width, 12291 height: height 12292 }; 12293 12294 item.attr('data-video', url); 12295 12296 this.thumbnail(target, this._videos[url]); 12297 }; 12298 12299 /** 12300 * Creates video thumbnail. 12301 * @protected 12302 * @param {jQuery} target - The target containing the video data. 12303 * @param {Object} info - The video info object. 12304 * @see `fetch` 12305 */ 12306 Video.prototype.thumbnail = function(target, video) { 12307 var tnLink, 12308 icon, 12309 path, 12310 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 12311 customTn = target.find('img'), 12312 srcType = 'src', 12313 lazyClass = '', 12314 settings = this._core.settings, 12315 create = function(path) { 12316 icon = '<div class="owl-video-play-icon"></div>'; 12317 12318 if (settings.lazyLoad) { 12319 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 12320 } else { 12321 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 12322 } 12323 target.after(tnLink); 12324 target.after(icon); 12325 }; 12326 12327 // wrap video content into owl-video-wrapper div 12328 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 12329 12330 if (this._core.settings.lazyLoad) { 12331 srcType = 'data-src'; 12332 lazyClass = 'owl-lazy'; 12333 } 12334 12335 // custom thumbnail 12336 if (customTn.length) { 12337 create(customTn.attr(srcType)); 12338 customTn.remove(); 12339 return false; 12340 } 12341 12342 if (video.type === 'youtube') { 12343 path = "http://img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 12344 create(path); 12345 } else if (video.type === 'vimeo') { 12346 $.ajax({ 12347 type: 'GET', 12348 url: 'http://vimeo.com/api/v2/video/' + video.id + '.json', 12349 jsonp: 'callback', 12350 dataType: 'jsonp', 12351 success: function(data) { 12352 path = data[0].thumbnail_large; 12353 create(path); 12354 } 12355 }); 12356 } 12357 }; 12358 12359 /** 12360 * Stops the current video. 12361 * @public 12362 */ 12363 Video.prototype.stop = function() { 12364 this._core.trigger('stop', null, 'video'); 12365 this._playing.find('.owl-video-frame').remove(); 12366 this._playing.removeClass('owl-video-playing'); 12367 this._playing = null; 12368 this._core.leave('playing'); 12369 this._core.trigger('stopped', null, 'video'); 12370 }; 12371 12372 /** 12373 * Starts the current video. 12374 * @public 12375 * @param {Event} event - The event arguments. 12376 */ 12377 Video.prototype.play = function(event) { 12378 var target = $(event.target), 12379 item = target.closest('.' + this._core.settings.itemClass), 12380 video = this._videos[item.attr('data-video')], 12381 width = video.width || '100%', 12382 height = video.height || this._core.$stage.height(), 12383 html; 12384 12385 if (this._playing) { 12386 return; 12387 } 12388 12389 this._core.enter('playing'); 12390 this._core.trigger('play', null, 'video'); 12391 12392 item = this._core.items(this._core.relative(item.index())); 12393 12394 this._core.reset(item.index()); 12395 12396 if (video.type === 'youtube') { 12397 html = '<iframe width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/' + 12398 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 12399 } else if (video.type === 'vimeo') { 12400 html = '<iframe src="http://player.vimeo.com/video/' + video.id + 12401 '?autoplay=1" width="' + width + '" height="' + height + 12402 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 12403 } 12404 12405 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 12406 12407 this._playing = item.addClass('owl-video-playing'); 12408 }; 12409 12410 /** 12411 * Checks whether an video is currently in full screen mode or not. 12412 * @todo Bad style because looks like a readonly method but changes members. 12413 * @protected 12414 * @returns {Boolean} 12415 */ 12416 Video.prototype.isInFullScreen = function() { 12417 var element = document.fullscreenElement || document.mozFullScreenElement || 12418 document.webkitFullscreenElement; 12419 12420 return element && $(element).parent().hasClass('owl-video-frame'); 12421 }; 12422 12423 /** 12424 * Destroys the plugin. 12425 */ 12426 Video.prototype.destroy = function() { 12427 var handler, property; 12428 12429 this._core.$element.off('click.owl.video'); 12430 12431 for (handler in this._handlers) { 12432 this._core.$element.off(handler, this._handlers[handler]); 12433 } 12434 for (property in Object.getOwnPropertyNames(this)) { 12435 typeof this[property] != 'function' && (this[property] = null); 12436 } 12437 }; 12438 12439 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 12440 12441})(window.Zepto || window.jQuery, window, document); 12442 12443/** 12444 * Animate Plugin 12445 * @version 2.0.0-beta.3 12446 * @author Bartosz Wojciechowski 12447 * @license The MIT License (MIT) 12448 */ 12449;(function($, window, document, undefined) { 12450 12451 /** 12452 * Creates the animate plugin. 12453 * @class The Navigation Plugin 12454 * @param {Owl} scope - The Owl Carousel 12455 */ 12456 var Animate = function(scope) { 12457 this.core = scope; 12458 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 12459 this.swapping = true; 12460 this.previous = undefined; 12461 this.next = undefined; 12462 12463 this.handlers = { 12464 'change.owl.carousel': $.proxy(function(e) { 12465 if (e.namespace && e.property.name == 'position') { 12466 this.previous = this.core.current(); 12467 this.next = e.property.value; 12468 } 12469 }, this), 12470 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 12471 if (e.namespace) { 12472 this.swapping = e.type == 'translated'; 12473 } 12474 }, this), 12475 'translate.owl.carousel': $.proxy(function(e) { 12476 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 12477 this.swap(); 12478 } 12479 }, this) 12480 }; 12481 12482 this.core.$element.on(this.handlers); 12483 }; 12484 12485 /** 12486 * Default options. 12487 * @public 12488 */ 12489 Animate.Defaults = { 12490 animateOut: false, 12491 animateIn: false 12492 }; 12493 12494 /** 12495 * Toggles the animation classes whenever an translations starts. 12496 * @protected 12497 * @returns {Boolean|undefined} 12498 */ 12499 Animate.prototype.swap = function() { 12500 12501 if (this.core.settings.items !== 1) { 12502 return; 12503 } 12504 12505 if (!$.support.animation || !$.support.transition) { 12506 return; 12507 } 12508 12509 this.core.speed(0); 12510 12511 var left, 12512 clear = $.proxy(this.clear, this), 12513 previous = this.core.$stage.children().eq(this.previous), 12514 next = this.core.$stage.children().eq(this.next), 12515 incoming = this.core.settings.animateIn, 12516 outgoing = this.core.settings.animateOut; 12517 12518 if (this.core.current() === this.previous) { 12519 return; 12520 } 12521 12522 if (outgoing) { 12523 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 12524 previous.css( { 'left': left + 'px' } ) 12525 .addClass('animated owl-animated-out') 12526 .addClass(outgoing) 12527 .on($.support.animation.end, clear); 12528 } 12529 12530 if (incoming) { 12531 next.addClass('animated owl-animated-in') 12532 .addClass(incoming) 12533 .on($.support.animation.end, clear); 12534 } 12535 }; 12536 12537 Animate.prototype.clear = function(e) { 12538 if ($(e.target).hasClass('animated')) { 12539 $(e.target).css( { 'left': '' } ) 12540 .removeClass('animated owl-animated-out owl-animated-in') 12541 .removeClass(this.core.settings.animateIn) 12542 .removeClass(this.core.settings.animateOut); 12543 this.core.onTransitionEnd(); 12544 } 12545 }; 12546 12547 /** 12548 * Destroys the plugin. 12549 * @public 12550 */ 12551 Animate.prototype.destroy = function() { 12552 var handler, property; 12553 12554 for (handler in this.handlers) { 12555 this.core.$element.off(handler, this.handlers[handler]); 12556 } 12557 for (property in Object.getOwnPropertyNames(this)) { 12558 typeof this[property] != 'function' && (this[property] = null); 12559 } 12560 }; 12561 12562 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 12563 12564})(window.Zepto || window.jQuery, window, document); 12565 12566/** 12567 * Autoplay Plugin 12568 * @version 2.0.0-beta.3 12569 * @author Bartosz Wojciechowski 12570 * @author Artus Kolanowski 12571 * @license The MIT License (MIT) 12572 */ 12573;(function($, window, document, undefined) { 12574 12575 /** 12576 * Creates the autoplay plugin. 12577 * @class The Autoplay Plugin 12578 * @param {Owl} scope - The Owl Carousel 12579 */ 12580 var Autoplay = function(carousel) { 12581 /** 12582 * Reference to the core. 12583 * @protected 12584 * @type {Owl} 12585 */ 12586 this._core = carousel; 12587 12588 /** 12589 * The autoplay interval. 12590 * @type {Number} 12591 */ 12592 this._interval = null; 12593 12594 /** 12595 * Indicates whenever the autoplay is paused. 12596 * @type {Boolean} 12597 */ 12598 this._paused = false; 12599 12600 /** 12601 * All event handlers. 12602 * @protected 12603 * @type {Object} 12604 */ 12605 this._handlers = { 12606 'changed.owl.carousel': $.proxy(function(e) { 12607 if (e.namespace && e.property.name === 'settings') { 12608 if (this._core.settings.autoplay) { 12609 this.play(); 12610 } else { 12611 this.stop(); 12612 } 12613 } 12614 }, this), 12615 'initialized.owl.carousel': $.proxy(function(e) { 12616 if (e.namespace && this._core.settings.autoplay) { 12617 this.play(); 12618 } 12619 }, this), 12620 'play.owl.autoplay': $.proxy(function(e, t, s) { 12621 if (e.namespace) { 12622 this.play(t, s); 12623 } 12624 }, this), 12625 'stop.owl.autoplay': $.proxy(function(e) { 12626 if (e.namespace) { 12627 this.stop(); 12628 } 12629 }, this), 12630 'mouseover.owl.autoplay': $.proxy(function() { 12631 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12632 this.pause(); 12633 } 12634 }, this), 12635 'mouseleave.owl.autoplay': $.proxy(function() { 12636 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12637 this.play(); 12638 } 12639 }, this) 12640 }; 12641 12642 // register event handlers 12643 this._core.$element.on(this._handlers); 12644 12645 // set default options 12646 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 12647 }; 12648 12649 /** 12650 * Default options. 12651 * @public 12652 */ 12653 Autoplay.Defaults = { 12654 autoplay: false, 12655 autoplayTimeout: 5000, 12656 autoplayHoverPause: false, 12657 autoplaySpeed: false 12658 }; 12659 12660 /** 12661 * Starts the autoplay. 12662 * @public 12663 * @param {Number} [timeout] - The interval before the next animation starts. 12664 * @param {Number} [speed] - The animation speed for the animations. 12665 */ 12666 Autoplay.prototype.play = function(timeout, speed) { 12667 this._paused = false; 12668 12669 if (this._core.is('rotating')) { 12670 return; 12671 } 12672 12673 this._core.enter('rotating'); 12674 12675 this._interval = window.setInterval($.proxy(function() { 12676 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 12677 return; 12678 } 12679 this._core.next(speed || this._core.settings.autoplaySpeed); 12680 }, this), timeout || this._core.settings.autoplayTimeout); 12681 }; 12682 12683 /** 12684 * Stops the autoplay. 12685 * @public 12686 */ 12687 Autoplay.prototype.stop = function() { 12688 if (!this._core.is('rotating')) { 12689 return; 12690 } 12691 12692 window.clearInterval(this._interval); 12693 this._core.leave('rotating'); 12694 }; 12695 12696 /** 12697 * Stops the autoplay. 12698 * @public 12699 */ 12700 Autoplay.prototype.pause = function() { 12701 if (!this._core.is('rotating')) { 12702 return; 12703 } 12704 12705 this._paused = true; 12706 }; 12707 12708 /** 12709 * Destroys the plugin. 12710 */ 12711 Autoplay.prototype.destroy = function() { 12712 var handler, property; 12713 12714 this.stop(); 12715 12716 for (handler in this._handlers) { 12717 this._core.$element.off(handler, this._handlers[handler]); 12718 } 12719 for (property in Object.getOwnPropertyNames(this)) { 12720 typeof this[property] != 'function' && (this[property] = null); 12721 } 12722 }; 12723 12724 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 12725 12726})(window.Zepto || window.jQuery, window, document); 12727 12728/** 12729 * Navigation Plugin 12730 * @version 2.0.0-beta.3 12731 * @author Artus Kolanowski 12732 * @license The MIT License (MIT) 12733 */ 12734;(function($, window, document, undefined) { 12735 'use strict'; 12736 12737 /** 12738 * Creates the navigation plugin. 12739 * @class The Navigation Plugin 12740 * @param {Owl} carousel - The Owl Carousel. 12741 */ 12742 var Navigation = function(carousel) { 12743 /** 12744 * Reference to the core. 12745 * @protected 12746 * @type {Owl} 12747 */ 12748 this._core = carousel; 12749 12750 /** 12751 * Indicates whether the plugin is initialized or not. 12752 * @protected 12753 * @type {Boolean} 12754 */ 12755 this._initialized = false; 12756 12757 /** 12758 * The current paging indexes. 12759 * @protected 12760 * @type {Array} 12761 */ 12762 this._pages = []; 12763 12764 /** 12765 * All DOM elements of the user interface. 12766 * @protected 12767 * @type {Object} 12768 */ 12769 this._controls = {}; 12770 12771 /** 12772 * Markup for an indicator. 12773 * @protected 12774 * @type {Array.<String>} 12775 */ 12776 this._templates = []; 12777 12778 /** 12779 * The carousel element. 12780 * @type {jQuery} 12781 */ 12782 this.$element = this._core.$element; 12783 12784 /** 12785 * Overridden methods of the carousel. 12786 * @protected 12787 * @type {Object} 12788 */ 12789 this._overrides = { 12790 next: this._core.next, 12791 prev: this._core.prev, 12792 to: this._core.to 12793 }; 12794 12795 /** 12796 * All event handlers. 12797 * @protected 12798 * @type {Object} 12799 */ 12800 this._handlers = { 12801 'prepared.owl.carousel': $.proxy(function(e) { 12802 if (e.namespace && this._core.settings.dotsData) { 12803 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 12804 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 12805 } 12806 }, this), 12807 'added.owl.carousel': $.proxy(function(e) { 12808 if (e.namespace && this._core.settings.dotsData) { 12809 this._templates.splice(e.position, 0, this._templates.pop()); 12810 } 12811 }, this), 12812 'remove.owl.carousel': $.proxy(function(e) { 12813 if (e.namespace && this._core.settings.dotsData) { 12814 this._templates.splice(e.position, 1); 12815 } 12816 }, this), 12817 'changed.owl.carousel': $.proxy(function(e) { 12818 if (e.namespace && e.property.name == 'position') { 12819 this.draw(); 12820 } 12821 }, this), 12822 'initialized.owl.carousel': $.proxy(function(e) { 12823 if (e.namespace && !this._initialized) { 12824 this._core.trigger('initialize', null, 'navigation'); 12825 this.initialize(); 12826 this.update(); 12827 this.draw(); 12828 this._initialized = true; 12829 this._core.trigger('initialized', null, 'navigation'); 12830 } 12831 }, this), 12832 'refreshed.owl.carousel': $.proxy(function(e) { 12833 if (e.namespace && this._initialized) { 12834 this._core.trigger('refresh', null, 'navigation'); 12835 this.update(); 12836 this.draw(); 12837 this._core.trigger('refreshed', null, 'navigation'); 12838 } 12839 }, this) 12840 }; 12841 12842 // set default options 12843 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 12844 12845 // register event handlers 12846 this.$element.on(this._handlers); 12847 }; 12848 12849 /** 12850 * Default options. 12851 * @public 12852 * @todo Rename `slideBy` to `navBy` 12853 */ 12854 Navigation.Defaults = { 12855 nav: false, 12856 navText: [ 'prev', 'next' ], 12857 navSpeed: false, 12858 navElement: 'div', 12859 navContainer: false, 12860 navContainerClass: 'owl-nav', 12861 navClass: [ 'owl-prev', 'owl-next' ], 12862 slideBy: 1, 12863 dotClass: 'owl-dot', 12864 dotsClass: 'owl-dots', 12865 dots: true, 12866 dotsEach: false, 12867 dotsData: false, 12868 dotsSpeed: false, 12869 dotsContainer: false 12870 }; 12871 12872 /** 12873 * Initializes the layout of the plugin and extends the carousel. 12874 * @protected 12875 */ 12876 Navigation.prototype.initialize = function() { 12877 var override, 12878 settings = this._core.settings; 12879 12880 // create DOM structure for relative navigation 12881 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 12882 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 12883 12884 this._controls.$previous = $('<' + settings.navElement + '>') 12885 .addClass(settings.navClass[0]) 12886 .html(settings.navText[0]) 12887 .prependTo(this._controls.$relative) 12888 .on('click', $.proxy(function(e) { 12889 this.prev(settings.navSpeed); 12890 }, this)); 12891 this._controls.$next = $('<' + settings.navElement + '>') 12892 .addClass(settings.navClass[1]) 12893 .html(settings.navText[1]) 12894 .appendTo(this._controls.$relative) 12895 .on('click', $.proxy(function(e) { 12896 this.next(settings.navSpeed); 12897 }, this)); 12898 12899 // create DOM structure for absolute navigation 12900 if (!settings.dotsData) { 12901 this._templates = [ $('<div>') 12902 .addClass(settings.dotClass) 12903 .append($('<span>')) 12904 .prop('outerHTML') ]; 12905 } 12906 12907 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 12908 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 12909 12910 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 12911 var index = $(e.target).parent().is(this._controls.$absolute) 12912 ? $(e.target).index() : $(e.target).parent().index(); 12913 12914 e.preventDefault(); 12915 12916 this.to(index, settings.dotsSpeed); 12917 }, this)); 12918 12919 // override public methods of the carousel 12920 for (override in this._overrides) { 12921 this._core[override] = $.proxy(this[override], this); 12922 } 12923 }; 12924 12925 /** 12926 * Destroys the plugin. 12927 * @protected 12928 */ 12929 Navigation.prototype.destroy = function() { 12930 var handler, control, property, override; 12931 12932 for (handler in this._handlers) { 12933 this.$element.off(handler, this._handlers[handler]); 12934 } 12935 for (control in this._controls) { 12936 this._controls[control].remove(); 12937 } 12938 for (override in this.overides) { 12939 this._core[override] = this._overrides[override]; 12940 } 12941 for (property in Object.getOwnPropertyNames(this)) { 12942 typeof this[property] != 'function' && (this[property] = null); 12943 } 12944 }; 12945 12946 /** 12947 * Updates the internal state. 12948 * @protected 12949 */ 12950 Navigation.prototype.update = function() { 12951 var i, j, k, 12952 lower = this._core.clones().length / 2, 12953 upper = lower + this._core.items().length, 12954 maximum = this._core.maximum(true), 12955 settings = this._core.settings, 12956 size = settings.center || settings.autoWidth || settings.dotsData 12957 ? 1 : settings.dotsEach || settings.items; 12958 12959 if (settings.slideBy !== 'page') { 12960 settings.slideBy = Math.min(settings.slideBy, settings.items); 12961 } 12962 12963 if (settings.dots || settings.slideBy == 'page') { 12964 this._pages = []; 12965 12966 for (i = lower, j = 0, k = 0; i < upper; i++) { 12967 if (j >= size || j === 0) { 12968 this._pages.push({ 12969 start: Math.min(maximum, i - lower), 12970 end: i - lower + size - 1 12971 }); 12972 if (Math.min(maximum, i - lower) === maximum) { 12973 break; 12974 } 12975 j = 0, ++k; 12976 } 12977 j += this._core.mergers(this._core.relative(i)); 12978 } 12979 } 12980 }; 12981 12982 /** 12983 * Draws the user interface. 12984 * @todo The option `dotsData` wont work. 12985 * @protected 12986 */ 12987 Navigation.prototype.draw = function() { 12988 var difference, 12989 settings = this._core.settings, 12990 disabled = this._core.items().length <= settings.items, 12991 index = this._core.relative(this._core.current()), 12992 loop = settings.loop || settings.rewind; 12993 12994 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 12995 12996 if (settings.nav) { 12997 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 12998 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 12999 } 13000 13001 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 13002 13003 if (settings.dots) { 13004 difference = this._pages.length - this._controls.$absolute.children().length; 13005 13006 if (settings.dotsData && difference !== 0) { 13007 this._controls.$absolute.html(this._templates.join('')); 13008 } else if (difference > 0) { 13009 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 13010 } else if (difference < 0) { 13011 this._controls.$absolute.children().slice(difference).remove(); 13012 } 13013 13014 this._controls.$absolute.find('.active').removeClass('active'); 13015 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 13016 } 13017 }; 13018 13019 /** 13020 * Extends event data. 13021 * @protected 13022 * @param {Event} event - The event object which gets thrown. 13023 */ 13024 Navigation.prototype.onTrigger = function(event) { 13025 var settings = this._core.settings; 13026 13027 event.page = { 13028 index: $.inArray(this.current(), this._pages), 13029 count: this._pages.length, 13030 size: settings && (settings.center || settings.autoWidth || settings.dotsData 13031 ? 1 : settings.dotsEach || settings.items) 13032 }; 13033 }; 13034 13035 /** 13036 * Gets the current page position of the carousel. 13037 * @protected 13038 * @returns {Number} 13039 */ 13040 Navigation.prototype.current = function() { 13041 var current = this._core.relative(this._core.current()); 13042 return $.grep(this._pages, $.proxy(function(page, index) { 13043 return page.start <= current && page.end >= current; 13044 }, this)).pop(); 13045 }; 13046 13047 /** 13048 * Gets the current succesor/predecessor position. 13049 * @protected 13050 * @returns {Number} 13051 */ 13052 Navigation.prototype.getPosition = function(successor) { 13053 var position, length, 13054 settings = this._core.settings; 13055 13056 if (settings.slideBy == 'page') { 13057 position = $.inArray(this.current(), this._pages); 13058 length = this._pages.length; 13059 successor ? ++position : --position;
vendor: 5,678 bytes, lines 13060-13284
13060 position = this._pages[((position % length) + length) % length].start; 13061 } else { 13062 position = this._core.relative(this._core.current()); 13063 length = this._core.items().length; 13064 successor ? position += settings.slideBy : position -= settings.slideBy; 13065 } 13066 13067 return position; 13068 }; 13069 13070 /** 13071 * Slides to the next item or page. 13072 * @public 13073 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13074 */ 13075 Navigation.prototype.next = function(speed) { 13076 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 13077 }; 13078 13079 /** 13080 * Slides to the previous item or page. 13081 * @public 13082 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13083 */ 13084 Navigation.prototype.prev = function(speed) { 13085 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 13086 }; 13087 13088 /** 13089 * Slides to the specified item or page. 13090 * @public 13091 * @param {Number} position - The position of the item or page. 13092 * @param {Number} [speed] - The time in milliseconds for the transition. 13093 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 13094 */ 13095 Navigation.prototype.to = function(position, speed, standard) { 13096 var length; 13097 13098 if (!standard) { 13099 length = this._pages.length; 13100 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 13101 } else { 13102 $.proxy(this._overrides.to, this._core)(position, speed); 13103 } 13104 }; 13105 13106 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 13107 13108})(window.Zepto || window.jQuery, window, document); 13109 13110/** 13111 * Hash Plugin 13112 * @version 2.0.0-beta.3 13113 * @author Artus Kolanowski 13114 * @license The MIT License (MIT) 13115 */ 13116;(function($, window, document, undefined) { 13117 'use strict'; 13118 13119 /** 13120 * Creates the hash plugin. 13121 * @class The Hash Plugin 13122 * @param {Owl} carousel - The Owl Carousel 13123 */ 13124 var Hash = function(carousel) { 13125 /** 13126 * Reference to the core. 13127 * @protected 13128 * @type {Owl} 13129 */ 13130 this._core = carousel; 13131 13132 /** 13133 * Hash index for the items. 13134 * @protected 13135 * @type {Object} 13136 */ 13137 this._hashes = {}; 13138 13139 /** 13140 * The carousel element. 13141 * @type {jQuery} 13142 */ 13143 this.$element = this._core.$element; 13144 13145 /** 13146 * All event handlers. 13147 * @protected 13148 * @type {Object} 13149 */ 13150 this._handlers = { 13151 /*'initialized.owl.carousel': $.proxy(function(e) { 13152 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 13153 $(window).trigger('hashchange.owl.navigation'); 13154 } 13155 }, this),*/ 13156 'prepared.owl.carousel': $.proxy(function(e) { 13157 if (e.namespace) { 13158 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 13159 13160 if (!hash) { 13161 return; 13162 } 13163 13164 this._hashes[hash] = e.content; 13165 } 13166 }, this), 13167 'changed.owl.carousel': $.proxy(function(e) { 13168 if (e.namespace && e.property.name === 'position') { 13169 var current = this._core.items(this._core.relative(this._core.current())), 13170 hash = $.map(this._hashes, function(item, hash) { 13171 return item === current ? hash : null; 13172 }).join(); 13173 13174 if (!hash || window.location.hash.slice(1) === hash) { 13175 return; 13176 } 13177 13178 window.location.hash = hash; 13179 } 13180 }, this) 13181 }; 13182 13183 // set default options 13184 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 13185 13186 // register the event handlers 13187 this.$element.on(this._handlers); 13188 13189 // register event listener for hash navigation 13190 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 13191 var hash = window.location.hash.substring(1), 13192 items = this._core.$stage.children(), 13193 position = this._hashes[hash] && items.index(this._hashes[hash]); 13194 13195 if (position === undefined || position === this._core.current()) { 13196 return; 13197 } 13198 13199 this._core.to(this._core.relative(position), false, true); 13200 }, this));*/ 13201 }; 13202 13203 /** 13204 * Default options. 13205 * @public 13206 */ 13207 Hash.Defaults = { 13208 URLhashListener: false 13209 }; 13210 13211 /** 13212 * Destroys the plugin. 13213 * @public 13214 */ 13215 Hash.prototype.destroy = function() { 13216 var handler, property; 13217 13218 $(window).off('hashchange.owl.navigation'); 13219 13220 for (handler in this._handlers) { 13221 this._core.$element.off(handler, this._handlers[handler]); 13222 } 13223 for (property in Object.getOwnPropertyNames(this)) { 13224 typeof this[property] != 'function' && (this[property] = null); 13225 } 13226 }; 13227 13228 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 13229 13230})(window.Zepto || window.jQuery, window, document); 13231 13232/** 13233 * Support Plugin 13234 * 13235 * @version 2.0.0-beta.3 13236 * @author Vivid Planet Software GmbH 13237 * @author Artus Kolanowski 13238 * @license The MIT License (MIT) 13239 */ 13240;(function($, window, document, undefined) { 13241 13242 var style = $('<support>').get(0).style, 13243 prefixes = 'Webkit Moz O ms'.split(' '), 13244 events = { 13245 transition: { 13246 end: { 13247 WebkitTransition: 'webkitTransitionEnd', 13248 MozTransition: 'transitionend', 13249 OTransition: 'oTransitionEnd', 13250 transition: 'transitionend' 13251 } 13252 }, 13253 animation: { 13254 end: { 13255 WebkitAnimation: 'webkitAnimationEnd', 13256 MozAnimation: 'animationend', 13257 OAnimation: 'oAnimationEnd', 13258 animation: 'animationend' 13259 } 13260 } 13261 }, 13262 tests = { 13263 csstransforms: function() { 13264 return !!test('transform'); 13265 }, 13266 csstransforms3d: function() { 13267 return !!test('perspective'); 13268 }, 13269 csstransitions: function() { 13270 return !!test('transition'); 13271 }, 13272 cssanimations: function() { 13273 return !!test('animation'); 13274 } 13275 }; 13276 13277 function test(property, prefixed) { 13278 var result = false, 13279 upper = property.charAt(0).toUpperCase() + property.slice(1); 13280 13281 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 13282 if (style[property] !== undefined) { 13283 result = prefixed ? property : true; 13284 return false;
13285 } 13286 }); 13287 13288 return result; 13289 } 13290 13291 function prefixed(property) { 13292 return test(property, true); 13293 } 13294 13295 if (tests.csstransitions()) { 13296 /* jshint -W053 */ 13297 $.support.transition = new String(prefixed('transition')) 13298 $.support.transition.end = events.transition.end[ $.support.transition ]; 13299 } 13300 13301 if (tests.cssanimations()) { 13302 /* jshint -W053 */ 13303 $.support.animation = new String(prefixed('animation')) 13304 $.support.animation.end = events.animation.end[ $.support.animation ]; 13305 } 13306 13307 if (tests.csstransforms()) { 13308 /* jshint -W053 */ 13309 $.support.transform = new String(prefixed('transform')); 13310 $.support.transform3d = tests.csstransforms3d(); 13311 } 13312 13313})(window.Zepto || window.jQuery, window, document); 13314 13315(function(window, document, undefined) { 13316 13317 /** 13318 * Find the absolute position of an element 13319 */ 13320 var absPos = function(element) { 13321 var offsetLeft, offsetTop; 13322 offsetLeft = offsetTop = 0; 13323 if (element.offsetParent) { 13324 do { 13325 offsetLeft += element.offsetLeft; 13326 offsetTop += element.offsetTop; 13327 } while (element = element.offsetParent); 13328 } 13329 return [offsetLeft, offsetTop]; 13330 }; 13331 13332 /** 13333 * @constructor Progress Circle class 13334 * @param params.canvas Canvas on which the circles will be drawn. 13335 * @param params.minRadius Inner radius of the innermost circle, in px. 13336 * @param params.arcWidth Width of each circle(to be more accurate, ring). 13337 * @param params.gapWidth Space between each circle. 13338 * @param params.centerX X coordinate of the center of circles. 13339 * @param params.centerY Y coordinate of the center of circles. 13340 * @param params.infoLineBaseAngle Base angle of the info line. 13341 * @param params.infoLineAngleInterval Angles between the info lines. 13342 */ 13343 var ProgressCircle = function(params) { 13344 this.canvas = params.canvas; 13345 this.minRadius = params.minRadius || 15; 13346 this.arcWidth = params.arcWidth || 5; 13347 this.gapWidth = params.gapWidth || 3; 13348 this.centerX = params.centerX || this.canvas.width / 2; 13349 this.centerY = params.centerY || this.canvas.height / 2;
13350 this.infoLineLength = params.infoLineLength || 60; 13351 this.horizLineLength = params.horizLineLength || 10; 13352 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 13353 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 13354 13355 this.context = this.canvas.getContext('2d'); 13356 13357 this.width = this.canvas.width; 13358 this.height = this.canvas.height; 13359 13360 this.circles = []; 13361 this.runningCount = 0; 13362 }; 13363 13364 ProgressCircle.prototype = { 13365 constructor: ProgressCircle, 13366 13367 /** 13368 * @method Adds an progress monitor entry. 13369 * @param params.fillColor Color to fill in the circle. 13370 * @param params.outlineColor Color to outline the circle. 13371 * @param params.progressListener Callback function to fetch the progress. 13372 * @param params.infoListener Callback function to fetch the info. 13373 * @returns this 13374 */ 13375 addEntry: function(params) { 13376 this.circles.push(new Circle({ 13377 canvas: this.canvas, 13378 context: this.context, 13379 centerX: this.centerX, 13380 centerY: this.centerY, 13381 innerRadius: this.minRadius + this.circles.length * 13382 (this.gapWidth + this.arcWidth), 13383 arcWidth: this.arcWidth,
13384 infoLineLength: this.infoLineLength, 13385 horizLineLength: this.horizLineLength, 13386 13387 id: this.circles.length, 13388 fillColor: params.fillColor, 13389 outlineColor: params.outlineColor, 13390 progressListener: params.progressListener, 13391 infoListener: params.infoListener, 13392 infoLineAngle: this.infoLineBaseAngle + 13393 this.circles.length * this.infoLineAngleInterval, 13394 })); 13395 13396 return this; 13397 }, 13398 13399 /** 13400 * @method Starts the monitor and updates with the given interval. 13401 * @param interval Interval between updates, in millisecond. 13402 * @returns this 13403 */ 13404 start: function(interval) { 13405 var self = this; 13406 this.timer = setInterval(function() { 13407 self._update(); 13408 }, interval || 33); 13409 13410 return this; 13411 }, 13412 13413 /** 13414 * @method Stop the animation. 13415 */ 13416 stop: function() { 13417 clearTimeout(this.timer); 13418 }, 13419 13420 /** 13421 * @private 13422 * @method Call update on each circle and redraw them. 13423 * @returns this 13424 */ 13425 _update: function() { 13426 this._clear(); 13427 this.circles.forEach(function(circle, idx, array) { 13428 circle.update(); 13429 }); 13430 13431 return this; 13432 }, 13433 13434 /** 13435 * @private 13436 * @method Clear the canvas. 13437 * @returns this 13438 */ 13439 _clear: function() { 13440 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 13441 13442 return this; 13443 }, 13444 13445 }; 13446 13447 /** 13448 * @private 13449 * @class Individual progress circle. 13450 * @param params.canvas Canvas on which the circle will be drawn. 13451 * @param params.context Context of the canvas. 13452 * @param params.innerRadius Inner radius of the circle, in px. 13453 * @param params.arcWidth Width of each arc(circle). 13454 * @param params.gapWidth Distance between each arc. 13455 * @param params.centerX X coordinate of the center of circles. 13456 * @param params.centerY Y coordinate of the center of circles. 13457 * @param params.fillColor Color to fill in the circle. 13458 * @param params.outlineColor Color to outline the circle. 13459 * @param params.progressListener Callback function to fetch the progress. 13460 * @param params.infoListener Callback function to fetch the info. 13461 * @param params.infoLineAngle Angle of info line. 13462 */ 13463 var Circle = function(params) { 13464 this.id = params.id; 13465 this.canvas = params.canvas; 13466 this.context = params.context; 13467 this.centerX = params.centerX; 13468 this.centerY = params.centerY; 13469 this.arcWidth = params.arcWidth; 13470 this.innerRadius = params.innerRadius || 0; 13471 this.fillColor = params.fillColor || '#fff'; 13472 this.outlineColor = params.outlineColor || this.fillColor; 13473 this.progressListener = params.progressListener;
13474 this.infoLineLength = params.infoLineLength || 250; 13475 this.horizLineLength = params.horizLineLength || 50; 13476 this.infoListener = params.infoListener; 13477 this.infoLineAngle = params.infoLineAngle; 13478 13479 this.outerRadius = this.innerRadius + this.arcWidth; 13480 13481 // If the info listener is not registered, then don't calculate 13482 // the related coordinates 13483 if (!this.infoListener) return; 13484 13485 // calculate the info-line turning points 13486 var angle = this.infoLineAngle, 13487 arcDistance = (this.innerRadius + this.outerRadius) / 2, 13488 13489 sinA = Math.sin(angle), 13490 cosA = Math.cos(angle); 13491 13492 this.infoLineStartX = this.centerX + sinA * arcDistance; 13493 this.infoLineStartY = this.centerY - cosA * arcDistance; 13494 13495 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 13496 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 13497 13498 this.infoLineEndX = this.infoLineMidX + 13499 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 13500 this.infoLineEndY = this.infoLineMidY; 13501 13502 var infoText = document.createElement('div'), 13503 style = infoText.style; 13504 13505 style.color = this.fillColor; 13506 style.position = 'absolute'; 13507 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 13508 // style.top will be calculated in the `drawInfo` method. Since 13509 // user may want to change the size of the font, so the top offset 13510 // must be updated in each loop. 13511 infoText.className = 'ProgressCircleInfo'; // For css styling 13512 infoText.id = 'progress_circle_info_' + this.id; 13513 document.body.appendChild(infoText); 13514 this.infoText = infoText; 13515 }; 13516 13517 Circle.prototype = { 13518 constructor: Circle, 13519 13520 update: function() { 13521 this.progress = this.progressListener(); 13522 this._draw(); 13523 13524 if (this.infoListener) { 13525 this.info = this.infoListener(); 13526 this._drawInfo(); 13527 } 13528 }, 13529 13530 /** 13531 * @private 13532 * @method Draw the circle on the canvas. 13533 * @returns this 13534 */ 13535 _draw: function() { 13536 var ctx = this.context, 13537 13538 ANGLE_OFFSET = -Math.PI / 2, 13539 13540 startAngle = 0 + ANGLE_OFFSET, 13541 endAngle= startAngle + this.progress * Math.PI * 2, 13542 13543 x = this.centerX, 13544 y = this.centerY, 13545 13546 innerRadius = this.innerRadius - this.arcWidth - 1, 13547 outerRadius = this.outerRadius - this.arcWidth - 1; 13548 13549 ctx.fillStyle = this.fillColor; 13550 ctx.strokeStyle = this.outlineColor; 13551 13552 ctx.beginPath(); 13553 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 13554 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 13555 ctx.closePath(); 13556 ctx.stroke(); 13557 ctx.fill(); 13558 13559 return this; 13560 }, 13561 13562 /** 13563 * @private 13564 * @method Draw the info lines and info text. 13565 * @returns this 13566 */ 13567 _drawInfo: function() { 13568 13569 var pointList, lineHeight; 13570 13571 pointList = [ 13572 [this.infoLineStartX, this.infoLineStartY], 13573 [this.infoLineMidX, this.infoLineMidY], 13574 [this.infoLineEndX, this.infoLineEndY], 13575 ]; 13576 this._drawSegments(pointList, false); 13577 13578 this.infoText.innerHTML = this.info; 13579 13580 lineHeight = this.infoText.offsetHeight; 13581 this.infoText.style.top = this.infoLineEndY + 13582 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 13583 13584 return this; 13585 }, 13586 13587 /** 13588 * @private 13589 * @method Helper function to draw the segments 13590 * @param pointList An array of points in the form of [x, y]. 13591 * @param close Whether to connect the first and last point. 13592 */ 13593 _drawSegments: function(pointList, close) { 13594 var ctx = this.context; 13595 13596 ctx.beginPath(); 13597 ctx.moveTo(pointList[0][0], pointList[0][1]); 13598 for (var i = 1; i < pointList.length; ++i) { 13599 ctx.lineTo(pointList[i][0], pointList[i][1]); 13600 } 13601 13602 if (close) { 13603 ctx.closePath(); 13604 } 13605 ctx.stroke(); 13606 }, 13607 }; 13608 13609 window.ProgressCircle = ProgressCircle; 13610 13611})(window, document); 13612 13613 13614 13615 13616/* ========================================================= 13617 * jquery.vc_chart.js v1.0 13618 * ========================================================= 13619 * Copyright 2013 Wpbakery 13620 * 13621 * Jquery chart plugin for the Visual Composer.
13622 * ========================================================= */ 13623(function($){ 13624 /** 13625 * Pie chart animated. 13626 * @param element - DOM element 13627 * @param options - settings object. 13628 * @constructor 13629 */ 13630 var VcChart = function(element, options) { 13631 this.el = element; 13632 this.$el = $(this.el); 13633 this.options = $.extend({ 13634 color: 'wpb_button', 13635 units: '', 13636 width: '', 13637 label_selector: '.vc_pie_chart_value', 13638 back_selector: '.vc_pie_chart_back', 13639 responsive: true 13640 }, options); 13641 this.init(); 13642 }; 13643 VcChart.prototype = { 13644 constructor: VcChart, 13645 _progress_v: 0, 13646 animated: false, 13647 colors: { 13648 'wpb_button': 'rgba(247, 247, 247, 1)', 13649 'btn-primary': 'rgba(0, 136, 204, 1)', 13650 'btn-info': 'rgba(88, 185, 218, 1)', 13651 'btn-success': 'rgba(106, 177, 101, 1)', 13652 'btn-warning': 'rgba(255, 153, 0, 1)', 13653 'btn-danger': 'rgba(255, 103, 91, 1)', 13654 'btn-inverse': 'rgba(85, 85, 85, 1)' 13655 }, 13656 init: function() { 13657 this.setupColor(); 13658 this.value = this.$el.data('pie-value')/100; 13659 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 13660 this.$wrapper = $('.vc_pie_wrapper', this.$el); 13661 this.$label = $(this.options.label_selector, this.$el); 13662 this.$back = $(this.options.back_selector, this.$el); 13663 this.$canvas = this.$el.find('canvas'); 13664 this.arcWidth = this.$el.data('pie-width') * 2; 13665 this.draw(); 13666 this.setWayPoint(); 13667 if(this.options.responsive === true) this.setResponsive(); 13668 if (UNCODE.isMobile) this._progress_v = this.value; 13669 }, 13670 setupColor: function() { 13671 // if(typeof this.colors[this.options.color] !== 'undefined') { 13672 // this.color = this.colors[this.options.color]; 13673 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 13674 // this.color = this.options.color; 13675 // } else { 13676 // this.color = 'rgba(247, 247, 247, 0.2)'; 13677 // } 13678 if(typeof this.options.color !== 'undefined') { 13679 this.color = this.options.color; 13680 } else this.color = 'rgba(247, 247, 247, 0.2)'; 13681 13682 }, 13683 setResponsive: function() { 13684 var that = this; 13685 if (!UNCODE.isMobile) { 13686 $(window).resize(function(){ 13687 if(that.animated === true) that.circle.stop(); 13688 that.draw(true); 13689 }); 13690 } 13691 }, 13692 draw: function(redraw) { 13693 var w = this.$el.addClass('vc_ready').width() * 2, 13694 border_w = this.arcWidth, 13695 radius; 13696 if(!w) w = this.$el.parents(':visible').first().width()-2; 13697 //w = Math.round(w/100*80); 13698 //if (w < 250) w = 250; 13699 radius = w/2; 13700 this.$wrapper.css({"width" : (w / 2) + "px"}); 13701 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 13702 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 13703 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 13704 this.$el.addClass('vc_ready'); 13705 this.circle = new ProgressCircle({ 13706 canvas: this.$canvas.get(0), 13707 minRadius: radius, 13708 arcWidth: border_w 13709 }); 13710 if(redraw === true && this.animated === true) { 13711 this._progress_v = this.value; 13712 this.circle.addEntry({ 13713 fillColor: this.color, 13714 progressListener: $.proxy(this.setProgress, this) 13715 }).start(); 13716 } 13717 }, 13718 setProgress: function() { 13719 if (this._progress_v >= this.value) { 13720 this.circle.stop(); 13721 this.$label.html(this.label_value + this.options.units); 13722 return this._progress_v; 13723 } 13724 this._progress_v += 0.01; 13725 if (!isNaN(this.label_value)) { 13726 var label_value = this._progress_v/this.value*this.label_value; 13727 var val = Math.round(label_value) + this.options.units; 13728 this.$label.html(val); 13729 } else this.$label.html(this.label_value + this.options.units); 13730 return this._progress_v; 13731 }, 13732 animate: function() { 13733 if(this.animated !== true) { 13734 this.animated = true; 13735 this.circle.addEntry({ 13736 fillColor: this.color, 13737 progressListener: $.proxy(this.setProgress, this) 13738 }).start(5); 13739 } 13740 }, 13741 setWayPoint: function() { 13742 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 13743 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 13744 } else { 13745 this.animate(); 13746 } 13747 } 13748 }; 13749 /** 13750 * jQuery plugin 13751 * @param option - object with settings 13752 * @return {*} 13753 */ 13754 $.fn.vcChat = function(option, value) { 13755 return this.each(function () { 13756 var $this = $(this), 13757 data = $this.data('vc_chart'), 13758 options = typeof option === 'object' ? option : { 13759 color: $this.data('pie-color'), 13760 units: $this.data('pie-units') 13761 }; 13762 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 13763 if (typeof option == 'string') data[option](value); 13764 }); 13765 }; 13766 /** 13767 * Allows users to rewrite function inside theme. 13768 */ 13769 if ( typeof window['vc_pieChart'] !== 'function' ) { 13770 window.vc_pieChart = function() { 13771 $('.vc_pie_chart:visible').vcChat(); 13772 } 13773 } 13774 $(document).ready(function(){ 13775 !window.vc_iframe && vc_pieChart(); 13776 }); 13777 13778})(window.jQuery); 13779 13780 13781/* Progress bar 13782 ---------------------------------------------------------- */ 13783function uncode_progress_bar() {    13784 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 13785 if (!UNCODE.isMobile) { 13786 new Waypoint({ 13787 element: val, 13788 handler: function() { 13789 var element = jQuery(this.element); 13790 element.find('.vc_single_bar').each(function(index) {          13791 var $this = jQuery(this), 13792             bar = $this.find('.vc_bar'), 13793             val = bar.data('percentage-value');          13794 setTimeout(function() {            13795 bar.css({ 13796 "width": val + '%' 13797 });          13798 }, index * 200);        13799 }); 13800 }, 13801 offset: '80%' 13802 }); 13803 } else { 13804 var element = jQuery(val); 13805 element.find('.vc_single_bar').each(function(index) {          13806 var $this = jQuery(this), 13807             bar = $this.find('.vc_bar'), 13808             val = bar.data('percentage-value');          13809 setTimeout(function() {            13810 bar.css({ 13811 "width": val + '%' 13812 });          13813 }, index * 200);        13814 }); 13815 } 13816 }); 13817}; 13818uncode_progress_bar(); 13819 13820/*! 13821 * jquery.counterup.js 1.0 13822 * 13823 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 13824 * Released under the GPL v2 License 13825 * 13826 * Date: Nov 26, 2013 13827 */ 13828(function($) { 13829 "use strict"; 13830 $.fn.counterUp = function(options) { 13831 // Defaults 13832 var settings = $.extend({ 13833 'time': 400, 13834 'delay': 10 13835 }, options); 13836 return this.each(function() { 13837 // Store the object 13838 var $this = $(this); 13839 var $settings = settings; 13840 var counterUpper = function() { 13841 var nums = []; 13842 var divisions = $settings.time / $settings.delay; 13843 var numReal = $this.text(), 13844 num = numReal; 13845 var isComma = /[0-9]+,[0-9]+/.test(num); 13846 num = num.replace(/,/g, ''); 13847 var isInt = /^[0-9]+$/.test(num); 13848 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 13849 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 13850 // Generate list of incremental numbers to display 13851 for (var i = divisions; i >= 1; i--) { 13852 // Preserve as int if input was int 13853 var newNum = parseInt(num / divisions * i); 13854 // Preserve float if input was float 13855 if (isFloat) { 13856 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 13857 } 13858 // Preserve commas if input had commas 13859 if (isComma) { 13860 while (/(\d+)(\d{3})/.test(newNum.toString())) { 13861 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 13862 } 13863 } 13864 nums.unshift(newNum); 13865 } 13866 nums.push(numReal); 13867 $this.data('counterup-nums', nums); 13868 $this.text('0'); 13869 // Updates the number until we're done 13870 var f = function() { 13871 if ($this.data('counterup-nums') != null) { 13872 $this.text($this.data('counterup-nums').shift()); 13873 if ($this.data('counterup-nums').length) { 13874 setTimeout($this.data('counterup-func'), $settings.delay); 13875 } else { 13876 delete $this.data('counterup-nums'); 13877 $this.data('counterup-nums', null); 13878 $this.data('counterup-func', null); 13879 } 13880 } 13881 }; 13882 $this.data('counterup-func', f); 13883 // Start the count up 13884 setTimeout($this.data('counterup-func'), $settings.delay); 13885 }; 13886 // Perform counts when the element gets into view 13887 new Waypoint({ 13888 element: this, 13889 handler: function() { 13890 counterUpper(); 13891 this.destroy(); 13892 }, 13893 offset: '80%' 13894 }); 13895 }); 13896 }; 13897})(jQuery); 13898 13899/*! 13900 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 13901 * Copyright (c) 2014 Edson Hilios 13902 * 13903 * Permission is hereby granted, free of charge, to any person obtaining a copy of 13904 * this software and associated documentation files (the "Software"), to deal in 13905 * the Software without restriction, including without limitation the rights to 13906 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13907 * the Software, and to permit persons to whom the Software is furnished to do so, 13908 * subject to the following conditions: 13909 * 13910 * The above copyright notice and this permission notice shall be included in all 13911 * copies or substantial portions of the Software. 13912 * 13913 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13914 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13915 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13916 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13917 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 13918 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13919 */ 13920!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;
13920if(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])})}}); 13921 13922/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 13923* https://github.com/alexanderdickson/waitForImages 13924* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 13925;(function (factory) { 13926 if (typeof define === 'function' && define.amd) { 13927 // AMD. Register as an anonymous module. 13928 define(['jquery'], factory); 13929 } else if (typeof exports === 'object') { 13930 // CommonJS / nodejs module 13931 module.exports = factory(require('jquery')); 13932 } else { 13933 // Browser globals 13934 factory(jQuery); 13935 } 13936}(function ($) { 13937 // Namespace all events. 13938 var eventNamespace = 'waitForImages'; 13939 13940 // CSS properties which contain references to images. 13941 $.waitForImages = { 13942 hasImageProperties: [ 13943 'backgroundImage', 13944 'listStyleImage', 13945 'borderImage', 13946 'borderCornerImage', 13947 'cursor' 13948 ], 13949 hasImageAttributes: ['srcset'] 13950 }; 13951 13952 // Custom selector to find `img` elements that have a valid `src` 13953 // attribute and have not already loaded. 13954 $.expr[':'].uncached = function (obj) { 13955 // Ensure we are dealing with an `img` element with a valid 13956 // `src` attribute. 13957 if (!$(obj).is('img[src][src!=""]')) { 13958 return false;
13959 } 13960 13961 return !obj.complete; 13962 }; 13963 13964 $.fn.waitForImages = function () { 13965 13966 var allImgsLength = 0; 13967 var allImgsLoaded = 0; 13968 var deferred = $.Deferred(); 13969 13970 var finishedCallback; 13971 var eachCallback; 13972 var waitForAll; 13973 13974 // Handle options object (if passed). 13975 if ($.isPlainObject(arguments[0])) { 13976 13977 waitForAll = arguments[0].waitForAll; 13978 eachCallback = arguments[0].each; 13979 finishedCallback = arguments[0].finished; 13980 13981 } else { 13982 13983 // Handle if using deferred object and only one param was passed in. 13984 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 13985 waitForAll = arguments[0]; 13986 } else { 13987 finishedCallback = arguments[0]; 13988 eachCallback = arguments[1]; 13989 waitForAll = arguments[2]; 13990 } 13991 13992 } 13993 13994 // Handle missing callbacks. 13995 finishedCallback = finishedCallback || $.noop; 13996 eachCallback = eachCallback || $.noop; 13997 13998 // Convert waitForAll to Boolean 13999 waitForAll = !! waitForAll; 14000 14001 // Ensure callbacks are functions. 14002 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 14003 throw new TypeError('An invalid callback was supplied.'); 14004 } 14005 14006 this.each(function () { 14007 // Build a list of all imgs, dependent on what images will 14008 // be considered. 14009 var obj = $(this); 14010 var allImgs = []; 14011 // CSS properties which may contain an image. 14012 var hasImgProperties = $.waitForImages.hasImageProperties || []; 14013 // Element attributes which may contain an image. 14014 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 14015 // To match `url()` references. 14016 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 14017 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 14018 14019 if (waitForAll) { 14020 14021 // Get all elements (including the original), as any one of 14022 // them could have a background image. 14023 obj.find('*').addBack().each(function () { 14024 var element = $(this); 14025 14026 // If an `img` element, add it. But keep iterating in 14027 // case it has a background image too. 14028 if (element.is('img:uncached')) { 14029 allImgs.push({ 14030 src: element.attr('src'), 14031 element: element[0] 14032 }); 14033 } 14034 14035 $.each(hasImgProperties, function (i, property) { 14036 var propertyValue = element.css(property); 14037 var match; 14038 14039 // If it doesn't contain this property, skip. 14040 if (!propertyValue) { 14041 return true; 14042 } 14043 14044 // Get all url() of this element. 14045 while (match = matchUrl.exec(propertyValue)) { 14046 allImgs.push({ 14047 src: match[2], 14048 element: element[0] 14049 }); 14050 } 14051 }); 14052 14053 $.each(hasImageAttributes, function (i, attribute) { 14054 var attributeValue = element.attr(attribute); 14055 var attributeValues; 14056 14057 // If it doesn't contain this property, skip. 14058 if (!attributeValue) { 14059 return true; 14060 } 14061 14062 // Check for multiple comma separated images 14063 attributeValues = attributeValue.split(','); 14064 14065 $.each(attributeValues, function(i, value) { 14066 // Trim value and get string before first 14067 // whitespace (for use with srcset). 14068 value = $.trim(value).split(' ')[0]; 14069 allImgs.push({ 14070 src: value, 14071 element: element[0] 14072 }); 14073 }); 14074 }); 14075 }); 14076 } else { 14077 // For images only, the task is simpler. 14078 obj.find('img:uncached') 14079 .each(function () { 14080 allImgs.push({ 14081 src: this.src, 14082 element: this 14083 }); 14084 }); 14085 } 14086 14087 allImgsLength = allImgs.length; 14088 allImgsLoaded = 0; 14089 14090 // If no images found, don't bother. 14091 if (allImgsLength === 0) { 14092 finishedCallback.call(obj[0]); 14093 deferred.resolveWith(obj[0]); 14094 } 14095 14096 $.each(allImgs, function (i, img) { 14097 14098 var image = new Image(); 14099 var events = 14100 'load.' + eventNamespace + ' error.' + eventNamespace; 14101 14102 // Handle the image loading and error with the same callback. 14103 $(image).one(events, function me (event) { 14104 // If an error occurred with loading the image, set the 14105 // third argument accordingly. 14106 var eachArguments = [ 14107 allImgsLoaded, 14108 allImgsLength,
14109 event.type == 'load' 14110 ]; 14111 allImgsLoaded++; 14112 14113 eachCallback.apply(img.element, eachArguments); 14114 deferred.notifyWith(img.element, eachArguments); 14115 14116 // Unbind the event listeners. I use this in addition to 14117 // `one` as one of those events won't be called (either 14118 // 'load' or 'error' will be called). 14119 $(this).off(events, me); 14120 14121 if (allImgsLoaded == allImgsLength) { 14122 finishedCallback.call(obj[0]); 14123 deferred.resolveWith(obj[0]); 14124 return false; 14125 } 14126 14127 }); 14128 14129 image.src = img.src; 14130 }); 14131 }); 14132 14133 return deferred.promise(); 14134 14135 }; 14136})); 14137 14138/** 14139 * @preserve textfill 14140 * @name jquery.textfill.js 14141 * @author Russ Painter 14142 * @author Yu-Jie Lin 14143 * @author Alexandre Dantas 14144 * @version 0.6.0 14145 * @date 2014-08-19 14146 * @copyright (c) 2014 Alexandre Dantas 14147 * @copyright (c) 2012-2013 Yu-Jie Lin 14148 * @copyright (c) 2009 Russ Painter 14149 * @license MIT License 14150 * @homepage https://github.com/jquery-textfill/jquery-textfill 14151 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 14152 */ 14153; (function($) { 14154 14155 /** 14156 * Resizes an inner element's font so that the 14157 * inner element completely fills the outer element. 14158 * 14159 * @param {Object} options User options that take 14160 * higher precedence when 14161 * merging with the default ones. 14162 * 14163 * @return All outer elements processed 14164 */ 14165 $.fn.textfill = function(options) { 14166 14167 // ______ _______ _______ _______ _ _ _______ _______ 14168 // | \ |______ |______ |_____| | | | | |______ 14169 // |_____/ |______ | | | |_____| |_____ | ______| 14170 // 14171 // Merging user options with the default values 14172 14173 var defaults = { 14174 debug : false, 14175 maxFontPixels : 40, 14176 minFontPixels : 4, 14177 innerTag : 'span', 14178 widthOnly : false, 14179 success : null, // callback when a resizing is done 14180 callback : null, // callback when a resizing is done (deprecated, use success) 14181 fail : null, // callback when a resizing is failed 14182 complete : null, // callback when all is done 14183 explicitWidth : null, 14184 explicitHeight : null, 14185 changeLineHeight : false 14186 }; 14187 14188 var Opts = $.extend(defaults, options); 14189 14190 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 14191 // |______ | | | \ | | | | | | | \ | |______ 14192 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 14193 // 14194 // Predefining the awesomeness 14195 14196 // Output arguments to the Debug console 14197 // if "Debug Mode" is enabled 14198 function _debug() { 14199 if (!Opts.debug 14200 || typeof console == 'undefined' 14201 || typeof console.debug == 'undefined') { 14202 return; 14203 } 14204 console.debug.apply(console, arguments); 14205 } 14206 14207 // Output arguments to the Warning console 14208 function _warn() { 14209 if (typeof console == 'undefined' || 14210 typeof console.warn == 'undefined') { 14211 return; 14212 } 14213 console.warn.apply(console, arguments); 14214 } 14215 14216 // Outputs all information on the current sizing 14217 // of the font. 14218 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14219 14220 function _m(v1, v2) { 14221 14222 var marker = ' / '; 14223 14224 if (v1 > v2) 14225 marker = ' > '; 14226 14227 else if (v1 == v2) 14228 marker = ' = '; 14229 14230 return marker; 14231 } 14232 14233 _debug( 14234 '[TextFill] ' + prefix + ' { ' + 14235 'font-size: ' + ourText.css('font-size') + ',' +
14236 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 14237 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 14238 'minFontPixels: ' + minFontPixels + 'px, ' + 14239 'maxFontPixels: ' + maxFontPixels + 'px }' 14240 ); 14241 } 14242 14243 /** 14244 * Calculates which size the font can get resized, 14245 * according to constrains. 14246 * 14247 * @param {String} prefix Gets shown on the console before 14248 * all the arguments, if debug mode is on. 14249 * @param {Object} ourText The DOM element to resize, 14250 * that contains the text. 14251 * @param {function} func Function called on `ourText` that's 14252 * used to compare with `max`. 14253 * @param {number} max Maximum value, that gets compared with 14254 * `func` called on `ourText`. 14255 * @param {number} minFontPixels Minimum value the font can 14256 * get resized to (in pixels). 14257 * @param {number} maxFontPixels Maximum value the font can 14258 * get resized to (in pixels). 14259 * 14260 * @return Size (in pixels) that the font can be resized. 14261 */ 14262 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14263 14264 _debug_sizing( 14265 prefix, ourText, 14266 maxHeight, maxWidth, 14267 minFontPixels, maxFontPixels 14268 ); 14269 14270 // The kernel of the whole plugin, take most attention 14271 // on this part. 14272 // 14273 // This is a loop that keeps increasing the `font-size` 14274 // until it fits the parent element. 14275 // 14276 // - Start from the minimal allowed value (`minFontPixels`) 14277 // - Guesses an average font size (in pixels) for the font, 14278 // - Resizes the text and sees if its size is within the 14279 // boundaries (`minFontPixels` and `maxFontPixels`). 14280 // - If so, keep guessing until we break. 14281 // - If not, return the last calculated size. 14282 // 14283 // I understand this is not optimized and we should 14284 // consider implementing something akin to 14285 // Daniel Hoffmann's answer here: 14286 // 14287 // http://stackoverflow.com/a/17433451/1094964 14288 // 14289 14290 while (minFontPixels < (maxFontPixels - 1)) { 14291 14292 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 14293 ourText.css('font-size', fontSize); 14294 14295 if (func.call(ourText) <= max) { 14296 minFontPixels = fontSize; 14297 14298 if (func.call(ourText) == max) 14299 break; 14300 } 14301 else 14302 maxFontPixels = fontSize; 14303 14304 _debug_sizing( 14305 prefix, ourText, 14306 maxHeight, maxWidth, 14307 minFontPixels, maxFontPixels 14308 ); 14309 } 14310 14311 ourText.css('font-size', maxFontPixels); 14312 14313 if (func.call(ourText) <= max) { 14314 minFontPixels = maxFontPixels; 14315 14316 _debug_sizing( 14317 prefix + '* ', ourText, 14318 maxHeight, maxWidth, 14319 minFontPixels, maxFontPixels 14320 ); 14321 } 14322 return minFontPixels; 14323 } 14324 14325 // _______ _______ _______ ______ _______ 14326 // |______ | |_____| |_____/ | 14327 // ______| | | | | \_ | 14328 // 14329 // Let's get it started (yeah)! 14330 14331 _debug('[TextFill] Start Debug'); 14332 14333 this.each(function() { 14334 14335 // Contains the child element we will resize. 14336 // $(this) means the parent container 14337 var ourText = $(Opts.innerTag + ':visible:first', this); 14338 14339 // Will resize to this dimensions. 14340 // Use explicit dimensions when specified 14341 var maxHeight = Opts.explicitHeight || $(this).height(); 14342 var maxWidth = Opts.explicitWidth || $(this).width(); 14343 14344 var oldFontSize = ourText.css('font-size'); 14345 14346 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 14347 14348 _debug('[TextFill] Inner text: ' + ourText.text()); 14349 _debug('[TextFill] All options: ', Opts); 14350 _debug('[TextFill] Maximum sizes: { ' + 14351 'Height: ' + maxHeight + 'px, ' + 14352 'Width: ' + maxWidth + 'px' + ' }' 14353 ); 14354 14355 var minFontPixels = Opts.minFontPixels; 14356 14357 // Remember, if this `maxFontPixels` is negative, 14358 // the text will resize to as long as the container 14359 // can accomodate 14360 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 14361 maxHeight : 14362 Opts.maxFontPixels); 14363 14364 14365 // Let's start it all! 14366 14367 // 1. Calculate which `font-size` would 14368 // be best for the Height 14369 var fontSizeHeight = undefined; 14370 14371 if (! Opts.widthOnly) 14372 fontSizeHeight = _sizing( 14373 'Height', ourText, 14374 $.fn.height, maxHeight, 14375 maxHeight, maxWidth, 14376 minFontPixels, maxFontPixels 14377 ); 14378 14379 // 2. Calculate which `font-size` would 14380 // be best for the Width 14381 var fontSizeWidth = undefined; 14382 14383 fontSizeWidth = _sizing( 14384 'Width', ourText, 14385 $.fn.width, maxWidth, 14386 maxHeight, maxWidth, 14387 minFontPixels, maxFontPixels 14388 ); 14389 14390 // 3. Actually resize the text! 14391 14392 if (Opts.widthOnly) { 14393 ourText.css({ 14394 'font-size' : fontSizeWidth, 14395 'white-space': 'nowrap' 14396 }); 14397 14398 if (Opts.changeLineHeight) 14399 ourText.parent().css( 14400 'line-height', 14401 (lineHeight * fontSizeWidth + 'px') 14402 ); 14403 } 14404 else { 14405 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 14406 14407 ourText.css('font-size', fontSizeFinal); 14408 14409 if (Opts.changeLineHeight) 14410 ourText.parent().css( 14411 'line-height', 14412 (lineHeight * fontSizeFinal) + 'px' 14413 ); 14414 } 14415 14416 _debug( 14417 '[TextFill] Finished { ' + 14418 'Old font-size: ' + oldFontSize + ', ' + 14419 'New font-size: ' + ourText.css('font-size') + ' }' 14420 ); 14421 14422 // Oops, something wrong happened! 14423 // We weren't supposed to exceed the original size 14424 if ((ourText.width() > maxWidth) ||
14425 (ourText.height() > maxHeight && !Opts.widthOnly)) { 14426 14427 ourText.css('font-size', oldFontSize); 14428 14429 // Failure callback 14430 if (Opts.fail) 14431 Opts.fail(this); 14432 14433 _debug( 14434 '[TextFill] Failure { ' + 14435 'Current Width: ' + ourText.width() + ', ' + 14436 'Maximum Width: ' + maxWidth + ', ' + 14437 'Current Height: ' + ourText.height() + ', ' + 14438 'Maximum Height: ' + maxHeight + ' }' 14439 ); 14440 } 14441 else if (Opts.success) { 14442 Opts.success(this); 14443 } 14444 else if (Opts.callback) { 14445 _warn('callback is deprecated, use success, instead'); 14446 14447 // Success callback 14448 Opts.callback(this); 14449 } 14450 }); 14451 14452 // Complete callback 14453 if (Opts.complete) 14454 Opts.complete(this); 14455 14456 _debug('[TextFill] End Debug'); 14457 return this; 14458 }; 14459 14460})(window.jQuery); 14461 14462 14463!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; 14464function getStyles(config){ 14465 // 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;
14465left: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+"}" 14466}; 14467 var ShareUtils; 14468 14469if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 14470 Object.defineProperty(HTMLElement.prototype, "classList", { 14471 get: function() { 14472 var ret, self, update; 14473 update = function(fn) { 14474 return function(value) { 14475 var classes, index; 14476 classes = self.className.split(/\s+/); 14477 index = classes.indexOf(value); 14478 fn(classes, index, value); 14479 self.className = classes.join(" "); 14480 }; 14481 }; 14482 self = this; 14483 ret = { 14484 add: update(function(classes, index, value) { 14485 ~index || classes.push(value); 14486 }), 14487 remove: update(function(classes, index) { 14488 ~index && classes.splice(index, 1); 14489 }), 14490 toggle: update(function(classes, index, value) { 14491 if (~index) { 14492 classes.splice(index, 1); 14493 } else { 14494 classes.push(value); 14495 } 14496 }), 14497 contains: function(value) { 14498 return !!~self.className.split(/\s+/).indexOf(value); 14499 }, 14500 item: function(i) { 14501 return self.className.split(/\s+/)[i] || null; 14502 } 14503 }; 14504 Object.defineProperty(ret, "length", { 14505 get: function() { 14506 return self.className.split(/\s+/).length; 14507 } 14508 }); 14509 return ret; 14510 } 14511 }); 14512} 14513 14514String.prototype.to_rfc3986 = function() { 14515 var tmp; 14516 tmp = encodeURIComponent(this); 14517 return tmp.replace(/[!'()*]/g, function(c) { 14518 return "%" + c.charCodeAt(0).toString(16); 14519 }); 14520}; 14521 14522ShareUtils = (function() { 14523 function ShareUtils() {} 14524 14525 ShareUtils.prototype.extend = function(to, from, overwrite) { 14526 var hasProp, prop; 14527 for (prop in from) { 14528 hasProp = to[prop] !== undefined; 14529 if (hasProp && typeof from[prop] === "object") { 14530 this.extend(to[prop], from[prop], overwrite); 14531 } else { 14532 if (overwrite || !hasProp) { 14533 to[prop] = from[prop]; 14534 } 14535 } 14536 } 14537 }; 14538 14539 ShareUtils.prototype.hide = function(el) { 14540 return el.style.display = "none"; 14541 }; 14542 14543 ShareUtils.prototype.show = function(el) { 14544 return el.style.display = "block"; 14545 }; 14546 14547 ShareUtils.prototype.has_class = function(el, class_name) { 14548 return el.classList.contains(class_name); 14549 }; 14550 14551 ShareUtils.prototype.add_class = function(el, class_name) { 14552 return el.classList.add(class_name); 14553 }; 14554 14555 ShareUtils.prototype.remove_class = function(el, class_name) { 14556 return el.classList.remove(class_name); 14557 }; 14558 14559 ShareUtils.prototype.is_encoded = function(str) { 14560 str = str.to_rfc3986(); 14561 return decodeURIComponent(str) !== str; 14562 }; 14563 14564 ShareUtils.prototype.encode = function(str) { 14565 if (typeof str === "undefined" || this.is_encoded(str)) { 14566 return str; 14567 } else { 14568 return str.to_rfc3986(); 14569 } 14570 }; 14571 14572 ShareUtils.prototype.popup = function(url, params) { 14573 var k, popup, qs, v; 14574 if (params == null) { 14575 params = {}; 14576 } 14577 popup = { 14578 width: 500, 14579 height: 350 14580 }; 14581 popup.top = (screen.height / 2) - (popup.height / 2); 14582 popup.left = (screen.width / 2) - (popup.width / 2); 14583 qs = ((function() { 14584 var _results; 14585 _results = []; 14586 for (k in params) { 14587 v = params[k]; 14588 _results.push("" + k + "=" + (this.encode(v))); 14589 } 14590 return _results; 14591 }).call(this)).join('&'); 14592 if (qs) { 14593 qs = "?" + qs; 14594 } 14595 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="
14595+ popup.width + ",height=" + popup.height); 14596 }; 14597 14598 return ShareUtils; 14599 14600})(); 14601var Share, 14602 __hasProp = {}.hasOwnProperty, 14603 __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; }; 14604 14605Share = (function(_super) { 14606 __extends(Share, _super); 14607 14608 function Share(element, options) { 14609 this.element = element; 14610 this.el = { 14611 head: document.getElementsByTagName('head')[0], 14612 body: document.getElementsByTagName('body')[0] 14613 }; 14614 this.config = { 14615 enabled_networks: 0, 14616 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 14617 url: window.location.href, 14618 caption: null, 14619 title: this.default_title(), 14620 image: this.default_image(), 14621 description: this.default_description(), 14622 ui: { 14623 flyout: 'top center', 14624 button_text: 'Share', 14625 button_font: true, 14626 icon_font: true 14627 }, 14628 networks: { 14629 google_plus: { 14630 enabled: true, 14631 url: null 14632 }, 14633 twitter: { 14634 enabled: true, 14635 url: null, 14636 title: null, 14637 description: null 14638 }, 14639 facebook: { 14640 enabled: true, 14641 load_sdk: true, 14642 url: null, 14643 app_id: null, 14644 title: null, 14645 caption: null, 14646 description: null, 14647 image: null 14648 }, 14649 pinterest: { 14650 enabled: true, 14651 url: null, 14652 image: null, 14653 description: null 14654 }, 14655 reddit: { 14656 enabled: true, 14657 url: null, 14658 title: null 14659 }, 14660 linkedin: { 14661 enabled: true, 14662 url: null, 14663 title: null, 14664 description: null 14665 }, 14666 xing: { 14667 enabled: true, 14668 url: null, 14669 title: null, 14670 image: null, 14671 description: null 14672 }, 14673 whatsapp: { 14674 enabled: true, 14675 description: null, 14676 url: null 14677 }, 14678 email: { 14679 enabled: true, 14680 title: null, 14681 description: null, 14682 url: null 14683 } 14684 } 14685 }; 14686 this.setup(element, options); 14687 return this; 14688 } 14689 14690 Share.prototype.setup = function(element, opts) { 14691 var index, instance, instances, _i, _len; 14692 instances = document.querySelectorAll(element); 14693 this.extend(this.config, opts, true); 14694 this.set_global_configuration(); 14695 this.normalize_network_configuration(); 14696 if (this.config.ui.icon_font) { 14697 this.inject_icons(); 14698 } 14699 if (this.config.ui.button_font) { 14700 this.inject_fonts(); 14701 } 14702 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 14703 this.inject_facebook_sdk(); 14704 } 14705 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 14706 instance = instances[index]; 14707 this.setup_instance(element, index); 14708 } 14709 }; 14710 14711 Share.prototype.setup_instance = function(element, index) { 14712 var button, instance, label, network, networks, _i, _len, _results, 14713 _this = this; 14714 instance = document.querySelectorAll(element)[index]; 14715 this.hide(instance); 14716 this.add_class(instance, "sharer-" + index); 14717 instance = document.querySelectorAll(element)[index]; 14718 this.inject_css(instance); 14719 this.inject_html(instance); 14720 this.show(instance); 14721 label = instance.getElementsByTagName("label")[0]; 14722 button = instance.getElementsByClassName("social")[0]; 14723 networks = instance.getElementsByTagName('li'); 14724 this.add_class(button, "networks-" + this.config.enabled_networks); 14725 label.addEventListener("click", function() { 14726 return _this.event_toggle(button); 14727 }); 14728 _this = this; 14729 _results = []; 14730 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 14731 network = networks[index]; 14732 _results.push(network.addEventListener("click", function() { 14733 _this.event_network(instance, this); 14734 return _this.event_close(button); 14735 })); 14736 } 14737 return _results; 14738 }; 14739 14740 Share.prototype.event_toggle = function(button) { 14741 if (this.has_class(button, "active")) { 14742 return this.event_close(button); 14743 } else { 14744 return this.event_open(button); 14745 } 14746 }; 14747 14748 Share.prototype.event_open = function(button) { 14749 if (this.has_class(button, "load")) { 14750 this.remove_class(button, "load"); 14751 } 14752 return this.add_class(button, "active"); 14753 }; 14754 14755 Share.prototype.event_close = function(button) { 14756 return this.remove_class(button, "active"); 14757 }; 14758 14759 Share.prototype.event_network = function(instance, network) { 14760 var name; 14761 name = network.getAttribute("data-network"); 14762 this.hook("before", name, instance);
14763 this["network_" + name](); 14764 return this.hook("after", name, instance); 14765 }; 14766 14767 Share.prototype.open = function() { 14768 return this["public"]("open"); 14769 }; 14770 14771 Share.prototype.close = function() { 14772 return this["public"]("close"); 14773 }; 14774 14775 Share.prototype.toggle = function() { 14776 return this["public"]("toggle"); 14777 }; 14778 14779 Share.prototype["public"] = function(action) { 14780 var button, index, instance, _i, _len, _ref, _results; 14781 _ref = document.querySelectorAll(this.element); 14782 _results = []; 14783 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 14784 instance = _ref[index]; 14785 button = instance.getElementsByClassName("social")[0]; 14786 _results.push(this["event_" + action](button)); 14787 } 14788 return _results; 14789 }; 14790 14791 Share.prototype.network_facebook = function() { 14792 if (this.config.networks.facebook.load_sdk) { 14793 if (!window.FB) { 14794 return console.error("The Facebook JS SDK hasn't loaded yet."); 14795 } 14796 return FB.ui({ 14797 method: 'feed', 14798 name: this.config.networks.facebook.title, 14799 link: this.config.networks.facebook.url, 14800 picture: this.config.networks.facebook.image, 14801 caption: this.config.networks.facebook.caption, 14802 description: this.config.networks.facebook.description 14803 }); 14804 } else { 14805 return this.popup('https://www.facebook.com/sharer/sharer.php', { 14806 u: this.config.networks.facebook.url 14807 }); 14808 } 14809 }; 14810 14811 Share.prototype.network_twitter = function() { 14812 return this.popup('https://twitter.com/intent/tweet', { 14813 text: this.config.networks.twitter.title, 14814 url: this.config.networks.twitter.url 14815 }); 14816 }; 14817 14818 Share.prototype.network_google_plus = function() { 14819 return this.popup('https://plus.google.com/share', { 14820 url: this.config.networks.google_plus.url 14821 }); 14822 }; 14823 14824 Share.prototype.network_pinterest = function() { 14825 return this.popup('https://www.pinterest.com/pin/create/button', { 14826 url: this.config.networks.pinterest.url, 14827 media: this.config.networks.pinterest.image, 14828 description: this.config.networks.pinterest.description 14829 }); 14830 }; 14831 14832 Share.prototype.network_linkedin = function() { 14833 return this.popup('https://www.linkedin.com/shareArticle', { 14834 url: this.config.networks.linkedin.url, 14835 title: this.config.networks.linkedin.title, 14836 summary: this.config.networks.linkedin.description 14837 }); 14838 } 14839 14840 Share.prototype.network_xing = function() { 14841 return this.popup('https://www.xing.com/spi/shares/new', { 14842 url: this.config.networks.xing.url, 14843 image: this.config.networks.xing.image, 14844 title: this.config.networks.xing.title, 14845 summary: this.config.networks.xing.description 14846 }); 14847 } 14848 14849 Share.prototype.network_email = function() { 14850 return this.popup('mailto:', { 14851 subject: this.config.networks.email.title, 14852 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 14853 }); 14854 }; 14855 14856 Share.prototype.inject_icons = function() { 14857 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 14858 }; 14859 14860 Share.prototype.inject_fonts = function() { 14861 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 14862 }; 14863 14864 Share.prototype.inject_stylesheet = function(url) { 14865 var link; 14866 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 14867 link = document.createElement("link"); 14868 link.setAttribute("rel", "stylesheet"); 14869 link.setAttribute("href", url); 14870 return this.el.head.appendChild(link); 14871 } 14872 }; 14873 14874 Share.prototype.inject_css = function(instance) { 14875 var css, meta, selector, style; 14876 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 14877 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 14878 this.config.selector = selector; 14879 css = getStyles(this.config); 14880 style = document.createElement("style"); 14881 style.type = "text/css"; 14882 if (style.styleSheet) { 14883 style.styleSheet.cssText = css; 14884 } else { 14885 style.appendChild(document.createTextNode(css)); 14886 } 14887 this.el.head.appendChild(style); 14888 delete this.config.selector; 14889 meta = document.createElement("meta"); 14890 meta.setAttribute("name", "sharer" + selector); 14891 return this.el.head.appendChild(meta); 14892 } 14893 }; 14894 14895 Share.prototype.inject_html = function(instance) { 14896 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>"; 14897 }; 14898 14899 Share.prototype.inject_facebook_sdk = function() { 14900 var fb_root, script; 14901 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 14902 script = document.createElement("script"); 14903 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')"; 14904 fb_root = document.createElement("div"); 14905 fb_root.id = "fb-root"; 14906 this.el.body.appendChild(fb_root); 14907 return this.el.body.appendChild(script); 14908 } 14909 }; 14910 14911 Share.prototype.hook = function(type, network, instance) { 14912 var fn, opts; 14913 fn = this.config.networks[network][type]; 14914 if (typeof fn === "function") { 14915 opts = fn.call(this.config.networks[network], instance); 14916 if (opts !== void 0) { 14917 opts = this.normalize_filter_config_updates(opts); 14918 this.extend(this.config.networks[network], opts, true); 14919 this.normalize_network_configuration(); 14920 } 14921 } 14922 }; 14923 14924 Share.prototype.default_title = function() { 14925 var content; 14926 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 14927 return encodeURIComponent(content.getAttribute('content')); 14928 } else if (content = document.querySelector('title')) { 14929 return encodeURIComponent(content.innerText); 14930 } 14931 }; 14932 14933 Share.prototype.default_image = function() { 14934 var content; 14935 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 14936 return content.getAttribute('content'); 14937 } 14938 }; 14939 14940 Share.prototype.default_description = function() { 14941 var content; 14942 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 14943 return encodeURIComponent(content.getAttribute('content')); 14944 } else { 14945 return ''; 14946 } 14947 }; 14948 14949 Share.prototype.set_global_configuration = function() { 14950 var display, network, option, options, _ref, _results; 14951 _ref = this.config.networks; 14952 _results = []; 14953 for (network in _ref) { 14954 options = _ref[network]; 14955 for (option in options) { 14956 if (this.config.networks[network][option] == null) { 14957 this.config.networks[network][option] = this.config[option]; 14958 } 14959 } 14960 if (this.config.networks[network].enabled) { 14961 display = 'block'; 14962 this.config.enabled_networks += 1; 14963 } else { 14964 display = 'none'; 14965 } 14966 _results.push(this.config.networks[network].display = display); 14967 } 14968 return _results; 14969 }; 14970 14971 Share.prototype.normalize_network_configuration = function() { 14972 if (!this.config.networks.facebook.app_id) { 14973 this.config.networks.facebook.load_sdk = false;
14974 } 14975 if (!this.is_encoded(this.config.networks.twitter.description)) { 14976 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 14977 } 14978 if (typeof this.config.networks.facebook.app_id === 'number') { 14979 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 14980 } 14981 }; 14982 14983 Share.prototype.normalize_filter_config_updates = function(opts) { 14984 if (this.config.networks.facebook.app_id !== opts.app_id) { 14985 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."); 14986 delete opts.app_id; 14987 } 14988 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 14989 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."); 14990 delete opts.app_id; 14991 } 14992 return opts; 14993 }; 14994 14995 return Share; 14996 14997})(ShareUtils); 14998 return Share; 14999}); 15000 15001 15002// Generated by CoffeeScript 1.9.2 15003 15004// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 15005 15006(function() { 15007 var $, win; 15008 15009 $ = this.jQuery || window.jQuery; 15010 15011 win = $(window); 15012 15013 $.fn.stick_in_parent = function(opts) { 15014 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 15015 if (opts == null) { 15016 opts = {}; 15017 } 15018 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; 15019 if (offset_top == null) { 15020 offset_top = 0; 15021 } 15022 if (parent_selector == null) { 15023 parent_selector = void 0; 15024 } 15025 if (inner_scrolling == null) { 15026 inner_scrolling = true; 15027 } 15028 if (sticky_class == null) { 15029 sticky_class = "is_stuck"; 15030 } 15031 doc = $(document); 15032 if (enable_bottoming == null) { 15033 enable_bottoming = true; 15034 } 15035 outer_width = function(el) { 15036 var _el, computed, w; 15037 if (window.getComputedStyle) { 15038 _el = el[0]; 15039 computed = window.getComputedStyle(el[0]); 15040 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 15041 if (computed.getPropertyValue("box-sizing") !== "border-box") { 15042 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 15043 } 15044 return w; 15045 } else { 15046 return el.outerWidth(true); 15047 } 15048 }; 15049 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 15050 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 15051 if (elm.data("sticky_kit")) { 15052 return; 15053 } 15054 elm.data("sticky_kit", true); 15055 last_scroll_height = doc.height(); 15056 parent = elm.parent(); 15057 if (parent_selector != null) { 15058 parent = parent.closest(parent_selector); 15059 } 15060 if (!parent.length) { 15061 throw "failed to find stick parent"; 15062 } 15063 fixed = false; 15064 bottomed = false; 15065 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 15066 if (spacer) { 15067 spacer.css('position', elm.css('position')); 15068 } 15069 recalc = function() { 15070 var border_top, padding_top, restore; 15071 if (detached) { 15072 return; 15073 } 15074 last_scroll_height = doc.height(); 15075 border_top = parseInt(parent.css("border-top-width"), 10); 15076 padding_top = parseInt(parent.css("padding-top"), 10); 15077 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 15078 parent_top = parent.offset().top + border_top + padding_top; 15079 parent_height = parent.height(); 15080 if (fixed) { 15081 fixed = false;
vendor: 6,069 bytes, lines 15082-15277
15082 bottomed = false; 15083 if (manual_spacer == null) { 15084 elm.insertAfter(spacer); 15085 spacer.detach(); 15086 } 15087 elm.css({ 15088 position: "", 15089 top: "", 15090 width: "", 15091 bottom: "" 15092 }).removeClass(sticky_class); 15093 restore = true; 15094 } 15095 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 15096 height = elm.outerHeight(true); 15097 el_float = elm.css("float"); 15098 if (spacer) { 15099 spacer.css({ 15100 width: outer_width(elm), 15101 height: height, 15102 display: elm.css("display"), 15103 "vertical-align": elm.css("vertical-align"), 15104 "float": el_float 15105 }); 15106 } 15107 if (restore) { 15108 return tick(); 15109 } 15110 }; 15111 recalc(); 15112 if (height === parent_height) { 15113 return; 15114 } 15115 last_pos = void 0; 15116 offset = offset_top; 15117 recalc_counter = recalc_every; 15118 tick = function() { 15119 var css, delta, recalced, scroll, will_bottom, win_height; 15120 if (detached) { 15121 return; 15122 } 15123 recalced = false; 15124 if (recalc_counter != null) { 15125 recalc_counter -= 1; 15126 if (recalc_counter <= 0) { 15127 recalc_counter = recalc_every; 15128 recalc(); 15129 recalced = true; 15130 } 15131 } 15132 if (!recalced && doc.height() !== last_scroll_height) { 15133 recalc(); 15134 recalced = true; 15135 } 15136 scroll = win.scrollTop(); 15137 if (last_pos != null) { 15138 delta = scroll - last_pos; 15139 } 15140 last_pos = scroll; 15141 if (fixed) { 15142 if (enable_bottoming) { 15143 will_bottom = scroll + height + offset > parent_height + parent_top; 15144 if (bottomed && !will_bottom) { 15145 bottomed = false; 15146 elm.css({ 15147 position: "fixed", 15148 bottom: "", 15149 top: offset 15150 }).trigger("sticky_kit:unbottom"); 15151 } 15152 } 15153 if (scroll < top) { 15154 fixed = false; 15155 offset = offset_top; 15156 if (manual_spacer == null) { 15157 if (el_float === "left" || el_float === "right") { 15158 elm.insertAfter(spacer); 15159 } 15160 spacer.detach(); 15161 } 15162 css = { 15163 position: "", 15164 width: "", 15165 top: "" 15166 }; 15167 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 15168 } 15169 if (inner_scrolling) { 15170 win_height = win.height(); 15171 if (height + offset_top > win_height) { 15172 if (!bottomed) { 15173 offset -= delta; 15174 offset = Math.max(win_height - height, offset); 15175 offset = Math.min(offset_top, offset); 15176 if (fixed) { 15177 elm.css({ 15178 top: offset + "px" 15179 }); 15180 } 15181 } 15182 } 15183 } 15184 } else { 15185 if (scroll > top) { 15186 fixed = true; 15187 css = { 15188 position: "fixed", 15189 top: offset 15190 }; 15191 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 15192 elm.css(css).addClass(sticky_class); 15193 if (manual_spacer == null) { 15194 elm.after(spacer); 15195 if (el_float === "left" || el_float === "right") { 15196 spacer.append(elm); 15197 } 15198 } 15199 elm.trigger("sticky_kit:stick"); 15200 } 15201 } 15202 if (fixed && enable_bottoming) { 15203 if (will_bottom == null) { 15204 will_bottom = scroll + height + offset > parent_height + parent_top; 15205 } 15206 if (!bottomed && will_bottom) { 15207 bottomed = true; 15208 if (parent.css("position") === "static") { 15209 parent.css({ 15210 position: "relative" 15211 }); 15212 } 15213 return elm.css({ 15214 position: "absolute", 15215 bottom: padding_bottom, 15216 top: "auto" 15217 }).trigger("sticky_kit:bottom"); 15218 } 15219 } 15220 }; 15221 recalc_and_tick = function() { 15222 recalc(); 15223 return tick(); 15224 }; 15225 detach = function() { 15226 detached = true; 15227 win.off("touchmove", tick); 15228 win.off("scroll", tick); 15229 win.off("resize", recalc_and_tick); 15230 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 15231 elm.off("sticky_kit:detach", detach); 15232 elm.removeData("sticky_kit"); 15233 elm.css({ 15234 position: "", 15235 bottom: "", 15236 top: "", 15237 width: "" 15238 }); 15239 parent.position("position", ""); 15240 if (fixed) { 15241 if (manual_spacer == null) { 15242 if (el_float === "left" || el_float === "right") { 15243 elm.insertAfter(spacer); 15244 } 15245 spacer.remove(); 15246 } 15247 return elm.removeClass(sticky_class); 15248 } 15249 }; 15250 win.on("touchmove", tick); 15251 win.on("scroll", tick); 15252 win.on("resize", recalc_and_tick); 15253 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 15254 elm.on("sticky_kit:detach", detach); 15255 return setTimeout(tick, 0); 15256 }; 15257 for (i = 0, len = this.length; i < len; i++) { 15258 elm = this[i]; 15259 fn($(elm)); 15260 } 15261 return this; 15262 }; 15263 15264}).call(this); 15265 15266/* ========================================================================== 15267 * bootstrap-tab-history.js 15268 * Author: Michael Narayan <[email protected]> 15269 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 15270 * ========================================================================== 15271 * Licensed under the Apache License, Version 2.0 (the "License"); you may 15272 * not use this file except in compliance with the License. You may obtain a 15273 * copy of the License at 15274 * 15275 * http://www.apache.org/licenses/LICENSE-2.0 15276 * 15277 * Unless required by applicable law or agreed to in writing, softw
15277are 15278 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15279 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15280 * License for the specific language governing permissions and limitations 15281 * under the License. 15282 * ========================================================================== */ 15283 15284/* ========================================================================== */ 15285/* JSHint directives */ 15286/* */ 15287/* global BootstrapTabHistory: true */ 15288/* */ 15289/* global document */ 15290/* global jQuery */ 15291/* global history */ 15292/* global window */ 15293/* ========================================================================== */ 15294 15295/** 15296 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 15297 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 15298 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 15299 * 15300 * See the README for additional information. 15301 * 15302 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 15303 */ 15304 15305BootstrapTabHistory = { 15306 options: { 15307 /** 15308 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 15309 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 15310 * 15311 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 15312 * 15313 * @public 15314 * @type {?number} 15315 */ 15316 defaultAnchorYOffset: 0, 15317 /** 15318 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 15319 * 15320 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 15321 * 15322 * @public 15323 * @type {string} 15324 */ 15325 defaultChanger: 'replace', 15326 /** 15327 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 15328 * `null` is passed as the third parameter to these calls. 15329 * 15330 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 15331 * 15332 * @public 15333 * @type {boolean} 15334 */ 15335 defaultUpdateURL: false, 15336 /** 15337 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 15338 * load. 15339 * 15340 * @public 15341 * @type {boolean} 15342 */ 15343 showTabsBasedOnAnchor: true 15344 } 15345}; 15346 15347(function () { 15348 'use strict'; 15349 15350 jQuery(function () { 15351 if(history && history.pushState && history.replaceState) { 15352 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15353 15354 if(bootstrapTabHistory) { 15355 showTabsBasedOnState(bootstrapTabHistory); 15356 } else { 15357 showTabsBasedOnAnchor(); 15358 } 15359 15360 backfillHistoryState(); 15361 15362 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 15363 jQuery(window).on('popstate', onPopState); 15364 } else { 15365 showTabsBasedOnAnchor(); 15366 } 15367 }); 15368 15369 /** 15370 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 15371 * 15372 * @type {boolean} 15373 */ 15374 var showingTabsBasedOnState = false; 15375 15376 /** 15377 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 15378 * `history.back` handling when `data-tab-history-update-url` is true. 15379 */ 15380 function backfillHistoryState() { 15381 var newState = null; 15382 15383 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 15384 var $activeTabElement = jQuery(this); 15385 var selector = getTabSelector($activeTabElement); 15386 15387 if(selector) { 15388 var tabGroup = getTabGroup($activeTabElement); 15389 15390 if(tabGroup) { 15391 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 15392 } 15393 } 15394 }); 15395 15396 if(newState) { 15397 history.replaceState(newState, '', null); 15398 } 15399 } 15400 15401 /** 15402 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 15403 * said bootstrapTabHistory attribute. 15404 * 15405 * @param {?object} existingState 15406 * @param {!string} tabGroup 15407 * @param {!string} selector 15408 * @returns {!object} 15409 */ 15410 function createNewHistoryState(existingState, tabGroup, selector) { 15411 // Clone history.state and ensure it has a bootstrapTabHistory entry. 15412 var newState = jQuery.extend(true, {}, existingState, { 15413 bootstrapTabHistory: {} 15414 }); 15415 15416 newState.bootstrapTabHistory[tabGroup] = selector; 15417 15418 return newState; 15419 } 15420 15421 /** 15422 * @param {jQuery} $tab
15423 * @returns {?string} 15424 */ 15425 function getTabGroup($tab) { 15426 return parseTruthyAttributeValue($tab.data('tab-history')); 15427 } 15428 15429 /** 15430 * @param {jQuery} $tab 15431 * @returns {?string} 15432 */ 15433 function getTabSelector($tab) { 15434 return $tab.data('target') || $tab.attr('href'); 15435 } 15436 15437 /** 15438 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 15439 * 15440 * @param {jQuery.Event} shownEvt 15441 */ 15442 function onShownTab(shownEvt) { 15443 if(!showingTabsBasedOnState) { 15444 var $activatedTab = jQuery(shownEvt.target); 15445 if ( $activatedTab.hasClass('panel-collapse') ) 15446 $activatedTab = $activatedTab.closest('.panel').find('a'); 15447 var selector = getTabSelector($activatedTab); 15448 15449 if(selector) { 15450 var tabGroup = getTabGroup($activatedTab); 15451 15452 if(tabGroup) { 15453 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 15454 var newState = createNewHistoryState(history.state, tabGroup, selector); 15455 var updateURL = (function ($activatedTab) { 15456 if(selector[0] === '#') { 15457 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 15458 15459 if(elementUpdateURLOption === undefined) { 15460 return BootstrapTabHistory.options.defaultUpdateURL; 15461 } else { 15462 return elementUpdateURLOption; 15463 } 15464 } else { 15465 return false; 15466 } 15467 })($activatedTab); 15468 15469 switch(historyChanger) { 15470 case 'push': 15471 history.pushState(newState, '', updateURL ? selector : null); 15472 break; 15473 case 'replace': 15474 history.replaceState(newState, '', updateURL ? selector : null); 15475 break; 15476 default: 15477 throw new Error('Unknown tab-history-changer: ' + historyChanger); 15478 } 15479 } 15480 } 15481 } 15482 } 15483 15484 /** 15485 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 15486 */ 15487 function onPopState() { 15488 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15489 15490 if(bootstrapTabHistory) { 15491 showTabsBasedOnState(bootstrapTabHistory); 15492 } 15493 } 15494 15495 /** 15496 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 15497 * 15498 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 15499 * 15500 * @param {*} value 15501 * @returns {*} 15502 */ 15503 function parseTruthyAttributeValue(value) { 15504 if(value) { 15505 return value; 15506 } else if(value === '') { 15507 return true; 15508 } else { 15509 return value; 15510 } 15511 } 15512 15513 /** 15514 * Show tabs based upon the anchor component of `window.location`. 15515 */ 15516 function showTabsBasedOnAnchor() { 15517 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 15518 var anchor = window.location && window.location.hash; 15519 15520 if(anchor) { 15521 var $tabElement = showTabForSelector(anchor); 15522 15523 if($tabElement && window.addEventListener && window.removeEventListener) { 15524 var anchorYOffset = (function ($tabElement) { 15525 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 15526 15527 if(elementSetting === undefined) { 15528 return BootstrapTabHistory.options.defaultAnchorYOffset; 15529 } else { 15530 return elementSetting; 15531 } 15532 })($tabElement); 15533 15534 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 15535 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 15536 // `history.state` object should have been used (unless the browser did not support the modern History API). 15537 if(anchorYOffset || anchorYOffset === 0) { 15538 var scrollListener = function resetAnchorScroll () { 15539 window.removeEventListener('scroll', scrollListener); 15540 window.scrollTo(0, anchorYOffset); 15541 }; 15542 15543 window.addEventListener('scroll', scrollListener); 15544 } 15545 } 15546 } 15547 } 15548 } 15549 15550 /** 15551 * Show a tab which corresponds to the provided selector. 15552 * 15553 * @param {string} selector - A CSS selector. 15554 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 15555 */ 15556 function showTabForSelector(selector) { 15557 var $tabElement = (function (selector) { 15558 var $ret = null; 15559 15560 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 15561 var $potentialTab = jQuery(this); 15562 15563 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 15564 $ret = $potentialTab; 15565 return false;
vendor: 4,523 bytes, lines 15566-15716
15566 } else { 15567 return null; 15568 } 15569 }); 15570 15571 return $ret; 15572 })(selector); 15573 15574 if($tabElement) { 15575 $tabElement.trigger('click'); 15576 //$tabElement.tab('show'); 15577 } 15578 15579 return $tabElement; 15580 } 15581 15582 /** 15583 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 15584 * 15585 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 15586 */ 15587 function showTabsBasedOnState(bootstrapTabHistory) { 15588 showingTabsBasedOnState = true; 15589 15590 try { 15591 for(var k in bootstrapTabHistory) { 15592 if(bootstrapTabHistory.hasOwnProperty(k)) { 15593 showTabForSelector(bootstrapTabHistory[k]); 15594 } 15595 } 15596 } finally { 15597 showingTabsBasedOnState = false; 15598 } 15599 } 15600})(); 15601 15602 15603/*! 15604 * Justified Gallery - v3.6.3 15605 * http://miromannino.github.io/Justified-Gallery/ 15606 * Copyright (c) 2016 Miro Mannino 15607 * Licensed under the MIT license. 15608 */ 15609(function($) { 15610 15611 function hasScrollBar() { 15612 return $("body").height() > $(window).height(); 15613 } 15614 /** 15615 * Justified Gallery controller constructor 15616 * 15617 * @param $gallery the gallery to build 15618 * @param settings the settings (the defaults are in $.fn.justifiedGallery.defaults) 15619 * @constructor 15620 */ 15621 var JustifiedGallery = function ($gallery, settings) { 15622 15623 this.settings = settings; 15624 this.checkSettings(); 15625 15626 this.imgAnalyzerTimeout = null; 15627 this.entries = null; 15628 this.buildingRow = { 15629 entriesBuff : [], 15630 width : 0, 15631 height : 0, 15632 aspectRatio : 0 15633 }; 15634 this.lastFetchedEntry = null; 15635 this.lastAnalyzedIndex = -1; 15636 this.yield = { 15637 every : 2, // do a flush every n flushes (must be greater than 1) 15638 flushed : 0 // flushed rows without a yield 15639 }; 15640 this.border = settings.border >= 0 ? settings.border : settings.margins; 15641 this.maxRowHeight = this.retrieveMaxRowHeight(); 15642 this.suffixRanges = this.retrieveSuffixRanges(); 15643 this.offY = this.border; 15644 this.rows = 0; 15645 this.spinner = { 15646 phase : 0, 15647 timeSlot : 150, 15648 $el : $('<div class="spinner"><span></span><span></span><span></span></div>'), 15649 intervalId : null 15650 }; 15651 this.checkWidthIntervalId = null; 15652 this.galleryWidth = $gallery.width(); 15653 this.$gallery = $gallery; 15654 15655 }; 15656 15657 /** @returns {String} the best suffix given the width and the height */ 15658 JustifiedGallery.prototype.getSuffix = function (width, height) { 15659 var longestSide, i; 15660 longestSide = (width > height) ? width : height; 15661 for (i = 0; i < this.suffixRanges.length; i++) { 15662 if (longestSide <= this.suffixRanges[i]) { 15663 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 15664 } 15665 } 15666 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 15667 }; 15668 15669 /** 15670 * Remove the suffix from the string 15671 * 15672 * @returns {string} a new string without the suffix 15673 */ 15674 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 15675 return str.substring(0, str.length - suffix.length); 15676 }; 15677 15678 /** 15679 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 15680 */ 15681 JustifiedGallery.prototype.endsWith = function (str, suffix) { 15682 return str.indexOf(suffix, str.length - suffix.length) !== -1; 15683 }; 15684 15685 /** 15686 * Get the used suffix of a particular url 15687 * 15688 * @param str 15689 * @returns {String} return the used suffix 15690 */ 15691 JustifiedGallery.prototype.getUsedSuffix = function (str) { 15692 for (var si in this.settings.sizeRangeSuffixes) { 15693 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 15694 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 15695 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 15696 } 15697 } 15698 return ''; 15699 }; 15700 15701 /** 15702 * Given an image src, with the width and the height, returns the new image src with the 15703 * best suffix to show the best quality thumbnail. 15704 * 15705 * @returns {String} the suffix to use 15706 */ 15707 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 15708 var newImageSrc; 15709 15710 if (this.settings.thumbnailPath) { 15711 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 15712 } else { 15713 var matchRes = imageSrc.match(this.settings.extension); 15714 var ext = (matchRes !== null) ? matchRes[0] : ''; 15715 newImageSrc = imageSrc.replace(this.settings.extension, ''); 15716 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
15717 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 15718 } 15719 15720 return newImageSrc; 15721 }; 15722 15723 /** 15724 * Shows the images that is in the given entry 15725 * 15726 * @param $entry the entry 15727 * @param callback the callback that is called when the show animation is finished 15728 */ 15729 JustifiedGallery.prototype.showImg = function ($entry, callback) { 15730 if (this.settings.cssAnimation) { 15731 $entry.addClass('entry-visible'); 15732 if (callback) callback(); 15733 } else { 15734 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15735 $entry.find('> img, > a > img').stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15736 } 15737 }; 15738 15739 /** 15740 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 15741 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 15742 * 15743 * @param $image the image to analyze 15744 * @returns {String} the extracted src 15745 */ 15746 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 15747 var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src'); 15748 $image.data('jg.originalSrc', imageSrc); 15749 return imageSrc; 15750 }; 15751 15752 /** @returns {jQuery} the image in the given entry */ 15753 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 15754 var $img = $entry.find('> img'); 15755 if ($img.length === 0) $img = $entry.find('> a > img'); 15756 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 15757 return $img.length === 0 ? null : $img; 15758 }; 15759 15760 /** @returns {jQuery} the caption in the given entry */ 15761 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 15762 var $caption = $entry.find('> .caption'); 15763 return $caption.length === 0 ? null : $caption; 15764 }; 15765 15766 /** 15767 * Display the entry 15768 * 15769 * @param {jQuery} $entry the entry to display 15770 * @param {int} x the x position where the entry must be positioned 15771 * @param y the y position where the entry must be positioned 15772 * @param imgWidth the image width 15773 * @param imgHeight the image height 15774 * @param rowHeight the row height of the row that owns the entry 15775 */ 15776 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 15777 $entry.width(imgWidth); 15778 $entry.height(Math.floor(rowHeight));//hacked by Uncode 15779 $entry.css('top', Math.floor(y));//hacked by Uncode 15780 $entry.css('left', x); 15781 15782 var $image = this.imgFromEntry($entry); 15783 if ($image !== null) { 15784 $image.css('width', imgWidth); 15785 $image.css('height', imgHeight); 15786 $image.css('margin-left', - imgWidth / 2); 15787 $image.css('margin-top', - imgHeight / 2); 15788 15789 // Image reloading for an high quality of thumbnails 15790 var imageSrc = $image.attr('src'); 15791 var newImageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 15792 15793 $image.one('error', function () { 15794 $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it. 15795 }); 15796 15797 var loadNewImage = function () { 15798 if (imageSrc !== newImageSrc) { //load the new image after the fadeIn 15799 $image.attr('src', newImageSrc); 15800 } 15801 }; 15802 15803 if ($entry.data('jg.loaded') === 'skipped') { 15804 this.onImageEvent(imageSrc, $.proxy(function() { 15805 this.showImg($entry, loadNewImage); 15806 $entry.data('jg.loaded', true); 15807 }, this)); 15808 } else { 15809 this.showImg($entry, loadNewImage); 15810 } 15811 15812 } else { 15813 this.showImg($entry); 15814 } 15815 15816 this.displayEntryCaption($entry); 15817 }; 15818 15819 /** 15820 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 15821 * or the 'title' attributes. 15822 * 15823 * @param {jQuery} $entry the entry to process 15824 */ 15825 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 15826 var $image = this.imgFromEntry($entry); 15827 if ($image !== null && this.settings.captions) { 15828 var $imgCaption = this.captionFromEntry($entry); 15829 15830 // Create it if it doesn't exists 15831 if ($imgCaption === null) { 15832 var caption = $image.attr('alt'); 15833 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 15834 if (this.isValidCaption(caption)) { // Create only we found something 15835 $imgCaption = $('<div class="caption">' + caption + '</div>'); 15836 $entry.append($imgCaption); 15837 $entry.data('jg.createdCaption', true); 15838 } 15839 } 15840 15841 // Create events (we check again the $imgCaption because it can be still inexistent) 15842 if ($imgCaption !== null) { 15843 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 15844 this.addCaptionEventsHandlers($entry); 15845 } 15846 } else { 15847 this.removeCaptionEventsHandlers($entry); 15848 } 15849 }; 15850 15851 /** 15852 * Validates the caption 15853 * 15854 * @param caption The caption that should be validated 15855 * @return {boolean} Validation result 15856 */ 15857 JustifiedGallery.prototype.isValidCaption = function (caption) { 15858 return (typeof caption !== 'undefined' && caption.length > 0); 15859 }; 15860 15861 /** 15862 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 15863 * It shows the caption using jQuery (or using CSS if it is configured so) 15864 * 15865 * @param {Event} eventObject the event object 15866 */ 15867 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 15868 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15869 if (this.settings.cssAnimation) { 15870 $caption.addClass('caption-visible').removeClass('caption-hidden'); 15871 } else { 15872 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15873 this.settings.captionSettings.visibleOpacity); 15874 } 15875 }; 15876 15877 /** 15878 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 15879 * It hides the caption using jQuery (or using CSS if it is configured so) 15880 * 15881 * @param {Event} eventObject the event object 15882 */ 15883 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 15884 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15885 if (this.settings.cssAnimation) { 15886 $caption.removeClass('caption-visible').removeClass('caption-hidden'); 15887 } else { 15888 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15889 this.settings.captionSettings.nonVisibleOpacity); 15890 } 15891 }; 15892 15893 /** 15894 * Add the handlers of the entry for the caption 15895 * 15896 * @param $entry the entry to modify 15897 */ 15898 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 15899 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15900 if (typeof captionMouseEvents === 'undefined') { 15901 captionMouseEvents = { 15902 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 15903 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 15904 }; 15905 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 15906 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 15907 $entry.data('jg.captionMouseEvents', captionMouseEvents); 15908 } 15909 }; 15910 15911 /** 15912 * Remove the handlers of the entry for the caption 15913 * 15914 * @param $entry the entry to modify 15915 */ 15916 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 15917 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15918 if (typeof captionMouseEvents !== 'undefined') { 15919 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 15920 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 15921 $entry.removeData('jg.captionMouseEvents'); 15922 } 15923 }; 15924 15925 /** 15926 * Justify the building row, preparing it to 15927 * 15928 * @param isLastRow 15929 * @returns a boolean to know if the row has been justified or not 15930 */ 15931 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow) { 15932 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 15933 var minHeight = 0; 15934 var availableWidth = this.galleryWidth - 2 * this.border - ( 15935 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 15936 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 15937 var defaultRowHeight = this.settings.rowHeight; 15938 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 15939 15940 //Skip the last row if we can't justify it and the lastRow == 'hide' 15941 if (isLastRow && this.settings.lastRow === 'hide' && !justifiable) { 15942 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15943 $entry = this.buildingRow.entriesBuff[i]; 15944 if (this.settings.cssAnimation) 15945 $entry.removeClass('entry-visible'); 15946 else { 15947 $entry.stop().fadeTo(0, 0.1); 15948 $entry.find('> img, > a > img').fadeTo(0, 0); 15949 } 15950 } 15951 return -1; 15952 } 15953 15954 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 15955 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 15956 justify = false;
15957 15958 if (this.rows > 0) { 15959 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 15960 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 15961 } 15962 } 15963 15964 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15965 $entry = this.buildingRow.entriesBuff[i]; 15966 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 15967 15968 if (justify) { 15969 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 15970 newImgH = rowHeight; 15971 } else { 15972 newImgW = defaultRowHeight * imgAspectRatio; 15973 newImgH = defaultRowHeight; 15974 } 15975 15976 availableWidth -= Math.round(newImgW); 15977 $entry.data('jg.jwidth', Math.round(newImgW)); 15978 $entry.data('jg.jheight', Math.ceil(newImgH)); 15979 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 15980 } 15981 15982 this.buildingRow.height = minHeight; 15983 return justify; 15984 }; 15985 15986 /** 15987 * Clear the building row data to be used for a new row 15988 */ 15989 JustifiedGallery.prototype.clearBuildingRow = function () { 15990 this.buildingRow.entriesBuff = []; 15991 this.buildingRow.aspectRatio = 0; 15992 this.buildingRow.width = 0; 15993 }; 15994 15995 /** 15996 * Flush a row: justify it, modify the gallery height accordingly to the row height 15997 * 15998 * @param isLastRow 15999 */ 16000 JustifiedGallery.prototype.flushRow = function (isLastRow) { 16001 var settings = this.settings; 16002 var $entry, buildingRowRes, offX = this.border, i; 16003 16004 buildingRowRes = this.prepareBuildingRow(isLastRow); 16005 if (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1) { 16006 this.clearBuildingRow(); 16007 return; 16008 } 16009 16010 if (this.maxRowHeight) { 16011 if (this.maxRowHeight.isPercentage && this.maxRowHeight.value * settings.rowHeight < this.buildingRow.height) { 16012 this.buildingRow.height = this.maxRowHeight.value * settings.rowHeight; 16013 } else if (this.maxRowHeight.value >= settings.rowHeight && this.maxRowHeight.value < this.buildingRow.height) { 16014 this.buildingRow.height = this.maxRowHeight.value; 16015 } 16016 } 16017 16018 //Align last (unjustified) row 16019 if (settings.lastRow === 'center' || settings.lastRow === 'right') { 16020 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 16021 16022 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16023 $entry = this.buildingRow.entriesBuff[i]; 16024 availableWidth -= $entry.data('jg.jwidth'); 16025 } 16026 16027 if (settings.lastRow === 'center') 16028 offX += availableWidth / 2; 16029 else if (settings.lastRow === 'right') 16030 offX += availableWidth; 16031 } 16032 16033 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16034 $entry = this.buildingRow.entriesBuff[i]; 16035 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 16036 offX += $entry.data('jg.jwidth') + settings.margins; 16037 } 16038 16039 //Gallery Height 16040 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 16041 this.$gallery.height(this.galleryHeightToSet + this.getSpinnerHeight()); 16042 16043 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 16044 //Ready for a new row 16045 this.offY += this.buildingRow.height + settings.margins; 16046 this.rows += 1; 16047 this.clearBuildingRow(); 16048 this.$gallery.trigger('jg.rowflush'); 16049 } 16050 }; 16051 16052 /** 16053 * Checks the width of the gallery container, to know if a new justification is needed 16054 */ 16055 var scrollBarOn = false; 16056 JustifiedGallery.prototype.checkWidth = function () { 16057 this.checkWidthIntervalId = setInterval($.proxy(function () { 16058 var galleryWidth = parseFloat(this.$gallery.width()); 16059 if (hasScrollBar() === scrollBarOn) { 16060 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 16061 this.galleryWidth = galleryWidth; 16062 this.rewind(); 16063 16064 // Restart to analyze 16065 this.startImgAnalyzer(true); 16066 } 16067 } else { 16068 scrollBarOn = hasScrollBar(); 16069 this.galleryWidth = galleryWidth; 16070 } 16071 }, this), this.settings.refreshTime); 16072 }; 16073 16074 /** 16075 * @returns {boolean} a boolean saying if the spinner is active or not 16076 */ 16077 JustifiedGallery.prototype.isSpinnerActive = function () { 16078 return this.spinner.intervalId !== null; 16079 }; 16080 16081 /** 16082 * @returns {int} the spinner height 16083 */ 16084 JustifiedGallery.prototype.getSpinnerHeight = function () {
16085 return this.spinner.$el.innerHeight(); 16086 }; 16087 16088 /** 16089 * Stops the spinner animation and modify the gallery height to exclude the spinner 16090 */ 16091 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 16092 clearInterval(this.spinner.intervalId); 16093 this.spinner.intervalId = null; 16094 this.$gallery.height(this.$gallery.height() - this.getSpinnerHeight()); 16095 this.spinner.$el.detach(); 16096 }; 16097 16098 /** 16099 * Starts the spinner animation 16100 */ 16101 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 16102 var spinnerContext = this.spinner; 16103 var $spinnerPoints = spinnerContext.$el.find('span'); 16104 clearInterval(spinnerContext.intervalId); 16105 this.$gallery.append(spinnerContext.$el); 16106 this.$gallery.height(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 16107 spinnerContext.intervalId = setInterval(function () { 16108 if (spinnerContext.phase < $spinnerPoints.length) { 16109 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 16110 } else {
vendor: 4,333 bytes, lines 16111-16255
16111 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 16112 } 16113 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 16114 }, spinnerContext.timeSlot); 16115 }; 16116 16117 /** 16118 * Rewind the image analysis to start from the first entry. 16119 */ 16120 JustifiedGallery.prototype.rewind = function () { 16121 this.lastFetchedEntry = null; 16122 this.lastAnalyzedIndex = -1; 16123 this.offY = this.border; 16124 this.rows = 0; 16125 this.clearBuildingRow(); 16126 }; 16127 16128 /** 16129 * Update the entries searching it from the justified gallery HTML element 16130 * 16131 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 16132 * @returns {boolean} true if some entries has been founded 16133 */ 16134 JustifiedGallery.prototype.updateEntries = function (norewind) { 16135 var newEntries; 16136 16137 if (norewind && this.lastFetchedEntry != null) { 16138 newEntries = $(this.lastFetchedEntry).nextAll(this.settings.selector).toArray(); 16139 } else { 16140 this.entries = []; 16141 newEntries = this.$gallery.children(this.settings.selector).toArray(); 16142 } 16143 16144 if (newEntries.length > 0) { 16145 16146 // Sort or randomize 16147 if ($.isFunction(this.settings.sort)) { 16148 newEntries = this.sortArray(newEntries); 16149 } else if (this.settings.randomize) { 16150 newEntries = this.shuffleArray(newEntries); 16151 } 16152 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 16153 16154 // Filter 16155 if (this.settings.filter) { 16156 newEntries = this.filterArray(newEntries); 16157 } else { 16158 this.resetFilters(newEntries); 16159 } 16160 16161 } 16162 16163 this.entries = this.entries.concat(newEntries); 16164 return true; 16165 }; 16166 16167 /** 16168 * Apply the entries order to the DOM, iterating the entries and appending the images 16169 * 16170 * @param entries the entries that has been modified and that must be re-ordered in the DOM 16171 */ 16172 JustifiedGallery.prototype.insertToGallery = function (entries) { 16173 var that = this; 16174 $.each(entries, function () { 16175 $(this).appendTo(that.$gallery); 16176 }); 16177 }; 16178 16179 /** 16180 * Shuffle the array using the Fisher-Yates shuffle algorithm 16181 * 16182 * @param a the array to shuffle 16183 * @return the shuffled array 16184 */ 16185 JustifiedGallery.prototype.shuffleArray = function (a) { 16186 var i, j, temp; 16187 for (i = a.length - 1; i > 0; i--) { 16188 j = Math.floor(Math.random() * (i + 1)); 16189 temp = a[i]; 16190 a[i] = a[j]; 16191 a[j] = temp; 16192 } 16193 this.insertToGallery(a); 16194 return a; 16195 }; 16196 16197 /** 16198 * Sort the array using settings.comparator as comparator 16199 * 16200 * @param a the array to sort (it is sorted) 16201 * @return the sorted array 16202 */ 16203 JustifiedGallery.prototype.sortArray = function (a) { 16204 a.sort(this.settings.sort); 16205 this.insertToGallery(a); 16206 return a; 16207 }; 16208 16209 /** 16210 * Reset the filters removing the 'jg-filtered' class from all the entries 16211 * 16212 * @param a the array to reset 16213 */ 16214 JustifiedGallery.prototype.resetFilters = function (a) { 16215 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 16216 }; 16217 16218 /** 16219 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 16220 * 16221 * @param a the array to filter 16222 * @return the filtered array 16223 */ 16224 JustifiedGallery.prototype.filterArray = function (a) { 16225 var settings = this.settings; 16226 if ($.type(settings.filter) === 'string') { 16227 // Filter only keeping the entries passed in the string 16228 return a.filter(function (el) { 16229 var $el = $(el); 16230 if ($el.is(settings.filter)) { 16231 $el.removeClass('jg-filtered'); 16232 return true; 16233 } else { 16234 $el.addClass('jg-filtered').removeClass('jg-visible'); 16235 return false; 16236 } 16237 }); 16238 } else if ($.isFunction(settings.filter)) { 16239 // Filter using the passed function 16240 var filteredArr = a.filter(settings.filter); 16241 for (var i = 0; i < a.length; i++) { 16242 if (filteredArr.indexOf(a[i]) == -1) { 16243 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 16244 } else { 16245 $(a[i]).removeClass('jg-filtered'); 16246 } 16247 } 16248 return filteredArr; 16249 } 16250 }; 16251 16252 /** 16253 * Destroy the Justified Gallery instance. 16254 * 16255 * It clears all the css properties added in the style attributes. We doesn't backup the original
16256 * values for those css attributes, because it costs (performance) and because in general one 16257 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 16258 * classes). Creating a backup is also difficult because JG could be called multiple times and 16259 * with different style attributes. 16260 */ 16261 JustifiedGallery.prototype.destroy = function () { 16262 clearInterval(this.checkWidthIntervalId); 16263 16264 $.each(this.entries, $.proxy(function(_, entry) { 16265 var $entry = $(entry); 16266 16267 // Reset entry style 16268 $entry.css('width', ''); 16269 $entry.css('height', ''); 16270 $entry.css('top', ''); 16271 $entry.css('left', ''); 16272 $entry.data('jg.loaded', undefined); 16273 $entry.removeClass('jg-entry'); 16274 16275 // Reset image style 16276 var $img = this.imgFromEntry($entry); 16277 $img.css('width', ''); 16278 $img.css('height', ''); 16279 $img.css('margin-left', ''); 16280 $img.css('margin-top', ''); 16281 $img.attr('src', $img.data('jg.originalSrc')); 16282 $img.data('jg.originalSrc', undefined); 16283 16284 // Remove caption 16285 this.removeCaptionEventsHandlers($entry); 16286 var $caption = this.captionFromEntry($entry); 16287 if ($entry.data('jg.createdCaption')) { 16288 // remove also the caption element (if created by jg) 16289 $entry.data('jg.createdCaption', undefined); 16290 if ($caption !== null) $caption.remove(); 16291 } else { 16292 if ($caption !== null) $caption.fadeTo(0, 1); 16293 } 16294 16295 }, this)); 16296 16297 this.$gallery.css('height', ''); 16298 this.$gallery.removeClass('justified-gallery'); 16299 this.$gallery.data('jg.controller', undefined); 16300 }; 16301 16302 /** 16303 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 16304 * 16305 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 16306 */ 16307 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 16308 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 16309 var $entry = $(this.entries[i]); 16310 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 16311 var availableWidth = this.galleryWidth - 2 * this.border - ( 16312 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 16313 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 16314 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 16315 this.flushRow(false); 16316 if(++this.yield.flushed >= this.yield.every) { 16317 this.startImgAnalyzer(isForResize); 16318 return; 16319 } 16320 } 16321 16322 this.buildingRow.entriesBuff.push($entry); 16323 this.buildingRow.aspectRatio += imgAspectRatio; 16324 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 16325 this.lastAnalyzedIndex = i; 16326 16327 } else if ($entry.data('jg.loaded') !== 'error') { 16328 return; 16329 } 16330 } 16331 16332 // Last row flush (the row is not full) 16333 if (this.buildingRow.entriesBuff.length > 0) this.flushRow(true); 16334 16335 if (this.isSpinnerActive()) { 16336 this.stopLoadingSpinnerAnimation(); 16337 } 16338 16339 /* Stop, if there is, the timeout to start the analyzeImages. 16340 This is because an image can be set loaded, and the timeout can be set, 16341 but this image can be analyzed yet. 16342 */ 16343 this.stopImgAnalyzerStarter(); 16344 16345 //On complete callback 16346 this.$gallery.trigger(isForResize ? 'jg.resize' : 'jg.complete'); 16347 this.$gallery.height(this.galleryHeightToSet); 16348 }; 16349 16350 /** 16351 * Stops any ImgAnalyzer starter (that has an assigned timeout) 16352 */ 16353 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 16354 this.yield.flushed = 0; 16355 if (this.imgAnalyzerTimeout !== null) clearTimeout(this.imgAnalyzerTimeout); 16356 }; 16357 16358 /** 16359 * Starts the image analyzer. It is not immediately called to let the browser to update the view 16360 * 16361 * @param isForResize specifies if the image analyzer must be called for resizing or not 16362 */ 16363 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 16364 var that = this; 16365 this.stopImgAnalyzerStarter(); 16366 this.imgAnalyzerTimeout = setTimeout(function () { 16367 that.analyzeImages(isForResize); 16368 }, 0.001); // we can't start it immediately due to a IE different behaviour 16369 }; 16370 16371 /** 16372 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 16373 * because some browsers, with a 404 set complete = true. 16374 * 16375 * @param imageSrc the image src to load 16376 * @param onLoad callback that is called when the image has been loaded
vendor: 13,320 bytes, lines 16377-16727
16377 * @param onError callback that is called in case of an error 16378 */ 16379 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 16380 if (!onLoad && !onError) return; 16381 16382 var memImage = new Image(); 16383 var $memImage = $(memImage); 16384 if (onLoad) { 16385 $memImage.one('load', function () { 16386 $memImage.off('load error'); 16387 onLoad(memImage); 16388 }); 16389 } 16390 if (onError) { 16391 $memImage.one('error', function() { 16392 $memImage.off('load error'); 16393 onError(memImage); 16394 }); 16395 } 16396 memImage.src = imageSrc; 16397 }; 16398 16399 /** 16400 * Init of Justified Gallery controlled 16401 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 16402 */ 16403 JustifiedGallery.prototype.init = function () { 16404 var imagesToLoad = false, skippedImages = false, that = this; 16405 $.each(this.entries, function (index, entry) { 16406 var $entry = $(entry); 16407 var $image = that.imgFromEntry($entry); 16408 16409 $entry.addClass('jg-entry'); 16410 16411 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 16412 16413 // Link Rel global overwrite 16414 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 16415 16416 // Link Target global overwrite 16417 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 16418 16419 if ($image !== null) { 16420 16421 // Image src 16422 var imageSrc = that.extractImgSrcFromImage($image); 16423 $image.attr('src', imageSrc); 16424 16425 /* If we have the height and the width, we don't wait that the image is loaded, but we start directly 16426 * with the justification */ 16427 if (that.settings.waitThumbnailsLoad === false) { 16428 var width = parseFloat($image.attr('width')); 16429 var height = parseFloat($image.attr('height')); 16430 if (!isNaN(width) && !isNaN(height)) { 16431 $entry.data('jg.width', width); 16432 $entry.data('jg.height', height); 16433 $entry.data('jg.loaded', 'skipped'); 16434 skippedImages = true; 16435 that.startImgAnalyzer(false); 16436 return true; // continue 16437 } 16438 } 16439 16440 $entry.data('jg.loaded', false); 16441 imagesToLoad = true; 16442 16443 // Spinner start 16444 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 16445 16446 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 16447 $entry.data('jg.width', loadImg.width); 16448 $entry.data('jg.height', loadImg.height); 16449 $entry.data('jg.loaded', true); 16450 that.startImgAnalyzer(false); 16451 }, function () { // image load error 16452 $entry.data('jg.loaded', 'error'); 16453 that.startImgAnalyzer(false); 16454 }); 16455 16456 } else { 16457 $entry.data('jg.loaded', true); 16458 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 16459 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 16460 } 16461 16462 } 16463 16464 }); 16465 16466 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 16467 this.checkWidth(); 16468 }; 16469 16470 /** 16471 * Checks that it is a valid number. If a string is passed it is converted to a number 16472 * 16473 * @param settingContainer the object that contains the setting (to allow the conversion) 16474 * @param settingName the setting name 16475 */ 16476 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 16477 if ($.type(settingContainer[settingName]) === 'string') { 16478 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 16479 } 16480 16481 if ($.type(settingContainer[settingName]) === 'number') { 16482 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 16483 } else { 16484 throw settingName + ' must be a number'; 16485 } 16486 }; 16487 16488 /** 16489 * Checks the sizeRangeSuffixes and, if necessary, converts 16490 * its keys from string (e.g. old settings with 'lt100') to int. 16491 */ 16492 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 16493 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 16494 throw 'sizeRangeSuffixes must be defined and must be an object'; 16495 } 16496 16497 var suffixRanges = []; 16498 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16499 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 16500 } 16501 16502 var newSizeRngSuffixes = {0: ''}; 16503 for (var i = 0; i < suffixRanges.length; i++) { 16504 if ($.type(suffixRanges[i]) === 'string') { 16505 try { 16506 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 16507 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16508 } catch (e) { 16509 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 16510 } 16511 } else { 16512 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16513 } 16514 } 16515 16516 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 16517 }; 16518 16519 /** 16520 * check and convert the maxRowHeight setting 16521 */ 16522 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 16523 var newMaxRowHeight = { }; 16524 16525 if ($.type(this.settings.maxRowHeight) === 'string') { 16526 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 16527 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 16528 newMaxRowHeight.isPercentage = false; 16529 } else { 16530 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight); 16531 newMaxRowHeight.isPercentage = true; 16532 } 16533 } else if ($.type(this.settings.maxRowHeight) === 'number') { 16534 newMaxRowHeight.value = this.settings.maxRowHeight; 16535 newMaxRowHeight.isPercentage = false; 16536 } else if (this.settings.maxRowHeight === false || 16537 this.settings.maxRowHeight === null || 16538 typeof this.settings.maxRowHeight == 'undefined') { 16539 return null; 16540 } else { 16541 throw 'maxRowHeight must be a number or a percentage'; 16542 } 16543 16544 // check if the converted value is not a number 16545 if (isNaN(newMaxRowHeight.value)) throw 'invalid number for maxRowHeight'; 16546 16547 // check values 16548 if (newMaxRowHeight.isPercentage) { 16549 if (newMaxRowHeight.value < 100) newMaxRowHeight.value = 100; 16550 } 16551 16552 return newMaxRowHeight; 16553 }; 16554 16555 /** 16556 * Checks the settings 16557 */ 16558 JustifiedGallery.prototype.checkSettings = function () { 16559 this.checkSizeRangesSuffixes(); 16560 16561 this.checkOrConvertNumber(this.settings, 'rowHeight'); 16562 this.checkOrConvertNumber(this.settings, 'margins'); 16563 this.checkOrConvertNumber(this.settings, 'border'); 16564 16565 var lastRowModes = [ 16566 'justify', 16567 'nojustify', 16568 'left', 16569 'center', 16570 'right', 16571 'hide' 16572 ]; 16573 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 16574 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 16575 } 16576 16577 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 16578 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 16579 throw 'justifyThreshold must be in the interval [0,1]'; 16580 } 16581 if ($.type(this.settings.cssAnimation) !== 'boolean') { 16582 throw 'cssAnimation must be a boolean'; 16583 } 16584 16585 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 16586 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 16587 16588 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 16589 if (this.settings.captionSettings.visibleOpacity < 0 || 16590 this.settings.captionSettings.visibleOpacity > 1) { 16591 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 16592 } 16593 16594 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 16595 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 16596 this.settings.captionSettings.nonVisibleOpacity > 1) { 16597 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 16598 } 16599 16600 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 16601 this.checkOrConvertNumber(this.settings, 'refreshTime'); 16602 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 16603 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 16604 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 16605 16606 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 16607 throw 'sort must be false or a comparison function'; 16608 } 16609 16610 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 16611 $.type(this.settings.filter) !== 'string') { 16612 throw 'filter must be false, a string or a filter function'; 16613 } 16614 }; 16615 16616 /** 16617 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 16618 * @returns {Array} sorted suffix ranges 16619 */ 16620 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 16621 var suffixRanges = []; 16622 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16623 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 16624 } 16625 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 16626 return suffixRanges; 16627 }; 16628 16629 /** 16630 * Update the existing settings only changing some of them 16631 * 16632 * @param newSettings the new settings (or a subgroup of them) 16633 */ 16634 JustifiedGallery.prototype.updateSettings = function (newSettings) { 16635 // In this case Justified Gallery has been called again changing only some options 16636 this.settings = $.extend({}, this.settings, newSettings); 16637 this.checkSettings(); 16638 16639 // As reported in the settings: negative value = same as margins, 0 = disabled 16640 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 16641 16642 this.maxRowHeight = this.retrieveMaxRowHeight(); 16643 this.suffixRanges = this.retrieveSuffixRanges(); 16644 }; 16645 16646 /** 16647 * Justified Gallery plugin for jQuery 16648 * 16649 * Events 16650 * - jg.complete : called when all the gallery has been created 16651 * - jg.resize : called when the gallery has been resized 16652 * - jg.rowflush : when a new row appears 16653 * 16654 * @param arg the action (or the settings) passed when the plugin is called 16655 * @returns {*} the object itself 16656 */ 16657 $.fn.justifiedGallery = function (arg) { 16658 return this.each(function (index, gallery) { 16659 16660 var $gallery = $(gallery); 16661 $gallery.addClass('justified-gallery'); 16662 16663 var controller = $gallery.data('jg.controller'); 16664 if (typeof controller === 'undefined') { 16665 // Create controller and assign it to the object data 16666 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 16667 if (arg === 'destroy') return; // Just a call to an unexisting object 16668 throw 'The argument must be an object'; 16669 } 16670 controller = new JustifiedGallery($gallery, $.extend({}, $.fn.justifiedGallery.defaults, arg)); 16671 $gallery.data('jg.controller', controller); 16672 } else if (arg === 'norewind') { 16673 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 16674 // ... left to be more readable 16675 } else if (arg === 'destroy') { 16676 controller.destroy(); 16677 return; 16678 } else { 16679 // In this case Justified Gallery has been called again changing only some options 16680 controller.updateSettings(arg); 16681 controller.rewind(); 16682 } 16683 16684 // Update the entries list 16685 if (!controller.updateEntries(arg === 'norewind')) return; 16686 16687 // Init justified gallery 16688 controller.init(); 16689 16690 }); 16691 }; 16692 16693 // Default options 16694 $.fn.justifiedGallery.defaults = { 16695 sizeRangeSuffixes: { }, /* e.g. Flickr configuration 16696 { 16697 100: '_t', // used when longest is less than 100px 16698 240: '_m', // used when longest is between 101px and 240px 16699 320: '_n', // ... 16700 500: '', 16701 640: '_z', 16702 1024: '_b' // used as else case because it is the last 16703 } 16704 */ 16705 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 16706 path relative to a specific thumbnail size. The function should accept respectively three arguments: 16707 current path, width and height */ 16708 rowHeight: 120, 16709 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 16710 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 16711 // can't exceed 3 * rowHeight) 16712 margins: 1, 16713 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 16714 16715 lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 16716 16717 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 16718 * (i.e. lastRow setting is not considered) */ 16719 waitThumbnailsLoad: true, 16720 captions: true, 16721 cssAnimation: true, 16722 imagesAnimationDuration: 500, // ignored with css animations 16723 captionSettings: { // ignored with css animations 16724 animationDuration: 500, 16725 visibleOpacity: 0.7, 16726 nonVisibleOpacity: 0.0 16727 },
vendor: 5,760 bytes, lines 16728-16871
16728 rel: null, // rewrite the rel of each analyzed links 16729 target: null, // rewrite the target of all links 16730 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 16731 refreshTime: 200, // time interval (in ms) to check if the page changes its width 16732 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 16733 randomize: false, 16734 sort: false, /* 16735 - false: to do not sort 16736 - function: to sort them using the function as comparator (see Array.prototype.sort()) 16737 */ 16738 filter: false, /* 16739 - false, null or undefined: for a disabled filter 16740 - a string: an entry is kept if entry.is(filter string) returns true 16741 see jQuery's .is() function for further information 16742 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 16743 It follows the specifications of the Array.prototype.filter() function of JavaScript. 16744 */ 16745 selector: 'a, div:not(.spinner)' // The selector that is used to know what are the entries of the gallery 16746 }; 16747 16748}(jQuery)); 16749 16750/*! 16751* Customized version of iScroll.js 0.0.1 16752* It fixes bugs affecting its integration with fullpage.js 16753*/ 16754/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 16755(function (window, document, Math) { 16756var rAF = window.requestAnimationFrame || 16757 window.webkitRequestAnimationFrame || 16758 window.mozRequestAnimationFrame || 16759 window.oRequestAnimationFrame || 16760 window.msRequestAnimationFrame || 16761 function (callback) { window.setTimeout(callback, 1000 / 60); }; 16762 16763var utils = (function () { 16764 var me = {}; 16765 16766 var _elementStyle = document.createElement('div').style; 16767 var _vendor = (function () { 16768 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 16769 transform, 16770 i = 0, 16771 l = vendors.length; 16772 16773 for ( ; i < l; i++ ) { 16774 transform = vendors[i] + 'ransform'; 16775 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 16776 } 16777 16778 return false; 16779 })(); 16780 16781 function _prefixStyle (style) { 16782 if ( _vendor === false ) return false; 16783 if ( _vendor === '' ) return style; 16784 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 16785 } 16786 16787 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 16788 16789 me.extend = function (target, obj) { 16790 for ( var i in obj ) { 16791 target[i] = obj[i]; 16792 } 16793 }; 16794 16795 me.addEvent = function (el, type, fn, capture) { 16796 el.addEventListener(type, fn, !!capture); 16797 }; 16798 16799 me.removeEvent = function (el, type, fn, capture) { 16800 el.removeEventListener(type, fn, !!capture); 16801 }; 16802 16803 me.prefixPointerEvent = function (pointerEvent) { 16804 return window.MSPointerEvent ? 16805 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 16806 pointerEvent; 16807 }; 16808 16809 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 16810 var distance = current - start, 16811 speed = Math.abs(distance) / time, 16812 destination, 16813 duration; 16814 16815 deceleration = deceleration === undefined ? 0.0006 : deceleration; 16816 16817 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 16818 duration = speed / deceleration; 16819 16820 if ( destination < lowerMargin ) { 16821 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 16822 distance = Math.abs(destination - current); 16823 duration = distance / speed; 16824 } else if ( destination > 0 ) { 16825 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 16826 distance = Math.abs(current) + destination; 16827 duration = distance / speed; 16828 } 16829 16830 return { 16831 destination: Math.round(destination), 16832 duration: duration 16833 }; 16834 }; 16835 16836 var _transform = _prefixStyle('transform'); 16837 16838 me.extend(me, { 16839 hasTransform: _transform !== false, 16840 hasPerspective: _prefixStyle('perspective') in _elementStyle, 16841 hasTouch: 'ontouchstart' in window, 16842 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 16843 hasTransition: _prefixStyle('transition') in _elementStyle 16844 }); 16845 16846 /* 16847 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 16848 - galaxy S2 is ok 16849 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 16850 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16851 - galaxy S3 is badAndroid (stock brower, webview) 16852 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16853 - galaxy S4 is badAndroid (stock brower, webview) 16854 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16855 - galaxy S5 is OK 16856 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16857 - galaxy S6 is OK 16858 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16859 */ 16860 me.isBadAndroid = (function() { 16861 var appVersion = window.navigator.appVersion; 16862 // Android browser is not a chrome browser. 16863 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 16864 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 16865 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 16866 return parseFloat(safariVersion[1]) < 535.19; 16867 } else { 16868 return true; 16869 } 16870 } else { 16871 return false;
vendor: 5,536 bytes, lines 16872-17064
16872 } 16873 })(); 16874 16875 me.extend(me.style = {}, { 16876 transform: _transform, 16877 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 16878 transitionDuration: _prefixStyle('transitionDuration'), 16879 transitionDelay: _prefixStyle('transitionDelay'), 16880 transformOrigin: _prefixStyle('transformOrigin') 16881 }); 16882 16883 me.hasClass = function (e, c) { 16884 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 16885 return re.test(e.className); 16886 }; 16887 16888 me.addClass = function (e, c) { 16889 if ( me.hasClass(e, c) ) { 16890 return; 16891 } 16892 16893 var newclass = e.className.split(' '); 16894 newclass.push(c); 16895 e.className = newclass.join(' '); 16896 }; 16897 16898 me.removeClass = function (e, c) { 16899 if ( !me.hasClass(e, c) ) { 16900 return; 16901 } 16902 16903 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 16904 e.className = e.className.replace(re, ' '); 16905 }; 16906 16907 me.offset = function (el) { 16908 var left = -el.offsetLeft, 16909 top = -el.offsetTop; 16910 16911 // jshint -W084 16912 while (el = el.offsetParent) { 16913 left -= el.offsetLeft; 16914 top -= el.offsetTop; 16915 } 16916 // jshint +W084 16917 16918 return { 16919 left: left, 16920 top: top 16921 }; 16922 }; 16923 16924 me.preventDefaultException = function (el, exceptions) { 16925 for ( var i in exceptions ) { 16926 if ( exceptions[i].test(el[i]) ) { 16927 return true; 16928 } 16929 } 16930 16931 return false; 16932 }; 16933 16934 me.extend(me.eventType = {}, { 16935 touchstart: 1, 16936 touchmove: 1, 16937 touchend: 1, 16938 16939 mousedown: 2, 16940 mousemove: 2, 16941 mouseup: 2, 16942 16943 pointerdown: 3, 16944 pointermove: 3, 16945 pointerup: 3, 16946 16947 MSPointerDown: 3, 16948 MSPointerMove: 3, 16949 MSPointerUp: 3 16950 }); 16951 16952 me.extend(me.ease = {}, { 16953 quadratic: { 16954 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 16955 fn: function (k) { 16956 return k * ( 2 - k ); 16957 } 16958 }, 16959 circular: { 16960 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) 16961 fn: function (k) { 16962 return Math.sqrt( 1 - ( --k * k ) ); 16963 } 16964 }, 16965 back: { 16966 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 16967 fn: function (k) { 16968 var b = 4; 16969 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 16970 } 16971 }, 16972 bounce: { 16973 style: '', 16974 fn: function (k) { 16975 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 16976 return 7.5625 * k * k; 16977 } else if ( k < ( 2 / 2.75 ) ) { 16978 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 16979 } else if ( k < ( 2.5 / 2.75 ) ) { 16980 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 16981 } else { 16982 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 16983 } 16984 } 16985 }, 16986 elastic: { 16987 style: '', 16988 fn: function (k) { 16989 var f = 0.22, 16990 e = 0.4; 16991 16992 if ( k === 0 ) { return 0; } 16993 if ( k == 1 ) { return 1; } 16994 16995 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 16996 } 16997 } 16998 }); 16999 17000 me.tap = function (e, eventName) { 17001 var ev = document.createEvent('Event'); 17002 ev.initEvent(eventName, true, true); 17003 ev.pageX = e.pageX; 17004 ev.pageY = e.pageY; 17005 e.target.dispatchEvent(ev); 17006 }; 17007 17008 me.click = function (e) { 17009 var target = e.target, 17010 ev; 17011 17012 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 17013 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 17014 // initMouseEvent is deprecated. 17015 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 17016 ev.initEvent('click', true, true); 17017 ev.view = e.view || window; 17018 ev.detail = 1; 17019 ev.screenX = target.screenX || 0; 17020 ev.screenY = target.screenY || 0; 17021 ev.clientX = target.clientX || 0; 17022 ev.clientY = target.clientY || 0; 17023 ev.ctrlKey = !!e.ctrlKey; 17024 ev.altKey = !!e.altKey; 17025 ev.shiftKey = !!e.shiftKey; 17026 ev.metaKey = !!e.metaKey; 17027 ev.button = 0; 17028 ev.relatedTarget = null; 17029 ev._constructed = true; 17030 target.dispatchEvent(ev); 17031 } 17032 }; 17033 17034 return me; 17035})(); 17036function IScroll (el, options) { 17037 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 17038 this.scroller = this.wrapper.children[0]; 17039 this.scrollerStyle = this.scroller.style; // cache style for better performance 17040 17041 this.options = { 17042 17043 resizeScrollbars: true, 17044 17045 mouseWheelSpeed: 20, 17046 17047 snapThreshold: 0.334, 17048 17049// INSERT POINT: OPTIONS 17050 disablePointer : !utils.hasPointer, 17051 disableTouch : utils.hasPointer || !utils.hasTouch, 17052 disableMouse : utils.hasPointer || utils.hasTouch, 17053 startX: 0, 17054 startY: 0, 17055 scrollY: true, 17056 directionLockThreshold: 5, 17057 momentum: true, 17058 17059 bounce: true, 17060 bounceTime: 600, 17061 bounceEasing: '', 17062 17063 preventDefault: true, 17064 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|
vendor: 4,420 bytes, lines 17064-17208
17064SELECT|LABEL)$/ }, 17065 17066 HWCompositing: true, 17067 useTransition: true, 17068 useTransform: true, 17069 bindToWrapper: typeof window.onmousedown === "undefined" 17070 }; 17071 17072 for ( var i in options ) { 17073 this.options[i] = options[i]; 17074 } 17075 17076 // Normalize options 17077 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 17078 17079 this.options.useTransition = utils.hasTransition && this.options.useTransition; 17080 this.options.useTransform = utils.hasTransform && this.options.useTransform; 17081 17082 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 17083 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 17084 17085 // If you want eventPassthrough I have to lock one of the axes 17086 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 17087 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 17088 17089 // With eventPassthrough we also need lockDirection mechanism 17090 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 17091 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 17092 17093 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 17094 17095 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 17096 17097 if ( this.options.tap === true ) { 17098 this.options.tap = 'tap'; 17099 } 17100 17101 // https://github.com/cubiq/iscroll/issues/1029 17102 if (!this.options.useTransition && !this.options.useTransform) { 17103 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 17104 this.scrollerStyle.position = "relative"; 17105 } 17106 } 17107 17108 if ( this.options.shrinkScrollbars == 'scale' ) { 17109 this.options.useTransition = false; 17110 } 17111 17112 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 17113 17114// INSERT POINT: NORMALIZATION 17115 17116 // Some defaults 17117 this.x = 0; 17118 this.y = 0; 17119 this.directionX = 0; 17120 this.directionY = 0; 17121 this._events = {}; 17122 17123// INSERT POINT: DEFAULTS 17124 17125 this._init(); 17126 this.refresh(); 17127 17128 this.scrollTo(this.options.startX, this.options.startY); 17129 this.enable(); 17130} 17131 17132IScroll.prototype = { 17133 version: '5.2.0', 17134 17135 _init: function () { 17136 this._initEvents(); 17137 17138 if ( this.options.scrollbars || this.options.indicators ) { 17139 this._initIndicators(); 17140 } 17141 17142 if ( this.options.mouseWheel ) { 17143 this._initWheel(); 17144 } 17145 17146 if ( this.options.snap ) { 17147 this._initSnap(); 17148 } 17149 17150 if ( this.options.keyBindings ) { 17151 this._initKeys(); 17152 } 17153 17154// INSERT POINT: _init 17155 17156 }, 17157 17158 destroy: function () { 17159 this._initEvents(true); 17160 clearTimeout(this.resizeTimeout); 17161 this.resizeTimeout = null; 17162 this._execEvent('destroy'); 17163 }, 17164 17165 _transitionEnd: function (e) { 17166 if ( e.target != this.scroller || !this.isInTransition ) { 17167 return; 17168 } 17169 17170 this._transitionTime(); 17171 if ( !this.resetPosition(this.options.bounceTime) ) { 17172 this.isInTransition = false; 17173 this._execEvent('scrollEnd'); 17174 } 17175 }, 17176 17177 _start: function (e) { 17178 // React to left mouse button only 17179 if ( utils.eventType[e.type] != 1 ) { 17180 // for button property 17181 // http://unixpapa.com/js/mouse.html 17182 var button; 17183 if (!e.which) { 17184 /* IE case */ 17185 button = (e.button < 2) ? 0 : 17186 ((e.button == 4) ? 1 : 2); 17187 } else { 17188 /* All others */ 17189 button = e.button; 17190 } 17191 if ( button !== 0 ) { 17192 return; 17193 } 17194 } 17195 17196 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 17197 return; 17198 } 17199 17200 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17201 e.preventDefault(); 17202 } 17203 17204 var point = e.touches ? e.touches[0] : e, 17205 pos; 17206 17207 this.initiated = utils.eventType[e.type]; 17208 this.moved = false;
vendor: 5,928 bytes, lines 17209-17387
17209 this.distX = 0; 17210 this.distY = 0; 17211 this.directionX = 0; 17212 this.directionY = 0; 17213 this.directionLocked = 0; 17214 17215 this.startTime = utils.getTime(); 17216 17217 if ( this.options.useTransition && this.isInTransition ) { 17218 this._transitionTime(); 17219 this.isInTransition = false; 17220 pos = this.getComputedPosition(); 17221 this._translate(Math.round(pos.x), Math.round(pos.y)); 17222 this._execEvent('scrollEnd'); 17223 } else if ( !this.options.useTransition && this.isAnimating ) { 17224 this.isAnimating = false; 17225 this._execEvent('scrollEnd'); 17226 } 17227 17228 this.startX = this.x; 17229 this.startY = this.y; 17230 this.absStartX = this.x; 17231 this.absStartY = this.y; 17232 this.pointX = point.pageX; 17233 this.pointY = point.pageY; 17234 17235 this._execEvent('beforeScrollStart'); 17236 }, 17237 17238 _move: function (e) { 17239 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17240 return; 17241 } 17242 17243 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 17244 e.preventDefault(); 17245 } 17246 17247 var point = e.touches ? e.touches[0] : e, 17248 deltaX = point.pageX - this.pointX, 17249 deltaY = point.pageY - this.pointY, 17250 timestamp = utils.getTime(), 17251 newX, newY, 17252 absDistX, absDistY; 17253 17254 this.pointX = point.pageX; 17255 this.pointY = point.pageY; 17256 17257 this.distX += deltaX; 17258 this.distY += deltaY; 17259 absDistX = Math.abs(this.distX); 17260 absDistY = Math.abs(this.distY); 17261 17262 // We need to move at least 10 pixels for the scrolling to initiate 17263 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 17264 return; 17265 } 17266 17267 // If you are scrolling in one direction lock the other 17268 if ( !this.directionLocked && !this.options.freeScroll ) { 17269 if ( absDistX > absDistY + this.options.directionLockThreshold ) { 17270 this.directionLocked = 'h'; // lock horizontally 17271 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 17272 this.directionLocked = 'v'; // lock vertically 17273 } else { 17274 this.directionLocked = 'n'; // no lock 17275 } 17276 } 17277 17278 if ( this.directionLocked == 'h' ) { 17279 if ( this.options.eventPassthrough == 'vertical' ) { 17280 e.preventDefault(); 17281 } else if ( this.options.eventPassthrough == 'horizontal' ) { 17282 this.initiated = false; 17283 return; 17284 } 17285 17286 deltaY = 0; 17287 } else if ( this.directionLocked == 'v' ) { 17288 if ( this.options.eventPassthrough == 'horizontal' ) { 17289 e.preventDefault(); 17290 } else if ( this.options.eventPassthrough == 'vertical' ) { 17291 this.initiated = false; 17292 return; 17293 } 17294 17295 deltaX = 0; 17296 } 17297 17298 deltaX = this.hasHorizontalScroll ? deltaX : 0; 17299 deltaY = this.hasVerticalScroll ? deltaY : 0; 17300 17301 newX = this.x + deltaX; 17302 newY = this.y + deltaY; 17303 17304 // Slow down if outside of the boundaries 17305 if ( newX > 0 || newX < this.maxScrollX ) { 17306 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 17307 } 17308 if ( newY > 0 || newY < this.maxScrollY ) { 17309 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 17310 } 17311 17312 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 17313 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 17314 17315 if ( !this.moved ) { 17316 this._execEvent('scrollStart'); 17317 } 17318 17319 this.moved = true; 17320 17321 this._translate(newX, newY); 17322 17323/* REPLACE START: _move */ 17324 17325 if ( timestamp - this.startTime > 300 ) { 17326 this.startTime = timestamp; 17327 this.startX = this.x; 17328 this.startY = this.y; 17329 } 17330 17331/* REPLACE END: _move */ 17332 17333 }, 17334 17335 _end: function (e) { 17336 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17337 return; 17338 } 17339 17340 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17341 e.preventDefault(); 17342 } 17343 17344 var point = e.changedTouches ? e.changedTouches[0] : e, 17345 momentumX, 17346 momentumY, 17347 duration = utils.getTime() - this.startTime, 17348 newX = Math.round(this.x), 17349 newY = Math.round(this.y), 17350 distanceX = Math.abs(newX - this.startX), 17351 distanceY = Math.abs(newY - this.startY), 17352 time = 0, 17353 easing = ''; 17354 17355 this.isInTransition = 0; 17356 this.initiated = 0; 17357 this.endTime = utils.getTime(); 17358 17359 // reset if we are outside of the boundaries 17360 if ( this.resetPosition(this.options.bounceTime) ) { 17361 return; 17362 } 17363 17364 this.scrollTo(newX, newY); // ensures that the last position is rounded 17365 17366 // we scrolled less than 10 pixels 17367 if ( !this.moved ) { 17368 if ( this.options.tap ) { 17369 utils.tap(e, this.options.tap); 17370 } 17371 17372 if ( this.options.click ) { 17373 utils.click(e); 17374 } 17375 17376 this._execEvent('scrollCancel'); 17377 return; 17378 } 17379 17380 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 17381 this._execEvent('flick'); 17382 return; 17383 } 17384 17385 // start momentum animation if needed 17386 if ( this.options.momentum && duration < 300 ) { 17387 momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperW
vendor: 7,740 bytes, lines 17387-17660
17387idth : 0, this.options.deceleration) : { destination: newX, duration: 0 }; 17388 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 }; 17389 newX = momentumX.destination; 17390 newY = momentumY.destination; 17391 time = Math.max(momentumX.duration, momentumY.duration); 17392 this.isInTransition = 1; 17393 } 17394 17395 17396 if ( this.options.snap ) { 17397 var snap = this._nearestSnap(newX, newY); 17398 this.currentPage = snap; 17399 time = this.options.snapSpeed || Math.max( 17400 Math.max( 17401 Math.min(Math.abs(newX - snap.x), 1000), 17402 Math.min(Math.abs(newY - snap.y), 1000) 17403 ), 300); 17404 newX = snap.x; 17405 newY = snap.y; 17406 17407 this.directionX = 0; 17408 this.directionY = 0; 17409 easing = this.options.bounceEasing; 17410 } 17411 17412// INSERT POINT: _end 17413 17414 if ( newX != this.x || newY != this.y ) { 17415 // change easing function when scroller goes out of the boundaries 17416 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 17417 easing = utils.ease.quadratic; 17418 } 17419 17420 this.scrollTo(newX, newY, time, easing); 17421 return; 17422 } 17423 17424 this._execEvent('scrollEnd'); 17425 }, 17426 17427 _resize: function () { 17428 var that = this; 17429 17430 clearTimeout(this.resizeTimeout); 17431 17432 this.resizeTimeout = setTimeout(function () { 17433 that.refresh(); 17434 }, this.options.resizePolling); 17435 }, 17436 17437 resetPosition: function (time) { 17438 var x = this.x, 17439 y = this.y; 17440 17441 time = time || 0; 17442 17443 if ( !this.hasHorizontalScroll || this.x > 0 ) { 17444 x = 0; 17445 } else if ( this.x < this.maxScrollX ) { 17446 x = this.maxScrollX; 17447 } 17448 17449 if ( !this.hasVerticalScroll || this.y > 0 ) { 17450 y = 0; 17451 } else if ( this.y < this.maxScrollY ) { 17452 y = this.maxScrollY; 17453 } 17454 17455 if ( x == this.x && y == this.y ) { 17456 return false; 17457 } 17458 17459 this.scrollTo(x, y, time, this.options.bounceEasing); 17460 17461 return true; 17462 }, 17463 17464 disable: function () { 17465 this.enabled = false; 17466 }, 17467 17468 enable: function () { 17469 this.enabled = true; 17470 }, 17471 17472 refresh: function () { 17473 var rf = this.wrapper.offsetHeight; // Force reflow 17474 17475 this.wrapperWidth = this.wrapper.clientWidth; 17476 this.wrapperHeight = this.wrapper.clientHeight; 17477 17478/* REPLACE START: refresh */ 17479 17480 this.scrollerWidth = this.scroller.offsetWidth; 17481 this.scrollerHeight = this.scroller.offsetHeight; 17482 17483 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 17484 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 17485 17486/* REPLACE END: refresh */ 17487 17488 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 17489 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 17490 17491 if ( !this.hasHorizontalScroll ) { 17492 this.maxScrollX = 0; 17493 this.scrollerWidth = this.wrapperWidth; 17494 } 17495 17496 if ( !this.hasVerticalScroll ) { 17497 this.maxScrollY = 0; 17498 this.scrollerHeight = this.wrapperHeight; 17499 } 17500 17501 this.endTime = 0; 17502 this.directionX = 0; 17503 this.directionY = 0; 17504 17505 this.wrapperOffset = utils.offset(this.wrapper); 17506 17507 this._execEvent('refresh'); 17508 17509 this.resetPosition(); 17510 17511// INSERT POINT: _refresh 17512 17513 }, 17514 17515 on: function (type, fn) { 17516 if ( !this._events[type] ) { 17517 this._events[type] = []; 17518 } 17519 17520 this._events[type].push(fn); 17521 }, 17522 17523 off: function (type, fn) { 17524 if ( !this._events[type] ) { 17525 return; 17526 } 17527 17528 var index = this._events[type].indexOf(fn); 17529 17530 if ( index > -1 ) { 17531 this._events[type].splice(index, 1); 17532 } 17533 }, 17534 17535 _execEvent: function (type) { 17536 if ( !this._events[type] ) { 17537 return; 17538 } 17539 17540 var i = 0, 17541 l = this._events[type].length; 17542 17543 if ( !l ) { 17544 return; 17545 } 17546 17547 for ( ; i < l; i++ ) { 17548 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 17549 } 17550 }, 17551 17552 scrollBy: function (x, y, time, easing) { 17553 x = this.x + x; 17554 y = this.y + y; 17555 time = time || 0; 17556 17557 this.scrollTo(x, y, time, easing); 17558 }, 17559 17560 scrollTo: function (x, y, time, easing) { 17561 easing = easing || utils.ease.circular; 17562 17563 this.isInTransition = this.options.useTransition && time > 0; 17564 var transitionType = this.options.useTransition && easing.style; 17565 if ( !time || transitionType ) { 17566 if(transitionType) { 17567 this._transitionTimingFunction(easing.style); 17568 this._transitionTime(time); 17569 } 17570 this._translate(x, y); 17571 } else { 17572 this._animate(x, y, time, easing.fn); 17573 } 17574 }, 17575 17576 scrollToElement: function (el, time, offsetX, offsetY, easing) { 17577 el = el.nodeType ? el : this.scroller.querySelector(el); 17578 17579 if ( !el ) { 17580 return; 17581 } 17582 17583 var pos = utils.offset(el); 17584 17585 pos.left -= this.wrapperOffset.left; 17586 pos.top -= this.wrapperOffset.top; 17587 17588 // if offsetX/Y are true we center the element to the screen 17589 if ( offsetX === true ) { 17590 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 17591 } 17592 if ( offsetY === true ) { 17593 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 17594 } 17595 17596 pos.left -= offsetX || 0; 17597 pos.top -= offsetY || 0; 17598 17599 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 17600 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 17601 17602 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 17603 17604 this.scrollTo(pos.left, pos.top, time, easing); 17605 }, 17606 17607 _transitionTime: function (time) { 17608 if (!this.options.useTransition) { 17609 return; 17610 } 17611 time = time || 0; 17612 var durationProp = utils.style.transitionDuration; 17613 if(!durationProp) { 17614 return; 17615 } 17616 17617 this.scrollerStyle[durationProp] = time + 'ms'; 17618 17619 if ( !time && utils.isBadAndroid ) { 17620 this.scrollerStyle[durationProp] = '0.0001ms'; 17621 // remove 0.0001ms 17622 var self = this; 17623 rAF(function() { 17624 if(self.scrollerStyle[durationProp] === '0.0001ms') { 17625 self.scrollerStyle[durationProp] = '0s'; 17626 } 17627 }); 17628 } 17629 17630 17631 if ( this.indicators ) { 17632 for ( var i = this.indicators.length; i--; ) { 17633 this.indicators[i].transitionTime(time); 17634 } 17635 } 17636 17637 17638// INSERT POINT: _transitionTime 17639 17640 }, 17641 17642 _transitionTimingFunction: function (easing) { 17643 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 17644 17645 17646 if ( this.indicators ) { 17647 for ( var i = this.indicators.length; i--; ) { 17648 this.indicators[i].transitionTimingFunction(easing); 17649 } 17650 } 17651 17652 17653// INSERT POINT: _transitionTimingFunction 17654 17655 }, 17656 17657 _translate: function (x, y) { 17658 //Uncode addition 17659 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 17660 return false;
vendor: 9,940 bytes, lines 17661-17972
17661 17662 if ( this.options.useTransform ) { 17663 17664/* REPLACE START: _translate */ 17665 17666 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 17667 17668/* REPLACE END: _translate */ 17669 17670 } else { 17671 x = Math.round(x); 17672 y = Math.round(y); 17673 this.scrollerStyle.left = x + 'px'; 17674 this.scrollerStyle.top = y + 'px'; 17675 } 17676 17677 this.x = x; 17678 this.y = y; 17679 17680 17681 if ( this.indicators ) { 17682 for ( var i = this.indicators.length; i--; ) { 17683 this.indicators[i].updatePosition(); 17684 } 17685 } 17686 17687 //Uncode addition 17688 var uncodevent = new Event('fp-slide-scroll'); 17689 window.dispatchEvent(uncodevent); 17690 17691// INSERT POINT: _translate 17692 17693 }, 17694 17695 _initEvents: function (remove) { 17696 var eventType = remove ? utils.removeEvent : utils.addEvent, 17697 target = this.options.bindToWrapper ? this.wrapper : window; 17698 17699 eventType(window, 'orientationchange', this); 17700 eventType(window, 'resize', this); 17701 17702 if ( this.options.click ) { 17703 eventType(this.wrapper, 'click', this, true); 17704 } 17705 17706 if ( !this.options.disableMouse ) { 17707 eventType(this.wrapper, 'mousedown', this); 17708 eventType(target, 'mousemove', this); 17709 eventType(target, 'mousecancel', this); 17710 eventType(target, 'mouseup', this); 17711 } 17712 17713 if ( utils.hasPointer && !this.options.disablePointer ) { 17714 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 17715 eventType(target, utils.prefixPointerEvent('pointermove'), this); 17716 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 17717 eventType(target, utils.prefixPointerEvent('pointerup'), this); 17718 } 17719 17720 if ( utils.hasTouch && !this.options.disableTouch ) { 17721 eventType(this.wrapper, 'touchstart', this); 17722 eventType(target, 'touchmove', this); 17723 eventType(target, 'touchcancel', this); 17724 eventType(target, 'touchend', this); 17725 } 17726 17727 eventType(this.scroller, 'transitionend', this); 17728 eventType(this.scroller, 'webkitTransitionEnd', this); 17729 eventType(this.scroller, 'oTransitionEnd', this); 17730 eventType(this.scroller, 'MSTransitionEnd', this); 17731 }, 17732 17733 getComputedPosition: function () { 17734 var matrix = window.getComputedStyle(this.scroller, null), 17735 x, y; 17736 17737 if ( this.options.useTransform ) { 17738 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 17739 x = +(matrix[12] || matrix[4]); 17740 y = +(matrix[13] || matrix[5]); 17741 } else { 17742 x = +matrix.left.replace(/[^-\d.]/g, ''); 17743 y = +matrix.top.replace(/[^-\d.]/g, ''); 17744 } 17745 17746 return { x: x, y: y }; 17747 }, 17748 _initIndicators: function () { 17749 var interactive = this.options.interactiveScrollbars, 17750 customStyle = typeof this.options.scrollbars != 'string', 17751 indicators = [], 17752 indicator; 17753 17754 var that = this; 17755 17756 this.indicators = []; 17757 17758 if ( this.options.scrollbars ) { 17759 // Vertical scrollbar 17760 if ( this.options.scrollY ) { 17761 indicator = { 17762 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 17763 interactive: interactive, 17764 defaultScrollbars: true, 17765 customStyle: customStyle, 17766 resize: this.options.resizeScrollbars, 17767 shrink: this.options.shrinkScrollbars, 17768 fade: this.options.fadeScrollbars, 17769 listenX: false 17770 }; 17771 17772 this.wrapper.appendChild(indicator.el); 17773 indicators.push(indicator); 17774 } 17775 17776 // Horizontal scrollbar 17777 if ( this.options.scrollX ) { 17778 indicator = { 17779 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 17780 interactive: interactive, 17781 defaultScrollbars: true, 17782 customStyle: customStyle, 17783 resize: this.options.resizeScrollbars, 17784 shrink: this.options.shrinkScrollbars, 17785 fade: this.options.fadeScrollbars, 17786 listenY: false 17787 }; 17788 17789 this.wrapper.appendChild(indicator.el); 17790 indicators.push(indicator); 17791 } 17792 } 17793 17794 if ( this.options.indicators ) { 17795 // TODO: check concat compatibility 17796 indicators = indicators.concat(this.options.indicators); 17797 } 17798 17799 for ( var i = indicators.length; i--; ) { 17800 this.indicators.push( new Indicator(this, indicators[i]) ); 17801 } 17802 17803 // TODO: check if we can use array.map (wide compatibility and performance issues) 17804 function _indicatorsMap (fn) { 17805 if (that.indicators) { 17806 for ( var i = that.indicators.length; i--; ) { 17807 fn.call(that.indicators[i]); 17808 } 17809 } 17810 } 17811 17812 if ( this.options.fadeScrollbars ) { 17813 this.on('scrollEnd', function () { 17814 _indicatorsMap(function () { 17815 this.fade(); 17816 }); 17817 }); 17818 17819 this.on('scrollCancel', function () { 17820 _indicatorsMap(function () { 17821 this.fade(); 17822 }); 17823 }); 17824 17825 this.on('scrollStart', function () { 17826 _indicatorsMap(function () { 17827 this.fade(1); 17828 }); 17829 }); 17830 17831 this.on('beforeScrollStart', function () { 17832 _indicatorsMap(function () { 17833 this.fade(1, true); 17834 }); 17835 }); 17836 } 17837 17838 17839 this.on('refresh', function () { 17840 _indicatorsMap(function () { 17841 this.refresh(); 17842 }); 17843 }); 17844 17845 this.on('destroy', function () { 17846 _indicatorsMap(function () { 17847 this.destroy(); 17848 }); 17849 17850 delete this.indicators; 17851 }); 17852 }, 17853 17854 _initWheel: function () { 17855 utils.addEvent(this.wrapper, 'wheel', this); 17856 utils.addEvent(this.wrapper, 'mousewheel', this); 17857 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 17858 17859 this.on('destroy', function () { 17860 clearTimeout(this.wheelTimeout); 17861 this.wheelTimeout = null; 17862 utils.removeEvent(this.wrapper, 'wheel', this); 17863 utils.removeEvent(this.wrapper, 'mousewheel', this); 17864 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 17865 }); 17866 }, 17867 17868 _wheel: function (e) { 17869 if ( !this.enabled ) { 17870 return; 17871 } 17872 17873 var wheelDeltaX, wheelDeltaY, 17874 newX, newY, 17875 that = this; 17876 17877 if ( this.wheelTimeout === undefined ) { 17878 that._execEvent('scrollStart'); 17879 } 17880 17881 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 17882 clearTimeout(this.wheelTimeout); 17883 this.wheelTimeout = setTimeout(function () { 17884 if(!that.options.snap) { 17885 that._execEvent('scrollEnd'); 17886 } 17887 that.wheelTimeout = undefined; 17888 }, 400); 17889 17890 if ( 'deltaX' in e ) { 17891 if (e.deltaMode === 1) { 17892 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 17893 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 17894 } else { 17895 wheelDeltaX = -e.deltaX; 17896 wheelDeltaY = -e.deltaY; 17897 } 17898 } else if ( 'wheelDeltaX' in e ) { 17899 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 17900 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 17901 } else if ( 'wheelDelta' in e ) { 17902 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 17903 } else if ( 'detail' in e ) { 17904 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 17905 } else { 17906 return; 17907 } 17908 17909 wheelDeltaX *= this.options.invertWheelDirection; 17910 wheelDeltaY *= this.options.invertWheelDirection; 17911 17912 if ( !this.hasVerticalScroll ) { 17913 wheelDeltaX = wheelDeltaY; 17914 wheelDeltaY = 0; 17915 } 17916 17917 if ( this.options.snap ) { 17918 newX = this.currentPage.pageX; 17919 newY = this.currentPage.pageY; 17920 17921 if ( wheelDeltaX > 0 ) { 17922 newX--; 17923 } else if ( wheelDeltaX < 0 ) { 17924 newX++; 17925 } 17926 17927 if ( wheelDeltaY > 0 ) { 17928 newY--; 17929 } else if ( wheelDeltaY < 0 ) { 17930 newY++; 17931 } 17932 17933 this.goToPage(newX, newY); 17934 17935 return; 17936 } 17937 17938 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 17939 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 17940 17941 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 17942 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 17943 17944 if ( newX > 0 ) { 17945 newX = 0; 17946 } else if ( newX < this.maxScrollX ) { 17947 newX = this.maxScrollX; 17948 } 17949 17950 if ( newY > 0 ) { 17951 newY = 0; 17952 } else if ( newY < this.maxScrollY ) { 17953 newY = this.maxScrollY; 17954 } 17955 17956 this.scrollTo(newX, newY, 0); 17957 17958// INSERT POINT: _wheel 17959 }, 17960 17961 _initSnap: function () { 17962 this.currentPage = {}; 17963 17964 if ( typeof this.options.snap == 'string' ) { 17965 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 17966 } 17967 17968 this.on('refresh', function () { 17969 var i = 0, l, 17970 m = 0, n, 17971 cx, cy, 17972 x = 0, y,
vendor: 7,339 bytes, lines 17973-18226
17973 stepX = this.options.snapStepX || this.wrapperWidth, 17974 stepY = this.options.snapStepY || this.wrapperHeight, 17975 el; 17976 17977 this.pages = []; 17978 17979 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 17980 return; 17981 } 17982 17983 if ( this.options.snap === true ) { 17984 cx = Math.round( stepX / 2 ); 17985 cy = Math.round( stepY / 2 ); 17986 17987 while ( x > -this.scrollerWidth ) { 17988 this.pages[i] = []; 17989 l = 0; 17990 y = 0; 17991 17992 while ( y > -this.scrollerHeight ) { 17993 this.pages[i][l] = { 17994 x: Math.max(x, this.maxScrollX), 17995 y: Math.max(y, this.maxScrollY), 17996 width: stepX, 17997 height: stepY, 17998 cx: x - cx, 17999 cy: y - cy 18000 }; 18001 18002 y -= stepY; 18003 l++; 18004 } 18005 18006 x -= stepX; 18007 i++; 18008 } 18009 } else { 18010 el = this.options.snap; 18011 l = el.length; 18012 n = -1; 18013 18014 for ( ; i < l; i++ ) { 18015 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 18016 m = 0; 18017 n++; 18018 } 18019 18020 if ( !this.pages[m] ) { 18021 this.pages[m] = []; 18022 } 18023 18024 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 18025 y = Math.max(-el[i].offsetTop, this.maxScrollY); 18026 cx = x - Math.round(el[i].offsetWidth / 2); 18027 cy = y - Math.round(el[i].offsetHeight / 2); 18028 18029 this.pages[m][n] = { 18030 x: x, 18031 y: y, 18032 width: el[i].offsetWidth, 18033 height: el[i].offsetHeight, 18034 cx: cx, 18035 cy: cy 18036 }; 18037 18038 if ( x > this.maxScrollX ) { 18039 m++; 18040 } 18041 } 18042 } 18043 18044 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 18045 18046 // Update snap threshold if needed 18047 if ( this.options.snapThreshold % 1 === 0 ) { 18048 this.snapThresholdX = this.options.snapThreshold; 18049 this.snapThresholdY = this.options.snapThreshold; 18050 } else { 18051 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 18052 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 18053 } 18054 }); 18055 18056 this.on('flick', function () { 18057 var time = this.options.snapSpeed || Math.max( 18058 Math.max( 18059 Math.min(Math.abs(this.x - this.startX), 1000), 18060 Math.min(Math.abs(this.y - this.startY), 1000) 18061 ), 300); 18062 18063 this.goToPage( 18064 this.currentPage.pageX + this.directionX, 18065 this.currentPage.pageY + this.directionY, 18066 time 18067 ); 18068 }); 18069 }, 18070 18071 _nearestSnap: function (x, y) { 18072 if ( !this.pages.length ) { 18073 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 18074 } 18075 18076 var i = 0, 18077 l = this.pages.length, 18078 m = 0; 18079 18080 // Check if we exceeded the snap threshold 18081 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 18082 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 18083 return this.currentPage; 18084 } 18085 18086 if ( x > 0 ) { 18087 x = 0; 18088 } else if ( x < this.maxScrollX ) { 18089 x = this.maxScrollX; 18090 } 18091 18092 if ( y > 0 ) { 18093 y = 0; 18094 } else if ( y < this.maxScrollY ) { 18095 y = this.maxScrollY; 18096 } 18097 18098 for ( ; i < l; i++ ) { 18099 if ( x >= this.pages[i][0].cx ) { 18100 x = this.pages[i][0].x; 18101 break; 18102 } 18103 } 18104 18105 l = this.pages[i].length; 18106 18107 for ( ; m < l; m++ ) { 18108 if ( y >= this.pages[0][m].cy ) { 18109 y = this.pages[0][m].y; 18110 break; 18111 } 18112 } 18113 18114 if ( i == this.currentPage.pageX ) { 18115 i += this.directionX; 18116 18117 if ( i < 0 ) { 18118 i = 0; 18119 } else if ( i >= this.pages.length ) { 18120 i = this.pages.length - 1; 18121 } 18122 18123 x = this.pages[i][0].x; 18124 } 18125 18126 if ( m == this.currentPage.pageY ) { 18127 m += this.directionY; 18128 18129 if ( m < 0 ) { 18130 m = 0; 18131 } else if ( m >= this.pages[0].length ) { 18132 m = this.pages[0].length - 1; 18133 } 18134 18135 y = this.pages[0][m].y; 18136 } 18137 18138 return { 18139 x: x, 18140 y: y, 18141 pageX: i, 18142 pageY: m 18143 }; 18144 }, 18145 18146 goToPage: function (x, y, time, easing) { 18147 easing = easing || this.options.bounceEasing; 18148 18149 if ( x >= this.pages.length ) { 18150 x = this.pages.length - 1; 18151 } else if ( x < 0 ) { 18152 x = 0; 18153 } 18154 18155 if ( y >= this.pages[x].length ) { 18156 y = this.pages[x].length - 1; 18157 } else if ( y < 0 ) { 18158 y = 0; 18159 } 18160 18161 var posX = this.pages[x][y].x, 18162 posY = this.pages[x][y].y; 18163 18164 time = time === undefined ? this.options.snapSpeed || Math.max( 18165 Math.max( 18166 Math.min(Math.abs(posX - this.x), 1000), 18167 Math.min(Math.abs(posY - this.y), 1000) 18168 ), 300) : time; 18169 18170 this.currentPage = { 18171 x: posX, 18172 y: posY, 18173 pageX: x, 18174 pageY: y 18175 }; 18176 18177 this.scrollTo(posX, posY, time, easing); 18178 }, 18179 18180 next: function (time, easing) { 18181 var x = this.currentPage.pageX, 18182 y = this.currentPage.pageY; 18183 18184 x++; 18185 18186 if ( x >= this.pages.length && this.hasVerticalScroll ) { 18187 x = 0; 18188 y++; 18189 } 18190 18191 this.goToPage(x, y, time, easing); 18192 }, 18193 18194 prev: function (time, easing) { 18195 var x = this.currentPage.pageX, 18196 y = this.currentPage.pageY; 18197 18198 x--; 18199 18200 if ( x < 0 && this.hasVerticalScroll ) { 18201 x = 0; 18202 y--; 18203 } 18204 18205 this.goToPage(x, y, time, easing); 18206 }, 18207 18208 _initKeys: function (e) { 18209 // default key bindings 18210 var keys = { 18211 pageUp: 33, 18212 pageDown: 34, 18213 end: 35, 18214 home: 36, 18215 left: 37, 18216 up: 38, 18217 right: 39, 18218 down: 40 18219 }; 18220 var i; 18221 18222 // if you give me characters I give you keycode 18223 if ( typeof this.options.keyBindings == 'object' ) { 18224 for ( i in this.options.keyBindings ) { 18225 if ( typeof this.options.keyBindings[i] == 'string' ) { 18226 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 18226-18579
18226deAt(0); 18227 } 18228 } 18229 } else { 18230 this.options.keyBindings = {}; 18231 } 18232 18233 for ( i in keys ) { 18234 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 18235 } 18236 18237 utils.addEvent(window, 'keydown', this); 18238 18239 this.on('destroy', function () { 18240 utils.removeEvent(window, 'keydown', this); 18241 }); 18242 }, 18243 18244 _key: function (e) { 18245 if ( !this.enabled ) { 18246 return; 18247 } 18248 18249 var snap = this.options.snap, // we are using this alot, better to cache it 18250 newX = snap ? this.currentPage.pageX : this.x, 18251 newY = snap ? this.currentPage.pageY : this.y, 18252 now = utils.getTime(), 18253 prevTime = this.keyTime || 0, 18254 acceleration = 0.250, 18255 pos; 18256 18257 if ( this.options.useTransition && this.isInTransition ) { 18258 pos = this.getComputedPosition(); 18259 18260 this._translate(Math.round(pos.x), Math.round(pos.y)); 18261 this.isInTransition = false; 18262 } 18263 18264 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 18265 18266 switch ( e.keyCode ) { 18267 case this.options.keyBindings.pageUp: 18268 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18269 newX += snap ? 1 : this.wrapperWidth; 18270 } else { 18271 newY += snap ? 1 : this.wrapperHeight; 18272 } 18273 break; 18274 case this.options.keyBindings.pageDown: 18275 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18276 newX -= snap ? 1 : this.wrapperWidth; 18277 } else { 18278 newY -= snap ? 1 : this.wrapperHeight; 18279 } 18280 break; 18281 case this.options.keyBindings.end: 18282 newX = snap ? this.pages.length-1 : this.maxScrollX; 18283 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 18284 break; 18285 case this.options.keyBindings.home: 18286 newX = 0; 18287 newY = 0; 18288 break; 18289 case this.options.keyBindings.left: 18290 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 18291 break; 18292 case this.options.keyBindings.up: 18293 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 18294 break; 18295 case this.options.keyBindings.right: 18296 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 18297 break; 18298 case this.options.keyBindings.down: 18299 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 18300 break; 18301 default: 18302 return; 18303 } 18304 18305 if ( snap ) { 18306 this.goToPage(newX, newY); 18307 return; 18308 } 18309 18310 if ( newX > 0 ) { 18311 newX = 0; 18312 this.keyAcceleration = 0; 18313 } else if ( newX < this.maxScrollX ) { 18314 newX = this.maxScrollX; 18315 this.keyAcceleration = 0; 18316 } 18317 18318 if ( newY > 0 ) { 18319 newY = 0; 18320 this.keyAcceleration = 0; 18321 } else if ( newY < this.maxScrollY ) { 18322 newY = this.maxScrollY; 18323 this.keyAcceleration = 0; 18324 } 18325 18326 this.scrollTo(newX, newY, 0); 18327 18328 this.keyTime = now; 18329 }, 18330 18331 _animate: function (destX, destY, duration, easingFn) { 18332 var that = this, 18333 startX = this.x, 18334 startY = this.y, 18335 startTime = utils.getTime(), 18336 destTime = startTime + duration; 18337 18338 function step () { 18339 var now = utils.getTime(), 18340 newX, newY, 18341 easing; 18342 18343 if ( now >= destTime ) { 18344 that.isAnimating = false; 18345 that._translate(destX, destY); 18346 18347 if ( !that.resetPosition(that.options.bounceTime) ) { 18348 that._execEvent('scrollEnd'); 18349 } 18350 18351 return; 18352 } 18353 18354 now = ( now - startTime ) / duration; 18355 easing = easingFn(now); 18356 newX = ( destX - startX ) * easing + startX; 18357 newY = ( destY - startY ) * easing + startY; 18358 that._translate(newX, newY); 18359 18360 if ( that.isAnimating ) { 18361 rAF(step); 18362 } 18363 } 18364 18365 this.isAnimating = true; 18366 step(); 18367 }, 18368 handleEvent: function (e) { 18369 switch ( e.type ) { 18370 case 'touchstart': 18371 case 'pointerdown': 18372 case 'MSPointerDown': 18373 case 'mousedown': 18374 this._start(e); 18375 break; 18376 case 'touchmove': 18377 case 'pointermove': 18378 case 'MSPointerMove': 18379 case 'mousemove': 18380 this._move(e); 18381 break; 18382 case 'touchend': 18383 case 'pointerup': 18384 case 'MSPointerUp': 18385 case 'mouseup': 18386 case 'touchcancel': 18387 case 'pointercancel': 18388 case 'MSPointerCancel': 18389 case 'mousecancel': 18390 this._end(e); 18391 break; 18392 case 'orientationchange': 18393 case 'resize': 18394 this._resize(); 18395 break; 18396 case 'transitionend': 18397 case 'webkitTransitionEnd': 18398 case 'oTransitionEnd': 18399 case 'MSTransitionEnd': 18400 this._transitionEnd(e); 18401 break; 18402 case 'wheel': 18403 case 'DOMMouseScroll': 18404 case 'mousewheel': 18405 this._wheel(e); 18406 break; 18407 case 'keydown': 18408 this._key(e); 18409 break; 18410 case 'click': 18411 if ( this.enabled && !e._constructed ) { 18412 e.preventDefault(); 18413 e.stopPropagation(); 18414 } 18415 break; 18416 } 18417 } 18418}; 18419function createDefaultScrollbar (direction, interactive, type) { 18420 var scrollbar = document.createElement('div'), 18421 indicator = document.createElement('div'); 18422 18423 if ( type === true ) { 18424 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 18425 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'; 18426 } 18427 18428 indicator.className = 'iScrollIndicator'; 18429 18430 if ( direction == 'h' ) { 18431 if ( type === true ) { 18432 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 18433 indicator.style.height = '100%'; 18434 } 18435 scrollbar.className = 'iScrollHorizontalScrollbar'; 18436 } else { 18437 if ( type === true ) { 18438 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 18439 indicator.style.width = '100%'; 18440 } 18441 scrollbar.className = 'iScrollVerticalScrollbar'; 18442 } 18443 18444 scrollbar.style.cssText += ';overflow:hidden'; 18445 18446 if ( !interactive ) { 18447 scrollbar.style.pointerEvents = 'none'; 18448 } 18449 18450 scrollbar.appendChild(indicator); 18451 18452 return scrollbar; 18453} 18454 18455function Indicator (scroller, options) { 18456 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 18457 this.wrapperStyle = this.wrapper.style; 18458 this.indicator = this.wrapper.children[0]; 18459 this.indicatorStyle = this.indicator.style; 18460 this.scroller = scroller; 18461 18462 this.options = { 18463 listenX: true, 18464 listenY: true, 18465 interactive: false, 18466 resize: true, 18467 defaultScrollbars: false, 18468 shrink: false, 18469 fade: false, 18470 speedRatioX: 0, 18471 speedRatioY: 0 18472 }; 18473 18474 for ( var i in options ) { 18475 this.options[i] = options[i]; 18476 } 18477 18478 this.sizeRatioX = 1; 18479 this.sizeRatioY = 1; 18480 this.maxPosX = 0; 18481 this.maxPosY = 0; 18482 18483 if ( this.options.interactive ) { 18484 if ( !this.options.disableTouch ) { 18485 utils.addEvent(this.indicator, 'touchstart', this); 18486 utils.addEvent(window, 'touchend', this); 18487 } 18488 if ( !this.options.disablePointer ) { 18489 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18490 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 18491 } 18492 if ( !this.options.disableMouse ) { 18493 utils.addEvent(this.indicator, 'mousedown', this); 18494 utils.addEvent(window, 'mouseup', this); 18495 } 18496 } 18497 18498 if ( this.options.fade ) { 18499 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 18500 var durationProp = utils.style.transitionDuration; 18501 if(!durationProp) { 18502 return; 18503 } 18504 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 18505 // remove 0.0001ms 18506 var self = this; 18507 if(utils.isBadAndroid) { 18508 rAF(function() { 18509 if(self.wrapperStyle[durationProp] === '0.0001ms') { 18510 self.wrapperStyle[durationProp] = '0s'; 18511 } 18512 }); 18513 } 18514 this.wrapperStyle.opacity = '0'; 18515 } 18516} 18517 18518Indicator.prototype = { 18519 handleEvent: function (e) { 18520 switch ( e.type ) { 18521 case 'touchstart': 18522 case 'pointerdown': 18523 case 'MSPointerDown': 18524 case 'mousedown': 18525 this._start(e); 18526 break; 18527 case 'touchmove': 18528 case 'pointermove': 18529 case 'MSPointerMove': 18530 case 'mousemove': 18531 this._move(e); 18532 break; 18533 case 'touchend': 18534 case 'pointerup': 18535 case 'MSPointerUp': 18536 case 'mouseup': 18537 case 'touchcancel': 18538 case 'pointercancel': 18539 case 'MSPointerCancel': 18540 case 'mousecancel': 18541 this._end(e); 18542 break; 18543 } 18544 }, 18545 18546 destroy: function () { 18547 if ( this.options.fadeScrollbars ) { 18548 clearTimeout(this.fadeTimeout); 18549 this.fadeTimeout = null; 18550 } 18551 if ( this.options.interactive ) { 18552 utils.removeEvent(this.indicator, 'touchstart', this); 18553 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18554 utils.removeEvent(this.indicator, 'mousedown', this); 18555 18556 utils.removeEvent(window, 'touchmove', this); 18557 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18558 utils.removeEvent(window, 'mousemove', this); 18559 18560 utils.removeEvent(window, 'touchend', this); 18561 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 18562 utils.removeEvent(window, 'mouseup', this); 18563 } 18564 18565 if ( this.options.defaultScrollbars ) { 18566 this.wrapper.parentNode.removeChild(this.wrapper); 18567 } 18568 }, 18569 18570 _start: function (e) { 18571 var point = e.touches ? e.touches[0] : e; 18572 18573 e.preventDefault(); 18574 e.stopPropagation(); 18575 18576 this.transitionTime(); 18577 18578 this.initiated = true; 18579 this.moved = false;
vendor: 9,615 bytes, lines 18580-18838
18580 this.lastPointX = point.pageX; 18581 this.lastPointY = point.pageY; 18582 18583 this.startTime = utils.getTime(); 18584 18585 if ( !this.options.disableTouch ) { 18586 utils.addEvent(window, 'touchmove', this); 18587 } 18588 if ( !this.options.disablePointer ) { 18589 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 18590 } 18591 if ( !this.options.disableMouse ) { 18592 utils.addEvent(window, 'mousemove', this); 18593 } 18594 18595 this.scroller._execEvent('beforeScrollStart'); 18596 }, 18597 18598 _move: function (e) { 18599 var point = e.touches ? e.touches[0] : e, 18600 deltaX, deltaY, 18601 newX, newY, 18602 timestamp = utils.getTime(); 18603 18604 if ( !this.moved ) { 18605 this.scroller._execEvent('scrollStart'); 18606 } 18607 18608 this.moved = true; 18609 18610 deltaX = point.pageX - this.lastPointX; 18611 this.lastPointX = point.pageX; 18612 18613 deltaY = point.pageY - this.lastPointY; 18614 this.lastPointY = point.pageY; 18615 18616 newX = this.x + deltaX; 18617 newY = this.y + deltaY; 18618 18619 this._pos(newX, newY); 18620 18621// INSERT POINT: indicator._move 18622 18623 e.preventDefault(); 18624 e.stopPropagation(); 18625 }, 18626 18627 _end: function (e) { 18628 if ( !this.initiated ) { 18629 return; 18630 } 18631 18632 this.initiated = false; 18633 18634 e.preventDefault(); 18635 e.stopPropagation(); 18636 18637 utils.removeEvent(window, 'touchmove', this); 18638 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18639 utils.removeEvent(window, 'mousemove', this); 18640 18641 if ( this.scroller.options.snap ) { 18642 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 18643 18644 var time = this.options.snapSpeed || Math.max( 18645 Math.max( 18646 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 18647 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 18648 ), 300); 18649 18650 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 18651 this.scroller.directionX = 0; 18652 this.scroller.directionY = 0; 18653 this.scroller.currentPage = snap; 18654 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 18655 } 18656 } 18657 18658 if ( this.moved ) { 18659 this.scroller._execEvent('scrollEnd'); 18660 } 18661 }, 18662 18663 transitionTime: function (time) { 18664 time = time || 0; 18665 var durationProp = utils.style.transitionDuration; 18666 if(!durationProp) { 18667 return; 18668 } 18669 18670 this.indicatorStyle[durationProp] = time + 'ms'; 18671 18672 if ( !time && utils.isBadAndroid ) { 18673 this.indicatorStyle[durationProp] = '0.0001ms'; 18674 // remove 0.0001ms 18675 var self = this; 18676 rAF(function() { 18677 if(self.indicatorStyle[durationProp] === '0.0001ms') { 18678 self.indicatorStyle[durationProp] = '0s'; 18679 } 18680 }); 18681 } 18682 }, 18683 18684 transitionTimingFunction: function (easing) { 18685 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 18686 }, 18687 18688 refresh: function () { 18689 this.transitionTime(); 18690 18691 if ( this.options.listenX && !this.options.listenY ) { 18692 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 18693 } else if ( this.options.listenY && !this.options.listenX ) { 18694 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 18695 } else { 18696 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 18697 } 18698 18699 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 18700 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 18701 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 18702 18703 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18704 if ( this.options.listenX ) { 18705 this.wrapper.style.right = '8px'; 18706 } else { 18707 this.wrapper.style.bottom = '8px'; 18708 } 18709 } 18710 } else { 18711 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 18712 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 18713 18714 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18715 if ( this.options.listenX ) { 18716 this.wrapper.style.right = '2px'; 18717 } else { 18718 this.wrapper.style.bottom = '2px'; 18719 } 18720 } 18721 } 18722 18723 var r = this.wrapper.offsetHeight; // force refresh 18724 18725 if ( this.options.listenX ) { 18726 this.wrapperWidth = this.wrapper.clientWidth; 18727 if ( this.options.resize ) { 18728 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 18729 this.indicatorStyle.width = this.indicatorWidth + 'px'; 18730 } else { 18731 this.indicatorWidth = this.indicator.clientWidth; 18732 } 18733 18734 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 18735 18736 if ( this.options.shrink == 'clip' ) { 18737 this.minBoundaryX = -this.indicatorWidth + 8; 18738 this.maxBoundaryX = this.wrapperWidth - 8; 18739 } else { 18740 this.minBoundaryX = 0; 18741 this.maxBoundaryX = this.maxPosX; 18742 } 18743 18744 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 18745 } 18746 18747 if ( this.options.listenY ) { 18748 this.wrapperHeight = this.wrapper.clientHeight; 18749 if ( this.options.resize ) { 18750 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 18751 this.indicatorStyle.height = this.indicatorHeight + 'px'; 18752 } else { 18753 this.indicatorHeight = this.indicator.clientHeight; 18754 } 18755 18756 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18757 18758 if ( this.options.shrink == 'clip' ) { 18759 this.minBoundaryY = -this.indicatorHeight + 8; 18760 this.maxBoundaryY = this.wrapperHeight - 8; 18761 } else { 18762 this.minBoundaryY = 0; 18763 this.maxBoundaryY = this.maxPosY; 18764 } 18765 18766 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18767 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 18768 } 18769 18770 this.updatePosition(); 18771 }, 18772 18773 updatePosition: function () { 18774 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 18775 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 18776 18777 if ( !this.options.ignoreBoundaries ) { 18778 if ( x < this.minBoundaryX ) { 18779 if ( this.options.shrink == 'scale' ) { 18780 this.width = Math.max(this.indicatorWidth + x, 8); 18781 this.indicatorStyle.width = this.width + 'px'; 18782 } 18783 x = this.minBoundaryX; 18784 } else if ( x > this.maxBoundaryX ) { 18785 if ( this.options.shrink == 'scale' ) { 18786 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 18787 this.indicatorStyle.width = this.width + 'px'; 18788 x = this.maxPosX + this.indicatorWidth - this.width; 18789 } else { 18790 x = this.maxBoundaryX; 18791 } 18792 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 18793 this.width = this.indicatorWidth; 18794 this.indicatorStyle.width = this.width + 'px'; 18795 } 18796 18797 if ( y < this.minBoundaryY ) { 18798 if ( this.options.shrink == 'scale' ) { 18799 this.height = Math.max(this.indicatorHeight + y * 3, 8); 18800 this.indicatorStyle.height = this.height + 'px'; 18801 } 18802 y = this.minBoundaryY; 18803 } else if ( y > this.maxBoundaryY ) { 18804 if ( this.options.shrink == 'scale' ) { 18805 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 18806 this.indicatorStyle.height = this.height + 'px'; 18807 y = this.maxPosY + this.indicatorHeight - this.height; 18808 } else { 18809 y = this.maxBoundaryY; 18810 } 18811 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 18812 this.height = this.indicatorHeight; 18813 this.indicatorStyle.height = this.height + 'px'; 18814 } 18815 } 18816 18817 this.x = x; 18818 this.y = y; 18819 18820 if ( this.scroller.options.useTransform ) { 18821 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 18822 } else { 18823 this.indicatorStyle.left = x + 'px'; 18824 this.indicatorStyle.top = y + 'px'; 18825 } 18826 }, 18827 18828 _pos: function (x, y) { 18829 if ( x < 0 ) { 18830 x = 0; 18831 } else if ( x > this.maxPosX ) { 18832 x = this.maxPosX; 18833 } 18834 18835 if ( y < 0 ) { 18836 y = 0; 18837 } else if ( y > this.maxPosY ) { 18838 y = this.maxPosY;
18839 } 18840 18841 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 18842 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 18843 18844 this.scroller.scrollTo(x, y); 18845 }, 18846 18847 fade: function (val, hold) { 18848 if ( hold && !this.visible ) { 18849 return; 18850 } 18851 18852 clearTimeout(this.fadeTimeout); 18853 this.fadeTimeout = null; 18854 18855 var time = val ? 250 : 500, 18856 delay = val ? 0 : 300; 18857 18858 val = val ? '1' : '0'; 18859 18860 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 18861 18862 this.fadeTimeout = setTimeout((function (val) { 18863 this.wrapperStyle.opacity = val; 18864 this.visible = +val; 18865 }).bind(this, val), delay); 18866 } 18867}; 18868 18869IScroll.utils = utils; 18870 18871if ( typeof module != 'undefined' && module.exports ) { 18872 module.exports = IScroll; 18873} else if ( typeof define == 'function' && define.amd ) { 18874 define( function () { return IScroll; } ); 18875} else { 18876 window.IScroll = IScroll; 18877} 18878 18879})(window, document, Math); 18880/*! 18881 * fullPage 2.9.4 18882 * https://github.com/alvarotrigo/fullPage.js 18883 * @license MIT licensed 18884 * 18885 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 18886 */ 18887(function(global, factory) { 18888 'use strict'; 18889 if (typeof define === 'function' && define.amd) { 18890 define(['jquery'], function($) { 18891 return factory($, global, global.document, global.Math); 18892 }); 18893 } else if (typeof exports === "object" && exports) { 18894 module.exports = factory(require('jquery'), global, global.document, global.Math); 18895 } else { 18896 factory(jQuery, global, global.document, global.Math); 18897 } 18898})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 18899 'use strict'; 18900 18901 // keeping central set of classnames and selectors 18902 var WRAPPER = 'fullpage-wrapper'; 18903 var WRAPPER_SEL = '.' + WRAPPER; 18904 18905 // slimscroll 18906 var SCROLLABLE = 'fp-scrollable'; 18907 var SCROLLABLE_SEL = '.' + SCROLLABLE; 18908 18909 // util 18910 var RESPONSIVE = 'fp-responsive'; 18911 var NO_TRANSITION = 'fp-notransition'; 18912 var DESTROYED = 'fp-destroyed'; 18913 var ENABLED = 'fp-enabled'; 18914 var VIEWING_PREFIX = 'fp-viewing'; 18915 var ACTIVE = 'active'; 18916 var ACTIVE_SEL = '.' + ACTIVE; 18917 var COMPLETELY = 'fp-completely'; 18918 var COMPLETELY_SEL = '.' + COMPLETELY; 18919 18920 // section 18921 var SECTION_DEFAULT_SEL = '.section'; 18922 var SECTION = 'fp-section'; 18923 var SECTION_SEL = '.' + SECTION; 18924 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 18925 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 18926 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 18927 var TABLE_CELL = 'fp-tableCell'; 18928 var TABLE_CELL_SEL = '.' + TABLE_CELL; 18929 var AUTO_HEIGHT = 'fp-auto-height'; 18930 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 18931 var NORMAL_SCROLL = 'fp-normal-scroll'; 18932 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 18933 18934 // section nav 18935 var SECTION_NAV = 'fp-nav'; 18936 var SECTION_NAV_SEL = '#' + SECTION_NAV; 18937 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 18938 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 18939 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 18940 18941 // slide 18942 var SLIDE_DEFAULT_SEL = '.slide'; 18943 var SLIDE = 'fp-slide'; 18944 var SLIDE_SEL = '.' + SLIDE; 18945 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 18946 var SLIDES_WRAPPER = 'fp-slides'; 18947 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 18948 var SLIDES_CONTAINER = 'fp-slidesContainer'; 18949 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 18950 var TABLE = 'fp-table'; 18951 18952 // slide nav 18953 var SLIDES_NAV = 'fp-slidesNav'; 18954 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 18955 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 18956 var SLIDES_ARROW = 'fp-controlArrow'; 18957 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 18958 var SLIDES_PREV = 'fp-prev'; 18959 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 18960 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 18961 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 18962 var SLIDES_NEXT = 'fp-next';
18963 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 18964 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 18965 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 18966 18967 var $window = $(window); 18968 var $document = $(document); 18969 18970 // Default options for iScroll.js used when using scrollOverflow 18971 var iscrollOptions = { 18972 scrollbars: true, 18973 mouseWheel: true, 18974 hideScrollbars: false, 18975 fadeScrollbars: false, 18976 disableMouse: true, 18977 interactiveScrollbars: true, 18978 bounce: false, 18979 }; 18980 18981 $.fn.fullpage = function(options) { 18982 //only once my friend! 18983 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 18984 18985 // common jQuery objects 18986 var $htmlBody = $('html, body'); 18987 var $body = $('body'); 18988 18989 var FP = $.fn.fullpage; 18990 18991 // Creating some defaults, extending them with any options that were provided 18992 options = $.extend({ 18993 //navigation 18994 menu: false, 18995 anchors:[], 18996 lockAnchors: false, 18997 navigation: false, 18998 navigationPosition: 'right', 18999 navigationTooltips: [], 19000 showActiveTooltip: false, 19001 slidesNavigation: false, 19002 slidesNavPosition: 'bottom', 19003 scrollBar: false, 19004 hybrid: false, 19005 19006 //scrolling 19007 css3: true, 19008 scrollingSpeed: 700, 19009 autoScrolling: true, 19010 fitToSection: true, 19011 fitToSectionDelay: 1000, 19012 easing: 'easeInOutCubic', 19013 easingcss3: 'ease', 19014 loopBottom: false, 19015 loopTop: false, 19016 loopHorizontal: true, 19017 continuousVertical: false, 19018 continuousHorizontal: false, 19019 scrollHorizontally: false, 19020 interlockedSlides: false, 19021 dragAndMove: false, 19022 offsetSections: false, 19023 resetSliders: false, 19024 fadingEffect: false, 19025 normalScrollElements: null, 19026 scrollOverflow: false, 19027 scrollOverflowReset: false, 19028 scrollOverflowHandler: iscrollHandler, 19029 scrollOverflowOptions: null, 19030 touchSensitivity: 5, 19031 normalScrollElementTouchThreshold: 5, 19032 bigSectionsDestination: null, 19033 19034 //Accessibility 19035 keyboardScrolling: true, 19036 animateAnchor: true, 19037 recordHistory: true, 19038 19039 //design 19040 controlArrows: true, 19041 controlArrowColor: '#fff', 19042 verticalCentered: true, 19043 sectionsColor : [], 19044 paddingTop: 0, 19045 paddingBottom: 0, 19046 fixedElements: null, 19047 responsive: 0, //backwards compabitility with responsiveWiddth 19048 responsiveWidth: 0, 19049 responsiveHeight: 0, 19050 responsiveSlides: false, 19051 parallax: false, 19052 parallaxOptions: { 19053 type: 'reveal', 19054 percentage: 62, 19055 property: 'translate' 19056 }, 19057 19058 //Custom selectors 19059 sectionSelector: SECTION_DEFAULT_SEL, 19060 slideSelector: SLIDE_DEFAULT_SEL, 19061 19062 //events 19063 afterLoad: null, 19064 onLeave: null, 19065 afterRender: null, 19066 afterResize: null, 19067 afterReBuild: null, 19068 afterSlideLoad: null, 19069 onSlideLeave: null, 19070 afterResponsive: null, 19071 19072 lazyLoading: true 19073 }, options); 19074 19075 //flag to avoid very fast sliding for landscape sliders 19076 var slideMoving = false; 19077 19078 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 19079 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 19080 var container = $(this); 19081 var windowsHeight = $window.height(); 19082 var isResizing = false; 19083 var isWindowFocused = true; 19084 var lastScrolledDestiny; 19085 var lastScrolledSlide; 19086 var canScroll = true; 19087 var scrollings = []; 19088 var controlPressed; 19089 var startingSection; 19090 var isScrollAllowed = {}; 19091 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 19092 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 19093 var MSPointer = getMSPointer(); 19094 var events = { 19095 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 19096 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 19097 }; 19098 19099 //timeouts 19100 var resizeId; 19101 var afterSectionLoadsId; 19102 var afterSlideLoadsId; 19103 var scrollId; 19104 var scrollId2;
19105 var keydownId; 19106 var originals = $.extend(true, {}, options); //deep copy 19107 19108 //Uncode addition 19109 var $masthead = $('#masthead'); 19110 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 19111 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 19112 var bodyBorder = UNCODE.bodyBorder; 19113 var adminBarHeight = UNCODE.adminBarHeight; 19114 19115 displayWarnings(); 19116 19117 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 19118 iscrollOptions.click = isTouch; // see #2035 19119 19120 //extending iScroll options with the user custom ones 19121 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 19122 19123 //easeInOutCubic animation included in the plugin 19124 $.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;}}); 19125 19126 /** 19127 * Sets the autoScroll option. 19128 * It changes the scroll bar visibility and the history of the site as a result. 19129 */ 19130 function setAutoScrolling(value, type){ 19131 //removing the transformation 19132 if(!value){ 19133 silentScroll(0); 19134 } 19135 19136 setVariableState('autoScrolling', value, type); 19137 19138 var element = $(SECTION_ACTIVE_SEL); 19139 19140 if(options.autoScrolling && !options.scrollBar){ 19141 $htmlBody.css({ 19142 'overflow' : 'hidden !important', 19143 'height' : '100%' 19144 }); 19145 19146 //Uncode addition 19147 //setRecordHistory(originals.recordHistory, 'internal'); 19148 19149 //for IE touch devices 19150 container.css({ 19151 '-ms-touch-action': 'none', 19152 'touch-action': 'none' 19153 }); 19154 19155 if(element.length){ 19156 //moving the container up 19157 silentScroll(element.position().top); 19158 } 19159 19160 }else{ 19161 $htmlBody.css({ 19162 'overflow' : 'visible !important', 19163 'height' : 'initial' 19164 }); 19165 19166 //Uncode addition 19167 //setRecordHistory(false, 'internal'); 19168 19169 //for IE touch devices 19170 container.css({ 19171 '-ms-touch-action': '', 19172 'touch-action': '' 19173 }); 19174 19175 //scrolling the page to the section with no animation 19176 if (element.length) { 19177 $htmlBody.scrollTop(element.position().top); 19178 } 19179 } 19180 } 19181 19182 /** 19183 * Defines wheter to record the history for each hash change in the URL. 19184 */ 19185 function setRecordHistory(value, type){ 19186 setVariableState('recordHistory', value, type); 19187 } 19188 19189 /** 19190 * Defines the scrolling speed 19191 */ 19192 function setScrollingSpeed(value, type){ 19193 setVariableState('scrollingSpeed', value, type); 19194 } 19195 19196 /** 19197 * Sets fitToSection 19198 */ 19199 function setFitToSection(value, type){ 19200 setVariableState('fitToSection', value, type); 19201 } 19202 19203 /** 19204 * Sets lockAnchors 19205 */ 19206 function setLockAnchors(value){ 19207 options.lockAnchors = value; 19208 } 19209 19210 /** 19211 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 19212 */ 19213 function setMouseWheelScrolling(value){ 19214 if(value){ 19215 addMouseWheelHandler(); 19216 addMiddleWheelHandler(); 19217 }else{ 19218 removeMouseWheelHandler(); 19219 removeMiddleWheelHandler(); 19220 } 19221 } 19222 19223 /** 19224 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 19225 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 19226 * 19227 * @param directions string containing the direction or directions separated by comma. 19228 */ 19229 function setAllowScrolling(value, directions){ 19230 if(typeof directions !== 'undefined'){ 19231 directions = directions.replace(/ /g,'').split(','); 19232 19233 $.each(directions, function (index, direction){ 19234 setIsScrollAllowed(value, direction, 'm'); 19235 }); 19236 } 19237 else if(value){ 19238 setMouseWheelScrolling(true); 19239 addTouchHandler(); 19240 }else{ 19241 setMouseWheelScrolling(false); 19242 removeTouchHandler(); 19243 } 19244 } 19245 19246 /** 19247 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 19248 */ 19249 function setKeyboardScrolling(value, directions){ 19250 if(typeof directions !== 'undefined'){ 19251 directions = directions.replace(/ /g,'').split(','); 19252 19253 $.each(directions, function (index, direction){ 19254 setIsScrollAllowed(value, direction, 'k'); 19255 }); 19256 }else{ 19257 options.keyboardScrolling = value; 19258 } 19259 } 19260 19261 /** 19262 * Moves the page up one section. 19263 */ 19264 function moveSectionUp(){ 19265 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 19266 19267 //looping to the bottom if there's no more sections above 19268 if (!prev.length && (options.loopTop || options.continuousVertical)) {
19269 prev = $(SECTION_SEL).last(); 19270 } 19271 19272 if (prev.length) { 19273 scrollPage(prev, null, true); 19274 } 19275 } 19276 19277 /** 19278 * Moves the page down one section. 19279 */ 19280 function moveSectionDown(){ 19281 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 19282 19283 //looping to the top if there's no more sections below 19284 if(!next.length && 19285 (options.loopBottom || options.continuousVertical)){ 19286 next = $(SECTION_SEL).first(); 19287 } 19288 19289 if(next.length){ 19290 scrollPage(next, null, false); 19291 } 19292 } 19293 19294 /** 19295 * Moves the page to the given section and slide with no animation. 19296 * Anchors or index positions can be used as params. 19297 */ 19298 function silentMoveTo(sectionAnchor, slideAnchor){ 19299 setScrollingSpeed (0, 'internal'); 19300 moveTo(sectionAnchor, slideAnchor); 19301 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 19302 } 19303 19304 /** 19305 * Moves the page to the given section and slide. 19306 * Anchors or index positions can be used as params. 19307 */ 19308 function moveTo(sectionAnchor, slideAnchor){ 19309 var destiny = getSectionByAnchor(sectionAnchor); 19310 19311 if (typeof slideAnchor !== 'undefined'){ 19312 scrollPageAndSlide(sectionAnchor, slideAnchor); 19313 }else if(destiny.length > 0){ 19314 scrollPage(destiny); 19315 } 19316 } 19317 19318 /** 19319 * Slides right the slider of the active section. 19320 * Optional `section` param. 19321 */ 19322 function moveSlideRight(section){ 19323 moveSlide('right', section); 19324 } 19325 19326 /** 19327 * Slides left the slider of the active section. 19328 * Optional `section` param. 19329 */ 19330 function moveSlideLeft(section){ 19331 moveSlide('left', section); 19332 } 19333 19334 /** 19335 * When resizing is finished, we adjust the slides sizes and positions 19336 */ 19337 function reBuild(resizing){ 19338 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 19339 19340 isResizing = true; 19341 19342 windowsHeight = $window.height(); //updating global var 19343 19344 $(SECTION_SEL).each(function(){ 19345 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 19346 var slides = $(this).find(SLIDE_SEL); 19347 19348 //adjusting the height of the table-cell for IE and Firefox 19349 if(options.verticalCentered){ 19350 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 19351 } 19352 19353 $(this).css('height', windowsHeight + 'px'); 19354 19355 //resizing the scrolling divs 19356 if(options.scrollOverflow){ 19357 if(slides.length){ 19358 slides.each(function(){ 19359 createScrollBar($(this)); 19360 }); 19361 }else{ 19362 createScrollBar($(this)); 19363 } 19364 } 19365 19366 //adjusting the position fo the FULL WIDTH slides... 19367 if (slides.length > 1) { 19368 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 19369 } 19370 }); 19371 19372 var activeSection = $(SECTION_ACTIVE_SEL); 19373 var sectionIndex = activeSection.index(SECTION_SEL); 19374 19375 //isn't it the first section? 19376 if(sectionIndex){ 19377 //adjusting the position for the current section 19378 silentMoveTo(sectionIndex + 1); 19379 } 19380 19381 isResizing = false; 19382 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 19383 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 19384 } 19385 19386 /** 19387 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 19388 * are smaller than the set limit values. 19389 */ 19390 function setResponsive(active){ 19391 var isResponsive = $body.hasClass(RESPONSIVE); 19392 19393 if(active){ 19394 if(!isResponsive){ 19395 setAutoScrolling(false, 'internal'); 19396 setFitToSection(false, 'internal'); 19397 $(SECTION_NAV_SEL).hide(); 19398 $body.addClass(RESPONSIVE); 19399 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19400 } 19401 } 19402 else if(isResponsive){ 19403 setAutoScrolling(originals.autoScrolling, 'internal'); 19404 setFitToSection(originals.autoScrolling, 'internal'); 19405 $(SECTION_NAV_SEL).show(); 19406 $body.removeClass(RESPONSIVE); 19407 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19408 } 19409 } 19410 19411 if($(this).length){ 19412 //public functions 19413 FP.setAutoScrolling = setAutoScrolling; 19414 FP.setRecordHistory = setRecordHistory; 19415 FP.setScrollingSpeed = setScrollingSpeed; 19416 FP.setFitToSection = setFitToSection; 19417 FP.setLockAnchors = setLockAnchors; 19418 FP.setMouseWheelScrolling = setMouseWheelScrolling; 19419 FP.setAllowScrolling = setAllowScrolling; 19420 FP.setKeyboardScrolling = setKeyboardScrolling; 19421 FP.moveSectionUp = moveSectionUp; 19422 FP.moveSectionDown = moveSectionDown; 19423 FP.silentMoveTo = silentMoveTo; 19424 FP.moveTo = moveTo; 19425 FP.moveSlideRight = moveSlideRight; 19426 FP.moveSlideLeft = moveSlideLeft; 19427 FP.fitToSection = fitToSection; 19428 FP.reBuild = reBuild; 19429 FP.setResponsive = setResponsive; 19430 FP.destroy = destroy; 19431 19432 init(); 19433 19434 bindEvents(); 19435 } 19436
19437 function init(){ 19438 //if css3 is not supported, it will use jQuery animations 19439 if(options.css3){ 19440 options.css3 = support3d(); 19441 } 19442 19443 options.scrollBar = options.scrollBar || options.hybrid; 19444 19445 setOptionsFromDOM(); 19446 prepareDom(); 19447 setAllowScrolling(true); 19448 setAutoScrolling(options.autoScrolling, 'internal'); 19449 responsive(); 19450 19451 //setting the class for the body element 19452 setBodyClass(); 19453 19454 //Uncode addition 19455 // if(document.readyState === 'complete'){ 19456 // scrollToAnchor(); 19457 // } 19458 // $window.on('load', scrollToAnchor); 19459 } 19460 19461 function bindEvents(){ 19462 $window 19463 //when scrolling... 19464 //.on('scroll', scrollHandler) 19465 19466 //detecting any change on the URL to scroll to the given anchor link 19467 //(a way to detect back history button as we play with the hashes on the URL) 19468 .on('hashchange', hashChangeHandler) 19469 19470 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 19471 .blur(blurHandler) 19472 19473 //when resizing the site, we adjust the heights of the sections, slimScroll... 19474 .resize(resizeHandler); 19475 19476 $document 19477 //Sliding with arrow keys, both, vertical and horizontal 19478 .keydown(keydownHandler) 19479 19480 //to prevent scrolling while zooming 19481 .keyup(keyUpHandler) 19482 19483 //Scrolls to the section when clicking the navigation bullet 19484 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 19485 19486 //Scrolls the slider to the given slide destination for the given section 19487 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 19488 19489 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 19490 19491 //Scrolling horizontally when clicking on the slider controls. 19492 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 19493 19494 /** 19495 * Applying normalScroll elements. 19496 * Ignoring the scrolls over the specified selectors. 19497 */ 19498 if(options.normalScrollElements){ 19499 $document.on('mouseenter', options.normalScrollElements, function () { 19500 setMouseWheelScrolling(false); 19501 }); 19502 19503 $document.on('mouseleave', options.normalScrollElements, function(){ 19504 setMouseWheelScrolling(true); 19505 }); 19506 } 19507 } 19508 19509 /** 19510 * Setting options from DOM elements if they are not provided. 19511 */ 19512 function setOptionsFromDOM(){ 19513 var sections = container.find(options.sectionSelector); 19514 19515 //no anchors option? Checking for them in the DOM attributes 19516 if(!options.anchors.length){ 19517 options.anchors = sections.filter('[data-anchor]').map(function(){ 19518 return $(this).data('anchor').toString(); 19519 }).get(); 19520 } 19521 19522 //no tooltips option? Checking for them in the DOM attributes 19523 if(!options.navigationTooltips.length){ 19524 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 19525 return $(this).data('tooltip').toString(); 19526 }).get(); 19527 } 19528 } 19529 19530 /** 19531 * Works over the DOM structure to set it up for the current fullpage options. 19532 */ 19533 function prepareDom(){ 19534 container.css({ 19535 'height': '100%', 19536 'position': 'relative' 19537 }); 19538 19539 //adding a class to recognize the container internally in the code 19540 container.addClass(WRAPPER); 19541 $('html').addClass(ENABLED); 19542 19543 windowsHeight = $window.height(); 19544 19545 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 19546 19547 addInternalSelectors(); 19548 19549 //styling the sections / slides / menu 19550 $(SECTION_SEL).each(function(index){ 19551 var section = $(this); 19552 var slides = section.find(SLIDE_SEL); 19553 var numSlides = slides.length; 19554 19555 styleSection(section, index); 19556 styleMenu(section, index); 19557 19558 // if there's any slide 19559 if (numSlides > 0) { 19560 styleSlides(section, slides, numSlides); 19561 }else{ 19562 if(options.verticalCentered){ 19563 addTableClass(section); 19564 } 19565 } 19566 }); 19567 19568 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 19569 if(options.fixedElements && options.css3){ 19570 $(options.fixedElements).appendTo($body); 19571 } 19572 19573 //vertical centered of the navigation + active bullet 19574 if(options.navigation){ 19575 addVerticalNavigation(); 19576 } 19577 19578 enableYoutubeAPI(); 19579 19580 if(options.scrollOverflow){ 19581 if(document.readyState === 'complete'){ 19582 createScrollBarHandler(); 19583 } 19584 //after DOM and images are loaded 19585 $window.on('load', createScrollBarHandler); 19586 }else{ 19587 afterRenderActions(); 19588 } 19589 } 19590 19591 /** 19592 * Styles the horizontal slides for a section. 19593 */ 19594 function styleSlides(section, slides, numSlides){ 19595 var sliderWidth = numSlides * 100; 19596 var slideWidth = 100 / numSlides; 19597 19598 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 19599 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 19600 19601 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 19602 19603 if(numSlides > 1){ 19604 if(options.controlArrows){ 19605 createSlideArrows(section); 19606 } 19607 19608 if(options.slidesNavigation){ 19609 addSlidesNavigation(section, numSlides); 19610 } 19611 } 19612 19613 slides.each(function(index) { 19614 $(this).css('width', slideWidth + '%'); 19615 19616 if(options.verticalCentered){ 19617 addTableClass($(this)); 19618 } 19619 }); 19620 19621 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 19622 19623 //if the slide won't be an starting point, the default will be the first one 19624 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
19624ide by default. 19625 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 19626 silentLandscapeScroll(startingSlide, 'internal'); 19627 }else{ 19628 slides.eq(0).addClass(ACTIVE); 19629 } 19630 } 19631 19632 /** 19633 * Styling vertical sections 19634 */ 19635 function styleSection(section, index){ 19636 //if no active section is defined, the 1st one will be the default one 19637 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 19638 section.addClass(ACTIVE); 19639 } 19640 startingSection = $(SECTION_ACTIVE_SEL); 19641 19642 section.css('height', windowsHeight + 'px'); 19643 19644 if(options.paddingTop){ 19645 section.css('padding-top', options.paddingTop); 19646 } 19647 19648 if(options.paddingBottom){ 19649 section.css('padding-bottom', options.paddingBottom); 19650 } 19651 19652 if (typeof options.sectionsColor[index] !== 'undefined') { 19653 section.css('background-color', options.sectionsColor[index]); 19654 } 19655 19656 if (typeof options.anchors[index] !== 'undefined') { 19657 section.attr('data-anchor', options.anchors[index]); 19658 } 19659 } 19660 19661 /** 19662 * Sets the data-anchor attributes to the menu elements and activates the current one. 19663 */ 19664 function styleMenu(section, index){ 19665 if (typeof options.anchors[index] !== 'undefined') { 19666 //activating the menu / nav element on load 19667 if(section.hasClass(ACTIVE)){ 19668 activateMenuAndNav(options.anchors[index], index); 19669 } 19670 } 19671 19672 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 19673 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 19674 $(options.menu).appendTo($body); 19675 } 19676 } 19677 19678 /** 19679 * Adds internal classes to be able to provide customizable selectors 19680 * keeping the link with the style sheet. 19681 */ 19682 function addInternalSelectors(){ 19683 container.find(options.sectionSelector).addClass(SECTION); 19684 container.find(options.slideSelector).addClass(SLIDE); 19685 } 19686 19687 /** 19688 * Creates the control arrows for the given section 19689 */ 19690 function createSlideArrows(section){ 19691 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 19692 19693 if(options.controlArrowColor!='#fff'){ 19694 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 19695 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 19696 } 19697 19698 if(!options.loopHorizontal){ 19699 section.find(SLIDES_ARROW_PREV_SEL).hide(); 19700 } 19701 } 19702 19703 /** 19704 * Creates a vertical navigation bar. 19705 */ 19706 function addVerticalNavigation(){ 19707 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 19708 var nav = $(SECTION_NAV_SEL); 19709 19710 nav.addClass(function() { 19711 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 19712 }); 19713 19714 for (var i = 0; i < $(SECTION_SEL).length; i++) { 19715 var link = ''; 19716 if (options.anchors.length) { 19717 link = options.anchors[i]; 19718 } 19719 19720 var li = '<li><a href="#' + link + '"><span></span></a>'; 19721 19722 // Only add tooltip if needed (defined by user) 19723 var tooltip = options.navigationTooltips[i]; 19724 19725 if (typeof tooltip !== 'undefined' && tooltip !== '') { 19726 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 19727 } 19728 19729 li += '</li>'; 19730 19731 nav.find('ul').append(li); 19732 } 19733 19734 //centering it vertically 19735 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 19736 19737 //activating the current active section 19738 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 19739 } 19740 19741 /** 19742 * Creates the slim scroll scrollbar for the sections and slides inside them. 19743 */ 19744 function createScrollBarHandler(){ 19745 $(SECTION_SEL).each(function(){ 19746 var slides = $(this).find(SLIDE_SEL); 19747 19748 if(slides.length){ 19749 slides.each(function(){ 19750 createScrollBar($(this)); 19751 }); 19752 }else{ 19753 createScrollBar($(this)); 19754 } 19755 19756 }); 19757 afterRenderActions(); 19758 } 19759 19760 /*
19761 * Enables the Youtube videos API so we can control their flow if necessary. 19762 */ 19763 function enableYoutubeAPI(){ 19764 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 19765 addURLParam($(this), 'enablejsapi=1'); 19766 }); 19767 } 19768 19769 /** 19770 * Adds a new parameter and its value to the `src` of a given element 19771 */ 19772 function addURLParam(element, newParam){ 19773 var originalSrc = element.attr('src'); 19774 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 19775 } 19776 19777 /* 19778 * Returns the prefix sign to use for a new parameter in an existen URL. 19779 * 19780 * @return {String} ? | & 19781 */ 19782 function getUrlParamSign(url){ 19783 return ( !/\?/.test( url ) ) ? '?' : '&'; 19784 } 19785 19786 /** 19787 * Actions and callbacks to fire afterRender 19788 */ 19789 function afterRenderActions(){ 19790 var section = $(SECTION_ACTIVE_SEL); 19791 19792 section.addClass(COMPLETELY); 19793 19794 if(options.scrollOverflowHandler.afterRender){ 19795 options.scrollOverflowHandler.afterRender(section); 19796 } 19797 lazyLoad(section); 19798 playMedia(section); 19799 options.scrollOverflowHandler.afterLoad(); 19800 19801 if(isDestinyTheStartingSection()){ 19802 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 19803 } 19804 19805 $.isFunction( options.afterRender ) && options.afterRender.call(container); 19806 } 19807 19808 /** 19809 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 19810 */ 19811 function isDestinyTheStartingSection(){ 19812 var anchors = window.location.hash.replace('#', '').split('/'); 19813 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 19814 19815 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 19816 } 19817 19818 19819 var isScrolling = false; 19820 var lastScroll = 0; 19821 19822 //when scrolling... 19823 function scrollHandler(){ 19824 var currentSection; 19825 19826 if(!options.autoScrolling || options.scrollBar){ 19827 var currentScroll = $window.scrollTop(); 19828 var scrollDirection = getScrollDirection(currentScroll); 19829 var visibleSectionIndex = 0; 19830 var screen_mid = currentScroll + ($window.height() / 2.0); 19831 var isAtBottom = $body.height() - $window.height() === currentScroll; 19832 var sections = document.querySelectorAll(SECTION_SEL); 19833 19834 //when using `auto-height` for a small last section it won't be centered in the viewport 19835 if(isAtBottom){ 19836 visibleSectionIndex = sections.length - 1; 19837 } 19838 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 19839 else if(!currentScroll){ 19840 visibleSectionIndex = 0; 19841 } 19842 19843 //taking the section which is showing more content in the viewport 19844 else{ 19845 for (var i = 0; i < sections.length; ++i) { 19846 var section = sections[i]; 19847 19848 // Pick the the last section which passes the middle line of the screen. 19849 if (section.offsetTop <= screen_mid) 19850 { 19851 visibleSectionIndex = i; 19852 } 19853 } 19854 } 19855 19856 if(isCompletelyInViewPort(scrollDirection)){ 19857 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 19858 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 19859 } 19860 } 19861 19862 //geting the last one, the current one on the screen 19863 currentSection = $(sections).eq(visibleSectionIndex); 19864 19865 //setting the visible section as active when manually scrolling 19866 //executing only once the first time we reach the section 19867 if(!currentSection.hasClass(ACTIVE)){ 19868 isScrolling = true; 19869 var leavingSection = $(SECTION_ACTIVE_SEL); 19870 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 19871 var yMovement = getYmovement(currentSection); 19872 var anchorLink = currentSection.data('anchor'); 19873 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 19874 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 19875 var slideIndex; 19876 var slideAnchorLink; 19877 19878 if(activeSlide.length){ 19879 slideAnchorLink = activeSlide.data('anchor'); 19880 slideIndex = activeSlide.index(); 19881 } 19882 19883 if(canScroll){ 19884 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 19885 19886 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 19887 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 19888 19889 stopMedia(leavingSection); 19890 lazyLoad(currentSection); 19891 playMedia(currentSection); 19892 19893 activateMenuAndNav(anchorLink, sectionIndex - 1); 19894 19895 if(options.anchors.length){ 19896 //needed to enter in hashChange event when using the menu with anchor links 19897 lastScrolledDestiny = anchorLink; 19898 } 19899 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 19900 } 19901 19902 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 19903 clearTimeout(scrollId); 19904 scrollId = setTimeout(function(){ 19905 isScrolling = false;
19906 }, 100); 19907 } 19908 19909 if(options.fitToSection){ 19910 //for the auto adjust of the viewport to fit a whole section 19911 clearTimeout(scrollId2); 19912 19913 scrollId2 = setTimeout(function(){ 19914 //checking it again in case it changed during the delay 19915 if(options.fitToSection){ 19916 fitToSection(); 19917 } 19918 }, options.fitToSectionDelay); 19919 } 19920 } 19921 } 19922 19923 /** 19924 * Fits the site to the nearest active section 19925 */ 19926 function fitToSection(){ 19927 //checking fitToSection again in case it was set to false before the timeout delay 19928 if(canScroll){ 19929 //allows to scroll to an active section and 19930 //if the section is already active, we prevent firing callbacks 19931 isResizing = true; 19932 19933 scrollPage($(SECTION_ACTIVE_SEL)); 19934 isResizing = false; 19935 } 19936 } 19937 19938 /** 19939 * Determines whether the active section has seen in its whole or not. 19940 */ 19941 function isCompletelyInViewPort(movement){ 19942 var top = $(SECTION_ACTIVE_SEL).position().top; 19943 var bottom = top + $window.height(); 19944 19945 if(movement == 'up'){ 19946 return bottom >= ($window.scrollTop() + $window.height()); 19947 } 19948 return top <= $window.scrollTop(); 19949 } 19950 19951 /** 19952 * Gets the directon of the the scrolling fired by the scroll event. 19953 */ 19954 function getScrollDirection(currentScroll){ 19955 var direction = currentScroll > lastScroll ? 'down' : 'up'; 19956 19957 lastScroll = currentScroll; 19958 19959 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 19960 previousDestTop = currentScroll; 19961 19962 return direction; 19963 } 19964 19965 /** 19966 * Determines the way of scrolling up or down: 19967 * by 'automatically' scrolling a section or by using the default and normal scrolling. 19968 */ 19969 function scrolling(type, scrollable){ 19970 if (!isScrollAllowed.m[type]){ 19971 return; 19972 } 19973 var check = (type === 'down') ? 'bottom' : 'top'; 19974 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 19975 19976 if(scrollable.length > 0 ){ 19977 //is the scrollbar at the start/end of the scroll? 19978 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 19979 scrollSection(); 19980 }else{ 19981 return true; 19982 } 19983 }else{ 19984 // moved up/down 19985 scrollSection(); 19986 } 19987 } 19988 19989 /* 19990 * Preventing bouncing in iOS #2285 19991 */ 19992 function preventBouncing(event){ 19993 var e = event.originalEvent; 19994 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e)){ 19995 //preventing the easing on iOS devices 19996 event.preventDefault(); 19997 } 19998 } 19999 20000 var touchStartY = 0; 20001 var touchStartX = 0; 20002 var touchEndY = 0; 20003 var touchEndX = 0; 20004 20005 /* Detecting touch events 20006 20007 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 20008 * This way, the touchstart and the touch moves shows an small difference between them which is the 20009 * used one to determine the direction. 20010 */ 20011 function touchMoveHandler(event){ 20012 var e = event.originalEvent; 20013 var activeSection = $(e.target).closest(SECTION_SEL); 20014 20015 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 20016 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 20017 20018 if(options.autoScrolling){ 20019 //preventing the easing on iOS devices 20020 event.preventDefault(); 20021 } 20022 20023 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20024 var touchEvents = getEventsPage(e); 20025 20026 touchEndY = touchEvents.y; 20027 touchEndX = touchEvents.x; 20028 20029 //if movement in the X axys is greater than in the Y and the currect section has slides... 20030 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 20031 20032 //is the movement greater than the minimum resistance to scroll? 20033 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 20034 if (touchStartX > touchEndX) { 20035 if(isScrollAllowed.m.right){ 20036 moveSlideRight(activeSection); //next 20037 } 20038 } else { 20039 if(isScrollAllowed.m.left){ 20040 moveSlideLeft(activeSection); //prev 20041 } 20042 } 20043 } 20044 } 20045 20046 //vertical scrolling (only when autoScrolling is enabled) 20047 else if(options.autoScrolling && canScroll){ 20048 20049 //is the movement greater than the minimum resistance to scroll? 20050 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 20051 if (touchStartY > touchEndY) { 20052 scrolling('down', scrollable); 20053 } else if (touchEndY > touchStartY) { 20054 scrolling('up', scrollable); 20055 } 20056 } 20057 } 20058 } 20059 } 20060 20061 /** 20062 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 20063 * Currently works well for iOS - Android might need some testing 20064 * @param {Element} el target element / jquery selector (in subsequent nodes) 20065 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 20066 * @return {boolean} true if there is a match to options.normalScrollElements 20067 */ 20068 function checkParentForNormalScrollElement (el, hop) { 20069 hop = hop || 0; 20070 var parent = $(el).parent(); 20071 20072 if (hop < options.normalScrollElementTouchThreshold && 20073 parent.is(options.normalScrollElements) ) { 20074 return true; 20075 } else if (hop == options.normalScrollElementTouchThreshold) { 20076 return false;
20077 } else { 20078 return checkParentForNormalScrollElement(parent, ++hop); 20079 } 20080 } 20081 20082 /** 20083 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 20084 * this way we make sure that is really a touch event what IE is detecting. 20085 */ 20086 function isReallyTouch(e){ 20087 //if is not IE || IE is detecting `touch` or `pen` 20088 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 20089 } 20090 20091 /** 20092 * Handler for the touch start event. 20093 */ 20094 function touchStartHandler(event){ 20095 var e = event.originalEvent; 20096 20097 //stopping the auto scroll to adjust to a section 20098 if(options.fitToSection){ 20099 $htmlBody.stop(); 20100 } 20101 20102 if(isReallyTouch(e)){ 20103 var touchEvents = getEventsPage(e); 20104 touchStartY = touchEvents.y; 20105 touchStartX = touchEvents.x; 20106 } 20107 } 20108 20109 /** 20110 * Gets the average of the last `number` elements of the given array. 20111 */ 20112 function getAverage(elements, number){ 20113 var sum = 0; 20114 20115 //taking `number` elements from the end to make the average, if there are not enought, 1 20116 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 20117 20118 for(var i = 0; i < lastElements.length; i++){ 20119 sum = sum + lastElements[i]; 20120 } 20121 20122 return Math.ceil(sum/number); 20123 } 20124 20125 /** 20126 * Detecting mousewheel scrolling 20127 * 20128 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 20129 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 20130 */ 20131 var prevTime = new Date().getTime(); 20132 20133 function MouseWheelHandler(e) { 20134 var curTime = new Date().getTime(); 20135 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 20136 20137 //autoscrolling and not zooming? 20138 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 20139 // cross-browser wheel delta 20140 e = e || window.event; 20141 var value = e.wheelDelta || -e.deltaY || -e.detail; 20142 var delta = Math.max(-1, Math.min(1, value)); 20143 20144 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 20145 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 20146 20147 //Limiting the array to 150 (lets not waste memory!) 20148 if(scrollings.length > 149){ 20149 scrollings.shift(); 20150 } 20151 20152 //keeping record of the previous scrollings 20153 scrollings.push(Math.abs(value)); 20154 20155 //preventing to scroll the site on mouse wheel when scrollbar is present 20156 if(options.scrollBar){ 20157 e.preventDefault ? e.preventDefault() : e.returnValue = false; 20158 } 20159 20160 var activeSection = $(SECTION_ACTIVE_SEL); 20161 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20162 20163 //time difference between the last scroll and the current one 20164 var timeDiff = curTime-prevTime; 20165 prevTime = curTime; 20166 20167 //haven't they scrolled in a while? 20168 //(enough to be consider a different scrolling action to scroll another section) 20169 if(timeDiff > 200){ 20170 //emptying the array, we dont care about old scrollings for our averages 20171 scrollings = []; 20172 } 20173 20174 if(canScroll){ 20175 var averageEnd = getAverage(scrollings, 10); 20176 var averageMiddle = getAverage(scrollings, 70); 20177 var isAccelerating = averageEnd >= averageMiddle; 20178 20179 //to avoid double swipes... 20180 if(isAccelerating && isScrollingVertically){ 20181 //scrolling down? 20182 if (delta < 0) { 20183 scrolling('down', scrollable); 20184 20185 //scrolling up? 20186 }else { 20187 scrolling('up', scrollable); 20188 } 20189 } 20190 } 20191 20192 return false;
20193 } 20194 20195 if(options.fitToSection){ 20196 //stopping the auto scroll to adjust to a section 20197 $htmlBody.stop(); 20198 } 20199 } 20200 20201 /** 20202 * Slides a slider to the given direction. 20203 * Optional `section` param. 20204 */ 20205 function moveSlide(direction, section){ 20206 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 20207 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 20208 var numSlides = slides.find(SLIDE_SEL).length; 20209 20210 // more than one slide needed and nothing should be sliding 20211 if (!slides.length || slideMoving || numSlides < 2) { 20212 return; 20213 } 20214 20215 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 20216 var destiny = null; 20217 20218 if(direction === 'left'){ 20219 destiny = currentSlide.prev(SLIDE_SEL); 20220 }else{ 20221 destiny = currentSlide.next(SLIDE_SEL); 20222 } 20223 20224 //isn't there a next slide in the secuence? 20225 if(!destiny.length){ 20226 //respect loopHorizontal settin 20227 if (!options.loopHorizontal) return; 20228 20229 if(direction === 'left'){ 20230 destiny = currentSlide.siblings(':last'); 20231 }else{ 20232 destiny = currentSlide.siblings(':first'); 20233 } 20234 } 20235 20236 slideMoving = true; 20237 20238 landscapeScroll(slides, destiny, direction); 20239 } 20240 20241 /** 20242 * Maintains the active slides in the viewport 20243 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 20244 */ 20245 function keepSlidesPosition(){ 20246 $(SLIDE_ACTIVE_SEL).each(function(){ 20247 silentLandscapeScroll($(this), 'internal'); 20248 }); 20249 } 20250 20251 var previousDestTop = 0; 20252 /** 20253 * Returns the destination Y position based on the scrolling direction and 20254 * the height of the section. 20255 */ 20256 function getDestinationPosition(element){ 20257 var elemPosition = element.position(); 20258 20259 //top of the desination will be at the top of the viewport 20260 var position = elemPosition.top; 20261 var isScrollingDown = elemPosition.top > previousDestTop; 20262 var sectionBottom = position - windowsHeight + element.outerHeight(); 20263 var bigSectionsDestination = options.bigSectionsDestination; 20264 20265 //Uncode addition 20266 var containerH = container.outerHeight(); 20267 var containerPosition = container.offset(); 20268 20269 //########### Commented by Uncode - START ########### 20270 //is the destination element bigger than the viewport? 20271 // if(element.outerHeight() > windowsHeight){ 20272 // //scrolling up? 20273 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 20274 // position = sectionBottom; 20275 // } 20276 // } 20277 20278 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 20279 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 20280 // //The bottom of the destination will be at the bottom of the viewport 20281 // position = sectionBottom; 20282 // } 20283 //########### Commented by Uncode - END ########### 20284 20285 //Uncode addition 20286 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 20287 position += 18; 20288 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 20289 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 20290 } 20291 20292 /* 20293 Keeping record of the last scrolled position to determine the scrolling direction. 20294 No conventional methods can be used as the scroll bar might not be present 20295 AND the section might not be active if it is auto-height and didnt reach the middle 20296 of the viewport. 20297 */ 20298 previousDestTop = position; 20299 return position; 20300 } 20301 20302 /** 20303 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 20304 */ 20305 function scrollPage(element, callback, isMovementUp){ 20306 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 20307 20308 var dtop = getDestinationPosition(element); 20309 var slideAnchorLink; 20310 var slideIndex; 20311 20312 //local variables 20313 var v = { 20314 element: element, 20315 callback: callback, 20316 isMovementUp: isMovementUp, 20317 dtop: dtop, 20318 yMovement: getYmovement(element), 20319 anchorLink: element.data('anchor'), 20320 sectionIndex: element.index(SECTION_SEL), 20321 activeSlide: element.find(SLIDE_ACTIVE_SEL), 20322 activeSection: $(SECTION_ACTIVE_SEL), 20323 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 20324 20325 //caching the value of isResizing at the momment the function is called 20326 //because it will be checked later inside a setTimeout and the value might change 20327 localIsResizing: isResizing 20328 }; 20329 20330 //quiting when destination scroll is the same as the current one 20331 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 20332 20333 if(v.activeSlide.length){ 20334 slideAnchorLink = v.activeSlide.data('anchor'); 20335 slideIndex = v.activeSlide.index(); 20336 } 20337 20338 // If continuousVertical && we need to wrap around 20339 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 20340 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 20341 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 20342 20343 v = createInfiniteSections(v); 20344 } 20345 20346 //callback (onLeave) if the site is not just resizing and readjusting the slides 20347 if($.isFunction(options.onLeave) && !v.localIsResizing){ 20348 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 20349 return; 20350 } 20351 } 20352 20353 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 20354 if(!v.localIsResizing){ 20355 stopMedia(v.activeSection); 20356 } 20357 20358 options.scrollOverflowHandler.beforeLeave(); 20359 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20360 lazyLoad(element); 20361 options.scrollOverflowHandler.onLeave(); 20362 20363 20364 //preventing from activating the MouseWheelHandler event 20365 //more than once if the page is scrolling 20366 canScroll = false;
20367 20368 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 20369 20370 performMovement(v); 20371 20372 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 20373 lastScrolledDestiny = v.anchorLink; 20374 20375 //avoid firing it twice (as it does also on scroll) 20376 activateMenuAndNav(v.anchorLink, v.sectionIndex); 20377 } 20378 20379 /** 20380 * Performs the vertical movement (by CSS3 or by jQuery) 20381 */ 20382 function performMovement(v){ 20383 // using CSS3 translate functionality 20384 if (options.css3 && options.autoScrolling && !options.scrollBar) { 20385 20386 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 20387 // that's why we round it to 0. 20388 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 20389 transformContainer(translate3d, true); 20390 20391 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 20392 //scrollingSpeed to change in case of using silentMoveTo(); 20393 if(options.scrollingSpeed){ 20394 clearTimeout(afterSectionLoadsId); 20395 afterSectionLoadsId = setTimeout(function () { 20396 afterSectionLoads(v); 20397 }, options.scrollingSpeed); 20398 }else{ 20399 afterSectionLoads(v); 20400 } 20401 } 20402 20403 // using jQuery animate 20404 else{ 20405 var scrollSettings = getScrollSettings(v); 20406 20407 $(scrollSettings.element).animate( 20408 scrollSettings.options, 20409 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 20410 if(options.scrollBar){ 20411 20412 /* Hack! 20413 The timeout prevents setting the most dominant section in the viewport as "active" when the user 20414 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 20415 20416 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 20417 */ 20418 setTimeout(function(){ 20419 afterSectionLoads(v); 20420 },30); 20421 }else{ 20422 afterSectionLoads(v); 20423 } 20424 }); 20425 } 20426 } 20427 20428 /** 20429 * Gets the scrolling settings depending on the plugin autoScrolling option 20430 */ 20431 function getScrollSettings(v){ 20432 var scroll = {}; 20433 20434 if(options.autoScrolling && !options.scrollBar){ 20435 scroll.options = { 'top': -v.dtop}; 20436 scroll.element = WRAPPER_SEL; 20437 }else{ 20438 scroll.options = { 'scrollTop': v.dtop}; 20439 scroll.element = 'html, body'; 20440 } 20441 20442 return scroll; 20443 } 20444 20445 /** 20446 * Adds sections before or after the current one to create the infinite effect. 20447 */ 20448 function createInfiniteSections(v){ 20449 // Scrolling down 20450 if (!v.isMovementUp) { 20451 // Move all previous sections to after the active section 20452 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 20453 } 20454 else { // Scrolling up 20455 // Move all next sections to before the active section 20456 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 20457 } 20458 20459 // Maintain the displayed position (now that we changed the element order) 20460 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20461 20462 // Maintain the active slides visible in the viewport 20463 keepSlidesPosition(); 20464 20465 // save for later the elements that still need to be reordered 20466 v.wrapAroundElements = v.activeSection; 20467 20468 // Recalculate animation variables 20469 v.dtop = v.element.position().top; 20470 v.yMovement = getYmovement(v.element); 20471 20472 return v; 20473 } 20474 20475 /** 20476 * Fix section order after continuousVertical changes have been animated 20477 */ 20478 function continuousVerticalFixSectionOrder (v) {
20479 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 20480 // finish moving the elements around so the direct navigation will function more simply 20481 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 20482 return; 20483 } 20484 20485 if (v.isMovementUp) { 20486 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 20487 } 20488 else { 20489 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 20490 } 20491 20492 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20493 20494 // Maintain the active slides visible in the viewport 20495 keepSlidesPosition(); 20496 } 20497 20498 20499 /** 20500 * Actions to do once the section is loaded. 20501 */ 20502 function afterSectionLoads (v){ 20503 continuousVerticalFixSectionOrder(v); 20504 20505 //callback (afterLoad) if the site is not just resizing and readjusting the slides 20506 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 20507 options.scrollOverflowHandler.afterLoad(); 20508 20509 if(!v.localIsResizing){ 20510 playMedia(v.element); 20511 } 20512 20513 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 20514 20515 canScroll = true; 20516 20517 $.isFunction(v.callback) && v.callback.call(this); 20518 } 20519 20520 /** 20521 * Sets the value for the given attribute from the `data-` attribute with the same suffix 20522 * ie: data-srcset ==> srcset | data-src ==> src 20523 */ 20524 function setSrc(element, attribute){ 20525 element 20526 .attr(attribute, element.data(attribute)) 20527 .removeAttr('data-' + attribute); 20528 } 20529 20530 /** 20531 * Lazy loads image, video and audio elements. 20532 */ 20533 function lazyLoad(destiny){ 20534 if (!options.lazyLoading){ 20535 return; 20536 } 20537 20538 var panel = getSlideOrSection(destiny); 20539 var element; 20540 20541 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 20542 element = $(this); 20543 20544 $.each(['src', 'srcset'], function(index, type){ 20545 var attribute = element.attr('data-' + type); 20546 if(typeof attribute !== 'undefined' && attribute){ 20547 setSrc(element, type); 20548 } 20549 }); 20550 20551 if(element.is('source')){ 20552 element.closest('video').get(0).load(); 20553 } 20554 }); 20555 } 20556 20557 /** 20558 * Plays video and audio elements. 20559 */ 20560 function playMedia(destiny){ 20561 var panel = getSlideOrSection(destiny); 20562 20563 //playing HTML5 media elements 20564 panel.find('video, audio').each(function(){ 20565 var element = $(this).get(0); 20566 20567 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 20568 element.play(); 20569 } 20570 }); 20571 20572 //youtube videos 20573 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20574 var element = $(this).get(0); 20575 20576 if ( element.hasAttribute('data-autoplay') ){ 20577 playYoutube(element); 20578 } 20579 20580 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 20581 element.onload = function() { 20582 if ( element.hasAttribute('data-autoplay') ){ 20583 playYoutube(element); 20584 } 20585 }; 20586 }); 20587 } 20588 20589 /** 20590 * Plays a youtube video 20591 */ 20592 function playYoutube(element){ 20593 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 20594 } 20595 20596 /** 20597 * Stops video and audio elements. 20598 */ 20599 function stopMedia(destiny){ 20600 var panel = getSlideOrSection(destiny); 20601 20602 //stopping HTML5 media elements 20603 panel.find('video, audio').each(function(){ 20604 var element = $(this).get(0); 20605 20606 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 20607 element.pause(); 20608 } 20609 }); 20610 20611 //youtube videos 20612 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20613 var element = $(this).get(0); 20614 20615 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 20616 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 20617 } 20618 }); 20619 } 20620 20621 /** 20622 * Gets the active slide (or section) for the given section 20623 */ 20624 function getSlideOrSection(destiny){ 20625 var slide = destiny.find(SLIDE_ACTIVE_SEL); 20626 if( slide.length ) { 20627 destiny = $(slide); 20628 } 20629 20630 return destiny; 20631 } 20632 20633 /**
20634 * Scrolls to the anchor in the URL when loading the site 20635 */ 20636 function scrollToAnchor(){ 20637 //getting the anchor link in the URL and deleting the `#` 20638 var value = window.location.hash.replace('#', '').split('/'); 20639 var sectionAnchor = decodeURIComponent(value[0]); 20640 var slideAnchor = decodeURIComponent(value[1]); 20641 20642 if(sectionAnchor){ //if theres any # 20643 if(options.animateAnchor){ 20644 scrollPageAndSlide(sectionAnchor, slideAnchor); 20645 }else{ 20646 silentMoveTo(sectionAnchor, slideAnchor); 20647 } 20648 } 20649 } 20650 20651 /** 20652 * Detecting any change on the URL to scroll to the given anchor link 20653 * (a way to detect back history button as we play with the hashes on the URL) 20654 */ 20655 function hashChangeHandler(){ 20656 if(!isScrolling && !options.lockAnchors){ 20657 var value = window.location.hash.replace('#', '').split('/'); 20658 var sectionAnchor = decodeURIComponent(value[0]); 20659 var slideAnchor = decodeURIComponent(value[1]); 20660 20661 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 20662 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 20663 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 20664 20665 20666 if(sectionAnchor.length){ 20667 /*in order to call scrollpage() only once for each destination at a time 20668 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 20669 event is fired on every scroll too.*/ 20670 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 20671 scrollPageAndSlide(sectionAnchor, slideAnchor); 20672 } 20673 } 20674 } 20675 } 20676 20677 //Sliding with arrow keys, both, vertical and horizontal 20678 function keydownHandler(e) { 20679 20680 clearTimeout(keydownId); 20681 20682 var activeElement = $(':focus'); 20683 20684 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 20685 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 20686 options.keyboardScrolling && options.autoScrolling){ 20687 var keyCode = e.which; 20688 20689 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 20690 var keyControls = [40, 38, 32, 33, 34]; 20691 if($.inArray(keyCode, keyControls) > -1){ 20692 e.preventDefault(); 20693 } 20694 20695 controlPressed = e.ctrlKey; 20696 20697 keydownId = setTimeout(function(){ 20698 onkeydown(e); 20699 },150); 20700 } 20701 } 20702 20703 function tooltipTextHandler(){ 20704 $(this).prev().trigger('click'); 20705 } 20706 20707 //to prevent scrolling while zooming 20708 function keyUpHandler(e){ 20709 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 20710 controlPressed = e.ctrlKey; 20711 } 20712 } 20713 20714 //binding the mousemove when the mouse's middle button is released 20715 function mouseDownHandler(e){ 20716 //middle button 20717 if (e.which == 2){ 20718 oldPageY = e.pageY; 20719 container.on('mousemove', mouseMoveHandler); 20720 } 20721 } 20722 20723 //unbinding the mousemove when the mouse's middle button is released 20724 function mouseUpHandler(e){ 20725 //middle button 20726 if (e.which == 2){ 20727 container.off('mousemove'); 20728 } 20729 } 20730 20731 //Scrolling horizontally when clicking on the slider controls. 20732 function slideArrowHandler(){ 20733 var section = $(this).closest(SECTION_SEL); 20734 20735 if ($(this).hasClass(SLIDES_PREV)) { 20736 if(isScrollAllowed.m.left){ 20737 moveSlideLeft(section); 20738 } 20739 } else { 20740 if(isScrollAllowed.m.right){ 20741 moveSlideRight(section); 20742 } 20743 } 20744 } 20745 20746 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 20747 function blurHandler(){ 20748 isWindowFocused = false;
20749 controlPressed = false; 20750 } 20751 20752 //Scrolls to the section when clicking the navigation bullet 20753 function sectionBulletHandler(e){ 20754 e.preventDefault(); 20755 var index = $(this).parent().index(); 20756 scrollPage($(SECTION_SEL).eq(index)); 20757 } 20758 20759 //Scrolls the slider to the given slide destination for the given section 20760 function slideBulletHandler(e){ 20761 e.preventDefault(); 20762 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 20763 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 20764 20765 landscapeScroll(slides, destiny); 20766 } 20767 20768 /** 20769 * Keydown event 20770 */ 20771 function onkeydown(e){ 20772 var shiftPressed = e.shiftKey; 20773 20774 //do nothing if we can not scroll or we are not using horizotnal key arrows. 20775 if(!canScroll && [37,39].indexOf(e.which) < 0){ 20776 return; 20777 } 20778 20779 switch (e.which) { 20780 //up 20781 case 38: 20782 case 33: 20783 if(isScrollAllowed.k.up){ 20784 moveSectionUp(); 20785 } 20786 break; 20787 20788 //down 20789 case 32: //spacebar 20790 if(shiftPressed && isScrollAllowed.k.up){ 20791 moveSectionUp(); 20792 break; 20793 } 20794 /* falls through */ 20795 case 40: 20796 case 34: 20797 if(isScrollAllowed.k.down){ 20798 moveSectionDown(); 20799 } 20800 break; 20801 20802 //Home 20803 case 36: 20804 if(isScrollAllowed.k.up){ 20805 moveTo(1); 20806 } 20807 break; 20808 20809 //End 20810 case 35: 20811 if(isScrollAllowed.k.down){ 20812 moveTo( $(SECTION_SEL).length ); 20813 } 20814 break; 20815 20816 //left 20817 case 37: 20818 if(isScrollAllowed.k.left){ 20819 moveSlideLeft(); 20820 } 20821 break; 20822 20823 //right 20824 case 39: 20825 if(isScrollAllowed.k.right){ 20826 moveSlideRight(); 20827 } 20828 break; 20829 20830 default: 20831 return; // exit this handler for other keys 20832 } 20833 } 20834 20835 /** 20836 * Detecting the direction of the mouse movement. 20837 * Used only for the middle button of the mouse. 20838 */ 20839 var oldPageY = 0; 20840 function mouseMoveHandler(e){ 20841 if(canScroll){ 20842 // moving up 20843 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 20844 moveSectionUp(); 20845 } 20846 20847 // moving down 20848 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 20849 moveSectionDown(); 20850 } 20851 } 20852 oldPageY = e.pageY; 20853 } 20854 20855 /** 20856 * Scrolls horizontal sliders. 20857 */ 20858 function landscapeScroll(slides, destiny, direction){ 20859 var section = slides.closest(SECTION_SEL); 20860 var v = { 20861 slides: slides, 20862 destiny: destiny, 20863 direction: direction, 20864 destinyPos: destiny.position(), 20865 slideIndex: destiny.index(), 20866 section: section, 20867 sectionIndex: section.index(SECTION_SEL), 20868 anchorLink: section.data('anchor'), 20869 slidesNav: section.find(SLIDES_NAV_SEL), 20870 slideAnchor: getAnchor(destiny), 20871 prevSlide: section.find(SLIDE_ACTIVE_SEL), 20872 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 20873 20874 //caching the value of isResizing at the momment the function is called 20875 //because it will be checked later inside a setTimeout and the value might change 20876 localIsResizing: isResizing 20877 }; 20878 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 20879 20880 //important!! Only do it when not resizing 20881 if(!v.localIsResizing){ 20882 //preventing from scrolling to the next/prev section when using scrollHorizontally 20883 canScroll = false;
20884 } 20885 20886 if(options.onSlideLeave){ 20887 20888 //if the site is not just resizing and readjusting the slides 20889 if(!v.localIsResizing && v.xMovement!=='none'){ 20890 if($.isFunction( options.onSlideLeave )){ 20891 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 20892 slideMoving = false; 20893 return; 20894 } 20895 } 20896 } 20897 } 20898 20899 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20900 20901 if(!v.localIsResizing){ 20902 stopMedia(v.prevSlide); 20903 lazyLoad(destiny); 20904 } 20905 20906 if(!options.loopHorizontal && options.controlArrows){ 20907 //hidding it for the fist slide, showing for the rest 20908 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 20909 20910 //hidding it for the last slide, showing for the rest 20911 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 20912 } 20913 20914 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 20915 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 20916 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 20917 } 20918 20919 performHorizontalMove(slides, v, true); 20920 } 20921 20922 20923 function afterSlideLoads(v){ 20924 activeSlidesNavigation(v.slidesNav, v.slideIndex); 20925 20926 //if the site is not just resizing and readjusting the slides 20927 if(!v.localIsResizing){ 20928 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 20929 20930 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 20931 //and to prevent double scroll right after a windows resize 20932 canScroll = true; 20933 20934 playMedia(v.destiny); 20935 } 20936 20937 //letting them slide again 20938 slideMoving = false; 20939 } 20940 20941 /** 20942 * Performs the horizontal movement. (CSS3 or jQuery) 20943 * 20944 * @param fireCallback {Bool} - determines whether or not to fire the callback 20945 */ 20946 function performHorizontalMove(slides, v, fireCallback){ 20947 var destinyPos = v.destinyPos; 20948 20949 if(options.css3){ 20950 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 20951 20952 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 20953 20954 afterSlideLoadsId = setTimeout(function(){ 20955 fireCallback && afterSlideLoads(v); 20956 }, options.scrollingSpeed, options.easing); 20957 }else{ 20958 slides.animate({ 20959 scrollLeft : Math.round(destinyPos.left) 20960 }, options.scrollingSpeed, options.easing, function() { 20961 20962 fireCallback && afterSlideLoads(v); 20963 }); 20964 } 20965 } 20966 20967 /** 20968 * Sets the state for the horizontal bullet navigations. 20969 */ 20970 function activeSlidesNavigation(slidesNav, slideIndex){ 20971 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 20972 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 20973 } 20974 20975 var previousHeight = windowsHeight; 20976 20977 //when resizing the site, we adjust the heights of the sections, slimScroll... 20978 function resizeHandler(){ 20979 //checking if it needs to get responsive 20980 responsive(); 20981 20982 // rebuild immediately on touch devices 20983 if (isTouchDevice) { 20984 var activeElement = $(document.activeElement); 20985 20986 //if the keyboard is NOT visible 20987 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 20988 var currentHeight = $window.height(); 20989 20990 //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) 20991 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 20992 reBuild(true); 20993 previousHeight = currentHeight; 20994 } 20995 } 20996 }else{ 20997 //in order to call the functions only when the resize is finished 20998 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 20999 clearTimeout(resizeId); 21000 21001 resizeId = setTimeout(function(){ 21002 reBuild(true); 21003 }, 350); 21004 } 21005 } 21006 21007 /** 21008 * Checks if the site needs to get responsive and disables autoScrolling if so. 21009 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 21010 */ 21011 function responsive(){ 21012 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 21013 var heightLimit = options.responsiveHeight; 21014 21015 //only calculating what we need. Remember its called on the resize event. 21016 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 21017 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 21018 21019 if(widthLimit && heightLimit){ 21020 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 21021 } 21022 else if(widthLimit){ 21023 setResponsive(isBreakingPointWidth); 21024 } 21025 else if(heightLimit){ 21026 setResponsive(isBreakingPointHeight); 21027 } 21028 } 21029 21030 /** 21031 * Adds transition animations for the given element 21032 */ 21033 function addAnimation(container, element){ 21034 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 21035 21036 container.removeClass(NO_TRANSITION); 21037 return container.css({
21038 '-webkit-transition': transition, 21039 'transition': transition 21040 }); 21041 } 21042 21043 /** 21044 * Remove transition animations for the given element 21045 */ 21046 function removeAnimation(element){ 21047 return element.addClass(NO_TRANSITION); 21048 } 21049 21050 /** 21051 * Activating the vertical navigation bullets according to the given slide name. 21052 */ 21053 function activateNavDots(name, sectionIndex){ 21054 if(options.navigation){ 21055 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 21056 if(name){ 21057 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 21058 }else{ 21059 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 21060 } 21061 } 21062 } 21063 21064 /** 21065 * Activating the website main menu elements according to the given slide name. 21066 */ 21067 function activateMenuElement(name){ 21068 if(options.menu){ 21069 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 21070 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 21071 } 21072 } 21073 21074 /** 21075 * Sets to active the current menu and vertical nav items. 21076 */ 21077 function activateMenuAndNav(anchor, index){ 21078 activateMenuElement(anchor); 21079 activateNavDots(anchor, index); 21080 } 21081 21082 /** 21083 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 21084 * from the current section. 21085 */ 21086 function getYmovement(destiny){ 21087 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 21088 var toIndex = destiny.index(SECTION_SEL); 21089 if( fromIndex == toIndex){ 21090 return 'none'; 21091 } 21092 if(fromIndex > toIndex){ 21093 return 'up'; 21094 } 21095 return 'down'; 21096 } 21097 21098 /** 21099 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 21100 * from the current slide. 21101 */ 21102 function getXmovement(fromIndex, toIndex){ 21103 if( fromIndex == toIndex){ 21104 return 'none'; 21105 } 21106 if(fromIndex > toIndex){ 21107 return 'left'; 21108 } 21109 return 'right'; 21110 } 21111 21112 /** 21113 * Checks if the element needs scrollbar and if the user wants to apply it. 21114 * If so it creates it. 21115 * 21116 * @param {Object} element jQuery object of the section or slide 21117 */ 21118 function createScrollBar(element){ 21119 //User doesn't want scrollbar here? Sayonara baby! 21120 if(element.hasClass('fp-noscroll')) return; 21121 21122 //needed to make `scrollHeight` work under Opera 12 21123 element.css('overflow', 'hidden'); 21124 21125 var scrollOverflowHandler = options.scrollOverflowHandler; 21126 var wrap = scrollOverflowHandler.wrapContent(); 21127 //in case element is a slide 21128 var section = element.closest(SECTION_SEL); 21129 var scrollable = scrollOverflowHandler.scrollable(element); 21130 var contentHeight; 21131 21132 //if there was scroll, the contentHeight will be the one in the scrollable section 21133 if(scrollable.length){ 21134 contentHeight = scrollOverflowHandler.scrollHeight(element); 21135 }else{ 21136 contentHeight = element.get(0).scrollHeight; 21137 if(options.verticalCentered){ 21138 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 21139 } 21140 } 21141 21142 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 21143 //Uncode addition 21144 scrollHeight -= UNCODE.bodyBorder*2 + UNCODE.adminBarHeight; 21145 21146 //needs scroll? 21147 if ( contentHeight > scrollHeight) { 21148 //did we already have an scrollbar ? Updating it 21149 if(scrollable.length){ 21150 scrollOverflowHandler.update(element, scrollHeight); 21151 } 21152 //creating the scrolling 21153 else{ 21154 if(options.verticalCentered){ 21155 element.find(TABLE_CELL_SEL).wrapInner(wrap); 21156 }else{ 21157 element.wrapInner(wrap); 21158 } 21159 scrollOverflowHandler.create(element, scrollHeight); 21160 } 21161 } 21162 //removing the scrolling when it is not necessary anymore 21163 else{ 21164 scrollOverflowHandler.remove(element); 21165 } 21166 21167 //undo 21168 element.css('overflow', ''); 21169 } 21170 21171 function addTableClass(element){ 21172 //In case we are styling for the 2nd time as in with reponsiveSlides 21173 if(!element.hasClass(TABLE)){ 21174 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 21175 } 21176 } 21177 21178 function getTableHeight(element){ 21179 var sectionHeight = windowsHeight; 21180 21181 if(options.paddingTop || options.paddingBottom){ 21182 var section = element; 21183 if(!section.hasClass(SECTION)){ 21184 section = element.closest(SECTION_SEL); 21185 } 21186 21187 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 21188 sectionHeight = (windowsHeight - paddings); 21189 } 21190 21191 return sectionHeight; 21192 } 21193 21194 /** 21195 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 21196 */ 21197 function transformContainer(translate3d, animated){ 21198 if(animated){ 21199 addAnimation(container); 21200 }else{ 21201 removeAnimation(container); 21202 } 21203 21204 container.css(getTransforms(translate3d)); 21205 21206 //syncronously removing the class after the animation has been applied. 21207 setTimeout(function(){ 21208 container.removeClass(NO_TRANSITION); 21209 },10); 21210 } 21211 21212 /** 21213 * Gets a section by its anchor / index 21214 */ 21215 function getSectionByAnchor(sectionAnchor){ 21216 if(!sectionAnchor) return []; 21217 21218 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 21219 if(!section.length){ 21220 section = $(SECTION_SEL).eq( sectionAnchor -1); 21221 } 21222 21223 return section; 21224 } 21225 21226 /** 21227 * Gets a slide inside a given section by its anchor / index 21228 */ 21229 function getSlideByAnchor(slideAnchor, section){ 21230 var slides = section.find(SLIDES_WRAPPER_SEL); 21231 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 21232
21233 if(!slide.length){ 21234 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 21235 } 21236 21237 return slide; 21238 } 21239 21240 /** 21241 * Scrolls to the given section and slide anchors 21242 */ 21243 function scrollPageAndSlide(destiny, slide){ 21244 var section = getSectionByAnchor(destiny); 21245 21246 //do nothing if there's no section with the given anchor name 21247 if(!section.length) return; 21248 21249 //default slide 21250 if (typeof slide === 'undefined') { 21251 slide = 0; 21252 } 21253 21254 //we need to scroll to the section and then to the slide 21255 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 21256 scrollPage(section, function(){ 21257 scrollSlider(section, slide); 21258 }); 21259 } 21260 //if we were already in the section 21261 else{ 21262 scrollSlider(section, slide); 21263 } 21264 } 21265 21266 /** 21267 * Scrolls the slider to the given slide destination for the given section 21268 */ 21269 function scrollSlider(section, slideAnchor){ 21270 if(typeof slideAnchor !== 'undefined'){ 21271 var slides = section.find(SLIDES_WRAPPER_SEL); 21272 var destiny = getSlideByAnchor(slideAnchor, section); 21273 21274 if(destiny.length){ 21275 landscapeScroll(slides, destiny); 21276 } 21277 } 21278 } 21279 21280 /** 21281 * Creates a landscape navigation bar with dots for horizontal sliders. 21282 */ 21283 function addSlidesNavigation(section, numSlides){ 21284 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 21285 var nav = section.find(SLIDES_NAV_SEL); 21286 21287 //top or bottom 21288 nav.addClass(options.slidesNavPosition); 21289 21290 for(var i=0; i< numSlides; i++){ 21291 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 21292 } 21293 21294 //centering it 21295 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 21296 21297 nav.find('li').first().find('a').addClass(ACTIVE); 21298 } 21299 21300 21301 /** 21302 * Sets the state of the website depending on the active section/slide. 21303 * It changes the URL hash when needed and updates the body class. 21304 */ 21305 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 21306 var sectionHash = ''; 21307 21308 if(options.anchors.length && !options.lockAnchors){ 21309 21310 //isn't it the first slide? 21311 if(slideIndex){ 21312 if(typeof anchorLink !== 'undefined'){ 21313 sectionHash = anchorLink; 21314 } 21315 21316 //slide without anchor link? We take the index instead. 21317 if(typeof slideAnchor === 'undefined'){ 21318 slideAnchor = slideIndex; 21319 } 21320 21321 lastScrolledSlide = slideAnchor; 21322 setUrlHash(sectionHash + '/' + slideAnchor); 21323 21324 //first slide won't have slide anchor, just the section one 21325 }else if(typeof slideIndex !== 'undefined'){ 21326 lastScrolledSlide = slideAnchor; 21327 setUrlHash(anchorLink); 21328 } 21329 21330 //section without slides 21331 else{ 21332 setUrlHash(anchorLink); 21333 } 21334 } 21335 21336 setBodyClass(); 21337 } 21338 21339 /** 21340 * Sets the URL hash. 21341 */ 21342 function setUrlHash(url){ 21343 //Uncode addition 21344 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 21345 return false; 21346 21347 if(options.recordHistory){ 21348 location.hash = url; 21349 }else{ 21350 //Uncode addition 21351 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 21352 // if(isTouchDevice || isTouch){ 21353 // window.history.replaceState(undefined, undefined, '#' + url); 21354 // }else{ 21355 // var baseUrl = window.location.href.split('#')[0]; 21356 // window.location.replace( baseUrl + '#' + url ); 21357 // } 21358 return false;
21359 } 21360 } 21361 21362 /** 21363 * Gets the anchor for the given slide / section. Its index will be used if there's none. 21364 */ 21365 function getAnchor(element){ 21366 var anchor = element.data('anchor'); 21367 var index = element.index(); 21368 21369 //Slide without anchor link? We take the index instead. 21370 if(typeof anchor === 'undefined'){ 21371 anchor = index; 21372 } 21373 21374 return anchor; 21375 } 21376 21377 /** 21378 * Sets a class for the body of the page depending on the active section / slide 21379 */ 21380 function setBodyClass(){ 21381 var section = $(SECTION_ACTIVE_SEL); 21382 var slide = section.find(SLIDE_ACTIVE_SEL); 21383 21384 var sectionAnchor = getAnchor(section); 21385 var slideAnchor = getAnchor(slide); 21386 21387 var text = String(sectionAnchor); 21388 21389 if(slide.length){ 21390 text = text + '-' + slideAnchor; 21391 } 21392 21393 //changing slash for dash to make it a valid CSS style 21394 text = text.replace('/', '-').replace('#',''); 21395 21396 //removing previous anchor classes 21397 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 21398 $body[0].className = $body[0].className.replace(classRe, ''); 21399 21400 //adding the current anchor 21401 $body.addClass(VIEWING_PREFIX + '-' + text); 21402 } 21403 21404 /** 21405 * Checks for translate3d support 21406 * @return boolean 21407 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 21408 */ 21409 function support3d() { 21410 var el = document.createElement('p'), 21411 has3d, 21412 transforms = { 21413 'webkitTransform':'-webkit-transform', 21414 'OTransform':'-o-transform', 21415 'msTransform':'-ms-transform', 21416 'MozTransform':'-moz-transform', 21417 'transform':'transform' 21418 }; 21419 21420 // Add it to the body to get the computed style. 21421 document.body.insertBefore(el, null); 21422 21423 for (var t in transforms) { 21424 if (el.style[t] !== undefined) { 21425 el.style[t] = 'translate3d(1px,1px,1px)'; 21426 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 21427 } 21428 } 21429 21430 document.body.removeChild(el); 21431 21432 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 21433 } 21434 21435 /** 21436 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 21437 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 21438 */ 21439 function removeMouseWheelHandler(){ 21440 if (document.addEventListener) { 21441 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 21442 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 21443 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 21444 } else { 21445 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 21446 } 21447 } 21448 21449 /** 21450 * Adds the auto scrolling action for the mouse wheel and trackpad. 21451 * After this function is called, the mousewheel and trackpad movements will scroll through sections 21452 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 21453 */ 21454 function addMouseWheelHandler(){ 21455 var prefix = ''; 21456 var _addEventListener; 21457 21458 if (window.addEventListener){ 21459 _addEventListener = "addEventListener"; 21460 }else{ 21461 _addEventListener = "attachEvent"; 21462 prefix = 'on'; 21463 } 21464 21465 // detect available wheel event 21466 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 21467 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 21468 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 21469 21470 21471 if(support == 'DOMMouseScroll'){ 21472 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false); 21473 } 21474 21475 //handle MozMousePixelScroll in older Firefox 21476 else{ 21477 document[ _addEventListener ](prefix + support, MouseWheelHandler, false); 21478 } 21479 } 21480 21481 /** 21482 * Binding the mousemove when the mouse's middle button is pressed 21483 */ 21484 function addMiddleWheelHandler(){ 21485 container 21486 .on('mousedown', mouseDownHandler) 21487 .on('mouseup', mouseUpHandler); 21488 } 21489 21490 /** 21491 * Unbinding the mousemove when the mouse's middle button is released 21492 */ 21493 function removeMiddleWheelHandler(){ 21494 container 21495 .off('mousedown', mouseDownHandler) 21496 .off('mouseup', mouseUpHandler); 21497 } 21498 21499 /** 21500 * Adds the possibility to auto scroll through sections on touch devices. 21501 */ 21502 function addTouchHandler(){ 21503 if(isTouchDevice || isTouch){ 21504 if(options.autoScrolling){ 21505 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 21506 } 21507 21508 $(WRAPPER_SEL) 21509 .off(events.touchstart).on(events.touchstart, touchStartHandler) 21510 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 21511 } 21512 } 21513 21514 /** 21515 * Removes the auto scrolling for touch devices. 21516 */ 21517 function removeTouchHandler(){ 21518 if(isTouchDevice || isTouch){ 21519 $(WRAPPER_SEL) 21520 .off(events.touchstart) 21521 .off(events.touchmove); 21522 } 21523 } 21524 21525 /* 21526 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
21527 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 21528 */ 21529 function getMSPointer(){ 21530 var pointer; 21531 21532 //IE >= 11 & rest of browsers 21533 if(window.PointerEvent){ 21534 pointer = { down: 'pointerdown', move: 'pointermove'}; 21535 } 21536 21537 //IE < 11 21538 else{ 21539 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 21540 } 21541 21542 return pointer; 21543 } 21544 21545 /** 21546 * Gets the pageX and pageY properties depending on the browser. 21547 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 21548 */ 21549 function getEventsPage(e){ 21550 var events = []; 21551 21552 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 21553 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 21554 21555 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 21556 if(isTouch && isReallyTouch(e) && options.scrollBar){ 21557 events.y = e.touches[0].pageY; 21558 events.x = e.touches[0].pageX; 21559 } 21560 21561 return events; 21562 } 21563 21564 /** 21565 * Slides silently (with no animation) the active slider to the given slide. 21566 * @param noCallback {bool} true or defined -> no callbacks 21567 */ 21568 function silentLandscapeScroll(activeSlide, noCallbacks){ 21569 setScrollingSpeed (0, 'internal'); 21570 21571 if(typeof noCallbacks !== 'undefined'){ 21572 //preventing firing callbacks afterSlideLoad etc. 21573 isResizing = true; 21574 } 21575 21576 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 21577 21578 if(typeof noCallbacks !== 'undefined'){ 21579 isResizing = false; 21580 } 21581 21582 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 21583 } 21584 21585 /** 21586 * Scrolls silently (with no animation) the page to the given Y position. 21587 */ 21588 function silentScroll(top){ 21589 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 21590 // that's why we round it to 0. 21591 var roundedTop = Math.round(top); 21592 21593 if (options.css3 && options.autoScrolling && !options.scrollBar){ 21594 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 21595 transformContainer(translate3d, false); 21596 } 21597 else if(options.autoScrolling && !options.scrollBar){ 21598 container.css('top', -roundedTop); 21599 } 21600 else{ 21601 $htmlBody.scrollTop(roundedTop); 21602 } 21603 } 21604 21605 /** 21606 * Returns the cross-browser transform string. 21607 */ 21608 function getTransforms(translate3d){ 21609 return { 21610 '-webkit-transform': translate3d, 21611 '-moz-transform': translate3d, 21612 '-ms-transform':translate3d, 21613 'transform': translate3d 21614 }; 21615 } 21616 21617 /** 21618 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 21619 * @type m (mouse) or k (keyboard) 21620 */ 21621 function setIsScrollAllowed(value, direction, type){ 21622 switch (direction){ 21623 case 'up': isScrollAllowed[type].up = value; break; 21624 case 'down': isScrollAllowed[type].down = value; break; 21625 case 'left': isScrollAllowed[type].left = value; break; 21626 case 'right': isScrollAllowed[type].right = value; break; 21627 case 'all': 21628 if(type == 'm'){ 21629 setAllowScrolling(value); 21630 }else{ 21631 setKeyboardScrolling(value); 21632 } 21633 } 21634 } 21635 21636 /* 21637 * Destroys fullpage.js plugin events and optinally its html markup and styles 21638 */ 21639 function destroy(all){ 21640 setAutoScrolling(false, 'internal'); 21641 setAllowScrolling(false); 21642 setKeyboardScrolling(false); 21643 container.addClass(DESTROYED); 21644 21645 clearTimeout(afterSlideLoadsId); 21646 clearTimeout(afterSectionLoadsId); 21647 clearTimeout(resizeId); 21648 clearTimeout(scrollId); 21649 clearTimeout(scrollId2); 21650 21651 $window 21652 .off('scroll', scrollHandler) 21653 .off('hashchange', hashChangeHandler) 21654 .off('resize', resizeHandler); 21655 21656 $document 21657 .off('click touchstart', SECTION_NAV_SEL + ' a') 21658 .off('mouseenter', SECTION_NAV_SEL + ' li') 21659 .off('mouseleave', SECTION_NAV_SEL + ' li') 21660 .off('click touchstart', SLIDES_NAV_LINK_SEL) 21661 .off('mouseover', options.normalScrollElements) 21662 .off('mouseout', options.normalScrollElements); 21663 21664 $(SECTION_SEL) 21665 .off('click touchstart', SLIDES_ARROW_SEL); 21666 21667 clearTimeout(afterSlideLoadsId); 21668 clearTimeout(afterSectionLoadsId); 21669 21670 //lets make a mess! 21671 if(all){ 21672 destroyStructure(); 21673 } 21674 } 21675 21676 /* 21677 * Removes inline styles added by fullpage.js 21678 */ 21679 function destroyStructure(){ 21680 //reseting the `top` or `translate` properties to 0 21681 silentScroll(0); 21682 21683 //loading all the lazy load content 21684 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 21685 setSrc($(this), 'src'); 21686 }); 21687 21688 container.find('img[data-srcset]').each(function(){ 21689 setSrc($(this), 'srcset'); 21690 }); 21691 21692 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 21693 21694 //removing inline styles 21695 $(SECTION_SEL).css( { 21696 'height': '', 21697 'background-color' : '', 21698 'padding': '' 21699 }); 21700 21701 $(SLIDE_SEL).css( { 21702 'width': '' 21703 }); 21704 21705 container.css({ 21706 'height': '', 21707 'position': '',
21708 '-ms-touch-action': '', 21709 'touch-action': '' 21710 }); 21711 21712 $htmlBody.css({ 21713 'overflow': '', 21714 'height': '' 21715 }); 21716 21717 // remove .fp-enabled class 21718 $('html').removeClass(ENABLED); 21719 21720 // remove .fp-responsive class 21721 $body.removeClass(RESPONSIVE); 21722 21723 // remove all of the .fp-viewing- classes 21724 $.each($body.get(0).className.split(/\s+/), function (index, className) { 21725 if (className.indexOf(VIEWING_PREFIX) === 0) { 21726 $body.removeClass(className); 21727 } 21728 }); 21729 21730 //removing added classes 21731 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 21732 options.scrollOverflowHandler.remove($(this)); 21733 $(this).removeClass(TABLE + ' ' + ACTIVE); 21734 }); 21735 21736 removeAnimation(container); 21737 21738 //Unwrapping content 21739 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 21740 //unwrap not being use in case there's no child element inside and its just text 21741 $(this).replaceWith(this.childNodes); 21742 }); 21743 21744 //removing the applied transition from the fullpage wrapper 21745 container.css({ 21746 '-webkit-transition': 'none', 21747 'transition': 'none' 21748 }); 21749 21750 //scrolling the page to the top with no animation 21751 $htmlBody.scrollTop(0); 21752 21753 //removing selectors 21754 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 21755 $.each(usedSelectors, function(index, value){ 21756 $('.' + value).removeClass(value); 21757 }); 21758 } 21759 21760 /* 21761 * Sets the state for a variable with multiple states (original, and temporal) 21762 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 21763 * This function is used to keep track of both states, the original and the temporal one. 21764 * If type is not 'internal', then we assume the user is globally changing the variable. 21765 */ 21766 function setVariableState(variable, value, type){ 21767 options[variable] = value; 21768 if(type !== 'internal'){ 21769 originals[variable] = value; 21770 } 21771 } 21772 21773 /** 21774 * Displays warnings 21775 */ 21776 function displayWarnings(){ 21777 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 21778 //UNCODE.addition 21779 // if($('html').hasClass(ENABLED)){ 21780 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 21781 // return; 21782 // } 21783 21784 // Disable mutually exclusive settings 21785 //UNCODE.addition 21786 // if (options.continuousVertical && 21787 // (options.loopTop || options.loopBottom)) { 21788 // options.continuousVertical = false;
21789 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21790 // } 21791 21792 // if(options.scrollBar && options.scrollOverflow){ 21793 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 21794 // } 21795 21796 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 21797 // options.continuousVertical = false; 21798 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21799 // } 21800 21801 //using extensions? Wrong file! 21802 $.each(extensions, function(index, extension){ 21803 //is the option set to true? 21804 if(options[extension]){ 21805 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 21806 } 21807 }); 21808 21809 //anchors can not have the same value as any element ID or NAME 21810 $.each(options.anchors, function(index, name){ 21811 21812 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 21813 var nameAttr = $document.find('[name]').filter(function() { 21814 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 21815 }); 21816 21817 var idAttr = $document.find('[id]').filter(function() { 21818 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 21819 }); 21820 21821 if(idAttr.length || nameAttr.length ){ 21822 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 21823 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 21824 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 21825 } 21826 }); 21827 } 21828 21829 /** 21830 * Shows a message in the console of the given type. 21831 */ 21832 function showError(type, text){ 21833 console && console[type] && console[type]('fullPage: ' + text); 21834 } 21835 21836 }; //end of $.fn.fullpage 21837 21838 if(typeof IScroll !== 'undefined'){ 21839 /* 21840 * Turns iScroll `mousewheel` option off dynamically 21841 * https://github.com/cubiq/iscroll/issues/1036 21842 */ 21843 IScroll.prototype.wheelOn = function () { 21844 this.wrapper.addEventListener('wheel', this); 21845 this.wrapper.addEventListener('mousewheel', this); 21846 this.wrapper.addEventListener('DOMMouseScroll', this); 21847 }; 21848 21849 /* 21850 * Turns iScroll `mousewheel` option on dynamically 21851 * https://github.com/cubiq/iscroll/issues/1036 21852 */ 21853 IScroll.prototype.wheelOff = function () { 21854 this.wrapper.removeEventListener('wheel', this); 21855 this.wrapper.removeEventListener('mousewheel', this); 21856 this.wrapper.removeEventListener('DOMMouseScroll', this); 21857 }; 21858 } 21859 21860 /** 21861 * An object to handle overflow scrolling. 21862 * This uses jquery.slimScroll to accomplish overflow scrolling. 21863 * It is possible to pass in an alternate scrollOverflowHandler 21864 * to the fullpage.js option that implements the same functions 21865 * as this handler. 21866 * 21867 * @type {Object} 21868 */ 21869 var iscrollHandler = { 21870 refreshId: null, 21871 iScrollInstances: [], 21872 21873 // Enables or disables the mouse wheel for the active section or all slides in it 21874 toggleWheel: function(value){ 21875 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 21876 scrollable.each(function(){ 21877 var iScrollInstance = $(this).data('iscrollInstance'); 21878 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 21879 if(value){ 21880 iScrollInstance.wheelOn(); 21881 } 21882 else{ 21883 iScrollInstance.wheelOff(); 21884 } 21885 } 21886 }); 21887 }, 21888 21889 /** 21890 * Turns off iScroll for the destination section. 21891 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
21892 * scroll the destination section/slide before the sections animations ends. 21893 */ 21894 onLeave: function(){ 21895 iscrollHandler.toggleWheel(false); 21896 }, 21897 21898 // Turns off iScroll for the leaving section 21899 beforeLeave: function(){ 21900 iscrollHandler.onLeave() 21901 }, 21902 21903 // Turns on iScroll on section load 21904 afterLoad: function(){ 21905 iscrollHandler.toggleWheel(true); 21906 }, 21907 21908 /** 21909 * Called when overflow scrolling is needed for a section. 21910 * 21911 * @param {Object} element jQuery object containing current section 21912 * @param {Number} scrollHeight Current window height in pixels 21913 */ 21914 create: function(element, scrollHeight) { 21915 var scrollable = element.find(SCROLLABLE_SEL); 21916 21917 scrollable.height(scrollHeight); 21918 scrollable.each(function() { 21919 var $this = $(this); 21920 var iScrollInstance = $this.data('iscrollInstance'); 21921 if (iScrollInstance) { 21922 $.each(iscrollHandler.iScrollInstances, function(){ 21923 $(this).destroy(); 21924 }); 21925 } 21926 21927 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 21928 iscrollHandler.iScrollInstances.push(iScrollInstance); 21929 21930 //off by default until the section gets active 21931 iScrollInstance.wheelOff(); 21932 21933 $this.data('iscrollInstance', iScrollInstance); 21934 }); 21935 }, 21936 21937 /** 21938 * Return a boolean depending on whether the scrollable element is a 21939 * the end or at the start of the scrolling depending on the given type. 21940 * 21941 * @param {String} type Either 'top' or 'bottom' 21942 * @param {Object} scrollable jQuery object for the scrollable element 21943 * @return {Boolean} 21944 */ 21945 isScrolled: function(type, scrollable) { 21946 var scroller = scrollable.data('iscrollInstance'); 21947 21948 //no scroller? 21949 if (!scroller) { 21950 return true; 21951 } 21952 21953 if (type === 'top') { 21954 return scroller.y >= 0 && !scrollable.scrollTop(); 21955 } else if (type === 'bottom') { 21956 return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight; 21957 } 21958 }, 21959 21960 /** 21961 * Returns the scrollable element for the given section. 21962 * If there are landscape slides, will only return a scrollable element 21963 * if it is in the active slide. 21964 * 21965 * @param {Object} activeSection jQuery object containing current section 21966 * @return {Boolean} 21967 */ 21968 scrollable: function(activeSection){ 21969 // if there are landscape slides, we check if the scrolling bar is in the current one or not 21970 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 21971 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 21972 } 21973 return activeSection.find(SCROLLABLE_SEL); 21974 }, 21975 21976 /** 21977 * Returns the scroll height of the wrapped content. 21978 * If this is larger than the window height minus section padding, 21979 * overflow scrolling is needed. 21980 * 21981 * @param {Object} element jQuery object containing current section 21982 * @return {Number} 21983 */ 21984 scrollHeight: function(element) { 21985 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 21986 }, 21987 21988 /** 21989 * Called when overflow scrolling is no longer needed for a section. 21990 * 21991 * @param {Object} element jQuery object containing current section 21992 */ 21993 remove: function(element) { 21994 var scrollable = element.find(SCROLLABLE_SEL); 21995 if (scrollable.length) { 21996 var iScrollInstance = scrollable.data('iscrollInstance'); 21997 iScrollInstance.destroy(); 21998 21999 scrollable.data('iscrollInstance', null); 22000 } 22001 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 22002 }, 22003 22004 /** 22005 * Called when overflow scrolling has already been setup but the 22006 * window height has potentially changed. 22007 * 22008 * @param {Object}
vendor: 16,384 bytes, lines 22008-22555
22008 element jQuery object containing current section 22009 * @param {Number} scrollHeight Current window height in pixels 22010 */ 22011 update: function(element, scrollHeight) { 22012 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 22013 //short period of time. 22014 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 22015 clearTimeout(iscrollHandler.refreshId); 22016 iscrollHandler.refreshId = setTimeout(function(){ 22017 $.each(iscrollHandler.iScrollInstances, function(){ 22018 $(this).get(0).refresh(); 22019 }); 22020 }, 150); 22021 22022 //updating the wrappers height 22023 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 22024 }, 22025 22026 /** 22027 * Called to get any additional elements needed to wrap the section 22028 * content in order to facilitate overflow scrolling. 22029 * 22030 * @return {String|Object} Can be a string containing HTML, 22031 * a DOM element, or jQuery object. 22032 */ 22033 wrapContent: function() { 22034 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 22035 } 22036 }; 22037}); 22038 22039 22040 22041/* ======================================================================== 22042 * Bootstrap: collapse.js v3.1.1 22043 * http://getbootstrap.com/javascript/#collapse 22044 * ======================================================================== 22045 * Copyright 2011-2014 Twitter, Inc. 22046 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22047 * ======================================================================== */ 22048 22049 22050+function ($) { 22051 'use strict'; 22052 22053 // COLLAPSE PUBLIC CLASS DEFINITION 22054 // ================================ 22055 22056 var Collapse = function (element, options) { 22057 this.$element = $(element) 22058 this.options = $.extend({}, Collapse.DEFAULTS, options) 22059 this.transitioning = null 22060 22061 if (this.options.parent) this.$parent = $(this.options.parent) 22062 if (this.options.toggle) this.toggle() 22063 } 22064 22065 Collapse.DEFAULTS = { 22066 toggle: true 22067 } 22068 22069 Collapse.prototype.dimension = function () { 22070 var hasWidth = this.$element.hasClass('width') 22071 return hasWidth ? 'width' : 'height' 22072 } 22073 22074 Collapse.prototype.show = function () { 22075 if (this.transitioning || this.$element.hasClass('in')) return 22076 22077 var startEvent = $.Event('show.bs.collapse') 22078 this.$element.trigger(startEvent) 22079 if (startEvent.isDefaultPrevented()) return 22080 22081 var actives = this.$parent && this.$parent.find('> .panel > .in') 22082 22083 if (actives && actives.length) { 22084 var hasData = actives.data('bs.collapse') 22085 if (hasData && hasData.transitioning) return 22086 actives.collapse('hide') 22087 hasData || actives.data('bs.collapse', null) 22088 } 22089 22090 var dimension = this.dimension() 22091 22092 this.$element 22093 .removeClass('collapse') 22094 .addClass('collapsing')[dimension](0) 22095 22096 this.transitioning = 1 22097 22098 var complete = function (e) { 22099 if (e && e.target != this.$element[0]) return 22100 this.$element 22101 .removeClass('collapsing') 22102 .addClass('collapse in')[dimension]('auto') 22103 this.transitioning = 0 22104 this.$element.trigger('shown.bs.collapse') 22105 } 22106 22107 if (!$.support.transition) return complete.call(this) 22108 22109 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 22110 22111 this.$element 22112 .one($.support.transition.end, $.proxy(complete, this)) 22113 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 22114 } 22115 22116 Collapse.prototype.hide = function () { 22117 if (this.transitioning || !this.$element.hasClass('in')) return 22118 22119 var startEvent = $.Event('hide.bs.collapse') 22120 this.$element.trigger(startEvent) 22121 if (startEvent.isDefaultPrevented()) return 22122 22123 var dimension = this.dimension() 22124 22125 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 22126 22127 this.$element 22128 .addClass('collapsing') 22129 .removeClass('collapse') 22130 .removeClass('in') 22131 22132 this.transitioning = 1 22133 22134 var complete = function (e) { 22135 if (e && e.target != this.$element[0]) return 22136 this.transitioning = 0 22137 this.$element 22138 .trigger('hidden.bs.collapse') 22139 .removeClass('collapsing') 22140 .addClass('collapse') 22141 } 22142 22143 if (!$.support.transition) return complete.call(this) 22144 22145 this.$element 22146 [dimension](0) 22147 .one($.support.transition.end, $.proxy(complete, this)) 22148 .emulateTransitionEnd(350) 22149 } 22150 22151 Collapse.prototype.toggle = function () { 22152 this[this.$element.hasClass('in') ? 'hide' : 'show']() 22153 } 22154 22155 22156 // COLLAPSE PLUGIN DEFINITION 22157 // ========================== 22158 22159 var old = $.fn.collapse 22160 22161 $.fn.collapse = function (option) { 22162 return this.each(function () { 22163 var $this = $(this) 22164 var data = $this.data('bs.collapse') 22165 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 22166 22167 if (!data && options.toggle && option == 'show') option = !option 22168 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 22169 if (typeof option == 'string') data[option]() 22170 }) 22171 } 22172 22173 $.fn.collapse.Constructor = Collapse 22174 22175 22176 // COLLAPSE NO CONFLICT 22177 // ==================== 22178 22179 $.fn.collapse.noConflict = function () { 22180 $.fn.collapse = old 22181 return this 22182 } 22183 22184 22185 // COLLAPSE DATA-API 22186 // ================= 22187 22188 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 22189 var $this = $(this), href 22190 var target = $this.attr('data-target') 22191 || e.preventDefault() 22192 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 22193 //Edited by Uncode to replace ID in panel [START] 22194 var _target = href.replace(/^#/, ""); 22195 if ( $('[data-id="' + _target + '"]').length ) { 22196 var $target = $('[data-id="' + _target + '"]') 22197 } else { 22198 var $target = $(target) 22199 } 22200 //Edited by Uncode to replace ID in panel [END] 22201 var data = $target.data('bs.collapse') 22202 var option = data ? 'toggle' : $this.data() 22203 var parent = $this.attr('data-parent') 22204 var $parent = parent && $(parent) 22205 22206 if (!data || !data.transitioning) { 22207 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 22208 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 22209 } 22210 22211 $target.collapse(option) 22212 }) 22213 22214}(jQuery); 22215 22216 22217/* ======================================================================== 22218 * Bootstrap: tab.js v3.1.1 22219 * http://getbootstrap.com/javascript/#tabs 22220 * ======================================================================== 22221 * Copyright 2011-2014 Twitter, Inc. 22222 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22223 * ======================================================================== */ 22224 22225 22226+function ($) { 22227 'use strict'; 22228 22229 // TAB CLASS DEFINITION 22230 // ==================== 22231 22232 var Tab = function (element) { 22233 this.element = $(element) 22234 } 22235 22236 Tab.prototype.show = function () { 22237 var $this = this.element 22238 var $ul = $this.closest('ul:not(.dropdown-menu)') 22239 var selector = $this.data('target') 22240 22241 if (!selector) { 22242 selector = $this.attr('href') 22243 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 22244 } 22245 22246 if ($this.parent('li').hasClass('active')) return 22247 22248 var previous = $ul.find('.active:last a')[0] 22249 var e = $.Event('show.bs.tab', { 22250 relatedTarget: previous 22251 }) 22252 22253 $this.trigger(e) 22254 22255 if (e.isDefaultPrevented()) return 22256 22257 //Edited by Uncode to replace ID in panel [START] 22258 var _target = selector.replace(/^#/, ""); 22259 if ( $('[data-id="' + _target + '"]').length ) 22260 var $target = $('[data-id="' + _target + '"]') 22261 else 22262 var $target = $(selector) 22263 //Edited by Uncode to replace ID in panel [END] 22264 22265 this.activate($this.parent('li'), $ul) 22266 this.activate($target, $target.parent(), function () { 22267 $this.trigger({ 22268 type: 'shown.bs.tab', 22269 relatedTarget: previous 22270 }) 22271 }) 22272 } 22273 22274 Tab.prototype.activate = function (element, container, callback) { 22275 var $active = container.find('> .active') 22276 var transition = callback 22277 && $.support.transition 22278 && $active.hasClass('fade') 22279 22280 function next() { 22281 $active 22282 .removeClass('active') 22283 .find('> .dropdown-menu > .active') 22284 .removeClass('active') 22285 22286 element.addClass('active') 22287 22288 if (transition) { 22289 element[0].offsetWidth // reflow for transition 22290 element.addClass('in') 22291 } else { 22292 element.removeClass('fade') 22293 } 22294 22295 if (element.parent('.dropdown-menu')) { 22296 element.closest('li.dropdown').addClass('active') 22297 } 22298 22299 callback && callback() 22300 } 22301 22302 transition ? 22303 $active 22304 .one($.support.transition.end, next) 22305 .emulateTransitionEnd(150) : 22306 next() 22307 22308 $active.removeClass('in') 22309 } 22310 22311 22312 // TAB PLUGIN DEFINITION 22313 // ===================== 22314 22315 var old = $.fn.tab 22316 22317 $.fn.tab = function ( option ) { 22318 return this.each(function () { 22319 var $this = $(this) 22320 var data = $this.data('bs.tab') 22321 22322 if (!data) $this.data('bs.tab', (data = new Tab(this))) 22323 if (typeof option == 'string') data[option]() 22324 }) 22325 } 22326 22327 $.fn.tab.Constructor = Tab 22328 22329 22330 // TAB NO CONFLICT 22331 // =============== 22332 22333 $.fn.tab.noConflict = function () { 22334 $.fn.tab = old 22335 return this 22336 } 22337 22338 22339 // TAB DATA-API 22340 // ============ 22341 22342 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 22343 e.preventDefault() 22344 $(this).tab('show') 22345 }) 22346 22347}(jQuery); 22348 22349 22350/* ======================================================================== 22351 * Bootstrap: tooltip.js v3.1.1 22352 * http://getbootstrap.com/javascript/#tooltip 22353 * Inspired by the original jQuery.tipsy by Jason Frame 22354 * ======================================================================== 22355 * Copyright 2011-2014 Twitter, Inc. 22356 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22357 * ======================================================================== */ 22358 22359 22360+function ($) { 22361 'use strict'; 22362 22363 // TOOLTIP PUBLIC CLASS DEFINITION 22364 // =============================== 22365 22366 var Tooltip = function (element, options) { 22367 this.type = 22368 this.options = 22369 this.enabled = 22370 this.timeout = 22371 this.hoverState = 22372 this.$element = null 22373 22374 this.init('tooltip', element, options) 22375 } 22376 22377 Tooltip.DEFAULTS = { 22378 animation: true, 22379 placement: 'top', 22380 selector: false, 22381 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 22382 trigger: 'hover focus', 22383 title: '', 22384 delay: 0, 22385 html: false, 22386 container: false, 22387 viewport: { 22388 selector: 'body', 22389 padding: 0 22390 } 22391 } 22392 22393 Tooltip.prototype.init = function (type, element, options) { 22394 this.enabled = true 22395 this.type = type 22396 this.$element = $(element) 22397 this.options = this.getOptions(options) 22398 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 22399 22400 var triggers = this.options.trigger.split(' ') 22401 22402 for (var i = triggers.length; i--;) { 22403 var trigger = triggers[i] 22404 22405 if (trigger == 'click') { 22406 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 22407 } else if (trigger != 'manual') { 22408 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 22409 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 22410 22411 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 22412 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 22413 } 22414 } 22415 22416 this.options.selector ? 22417 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 22418 this.fixTitle() 22419 } 22420 22421 Tooltip.prototype.getDefaults = function () { 22422 return Tooltip.DEFAULTS 22423 } 22424 22425 Tooltip.prototype.getOptions = function (options) { 22426 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 22427 22428 if (options.delay && typeof options.delay == 'number') { 22429 options.delay = { 22430 show: options.delay, 22431 hide: options.delay 22432 } 22433 } 22434 22435 return options 22436 } 22437 22438 Tooltip.prototype.getDelegateOptions = function () { 22439 var options = {} 22440 var defaults = this.getDefaults() 22441 22442 this._options && $.each(this._options, function (key, value) { 22443 if (defaults[key] != value) options[key] = value 22444 }) 22445 22446 return options 22447 } 22448 22449 Tooltip.prototype.enter = function (obj) { 22450 var self = obj instanceof this.constructor ? 22451 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22452 22453 clearTimeout(self.timeout) 22454 22455 self.hoverState = 'in' 22456 22457 if (!self.options.delay || !self.options.delay.show) return self.show() 22458 22459 self.timeout = setTimeout(function () { 22460 if (self.hoverState == 'in') self.show() 22461 }, self.options.delay.show) 22462 } 22463 22464 Tooltip.prototype.leave = function (obj) { 22465 var self = obj instanceof this.constructor ? 22466 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22467 22468 clearTimeout(self.timeout) 22469 22470 self.hoverState = 'out' 22471 22472 if (!self.options.delay || !self.options.delay.hide) return self.hide() 22473 22474 self.timeout = setTimeout(function () { 22475 if (self.hoverState == 'out') self.hide() 22476 }, self.options.delay.hide) 22477 } 22478 22479 Tooltip.prototype.show = function () { 22480 var e = $.Event('show.bs.' + this.type) 22481 22482 if (this.hasContent() && this.enabled) { 22483 this.$element.trigger(e) 22484 22485 if (e.isDefaultPrevented()) return 22486 var that = this; 22487 22488 var $tip = this.tip() 22489 22490 this.setContent() 22491 22492 if (this.options.animation) $tip.addClass('fade') 22493 22494 var placement = typeof this.options.placement == 'function' ? 22495 this.options.placement.call(this, $tip[0], this.$element[0]) : 22496 this.options.placement 22497 22498 var autoToken = /\s?auto?\s?/i 22499 var autoPlace = autoToken.test(placement) 22500 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 22501 22502 $tip 22503 .detach() 22504 .css({ top: 0, left: 0, display: 'block' }) 22505 .addClass(placement) 22506 22507 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 22508 22509 var pos = this.getPosition() 22510 var actualWidth = $tip[0].offsetWidth 22511 var actualHeight = $tip[0].offsetHeight 22512 22513 if (autoPlace) { 22514 var orgPlacement = placement 22515 var $parent = this.$element.parent() 22516 var parentDim = this.getPosition($parent) 22517 22518 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 22519 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 22520 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 22521 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 22522 placement 22523 22524 $tip 22525 .removeClass(orgPlacement) 22526 .addClass(placement) 22527 } 22528 22529 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 22530 22531 this.applyPlacement(calculatedOffset, placement) 22532 this.hoverState = null 22533 22534 var complete = function() { 22535 that.$element.trigger('shown.bs.' + that.type) 22536 } 22537 22538 $.support.transition && this.$tip.hasClass('fade') ? 22539 $tip 22540 .one($.support.transition.end, complete) 22541 .emulateTransitionEnd(150) : 22542 complete() 22543 } 22544 } 22545 22546 Tooltip.prototype.applyPlacement = function (offset, placement) { 22547 var $tip = this.tip() 22548 var width = $tip[0].offsetWidth 22549 var height = $tip[0].offsetHeight 22550 22551 // manually read margins because getBoundingClientRect includes difference 22552 var marginTop = parseInt($tip.css('margin-top'), 10) 22553 var marginLeft = parseInt($tip.css('margin-left'), 10) 22554 22555 // we must check for NaN for i
22555e 8/9 22556 if (isNaN(marginTop)) marginTop = 0 22557 if (isNaN(marginLeft)) marginLeft = 0 22558 22559 offset.top = offset.top + marginTop 22560 offset.left = offset.left + marginLeft 22561 22562 // $.fn.offset doesn't round pixel values 22563 // so we use setOffset directly with our own function B-0 22564 $.offset.setOffset($tip[0], $.extend({ 22565 using: function (props) { 22566 $tip.css({ 22567 top: Math.round(props.top), 22568 left: Math.round(props.left) 22569 }) 22570 } 22571 }, offset), 0) 22572 22573 $tip.addClass('in') 22574 22575 // check to see if placing tip in new offset caused the tip to resize itself 22576 var actualWidth = $tip[0].offsetWidth 22577 var actualHeight = $tip[0].offsetHeight 22578 22579 if (placement == 'top' && actualHeight != height) { 22580 offset.top = offset.top + height - actualHeight 22581 } 22582 22583 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 22584 22585 if (delta.left) offset.left += delta.left 22586 else offset.top += delta.top 22587 22588 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 22589 var arrowPosition = delta.left ? 'left' : 'top' 22590 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 22591 22592 $tip.offset(offset) 22593 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 22594 } 22595 22596 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 22597 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 22598 } 22599 22600 Tooltip.prototype.setContent = function () { 22601 var $tip = this.tip() 22602 var title = this.getTitle() 22603 22604 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 22605 $tip.removeClass('fade in top bottom left right') 22606 } 22607 22608 Tooltip.prototype.hide = function () { 22609 var that = this 22610 var $tip = this.tip() 22611 var e = $.Event('hide.bs.' + this.type) 22612 22613 function complete() { 22614 if (that.hoverState != 'in') $tip.detach() 22615 that.$element.trigger('hidden.bs.' + that.type) 22616 } 22617 22618 this.$element.trigger(e) 22619 22620 if (e.isDefaultPrevented()) return 22621 22622 $tip.removeClass('in') 22623 22624 $.support.transition && this.$tip.hasClass('fade') ? 22625 $tip 22626 .one($.support.transition.end, complete) 22627 .emulateTransitionEnd(150) : 22628 complete() 22629 22630 this.hoverState = null 22631 22632 return this 22633 } 22634 22635 Tooltip.prototype.fixTitle = function () { 22636 var $e = this.$element 22637 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 22638 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 22639 } 22640 } 22641 22642 Tooltip.prototype.hasContent = function () { 22643 return this.getTitle() 22644 } 22645 22646 Tooltip.prototype.getPosition = function ($element) { 22647 $element = $element || this.$element 22648 var el = $element[0] 22649 var isBody = el.tagName == 'BODY' 22650 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 22651 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 22652 width: isBody ? $(window).width() : $element.outerWidth(), 22653 height: isBody ? $(window).height() : $element.outerHeight() 22654 }, isBody ? {top: 0, left: 0} : $element.offset()) 22655 } 22656 22657 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 22658 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22659 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22660 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 22661 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 22662 22663 } 22664 22665 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 22666 var delta = { top: 0, left: 0 } 22667 if (!this.$viewport) return delta 22668 22669 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 22670 var viewportDimensions = this.getPosition(this.$viewport) 22671 22672 if (/right|left/.test(placement)) { 22673 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 22674 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 22675 if (topEdgeOffset < viewportDimensions.top) { // top overflow 22676 delta.top = viewportDimensions.top - topEdgeOffset 22677 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 22678 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
22678EdgeOffset 22679 } 22680 } else { 22681 var leftEdgeOffset = pos.left - viewportPadding 22682 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 22683 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 22684 delta.left = viewportDimensions.left - leftEdgeOffset 22685 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 22686 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 22687 } 22688 } 22689 22690 return delta 22691 } 22692 22693 Tooltip.prototype.getTitle = function () { 22694 var title 22695 var $e = this.$element 22696 var o = this.options 22697 22698 title = $e.attr('data-original-title') 22699 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 22700 22701 return title 22702 } 22703 22704 Tooltip.prototype.tip = function () { 22705 return this.$tip = this.$tip || $(this.options.template) 22706 } 22707 22708 Tooltip.prototype.arrow = function () { 22709 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 22710 } 22711 22712 Tooltip.prototype.validate = function () { 22713 if (!this.$element[0].parentNode) { 22714 this.hide() 22715 this.$element = null 22716 this.options = null 22717 } 22718 } 22719 22720 Tooltip.prototype.enable = function () { 22721 this.enabled = true 22722 } 22723 22724 Tooltip.prototype.disable = function () { 22725 this.enabled = false 22726 } 22727 22728 Tooltip.prototype.toggleEnabled = function () { 22729 this.enabled = !this.enabled 22730 } 22731 22732 Tooltip.prototype.toggle = function (e) { 22733 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 22734 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 22735 } 22736 22737 Tooltip.prototype.destroy = function () { 22738 clearTimeout(this.timeout) 22739 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 22740 } 22741 22742 22743 // TOOLTIP PLUGIN DEFINITION 22744 // ========================= 22745 22746 var old = $.fn.tooltip 22747 22748 $.fn.tooltip = function (option) { 22749 return this.each(function () { 22750 var $this = $(this) 22751 var data = $this.data('bs.tooltip') 22752 var options = typeof option == 'object' && option 22753 22754 if (!data && option == 'destroy') return 22755 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 22756 if (typeof option == 'string') data[option]() 22757 }) 22758 } 22759 22760 $.fn.tooltip.Constructor = Tooltip 22761 22762 22763 // TOOLTIP NO CONFLICT 22764 // =================== 22765 22766 $.fn.tooltip.noConflict = function () { 22767 $.fn.tooltip = old 22768 return this 22769 } 22770 22771}(jQuery); 22772 22773 22774/* ======================================================================== 22775 * Bootstrap: transition.js v3.1.1 22776 * http://getbootstrap.com/javascript/#transitions 22777 * ======================================================================== 22778 * Copyright 2011-2014 Twitter, Inc. 22779 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22780 * ======================================================================== */ 22781 22782 22783+function ($) { 22784 'use strict'; 22785 22786 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 22787 // ============================================================ 22788 22789 function transitionEnd() { 22790 var el = document.createElement('bootstrap') 22791 22792 var transEndEventNames = { 22793 WebkitTransition : 'webkitTransitionEnd', 22794 MozTransition : 'transitionend', 22795 OTransition : 'oTransitionEnd otransitionend', 22796 transition : 'transitionend' 22797 } 22798 22799 for (var name in transEndEventNames) { 22800 if (el.style[name] !== undefined) { 22801 return { end: transEndEventNames[name] } 22802 } 22803 } 22804 22805 return false // explicit for ie8 ( ._.) 22806 } 22807 22808 // http://blog.alexmaccaw.com/css-transitions 22809 $.fn.emulateTransitionEnd = function (duration) { 22810 var called = false, $el = this 22811 $(this).one($.support.transition.end, function () { called = true }) 22812 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 22813 setTimeout(callback, duration) 22814 return this 22815 } 22816 22817 $(function () { 22818 $.support.transition = transitionEnd() 22819 }) 22820 22821}(jQuery); 22822 22823
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.