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 }, init: function() { 43 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 44 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 45 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 46 } 47 }, 48 bindResize: function(eventName, resizeFunction) { 49 var timeoutId; 50 $(window).unbind(eventName).bind(eventName, function() { 51 if( timeoutId ) { 52 clearTimeout( timeoutId ); 53 } 54 timeoutId = setTimeout( resizeFunction, 300 ); 55 }); 56 }, 57 getStyleId: function(id) 58 { 59 return BigText.STYLE_ID + '-' + id; 60 }, 61 generateStyleTag: function(id, css) 62 { 63 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 64 }, 65 clearCss: function(id) 66 { 67 var styleId = BigText.getStyleId(id); 68 $('#' + styleId).remove(); 69 }, 70 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 71 { 72 var css = []; 73 74 BigText.clearCss(id); 75 76 for(var j=0, k=linesFontSizes.length; j<k; j++) { 77 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 78 (minFontSizes[j] ? ' white-space: normal;' : '') + 79 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 80 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 81 '}'); 82 } 83 84 return BigText.generateStyleTag(BigText.getStyleId(id), css); 85 }, 86 jQueryMethod: function(options) 87 { 88 BigText.init(); 89 90 options = $.extend({ 91 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 92 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 93 childSelector: '', 94 resize: true 95 }, options || {}); 96 97 this.each(function() 98 { 99 var $t = $(this).addClass('bigtext'), 100 maxWidth = $t.width(), 101 id = $t.attr('id'), 102 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 103 104 if(!id) { 105 id = 'bigtext-id' + (counter++); 106 $t.attr('id', id); 107 } 108 109 if(options.resize) { 110 BigText.bindResize('resize.bigtext-event-' + id, function() 111 { 112 // TODO only call this if the width has changed. 113 BigText.jQueryMethod.call($('#' + id), options); 114 }); 115 } 116 117 BigText.clearCss(id); 118 119 $children.addClass(function(lineNumber, className) 120 { 121 // remove existing line classes. 122 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 123 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 124 }); 125 126 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 127 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 128 }); 129 130 return this.trigger('bigtext:complete'); 131 } 132 }; 133 134 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 135 { 136 var width; 137 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 138 $line.css(property, size + units); 139 140 width = $line.width(); 141 142 if(width >= maxWidth) { 143 144 $line.css(property, ''); 145 146 if(width === maxWidth) { 147 return { 148 match: 'exact', 149 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 150 }; 151 } 152 153 // Since this is an estimate, we calculate how far over the width we went with the new value. 154 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 155 // Otherwise, we revert to the underestimate. 156 var under = maxWidth - previousWidth, 157 over = width - maxWidth; 158 159 return { 160 match: 'estimate', 161 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 162 }; 163 } 164 165 return width; 166 } 167 168 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 169 { 170 var $c = $t.clone(true) 171 .addClass('bigtext-cloned') 172 .css({ 173 fontFamily: $t.css('font-family'), 174 textTransform: $t.css('text-transform'), 175 wordSpacing: $t.css('word-spacing'), 176 letterSpacing: $t.css('letter-spacing'), 177 position: 'absolute', 178 left: BigText.DEBUG_MODE ? 0 : -9999, 179 top: BigText.DEBUG_MODE ? 0 : -9999
180 }) 181 .appendTo(document.body); 182 183 // font-size isn't the only thing we can modify, we can also mess with: 184 // word-spacing and letter-spacing. WebKit does not respect subpixel 185 // letter-spacing, word-spacing, or font-size. 186 // TODO try -webkit-transform: scale() as a workaround. 187 var fontSizes = [], 188 wordSpacings = [], 189 minFontSizes = [], 190 ratios = []; 191 192 $children.css('float', 'left').each(function() { 193 var $line = $(this), 194 // TODO replace 8, 4 with a proportional size to the calculated font-size. 195 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 196 lineMax, 197 newFontSize; 198 199 if($line.hasClass(BigText.EXEMPT_CLASS)) { 200 fontSizes.push(null); 201 ratios.push(null); 202 minFontSizes.push(false); 203 return; 204 } 205 206 // TODO we can cache this ratio? 207 var autoGuessSubtraction = 32, // font size in px 208 currentFontSize = parseFloat($line.css('font-size')), 209 ratio = ( $line.width() / currentFontSize ).toFixed(6); 210 211 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 212 213 outer: for(var m=0, n=intervals.length; m<n; m++) { 214 inner: for(var j=1, k=10; j<=k; j++) { 215 if(newFontSize + j*intervals[m] > maxFontSize) { 216 newFontSize = maxFontSize; 217 break outer; 218 } 219 220 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 221 if(typeof lineMax !== 'number') { 222 newFontSize = lineMax.size; 223 224 if(lineMax.match === 'exact') { 225 break outer; 226 } 227 break inner; 228 } 229 } 230 } 231 232 ratios.push(maxWidth / newFontSize); 233 234 if(newFontSize > maxFontSize) { 235 fontSizes.push(maxFontSize); 236 minFontSizes.push(false); 237 } else if(!!minFontSize && newFontSize < minFontSize) { 238 fontSizes.push(minFontSize); 239 minFontSizes.push(true); 240 } else { 241 fontSizes.push(newFontSize); 242 minFontSizes.push(false); 243 } 244 }).each(function(lineNumber) { 245 var $line = $(this), 246 wordSpacing = 0, 247 interval = 1, 248 maxWordSpacing; 249 250 if($line.hasClass(BigText.EXEMPT_CLASS)) { 251 wordSpacings.push(null); 252 return; 253 } 254 255 // must re-use font-size, even though it was removed above. 256 $line.css('font-size', fontSizes[lineNumber] + 'px'); 257 258 for(var m=1, n=3; m<n; m+=interval) { 259 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 260 if(typeof maxWordSpacing !== 'number') { 261 wordSpacing = maxWordSpacing.size; 262 break; 263 } 264 } 265 266 $line.css('font-size', ''); 267 wordSpacings.push(wordSpacing); 268 }).removeAttr('style'); 269 270 if( !BigText.DEBUG_MODE ) { 271 $c.remove(); 272 } else { 273 $c.css({ 274 'background-color': 'rgba(255,255,255,.4)' 275 }); 276 } 277 278 return { 279 fontSizes: fontSizes, 280 wordSpacings: wordSpacings, 281 ratios: ratios, 282 minFontSizes: minFontSizes 283 }; 284 } 285 286 $.fn.bigtext = BigText.jQueryMethod; 287 window.BigText = BigText; 288 289})(this, jQuery); 290 291/*! 292 * Isotope PACKAGED v2.2.2 293 * 294 * Licensed GPLv3 for open source use 295 * or Isotope Commercial License for commercial use 296 * 297 * http://isotope.metafizzy.co 298 * Copyright 2015 Metafizzy 299 */ 300 301/** 302 * Bridget makes jQuery widgets 303 * v1.1.0 304 * MIT license 305 */ 306 307( function( window ) { 308 309 310 311// -------------------------- utils -------------------------- // 312 313var slice = Array.prototype.slice; 314 315function noop() {} 316 317// -------------------------- definition -------------------------- // 318 319function defineBridget( $ ) { 320 321// bail if no jQuery 322if ( !$ ) { 323 return; 324} 325 326// -------------------------- addOptionMethod -------------------------- // 327 328/** 329 * adds option method -> $().plugin('option', {...}) 330 * @param {Function} PluginClass - constructor class 331 */ 332function addOptionMethod( PluginClass ) { 333 // don't overwrite original option method 334 if ( PluginClass.prototype.option ) { 335 return; 336 } 337 338 // option setter 339 PluginClass.prototype.option = function( opts ) { 340 // bail out if not an object 341 if ( !$.isPlainObject( opts ) ){ 342 return; 343 } 344 this.options = $.extend( true, this.options, opts ); 345 }; 346} 347 348// -------------------------- plugin bridge -------------------------- // 349 350// helper function for logging errors 351// $.error breaks jQuery chaining 352var logError = typeof console === 'undefined' ? noop : 353 function( message ) { 354 console.error( message ); 355 }; 356 357/** 358 * jQuery plugin bridge, access methods like $elem.plugin('method') 359 * @param {String} namespace - plugin name 360 * @param {Function} PluginClass - constructor class 361 */ 362function bridge( namespace, PluginClass ) { 363 // add to jQuery fn namespace 364 $.fn[ namespace ] = function( options ) { 365 if ( typeof options === 'string' ) { 366 // call plugin method when first argument is a string 367 // get arguments for method 368 var args = slice.call( arguments, 1 ); 369 370 for ( var i=0, len = this.length; i < len; i++ ) { 371 var elem = this[i]; 372 var instance = $.data( elem, namespace ); 373 if ( !instance ) { 374 logError( "cannot call methods on " + namespace + " prior to initialization; " + 375 "attempted to call '" + options + "'" ); 376 continue; 377 } 378 if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { 379 logError( "no such method '" + options + "' for " + namespace + " instance" ); 380 continue; 381 } 382 383 // trigger method with arguments 384 var returnValue = instance[ options ].apply( instance, args ); 385 386 // break look and return first value if provided 387 if ( returnValue !== undefined ) { 388 return returnValue; 389 } 390 } 391 // return this if no return value 392 return this; 393 } else { 394 return this.each( function() { 395 var instance = $.data( this, namespace ); 396 if ( instance ) { 397 // apply options & init 398 instance.option( options ); 399 instance._init(); 400 } else { 401 // initialize new instance 402 instance = new PluginClass( this, options ); 403 $.data( this, namespace, instance ); 404 } 405 }); 406 } 407 }; 408 409} 410 411// -------------------------- bridget -------------------------- // 412 413/** 414 * converts a Prototypical class into a proper jQuery plugin 415 * the class must have a ._init method 416 * @param {String} namespace - plugin name, used in $().pluginName 417 * @param {Function} PluginClass - constructor class 418 */ 419$.bridget = function( namespace, PluginClass ) { 420 addOptionMethod( PluginClass ); 421 bridge( namespace, PluginClass ); 422}; 423 424return $.bridget; 425 426} 427 428// transport 429if ( typeof define === 'function' && define.amd ) { 430 // AMD 431 define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget ); 432} else if ( typeof exports === 'object' ) { 433 defineBridget( require('jquery') ); 434} else { 435 // get jquery from browser global 436 defineBridget( window.jQuery ); 437} 438 439})( window ); 440 441/*! 442 * eventie v1.0.6 443 * event binding helper 444 * eventie.bind( elem, 'click', myFn ) 445 * eventie.unbind( elem, 'click', myFn ) 446 * MIT license 447 */ 448 449/*jshint browser: true, undef: true, unused: true */ 450/*global define: false, module: false */ 451 452( function( window ) { 453 454 455 456var docElem = document.documentElement; 457 458var bind = function() {}; 459 460function getIEEvent( obj ) { 461 var event = window.event; 462 // add event.target 463 event.target = event.target || event.srcElement || obj; 464 return event; 465} 466 467if ( docElem.addEventListener ) { 468 bind = function( obj, type, fn ) { 469 obj.addEventListener( type, fn, false ); 470 }; 471} else if ( docElem.attachEvent ) { 472 bind = function( obj, type, fn ) { 473 obj[ type + fn ] = fn.handleEvent ? 474 function() { 475 var event = getIEEvent( obj ); 476 fn.handleEvent.call( fn, event ); 477 } : 478 function() { 479 var event = getIEEvent( obj ); 480 fn.call( obj, event ); 481 }; 482 obj.attachEvent( "on" + type, obj[ type + fn ] ); 483 }; 484} 485 486var unbind = function() {}; 487 488if ( docElem.removeEventListener ) { 489 unbind = function( obj, type, fn ) { 490 obj.removeEventListener( type, fn, false ); 491 }; 492} else if ( docElem.detachEvent ) { 493 unbind = function( obj, type, fn ) { 494 obj.detachEvent( "on" + type, obj[ type + fn ] ); 495 try { 496 delete obj[ type + fn ]; 497 } catch ( err ) { 498 // can't delete window object properties 499 obj[ type + fn ] = undefined; 500 } 501 }; 502} 503 504var eventie = { 505 bind: bind, 506 unbind: unbind 507}; 508 509// ----- module definition ----- // 510 511if ( typeof define === 'function' && define.amd ) { 512 // AMD 513 define( 'eventie/eventie',eventie ); 514} else if ( typeof exports === 'object' ) { 515 // CommonJS 516 module.exports = eventie; 517} else { 518 // browser global 519 window.eventie = eventie; 520} 521 522})( window ); 523 524/*! 525 * EventEmitter v4.2.11 - git.io/ee 526 * Unlicense - http://unlicense.org/ 527 * Oliver Caldwell - http://oli.me.uk/ 528 * @preserve 529 */ 530 531;(function () { 532 'use strict'; 533 534 /** 535 * Class for managing events. 536 * Can be extended to provide event functionality in other classes. 537 * 538 * @class EventEmitter Manages event registering and emitting. 539 */ 540 function EventEmitter() {} 541 542 // Shortcuts to improve speed and size 543 var proto = EventEmitter.prototype; 544 var exports = this; 545 var originalGlobalValue = exports.EventEmitter; 546 547 /** 548 * Finds the index of the listener for the event in its storage array. 549 * 550 * @param {Function[]} listeners Array of listeners to search through. 551 * @param {Function} listener Method to look for. 552 * @return {Number} Index of the specified listener, -1 if not found 553 * @api private 554 */ 555 function indexOfListener(listeners, listener) { 556 var i = listeners.length; 557 while (i--) { 558 if (listeners[i].listener === listener) { 559 return i; 560 } 561 } 562 563 return -1; 564 } 565 566 /** 567 * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 567-1025
567writing of target method. 568 * 569 * @param {String} name The name of the target method. 570 * @return {Function} The aliased method 571 * @api private 572 */ 573 function alias(name) { 574 return function aliasClosure() { 575 return this[name].apply(this, arguments); 576 }; 577 } 578 579 /** 580 * Returns the listener array for the specified event. 581 * Will initialise the event object and listener arrays if required. 582 * 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. 583 * Each property in the object response is an array of listener functions. 584 * 585 * @param {String|RegExp} evt Name of the event to return the listeners from. 586 * @return {Function[]|Object} All listener functions for the event. 587 */ 588 proto.getListeners = function getListeners(evt) { 589 var events = this._getEvents(); 590 var response; 591 var key; 592 593 // Return a concatenated array of all matching events if 594 // the selector is a regular expression. 595 if (evt instanceof RegExp) { 596 response = {}; 597 for (key in events) { 598 if (events.hasOwnProperty(key) && evt.test(key)) { 599 response[key] = events[key]; 600 } 601 } 602 } 603 else { 604 response = events[evt] || (events[evt] = []); 605 } 606 607 return response; 608 }; 609 610 /** 611 * Takes a list of listener objects and flattens it into a list of listener functions. 612 * 613 * @param {Object[]} listeners Raw listener objects. 614 * @return {Function[]} Just the listener functions. 615 */ 616 proto.flattenListeners = function flattenListeners(listeners) { 617 var flatListeners = []; 618 var i; 619 620 for (i = 0; i < listeners.length; i += 1) { 621 flatListeners.push(listeners[i].listener); 622 } 623 624 return flatListeners; 625 }; 626 627 /** 628 * 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. 629 * 630 * @param {String|RegExp} evt Name of the event to return the listeners from. 631 * @return {Object} All listener functions for an event in an object. 632 */ 633 proto.getListenersAsObject = function getListenersAsObject(evt) { 634 var listeners = this.getListeners(evt); 635 var response; 636 637 if (listeners instanceof Array) { 638 response = {}; 639 response[evt] = listeners; 640 } 641 642 return response || listeners; 643 }; 644 645 /** 646 * Adds a listener function to the specified event. 647 * The listener will not be added if it is a duplicate. 648 * If the listener returns true then it will be removed after it is called. 649 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 650 * 651 * @param {String|RegExp} evt Name of the event to attach the listener to. 652 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 653 * @return {Object} Current instance of EventEmitter for chaining. 654 */ 655 proto.addListener = function addListener(evt, listener) { 656 var listeners = this.getListenersAsObject(evt); 657 var listenerIsWrapped = typeof listener === 'object'; 658 var key; 659 660 for (key in listeners) { 661 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 662 listeners[key].push(listenerIsWrapped ? listener : { 663 listener: listener, 664 once: false 665 }); 666 } 667 } 668 669 return this; 670 }; 671 672 /** 673 * Alias of addListener 674 */ 675 proto.on = alias('addListener'); 676 677 /** 678 * Semi-alias of addListener. It will add a listener that will be 679 * automatically removed after its first execution. 680 * 681 * @param {String|RegExp} evt Name of the event to attach the listener to. 682 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 683 * @return {Object} Current instance of EventEmitter for chaining. 684 */ 685 proto.addOnceListener = function addOnceListener(evt, listener) { 686 return this.addListener(evt, { 687 listener: listener, 688 once: true 689 }); 690 }; 691 692 /** 693 * Alias of addOnceListener. 694 */ 695 proto.once = alias('addOnceListener'); 696 697 /** 698 * 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. 699 * You need to tell it what event names should be matched by a regex. 700 * 701 * @param {String} evt Name of the event to create. 702 * @return {Object} Current instance of EventEmitter for chaining. 703 */ 704 proto.defineEvent = function defineEvent(evt) { 705 this.getListeners(evt); 706 return this; 707 }; 708 709 /** 710 * Uses defineEvent to define multiple events. 711 * 712 * @param {String[]} evts An array of event names to define. 713 * @return {Object} Current instance of EventEmitter for chaining. 714 */ 715 proto.defineEvents = function defineEvents(evts) { 716 for (var i = 0; i < evts.length; i += 1) { 717 this.defineEvent(evts[i]); 718 } 719 return this; 720 }; 721 722 /** 723 * Removes a listener function from the specified event. 724 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 725 * 726 * @param {String|RegExp} evt Name of the event to remove the listener from. 727 * @param {Function} listener Method to remove from the event. 728 * @return {Object} Current instance of EventEmitter for chaining. 729 */ 730 proto.removeListener = function removeListener(evt, listener) { 731 var listeners = this.getListenersAsObject(evt); 732 var index; 733 var key; 734 735 for (key in listeners) { 736 if (listeners.hasOwnProperty(key)) { 737 index = indexOfListener(listeners[key], listener); 738 739 if (index !== -1) { 740 listeners[key].splice(index, 1); 741 } 742 } 743 } 744 745 return this; 746 }; 747 748 /** 749 * Alias of removeListener 750 */ 751 proto.off = alias('removeListener'); 752 753 /** 754 * Adds listeners in bulk using the manipulateListeners method. 755 * 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. 756 * You can also pass it a regular expression to add the array of listeners to all events that match it. 757 * Yeah, this function does quite a bit. That's probably a bad thing. 758 * 759 * @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. 760 * @param {Function[]} [listeners] An optional array of listener functions to add. 761 * @return {Object} Current instance of EventEmitter for chaining. 762 */ 763 proto.addListeners = function addListeners(evt, listeners) { 764 // Pass through to manipulateListeners 765 return this.manipulateListeners(false, evt, listeners); 766 }; 767 768 /** 769 * Removes listeners in bulk using the manipulateListeners method. 770 * 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. 771 * You can also pass it an event name and an array of listeners to be removed. 772 * You can also pass it a regular expression to remove the listeners from all events that match it. 773 * 774 * @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. 775 * @param {Function[]} [listeners] An optional array of listener functions to remove. 776 * @return {Object} Current instance of EventEmitter for chaining. 777 */ 778 proto.removeListeners = function removeListeners(evt, listeners) { 779 // Pass through to manipulateListeners 780 return this.manipulateListeners(true, evt, listeners); 781 }; 782 783 /** 784 * 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. 785 * The first argument will determine if the listeners are removed (true) or added (false). 786 * 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. 787 * You can also pass it an event name and an array of listeners to be added/removed. 788 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 789 * 790 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 791 * @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. 792 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 793 * @return {Object} Current instance of EventEmitter for chaining. 794 */ 795 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 796 var i; 797 var value; 798 var single = remove ? this.removeListener : this.addListener; 799 var multiple = remove ? this.removeListeners : this.addListeners; 800 801 // If evt is an object then pass each of its properties to this method 802 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 803 for (i in evt) { 804 if (evt.hasOwnProperty(i) && (value = evt[i])) { 805 // Pass the single listener straight through to the singular method 806 if (typeof value === 'function') { 807 single.call(this, i, value); 808 } 809 else { 810 // Otherwise pass back to the multiple function 811 multiple.call(this, i, value); 812 } 813 } 814 } 815 } 816 else { 817 // So evt must be a string 818 // And listeners must be an array of listeners 819 // Loop over it and pass each one to the multiple method 820 i = listeners.length; 821 while (i--) { 822 single.call(this, evt, listeners[i]); 823 } 824 } 825 826 return this; 827 }; 828 829 /** 830 * Removes all listeners from a specified event. 831 * If you do not specify an event then all listeners will be removed. 832 * That means every event will be emptied. 833 * You can also pass a regex to remove all events that match it. 834 * 835 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 836 * @return {Object} Current instance of EventEmitter for chaining. 837 */ 838 proto.removeEvent = function removeEvent(evt) { 839 var type = typeof evt; 840 var events = this._getEvents(); 841 var key; 842 843 // Remove different things depending on the state of evt 844 if (type === 'string') { 845 // Remove all listeners for the specified event 846 delete events[evt]; 847 } 848 else if (evt instanceof RegExp) { 849 // Remove all events matching the regex. 850 for (key in events) { 851 if (events.hasOwnProperty(key) && evt.test(key)) { 852 delete events[key]; 853 } 854 } 855 } 856 else { 857 // Remove all listeners in all events 858 delete this._events; 859 } 860 861 return this; 862 }; 863 864 /** 865 * Alias of removeEvent. 866 * 867 * Added to mirror the node API. 868 */ 869 proto.removeAllListeners = alias('removeEvent'); 870 871 /** 872 * Emits an event of your choice. 873 * When emitted, every listener attached to that event will be executed. 874 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 875 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. 876 * So they will not arrive within the array on the other side, they will be separate. 877 * You can also pass a regular expression to emit to all events that match it. 878 * 879 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 880 * @param {Array} [args] Optional array of arguments to be passed to each listener. 881 * @return {Object} Current instance of EventEmitter for chaining. 882 */ 883 proto.emitEvent = function emitEvent(evt, args) { 884 var listeners = this.getListenersAsObject(evt); 885 var listener; 886 var i; 887 var key; 888 var response; 889 890 for (key in listeners) { 891 if (listeners.hasOwnProperty(key)) { 892 i = listeners[key].length; 893 894 while (i--) { 895 // If the listener returns true then it shall be removed from the event 896 // The function is executed either with a basic call or an apply if there is an args array 897 listener = listeners[key][i]; 898 899 if (listener.once === true) { 900 this.removeListener(evt, listener.listener); 901 } 902 903 response = listener.listener.apply(this, args || []); 904 905 if (response === this._getOnceReturnValue()) { 906 this.removeListener(evt, listener.listener); 907 } 908 } 909 } 910 } 911 912 return this; 913 }; 914 915 /** 916 * Alias of emitEvent 917 */ 918 proto.trigger = alias('emitEvent'); 919 920 /** 921 * 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. 922 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 923 * 924 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 925 * @param {...*} Optional additional arguments to be passed to each listener. 926 * @return {Object} Current instance of EventEmitter for chaining. 927 */ 928 proto.emit = function emit(evt) { 929 var args = Array.prototype.slice.call(arguments, 1); 930 return this.emitEvent(evt, args); 931 }; 932 933 /** 934 * Sets the current value to check against when executing listeners. If a 935 * listeners return value matches the one set here then it will be removed 936 * after execution. This value defaults to true. 937 * 938 * @param {*} value The new value to check for when executing listeners. 939 * @return {Object} Current instance of EventEmitter for chaining. 940 */ 941 proto.setOnceReturnValue = function setOnceReturnValue(value) { 942 this._onceReturnValue = value; 943 return this; 944 }; 945 946 /** 947 * Fetches the current value to check against when executing listeners. If 948 * the listeners return value matches this one then it should be removed 949 * automatically. It will return true by default. 950 * 951 * @return {*|Boolean} The current value to check for or the default, true. 952 * @api private 953 */ 954 proto._getOnceReturnValue = function _getOnceReturnValue() { 955 if (this.hasOwnProperty('_onceReturnValue')) { 956 return this._onceReturnValue; 957 } 958 else { 959 return true; 960 } 961 }; 962 963 /** 964 * Fetches the events object and creates one if required. 965 * 966 * @return {Object} The events storage object. 967 * @api private 968 */ 969 proto._getEvents = function _getEvents() { 970 return this._events || (this._events = {}); 971 }; 972 973 /** 974 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. 975 * 976 * @return {Function} Non conflicting EventEmitter class. 977 */ 978 EventEmitter.noConflict = function noConflict() { 979 exports.EventEmitter = originalGlobalValue; 980 return EventEmitter; 981 }; 982 983 // Expose the class either via AMD, CommonJS or the global object 984 if (typeof define === 'function' && define.amd) { 985 define('eventEmitter/EventEmitter',[],function () { 986 return EventEmitter; 987 }); 988 } 989 else if (typeof module === 'object' && module.exports){ 990 module.exports = EventEmitter; 991 } 992 else { 993 exports.EventEmitter = EventEmitter; 994 } 995}.call(this)); 996 997/*! 998 * getStyleProperty v1.0.4 999 * original by kangax 1000 * http://perfectionkills.com/feature-testing-css-properties/ 1001 * MIT license 1002 */ 1003 1004/*jshint browser: true, strict: true, undef: true */ 1005/*global define: false, exports: false, module: false */ 1006 1007( function( window ) { 1008 1009 1010 1011var prefixes = 'Webkit Moz ms Ms O'.split(' '); 1012var docElemStyle = document.documentElement.style; 1013 1014function getStyleProperty( propName ) { 1015 if ( !propName ) { 1016 return; 1017 } 1018 1019 // test standard property first 1020 if ( typeof docElemStyle[ propName ] === 'string' ) { 1021 return propName; 1022 } 1023 1024 // capitalize 1025 propName = pr
1025opName.charAt(0).toUpperCase() + propName.slice(1); 1026 1027 // test vendor specific properties 1028 var prefixed; 1029 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1030 prefixed = prefixes[i] + propName; 1031 if ( typeof docElemStyle[ prefixed ] === 'string' ) { 1032 return prefixed; 1033 } 1034 } 1035} 1036 1037// transport 1038if ( typeof define === 'function' && define.amd ) { 1039 // AMD 1040 define( 'get-style-property/get-style-property',[],function() { 1041 return getStyleProperty; 1042 }); 1043} else if ( typeof exports === 'object' ) { 1044 // CommonJS for Component 1045 module.exports = getStyleProperty; 1046} else { 1047 // browser global 1048 window.getStyleProperty = getStyleProperty; 1049} 1050 1051})( window ); 1052 1053/*! 1054 * getSize v1.2.2 1055 * measure size of elements 1056 * MIT license 1057 */ 1058 1059/*jshint browser: true, strict: true, undef: true, unused: true */ 1060/*global define: false, exports: false, require: false, module: false, console: false */ 1061 1062( function( window, undefined ) { 1063 1064 1065 1066// -------------------------- helpers -------------------------- // 1067 1068// get a number from a string, not a percentage 1069function getStyleSize( value ) { 1070 var num = parseFloat( value ); 1071 // not a percent like '100%', and a number 1072 var isValid = value.indexOf('%') === -1 && !isNaN( num ); 1073 return isValid && num; 1074} 1075 1076function noop() {} 1077 1078var logError = typeof console === 'undefined' ? noop : 1079 function( message ) { 1080 console.error( message ); 1081 }; 1082 1083// -------------------------- measurements -------------------------- // 1084 1085var measurements = [ 1086 'paddingLeft', 1087 'paddingRight', 1088 'paddingTop', 1089 'paddingBottom', 1090 'marginLeft', 1091 'marginRight', 1092 'marginTop', 1093 'marginBottom', 1094 'borderLeftWidth', 1095 'borderRightWidth', 1096 'borderTopWidth', 1097 'borderBottomWidth' 1098]; 1099 1100function getZeroSize() { 1101 var size = { 1102 width: 0, 1103 height: 0, 1104 innerWidth: 0, 1105 innerHeight: 0, 1106 outerWidth: 0, 1107 outerHeight: 0 1108 }; 1109 for ( var i=0, len = measurements.length; i < len; i++ ) { 1110 var measurement = measurements[i]; 1111 size[ measurement ] = 0; 1112 } 1113 return size; 1114} 1115 1116 1117 1118function defineGetSize( getStyleProperty ) { 1119 1120// -------------------------- setup -------------------------- // 1121 1122var isSetup = false; 1123 1124var getStyle, boxSizingProp, isBoxSizeOuter; 1125 1126/** 1127 * setup vars and functions 1128 * do it on initial getSize(), rather than on script load 1129 * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397 1130 */ 1131function setup() { 1132 // setup once 1133 if ( isSetup ) { 1134 return; 1135 } 1136 isSetup = true; 1137 1138 var getComputedStyle = window.getComputedStyle; 1139 getStyle = ( function() { 1140 var getStyleFn = getComputedStyle ? 1141 function( elem ) { 1142 return getComputedStyle( elem, null ); 1143 } : 1144 function( elem ) { 1145 return elem.currentStyle; 1146 }; 1147 1148 return function getStyle( elem ) { 1149 var style = getStyleFn( elem ); 1150 if ( !style ) { 1151 logError( 'Style returned ' + style + 1152 '. Are you running this code in a hidden iframe on Firefox? ' + 1153 'See http://bit.ly/getsizebug1' ); 1154 } 1155 return style; 1156 }; 1157 })(); 1158 1159 // -------------------------- box sizing -------------------------- // 1160 1161 boxSizingProp = getStyleProperty('boxSizing'); 1162 1163 /** 1164 * WebKit measures the outer-width on style.width on border-box elems 1165 * IE & Firefox measures the inner-width 1166 */ 1167 if ( boxSizingProp ) { 1168 var div = document.createElement('div'); 1169 div.style.width = '200px'; 1170 div.style.padding = '1px 2px 3px 4px'; 1171 div.style.borderStyle = 'solid'; 1172 div.style.borderWidth = '1px 2px 3px 4px'; 1173 div.style[ boxSizingProp ] = 'border-box'; 1174 1175 var body = document.body || document.documentElement; 1176 body.appendChild( div ); 1177 var style = getStyle( div ); 1178 1179 isBoxSizeOuter = getStyleSize( style.width ) === 200; 1180 body.removeChild( div ); 1181 } 1182 1183} 1184 1185// -------------------------- getSize -------------------------- // 1186 1187function getSize( elem ) { 1188 setup(); 1189 1190 // use querySeletor if elem is string 1191 if ( typeof elem === 'string' ) { 1192 elem = document.querySelector( elem ); 1193 } 1194 1195 // do not proceed on non-objects 1196 if ( !elem || typeof elem !== 'object' || !elem.nodeType ) { 1197 return; 1198 } 1199 1200 var style = getStyle( elem ); 1201 1202 // if hidden, everything is 0 1203 if ( style.display === 'none' ) { 1204 return getZeroSize(); 1205 } 1206 1207 var size = {}; 1208 size.width = elem.offsetWidth; 1209 size.height = elem.offsetHeight; 1210 1211 var isBorderBox = size.isBorderBox = !!( boxSizingProp && 1212 style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' ); 1213 1214 // get all measurements 1215 for ( var i=0, len = measurements.length; i < len; i++ ) { 1216 var measurement = measurements[i]; 1217 var value = style[ measurement ]; 1218 value = mungeNonPixel( elem, value ); 1219 var num = parseFloat( value ); 1220 // any 'auto', 'medium' value will be 0 1221 size[ measurement ] = !isNaN( num ) ? num : 0; 1222 } 1223 1224 var paddingWidth = size.paddingLeft + size.paddingRight; 1225 var paddingHeight = size.paddingTop + size.paddingBottom; 1226 var marginWidth = size.marginLeft + size.marginRight; 1227 var marginHeight = size.marginTop + size.marginBottom; 1228 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 1229 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 1230 1231 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 1232 1233 // overwrite width and height if we can get it from style 1234 var styleWidth = getStyleSize( style.width ); 1235 if ( styleWidth !== false ) { 1236 size.width = styleWidth + 1237 // add padding and border unless it's already including it 1238 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 1239 } 1240 1241 var styleHeight = getStyleSize( style.height ); 1242 if ( styleHeight !== false ) { 1243 size.height = styleHeight + 1244 // add padding and border unless it's already including it 1245 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 1246 } 1247
1248 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 1249 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 1250 1251 size.outerWidth = size.width + marginWidth; 1252 size.outerHeight = size.height + marginHeight; 1253 1254 return size; 1255} 1256 1257// IE8 returns percent values, not pixels 1258// taken from jQuery's curCSS 1259function mungeNonPixel( elem, value ) { 1260 // IE8 and has percent value 1261 if ( window.getComputedStyle || value.indexOf('%') === -1 ) { 1262 return value; 1263 } 1264 var style = elem.style; 1265 // Remember the original values 1266 var left = style.left; 1267 var rs = elem.runtimeStyle; 1268 var rsLeft = rs && rs.left; 1269 1270 // Put in the new values to get a computed value out 1271 if ( rsLeft ) { 1272 rs.left = elem.currentStyle.left; 1273 } 1274 style.left = value; 1275 value = style.pixelLeft; 1276 1277 // Revert the changed values 1278 style.left = left; 1279 if ( rsLeft ) { 1280 rs.left = rsLeft; 1281 } 1282 1283 return value; 1284} 1285 1286return getSize; 1287 1288} 1289 1290// transport 1291if ( typeof define === 'function' && define.amd ) { 1292 // AMD for RequireJS 1293 define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize ); 1294} else if ( typeof exports === 'object' ) { 1295 // CommonJS for Component 1296 module.exports = defineGetSize( require('desandro-get-style-property') ); 1297} else { 1298 // browser global 1299 window.getSize = defineGetSize( window.getStyleProperty ); 1300} 1301 1302})( window ); 1303 1304/*! 1305 * docReady v1.0.4 1306 * Cross browser DOMContentLoaded event emitter 1307 * MIT license 1308 */ 1309 1310/*jshint browser: true, strict: true, undef: true, unused: true*/ 1311/*global define: false, require: false, module: false */ 1312 1313( function( window ) { 1314 1315 1316 1317var document = window.document; 1318// collection of functions to be triggered on ready 1319var queue = []; 1320 1321function docReady( fn ) { 1322 // throw out non-functions 1323 if ( typeof fn !== 'function' ) { 1324 return; 1325 } 1326 1327 if ( docReady.isReady ) { 1328 // ready now, hit it 1329 fn(); 1330 } else { 1331 // queue function when ready 1332 queue.push( fn ); 1333 } 1334} 1335 1336docReady.isReady = false; 1337 1338// triggered on various doc ready events 1339function onReady( event ) { 1340 // bail if already triggered or IE8 document is not ready just yet 1341 var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete'; 1342 if ( docReady.isReady || isIE8NotReady ) { 1343 return; 1344 } 1345 1346 trigger(); 1347} 1348 1349function trigger() { 1350 docReady.isReady = true; 1351 // process queue 1352 for ( var i=0, len = queue.length; i < len; i++ ) { 1353 var fn = queue[i]; 1354 fn(); 1355 } 1356} 1357 1358function defineDocReady( eventie ) { 1359 // trigger ready if page is ready 1360 if ( document.readyState === 'complete' ) { 1361 trigger(); 1362 } else { 1363 // listen for events 1364 eventie.bind( document, 'DOMContentLoaded', onReady ); 1365 eventie.bind( document, 'readystatechange', onReady ); 1366 eventie.bind( window, 'load', onReady ); 1367 } 1368 1369 return docReady; 1370} 1371 1372// transport 1373if ( typeof define === 'function' && define.amd ) { 1374 // AMD 1375 define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady ); 1376} else if ( typeof exports === 'object' ) { 1377 module.exports = defineDocReady( require('eventie') ); 1378} else { 1379 // browser global 1380 window.docReady = defineDocReady( window.eventie ); 1381} 1382 1383})( window ); 1384 1385/** 1386 * matchesSelector v1.0.3 1387 * matchesSelector( element, '.selector' ) 1388 * MIT license 1389 */ 1390 1391/*jshint browser: true, strict: true, undef: true, unused: true */ 1392/*global define: false, module: false */ 1393 1394( function( ElemProto ) { 1395 1396 'use strict'; 1397 1398 var matchesMethod = ( function() { 1399 // check for the standard method name first 1400 if ( ElemProto.matches ) { 1401 return 'matches'; 1402 } 1403 // check un-prefixed 1404 if ( ElemProto.matchesSelector ) { 1405 return 'matchesSelector'; 1406 } 1407 // check vendor prefixes 1408 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 1409 1410 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1411 var prefix = prefixes[i]; 1412 var method = prefix + 'MatchesSelector'; 1413 if ( ElemProto[ method ] ) { 1414 return method; 1415 } 1416 } 1417 })(); 1418 1419 // ----- match ----- // 1420 1421 function match( elem, selector ) { 1422 return elem[ matchesMethod ]( selector ); 1423 } 1424 1425 // ----- appendToFragment ----- // 1426 1427 function checkParent( elem ) { 1428 // not needed if already has parent 1429 if ( elem.parentNode ) { 1430 return; 1431 } 1432 var fragment = document.createDocumentFragment(); 1433 fragment.appendChild( elem ); 1434 } 1435 1436 // ----- query ----- // 1437 1438 // fall back to using QSA 1439 // thx @jonathantneal https://gist.github.com/3062955 1440 function query( elem, selector ) { 1441 // append to fragment if no parent 1442 checkParent( elem ); 1443 1444 // match elem with all selected elems of parent 1445 var elems = elem.parentNode.querySelectorAll( selector ); 1446 for ( var i=0, len = elems.length; i < len; i++ ) { 1447 // return true if match 1448 if ( elems[i] === elem ) { 1449 return true; 1450 } 1451 } 1452 // otherwise return false 1453 return false;
1454 } 1455 1456 // ----- matchChild ----- // 1457 1458 function matchChild( elem, selector ) { 1459 checkParent( elem ); 1460 return match( elem, selector ); 1461 } 1462 1463 // ----- matchesSelector ----- // 1464 1465 var matchesSelector; 1466 1467 if ( matchesMethod ) { 1468 // IE9 supports matchesSelector, but doesn't work on orphaned elems 1469 // check for that 1470 var div = document.createElement('div'); 1471 var supportsOrphans = match( div, 'div' ); 1472 matchesSelector = supportsOrphans ? match : matchChild; 1473 } else { 1474 matchesSelector = query; 1475 } 1476 1477 // transport 1478 if ( typeof define === 'function' && define.amd ) { 1479 // AMD 1480 define( 'matches-selector/matches-selector',[],function() { 1481 return matchesSelector; 1482 }); 1483 } else if ( typeof exports === 'object' ) { 1484 module.exports = matchesSelector; 1485 } 1486 else { 1487 // browser global 1488 window.matchesSelector = matchesSelector; 1489 } 1490 1491})( Element.prototype ); 1492 1493/** 1494 * Fizzy UI utils v1.0.1 1495 * MIT license 1496 */ 1497 1498/*jshint browser: true, undef: true, unused: true, strict: true */ 1499 1500( function( window, factory ) { 1501 /*global define: false, module: false, require: false */ 1502 'use strict'; 1503 // universal module definition 1504 1505 if ( typeof define == 'function' && define.amd ) { 1506 // AMD 1507 define( 'fizzy-ui-utils/utils',[ 1508 'doc-ready/doc-ready', 1509 'matches-selector/matches-selector' 1510 ], function( docReady, matchesSelector ) { 1511 return factory( window, docReady, matchesSelector ); 1512 }); 1513 } else if ( typeof exports == 'object' ) { 1514 // CommonJS 1515 module.exports = factory( 1516 window, 1517 require('doc-ready'), 1518 require('desandro-matches-selector') 1519 ); 1520 } else { 1521 // browser global 1522 window.fizzyUIUtils = factory( 1523 window, 1524 window.docReady, 1525 window.matchesSelector 1526 ); 1527 } 1528 1529}( window, function factory( window, docReady, matchesSelector ) { 1530 1531 1532 1533var utils = {}; 1534 1535// ----- extend ----- // 1536 1537// extends objects 1538utils.extend = function( a, b ) { 1539 for ( var prop in b ) { 1540 a[ prop ] = b[ prop ]; 1541 } 1542 return a; 1543}; 1544 1545// ----- modulo ----- // 1546 1547utils.modulo = function( num, div ) { 1548 return ( ( num % div ) + div ) % div; 1549}; 1550 1551// ----- isArray ----- // 1552 1553var objToString = Object.prototype.toString; 1554utils.isArray = function( obj ) { 1555 return objToString.call( obj ) == '[object Array]'; 1556}; 1557 1558// ----- makeArray ----- // 1559 1560// turn element or nodeList into an array 1561utils.makeArray = function( obj ) { 1562 var ary = []; 1563 if ( utils.isArray( obj ) ) { 1564 // use object if already an array 1565 ary = obj; 1566 } else if ( obj && typeof obj.length == 'number' ) { 1567 // convert nodeList to array 1568 for ( var i=0, len = obj.length; i < len; i++ ) { 1569 ary.push( obj[i] ); 1570 } 1571 } else { 1572 // array of single index 1573 ary.push( obj ); 1574 } 1575 return ary; 1576}; 1577 1578// ----- indexOf ----- // 1579 1580// index of helper cause IE8 1581utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) { 1582 return ary.indexOf( obj ); 1583 } : function( ary, obj ) { 1584 for ( var i=0, len = ary.length; i < len; i++ ) { 1585 if ( ary[i] === obj ) { 1586 return i; 1587 } 1588 } 1589 return -1; 1590 }; 1591 1592// ----- removeFrom ----- // 1593 1594utils.removeFrom = function( ary, obj ) { 1595 var index = utils.indexOf( ary, obj ); 1596 if ( index != -1 ) { 1597 ary.splice( index, 1 ); 1598 } 1599}; 1600 1601// ----- isElement ----- // 1602 1603// http://stackoverflow.com/a/384380/182183 1604utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ? 1605 function isElementDOM2( obj ) { 1606 return obj instanceof HTMLElement; 1607 } : 1608 function isElementQuirky( obj ) { 1609 return obj && typeof obj == 'object' && 1610 obj.nodeType == 1 && typeof obj.nodeName == 'string'; 1611 }; 1612 1613// ----- setText ----- // 1614 1615utils.setText = ( function() { 1616 var setTextProperty; 1617 function setText( elem, text ) { 1618 // only check setTextProperty once 1619 setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' ); 1620 elem[ setTextProperty ] = text; 1621 } 1622 return setText; 1623})(); 1624 1625// ----- getParent ----- // 1626 1627utils.getParent = function( elem, selector ) { 1628 while ( elem != document.body ) { 1629 elem = elem.parentNode; 1630 if ( matchesSelector( elem, selector ) ) { 1631 return elem; 1632 } 1633 } 1634}; 1635 1636// ----- getQueryElement ----- // 1637 1638// use element as selector string 1639utils.getQueryElement = function( elem ) { 1640 if ( typeof elem == 'string' ) { 1641 return document.querySelector( elem ); 1642 } 1643 return elem; 1644}; 1645 1646// ----- handleEvent ----- // 1647 1648// enable .ontype to trigger from .addEventListener( elem, 'type' ) 1649utils.handleEvent = function( event ) { 1650 var method = 'on' + event.type; 1651 if ( this[ method ] ) { 1652 this[ method ]( event ); 1653 } 1654}; 1655 1656// ----- filterFindElements ----- // 1657 1658utils.filterFindElements = function( elems, selector ) { 1659 // make array of elems 1660 elems = utils.makeArray( elems ); 1661 var ffElems = []; 1662 1663 for ( var i=0, len = elems.length; i < len; i++ ) { 1664 var elem = elems[i]; 1665 // check that elem is an actual element 1666 if ( !utils.isElement( elem ) ) { 1667 continue; 1668 } 1669 // filter & find items if we have a selector 1670 if ( selector ) { 1671 // filter siblings 1672 if ( matchesSelector( elem, selector ) ) { 1673 ffElems.push( elem ); 1674 } 1675 // find children 1676 var childElems = elem.querySelectorAll( selector ); 1677 // concat childElems to filterFound array 1678 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 1679 ffElems.push( childElems[j] ); 1680 } 1681 } else { 1682 ffElems.push( elem ); 1683 } 1684 } 1685 1686 return ffElems; 1687}; 1688 1689// ----- debounceMethod ----- // 1690 1691utils.debounceMethod = function( _class, methodName, threshold ) { 1692 // original method 1693 var method = _class.prototype[ methodName ]; 1694 var timeoutName = methodName + 'Timeout'; 1695 1696 _class.prototype[ methodName ] = function() { 1697 var timeout = this[ timeoutName ]; 1698 if ( timeout ) { 1699 clearTimeout( timeout ); 1700 } 1701 var args = arguments; 1702 1703 var _this = this; 1704 this[ timeoutName ] = setTimeout( function() { 1705 method.apply( _this, args ); 1706 delete _this[ timeoutName ]; 1707 }, threshold || 100 ); 1708 }; 1709}; 1710 1711// ----- htmlInit ----- // 1712 1713// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 1714utils.toDashed = function( str ) { 1715 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 1716 return $1 + '-' + $2; 1717 }).toLowerCase(); 1718}; 1719
1720var console = window.console; 1721/** 1722 * allow user to initialize classes via .js-namespace class 1723 * htmlInit( Widget, 'widgetName' ) 1724 * options are parsed from data-namespace-option attribute 1725 */ 1726utils.htmlInit = function( WidgetClass, namespace ) { 1727 docReady( function() { 1728 var dashedNamespace = utils.toDashed( namespace ); 1729 var elems = document.querySelectorAll( '.js-' + dashedNamespace ); 1730 var dataAttr = 'data-' + dashedNamespace + '-options'; 1731 1732 for ( var i=0, len = elems.length; i < len; i++ ) { 1733 var elem = elems[i]; 1734 var attr = elem.getAttribute( dataAttr ); 1735 var options; 1736 try { 1737 options = attr && JSON.parse( attr ); 1738 } catch ( error ) { 1739 // log error, do not initialize 1740 if ( console ) { 1741 console.error( 'Error parsing ' + dataAttr + ' on ' + 1742 elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' + 1743 error ); 1744 } 1745 continue; 1746 } 1747 // initialize 1748 var instance = new WidgetClass( elem, options ); 1749 // make available via $().data('layoutname') 1750 var jQuery = window.jQuery; 1751 if ( jQuery ) { 1752 jQuery.data( elem, namespace, instance ); 1753 } 1754 } 1755 }); 1756}; 1757 1758// ----- ----- // 1759 1760return utils; 1761 1762})); 1763 1764/** 1765 * Outlayer Item 1766 */ 1767 1768( function( window, factory ) { 1769 'use strict'; 1770 // universal module definition 1771 if ( typeof define === 'function' && define.amd ) { 1772 // AMD 1773 define( 'outlayer/item',[ 1774 'eventEmitter/EventEmitter', 1775 'get-size/get-size', 1776 'get-style-property/get-style-property', 1777 'fizzy-ui-utils/utils' 1778 ], 1779 function( EventEmitter, getSize, getStyleProperty, utils ) { 1780 return factory( window, EventEmitter, getSize, getStyleProperty, utils ); 1781 } 1782 ); 1783 } else if (typeof exports === 'object') { 1784 // CommonJS 1785 module.exports = factory( 1786 window, 1787 require('wolfy87-eventemitter'), 1788 require('get-size'), 1789 require('desandro-get-style-property'), 1790 require('fizzy-ui-utils') 1791 ); 1792 } else { 1793 // browser global 1794 window.Outlayer = {}; 1795 window.Outlayer.Item = factory( 1796 window, 1797 window.EventEmitter, 1798 window.getSize, 1799 window.getStyleProperty, 1800 window.fizzyUIUtils 1801 ); 1802 } 1803 1804}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) { 1805'use strict'; 1806 1807// ----- helpers ----- // 1808 1809var getComputedStyle = window.getComputedStyle; 1810var getStyle = getComputedStyle ? 1811 function( elem ) { 1812 return getComputedStyle( elem, null ); 1813 } : 1814 function( elem ) { 1815 return elem.currentStyle; 1816 }; 1817 1818 1819function isEmptyObj( obj ) { 1820 for ( var prop in obj ) { 1821 return false; 1822 } 1823 prop = null; 1824 return true; 1825} 1826 1827// -------------------------- CSS3 support -------------------------- // 1828 1829var transitionProperty = getStyleProperty('transition'); 1830var transformProperty = getStyleProperty('transform'); 1831var supportsCSS3 = transitionProperty && transformProperty; 1832var is3d = !!getStyleProperty('perspective'); 1833 1834var transitionEndEvent = { 1835 WebkitTransition: 'webkitTransitionEnd', 1836 MozTransition: 'transitionend', 1837 OTransition: 'otransitionend', 1838 transition: 'transitionend' 1839}[ transitionProperty ]; 1840 1841// properties that could have vendor prefix 1842var prefixableProperties = [ 1843 'transform', 1844 'transition', 1845 'transitionDuration', 1846 'transitionProperty' 1847]; 1848 1849// cache all vendor properties 1850var vendorProperties = ( function() { 1851 var cache = {}; 1852 for ( var i=0, len = prefixableProperties.length; i < len; i++ ) { 1853 var prop = prefixableProperties[i]; 1854 var supportedProp = getStyleProperty( prop ); 1855 if ( supportedProp && supportedProp !== prop ) { 1856 cache[ prop ] = supportedProp; 1857 } 1858 } 1859 return cache; 1860})(); 1861 1862// -------------------------- Item -------------------------- // 1863 1864function Item( element, layout ) { 1865 if ( !element ) { 1866 return; 1867 } 1868 1869 this.element = element; 1870 // parent layout class, i.e. Masonry, Isotope, or Packery 1871 this.layout = layout; 1872 this.position = { 1873 x: 0, 1874 y: 0 1875 }; 1876 1877 this._create(); 1878} 1879 1880// inherit EventEmitter 1881utils.extend( Item.prototype, EventEmitter.prototype ); 1882 1883Item.prototype._create = function() { 1884 // transition objects 1885 this._transn = { 1886 ingProperties: {}, 1887 clean: {}, 1888 onEnd: {} 1889 }; 1890 1891 this.css({ 1892 position: 'absolute' 1893 }); 1894}; 1895 1896// trigger specified handler for event type 1897Item.prototype.handleEvent = function( event ) { 1898 var method = 'on' + event.type; 1899 if ( this[ method ] ) { 1900 this[ method ]( event ); 1901 } 1902}; 1903 1904Item.prototype.getSize = function() { 1905 this.size = getSize( this.element ); 1906}; 1907 1908/** 1909 * apply CSS styles to element 1910 * @param {Object} style 1911 */ 1912Item.prototype.css = function( style ) { 1913 var elemStyle = this.element.style; 1914 1915 for ( var prop in style ) { 1916 // use vendor property if available
1917 var supportedProp = vendorProperties[ prop ] || prop; 1918 elemStyle[ supportedProp ] = style[ prop ]; 1919 } 1920}; 1921 1922 // measure position, and sets it 1923Item.prototype.getPosition = function() { 1924 var style = getStyle( this.element ); 1925 var layoutOptions = this.layout.options; 1926 var isOriginLeft = layoutOptions.isOriginLeft; 1927 var isOriginTop = layoutOptions.isOriginTop; 1928 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 1929 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 1930 // convert percent to pixels 1931 var layoutSize = this.layout.size; 1932 var x = xValue.indexOf('%') != -1 ? 1933 ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 ); 1934 var y = yValue.indexOf('%') != -1 ? 1935 ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 ); 1936 1937 // clean up 'auto' or other non-integer values 1938 x = isNaN( x ) ? 0 : x; 1939 y = isNaN( y ) ? 0 : y; 1940 // remove padding from measurement 1941 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 1942 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 1943 1944 this.position.x = x; 1945 this.position.y = y; 1946}; 1947 1948// set settled position, apply padding 1949Item.prototype.layoutPosition = function() { 1950 var layoutSize = this.layout.size; 1951 var layoutOptions = this.layout.options; 1952 var style = {}; 1953 1954 // x 1955 var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight'; 1956 var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right'; 1957 var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left'; 1958 1959 var x = this.position.x + layoutSize[ xPadding ]; 1960 // set in percentage or pixels 1961 style[ xProperty ] = this.getXValue( x ); 1962 // reset other property 1963 style[ xResetProperty ] = ''; 1964 1965 // y 1966 var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom'; 1967 var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom'; 1968 var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top'; 1969 1970 var y = this.position.y + layoutSize[ yPadding ]; 1971 // set in percentage or pixels 1972 style[ yProperty ] = this.getYValue( y ); 1973 // reset other property 1974 style[ yResetProperty ] = ''; 1975 1976 this.css( style ); 1977 this.emitEvent( 'layout', [ this ] ); 1978}; 1979 1980Item.prototype.getXValue = function( x ) { 1981 var layoutOptions = this.layout.options; 1982 return layoutOptions.percentPosition && !layoutOptions.isHorizontal ? 1983 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 1984}; 1985 1986Item.prototype.getYValue = function( y ) { 1987 var layoutOptions = this.layout.options; 1988 return layoutOptions.percentPosition && layoutOptions.isHorizontal ? 1989 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 1990}; 1991 1992 1993Item.prototype._transitionTo = function( x, y ) { 1994 this.getPosition(); 1995 // get current x & y from top/left 1996 var curX = this.position.x; 1997 var curY = this.position.y; 1998 1999 var compareX = parseInt( x, 10 ); 2000 var compareY = parseInt( y, 10 ); 2001 var didNotMove = compareX === this.position.x && compareY === this.position.y; 2002 2003 // save end position 2004 this.setPosition( x, y ); 2005 2006 // if did not move and not transitioning, just go to layout 2007 if ( didNotMove && !this.isTransitioning ) { 2008 this.layoutPosition(); 2009 return; 2010 } 2011 2012 var transX = x - curX; 2013 var transY = y - curY; 2014 var transitionStyle = {}; 2015 transitionStyle.transform = this.getTranslate( transX, transY ); 2016 2017 this.transition({ 2018 to: transitionStyle, 2019 onTransitionEnd: { 2020 transform: this.layoutPosition 2021 }, 2022 isCleaning: true 2023 }); 2024}; 2025 2026Item.prototype.getTranslate = function( x, y ) { 2027 // flip cooridinates if origin on right or bottom 2028 var layoutOptions = this.layout.options; 2029 x = layoutOptions.isOriginLeft ? x : -x; 2030 y = layoutOptions.isOriginTop ? y : -y; 2031 2032 if ( is3d ) { 2033 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 2034 } 2035 2036 return 'translate(' + x + 'px, ' + y + 'px)'; 2037}; 2038 2039// non transition + transform support 2040Item.prototype.goTo = function( x, y ) { 2041 this.setPosition( x, y ); 2042 this.layoutPosition(); 2043}; 2044 2045// use transition and transforms if supported 2046Item.prototype.moveTo = supportsCSS3 ? 2047 Item.prototype._transitionTo : Item.prototype.goTo; 2048 2049Item.prototype.setPosition = function( x, y ) { 2050 this.position.x = parseInt( x, 10 ); 2051 this.position.y = parseInt( y, 10 ); 2052}; 2053 2054// ----- transition ----- // 2055 2056/** 2057 * @param {Object} style - CSS 2058 * @param {Function} onTransitionEnd 2059 */ 2060 2061// non transition, just trigger callback 2062Item.prototype._nonTransition = function( args ) { 2063 this.css( args.to ); 2064 if ( args.isCleaning ) { 2065 this._removeStyles( args.to ); 2066 } 2067 for ( var prop in args.onTransitionEnd ) { 2068 args.onTransitionEnd[ prop ].call( this ); 2069 } 2070}; 2071 2072/** 2073 * proper transition 2074 * @param {Object} args - arguments 2075 * @param {Object} to - style to transition to 2076 * @param {Object} from - style to start transition from 2077 * @param {Boolean} isCleaning - removes transition styles after transition 2078 * @param {Function} onTransitionEnd - callback 2079 */ 2080Item.prototype._transition = function( args ) { 2081 // redirect to nonTransition if no transition duration 2082 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 2083 this._nonTransition( args ); 2084 return; 2085 } 2086 2087 var _transition = this._transn; 2088 // keep track of onTransitionEnd callback by css property 2089 for ( var prop in args.onTransitionEnd ) { 2090 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 2091 } 2092 // keep track of properties that are transitioning 2093 for ( prop in args.to ) { 2094 _transition.ingProperties[ prop ] = true; 2095 // keep track of properties to clean up when transition is done 2096 if ( args.isCleaning ) { 2097 _transition.clean[ prop ] = true; 2098 } 2099 } 2100 2101 // set from styles 2102 if ( args.from ) { 2103 this.css( args.from ); 2104 // force redraw. http://blog.alexmaccaw.com/css-transitions
vendor: 11,318 bytes, lines 2105-2573
2105 var h = this.element.offsetHeight; 2106 // hack for JSHint to hush about unused var 2107 h = null; 2108 } 2109 // enable transition 2110 this.enableTransition( args.to ); 2111 // set styles that are transitioning 2112 this.css( args.to ); 2113 2114 this.isTransitioning = true; 2115 2116}; 2117 2118// dash before all cap letters, including first for 2119// WebkitTransform => -webkit-transform 2120function toDashedAll( str ) { 2121 return str.replace( /([A-Z])/g, function( $1 ) { 2122 return '-' + $1.toLowerCase(); 2123 }); 2124} 2125 2126var transitionProps = 'opacity,' + 2127 toDashedAll( vendorProperties.transform || 'transform' ); 2128 2129Item.prototype.enableTransition = function(/* style */) { 2130 // HACK changing transitionProperty during a transition 2131 // will cause transition to jump 2132 if ( this.isTransitioning ) { 2133 return; 2134 } 2135 2136 // make `transition: foo, bar, baz` from style object 2137 // HACK un-comment this when enableTransition can work 2138 // while a transition is happening 2139 // var transitionValues = []; 2140 // for ( var prop in style ) { 2141 // // dash-ify camelCased properties like WebkitTransition 2142 // prop = vendorProperties[ prop ] || prop; 2143 // transitionValues.push( toDashedAll( prop ) ); 2144 // } 2145 // enable transition styles 2146 this.css({ 2147 transitionProperty: transitionProps, 2148 transitionDuration: this.layout.options.transitionDuration 2149 }); 2150 // listen for transition end event 2151 this.element.addEventListener( transitionEndEvent, this, false ); 2152}; 2153 2154Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ]; 2155 2156// ----- events ----- // 2157 2158Item.prototype.onwebkitTransitionEnd = function( event ) { 2159 this.ontransitionend( event ); 2160}; 2161 2162Item.prototype.onotransitionend = function( event ) { 2163 this.ontransitionend( event ); 2164}; 2165 2166// properties that I munge to make my life easier 2167var dashedVendorProperties = { 2168 '-webkit-transform': 'transform', 2169 '-moz-transform': 'transform', 2170 '-o-transform': 'transform' 2171}; 2172 2173Item.prototype.ontransitionend = function( event ) { 2174 // disregard bubbled events from children 2175 if ( event.target !== this.element ) { 2176 return; 2177 } 2178 var _transition = this._transn; 2179 // get property name of transitioned property, convert to prefix-free 2180 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 2181 2182 // remove property that has completed transitioning 2183 delete _transition.ingProperties[ propertyName ]; 2184 // check if any properties are still transitioning 2185 if ( isEmptyObj( _transition.ingProperties ) ) { 2186 // all properties have completed transitioning 2187 this.disableTransition(); 2188 } 2189 // clean style 2190 if ( propertyName in _transition.clean ) { 2191 // clean up style 2192 this.element.style[ event.propertyName ] = ''; 2193 delete _transition.clean[ propertyName ]; 2194 } 2195 // trigger onTransitionEnd callback 2196 if ( propertyName in _transition.onEnd ) { 2197 var onTransitionEnd = _transition.onEnd[ propertyName ]; 2198 onTransitionEnd.call( this ); 2199 delete _transition.onEnd[ propertyName ]; 2200 } 2201 2202 this.emitEvent( 'transitionEnd', [ this ] ); 2203}; 2204 2205Item.prototype.disableTransition = function() { 2206 this.removeTransitionStyles(); 2207 this.element.removeEventListener( transitionEndEvent, this, false ); 2208 this.isTransitioning = false; 2209}; 2210 2211/** 2212 * removes style property from element 2213 * @param {Object} style 2214**/ 2215Item.prototype._removeStyles = function( style ) { 2216 // clean up transition styles 2217 var cleanStyle = {}; 2218 for ( var prop in style ) { 2219 cleanStyle[ prop ] = ''; 2220 } 2221 this.css( cleanStyle ); 2222}; 2223 2224var cleanTransitionStyle = { 2225 transitionProperty: '', 2226 transitionDuration: '' 2227}; 2228 2229Item.prototype.removeTransitionStyles = function() { 2230 // remove transition 2231 this.css( cleanTransitionStyle ); 2232}; 2233 2234// ----- show/hide/remove ----- // 2235 2236// remove element from DOM 2237Item.prototype.removeElem = function() { 2238 this.element.parentNode.removeChild( this.element ); 2239 // remove display: none 2240 this.css({ display: '' }); 2241 this.emitEvent( 'remove', [ this ] ); 2242}; 2243 2244Item.prototype.remove = function() { 2245 // just remove element if no transition support or no transition 2246 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 2247 this.removeElem(); 2248 return; 2249 } 2250 2251 // start transition 2252 var _this = this; 2253 this.once( 'transitionEnd', function() { 2254 _this.removeElem(); 2255 }); 2256 this.hide(); 2257}; 2258 2259Item.prototype.reveal = function() { 2260 delete this.isHidden; 2261 // remove display: none 2262 this.css({ display: '' }); 2263 2264 var options = this.layout.options; 2265 2266 var onTransitionEnd = {}; 2267 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 2268 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 2269 2270 this.transition({ 2271 from: options.hiddenStyle, 2272 to: options.visibleStyle, 2273 isCleaning: true, 2274 onTransitionEnd: onTransitionEnd 2275 }); 2276}; 2277 2278Item.prototype.onRevealTransitionEnd = function() { 2279 // check if still visible 2280 // during transition, item may have been hidden 2281 if ( !this.isHidden ) { 2282 this.emitEvent('reveal'); 2283 } 2284}; 2285 2286/** 2287 * get style property use for hide/reveal transition end 2288 * @param {String} styleProperty - hiddenStyle/visibleStyle 2289 * @returns {String} 2290 */ 2291Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) { 2292 var optionStyle = this.layout.options[ styleProperty ]; 2293 // use opacity 2294 if ( optionStyle.opacity ) { 2295 return 'opacity'; 2296 } 2297 // get first property 2298 for ( var prop in optionStyle ) { 2299 return prop; 2300 } 2301}; 2302 2303Item.prototype.hide = function() { 2304 // set flag 2305 this.isHidden = true; 2306 // remove display: none 2307 this.css({ display: '' }); 2308 2309 var options = this.layout.options; 2310 2311 var onTransitionEnd = {}; 2312 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 2313 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 2314 2315 this.transition({ 2316 from: options.visibleStyle, 2317 to: options.hiddenStyle, 2318 // keep hidden stuff hidden 2319 isCleaning: true, 2320 onTransitionEnd: onTransitionEnd 2321 }); 2322}; 2323 2324Item.prototype.onHideTransitionEnd = function() { 2325 // check if still hidden 2326 // during transition, item may have been un-hidden 2327 if ( this.isHidden ) { 2328 this.css({ display: 'none' }); 2329 this.emitEvent('hide'); 2330 } 2331}; 2332 2333Item.prototype.destroy = function() { 2334 this.css({ 2335 position: '', 2336 left: '', 2337 right: '', 2338 top: '', 2339 bottom: '', 2340 transition: '', 2341 transform: '' 2342 }); 2343}; 2344 2345return Item; 2346 2347})); 2348 2349/*! 2350 * Outlayer v1.4.2 2351 * the brains and guts of a layout library 2352 * MIT license 2353 */ 2354 2355( function( window, factory ) { 2356 'use strict'; 2357 // universal module definition 2358 2359 if ( typeof define == 'function' && define.amd ) { 2360 // AMD 2361 define( 'outlayer/outlayer',[ 2362 'eventie/eventie', 2363 'eventEmitter/EventEmitter', 2364 'get-size/get-size', 2365 'fizzy-ui-utils/utils', 2366 './item' 2367 ], 2368 function( eventie, EventEmitter, getSize, utils, Item ) { 2369 return factory( window, eventie, EventEmitter, getSize, utils, Item); 2370 } 2371 ); 2372 } else if ( typeof exports == 'object' ) { 2373 // CommonJS 2374 module.exports = factory( 2375 window, 2376 require('eventie'), 2377 require('wolfy87-eventemitter'), 2378 require('get-size'), 2379 require('fizzy-ui-utils'), 2380 require('./item') 2381 ); 2382 } else { 2383 // browser global 2384 window.Outlayer = factory( 2385 window, 2386 window.eventie, 2387 window.EventEmitter, 2388 window.getSize, 2389 window.fizzyUIUtils, 2390 window.Outlayer.Item 2391 ); 2392 } 2393 2394}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) { 2395'use strict'; 2396 2397// ----- vars ----- // 2398 2399var console = window.console; 2400var jQuery = window.jQuery; 2401var noop = function() {}; 2402 2403// -------------------------- Outlayer -------------------------- // 2404 2405// globally unique identifiers 2406var GUID = 0; 2407// internal store of all Outlayer intances 2408var instances = {}; 2409 2410 2411/** 2412 * @param {Element, String} element 2413 * @param {Object} options 2414 * @constructor 2415 */ 2416function Outlayer( element, options ) { 2417 var queryElement = utils.getQueryElement( element ); 2418 if ( !queryElement ) { 2419 if ( console ) { 2420 console.error( 'Bad element for ' + this.constructor.namespace + 2421 ': ' + ( queryElement || element ) ); 2422 } 2423 return; 2424 } 2425 this.element = queryElement; 2426 // add jQuery 2427 if ( jQuery ) { 2428 this.$element = jQuery( this.element ); 2429 } 2430 2431 // options 2432 this.options = utils.extend( {}, this.constructor.defaults ); 2433 this.option( options ); 2434 2435 // add id for Outlayer.getFromElement 2436 var id = ++GUID; 2437 this.element.outlayerGUID = id; // expando 2438 instances[ id ] = this; // associate via id 2439 2440 // kick it off 2441 this._create(); 2442 2443 if ( this.options.isInitLayout ) { 2444 this.layout(); 2445 } 2446} 2447 2448// settings are for internal use only 2449Outlayer.namespace = 'outlayer'; 2450Outlayer.Item = Item; 2451 2452// default options 2453Outlayer.defaults = { 2454 containerStyle: { 2455 position: 'relative' 2456 }, 2457 isInitLayout: true, 2458 isOriginLeft: true, 2459 isOriginTop: true, 2460 isResizeBound: true, 2461 isResizingContainer: true, 2462 // item options 2463 transitionDuration: '0.4s', 2464 hiddenStyle: { 2465 opacity: 0, 2466 transform: 'scale(0.001)' 2467 }, 2468 visibleStyle: { 2469 opacity: 1, 2470 transform: 'scale(1)' 2471 } 2472}; 2473 2474// inherit EventEmitter 2475utils.extend( Outlayer.prototype, EventEmitter.prototype ); 2476 2477/** 2478 * set options 2479 * @param {Object} opts 2480 */ 2481Outlayer.prototype.option = function( opts ) { 2482 utils.extend( this.options, opts ); 2483}; 2484 2485Outlayer.prototype._create = function() { 2486 // get items from children 2487 this.reloadItems(); 2488 // elements that affect layout, but are not laid out 2489 this.stamps = []; 2490 this.stamp( this.options.stamp ); 2491 // set container style 2492 utils.extend( this.element.style, this.options.containerStyle ); 2493 2494 // bind resize method 2495 if ( this.options.isResizeBound ) { 2496 this.bindResize(); 2497 } 2498}; 2499 2500// goes through all children again and gets bricks in proper order 2501Outlayer.prototype.reloadItems = function() { 2502 // collection of item elements 2503 this.items = this._itemize( this.element.children ); 2504}; 2505 2506 2507/** 2508 * turn elements into Outlayer.Items to be used in layout 2509 * @param {Array or NodeList or HTMLElement} elems 2510 * @returns {Array} items - collection of new Outlayer Items 2511 */ 2512Outlayer.prototype._itemize = function( elems ) { 2513 2514 var itemElems = this._filterFindItemElements( elems ); 2515 var Item = this.constructor.Item; 2516 2517 // create new Outlayer Items for collection 2518 var items = []; 2519 for ( var i=0, len = itemElems.length; i < len; i++ ) { 2520 var elem = itemElems[i]; 2521 var item = new Item( elem, this ); 2522 items.push( item ); 2523 } 2524 2525 return items; 2526}; 2527 2528/** 2529 * get item elements to be used in layout 2530 * @param {Array or NodeList or HTMLElement} elems 2531 * @returns {Array} items - item elements 2532 */ 2533Outlayer.prototype._filterFindItemElements = function( elems ) { 2534 return utils.filterFindElements( elems, this.options.itemSelector ); 2535}; 2536 2537/** 2538 * getter method for getting item elements 2539 * @returns {Array} elems - collection of item elements 2540 */ 2541Outlayer.prototype.getItemElements = function() { 2542 var elems = []; 2543 for ( var i=0, len = this.items.length; i < len; i++ ) { 2544 elems.push( this.items[i].element ); 2545 } 2546 return elems; 2547}; 2548 2549// ----- init & layout ----- // 2550 2551/** 2552 * lays out all items 2553 */ 2554Outlayer.prototype.layout = function() { 2555 this._resetLayout(); 2556 this._manageStamps(); 2557 2558 // don't animate first layout 2559 var isInstant = this.options.isLayoutInstant !== undefined ? 2560 this.options.isLayoutInstant : !this._isLayoutInited; 2561 this.layoutItems( this.items, isInstant ); 2562 2563 // flag for initalized 2564 this._isLayoutInited = true; 2565}; 2566 2567// _init is alias for layout 2568Outlayer.prototype._init = Outlayer.prototype.layout; 2569 2570/** 2571 * logic before any new layout 2572 */ 2573Outlayer.prototype._resetLayout = function() {
2574 this.getSize(); 2575}; 2576 2577 2578Outlayer.prototype.getSize = function() { 2579 this.size = getSize( this.element ); 2580}; 2581 2582/** 2583 * get measurement from option, for columnWidth, rowHeight, gutter 2584 * if option is String -> get element from selector string, & get size of element 2585 * if option is Element -> get size of element 2586 * else use option as a number 2587 * 2588 * @param {String} measurement 2589 * @param {String} size - width or height 2590 * @private 2591 */ 2592Outlayer.prototype._getMeasurement = function( measurement, size ) { 2593 var option = this.options[ measurement ]; 2594 var elem; 2595 if ( !option ) { 2596 // default to 0 2597 this[ measurement ] = 0; 2598 } else { 2599 // use option as an element 2600 if ( typeof option === 'string' ) { 2601 elem = this.element.querySelector( option ); 2602 } else if ( utils.isElement( option ) ) { 2603 elem = option; 2604 } 2605 // use size of element, if element 2606 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 2607 } 2608}; 2609 2610/** 2611 * layout a collection of item elements 2612 * @api public 2613 */ 2614Outlayer.prototype.layoutItems = function( items, isInstant ) { 2615 items = this._getItemsForLayout( items ); 2616 2617 this._layoutItems( items, isInstant ); 2618 2619 this._postLayout(); 2620}; 2621 2622/** 2623 * get the items to be laid out 2624 * you may want to skip over some items 2625 * @param {Array} items 2626 * @returns {Array} items 2627 */ 2628Outlayer.prototype._getItemsForLayout = function( items ) { 2629 var layoutItems = []; 2630 for ( var i=0, len = items.length; i < len; i++ ) { 2631 var item = items[i]; 2632 if ( !item.isIgnored ) { 2633 layoutItems.push( item ); 2634 } 2635 } 2636 return layoutItems; 2637}; 2638 2639/** 2640 * layout items 2641 * @param {Array} items 2642 * @param {Boolean} isInstant 2643 */ 2644Outlayer.prototype._layoutItems = function( items, isInstant ) { 2645 this._emitCompleteOnItems( 'layout', items ); 2646 2647 if ( !items || !items.length ) { 2648 // no items, emit event with empty array 2649 return; 2650 } 2651 2652 var queue = []; 2653 2654 for ( var i=0, len = items.length; i < len; i++ ) { 2655 var item = items[i]; 2656 // get x/y object from method 2657 var position = this._getItemLayoutPosition( item ); 2658 // enqueue 2659 position.item = item; 2660 position.isInstant = isInstant || item.isLayoutInstant; 2661 queue.push( position ); 2662 } 2663 2664 this._processLayoutQueue( queue ); 2665}; 2666 2667/** 2668 * get item layout position 2669 * @param {Outlayer.Item} item 2670 * @returns {Object} x and y position 2671 */ 2672Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) { 2673 return { 2674 x: 0, 2675 y: 0 2676 }; 2677}; 2678 2679/** 2680 * iterate over array and position each item 2681 * Reason being - separating this logic prevents 'layout invalidation' 2682 * thx @paul_irish 2683 * @param {Array} queue 2684 */ 2685Outlayer.prototype._processLayoutQueue = function( queue ) { 2686 for ( var i=0, len = queue.length; i < len; i++ ) { 2687 var obj = queue[i]; 2688 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant ); 2689 } 2690}; 2691 2692/** 2693 * Sets position of item in DOM 2694 * @param {Outlayer.Item} item 2695 * @param {Number} x - horizontal position 2696 * @param {Number} y - vertical position 2697 * @param {Boolean} isInstant - disables transitions 2698 */ 2699Outlayer.prototype._positionItem = function( item, x, y, isInstant ) { 2700 if ( isInstant ) { 2701 // if not transition, just set CSS 2702 item.goTo( x, y ); 2703 } else { 2704 item.moveTo( x, y ); 2705 } 2706}; 2707 2708/** 2709 * Any logic you want to do after each layout, 2710 * i.e. size the container 2711 */ 2712Outlayer.prototype._postLayout = function() { 2713 this.resizeContainer(); 2714}; 2715 2716Outlayer.prototype.resizeContainer = function() { 2717 if ( !this.options.isResizingContainer ) { 2718 return; 2719 } 2720 var size = this._getContainerSize(); 2721 if ( size ) { 2722 this._setContainerMeasure( size.width, true ); 2723 this._setContainerMeasure( size.height, false ); 2724 } 2725}; 2726 2727/** 2728 * Sets width or height of container if returned 2729 * @returns {Object} size 2730 * @param {Number} width 2731 * @param {Number} height 2732 */ 2733Outlayer.prototype._getContainerSize = noop; 2734 2735/** 2736 * @param {Number} measure - size of width or height 2737 * @param {Boolean} isWidth 2738 */ 2739Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) { 2740 if ( measure === undefined ) { 2741 return; 2742 } 2743 2744 var elemSize = this.size; 2745 // add padding and border width if border box 2746 if ( elemSize.isBorderBox ) { 2747 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 2748 elemSize.borderLeftWidth + elemSize.borderRightWidth : 2749 elemSize.paddingBottom + elemSize.paddingTop + 2750 elemSize.borderTopWidth + elemSize.borderBottomWidth; 2751 } 2752 2753 measure = Math.max( measure, 0 ); 2754 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 2755}; 2756 2757/** 2758 * emit eventComplete on a collection of items events 2759 * @param {String} eventName 2760 * @param {Array} items - Outlayer.Items 2761 */ 2762Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) { 2763 var _this = this; 2764 function onComplete() { 2765 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 2766 } 2767 2768 var count = items.length; 2769 if ( !items || !count ) { 2770 onComplete(); 2771 return; 2772 } 2773 2774 var doneCount = 0; 2775 function tick() { 2776 doneCount++; 2777 if ( doneCount === count ) { 2778 onComplete(); 2779 } 2780 } 2781 2782 // bind callback 2783 for ( var i=0, len = items.length; i < len; i++ ) { 2784 var item = items[i]; 2785 item.once( eventName, tick ); 2786 } 2787}; 2788 2789/** 2790 * emits events via eventEmitter and jQuery events 2791 * @param {String} type - name of event 2792 * @param {Event} event - original event 2793 * @param {Array} args - extra arguments 2794 */ 2795Outlayer.prototype.dispatchEvent = function( type, event, args ) { 2796 // add original event to arguments 2797 var emitArgs = event ? [ event ].concat( args ) : args; 2798 this.emitEvent( type, emitArgs ); 2799 2800 if ( jQuery ) { 2801 // set this.$element 2802 this.$element = this.$element || jQuery( this.element ); 2803 if ( event ) { 2804 // create jQuery event 2805 var $event = jQuery.Event( event ); 2806 $event.type = type; 2807 this.$element.trigger( $event, args ); 2808 } else { 2809 // just trigger with type if no event available 2810 this.$element.trigger( type, args ); 2811 } 2812 } 2813}; 2814 2815// -------------------------- ignore & stamps -------------------------- // 2816 2817 2818/** 2819 * keep item in collection, but do not lay it out 2820 * ignored items do not get skipped in layout 2821 * @param {Element} elem 2822 */ 2823Outlayer.prototype.ignore = function( elem ) { 2824 var item = this.getItem( elem ); 2825 if ( item ) { 2826 item.isIgnored = true; 2827 } 2828}; 2829 2830/** 2831 * return item to layout collection 2832 * @param {Element} elem 2833 */ 2834Outlayer.prototype.unignore = function( elem ) { 2835 var item = this.getItem( elem ); 2836 if ( item ) { 2837 delete item.isIgnored; 2838 } 2839}; 2840 2841/** 2842 * adds elements to stamps 2843 * @param {NodeList, Array, Element, or String} elems 2844 */ 2845Outlayer.prototype.stamp = function( elems ) { 2846 elems = this._find( elems ); 2847 if ( !elems ) { 2848 return; 2849 } 2850
2851 this.stamps = this.stamps.concat( elems ); 2852 // ignore 2853 for ( var i=0, len = elems.length; i < len; i++ ) { 2854 var elem = elems[i]; 2855 this.ignore( elem ); 2856 } 2857}; 2858 2859/** 2860 * removes elements to stamps 2861 * @param {NodeList, Array, or Element} elems 2862 */ 2863Outlayer.prototype.unstamp = function( elems ) { 2864 elems = this._find( elems ); 2865 if ( !elems ){ 2866 return; 2867 } 2868 2869 for ( var i=0, len = elems.length; i < len; i++ ) { 2870 var elem = elems[i]; 2871 // filter out removed stamp elements 2872 utils.removeFrom( this.stamps, elem ); 2873 this.unignore( elem ); 2874 } 2875 2876}; 2877 2878/** 2879 * finds child elements 2880 * @param {NodeList, Array, Element, or String} elems 2881 * @returns {Array} elems 2882 */ 2883Outlayer.prototype._find = function( elems ) { 2884 if ( !elems ) { 2885 return; 2886 } 2887 // if string, use argument as selector string 2888 if ( typeof elems === 'string' ) { 2889 elems = this.element.querySelectorAll( elems ); 2890 } 2891 elems = utils.makeArray( elems ); 2892 return elems; 2893}; 2894 2895Outlayer.prototype._manageStamps = function() { 2896 if ( !this.stamps || !this.stamps.length ) { 2897 return; 2898 } 2899 2900 this._getBoundingRect(); 2901 2902 for ( var i=0, len = this.stamps.length; i < len; i++ ) { 2903 var stamp = this.stamps[i]; 2904 this._manageStamp( stamp ); 2905 } 2906}; 2907 2908// update boundingLeft / Top 2909Outlayer.prototype._getBoundingRect = function() { 2910 // get bounding rect for container element 2911 var boundingRect = this.element.getBoundingClientRect(); 2912 var size = this.size; 2913 this._boundingRect = { 2914 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 2915 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 2916 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 2917 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 2918 }; 2919}; 2920 2921/** 2922 * @param {Element} stamp 2923**/ 2924Outlayer.prototype._manageStamp = noop; 2925 2926/** 2927 * get x/y position of element relative to container element 2928 * @param {Element} elem 2929 * @returns {Object} offset - has left, top, right, bottom 2930 */ 2931Outlayer.prototype._getElementOffset = function( elem ) { 2932 var boundingRect = elem.getBoundingClientRect(); 2933 var thisRect = this._boundingRect; 2934 var size = getSize( elem ); 2935 var offset = { 2936 left: boundingRect.left - thisRect.left - size.marginLeft, 2937 top: boundingRect.top - thisRect.top - size.marginTop, 2938 right: thisRect.right - boundingRect.right - size.marginRight, 2939 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 2940 }; 2941 return offset; 2942}; 2943 2944// -------------------------- resize -------------------------- // 2945 2946// enable event handlers for listeners 2947// i.e. resize -> onresize 2948Outlayer.prototype.handleEvent = function( event ) { 2949 var method = 'on' + event.type; 2950 if ( this[ method ] ) { 2951 this[ method ]( event ); 2952 } 2953}; 2954 2955/** 2956 * Bind layout to window resizing 2957 */ 2958Outlayer.prototype.bindResize = function() { 2959 // bind just one listener 2960 if ( this.isResizeBound ) { 2961 return; 2962 } 2963 eventie.bind( window, 'resize', this ); 2964 this.isResizeBound = true; 2965}; 2966 2967/** 2968 * Unbind layout to window resizing 2969 */ 2970Outlayer.prototype.unbindResize = function() { 2971 if ( this.isResizeBound ) { 2972 eventie.unbind( window, 'resize', this ); 2973 } 2974 this.isResizeBound = false; 2975}; 2976 2977// original debounce by John Hann 2978// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 2979 2980// this fires every resize 2981Outlayer.prototype.onresize = function() { 2982 if ( this.resizeTimeout ) { 2983 clearTimeout( this.resizeTimeout ); 2984 } 2985 2986 var _this = this; 2987 function delayed() { 2988 _this.resize(); 2989 delete _this.resizeTimeout; 2990 } 2991 2992 this.resizeTimeout = setTimeout( delayed, 100 ); 2993}; 2994 2995// debounced, layout on resize 2996Outlayer.prototype.resize = function() { 2997 // don't trigger if size did not change 2998 // or if resize was unbound. See #9 2999 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 3000 return; 3001 } 3002 3003 this.layout(); 3004}; 3005 3006/** 3007 * check if layout is needed post layout 3008 * @returns Boolean 3009 */ 3010Outlayer.prototype.needsResizeLayout = function() { 3011 var size = getSize( this.element ); 3012 // check that this.size and size are there 3013 // IE8 triggers resize on body size change, so they might not be 3014 var hasSizes = this.size && size; 3015 return hasSizes && size.innerWidth !== this.size.innerWidth; 3016}; 3017 3018// -------------------------- methods -------------------------- // 3019 3020/** 3021 * add items to Outlayer instance 3022 * @param {Array or NodeList or Element} elems 3023 * @returns {Array} items - Outlayer.Items 3024**/ 3025Outlayer.prototype.addItems = function( elems ) { 3026 var items = this._itemize( elems ); 3027 // add items to collection 3028 if ( items.length ) { 3029 this.items = this.items.concat( items ); 3030 } 3031 return items; 3032}; 3033 3034/** 3035 * Layout newly-appended item elements 3036 * @param {Array or NodeList or Element} elems 3037 */ 3038Outlayer.prototype.appended = function( elems ) { 3039 var items = this.addItems( elems ); 3040 if ( !items.length ) { 3041 return; 3042 } 3043 // layout and reveal just the new items 3044 this.layoutItems( items, true ); 3045 this.reveal( items ); 3046}; 3047 3048/** 3049 * Layout prepended elements 3050 * @param {Array or NodeList or Element} elems 3051 */ 3052Outlayer.prototype.prepended = function( elems ) { 3053 var items = this._itemize( elems ); 3054 if ( !items.length ) { 3055 return; 3056 } 3057 // add items to beginning of collection 3058 var previousItems = this.items.slice(0); 3059 this.items = items.concat( previousItems ); 3060 // start new layout 3061 this._resetLayout(); 3062 this._manageStamps(); 3063 // layout new stuff without transition 3064 this.layoutItems( items, true ); 3065 this.reveal( items ); 3066 // layout previous items 3067 this.layoutItems( previousItems ); 3068}; 3069 3070/** 3071 * reveal a collection of items 3072 * @param {Array of Outlayer.Items} items 3073 */ 3074Outlayer.prototype.reveal = function( items ) { 3075 this._emitCompleteOnItems( 'reveal', items ); 3076 3077 var len = items && items.length; 3078 for ( var i=0; len && i < len; i++ ) { 3079 var item = items[i]; 3080 item.reveal(); 3081 } 3082}; 3083 3084/** 3085 * hide a collection of items 3086 * @param {Array of Outlayer.Items} items 3087 */ 3088Outlayer.prototype.hide = function( items ) { 3089 this._emitCompleteOnItems( 'hide', items ); 3090 3091 var len = items && items.length; 3092 for ( var i=0; len && i < len; i++ ) { 3093 var item = items[i]; 3094 item.hide(); 3095 } 3096}; 3097 3098/** 3099 * reveal item elements 3100 * @param {Array}, {Element}, {NodeList} items 3101 */ 3102Outlayer.prototype.revealItemElements = function( elems ) { 3103 var items = this.getItems( elems ); 3104 this.reveal( items ); 3105}; 3106 3107/** 3108 * hide item elements 3109 * @param {Array}, {Element}, {NodeList} items 3110 */ 3111Outlayer.prototype.hideItemElements = function( elems ) { 3112 var items = this.getItems( elems ); 3113 this.hide( items ); 3114}; 3115 3116/** 3117 * get Outlayer.Item, given an Element 3118 * @param {Element} elem 3119 * @param {Function} callback 3120 * @returns {Outlayer.Item} item 3121 */ 3122Outlayer.prototype.getItem = function( elem ) { 3123 // loop through items to get the one that matches 3124 for ( var i=0, len = this.items.length; i < len; i++ ) { 3125 var item = this.items[i]; 3126 if ( item.element === elem ) { 3127 // return item 3128 return item; 3129 } 3130 } 3131}; 3132 3133/** 3134 * get collection of Outlayer.Items, given Elements 3135 * @param {Array} elems 3136 * @returns {Array} items - Outlayer.Items 3137 */ 3138Outlayer.prototype.getItems = function( elems ) { 3139 elems = utils.makeArray( elems ); 3140 var items = []; 3141 for ( var i=0, len = elems.length; i < len; i++ ) { 3142 var elem = elems[i]; 3143 var item = this.getItem( elem ); 3144 if ( item ) { 3145 items.push( item ); 3146 } 3147 } 3148 3149 return items; 3150}; 3151 3152/**
3153 * remove element(s) from instance and DOM 3154 * @param {Array or NodeList or Element} elems 3155 */ 3156Outlayer.prototype.remove = function( elems ) { 3157 var removeItems = this.getItems( elems ); 3158 3159 this._emitCompleteOnItems( 'remove', removeItems ); 3160 3161 // bail if no items to remove 3162 if ( !removeItems || !removeItems.length ) { 3163 return; 3164 } 3165 3166 for ( var i=0, len = removeItems.length; i < len; i++ ) { 3167 var item = removeItems[i]; 3168 item.remove(); 3169 // remove item from collection 3170 utils.removeFrom( this.items, item ); 3171 } 3172}; 3173 3174// ----- destroy ----- // 3175 3176// remove and disable Outlayer instance 3177Outlayer.prototype.destroy = function() { 3178 // clean up dynamic styles 3179 var style = this.element.style; 3180 style.height = ''; 3181 style.position = ''; 3182 style.width = ''; 3183 // destroy items 3184 for ( var i=0, len = this.items.length; i < len; i++ ) { 3185 var item = this.items[i]; 3186 item.destroy(); 3187 } 3188 3189 this.unbindResize(); 3190 3191 var id = this.element.outlayerGUID; 3192 delete instances[ id ]; // remove reference to instance by id 3193 delete this.element.outlayerGUID; 3194 // remove data for jQuery 3195 if ( jQuery ) { 3196 jQuery.removeData( this.element, this.constructor.namespace ); 3197 } 3198 3199}; 3200 3201// -------------------------- data -------------------------- // 3202 3203/** 3204 * get Outlayer instance from element 3205 * @param {Element} elem 3206 * @returns {Outlayer} 3207 */ 3208Outlayer.data = function( elem ) { 3209 elem = utils.getQueryElement( elem ); 3210 var id = elem && elem.outlayerGUID; 3211 return id && instances[ id ]; 3212}; 3213 3214 3215// -------------------------- create Outlayer class -------------------------- // 3216 3217/** 3218 * create a layout class 3219 * @param {String} namespace 3220 */ 3221Outlayer.create = function( namespace, options ) { 3222 // sub-class Outlayer 3223 function Layout() { 3224 Outlayer.apply( this, arguments ); 3225 } 3226 // inherit Outlayer prototype, use Object.create if there 3227 if ( Object.create ) { 3228 Layout.prototype = Object.create( Outlayer.prototype ); 3229 } else { 3230 utils.extend( Layout.prototype, Outlayer.prototype ); 3231 } 3232 // set contructor, used for namespace and Item 3233 Layout.prototype.constructor = Layout; 3234 3235 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 3236 // apply new options 3237 utils.extend( Layout.defaults, options ); 3238 // keep prototype.settings for backwards compatibility (Packery v1.2.0) 3239 Layout.prototype.settings = {}; 3240 3241 Layout.namespace = namespace; 3242 3243 Layout.data = Outlayer.data; 3244 3245 // sub-class Item 3246 Layout.Item = function LayoutItem() { 3247 Item.apply( this, arguments ); 3248 }; 3249 3250 Layout.Item.prototype = new Item(); 3251 3252 // -------------------------- declarative -------------------------- // 3253 3254 utils.htmlInit( Layout, namespace ); 3255 3256 // -------------------------- jQuery bridge -------------------------- // 3257 3258 // make into jQuery plugin 3259 if ( jQuery && jQuery.bridget ) { 3260 jQuery.bridget( namespace, Layout ); 3261 } 3262 3263 return Layout; 3264}; 3265 3266// ----- fin ----- // 3267 3268// back in global 3269Outlayer.Item = Item; 3270 3271return Outlayer; 3272 3273})); 3274 3275 3276/** 3277 * Isotope Item 3278**/ 3279 3280( function( window, factory ) { 3281'use strict'; 3282 // universal module definition 3283 if ( typeof define == 'function' && define.amd ) { 3284 // AMD 3285 define( 'isotope/js/item',[ 3286 'outlayer/outlayer' 3287 ], 3288 factory ); 3289 } else if ( typeof exports == 'object' ) { 3290 // CommonJS 3291 module.exports = factory( 3292 require('outlayer') 3293 ); 3294 } else { 3295 // browser global 3296 window.Isotope = window.Isotope || {}; 3297 window.Isotope.Item = factory( 3298 window.Outlayer 3299 ); 3300 } 3301 3302}( window, function factory( Outlayer ) { 3303'use strict'; 3304 3305// -------------------------- Item -------------------------- // 3306 3307// sub-class Outlayer Item 3308function Item() { 3309 Outlayer.Item.apply( this, arguments ); 3310} 3311 3312Item.prototype = new Outlayer.Item(); 3313 3314Item.prototype._create = function() { 3315 // assign id, used for original-order sorting 3316 this.id = this.layout.itemGUID++; 3317 Outlayer.Item.prototype._create.call( this ); 3318 this.sortData = {}; 3319}; 3320 3321Item.prototype.updateSortData = function() { 3322 if ( this.isIgnored ) { 3323 return; 3324 } 3325 // default sorters 3326 this.sortData.id = this.id; 3327 // for backward compatibility 3328 this.sortData['original-order'] = this.id; 3329 this.sortData.random = Math.random(); 3330 // go thru getSortData obj and apply the sorters 3331 var getSortData = this.layout.options.getSortData; 3332 var sorters = this.layout._sorters; 3333 for ( var key in getSortData ) { 3334 var sorter = sorters[ key ]; 3335 this.sortData[ key ] = sorter( this.element, this ); 3336 } 3337}; 3338 3339var _destroy = Item.prototype.destroy; 3340Item.prototype.destroy = function() { 3341 // call super 3342 _destroy.apply( this, arguments ); 3343 // reset display, #741 3344 this.css({ 3345 display: '' 3346 }); 3347}; 3348 3349return Item; 3350 3351})); 3352 3353/** 3354 * Isotope LayoutMode 3355 */ 3356 3357( function( window, factory ) { 3358 'use strict'; 3359 // universal module definition 3360 3361 if ( typeof define == 'function' && define.amd ) { 3362 // AMD 3363 define( 'isotope/js/layout-mode',[ 3364 'get-size/get-size', 3365 'outlayer/outlayer' 3366 ], 3367 factory ); 3368 } else if ( typeof exports == 'object' ) { 3369 // CommonJS 3370 module.exports = factory( 3371 require('get-size'), 3372 require('outlayer') 3373 ); 3374 } else { 3375 // browser global 3376 window.Isotope = window.Isotope || {}; 3377 window.Isotope.LayoutMode = factory( 3378 window.getSize, 3379 window.Outlayer 3380 ); 3381 } 3382 3383}( window, function factory( getSize, Outlayer ) { 3384 'use strict'; 3385 3386 // layout mode class 3387 function LayoutMode( isotope ) { 3388 this.isotope = isotope; 3389 // link properties 3390 if ( isotope ) { 3391 this.options = isotope.options[ this.namespace ]; 3392 this.element = isotope.element; 3393 this.items = isotope.filteredItems; 3394 this.size = isotope.size; 3395 } 3396 } 3397
vendor: 4,949 bytes, lines 3398-3591
3398 /** 3399 * some methods should just defer to default Outlayer method 3400 * and reference the Isotope instance as `this` 3401 **/ 3402 ( function() { 3403 var facadeMethods = [ 3404 '_resetLayout', 3405 '_getItemLayoutPosition', 3406 '_manageStamp', 3407 '_getContainerSize', 3408 '_getElementOffset', 3409 'needsResizeLayout' 3410 ]; 3411 3412 for ( var i=0, len = facadeMethods.length; i < len; i++ ) { 3413 var methodName = facadeMethods[i]; 3414 LayoutMode.prototype[ methodName ] = getOutlayerMethod( methodName ); 3415 } 3416 3417 function getOutlayerMethod( methodName ) { 3418 return function() { 3419 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 3420 }; 3421 } 3422 })(); 3423 3424 // ----- ----- // 3425 3426 // for horizontal layout modes, check vertical size 3427 LayoutMode.prototype.needsVerticalResizeLayout = function() { 3428 // don't trigger if size did not change 3429 var size = getSize( this.isotope.element ); 3430 // check that this.size and size are there 3431 // IE8 triggers resize on body size change, so they might not be 3432 var hasSizes = this.isotope.size && size; 3433 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 3434 }; 3435 3436 // ----- measurements ----- // 3437 3438 LayoutMode.prototype._getMeasurement = function() { 3439 this.isotope._getMeasurement.apply( this, arguments ); 3440 }; 3441 3442 LayoutMode.prototype.getColumnWidth = function() { 3443 this.getSegmentSize( 'column', 'Width' ); 3444 }; 3445 3446 LayoutMode.prototype.getRowHeight = function() { 3447 this.getSegmentSize( 'row', 'Height' ); 3448 }; 3449 3450 /** 3451 * get columnWidth or rowHeight 3452 * segment: 'column' or 'row' 3453 * size 'Width' or 'Height' 3454 **/ 3455 LayoutMode.prototype.getSegmentSize = function( segment, size ) { 3456 var segmentName = segment + size; 3457 var outerSize = 'outer' + size; 3458 // columnWidth / outerWidth // rowHeight / outerHeight 3459 this._getMeasurement( segmentName, outerSize ); 3460 // got rowHeight or columnWidth, we can chill 3461 if ( this[ segmentName ] ) { 3462 return; 3463 } 3464 // fall back to item of first element 3465 var firstItemSize = this.getFirstItemSize(); 3466 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 3467 // or size of container 3468 this.isotope.size[ 'inner' + size ]; 3469 }; 3470 3471 LayoutMode.prototype.getFirstItemSize = function() { 3472 var firstItem = this.isotope.filteredItems[0]; 3473 return firstItem && firstItem.element && getSize( firstItem.element ); 3474 }; 3475 3476 // ----- methods that should reference isotope ----- // 3477 3478 LayoutMode.prototype.layout = function() { 3479 this.isotope.layout.apply( this.isotope, arguments ); 3480 }; 3481 3482 LayoutMode.prototype.getSize = function() { 3483 this.isotope.getSize(); 3484 this.size = this.isotope.size; 3485 }; 3486 3487 // -------------------------- create -------------------------- // 3488 3489 LayoutMode.modes = {}; 3490 3491 LayoutMode.create = function( namespace, options ) { 3492 3493 function Mode() { 3494 LayoutMode.apply( this, arguments ); 3495 } 3496 3497 Mode.prototype = new LayoutMode(); 3498 3499 // default options 3500 if ( options ) { 3501 Mode.options = options; 3502 } 3503 3504 Mode.prototype.namespace = namespace; 3505 // register in Isotope 3506 LayoutMode.modes[ namespace ] = Mode; 3507 3508 return Mode; 3509 }; 3510 3511 return LayoutMode; 3512 3513})); 3514 3515/*! 3516 * Masonry v3.3.1 3517 * Cascading grid layout library 3518 * http://masonry.desandro.com 3519 * MIT License 3520 * by David DeSandro 3521 */ 3522 3523( function( window, factory ) { 3524 'use strict'; 3525 // universal module definition 3526 if ( typeof define === 'function' && define.amd ) { 3527 // AMD 3528 define( 'masonry/masonry',[ 3529 'outlayer/outlayer', 3530 'get-size/get-size', 3531 'fizzy-ui-utils/utils' 3532 ], 3533 factory ); 3534 } else if ( typeof exports === 'object' ) { 3535 // CommonJS 3536 module.exports = factory( 3537 require('outlayer'), 3538 require('get-size'), 3539 require('fizzy-ui-utils') 3540 ); 3541 } else { 3542 // browser global 3543 window.Masonry = factory( 3544 window.Outlayer, 3545 window.getSize, 3546 window.fizzyUIUtils 3547 ); 3548 } 3549 3550}( window, function factory( Outlayer, getSize, utils ) { 3551 3552 3553 3554// -------------------------- masonryDefinition -------------------------- // 3555 3556 // create an Outlayer layout class 3557 var Masonry = Outlayer.create('masonry'); 3558 3559 Masonry.prototype._resetLayout = function() { 3560 this.getSize(); 3561 this._getMeasurement( 'columnWidth', 'outerWidth' ); 3562 this._getMeasurement( 'gutter', 'outerWidth' ); 3563 this.measureColumns(); 3564 3565 // reset column Y 3566 var i = this.cols; 3567 this.colYs = []; 3568 while (i--) { 3569 this.colYs.push( 0 ); 3570 } 3571 3572 this.maxY = 0; 3573 }; 3574 3575 Masonry.prototype.measureColumns = function() { 3576 this.getContainerWidth(); 3577 // if columnWidth is 0, default to outerWidth of first item 3578 if ( !this.columnWidth ) { 3579 var firstItem = this.items[0]; 3580 var firstItemElem = firstItem && firstItem.element; 3581 // columnWidth fall back to item of first element 3582 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 3583 // if first elem has no width, default to size of container 3584 this.containerWidth; 3585 } 3586 3587 var columnWidth = this.columnWidth += this.gutter; 3588 3589 // calculate columns 3590 var containerWidth = this.containerWidth + this.gutter; 3591 var cols = containerWidth / columnWidth;
3592 // fix rounding errors, typically with gutters 3593 var excess = columnWidth - containerWidth % columnWidth; 3594 // if overshoot is less than a pixel, round up, otherwise floor it 3595 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 3596 cols = Math[ mathMethod ]( cols ); 3597 this.cols = Math.max( cols, 1 ); 3598 }; 3599 3600 Masonry.prototype.getContainerWidth = function() { 3601 // container is parent if fit width 3602 var container = this.options.isFitWidth ? this.element.parentNode : this.element; 3603 // check that this.size and size are there 3604 // IE8 triggers resize on body size change, so they might not be 3605 var size = getSize( container ); 3606 this.containerWidth = size && size.innerWidth; 3607 }; 3608 3609 Masonry.prototype._getItemLayoutPosition = function( item ) { 3610 item.getSize(); 3611 // how many columns does this brick span 3612 var remainder = item.size.outerWidth % this.columnWidth; 3613 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 3614 // round if off by 1 pixel, otherwise use ceil 3615 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 3616 colSpan = Math.min( colSpan, this.cols ); 3617 3618 var colGroup = this._getColGroup( colSpan ); 3619 // get the minimum Y value from the columns 3620 var minimumY = Math.min.apply( Math, colGroup ); 3621 var shortColIndex = utils.indexOf( colGroup, minimumY ); 3622 3623 // position the brick 3624 var position = { 3625 x: this.columnWidth * shortColIndex, 3626 y: minimumY 3627 }; 3628 3629 // apply setHeight to necessary columns 3630 var setHeight = minimumY + item.size.outerHeight; 3631 var setSpan = this.cols + 1 - colGroup.length; 3632 for ( var i = 0; i < setSpan; i++ ) { 3633 this.colYs[ shortColIndex + i ] = setHeight; 3634 } 3635 3636 return position; 3637 }; 3638 3639 /** 3640 * @param {Number} colSpan - number of columns the element spans 3641 * @returns {Array} colGroup 3642 */ 3643 Masonry.prototype._getColGroup = function( colSpan ) { 3644 if ( colSpan < 2 ) { 3645 // if brick spans only one column, use all the column Ys 3646 return this.colYs; 3647 } 3648 3649 var colGroup = []; 3650 // how many different places could this brick fit horizontally 3651 var groupCount = this.cols + 1 - colSpan; 3652 // for each group potential horizontal position 3653 for ( var i = 0; i < groupCount; i++ ) { 3654 // make an array of colY values for that one group 3655 var groupColYs = this.colYs.slice( i, i + colSpan ); 3656 // and get the max value of the array 3657 colGroup[i] = Math.max.apply( Math, groupColYs ); 3658 } 3659 return colGroup; 3660 }; 3661 3662 Masonry.prototype._manageStamp = function( stamp ) { 3663 var stampSize = getSize( stamp ); 3664 var offset = this._getElementOffset( stamp ); 3665 // get the columns that this stamp affects 3666 var firstX = this.options.isOriginLeft ? offset.left : offset.right; 3667 var lastX = firstX + stampSize.outerWidth; 3668 var firstCol = Math.floor( firstX / this.columnWidth ); 3669 firstCol = Math.max( 0, firstCol ); 3670 var lastCol = Math.floor( lastX / this.columnWidth ); 3671 // lastCol should not go over if multiple of columnWidth #425 3672 lastCol -= lastX % this.columnWidth ? 0 : 1; 3673 lastCol = Math.min( this.cols - 1, lastCol ); 3674 // set colYs to bottom of the stamp 3675 var stampMaxY = ( this.options.isOriginTop ? offset.top : offset.bottom ) + 3676 stampSize.outerHeight; 3677 for ( var i = firstCol; i <= lastCol; i++ ) { 3678 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 3679 } 3680 }; 3681 3682 Masonry.prototype._getContainerSize = function() { 3683 this.maxY = Math.max.apply( Math, this.colYs ); 3684 var size = { 3685 height: this.maxY 3686 }; 3687 3688 if ( this.options.isFitWidth ) { 3689 size.width = this._getContainerFitWidth(); 3690 } 3691 3692 return size; 3693 }; 3694 3695 Masonry.prototype._getContainerFitWidth = function() { 3696 var unusedCols = 0; 3697 // count unused columns 3698 var i = this.cols; 3699 while ( --i ) { 3700 if ( this.colYs[i] !== 0 ) { 3701 break; 3702 } 3703 unusedCols++; 3704 } 3705 // fit container to columns that have been used 3706 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 3707 }; 3708 3709 Masonry.prototype.needsResizeLayout = function() { 3710 var previousWidth = this.containerWidth; 3711 this.getContainerWidth(); 3712 return previousWidth !== this.containerWidth; 3713 }; 3714 3715 return Masonry; 3716 3717})); 3718 3719/*! 3720 * Masonry layout mode 3721 * sub-classes Masonry 3722 * http://masonry.desandro.com 3723 */ 3724 3725( function( window, factory ) { 3726 'use strict'; 3727 // universal module definition 3728 if ( typeof define == 'function' && define.amd ) { 3729 // AMD 3730 define( 'isotope/js/layout-modes/masonry',[ 3731 '../layout-mode', 3732 'masonry/masonry' 3733 ], 3734 factory ); 3735 } else if ( typeof exports == 'object' ) { 3736 // CommonJS 3737 module.exports = factory( 3738 require('../layout-mode'), 3739 require('masonry-layout') 3740 ); 3741 } else { 3742 // browser global 3743 factory( 3744 window.Isotope.LayoutMode, 3745 window.Masonry 3746 ); 3747 } 3748 3749}( window, function factory( LayoutMode, Masonry ) { 3750'use strict'; 3751 3752// -------------------------- helpers -------------------------- // 3753 3754// extend objects 3755function extend( a, b ) { 3756 for ( var prop in b ) { 3757 a[ prop ] = b[ prop ]; 3758 } 3759 return a; 3760} 3761 3762// -------------------------- masonryDefinition -------------------------- // 3763 3764 // create an Outlayer layout class
vendor: 8,024 bytes, lines 3765-4098
3765 var MasonryMode = LayoutMode.create('masonry'); 3766 3767 // save on to these methods 3768 var _getElementOffset = MasonryMode.prototype._getElementOffset; 3769 var layout = MasonryMode.prototype.layout; 3770 var _getMeasurement = MasonryMode.prototype._getMeasurement; 3771 3772 // sub-class Masonry 3773 extend( MasonryMode.prototype, Masonry.prototype ); 3774 3775 // set back, as it was overwritten by Masonry 3776 MasonryMode.prototype._getElementOffset = _getElementOffset; 3777 MasonryMode.prototype.layout = layout; 3778 MasonryMode.prototype._getMeasurement = _getMeasurement; 3779 3780 var measureColumns = MasonryMode.prototype.measureColumns; 3781 MasonryMode.prototype.measureColumns = function() { 3782 // set items, used if measuring first item 3783 this.items = this.isotope.filteredItems; 3784 measureColumns.call( this ); 3785 }; 3786 3787 // HACK copy over isOriginLeft/Top options 3788 var _manageStamp = MasonryMode.prototype._manageStamp; 3789 MasonryMode.prototype._manageStamp = function() { 3790 this.options.isOriginLeft = this.isotope.options.isOriginLeft; 3791 this.options.isOriginTop = this.isotope.options.isOriginTop; 3792 _manageStamp.apply( this, arguments ); 3793 }; 3794 3795 return MasonryMode; 3796 3797})); 3798 3799/** 3800 * fitRows layout mode 3801 */ 3802 3803( function( window, factory ) { 3804 'use strict'; 3805 // universal module definition 3806 if ( typeof define == 'function' && define.amd ) { 3807 // AMD 3808 define( 'isotope/js/layout-modes/fit-rows',[ 3809 '../layout-mode' 3810 ], 3811 factory ); 3812 } else if ( typeof exports == 'object' ) { 3813 // CommonJS 3814 module.exports = factory( 3815 require('../layout-mode') 3816 ); 3817 } else { 3818 // browser global 3819 factory( 3820 window.Isotope.LayoutMode 3821 ); 3822 } 3823 3824}( window, function factory( LayoutMode ) { 3825'use strict'; 3826 3827var FitRows = LayoutMode.create('fitRows'); 3828 3829FitRows.prototype._resetLayout = function() { 3830 this.x = 0; 3831 this.y = 0; 3832 this.maxY = 0; 3833 this._getMeasurement( 'gutter', 'outerWidth' ); 3834}; 3835 3836FitRows.prototype._getItemLayoutPosition = function( item ) { 3837 item.getSize(); 3838 3839 var itemWidth = item.size.outerWidth + this.gutter; 3840 // if this element cannot fit in the current row 3841 var containerWidth = this.isotope.size.innerWidth + this.gutter; 3842 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 3843 this.x = 0; 3844 this.y = this.maxY; 3845 } 3846 3847 var position = { 3848 x: this.x, 3849 y: this.y 3850 }; 3851 3852 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 3853 this.x += itemWidth; 3854 3855 return position; 3856}; 3857 3858FitRows.prototype._getContainerSize = function() { 3859 return { height: this.maxY }; 3860}; 3861 3862return FitRows; 3863 3864})); 3865 3866/** 3867 * vertical layout mode 3868 */ 3869 3870( function( window, factory ) { 3871 'use strict'; 3872 // universal module definition 3873 if ( typeof define == 'function' && define.amd ) { 3874 // AMD 3875 define( 'isotope/js/layout-modes/vertical',[ 3876 '../layout-mode' 3877 ], 3878 factory ); 3879 } else if ( typeof exports == 'object' ) { 3880 // CommonJS 3881 module.exports = factory( 3882 require('../layout-mode') 3883 ); 3884 } else { 3885 // browser global 3886 factory( 3887 window.Isotope.LayoutMode 3888 ); 3889 } 3890 3891}( window, function factory( LayoutMode ) { 3892'use strict'; 3893 3894var Vertical = LayoutMode.create( 'vertical', { 3895 horizontalAlignment: 0 3896}); 3897 3898Vertical.prototype._resetLayout = function() { 3899 this.y = 0; 3900}; 3901 3902Vertical.prototype._getItemLayoutPosition = function( item ) { 3903 item.getSize(); 3904 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 3905 this.options.horizontalAlignment; 3906 var y = this.y; 3907 this.y += item.size.outerHeight; 3908 return { x: x, y: y }; 3909}; 3910 3911Vertical.prototype._getContainerSize = function() { 3912 return { height: this.y }; 3913}; 3914 3915return Vertical; 3916 3917})); 3918 3919/*! 3920 * Isotope v2.2.2 3921 * 3922 * Licensed GPLv3 for open source use 3923 * or Isotope Commercial License for commercial use 3924 * 3925 * http://isotope.metafizzy.co 3926 * Copyright 2015 Metafizzy 3927 */ 3928 3929( function( window, factory ) { 3930 'use strict'; 3931 // universal module definition 3932 3933 if ( typeof define == 'function' && define.amd ) { 3934 // AMD 3935 define( [ 3936 'outlayer/outlayer', 3937 'get-size/get-size', 3938 'matches-selector/matches-selector', 3939 'fizzy-ui-utils/utils', 3940 'isotope/js/item', 3941 'isotope/js/layout-mode', 3942 // include default layout modes 3943 'isotope/js/layout-modes/masonry', 3944 'isotope/js/layout-modes/fit-rows', 3945 'isotope/js/layout-modes/vertical' 3946 ], 3947 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 3948 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 3949 }); 3950 } else if ( typeof exports == 'object' ) { 3951 // CommonJS 3952 module.exports = factory( 3953 window, 3954 require('outlayer'), 3955 require('get-size'), 3956 require('desandro-matches-selector'), 3957 require('fizzy-ui-utils'), 3958 require('./item'), 3959 require('./layout-mode'), 3960 // include default layout modes 3961 require('./layout-modes/masonry'), 3962 require('./layout-modes/fit-rows'), 3963 require('./layout-modes/vertical') 3964 ); 3965 } else { 3966 // browser global 3967 window.Isotope = factory( 3968 window, 3969 window.Outlayer, 3970 window.getSize, 3971 window.matchesSelector, 3972 window.fizzyUIUtils, 3973 window.Isotope.Item, 3974 window.Isotope.LayoutMode 3975 ); 3976 } 3977 3978}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 3979 Item, LayoutMode ) { 3980 3981 3982 3983// -------------------------- vars -------------------------- // 3984 3985var jQuery = window.jQuery; 3986 3987// -------------------------- helpers -------------------------- // 3988 3989var trim = String.prototype.trim ? 3990 function( str ) { 3991 return str.trim(); 3992 } : 3993 function( str ) { 3994 return str.replace( /^\s+|\s+$/g, '' ); 3995 }; 3996 3997var docElem = document.documentElement; 3998 3999var getText = docElem.textContent ? 4000 function( elem ) { 4001 return elem.textContent; 4002 } : 4003 function( elem ) { 4004 return elem.innerText; 4005 }; 4006 4007// -------------------------- isotopeDefinition -------------------------- // 4008 4009 // create an Outlayer layout class 4010 var Isotope = Outlayer.create( 'isotope', { 4011 layoutMode: "masonry", 4012 isJQueryFiltering: true, 4013 sortAscending: true 4014 }); 4015 4016 Isotope.Item = Item; 4017 Isotope.LayoutMode = LayoutMode; 4018 4019 Isotope.prototype._create = function() { 4020 this.itemGUID = 0; 4021 // functions that sort items 4022 this._sorters = {}; 4023 this._getSorters(); 4024 // call super 4025 Outlayer.prototype._create.call( this ); 4026 4027 // create layout modes 4028 this.modes = {}; 4029 // start filteredItems with all items 4030 this.filteredItems = this.items; 4031 // keep of track of sortBys 4032 this.sortHistory = [ 'original-order' ]; 4033 // create from registered layout modes 4034 for ( var name in LayoutMode.modes ) { 4035 this._initLayoutMode( name ); 4036 } 4037 }; 4038 4039 Isotope.prototype.reloadItems = function() { 4040 // reset item ID counter 4041 this.itemGUID = 0; 4042 // call super 4043 Outlayer.prototype.reloadItems.call( this ); 4044 }; 4045 4046 Isotope.prototype._itemize = function() { 4047 var items = Outlayer.prototype._itemize.apply( this, arguments ); 4048 // assign ID for original-order 4049 for ( var i=0, len = items.length; i < len; i++ ) { 4050 var item = items[i]; 4051 item.id = this.itemGUID++; 4052 } 4053 this._updateItemsSortData( items ); 4054 return items; 4055 }; 4056 4057 4058 // -------------------------- layout -------------------------- // 4059 4060 Isotope.prototype._initLayoutMode = function( name ) { 4061 var Mode = LayoutMode.modes[ name ]; 4062 // set mode options 4063 // HACK extend initial options, back-fill in default options 4064 var initialOpts = this.options[ name ] || {}; 4065 this.options[ name ] = Mode.options ? 4066 utils.extend( Mode.options, initialOpts ) : initialOpts; 4067 // init layout mode instance 4068 this.modes[ name ] = new Mode( this ); 4069 }; 4070 4071 4072 Isotope.prototype.layout = function() { 4073 // if first time doing layout, do all magic 4074 if ( !this._isLayoutInited && this.options.isInitLayout ) { 4075 this.arrange(); 4076 return; 4077 } 4078 this._layout(); 4079 }; 4080 4081 // private method to be used in layout() & magic() 4082 Isotope.prototype._layout = function() { 4083 // don't animate first layout 4084 var isInstant = this._getIsInstant(); 4085 // layout flow 4086 this._resetLayout(); 4087 this._manageStamps(); 4088 this.layoutItems( this.filteredItems, isInstant ); 4089 4090 // flag for initalized 4091 this._isLayoutInited = true; 4092 }; 4093 4094 // filter + sort + layout 4095 Isotope.prototype.arrange = function( opts ) { 4096 // set any options pass 4097 this.option( opts ); 4098 this._getIsInstant();
4099 // filter, sort, and layout 4100 4101 // filter 4102 var filtered = this._filter( this.items ); 4103 this.filteredItems = filtered.matches; 4104 4105 var _this = this; 4106 function hideReveal() { 4107 _this.reveal( filtered.needReveal ); 4108 _this.hide( filtered.needHide ); 4109 } 4110 4111 this._bindArrangeComplete(); 4112 4113 if ( this._isInstant ) { 4114 this._noTransition( hideReveal ); 4115 } else { 4116 hideReveal(); 4117 } 4118 4119 this._sort(); 4120 this._layout(); 4121 }; 4122 // alias to _init for main plugin method 4123 Isotope.prototype._init = Isotope.prototype.arrange; 4124 4125 // HACK 4126 // Don't animate/transition first layout 4127 // Or don't animate/transition other layouts 4128 Isotope.prototype._getIsInstant = function() { 4129 var isInstant = this.options.isLayoutInstant !== undefined ? 4130 this.options.isLayoutInstant : !this._isLayoutInited; 4131 this._isInstant = isInstant; 4132 return isInstant; 4133 }; 4134 4135 // listen for layoutComplete, hideComplete and revealComplete 4136 // to trigger arrangeComplete 4137 Isotope.prototype._bindArrangeComplete = function() { 4138 // listen for 3 events to trigger arrangeComplete 4139 var isLayoutComplete, isHideComplete, isRevealComplete; 4140 var _this = this; 4141 function arrangeParallelCallback() { 4142 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 4143 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 4144 } 4145 } 4146 this.once( 'layoutComplete', function() { 4147 isLayoutComplete = true; 4148 arrangeParallelCallback(); 4149 }); 4150 this.once( 'hideComplete', function() { 4151 isHideComplete = true; 4152 arrangeParallelCallback(); 4153 }); 4154 this.once( 'revealComplete', function() { 4155 isRevealComplete = true; 4156 arrangeParallelCallback(); 4157 }); 4158 }; 4159 4160 // -------------------------- filter -------------------------- // 4161 4162 Isotope.prototype._filter = function( items ) { 4163 var filter = this.options.filter; 4164 filter = filter || '*'; 4165 var matches = []; 4166 var hiddenMatched = []; 4167 var visibleUnmatched = []; 4168 4169 var test = this._getFilterTest( filter ); 4170 4171 // test each item 4172 for ( var i=0, len = items.length; i < len; i++ ) { 4173 var item = items[i]; 4174 if ( item.isIgnored ) { 4175 continue; 4176 } 4177 // add item to either matched or unmatched group 4178 var isMatched = test( item ); 4179 // item.isFilterMatched = isMatched; 4180 // add to matches if its a match 4181 if ( isMatched ) { 4182 matches.push( item ); 4183 } 4184 // add to additional group if item needs to be hidden or revealed 4185 if ( isMatched && item.isHidden ) { 4186 hiddenMatched.push( item ); 4187 } else if ( !isMatched && !item.isHidden ) { 4188 visibleUnmatched.push( item ); 4189 } 4190 } 4191 4192 // return collections of items to be manipulated 4193 return { 4194 matches: matches, 4195 needReveal: hiddenMatched, 4196 needHide: visibleUnmatched 4197 }; 4198 }; 4199 4200 // get a jQuery, function, or a matchesSelector test given the filter 4201 Isotope.prototype._getFilterTest = function( filter ) { 4202 if ( jQuery && this.options.isJQueryFiltering ) { 4203 // use jQuery 4204 return function( item ) { 4205 return jQuery( item.element ).is( filter ); 4206 }; 4207 } 4208 if ( typeof filter == 'function' ) { 4209 // use filter as function 4210 return function( item ) { 4211 return filter( item.element ); 4212 }; 4213 } 4214 // default, use filter as selector string 4215 return function( item ) { 4216 return matchesSelector( item.element, filter ); 4217 }; 4218 }; 4219 4220 // -------------------------- sorting -------------------------- // 4221 4222 /** 4223 * @params {Array} elems 4224 * @public 4225 */ 4226 Isotope.prototype.updateSortData = function( elems ) { 4227 // get items 4228 var items; 4229 if ( elems ) { 4230 elems = utils.makeArray( elems ); 4231 items = this.getItems( elems ); 4232 } else { 4233 // update all items if no elems provided 4234 items = this.items; 4235 } 4236 4237 this._getSorters(); 4238 this._updateItemsSortData( items ); 4239 }; 4240 4241 Isotope.prototype._getSorters = function() { 4242 var getSortData = this.options.getSortData; 4243 for ( var key in getSortData ) { 4244 var sorter = getSortData[ key ]; 4245 this._sorters[ key ] = mungeSorter( sorter ); 4246 } 4247 }; 4248 4249 /** 4250 * @params {Array} items - of Isotope.Items 4251 * @private 4252 */ 4253 Isotope.prototype._updateItemsSortData = function( items ) { 4254 // do not update if no items 4255 var len = items && items.length; 4256 4257 for ( var i=0; len && i < len; i++ ) { 4258 var item = items[i]; 4259 item.updateSortData(); 4260 } 4261 }; 4262 4263 // ----- munge sorter ----- // 4264 4265 // encapsulate this, as we just need mungeSorter 4266 // other functions in here are just for munging 4267 var mungeSorter = ( function() { 4268 // add a magic layer to sorters for convienent shorthands 4269 // `.foo-bar` will use the text of .foo-bar querySelector 4270 // `[foo-bar]` will use attribute 4271 // you can also add parser 4272 // `.foo-bar parseInt` will parse that as a number 4273 function mungeSorter( sorter ) { 4274 // if not a string, return function or whatever it is 4275 if ( typeof sorter != 'string' ) { 4276 return sorter; 4277 } 4278 // parse the sorter string 4279 var args = trim( sorter ).split(' '); 4280 var query = args[0]; 4281 // check if query looks like [an-attribute] 4282 var attrMatch = query.match( /^\[(.+)\]$/ ); 4283 var attr = attrMatch && attrMatch[1]; 4284 var getValue = getValueGetter( attr, query ); 4285 // use second argument as a parser 4286 var parser = Isotope.sortDataParsers[ args[1] ]; 4287 // parse the value, if there was a parser 4288 sorter = parser ? function( elem ) { 4289 return elem && parser( getValue( elem ) ); 4290 } : 4291 // otherwise just return value 4292 function( elem ) { 4293 return elem && getValue( elem ); 4294 }; 4295 4296 return sorter; 4297 } 4298 4299 // get an attribute getter, or get text of the querySelector 4300 function getValueGetter( attr, query ) { 4301 var getValue; 4302 // if query looks like [foo-bar], get attribute 4303 if ( attr ) { 4304 getValue = function( elem ) { 4305 return elem.getAttribute( attr ); 4306 }; 4307 } else { 4308 // otherwise, assume its a querySelector, and get its text 4309 getValue = function( elem ) { 4310 var child = elem.querySelector( query ); 4311 return child && getText( child ); 4312 }; 4313 } 4314 return getValue; 4315 } 4316 4317 return mungeSorter; 4318 })(); 4319 4320 // parsers used in getSortData shortcut strings 4321 Isotope.sortDataParsers = { 4322 'parseInt': function( val ) { 4323 return parseInt( val, 10 ); 4324 }, 4325 'parseFloat': function( val ) { 4326 return parseFloat( val ); 4327 } 4328 }; 4329 4330 // ----- sort method ----- // 4331 4332 // sort filteredItem order 4333 Isotope.prototype._sort = function() { 4334 var sortByOpt = this.options.sortBy; 4335 if ( !sortByOpt ) { 4336 return; 4337 } 4338 // concat all sortBy and sortHistory 4339 var sortBys = [].concat.apply( sortByOpt, this.sortHistory ); 4340 // sort magic 4341 var itemSorter = getItemSorter( sortBys, this.options.sortAscending ); 4342 this.filteredItems.sort( itemSorter ); 4343 // keep track of sortBy History 4344 if ( sortByOpt != this.sortHistory[0] ) { 4345 // add to front, oldest goes in last 4346 this.sortHistory.unshift( sortByOpt ); 4347 } 4348 }; 4349 4350 // returns a function used for sorting 4351 function getItemSorter( sortBys, sortAsc ) { 4352 return function sorter( itemA, itemB ) { 4353 // cycle through all sortKeys 4354 for ( var i = 0, len = sortBys.length; i < len; i++ ) { 4355 var sortBy = sortBys[i]; 4356 var a = itemA.sortData[ sortBy ]; 4357 var b = itemB.sortData[ sortBy ]; 4358 if ( a > b || a < b ) { 4359 // if sortAsc is an object, use the value given the sortBy key
4360 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 4361 var direction = isAscending ? 1 : -1; 4362 return ( a > b ? 1 : -1 ) * direction; 4363 } 4364 } 4365 return 0; 4366 }; 4367 } 4368 4369 // -------------------------- methods -------------------------- // 4370 4371 // get layout mode 4372 Isotope.prototype._mode = function() { 4373 var layoutMode = this.options.layoutMode; 4374 var mode = this.modes[ layoutMode ]; 4375 if ( !mode ) { 4376 // TODO console.error 4377 throw new Error( 'No layout mode: ' + layoutMode ); 4378 } 4379 // HACK sync mode's options 4380 // any options set after init for layout mode need to be synced 4381 mode.options = this.options[ layoutMode ]; 4382 return mode; 4383 }; 4384 4385 Isotope.prototype._resetLayout = function() { 4386 // trigger original reset layout 4387 Outlayer.prototype._resetLayout.call( this ); 4388 this._mode()._resetLayout(); 4389 }; 4390 4391 Isotope.prototype._getItemLayoutPosition = function( item ) { 4392 return this._mode()._getItemLayoutPosition( item ); 4393 }; 4394 4395 Isotope.prototype._manageStamp = function( stamp ) { 4396 this._mode()._manageStamp( stamp ); 4397 }; 4398 4399 Isotope.prototype._getContainerSize = function() { 4400 return this._mode()._getContainerSize(); 4401 }; 4402 4403 Isotope.prototype.needsResizeLayout = function() { 4404 return this._mode().needsResizeLayout(); 4405 }; 4406 4407 // -------------------------- adding & removing -------------------------- // 4408 4409 // HEADS UP overwrites default Outlayer appended 4410 Isotope.prototype.appended = function( elems ) { 4411 var items = this.addItems( elems ); 4412 if ( !items.length ) { 4413 return; 4414 } 4415 // filter, layout, reveal new items 4416 var filteredItems = this._filterRevealAdded( items ); 4417 // add to filteredItems 4418 this.filteredItems = this.filteredItems.concat( filteredItems ); 4419 }; 4420 4421 // HEADS UP overwrites default Outlayer prepended 4422 Isotope.prototype.prepended = function( elems ) { 4423 var items = this._itemize( elems ); 4424 if ( !items.length ) { 4425 return; 4426 } 4427 // start new layout 4428 this._resetLayout(); 4429 this._manageStamps(); 4430 // filter, layout, reveal new items 4431 var filteredItems = this._filterRevealAdded( items ); 4432 // layout previous items 4433 this.layoutItems( this.filteredItems ); 4434 // add to items and filteredItems 4435 this.filteredItems = filteredItems.concat( this.filteredItems ); 4436 this.items = items.concat( this.items ); 4437 }; 4438 4439 Isotope.prototype._filterRevealAdded = function( items ) { 4440 var filtered = this._filter( items ); 4441 this.hide( filtered.needHide ); 4442 // reveal all new items 4443 this.reveal( filtered.matches ); 4444 // layout new items, no transition 4445 this.layoutItems( filtered.matches, true ); 4446 return filtered.matches; 4447 }; 4448 4449 /** 4450 * Filter, sort, and layout newly-appended item elements 4451 * @param {Array or NodeList or Element} elems 4452 */ 4453 Isotope.prototype.insert = function( elems ) { 4454 var items = this.addItems( elems ); 4455 if ( !items.length ) { 4456 return; 4457 } 4458 // append item elements 4459 var i, item; 4460 var len = items.length; 4461 for ( i=0; i < len; i++ ) { 4462 item = items[i]; 4463 this.element.appendChild( item.element ); 4464 } 4465 // filter new stuff 4466 var filteredInsertItems = this._filter( items ).matches; 4467 // set flag 4468 for ( i=0; i < len; i++ ) { 4469 items[i].isLayoutInstant = true; 4470 } 4471 this.arrange(); 4472 // reset flag 4473 for ( i=0; i < len; i++ ) { 4474 delete items[i].isLayoutInstant; 4475 } 4476 this.reveal( filteredInsertItems ); 4477 }; 4478 4479 var _remove = Isotope.prototype.remove; 4480 Isotope.prototype.remove = function( elems ) { 4481 elems = utils.makeArray( elems ); 4482 var removeItems = this.getItems( elems ); 4483 // do regular thing 4484 _remove.call( this, elems ); 4485 // bail if no items to remove 4486 var len = removeItems && removeItems.length; 4487 if ( !len ) { 4488 return; 4489 } 4490 // remove elems from filteredItems 4491 for ( var i=0; i < len; i++ ) { 4492 var item = removeItems[i]; 4493 // remove item from collection 4494 utils.removeFrom( this.filteredItems, item ); 4495 } 4496 }; 4497 4498 Isotope.prototype.shuffle = function() { 4499 // update random sortData 4500 for ( var i=0, len = this.items.length; i < len; i++ ) { 4501 var item = this.items[i]; 4502 item.sortData.random = Math.random(); 4503 } 4504 this.options.sortBy = 'random'; 4505 this._sort(); 4506 this._layout(); 4507 }; 4508 4509 /** 4510 * trigger fn without transition 4511 * kind of hacky to have this in the first place 4512 * @param {Function} fn 4513 * @returns ret 4514 * @private 4515 */ 4516 Isotope.prototype._noTransition = function( fn ) { 4517 // save transitionDuration before disabling 4518 var transitionDuration = this.options.transitionDuration; 4519 // disable transition 4520 this.options.transitionDuration = 0; 4521 // do it 4522 var returnValue = fn.call( this ); 4523 // re-enable transition for reveal 4524 this.options.transitionDuration = transitionDuration; 4525 return returnValue; 4526 }; 4527 4528 // ----- helper methods ----- // 4529 4530 /** 4531 * getter method for getting filtered item elements 4532 * @returns {Array} elems - collection of item elements 4533 */ 4534 Isotope.prototype.getFilteredItemElements = function() { 4535 var elems = []; 4536 for ( var i=0, len = this.filteredItems.length; i < len; i++ ) { 4537 elems.push( this.filteredItems[i].element ); 4538 } 4539 return elems; 4540 }; 4541 4542 // ----- ----- // 4543 4544 return Isotope; 4545 4546})); 4547 4548 4549/*! 4550 * Packery layout mode PACKAGED v2.0.1 4551 * sub-classes Packery 4552 */ 4553 4554!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);
4554e?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")}
4554,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};
4554this.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}); 4555 4556/*! 4557 * cellsByRows layout mode for Isotope 4558 * v1.1.3 4559 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 4560 */ 4561 4562/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 4563 4564( function( window, factory ) { 4565 // universal module definition 4566 /* jshint strict: false */ /*globals define, module, require */ 4567 if ( typeof define === 'function' && define.amd ) { 4568 // AMD 4569 define( [ 4570 'isotope/js/layout-mode' 4571 ], 4572 factory ); 4573 } else if ( typeof exports === 'object' ) { 4574 // CommonJS 4575 module.exports = factory( 4576 require('isotope-layout/js/layout-mode') 4577 ); 4578 } else { 4579 // browser global 4580 factory( 4581 window.Isotope.LayoutMode 4582 ); 4583 } 4584 4585}( window, function factory( LayoutMode ) { 4586 'use strict'; 4587 4588 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 4589 var proto = CellsByRow.prototype; 4590 4591 proto._resetLayout = function() { 4592 // reset properties 4593 this.itemIndex = 0; 4594 // measurements 4595 this.getColumnWidth(); 4596 this.getRowHeight(); 4597 // set cols 4598 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 4599 this.cols = Math.max( this.cols, 1 ); 4600 }; 4601 4602 proto._getItemLayoutPosition = function( item ) { 4603 item.getSize(); 4604 var col = this.itemIndex % this.cols; 4605 var row = Math.floor( this.itemIndex / this.cols ); 4606 // center item within cell 4607 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 4608 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 4609 this.itemIndex++; 4610 return { x: x, y: y }; 4611 }; 4612 4613 proto._getContainerSize = function() { 4614 return {
4615 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 4616 }; 4617 }; 4618 4619 return CellsByRow; 4620 4621})); 4622 4623/*! 4624 -------------------------------- 4625 Infinite Scroll 4626 -------------------------------- 4627 + https://github.com/paulirish/infinite-scroll 4628 + version 2.1.0 4629 + Copyright 2011/12 Paul Irish & Luke Shumard 4630 + Licensed under the MIT license 4631 4632 + Documentation: http://infinite-scroll.com/ 4633*/ 4634;(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
4634ohVeDeCfXkcCQqDVQcQhn+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
4634iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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
4634ing"){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;
4634r.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";
4634switch(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"])}}); 4635 4636/*!
4637Waypoints - 4.0.1 4638Copyright © 2011-2016 Caleb Troughton 4639Licensed under the MIT license. 4640https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 4641*/ 4642(function() { 4643 'use strict' 4644 4645 var keyCounter = 0 4646 var allWaypoints = {} 4647 4648 /* http://imakewebthings.com/waypoints/api/waypoint */ 4649 function Waypoint(options) { 4650 if (!options) { 4651 throw new Error('No options passed to Waypoint constructor') 4652 } 4653 if (!options.element) { 4654 throw new Error('No element option passed to Waypoint constructor') 4655 } 4656 if (!options.handler) { 4657 throw new Error('No handler option passed to Waypoint constructor') 4658 } 4659 4660 this.key = 'waypoint-' + keyCounter 4661 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 4662 this.element = this.options.element 4663 this.adapter = new Waypoint.Adapter(this.element) 4664 this.callback = options.handler 4665 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 4666 this.enabled = this.options.enabled 4667 this.triggerPoint = null 4668 this.group = Waypoint.Group.findOrCreate({ 4669 name: this.options.group, 4670 axis: this.axis 4671 }) 4672 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 4673 4674 if (Waypoint.offsetAliases[this.options.offset]) { 4675 this.options.offset = Waypoint.offsetAliases[this.options.offset] 4676 } 4677 this.group.add(this) 4678 this.context.add(this) 4679 allWaypoints[this.key] = this 4680 keyCounter += 1 4681 } 4682 4683 /* Private */ 4684 Waypoint.prototype.queueTrigger = function(direction) { 4685 this.group.queueTrigger(this, direction) 4686 } 4687 4688 /* Private */ 4689 Waypoint.prototype.trigger = function(args) { 4690 if (!this.enabled) { 4691 return 4692 } 4693 if (this.callback) { 4694 this.callback.apply(this, args) 4695 } 4696 } 4697 4698 /* Public */ 4699 /* http://imakewebthings.com/waypoints/api/destroy */ 4700 Waypoint.prototype.destroy = function() { 4701 this.context.remove(this) 4702 this.group.remove(this) 4703 delete allWaypoints[this.key] 4704 } 4705 4706 /* Public */ 4707 /* http://imakewebthings.com/waypoints/api/disable */ 4708 Waypoint.prototype.disable = function() { 4709 this.enabled = false 4710 return this 4711 } 4712 4713 /* Public */ 4714 /* http://imakewebthings.com/waypoints/api/enable */ 4715 Waypoint.prototype.enable = function() { 4716 this.context.refresh() 4717 this.enabled = true 4718 return this 4719 } 4720 4721 /* Public */ 4722 /* http://imakewebthings.com/waypoints/api/next */ 4723 Waypoint.prototype.next = function() { 4724 return this.group.next(this) 4725 } 4726 4727 /* Public */ 4728 /* http://imakewebthings.com/waypoints/api/previous */ 4729 Waypoint.prototype.previous = function() { 4730 return this.group.previous(this) 4731 } 4732 4733 /* Private */ 4734 Waypoint.invokeAll = function(method) { 4735 var allWaypointsArray = []
4736 for (var waypointKey in allWaypoints) { 4737 allWaypointsArray.push(allWaypoints[waypointKey]) 4738 } 4739 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 4740 allWaypointsArray[i][method]() 4741 } 4742 } 4743 4744 /* Public */ 4745 /* http://imakewebthings.com/waypoints/api/destroy-all */ 4746 Waypoint.destroyAll = function() { 4747 Waypoint.invokeAll('destroy') 4748 } 4749 4750 /* Public */ 4751 /* http://imakewebthings.com/waypoints/api/disable-all */ 4752 Waypoint.disableAll = function() { 4753 Waypoint.invokeAll('disable') 4754 } 4755 4756 /* Public */ 4757 /* http://imakewebthings.com/waypoints/api/enable-all */ 4758 Waypoint.enableAll = function() { 4759 Waypoint.Context.refreshAll() 4760 for (var waypointKey in allWaypoints) { 4761 allWaypoints[waypointKey].enabled = true 4762 } 4763 return this 4764 } 4765 4766 /* Public */ 4767 /* http://imakewebthings.com/waypoints/api/refresh-all */ 4768 Waypoint.refreshAll = function() { 4769 Waypoint.Context.refreshAll() 4770 } 4771 4772 /* Public */ 4773 /* http://imakewebthings.com/waypoints/api/viewport-height */ 4774 Waypoint.viewportHeight = function() { 4775 return window.innerHeight || document.documentElement.clientHeight 4776 } 4777 4778 /* Public */ 4779 /* http://imakewebthings.com/waypoints/api/viewport-width */ 4780 Waypoint.viewportWidth = function() { 4781 return document.documentElement.clientWidth 4782 } 4783 4784 Waypoint.adapters = [] 4785 4786 Waypoint.defaults = { 4787 context: window, 4788 continuous: true, 4789 enabled: true, 4790 group: 'default', 4791 horizontal: false, 4792 offset: 0 4793 } 4794 4795 Waypoint.offsetAliases = { 4796 'bottom-in-view': function() { 4797 return this.context.innerHeight() - this.adapter.outerHeight() 4798 }, 4799 'right-in-view': function() { 4800 return this.context.innerWidth() - this.adapter.outerWidth() 4801 } 4802 } 4803 4804 window.Waypoint = Waypoint 4805}()) 4806;(function() { 4807 'use strict' 4808 4809 function requestAnimationFrameShim(callback) { 4810 window.setTimeout(callback, 1000 / 60) 4811 } 4812 4813 var keyCounter = 0 4814 var contexts = {} 4815 var Waypoint = window.Waypoint 4816 var oldWindowLoad = window.onload 4817 4818 /* http://imakewebthings.com/waypoints/api/context */ 4819 function Context(element) { 4820 this.element = element 4821 this.Adapter = Waypoint.Adapter 4822 this.adapter = new this.Adapter(element) 4823 this.key = 'waypoint-context-' + keyCounter 4824 this.didScroll = false 4825 this.didResize = false 4826 this.oldScroll = { 4827 x: this.adapter.scrollLeft(), 4828 y: this.adapter.scrollTop() 4829 } 4830 this.waypoints = { 4831 vertical: {}, 4832 horizontal: {} 4833 } 4834 4835 element.waypointContextKey = this.key 4836 contexts[element.waypointContextKey] = this 4837 keyCounter += 1 4838 if (!Waypoint.windowContext) { 4839 Waypoint.windowContext = true 4840 Waypoint.windowContext = new Context(window) 4841 } 4842 4843 this.createThrottledScrollHandler() 4844 this.createThrottledResizeHandler() 4845 } 4846 4847 /* Private */ 4848 Context.prototype.add = function(waypoint) { 4849 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 4850 this.waypoints[axis][waypoint.key] = waypoint 4851 this.refresh() 4852 } 4853 4854 /* Private */ 4855 Context.prototype.checkEmpty = function() { 4856 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 4857 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 4858 var isWindow = this.element == this.element.window 4859 if (horizontalEmpty && verticalEmpty && !isWindow) { 4860 this.adapter.off('.waypoints') 4861 delete contexts[this.key] 4862 } 4863 } 4864 4865 /* Private */ 4866 Context.prototype.createThrottledResizeHandler = function() { 4867 var self = this 4868 4869 function resizeHandler() { 4870 self.handleResize() 4871 self.didResize = false 4872 } 4873 4874 this.adapter.on('resize.waypoints', function() { 4875 if (!self.didResize) { 4876 self.didResize = true 4877 Waypoint.requestAnimationFrame(resizeHandler) 4878 } 4879 }) 4880 } 4881 4882 /* Private */ 4883 Context.prototype.createThrottledScrollHandler = function() { 4884 var self = this 4885 function scrollHandler() { 4886 self.handleScroll() 4887 self.didScroll = false 4888 } 4889 4890 this.adapter.on('scroll.waypoints', function() { 4891 if (!self.didScroll || Waypoint.isTouch) { 4892 self.didScroll = true 4893 Waypoint.requestAnimationFrame(scrollHandler) 4894 } 4895 }) 4896 } 4897 4898 /* Private */ 4899 Context.prototype.handleResize = function() { 4900 Waypoint.Context.refreshAll() 4901 } 4902 4903 /* Private */ 4904 Context.prototype.handleScroll = function() { 4905 var triggeredGroups = {} 4906 var axes = { 4907 horizontal: { 4908 newScroll: this.adapter.scrollLeft(), 4909 oldScroll: this.oldScroll.x, 4910 forward: 'right', 4911 backward: 'left' 4912 }, 4913 vertical: { 4914 newScroll: this.adapter.scrollTop(), 4915 oldScroll: this.oldScroll.y, 4916 forward: 'down', 4917 backward: 'up' 4918 } 4919 } 4920 4921 for (var axisKey in axes) { 4922 var axis = axes[axisKey] 4923 var isForward = axis.newScroll > axis.oldScroll 4924 var direction = isForward ? axis.forward : axis.backward 4925
4926 for (var waypointKey in this.waypoints[axisKey]) { 4927 var waypoint = this.waypoints[axisKey][waypointKey] 4928 if (waypoint.triggerPoint === null) { 4929 continue 4930 } 4931 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 4932 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 4933 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 4934 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 4935 if (crossedForward || crossedBackward) { 4936 waypoint.queueTrigger(direction) 4937 triggeredGroups[waypoint.group.id] = waypoint.group 4938 } 4939 } 4940 } 4941 4942 for (var groupKey in triggeredGroups) { 4943 triggeredGroups[groupKey].flushTriggers() 4944 } 4945 4946 this.oldScroll = { 4947 x: axes.horizontal.newScroll, 4948 y: axes.vertical.newScroll 4949 } 4950 } 4951 4952 /* Private */ 4953 Context.prototype.innerHeight = function() { 4954 /*eslint-disable eqeqeq */ 4955 if (this.element == this.element.window) { 4956 return Waypoint.viewportHeight() 4957 } 4958 /*eslint-enable eqeqeq */ 4959 return this.adapter.innerHeight() 4960 } 4961 4962 /* Private */ 4963 Context.prototype.remove = function(waypoint) { 4964 delete this.waypoints[waypoint.axis][waypoint.key] 4965 this.checkEmpty() 4966 } 4967 4968 /* Private */ 4969 Context.prototype.innerWidth = function() { 4970 /*eslint-disable eqeqeq */ 4971 if (this.element == this.element.window) { 4972 return Waypoint.viewportWidth() 4973 } 4974 /*eslint-enable eqeqeq */ 4975 return this.adapter.innerWidth() 4976 } 4977 4978 /* Public */ 4979 /* http://imakewebthings.com/waypoints/api/context-destroy */ 4980 Context.prototype.destroy = function() { 4981 var allWaypoints = [] 4982 for (var axis in this.waypoints) {
4983 for (var waypointKey in this.waypoints[axis]) { 4984 allWaypoints.push(this.waypoints[axis][waypointKey]) 4985 } 4986 } 4987 for (var i = 0, end = allWaypoints.length; i < end; i++) { 4988 allWaypoints[i].destroy() 4989 } 4990 } 4991 4992 /* Public */ 4993 /* http://imakewebthings.com/waypoints/api/context-refresh */ 4994 Context.prototype.refresh = function() { 4995 /*eslint-disable eqeqeq */ 4996 var isWindow = this.element == this.element.window 4997 /*eslint-enable eqeqeq */ 4998 var contextOffset = isWindow ? undefined : this.adapter.offset() 4999 var triggeredGroups = {} 5000 var axes 5001 5002 this.handleScroll() 5003 axes = { 5004 horizontal: { 5005 contextOffset: isWindow ? 0 : contextOffset.left, 5006 contextScroll: isWindow ? 0 : this.oldScroll.x, 5007 contextDimension: this.innerWidth(), 5008 oldScroll: this.oldScroll.x, 5009 forward: 'right', 5010 backward: 'left', 5011 offsetProp: 'left' 5012 }, 5013 vertical: { 5014 contextOffset: isWindow ? 0 : contextOffset.top, 5015 contextScroll: isWindow ? 0 : this.oldScroll.y, 5016 contextDimension: this.innerHeight(), 5017 oldScroll: this.oldScroll.y, 5018 forward: 'down', 5019 backward: 'up', 5020 offsetProp: 'top' 5021 } 5022 } 5023 5024 for (var axisKey in axes) { 5025 var axis = axes[axisKey]
5026 for (var waypointKey in this.waypoints[axisKey]) { 5027 var waypoint = this.waypoints[axisKey][waypointKey] 5028 var adjustment = waypoint.options.offset 5029 var oldTriggerPoint = waypoint.triggerPoint 5030 var elementOffset = 0 5031 var freshWaypoint = oldTriggerPoint == null 5032 var contextModifier, wasBeforeScroll, nowAfterScroll 5033 var triggeredBackward, triggeredForward 5034 5035 if (waypoint.element !== waypoint.element.window) { 5036 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 5037 } 5038 5039 if (typeof adjustment === 'function') { 5040 adjustment = adjustment.apply(waypoint) 5041 } 5042 else if (typeof adjustment === 'string') { 5043 adjustment = parseFloat(adjustment) 5044 if (waypoint.options.offset.indexOf('%') > - 1) { 5045 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 5046 } 5047 } 5048 5049 contextModifier = axis.contextScroll - axis.contextOffset 5050 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 5051 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 5052 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 5053 triggeredBackward = wasBeforeScroll && nowAfterScroll 5054 triggeredForward = !wasBeforeScroll && !nowAfterScroll 5055 5056 if (!freshWaypoint && triggeredBackward) { 5057 waypoint.queueTrigger(axis.backward) 5058 triggeredGroups[waypoint.group.id] = waypoint.group 5059 } 5060 else if (!freshWaypoint && triggeredForward) { 5061 waypoint.queueTrigger(axis.forward) 5062 triggeredGroups[waypoint.group.id] = waypoint.group 5063 } 5064 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 5065 waypoint.queueTrigger(axis.forward) 5066 triggeredGroups[waypoint.group.id] = waypoint.group 5067 } 5068 } 5069 } 5070 5071 Waypoint.requestAnimationFrame(function() { 5072 for (var groupKey in triggeredGroups) { 5073 triggeredGroups[groupKey].flushTriggers() 5074 } 5075 }) 5076 5077 return this 5078 } 5079 5080 /* Private */ 5081 Context.findOrCreateByElement = function(element) { 5082 return Context.findByElement(element) || new Context(element) 5083 } 5084 5085 /* Private */ 5086 Context.refreshAll = function() { 5087 for (var contextId in contexts) { 5088 contexts[contextId].refresh() 5089 } 5090 } 5091 5092 /* Public */ 5093 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 5094 Context.findByElement = function(element) { 5095 return contexts[element.waypointContextKey] 5096 } 5097 5098 window.onload = function() { 5099 if (oldWindowLoad) { 5100 oldWindowLoad() 5101 } 5102 Context.refreshAll() 5103 } 5104 5105 5106 Waypoint.requestAnimationFrame = function(callback) { 5107 var requestFn = window.requestAnimationFrame || 5108 window.mozRequestAnimationFrame || 5109 window.webkitRequestAnimationFrame || 5110 requestAnimationFrameShim 5111 requestFn.call(window, callback) 5112 } 5113 Waypoint.Context = Context 5114}()) 5115;(function() { 5116 'use strict' 5117 5118 function byTriggerPoint(a, b) { 5119 return a.triggerPoint - b.triggerPoint 5120 } 5121 5122 function byReverseTriggerPoint(a, b) { 5123 return b.triggerPoint - a.triggerPoint 5124 } 5125 5126 var groups = { 5127 vertical: {}, 5128 horizontal: {} 5129 } 5130 var Waypoint = window.Waypoint 5131 5132 /* http://imakewebthings.com/waypoints/api/group */ 5133 function Group(options) { 5134 this.name = options.name 5135 this.axis = options.axis 5136 this.id = this.name + '-' + this.axis 5137 this.waypoints = [] 5138 this.clearTriggerQueues() 5139 groups[this.axis][this.name] = this 5140 } 5141 5142 /* Private */ 5143 Group.prototype.add = function(waypoint) { 5144 this.waypoints.push(waypoint) 5145 } 5146 5147 /* Private */ 5148 Group.prototype.clearTriggerQueues = function() { 5149 this.triggerQueues = { 5150 up: [], 5151 down: [], 5152 left: [], 5153 right: [] 5154 } 5155 } 5156 5157 /* Private */ 5158 Group.prototype.flushTriggers = function() { 5159 for (var direction in this.triggerQueues) { 5160 var waypoints = this.triggerQueues[direction] 5161 var reverse = direction === 'up' || direction === 'left' 5162 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 5163 for (var i = 0, end = waypoints.length; i < end; i += 1) { 5164 var waypoint = waypoints[i] 5165 if (waypoint.options.continuous || i === waypoints.length - 1) { 5166 waypoint.trigger([direction]) 5167 } 5168 } 5169 } 5170 this.clearTriggerQueues() 5171 } 5172 5173 /* Private */ 5174 Group.prototype.next = function(waypoint) { 5175 this.waypoints.sort(byTriggerPoint) 5176 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5177 var isLast = index === this.waypoints.length - 1 5178 return isLast ? null : this.waypoints[index + 1] 5179 } 5180 5181 /* Private */ 5182 Group.prototype.previous = function(waypoint) { 5183 this.waypoints.sort(byTriggerPoint) 5184 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5185 return index ? this.waypoints[index - 1] : null 5186 } 5187 5188 /* Private */ 5189 Group.prototype.queueTrigger = function(waypoint, direction) { 5190 this.triggerQueues[direction].push(waypoint) 5191 } 5192 5193 /* Private */ 5194 Group.prototype.remove = function(waypoint) { 5195 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5196 if (index > -1) { 5197 this.waypoints.splice(index, 1) 5198 } 5199 } 5200 5201 /* Public */ 5202 /* http://imakewebthings.com/waypoints/api/first */ 5203 Group.prototype.first = function() { 5204 return this.waypoints[0] 5205 } 5206 5207 /* Public */ 5208 /* http://imakewebthings.com/waypoints/api/last */ 5209 Group.prototype.last = function() { 5210 return this.waypoints[this.waypoints.length - 1] 5211 } 5212 5213 /* Private */ 5214 Group.findOrCreate = function(options) { 5215 return groups[options.axis][options.name] || new Group(options) 5216 } 5217 5218 Waypoint.Group = Group 5219}()) 5220;(function() { 5221 'use strict' 5222 5223 var $ = window.jQuery 5224 var Waypoint = window.Waypoint 5225 5226 function JQueryAdapter(element) { 5227 this.$element = $(element) 5228 } 5229 5230 $.each([
5231 'innerHeight', 5232 'innerWidth', 5233 'off', 5234 'offset', 5235 'on', 5236 'outerHeight', 5237 'outerWidth', 5238 'scrollLeft', 5239 'scrollTop' 5240 ], function(i, method) { 5241 JQueryAdapter.prototype[method] = function() { 5242 var args = Array.prototype.slice.call(arguments) 5243 return this.$element[method].apply(this.$element, args) 5244 } 5245 }) 5246 5247 $.each([ 5248 'extend', 5249 'inArray', 5250 'isEmptyObject' 5251 ], function(i, method) { 5252 JQueryAdapter[method] = $[method] 5253 }) 5254 5255 Waypoint.adapters.push({ 5256 name: 'jquery', 5257 Adapter: JQueryAdapter 5258 }) 5259 Waypoint.Adapter = JQueryAdapter 5260}()) 5261;(function() { 5262 'use strict' 5263 5264 var Waypoint = window.Waypoint 5265 5266 function createExtension(framework) { 5267 return function() { 5268 var waypoints = [] 5269 var overrides = arguments[0] 5270 5271 if (framework.isFunction(arguments[0])) { 5272 overrides = framework.extend({}, arguments[1]) 5273 overrides.handler = arguments[0] 5274 } 5275 5276 this.each(function() { 5277 var options = framework.extend({}, overrides, { 5278 element: this 5279 }) 5280 if (typeof options.context === 'string') { 5281 options.context = framework(this).closest(options.context)[0] 5282 } 5283 waypoints.push(new Waypoint(options)) 5284 }) 5285 5286 return waypoints 5287 } 5288 } 5289 5290 if (window.jQuery) { 5291 window.jQuery.fn.waypoint = createExtension(window.jQuery) 5292 } 5293 if (window.Zepto) { 5294 window.Zepto.fn.waypoint = createExtension(window.Zepto) 5295 } 5296}()) 5297; 5298 5299/*! 5300Waypoints Inview Shortcut - 4.0.1 5301Copyright © 2011-2016 Caleb Troughton 5302Licensed under the MIT license. 5303https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 5304*/ 5305(function() { 5306 'use strict' 5307 5308 function noop() {} 5309 5310 var Waypoint = window.Waypoint 5311 5312 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 5313 function Inview(options) { 5314 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 5315 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 5316 this.waypoints = [] 5317 this.element = this.options.element 5318 this.createWaypoints() 5319 } 5320 5321 /* Private */ 5322 Inview.prototype.createWaypoints = function() { 5323 var configs = { 5324 vertical: [{ 5325 down: 'enter', 5326 up: 'exited', 5327 offset: '100%' 5328 }, { 5329 down: 'entered', 5330 up: 'exit', 5331 offset: 'bottom-in-view' 5332 }, { 5333 down: 'exit', 5334 up: 'entered', 5335 offset: 0 5336 }, { 5337 down: 'exited', 5338 up: 'enter', 5339 offset: function() { 5340 return -this.adapter.outerHeight() 5341 } 5342 }], 5343 horizontal: [{ 5344 right: 'enter', 5345 left: 'exited', 5346 offset: '100%' 5347 }, { 5348 right: 'entered', 5349 left: 'exit', 5350 offset: 'right-in-view' 5351 }, { 5352 right: 'exit', 5353 left: 'entered', 5354 offset: 0 5355 }, { 5356 right: 'exited', 5357 left: 'enter', 5358 offset: function() { 5359 return -this.adapter.outerWidth() 5360 } 5361 }] 5362 } 5363 5364 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 5365 var config = configs[this.axis][i] 5366 this.createWaypoint(config) 5367 } 5368 } 5369 5370 /* Private */ 5371 Inview.prototype.createWaypoint = function(config) { 5372 var self = this 5373 this.waypoints.push(new Waypoint({ 5374 context: this.options.context, 5375 element: this.options.element, 5376 enabled: this.options.enabled, 5377 handler: (function(config) { 5378 return function(direction) { 5379 self.options[config[direction]].call(self, direction) 5380 } 5381 }(config)), 5382 offset: config.offset, 5383 horizontal: this.options.horizontal 5384 })) 5385 } 5386 5387 /* Public */ 5388 Inview.prototype.destroy = function() { 5389 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5390 this.waypoints[i].destroy() 5391 } 5392 this.waypoints = [] 5393 } 5394 5395 Inview.prototype.disable = function() { 5396 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5397 this.waypoints[i].disable() 5398 } 5399 } 5400 5401 Inview.prototype.enable = function() { 5402 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5403 this.waypoints[i].enable() 5404 } 5405 } 5406 5407 Inview.defaults = { 5408 context: window, 5409 enabled: true, 5410 enter: noop, 5411 entered: noop, 5412 exit: noop, 5413 exited: noop 5414 } 5415 5416 Waypoint.Inview = Inview 5417}()) 5418; 5419 5420/* 5421 * SmartMenus jQuery v0.9.6 5422 * http://www.smartmenus.org/ 5423 * 5424 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 5425 * http://vadikom.com/ 5426 * 5427 * Released under the MIT license: 5428 * http://www.opensource.org/licenses/MIT 5429 */ 5430 5431(function($) { 5432 5433 var menuTrees = [], 5434 IE = !!window.createPopup, // we need to detect it, unfortunately 5435 IElt9 = IE && !document.defaultView, 5436 IElt8 = IE && !document.querySelector, 5437 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 5438 mouse = false, // optimize for touch by default - we will detect for mouse input 5439 mouseDetectionEnabled = false;
5440 5441 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 5442 function initMouseDetection(disable) { 5443 if (!mouseDetectionEnabled && !disable) { 5444 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 5445 // 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) 5446 var firstTime = true, 5447 lastMove = null; 5448 $(document).bind({ 5449 'mousemove.smartmenus_mouse': function(e) { 5450 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 5451 if (lastMove) { 5452 var deltaX = Math.abs(lastMove.x - thisMove.x), 5453 deltaY = Math.abs(lastMove.y - thisMove.y); 5454 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 5455 mouse = true; 5456 // 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 5457 if (firstTime) { 5458 var $a = $(e.target).closest('a'); 5459 if ($a.is('a')) { 5460 $.each(menuTrees, function() { 5461 if ($.contains(this.$root[0], $a[0])) { 5462 this.itemEnter({ currentTarget: $a[0] }); 5463 return false; 5464 } 5465 }); 5466 } 5467 firstTime = false; 5468 } 5469 } 5470 } 5471 lastMove = thisMove; 5472 }, 5473 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 5474 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 5475 mouse = false; 5476 } 5477 } 5478 }); 5479 mouseDetectionEnabled = true; 5480 } else if (mouseDetectionEnabled && disable) { 5481 $(document).unbind('.smartmenus_mouse'); 5482 mouseDetectionEnabled = false; 5483 } 5484 }; 5485 5486 $.SmartMenus = function(elm, options) { 5487 this.$root = $(elm); 5488 this.opts = options; 5489 this.rootId = ''; // internal 5490 this.$subArrow = null; 5491 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) 5492 this.activatedItems = []; // stores last activated A's for each level 5493 this.visibleSubMenus = []; // stores visible sub menus UL's 5494 this.showTimeout = 0; 5495 this.hideTimeout = 0; 5496 this.scrollTimeout = 0; 5497 this.clickActivated = false; 5498 this.zIndexInc = 0; 5499 this.$firstLink = null; // we'll use these for some tests 5500 this.$firstSub = null; // at runtime so we'll cache them 5501 this.disabled = false; 5502 this.$disableOverlay = null; 5503 this.init(); 5504 }; 5505 5506 $.extend($.SmartMenus, { 5507 hideAll: function() { 5508 $.each(menuTrees, function() { 5509 this.menuHideAll(); 5510 }); 5511 }, 5512 destroy: function() { 5513 while (menuTrees.length) { 5514 menuTrees[0].destroy(); 5515 } 5516 initMouseDetection(true); 5517 }, 5518 prototype: { 5519 init: function(refresh) { 5520 var self = this; 5521 5522 if (!refresh) { 5523 menuTrees.push(this); 5524 5525 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 5526 5527 if (this.$root.hasClass('sm-rtl')) { 5528 this.opts.rightToLeftSubMenus = true; 5529 } 5530 5531 // init root (main menu) 5532 this.$root 5533 .data('smartmenus', this) 5534 .attr('data-smartmenus-id', this.rootId) 5535 .dataSM('level', 1) 5536 .bind({ 5537 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this), 5538 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 5539 }) 5540 .delegate('a', { 5541 'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
5542 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 5543 'mousedown.smartmenus': $.proxy(this.itemDown, this), 5544 'focus.smartmenus': $.proxy(this.itemFocus, this), 5545 'blur.smartmenus': $.proxy(this.itemBlur, this), 5546 'click.smartmenus': $.proxy(this.itemClick, this), 5547 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 5548 }); 5549 5550 var eNamespace = '.smartmenus' + this.rootId; 5551 // hide menus on tap or click outside the root UL 5552 if (this.opts.hideOnClick) { 5553 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 5554 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 5555 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 5556 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 5557 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 5558 } 5559 // hide sub menus on resize 5560 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5561 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5562 5563 if (this.opts.subIndicators) { 5564 this.$subArrow = $('<span/>').addClass('sub-arrow'); 5565 if (this.opts.subIndicatorsText) { 5566 this.$subArrow.html(this.opts.subIndicatorsText); 5567 } 5568 } 5569 5570 // make sure mouse detection is enabled 5571 initMouseDetection(); 5572 } 5573 5574 // init sub menus 5575 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 5576 5577 this.$firstLink = this.$root.find('a').eq(0); 5578 5579 // find current item 5580 if (this.opts.markCurrentItem) { 5581 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 5582 reHash = /#.*/, 5583 locHref = window.location.href.replace(reDefaultDoc, ''), 5584 locHrefNoHash = locHref.replace(reHash, ''); 5585 this.$root.find('a').each(function() { 5586 var href = this.href.replace(reDefaultDoc, ''), 5587 $this = $(this); 5588 if (href == locHref || href == locHrefNoHash) { 5589 $this.addClass('current'); 5590 if (self.opts.markCurrentTree) { 5591 $this.parents('li').each(function() { 5592 var $this = $(this); 5593 if ($this.dataSM('sub')) { 5594 $this.children('a').addClass('current'); 5595 } 5596 }); 5597 } 5598 } 5599 }); 5600 } 5601 }, 5602 destroy: function() { 5603 this.menuHideAll(); 5604 this.$root 5605 .removeData('smartmenus') 5606 .removeAttr('data-smartmenus-id') 5607 .removeDataSM('level') 5608 .unbind('.smartmenus') 5609 .undelegate('.smartmenus'); 5610 var eNamespace = '.smartmenus' + this.rootId; 5611 $(document).unbind(eNamespace); 5612 $(window).unbind(eNamespace); 5613 if (this.opts.subIndicators) { 5614 this.$subArrow = null; 5615 } 5616 var self = this; 5617 $.each(this.subMenus, function() { 5618 if (this.hasClass('mega-menu')) { 5619 this.find('ul').removeDataSM('in-mega'); 5620 } 5621 if (this.dataSM('shown-before')) { 5622 if (IElt8) { 5623 this.children().css({ styleFloat: '', width: '' }); 5624 } 5625 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 5626 if (!IE6) { 5627 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 5628 } else { 5629 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 5630 } 5631 } 5632 if (this.dataSM('scroll-arrows')) { 5633 this.dataSM('scroll-arrows').remove(); 5634 } 5635 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 5636 } 5637 if (self.opts.subIndicators) { 5638 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 5639 } 5640 this.removeDataSM('shown-before') 5641 .removeDataSM('ie-shim') 5642 .removeDataSM('scroll-arrows') 5643 .removeDataSM('parent-a') 5644 .removeDataSM('level') 5645 .removeDataSM('beforefirstshowfired') 5646 .parent().removeDataSM('sub'); 5647 }); 5648 if (this.opts.markCurrentItem) { 5649 this.$root.find('a.current').removeClass('current'); 5650 } 5651 this.$root = null; 5652 this.$firstLink = null; 5653 this.$firstSub = null; 5654 if (this.$disableOverlay) { 5655 this.$disableOverlay.remove(); 5656 this.$disableOverlay = null; 5657 } 5658 menuTrees.splice($.inArray(this, menuTrees), 1); 5659 }, 5660 disable: function(noOverlay) { 5661 if (!this.disabled) { 5662 this.menuHideAll(); 5663 // display overlay over the menu to prevent interaction 5664 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 5665 var pos = this.$root.offset(); 5666 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 5667 position: 'absolute', 5668 top: pos.top, 5669 left: pos.left, 5670 width: this.$root.outerWidth(), 5671 height: this.$root.outerHeight(),
5672 zIndex: this.getStartZIndex() + 1, 5673 opacity: 0 5674 }).appendTo(document.body); 5675 } 5676 this.disabled = true; 5677 } 5678 }, 5679 docClick: function(e) { 5680 // hide on any click outside the menu or on a menu link 5681 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 5682 this.menuHideAll($(e.target)); 5683 } 5684 }, 5685 docTouchEnd: function(e) { 5686 if (!this.lastTouch) { 5687 return; 5688 } 5689 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))) { 5690 if (this.hideTimeout) { 5691 clearTimeout(this.hideTimeout); 5692 this.hideTimeout = 0; 5693 } 5694 // hide with a delay to prevent triggering accidental unwanted click on some page element 5695 var self = this; 5696 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 5697 } 5698 this.lastTouch = null; 5699 }, 5700 docTouchMove: function(e) { 5701 if (!this.lastTouch) { 5702 return; 5703 } 5704 var touchPoint = e.originalEvent.touches[0]; 5705 this.lastTouch.x2 = touchPoint.pageX; 5706 this.lastTouch.y2 = touchPoint.pageY; 5707 }, 5708 docTouchStart: function(e) { 5709 var touchPoint = e.originalEvent.touches[0]; 5710 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 5711 }, 5712 enable: function() { 5713 if (this.disabled) { 5714 if (this.$disableOverlay) { 5715 this.$disableOverlay.remove(); 5716 this.$disableOverlay = null; 5717 } 5718 this.disabled = false; 5719 } 5720 }, 5721 getHeight: function($elm) { 5722 return this.getOffset($elm, true); 5723 }, 5724 // returns precise width/height float values in IE9+, FF4+, recent WebKit 5725 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 5726 getOffset: function($elm, height) { 5727 var old; 5728 if ($elm.css('display') == 'none') { 5729 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 5730 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 5731 } 5732 var defaultView = $elm[0].ownerDocument.defaultView, 5733 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 5734 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 5735 if (val) { 5736 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 5737 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 5738 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 5739 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 5740 } else { 5741 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 5742 } 5743 if (old) { 5744 $elm.hide().css(old); 5745 } 5746 return val; 5747 }, 5748 getWidth: function($elm) { 5749 return this.getOffset($elm); 5750 }, 5751 getStartZIndex: function() { 5752 var zIndex = parseInt(this.$root.css('z-index')); 5753 return !isNaN(zIndex) ? zIndex : 1; 5754 }, 5755 handleEvents: function() { 5756 return !this.disabled && this.isCSSOn(); 5757 }, 5758 handleItemEvents: function($a) { 5759 return this.handleEvents() && !this.isLinkInMegaMenu($a); 5760 }, 5761 isCollapsible: function() { 5762 return this.$firstSub.css('position') == 'static'; 5763 }, 5764 isCSSOn: function() { 5765 return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'inline'; 5766 }, 5767 isFixed: function() { 5768 return this.$root.css('position') == 'fixed'; 5769 }, 5770 isLinkInMegaMenu: function($a) { 5771 return !$a.parent().parent().dataSM('level'); 5772 }, 5773 isTouchMode: function() { 5774 return !mouse || this.isCollapsible(); 5775 }, 5776 itemActivate: function($a) { 5777 var $li = $a.parent(), 5778 $ul = $li.parent(), 5779 level = $ul.dataSM('level'); 5780 // 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 5781 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 5782 var self = this; 5783 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 5784 self.itemActivate($(this).dataSM('parent-a')); 5785 }); 5786 } 5787 // hide any visible deeper level sub menus 5788 if (this.visibleSubMenus.length > level) { 5789 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--) { 5790 this.menuHide(this.visibleSubMenus[i]); 5791 } 5792 } 5793 // save new active item and sub menu for this level 5794 this.activatedItems[level - 1] = $a; 5795 this.visibleSubMenus[level - 1] = $ul; 5796 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 5797 return; 5798 } 5799 // show the sub menu if this item has one 5800 var $sub = $li.dataSM('sub'); 5801 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 5802 this.menuShow($sub); 5803 } 5804 }, 5805 itemBlur: function(e) { 5806 var $a = $(e.currentTarget); 5807 if (!this.handleItemEvents($a)) { 5808 return; 5809 } 5810 this.$root.triggerHandler('blur.smapi', $a[0]); 5811 }, 5812 itemClick: function(e) { 5813 var $a = $(e.currentTarget); 5814 5815 if (!this.handleItemEvents($a)) { 5816 return; 5817 } 5818 $a.removeDataSM('mousedown'); 5819 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 5820 return false;
5821 } 5822 var $sub = $a.parent().dataSM('sub'); 5823 if (this.isTouchMode()) { 5824 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 5825 if ($a.dataSM('href')) { 5826 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 5827 } 5828 // if the sub is not visible 5829 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5830 // try to activate the item and show the sub 5831 this.itemActivate($a); 5832 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 5833 // 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 5834 if ($sub.is(':visible')) { 5835 return false; 5836 } 5837 } 5838 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 5839 this.clickActivated = true; 5840 this.menuShow($sub); 5841 return false; 5842 } 5843 if ($a.hasClass('disabled')) { 5844 return false; 5845 } 5846 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 5847 return false; 5848 } 5849 }, 5850 itemDown: function(e) { 5851 var $a = $(e.currentTarget); 5852 if (!this.handleItemEvents($a)) { 5853 return; 5854 } 5855 $a.dataSM('mousedown', true); 5856 }, 5857 itemEnter: function(e) { 5858 var $a = $(e.currentTarget); 5859 if (!this.handleItemEvents($a)) { 5860 return; 5861 } 5862 if (!this.isTouchMode()) { 5863 if (this.showTimeout) { 5864 clearTimeout(this.showTimeout); 5865 this.showTimeout = 0; 5866 } 5867 var self = this; 5868 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 5869 } 5870 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 5871 }, 5872 itemFocus: function(e) { 5873 var $a = $(e.currentTarget); 5874 if (!this.handleItemEvents($a)) { 5875 return; 5876 } 5877 // 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 5878 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 5879 this.itemActivate($a); 5880 } 5881 this.$root.triggerHandler('focus.smapi', $a[0]); 5882 }, 5883 itemLeave: function(e) { 5884 var $a = $(e.currentTarget); 5885 if (!this.handleItemEvents($a)) { 5886 return; 5887 } 5888 if (!this.isTouchMode()) { 5889 if ($a[0].blur) { 5890 $a[0].blur(); 5891 } 5892 if (this.showTimeout) { 5893 clearTimeout(this.showTimeout); 5894 this.showTimeout = 0; 5895 } 5896 } 5897 $a.removeDataSM('mousedown'); 5898 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 5899 }, 5900 itemTouchEnd: function(e) { 5901 var $a = $(e.currentTarget); 5902 if (!this.handleItemEvents($a)) { 5903 return; 5904 } 5905 // prevent the address bar on iPhone from sliding down when expanding a sub menu 5906 var $sub = $a.parent().dataSM('sub'); 5907 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5908 $a.dataSM('href', $a.attr('href')); 5909 $a.attr('href', '#'); 5910 } 5911 }, 5912 menuFixLayout: function($ul) { 5913 // fixes a menu that is being shown for the first time 5914 if (!$ul.dataSM('shown-before')) { 5915 $ul.hide().dataSM('shown-before', true); 5916 // fix the layout of the items in IE<8 5917 if (IElt8) { 5918 $ul.children().css({ styleFloat: 'left', width: '100%' }); 5919 } 5920 } 5921 }, 5922 menuHide: function($sub) { 5923 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 5924 return; 5925 } 5926 $sub.stop(true, true); 5927 if ($sub.is(':visible')) { 5928 var complete = function() { 5929 // unset z-index 5930 if (IElt9) { 5931 $sub.parent().css('z-index', ''); 5932 } else { 5933 $sub.css('z-index', ''); 5934 } 5935 }; 5936 // if sub is collapsible (mobile view) 5937 if (this.isCollapsible()) { 5938 if (this.opts.collapsibleHideFunction) { 5939 this.opts.collapsibleHideFunction.call(this, $sub, complete); 5940 } else { 5941 $sub.hide(this.opts.collapsibleHideDuration, complete); 5942 } 5943 } else { 5944 if (this.opts.hideFunction) { 5945 this.opts.hideFunction.call(this, $sub, complete); 5946 } else { 5947 $sub.hide(this.opts.hideDuration, complete); 5948 } 5949 } 5950 // remove IE iframe shim 5951 if ($sub.dataSM('ie-shim')) { 5952 $sub.dataSM('ie-shim').remove(); 5953 } 5954 // deactivate scrolling if it is activated for this sub 5955 if ($sub.dataSM('scroll')) { 5956 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 5957 } 5958 // unhighlight parent item 5959 $sub.dataSM('parent-a').removeClass('highlighted'); 5960 var level = $sub.dataSM('level'); 5961 this.activatedItems.splice(level - 1, 1); 5962 this.visibleSubMenus.splice(level - 1, 1); 5963 this.$root.triggerHandler('hide.smapi', $sub[0]); 5964 } 5965 }, 5966 menuHideAll: function($item) { 5967 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 5968 if (this.showTimeout) { 5969 clearTimeout(this.showTimeout); 5970 this.showTimeout = 0; 5971 } 5972 // hide all subs 5973 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 5974 this.menuHide(this.visibleSubMenus[i]); 5975 } 5976 // hide root if it's popup 5977 if (this.opts.isPopup) { 5978 this.$root.stop(true, true); 5979 if (this.$root.is(':visible')) { 5980 if (this.opts.hideFunction) { 5981 this.opts.hideFunction.call(this, this.$root); 5982 } else { 5983 this.$root.hide(this.opts.hideDuration); 5984 } 5985 // remove IE iframe shim 5986 if (this.$root.dataSM('ie-shim')) { 5987 this.$root.dataSM('ie-shim').remove(); 5988 } 5989 } 5990 } 5991 this.activatedItems = []; 5992 this.visibleSubMenus = []; 5993 this.clickActivated = false;
5994 // reset z-index increment 5995 this.zIndexInc = 0; 5996 }, 5997 menuIframeShim: function($ul) { 5998 // create iframe shim for the menu 5999 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 6000 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 6001 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 6002 ); 6003 } 6004 }, 6005 menuInit: function($ul) { 6006 if (!$ul.dataSM('in-mega')) { 6007 this.subMenus.push($ul); 6008 // mark UL's in mega drop downs (if any) so we can neglect them 6009 if ($ul.hasClass('mega-menu')) { 6010 $ul.find('ul').dataSM('in-mega', true); 6011 } 6012 // get level (much faster than, for example, using parentsUntil) 6013 var level = 2, 6014 par = $ul[0]; 6015 while ((par = par.parentNode.parentNode) != this.$root[0]) { 6016 level++; 6017 } 6018 // cache stuff 6019 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 6020 .dataSM('level', level) 6021 .parent().dataSM('sub', $ul); 6022 // add sub indicator to parent item 6023 if (this.opts.subIndicators) { 6024 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 6025 } 6026 } 6027 }, 6028 menuPosition: function($sub) { 6029 var fixIE = $('html.ie').length; 6030 // if (fixIE) { 6031 // var $rowParent = $($sub).closest('.main-menu-container'); 6032 // $rowParent.height($rowParent.height()); 6033 // } 6034 var $a = $sub.dataSM('parent-a'), 6035 $li = $sub.parent(), 6036 $ul = $sub.parent().parent(), 6037 $container = $ul.closest('.row-menu-inner'), 6038 level = $sub.dataSM('level'), 6039 subW = this.getWidth($sub), 6040 subH = this.getHeight($sub), 6041 itemOffset = $a.offset(), 6042 itemX = itemOffset.left, 6043 itemY = itemOffset.top, 6044 itemW = this.getWidth($a), 6045 itemH = this.getHeight($a), 6046 $win = $(window), 6047 winX = $win.scrollLeft(), 6048 winY = $win.scrollTop(), 6049 winW = $win.width(), 6050 winH = $win.height(), 6051 containerW = $container.width(), 6052 containerOffsetX = containerW + ((winW - containerW) / 2), 6053 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 6054 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 6055 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 6056 x, y, leftPos; 6057 if (horizontalParent) { 6058 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 6059 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 6060 } else { 6061 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX; 6062 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 6063 } 6064 if (this.opts.keepInViewport && !this.isCollapsible()) { 6065 if (this.isFixed()) { 6066 itemX -= winX; 6067 itemY -= winY; 6068 winX = winY = 0; 6069 } 6070 var absX = itemX + x, 6071 absY = itemY + y; 6072 if (this.opts.rightToLeftSubMenus && absX < winX) { 6073 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 6074 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 6075 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 6076 } 6077 if (!horizontalParent) { 6078 if (subH < winH && absY + subH > winY + winH) { 6079 y += winY + winH - subH - absY; 6080 } else if (subH >= winH || absY < winY) { 6081 y += winY - absY; 6082 } 6083 } 6084 // do we need scrolling? 6085 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 6086 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 6087 var self = this; 6088 if (!$sub.dataSM('scroll-arrows')) { 6089 $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]]) 6090 .bind({ 6091 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 6092 mouseleave: function(e) { 6093 self.menuScrollStop($sub); 6094 self.menuScrollOut($sub, e); 6095 }, 6096 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 6097 }) 6098 .insertAfter($sub) 6099 ); 6100 } 6101 // bind events to show/hide arrows on hover and save scrolling data for this sub 6102 var vportY = winY - (itemY + itemH); 6103 $sub.dataSM('scroll', { 6104 vportY: vportY, 6105 subH: subH, 6106 winH: winH, 6107 step: 1 6108 }) 6109 .bind({ 6110 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 6111 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 6112 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 6113 }) 6114 .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
6114StartZIndex() + this.zIndexInc }) 6115 .eq(0).css('margin-top', vportY).end() 6116 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 6117 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 6118 } 6119 } 6120 // if ($sub.hasClass('mega-menu-inner')) { 6121 // if ($('.menu-wrapper .megamenu-diff').length > 0) { 6122 // leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth()); 6123 // leftPos = -leftPos; 6124 // } else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft')); 6125 6126 // if ($('body.header-full-width').length > 0) { 6127 // $sub.css({ width: $('.box-container').width()}); 6128 // leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft'))); 6129 // } else $sub.css({ width: containerW}); 6130 // leftPos = leftPos + 'px'; 6131 6132 // } else { 6133 // leftPos = $li.position().left + 'px'; 6134 // } 6135 if ($sub.hasClass('mega-menu-inner')) { 6136 $sub.css({ width: containerW}); 6137 if ($('body.hmenu-center-split').length > 0 && !$sub.closest('.navbar-cta').length ) { 6138 leftPos = - ($sub.closest('.menu-primary-inner')[0].offsetLeft) + 'px'; 6139 } else { 6140 if ( $sub.closest('.navbar-cta').length && !$('body.hmenu').length && !$('body.hmenu-center').length ) { 6141 leftPos = - ( parseFloat($sub.closest('.navbar-cta').offset().left) - parseFloat($sub.closest('.row-menu-inner').find('.logo-container').offset().left) ) + 'px'; 6142 } else if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0 && !$('body.hmenu-center-split').length) { 6143 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 6144 } else { 6145 leftPos = '0px'; 6146 } 6147 } 6148 } else { 6149 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 6150 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 6151 } 6152 6153 $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) }); 6154 // IE iframe shim 6155 this.menuIframeShim($sub); 6156 if ($sub.dataSM('ie-shim')) { 6157 $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) }); 6158 } 6159 }, 6160 menuScroll: function($sub, up, wheel) { 6161 var y = parseFloat($sub.css('margin-top')), 6162 scroll = $sub.dataSM('scroll'), 6163 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 6164 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 6165 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 6166 y = parseFloat($sub.css('margin-top')); 6167 // show opposite arrow if appropriate 6168 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 6169 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 6170 } 6171 // accelerate when not using mousewheel to scroll 6172 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 6173 $sub.dataSM('scroll').step += 0.5; 6174 } 6175 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 6176 if (Math.abs(y - end) < 1) { 6177 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 6178 $sub.dataSM('scroll').step = 1; 6179 } else if (!wheel) { 6180 var self = this; 6181 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 6182 } 6183 }, 6184 menuScrollMousewheel: function($sub, e) { 6185 var $closestSub = $(e.target).closest('ul'); 6186 while ($closestSub.dataSM('in-mega')) { 6187 $closestSub = $closestSub.parent().closest('ul'); 6188 } 6189 if ($closestSub[0] == $sub[0]) { 6190 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 6191 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 6192 this.menuScroll($sub, up, true); 6193 } 6194 } 6195 e.preventDefault(); 6196 }, 6197 menuScrollOut: function($sub, e) { 6198 var reClass = /^scroll-(up|down)/, 6199 $closestSub = $(e.relatedTarget).closest('ul'); 6200 while ($closestSub.dataSM('in-mega')) { 6201 $closestSub = $closestSub.parent().closest('ul'); 6202 } 6203 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 6204 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 6205 } 6206 }, 6207 menuScrollOver: function($sub, e) { 6208 var reClass = /^scroll-(up|down)/, 6209 $closestSub = $(e.target).closest('ul'); 6210 while ($closestSub.dataSM('in-mega')) { 6211 $closestSub = $closestSub.parent().closest('ul'); 6212 } 6213 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 6214 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 6215 } 6216 }, 6217 menuScrollStop: function($sub) { 6218 if (this.scrollTimeout) { 6219 clearTimeout(this.scrollTimeout); 6220 this.scrollTimeout = 0; 6221 $sub.dataSM('scroll').step = 1; 6222 } 6223 }, 6224 menuShow: function($sub) { 6225 if (!$sub.dataSM('beforefirstshowfired')) { 6226 $sub.dataSM('beforefirstshowfired', true); 6227 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 6228 return; 6229 } 6230 } 6231 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 6232 return; 6233 } 6234 this.menuFixLayout($sub); 6235 $sub.stop(true, true); 6236 if (!$sub.is(':visible')) { 6237 // set z-index - for IE < 9 set it to the parent LI
6238 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 6239 if (IElt9) { 6240 $sub.parent().css('z-index', zIndex); 6241 } else { 6242 $sub.css('z-index', zIndex); 6243 } 6244 // highlight parent item 6245 if (this.opts.keepHighlighted || this.isCollapsible()) { 6246 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 6247 $sub.dataSM('parent-a').addClass('highlighted'); 6248 } 6249 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 6250 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 6251 if (!IElt8) { 6252 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6253 if (this.opts.subMenusMinWidth) { 6254 $sub.css('min-width', this.opts.subMenusMinWidth); 6255 } 6256 if (this.opts.subMenusMaxWidth) { 6257 var noMaxWidth = this.getWidth($sub); 6258 $sub.css('max-width', this.opts.subMenusMaxWidth); 6259 if (noMaxWidth > this.getWidth($sub)) { 6260 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6261 } 6262 } 6263 // IE6,7 6264 } else { 6265 $sub.children().css('styleFloat', 'none'); 6266 if (IE6) { 6267 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 6268 .children().children('a').css('white-space', 'nowrap'); 6269 } else { // IE7 6270 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6271 if (this.opts.subMenusMinWidth) { 6272 $sub.css('min-width', this.opts.subMenusMinWidth); 6273 } 6274 } 6275 if (this.opts.subMenusMaxWidth) { 6276 var noMaxWidth = $sub.width(); 6277 if (IE6) { 6278 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 6279 if (noMaxWidth > maxWidth) { 6280 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 6281 } else { 6282 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 6283 } 6284 } else { // IE7 6285 $sub.css('max-width', this.opts.subMenusMaxWidth); 6286 if (noMaxWidth > $sub.width()) { 6287 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6288 } else { 6289 $sub.width(noMaxWidth); 6290 } 6291 } 6292 } else { 6293 $sub.width($sub.width()); 6294 } 6295 $sub.children().css('styleFloat', 'left'); 6296 } 6297 } 6298 this.menuPosition($sub); 6299 // insert IE iframe shim 6300 if ($sub.dataSM('ie-shim')) { 6301 $sub.dataSM('ie-shim').insertBefore($sub); 6302 } 6303 var complete = function() { 6304 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 6305 $sub.css('overflow', ''); 6306 }; 6307 // if sub is collapsible (mobile view) 6308 if (this.isCollapsible()) { 6309 if (this.opts.collapsibleShowFunction) { 6310 this.opts.collapsibleShowFunction.call(this, $sub, complete); 6311 } else { 6312 $sub.show(this.opts.collapsibleShowDuration, complete); 6313 } 6314 } else { 6315 if (this.opts.showFunction) { 6316 this.opts.showFunction.call(this, $sub, complete); 6317 } else { 6318 $sub.show(this.opts.showDuration, complete); 6319 } 6320 } 6321 // save new sub menu for this level 6322 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 6323 this.$root.triggerHandler('show.smapi', $sub[0]); 6324 } 6325 }, 6326 popupHide: function(noHideTimeout) { 6327 if (this.hideTimeout) { 6328 clearTimeout(this.hideTimeout); 6329 this.hideTimeout = 0; 6330 } 6331 var self = this; 6332 this.hideTimeout = setTimeout(function() { 6333 self.menuHideAll(); 6334 }, noHideTimeout ? 1 : this.opts.hideTimeout); 6335 }, 6336 popupShow: function(left, top) { 6337 if (!this.opts.isPopup) { 6338 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 6339 return; 6340 } 6341 if (this.hideTimeout) { 6342 clearTimeout(this.hideTimeout); 6343 this.hideTimeout = 0; 6344 } 6345 this.menuFixLayout(this.$root); 6346 this.$root.stop(true, true); 6347 if (!this.$root.is(':visible')) { 6348 this.$root.css({ left: left, top: top }); 6349 // IE iframe shim 6350 this.menuIframeShim(this.$root); 6351 if (this.$root.dataSM('ie-shim')) { 6352 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6352: left, top: top }).insertBefore(this.$root); 6353 } 6354 // show menu 6355 if (this.opts.showFunction) { 6356 this.opts.showFunction.call(this, this.$root); 6357 } else { 6358 this.$root.show(this.opts.showDuration); 6359 } 6360 this.visibleSubMenus[0] = this.$root; 6361 } 6362 }, 6363 refresh: function() { 6364 this.menuHideAll(); 6365 this.$root.find('ul').each(function() { 6366 var $this = $(this); 6367 if ($this.dataSM('scroll-arrows')) { 6368 $this.dataSM('scroll-arrows').remove(); 6369 } 6370 }) 6371 .removeDataSM('in-mega') 6372 .removeDataSM('shown-before') 6373 .removeDataSM('ie-shim') 6374 .removeDataSM('scroll-arrows') 6375 .removeDataSM('parent-a') 6376 .removeDataSM('level') 6377 .removeDataSM('beforefirstshowfired'); 6378 this.$root.find('a.has-submenu').removeClass('has-submenu') 6379 .parent().removeDataSM('sub'); 6380 if (this.opts.subIndicators) { 6381 this.$root.find('span.sub-arrow').remove(); 6382 } 6383 if (this.opts.markCurrentItem) { 6384 this.$root.find('a.current').removeClass('current'); 6385 } 6386 this.subMenus = []; 6387 this.init(true); 6388 }, 6389 rootOut: function(e) { 6390 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6391 return; 6392 } 6393 if (this.hideTimeout) { 6394 clearTimeout(this.hideTimeout); 6395 this.hideTimeout = 0; 6396 } 6397 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 6398 var self = this; 6399 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 6400 } 6401 }, 6402 rootOver: function(e) { 6403 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6404 return; 6405 } 6406 if (this.hideTimeout) { 6407 clearTimeout(this.hideTimeout); 6408 this.hideTimeout = 0; 6409 } 6410 }, 6411 winResize: function(e) { 6412 if (!this.handleEvents()) { 6413 // we still need to resize the disable overlay if it's visible 6414 if (this.$disableOverlay) { 6415 var pos = this.$root.offset(); 6416 this.$disableOverlay.css({ 6417 top: pos.top, 6418 left: pos.left, 6419 width: this.$root.outerWidth(), 6420 height: this.$root.outerHeight() 6421 }); 6422 } 6423 return; 6424 } 6425 // hide sub menus on resize - on mobile do it only on orientation change 6426 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 6427 if (this.activatedItems.length) { 6428 this.activatedItems[this.activatedItems.length - 1][0].blur(); 6429 } 6430 this.menuHideAll(); 6431 } 6432 } 6433 } 6434 }); 6435 6436 $.fn.dataSM = function(key, val) { 6437 if (val) { 6438 return this.data(key + '_smartmenus', val); 6439 } 6440 return this.data(key + '_smartmenus'); 6441 } 6442 6443 $.fn.removeDataSM = function(key) { 6444 return this.removeData(key + '_smartmenus'); 6445 } 6446 6447 $.fn.smartmenus = function(options) { 6448 if (typeof options == 'string') { 6449 var args = arguments, 6450 method = options; 6451 Array.prototype.shift.call(args); 6452 return this.each(function() { 6453 var smartmenus = $(this).data('smartmenus'); 6454 if (smartmenus && smartmenus[method]) { 6455 smartmenus[method].apply(smartmenus, args); 6456 } 6457 }); 6458 } 6459 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 6460 return this.each(function() { 6461 new $.SmartMenus(this, opts); 6462 }); 6463 } 6464 6465 // default settings 6466 $.fn.smartmenus.defaults = { 6467 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 6468 mainMenuSubOffsetX: 0, // pixels offset from default position
6469 mainMenuSubOffsetY: 0, // pixels offset from default position 6470 subMenusSubOffsetX: 0, // pixels offset from default position 6471 subMenusSubOffsetY: 0, // pixels offset from default position 6472 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6473 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6474 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 6475 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 6476 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 6477 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 6478 scrollInterval: 30, // interval between each scrolling step 6479 scrollAccelerate: true, // accelerate scrolling or use a fixed step 6480 showTimeout: 250, // timeout before showing the sub menus 6481 hideTimeout: 500, // timeout before hiding the sub menus 6482 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 6483 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 6484 // don't forget to call complete() at the end of whatever you do 6485 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 6486 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 6487 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 6488 // don't forget to call complete() at the end of whatever you do 6489 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 6490 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 6491 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 6492 // (i.e. when mobile styles are used to make the sub menus collapsible) 6493 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 6494 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 6495 // (i.e. when mobile styles are used to make the sub menus collapsible) 6496 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 6497 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 6498 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 6499 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 6500 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 6501 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 6502 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 6503 bottomToTopSubMenus: false, // bottom to top display of the sub menus 6504 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 6505 }; 6506 6507})(jQuery); 6508 6509/* 6510 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 6511 * 6512 * Uses the built in easing capabilities added In jQuery 1.1 6513 * to offer multiple easing options 6514 * 6515 * TERMS OF USE - jQuery Easing 6516 * 6517 * Open source under the BSD License. 6518 * 6519 * Copyright © 2008 George McGinley Smith 6520 * All rights reserved. 6521 * 6522 * Redistribution and use in source and binary forms, with or without modification, 6523 * are permitted provided that the following conditions are met: 6524 * 6525 * Redistributions of source code must retain the above copyright notice, this list of 6526 * conditions and the following disclaimer. 6527 * Redistributions in binary form must reproduce the above copyright notice, this list 6528 * of conditions and the following disclaimer in the documentation and/or other materials 6529 * provided with the distribution. 6530 * 6531 * Neither the name of the author nor the names of contributors may be used to endorse 6532 * or promote products derived from this software without specific prior written permission. 6533 * 6534 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6535 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6536 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6537 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,087 bytes, lines 6538-6683
6538 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6539 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6540 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6541 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6542 * OF THE POSSIBILITY OF SUCH DAMAGE. 6543 * 6544*/ 6545 6546// t: current time, b: begInnIng value, c: change In value, d: duration 6547jQuery.easing['jswing'] = jQuery.easing['swing']; 6548 6549jQuery.extend( jQuery.easing, 6550{ 6551 def: 'easeOutQuad', 6552 swing: function (x, t, b, c, d) { 6553 //alert(jQuery.easing.default); 6554 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 6555 }, 6556 easeInQuad: function (x, t, b, c, d) { 6557 return c*(t/=d)*t + b; 6558 }, 6559 easeOutQuad: function (x, t, b, c, d) { 6560 return -c *(t/=d)*(t-2) + b; 6561 }, 6562 easeInOutQuad: function (x, t, b, c, d) { 6563 if ((t/=d/2) < 1) return c/2*t*t + b; 6564 return -c/2 * ((--t)*(t-2) - 1) + b; 6565 }, 6566 easeInCubic: function (x, t, b, c, d) { 6567 return c*(t/=d)*t*t + b; 6568 }, 6569 easeOutCubic: function (x, t, b, c, d) { 6570 return c*((t=t/d-1)*t*t + 1) + b; 6571 }, 6572 easeInOutCubic: function (x, t, b, c, d) { 6573 if ((t/=d/2) < 1) return c/2*t*t*t + b; 6574 return c/2*((t-=2)*t*t + 2) + b; 6575 }, 6576 easeInQuart: function (x, t, b, c, d) { 6577 return c*(t/=d)*t*t*t + b; 6578 }, 6579 easeOutQuart: function (x, t, b, c, d) { 6580 return -c * ((t=t/d-1)*t*t*t - 1) + b; 6581 }, 6582 easeInOutQuart: function (x, t, b, c, d) { 6583 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 6584 return -c/2 * ((t-=2)*t*t*t - 2) + b; 6585 }, 6586 easeInQuint: function (x, t, b, c, d) { 6587 return c*(t/=d)*t*t*t*t + b; 6588 }, 6589 easeOutQuint: function (x, t, b, c, d) { 6590 return c*((t=t/d-1)*t*t*t*t + 1) + b; 6591 }, 6592 easeInOutQuint: function (x, t, b, c, d) { 6593 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 6594 return c/2*((t-=2)*t*t*t*t + 2) + b; 6595 }, 6596 easeInSine: function (x, t, b, c, d) { 6597 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 6598 }, 6599 easeOutSine: function (x, t, b, c, d) { 6600 return c * Math.sin(t/d * (Math.PI/2)) + b; 6601 }, 6602 easeInOutSine: function (x, t, b, c, d) { 6603 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 6604 }, 6605 easeInExpo: function (x, t, b, c, d) { 6606 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 6607 }, 6608 easeOutExpo: function (x, t, b, c, d) { 6609 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 6610 }, 6611 easeInOutExpo: function (x, t, b, c, d) { 6612 if (t==0) return b; 6613 if (t==d) return b+c; 6614 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 6615 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 6616 }, 6617 easeInCirc: function (x, t, b, c, d) { 6618 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 6619 }, 6620 easeOutCirc: function (x, t, b, c, d) { 6621 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 6622 }, 6623 easeInOutCirc: function (x, t, b, c, d) { 6624 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 6625 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 6626 }, 6627 easeInElastic: function (x, t, b, c, d) { 6628 var s=1.70158;var p=0;var a=c; 6629 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6630 if (a < Math.abs(c)) { a=c; var s=p/4; } 6631 else var s = p/(2*Math.PI) * Math.asin (c/a); 6632 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6633 }, 6634 easeOutElastic: function (x, t, b, c, d) { 6635 var s=1.70158;var p=0;var a=c; 6636 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6637 if (a < Math.abs(c)) { a=c; var s=p/4; } 6638 else var s = p/(2*Math.PI) * Math.asin (c/a); 6639 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 6640 }, 6641 easeInOutElastic: function (x, t, b, c, d) { 6642 var s=1.70158;var p=0;var a=c; 6643 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 6644 if (a < Math.abs(c)) { a=c; var s=p/4; } 6645 else var s = p/(2*Math.PI) * Math.asin (c/a); 6646 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6647 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 6648 }, 6649 easeInBack: function (x, t, b, c, d, s) { 6650 if (s == undefined) s = 1.70158; 6651 return c*(t/=d)*t*((s+1)*t - s) + b; 6652 }, 6653 easeOutBack: function (x, t, b, c, d, s) { 6654 if (s == undefined) s = 1.70158; 6655 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 6656 }, 6657 easeInOutBack: function (x, t, b, c, d, s) { 6658 if (s == undefined) s = 1.70158; 6659 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 6660 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 6661 }, 6662 easeInBounce: function (x, t, b, c, d) { 6663 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 6664 }, 6665 easeOutBounce: function (x, t, b, c, d) { 6666 if ((t/=d) < (1/2.75)) { 6667 return c*(7.5625*t*t) + b; 6668 } else if (t < (2/2.75)) { 6669 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 6670 } else if (t < (2.5/2.75)) { 6671 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 6672 } else { 6673 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 6674 } 6675 }, 6676 easeInOutBounce: function (x, t, b, c, d) { 6677 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 6678 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 6679 } 6680}); 6681 6682/* 6683 *
6684 * TERMS OF USE - EASING EQUATIONS 6685 * 6686 * Open source under the BSD License. 6687 * 6688 * Copyright © 2001 Robert Penner 6689 * All rights reserved. 6690 * 6691 * Redistribution and use in source and binary forms, with or without modification, 6692 * are permitted provided that the following conditions are met: 6693 * 6694 * Redistributions of source code must retain the above copyright notice, this list of 6695 * conditions and the following disclaimer. 6696 * Redistributions in binary form must reproduce the above copyright notice, this list 6697 * of conditions and the following disclaimer in the documentation and/or other materials 6698 * provided with the distribution. 6699 * 6700 * Neither the name of the author nor the names of contributors may be used to endorse 6701 * or promote products derived from this software without specific prior written permission. 6702 * 6703 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6704 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6705 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6706 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 6707 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6708 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6709 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6710 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6711 * OF THE POSSIBILITY OF SUCH DAMAGE. 6712 * 6713 */ 6714 6715(function($, window, undefined) { 6716 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 6717 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 6718 6719 // requestAnimationFrame polyfill by Erik Möller 6720 // fixes from Paul Irish and Tino Zijdel 6721 6722 var lastTime = 0, 6723 running, 6724 animate = function (elem) { 6725 if (running) { 6726 window.requestAnimationFrame(animate, elem); 6727 jQuery.fx.tick(); 6728 } 6729 }, 6730 vendors = ['ms', 'moz', 'webkit', 'o']; 6731 6732 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 6733 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 6734 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 6735 || window[vendors[x]+'CancelRequestAnimationFrame']; 6736 } 6737 6738 if (!window.requestAnimationFrame) 6739 window.requestAnimationFrame = function(fn, element) { 6740 var currTime = new Date().getTime(), 6741 delta = currTime - lastTime, 6742 timeToCall = Math.max(0, 16 - delta); 6743 6744 var id = window.setTimeout(function() { 6745 fn(currTime + timeToCall); 6746 }, 6747 timeToCall 6748 ); 6749 6750 lastTime = currTime + timeToCall; 6751 6752 return id; 6753 }; 6754 6755 if (!window.cancelAnimationFrame) { 6756 window.cancelAnimationFrame = function(id) { 6757 clearTimeout(id); 6758 }; 6759 } 6760 6761 jQuery.fx.timer = function (timer) { 6762 if (timer() && jQuery.timers.push(timer) && !running) { 6763 running = true; 6764 animate(timer.elem); 6765 } 6766 }; 6767 6768 jQuery.fx.stop = function() { 6769 running = false; 6770 }; 6771 6772}(jQuery, this)); 6773 6774/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 6775 * Licensed under the MIT License (LICENSE.txt). 6776 * 6777 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 6778 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6779 * Thanks to: Seamus Leahy for adding deltaX and deltaY 6780 * 6781 * Version: 3.0.6 6782 * 6783 * Requires: 1.2.2+ 6784 */ 6785(function($) { 6786 var types = ['DOMMouseScroll', 'mousewheel']; 6787 if ($.event.fixHooks) { 6788 for (var i = types.length; i;) { 6789 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 6790 } 6791 } 6792 $.event.special.mousewheel = { 6793 setup: function() { 6794 if (this.addEventListener) { 6795 for (var i = types.length; i;) { 6796 this.addEventListener(types[--i], handler, false); 6797 } 6798 } else { 6799 this.onmousewheel = handler; 6800 } 6801 }, 6802 teardown: function() { 6803 if (this.removeEventListener) { 6804 for (var i = types.length; i;) { 6805 this.removeEventListener(types[--i], handler, false); 6806 } 6807 } else { 6808 this.onmousewheel = null; 6809 } 6810 } 6811 }; 6812 $.fn.extend({ 6813 mousewheel: function(fn) { 6814 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 6815 }, 6816 unmousewheel: function(fn) { 6817 return this.unbind("mousewheel", fn); 6818 } 6819 }); 6820 6821 function handler(event) { 6822 var orgEvent = event || window.event, 6823 args = [].slice.call(arguments, 1), 6824 delta = 0, 6825 returnValue = true, 6826 deltaX = 0, 6827 deltaY = 0; 6828 event = $.event.fix(orgEvent); 6829 event.type = "mousewheel"; 6830 // Old school scrollwheel delta 6831 if (orgEvent.wheelDelta) { 6832 delta = orgEvent.wheelDelta / 120; 6833 } 6834 if (orgEvent.detail) { 6835 delta = -orgEvent.detail / 3; 6836 } 6837 // New school multidimensional scroll (touchpads) deltas 6838 deltaY = delta; 6839 // Gecko 6840 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 6841 deltaY = 0; 6842 deltaX = -1 * delta; 6843 } 6844 // Webkit 6845 if (orgEvent.wheelDeltaY !== undefined) { 6846 deltaY = orgEvent.wheelDeltaY / 120; 6847 } 6848 if (orgEvent.wheelDeltaX !== undefined) { 6849 deltaX = -1 * orgEvent.wheelDeltaX / 120; 6850 } 6851 // Add event and delta to the front of the arguments 6852 args.unshift(event, delta, deltaX, deltaY); 6853 return ($.event.dispatch || $.event.handle).apply(this, args); 6854 } 6855})(jQuery); 6856 6857/** 6858 * jQuery iLightBox - Revolutionary Lightbox Plugin 6859 * http://www.ilightbox.net/ 6860 * 6861 * @version: 2.2.4 - October 14, 2017 6862 * 6863 * @author: iProDev (Hemn Chawroka) 6864 * http://www.iprodev.com/ 6865 * 6866 */ 6867(function($, window, undefined) { 6868 6869 var extensions = { 6870 flash: ['swf'], 6871 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 6872 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 6873 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 6874 }, 6875 6876 // Global DOM elements 6877 $win = $(window), 6878 $doc = $(document), 6879
6880 // Support indicators 6881 browser, 6882 transform, 6883 gpuAcceleration, 6884 fullScreenApi = '', 6885 userAgent = navigator.userAgent || navigator.vendor || window.opera, 6886 supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)), 6887 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)), 6888 6889 // Events 6890 clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox", 6891 touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 6892 touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 6893 touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 6894 6895 // Math shorthands 6896 abs = Math.abs, 6897 sqrt = Math.sqrt, 6898 round = Math.round, 6899 max = Math.max, 6900 min = Math.min, 6901 floor = Math.floor, 6902 random = Math.random, 6903 6904 pluginspages = { 6905 quicktime: 'http://www.apple.com/quicktime/download', 6906 flash: 'http://www.adobe.com/go/getflash' 6907 }, 6908 6909 iLightBox = function(el, options, items, instant) { 6910 var iL = this; 6911 6912 iL.options = options, 6913 iL.selector = el.selector || el, 6914 iL.context = el.context, 6915 iL.instant = instant; 6916 6917 if (items.length < 1) iL.attachItems(); 6918 else iL.items = items; 6919 6920 iL.vars = { 6921 total: iL.items.length, 6922 start: 0, 6923 current: null, 6924 next: null, 6925 prev: null, 6926 BODY: $('body'), 6927 loadRequests: 0, 6928 overlay: $('<div class="ilightbox-overlay"></div>'), 6929 loader: $('<div class="ilightbox-loader"><div></div></div>'), 6930 toolbar: $('<div class="ilightbox-toolbar"></div>'), 6931 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 6932 title: $('<div class="ilightbox-title"></div>'), 6933 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 6934 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 6935 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 6936 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 6937 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 6938 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6939 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6940 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6941 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 6942 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
6943 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>'), 6944 thumbs: false, 6945 nextLock: false, 6946 prevLock: false, 6947 hashLock: false, 6948 isMobile: false, 6949 mobileMaxWidth: 980, 6950 isInFullScreen: false, 6951 isSwipe: false, 6952 mouseID: 0, 6953 cycleID: 0, 6954 isPaused: 0, 6955 captionHeight: 39, 6956 }; 6957 6958 // Hideable elements with mousemove event 6959 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 6960 6961 iL.normalizeItems(); 6962 6963 //Check necessary plugins 6964 iL.availPlugins(); 6965 6966 //Set startFrom 6967 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 6968 6969 //If randomStart 6970 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 6971 iL.vars.start = iL.options.startFrom; 6972 6973 if (instant) iL.instantCall(); 6974 else iL.patchItemsEvents(); 6975 6976 if (iL.options.linkId) { 6977 iL.hashChangeHandler(); 6978 $win.iLightBoxHashChange(function() { 6979 iL.hashChangeHandler(); 6980 }); 6981 } 6982 6983 if (supportTouch) { 6984 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 6985 replace = "itap"; 6986 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 6987 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 6988 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 6989 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 6990 } 6991 6992 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 6993 $.extend(iL.options.styles, { 6994 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6995 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6996 nextOpacity: 0, 6997 prevOpacity: 0 6998 }); 6999 } 7000 }; 7001 7002 //iLightBox helpers 7003 iLightBox.prototype = { 7004 showLoader: function() { 7005 var iL = this; 7006 iL.vars.loadRequests += 1; 7007 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7008 //top: '-30px' 7009 opacity: '1' 7010 }, iL.options.show.speed, 'easeOutCirc'); 7011 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 7012 //left: '-30px' 7013 opacity: '1' 7014 }, iL.options.show.speed, 'easeOutCirc'); 7015 }, 7016 7017 hideLoader: function() { 7018 var iL = this; 7019 iL.vars.loadRequests -= 1; 7020 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 7021 if (iL.options.path.toLowerCase() == "horizontal") { 7022 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7023 //top: '-192px' 7024 opacity: '0' 7025 }, iL.options.show.speed, 'easeInCirc'); 7026 } else { 7027 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 7028 //left: '-192px' 7029 opacity: '0' 7030 }, iL.options.show.speed, 'easeInCirc'); 7031 } 7032 }, 7033 7034 createUI: function() { 7035 var iL = this; 7036 7037 iL.ui = { 7038 currentElement: iL.vars.holder, 7039 nextElement: iL.vars.nextPhoto, 7040 prevElement: iL.vars.prevPhoto, 7041 currentItem: iL.vars.current, 7042 nextItem: iL.vars.next, 7043 prevItem: iL.vars.prev, 7044 hide: function() { 7045 iL.closeAction(); 7046 }, 7047 refresh: function() { 7048 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7049 }, 7050 fullscreen: function() { 7051 iL.fullScreenAction(); 7052 } 7053 }; 7054 }, 7055 7056 attachItems: function() { 7057 var iL = this, 7058 itemsObject = new Array(), 7059 items = new Array(); 7060 7061 $(iL.selector, iL.context).each(function() { 7062 var t = $(this), 7063 URL = t.attr(iL.options.attr) || null, 7064 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 7065 caption = t.data('caption'), 7066 title = t.data('title'), 7067 type = t.data('type') || getTypeByExtension(URL), 7068 clone = t.data('lbox-clone') || false; 7069 7070 if (t.data('lbox-clone') != undefined) return; 7071 7072 //Uncode addition ##START## 7073 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 7074 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 7075 URL_i, 7076 URLS_LENGHT = ALBUM_URLS.length; 7077 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 7078 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 7079 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 7080 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 7081 items.push({ 7082 URL: ALBUM_URLS[URL_i].url, 7083 caption: ALBUM_URLS[URL_i].caption, 7084 title: ALBUM_URLS[URL_i].title, 7085 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 7086 options: item_opts, 7087 clone: clone 7088 }); 7089 var newT = t; 7090 newT.attr('href',ALBUM_URLS[URL_i].url); 7091 if (!iL.instant) itemsObject.push(newT); 7092 } 7093 } 7094 } else { 7095 //Uncode addition ##END## 7096 items.push({ 7097 URL: URL, 7098 caption: caption, 7099 title: title, 7100 type: type, 7101 options: options, 7102 clone: clone 7103 }); 7104 } 7105 7106 7107 if (iL.vars != undefined) iL.vars.total = items.length; 7108 7109 if (!iL.instant) itemsObject.push(t); 7110 }); 7111 7112 iL.items = items, 7113 iL.itemsObject = itemsObject; 7114 7115 }, 7116 7117 normalizeItems: function() { 7118 var iL = this, 7119 newItems = new Array(); 7120 7121 $.each(iL.items, function(key, val) { 7122 7123 if (typeof val == "string") val = { 7124 url: val 7125 }; 7126 7127 var URL = val.url || val.URL || null, 7128 options = val.options || {}, 7129 caption = val.caption || null, 7130 title = val.title || null, 7131 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 7132 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 7133 7134 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
7135 options.videoType = options.videoType || null, 7136 options.skin = options.skin || iL.options.skin, 7137 options.width = options.width || null, 7138 options.height = options.height || null, 7139 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 7140 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 7141 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 7142 7143 if (type == "video") { 7144 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 7145 7146 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 7147 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 7148 options.html5video.preload = options.html5video.preload || "metadata"; 7149 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 7150 } 7151 7152 if (!options.width || !options.height) { 7153 if (type == "video") options.width = 1280, options.height = 720; 7154 else if (type == "iframe") options.width = '100%', options.height = '90%'; 7155 else if (type == "flash") options.width = 1280, options.height = 720; 7156 } 7157 7158 delete val.url; 7159 val.index = key; 7160 val.URL = URL; 7161 val.caption = caption; 7162 val.title = title; 7163 val.type = type; 7164 val.options = options; 7165 val.ext = ext; 7166 7167 newItems.push(val); 7168 }); 7169 7170 iL.items = newItems; 7171 }, 7172 7173 instantCall: function() { 7174 var iL = this, 7175 key = iL.vars.start; 7176 7177 iL.vars.current = key; 7178 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 7179 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 7180 7181 iL.addContents(); 7182 iL.patchEvents(); 7183 }, 7184 7185 addContents: function() { 7186 var iL = this, 7187 vars = iL.vars, 7188 opts = iL.options, 7189 viewport = getViewport(), 7190 path = opts.path.toLowerCase(), 7191 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 7192 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 7193 }), 7194 needRecognition = recognizingItems.length > 0; 7195 7196 if (opts.mobileOptimizer && !opts.innerToolbar) 7197 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7198 7199 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 7200 7201 if (opts.linkId) 7202 vars.overlay[0].setAttribute('linkid', opts.linkId); 7203 7204 //Add Toolbar Buttons 7205 if (opts.controls.toolbar) { 7206 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 7207 if (opts.controls.fullscreen) 7208 vars.toolbar.append(vars.fullScreenButton); 7209 if (opts.controls.slideshow) 7210 vars.toolbar.append(vars.innerPlayButton); 7211 if (vars.total > 1) 7212 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 7213 } 7214 7215 //Append elements to body 7216 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 7217 7218 if (!opts.innerToolbar) 7219 vars.BODY.append(vars.toolbar); 7220 if (opts.controls.arrows) 7221 vars.BODY.append(vars.nextButton).append(vars.prevButton); 7222 7223 if (opts.controls.thumbnail && vars.total > 1) { 7224 vars.BODY.append(vars.thumbnails); 7225 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 7226 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 7227 vars.thumbs = true; 7228 } 7229 7230 //Configure loader and arrows 7231 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 7232 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 7233 } : { 7234 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 7235 }; 7236 vars.loader.addClass(opts.skin).css(loaderCss); 7237 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 7238 if (path == "horizontal") 7239 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 7240 7241 // Configure arrow buttons 7242 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7243 7244 if (!opts.infinite) { 7245 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 7246 7247 if (vars.current == 0) 7248 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 7249 if (vars.current >= vars.total - 1) 7250 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 7251 } 7252 7253 if (opts.show.effect) { 7254 vars.overlay.stop().fadeIn(opts.show.speed); 7255 vars.toolbar.stop().fadeIn(opts.show.speed); 7256 } else { 7257 vars.overlay.show(); 7258 vars.toolbar.show(); 7259 } 7260 7261 var length = recognizingItems.length; 7262 if (needRecognition) { 7263 iL.showLoader(); 7264 7265 $.each(recognizingItems, function(key, val) { 7266 var resultFnc = function(result) { 7267 var key = -1, 7268 filter = iL.items.filter(function(e, i, arr) { 7269 if (e.URL == result.url) 7270 key = i; 7271 7272 return e.URL == result.url; 7273 }), 7274 self = iL.items[key]; 7275 7276 if (result) 7277 $.extend(true, self, { 7278 URL: result.source, 7279 type: result.type, 7280 recognized: true, 7281 options: { 7282 html5video: result.html5video, 7283 width: (result.type == "image") ? 0 : (result.width || self.width), 7284 height: (result.type == "image") ? 0 : (result.height || self.height), 7285 thumbnail: self.options.thumbnail || result.thumbnail 7286 } 7287 }); 7288 7289 length--; 7290 7291 if (length == 0) { 7292 iL.hideLoader(); 7293 7294 vars.dontGenerateThumbs = false;
7295 iL.generateThumbnails(); 7296 7297 if (opts.show.effect) 7298 setTimeout(function() { 7299 iL.generateBoxes(); 7300 }, opts.show.speed); 7301 else 7302 iL.generateBoxes(); 7303 } 7304 }; 7305 7306 iL.ogpRecognition(this, resultFnc); 7307 }); 7308 } 7309 else { 7310 if (opts.show.effect) 7311 setTimeout(function() { 7312 iL.generateBoxes(); 7313 }, opts.show.speed); 7314 else 7315 iL.generateBoxes(); 7316 } 7317 7318 iL.createUI(); 7319 7320 window.iLightBox = { 7321 close: function() { 7322 iL.closeAction(); 7323 }, 7324 fullscreen: function() { 7325 iL.fullScreenAction(); 7326 }, 7327 moveNext: function() { 7328 iL.moveTo('next'); 7329 }, 7330 movePrev: function() { 7331 iL.moveTo('prev'); 7332 }, 7333 goTo: function(index) { 7334 iL.goTo(index); 7335 }, 7336 refresh: function() { 7337 iL.refresh(); 7338 }, 7339 reposition: function() { 7340 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7341 }, 7342 setOption: function(options) { 7343 iL.setOption(options); 7344 }, 7345 destroy: function() { 7346 iL.closeAction(); 7347 iL.dispatchItemsEvents(); 7348 } 7349 }; 7350 7351 if (opts.linkId) { 7352 vars.hashLock = true; 7353 window.location.hash = opts.linkId + '/' + vars.current; 7354 setTimeout(function() { 7355 vars.hashLock = false; 7356 }, 55); 7357 } 7358 7359 if (!opts.slideshow.startPaused) { 7360 iL.resume(); 7361 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 7362 } 7363 7364 //Trigger the onOpen callback 7365 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 7366 }, 7367 7368 loadContent: function(obj, opt, speed) { 7369 var iL = this, 7370 holder, item; 7371 7372 iL.createUI(); 7373 7374 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 7375 7376 if (opt == 'current') { 7377 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 7378 else iL.vars.lockWheel = false; 7379 7380 if (!obj.options.swipe) iL.vars.lockSwipe = true; 7381 else iL.vars.lockSwipe = false; 7382 } 7383 7384 switch (opt) { 7385 case 'current': 7386 holder = iL.vars.holder, item = iL.vars.current; 7387 break; 7388 case 'next': 7389 holder = iL.vars.nextPhoto, item = iL.vars.next; 7390 break; 7391 case 'prev': 7392 holder = iL.vars.prevPhoto, item = iL.vars.prev; 7393 break; 7394 } 7395 7396 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 7397 $('div.ilightbox-inner-toolbar', holder).remove(); 7398 7399 if (obj.title || iL.options.innerToolbar) { 7400 var innerToolbar = iL.vars.innerToolbar.clone(); 7401 if (obj.title && iL.options.show.title) { 7402 var title = iL.vars.title.clone(); 7403 title.empty().html(obj.title); 7404 innerToolbar.append(title); 7405 } 7406 if (iL.options.innerToolbar) { 7407 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 7408 } 7409 holder.prepend(innerToolbar); 7410 } 7411 7412 //console.warn('loadContent', arguments); 7413 7414 iL.loadSwitcher(obj, holder, item, opt); 7415 }, 7416 7417 loadSwitcher: function(obj, holder, item, opt) { 7418 var iL = this, 7419 opts = iL.options, 7420 api = { 7421 element: holder, 7422 position: item 7423 }; 7424 7425 switch (obj.type) { 7426 case 'image': 7427 //Trigger the onBeforeLoad callback 7428 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7429 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7430 7431 iL.loadImage(obj.URL, function(img) { 7432 //Trigger the onAfterLoad callback 7433 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7434 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7435 7436 var width = (img) ? img.width : 400, 7437 height = (img) ? img.height : 200; 7438 7439 holder.data({ 7440 naturalWidth: width, 7441 naturalHeight: height 7442 }); 7443 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 7444 7445 //Trigger the onRender callback 7446 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7447 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7448 7449 iL.configureHolder(obj, opt, holder); 7450 }); 7451 7452 break; 7453
7454 case 'video': 7455 holder.data({ 7456 naturalWidth: obj.options.width, 7457 naturalHeight: obj.options.height 7458 }); 7459 7460 if (opt === 'current') { 7461 iL.addContent(holder, obj); 7462 7463 //Trigger the onRender callback 7464 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7465 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7466 } else { 7467 $('div.ilightbox-container', holder).empty(); 7468 } 7469 7470 iL.configureHolder(obj, opt, holder); 7471 7472 break; 7473 7474 case 'iframe': 7475 //iL.showLoader(); 7476 holder.data({ 7477 naturalWidth: obj.options.width, 7478 naturalHeight: obj.options.height 7479 }); 7480 7481 iL.configureHolder(obj, opt, holder); 7482 7483 if (opt === 'current') { 7484 var el = iL.addContent(holder, obj); 7485 7486 //Trigger the onRender callback 7487 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7488 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7489 7490 //Trigger the onBeforeLoad callback 7491 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7492 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7493 7494 el.bind('load', function() { 7495 //Trigger the onAfterLoad callback 7496 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7497 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7498 7499 //iL.hideLoader(); 7500 el.unbind('load'); 7501 }); 7502 } else { 7503 $('div.ilightbox-container', holder).empty(); 7504 } 7505 7506 break; 7507 7508 case 'inline': 7509 var el = $(obj.URL), 7510 content = iL.addContent(holder, obj), 7511 images = findImageInElement(holder); 7512 7513 holder.data({ 7514 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7515 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7516 }); 7517 content.children().eq(0).show(); 7518 7519 //Trigger the onRender callback 7520 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7521 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7522 7523 //Trigger the onBeforeLoad callback 7524 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7525 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7526 7527 iL.loadImage(images, function() { 7528 //Trigger the onAfterLoad callback 7529 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7530 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7531 7532 iL.configureHolder(obj, opt, holder); 7533 }); 7534 7535 break; 7536 7537 case 'flash': 7538 var el = iL.addContent(holder, obj); 7539 7540 holder.data({ 7541 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7542 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7543 }); 7544 7545 //Trigger the onRender callback 7546 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7547 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7548 7549 iL.configureHolder(obj, opt, holder); 7550 7551 break; 7552 7553 case 'ajax': 7554 var ajax = obj.options.ajax || {}; 7555 //Trigger the onBeforeLoad callback 7556 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7557 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7558 7559 iL.showLoader(); 7560 $.ajax({ 7561 url: obj.URL || opts.ajaxSetup.url, 7562 data: ajax.data || null, 7563 dataType: ajax.dataType || "html", 7564 type: ajax.type || opts.ajaxSetup.type, 7565 cache: ajax.cache || opts.ajaxSetup.cache, 7566 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 7567 global: ajax.global || opts.ajaxSetup.global, 7568 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 7569 username: ajax.username || opts.ajaxSetup.username, 7570 password: ajax.password || opts.ajaxSetup.password, 7571 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 7572 complete: ajax.complete || opts.ajaxSetup.complete, 7573 success: function(data, textStatus, jqXHR) { 7574 iL.hideLoader(); 7575 7576 var el = $(data), 7577 container = $('div.ilightbox-container', holder), 7578 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 7579 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 7580 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 7581 'overflow': 'hidden' 7582 } : {}; 7583 7584 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 7585 holder.show().data({
7586 naturalWidth: (elWidth || container.outerWidth()), 7587 naturalHeight: (elHeight || container.outerHeight()) 7588 }).hide(); 7589 7590 //Trigger the onRender callback 7591 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7592 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7593 7594 var images = findImageInElement(holder); 7595 iL.loadImage(images, function() { 7596 //Trigger the onAfterLoad callback 7597 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7598 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7599 7600 iL.configureHolder(obj, opt, holder); 7601 }); 7602 7603 opts.ajaxSetup.success(data, textStatus, jqXHR); 7604 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 7605 }, 7606 error: function(jqXHR, textStatus, errorThrown) { 7607 //Trigger the onAfterLoad callback 7608 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7609 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7610 7611 iL.hideLoader(); 7612 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 7613 iL.configureHolder(obj, opt, holder); 7614 7615 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 7616 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 7617 } 7618 }); 7619 7620 break; 7621 7622 case 'html': 7623 var object = obj.URL, 7624 el 7625 container = $('div.ilightbox-container', holder); 7626 7627 if (object[0].nodeName) el = object.clone(); 7628 else { 7629 var dom = $(object); 7630 if (dom.selector) el = $('<div>' + dom + '</div>'); 7631 else el = dom; 7632 } 7633 7634 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 7635 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 7636 7637 iL.addContent(holder, obj); 7638 7639 el.appendTo(document.documentElement).hide(); 7640 7641 //Trigger the onRender callback 7642 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7643 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7644 7645 var images = findImageInElement(holder); 7646 7647 //Trigger the onBeforeLoad callback 7648 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7649 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7650 7651 iL.loadImage(images, function() { 7652 //Trigger the onAfterLoad callback 7653 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7654 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7655 7656 holder.show().data({ 7657 naturalWidth: (elWidth || container.outerWidth()), 7658 naturalHeight: (elHeight || container.outerHeight()) 7659 }).hide(); 7660 el.remove(); 7661 7662 iL.configureHolder(obj, opt, holder); 7663 }); 7664 7665 break; 7666 } 7667 }, 7668 7669 configureHolder: function(obj, opt, holder) { 7670 var iL = this, 7671 vars = iL.vars, 7672 opts = iL.options; 7673 7674 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 7675 7676 if (opt == "current") 7677 var item = vars.current; 7678 else if (opt == "next") 7679 var opacity = opts.styles.nextOpacity, 7680 item = vars.next; 7681 else 7682 var opacity = opts.styles.prevOpacity, 7683 item = vars.prev; 7684 7685 var api = { 7686 element: holder, 7687 position: item 7688 }; 7689 7690 iL.items[item].options.width = iL.items[item].options.width || 0, 7691 iL.items[item].options.height = iL.items[item].options.height || 0; 7692 7693 if (opt == "current") { 7694 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 7695 holder.css(transform, ''); 7696 if (obj.caption) { 7697 iL.setCaption(obj, holder); 7698 var caption = $('div.ilightbox-caption', holder), 7699 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 7700 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7700Speed); 7701 } 7702 7703 var social = obj.options.social; 7704 if (social) { 7705 iL.setSocial(social, obj.URL, holder); 7706 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 7707 } 7708 7709 //Generate thumbnails 7710 iL.generateThumbnails(); 7711 7712 //Trigger the onShow callback 7713 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7714 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7715 }); 7716 else { 7717 holder.show(); 7718 7719 //Generate thumbnails 7720 iL.generateThumbnails(); 7721 7722 //Trigger the onShow callback 7723 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7724 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7725 } 7726 } else { 7727 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 7728 if (opt == "next") vars.nextLock = false; 7729 else vars.prevLock = false; 7730 7731 //Generate thumbnails 7732 iL.generateThumbnails(); 7733 7734 //Trigger the onShow callback 7735 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7736 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7737 }); 7738 else { 7739 holder.css({ 7740 opacity: opacity 7741 }).show(); 7742 if (opt == "next") vars.nextLock = false; 7743 else vars.prevLock = false; 7744 7745 //Generate thumbnails 7746 iL.generateThumbnails(); 7747 7748 //Trigger the onShow callback 7749 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7750 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7751 } 7752 } 7753 7754 setTimeout(function() { 7755 iL.repositionPhoto(); 7756 }, 0); 7757 }, 7758 7759 generateBoxes: function() { 7760 var iL = this, 7761 vars = iL.vars, 7762 opts = iL.options; 7763 7764 if (opts.infinite && vars.total >= 3) { 7765 if (vars.current == vars.total - 1) vars.next = 0; 7766 if (vars.current == 0) vars.prev = vars.total - 1; 7767 } else opts.infinite = false; 7768 7769 //UNCODE addition 7770 if ( typeof iL.items[vars.current] == 'undefined' ) 7771 vars.current = 0; 7772 7773 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 7774 7775 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 7776 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 7777 }, 7778 7779 generateThumbnails: function() { 7780 var iL = this, 7781 vars = iL.vars, 7782 opts = iL.options, 7783 timeOut = null; 7784 7785 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 7786 var thumbnails = vars.thumbnails, 7787 container = $('div.ilightbox-thumbnails-container', thumbnails), 7788 grid = $('div.ilightbox-thumbnails-grid', container), 7789 i = 0; 7790 7791 grid.removeAttr('style').empty(); 7792 7793 $.each(iL.items, function(key, val) { 7794 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 7795 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 7796 thumb = val.options.thumbnail, 7797 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 7798 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 7799 7800 thumbnail.css({ 7801 opacity: 0 7802 }).addClass(isActive); 7803 7804 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 7805 icon.addClass('ilightbox-thumbnail-video'); 7806 thumbnail.append(icon); 7807 } else if (val.options.icon) { 7808 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 7809 thumbnail.append(icon); 7810 } 7811 7812 if (thumb) iL.loadImage(thumb, function(img) { 7813 i++; 7814 if (img) thumbnail.data({ 7815 naturalWidth: img.width, 7816 naturalHeight: img.height 7817 }).append('<img src="' + thumb + '" border="0" />'); 7818 else thumbnail.data({ 7819 naturalWidth: opts.thumbnails.maxWidth, 7820 naturalHeight: opts.thumbnails.maxHeight 7821 }); 7822 7823 clearTimeout(timeOut); 7824 timeOut = setTimeout(function() { 7825 iL.positionThumbnails(thumbnails, container, grid); 7826 }, 20); 7827 setTimeout(function() { 7828 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 7829 }, i * 20); 7830 }); 7831 7832 grid.append(thumbnail); 7833 }); 7834 iL.vars.dontGenerateThumbs = true; 7835 } 7836 }, 7837
7838 positionThumbnails: function(thumbnails, container, grid) { 7839 var iL = this, 7840 vars = iL.vars, 7841 opts = iL.options, 7842 viewport = getViewport(), 7843 path = opts.path.toLowerCase(); 7844 7845 if (!thumbnails) thumbnails = vars.thumbnails; 7846 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 7847 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 7848 7849 var thumbs = $('.ilightbox-thumbnail', grid), 7850 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 7851 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 7852 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 7853 gridHeight = (path == 'horizontal') ? heightAvail : 0, 7854 active = $('.ilightbox-active', grid), 7855 gridCss = {}, 7856 css = {}; 7857 7858 if (arguments.length < 3) { 7859 thumbs.css({ 7860 opacity: opts.thumbnails.normalOpacity 7861 }); 7862 active.css({ 7863 opacity: opts.thumbnails.activeOpacity 7864 }); 7865 } 7866 7867 thumbs.each(function(i) { 7868 var t = $(this), 7869 data = t.data(), 7870 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 7871 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 7872 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 7873 7874 t.css({ 7875 width: dims.width, 7876 height: dims.height 7877 }); 7878 if (path == 'horizontal') t.css({ 7879 'float': 'left' 7880 }); 7881 7882 (path == 'horizontal') ? ( 7883 gridWidth += t.outerWidth() 7884 ) : ( 7885 gridHeight += t.outerHeight() 7886 ); 7887 }); 7888 7889 gridCss = { 7890 width: gridWidth, 7891 height: gridHeight 7892 }; 7893 7894 grid.css(gridCss); 7895 7896 gridCss = {}; 7897 7898 var gridOffset = grid.offset(), 7899 activeOffset = (active.length) ? active.offset() : { 7900 top: parseInt(heightAvail / 2), 7901 left: parseInt(widthAvail / 2) 7902 }; 7903 7904 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 7905 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 7906 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 7907 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 7908 7909 (path == 'horizontal') ? ( 7910 gridCss.top = 0, 7911 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 7912 ) : ( 7913 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 7914 gridCss.left = 0 7915 ); 7916 7917 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 7918 else grid.css(gridCss); 7919 }, 7920 7921 loadImage: function(image, callback) { 7922 if (!$.isArray(image)) image = [image]; 7923 7924 var iL = this, 7925 length = image.length; 7926 7927 if (length > 0) { 7928 iL.showLoader(); 7929 $.each(image, function(index, value) { 7930 var img = new Image(); 7931 img.onload = function() { 7932 length -= 1; 7933 if (length == 0) { 7934 iL.hideLoader(); 7935 callback(img); 7936 } 7937 }; 7938 img.onerror = img.onabort = function() { 7939 length -= 1; 7940 if (length == 0) { 7941 iL.hideLoader(); 7942 callback(false); 7943 } 7944 }; 7945 img.src = image[index]; 7946 }); 7947 } else callback(false); 7948 }, 7949 7950 patchItemsEvents: function() { 7951 var iL = this, 7952 vars = iL.vars, 7953 clickEvent = supportTouch ? "itap.iL" : "click.iL", 7954 vEvent = supportTouch ? "click.iL" : "itap.iL"; 7955 7956 if (iL.context && iL.selector) { 7957 var $items = $(iL.selector, iL.context); 7958 7959 $(iL.context).on(clickEvent, iL.selector, function() { 7960 var $this = $(this), 7961 //UNCODE addition 7962 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 7963 if (UNCODE.isMobile) { 7964 var isCarousel = $this.closest('.owl-carousel'); 7965 if (isCarousel.length) { 7966 if (isCarousel.hasClass('owl-translating')) return false; 7967 } 7968 } 7969 7970 vars.current = key; 7971 vars.next = iL.items[key + 1] ? key + 1 : null; 7972 vars.prev = iL.items[key - 1] ? key - 1 : null; 7973 7974 //UNCODE addition 7975 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 7976 return false;
7977 7978 iL.addContents(); 7979 iL.patchEvents(); 7980 7981 return false; 7982 }).on(vEvent, iL.selector, function() { 7983 return false; 7984 }); 7985 } else 7986 $.each(iL.itemsObject, function(key, val) { 7987 val.on(clickEvent, function() { 7988 vars.current = key; 7989 vars.next = iL.items[key + 1] ? key + 1 : null; 7990 vars.prev = iL.items[key - 1] ? key - 1 : null; 7991 7992 iL.addContents(); 7993 iL.patchEvents(); 7994 7995 return false; 7996 }).on(vEvent, function() { 7997 return false; 7998 }); 7999 }); 8000 }, 8001 8002 dispatchItemsEvents: function() { 8003 var iL = this, 8004 vars = iL.vars, 8005 opts = iL.options; 8006 8007 if (iL.context && iL.selector) 8008 $(iL.context).off('.iL', iL.selector); 8009 else 8010 $.each(iL.itemsObject, function(key, val) { 8011 val.off('.iL'); 8012 }); 8013 }, 8014 8015 refresh: function() { 8016 var iL = this; 8017 8018 iL.dispatchItemsEvents(); 8019 iL.attachItems(); 8020 iL.normalizeItems(); 8021 iL.patchItemsEvents(); 8022 }, 8023 8024 patchEvents: function() { 8025 var iL = this, 8026 vars = iL.vars, 8027 opts = iL.options, 8028 path = opts.path.toLowerCase(), 8029 holders = $('.ilightbox-holder'), 8030 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 8031 durationThreshold = 1000, 8032 horizontalDistanceThreshold = 8033 verticalDistanceThreshold = 100, 8034 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 8035 8036 $win.bind('resize.iLightBox', function() { 8037 var viewport = getViewport(); 8038 8039 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 8040 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 8041 8042 iL.repositionPhoto(null); 8043 if (supportTouch) { 8044 clearTimeout(vars.setTime); 8045 vars.setTime = setTimeout(function() { 8046 var scrollTop = getScrollXY().y; 8047 window.scrollTo(0, scrollTop - 30); 8048 window.scrollTo(0, scrollTop + 30); 8049 window.scrollTo(0, scrollTop); 8050 }, 2000); 8051 } 8052 if (vars.thumbs) iL.positionThumbnails(); 8053 }).bind('keydown.iLightBox', function(event) { 8054 if (opts.controls.keyboard) { 8055 switch (event.keyCode) { 8056 case 13: 8057 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 8058 break; 8059 case 27: 8060 if (opts.keyboard.esc) iL.closeAction(); 8061 break; 8062 case 37: 8063 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 8064 break; 8065 case 38: 8066 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 8067 break; 8068 case 39: 8069 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 8070 break; 8071 case 40: 8072 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 8073 break; 8074 } 8075 } 8076 }); 8077 8078 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 8079 iL.doFullscreen(); 8080 }); 8081 8082 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 8083 return arr.lastIndexOf(e) === i; 8084 }), 8085 holderEvents = ""; 8086 8087 $.each(holderEventsArr, function(key, val) { 8088 if (key != 0) holderEvents += ' '; 8089 holderEvents += val; 8090 }); 8091 8092 $doc.on(clickEvent, '.ilightbox-overlay', function() { 8093 if (opts.overlay.blur) iL.closeAction(); 8094 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 8095 iL.moveTo('next'); 8096 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 8097 iL.moveTo('prev'); 8098 }).on(clickEvent, '.ilightbox-thumbnail', function() { 8099 var t = $(this), 8100 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 8101 index = thumbs.index(t); 8102 8103 if (index != vars.current) iL.goTo(index); 8104 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8105 var caption = $('div.ilightbox-caption', vars.holder), 8106 social = $('div.ilightbox-social', vars.holder), 8107 fadeSpeed = opts.effects.fadeSpeed; 8108 8109 if (vars.nextLock || vars.prevLock) { 8110 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 8111 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 8112 8113 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 8114 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 8115 } else { 8116 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 8117 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 8118 8119 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 8120 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 8121 } 8122 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 8123 if (e.type == 'mouseenter') vars.lockWheel = true; 8124 else vars.lockWheel = false;
8125 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 8126 var t = $(this); 8127 8128 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 8129 else if (t.hasClass('ilightbox-play')) { 8130 iL.resume(); 8131 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 8132 } else if (t.hasClass('ilightbox-pause')) { 8133 iL.pause(); 8134 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 8135 } else iL.closeAction(); 8136 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 8137 // prevent scrolling 8138 e.preventDefault(); 8139 }); 8140 8141 function mouseMoveHandler(e) { 8142 if (!vars.isMobile) { 8143 if (!vars.mouseID) { 8144 vars.hideableElements.show(); 8145 } 8146 8147 vars.mouseID = clearTimeout(vars.mouseID); 8148 8149 if (buttonsArray.indexOf(e.target) === -1) 8150 vars.mouseID = setTimeout(function() { 8151 vars.hideableElements.hide(); 8152 vars.mouseID = clearTimeout(vars.mouseID); 8153 }, 3000); 8154 } 8155 } 8156 8157 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 8158 8159 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8160 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 8161 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 8162 }); 8163 8164 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'); 8165 8166 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 8167 if (!vars.lockWheel) { 8168 event.preventDefault(); 8169 if (delta < 0) iL.moveTo('next'); 8170 else if (delta > 0) iL.moveTo('prev'); 8171 } 8172 }); 8173 8174 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 8175 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 8176 8177 vars.BODY.addClass('ilightbox-closedhand'); 8178 8179 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 8180 scrollTop = $doc.scrollTop(), 8181 scrollLeft = $doc.scrollLeft(), 8182 offsets = [ 8183 holders.eq(0).offset(), 8184 holders.eq(1).offset(), 8185 holders.eq(2).offset() 8186 ], 8187 offSet = [{ 8188 top: offsets[0].top - scrollTop, 8189 left: offsets[0].left - scrollLeft 8190 }, { 8191 top: offsets[1].top - scrollTop, 8192 left: offsets[1].left - scrollLeft 8193 }, { 8194 top: offsets[2].top - scrollTop, 8195 left: offsets[2].left - scrollLeft 8196 }], 8197 start = { 8198 time: (new Date()).getTime(), 8199 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8200 }, 8201 stop; 8202 8203 function moveEachHandler(i) { 8204 var t = $(this), 8205 offset = offSet[i], 8206 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 8207 8208 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 8209 } 8210 8211 function moveHandler(event) { 8212 8213 if (!start) return; 8214 8215 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 8216 8217 stop = { 8218 time: (new Date()).getTime(), 8219 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8220 }; 8221 8222 holders.each(moveEachHandler); 8223 8224 // prevent scrolling 8225 event.preventDefault(); 8226 } 8227 8228 function repositionHolders() { 8229 holders.each(function() { 8230 var t = $(this), 8231 offset = t.data('offset') || { 8232 top: t.offset().top - scrollTop, 8233 left: t.offset().left - scrollLeft 8234 }, 8235 top = offset.top, 8236 left = offset.left; 8237 8238 t.css(transform, gpuAcceleration).stop().animate({ 8239 top: top, 8240 left: left 8241 }, 500, 'easeOutCirc', function() { 8242 t.css(transform, ''); 8243 }); 8244 }); 8245 } 8246 8247 holders.bind(touchMoveEvent, moveHandler); 8248 $doc.one(touchStopEvent, function(event) { 8249 holders.unbind(touchMoveEvent, moveHandler); 8250 8251 vars.BODY.removeClass('ilightbox-closedhand'); 8252 8253 if (start && stop) { 8254 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 8255 if (start.coords[0] > stop.coords[0]) { 8256 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8257 else { 8258 vars.isSwipe = true; 8259 iL.moveTo('next'); 8260 } 8261 } else { 8262 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8263 else { 8264 vars.isSwipe = true; 8265 iL.moveTo('prev'); 8266 } 8267 } 8268 } 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) { 8269 if (start.coords[1] > stop.coords[1]) { 8270 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8271 else { 8272 vars.isSwipe = true; 8273 iL.moveTo('next'); 8274 } 8275 } else { 8276 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8277 else { 8278 vars.isSwipe = true; 8279 iL.moveTo('prev'); 8280 } 8281 } 8282 } else repositionHolders(); 8283 } 8284 start = stop = undefined; 8285 }); 8286 }); 8287 8288 }, 8289 8290 goTo: function(index) { 8291 var iL = this, 8292 vars = iL.vars, 8293 opts = iL.options, 8294 diff = (index - vars.current); 8295 8296 if (opts.infinite) { 8297 if (index == vars.total - 1 && vars.current == 0) diff = -1; 8298 if (vars.current == vars.total - 1 && index == 0) diff = 1; 8299 } 8300 8301 if (diff == 1) iL.moveTo('next'); 8302 else if (diff == -1) iL.moveTo('prev'); 8303 else { 8304 8305 if (vars.nextLock || vars.prevLock) return false;
8306 8307 //Trigger the onBeforeChange callback 8308 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 8309 8310 if (opts.linkId) { 8311 vars.hashLock = true; 8312 window.location.hash = opts.linkId + '/' + index; 8313 } 8314 8315 if (iL.items[index]) { 8316 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 8317 else iL.vars.lockWheel = false; 8318 8319 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 8320 else vars.lockSwipe = false; 8321 } 8322 8323 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 8324 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 8325 }); 8326 8327 vars.current = index; 8328 vars.next = index + 1; 8329 vars.prev = index - 1; 8330 8331 iL.createUI(); 8332 8333 setTimeout(function() { 8334 iL.generateBoxes(); 8335 }, opts.effects.loadedFadeSpeed + 50); 8336 8337 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 8338 iL.positionThumbnails(); 8339 8340 if (opts.linkId) setTimeout(function() { 8341 vars.hashLock = false; 8342 }, 55); 8343 8344 // Configure arrow buttons 8345 if (!opts.infinite) { 8346 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8347 8348 if (vars.current == 0) { 8349 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8350 } 8351 if (vars.current >= vars.total - 1) { 8352 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8353 } 8354 } 8355 8356 // Reset next cycle timeout 8357 iL.resetCycle(); 8358 8359 //Trigger the onAfterChange callback 8360 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 8361 } 8362 }, 8363 8364 moveTo: function(side) { 8365 var iL = this, 8366 vars = iL.vars, 8367 opts = iL.options, 8368 path = opts.path.toLowerCase(), 8369 viewport = getViewport(), 8370 switchSpeed = opts.effects.switchSpeed; 8371 8372 if (vars.nextLock || vars.prevLock) return false; 8373 else { 8374 8375 var item = (side == "next") ? vars.next : vars.prev; 8376 8377 if (opts.linkId) { 8378 vars.hashLock = true; 8379 window.location.hash = opts.linkId + '/' + item; 8380 } 8381 8382 if (side == "next") { 8383 if (!iL.items[item]) return false; 8384 var firstHolder = vars.nextPhoto, 8385 secondHolder = vars.holder, 8386 lastHolder = vars.prevPhoto, 8387 firstClass = 'ilightbox-prev', 8388 secondClass = 'ilightbox-next'; 8389 } else if (side == "prev") { 8390 if (!iL.items[item]) return false; 8391 var firstHolder = vars.prevPhoto, 8392 secondHolder = vars.holder, 8393 lastHolder = vars.nextPhoto, 8394 firstClass = 'ilightbox-next', 8395 secondClass = 'ilightbox-prev'; 8396 } 8397 8398 //Trigger the onBeforeChange callback 8399 if (typeof opts.callback.onBeforeChange == 'function') 8400 opts.callback.onBeforeChange.call(iL, iL.ui); 8401 8402 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 8403 8404 var captionFirst = $('div.ilightbox-caption', secondHolder), 8405 socialFirst = $('div.ilightbox-social', secondHolder); 8406 8407 if (captionFirst.length) 8408 captionFirst.stop().fadeOut(switchSpeed, function() { 8409 $(this).remove(); 8410 }); 8411 if (socialFirst.length) 8412 socialFirst.stop().fadeOut(switchSpeed, function() { 8413 $(this).remove(); 8414 }); 8415 8416 if (iL.items[item].caption) { 8417 iL.setCaption(iL.items[item], firstHolder); 8418 var caption = $('div.ilightbox-caption', firstHolder), 8419 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 8420 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 8421 } 8422 8423 var social = iL.items[item].options.social; 8424 if (social) { 8425 iL.setSocial(social, iL.items[item].URL, firstHolder); 8426 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 8427 } 8428 8429 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 8430 val.removeClass('ilightbox-next ilightbox-prev'); 8431 }); 8432 8433 var firstOffset = firstHolder.data('offset'), 8434 winW = (viewport.width - (opts.styles.pageOffsetX)), 8435 winH = (viewport.height - (opts.styles.pageOffsetY)), 8436 width = firstOffset.newDims.width, 8437 height = firstOffset.newDims.height, 8438 thumbsOffset = firstOffset.thumbsOffset, 8439 diff = firstOffset.diff, 8440 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8441 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8442 8443 var secondOffset = secondHolder.data('offset'), 8444 object = secondOffset.object; 8445 8446 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8447 var objRatio = width / height; 8448 height = height - vars.captionHeight; 8449 width = height * objRatio; 8450 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 8451 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8452 }*/ 8453 8454 firstHolder.show().css(transform, gpuAcceleration).animate({ 8455 top: top, 8456 left: left, 8457 opacity: 1 8458 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8459 firstHolder.css(transform, ''); 8460 }); 8461 8462 $('div.ilightbox-container', firstHolder).animate({ 8463 width: width, 8464 height: height 8465 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8466 8467 diff = secondOffset.diff; 8468 8469 width = secondOffset.newDims.width, 8470 height = secondOffset.newDims.height; 8471 8472 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8473 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8474 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 8475 8476 if (side == 'prev') 8477 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 8478 else { 8479 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 8480 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8481 } 8482 8483 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 8484 var objRatio = width / height; 8485 height = height - vars.captionHeight; 8486 width = height * objRatio; 8487 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 8488 }*/ 8489 8490 $('div.ilightbox-container', secondHolder).animate({ 8491 width: width, 8492 height: height 8493 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8494 8495 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 8496 top: top, 8497 left: left, 8498 opacity: opts.styles.prevOpacity, 8499 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8500 secondHolder.css(transform, ''); 8501
8502 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 8503 iL.positionThumbnails(); 8504 8505 if (iL.items[item]) { 8506 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 8507 else vars.lockWheel = false; 8508 8509 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 8510 else vars.lockSwipe = false; 8511 } 8512 8513 vars.isSwipe = false; 8514 8515 // Remove iframe & video from previous slide 8516 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8517 $('div.ilightbox-container', secondHolder).empty(); 8518 } 8519 8520 if (side == "next") { 8521 vars.nextPhoto = lastHolder, 8522 vars.prevPhoto = secondHolder, 8523 vars.holder = firstHolder; 8524 8525 vars.nextPhoto.hide(); 8526 8527 vars.next = vars.next + 1, 8528 vars.prev = vars.current, 8529 vars.current = vars.current + 1; 8530 8531 if (opts.infinite) { 8532 if (vars.current > vars.total - 1) vars.current = 0; 8533 if (vars.current == vars.total - 1) vars.next = 0; 8534 if (vars.current == 0) vars.prev = vars.total - 1; 8535 } 8536 8537 iL.createUI(); 8538 8539 if (!iL.items[vars.next]) 8540 vars.nextLock = false; 8541 else 8542 iL.loadContent(iL.items[vars.next], 'next'); 8543 } else { 8544 vars.prevPhoto = lastHolder; 8545 vars.nextPhoto = secondHolder; 8546 vars.holder = firstHolder; 8547 8548 vars.prevPhoto.hide(); 8549 8550 vars.next = vars.current; 8551 vars.current = vars.prev; 8552 vars.prev = vars.current - 1; 8553 8554 if (opts.infinite) { 8555 if (vars.current == vars.total - 1) vars.next = 0; 8556 if (vars.current == 0) vars.prev = vars.total - 1; 8557 } 8558 8559 iL.createUI(); 8560 8561 if (!iL.items[vars.prev]) 8562 vars.prevLock = false; 8563 else 8564 iL.loadContent(iL.items[vars.prev], 'prev'); 8565 } 8566 8567 // Add iframe & video content for current slide 8568 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 8569 iL.loadContent(iL.items[vars.current], 'current'); 8570 } 8571 8572 if (opts.linkId) setTimeout(function() { 8573 vars.hashLock = false; 8574 }, 55); 8575 8576 // Configure arrow buttons 8577 if (!opts.infinite) { 8578 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8579 8580 if (vars.current == 0) 8581 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8582 if (vars.current >= vars.total - 1) 8583 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8584 } 8585 8586 iL.repositionPhoto(); 8587 8588 // Reset next cycle timeout 8589 iL.resetCycle(); 8590 8591 //Trigger the onAfterChange callback 8592 if (typeof opts.callback.onAfterChange == 'function') 8593 opts.callback.onAfterChange.call(iL, iL.ui); 8594 }); 8595 8596 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 8597 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 8598 8599 lastHolder.css(transform, gpuAcceleration).animate({ 8600 top: top, 8601 left: left, 8602 opacity: opts.styles.nextOpacity 8603 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8604 lastHolder.css(transform, ''); 8605 }).addClass(secondClass); 8606 } 8607 }, 8608 8609 setCaption: function(obj, target) { 8610 var iL = this, 8611 caption = $('<div class="ilightbox-caption"></div>'); 8612 8613 if (obj.caption) { 8614 caption.html(obj.caption); 8615 $('div.ilightbox-container', target).append(caption); 8616 } 8617 }, 8618 8619 normalizeSocial: function(obj, url) { 8620 var iL = this, 8621 vars = iL.vars, 8622 opts = iL.options, 8623 baseURL = window.location.href; 8624 8625 $.each(obj, function(key, value) { 8626 if (!value) 8627 return true; 8628 8629 var item = key.toLowerCase(), 8630 source, text; 8631 8632 switch (item) { 8633 case 'facebook': 8634 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 8635 text = "Share on Facebook"; 8636 break; 8637 case 'twitter': 8638 source = "http://twitter.com/home?status={URL}", 8639 text = "Share on Twitter"; 8640 break; 8641 case 'googleplus': 8642 source = "https://plus.google.com/share?url={URL}", 8643 text = "Share on Google+"; 8644 break; 8645 case 'delicious': 8646 source = "http://delicious.com/post?url={URL}", 8647 text = "Share on Delicious"; 8648 break; 8649 case 'digg': 8650 source = "http://digg.com/submit?phase=2&url={URL}", 8651 text = "Share on Digg"; 8652 break; 8653 case 'reddit': 8654 source = "http://reddit.com/submit?url={URL}", 8655 text = "Share on reddit"; 8656 break; 8657 } 8658 8659 obj[key] = { 8660 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 8661 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 8662 text: value.text || text || "Share on " + key, 8663 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 8664 height: value.height || 360 8665 }; 8666 8667 }); 8668 8669 return obj; 8670 }, 8671 8672 setSocial: function(obj, url, target) { 8673 var iL = this, 8674 socialBar = $('<div class="ilightbox-social"></div>'), 8675 buttons = '<ul>'; 8676 8677 obj = iL.normalizeSocial(obj, url); 8678 8679 $.each(obj, function(key, value) { 8680 var item = key.toLowerCase(), 8681 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, '+')); 8682 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>'; 8683 }); 8684 8685 buttons += '</ul>'; 8686 8687 socialBar.html(buttons); 8688 $('div.ilightbox-container', target).append(socialBar); 8689 }, 8690 8691 fullScreenAction: function() { 8692 var iL = this, 8693 vars = iL.vars; 8694 8695 if (fullScreenApi.supportsFullScreen) { 8696 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 8697 else fullScreenApi.requestFullScreen(document.documentElement); 8698 } else { 8699 iL.doFullscreen(); 8700 } 8701 }, 8702 8703 doFullscreen: function() { 8704 var iL = this, 8705 vars = iL.vars, 8706 viewport = getViewport(), 8707 opts = iL.options; 8708 8709 if (opts.fullAlone) { 8710 var currentHolder = vars.holder, 8711 current = iL.items[vars.current], 8712 windowWidth = viewport.width, 8713 windowHeight = viewport.height, 8714 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 8715 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8716 8717 if (!vars.isInFullScreen) { 8718 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 8719 vars.overlay.css({ 8720 opacity: 1 8721 }); 8722 8723 $.each(hideElements, function(i, element) { 8724 element.hide(); 8725 }); 8726 8727 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 8728 8729 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8730 naturalWidthOld: currentHolder.data('naturalWidth'), 8731 naturalHeightOld: currentHolder.data('naturalHeight'), 8732 naturalWidth: windowWidth, 8733 naturalHeight: windowHeight 8734 }); 8735 else { 8736 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 8737 newWidth = windowWidth, 8738 newHeight = windowHeight, 8739 width = currentHolder.data('naturalWidth'), 8740 height = currentHolder.data('naturalHeight'); 8741 8742 if (viewport.toLowerCase() == 'fill') { 8743 newHeight = (newWidth / width) * height; 8744 8745 if (newHeight < windowHeight) { 8746 newWidth = (windowHeight / height) * width, 8747 newHeight = windowHeight; 8748 } 8749 } else if (viewport.toLowerCase() == 'fit') { 8750 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 8751 8752 newWidth = dims.width, 8753 newHeight = dims.height; 8754 } else if (viewport.toLowerCase() == 'stretch') { 8755 newWidth = newWidth, 8756 newHeight = newHeight; 8757 } else { 8758 var scale = (width > newWidth || height > newHeight) ? true : false, 8759 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 8760 newWidth = dims.width, 8761 newHeight = dims.height; 8762 } 8763 8764 currentHolder.data({ 8765 naturalWidthOld: currentHolder.data('naturalWidth'), 8766 naturalHeightOld: currentHolder.data('naturalHeight'), 8767 naturalWidth: newWidth, 8768 naturalHeight: newHeight 8769 }); 8770 } 8771 8772 $.each(elements, function(key, val) { 8773 val.addClass('ilightbox-fullscreen'); 8774 }); 8775 8776 //Trigger the onEnterFullScreen callback 8777 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 8778 } else { 8779 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 8780 vars.overlay.css({ 8781 opacity: iL.options.overlay.opacity 8782 }); 8783 8784 $.each(hideElements, function(i, element) { 8785 element.show(); 8786 }); 8787 8788 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 8789 8790 currentHolder.data({ 8791 naturalWidth: currentHolder.data('naturalWidthOld'), 8792 naturalHeight: currentHolder.data('naturalHeightOld'), 8793 naturalWidthOld: null, 8794 naturalHeightOld: null 8795 }); 8796 8797 $.each(elements, function(key, val) { 8798 val.removeClass('ilightbox-fullscreen'); 8799 }); 8800 8801 //Trigger the onExitFullScreen callback 8802 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 8803 } 8804 } else { 8805 if (!vars.isInFullScreen) vars.isInFullScreen = true; 8806 else vars.isInFullScreen = false; 8807 } 8808 iL.repositionPhoto(true); 8809 }, 8810 8811 closeAction: function() { 8812 var iL = this, 8813 vars = iL.vars, 8814 opts = iL.options; 8815 8816 $win.unbind('.iLightBox'); 8817 $doc.off('.iLightBox'); 8818 8819 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 8820 8821 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 8822 8823 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 8824 vars.overlay.remove(); 8825 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8826 }); 8827 else { 8828 vars.overlay.remove(); 8829 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8830 } 8831 8832 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8833 8834 $.each(fadeOuts, function(i, element) { 8835 element.removeAttr('style').remove(); 8836 }); 8837 8838 vars.dontGenerateThumbs = vars.isInFullScreen = false; 8839 8840 window.iLightBox = null; 8841 8842 if (opts.linkId) { 8843 vars.hashLock = true; 8844 removeHash(); 8845 setTimeout(function() { 8846 vars.hashLock = false; 8847 }, 55); 8848 } 8849 8850 //Trigger the onHide callback 8851 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 8852 }, 8853 8854 repositionPhoto: function() { 8855 var iL = this, 8856 vars = iL.vars, 8857 opts = iL.options, 8858 path = opts.path.toLowerCase(), 8859 viewport = getViewport(), 8860 winWidth = viewport.width, 8861 winHeight = viewport.height; 8862 8863 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 8864 8865 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 8866 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 8867 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 8868 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 8869 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, 8870 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))); 8871 8872 var elObject = { 8873 type: 'current', 8874 width: width, 8875 height: height, 8876 item: iL.items[vars.current], 8877 offsetW: offsetW, 8878 offsetH: offsetH,
8879 thumbsOffsetW: thumbsOffsetW, 8880 thumbsOffsetH: thumbsOffsetH, 8881 animate: arguments.length, 8882 holder: vars.holder 8883 }; 8884 8885 iL.repositionEl(elObject); 8886 8887 if (iL.items[vars.next]) { 8888 elObject = $.extend(elObject, { 8889 type: 'next', 8890 item: iL.items[vars.next], 8891 offsetX: opts.styles.nextOffsetX, 8892 offsetY: opts.styles.nextOffsetY, 8893 holder: vars.nextPhoto 8894 }); 8895 8896 iL.repositionEl(elObject); 8897 } 8898 8899 if (iL.items[vars.prev]) { 8900 elObject = $.extend(elObject, { 8901 type: 'prev', 8902 item: iL.items[vars.prev], 8903 offsetX: opts.styles.nextOffsetX, 8904 offsetY: opts.styles.prevOffsetY, 8905 holder: vars.prevPhoto 8906 }); 8907 8908 iL.repositionEl(elObject); 8909 } 8910 8911 var loaderCss = (path == "horizontal") ? { 8912 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 8913 } : { 8914 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 8915 }; 8916 vars.loader.css(loaderCss); 8917 }, 8918 8919 repositionEl: function(obj) { 8920 var iL = this, 8921 vars = iL.vars, 8922 opts = iL.options, 8923 path = opts.path.toLowerCase(), 8924 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 8925 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 8926 itemParent = obj.item, 8927 item = obj.item.options, 8928 holder = obj.holder, 8929 offsetX = obj.offsetX || 0, 8930 offsetY = obj.offsetY || 0, 8931 thumbsOffsetW = obj.thumbsOffsetW, 8932 thumbsOffsetH = obj.thumbsOffsetH; 8933 8934 if (obj.type == 'current') { 8935 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); 8936 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); 8937 } else { 8938 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 8939 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 8940 } 8941 8942 heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 8943 8944 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 8945 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 8946 8947 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 8948 width: width, 8949 height: height 8950 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 8951 newDims = $.extend({}, dims, {}); 8952 8953 if (obj.type == 'prev' || obj.type == 'next') 8954 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 8955 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 8956 else 8957 width = dims.width, 8958 height = dims.height; 8959 8960 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 8961 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); 8962 8963 switch (obj.type) { 8964 case 'current': 8965 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 8966 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8967 break; 8968
8969 case 'next': 8970 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 8971 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 8972 break; 8973 8974 case 'prev': 8975 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 8976 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8977 break; 8978 } 8979 8980 holder.data('offset', { 8981 top: top, 8982 left: left, 8983 newDims: newDims, 8984 diff: { 8985 W: widthDiff, 8986 H: heightDiff 8987 }, 8988 thumbsOffset: { 8989 W: thumbsOffsetW, 8990 H: thumbsOffsetH 8991 }, 8992 object: obj 8993 }); 8994 8995 var opacityMobile; 8996 if ( isMobile ) { 8997 opacityMobile = { 8998 opacity: 1, 8999 top: top, 9000 left: left 9001 }; 9002 } else { 9003 opacityMobile = { 9004 top: top, 9005 left: left 9006 }; 9007 } 9008 9009 if (obj.animate > 0 && opts.effects.reposition) { 9010 holder.css(transform, gpuAcceleration).stop().animate( 9011 opacityMobile, 9012 opts.effects.repositionSpeed, 'easeOutCirc', function() { 9013 holder.css(transform, ''); 9014 }); 9015 $('div.ilightbox-container', holder).stop().animate({ 9016 width: width, 9017 height: height 9018 }, opts.effects.repositionSpeed, 'easeOutCirc'); 9019 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 9020 width: width 9021 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 9022 $(this).css('overflow', 'visible'); 9023 }); 9024 } else { 9025 holder.css(opacityMobile); 9026 $('div.ilightbox-container', holder).css({ 9027 width: width, 9028 height: height 9029 }); 9030 $('div.ilightbox-inner-toolbar', holder).css({ 9031 width: width 9032 }); 9033 } 9034 }, 9035 9036 9037 resume: function(priority) { 9038 var iL = this, 9039 vars = iL.vars, 9040 opts = iL.options; 9041 9042 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 9043 return; 9044 } 9045 9046 vars.isPaused = 0; 9047 9048 if (vars.cycleID) { 9049 vars.cycleID = clearTimeout(vars.cycleID); 9050 } 9051 9052 vars.cycleID = setTimeout(function() { 9053 if (vars.current == vars.total - 1) iL.goTo(0); 9054 else iL.moveTo('next'); 9055 }, opts.slideshow.pauseTime); 9056 }, 9057 9058 pause: function(priority) { 9059 var iL = this, 9060 vars = iL.vars, 9061 opts = iL.options; 9062 9063 if (priority < vars.isPaused) { 9064 return; 9065 } 9066 9067 vars.isPaused = priority || 100; 9068 9069 if (vars.cycleID) { 9070 vars.cycleID = clearTimeout(vars.cycleID); 9071 } 9072 }, 9073 9074 resetCycle: function() { 9075 var iL = this, 9076 vars = iL.vars, 9077 opts = iL.options; 9078 9079 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 9080 iL.resume(); 9081 } 9082 }, 9083 9084 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 9085 var iL = this; 9086 9087 if (!width) factor = height / height_old; 9088 else if (!height) factor = width / width_old; 9089 else factor = min(width / width_old, height / height_old); 9090 9091 if (!thumb) { 9092 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 9093 else if (factor < iL.options.minScale) factor = iL.options.minScale; 9094 } 9095 9096 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 9097 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 9098 9099 return { 9100 width: final_width, 9101 height: final_height, 9102 ratio: factor 9103 }; 9104 }, 9105 9106 setOption: function(options) { 9107 var iL = this; 9108 9109 iL.options = $.extend(true, iL.options, options || {}); 9110 iL.refresh(); 9111 }, 9112 9113 availPlugins: function() { 9114 var iL = this, 9115 testEl = document.createElement("video"); 9116 9117 iL.plugins = { 9118 flash: !isMobile, 9119 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 9120 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 9121 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 9122 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 9123 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 9124 }; 9125 }, 9126 9127 addContent: function(element, obj) { 9128 var iL = this, 9129 el; 9130 9131 switch (obj.type) { 9132 case 'video': 9133 var HTML5 = false, 9134 videoType = obj.videoType, 9135 html5video = obj.options.html5video; 9136 9137 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 9138 obj.ext = 'mp4', 9139 obj.URL = html5video.h264 || obj.URL; 9140 else if (html5video.webm && iL.plugins.html5WebM) 9141 obj.ext = 'webm', 9142 obj.URL = html5video.webm || obj.URL; 9143 else if (html5video.ogg && iL.plugins.html5Vorbis) 9144 obj.ext = 'ogv', 9145 obj.URL = html5video.ogg || obj.URL; 9146 9147 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 9148 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 9149 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 9150 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 9151 9152 if (HTML5) { 9153 el = $('<video />
9153', { 9154 "width": "100%", 9155 "height": "100%", 9156 "preload": html5video.preload, 9157 "autoplay": html5video.autoplay, 9158 "poster": html5video.poster, 9159 "controls": html5video.controls 9160 }).append($('<source />', { 9161 "src": obj.URL, 9162 "type": videoType 9163 })); 9164 } else { 9165 if (!iL.plugins.quicktime) el = $('<span />', { 9166 "class": "ilightbox-alert", 9167 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 9168 }); 9169 else { 9170 9171 el = $('<object />', { 9172 "type": "video/quicktime", 9173 "pluginspage": pluginspages.quicktime 9174 }).attr({ 9175 "data": obj.URL, 9176 "width": "100%", 9177 "height": "100%" 9178 }).append($('<param />', { 9179 "name": "src", 9180 "value": obj.URL 9181 })).append($('<param />', { 9182 "name": "autoplay", 9183 "value": "false" 9184 })).append($('<param />', { 9185 "name": "loop", 9186 "value": "false" 9187 })).append($('<param />', { 9188 "name": "scale", 9189 "value": "tofit" 9190 })); 9191 9192 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 9193 } 9194 } 9195 9196 break; 9197 9198 case 'flash': 9199 if (!iL.plugins.flash) el = $('<span />', { 9200 "class": "ilightbox-alert", 9201 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 9202 }); 9203 else { 9204 var flashvars = "", 9205 i = 0; 9206 9207 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 9208 if (i != 0) flashvars += "&"; 9209 flashvars += k + "=" + encodeURIComponent(v); 9210 i++; 9211 }); 9212 else flashvars = null; 9213 9214 el = $('<embed />').attr({ 9215 "type": "application/x-shockwave-flash", 9216 "src": obj.URL, 9217 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9218 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9219 "quality": "high", 9220 "bgcolor": "#000000", 9221 "play": "true", 9222 "loop": "true", 9223 "menu": "true", 9224 "wmode": "transparent", 9225 "scale": "showall", 9226 "allowScriptAccess": "always", 9227 "allowFullScreen": "true", 9228 "flashvars": flashvars, 9229 "fullscreen": "yes" 9230 }); 9231 } 9232 9233 break; 9234 9235 case 'iframe': 9236 el = $('<iframe />').attr({ 9237 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9238 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9239 src: obj.URL, 9240 frameborder: 0, 9241 'hspace': 0, 9242 'vspace': 0, 9243 'scrolling': supportTouch ? 'auto' : 'scroll', 9244 'webkitAllowFullScreen': '', 9245 'mozallowfullscreen': '', 9246 'allowFullScreen': '' 9247 }); 9248 9249 break; 9250 9251 case 'inline': 9252 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 9253 9254 break; 9255 9256 case 'html': 9257 var object = obj.URL, 9258 el; 9259 9260 if (object[0].nodeName) { 9261 el = $('<div class="ilightbox-wrapper"></div>').html(object); 9262 } else { 9263 var dom = $(obj.URL), 9264 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 9265 el = $('<div class="ilightbox-wrapper"></div>').html(html); 9266 } 9267 9268 break; 9269 } 9270 9271 $('div.ilightbox-container', element).empty().html(el); 9272 9273 // For fixing Chrome about just playing the video for first time 9274 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 9275 var src = el[0].currentSrc + '?' + floor(random() * 30000); 9276 el[0].currentSrc = src; 9277 el[0].src = src; 9278 }); 9279 9280 return el; 9281 }, 9282 9283 ogpRecognition: function(obj, callback) { 9284 var iL = this, 9285 url = obj.URL; 9286 9287 iL.showLoader(); 9288 doAjax(url, function(data) { 9289 iL.hideLoader(); 9290 if (data) { 9291 var object = new Object(); 9292 9293 object.length = false, 9294 object.url = data.url; 9295 9296 if (data.status == 200) { 9297 var result = data.results, 9298 type = result.type, 9299 source = result.source; 9300 9301 object.source = source.src, 9302 object.width = source.width && parseInt(source.width) || 0, 9303 object.height = source.height && parseInt(source.height) || 0, 9304 object.type = type, 9305 object.thumbnail = source.thumbnail || result.images && result.images[0], 9306 object.html5video = result.html5video || {}, 9307 object.length = true; 9308 9309 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 9310 else if (source.type.indexOf("video/") != -1) object.type = "video"; 9311 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 9312 else if (source.type.indexOf("image/") != -1) object.type = "image"; 9313 9314 } else if (typeof data.response != 'undefined') 9315 throw data.response; 9316 9317 callback.call(this, object.length ? object : false); 9318 } 9319 }); 9320 }, 9321 9322 hashChangeHandler: function(url) { 9323 var iL = this, 9324 vars = iL.vars, 9325 opts = iL.options, 9326 URL = url || window.location.href, 9327 hash = parseURI(URL).hash, 9328 split = hash.split('/'), 9329 index = split[1]; 9330 9331 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 9332 9333 if (index) { 9334 var target = split[1] || 0; 9335 if (iL.items[target]) {
9336 var overlay = $('.ilightbox-overlay'); 9337 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 9338 iL.goTo(target); 9339 } else { 9340 iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click'); 9341 //iL.goTo(target); 9342 } 9343 } else { 9344 var overlay = $('.ilightbox-overlay'); 9345 if (overlay.length) iL.closeAction(); 9346 } 9347 } else { 9348 var overlay = $('.ilightbox-overlay'); 9349 if (overlay.length) iL.closeAction(); 9350 } 9351 } 9352 }; 9353 9354 /** 9355 * Parse style to pixels. 9356 * 9357 * @param {Object} $element jQuery object with element. 9358 * @param {Property} property CSS property to get the pixels from. 9359 * 9360 * @return {Int} 9361 */ 9362 function getPixel($element, property) { 9363 return parseInt($element.css(property), 10) || 0; 9364 } 9365 9366 /** 9367 * Make sure that number is within the limits. 9368 * 9369 * @param {Number} number 9370 * @param {Number} min 9371 * @param {Number} max 9372 * 9373 * @return {Number} 9374 */ 9375 function within(number, min, max) { 9376 return number < min ? min : number > max ? max : number; 9377 } 9378 9379 /** 9380 * Get viewport/window size (width and height). 9381 * 9382 * @return {Object} 9383 */ 9384 function getViewport() { 9385 var e = window, 9386 a = 'inner'; 9387 if (!('innerWidth' in window)) { 9388 a = 'client'; 9389 e = document.documentElement || document.body; 9390 } 9391 return { 9392 width: e[a + 'Width'], 9393 height: e[a + 'Height'] 9394 } 9395 } 9396 9397 /** 9398 * Remove hash tag from the URL 9399 * 9400 * @return {Void} 9401 */ 9402 function removeHash() { 9403 var scroll = getScrollXY(); 9404 9405 //UNCODE change 9406 //window.location.hash = ""; 9407 history.pushState("", document.title, window.location.pathname + window.location.search); 9408 9409 // Restore the scroll offset, should be flicker free 9410 window.scrollTo(scroll.x, scroll.y); 9411 } 9412 9413 /** 9414 * Do the ajax requests with callback. 9415 * 9416 * @param {String} url 9417 * @param {Function} callback 9418 * 9419 * @return {Void} 9420 */ 9421 function doAjax(url, callback) { 9422 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'); 9423 $.ajax({ 9424 url: url, 9425 dataType: 'jsonp' 9426 }); 9427 9428 iLCallback = function(data) { 9429 callback.call(this, data); 9430 }; 9431 } 9432 9433 /** 9434 * Find image from DOM elements 9435 * 9436 * @param {Element} element 9437 * 9438 * @return {Void} 9439 */ 9440 function findImageInElement(element) { 9441 var elements = $('*', element), 9442 imagesArr = new Array(); 9443 9444 elements.each(function() { 9445 var url = "", 9446 element = this; 9447 9448 if ($(element).css("background-image") != "none") { 9449 url = $(element).css("background-image"); 9450 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 9451 url = $(element).attr("src"); 9452 } 9453 9454 if (url.indexOf("gradient") == -1) { 9455 url = url.replace(/url\(\"/g, ""); 9456 url = url.replace(/url\(/g, ""); 9457 url = url.replace(/\"\)/g, ""); 9458 url = url.replace(/\)/g, ""); 9459 9460 var urls = url.split(","); 9461 9462 for (var i = 0; i < urls.length; i++) { 9463 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 9464 var extra = ""; 9465 if (browser.msie && browser.version < 9) { 9466 extra = "?" + floor(random() * 3000); 9467 } 9468 imagesArr.push(urls[i] + extra); 9469 } 9470 } 9471 } 9472 }); 9473 9474 return imagesArr; 9475 } 9476 9477 /** 9478 * Get file extension. 9479 * 9480 * @param {String} URL 9481 * 9482 * @return {String} 9483 */ 9484 function getExtension(URL) { 9485 if (URL !== null) { 9486 var ext = URL.split('.').pop().toLowerCase(), 9487 extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : ''; 9488 9489 //UNCODE: fix issue to detect media type with query strings 9490 ext = ext.replace('?'+extra, ''); 9491 9492 return ext.replace(extra, ''); 9493 } 9494 } 9495 9496 /** 9497 * Get type via extension. 9498 * 9499 * @param {String} URL 9500 * 9501 * @return {String} 9502 */ 9503 function getTypeByExtension(URL) { 9504 var type, 9505 ext = getExtension(URL); 9506 9507 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 9508 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 9509 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 9510 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 9511 else type = 'iframe'; 9512 9513 return type; 9514 } 9515 9516 /** 9517 * Return value from percent of a number. 9518 * 9519 * @param {Number} percent 9520 * @param {Number} total 9521 * 9522 * @return {Number} 9523 */ 9524 function percentToValue(percent, total) { 9525 return parseInt((total / 100) * percent); 9526 } 9527 9528 /** 9529 * A JavaScript equivalent of PHP’s parse_url. 9530 * 9531 * @param {String} url The URL to parse. 9532 * 9533 * @return {Mixed} 9534 */ 9535 function parseURI(url) { 9536 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 9537 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 9538 return (m ? { 9539 href: m[0] || '', 9540 protocol: m[1] || '', 9541 authority: m[2] || '', 9542 host: m[3] || '', 9543 hostname: m[4] || '', 9544 port: m[5] || '', 9545 pathname: m[6] || '', 9546 search: m[7] || '', 9547 hash: m[8] || '' 9548 } : null); 9549 } 9550 9551 /** 9552 * Gets the absolute URI. 9553 * 9554 * @param {String} href The relative URL. 9555 * @param {String} base The base URL. 9556 * 9557 * @return {String} The absolute URL. 9558 */ 9559 function absolutizeURI(base, href) { // RFC 3986 9560 var iL = this; 9561 9562 function removeDotSegments(input) { 9563 var output = []; 9564 input.replace(/^(\.\.?(\/|$))+/, '') 9565 .replace(/\/(\.(\/|$))+/g, '/') 9566 .replace(/\/\.\.$/, '/../') 9567 .replace(/\/?[^\/]*/g, function(p) { 9568 if (p === '/..') { 9569 output.pop(); 9570 } else { 9571 output.push(p); 9572 } 9573 }); 9574 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 9575 } 9576 9577 href = parseURI(href || ''); 9578 base = parseURI(base || ''); 9579 9580 return !href || !base ? null : (href.protocol || base.protocol) + 9581 (href.protocol || href.authority ? href.authority : base.authority) + 9582 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)) + 9583 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 9584 href.hash; 9585 } 9586 9587 /** 9588 * A JavaScript equivalent of PHP’s version_compare. 9589 * 9590 * @param {String} v1 9591 * @param {String} v2 9592 * @param {String} operator
9593 * 9594 * @return {Boolean} 9595 */ 9596 function version_compare(v1, v2, operator) { 9597 this.php_js = this.php_js || {}; 9598 this.php_js.ENV = this.php_js.ENV || {}; 9599 var i = 0, 9600 x = 0, 9601 compare = 0, 9602 vm = { 9603 'dev': -6, 9604 'alpha': -5, 9605 'a': -5, 9606 'beta': -4, 9607 'b': -4, 9608 'RC': -3, 9609 'rc': -3, 9610 '#': -2, 9611 'p': 1, 9612 'pl': 1 9613 }, 9614 prepVersion = function(v) { 9615 v = ('' + v).replace(/[_\-+]/g, '.'); 9616 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 9617 return (!v.length ? [-8] : v.split('.')); 9618 }, 9619 numVersion = function(v) { 9620 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 9621 }; 9622 v1 = prepVersion(v1); 9623 v2 = prepVersion(v2); 9624 x = max(v1.length, v2.length); 9625 for (i = 0; i < x; i++) { 9626 if (v1[i] == v2[i]) { 9627 continue; 9628 } 9629 v1[i] = numVersion(v1[i]); 9630 v2[i] = numVersion(v2[i]); 9631 if (v1[i] < v2[i]) { 9632 compare = -1; 9633 break; 9634 } else if (v1[i] > v2[i]) { 9635 compare = 1; 9636 break; 9637 } 9638 } 9639 if (!operator) { 9640 return compare; 9641 } 9642 9643 switch (operator) { 9644 case '>': 9645 case 'gt': 9646 return (compare > 0); 9647 case '>=': 9648 case 'ge': 9649 return (compare >= 0); 9650 case '<=': 9651 case 'le': 9652 return (compare <= 0); 9653 case '==': 9654 case '=': 9655 case 'eq': 9656 return (compare === 0); 9657 case '<>': 9658 case '!=': 9659 case 'ne': 9660 return (compare !== 0); 9661 case '': 9662 case '<': 9663 case 'lt': 9664 return (compare < 0); 9665 default: 9666 return null; 9667 } 9668 } 9669 9670 9671 // Begin the iLightBox plugin 9672 $.fn.iLightBox = function() { 9673 9674 var args = arguments, 9675 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 9676 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 9677 9678 if (!opt) opt = {}; 9679 9680 // Default options. Play carefully. 9681 var options = $.extend(true, { 9682 attr: 'href', 9683 path: 'vertical', 9684 skin: 'dark', 9685 linkId: false, 9686 infinite: false, 9687 startFrom: 0, 9688 randomStart: false, 9689 keepAspectRatio: true, 9690 maxScale: 1, 9691 minScale: .2, 9692 innerToolbar: false, 9693 smartRecognition: false, 9694 mobileOptimizer: true, 9695 fullAlone: true, 9696 fullViewPort: null, 9697 fullStretchTypes: 'flash, video', 9698 overlay: { 9699 blur: true, 9700 opacity: .85 9701 }, 9702 controls: { 9703 arrows: false, 9704 slideshow: false, 9705 toolbar: true, 9706 fullscreen: true, 9707 thumbnail: true, 9708 keyboard: true, 9709 mousewheel: true, 9710 swipe: true 9711 }, 9712 keyboard: { 9713 left: true, // previous 9714 right: true, // next 9715 up: true, // previous 9716 down: true, // next 9717 esc: true, // close 9718 shift_enter: true // fullscreen 9719 }, 9720 show: { 9721 effect: true, 9722 speed: 300, 9723 title: true 9724 }, 9725 hide: { 9726 effect: true, 9727 speed: 300 9728 }, 9729 caption: { 9730 start: true, 9731 show: 'mouseenter', 9732 hide: 'mouseleave' 9733 }, 9734 social: { 9735 start: true, 9736 show: 'mouseenter', 9737 hide: 'mouseleave',
9738 buttons: false 9739 }, 9740 styles: { 9741 pageOffsetX: 0, 9742 pageOffsetY: 0, 9743 nextOffsetX: 45, 9744 nextOffsetY: 0, 9745 nextOpacity: 1, 9746 nextScale: 1, 9747 prevOffsetX: 45, 9748 prevOffsetY: 0, 9749 prevOpacity: 1, 9750 prevScale: 1 9751 }, 9752 thumbnails: { 9753 maxWidth: 120, 9754 maxHeight: 80, 9755 normalOpacity: 1, 9756 activeOpacity: .6 9757 }, 9758 effects: { 9759 reposition: true, 9760 repositionSpeed: 200, 9761 switchSpeed: 500, 9762 loadedFadeSpeed: 180, 9763 fadeSpeed: 200 9764 }, 9765 slideshow: { 9766 pauseTime: 5000, 9767 pauseOnHover: false, 9768 startPaused: true 9769 }, 9770 text: { 9771 close: "Press Esc to close", 9772 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 9773 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 9774 slideShow: "Slideshow", 9775 next: "Next", 9776 previous: "Previous" 9777 }, 9778 errors: { 9779 loadImage: "An error occurred when trying to load photo.", 9780 loadContents: "An error occurred when trying to load contents.", 9781 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 9782 }, 9783 ajaxSetup: { 9784 url: '', 9785 beforeSend: function(jqXHR, settings) {}, 9786 cache: false, 9787 complete: function(jqXHR, textStatus) {}, 9788 crossDomain: false, 9789 error: function(jqXHR, textStatus, errorThrown) {}, 9790 success: function(data, textStatus, jqXHR) {}, 9791 global: true, 9792 ifModified: false, 9793 username: null, 9794 password: null, 9795 type: 'GET' 9796 }, 9797 callback: {} 9798 }, opt); 9799 9800 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 9801 9802 items = $.isArray(items) ? items : new Array(); 9803 9804 if (typeof args[0] == 'string') items[0] = args[0]; 9805 9806 if (version_compare($.fn.jquery, '1.8', '>=')) { 9807 var iLB = new iLightBox($(this), options, items, instant); 9808 return { 9809 close: function() { 9810 iLB.closeAction(); 9811 }, 9812 fullscreen: function() { 9813 iLB.fullScreenAction(); 9814 }, 9815 moveNext: function() { 9816 iLB.moveTo('next'); 9817 }, 9818 movePrev: function() { 9819 iLB.moveTo('prev'); 9820 }, 9821 goTo: function(index) { 9822 iLB.goTo(index); 9823 }, 9824 refresh: function() { 9825 iLB.refresh(); 9826 }, 9827 reposition: function() { 9828 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 9829 }, 9830 setOption: function(options) { 9831 iLB.setOption(options); 9832 }, 9833 destroy: function() { 9834 iLB.closeAction(); 9835 iLB.dispatchItemsEvents(); 9836 } 9837 }; 9838 } else { 9839 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 9840 } 9841 9842 }; 9843 9844 9845 $.iLightBox = function() { 9846 return $.fn.iLightBox(arguments[0], arguments[1]); 9847 }; 9848 9849 9850 $.extend($.easing, { 9851 easeInCirc: function(x, t, b, c, d) { 9852 return -c * (sqrt(1 - (t /= d) * t) - 1) + b; 9853 }, 9854 easeOutCirc: function(x, t, b, c, d) { 9855 return c * sqrt(1 - (t = t / d - 1) * t) + b; 9856 }, 9857 easeInOutCirc: function(x, t, b, c, d) { 9858 if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; 9859 return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b; 9860 } 9861 }); 9862 9863 function getScrollXY() { 9864 var scrOfX = 0, 9865 scrOfY = 0; 9866 if (typeof(window.pageYOffset) == 'number') { 9867 //Netscape compliant 9868 scrOfY = window.pageYOffset; 9869 scrOfX = window.pageXOffset; 9870 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 9871 //DOM compliant 9872 scrOfY = document.body.scrollTop; 9873 scrOfX = document.body.scrollLeft; 9874 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 9875 //IE6 standards compliant mode 9876 scrOfY = document.documentElement.scrollTop; 9877 scrOfX = document.documentElement.scrollLeft; 9878 } 9879 return { 9880 x: scrOfX, 9881 y: scrOfY 9882 }; 9883 } 9884 9885 (function() { 9886 // add new event shortcuts 9887 $.each(("touchstart touchmove touchend " + 9888 "tap taphold " + 9889 "swipe swipeleft swiperight " + 9890 "scrollstart scrollstop").split(" "), function(i, name) { 9891 9892 $.fn[name] = function(fn) { 9893 return fn ? this.bind(name, fn) : this.trigger(name); 9894 }; 9895 9896 // jQuery < 1.8 9897 // if ($.attrFn) { 9898 // $.attrFn[name] = true; 9899 // } 9900 }); 9901 9902 var tapSettings = { 9903 startEvent: 'touchstart.iTap', 9904 endEvent: 'touchend.iTap' 9905 }; 9906 9907 // tap Event: 9908 $.event.special.itap = { 9909 setup: function() { 9910 9911 var self = this, 9912 $self = $(this), 9913 start, stop; 9914 9915 $self.bind(tapSettings.startEvent, function(event) { 9916 start = getScrollXY(); 9917 9918 $self.one(tapSettings.endEvent, function(event) { 9919 stop = getScrollXY(); 9920 9921 var orgEvent = event || window.event; 9922 event = $.event.fix(orgEvent); 9923 event.type = "itap"; 9924 9925 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 9926 9927 start = stop = undefined; 9928 }); 9929 }); 9930 }, 9931 9932 teardown: function() { 9933 $(this).unbind(tapSettings.startEvent); 9934 } 9935 }; 9936 }()); 9937 9938 9939 //Fullscreen API 9940 (function() { 9941 fullScreenApi = { 9942 supportsFullScreen: false, 9943 isFullScreen: function() { 9944 return false;
9945 }, 9946 requestFullScreen: function() {}, 9947 cancelFullScreen: function() {}, 9948 fullScreenEventName: '', 9949 prefix: '' 9950 }, 9951 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 9952 9953 // check for native support 9954 if (typeof document.cancelFullScreen != 'undefined') { 9955 fullScreenApi.supportsFullScreen = true; 9956 } else { 9957 // check for fullscreen support by vendor prefix 9958 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 9959 fullScreenApi.prefix = browserPrefixes[i]; 9960 9961 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 9962 fullScreenApi.supportsFullScreen = true; 9963 9964 break; 9965 } 9966 } 9967 } 9968 9969 // update methods to do something useful 9970 if (fullScreenApi.supportsFullScreen) { 9971 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 9972 9973 fullScreenApi.isFullScreen = function() { 9974 switch (this.prefix) { 9975 case '': 9976 return document.fullScreen; 9977 case 'webkit': 9978 return document.webkitIsFullScreen; 9979 default: 9980 return document[this.prefix + 'FullScreen']; 9981 } 9982 } 9983 fullScreenApi.requestFullScreen = function(el) { 9984 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 9985 } 9986 fullScreenApi.cancelFullScreen = function(el) { 9987 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 9988 } 9989 } 9990 }()); 9991 9992 // Browser detect 9993 (function() { 9994 function uaMatch(ua) { 9995 ua = ua.toLowerCase(); 9996 9997 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 9998 /(webkit)[ \/]([\w.]+)/.exec(ua) || 9999 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 10000 /(msie) ([\w.]+)/.exec(ua) || 10001 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 10002 10003 return { 10004 browser: match[1] || "", 10005 version: match[2] || "0" 10006 }; 10007 } 10008 10009 var matched = uaMatch(navigator.userAgent); 10010 browser = {}; 10011 10012 if (matched.browser) { 10013 browser[matched.browser] = true; 10014 browser.version = matched.version; 10015 } 10016 10017 // Chrome is Webkit, but Webkit is also Safari. 10018 if (browser.chrome) { 10019 browser.webkit = true; 10020 } else if (browser.webkit) { 10021 browser.safari = true; 10022 } 10023 }()); 10024 10025 // Feature detects 10026 (function() { 10027 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 10028 var el = document.createElement('div'); 10029 10030 function testProp(prop) { 10031 for (var p = 0, pl = prefixes.length; p < pl; p++) { 10032 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 10033 if (el.style[prefixedProp] !== undefined) { 10034 return prefixedProp; 10035 } 10036 } 10037 } 10038 10039 // Global support indicators 10040 transform = testProp('transform') || ''; 10041 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 10042 }()); 10043 10044 10045 /* 10046 PluginDetect v0.7.9 10047 www.pinlady.net/PluginDetect/license/ 10048 [ getVersion onWindowLoaded BetterIE ] 10049 [ Flash QuickTime Shockwave ] 10050 */ 10051 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;
10051d++){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);
10051d.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)}
10051c.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;
10051if(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(); 10052 10053 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)}; 10054 10055 10056 /* 10057 jQuery hashchange event v1.3 10058 https://github.com/cowboy/jquery-hashchange 10059 Copyright (c) 2010 "Cowboy" Ben Alman 10060 Dual licensed under the MIT and GPL licenses. 10061 */ 10062 (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= 10063 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|| 10064 "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;
10064a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 10065 10066 if (!Array.prototype.filter) { 10067 Array.prototype.filter = function(fun /*, thisp */ ) { 10068 "use strict"; 10069 10070 if (this == null) 10071 throw new TypeError(); 10072 10073 var t = Object(this); 10074 var len = t.length >>> 0; 10075 if (typeof fun != "function") 10076 throw new TypeError(); 10077 10078 var res = []; 10079 var thisp = arguments[1]; 10080 for (var i = 0; i < len; i++) { 10081 if (i in t) { 10082 var val = t[i]; // in case fun mutates this 10083 if (fun.call(thisp, val, i, t)) 10084 res.push(val); 10085 } 10086 } 10087 10088 return res; 10089 }; 10090 } 10091 10092 if (!Array.prototype.indexOf) { 10093 Array.prototype.indexOf = function(searchElement, fromIndex) { 10094 var k; 10095 10096 if (this == null) { 10097 throw new TypeError('"this" is null or not defined'); 10098 } 10099 10100 var O = Object(this); 10101 10102 var len = O.length >>> 0; 10103 10104 if (len === 0) { 10105 return -1; 10106 } 10107 10108 var n = +fromIndex || 0; 10109 10110 if (abs(n) === Infinity) { 10111 n = 0; 10112 } 10113 10114 if (n >= len) { 10115 return -1; 10116 } 10117 10118 k = max(n >= 0 ? n : len - abs(n), 0); 10119 10120 while (k < len) { 10121 var kValue; 10122 if (k in O && O[k] === searchElement) { 10123 return k; 10124 } 10125 k++; 10126 } 10127 return -1; 10128 }; 10129 } 10130 10131 if (!Array.prototype.lastIndexOf) { 10132 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 10133 "use strict"; 10134 10135 if (this == null) 10136 throw new TypeError(); 10137 10138 var t = Object(this); 10139 var len = t.length >>> 0; 10140 if (len === 0) 10141 return -1; 10142 10143 var n = len; 10144 if (arguments.length > 1) { 10145 n = Number(arguments[1]); 10146 if (n != n) 10147 n = 0; 10148 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 10149 n = (n > 0 || -1) * floor(abs(n)); 10150 } 10151 10152 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 10153 10154 for (; k >= 0; k--) { 10155 if (k in t && t[k] === searchElement) 10156 return k; 10157 } 10158 return -1; 10159 }; 10160 } 10161})(jQuery, this); 10162 10163/** 10164 * Owl carousel
vendor: 12,045 bytes, lines 10165-10670
10165 * @version 2.0.0-beta.3 10166 * @author Bartosz Wojciechowski 10167 * @license The MIT License (MIT) 10168 * @todo Lazy Load Icon 10169 * @todo prevent animationend bubling 10170 * @todo itemsScaleUp 10171 * @todo Test Zepto 10172 * @todo stagePadding calculate wrong active classes 10173 */ 10174;(function($, window, document, undefined) { 10175 10176 /** 10177 * Creates a carousel. 10178 * @class The Owl Carousel. 10179 * @public 10180 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 10181 * @param {Object} [options] - The options 10182 */ 10183 function Owl(element, options) { 10184 10185 /** 10186 * Current settings for the carousel. 10187 * @public 10188 */ 10189 this.settings = null; 10190 10191 /** 10192 * Current options set by the caller including defaults. 10193 * @public 10194 */ 10195 this.options = $.extend({}, Owl.Defaults, options); 10196 10197 /** 10198 * Plugin element. 10199 * @public 10200 */ 10201 this.$element = $(element); 10202 10203 /** 10204 * Proxied event handlers. 10205 * @protected 10206 */ 10207 this._handlers = {}; 10208 10209 /** 10210 * References to the running plugins of this carousel. 10211 * @protected 10212 */ 10213 this._plugins = {}; 10214 10215 /** 10216 * Currently suppressed events to prevent them from beeing retriggered. 10217 * @protected 10218 */ 10219 this._supress = {}; 10220 10221 /** 10222 * Absolute current position. 10223 * @protected 10224 */ 10225 this._current = null; 10226 10227 /** 10228 * Animation speed in milliseconds. 10229 * @protected 10230 */ 10231 this._speed = null; 10232 10233 /** 10234 * Coordinates of all items in pixel. 10235 * @todo The name of this member is missleading. 10236 * @protected 10237 */ 10238 this._coordinates = []; 10239 10240 /** 10241 * Current breakpoint. 10242 * @todo Real media queries would be nice. 10243 * @protected 10244 */ 10245 this._breakpoint = null; 10246 10247 /** 10248 * Current width of the plugin element. 10249 */ 10250 this._width = null; 10251 10252 /** 10253 * All real items. 10254 * @protected 10255 */ 10256 this._items = []; 10257 10258 /** 10259 * All cloned items. 10260 * @protected 10261 */ 10262 this._clones = []; 10263 10264 /** 10265 * Merge values of all items. 10266 * @todo Maybe this could be part of a plugin. 10267 * @protected 10268 */ 10269 this._mergers = []; 10270 10271 /** 10272 * Widths of all items. 10273 */ 10274 this._widths = []; 10275 10276 /** 10277 * Invalidated parts within the update process. 10278 * @protected 10279 */ 10280 this._invalidated = {}; 10281 10282 /** 10283 * Ordered list of workers for the update process. 10284 * @protected 10285 */ 10286 this._pipe = []; 10287 10288 /** 10289 * Current state information for the drag operation. 10290 * @todo #261 10291 * @protected 10292 */ 10293 this._drag = { 10294 time: null, 10295 target: null, 10296 pointer: null, 10297 stage: { 10298 start: null, 10299 current: null 10300 }, 10301 direction: null 10302 }; 10303 10304 /** 10305 * Current state information and their tags. 10306 * @type {Object} 10307 * @protected 10308 */ 10309 this._states = { 10310 current: {}, 10311 tags: { 10312 'initializing': [ 'busy' ], 10313 'animating': [ 'busy' ], 10314 'dragging': [ 'interacting' ] 10315 } 10316 }; 10317 10318 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 10319 this._handlers[handler] = $.proxy(this[handler], this); 10320 }, this)); 10321 10322 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 10323 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 10324 = new plugin(this); 10325 }, this)); 10326 10327 $.each(Owl.Workers, $.proxy(function(priority, worker) { 10328 this._pipe.push({ 10329 'filter': worker.filter, 10330 'run': $.proxy(worker.run, this) 10331 }); 10332 }, this)); 10333 10334 this.setup(); 10335 this.initialize(); 10336 } 10337 10338 /** 10339 * Default options for the carousel. 10340 * @public 10341 */ 10342 Owl.Defaults = { 10343 items: 3, 10344 loop: false, 10345 center: false, 10346 rewind: false, 10347 10348 mouseDrag: true, 10349 touchDrag: true, 10350 pullDrag: true, 10351 freeDrag: false, 10352 10353 margin: 0, 10354 stagePadding: 0, 10355 10356 merge: false, 10357 mergeFit: true, 10358 autoWidth: false, 10359 10360 startPosition: 0, 10361 rtl: false, 10362 10363 smartSpeed: 250, 10364 fluidSpeed: false, 10365 dragEndSpeed: false, 10366 10367 responsive: {}, 10368 responsiveRefreshRate: 200, 10369 responsiveBaseElement: window, 10370 10371 fallbackEasing: 'swing', 10372 10373 info: false, 10374 10375 nestedItemSelector: false, 10376 itemElement: 'div', 10377 stageElement: 'div', 10378 10379 refreshClass: 'owl-refresh', 10380 loadedClass: 'owl-loaded', 10381 loadingClass: 'owl-loading', 10382 rtlClass: 'owl-rtl', 10383 responsiveClass: 'owl-responsive', 10384 dragClass: 'owl-drag', 10385 itemClass: 'owl-item', 10386 stageClass: 'owl-stage', 10387 stageOuterClass: 'owl-stage-outer', 10388 grabClass: 'owl-grab' 10389 }; 10390 10391 /** 10392 * Enumeration for width. 10393 * @public 10394 * @readonly 10395 * @enum {String} 10396 */ 10397 Owl.Width = { 10398 Default: 'default', 10399 Inner: 'inner', 10400 Outer: 'outer' 10401 }; 10402 10403 /** 10404 * Enumeration for types. 10405 * @public 10406 * @readonly 10407 * @enum {String} 10408 */ 10409 Owl.Type = { 10410 Event: 'event', 10411 State: 'state' 10412 }; 10413 10414 /** 10415 * Contains all registered plugins. 10416 * @public 10417 */ 10418 Owl.Plugins = {}; 10419 10420 /** 10421 * List of workers involved in the update process. 10422 */ 10423 Owl.Workers = [ { 10424 filter: [ 'width', 'settings' ], 10425 run: function() { 10426 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 10427 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 10428 } 10429 }, { 10430 filter: [ 'width', 'items', 'settings' ], 10431 run: function(cache) { 10432 cache.current = this._items && this._items[this.relative(this._current)]; 10433 } 10434 }, { 10435 filter: [ 'items', 'settings' ], 10436 run: function() { 10437 this.$stage.children('.cloned').remove(); 10438 } 10439 }, { 10440 filter: [ 'width', 'items', 'settings' ], 10441 run: function(cache) { 10442 var margin = this.settings.margin || '', 10443 grid = !this.settings.autoWidth, 10444 rtl = this.settings.rtl, 10445 css = { 10446 'width': 'auto', 10447 'margin-left': rtl ? margin : '', 10448 'margin-right': rtl ? '' : margin 10449 }; 10450 10451 !grid && this.$stage.children().css(css); 10452 10453 cache.css = css; 10454 } 10455 }, { 10456 filter: [ 'width', 'items', 'settings' ], 10457 run: function(cache) { 10458 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 10459 merge = null, 10460 iterator = this._items.length, 10461 grid = !this.settings.autoWidth, 10462 widths = []; 10463 10464 cache.items = { 10465 merge: false, 10466 width: width 10467 }; 10468 10469 while (iterator--) { 10470 merge = this._mergers[iterator]; 10471 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 10472 10473 cache.items.merge = merge > 1 || cache.items.merge; 10474 10475 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 10476 } 10477 10478 this._widths = widths; 10479 } 10480 }, { 10481 filter: [ 'items', 'settings' ], 10482 run: function() { 10483 var clones = [], 10484 items = this._items, 10485 settings = this.settings, 10486 view = Math.max(settings.items * 2, 4), 10487 size = Math.ceil(items.length / 2) * 2, 10488 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 10489 append = '', 10490 prepend = ''; 10491 10492 repeat /= 2; 10493 10494 while (repeat--) { 10495 clones.push(this.normalize(clones.length / 2, true)); 10496 append = append + items[clones[clones.length - 1]][0].outerHTML; 10497 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 10498 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 10499 } 10500 10501 this._clones = clones; 10502 10503 // var appendVideo = $(append).find('.uncode-video-container'); 10504 // if (appendVideo.length) { 10505 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 10506 // } 10507 // var prependVideo = $(prepend).find('.uncode-video-container'); 10508 // if (prependVideo.length) { 10509 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 10510 // } 10511 $(append).addClass('cloned').appendTo(this.$stage); 10512 $(prepend).addClass('cloned').prependTo(this.$stage); 10513 } 10514 }, { 10515 filter: [ 'width', 'items', 'settings' ], 10516 run: function() { 10517 var rtl = this.settings.rtl ? 1 : -1, 10518 size = this._clones.length + this._items.length, 10519 iterator = -1, 10520 previous = 0, 10521 current = 0, 10522 coordinates = []; 10523 10524 while (++iterator < size) { 10525 previous = coordinates[iterator - 1] || 0; 10526 current = this._widths[this.relative(iterator)] + this.settings.margin; 10527 coordinates.push(previous + current * rtl); 10528 } 10529 10530 this._coordinates = coordinates; 10531 } 10532 }, { 10533 filter: [ 'width', 'items', 'settings' ], 10534 run: function() { 10535 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10536 padding = stagePadding, 10537 coordinates = this._coordinates, 10538 css = { 10539 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 10540 'padding-left': padding || '', 10541 'padding-right': padding || '' 10542 }; 10543 10544 this.$stage.css(css); 10545 } 10546 }, { 10547 filter: [ 'width', 'items', 'settings' ], 10548 run: function(cache) { 10549 var iterator = this._coordinates.length, 10550 grid = !this.settings.autoWidth, 10551 items = this.$stage.children(); 10552 10553 if (grid && cache.items.merge) { 10554 while (iterator--) { 10555 cache.css.width = this._widths[this.relative(iterator)]; 10556 items.eq(iterator).css(cache.css); 10557 } 10558 } else if (grid) { 10559 cache.css.width = cache.items.width; 10560 items.css(cache.css); 10561 } 10562 } 10563 }, { 10564 filter: [ 'items' ], 10565 run: function() { 10566 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 10567 } 10568 }, { 10569 filter: [ 'width', 'items', 'settings' ], 10570 run: function(cache) { 10571 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 10572 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 10573 this.reset(cache.current); 10574 } 10575 }, { 10576 filter: [ 'position' ], 10577 run: function() { 10578 this.animate(this.coordinates(this._current)); 10579 } 10580 }, { 10581 filter: [ 'width', 'position', 'items', 'settings' ], 10582 run: function() { 10583 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 10584 rtl = this.settings.rtl ? 1 : -1, 10585 padding = this.settings.stagePadding * 2, 10586 begin = this.coordinates(this.current()) + padding, 10587 end = begin + this.width() * rtl, 10588 inner, outer, matches = [], i, n; 10589 10590 for (i = 0, n = this._coordinates.length; i < n; i++) { 10591 inner = this._coordinates[i - 1] || 0; 10592 outer = Math.abs(this._coordinates[i]) + padding * rtl; 10593 10594 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 10595 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 10596 matches.push(i); 10597 } 10598 } 10599 10600 this.$stage.children('.active').removeClass('active'); 10601 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 10602 10603 if (this.settings.center) { 10604 this.$stage.children('.center').removeClass('center'); 10605 this.$stage.children().eq(this.current()).addClass('center'); 10606 } 10607 } 10608 } ]; 10609 10610 /** 10611 * Initializes the carousel. 10612 * @protected 10613 */ 10614 Owl.prototype.initialize = function() { 10615 this.enter('initializing'); 10616 this.trigger('initialize'); 10617 10618 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 10619 10620 if (this.settings.autoWidth && !this.is('pre-loading')) { 10621 var imgs, nestedSelector, width; 10622 imgs = this.$element.find('img'); 10623 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 10624 width = this.$element.children(nestedSelector).width(); 10625 10626 if (imgs.length && width <= 0) { 10627 this.preloadAutoWidthImages(imgs); 10628 } 10629 } 10630 10631 this.$element.addClass(this.options.loadingClass); 10632 10633 // create stage 10634 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 10635 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 10636 10637 // append stage 10638 this.$element.append(this.$stage.parent()); 10639 10640 // append content 10641 this.replace(this.$element.children().not(this.$stage.parent())); 10642 10643 // check visibility 10644 if (this.$element.is(':visible')) { 10645 // update view 10646 this.refresh(); 10647 } else { 10648 // invalidate width 10649 this.invalidate('width'); 10650 } 10651 10652 this.$element 10653 .removeClass(this.options.loadingClass) 10654 .addClass(this.options.loadedClass); 10655 10656 // register event handlers 10657 this.registerEventHandlers(); 10658 10659 this.leave('initializing'); 10660 this.trigger('initialized'); 10661 }; 10662 10663 /** 10664 * Setups the current settings. 10665 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 10666 * @todo Support for media queries by using `matchMedia` would be nice. 10667 * @public 10668 */ 10669 Owl.prototype.setup = function() { 10670 var viewport = this.viewport(),
10671 overwrites = this.options.responsive, 10672 match = -1, 10673 settings = null; 10674 10675 if (!overwrites) { 10676 settings = $.extend({}, this.options); 10677 } else { 10678 $.each(overwrites, function(breakpoint) { 10679 if (breakpoint <= viewport && breakpoint > match) { 10680 match = Number(breakpoint); 10681 } 10682 }); 10683 10684 settings = $.extend({}, this.options, overwrites[match]); 10685 delete settings.responsive; 10686 10687 // responsive class 10688 if (settings.responsiveClass) { 10689 this.$element.attr('class', 10690 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 10691 ); 10692 } 10693 } 10694 10695 if (this.settings === null || this._breakpoint !== match) { 10696 this.trigger('change', { property: { name: 'settings', value: settings } }); 10697 this._breakpoint = match; 10698 this.settings = settings; 10699 this.invalidate('settings'); 10700 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 10701 } 10702 }; 10703 10704 /** 10705 * Updates option logic if necessery. 10706 * @protected 10707 */ 10708 Owl.prototype.optionsLogic = function() { 10709 if (this.settings.autoWidth) { 10710 this.settings.stagePadding = false; 10711 this.settings.merge = false; 10712 } 10713 }; 10714 10715 /** 10716 * Prepares an item before add. 10717 * @todo Rename event parameter `content` to `item`. 10718 * @protected 10719 * @returns {jQuery|HTMLElement} - The item container. 10720 */ 10721 Owl.prototype.prepare = function(item, index) { 10722 var event = this.trigger('prepare', { content: item }); 10723 if (!event.data) { 10724 event.data = $('<' + this.settings.itemElement + '/>') 10725 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 10726 } 10727 10728 this.trigger('prepared', { content: event.data }); 10729 10730 return event.data; 10731 }; 10732 10733 /** 10734 * Updates the view. 10735 * @public 10736 */ 10737 Owl.prototype.update = function() { 10738 var i = 0, 10739 n = this._pipe.length, 10740 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 10741 cache = {}; 10742 10743 while (i < n) { 10744 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 10745 this._pipe[i].run(cache); 10746 } 10747 i++; 10748 } 10749 10750 this._invalidated = {}; 10751 10752 !this.is('valid') && this.enter('valid'); 10753 }; 10754 10755 /** 10756 * Gets the width of the view. 10757 * @public 10758 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 10759 * @returns {Number} - The width of the view in pixel. 10760 */ 10761 Owl.prototype.width = function(dimension) { 10762 dimension = dimension || Owl.Width.Default; 10763 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 10764 switch (dimension) { 10765 case Owl.Width.Inner: 10766 case Owl.Width.Outer: 10767 return this._width; 10768 default: 10769 return this._width - stagePadding * 2 + this.settings.margin; 10770 } 10771 }; 10772 10773 /** 10774 * Refreshes the carousel primarily for adaptive purposes. 10775 * @public 10776 */ 10777 Owl.prototype.refresh = function() { 10778 this.enter('refreshing'); 10779 this.trigger('refresh'); 10780 10781 this.setup(); 10782 10783 this.optionsLogic(); 10784 10785 this.$element.addClass(this.options.refreshClass); 10786 10787 this.update(); 10788 10789 this.$element.removeClass(this.options.refreshClass); 10790 10791 this.leave('refreshing'); 10792 this.trigger('refreshed'); 10793 }; 10794 10795 /** 10796 * Checks window `resize` event. 10797 * @protected 10798 */ 10799 Owl.prototype.onThrottledResize = function() { 10800 window.clearTimeout(this.resizeTimer); 10801 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 10802 }; 10803 10804 /** 10805 * Checks window `resize` event. 10806 * @protected 10807 */ 10808 Owl.prototype.onResize = function() { 10809 if (!this._items.length) { 10810 return false; 10811 } 10812 10813 if (this._width === this.$element.width()) { 10814 return false; 10815 } 10816 10817 if (!this.$element.is(':visible')) { 10818 return false; 10819 } 10820 10821 this.enter('resizing'); 10822 10823 if (this.trigger('resize').isDefaultPrevented()) { 10824 this.leave('resizing'); 10825 return false; 10826 } 10827 10828 this.invalidate('width'); 10829 10830 this.refresh(); 10831 10832 this.leave('resizing'); 10833 this.trigger('resized'); 10834 }; 10835 10836 /** 10837 * Registers event handlers. 10838 * @todo Check `msPointerEnabled` 10839 * @todo #261 10840 * @protected 10841 */ 10842 Owl.prototype.registerEventHandlers = function() { 10843 if ($.support.transition) { 10844 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 10845 } 10846 10847 if (this.settings.responsive !== false) { 10848 this.on(window, 'resize', this._handlers.onThrottledResize); 10849 } 10850 10851 if (this.settings.mouseDrag) { 10852 this.$element.addClass(this.options.dragClass); 10853 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 10854 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 10855 } 10856 10857 if (this.settings.touchDrag){ 10858 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 10859 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 10860 } 10861 }; 10862 10863 /** 10864 * Handles `touchstart` and `mousedown` events. 10865 * @todo Horizontal swipe threshold as option 10866 * @todo #261 10867 * @protected 10868 * @param {Event} event - The event arguments. 10869 */ 10870 Owl.prototype.onDragStart = function(event) { 10871 var stage = null; 10872 10873 if (event.which === 3) { 10874 return; 10875 } 10876
vendor: 14,340 bytes, lines 10877-11367
10877 if ($.support.transform) { 10878 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 10879 stage = { 10880 x: stage[stage.length === 16 ? 12 : 4], 10881 y: stage[stage.length === 16 ? 13 : 5] 10882 }; 10883 } else { 10884 stage = this.$stage.position(); 10885 stage = { 10886 x: this.settings.rtl ? 10887 stage.left + this.$stage.width() - this.width() + this.settings.margin : 10888 stage.left, 10889 y: stage.top 10890 }; 10891 } 10892 10893 if (this.is('animating')) { 10894 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 10895 this.invalidate('position'); 10896 } 10897 10898 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 10899 10900 this.speed(0); 10901 10902 this._drag.time = new Date().getTime(); 10903 this._drag.target = $(event.target); 10904 this._drag.stage.start = stage; 10905 this._drag.stage.current = stage; 10906 this._drag.pointer = this.pointer(event); 10907 10908 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 10909 10910 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 10911 var delta = this.difference(this._drag.pointer, this.pointer(event)); 10912 10913 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 10914 10915 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 10916 return; 10917 } 10918 10919 event.preventDefault(); 10920 10921 this.enter('dragging'); 10922 this.trigger('drag'); 10923 }, this)); 10924 }; 10925 10926 /** 10927 * Handles the `touchmove` and `mousemove` events. 10928 * @todo #261 10929 * @protected 10930 * @param {Event} event - The event arguments. 10931 */ 10932 Owl.prototype.onDragMove = function(event) { 10933 var minimum = null, 10934 maximum = null, 10935 pull = null, 10936 delta = this.difference(this._drag.pointer, this.pointer(event)), 10937 stage = this.difference(this._drag.stage.start, delta); 10938 10939 if (!this.is('dragging')) { 10940 return; 10941 } 10942 10943 event.preventDefault(); 10944 10945 if (this.settings.loop) { 10946 minimum = this.coordinates(this.minimum()); 10947 maximum = this.coordinates(this.maximum() + 1) - minimum; 10948 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 10949 } else { 10950 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 10951 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 10952 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 10953 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 10954 } 10955 10956 this._drag.stage.current = stage; 10957 10958 this.animate(stage.x); 10959 }; 10960 10961 /** 10962 * Handles the `touchend` and `mouseup` events. 10963 * @todo #261 10964 * @todo Threshold for click event 10965 * @protected 10966 * @param {Event} event - The event arguments. 10967 */ 10968 Owl.prototype.onDragEnd = function(event) { 10969 var delta = this.difference(this._drag.pointer, this.pointer(event)), 10970 stage = this._drag.stage.current, 10971 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 10972 10973 $(document).off('.owl.core'); 10974 10975 this.$element.removeClass(this.options.grabClass); 10976 10977 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 10978 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 10979 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 10980 this.invalidate('position'); 10981 this.update(); 10982 10983 this._drag.direction = direction; 10984 10985 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 10986 this._drag.target.one('click.owl.core', function() { return false; }); 10987 } 10988 } 10989 10990 if (!this.is('dragging')) { 10991 return; 10992 } 10993 10994 this.leave('dragging'); 10995 this.trigger('dragged'); 10996 }; 10997 10998 /** 10999 * Gets absolute position of the closest item for a coordinate. 11000 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 11001 * @protected 11002 * @param {Number} coordinate - The coordinate in pixel. 11003 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 11004 * @return {Number} - The absolute position of the closest item. 11005 */ 11006 Owl.prototype.closest = function(coordinate, direction) { 11007 var position = -1, 11008 pull = 30, 11009 width = this.width(), 11010 coordinates = this.coordinates(); 11011 11012 if (!this.settings.freeDrag) { 11013 // check closest item 11014 $.each(coordinates, $.proxy(function(index, value) { 11015 if (coordinate > value - pull && coordinate < value + pull) { 11016 position = index; 11017 } else if (this.op(coordinate, '<', value) 11018 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 11019 position = direction === 'left' ? index + 1 : index; 11020 } 11021 return position === -1; 11022 }, this)); 11023 } 11024 11025 if (!this.settings.loop) { 11026 // non loop boundries 11027 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 11028 position = coordinate = this.minimum(); 11029 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 11030 position = coordinate = this.maximum(); 11031 } 11032 } 11033 11034 return position; 11035 }; 11036 11037 /** 11038 * Animates the stage. 11039 * @todo #270 11040 * @public 11041 * @param {Number} coordinate - The coordinate in pixels. 11042 */ 11043 Owl.prototype.animate = function(coordinate) { 11044 var animate = this.speed() > 0; 11045 11046 this.is('animating') && this.onTransitionEnd(); 11047 11048 if (animate) { 11049 this.enter('animating'); 11050 this.trigger('translate'); 11051 } 11052 11053 if ($.support.transform3d && $.support.transition) { 11054 this.$stage.css({ 11055 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 11056 transition: (this.speed() / 1000) + 's' 11057 }); 11058 } else if (animate) { 11059 this.$stage.animate({ 11060 left: coordinate + 'px' 11061 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 11062 } else { 11063 this.$stage.css({ 11064 left: coordinate + 'px' 11065 }); 11066 } 11067 }; 11068 11069 /** 11070 * Checks whether the carousel is in a specific state or not. 11071 * @param {String} state - The state to check. 11072 * @returns {Boolean} - The flag which indicates if the carousel is busy. 11073 */ 11074 Owl.prototype.is = function(state) { 11075 return this._states.current[state] && this._states.current[state] > 0; 11076 }; 11077 11078 /** 11079 * Sets the absolute position of the current item. 11080 * @public 11081 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 11082 * @returns {Number} - The absolute position of the current item. 11083 */ 11084 Owl.prototype.current = function(position) { 11085 if (position === undefined) { 11086 return this._current; 11087 } 11088 11089 if (this._items.length === 0) { 11090 return undefined; 11091 } 11092 11093 position = this.normalize(position); 11094 11095 if (this._current !== position) { 11096 var event = this.trigger('change', { property: { name: 'position', value: position } }); 11097 11098 if (event.data !== undefined) { 11099 position = this.normalize(event.data); 11100 } 11101 11102 this._current = position; 11103 11104 this.invalidate('position'); 11105 11106 this.trigger('changed', { property: { name: 'position', value: this._current } }); 11107 } 11108 11109 return this._current; 11110 }; 11111 11112 /** 11113 * Invalidates the given part of the update routine. 11114 * @param {String} [part] - The part to invalidate. 11115 * @returns {Array.<String>} - The invalidated parts. 11116 */ 11117 Owl.prototype.invalidate = function(part) { 11118 if ($.type(part) === 'string') { 11119 this._invalidated[part] = true; 11120 this.is('valid') && this.leave('valid'); 11121 } 11122 return $.map(this._invalidated, function(v, i) { return i }); 11123 }; 11124 11125 /** 11126 * Resets the absolute position of the current item. 11127 * @public 11128 * @param {Number} position - The absolute position of the new item. 11129 */ 11130 Owl.prototype.reset = function(position) { 11131 position = this.normalize(position); 11132 11133 if (position === undefined) { 11134 return; 11135 } 11136 11137 this._speed = 0; 11138 this._current = position; 11139 11140 this.suppress([ 'translate', 'translated' ]); 11141 11142 this.animate(this.coordinates(position)); 11143 11144 this.release([ 'translate', 'translated' ]); 11145 }; 11146 11147 /** 11148 * Normalizes an absolute or a relative position of an item. 11149 * @public 11150 * @param {Number} position - The absolute or relative position to normalize. 11151 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 11152 * @returns {Number} - The normalized position. 11153 */ 11154 Owl.prototype.normalize = function(position, relative) { 11155 var n = this._items.length, 11156 m = relative ? 0 : this._clones.length; 11157 11158 if (!$.isNumeric(position) || n < 1) { 11159 position = undefined; 11160 } else if (position < 0 || position >= n + m) { 11161 position = ((position - m / 2) % n + n) % n + m / 2; 11162 } 11163 11164 return position; 11165 }; 11166 11167 /** 11168 * Converts an absolute position of an item into a relative one. 11169 * @public 11170 * @param {Number} position - The absolute position to convert. 11171 * @returns {Number} - The converted position. 11172 */ 11173 Owl.prototype.relative = function(position) { 11174 position -= this._clones.length / 2; 11175 return this.normalize(position, true); 11176 }; 11177 11178 /** 11179 * Gets the maximum position for the current item. 11180 * @public 11181 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11182 * @returns {Number} 11183 */ 11184 Owl.prototype.maximum = function(relative) { 11185 var settings = this.settings, 11186 maximum = this._coordinates.length, 11187 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 11188 i = -1, j; 11189 11190 if (settings.loop) { 11191 maximum = this._clones.length / 2 + this._items.length - 1; 11192 } else if (settings.autoWidth || settings.merge) { 11193 // binary search 11194 while (maximum - i > 1) { 11195 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 11196 ? i = j : maximum = j; 11197 } 11198 } else if (settings.center) { 11199 maximum = this._items.length - 1; 11200 } else { 11201 maximum = this._items.length - settings.items; 11202 } 11203 11204 if (relative) { 11205 maximum -= this._clones.length / 2; 11206 } 11207 11208 return Math.max(maximum, 0); 11209 }; 11210 11211 /** 11212 * Gets the minimum position for the current item. 11213 * @public 11214 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11215 * @returns {Number} 11216 */ 11217 Owl.prototype.minimum = function(relative) { 11218 return relative ? 0 : this._clones.length / 2; 11219 }; 11220 11221 /** 11222 * Gets an item at the specified relative position. 11223 * @public 11224 * @param {Number} [position] - The relative position of the item. 11225 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11226 */ 11227 Owl.prototype.items = function(position) { 11228 if (position === undefined) { 11229 return this._items.slice(); 11230 } 11231 11232 position = this.normalize(position, true); 11233 return this._items[position]; 11234 }; 11235 11236 /** 11237 * Gets an item at the specified relative position. 11238 * @public 11239 * @param {Number} [position] - The relative position of the item. 11240 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11241 */ 11242 Owl.prototype.mergers = function(position) { 11243 if (position === undefined) { 11244 return this._mergers.slice(); 11245 } 11246 11247 position = this.normalize(position, true); 11248 return this._mergers[position]; 11249 }; 11250 11251 /** 11252 * Gets the absolute positions of clones for an item. 11253 * @public 11254 * @param {Number} [position] - The relative position of the item. 11255 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 11256 */ 11257 Owl.prototype.clones = function(position) { 11258 var odd = this._clones.length / 2, 11259 even = odd + this._items.length, 11260 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 11261 11262 if (position === undefined) { 11263 return $.map(this._clones, function(v, i) { return map(i) }); 11264 } 11265 11266 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 11267 }; 11268 11269 /** 11270 * Sets the current animation speed. 11271 * @public 11272 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 11273 * @returns {Number} - The current animation speed in milliseconds. 11274 */ 11275 Owl.prototype.speed = function(speed) { 11276 if (speed !== undefined) { 11277 this._speed = speed; 11278 } 11279 11280 return this._speed; 11281 }; 11282 11283 /** 11284 * Gets the coordinate of an item. 11285 * @todo The name of this method is missleanding. 11286 * @public 11287 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 11288 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 11289 */ 11290 Owl.prototype.coordinates = function(position) { 11291 var coordinate = null; 11292 11293 if (position === undefined) { 11294 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 11295 return this.coordinates(index); 11296 }, this)); 11297 } 11298 11299 if (this.settings.center) { 11300 coordinate = this._coordinates[position]; 11301 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 11302 } else { 11303 coordinate = this._coordinates[position - 1] || 0; 11304 } 11305 11306 return coordinate; 11307 }; 11308 11309 /** 11310 * Calculates the speed for a translation. 11311 * @protected 11312 * @param {Number} from - The absolute position of the start item. 11313 * @param {Number} to - The absolute position of the target item. 11314 * @param {Number} [factor=undefined] - The time factor in milliseconds. 11315 * @returns {Number} - The time in milliseconds for the translation. 11316 */ 11317 Owl.prototype.duration = function(from, to, factor) { 11318 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 11319 }; 11320 11321 /** 11322 * Slides to the specified item. 11323 * @public 11324 * @param {Number} position - The position of the item. 11325 * @param {Number} [speed] - The time in milliseconds for the transition. 11326 */ 11327 Owl.prototype.to = function(position, speed) { 11328 var current = this.current(), 11329 revert = null, 11330 distance = position - this.relative(current), 11331 direction = (distance > 0) - (distance < 0), 11332 items = this._items.length, 11333 minimum = this.minimum(), 11334 maximum = this.maximum(); 11335 11336 if (this.settings.loop) { 11337 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 11338 distance += direction * -1 * items; 11339 } 11340 11341 position = current + distance; 11342 revert = ((position - minimum) % items + items) % items + minimum; 11343 11344 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 11345 current = revert - distance; 11346 position = revert; 11347 this.reset(current); 11348 } 11349 } else if (this.settings.rewind) { 11350 maximum += 1; 11351 position = (position % maximum + maximum) % maximum; 11352 } else { 11353 position = Math.max(minimum, Math.min(maximum, position)); 11354 } 11355 11356 this.speed(this.duration(current, position, speed)); 11357 this.current(position); 11358 11359 if (this.$element.is(':visible')) { 11360 this.update(); 11361 } 11362 }; 11363 11364 /** 11365 * Slides to the next item. 11366 * @public 11367 * @param {Number}
vendor: 4,086 bytes, lines 11367-11503
11367 [speed] - The time in milliseconds for the transition. 11368 */ 11369 Owl.prototype.next = function(speed) { 11370 speed = speed || false; 11371 this.to(this.relative(this.current()) + 1, speed); 11372 }; 11373 11374 /** 11375 * Slides to the previous item. 11376 * @public 11377 * @param {Number} [speed] - The time in milliseconds for the transition. 11378 */ 11379 Owl.prototype.prev = function(speed) { 11380 speed = speed || false; 11381 this.to(this.relative(this.current()) - 1, speed); 11382 }; 11383 11384 /** 11385 * Handles the end of an animation. 11386 * @protected 11387 * @param {Event} event - The event arguments. 11388 */ 11389 Owl.prototype.onTransitionEnd = function(event) { 11390 11391 // if css2 animation then event object is undefined 11392 if (event !== undefined) { 11393 event.stopPropagation(); 11394 11395 // Catch only owl-stage transitionEnd event 11396 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 11397 return false; 11398 } 11399 } 11400 11401 this.leave('animating'); 11402 this.trigger('translated'); 11403 }; 11404 11405 /** 11406 * Gets viewport width. 11407 * @protected 11408 * @return {Number} - The width in pixel. 11409 */ 11410 Owl.prototype.viewport = function() { 11411 var width; 11412 if (this.options.responsiveBaseElement !== window) { 11413 width = $(this.options.responsiveBaseElement).width(); 11414 } else if (window.innerWidth) { 11415 width = window.innerWidth; 11416 } else if (document.documentElement && document.documentElement.clientWidth) { 11417 width = document.documentElement.clientWidth; 11418 } else { 11419 throw 'Can not detect viewport width.'; 11420 } 11421 11422 return width; 11423 }; 11424 11425 /** 11426 * Replaces the current content. 11427 * @public 11428 * @param {HTMLElement|jQuery|String} content - The new content. 11429 */ 11430 Owl.prototype.replace = function(content) { 11431 this.$stage.empty(); 11432 this._items = []; 11433 11434 if (content) { 11435 content = (content instanceof jQuery) ? content : $(content); 11436 } 11437 11438 if (this.settings.nestedItemSelector) { 11439 content = content.find('.' + this.settings.nestedItemSelector); 11440 } 11441 11442 content.filter(function() { 11443 return this.nodeType === 1; 11444 }).each($.proxy(function(index, item) { 11445 item = this.prepare(item, index); 11446 this.$stage.append(item); 11447 this._items.push(item); 11448 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 11449 }, this)); 11450 11451 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 11452 11453 this.invalidate('items'); 11454 }; 11455 11456 /** 11457 * Adds an item. 11458 * @todo Use `item` instead of `content` for the event arguments. 11459 * @public 11460 * @param {HTMLElement|jQuery|String} content - The item content to add. 11461 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 11462 */ 11463 Owl.prototype.add = function(content, position) { 11464 var current = this.relative(this._current); 11465 11466 position = position === undefined ? this._items.length : this.normalize(position, true); 11467 content = content instanceof jQuery ? content : $(content); 11468 11469 this.trigger('add', { content: content, position: position }); 11470 11471 content = this.prepare(content, this._items[current].index()); 11472 11473 if (this._items.length === 0 || position === this._items.length) { 11474 this._items.length === 0 && this.$stage.append(content); 11475 this._items.length !== 0 && this._items[position - 1].after(content); 11476 this._items.push(content); 11477 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11478 } else { 11479 this._items[position].before(content); 11480 this._items.splice(position, 0, content); 11481 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11482 } 11483 11484 this._items[current] && this.reset(this._items[current].index()); 11485 11486 this.invalidate('items'); 11487 11488 this.trigger('added', { content: content, position: position }); 11489 }; 11490 11491 /** 11492 * Removes an item by its position. 11493 * @todo Use `item` instead of `content` for the event arguments. 11494 * @public 11495 * @param {Number} position - The relative position of the item to remove. 11496 */ 11497 Owl.prototype.remove = function(position) { 11498 position = this.normalize(position, true); 11499 11500 if (position === undefined) { 11501 return; 11502 } 11503
vendor: 40,414 bytes, lines 11504-13070
11504 this.trigger('remove', { content: this._items[position], position: position }); 11505 11506 this._items[position].remove(); 11507 this._items.splice(position, 1); 11508 this._mergers.splice(position, 1); 11509 11510 this.invalidate('items'); 11511 11512 this.trigger('removed', { content: null, position: position }); 11513 }; 11514 11515 /** 11516 * Preloads images with auto width. 11517 * @todo Replace by a more generic approach 11518 * @protected 11519 */ 11520 Owl.prototype.preloadAutoWidthImages = function(images) { 11521 images.each($.proxy(function(i, element) { 11522 this.enter('pre-loading'); 11523 element = $(element); 11524 $(new Image()).one('load', $.proxy(function(e) { 11525 element.attr('src', e.target.src); 11526 element.css('opacity', 1); 11527 this.leave('pre-loading'); 11528 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 11529 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 11530 }, this)); 11531 }; 11532 11533 /** 11534 * Destroys the carousel. 11535 * @public 11536 */ 11537 Owl.prototype.destroy = function() { 11538 11539 this.$element.off('.owl.core'); 11540 this.$stage.off('.owl.core'); 11541 $(document).off('.owl.core'); 11542 11543 if (this.settings.responsive !== false) { 11544 window.clearTimeout(this.resizeTimer); 11545 this.off(window, 'resize', this._handlers.onThrottledResize); 11546 } 11547 11548 for (var i in this._plugins) { 11549 this._plugins[i].destroy(); 11550 } 11551 11552 this.$stage.children('.cloned').remove(); 11553 11554 this.$stage.unwrap(); 11555 this.$stage.children().contents().unwrap(); 11556 this.$stage.children().unwrap(); 11557 11558 this.$element 11559 .removeClass(this.options.refreshClass) 11560 .removeClass(this.options.loadingClass) 11561 .removeClass(this.options.loadedClass) 11562 .removeClass(this.options.rtlClass) 11563 .removeClass(this.options.dragClass) 11564 .removeClass(this.options.grabClass) 11565 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 11566 .removeData('owl.carousel'); 11567 }; 11568 11569 /** 11570 * Operators to calculate right-to-left and left-to-right. 11571 * @protected 11572 * @param {Number} [a] - The left side operand. 11573 * @param {String} [o] - The operator. 11574 * @param {Number} [b] - The right side operand. 11575 */ 11576 Owl.prototype.op = function(a, o, b) { 11577 var rtl = this.settings.rtl; 11578 switch (o) { 11579 case '<': 11580 return rtl ? a > b : a < b; 11581 case '>': 11582 return rtl ? a < b : a > b; 11583 case '>=': 11584 return rtl ? a <= b : a >= b; 11585 case '<=': 11586 return rtl ? a >= b : a <= b; 11587 default: 11588 break; 11589 } 11590 }; 11591 11592 /** 11593 * Attaches to an internal event. 11594 * @protected 11595 * @param {HTMLElement} element - The event source. 11596 * @param {String} event - The event name. 11597 * @param {Function} listener - The event handler to attach. 11598 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 11599 */ 11600 Owl.prototype.on = function(element, event, listener, capture) { 11601 if (element.addEventListener) { 11602 element.addEventListener(event, listener, capture); 11603 } else if (element.attachEvent) { 11604 element.attachEvent('on' + event, listener); 11605 } 11606 }; 11607 11608 /** 11609 * Detaches from an internal event. 11610 * @protected 11611 * @param {HTMLElement} element - The event source. 11612 * @param {String} event - The event name. 11613 * @param {Function} listener - The attached event handler to detach. 11614 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 11615 */ 11616 Owl.prototype.off = function(element, event, listener, capture) { 11617 if (element.removeEventListener) { 11618 element.removeEventListener(event, listener, capture); 11619 } else if (element.detachEvent) { 11620 element.detachEvent('on' + event, listener); 11621 } 11622 }; 11623 11624 /** 11625 * Triggers a public event. 11626 * @todo Remove `status`, `relatedTarget` should be used instead. 11627 * @protected 11628 * @param {String} name - The event name. 11629 * @param {*} [data=null] - The event data. 11630 * @param {String} [namespace=carousel] - The event namespace. 11631 * @param {String} [state] - The state which is associated with the event. 11632 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 11633 * @returns {Event} - The event arguments. 11634 */ 11635 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 11636 var status = { 11637 item: { count: this._items.length, index: this.current() } 11638 }, handler = $.camelCase( 11639 $.grep([ 'on', name, namespace ], function(v) { return v }) 11640 .join('-').toLowerCase() 11641 ), event = $.Event( 11642 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 11643 $.extend({ relatedTarget: this }, status, data) 11644 ); 11645 11646 if (!this._supress[name]) { 11647 $.each(this._plugins, function(name, plugin) { 11648 if (plugin.onTrigger) { 11649 plugin.onTrigger(event); 11650 } 11651 }); 11652 11653 this.register({ type: Owl.Type.Event, name: name }); 11654 this.$element.trigger(event); 11655 11656 if (this.settings && typeof this.settings[handler] === 'function') { 11657 this.settings[handler].call(this, event); 11658 } 11659 } 11660 11661 return event; 11662 }; 11663 11664 /** 11665 * Enters a state. 11666 * @param name - The state name. 11667 */ 11668 Owl.prototype.enter = function(name) { 11669 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11670 if (this._states.current[name] === undefined) { 11671 this._states.current[name] = 0; 11672 } 11673 11674 this._states.current[name]++; 11675 }, this)); 11676 }; 11677 11678 /** 11679 * Leaves a state. 11680 * @param name - The state name. 11681 */ 11682 Owl.prototype.leave = function(name) { 11683 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11684 this._states.current[name]--; 11685 }, this)); 11686 }; 11687 11688 /** 11689 * Registers an event or state. 11690 * @public 11691 * @param {Object} object - The event or state to register. 11692 */ 11693 Owl.prototype.register = function(object) { 11694 if (object.type === Owl.Type.Event) { 11695 if (!$.event.special[object.name]) { 11696 $.event.special[object.name] = {}; 11697 } 11698 11699 if (!$.event.special[object.name].owl) { 11700 var _default = $.event.special[object.name]._default; 11701 $.event.special[object.name]._default = function(e) { 11702 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 11703 return _default.apply(this, arguments); 11704 } 11705 return e.namespace && e.namespace.indexOf('owl') > -1; 11706 }; 11707 $.event.special[object.name].owl = true; 11708 } 11709 } else if (object.type === Owl.Type.State) { 11710 if (!this._states.tags[object.name]) { 11711 this._states.tags[object.name] = object.tags; 11712 } else { 11713 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 11714 } 11715 11716 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 11717 return $.inArray(tag, this._states.tags[object.name]) === i; 11718 }, this)); 11719 } 11720 }; 11721 11722 /** 11723 * Suppresses events. 11724 * @protected 11725 * @param {Array.<String>} events - The events to suppress. 11726 */ 11727 Owl.prototype.suppress = function(events) { 11728 $.each(events, $.proxy(function(index, event) { 11729 this._supress[event] = true; 11730 }, this)); 11731 }; 11732 11733 /** 11734 * Releases suppressed events. 11735 * @protected 11736 * @param {Array.<String>} events - The events to release. 11737 */ 11738 Owl.prototype.release = function(events) { 11739 $.each(events, $.proxy(function(index, event) { 11740 delete this._supress[event]; 11741 }, this)); 11742 }; 11743 11744 /** 11745 * Gets unified pointer coordinates from event. 11746 * @todo #261 11747 * @protected 11748 * @param {Event} - The `mousedown` or `touchstart` event. 11749 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 11750 */ 11751 Owl.prototype.pointer = function(event) { 11752 var result = { x: null, y: null }; 11753 11754 event = event.originalEvent || event || window.event; 11755 11756 event = event.touches && event.touches.length ? 11757 event.touches[0] : event.changedTouches && event.changedTouches.length ? 11758 event.changedTouches[0] : event; 11759 11760 if (event.pageX) { 11761 result.x = event.pageX; 11762 result.y = event.pageY; 11763 } else { 11764 result.x = event.clientX; 11765 result.y = event.clientY; 11766 } 11767 11768 return result; 11769 }; 11770 11771 /** 11772 * Gets the difference of two vectors. 11773 * @todo #261 11774 * @protected 11775 * @param {Object} - The first vector. 11776 * @param {Object} - The second vector. 11777 * @returns {Object} - The difference. 11778 */ 11779 Owl.prototype.difference = function(first, second) { 11780 return { 11781 x: first.x - second.x, 11782 y: first.y - second.y 11783 }; 11784 }; 11785 11786 /** 11787 * The jQuery Plugin for the Owl Carousel 11788 * @todo Navigation plugin `next` and `prev` 11789 * @public 11790 */ 11791 $.fn.owlCarousel = function(option) { 11792 var args = Array.prototype.slice.call(arguments, 1); 11793 11794 return this.each(function() { 11795 var $this = $(this), 11796 data = $this.data('owl.carousel'); 11797 11798 if (!data) { 11799 data = new Owl(this, typeof option == 'object' && option); 11800 $this.data('owl.carousel', data); 11801 11802 $.each([ 11803 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 11804 ], function(i, event) { 11805 data.register({ type: Owl.Type.Event, name: event }); 11806 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 11807 if (e.namespace && e.relatedTarget !== this) { 11808 this.suppress([ event ]); 11809 data[event].apply(this, [].slice.call(arguments, 1)); 11810 this.release([ event ]); 11811 } 11812 }, data)); 11813 }); 11814 } 11815 11816 if (typeof option == 'string' && option.charAt(0) !== '_') { 11817 data[option].apply(data, args); 11818 } 11819 }); 11820 }; 11821 11822 /** 11823 * The constructor for the jQuery Plugin 11824 * @public 11825 */ 11826 $.fn.owlCarousel.Constructor = Owl; 11827 11828})(window.Zepto || window.jQuery, window, document); 11829 11830/** 11831 * AutoRefresh Plugin 11832 * @version 2.0.0-beta.3 11833 * @author Artus Kolanowski 11834 * @license The MIT License (MIT) 11835 */ 11836;(function($, window, document, undefined) { 11837 11838 /** 11839 * Creates the auto refresh plugin. 11840 * @class The Auto Refresh Plugin 11841 * @param {Owl} carousel - The Owl Carousel 11842 */ 11843 var AutoRefresh = function(carousel) { 11844 /** 11845 * Reference to the core. 11846 * @protected 11847 * @type {Owl} 11848 */ 11849 this._core = carousel; 11850 11851 /** 11852 * Refresh interval. 11853 * @protected 11854 * @type {number} 11855 */ 11856 this._interval = null; 11857 11858 /** 11859 * Whether the element is currently visible or not. 11860 * @protected 11861 * @type {Boolean} 11862 */ 11863 this._visible = null; 11864 11865 /** 11866 * All event handlers. 11867 * @protected 11868 * @type {Object} 11869 */ 11870 this._handlers = { 11871 'initialized.owl.carousel': $.proxy(function(e) { 11872 if (e.namespace && this._core.settings.autoRefresh) { 11873 this.watch(); 11874 } 11875 }, this) 11876 }; 11877 11878 // set default options 11879 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 11880 11881 // register event handlers 11882 this._core.$element.on(this._handlers); 11883 }; 11884 11885 /** 11886 * Default options. 11887 * @public 11888 */ 11889 AutoRefresh.Defaults = { 11890 autoRefresh: true, 11891 autoRefreshInterval: 500 11892 }; 11893 11894 /** 11895 * Watches the element. 11896 */ 11897 AutoRefresh.prototype.watch = function() { 11898 if (this._interval) { 11899 return; 11900 } 11901 11902 this._visible = this._core.$element.is(':visible'); 11903 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 11904 }; 11905 11906 /** 11907 * Refreshes the element. 11908 */ 11909 AutoRefresh.prototype.refresh = function() { 11910 if (this._core.$element.is(':visible') === this._visible) { 11911 return; 11912 } 11913 11914 this._visible = !this._visible; 11915 11916 this._core.$element.toggleClass('owl-hidden', !this._visible); 11917 11918 this._visible && (this._core.invalidate('width') && this._core.refresh()); 11919 }; 11920 11921 /** 11922 * Destroys the plugin. 11923 */ 11924 AutoRefresh.prototype.destroy = function() { 11925 var handler, property; 11926 11927 window.clearInterval(this._interval); 11928 11929 for (handler in this._handlers) { 11930 this._core.$element.off(handler, this._handlers[handler]); 11931 } 11932 for (property in Object.getOwnPropertyNames(this)) { 11933 typeof this[property] != 'function' && (this[property] = null); 11934 } 11935 }; 11936 11937 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 11938 11939})(window.Zepto || window.jQuery, window, document); 11940 11941/** 11942 * Lazy Plugin 11943 * @version 2.0.0-beta.3 11944 * @author Bartosz Wojciechowski 11945 * @license The MIT License (MIT) 11946 */ 11947;(function($, window, document, undefined) { 11948 11949 /** 11950 * Creates the lazy plugin. 11951 * @class The Lazy Plugin 11952 * @param {Owl} carousel - The Owl Carousel 11953 */ 11954 var Lazy = function(carousel) { 11955 11956 /** 11957 * Reference to the core. 11958 * @protected 11959 * @type {Owl} 11960 */ 11961 this._core = carousel; 11962 11963 /** 11964 * Already loaded items. 11965 * @protected 11966 * @type {Array.<jQuery>} 11967 */ 11968 this._loaded = []; 11969 11970 /** 11971 * Event handlers. 11972 * @protected 11973 * @type {Object} 11974 */ 11975 this._handlers = { 11976 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 11977 if (!e.namespace) { 11978 return; 11979 } 11980 11981 if (!this._core.settings || !this._core.settings.lazyLoad) { 11982 return; 11983 } 11984 11985 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 11986 var settings = this._core.settings, 11987 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 11988 i = ((settings.center && n * -1) || 0), 11989 position = ((e.property && e.property.value) || this._core.current()) + i, 11990 clones = this._core.clones().length, 11991 load = $.proxy(function(i, v) { this.load(v) }, this); 11992 11993 while (i++ < n) { 11994 this.load(clones / 2 + this._core.relative(position)); 11995 clones && $.each(this._core.clones(this._core.relative(position)), load); 11996 position++; 11997 } 11998 } 11999 }, this) 12000 }; 12001 12002 // set the default options 12003 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 12004 12005 // register event handler 12006 this._core.$element.on(this._handlers); 12007 } 12008 12009 /** 12010 * Default options. 12011 * @public 12012 */ 12013 Lazy.Defaults = { 12014 lazyLoad: false 12015 } 12016 12017 /** 12018 * Loads all resources of an item at the specified position. 12019 * @param {Number} position - The absolute position of the item. 12020 * @protected 12021 */ 12022 Lazy.prototype.load = function(position) { 12023 var $item = this._core.$stage.children().eq(position), 12024 $elements = $item && $item.find('.owl-lazy'); 12025 12026 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 12027 return; 12028 } 12029 12030 $elements.each($.proxy(function(index, element) { 12031 var $element = $(element), image, 12032 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 12033 12034 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 12035 12036 if ($element.is('img')) { 12037 $element.one('load.owl.lazy', $.proxy(function() { 12038 $element.css('opacity', 1); 12039 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12040 }, this)).attr('src', url); 12041 } else { 12042 image = new Image(); 12043 image.onload = $.proxy(function() { 12044 $element.css({ 12045 'background-image': 'url(' + url + ')', 12046 'opacity': '1' 12047 }); 12048 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 12049 }, this); 12050 image.src = url; 12051 } 12052 }, this)); 12053 12054 this._loaded.push($item.get(0)); 12055 } 12056 12057 /** 12058 * Destroys the plugin. 12059 * @public 12060 */ 12061 Lazy.prototype.destroy = function() { 12062 var handler, property; 12063 12064 for (handler in this.handlers) { 12065 this._core.$element.off(handler, this.handlers[handler]); 12066 } 12067 for (property in Object.getOwnPropertyNames(this)) { 12068 typeof this[property] != 'function' && (this[property] = null); 12069 } 12070 }; 12071 12072 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 12073 12074})(window.Zepto || window.jQuery, window, document); 12075 12076/** 12077 * AutoHeight Plugin 12078 * @version 2.0.0-beta.3 12079 * @author Bartosz Wojciechowski 12080 * @license The MIT License (MIT) 12081 */ 12082;(function($, window, document, undefined) { 12083 12084 /** 12085 * Creates the auto height plugin. 12086 * @class The Auto Height Plugin 12087 * @param {Owl} carousel - The Owl Carousel 12088 */ 12089 var AutoHeight = function(carousel) { 12090 /** 12091 * Reference to the core. 12092 * @protected 12093 * @type {Owl} 12094 */ 12095 this._core = carousel; 12096 12097 /** 12098 * All event handlers. 12099 * @protected 12100 * @type {Object} 12101 */ 12102 this._handlers = { 12103 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 12104 if (e.namespace && this._core.settings.autoHeight) { 12105 this.update(); 12106 } 12107 }, this), 12108 'changed.owl.carousel': $.proxy(function(e) { 12109 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 12110 this.update(); 12111 } 12112 }, this), 12113 'loaded.owl.lazy': $.proxy(function(e) { 12114 if (e.namespace && this._core.settings.autoHeight 12115 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 12116 this.update(); 12117 } 12118 }, this) 12119 }; 12120 12121 // set default options 12122 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 12123 12124 // register event handlers 12125 this._core.$element.on(this._handlers); 12126 }; 12127 12128 /** 12129 * Default options. 12130 * @public 12131 */ 12132 AutoHeight.Defaults = { 12133 autoHeight: false, 12134 autoHeightClass: 'owl-height' 12135 }; 12136 12137 /** 12138 * Updates the view. 12139 */ 12140 AutoHeight.prototype.update = function() { 12141 var start = this._core._current, 12142 end = start + this._core.settings.items, 12143 visible = this._core.$stage.children().toArray().slice(start, end); 12144 heights = [], 12145 maxheight = 0; 12146 12147 $.each(visible, function(index, item) { 12148 heights.push($(item).height()); 12149 }); 12150 12151 maxheight = Math.max.apply(null, heights); 12152 12153 this._core.$stage.parent() 12154 .height(maxheight) 12155 .addClass(this._core.settings.autoHeightClass); 12156 }; 12157 12158 AutoHeight.prototype.destroy = function() { 12159 var handler, property; 12160 12161 for (handler in this._handlers) { 12162 this._core.$element.off(handler, this._handlers[handler]); 12163 } 12164 for (property in Object.getOwnPropertyNames(this)) { 12165 typeof this[property] != 'function' && (this[property] = null); 12166 } 12167 }; 12168 12169 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 12170 12171})(window.Zepto || window.jQuery, window, document); 12172 12173/** 12174 * Video Plugin 12175 * @version 2.0.0-beta.3 12176 * @author Bartosz Wojciechowski 12177 * @license The MIT License (MIT) 12178 */ 12179;(function($, window, document, undefined) { 12180 12181 /** 12182 * Creates the video plugin. 12183 * @class The Video Plugin 12184 * @param {Owl} carousel - The Owl Carousel 12185 */ 12186 var Video = function(carousel) { 12187 /** 12188 * Reference to the core. 12189 * @protected 12190 * @type {Owl} 12191 */ 12192 this._core = carousel; 12193 12194 /** 12195 * Cache all video URLs. 12196 * @protected 12197 * @type {Object} 12198 */ 12199 this._videos = {}; 12200 12201 /** 12202 * Current playing item. 12203 * @protected 12204 * @type {jQuery} 12205 */ 12206 this._playing = null; 12207 12208 /** 12209 * All event handlers. 12210 * @todo The cloned content removale is too late 12211 * @protected 12212 * @type {Object} 12213 */ 12214 this._handlers = { 12215 'initialized.owl.carousel': $.proxy(function(e) { 12216 if (e.namespace) { 12217 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 12218 } 12219 }, this), 12220 'resize.owl.carousel': $.proxy(function(e) { 12221 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 12222 e.preventDefault(); 12223 } 12224 }, this), 12225 'refreshed.owl.carousel': $.proxy(function(e) { 12226 if (e.namespace && this._core.is('resizing')) { 12227 this._core.$stage.find('.cloned .owl-video-frame').remove(); 12228 } 12229 }, this), 12230 'changed.owl.carousel': $.proxy(function(e) { 12231 if (e.namespace && e.property.name === 'position' && this._playing) { 12232 this.stop(); 12233 } 12234 }, this), 12235 'prepared.owl.carousel': $.proxy(function(e) { 12236 if (!e.namespace) { 12237 return; 12238 } 12239 12240 var $element = $(e.content).find('.owl-video'); 12241 12242 if ($element.length) { 12243 $element.css('display', 'none'); 12244 this.fetch($element, $(e.content)); 12245 } 12246 }, this) 12247 }; 12248 12249 // set default options 12250 this._core.options = $.extend({}, Video.Defaults, this._core.options); 12251 12252 // register event handlers 12253 this._core.$element.on(this._handlers); 12254 12255 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 12256 this.play(e); 12257 }, this)); 12258 }; 12259 12260 /** 12261 * Default options. 12262 * @public 12263 */ 12264 Video.Defaults = { 12265 video: false, 12266 videoHeight: false, 12267 videoWidth: false 12268 }; 12269 12270 /** 12271 * Gets the video ID and the type (YouTube/Vimeo only). 12272 * @protected 12273 * @param {jQuery} target - The target containing the video data. 12274 * @param {jQuery} item - The item containing the video. 12275 */ 12276 Video.prototype.fetch = function(target, item) { 12277 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 12278 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 12279 width = target.attr('data-width') || this._core.settings.videoWidth, 12280 height = target.attr('data-height') || this._core.settings.videoHeight, 12281 url = target.attr('href'); 12282 12283 if (url) { 12284 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+)?/); 12285 12286 if (id[3].indexOf('youtu') > -1) { 12287 type = 'youtube'; 12288 } else if (id[3].indexOf('vimeo') > -1) { 12289 type = 'vimeo'; 12290 } else { 12291 throw new Error('Video URL not supported.'); 12292 } 12293 id = id[6]; 12294 } else { 12295 throw new Error('Missing video URL.'); 12296 } 12297 12298 this._videos[url] = { 12299 type: type, 12300 id: id, 12301 width: width, 12302 height: height 12303 }; 12304 12305 item.attr('data-video', url); 12306 12307 this.thumbnail(target, this._videos[url]); 12308 }; 12309 12310 /** 12311 * Creates video thumbnail. 12312 * @protected 12313 * @param {jQuery} target - The target containing the video data. 12314 * @param {Object} info - The video info object. 12315 * @see `fetch` 12316 */ 12317 Video.prototype.thumbnail = function(target, video) { 12318 var tnLink, 12319 icon, 12320 path, 12321 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 12322 customTn = target.find('img'), 12323 srcType = 'src', 12324 lazyClass = '', 12325 settings = this._core.settings, 12326 create = function(path) { 12327 icon = '<div class="owl-video-play-icon"></div>'; 12328 12329 if (settings.lazyLoad) { 12330 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 12331 } else { 12332 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 12333 } 12334 target.after(tnLink); 12335 target.after(icon); 12336 }; 12337 12338 // wrap video content into owl-video-wrapper div 12339 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 12340 12341 if (this._core.settings.lazyLoad) { 12342 srcType = 'data-src'; 12343 lazyClass = 'owl-lazy'; 12344 } 12345 12346 // custom thumbnail 12347 if (customTn.length) { 12348 create(customTn.attr(srcType)); 12349 customTn.remove(); 12350 return false; 12351 } 12352 12353 if (video.type === 'youtube') { 12354 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 12355 create(path); 12356 } else if (video.type === 'vimeo') { 12357 $.ajax({ 12358 type: 'GET', 12359 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 12360 jsonp: 'callback', 12361 dataType: 'jsonp', 12362 success: function(data) { 12363 path = data[0].thumbnail_large; 12364 create(path); 12365 } 12366 }); 12367 } 12368 }; 12369 12370 /** 12371 * Stops the current video. 12372 * @public 12373 */ 12374 Video.prototype.stop = function() { 12375 this._core.trigger('stop', null, 'video'); 12376 this._playing.find('.owl-video-frame').remove(); 12377 this._playing.removeClass('owl-video-playing'); 12378 this._playing = null; 12379 this._core.leave('playing'); 12380 this._core.trigger('stopped', null, 'video'); 12381 }; 12382 12383 /** 12384 * Starts the current video. 12385 * @public 12386 * @param {Event} event - The event arguments. 12387 */ 12388 Video.prototype.play = function(event) { 12389 var target = $(event.target), 12390 item = target.closest('.' + this._core.settings.itemClass), 12391 video = this._videos[item.attr('data-video')], 12392 width = video.width || '100%', 12393 height = video.height || this._core.$stage.height(), 12394 html; 12395 12396 if (this._playing) { 12397 return; 12398 } 12399 12400 this._core.enter('playing'); 12401 this._core.trigger('play', null, 'video'); 12402 12403 item = this._core.items(this._core.relative(item.index())); 12404 12405 this._core.reset(item.index()); 12406 12407 if (video.type === 'youtube') { 12408 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 12409 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 12410 } else if (video.type === 'vimeo') { 12411 html = '<iframe src="//player.vimeo.com/video/' + video.id + 12412 '?autoplay=1" width="' + width + '" height="' + height + 12413 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 12414 } 12415 12416 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 12417 12418 this._playing = item.addClass('owl-video-playing'); 12419 }; 12420 12421 /** 12422 * Checks whether an video is currently in full screen mode or not. 12423 * @todo Bad style because looks like a readonly method but changes members. 12424 * @protected 12425 * @returns {Boolean} 12426 */ 12427 Video.prototype.isInFullScreen = function() { 12428 var element = document.fullscreenElement || document.mozFullScreenElement || 12429 document.webkitFullscreenElement; 12430 12431 return element && $(element).parent().hasClass('owl-video-frame'); 12432 }; 12433 12434 /** 12435 * Destroys the plugin. 12436 */ 12437 Video.prototype.destroy = function() { 12438 var handler, property; 12439 12440 this._core.$element.off('click.owl.video'); 12441 12442 for (handler in this._handlers) { 12443 this._core.$element.off(handler, this._handlers[handler]); 12444 } 12445 for (property in Object.getOwnPropertyNames(this)) { 12446 typeof this[property] != 'function' && (this[property] = null); 12447 } 12448 }; 12449 12450 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 12451 12452})(window.Zepto || window.jQuery, window, document); 12453 12454/** 12455 * Animate Plugin 12456 * @version 2.0.0-beta.3 12457 * @author Bartosz Wojciechowski 12458 * @license The MIT License (MIT) 12459 */ 12460;(function($, window, document, undefined) { 12461 12462 /** 12463 * Creates the animate plugin. 12464 * @class The Navigation Plugin 12465 * @param {Owl} scope - The Owl Carousel 12466 */ 12467 var Animate = function(scope) { 12468 this.core = scope; 12469 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 12470 this.swapping = true; 12471 this.previous = undefined; 12472 this.next = undefined; 12473 12474 this.handlers = { 12475 'change.owl.carousel': $.proxy(function(e) { 12476 if (e.namespace && e.property.name == 'position') { 12477 this.previous = this.core.current(); 12478 this.next = e.property.value; 12479 } 12480 }, this), 12481 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 12482 if (e.namespace) { 12483 this.swapping = e.type == 'translated'; 12484 } 12485 }, this), 12486 'translate.owl.carousel': $.proxy(function(e) { 12487 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 12488 this.swap(); 12489 } 12490 }, this) 12491 }; 12492 12493 this.core.$element.on(this.handlers); 12494 }; 12495 12496 /** 12497 * Default options. 12498 * @public 12499 */ 12500 Animate.Defaults = { 12501 animateOut: false, 12502 animateIn: false 12503 }; 12504 12505 /** 12506 * Toggles the animation classes whenever an translations starts. 12507 * @protected 12508 * @returns {Boolean|undefined} 12509 */ 12510 Animate.prototype.swap = function() { 12511 12512 if (this.core.settings.items !== 1) { 12513 return; 12514 } 12515 12516 if (!$.support.animation || !$.support.transition) { 12517 return; 12518 } 12519 12520 this.core.speed(0); 12521 12522 var left, 12523 clear = $.proxy(this.clear, this), 12524 previous = this.core.$stage.children().eq(this.previous), 12525 next = this.core.$stage.children().eq(this.next), 12526 incoming = this.core.settings.animateIn, 12527 outgoing = this.core.settings.animateOut; 12528 12529 if (this.core.current() === this.previous) { 12530 return; 12531 } 12532 12533 if (outgoing) { 12534 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 12535 previous.css( { 'left': left + 'px' } ) 12536 .addClass('animated owl-animated-out') 12537 .addClass(outgoing) 12538 .on($.support.animation.end, clear); 12539 } 12540 12541 if (incoming) { 12542 next.addClass('animated owl-animated-in') 12543 .addClass(incoming) 12544 .on($.support.animation.end, clear); 12545 } 12546 }; 12547 12548 Animate.prototype.clear = function(e) { 12549 if ($(e.target).hasClass('animated')) { 12550 $(e.target).css( { 'left': '' } ) 12551 .removeClass('animated owl-animated-out owl-animated-in') 12552 .removeClass(this.core.settings.animateIn) 12553 .removeClass(this.core.settings.animateOut); 12554 this.core.onTransitionEnd(); 12555 } 12556 }; 12557 12558 /** 12559 * Destroys the plugin. 12560 * @public 12561 */ 12562 Animate.prototype.destroy = function() { 12563 var handler, property; 12564 12565 for (handler in this.handlers) { 12566 this.core.$element.off(handler, this.handlers[handler]); 12567 } 12568 for (property in Object.getOwnPropertyNames(this)) { 12569 typeof this[property] != 'function' && (this[property] = null); 12570 } 12571 }; 12572 12573 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 12574 12575})(window.Zepto || window.jQuery, window, document); 12576 12577/** 12578 * Autoplay Plugin 12579 * @version 2.0.0-beta.3 12580 * @author Bartosz Wojciechowski 12581 * @author Artus Kolanowski 12582 * @license The MIT License (MIT) 12583 */ 12584;(function($, window, document, undefined) { 12585 12586 /** 12587 * Creates the autoplay plugin. 12588 * @class The Autoplay Plugin 12589 * @param {Owl} scope - The Owl Carousel 12590 */ 12591 var Autoplay = function(carousel) { 12592 /** 12593 * Reference to the core. 12594 * @protected 12595 * @type {Owl} 12596 */ 12597 this._core = carousel; 12598 12599 /** 12600 * The autoplay interval. 12601 * @type {Number} 12602 */ 12603 this._interval = null; 12604 12605 /** 12606 * Indicates whenever the autoplay is paused. 12607 * @type {Boolean} 12608 */ 12609 this._paused = false; 12610 12611 /** 12612 * All event handlers. 12613 * @protected 12614 * @type {Object} 12615 */ 12616 this._handlers = { 12617 'changed.owl.carousel': $.proxy(function(e) { 12618 if (e.namespace && e.property.name === 'settings') { 12619 if (this._core.settings.autoplay) { 12620 this.play(); 12621 } else { 12622 this.stop(); 12623 } 12624 } 12625 }, this), 12626 'initialized.owl.carousel': $.proxy(function(e) { 12627 if (e.namespace && this._core.settings.autoplay) { 12628 this.play(); 12629 } 12630 }, this), 12631 'play.owl.autoplay': $.proxy(function(e, t, s) { 12632 if (e.namespace) { 12633 this.play(t, s); 12634 } 12635 }, this), 12636 'stop.owl.autoplay': $.proxy(function(e) { 12637 if (e.namespace) { 12638 this.stop(); 12639 } 12640 }, this), 12641 'mouseover.owl.autoplay': $.proxy(function() { 12642 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12643 this.pause(); 12644 } 12645 }, this), 12646 'mouseleave.owl.autoplay': $.proxy(function() { 12647 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12648 this.play(); 12649 } 12650 }, this) 12651 }; 12652 12653 // register event handlers 12654 this._core.$element.on(this._handlers); 12655 12656 // set default options 12657 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 12658 }; 12659 12660 /** 12661 * Default options. 12662 * @public 12663 */ 12664 Autoplay.Defaults = { 12665 autoplay: false, 12666 autoplayTimeout: 5000, 12667 autoplayHoverPause: false, 12668 autoplaySpeed: false 12669 }; 12670 12671 /** 12672 * Starts the autoplay. 12673 * @public 12674 * @param {Number} [timeout] - The interval before the next animation starts. 12675 * @param {Number} [speed] - The animation speed for the animations. 12676 */ 12677 Autoplay.prototype.play = function(timeout, speed) { 12678 this._paused = false; 12679 12680 if (this._core.is('rotating')) { 12681 return; 12682 } 12683 12684 this._core.enter('rotating'); 12685 12686 this._interval = window.setInterval($.proxy(function() { 12687 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 12688 return; 12689 } 12690 this._core.next(speed || this._core.settings.autoplaySpeed); 12691 }, this), timeout || this._core.settings.autoplayTimeout); 12692 }; 12693 12694 /** 12695 * Stops the autoplay. 12696 * @public 12697 */ 12698 Autoplay.prototype.stop = function() { 12699 if (!this._core.is('rotating')) { 12700 return; 12701 } 12702 12703 window.clearInterval(this._interval); 12704 this._core.leave('rotating'); 12705 }; 12706 12707 /** 12708 * Stops the autoplay. 12709 * @public 12710 */ 12711 Autoplay.prototype.pause = function() { 12712 if (!this._core.is('rotating')) { 12713 return; 12714 } 12715 12716 this._paused = true; 12717 }; 12718 12719 /** 12720 * Destroys the plugin. 12721 */ 12722 Autoplay.prototype.destroy = function() { 12723 var handler, property; 12724 12725 this.stop(); 12726 12727 for (handler in this._handlers) { 12728 this._core.$element.off(handler, this._handlers[handler]); 12729 } 12730 for (property in Object.getOwnPropertyNames(this)) { 12731 typeof this[property] != 'function' && (this[property] = null); 12732 } 12733 }; 12734 12735 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 12736 12737})(window.Zepto || window.jQuery, window, document); 12738 12739/** 12740 * Navigation Plugin 12741 * @version 2.0.0-beta.3 12742 * @author Artus Kolanowski 12743 * @license The MIT License (MIT) 12744 */ 12745;(function($, window, document, undefined) { 12746 'use strict'; 12747 12748 /** 12749 * Creates the navigation plugin. 12750 * @class The Navigation Plugin 12751 * @param {Owl} carousel - The Owl Carousel. 12752 */ 12753 var Navigation = function(carousel) { 12754 /** 12755 * Reference to the core. 12756 * @protected 12757 * @type {Owl} 12758 */ 12759 this._core = carousel; 12760 12761 /** 12762 * Indicates whether the plugin is initialized or not. 12763 * @protected 12764 * @type {Boolean} 12765 */ 12766 this._initialized = false; 12767 12768 /** 12769 * The current paging indexes. 12770 * @protected 12771 * @type {Array} 12772 */ 12773 this._pages = []; 12774 12775 /** 12776 * All DOM elements of the user interface. 12777 * @protected 12778 * @type {Object} 12779 */ 12780 this._controls = {}; 12781 12782 /** 12783 * Markup for an indicator. 12784 * @protected 12785 * @type {Array.<String>} 12786 */ 12787 this._templates = []; 12788 12789 /** 12790 * The carousel element. 12791 * @type {jQuery} 12792 */ 12793 this.$element = this._core.$element; 12794 12795 /** 12796 * Overridden methods of the carousel. 12797 * @protected 12798 * @type {Object} 12799 */ 12800 this._overrides = { 12801 next: this._core.next, 12802 prev: this._core.prev, 12803 to: this._core.to 12804 }; 12805 12806 /** 12807 * All event handlers. 12808 * @protected 12809 * @type {Object} 12810 */ 12811 this._handlers = { 12812 'prepared.owl.carousel': $.proxy(function(e) { 12813 if (e.namespace && this._core.settings.dotsData) { 12814 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 12815 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 12816 } 12817 }, this), 12818 'added.owl.carousel': $.proxy(function(e) { 12819 if (e.namespace && this._core.settings.dotsData) { 12820 this._templates.splice(e.position, 0, this._templates.pop()); 12821 } 12822 }, this), 12823 'remove.owl.carousel': $.proxy(function(e) { 12824 if (e.namespace && this._core.settings.dotsData) { 12825 this._templates.splice(e.position, 1); 12826 } 12827 }, this), 12828 'changed.owl.carousel': $.proxy(function(e) { 12829 if (e.namespace && e.property.name == 'position') { 12830 this.draw(); 12831 } 12832 }, this), 12833 'initialized.owl.carousel': $.proxy(function(e) { 12834 if (e.namespace && !this._initialized) { 12835 this._core.trigger('initialize', null, 'navigation'); 12836 this.initialize(); 12837 this.update(); 12838 this.draw(); 12839 this._initialized = true; 12840 this._core.trigger('initialized', null, 'navigation'); 12841 } 12842 }, this), 12843 'refreshed.owl.carousel': $.proxy(function(e) { 12844 if (e.namespace && this._initialized) { 12845 this._core.trigger('refresh', null, 'navigation'); 12846 this.update(); 12847 this.draw(); 12848 this._core.trigger('refreshed', null, 'navigation'); 12849 } 12850 }, this) 12851 }; 12852 12853 // set default options 12854 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 12855 12856 // register event handlers 12857 this.$element.on(this._handlers); 12858 }; 12859 12860 /** 12861 * Default options. 12862 * @public 12863 * @todo Rename `slideBy` to `navBy` 12864 */ 12865 Navigation.Defaults = { 12866 nav: false, 12867 navText: [ 'prev', 'next' ], 12868 navSpeed: false, 12869 navElement: 'div', 12870 navContainer: false, 12871 navContainerClass: 'owl-nav', 12872 navClass: [ 'owl-prev', 'owl-next' ], 12873 slideBy: 1, 12874 dotClass: 'owl-dot', 12875 dotsClass: 'owl-dots', 12876 dots: true, 12877 dotsEach: false, 12878 dotsData: false, 12879 dotsSpeed: false, 12880 dotsContainer: false 12881 }; 12882 12883 /** 12884 * Initializes the layout of the plugin and extends the carousel. 12885 * @protected 12886 */ 12887 Navigation.prototype.initialize = function() { 12888 var override, 12889 settings = this._core.settings; 12890 12891 // create DOM structure for relative navigation 12892 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 12893 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 12894 12895 this._controls.$previous = $('<' + settings.navElement + '>') 12896 .addClass(settings.navClass[0]) 12897 .html(settings.navText[0]) 12898 .prependTo(this._controls.$relative) 12899 .on('click', $.proxy(function(e) { 12900 this.prev(settings.navSpeed); 12901 }, this)); 12902 this._controls.$next = $('<' + settings.navElement + '>') 12903 .addClass(settings.navClass[1]) 12904 .html(settings.navText[1]) 12905 .appendTo(this._controls.$relative) 12906 .on('click', $.proxy(function(e) { 12907 this.next(settings.navSpeed); 12908 }, this)); 12909 12910 // create DOM structure for absolute navigation 12911 if (!settings.dotsData) { 12912 this._templates = [ $('<div>') 12913 .addClass(settings.dotClass) 12914 .append($('<span>')) 12915 .prop('outerHTML') ]; 12916 } 12917 12918 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 12919 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 12920 12921 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 12922 var index = $(e.target).parent().is(this._controls.$absolute) 12923 ? $(e.target).index() : $(e.target).parent().index(); 12924 12925 e.preventDefault(); 12926 12927 this.to(index, settings.dotsSpeed); 12928 }, this)); 12929 12930 // override public methods of the carousel 12931 for (override in this._overrides) { 12932 this._core[override] = $.proxy(this[override], this); 12933 } 12934 }; 12935 12936 /** 12937 * Destroys the plugin. 12938 * @protected 12939 */ 12940 Navigation.prototype.destroy = function() { 12941 var handler, control, property, override; 12942 12943 for (handler in this._handlers) { 12944 this.$element.off(handler, this._handlers[handler]); 12945 } 12946 for (control in this._controls) { 12947 this._controls[control].remove(); 12948 } 12949 for (override in this.overides) { 12950 this._core[override] = this._overrides[override]; 12951 } 12952 for (property in Object.getOwnPropertyNames(this)) { 12953 typeof this[property] != 'function' && (this[property] = null); 12954 } 12955 }; 12956 12957 /** 12958 * Updates the internal state. 12959 * @protected 12960 */ 12961 Navigation.prototype.update = function() { 12962 var i, j, k, 12963 lower = this._core.clones().length / 2, 12964 upper = lower + this._core.items().length, 12965 maximum = this._core.maximum(true), 12966 settings = this._core.settings, 12967 size = settings.center || settings.autoWidth || settings.dotsData 12968 ? 1 : settings.dotsEach || settings.items; 12969 12970 if (settings.slideBy !== 'page') { 12971 settings.slideBy = Math.min(settings.slideBy, settings.items); 12972 } 12973 12974 if (settings.dots || settings.slideBy == 'page') { 12975 this._pages = []; 12976 12977 for (i = lower, j = 0, k = 0; i < upper; i++) { 12978 if (j >= size || j === 0) { 12979 this._pages.push({ 12980 start: Math.min(maximum, i - lower), 12981 end: i - lower + size - 1 12982 }); 12983 if (Math.min(maximum, i - lower) === maximum) { 12984 break; 12985 } 12986 j = 0, ++k; 12987 } 12988 j += this._core.mergers(this._core.relative(i)); 12989 } 12990 } 12991 }; 12992 12993 /** 12994 * Draws the user interface. 12995 * @todo The option `dotsData` wont work. 12996 * @protected 12997 */ 12998 Navigation.prototype.draw = function() { 12999 var difference, 13000 settings = this._core.settings, 13001 disabled = this._core.items().length <= settings.items, 13002 index = this._core.relative(this._core.current()), 13003 loop = settings.loop || settings.rewind; 13004 13005 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 13006 13007 if (settings.nav) { 13008 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 13009 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 13010 } 13011 13012 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 13013 13014 if (settings.dots) { 13015 difference = this._pages.length - this._controls.$absolute.children().length; 13016 13017 if (settings.dotsData && difference !== 0) { 13018 this._controls.$absolute.html(this._templates.join('')); 13019 } else if (difference > 0) { 13020 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 13021 } else if (difference < 0) { 13022 this._controls.$absolute.children().slice(difference).remove(); 13023 } 13024 13025 this._controls.$absolute.find('.active').removeClass('active'); 13026 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 13027 } 13028 }; 13029 13030 /** 13031 * Extends event data. 13032 * @protected 13033 * @param {Event} event - The event object which gets thrown. 13034 */ 13035 Navigation.prototype.onTrigger = function(event) { 13036 var settings = this._core.settings; 13037 13038 event.page = { 13039 index: $.inArray(this.current(), this._pages), 13040 count: this._pages.length, 13041 size: settings && (settings.center || settings.autoWidth || settings.dotsData 13042 ? 1 : settings.dotsEach || settings.items) 13043 }; 13044 }; 13045 13046 /** 13047 * Gets the current page position of the carousel. 13048 * @protected 13049 * @returns {Number} 13050 */ 13051 Navigation.prototype.current = function() { 13052 var current = this._core.relative(this._core.current()); 13053 return $.grep(this._pages, $.proxy(function(page, index) { 13054 return page.start <= current && page.end >= current; 13055 }, this)).pop(); 13056 }; 13057 13058 /** 13059 * Gets the current succesor/predecessor position. 13060 * @protected 13061 * @returns {Number} 13062 */ 13063 Navigation.prototype.getPosition = function(successor) { 13064 var position, length, 13065 settings = this._core.settings; 13066 13067 if (settings.slideBy == 'page') { 13068 position = $.inArray(this.current(), this._pages); 13069 length = this._pages.length; 13070 successor ? ++position : --position;
vendor: 5,678 bytes, lines 13071-13295
13071 position = this._pages[((position % length) + length) % length].start; 13072 } else { 13073 position = this._core.relative(this._core.current()); 13074 length = this._core.items().length; 13075 successor ? position += settings.slideBy : position -= settings.slideBy; 13076 } 13077 13078 return position; 13079 }; 13080 13081 /** 13082 * Slides to the next item or page. 13083 * @public 13084 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13085 */ 13086 Navigation.prototype.next = function(speed) { 13087 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 13088 }; 13089 13090 /** 13091 * Slides to the previous item or page. 13092 * @public 13093 * @param {Number} [speed=false] - The time in milliseconds for the transition. 13094 */ 13095 Navigation.prototype.prev = function(speed) { 13096 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 13097 }; 13098 13099 /** 13100 * Slides to the specified item or page. 13101 * @public 13102 * @param {Number} position - The position of the item or page. 13103 * @param {Number} [speed] - The time in milliseconds for the transition. 13104 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 13105 */ 13106 Navigation.prototype.to = function(position, speed, standard) { 13107 var length; 13108 13109 if (!standard) { 13110 length = this._pages.length; 13111 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 13112 } else { 13113 $.proxy(this._overrides.to, this._core)(position, speed); 13114 } 13115 }; 13116 13117 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 13118 13119})(window.Zepto || window.jQuery, window, document); 13120 13121/** 13122 * Hash Plugin 13123 * @version 2.0.0-beta.3 13124 * @author Artus Kolanowski 13125 * @license The MIT License (MIT) 13126 */ 13127;(function($, window, document, undefined) { 13128 'use strict'; 13129 13130 /** 13131 * Creates the hash plugin. 13132 * @class The Hash Plugin 13133 * @param {Owl} carousel - The Owl Carousel 13134 */ 13135 var Hash = function(carousel) { 13136 /** 13137 * Reference to the core. 13138 * @protected 13139 * @type {Owl} 13140 */ 13141 this._core = carousel; 13142 13143 /** 13144 * Hash index for the items. 13145 * @protected 13146 * @type {Object} 13147 */ 13148 this._hashes = {}; 13149 13150 /** 13151 * The carousel element. 13152 * @type {jQuery} 13153 */ 13154 this.$element = this._core.$element; 13155 13156 /** 13157 * All event handlers. 13158 * @protected 13159 * @type {Object} 13160 */ 13161 this._handlers = { 13162 /*'initialized.owl.carousel': $.proxy(function(e) { 13163 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 13164 $(window).trigger('hashchange.owl.navigation'); 13165 } 13166 }, this),*/ 13167 'prepared.owl.carousel': $.proxy(function(e) { 13168 if (e.namespace) { 13169 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 13170 13171 if (!hash) { 13172 return; 13173 } 13174 13175 this._hashes[hash] = e.content; 13176 } 13177 }, this), 13178 'changed.owl.carousel': $.proxy(function(e) { 13179 if (e.namespace && e.property.name === 'position') { 13180 var current = this._core.items(this._core.relative(this._core.current())), 13181 hash = $.map(this._hashes, function(item, hash) { 13182 return item === current ? hash : null; 13183 }).join(); 13184 13185 if (!hash || window.location.hash.slice(1) === hash) { 13186 return; 13187 } 13188 13189 window.location.hash = hash; 13190 } 13191 }, this) 13192 }; 13193 13194 // set default options 13195 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 13196 13197 // register the event handlers 13198 this.$element.on(this._handlers); 13199 13200 // register event listener for hash navigation 13201 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 13202 var hash = window.location.hash.substring(1), 13203 items = this._core.$stage.children(), 13204 position = this._hashes[hash] && items.index(this._hashes[hash]); 13205 13206 if (position === undefined || position === this._core.current()) { 13207 return; 13208 } 13209 13210 this._core.to(this._core.relative(position), false, true); 13211 }, this));*/ 13212 }; 13213 13214 /** 13215 * Default options. 13216 * @public 13217 */ 13218 Hash.Defaults = { 13219 URLhashListener: false 13220 }; 13221 13222 /** 13223 * Destroys the plugin. 13224 * @public 13225 */ 13226 Hash.prototype.destroy = function() { 13227 var handler, property; 13228 13229 $(window).off('hashchange.owl.navigation'); 13230 13231 for (handler in this._handlers) { 13232 this._core.$element.off(handler, this._handlers[handler]); 13233 } 13234 for (property in Object.getOwnPropertyNames(this)) { 13235 typeof this[property] != 'function' && (this[property] = null); 13236 } 13237 }; 13238 13239 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 13240 13241})(window.Zepto || window.jQuery, window, document); 13242 13243/** 13244 * Support Plugin 13245 * 13246 * @version 2.0.0-beta.3 13247 * @author Vivid Planet Software GmbH 13248 * @author Artus Kolanowski 13249 * @license The MIT License (MIT) 13250 */ 13251;(function($, window, document, undefined) { 13252 13253 var style = $('<support>').get(0).style, 13254 prefixes = 'Webkit Moz O ms'.split(' '), 13255 events = { 13256 transition: { 13257 end: { 13258 WebkitTransition: 'webkitTransitionEnd', 13259 MozTransition: 'transitionend', 13260 OTransition: 'oTransitionEnd', 13261 transition: 'transitionend' 13262 } 13263 }, 13264 animation: { 13265 end: { 13266 WebkitAnimation: 'webkitAnimationEnd', 13267 MozAnimation: 'animationend', 13268 OAnimation: 'oAnimationEnd', 13269 animation: 'animationend' 13270 } 13271 } 13272 }, 13273 tests = { 13274 csstransforms: function() { 13275 return !!test('transform'); 13276 }, 13277 csstransforms3d: function() { 13278 return !!test('perspective'); 13279 }, 13280 csstransitions: function() { 13281 return !!test('transition'); 13282 }, 13283 cssanimations: function() { 13284 return !!test('animation'); 13285 } 13286 }; 13287 13288 function test(property, prefixed) { 13289 var result = false, 13290 upper = property.charAt(0).toUpperCase() + property.slice(1); 13291 13292 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 13293 if (style[property] !== undefined) { 13294 result = prefixed ? property : true; 13295 return false;
13296 } 13297 }); 13298 13299 return result; 13300 } 13301 13302 function prefixed(property) { 13303 return test(property, true); 13304 } 13305 13306 if (tests.csstransitions()) { 13307 /* jshint -W053 */ 13308 $.support.transition = new String(prefixed('transition')) 13309 $.support.transition.end = events.transition.end[ $.support.transition ]; 13310 } 13311 13312 if (tests.cssanimations()) { 13313 /* jshint -W053 */ 13314 $.support.animation = new String(prefixed('animation')) 13315 $.support.animation.end = events.animation.end[ $.support.animation ]; 13316 } 13317 13318 if (tests.csstransforms()) { 13319 /* jshint -W053 */ 13320 $.support.transform = new String(prefixed('transform')); 13321 $.support.transform3d = tests.csstransforms3d(); 13322 } 13323 13324})(window.Zepto || window.jQuery, window, document); 13325 13326(function(window, document, undefined) { 13327 13328 /** 13329 * Find the absolute position of an element 13330 */ 13331 var absPos = function(element) { 13332 var offsetLeft, offsetTop; 13333 offsetLeft = offsetTop = 0; 13334 if (element.offsetParent) { 13335 do { 13336 offsetLeft += element.offsetLeft; 13337 offsetTop += element.offsetTop; 13338 } while (element = element.offsetParent); 13339 } 13340 return [offsetLeft, offsetTop]; 13341 }; 13342 13343 /** 13344 * @constructor Progress Circle class 13345 * @param params.canvas Canvas on which the circles will be drawn. 13346 * @param params.minRadius Inner radius of the innermost circle, in px. 13347 * @param params.arcWidth Width of each circle(to be more accurate, ring). 13348 * @param params.gapWidth Space between each circle. 13349 * @param params.centerX X coordinate of the center of circles. 13350 * @param params.centerY Y coordinate of the center of circles. 13351 * @param params.infoLineBaseAngle Base angle of the info line. 13352 * @param params.infoLineAngleInterval Angles between the info lines. 13353 */ 13354 var ProgressCircle = function(params) { 13355 this.canvas = params.canvas; 13356 this.minRadius = params.minRadius || 15; 13357 this.arcWidth = params.arcWidth || 5; 13358 this.gapWidth = params.gapWidth || 3; 13359 this.centerX = params.centerX || this.canvas.width / 2; 13360 this.centerY = params.centerY || this.canvas.height / 2;
13361 this.infoLineLength = params.infoLineLength || 60; 13362 this.horizLineLength = params.horizLineLength || 10; 13363 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 13364 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 13365 13366 this.context = this.canvas.getContext('2d'); 13367 13368 this.width = this.canvas.width; 13369 this.height = this.canvas.height; 13370 13371 this.circles = []; 13372 this.runningCount = 0; 13373 }; 13374 13375 ProgressCircle.prototype = { 13376 constructor: ProgressCircle, 13377 13378 /** 13379 * @method Adds an progress monitor entry. 13380 * @param params.fillColor Color to fill in the circle. 13381 * @param params.outlineColor Color to outline the circle. 13382 * @param params.progressListener Callback function to fetch the progress. 13383 * @param params.infoListener Callback function to fetch the info. 13384 * @returns this 13385 */ 13386 addEntry: function(params) { 13387 this.circles.push(new Circle({ 13388 canvas: this.canvas, 13389 context: this.context, 13390 centerX: this.centerX, 13391 centerY: this.centerY, 13392 innerRadius: this.minRadius + this.circles.length * 13393 (this.gapWidth + this.arcWidth), 13394 arcWidth: this.arcWidth,
13395 infoLineLength: this.infoLineLength, 13396 horizLineLength: this.horizLineLength, 13397 13398 id: this.circles.length, 13399 fillColor: params.fillColor, 13400 outlineColor: params.outlineColor, 13401 progressListener: params.progressListener, 13402 infoListener: params.infoListener, 13403 infoLineAngle: this.infoLineBaseAngle + 13404 this.circles.length * this.infoLineAngleInterval, 13405 })); 13406 13407 return this; 13408 }, 13409 13410 /** 13411 * @method Starts the monitor and updates with the given interval. 13412 * @param interval Interval between updates, in millisecond. 13413 * @returns this 13414 */ 13415 start: function(interval) { 13416 var self = this; 13417 this.timer = setInterval(function() { 13418 self._update(); 13419 }, interval || 33); 13420 13421 return this; 13422 }, 13423 13424 /** 13425 * @method Stop the animation. 13426 */ 13427 stop: function() { 13428 clearTimeout(this.timer); 13429 }, 13430 13431 /** 13432 * @private 13433 * @method Call update on each circle and redraw them. 13434 * @returns this 13435 */ 13436 _update: function() { 13437 this._clear(); 13438 this.circles.forEach(function(circle, idx, array) { 13439 circle.update(); 13440 }); 13441 13442 return this; 13443 }, 13444 13445 /** 13446 * @private 13447 * @method Clear the canvas. 13448 * @returns this 13449 */ 13450 _clear: function() { 13451 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 13452 13453 return this; 13454 }, 13455 13456 }; 13457 13458 /** 13459 * @private 13460 * @class Individual progress circle. 13461 * @param params.canvas Canvas on which the circle will be drawn. 13462 * @param params.context Context of the canvas. 13463 * @param params.innerRadius Inner radius of the circle, in px. 13464 * @param params.arcWidth Width of each arc(circle). 13465 * @param params.gapWidth Distance between each arc. 13466 * @param params.centerX X coordinate of the center of circles. 13467 * @param params.centerY Y coordinate of the center of circles. 13468 * @param params.fillColor Color to fill in the circle. 13469 * @param params.outlineColor Color to outline the circle. 13470 * @param params.progressListener Callback function to fetch the progress. 13471 * @param params.infoListener Callback function to fetch the info. 13472 * @param params.infoLineAngle Angle of info line. 13473 */ 13474 var Circle = function(params) { 13475 this.id = params.id; 13476 this.canvas = params.canvas; 13477 this.context = params.context; 13478 this.centerX = params.centerX; 13479 this.centerY = params.centerY; 13480 this.arcWidth = params.arcWidth; 13481 this.innerRadius = params.innerRadius || 0; 13482 this.fillColor = params.fillColor || '#fff'; 13483 this.outlineColor = params.outlineColor || this.fillColor; 13484 this.progressListener = params.progressListener;
13485 this.infoLineLength = params.infoLineLength || 250; 13486 this.horizLineLength = params.horizLineLength || 50; 13487 this.infoListener = params.infoListener; 13488 this.infoLineAngle = params.infoLineAngle; 13489 13490 this.outerRadius = this.innerRadius + this.arcWidth; 13491 13492 // If the info listener is not registered, then don't calculate 13493 // the related coordinates 13494 if (!this.infoListener) return; 13495 13496 // calculate the info-line turning points 13497 var angle = this.infoLineAngle, 13498 arcDistance = (this.innerRadius + this.outerRadius) / 2, 13499 13500 sinA = Math.sin(angle), 13501 cosA = Math.cos(angle); 13502 13503 this.infoLineStartX = this.centerX + sinA * arcDistance; 13504 this.infoLineStartY = this.centerY - cosA * arcDistance; 13505 13506 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 13507 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 13508 13509 this.infoLineEndX = this.infoLineMidX + 13510 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 13511 this.infoLineEndY = this.infoLineMidY; 13512 13513 var infoText = document.createElement('div'), 13514 style = infoText.style; 13515 13516 style.color = this.fillColor; 13517 style.position = 'absolute'; 13518 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 13519 // style.top will be calculated in the `drawInfo` method. Since 13520 // user may want to change the size of the font, so the top offset 13521 // must be updated in each loop. 13522 infoText.className = 'ProgressCircleInfo'; // For css styling 13523 infoText.id = 'progress_circle_info_' + this.id; 13524 document.body.appendChild(infoText); 13525 this.infoText = infoText; 13526 }; 13527 13528 Circle.prototype = { 13529 constructor: Circle, 13530 13531 update: function() { 13532 this.progress = this.progressListener(); 13533 this._draw(); 13534 13535 if (this.infoListener) { 13536 this.info = this.infoListener(); 13537 this._drawInfo(); 13538 } 13539 }, 13540 13541 /** 13542 * @private 13543 * @method Draw the circle on the canvas. 13544 * @returns this 13545 */ 13546 _draw: function() { 13547 var ctx = this.context, 13548 13549 ANGLE_OFFSET = -Math.PI / 2, 13550 13551 startAngle = 0 + ANGLE_OFFSET, 13552 endAngle= startAngle + this.progress * Math.PI * 2, 13553 13554 x = this.centerX, 13555 y = this.centerY, 13556 13557 innerRadius = this.innerRadius - this.arcWidth - 1, 13558 outerRadius = this.outerRadius - this.arcWidth - 1; 13559 13560 ctx.fillStyle = this.fillColor; 13561 ctx.strokeStyle = this.outlineColor; 13562 13563 ctx.beginPath(); 13564 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 13565 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 13566 ctx.closePath(); 13567 ctx.stroke(); 13568 ctx.fill(); 13569 13570 return this; 13571 }, 13572 13573 /** 13574 * @private 13575 * @method Draw the info lines and info text. 13576 * @returns this 13577 */ 13578 _drawInfo: function() { 13579 13580 var pointList, lineHeight; 13581 13582 pointList = [ 13583 [this.infoLineStartX, this.infoLineStartY], 13584 [this.infoLineMidX, this.infoLineMidY], 13585 [this.infoLineEndX, this.infoLineEndY], 13586 ]; 13587 this._drawSegments(pointList, false); 13588 13589 this.infoText.innerHTML = this.info; 13590 13591 lineHeight = this.infoText.offsetHeight; 13592 this.infoText.style.top = this.infoLineEndY + 13593 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 13594 13595 return this; 13596 }, 13597 13598 /** 13599 * @private 13600 * @method Helper function to draw the segments 13601 * @param pointList An array of points in the form of [x, y]. 13602 * @param close Whether to connect the first and last point. 13603 */ 13604 _drawSegments: function(pointList, close) { 13605 var ctx = this.context; 13606 13607 ctx.beginPath(); 13608 ctx.moveTo(pointList[0][0], pointList[0][1]); 13609 for (var i = 1; i < pointList.length; ++i) { 13610 ctx.lineTo(pointList[i][0], pointList[i][1]); 13611 } 13612 13613 if (close) { 13614 ctx.closePath(); 13615 } 13616 ctx.stroke(); 13617 }, 13618 }; 13619 13620 window.ProgressCircle = ProgressCircle; 13621 13622})(window, document); 13623 13624 13625 13626 13627/* ========================================================= 13628 * jquery.vc_chart.js v1.0 13629 * ========================================================= 13630 * Copyright 2013 Wpbakery 13631 * 13632 * Jquery chart plugin for the Visual Composer.
13633 * ========================================================= */ 13634(function($){ 13635 /** 13636 * Pie chart animated. 13637 * @param element - DOM element 13638 * @param options - settings object. 13639 * @constructor 13640 */ 13641 var VcChart = function(element, options) { 13642 this.el = element; 13643 this.$el = $(this.el); 13644 this.options = $.extend({ 13645 color: 'wpb_button', 13646 units: '', 13647 width: '', 13648 label_selector: '.vc_pie_chart_value', 13649 back_selector: '.vc_pie_chart_back', 13650 responsive: true 13651 }, options); 13652 this.init(); 13653 }; 13654 VcChart.prototype = { 13655 constructor: VcChart, 13656 _progress_v: 0, 13657 animated: false, 13658 colors: { 13659 'wpb_button': 'rgba(247, 247, 247, 1)', 13660 'btn-primary': 'rgba(0, 136, 204, 1)', 13661 'btn-info': 'rgba(88, 185, 218, 1)', 13662 'btn-success': 'rgba(106, 177, 101, 1)', 13663 'btn-warning': 'rgba(255, 153, 0, 1)', 13664 'btn-danger': 'rgba(255, 103, 91, 1)', 13665 'btn-inverse': 'rgba(85, 85, 85, 1)' 13666 }, 13667 init: function() { 13668 this.setupColor(); 13669 this.value = this.$el.data('pie-value')/100; 13670 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 13671 this.$wrapper = $('.vc_pie_wrapper', this.$el); 13672 this.$label = $(this.options.label_selector, this.$el); 13673 this.$back = $(this.options.back_selector, this.$el); 13674 this.$canvas = this.$el.find('canvas'); 13675 this.arcWidth = this.$el.data('pie-width') * 2; 13676 this.draw(); 13677 this.setWayPoint(); 13678 if(this.options.responsive === true) this.setResponsive(); 13679 if (UNCODE.isMobile) this._progress_v = this.value; 13680 }, 13681 setupColor: function() { 13682 // if(typeof this.colors[this.options.color] !== 'undefined') { 13683 // this.color = this.colors[this.options.color]; 13684 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 13685 // this.color = this.options.color; 13686 // } else { 13687 // this.color = 'rgba(247, 247, 247, 0.2)'; 13688 // } 13689 if(typeof this.options.color !== 'undefined') { 13690 this.color = this.options.color; 13691 } else this.color = 'rgba(247, 247, 247, 0.2)'; 13692 13693 }, 13694 setResponsive: function() { 13695 var that = this; 13696 if (!UNCODE.isMobile) { 13697 $(window).resize(function(){ 13698 if(that.animated === true) that.circle.stop(); 13699 that.draw(true); 13700 }); 13701 } 13702 }, 13703 draw: function(redraw) { 13704 var w = this.$el.addClass('vc_ready').width() * 2, 13705 border_w = this.arcWidth, 13706 radius; 13707 if(!w) w = this.$el.parents(':visible').first().width()-2; 13708 //w = Math.round(w/100*80); 13709 //if (w < 250) w = 250; 13710 radius = w/2; 13711 this.$wrapper.css({"width" : (w / 2) + "px"}); 13712 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 13713 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 13714 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 13715 this.$el.addClass('vc_ready'); 13716 this.circle = new ProgressCircle({ 13717 canvas: this.$canvas.get(0), 13718 minRadius: radius, 13719 arcWidth: border_w 13720 }); 13721 if(redraw === true && this.animated === true) { 13722 this._progress_v = this.value; 13723 this.circle.addEntry({ 13724 fillColor: this.color, 13725 progressListener: $.proxy(this.setProgress, this) 13726 }).start(); 13727 } 13728 }, 13729 setProgress: function() { 13730 if (this._progress_v >= this.value) { 13731 this.circle.stop(); 13732 this.$label.html(this.label_value + this.options.units); 13733 return this._progress_v; 13734 } 13735 this._progress_v += 0.01; 13736 if (!isNaN(this.label_value)) { 13737 var label_value = this._progress_v/this.value*this.label_value; 13738 var val = Math.round(label_value) + this.options.units; 13739 this.$label.html(val); 13740 } else this.$label.html(this.label_value + this.options.units); 13741 return this._progress_v; 13742 }, 13743 animate: function() { 13744 if(this.animated !== true) { 13745 this.animated = true; 13746 this.circle.addEntry({ 13747 fillColor: this.color, 13748 progressListener: $.proxy(this.setProgress, this) 13749 }).start(5); 13750 } 13751 }, 13752 setWayPoint: function() { 13753 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 13754 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 13755 } else { 13756 this.animate(); 13757 } 13758 } 13759 }; 13760 /** 13761 * jQuery plugin 13762 * @param option - object with settings 13763 * @return {*} 13764 */ 13765 $.fn.vcChat = function(option, value) { 13766 return this.each(function () { 13767 var $this = $(this), 13768 data = $this.data('vc_chart'), 13769 options = typeof option === 'object' ? option : { 13770 color: $this.data('pie-color'), 13771 units: $this.data('pie-units') 13772 }; 13773 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 13774 if (typeof option == 'string') data[option](value); 13775 }); 13776 }; 13777 /** 13778 * Allows users to rewrite function inside theme. 13779 */ 13780 if ( typeof window['vc_pieChart'] !== 'function' ) { 13781 window.vc_pieChart = function() { 13782 $('.vc_pie_chart:visible').vcChat(); 13783 } 13784 } 13785 $(document).ready(function(){ 13786 !window.vc_iframe && vc_pieChart(); 13787 }); 13788 13789})(window.jQuery); 13790 13791 13792/* Progress bar 13793 ---------------------------------------------------------- */ 13794function uncode_progress_bar() {    13795 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 13796 if (!UNCODE.isMobile) { 13797 new Waypoint({ 13798 element: val, 13799 handler: function() { 13800 var element = jQuery(this.element); 13801 element.find('.vc_single_bar').each(function(index) {          13802 var $this = jQuery(this), 13803 bar = $this.find('.vc_bar'), 13804 val = bar.data('percentage-value');          13805 setTimeout(function() {            13806 bar.css({ 13807 "width": val + '%' 13808 });          13809 }, index * 200);        13810 }); 13811 }, 13812 offset: '80%' 13813 }); 13814 } else { 13815 var element = jQuery(val); 13816 element.find('.vc_single_bar').each(function(index) {          13817 var $this = jQuery(this), 13818 bar = $this.find('.vc_bar'), 13819 val = bar.data('percentage-value');          13820 setTimeout(function() {            13821 bar.css({ 13822 "width": val + '%' 13823 });          13824 }, index * 200);        13825 }); 13826 } 13827 }); 13828}; 13829uncode_progress_bar(); 13830 13831/*! 13832 * jquery.counterup.js 1.0 13833 * 13834 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 13835 * Released under the GPL v2 License 13836 * 13837 * Date: Nov 26, 2013 13838 */ 13839(function($) { 13840 "use strict"; 13841 $.fn.counterUp = function(options) { 13842 // Defaults 13843 var settings = $.extend({ 13844 'time': 400, 13845 'delay': 10 13846 }, options); 13847 return this.each(function() { 13848 // Store the object 13849 var $this = $(this); 13850 var $settings = settings; 13851 var counterUpper = function() { 13852 var nums = []; 13853 var divisions = $settings.time / $settings.delay; 13854 var numReal = $this.text(), 13855 num = numReal; 13856 var isComma = /[0-9]+,[0-9]+/.test(num); 13857 num = num.replace(/,/g, ''); 13858 var isInt = /^[0-9]+$/.test(num); 13859 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 13860 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 13861 // Generate list of incremental numbers to display 13862 for (var i = divisions; i >= 1; i--) { 13863 // Preserve as int if input was int 13864 var newNum = parseInt(num / divisions * i); 13865 // Preserve float if input was float 13866 if (isFloat) { 13867 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 13868 } 13869 // Preserve commas if input had commas 13870 if (isComma) { 13871 while (/(\d+)(\d{3})/.test(newNum.toString())) { 13872 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 13873 } 13874 } 13875 nums.unshift(newNum); 13876 } 13877 nums.push(numReal); 13878 $this.data('counterup-nums', nums); 13879 $this.text('0'); 13880 // Updates the number until we're done 13881 var f = function() { 13882 if ($this.data('counterup-nums') != null) { 13883 $this.text($this.data('counterup-nums').shift()); 13884 if ($this.data('counterup-nums').length) { 13885 setTimeout($this.data('counterup-func'), $settings.delay); 13886 } else { 13887 delete $this.data('counterup-nums'); 13888 $this.data('counterup-nums', null); 13889 $this.data('counterup-func', null); 13890 } 13891 } 13892 }; 13893 $this.data('counterup-func', f); 13894 // Start the count up 13895 setTimeout($this.data('counterup-func'), $settings.delay); 13896 }; 13897 // Perform counts when the element gets into view 13898 new Waypoint({ 13899 element: this, 13900 handler: function() { 13901 counterUpper(); 13902 this.destroy(); 13903 }, 13904 offset: '80%' 13905 }); 13906 }); 13907 }; 13908})(jQuery); 13909 13910/*! 13911 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 13912 * Copyright (c) 2014 Edson Hilios 13913 * 13914 * Permission is hereby granted, free of charge, to any person obtaining a copy of 13915 * this software and associated documentation files (the "Software"), to deal in 13916 * the Software without restriction, including without limitation the rights to 13917 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13918 * the Software, and to permit persons to whom the Software is furnished to do so, 13919 * subject to the following conditions: 13920 * 13921 * The above copyright notice and this permission notice shall be included in all 13922 * copies or substantial portions of the Software. 13923 * 13924 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13925 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13926 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13927 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13928 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 13929 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13930 */ 13931!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;
13931if(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])})}}); 13932 13933/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 13934* https://github.com/alexanderdickson/waitForImages 13935* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 13936;(function (factory) { 13937 if (typeof define === 'function' && define.amd) { 13938 // AMD. Register as an anonymous module. 13939 define(['jquery'], factory); 13940 } else if (typeof exports === 'object') { 13941 // CommonJS / nodejs module 13942 module.exports = factory(require('jquery')); 13943 } else { 13944 // Browser globals 13945 factory(jQuery); 13946 } 13947}(function ($) { 13948 // Namespace all events. 13949 var eventNamespace = 'waitForImages'; 13950 13951 // CSS properties which contain references to images. 13952 $.waitForImages = { 13953 hasImageProperties: [ 13954 'backgroundImage', 13955 'listStyleImage', 13956 'borderImage', 13957 'borderCornerImage', 13958 'cursor' 13959 ], 13960 hasImageAttributes: ['srcset'] 13961 }; 13962 13963 // Custom selector to find `img` elements that have a valid `src` 13964 // attribute and have not already loaded. 13965 $.expr[':'].uncached = function (obj) { 13966 // Ensure we are dealing with an `img` element with a valid 13967 // `src` attribute. 13968 if (!$(obj).is('img[src][src!=""]')) { 13969 return false;
13970 } 13971 13972 return !obj.complete; 13973 }; 13974 13975 $.fn.waitForImages = function () { 13976 13977 var allImgsLength = 0; 13978 var allImgsLoaded = 0; 13979 var deferred = $.Deferred(); 13980 13981 var finishedCallback; 13982 var eachCallback; 13983 var waitForAll; 13984 13985 // Handle options object (if passed). 13986 if ($.isPlainObject(arguments[0])) { 13987 13988 waitForAll = arguments[0].waitForAll; 13989 eachCallback = arguments[0].each; 13990 finishedCallback = arguments[0].finished; 13991 13992 } else { 13993 13994 // Handle if using deferred object and only one param was passed in. 13995 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 13996 waitForAll = arguments[0]; 13997 } else { 13998 finishedCallback = arguments[0]; 13999 eachCallback = arguments[1]; 14000 waitForAll = arguments[2]; 14001 } 14002 14003 } 14004 14005 // Handle missing callbacks. 14006 finishedCallback = finishedCallback || $.noop; 14007 eachCallback = eachCallback || $.noop; 14008 14009 // Convert waitForAll to Boolean 14010 waitForAll = !! waitForAll; 14011 14012 // Ensure callbacks are functions. 14013 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 14014 throw new TypeError('An invalid callback was supplied.'); 14015 } 14016 14017 this.each(function () { 14018 // Build a list of all imgs, dependent on what images will 14019 // be considered. 14020 var obj = $(this); 14021 var allImgs = []; 14022 // CSS properties which may contain an image. 14023 var hasImgProperties = $.waitForImages.hasImageProperties || []; 14024 // Element attributes which may contain an image. 14025 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 14026 // To match `url()` references. 14027 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 14028 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 14029 14030 if (waitForAll) { 14031 14032 // Get all elements (including the original), as any one of 14033 // them could have a background image. 14034 obj.find('*').addBack().each(function () { 14035 var element = $(this); 14036 14037 // If an `img` element, add it. But keep iterating in 14038 // case it has a background image too. 14039 if (element.is('img:uncached')) { 14040 allImgs.push({ 14041 src: element.attr('src'), 14042 element: element[0] 14043 }); 14044 } 14045 14046 $.each(hasImgProperties, function (i, property) { 14047 var propertyValue = element.css(property); 14048 var match; 14049 14050 // If it doesn't contain this property, skip. 14051 if (!propertyValue) { 14052 return true; 14053 } 14054 14055 // Get all url() of this element. 14056 while (match = matchUrl.exec(propertyValue)) { 14057 allImgs.push({ 14058 src: match[2], 14059 element: element[0] 14060 }); 14061 } 14062 }); 14063 14064 $.each(hasImageAttributes, function (i, attribute) { 14065 var attributeValue = element.attr(attribute); 14066 var attributeValues; 14067 14068 // If it doesn't contain this property, skip. 14069 if (!attributeValue) { 14070 return true; 14071 } 14072 14073 // Check for multiple comma separated images 14074 attributeValues = attributeValue.split(','); 14075 14076 $.each(attributeValues, function(i, value) { 14077 // Trim value and get string before first 14078 // whitespace (for use with srcset). 14079 value = $.trim(value).split(' ')[0]; 14080 allImgs.push({ 14081 src: value, 14082 element: element[0] 14083 }); 14084 }); 14085 }); 14086 }); 14087 } else { 14088 // For images only, the task is simpler. 14089 obj.find('img:uncached') 14090 .each(function () { 14091 allImgs.push({ 14092 src: this.src, 14093 element: this 14094 }); 14095 }); 14096 } 14097 14098 allImgsLength = allImgs.length; 14099 allImgsLoaded = 0; 14100 14101 // If no images found, don't bother. 14102 if (allImgsLength === 0) { 14103 finishedCallback.call(obj[0]); 14104 deferred.resolveWith(obj[0]); 14105 } 14106 14107 $.each(allImgs, function (i, img) { 14108 14109 var image = new Image(); 14110 var events = 14111 'load.' + eventNamespace + ' error.' + eventNamespace; 14112 14113 // Handle the image loading and error with the same callback. 14114 $(image).one(events, function me (event) { 14115 // If an error occurred with loading the image, set the 14116 // third argument accordingly. 14117 var eachArguments = [ 14118 allImgsLoaded, 14119 allImgsLength,
14120 event.type == 'load' 14121 ]; 14122 allImgsLoaded++; 14123 14124 eachCallback.apply(img.element, eachArguments); 14125 deferred.notifyWith(img.element, eachArguments); 14126 14127 // Unbind the event listeners. I use this in addition to 14128 // `one` as one of those events won't be called (either 14129 // 'load' or 'error' will be called). 14130 $(this).off(events, me); 14131 14132 if (allImgsLoaded == allImgsLength) { 14133 finishedCallback.call(obj[0]); 14134 deferred.resolveWith(obj[0]); 14135 return false; 14136 } 14137 14138 }); 14139 14140 image.src = img.src; 14141 }); 14142 }); 14143 14144 return deferred.promise(); 14145 14146 }; 14147})); 14148 14149/** 14150 * @preserve textfill 14151 * @name jquery.textfill.js 14152 * @author Russ Painter 14153 * @author Yu-Jie Lin 14154 * @author Alexandre Dantas 14155 * @version 0.6.0 14156 * @date 2014-08-19 14157 * @copyright (c) 2014 Alexandre Dantas 14158 * @copyright (c) 2012-2013 Yu-Jie Lin 14159 * @copyright (c) 2009 Russ Painter 14160 * @license MIT License 14161 * @homepage https://github.com/jquery-textfill/jquery-textfill 14162 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 14163 */ 14164; (function($) { 14165 14166 /** 14167 * Resizes an inner element's font so that the 14168 * inner element completely fills the outer element. 14169 * 14170 * @param {Object} options User options that take 14171 * higher precedence when 14172 * merging with the default ones. 14173 * 14174 * @return All outer elements processed 14175 */ 14176 $.fn.textfill = function(options) { 14177 14178 // ______ _______ _______ _______ _ _ _______ _______ 14179 // | \ |______ |______ |_____| | | | | |______ 14180 // |_____/ |______ | | | |_____| |_____ | ______| 14181 // 14182 // Merging user options with the default values 14183 14184 var defaults = { 14185 debug : false, 14186 maxFontPixels : 40, 14187 minFontPixels : 4, 14188 innerTag : 'span', 14189 widthOnly : false, 14190 success : null, // callback when a resizing is done 14191 callback : null, // callback when a resizing is done (deprecated, use success) 14192 fail : null, // callback when a resizing is failed 14193 complete : null, // callback when all is done 14194 explicitWidth : null, 14195 explicitHeight : null, 14196 changeLineHeight : false 14197 }; 14198 14199 var Opts = $.extend(defaults, options); 14200 14201 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 14202 // |______ | | | \ | | | | | | | \ | |______ 14203 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 14204 // 14205 // Predefining the awesomeness 14206 14207 // Output arguments to the Debug console 14208 // if "Debug Mode" is enabled 14209 function _debug() { 14210 if (!Opts.debug 14211 || typeof console == 'undefined' 14212 || typeof console.debug == 'undefined') { 14213 return; 14214 } 14215 console.debug.apply(console, arguments); 14216 } 14217 14218 // Output arguments to the Warning console 14219 function _warn() { 14220 if (typeof console == 'undefined' || 14221 typeof console.warn == 'undefined') { 14222 return; 14223 } 14224 console.warn.apply(console, arguments); 14225 } 14226 14227 // Outputs all information on the current sizing 14228 // of the font. 14229 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14230 14231 function _m(v1, v2) { 14232 14233 var marker = ' / '; 14234 14235 if (v1 > v2) 14236 marker = ' > '; 14237 14238 else if (v1 == v2) 14239 marker = ' = '; 14240 14241 return marker; 14242 } 14243 14244 _debug( 14245 '[TextFill] ' + prefix + ' { ' + 14246 'font-size: ' + ourText.css('font-size') + ',' +
14247 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 14248 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 14249 'minFontPixels: ' + minFontPixels + 'px, ' + 14250 'maxFontPixels: ' + maxFontPixels + 'px }' 14251 ); 14252 } 14253 14254 /** 14255 * Calculates which size the font can get resized, 14256 * according to constrains. 14257 * 14258 * @param {String} prefix Gets shown on the console before 14259 * all the arguments, if debug mode is on. 14260 * @param {Object} ourText The DOM element to resize, 14261 * that contains the text. 14262 * @param {function} func Function called on `ourText` that's 14263 * used to compare with `max`. 14264 * @param {number} max Maximum value, that gets compared with 14265 * `func` called on `ourText`. 14266 * @param {number} minFontPixels Minimum value the font can 14267 * get resized to (in pixels). 14268 * @param {number} maxFontPixels Maximum value the font can 14269 * get resized to (in pixels). 14270 * 14271 * @return Size (in pixels) that the font can be resized. 14272 */ 14273 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14274 14275 _debug_sizing( 14276 prefix, ourText, 14277 maxHeight, maxWidth, 14278 minFontPixels, maxFontPixels 14279 ); 14280 14281 // The kernel of the whole plugin, take most attention 14282 // on this part. 14283 // 14284 // This is a loop that keeps increasing the `font-size` 14285 // until it fits the parent element. 14286 // 14287 // - Start from the minimal allowed value (`minFontPixels`) 14288 // - Guesses an average font size (in pixels) for the font, 14289 // - Resizes the text and sees if its size is within the 14290 // boundaries (`minFontPixels` and `maxFontPixels`). 14291 // - If so, keep guessing until we break. 14292 // - If not, return the last calculated size. 14293 // 14294 // I understand this is not optimized and we should 14295 // consider implementing something akin to 14296 // Daniel Hoffmann's answer here: 14297 // 14298 // http://stackoverflow.com/a/17433451/1094964 14299 // 14300 14301 while (minFontPixels < (maxFontPixels - 1)) { 14302 14303 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 14304 ourText.css('font-size', fontSize); 14305 14306 if (func.call(ourText) <= max) { 14307 minFontPixels = fontSize; 14308 14309 if (func.call(ourText) == max) 14310 break; 14311 } 14312 else 14313 maxFontPixels = fontSize; 14314 14315 _debug_sizing( 14316 prefix, ourText, 14317 maxHeight, maxWidth, 14318 minFontPixels, maxFontPixels 14319 ); 14320 } 14321 14322 ourText.css('font-size', maxFontPixels); 14323 14324 if (func.call(ourText) <= max) { 14325 minFontPixels = maxFontPixels; 14326 14327 _debug_sizing( 14328 prefix + '* ', ourText, 14329 maxHeight, maxWidth, 14330 minFontPixels, maxFontPixels 14331 ); 14332 } 14333 return minFontPixels; 14334 } 14335 14336 // _______ _______ _______ ______ _______ 14337 // |______ | |_____| |_____/ | 14338 // ______| | | | | \_ | 14339 // 14340 // Let's get it started (yeah)! 14341 14342 _debug('[TextFill] Start Debug'); 14343 14344 this.each(function() { 14345 14346 // Contains the child element we will resize. 14347 // $(this) means the parent container 14348 var ourText = $(Opts.innerTag + ':visible:first', this); 14349 14350 // Will resize to this dimensions. 14351 // Use explicit dimensions when specified 14352 var maxHeight = Opts.explicitHeight || $(this).height(); 14353 var maxWidth = Opts.explicitWidth || $(this).width(); 14354 14355 var oldFontSize = ourText.css('font-size'); 14356 14357 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 14358 14359 _debug('[TextFill] Inner text: ' + ourText.text()); 14360 _debug('[TextFill] All options: ', Opts); 14361 _debug('[TextFill] Maximum sizes: { ' + 14362 'Height: ' + maxHeight + 'px, ' + 14363 'Width: ' + maxWidth + 'px' + ' }' 14364 ); 14365 14366 var minFontPixels = Opts.minFontPixels; 14367 14368 // Remember, if this `maxFontPixels` is negative, 14369 // the text will resize to as long as the container 14370 // can accomodate 14371 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 14372 maxHeight : 14373 Opts.maxFontPixels); 14374 14375 14376 // Let's start it all! 14377 14378 // 1. Calculate which `font-size` would 14379 // be best for the Height 14380 var fontSizeHeight = undefined; 14381 14382 if (! Opts.widthOnly) 14383 fontSizeHeight = _sizing( 14384 'Height', ourText, 14385 $.fn.height, maxHeight, 14386 maxHeight, maxWidth, 14387 minFontPixels, maxFontPixels 14388 ); 14389 14390 // 2. Calculate which `font-size` would 14391 // be best for the Width 14392 var fontSizeWidth = undefined; 14393 14394 fontSizeWidth = _sizing( 14395 'Width', ourText, 14396 $.fn.width, maxWidth, 14397 maxHeight, maxWidth, 14398 minFontPixels, maxFontPixels 14399 ); 14400 14401 // 3. Actually resize the text! 14402 14403 if (Opts.widthOnly) { 14404 ourText.css({ 14405 'font-size' : fontSizeWidth, 14406 'white-space': 'nowrap' 14407 }); 14408 14409 if (Opts.changeLineHeight) 14410 ourText.parent().css( 14411 'line-height', 14412 (lineHeight * fontSizeWidth + 'px') 14413 ); 14414 } 14415 else { 14416 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 14417 14418 ourText.css('font-size', fontSizeFinal); 14419 14420 if (Opts.changeLineHeight) 14421 ourText.parent().css( 14422 'line-height', 14423 (lineHeight * fontSizeFinal) + 'px' 14424 ); 14425 } 14426 14427 _debug( 14428 '[TextFill] Finished { ' + 14429 'Old font-size: ' + oldFontSize + ', ' + 14430 'New font-size: ' + ourText.css('font-size') + ' }' 14431 ); 14432 14433 // Oops, something wrong happened! 14434 // We weren't supposed to exceed the original size 14435 if ((ourText.width() > maxWidth) ||
14436 (ourText.height() > maxHeight && !Opts.widthOnly)) { 14437 14438 ourText.css('font-size', oldFontSize); 14439 14440 // Failure callback 14441 if (Opts.fail) 14442 Opts.fail(this); 14443 14444 _debug( 14445 '[TextFill] Failure { ' + 14446 'Current Width: ' + ourText.width() + ', ' + 14447 'Maximum Width: ' + maxWidth + ', ' + 14448 'Current Height: ' + ourText.height() + ', ' + 14449 'Maximum Height: ' + maxHeight + ' }' 14450 ); 14451 } 14452 else if (Opts.success) { 14453 Opts.success(this); 14454 } 14455 else if (Opts.callback) { 14456 _warn('callback is deprecated, use success, instead'); 14457 14458 // Success callback 14459 Opts.callback(this); 14460 } 14461 }); 14462 14463 // Complete callback 14464 if (Opts.complete) 14465 Opts.complete(this); 14466 14467 _debug('[TextFill] End Debug'); 14468 return this; 14469 }; 14470 14471})(window.jQuery); 14472 14473 14474!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; 14475function getStyles(config){ 14476 // 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;
14476left: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+"}" 14477}; 14478 var ShareUtils; 14479 14480if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 14481 Object.defineProperty(HTMLElement.prototype, "classList", { 14482 get: function() { 14483 var ret, self, update; 14484 update = function(fn) { 14485 return function(value) { 14486 var classes, index; 14487 classes = self.className.split(/\s+/); 14488 index = classes.indexOf(value); 14489 fn(classes, index, value); 14490 self.className = classes.join(" "); 14491 }; 14492 }; 14493 self = this; 14494 ret = { 14495 add: update(function(classes, index, value) { 14496 ~index || classes.push(value); 14497 }), 14498 remove: update(function(classes, index) { 14499 ~index && classes.splice(index, 1); 14500 }), 14501 toggle: update(function(classes, index, value) { 14502 if (~index) { 14503 classes.splice(index, 1); 14504 } else { 14505 classes.push(value); 14506 } 14507 }), 14508 contains: function(value) { 14509 return !!~self.className.split(/\s+/).indexOf(value); 14510 }, 14511 item: function(i) { 14512 return self.className.split(/\s+/)[i] || null; 14513 } 14514 }; 14515 Object.defineProperty(ret, "length", { 14516 get: function() { 14517 return self.className.split(/\s+/).length; 14518 } 14519 }); 14520 return ret; 14521 } 14522 }); 14523} 14524 14525String.prototype.to_rfc3986 = function() { 14526 var tmp; 14527 tmp = encodeURIComponent(this); 14528 return tmp.replace(/[!'()*]/g, function(c) { 14529 return "%" + c.charCodeAt(0).toString(16); 14530 }); 14531}; 14532 14533ShareUtils = (function() { 14534 function ShareUtils() {} 14535 14536 ShareUtils.prototype.extend = function(to, from, overwrite) { 14537 var hasProp, prop; 14538 for (prop in from) { 14539 hasProp = to[prop] !== undefined; 14540 if (hasProp && typeof from[prop] === "object") { 14541 this.extend(to[prop], from[prop], overwrite); 14542 } else { 14543 if (overwrite || !hasProp) { 14544 to[prop] = from[prop]; 14545 } 14546 } 14547 } 14548 }; 14549 14550 ShareUtils.prototype.hide = function(el) { 14551 return el.style.display = "none"; 14552 }; 14553 14554 ShareUtils.prototype.show = function(el) { 14555 return el.style.display = "block"; 14556 }; 14557 14558 ShareUtils.prototype.has_class = function(el, class_name) { 14559 return el.classList.contains(class_name); 14560 }; 14561 14562 ShareUtils.prototype.add_class = function(el, class_name) { 14563 return el.classList.add(class_name); 14564 }; 14565 14566 ShareUtils.prototype.remove_class = function(el, class_name) { 14567 return el.classList.remove(class_name); 14568 }; 14569 14570 ShareUtils.prototype.is_encoded = function(str) { 14571 str = str.to_rfc3986(); 14572 return decodeURIComponent(str) !== str; 14573 }; 14574 14575 ShareUtils.prototype.encode = function(str) { 14576 if (typeof str === "undefined" || this.is_encoded(str)) { 14577 return str; 14578 } else { 14579 return str.to_rfc3986(); 14580 } 14581 }; 14582 14583 ShareUtils.prototype.popup = function(url, params) { 14584 var k, popup, qs, v; 14585 if (params == null) { 14586 params = {}; 14587 } 14588 popup = { 14589 width: 500, 14590 height: 350 14591 }; 14592 popup.top = (screen.height / 2) - (popup.height / 2); 14593 popup.left = (screen.width / 2) - (popup.width / 2); 14594 qs = ((function() { 14595 var _results; 14596 _results = []; 14597 for (k in params) { 14598 v = params[k]; 14599 _results.push("" + k + "=" + (this.encode(v))); 14600 } 14601 return _results; 14602 }).call(this)).join('&'); 14603 if (qs) { 14604 qs = "?" + qs; 14605 } 14606 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="
14606+ popup.width + ",height=" + popup.height); 14607 }; 14608 14609 return ShareUtils; 14610 14611})(); 14612var Share, 14613 __hasProp = {}.hasOwnProperty, 14614 __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; }; 14615 14616Share = (function(_super) { 14617 __extends(Share, _super); 14618 14619 function Share(element, options) { 14620 this.element = element; 14621 this.el = { 14622 head: document.getElementsByTagName('head')[0], 14623 body: document.getElementsByTagName('body')[0] 14624 }; 14625 this.config = { 14626 enabled_networks: 0, 14627 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 14628 url: window.location.href.replace("&", "%26"), 14629 caption: null, 14630 title: this.default_title(), 14631 image: this.default_image(), 14632 description: this.default_description(), 14633 ui: { 14634 flyout: 'top center', 14635 button_text: 'Share', 14636 button_font: true, 14637 icon_font: true 14638 }, 14639 networks: { 14640 google_plus: { 14641 enabled: true, 14642 url: null 14643 }, 14644 twitter: { 14645 enabled: true, 14646 url: null, 14647 title: null, 14648 description: null 14649 }, 14650 facebook: { 14651 enabled: true, 14652 load_sdk: true, 14653 url: null, 14654 app_id: null, 14655 title: null, 14656 caption: null, 14657 description: null, 14658 image: null 14659 }, 14660 pinterest: { 14661 enabled: true, 14662 url: null, 14663 image: null, 14664 description: null 14665 }, 14666 reddit: { 14667 enabled: true, 14668 url: null, 14669 title: null 14670 }, 14671 linkedin: { 14672 enabled: true, 14673 url: null, 14674 title: null, 14675 description: null 14676 }, 14677 xing: { 14678 enabled: true, 14679 url: null, 14680 title: null, 14681 image: null, 14682 description: null 14683 }, 14684 whatsapp: { 14685 enabled: true, 14686 description: null, 14687 url: null 14688 }, 14689 email: { 14690 enabled: true, 14691 title: null, 14692 description: null, 14693 url: null 14694 } 14695 } 14696 }; 14697 this.setup(element, options); 14698 return this; 14699 } 14700 14701 Share.prototype.setup = function(element, opts) { 14702 var index, instance, instances, _i, _len; 14703 instances = document.querySelectorAll(element); 14704 this.extend(this.config, opts, true); 14705 this.set_global_configuration(); 14706 this.normalize_network_configuration(); 14707 if (this.config.ui.icon_font) { 14708 this.inject_icons(); 14709 } 14710 if (this.config.ui.button_font) { 14711 this.inject_fonts(); 14712 } 14713 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 14714 this.inject_facebook_sdk(); 14715 } 14716 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 14717 instance = instances[index]; 14718 this.setup_instance(element, index); 14719 } 14720 }; 14721 14722 Share.prototype.setup_instance = function(element, index) { 14723 var button, instance, label, network, networks, _i, _len, _results, 14724 _this = this; 14725 instance = document.querySelectorAll(element)[index]; 14726 this.hide(instance); 14727 this.add_class(instance, "sharer-" + index); 14728 instance = document.querySelectorAll(element)[index]; 14729 this.inject_css(instance); 14730 this.inject_html(instance); 14731 this.show(instance); 14732 label = instance.getElementsByTagName("label")[0]; 14733 button = instance.getElementsByClassName("social")[0]; 14734 networks = instance.getElementsByTagName('li'); 14735 this.add_class(button, "networks-" + this.config.enabled_networks); 14736 label.addEventListener("click", function() { 14737 return _this.event_toggle(button); 14738 }); 14739 _this = this; 14740 _results = []; 14741 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 14742 network = networks[index]; 14743 _results.push(network.addEventListener("click", function() { 14744 _this.event_network(instance, this); 14745 return _this.event_close(button); 14746 })); 14747 } 14748 return _results; 14749 }; 14750 14751 Share.prototype.event_toggle = function(button) { 14752 if (this.has_class(button, "active")) { 14753 return this.event_close(button); 14754 } else { 14755 return this.event_open(button); 14756 } 14757 }; 14758 14759 Share.prototype.event_open = function(button) { 14760 if (this.has_class(button, "load")) { 14761 this.remove_class(button, "load"); 14762 } 14763 return this.add_class(button, "active"); 14764 }; 14765 14766 Share.prototype.event_close = function(button) { 14767 return this.remove_class(button, "active"); 14768 }; 14769 14770 Share.prototype.event_network = function(instance, network) { 14771 var name; 14772 name = network.getAttribute("data-network"); 14773 this.hook("before", name, instance);
14774 this["network_" + name](); 14775 return this.hook("after", name, instance); 14776 }; 14777 14778 Share.prototype.open = function() { 14779 return this["public"]("open"); 14780 }; 14781 14782 Share.prototype.close = function() { 14783 return this["public"]("close"); 14784 }; 14785 14786 Share.prototype.toggle = function() { 14787 return this["public"]("toggle"); 14788 }; 14789 14790 Share.prototype["public"] = function(action) { 14791 var button, index, instance, _i, _len, _ref, _results; 14792 _ref = document.querySelectorAll(this.element); 14793 _results = []; 14794 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 14795 instance = _ref[index]; 14796 button = instance.getElementsByClassName("social")[0]; 14797 _results.push(this["event_" + action](button)); 14798 } 14799 return _results; 14800 }; 14801 14802 Share.prototype.network_facebook = function() { 14803 if (this.config.networks.facebook.load_sdk) { 14804 if (!window.FB) { 14805 return console.error("The Facebook JS SDK hasn't loaded yet."); 14806 } 14807 return FB.ui({ 14808 method: 'feed', 14809 name: this.config.networks.facebook.title, 14810 link: this.config.networks.facebook.url, 14811 picture: this.config.networks.facebook.image, 14812 caption: this.config.networks.facebook.caption, 14813 description: this.config.networks.facebook.description 14814 }); 14815 } else { 14816 return this.popup('https://www.facebook.com/sharer/sharer.php', { 14817 u: this.config.networks.facebook.url 14818 }); 14819 } 14820 }; 14821 14822 Share.prototype.network_twitter = function() { 14823 return this.popup('https://twitter.com/intent/tweet', { 14824 text: this.config.networks.twitter.title, 14825 url: this.config.networks.twitter.url 14826 }); 14827 }; 14828 14829 Share.prototype.network_google_plus = function() { 14830 return this.popup('https://plus.google.com/share', { 14831 url: this.config.networks.google_plus.url 14832 }); 14833 }; 14834 14835 Share.prototype.network_pinterest = function() { 14836 return this.popup('https://www.pinterest.com/pin/create/button', { 14837 url: this.config.networks.pinterest.url, 14838 media: this.config.networks.pinterest.image, 14839 description: this.config.networks.pinterest.description 14840 }); 14841 }; 14842 14843 Share.prototype.network_linkedin = function() { 14844 return this.popup('https://www.linkedin.com/shareArticle', { 14845 url: this.config.networks.linkedin.url, 14846 title: this.config.networks.linkedin.title, 14847 summary: this.config.networks.linkedin.description 14848 }); 14849 } 14850 14851 Share.prototype.network_xing = function() { 14852 return this.popup('https://www.xing.com/spi/shares/new', { 14853 url: this.config.networks.xing.url, 14854 image: this.config.networks.xing.image, 14855 title: this.config.networks.xing.title, 14856 summary: this.config.networks.xing.description 14857 }); 14858 } 14859 14860 Share.prototype.network_email = function() { 14861 return this.popup('mailto:', { 14862 subject: this.config.networks.email.title, 14863 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 14864 }); 14865 }; 14866 14867 Share.prototype.inject_icons = function() { 14868 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 14869 }; 14870 14871 Share.prototype.inject_fonts = function() { 14872 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 14873 }; 14874 14875 Share.prototype.inject_stylesheet = function(url) { 14876 var link; 14877 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 14878 link = document.createElement("link"); 14879 link.setAttribute("rel", "stylesheet"); 14880 link.setAttribute("href", url); 14881 return this.el.head.appendChild(link); 14882 } 14883 }; 14884 14885 Share.prototype.inject_css = function(instance) { 14886 var css, meta, selector, style; 14887 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 14888 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 14889 this.config.selector = selector; 14890 css = getStyles(this.config); 14891 style = document.createElement("style"); 14892 style.type = "text/css"; 14893 if (style.styleSheet) { 14894 style.styleSheet.cssText = css; 14895 } else { 14896 style.appendChild(document.createTextNode(css)); 14897 } 14898 this.el.head.appendChild(style); 14899 delete this.config.selector; 14900 meta = document.createElement("meta"); 14901 meta.setAttribute("name", "sharer" + selector); 14902 return this.el.head.appendChild(meta); 14903 } 14904 }; 14905 14906 Share.prototype.inject_html = function(instance) { 14907 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>"; 14908 }; 14909 14910 Share.prototype.inject_facebook_sdk = function() { 14911 var fb_root, script; 14912 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 14913 script = document.createElement("script"); 14914 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')"; 14915 fb_root = document.createElement("div"); 14916 fb_root.id = "fb-root"; 14917 this.el.body.appendChild(fb_root); 14918 return this.el.body.appendChild(script); 14919 } 14920 }; 14921 14922 Share.prototype.hook = function(type, network, instance) { 14923 var fn, opts; 14924 fn = this.config.networks[network][type]; 14925 if (typeof fn === "function") { 14926 opts = fn.call(this.config.networks[network], instance); 14927 if (opts !== void 0) { 14928 opts = this.normalize_filter_config_updates(opts); 14929 this.extend(this.config.networks[network], opts, true); 14930 this.normalize_network_configuration(); 14931 } 14932 } 14933 }; 14934 14935 Share.prototype.default_title = function() { 14936 var content; 14937 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 14938 return encodeURIComponent(content.getAttribute('content')); 14939 } else if (content = document.querySelector('title')) { 14940 return encodeURIComponent(content.innerText); 14941 } 14942 }; 14943 14944 Share.prototype.default_image = function() { 14945 var content; 14946 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 14947 return content.getAttribute('content'); 14948 } 14949 }; 14950 14951 Share.prototype.default_description = function() { 14952 var content; 14953 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 14954 return encodeURIComponent(content.getAttribute('content')); 14955 } else { 14956 return ''; 14957 } 14958 }; 14959 14960 Share.prototype.set_global_configuration = function() { 14961 var display, network, option, options, _ref, _results; 14962 _ref = this.config.networks; 14963 _results = []; 14964 for (network in _ref) { 14965 options = _ref[network]; 14966 for (option in options) { 14967 if (this.config.networks[network][option] == null) { 14968 this.config.networks[network][option] = this.config[option]; 14969 } 14970 } 14971 if (this.config.networks[network].enabled) { 14972 display = 'block'; 14973 this.config.enabled_networks += 1; 14974 } else { 14975 display = 'none'; 14976 } 14977 _results.push(this.config.networks[network].display = display); 14978 } 14979 return _results; 14980 }; 14981 14982 Share.prototype.normalize_network_configuration = function() { 14983 if (!this.config.networks.facebook.app_id) { 14984 this.config.networks.facebook.load_sdk = false;
14985 } 14986 if (!this.is_encoded(this.config.networks.twitter.description)) { 14987 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 14988 } 14989 if (typeof this.config.networks.facebook.app_id === 'number') { 14990 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 14991 } 14992 }; 14993 14994 Share.prototype.normalize_filter_config_updates = function(opts) { 14995 if (this.config.networks.facebook.app_id !== opts.app_id) { 14996 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."); 14997 delete opts.app_id; 14998 } 14999 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 15000 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."); 15001 delete opts.app_id; 15002 } 15003 return opts; 15004 }; 15005 15006 return Share; 15007 15008})(ShareUtils); 15009 return Share; 15010}); 15011 15012 15013// Generated by CoffeeScript 1.9.2 15014 15015// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 15016 15017(function() { 15018 var $, win; 15019 15020 $ = this.jQuery || window.jQuery; 15021 15022 win = $(window); 15023 15024 $.fn.stick_in_parent = function(opts) { 15025 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 15026 if (opts == null) { 15027 opts = {}; 15028 } 15029 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; 15030 if (offset_top == null) { 15031 offset_top = 0; 15032 } 15033 if (parent_selector == null) { 15034 parent_selector = void 0; 15035 } 15036 if (inner_scrolling == null) { 15037 inner_scrolling = true; 15038 } 15039 if (sticky_class == null) { 15040 sticky_class = "is_stuck"; 15041 } 15042 doc = $(document); 15043 if (enable_bottoming == null) { 15044 enable_bottoming = true; 15045 } 15046 outer_width = function(el) { 15047 var _el, computed, w; 15048 if (window.getComputedStyle) { 15049 _el = el[0]; 15050 computed = window.getComputedStyle(el[0]); 15051 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 15052 if (computed.getPropertyValue("box-sizing") !== "border-box") { 15053 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 15054 } 15055 return w; 15056 } else { 15057 return el.outerWidth(true); 15058 } 15059 }; 15060 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 15061 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 15062 if (elm.data("sticky_kit")) { 15063 return; 15064 } 15065 elm.data("sticky_kit", true); 15066 last_scroll_height = doc.height(); 15067 parent = elm.parent(); 15068 if (parent_selector != null) { 15069 parent = parent.closest(parent_selector); 15070 } 15071 if (!parent.length) { 15072 throw "failed to find stick parent"; 15073 } 15074 fixed = false; 15075 bottomed = false; 15076 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 15077 if (spacer) { 15078 spacer.css('position', elm.css('position')); 15079 } 15080 recalc = function() { 15081 var border_top, padding_top, restore; 15082 if (detached) { 15083 return; 15084 } 15085 last_scroll_height = doc.height(); 15086 border_top = parseInt(parent.css("border-top-width"), 10); 15087 padding_top = parseInt(parent.css("padding-top"), 10); 15088 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 15089 parent_top = parent.offset().top + border_top + padding_top; 15090 parent_height = parent.height(); 15091 if (fixed) { 15092 fixed = false; 15093 bottomed = false; 15094 if (manual_spacer == null) { 15095 elm.insertAfter(spacer); 15096 spacer.detach(); 15097 } 15098 elm.css({ 15099 position: "", 15100 top: "", 15101 width: "", 15102 bottom: "" 15103 }).removeClass(sticky_class); 15104 restore = true; 15105 } 15106 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 15107 height = elm.outerHeight(true); 15108 el_float = elm.css("float"); 15109 if (spacer) { 15110 spacer.css({ 15111 width: outer_width(elm), 15112 height: height, 15113 display: elm.css("display"), 15114 "vertical-align": elm.css("vertical-align"), 15115 "float": el_float 15116 }); 15117 } 15118 if (restore) { 15119 return tick(); 15120 } 15121 }; 15122 recalc(); 15123 if (height === parent_height) { 15124 return; 15125 } 15126 last_pos = void 0; 15127 offset = offset_top; 15128 recalc_counter = recalc_every; 15129 tick = function() { 15130 var css, delta, recalced, scroll, will_bottom, win_height; 15131 if (detached) { 15132 return; 15133 } 15134 recalced = false;
vendor: 4,152 bytes, lines 15135-15288
15135 if (recalc_counter != null) { 15136 recalc_counter -= 1; 15137 if (recalc_counter <= 0) { 15138 recalc_counter = recalc_every; 15139 recalc(); 15140 recalced = true; 15141 } 15142 } 15143 if (!recalced && doc.height() !== last_scroll_height) { 15144 recalc(); 15145 recalced = true; 15146 } 15147 scroll = win.scrollTop(); 15148 if (last_pos != null) { 15149 delta = scroll - last_pos; 15150 } 15151 last_pos = scroll; 15152 if (fixed) { 15153 if (enable_bottoming) { 15154 will_bottom = scroll + height + offset > parent_height + parent_top; 15155 if (bottomed && !will_bottom) { 15156 bottomed = false; 15157 elm.css({ 15158 position: "fixed", 15159 bottom: "", 15160 top: offset 15161 }).trigger("sticky_kit:unbottom"); 15162 } 15163 } 15164 if (scroll < top) { 15165 fixed = false; 15166 offset = offset_top; 15167 if (manual_spacer == null) { 15168 if (el_float === "left" || el_float === "right") { 15169 elm.insertAfter(spacer); 15170 } 15171 spacer.detach(); 15172 } 15173 css = { 15174 position: "", 15175 width: "", 15176 top: "" 15177 }; 15178 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 15179 } 15180 if (inner_scrolling) { 15181 win_height = win.height(); 15182 if (height + offset_top > win_height) { 15183 if (!bottomed) { 15184 offset -= delta; 15185 offset = Math.max(win_height - height, offset); 15186 offset = Math.min(offset_top, offset); 15187 if (fixed) { 15188 elm.css({ 15189 top: offset + "px" 15190 }); 15191 } 15192 } 15193 } 15194 } 15195 } else { 15196 if (scroll > top) { 15197 fixed = true; 15198 css = { 15199 position: "fixed", 15200 top: offset 15201 }; 15202 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 15203 elm.css(css).addClass(sticky_class); 15204 if (manual_spacer == null) { 15205 elm.after(spacer); 15206 if (el_float === "left" || el_float === "right") { 15207 spacer.append(elm); 15208 } 15209 } 15210 elm.trigger("sticky_kit:stick"); 15211 } 15212 } 15213 if (fixed && enable_bottoming) { 15214 if (will_bottom == null) { 15215 will_bottom = scroll + height + offset > parent_height + parent_top; 15216 } 15217 if (!bottomed && will_bottom) { 15218 bottomed = true; 15219 if (parent.css("position") === "static") { 15220 parent.css({ 15221 position: "relative" 15222 }); 15223 } 15224 return elm.css({ 15225 position: "absolute", 15226 bottom: padding_bottom, 15227 top: "auto" 15228 }).trigger("sticky_kit:bottom"); 15229 } 15230 } 15231 }; 15232 recalc_and_tick = function() { 15233 recalc(); 15234 return tick(); 15235 }; 15236 detach = function() { 15237 detached = true; 15238 win.off("touchmove", tick); 15239 win.off("scroll", tick); 15240 win.off("resize", recalc_and_tick); 15241 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 15242 elm.off("sticky_kit:detach", detach); 15243 elm.removeData("sticky_kit"); 15244 elm.css({ 15245 position: "", 15246 bottom: "", 15247 top: "", 15248 width: "" 15249 }); 15250 parent.position("position", ""); 15251 if (fixed) { 15252 if (manual_spacer == null) { 15253 if (el_float === "left" || el_float === "right") { 15254 elm.insertAfter(spacer); 15255 } 15256 spacer.remove(); 15257 } 15258 return elm.removeClass(sticky_class); 15259 } 15260 }; 15261 win.on("touchmove", tick); 15262 win.on("scroll", tick); 15263 win.on("resize", recalc_and_tick); 15264 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 15265 elm.on("sticky_kit:detach", detach); 15266 return setTimeout(tick, 0); 15267 }; 15268 for (i = 0, len = this.length; i < len; i++) { 15269 elm = this[i]; 15270 fn($(elm)); 15271 } 15272 return this; 15273 }; 15274 15275}).call(this); 15276 15277/* ========================================================================== 15278 * bootstrap-tab-history.js 15279 * Author: Michael Narayan <[email protected]> 15280 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 15281 * ========================================================================== 15282 * Licensed under the Apache License, Version 2.0 (the "License"); you may 15283 * not use this file except in compliance with the License. You may obtain a 15284 * copy of the License at 15285 * 15286 * http://www.apache.org/licenses/LICENSE-2.0 15287 * 15288 * Unless required by applicable law or agreed to in writing, softw
15288are 15289 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15290 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15291 * License for the specific language governing permissions and limitations 15292 * under the License. 15293 * ========================================================================== */ 15294 15295/* ========================================================================== */ 15296/* JSHint directives */ 15297/* */ 15298/* global BootstrapTabHistory: true */ 15299/* */ 15300/* global document */ 15301/* global jQuery */ 15302/* global history */ 15303/* global window */ 15304/* ========================================================================== */ 15305 15306/** 15307 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 15308 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 15309 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 15310 * 15311 * See the README for additional information. 15312 * 15313 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 15314 */ 15315 15316BootstrapTabHistory = { 15317 options: { 15318 /** 15319 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 15320 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 15321 * 15322 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 15323 * 15324 * @public 15325 * @type {?number} 15326 */ 15327 defaultAnchorYOffset: 0, 15328 /** 15329 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 15330 * 15331 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 15332 * 15333 * @public 15334 * @type {string} 15335 */ 15336 defaultChanger: 'replace', 15337 /** 15338 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 15339 * `null` is passed as the third parameter to these calls. 15340 * 15341 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 15342 * 15343 * @public 15344 * @type {boolean} 15345 */ 15346 defaultUpdateURL: false, 15347 /** 15348 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 15349 * load. 15350 * 15351 * @public 15352 * @type {boolean} 15353 */ 15354 showTabsBasedOnAnchor: true 15355 } 15356}; 15357 15358(function () { 15359 'use strict'; 15360 15361 jQuery(function () { 15362 if(history && history.pushState && history.replaceState) { 15363 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15364 15365 if(bootstrapTabHistory) { 15366 showTabsBasedOnState(bootstrapTabHistory); 15367 } else { 15368 showTabsBasedOnAnchor(); 15369 } 15370 15371 backfillHistoryState(); 15372 15373 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 15374 jQuery(window).on('popstate', onPopState); 15375 } else { 15376 showTabsBasedOnAnchor(); 15377 } 15378 }); 15379 15380 /** 15381 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 15382 * 15383 * @type {boolean} 15384 */ 15385 var showingTabsBasedOnState = false; 15386 15387 /** 15388 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 15389 * `history.back` handling when `data-tab-history-update-url` is true. 15390 */ 15391 function backfillHistoryState() { 15392 var newState = null; 15393 15394 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 15395 var $activeTabElement = jQuery(this); 15396 var selector = getTabSelector($activeTabElement); 15397 15398 if(selector) { 15399 var tabGroup = getTabGroup($activeTabElement); 15400 15401 if(tabGroup) { 15402 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 15403 } 15404 } 15405 }); 15406 15407 if(newState) { 15408 history.replaceState(newState, '', null); 15409 } 15410 } 15411
15412 /** 15413 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 15414 * said bootstrapTabHistory attribute. 15415 * 15416 * @param {?object} existingState 15417 * @param {!string} tabGroup 15418 * @param {!string} selector 15419 * @returns {!object} 15420 */ 15421 function createNewHistoryState(existingState, tabGroup, selector) { 15422 // Clone history.state and ensure it has a bootstrapTabHistory entry. 15423 var newState = jQuery.extend(true, {}, existingState, { 15424 bootstrapTabHistory: {} 15425 }); 15426 15427 newState.bootstrapTabHistory[tabGroup] = selector; 15428 15429 return newState; 15430 } 15431 15432 /** 15433 * @param {jQuery} $tab 15434 * @returns {?string} 15435 */ 15436 function getTabGroup($tab) { 15437 return parseTruthyAttributeValue($tab.data('tab-history')); 15438 } 15439 15440 /** 15441 * @param {jQuery} $tab 15442 * @returns {?string} 15443 */ 15444 function getTabSelector($tab) { 15445 return $tab.data('target') || $tab.attr('href'); 15446 } 15447 15448 /** 15449 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 15450 * 15451 * @param {jQuery.Event} shownEvt 15452 */ 15453 function onShownTab(shownEvt) { 15454 if(!showingTabsBasedOnState) { 15455 var $activatedTab = jQuery(shownEvt.target); 15456 if ( $activatedTab.hasClass('panel-collapse') ) 15457 $activatedTab = $activatedTab.closest('.panel').find('a'); 15458 var selector = getTabSelector($activatedTab); 15459 15460 if(selector) { 15461 var tabGroup = getTabGroup($activatedTab); 15462 15463 if(tabGroup) { 15464 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 15465 var newState = createNewHistoryState(history.state, tabGroup, selector); 15466 var updateURL = (function ($activatedTab) { 15467 if(selector[0] === '#') { 15468 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 15469 15470 if(elementUpdateURLOption === undefined) { 15471 return BootstrapTabHistory.options.defaultUpdateURL; 15472 } else { 15473 return elementUpdateURLOption; 15474 } 15475 } else { 15476 return false; 15477 } 15478 })($activatedTab); 15479 15480 switch(historyChanger) { 15481 case 'push': 15482 history.pushState(newState, '', updateURL ? selector : null); 15483 break; 15484 case 'replace': 15485 history.replaceState(newState, '', updateURL ? selector : null); 15486 break; 15487 default: 15488 throw new Error('Unknown tab-history-changer: ' + historyChanger); 15489 } 15490 } 15491 } 15492 } 15493 } 15494 15495 /** 15496 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 15497 */ 15498 function onPopState() { 15499 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 15500 15501 if(bootstrapTabHistory) { 15502 showTabsBasedOnState(bootstrapTabHistory); 15503 } 15504 } 15505 15506 /** 15507 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 15508 * 15509 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 15510 * 15511 * @param {*} value 15512 * @returns {*} 15513 */ 15514 function parseTruthyAttributeValue(value) { 15515 if(value) { 15516 return value; 15517 } else if(value === '') { 15518 return true; 15519 } else { 15520 return value; 15521 } 15522 } 15523 15524 /** 15525 * Show tabs based upon the anchor component of `window.location`. 15526 */ 15527 function showTabsBasedOnAnchor() { 15528 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 15529 var anchor = window.location && window.location.hash; 15530 15531 if(anchor) { 15532 var $tabElement = showTabForSelector(anchor); 15533 15534 if($tabElement && window.addEventListener && window.removeEventListener) { 15535 var anchorYOffset = (function ($tabElement) { 15536 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 15537 15538 if(elementSetting === undefined) { 15539 return BootstrapTabHistory.options.defaultAnchorYOffset; 15540 } else { 15541 return elementSetting; 15542 } 15543 })($tabElement); 15544 15545 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 15546 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 15547 // `history.state` object should have been used (unless the browser did not support the modern History API). 15548 if(anchorYOffset || anchorYOffset === 0) { 15549 var scrollListener = function resetAnchorScroll () { 15550 window.removeEventListener('scroll', scrollListener); 15551 window.scrollTo(0, anchorYOffset); 15552 }; 15553 15554 window.addEventListener('scroll', scrollListener); 15555 } 15556 } 15557 } 15558 } 15559 } 15560
vendor: 4,905 bytes, lines 15561-15727
15561 /** 15562 * Show a tab which corresponds to the provided selector. 15563 * 15564 * @param {string} selector - A CSS selector. 15565 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 15566 */ 15567 function showTabForSelector(selector) { 15568 var $tabElement = (function (selector) { 15569 var $ret = null; 15570 15571 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 15572 var $potentialTab = jQuery(this); 15573 15574 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 15575 $ret = $potentialTab; 15576 return false; 15577 } else { 15578 return null; 15579 } 15580 }); 15581 15582 return $ret; 15583 })(selector); 15584 15585 if($tabElement) { 15586 $tabElement.trigger('click'); 15587 //$tabElement.tab('show'); 15588 } 15589 15590 return $tabElement; 15591 } 15592 15593 /** 15594 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 15595 * 15596 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 15597 */ 15598 function showTabsBasedOnState(bootstrapTabHistory) { 15599 showingTabsBasedOnState = true; 15600 15601 try { 15602 for(var k in bootstrapTabHistory) { 15603 if(bootstrapTabHistory.hasOwnProperty(k)) { 15604 showTabForSelector(bootstrapTabHistory[k]); 15605 } 15606 } 15607 } finally { 15608 showingTabsBasedOnState = false; 15609 } 15610 } 15611})(); 15612 15613 15614/*! 15615 * Justified Gallery - v3.6.3 15616 * http://miromannino.github.io/Justified-Gallery/ 15617 * Copyright (c) 2016 Miro Mannino 15618 * Licensed under the MIT license. 15619 */ 15620(function($) { 15621 15622 function hasScrollBar() { 15623 return $("body").height() > $(window).height(); 15624 } 15625 /** 15626 * Justified Gallery controller constructor 15627 * 15628 * @param $gallery the gallery to build 15629 * @param settings the settings (the defaults are in $.fn.justifiedGallery.defaults) 15630 * @constructor 15631 */ 15632 var JustifiedGallery = function ($gallery, settings) { 15633 15634 this.settings = settings; 15635 this.checkSettings(); 15636 15637 this.imgAnalyzerTimeout = null; 15638 this.entries = null; 15639 this.buildingRow = { 15640 entriesBuff : [], 15641 width : 0, 15642 height : 0, 15643 aspectRatio : 0 15644 }; 15645 this.lastFetchedEntry = null; 15646 this.lastAnalyzedIndex = -1; 15647 this.yield = { 15648 every : 2, // do a flush every n flushes (must be greater than 1) 15649 flushed : 0 // flushed rows without a yield 15650 }; 15651 this.border = settings.border >= 0 ? settings.border : settings.margins; 15652 this.maxRowHeight = this.retrieveMaxRowHeight(); 15653 this.suffixRanges = this.retrieveSuffixRanges(); 15654 this.offY = this.border; 15655 this.rows = 0; 15656 this.spinner = { 15657 phase : 0, 15658 timeSlot : 150, 15659 $el : $('<div class="spinner"><span></span><span></span><span></span></div>'), 15660 intervalId : null 15661 }; 15662 this.checkWidthIntervalId = null; 15663 this.galleryWidth = $gallery.width(); 15664 this.$gallery = $gallery; 15665 15666 }; 15667 15668 /** @returns {String} the best suffix given the width and the height */ 15669 JustifiedGallery.prototype.getSuffix = function (width, height) { 15670 var longestSide, i; 15671 longestSide = (width > height) ? width : height; 15672 for (i = 0; i < this.suffixRanges.length; i++) { 15673 if (longestSide <= this.suffixRanges[i]) { 15674 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 15675 } 15676 } 15677 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 15678 }; 15679 15680 /** 15681 * Remove the suffix from the string 15682 * 15683 * @returns {string} a new string without the suffix 15684 */ 15685 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 15686 return str.substring(0, str.length - suffix.length); 15687 }; 15688 15689 /** 15690 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 15691 */ 15692 JustifiedGallery.prototype.endsWith = function (str, suffix) { 15693 return str.indexOf(suffix, str.length - suffix.length) !== -1; 15694 }; 15695 15696 /** 15697 * Get the used suffix of a particular url 15698 * 15699 * @param str 15700 * @returns {String} return the used suffix 15701 */ 15702 JustifiedGallery.prototype.getUsedSuffix = function (str) { 15703 for (var si in this.settings.sizeRangeSuffixes) { 15704 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 15705 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 15706 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 15707 } 15708 } 15709 return ''; 15710 }; 15711 15712 /** 15713 * Given an image src, with the width and the height, returns the new image src with the 15714 * best suffix to show the best quality thumbnail. 15715 * 15716 * @returns {String} the suffix to use 15717 */ 15718 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 15719 var newImageSrc; 15720 15721 if (this.settings.thumbnailPath) { 15722 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 15723 } else { 15724 var matchRes = imageSrc.match(this.settings.extension); 15725 var ext = (matchRes !== null) ? matchRes[0] : ''; 15726 newImageSrc = imageSrc.replace(this.settings.extension, ''); 15727 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
15728 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 15729 } 15730 15731 return newImageSrc; 15732 }; 15733 15734 /** 15735 * Shows the images that is in the given entry 15736 * 15737 * @param $entry the entry 15738 * @param callback the callback that is called when the show animation is finished 15739 */ 15740 JustifiedGallery.prototype.showImg = function ($entry, callback) { 15741 if (this.settings.cssAnimation) { 15742 $entry.addClass('entry-visible'); 15743 if (callback) callback(); 15744 } else { 15745 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15746 $entry.find('> img, > a > img').stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 15747 } 15748 }; 15749 15750 /** 15751 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 15752 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 15753 * 15754 * @param $image the image to analyze 15755 * @returns {String} the extracted src 15756 */ 15757 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 15758 var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src'); 15759 $image.data('jg.originalSrc', imageSrc); 15760 return imageSrc; 15761 }; 15762 15763 /** @returns {jQuery} the image in the given entry */ 15764 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 15765 var $img = $entry.find('> img'); 15766 if ($img.length === 0) $img = $entry.find('> a > img'); 15767 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 15768 return $img.length === 0 ? null : $img; 15769 }; 15770 15771 /** @returns {jQuery} the caption in the given entry */ 15772 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 15773 var $caption = $entry.find('> .caption'); 15774 return $caption.length === 0 ? null : $caption; 15775 }; 15776 15777 /** 15778 * Display the entry 15779 * 15780 * @param {jQuery} $entry the entry to display 15781 * @param {int} x the x position where the entry must be positioned 15782 * @param y the y position where the entry must be positioned 15783 * @param imgWidth the image width 15784 * @param imgHeight the image height 15785 * @param rowHeight the row height of the row that owns the entry 15786 */ 15787 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 15788 $entry.width(imgWidth); 15789 $entry.height(Math.floor(rowHeight));//hacked by Uncode 15790 $entry.css('top', Math.floor(y));//hacked by Uncode 15791 $entry.css('left', x); 15792 15793 var $image = this.imgFromEntry($entry); 15794 if ($image !== null) { 15795 $image.css('width', imgWidth); 15796 $image.css('height', imgHeight); 15797 $image.css('margin-left', - imgWidth / 2); 15798 $image.css('margin-top', - imgHeight / 2); 15799 15800 // Image reloading for an high quality of thumbnails 15801 var imageSrc = $image.attr('src'); 15802 var newImageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 15803 15804 $image.one('error', function () { 15805 $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it. 15806 }); 15807 15808 var loadNewImage = function () { 15809 if (imageSrc !== newImageSrc) { //load the new image after the fadeIn 15810 $image.attr('src', newImageSrc); 15811 } 15812 }; 15813 15814 if ($entry.data('jg.loaded') === 'skipped') { 15815 this.onImageEvent(imageSrc, $.proxy(function() { 15816 this.showImg($entry, loadNewImage); 15817 $entry.data('jg.loaded', true); 15818 }, this)); 15819 } else { 15820 this.showImg($entry, loadNewImage); 15821 } 15822 15823 } else { 15824 this.showImg($entry); 15825 } 15826 15827 this.displayEntryCaption($entry); 15828 }; 15829 15830 /** 15831 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 15832 * or the 'title' attributes. 15833 * 15834 * @param {jQuery} $entry the entry to process 15835 */ 15836 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 15837 var $image = this.imgFromEntry($entry); 15838 if ($image !== null && this.settings.captions) { 15839 var $imgCaption = this.captionFromEntry($entry); 15840 15841 // Create it if it doesn't exists 15842 if ($imgCaption === null) { 15843 var caption = $image.attr('alt'); 15844 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 15845 if (this.isValidCaption(caption)) { // Create only we found something 15846 $imgCaption = $('<div class="caption">' + caption + '</div>'); 15847 $entry.append($imgCaption); 15848 $entry.data('jg.createdCaption', true); 15849 } 15850 } 15851 15852 // Create events (we check again the $imgCaption because it can be still inexistent) 15853 if ($imgCaption !== null) { 15854 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 15855 this.addCaptionEventsHandlers($entry); 15856 } 15857 } else { 15858 this.removeCaptionEventsHandlers($entry); 15859 } 15860 }; 15861 15862 /** 15863 * Validates the caption 15864 * 15865 * @param caption The caption that should be validated 15866 * @return {boolean} Validation result 15867 */ 15868 JustifiedGallery.prototype.isValidCaption = function (caption) { 15869 return (typeof caption !== 'undefined' && caption.length > 0); 15870 }; 15871 15872 /** 15873 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 15874 * It shows the caption using jQuery (or using CSS if it is configured so) 15875 * 15876 * @param {Event} eventObject the event object 15877 */ 15878 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 15879 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15880 if (this.settings.cssAnimation) { 15881 $caption.addClass('caption-visible').removeClass('caption-hidden'); 15882 } else { 15883 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15884 this.settings.captionSettings.visibleOpacity); 15885 } 15886 }; 15887 15888 /** 15889 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 15890 * It hides the caption using jQuery (or using CSS if it is configured so) 15891 * 15892 * @param {Event} eventObject the event object 15893 */ 15894 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 15895 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 15896 if (this.settings.cssAnimation) { 15897 $caption.removeClass('caption-visible').removeClass('caption-hidden'); 15898 } else { 15899 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 15900 this.settings.captionSettings.nonVisibleOpacity); 15901 } 15902 }; 15903 15904 /** 15905 * Add the handlers of the entry for the caption 15906 * 15907 * @param $entry the entry to modify 15908 */ 15909 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 15910 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15911 if (typeof captionMouseEvents === 'undefined') { 15912 captionMouseEvents = { 15913 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 15914 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 15915 }; 15916 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 15917 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 15918 $entry.data('jg.captionMouseEvents', captionMouseEvents); 15919 } 15920 }; 15921 15922 /** 15923 * Remove the handlers of the entry for the caption 15924 * 15925 * @param $entry the entry to modify 15926 */ 15927 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 15928 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 15929 if (typeof captionMouseEvents !== 'undefined') { 15930 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 15931 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 15932 $entry.removeData('jg.captionMouseEvents'); 15933 } 15934 }; 15935 15936 /** 15937 * Justify the building row, preparing it to 15938 * 15939 * @param isLastRow 15940 * @returns a boolean to know if the row has been justified or not 15941 */ 15942 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow) { 15943 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 15944 var minHeight = 0; 15945 var availableWidth = this.galleryWidth - 2 * this.border - ( 15946 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 15947 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 15948 var defaultRowHeight = this.settings.rowHeight; 15949 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 15950 15951 //Skip the last row if we can't justify it and the lastRow == 'hide' 15952 if (isLastRow && this.settings.lastRow === 'hide' && !justifiable) { 15953 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15954 $entry = this.buildingRow.entriesBuff[i]; 15955 if (this.settings.cssAnimation) 15956 $entry.removeClass('entry-visible'); 15957 else { 15958 $entry.stop().fadeTo(0, 0.1); 15959 $entry.find('> img, > a > img').fadeTo(0, 0); 15960 } 15961 } 15962 return -1; 15963 } 15964 15965 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 15966 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 15967 justify = false;
15968 15969 if (this.rows > 0) { 15970 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 15971 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 15972 } 15973 } 15974 15975 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 15976 $entry = this.buildingRow.entriesBuff[i]; 15977 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 15978 15979 if (justify) { 15980 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 15981 newImgH = rowHeight; 15982 } else { 15983 newImgW = defaultRowHeight * imgAspectRatio; 15984 newImgH = defaultRowHeight; 15985 } 15986 15987 availableWidth -= Math.round(newImgW); 15988 $entry.data('jg.jwidth', Math.round(newImgW)); 15989 $entry.data('jg.jheight', Math.ceil(newImgH)); 15990 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 15991 } 15992 15993 this.buildingRow.height = minHeight; 15994 return justify; 15995 }; 15996 15997 /** 15998 * Clear the building row data to be used for a new row 15999 */ 16000 JustifiedGallery.prototype.clearBuildingRow = function () { 16001 this.buildingRow.entriesBuff = []; 16002 this.buildingRow.aspectRatio = 0; 16003 this.buildingRow.width = 0; 16004 }; 16005 16006 /** 16007 * Flush a row: justify it, modify the gallery height accordingly to the row height 16008 * 16009 * @param isLastRow 16010 */ 16011 JustifiedGallery.prototype.flushRow = function (isLastRow) { 16012 var settings = this.settings; 16013 var $entry, buildingRowRes, offX = this.border, i; 16014 16015 buildingRowRes = this.prepareBuildingRow(isLastRow); 16016 if (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1) { 16017 this.clearBuildingRow(); 16018 return; 16019 } 16020 16021 if (this.maxRowHeight) { 16022 if (this.maxRowHeight.isPercentage && this.maxRowHeight.value * settings.rowHeight < this.buildingRow.height) { 16023 this.buildingRow.height = this.maxRowHeight.value * settings.rowHeight; 16024 } else if (this.maxRowHeight.value >= settings.rowHeight && this.maxRowHeight.value < this.buildingRow.height) { 16025 this.buildingRow.height = this.maxRowHeight.value; 16026 } 16027 } 16028 16029 //Align last (unjustified) row 16030 if (settings.lastRow === 'center' || settings.lastRow === 'right') { 16031 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 16032 16033 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16034 $entry = this.buildingRow.entriesBuff[i]; 16035 availableWidth -= $entry.data('jg.jwidth'); 16036 } 16037 16038 if (settings.lastRow === 'center') 16039 offX += availableWidth / 2; 16040 else if (settings.lastRow === 'right') 16041 offX += availableWidth; 16042 } 16043 16044 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 16045 $entry = this.buildingRow.entriesBuff[i]; 16046 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 16047 offX += $entry.data('jg.jwidth') + settings.margins; 16048 } 16049 16050 //Gallery Height 16051 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 16052 this.$gallery.height(this.galleryHeightToSet + this.getSpinnerHeight()); 16053 16054 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 16055 //Ready for a new row 16056 this.offY += this.buildingRow.height + settings.margins; 16057 this.rows += 1; 16058 this.clearBuildingRow(); 16059 this.$gallery.trigger('jg.rowflush'); 16060 } 16061 }; 16062 16063 /** 16064 * Checks the width of the gallery container, to know if a new justification is needed 16065 */ 16066 var scrollBarOn = false; 16067 JustifiedGallery.prototype.checkWidth = function () { 16068 this.checkWidthIntervalId = setInterval($.proxy(function () { 16069 var galleryWidth = parseFloat(this.$gallery.width()); 16070 if (hasScrollBar() === scrollBarOn) { 16071 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 16072 this.galleryWidth = galleryWidth; 16073 this.rewind(); 16074 16075 // Restart to analyze 16076 this.startImgAnalyzer(true); 16077 } 16078 } else { 16079 scrollBarOn = hasScrollBar(); 16080 this.galleryWidth = galleryWidth; 16081 } 16082 }, this), this.settings.refreshTime); 16083 }; 16084 16085 /** 16086 * @returns {boolean} a boolean saying if the spinner is active or not 16087 */ 16088 JustifiedGallery.prototype.isSpinnerActive = function () { 16089 return this.spinner.intervalId !== null; 16090 }; 16091 16092 /** 16093 * @returns {int} the spinner height 16094 */ 16095 JustifiedGallery.prototype.getSpinnerHeight = function () {
16096 return this.spinner.$el.innerHeight(); 16097 }; 16098 16099 /** 16100 * Stops the spinner animation and modify the gallery height to exclude the spinner 16101 */ 16102 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 16103 clearInterval(this.spinner.intervalId); 16104 this.spinner.intervalId = null; 16105 this.$gallery.height(this.$gallery.height() - this.getSpinnerHeight()); 16106 this.spinner.$el.detach(); 16107 }; 16108 16109 /** 16110 * Starts the spinner animation 16111 */ 16112 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 16113 var spinnerContext = this.spinner; 16114 var $spinnerPoints = spinnerContext.$el.find('span'); 16115 clearInterval(spinnerContext.intervalId); 16116 this.$gallery.append(spinnerContext.$el); 16117 this.$gallery.height(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 16118 spinnerContext.intervalId = setInterval(function () { 16119 if (spinnerContext.phase < $spinnerPoints.length) { 16120 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 16121 } else { 16122 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 16123 }
16124 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 16125 }, spinnerContext.timeSlot); 16126 }; 16127 16128 /** 16129 * Rewind the image analysis to start from the first entry. 16130 */ 16131 JustifiedGallery.prototype.rewind = function () { 16132 this.lastFetchedEntry = null; 16133 this.lastAnalyzedIndex = -1; 16134 this.offY = this.border; 16135 this.rows = 0; 16136 this.clearBuildingRow(); 16137 }; 16138 16139 /** 16140 * Update the entries searching it from the justified gallery HTML element 16141 * 16142 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 16143 * @returns {boolean} true if some entries has been founded 16144 */ 16145 JustifiedGallery.prototype.updateEntries = function (norewind) { 16146 var newEntries; 16147 16148 if (norewind && this.lastFetchedEntry != null) { 16149 newEntries = $(this.lastFetchedEntry).nextAll(this.settings.selector).toArray(); 16150 } else { 16151 this.entries = []; 16152 newEntries = this.$gallery.children(this.settings.selector).toArray(); 16153 } 16154 16155 if (newEntries.length > 0) { 16156 16157 // Sort or randomize 16158 if ($.isFunction(this.settings.sort)) { 16159 newEntries = this.sortArray(newEntries); 16160 } else if (this.settings.randomize) { 16161 newEntries = this.shuffleArray(newEntries); 16162 } 16163 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 16164 16165 // Filter 16166 if (this.settings.filter) { 16167 newEntries = this.filterArray(newEntries); 16168 } else { 16169 this.resetFilters(newEntries); 16170 } 16171 16172 } 16173 16174 this.entries = this.entries.concat(newEntries); 16175 return true; 16176 }; 16177 16178 /** 16179 * Apply the entries order to the DOM, iterating the entries and appending the images 16180 * 16181 * @param entries the entries that has been modified and that must be re-ordered in the DOM 16182 */ 16183 JustifiedGallery.prototype.insertToGallery = function (entries) { 16184 var that = this; 16185 $.each(entries, function () { 16186 $(this).appendTo(that.$gallery); 16187 }); 16188 }; 16189 16190 /** 16191 * Shuffle the array using the Fisher-Yates shuffle algorithm 16192 * 16193 * @param a the array to shuffle 16194 * @return the shuffled array 16195 */ 16196 JustifiedGallery.prototype.shuffleArray = function (a) { 16197 var i, j, temp; 16198 for (i = a.length - 1; i > 0; i--) { 16199 j = Math.floor(Math.random() * (i + 1)); 16200 temp = a[i]; 16201 a[i] = a[j]; 16202 a[j] = temp; 16203 } 16204 this.insertToGallery(a); 16205 return a; 16206 }; 16207 16208 /** 16209 * Sort the array using settings.comparator as comparator 16210 * 16211 * @param a the array to sort (it is sorted) 16212 * @return the sorted array 16213 */ 16214 JustifiedGallery.prototype.sortArray = function (a) { 16215 a.sort(this.settings.sort); 16216 this.insertToGallery(a); 16217 return a; 16218 }; 16219 16220 /** 16221 * Reset the filters removing the 'jg-filtered' class from all the entries 16222 * 16223 * @param a the array to reset 16224 */ 16225 JustifiedGallery.prototype.resetFilters = function (a) { 16226 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 16227 }; 16228 16229 /** 16230 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 16231 * 16232 * @param a the array to filter 16233 * @return the filtered array 16234 */ 16235 JustifiedGallery.prototype.filterArray = function (a) { 16236 var settings = this.settings; 16237 if ($.type(settings.filter) === 'string') { 16238 // Filter only keeping the entries passed in the string 16239 return a.filter(function (el) { 16240 var $el = $(el); 16241 if ($el.is(settings.filter)) { 16242 $el.removeClass('jg-filtered'); 16243 return true; 16244 } else { 16245 $el.addClass('jg-filtered').removeClass('jg-visible'); 16246 return false; 16247 } 16248 }); 16249 } else if ($.isFunction(settings.filter)) { 16250 // Filter using the passed function 16251 var filteredArr = a.filter(settings.filter); 16252 for (var i = 0; i < a.length; i++) { 16253 if (filteredArr.indexOf(a[i]) == -1) { 16254 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 16255 } else { 16256 $(a[i]).removeClass('jg-filtered'); 16257 } 16258 } 16259 return filteredArr; 16260 } 16261 }; 16262 16263 /** 16264 * Destroy the Justified Gallery instance. 16265 * 16266 * It clears all the css properties added in the style attributes. We doesn't backup the original 16267 * values for those css attributes, because it costs (performance) and because in general one 16268 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 16269 * classes). Creating a backup is also difficult because JG could be called multiple times and 16270 * with different style attributes. 16271 */ 16272 JustifiedGallery.prototype.destroy = function () { 16273 clearInterval(this.checkWidthIntervalId); 16274 16275 $.each(this.entries, $.proxy(function(_, entry) { 16276 var $entry = $(entry); 16277 16278 // Reset entry style 16279 $entry.css('width', ''); 16280 $entry.css('height', ''); 16281 $entry.css('top', ''); 16282 $entry.css('left', ''); 16283 $entry.data('jg.loaded', undefined); 16284 $entry.removeClass('jg-entry'); 16285 16286 // Reset image style 16287 var $img = this.imgFromEntry($entry); 16288 $img.css('width', ''); 16289 $img.css('height', ''); 16290 $img.css('margin-left', ''); 16291 $img.css('margin-top', ''); 16292 $img.attr('src', $img.data('jg.originalSrc')); 16293 $img.data('jg.originalSrc', undefined); 16294 16295 // Remove caption 16296 this.removeCaptionEventsHandlers($entry); 16297 var $caption = this.captionFromEntry($entry); 16298 if ($entry.data('jg.createdCaption')) { 16299 // remove also the caption element (if created by jg) 16300 $entry.data('jg.createdCaption', undefined); 16301 if ($caption !== null) $caption.remove(); 16302 } else { 16303 if ($caption !== null) $caption.fadeTo(0, 1); 16304 } 16305 16306 }, this)); 16307 16308 this.$gallery.css('height', ''); 16309 this.$gallery.removeClass('justified-gallery'); 16310 this.$gallery.data('jg.controller', undefined); 16311 }; 16312 16313 /** 16314 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 16315 * 16316 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 16317 */
16318 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 16319 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 16320 var $entry = $(this.entries[i]); 16321 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 16322 var availableWidth = this.galleryWidth - 2 * this.border - ( 16323 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 16324 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 16325 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 16326 this.flushRow(false); 16327 if(++this.yield.flushed >= this.yield.every) { 16328 this.startImgAnalyzer(isForResize); 16329 return; 16330 } 16331 } 16332 16333 this.buildingRow.entriesBuff.push($entry); 16334 this.buildingRow.aspectRatio += imgAspectRatio; 16335 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 16336 this.lastAnalyzedIndex = i; 16337 16338 } else if ($entry.data('jg.loaded') !== 'error') { 16339 return; 16340 } 16341 } 16342 16343 // Last row flush (the row is not full) 16344 if (this.buildingRow.entriesBuff.length > 0) this.flushRow(true); 16345 16346 if (this.isSpinnerActive()) { 16347 this.stopLoadingSpinnerAnimation(); 16348 } 16349 16350 /* Stop, if there is, the timeout to start the analyzeImages. 16351 This is because an image can be set loaded, and the timeout can be set, 16352 but this image can be analyzed yet. 16353 */ 16354 this.stopImgAnalyzerStarter(); 16355 16356 //On complete callback 16357 this.$gallery.trigger(isForResize ? 'jg.resize' : 'jg.complete'); 16358 this.$gallery.height(this.galleryHeightToSet); 16359 }; 16360 16361 /** 16362 * Stops any ImgAnalyzer starter (that has an assigned timeout) 16363 */ 16364 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 16365 this.yield.flushed = 0; 16366 if (this.imgAnalyzerTimeout !== null) clearTimeout(this.imgAnalyzerTimeout); 16367 }; 16368 16369 /** 16370 * Starts the image analyzer. It is not immediately called to let the browser to update the view 16371 * 16372 * @param isForResize specifies if the image analyzer must be called for resizing or not 16373 */ 16374 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 16375 var that = this; 16376 this.stopImgAnalyzerStarter(); 16377 this.imgAnalyzerTimeout = setTimeout(function () { 16378 that.analyzeImages(isForResize); 16379 }, 0.001); // we can't start it immediately due to a IE different behaviour 16380 }; 16381 16382 /** 16383 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 16384 * because some browsers, with a 404 set complete = true. 16385 * 16386 * @param imageSrc the image src to load 16387 * @param onLoad callback that is called when the image has been loaded 16388 * @param onError callback that is called in case of an error 16389 */ 16390 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 16391 if (!onLoad && !onError) return; 16392 16393 var memImage = new Image(); 16394 var $memImage = $(memImage); 16395 if (onLoad) { 16396 $memImage.one('load', function () { 16397 $memImage.off('load error'); 16398 onLoad(memImage); 16399 }); 16400 } 16401 if (onError) { 16402 $memImage.one('error', function() { 16403 $memImage.off('load error'); 16404 onError(memImage); 16405 }); 16406 } 16407 memImage.src = imageSrc; 16408 }; 16409 16410 /** 16411 * Init of Justified Gallery controlled 16412 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 16413 */ 16414 JustifiedGallery.prototype.init = function () { 16415 var imagesToLoad = false, skippedImages = false, that = this; 16416 $.each(this.entries, function (index, entry) { 16417 var $entry = $(entry); 16418 var $image = that.imgFromEntry($entry); 16419 16420 $entry.addClass('jg-entry'); 16421 16422 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 16423 16424 // Link Rel global overwrite 16425 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 16426 16427 // Link Target global overwrite 16428 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 16429 16430 if ($image !== null) { 16431 16432 // Image src 16433 var imageSrc = that.extractImgSrcFromImage($image); 16434 $image.attr('src', imageSrc); 16435 16436 /* If we have the height and the width, we don't wait that the image is loaded, but we start directly 16437 * with the justification */ 16438 if (that.settings.waitThumbnailsLoad === false) { 16439 var width = parseFloat($image.attr('width')); 16440 var height = parseFloat($image.attr('height')); 16441 if (!isNaN(width) && !isNaN(height)) { 16442 $entry.data('jg.width', width); 16443 $entry.data('jg.height', height); 16444 $entry.data('jg.loaded', 'skipped'); 16445 skippedImages = true; 16446 that.startImgAnalyzer(false); 16447 return true; // continue 16448 } 16449 } 16450 16451 $entry.data('jg.loaded', false); 16452 imagesToLoad = true; 16453 16454 // Spinner start 16455 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 16456 16457 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 16458 $entry.data('jg.width', loadImg.width);
vendor: 10,190 bytes, lines 16459-16738
16459 $entry.data('jg.height', loadImg.height); 16460 $entry.data('jg.loaded', true); 16461 that.startImgAnalyzer(false); 16462 }, function () { // image load error 16463 $entry.data('jg.loaded', 'error'); 16464 that.startImgAnalyzer(false); 16465 }); 16466 16467 } else { 16468 $entry.data('jg.loaded', true); 16469 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 16470 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 16471 } 16472 16473 } 16474 16475 }); 16476 16477 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 16478 this.checkWidth(); 16479 }; 16480 16481 /** 16482 * Checks that it is a valid number. If a string is passed it is converted to a number 16483 * 16484 * @param settingContainer the object that contains the setting (to allow the conversion) 16485 * @param settingName the setting name 16486 */ 16487 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 16488 if ($.type(settingContainer[settingName]) === 'string') { 16489 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 16490 } 16491 16492 if ($.type(settingContainer[settingName]) === 'number') { 16493 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 16494 } else { 16495 throw settingName + ' must be a number'; 16496 } 16497 }; 16498 16499 /** 16500 * Checks the sizeRangeSuffixes and, if necessary, converts 16501 * its keys from string (e.g. old settings with 'lt100') to int. 16502 */ 16503 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 16504 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 16505 throw 'sizeRangeSuffixes must be defined and must be an object'; 16506 } 16507 16508 var suffixRanges = []; 16509 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16510 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 16511 } 16512 16513 var newSizeRngSuffixes = {0: ''}; 16514 for (var i = 0; i < suffixRanges.length; i++) { 16515 if ($.type(suffixRanges[i]) === 'string') { 16516 try { 16517 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 16518 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16519 } catch (e) { 16520 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 16521 } 16522 } else { 16523 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 16524 } 16525 } 16526 16527 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 16528 }; 16529 16530 /** 16531 * check and convert the maxRowHeight setting 16532 */ 16533 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 16534 var newMaxRowHeight = { }; 16535 16536 if ($.type(this.settings.maxRowHeight) === 'string') { 16537 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 16538 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 16539 newMaxRowHeight.isPercentage = false; 16540 } else { 16541 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight); 16542 newMaxRowHeight.isPercentage = true; 16543 } 16544 } else if ($.type(this.settings.maxRowHeight) === 'number') { 16545 newMaxRowHeight.value = this.settings.maxRowHeight; 16546 newMaxRowHeight.isPercentage = false; 16547 } else if (this.settings.maxRowHeight === false || 16548 this.settings.maxRowHeight === null || 16549 typeof this.settings.maxRowHeight == 'undefined') { 16550 return null; 16551 } else { 16552 throw 'maxRowHeight must be a number or a percentage'; 16553 } 16554 16555 // check if the converted value is not a number 16556 if (isNaN(newMaxRowHeight.value)) throw 'invalid number for maxRowHeight'; 16557 16558 // check values 16559 if (newMaxRowHeight.isPercentage) { 16560 if (newMaxRowHeight.value < 100) newMaxRowHeight.value = 100; 16561 } 16562 16563 return newMaxRowHeight; 16564 }; 16565 16566 /** 16567 * Checks the settings 16568 */ 16569 JustifiedGallery.prototype.checkSettings = function () { 16570 this.checkSizeRangesSuffixes(); 16571 16572 this.checkOrConvertNumber(this.settings, 'rowHeight'); 16573 this.checkOrConvertNumber(this.settings, 'margins'); 16574 this.checkOrConvertNumber(this.settings, 'border'); 16575 16576 var lastRowModes = [ 16577 'justify', 16578 'nojustify', 16579 'left', 16580 'center', 16581 'right', 16582 'hide' 16583 ]; 16584 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 16585 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 16586 } 16587 16588 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 16589 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 16590 throw 'justifyThreshold must be in the interval [0,1]'; 16591 } 16592 if ($.type(this.settings.cssAnimation) !== 'boolean') { 16593 throw 'cssAnimation must be a boolean'; 16594 } 16595 16596 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 16597 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 16598 16599 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 16600 if (this.settings.captionSettings.visibleOpacity < 0 || 16601 this.settings.captionSettings.visibleOpacity > 1) { 16602 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 16603 } 16604 16605 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 16606 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 16607 this.settings.captionSettings.nonVisibleOpacity > 1) { 16608 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 16609 } 16610 16611 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 16612 this.checkOrConvertNumber(this.settings, 'refreshTime'); 16613 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 16614 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 16615 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 16616 16617 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 16618 throw 'sort must be false or a comparison function'; 16619 } 16620 16621 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 16622 $.type(this.settings.filter) !== 'string') { 16623 throw 'filter must be false, a string or a filter function'; 16624 } 16625 }; 16626 16627 /** 16628 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 16629 * @returns {Array} sorted suffix ranges 16630 */ 16631 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 16632 var suffixRanges = []; 16633 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 16634 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 16635 } 16636 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 16637 return suffixRanges; 16638 }; 16639 16640 /** 16641 * Update the existing settings only changing some of them 16642 * 16643 * @param newSettings the new settings (or a subgroup of them) 16644 */ 16645 JustifiedGallery.prototype.updateSettings = function (newSettings) { 16646 // In this case Justified Gallery has been called again changing only some options 16647 this.settings = $.extend({}, this.settings, newSettings); 16648 this.checkSettings(); 16649 16650 // As reported in the settings: negative value = same as margins, 0 = disabled 16651 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 16652 16653 this.maxRowHeight = this.retrieveMaxRowHeight(); 16654 this.suffixRanges = this.retrieveSuffixRanges(); 16655 }; 16656 16657 /** 16658 * Justified Gallery plugin for jQuery 16659 * 16660 * Events 16661 * - jg.complete : called when all the gallery has been created 16662 * - jg.resize : called when the gallery has been resized 16663 * - jg.rowflush : when a new row appears 16664 * 16665 * @param arg the action (or the settings) passed when the plugin is called 16666 * @returns {*} the object itself 16667 */ 16668 $.fn.justifiedGallery = function (arg) { 16669 return this.each(function (index, gallery) { 16670 16671 var $gallery = $(gallery); 16672 $gallery.addClass('justified-gallery'); 16673 16674 var controller = $gallery.data('jg.controller'); 16675 if (typeof controller === 'undefined') { 16676 // Create controller and assign it to the object data 16677 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 16678 if (arg === 'destroy') return; // Just a call to an unexisting object 16679 throw 'The argument must be an object'; 16680 } 16681 controller = new JustifiedGallery($gallery, $.extend({}, $.fn.justifiedGallery.defaults, arg)); 16682 $gallery.data('jg.controller', controller); 16683 } else if (arg === 'norewind') { 16684 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 16685 // ... left to be more readable 16686 } else if (arg === 'destroy') { 16687 controller.destroy(); 16688 return; 16689 } else { 16690 // In this case Justified Gallery has been called again changing only some options 16691 controller.updateSettings(arg); 16692 controller.rewind(); 16693 } 16694 16695 // Update the entries list 16696 if (!controller.updateEntries(arg === 'norewind')) return; 16697 16698 // Init justified gallery 16699 controller.init(); 16700 16701 }); 16702 }; 16703 16704 // Default options 16705 $.fn.justifiedGallery.defaults = { 16706 sizeRangeSuffixes: { }, /* e.g. Flickr configuration 16707 { 16708 100: '_t', // used when longest is less than 100px 16709 240: '_m', // used when longest is between 101px and 240px 16710 320: '_n', // ... 16711 500: '', 16712 640: '_z', 16713 1024: '_b' // used as else case because it is the last 16714 } 16715 */ 16716 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 16717 path relative to a specific thumbnail size. The function should accept respectively three arguments: 16718 current path, width and height */ 16719 rowHeight: 120, 16720 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 16721 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 16722 // can't exceed 3 * rowHeight) 16723 margins: 1, 16724 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 16725 16726 lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 16727 16728 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 16729 * (i.e. lastRow setting is not considered) */ 16730 waitThumbnailsLoad: true, 16731 captions: true, 16732 cssAnimation: true, 16733 imagesAnimationDuration: 500, // ignored with css animations 16734 captionSettings: { // ignored with css animations 16735 animationDuration: 500, 16736 visibleOpacity: 0.7, 16737 nonVisibleOpacity: 0.0 16738 },
16739 rel: null, // rewrite the rel of each analyzed links 16740 target: null, // rewrite the target of all links 16741 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 16742 refreshTime: 200, // time interval (in ms) to check if the page changes its width 16743 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 16744 randomize: false, 16745 sort: false, /* 16746 - false: to do not sort 16747 - function: to sort them using the function as comparator (see Array.prototype.sort()) 16748 */ 16749 filter: false, /* 16750 - false, null or undefined: for a disabled filter 16751 - a string: an entry is kept if entry.is(filter string) returns true 16752 see jQuery's .is() function for further information 16753 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 16754 It follows the specifications of the Array.prototype.filter() function of JavaScript. 16755 */ 16756 selector: 'a, div:not(.spinner)' // The selector that is used to know what are the entries of the gallery 16757 }; 16758 16759}(jQuery)); 16760 16761/*! 16762* Customized version of iScroll.js 0.0.1 16763* It fixes bugs affecting its integration with fullpage.js 16764*/ 16765/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 16766(function (window, document, Math) { 16767var rAF = window.requestAnimationFrame || 16768 window.webkitRequestAnimationFrame || 16769 window.mozRequestAnimationFrame || 16770 window.oRequestAnimationFrame || 16771 window.msRequestAnimationFrame || 16772 function (callback) { window.setTimeout(callback, 1000 / 60); }; 16773 16774var utils = (function () { 16775 var me = {}; 16776 16777 var _elementStyle = document.createElement('div').style; 16778 var _vendor = (function () { 16779 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 16780 transform, 16781 i = 0, 16782 l = vendors.length; 16783 16784 for ( ; i < l; i++ ) { 16785 transform = vendors[i] + 'ransform'; 16786 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 16787 } 16788 16789 return false; 16790 })(); 16791 16792 function _prefixStyle (style) { 16793 if ( _vendor === false ) return false; 16794 if ( _vendor === '' ) return style; 16795 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 16796 } 16797 16798 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 16799 16800 me.extend = function (target, obj) { 16801 for ( var i in obj ) { 16802 target[i] = obj[i]; 16803 } 16804 }; 16805 16806 me.addEvent = function (el, type, fn, capture) { 16807 el.addEventListener(type, fn, !!capture); 16808 }; 16809 16810 me.removeEvent = function (el, type, fn, capture) { 16811 el.removeEventListener(type, fn, !!capture); 16812 }; 16813 16814 me.prefixPointerEvent = function (pointerEvent) { 16815 return window.MSPointerEvent ? 16816 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 16817 pointerEvent; 16818 }; 16819 16820 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 16821 var distance = current - start, 16822 speed = Math.abs(distance) / time, 16823 destination, 16824 duration; 16825 16826 deceleration = deceleration === undefined ? 0.0006 : deceleration; 16827 16828 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 16829 duration = speed / deceleration; 16830 16831 if ( destination < lowerMargin ) { 16832 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 16833 distance = Math.abs(destination - current); 16834 duration = distance / speed; 16835 } else if ( destination > 0 ) { 16836 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 16837 distance = Math.abs(current) + destination; 16838 duration = distance / speed; 16839 } 16840 16841 return { 16842 destination: Math.round(destination), 16843 duration: duration 16844 }; 16845 }; 16846 16847 var _transform = _prefixStyle('transform'); 16848 16849 me.extend(me, { 16850 hasTransform: _transform !== false, 16851 hasPerspective: _prefixStyle('perspective') in _elementStyle, 16852 hasTouch: 'ontouchstart' in window, 16853 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 16854 hasTransition: _prefixStyle('transition') in _elementStyle 16855 }); 16856 16857 /* 16858 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 16859 - galaxy S2 is ok 16860 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 16861 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16862 - galaxy S3 is badAndroid (stock brower, webview) 16863 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16864 - galaxy S4 is badAndroid (stock brower, webview) 16865 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 16866 - galaxy S5 is OK 16867 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16868 - galaxy S6 is OK 16869 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 16870 */ 16871 me.isBadAndroid = (function() { 16872 var appVersion = window.navigator.appVersion; 16873 // Android browser is not a chrome browser. 16874 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 16875 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 16876 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 16877 return parseFloat(safariVersion[1]) < 535.19; 16878 } else { 16879 return true; 16880 } 16881 } else { 16882 return false;
16883 } 16884 })(); 16885 16886 me.extend(me.style = {}, { 16887 transform: _transform, 16888 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 16889 transitionDuration: _prefixStyle('transitionDuration'), 16890 transitionDelay: _prefixStyle('transitionDelay'), 16891 transformOrigin: _prefixStyle('transformOrigin') 16892 }); 16893 16894 me.hasClass = function (e, c) { 16895 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 16896 return re.test(e.className); 16897 }; 16898 16899 me.addClass = function (e, c) { 16900 if ( me.hasClass(e, c) ) { 16901 return; 16902 } 16903 16904 var newclass = e.className.split(' '); 16905 newclass.push(c); 16906 e.className = newclass.join(' '); 16907 }; 16908 16909 me.removeClass = function (e, c) { 16910 if ( !me.hasClass(e, c) ) { 16911 return; 16912 } 16913 16914 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 16915 e.className = e.className.replace(re, ' '); 16916 }; 16917 16918 me.offset = function (el) { 16919 var left = -el.offsetLeft, 16920 top = -el.offsetTop; 16921 16922 // jshint -W084 16923 while (el = el.offsetParent) { 16924 left -= el.offsetLeft; 16925 top -= el.offsetTop; 16926 } 16927 // jshint +W084 16928 16929 return { 16930 left: left, 16931 top: top 16932 }; 16933 }; 16934 16935 me.preventDefaultException = function (el, exceptions) { 16936 for ( var i in exceptions ) { 16937 if ( exceptions[i].test(el[i]) ) { 16938 return true; 16939 } 16940 } 16941 16942 return false; 16943 }; 16944 16945 me.extend(me.eventType = {}, { 16946 touchstart: 1, 16947 touchmove: 1, 16948 touchend: 1, 16949 16950 mousedown: 2, 16951 mousemove: 2, 16952 mouseup: 2, 16953 16954 pointerdown: 3, 16955 pointermove: 3, 16956 pointerup: 3, 16957 16958 MSPointerDown: 3, 16959 MSPointerMove: 3, 16960 MSPointerUp: 3 16961 }); 16962 16963 me.extend(me.ease = {}, { 16964 quadratic: { 16965 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 16966 fn: function (k) { 16967 return k * ( 2 - k ); 16968 } 16969 }, 16970 circular: { 16971 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) 16972 fn: function (k) { 16973 return Math.sqrt( 1 - ( --k * k ) ); 16974 } 16975 }, 16976 back: { 16977 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 16978 fn: function (k) { 16979 var b = 4; 16980 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 16981 } 16982 }, 16983 bounce: { 16984 style: '', 16985 fn: function (k) { 16986 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 16987 return 7.5625 * k * k; 16988 } else if ( k < ( 2 / 2.75 ) ) { 16989 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 16990 } else if ( k < ( 2.5 / 2.75 ) ) { 16991 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 16992 } else { 16993 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 16994 } 16995 } 16996 }, 16997 elastic: { 16998 style: '', 16999 fn: function (k) { 17000 var f = 0.22, 17001 e = 0.4; 17002 17003 if ( k === 0 ) { return 0; } 17004 if ( k == 1 ) { return 1; } 17005 17006 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 17007 } 17008 } 17009 }); 17010 17011 me.tap = function (e, eventName) { 17012 var ev = document.createEvent('Event'); 17013 ev.initEvent(eventName, true, true); 17014 ev.pageX = e.pageX; 17015 ev.pageY = e.pageY; 17016 e.target.dispatchEvent(ev); 17017 }; 17018 17019 me.click = function (e) { 17020 var target = e.target, 17021 ev; 17022 17023 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 17024 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 17025 // initMouseEvent is deprecated. 17026 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 17027 ev.initEvent('click', true, true); 17028 ev.view = e.view || window; 17029 ev.detail = 1; 17030 ev.screenX = target.screenX || 0; 17031 ev.screenY = target.screenY || 0; 17032 ev.clientX = target.clientX || 0; 17033 ev.clientY = target.clientY || 0; 17034 ev.ctrlKey = !!e.ctrlKey; 17035 ev.altKey = !!e.altKey; 17036 ev.shiftKey = !!e.shiftKey; 17037 ev.metaKey = !!e.metaKey; 17038 ev.button = 0; 17039 ev.relatedTarget = null; 17040 ev._constructed = true; 17041 target.dispatchEvent(ev); 17042 } 17043 }; 17044 17045 return me; 17046})(); 17047function IScroll (el, options) { 17048 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 17049 this.scroller = this.wrapper.children[0]; 17050 this.scrollerStyle = this.scroller.style; // cache style for better performance 17051 17052 this.options = { 17053 17054 resizeScrollbars: true, 17055 17056 mouseWheelSpeed: 20, 17057 17058 snapThreshold: 0.334, 17059 17060// INSERT POINT: OPTIONS 17061 disablePointer : !utils.hasPointer, 17062 disableTouch : utils.hasPointer || !utils.hasTouch, 17063 disableMouse : utils.hasPointer || utils.hasTouch, 17064 startX: 0, 17065 startY: 0, 17066 scrollY: true, 17067 directionLockThreshold: 5, 17068 momentum: true, 17069 17070 bounce: true, 17071 bounceTime: 600, 17072 bounceEasing: '', 17073 17074 preventDefault: true, 17075 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|
17075SELECT|LABEL)$/ }, 17076 17077 HWCompositing: true, 17078 useTransition: true, 17079 useTransform: true, 17080 bindToWrapper: typeof window.onmousedown === "undefined" 17081 }; 17082 17083 for ( var i in options ) { 17084 this.options[i] = options[i]; 17085 } 17086 17087 // Normalize options 17088 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 17089 17090 this.options.useTransition = utils.hasTransition && this.options.useTransition; 17091 this.options.useTransform = utils.hasTransform && this.options.useTransform; 17092 17093 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 17094 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 17095 17096 // If you want eventPassthrough I have to lock one of the axes 17097 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 17098 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 17099 17100 // With eventPassthrough we also need lockDirection mechanism 17101 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 17102 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 17103 17104 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 17105 17106 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 17107 17108 if ( this.options.tap === true ) { 17109 this.options.tap = 'tap'; 17110 } 17111 17112 // https://github.com/cubiq/iscroll/issues/1029 17113 if (!this.options.useTransition && !this.options.useTransform) { 17114 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 17115 this.scrollerStyle.position = "relative"; 17116 } 17117 } 17118 17119 if ( this.options.shrinkScrollbars == 'scale' ) { 17120 this.options.useTransition = false; 17121 } 17122 17123 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 17124 17125// INSERT POINT: NORMALIZATION 17126 17127 // Some defaults 17128 this.x = 0; 17129 this.y = 0; 17130 this.directionX = 0; 17131 this.directionY = 0; 17132 this._events = {}; 17133 17134// INSERT POINT: DEFAULTS 17135 17136 this._init(); 17137 this.refresh(); 17138 17139 this.scrollTo(this.options.startX, this.options.startY); 17140 this.enable(); 17141} 17142 17143IScroll.prototype = { 17144 version: '5.2.0', 17145 17146 _init: function () { 17147 this._initEvents(); 17148 17149 if ( this.options.scrollbars || this.options.indicators ) { 17150 this._initIndicators(); 17151 } 17152 17153 if ( this.options.mouseWheel ) { 17154 this._initWheel(); 17155 } 17156 17157 if ( this.options.snap ) { 17158 this._initSnap(); 17159 } 17160 17161 if ( this.options.keyBindings ) { 17162 this._initKeys(); 17163 } 17164 17165// INSERT POINT: _init 17166 17167 }, 17168 17169 destroy: function () { 17170 this._initEvents(true); 17171 clearTimeout(this.resizeTimeout); 17172 this.resizeTimeout = null; 17173 this._execEvent('destroy'); 17174 }, 17175 17176 _transitionEnd: function (e) { 17177 if ( e.target != this.scroller || !this.isInTransition ) { 17178 return; 17179 } 17180 17181 this._transitionTime(); 17182 if ( !this.resetPosition(this.options.bounceTime) ) { 17183 this.isInTransition = false; 17184 this._execEvent('scrollEnd'); 17185 } 17186 }, 17187 17188 _start: function (e) { 17189 // React to left mouse button only 17190 if ( utils.eventType[e.type] != 1 ) { 17191 // for button property 17192 // http://unixpapa.com/js/mouse.html 17193 var button; 17194 if (!e.which) { 17195 /* IE case */ 17196 button = (e.button < 2) ? 0 : 17197 ((e.button == 4) ? 1 : 2); 17198 } else { 17199 /* All others */ 17200 button = e.button; 17201 } 17202 if ( button !== 0 ) { 17203 return; 17204 } 17205 } 17206 17207 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 17208 return; 17209 } 17210 17211 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17212 e.preventDefault(); 17213 } 17214 17215 var point = e.touches ? e.touches[0] : e, 17216 pos; 17217 17218 this.initiated = utils.eventType[e.type]; 17219 this.moved = false; 17220 this.distX = 0; 17221 this.distY = 0; 17222 this.directionX = 0; 17223 this.directionY = 0;
17224 this.directionLocked = 0; 17225 17226 this.startTime = utils.getTime(); 17227 17228 if ( this.options.useTransition && this.isInTransition ) { 17229 this._transitionTime(); 17230 this.isInTransition = false; 17231 pos = this.getComputedPosition(); 17232 this._translate(Math.round(pos.x), Math.round(pos.y)); 17233 this._execEvent('scrollEnd'); 17234 } else if ( !this.options.useTransition && this.isAnimating ) { 17235 this.isAnimating = false; 17236 this._execEvent('scrollEnd'); 17237 } 17238 17239 this.startX = this.x; 17240 this.startY = this.y; 17241 this.absStartX = this.x; 17242 this.absStartY = this.y; 17243 this.pointX = point.pageX; 17244 this.pointY = point.pageY; 17245 17246 this._execEvent('beforeScrollStart'); 17247 }, 17248 17249 _move: function (e) { 17250 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17251 return; 17252 } 17253 17254 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 17255 e.preventDefault(); 17256 } 17257 17258 var point = e.touches ? e.touches[0] : e, 17259 deltaX = point.pageX - this.pointX, 17260 deltaY = point.pageY - this.pointY, 17261 timestamp = utils.getTime(), 17262 newX, newY, 17263 absDistX, absDistY; 17264 17265 this.pointX = point.pageX; 17266 this.pointY = point.pageY; 17267 17268 this.distX += deltaX; 17269 this.distY += deltaY; 17270 absDistX = Math.abs(this.distX); 17271 absDistY = Math.abs(this.distY); 17272 17273 // We need to move at least 10 pixels for the scrolling to initiate 17274 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 17275 return; 17276 } 17277 17278 // If you are scrolling in one direction lock the other 17279 if ( !this.directionLocked && !this.options.freeScroll ) { 17280 if ( absDistX > absDistY + this.options.directionLockThreshold ) { 17281 this.directionLocked = 'h'; // lock horizontally 17282 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 17283 this.directionLocked = 'v'; // lock vertically 17284 } else { 17285 this.directionLocked = 'n'; // no lock 17286 } 17287 } 17288 17289 if ( this.directionLocked == 'h' ) { 17290 if ( this.options.eventPassthrough == 'vertical' ) { 17291 e.preventDefault(); 17292 } else if ( this.options.eventPassthrough == 'horizontal' ) { 17293 this.initiated = false; 17294 return; 17295 } 17296 17297 deltaY = 0; 17298 } else if ( this.directionLocked == 'v' ) { 17299 if ( this.options.eventPassthrough == 'horizontal' ) { 17300 e.preventDefault(); 17301 } else if ( this.options.eventPassthrough == 'vertical' ) { 17302 this.initiated = false; 17303 return; 17304 } 17305 17306 deltaX = 0; 17307 } 17308 17309 deltaX = this.hasHorizontalScroll ? deltaX : 0; 17310 deltaY = this.hasVerticalScroll ? deltaY : 0; 17311 17312 newX = this.x + deltaX; 17313 newY = this.y + deltaY; 17314 17315 // Slow down if outside of the boundaries 17316 if ( newX > 0 || newX < this.maxScrollX ) { 17317 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 17318 } 17319 if ( newY > 0 || newY < this.maxScrollY ) { 17320 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 17321 } 17322 17323 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 17324 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 17325 17326 if ( !this.moved ) { 17327 this._execEvent('scrollStart'); 17328 } 17329 17330 this.moved = true; 17331 17332 this._translate(newX, newY); 17333 17334/* REPLACE START: _move */ 17335 17336 if ( timestamp - this.startTime > 300 ) { 17337 this.startTime = timestamp; 17338 this.startX = this.x; 17339 this.startY = this.y; 17340 } 17341 17342/* REPLACE END: _move */ 17343 17344 }, 17345 17346 _end: function (e) { 17347 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 17348 return; 17349 } 17350 17351 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 17352 e.preventDefault(); 17353 } 17354 17355 var point = e.changedTouches ? e.changedTouches[0] : e, 17356 momentumX, 17357 momentumY, 17358 duration = utils.getTime() - this.startTime, 17359 newX = Math.round(this.x), 17360 newY = Math.round(this.y), 17361 distanceX = Math.abs(newX - this.startX), 17362 distanceY = Math.abs(newY - this.startY), 17363 time = 0, 17364 easing = ''; 17365 17366 this.isInTransition = 0; 17367 this.initiated = 0; 17368 this.endTime = utils.getTime(); 17369 17370 // reset if we are outside of the boundaries 17371 if ( this.resetPosition(this.options.bounceTime) ) { 17372 return; 17373 } 17374 17375 this.scrollTo(newX, newY); // ensures that the last position is rounded 17376 17377 // we scrolled less than 10 pixels 17378 if ( !this.moved ) { 17379 if ( this.options.tap ) { 17380 utils.tap(e, this.options.tap); 17381 } 17382 17383 if ( this.options.click ) { 17384 utils.click(e); 17385 } 17386 17387 this._execEvent('scrollCancel'); 17388 return; 17389 } 17390 17391 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 17392 this._execEvent('flick'); 17393 return; 17394 } 17395 17396 // start momentum animation if needed 17397 if ( this.options.momentum && duration < 300 ) { 17398 momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperW
17398idth : 0, this.options.deceleration) : { destination: newX, duration: 0 }; 17399 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 }; 17400 newX = momentumX.destination; 17401 newY = momentumY.destination; 17402 time = Math.max(momentumX.duration, momentumY.duration); 17403 this.isInTransition = 1; 17404 } 17405 17406 17407 if ( this.options.snap ) { 17408 var snap = this._nearestSnap(newX, newY); 17409 this.currentPage = snap; 17410 time = this.options.snapSpeed || Math.max( 17411 Math.max( 17412 Math.min(Math.abs(newX - snap.x), 1000), 17413 Math.min(Math.abs(newY - snap.y), 1000) 17414 ), 300); 17415 newX = snap.x; 17416 newY = snap.y; 17417 17418 this.directionX = 0; 17419 this.directionY = 0; 17420 easing = this.options.bounceEasing; 17421 } 17422 17423// INSERT POINT: _end 17424 17425 if ( newX != this.x || newY != this.y ) { 17426 // change easing function when scroller goes out of the boundaries 17427 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 17428 easing = utils.ease.quadratic; 17429 } 17430 17431 this.scrollTo(newX, newY, time, easing); 17432 return; 17433 } 17434 17435 this._execEvent('scrollEnd'); 17436 }, 17437 17438 _resize: function () { 17439 var that = this; 17440 17441 clearTimeout(this.resizeTimeout); 17442 17443 this.resizeTimeout = setTimeout(function () { 17444 that.refresh(); 17445 }, this.options.resizePolling); 17446 }, 17447 17448 resetPosition: function (time) { 17449 var x = this.x, 17450 y = this.y; 17451 17452 time = time || 0; 17453 17454 if ( !this.hasHorizontalScroll || this.x > 0 ) { 17455 x = 0; 17456 } else if ( this.x < this.maxScrollX ) { 17457 x = this.maxScrollX; 17458 } 17459 17460 if ( !this.hasVerticalScroll || this.y > 0 ) { 17461 y = 0; 17462 } else if ( this.y < this.maxScrollY ) { 17463 y = this.maxScrollY; 17464 } 17465 17466 if ( x == this.x && y == this.y ) { 17467 return false; 17468 } 17469 17470 this.scrollTo(x, y, time, this.options.bounceEasing); 17471 17472 return true; 17473 }, 17474 17475 disable: function () { 17476 this.enabled = false; 17477 }, 17478 17479 enable: function () { 17480 this.enabled = true; 17481 }, 17482 17483 refresh: function () { 17484 var rf = this.wrapper.offsetHeight; // Force reflow 17485 17486 this.wrapperWidth = this.wrapper.clientWidth; 17487 this.wrapperHeight = this.wrapper.clientHeight; 17488 17489/* REPLACE START: refresh */ 17490 17491 this.scrollerWidth = this.scroller.offsetWidth; 17492 this.scrollerHeight = this.scroller.offsetHeight; 17493 17494 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 17495 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 17496 17497/* REPLACE END: refresh */ 17498 17499 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 17500 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 17501 17502 if ( !this.hasHorizontalScroll ) { 17503 this.maxScrollX = 0; 17504 this.scrollerWidth = this.wrapperWidth; 17505 } 17506 17507 if ( !this.hasVerticalScroll ) { 17508 this.maxScrollY = 0; 17509 this.scrollerHeight = this.wrapperHeight; 17510 } 17511 17512 this.endTime = 0; 17513 this.directionX = 0; 17514 this.directionY = 0; 17515 17516 this.wrapperOffset = utils.offset(this.wrapper); 17517 17518 this._execEvent('refresh'); 17519 17520 this.resetPosition(); 17521 17522// INSERT POINT: _refresh 17523 17524 }, 17525 17526 on: function (type, fn) { 17527 if ( !this._events[type] ) { 17528 this._events[type] = []; 17529 } 17530 17531 this._events[type].push(fn); 17532 }, 17533 17534 off: function (type, fn) { 17535 if ( !this._events[type] ) { 17536 return; 17537 } 17538 17539 var index = this._events[type].indexOf(fn); 17540 17541 if ( index > -1 ) { 17542 this._events[type].splice(index, 1); 17543 } 17544 }, 17545 17546 _execEvent: function (type) { 17547 if ( !this._events[type] ) { 17548 return; 17549 } 17550 17551 var i = 0, 17552 l = this._events[type].length; 17553 17554 if ( !l ) { 17555 return; 17556 } 17557 17558 for ( ; i < l; i++ ) { 17559 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 17560 } 17561 }, 17562 17563 scrollBy: function (x, y, time, easing) { 17564 x = this.x + x; 17565 y = this.y + y; 17566 time = time || 0; 17567 17568 this.scrollTo(x, y, time, easing); 17569 }, 17570 17571 scrollTo: function (x, y, time, easing) { 17572 easing = easing || utils.ease.circular; 17573 17574 this.isInTransition = this.options.useTransition && time > 0; 17575 var transitionType = this.options.useTransition && easing.style; 17576 if ( !time || transitionType ) { 17577 if(transitionType) { 17578 this._transitionTimingFunction(easing.style); 17579 this._transitionTime(time); 17580 } 17581 this._translate(x, y); 17582 } else { 17583 this._animate(x, y, time, easing.fn); 17584 } 17585 }, 17586 17587 scrollToElement: function (el, time, offsetX, offsetY, easing) { 17588 el = el.nodeType ? el : this.scroller.querySelector(el); 17589 17590 if ( !el ) { 17591 return; 17592 } 17593 17594 var pos = utils.offset(el); 17595 17596 pos.left -= this.wrapperOffset.left; 17597 pos.top -= this.wrapperOffset.top; 17598 17599 // if offsetX/Y are true we center the element to the screen 17600 if ( offsetX === true ) { 17601 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 17602 } 17603 if ( offsetY === true ) { 17604 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 17605 } 17606 17607 pos.left -= offsetX || 0; 17608 pos.top -= offsetY || 0; 17609 17610 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 17611 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 17612 17613 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 17614 17615 this.scrollTo(pos.left, pos.top, time, easing); 17616 }, 17617 17618 _transitionTime: function (time) { 17619 if (!this.options.useTransition) { 17620 return; 17621 } 17622 time = time || 0; 17623 var durationProp = utils.style.transitionDuration; 17624 if(!durationProp) { 17625 return; 17626 } 17627 17628 this.scrollerStyle[durationProp] = time + 'ms'; 17629 17630 if ( !time && utils.isBadAndroid ) { 17631 this.scrollerStyle[durationProp] = '0.0001ms'; 17632 // remove 0.0001ms 17633 var self = this; 17634 rAF(function() { 17635 if(self.scrollerStyle[durationProp] === '0.0001ms') { 17636 self.scrollerStyle[durationProp] = '0s'; 17637 } 17638 }); 17639 } 17640 17641 17642 if ( this.indicators ) { 17643 for ( var i = this.indicators.length; i--; ) { 17644 this.indicators[i].transitionTime(time); 17645 } 17646 } 17647 17648 17649// INSERT POINT: _transitionTime 17650 17651 }, 17652 17653 _transitionTimingFunction: function (easing) { 17654 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 17655 17656 17657 if ( this.indicators ) { 17658 for ( var i = this.indicators.length; i--; ) { 17659 this.indicators[i].transitionTimingFunction(easing); 17660 } 17661 } 17662 17663 17664// INSERT POINT: _transitionTimingFunction 17665 17666 }, 17667 17668 _translate: function (x, y) { 17669 //Uncode addition 17670 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 17671 return false;
17672 17673 if ( this.options.useTransform ) { 17674 17675/* REPLACE START: _translate */ 17676 17677 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 17678 17679/* REPLACE END: _translate */ 17680 17681 } else { 17682 x = Math.round(x); 17683 y = Math.round(y); 17684 this.scrollerStyle.left = x + 'px'; 17685 this.scrollerStyle.top = y + 'px'; 17686 } 17687 17688 this.x = x; 17689 this.y = y; 17690 17691 17692 if ( this.indicators ) { 17693 for ( var i = this.indicators.length; i--; ) { 17694 this.indicators[i].updatePosition(); 17695 } 17696 } 17697 17698 //Uncode addition 17699 var uncodevent = new CustomEvent('fp-slide-scroll'); 17700 window.dispatchEvent(uncodevent); 17701 17702// INSERT POINT: _translate 17703 17704 }, 17705 17706 _initEvents: function (remove) { 17707 var eventType = remove ? utils.removeEvent : utils.addEvent, 17708 target = this.options.bindToWrapper ? this.wrapper : window; 17709 17710 eventType(window, 'orientationchange', this); 17711 eventType(window, 'resize', this); 17712 17713 if ( this.options.click ) { 17714 eventType(this.wrapper, 'click', this, true); 17715 } 17716 17717 if ( !this.options.disableMouse ) { 17718 eventType(this.wrapper, 'mousedown', this); 17719 eventType(target, 'mousemove', this); 17720 eventType(target, 'mousecancel', this); 17721 eventType(target, 'mouseup', this); 17722 } 17723 17724 if ( utils.hasPointer && !this.options.disablePointer ) { 17725 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 17726 eventType(target, utils.prefixPointerEvent('pointermove'), this); 17727 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 17728 eventType(target, utils.prefixPointerEvent('pointerup'), this); 17729 } 17730 17731 if ( utils.hasTouch && !this.options.disableTouch ) { 17732 eventType(this.wrapper, 'touchstart', this); 17733 eventType(target, 'touchmove', this); 17734 eventType(target, 'touchcancel', this); 17735 eventType(target, 'touchend', this); 17736 } 17737 17738 eventType(this.scroller, 'transitionend', this); 17739 eventType(this.scroller, 'webkitTransitionEnd', this); 17740 eventType(this.scroller, 'oTransitionEnd', this); 17741 eventType(this.scroller, 'MSTransitionEnd', this); 17742 }, 17743 17744 getComputedPosition: function () { 17745 var matrix = window.getComputedStyle(this.scroller, null), 17746 x, y; 17747 17748 if ( this.options.useTransform ) { 17749 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 17750 x = +(matrix[12] || matrix[4]); 17751 y = +(matrix[13] || matrix[5]); 17752 } else { 17753 x = +matrix.left.replace(/[^-\d.]/g, ''); 17754 y = +matrix.top.replace(/[^-\d.]/g, ''); 17755 } 17756 17757 return { x: x, y: y }; 17758 }, 17759 _initIndicators: function () { 17760 var interactive = this.options.interactiveScrollbars, 17761 customStyle = typeof this.options.scrollbars != 'string', 17762 indicators = [], 17763 indicator; 17764 17765 var that = this; 17766 17767 this.indicators = []; 17768 17769 if ( this.options.scrollbars ) { 17770 // Vertical scrollbar 17771 if ( this.options.scrollY ) { 17772 indicator = { 17773 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 17774 interactive: interactive, 17775 defaultScrollbars: true, 17776 customStyle: customStyle, 17777 resize: this.options.resizeScrollbars, 17778 shrink: this.options.shrinkScrollbars, 17779 fade: this.options.fadeScrollbars, 17780 listenX: false 17781 }; 17782 17783 this.wrapper.appendChild(indicator.el); 17784 indicators.push(indicator); 17785 } 17786 17787 // Horizontal scrollbar 17788 if ( this.options.scrollX ) { 17789 indicator = { 17790 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 17791 interactive: interactive, 17792 defaultScrollbars: true, 17793 customStyle: customStyle, 17794 resize: this.options.resizeScrollbars, 17795 shrink: this.options.shrinkScrollbars, 17796 fade: this.options.fadeScrollbars, 17797 listenY: false 17798 }; 17799 17800 this.wrapper.appendChild(indicator.el); 17801 indicators.push(indicator); 17802 } 17803 } 17804 17805 if ( this.options.indicators ) { 17806 // TODO: check concat compatibility 17807 indicators = indicators.concat(this.options.indicators); 17808 } 17809 17810 for ( var i = indicators.length; i--; ) { 17811 this.indicators.push( new Indicator(this, indicators[i]) ); 17812 } 17813 17814 // TODO: check if we can use array.map (wide compatibility and performance issues) 17815 function _indicatorsMap (fn) { 17816 if (that.indicators) { 17817 for ( var i = that.indicators.length; i--; ) { 17818 fn.call(that.indicators[i]); 17819 } 17820 } 17821 } 17822 17823 if ( this.options.fadeScrollbars ) { 17824 this.on('scrollEnd', function () { 17825 _indicatorsMap(function () { 17826 this.fade(); 17827 }); 17828 }); 17829 17830 this.on('scrollCancel', function () { 17831 _indicatorsMap(function () { 17832 this.fade(); 17833 }); 17834 }); 17835 17836 this.on('scrollStart', function () { 17837 _indicatorsMap(function () { 17838 this.fade(1); 17839 }); 17840 }); 17841 17842 this.on('beforeScrollStart', function () { 17843 _indicatorsMap(function () { 17844 this.fade(1, true); 17845 }); 17846 }); 17847 } 17848 17849 17850 this.on('refresh', function () { 17851 _indicatorsMap(function () { 17852 this.refresh(); 17853 }); 17854 }); 17855 17856 this.on('destroy', function () { 17857 _indicatorsMap(function () { 17858 this.destroy(); 17859 }); 17860 17861 delete this.indicators; 17862 }); 17863 }, 17864 17865 _initWheel: function () { 17866 utils.addEvent(this.wrapper, 'wheel', this); 17867 utils.addEvent(this.wrapper, 'mousewheel', this); 17868 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 17869 17870 this.on('destroy', function () { 17871 clearTimeout(this.wheelTimeout); 17872 this.wheelTimeout = null; 17873 utils.removeEvent(this.wrapper, 'wheel', this); 17874 utils.removeEvent(this.wrapper, 'mousewheel', this); 17875 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 17876 }); 17877 }, 17878 17879 _wheel: function (e) { 17880 if ( !this.enabled ) { 17881 return; 17882 } 17883 17884 var wheelDeltaX, wheelDeltaY, 17885 newX, newY, 17886 that = this; 17887 17888 if ( this.wheelTimeout === undefined ) { 17889 that._execEvent('scrollStart'); 17890 } 17891 17892 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 17893 clearTimeout(this.wheelTimeout); 17894 this.wheelTimeout = setTimeout(function () { 17895 if(!that.options.snap) { 17896 that._execEvent('scrollEnd'); 17897 } 17898 that.wheelTimeout = undefined; 17899 }, 400); 17900 17901 if ( 'deltaX' in e ) { 17902 if (e.deltaMode === 1) { 17903 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 17904 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 17905 } else { 17906 wheelDeltaX = -e.deltaX; 17907 wheelDeltaY = -e.deltaY; 17908 } 17909 } else if ( 'wheelDeltaX' in e ) { 17910 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 17911 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 17912 } else if ( 'wheelDelta' in e ) { 17913 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 17914 } else if ( 'detail' in e ) { 17915 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 17916 } else { 17917 return; 17918 } 17919 17920 wheelDeltaX *= this.options.invertWheelDirection; 17921 wheelDeltaY *= this.options.invertWheelDirection; 17922 17923 if ( !this.hasVerticalScroll ) { 17924 wheelDeltaX = wheelDeltaY; 17925 wheelDeltaY = 0; 17926 } 17927 17928 if ( this.options.snap ) { 17929 newX = this.currentPage.pageX; 17930 newY = this.currentPage.pageY; 17931 17932 if ( wheelDeltaX > 0 ) { 17933 newX--; 17934 } else if ( wheelDeltaX < 0 ) { 17935 newX++; 17936 } 17937 17938 if ( wheelDeltaY > 0 ) { 17939 newY--; 17940 } else if ( wheelDeltaY < 0 ) { 17941 newY++; 17942 } 17943 17944 this.goToPage(newX, newY); 17945 17946 return; 17947 } 17948 17949 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 17950 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 17951 17952 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 17953 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 17954 17955 if ( newX > 0 ) { 17956 newX = 0; 17957 } else if ( newX < this.maxScrollX ) { 17958 newX = this.maxScrollX; 17959 } 17960 17961 if ( newY > 0 ) { 17962 newY = 0; 17963 } else if ( newY < this.maxScrollY ) { 17964 newY = this.maxScrollY; 17965 } 17966 17967 this.scrollTo(newX, newY, 0); 17968 17969// INSERT POINT: _wheel 17970 }, 17971 17972 _initSnap: function () { 17973 this.currentPage = {}; 17974 17975 if ( typeof this.options.snap == 'string' ) { 17976 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 17977 } 17978 17979 this.on('refresh', function () { 17980 var i = 0, l, 17981 m = 0, n, 17982 cx, cy, 17983 x = 0, y,
17984 stepX = this.options.snapStepX || this.wrapperWidth, 17985 stepY = this.options.snapStepY || this.wrapperHeight, 17986 el; 17987 17988 this.pages = []; 17989 17990 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 17991 return; 17992 } 17993 17994 if ( this.options.snap === true ) { 17995 cx = Math.round( stepX / 2 ); 17996 cy = Math.round( stepY / 2 ); 17997 17998 while ( x > -this.scrollerWidth ) { 17999 this.pages[i] = []; 18000 l = 0; 18001 y = 0; 18002 18003 while ( y > -this.scrollerHeight ) { 18004 this.pages[i][l] = { 18005 x: Math.max(x, this.maxScrollX), 18006 y: Math.max(y, this.maxScrollY), 18007 width: stepX, 18008 height: stepY, 18009 cx: x - cx, 18010 cy: y - cy 18011 }; 18012 18013 y -= stepY; 18014 l++; 18015 } 18016 18017 x -= stepX; 18018 i++; 18019 } 18020 } else { 18021 el = this.options.snap; 18022 l = el.length; 18023 n = -1; 18024 18025 for ( ; i < l; i++ ) { 18026 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 18027 m = 0; 18028 n++; 18029 } 18030 18031 if ( !this.pages[m] ) { 18032 this.pages[m] = []; 18033 } 18034 18035 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 18036 y = Math.max(-el[i].offsetTop, this.maxScrollY); 18037 cx = x - Math.round(el[i].offsetWidth / 2); 18038 cy = y - Math.round(el[i].offsetHeight / 2); 18039 18040 this.pages[m][n] = { 18041 x: x, 18042 y: y, 18043 width: el[i].offsetWidth, 18044 height: el[i].offsetHeight, 18045 cx: cx, 18046 cy: cy 18047 }; 18048 18049 if ( x > this.maxScrollX ) { 18050 m++; 18051 } 18052 } 18053 } 18054 18055 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 18056 18057 // Update snap threshold if needed 18058 if ( this.options.snapThreshold % 1 === 0 ) { 18059 this.snapThresholdX = this.options.snapThreshold; 18060 this.snapThresholdY = this.options.snapThreshold; 18061 } else { 18062 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 18063 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 18064 } 18065 }); 18066 18067 this.on('flick', function () { 18068 var time = this.options.snapSpeed || Math.max( 18069 Math.max( 18070 Math.min(Math.abs(this.x - this.startX), 1000), 18071 Math.min(Math.abs(this.y - this.startY), 1000) 18072 ), 300); 18073 18074 this.goToPage( 18075 this.currentPage.pageX + this.directionX, 18076 this.currentPage.pageY + this.directionY, 18077 time 18078 ); 18079 }); 18080 }, 18081 18082 _nearestSnap: function (x, y) { 18083 if ( !this.pages.length ) { 18084 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 18085 } 18086 18087 var i = 0, 18088 l = this.pages.length, 18089 m = 0; 18090 18091 // Check if we exceeded the snap threshold 18092 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 18093 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 18094 return this.currentPage; 18095 } 18096 18097 if ( x > 0 ) { 18098 x = 0; 18099 } else if ( x < this.maxScrollX ) { 18100 x = this.maxScrollX; 18101 } 18102 18103 if ( y > 0 ) { 18104 y = 0; 18105 } else if ( y < this.maxScrollY ) { 18106 y = this.maxScrollY; 18107 } 18108 18109 for ( ; i < l; i++ ) { 18110 if ( x >= this.pages[i][0].cx ) { 18111 x = this.pages[i][0].x; 18112 break; 18113 } 18114 } 18115 18116 l = this.pages[i].length; 18117 18118 for ( ; m < l; m++ ) { 18119 if ( y >= this.pages[0][m].cy ) { 18120 y = this.pages[0][m].y; 18121 break; 18122 } 18123 } 18124 18125 if ( i == this.currentPage.pageX ) { 18126 i += this.directionX; 18127 18128 if ( i < 0 ) { 18129 i = 0; 18130 } else if ( i >= this.pages.length ) { 18131 i = this.pages.length - 1; 18132 } 18133 18134 x = this.pages[i][0].x; 18135 } 18136 18137 if ( m == this.currentPage.pageY ) { 18138 m += this.directionY; 18139 18140 if ( m < 0 ) { 18141 m = 0; 18142 } else if ( m >= this.pages[0].length ) { 18143 m = this.pages[0].length - 1; 18144 } 18145 18146 y = this.pages[0][m].y; 18147 } 18148 18149 return { 18150 x: x, 18151 y: y, 18152 pageX: i, 18153 pageY: m 18154 }; 18155 }, 18156 18157 goToPage: function (x, y, time, easing) { 18158 easing = easing || this.options.bounceEasing; 18159 18160 if ( x >= this.pages.length ) { 18161 x = this.pages.length - 1; 18162 } else if ( x < 0 ) { 18163 x = 0; 18164 } 18165 18166 if ( y >= this.pages[x].length ) { 18167 y = this.pages[x].length - 1; 18168 } else if ( y < 0 ) { 18169 y = 0; 18170 } 18171 18172 var posX = this.pages[x][y].x, 18173 posY = this.pages[x][y].y; 18174 18175 time = time === undefined ? this.options.snapSpeed || Math.max( 18176 Math.max( 18177 Math.min(Math.abs(posX - this.x), 1000), 18178 Math.min(Math.abs(posY - this.y), 1000) 18179 ), 300) : time; 18180 18181 this.currentPage = { 18182 x: posX, 18183 y: posY, 18184 pageX: x, 18185 pageY: y 18186 }; 18187 18188 this.scrollTo(posX, posY, time, easing); 18189 }, 18190 18191 next: function (time, easing) { 18192 var x = this.currentPage.pageX, 18193 y = this.currentPage.pageY; 18194 18195 x++; 18196 18197 if ( x >= this.pages.length && this.hasVerticalScroll ) { 18198 x = 0; 18199 y++; 18200 } 18201 18202 this.goToPage(x, y, time, easing); 18203 }, 18204 18205 prev: function (time, easing) { 18206 var x = this.currentPage.pageX, 18207 y = this.currentPage.pageY; 18208 18209 x--; 18210 18211 if ( x < 0 && this.hasVerticalScroll ) { 18212 x = 0; 18213 y--; 18214 } 18215 18216 this.goToPage(x, y, time, easing); 18217 }, 18218 18219 _initKeys: function (e) { 18220 // default key bindings 18221 var keys = { 18222 pageUp: 33, 18223 pageDown: 34, 18224 end: 35, 18225 home: 36, 18226 left: 37, 18227 up: 38, 18228 right: 39, 18229 down: 40 18230 }; 18231 var i; 18232 18233 // if you give me characters I give you keycode 18234 if ( typeof this.options.keyBindings == 'object' ) { 18235 for ( i in this.options.keyBindings ) { 18236 if ( typeof this.options.keyBindings[i] == 'string' ) { 18237 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
18237deAt(0); 18238 } 18239 } 18240 } else { 18241 this.options.keyBindings = {}; 18242 } 18243 18244 for ( i in keys ) { 18245 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 18246 } 18247 18248 utils.addEvent(window, 'keydown', this); 18249 18250 this.on('destroy', function () { 18251 utils.removeEvent(window, 'keydown', this); 18252 }); 18253 }, 18254 18255 _key: function (e) { 18256 if ( !this.enabled ) { 18257 return; 18258 } 18259 18260 var snap = this.options.snap, // we are using this alot, better to cache it 18261 newX = snap ? this.currentPage.pageX : this.x, 18262 newY = snap ? this.currentPage.pageY : this.y, 18263 now = utils.getTime(), 18264 prevTime = this.keyTime || 0, 18265 acceleration = 0.250, 18266 pos; 18267 18268 if ( this.options.useTransition && this.isInTransition ) { 18269 pos = this.getComputedPosition(); 18270 18271 this._translate(Math.round(pos.x), Math.round(pos.y)); 18272 this.isInTransition = false; 18273 } 18274 18275 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 18276 18277 switch ( e.keyCode ) { 18278 case this.options.keyBindings.pageUp: 18279 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18280 newX += snap ? 1 : this.wrapperWidth; 18281 } else { 18282 newY += snap ? 1 : this.wrapperHeight; 18283 } 18284 break; 18285 case this.options.keyBindings.pageDown: 18286 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 18287 newX -= snap ? 1 : this.wrapperWidth; 18288 } else { 18289 newY -= snap ? 1 : this.wrapperHeight; 18290 } 18291 break; 18292 case this.options.keyBindings.end: 18293 newX = snap ? this.pages.length-1 : this.maxScrollX; 18294 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 18295 break; 18296 case this.options.keyBindings.home: 18297 newX = 0; 18298 newY = 0; 18299 break; 18300 case this.options.keyBindings.left: 18301 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 18302 break; 18303 case this.options.keyBindings.up: 18304 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 18305 break; 18306 case this.options.keyBindings.right: 18307 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 18308 break; 18309 case this.options.keyBindings.down: 18310 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 18311 break; 18312 default: 18313 return; 18314 } 18315 18316 if ( snap ) { 18317 this.goToPage(newX, newY); 18318 return; 18319 } 18320 18321 if ( newX > 0 ) { 18322 newX = 0; 18323 this.keyAcceleration = 0; 18324 } else if ( newX < this.maxScrollX ) { 18325 newX = this.maxScrollX; 18326 this.keyAcceleration = 0; 18327 } 18328 18329 if ( newY > 0 ) { 18330 newY = 0; 18331 this.keyAcceleration = 0; 18332 } else if ( newY < this.maxScrollY ) { 18333 newY = this.maxScrollY; 18334 this.keyAcceleration = 0; 18335 } 18336 18337 this.scrollTo(newX, newY, 0); 18338 18339 this.keyTime = now; 18340 }, 18341 18342 _animate: function (destX, destY, duration, easingFn) { 18343 var that = this, 18344 startX = this.x, 18345 startY = this.y, 18346 startTime = utils.getTime(), 18347 destTime = startTime + duration; 18348 18349 function step () { 18350 var now = utils.getTime(), 18351 newX, newY, 18352 easing; 18353 18354 if ( now >= destTime ) { 18355 that.isAnimating = false; 18356 that._translate(destX, destY); 18357 18358 if ( !that.resetPosition(that.options.bounceTime) ) { 18359 that._execEvent('scrollEnd'); 18360 } 18361 18362 return; 18363 } 18364 18365 now = ( now - startTime ) / duration; 18366 easing = easingFn(now); 18367 newX = ( destX - startX ) * easing + startX; 18368 newY = ( destY - startY ) * easing + startY; 18369 that._translate(newX, newY); 18370 18371 if ( that.isAnimating ) { 18372 rAF(step); 18373 } 18374 } 18375 18376 this.isAnimating = true; 18377 step(); 18378 }, 18379 handleEvent: function (e) { 18380 switch ( e.type ) { 18381 case 'touchstart': 18382 case 'pointerdown': 18383 case 'MSPointerDown': 18384 case 'mousedown': 18385 this._start(e); 18386 break; 18387 case 'touchmove': 18388 case 'pointermove': 18389 case 'MSPointerMove': 18390 case 'mousemove': 18391 this._move(e); 18392 break; 18393 case 'touchend': 18394 case 'pointerup': 18395 case 'MSPointerUp': 18396 case 'mouseup': 18397 case 'touchcancel': 18398 case 'pointercancel': 18399 case 'MSPointerCancel': 18400 case 'mousecancel': 18401 this._end(e); 18402 break; 18403 case 'orientationchange': 18404 case 'resize': 18405 this._resize(); 18406 break; 18407 case 'transitionend': 18408 case 'webkitTransitionEnd': 18409 case 'oTransitionEnd': 18410 case 'MSTransitionEnd': 18411 this._transitionEnd(e); 18412 break; 18413 case 'wheel': 18414 case 'DOMMouseScroll': 18415 case 'mousewheel': 18416 this._wheel(e); 18417 break; 18418 case 'keydown': 18419 this._key(e); 18420 break; 18421 case 'click': 18422 if ( this.enabled && !e._constructed ) { 18423 e.preventDefault(); 18424 e.stopPropagation(); 18425 } 18426 break; 18427 } 18428 } 18429}; 18430function createDefaultScrollbar (direction, interactive, type) { 18431 var scrollbar = document.createElement('div'), 18432 indicator = document.createElement('div'); 18433 18434 if ( type === true ) { 18435 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 18436 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'; 18437 } 18438 18439 indicator.className = 'iScrollIndicator'; 18440 18441 if ( direction == 'h' ) { 18442 if ( type === true ) { 18443 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 18444 indicator.style.height = '100%'; 18445 } 18446 scrollbar.className = 'iScrollHorizontalScrollbar'; 18447 } else { 18448 if ( type === true ) { 18449 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 18450 indicator.style.width = '100%'; 18451 } 18452 scrollbar.className = 'iScrollVerticalScrollbar'; 18453 } 18454 18455 scrollbar.style.cssText += ';overflow:hidden'; 18456 18457 if ( !interactive ) { 18458 scrollbar.style.pointerEvents = 'none'; 18459 } 18460 18461 scrollbar.appendChild(indicator); 18462 18463 return scrollbar; 18464} 18465 18466function Indicator (scroller, options) { 18467 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 18468 this.wrapperStyle = this.wrapper.style; 18469 this.indicator = this.wrapper.children[0]; 18470 this.indicatorStyle = this.indicator.style; 18471 this.scroller = scroller; 18472 18473 this.options = { 18474 listenX: true, 18475 listenY: true, 18476 interactive: false, 18477 resize: true, 18478 defaultScrollbars: false, 18479 shrink: false, 18480 fade: false, 18481 speedRatioX: 0, 18482 speedRatioY: 0 18483 }; 18484 18485 for ( var i in options ) { 18486 this.options[i] = options[i]; 18487 } 18488 18489 this.sizeRatioX = 1; 18490 this.sizeRatioY = 1; 18491 this.maxPosX = 0; 18492 this.maxPosY = 0; 18493 18494 if ( this.options.interactive ) { 18495 if ( !this.options.disableTouch ) { 18496 utils.addEvent(this.indicator, 'touchstart', this); 18497 utils.addEvent(window, 'touchend', this); 18498 } 18499 if ( !this.options.disablePointer ) { 18500 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18501 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 18502 } 18503 if ( !this.options.disableMouse ) { 18504 utils.addEvent(this.indicator, 'mousedown', this); 18505 utils.addEvent(window, 'mouseup', this); 18506 } 18507 } 18508 18509 if ( this.options.fade ) { 18510 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 18511 var durationProp = utils.style.transitionDuration; 18512 if(!durationProp) { 18513 return; 18514 } 18515 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 18516 // remove 0.0001ms 18517 var self = this; 18518 if(utils.isBadAndroid) { 18519 rAF(function() { 18520 if(self.wrapperStyle[durationProp] === '0.0001ms') { 18521 self.wrapperStyle[durationProp] = '0s'; 18522 } 18523 }); 18524 } 18525 this.wrapperStyle.opacity = '0'; 18526 } 18527} 18528 18529Indicator.prototype = { 18530 handleEvent: function (e) { 18531 switch ( e.type ) { 18532 case 'touchstart': 18533 case 'pointerdown': 18534 case 'MSPointerDown': 18535 case 'mousedown': 18536 this._start(e); 18537 break; 18538 case 'touchmove': 18539 case 'pointermove': 18540 case 'MSPointerMove': 18541 case 'mousemove': 18542 this._move(e); 18543 break; 18544 case 'touchend': 18545 case 'pointerup': 18546 case 'MSPointerUp': 18547 case 'mouseup': 18548 case 'touchcancel': 18549 case 'pointercancel': 18550 case 'MSPointerCancel': 18551 case 'mousecancel': 18552 this._end(e); 18553 break; 18554 } 18555 }, 18556 18557 destroy: function () { 18558 if ( this.options.fadeScrollbars ) { 18559 clearTimeout(this.fadeTimeout); 18560 this.fadeTimeout = null; 18561 } 18562 if ( this.options.interactive ) { 18563 utils.removeEvent(this.indicator, 'touchstart', this); 18564 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 18565 utils.removeEvent(this.indicator, 'mousedown', this); 18566 18567 utils.removeEvent(window, 'touchmove', this); 18568 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18569 utils.removeEvent(window, 'mousemove', this); 18570 18571 utils.removeEvent(window, 'touchend', this); 18572 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 18573 utils.removeEvent(window, 'mouseup', this); 18574 } 18575 18576 if ( this.options.defaultScrollbars ) { 18577 this.wrapper.parentNode.removeChild(this.wrapper); 18578 } 18579 }, 18580 18581 _start: function (e) { 18582 var point = e.touches ? e.touches[0] : e; 18583 18584 e.preventDefault(); 18585 e.stopPropagation(); 18586 18587 this.transitionTime(); 18588 18589 this.initiated = true; 18590 this.moved = false;
18591 this.lastPointX = point.pageX; 18592 this.lastPointY = point.pageY; 18593 18594 this.startTime = utils.getTime(); 18595 18596 if ( !this.options.disableTouch ) { 18597 utils.addEvent(window, 'touchmove', this); 18598 } 18599 if ( !this.options.disablePointer ) { 18600 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 18601 } 18602 if ( !this.options.disableMouse ) { 18603 utils.addEvent(window, 'mousemove', this); 18604 } 18605 18606 this.scroller._execEvent('beforeScrollStart'); 18607 }, 18608 18609 _move: function (e) { 18610 var point = e.touches ? e.touches[0] : e, 18611 deltaX, deltaY, 18612 newX, newY, 18613 timestamp = utils.getTime(); 18614 18615 if ( !this.moved ) { 18616 this.scroller._execEvent('scrollStart'); 18617 } 18618 18619 this.moved = true; 18620 18621 deltaX = point.pageX - this.lastPointX; 18622 this.lastPointX = point.pageX; 18623 18624 deltaY = point.pageY - this.lastPointY; 18625 this.lastPointY = point.pageY; 18626 18627 newX = this.x + deltaX; 18628 newY = this.y + deltaY; 18629 18630 this._pos(newX, newY); 18631 18632// INSERT POINT: indicator._move 18633 18634 e.preventDefault(); 18635 e.stopPropagation(); 18636 }, 18637 18638 _end: function (e) { 18639 if ( !this.initiated ) { 18640 return; 18641 } 18642 18643 this.initiated = false; 18644 18645 e.preventDefault(); 18646 e.stopPropagation(); 18647 18648 utils.removeEvent(window, 'touchmove', this); 18649 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 18650 utils.removeEvent(window, 'mousemove', this); 18651 18652 if ( this.scroller.options.snap ) { 18653 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 18654 18655 var time = this.options.snapSpeed || Math.max( 18656 Math.max( 18657 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 18658 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 18659 ), 300); 18660 18661 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 18662 this.scroller.directionX = 0; 18663 this.scroller.directionY = 0; 18664 this.scroller.currentPage = snap; 18665 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 18666 } 18667 } 18668 18669 if ( this.moved ) { 18670 this.scroller._execEvent('scrollEnd'); 18671 } 18672 }, 18673 18674 transitionTime: function (time) { 18675 time = time || 0; 18676 var durationProp = utils.style.transitionDuration; 18677 if(!durationProp) { 18678 return; 18679 } 18680 18681 this.indicatorStyle[durationProp] = time + 'ms'; 18682 18683 if ( !time && utils.isBadAndroid ) { 18684 this.indicatorStyle[durationProp] = '0.0001ms'; 18685 // remove 0.0001ms 18686 var self = this; 18687 rAF(function() { 18688 if(self.indicatorStyle[durationProp] === '0.0001ms') { 18689 self.indicatorStyle[durationProp] = '0s'; 18690 } 18691 }); 18692 } 18693 }, 18694 18695 transitionTimingFunction: function (easing) { 18696 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 18697 }, 18698 18699 refresh: function () { 18700 this.transitionTime(); 18701 18702 if ( this.options.listenX && !this.options.listenY ) { 18703 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 18704 } else if ( this.options.listenY && !this.options.listenX ) { 18705 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 18706 } else { 18707 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 18708 } 18709 18710 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 18711 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 18712 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 18713 18714 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18715 if ( this.options.listenX ) { 18716 this.wrapper.style.right = '8px'; 18717 } else { 18718 this.wrapper.style.bottom = '8px'; 18719 } 18720 } 18721 } else { 18722 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 18723 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 18724 18725 if ( this.options.defaultScrollbars && this.options.customStyle ) { 18726 if ( this.options.listenX ) { 18727 this.wrapper.style.right = '2px'; 18728 } else { 18729 this.wrapper.style.bottom = '2px'; 18730 } 18731 } 18732 } 18733 18734 var r = this.wrapper.offsetHeight; // force refresh 18735 18736 if ( this.options.listenX ) {
18737 this.wrapperWidth = this.wrapper.clientWidth; 18738 if ( this.options.resize ) { 18739 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 18740 this.indicatorStyle.width = this.indicatorWidth + 'px'; 18741 } else { 18742 this.indicatorWidth = this.indicator.clientWidth; 18743 } 18744 18745 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 18746 18747 if ( this.options.shrink == 'clip' ) { 18748 this.minBoundaryX = -this.indicatorWidth + 8; 18749 this.maxBoundaryX = this.wrapperWidth - 8; 18750 } else { 18751 this.minBoundaryX = 0; 18752 this.maxBoundaryX = this.maxPosX; 18753 } 18754 18755 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 18756 } 18757 18758 if ( this.options.listenY ) { 18759 this.wrapperHeight = this.wrapper.clientHeight; 18760 if ( this.options.resize ) { 18761 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 18762 this.indicatorStyle.height = this.indicatorHeight + 'px'; 18763 } else { 18764 this.indicatorHeight = this.indicator.clientHeight; 18765 } 18766 18767 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18768 18769 if ( this.options.shrink == 'clip' ) { 18770 this.minBoundaryY = -this.indicatorHeight + 8; 18771 this.maxBoundaryY = this.wrapperHeight - 8; 18772 } else { 18773 this.minBoundaryY = 0; 18774 this.maxBoundaryY = this.maxPosY; 18775 } 18776 18777 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 18778 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 18779 } 18780 18781 this.updatePosition(); 18782 }, 18783 18784 updatePosition: function () { 18785 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 18786 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 18787 18788 if ( !this.options.ignoreBoundaries ) { 18789 if ( x < this.minBoundaryX ) { 18790 if ( this.options.shrink == 'scale' ) { 18791 this.width = Math.max(this.indicatorWidth + x, 8); 18792 this.indicatorStyle.width = this.width + 'px'; 18793 } 18794 x = this.minBoundaryX; 18795 } else if ( x > this.maxBoundaryX ) { 18796 if ( this.options.shrink == 'scale' ) { 18797 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 18798 this.indicatorStyle.width = this.width + 'px'; 18799 x = this.maxPosX + this.indicatorWidth - this.width; 18800 } else { 18801 x = this.maxBoundaryX; 18802 } 18803 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 18804 this.width = this.indicatorWidth; 18805 this.indicatorStyle.width = this.width + 'px'; 18806 } 18807 18808 if ( y < this.minBoundaryY ) { 18809 if ( this.options.shrink == 'scale' ) { 18810 this.height = Math.max(this.indicatorHeight + y * 3, 8); 18811 this.indicatorStyle.height = this.height + 'px'; 18812 } 18813 y = this.minBoundaryY; 18814 } else if ( y > this.maxBoundaryY ) { 18815 if ( this.options.shrink == 'scale' ) { 18816 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 18817 this.indicatorStyle.height = this.height + 'px'; 18818 y = this.maxPosY + this.indicatorHeight - this.height; 18819 } else { 18820 y = this.maxBoundaryY; 18821 } 18822 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 18823 this.height = this.indicatorHeight; 18824 this.indicatorStyle.height = this.height + 'px'; 18825 } 18826 } 18827 18828 this.x = x; 18829 this.y = y; 18830 18831 if ( this.scroller.options.useTransform ) { 18832 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 18833 } else { 18834 this.indicatorStyle.left = x + 'px'; 18835 this.indicatorStyle.top = y + 'px'; 18836 } 18837 }, 18838 18839 _pos: function (x, y) { 18840 if ( x < 0 ) { 18841 x = 0; 18842 } else if ( x > this.maxPosX ) { 18843 x = this.maxPosX; 18844 } 18845 18846 if ( y < 0 ) { 18847 y = 0; 18848 } else if ( y > this.maxPosY ) { 18849 y = this.maxPosY;
18850 } 18851 18852 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 18853 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 18854 18855 this.scroller.scrollTo(x, y); 18856 }, 18857 18858 fade: function (val, hold) { 18859 if ( hold && !this.visible ) { 18860 return; 18861 } 18862 18863 clearTimeout(this.fadeTimeout); 18864 this.fadeTimeout = null; 18865 18866 var time = val ? 250 : 500, 18867 delay = val ? 0 : 300; 18868 18869 val = val ? '1' : '0'; 18870 18871 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 18872 18873 this.fadeTimeout = setTimeout((function (val) { 18874 this.wrapperStyle.opacity = val; 18875 this.visible = +val; 18876 }).bind(this, val), delay); 18877 } 18878}; 18879 18880IScroll.utils = utils; 18881 18882if ( typeof module != 'undefined' && module.exports ) { 18883 module.exports = IScroll; 18884} else if ( typeof define == 'function' && define.amd ) { 18885 define( function () { return IScroll; } ); 18886} else { 18887 window.IScroll = IScroll; 18888} 18889 18890})(window, document, Math); 18891/*! 18892 * fullPage 2.9.4 18893 * https://github.com/alvarotrigo/fullPage.js 18894 * @license MIT licensed 18895 * 18896 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 18897 */ 18898(function(global, factory) { 18899 'use strict'; 18900 if (typeof define === 'function' && define.amd) { 18901 define(['jquery'], function($) { 18902 return factory($, global, global.document, global.Math); 18903 }); 18904 } else if (typeof exports === "object" && exports) { 18905 module.exports = factory(require('jquery'), global, global.document, global.Math); 18906 } else { 18907 factory(jQuery, global, global.document, global.Math); 18908 } 18909})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 18910 'use strict'; 18911 18912 // keeping central set of classnames and selectors 18913 var WRAPPER = 'fullpage-wrapper'; 18914 var WRAPPER_SEL = '.' + WRAPPER; 18915 18916 // slimscroll 18917 var SCROLLABLE = 'fp-scrollable'; 18918 var SCROLLABLE_SEL = '.' + SCROLLABLE; 18919 18920 // util 18921 var RESPONSIVE = 'fp-responsive'; 18922 var NO_TRANSITION = 'fp-notransition'; 18923 var DESTROYED = 'fp-destroyed'; 18924 var ENABLED = 'fp-enabled'; 18925 var VIEWING_PREFIX = 'fp-viewing'; 18926 var ACTIVE = 'active'; 18927 var ACTIVE_SEL = '.' + ACTIVE; 18928 var COMPLETELY = 'fp-completely'; 18929 var COMPLETELY_SEL = '.' + COMPLETELY; 18930 18931 // section 18932 var SECTION_DEFAULT_SEL = '.section'; 18933 var SECTION = 'fp-section'; 18934 var SECTION_SEL = '.' + SECTION; 18935 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 18936 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 18937 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 18938 var TABLE_CELL = 'fp-tableCell'; 18939 var TABLE_CELL_SEL = '.' + TABLE_CELL; 18940 var AUTO_HEIGHT = 'fp-auto-height'; 18941 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 18942 var NORMAL_SCROLL = 'fp-normal-scroll'; 18943 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 18944 18945 // section nav 18946 var SECTION_NAV = 'fp-nav'; 18947 var SECTION_NAV_SEL = '#' + SECTION_NAV; 18948 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 18949 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 18950 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 18951 18952 // slide 18953 var SLIDE_DEFAULT_SEL = '.slide'; 18954 var SLIDE = 'fp-slide'; 18955 var SLIDE_SEL = '.' + SLIDE; 18956 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 18957 var SLIDES_WRAPPER = 'fp-slides'; 18958 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 18959 var SLIDES_CONTAINER = 'fp-slidesContainer'; 18960 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 18961 var TABLE = 'fp-table'; 18962 18963 // slide nav 18964 var SLIDES_NAV = 'fp-slidesNav'; 18965 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 18966 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 18967 var SLIDES_ARROW = 'fp-controlArrow'; 18968 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 18969 var SLIDES_PREV = 'fp-prev'; 18970 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 18971 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 18972 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 18973 var SLIDES_NEXT = 'fp-next';
18974 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 18975 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 18976 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 18977 18978 var $window = $(window); 18979 var $document = $(document); 18980 18981 // Default options for iScroll.js used when using scrollOverflow 18982 var iscrollOptions = { 18983 scrollbars: true, 18984 mouseWheel: true, 18985 hideScrollbars: false, 18986 fadeScrollbars: false, 18987 disableMouse: true, 18988 interactiveScrollbars: true, 18989 bounce: false, 18990 }; 18991 18992 $.fn.fullpage = function(options) { 18993 //only once my friend! 18994 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 18995 18996 // common jQuery objects 18997 var $htmlBody = $('html, body'); 18998 var $body = $('body'); 18999 19000 var FP = $.fn.fullpage; 19001 19002 // Creating some defaults, extending them with any options that were provided 19003 options = $.extend({ 19004 //navigation 19005 menu: false, 19006 anchors:[], 19007 lockAnchors: false, 19008 navigation: false, 19009 navigationPosition: 'right', 19010 navigationTooltips: [], 19011 showActiveTooltip: false, 19012 slidesNavigation: false, 19013 slidesNavPosition: 'bottom', 19014 scrollBar: false, 19015 hybrid: false, 19016 19017 //scrolling 19018 css3: true, 19019 scrollingSpeed: 700, 19020 autoScrolling: true, 19021 fitToSection: true, 19022 fitToSectionDelay: 1000, 19023 easing: 'easeInOutCubic', 19024 easingcss3: 'ease', 19025 loopBottom: false, 19026 loopTop: false, 19027 loopHorizontal: true, 19028 continuousVertical: false, 19029 continuousHorizontal: false, 19030 scrollHorizontally: false, 19031 interlockedSlides: false, 19032 dragAndMove: false, 19033 offsetSections: false, 19034 resetSliders: false, 19035 fadingEffect: false, 19036 normalScrollElements: null, 19037 scrollOverflow: false, 19038 scrollOverflowReset: false, 19039 scrollOverflowHandler: iscrollHandler, 19040 scrollOverflowOptions: null, 19041 touchSensitivity: 5, 19042 normalScrollElementTouchThreshold: 5, 19043 bigSectionsDestination: null, 19044 19045 //Accessibility 19046 keyboardScrolling: true, 19047 animateAnchor: true, 19048 recordHistory: true, 19049 19050 //design 19051 controlArrows: true, 19052 controlArrowColor: '#fff', 19053 verticalCentered: true, 19054 sectionsColor : [], 19055 paddingTop: 0, 19056 paddingBottom: 0, 19057 fixedElements: null, 19058 responsive: 0, //backwards compabitility with responsiveWiddth 19059 responsiveWidth: 0, 19060 responsiveHeight: 0, 19061 responsiveSlides: false, 19062 parallax: false, 19063 parallaxOptions: { 19064 type: 'reveal', 19065 percentage: 62, 19066 property: 'translate' 19067 }, 19068 19069 //Custom selectors 19070 sectionSelector: SECTION_DEFAULT_SEL, 19071 slideSelector: SLIDE_DEFAULT_SEL, 19072 19073 //events 19074 afterLoad: null, 19075 onLeave: null, 19076 afterRender: null, 19077 afterResize: null, 19078 afterReBuild: null, 19079 afterSlideLoad: null, 19080 onSlideLeave: null, 19081 afterResponsive: null, 19082 19083 lazyLoading: true 19084 }, options); 19085 19086 //flag to avoid very fast sliding for landscape sliders 19087 var slideMoving = false; 19088 19089 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 19090 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 19091 var container = $(this); 19092 var windowsHeight = $window.height(); 19093 var isResizing = false; 19094 var isWindowFocused = true; 19095 var lastScrolledDestiny; 19096 var lastScrolledSlide; 19097 var canScroll = true; 19098 var scrollings = []; 19099 var controlPressed; 19100 var startingSection; 19101 var isScrollAllowed = {}; 19102 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 19103 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 19104 var MSPointer = getMSPointer(); 19105 var events = { 19106 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 19107 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 19108 }; 19109 19110 //timeouts 19111 var resizeId; 19112 var afterSectionLoadsId; 19113 var afterSlideLoadsId; 19114 var scrollId; 19115 var scrollId2;
19116 var keydownId; 19117 var originals = $.extend(true, {}, options); //deep copy 19118 19119 //Uncode addition 19120 var $masthead = $('#masthead'); 19121 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 19122 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 19123 var bodyBorder = UNCODE.bodyBorder; 19124 var adminBarHeight = UNCODE.adminBarHeight; 19125 19126 displayWarnings(); 19127 19128 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 19129 iscrollOptions.click = isTouch; // see #2035 19130 19131 //extending iScroll options with the user custom ones 19132 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 19133 19134 //easeInOutCubic animation included in the plugin 19135 $.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;}}); 19136 19137 /** 19138 * Sets the autoScroll option. 19139 * It changes the scroll bar visibility and the history of the site as a result. 19140 */ 19141 function setAutoScrolling(value, type){ 19142 //removing the transformation 19143 if(!value){ 19144 silentScroll(0); 19145 } 19146 19147 setVariableState('autoScrolling', value, type); 19148 19149 var element = $(SECTION_ACTIVE_SEL); 19150 19151 if(options.autoScrolling && !options.scrollBar){ 19152 $htmlBody.css({ 19153 'overflow' : 'hidden !important', 19154 'height' : '100%' 19155 }); 19156 19157 //Uncode addition 19158 //setRecordHistory(originals.recordHistory, 'internal'); 19159 19160 //for IE touch devices 19161 container.css({ 19162 '-ms-touch-action': 'none', 19163 'touch-action': 'none' 19164 }); 19165 19166 if(element.length){ 19167 //moving the container up 19168 silentScroll(element.position().top); 19169 } 19170 19171 }else{ 19172 $htmlBody.css({ 19173 'overflow' : 'visible !important', 19174 'height' : 'initial' 19175 }); 19176 19177 //Uncode addition 19178 //setRecordHistory(false, 'internal'); 19179 19180 //for IE touch devices 19181 container.css({ 19182 '-ms-touch-action': '', 19183 'touch-action': '' 19184 }); 19185 19186 //scrolling the page to the section with no animation 19187 if (element.length) { 19188 $htmlBody.scrollTop(element.position().top); 19189 } 19190 } 19191 } 19192 19193 /** 19194 * Defines wheter to record the history for each hash change in the URL. 19195 */ 19196 function setRecordHistory(value, type){ 19197 setVariableState('recordHistory', value, type); 19198 } 19199 19200 /** 19201 * Defines the scrolling speed 19202 */ 19203 function setScrollingSpeed(value, type){ 19204 setVariableState('scrollingSpeed', value, type); 19205 } 19206 19207 /** 19208 * Sets fitToSection 19209 */ 19210 function setFitToSection(value, type){ 19211 setVariableState('fitToSection', value, type); 19212 } 19213 19214 /** 19215 * Sets lockAnchors 19216 */ 19217 function setLockAnchors(value){ 19218 options.lockAnchors = value; 19219 } 19220 19221 /** 19222 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 19223 */ 19224 function setMouseWheelScrolling(value){ 19225 if(value){ 19226 addMouseWheelHandler(); 19227 addMiddleWheelHandler(); 19228 }else{ 19229 removeMouseWheelHandler(); 19230 removeMiddleWheelHandler(); 19231 } 19232 } 19233 19234 /** 19235 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 19236 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 19237 * 19238 * @param directions string containing the direction or directions separated by comma. 19239 */ 19240 function setAllowScrolling(value, directions){ 19241 if(typeof directions !== 'undefined'){ 19242 directions = directions.replace(/ /g,'').split(','); 19243 19244 $.each(directions, function (index, direction){ 19245 setIsScrollAllowed(value, direction, 'm'); 19246 }); 19247 } 19248 else if(value){ 19249 setMouseWheelScrolling(true); 19250 addTouchHandler(); 19251 }else{ 19252 setMouseWheelScrolling(false); 19253 removeTouchHandler(); 19254 } 19255 } 19256 19257 /** 19258 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 19259 */ 19260 function setKeyboardScrolling(value, directions){ 19261 if(typeof directions !== 'undefined'){ 19262 directions = directions.replace(/ /g,'').split(','); 19263 19264 $.each(directions, function (index, direction){ 19265 setIsScrollAllowed(value, direction, 'k'); 19266 }); 19267 }else{ 19268 options.keyboardScrolling = value; 19269 } 19270 } 19271 19272 /** 19273 * Moves the page up one section. 19274 */ 19275 function moveSectionUp(){ 19276 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 19277 19278 //looping to the bottom if there's no more sections above 19279 if (!prev.length && (options.loopTop || options.continuousVertical)) {
19280 prev = $(SECTION_SEL).last(); 19281 } 19282 19283 if (prev.length) { 19284 scrollPage(prev, null, true); 19285 } 19286 } 19287 19288 /** 19289 * Moves the page down one section. 19290 */ 19291 function moveSectionDown(){ 19292 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 19293 19294 //looping to the top if there's no more sections below 19295 if(!next.length && 19296 (options.loopBottom || options.continuousVertical)){ 19297 next = $(SECTION_SEL).first(); 19298 } 19299 19300 if(next.length){ 19301 scrollPage(next, null, false); 19302 } 19303 } 19304 19305 /** 19306 * Moves the page to the given section and slide with no animation. 19307 * Anchors or index positions can be used as params. 19308 */ 19309 function silentMoveTo(sectionAnchor, slideAnchor){ 19310 setScrollingSpeed (0, 'internal'); 19311 moveTo(sectionAnchor, slideAnchor); 19312 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 19313 } 19314 19315 /** 19316 * Moves the page to the given section and slide. 19317 * Anchors or index positions can be used as params. 19318 */ 19319 function moveTo(sectionAnchor, slideAnchor){ 19320 var destiny = getSectionByAnchor(sectionAnchor); 19321 19322 if (typeof slideAnchor !== 'undefined'){ 19323 scrollPageAndSlide(sectionAnchor, slideAnchor); 19324 }else if(destiny.length > 0){ 19325 scrollPage(destiny); 19326 } 19327 } 19328 19329 /** 19330 * Slides right the slider of the active section. 19331 * Optional `section` param. 19332 */ 19333 function moveSlideRight(section){ 19334 moveSlide('right', section); 19335 } 19336 19337 /** 19338 * Slides left the slider of the active section. 19339 * Optional `section` param. 19340 */ 19341 function moveSlideLeft(section){ 19342 moveSlide('left', section); 19343 } 19344 19345 /** 19346 * When resizing is finished, we adjust the slides sizes and positions 19347 */ 19348 function reBuild(resizing){ 19349 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 19350 19351 isResizing = true; 19352 19353 windowsHeight = $window.height(); //updating global var 19354 19355 $(SECTION_SEL).each(function(){ 19356 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 19357 var slides = $(this).find(SLIDE_SEL); 19358 19359 //adjusting the height of the table-cell for IE and Firefox 19360 if(options.verticalCentered){ 19361 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 19362 } 19363 19364 $(this).css('height', windowsHeight + 'px'); 19365 19366 //resizing the scrolling divs 19367 if(options.scrollOverflow){ 19368 if(slides.length){ 19369 slides.each(function(){ 19370 createScrollBar($(this)); 19371 }); 19372 }else{ 19373 createScrollBar($(this)); 19374 } 19375 } 19376 19377 //adjusting the position fo the FULL WIDTH slides... 19378 if (slides.length > 1) { 19379 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 19380 } 19381 }); 19382 19383 var activeSection = $(SECTION_ACTIVE_SEL); 19384 var sectionIndex = activeSection.index(SECTION_SEL); 19385 19386 //isn't it the first section? 19387 if(sectionIndex){ 19388 //adjusting the position for the current section 19389 silentMoveTo(sectionIndex + 1); 19390 } 19391 19392 isResizing = false; 19393 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 19394 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 19395 } 19396 19397 /** 19398 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 19399 * are smaller than the set limit values. 19400 */ 19401 function setResponsive(active){ 19402 var isResponsive = $body.hasClass(RESPONSIVE); 19403 19404 if(active){ 19405 if(!isResponsive){ 19406 setAutoScrolling(false, 'internal'); 19407 setFitToSection(false, 'internal'); 19408 $(SECTION_NAV_SEL).hide(); 19409 $body.addClass(RESPONSIVE); 19410 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19411 } 19412 } 19413 else if(isResponsive){ 19414 setAutoScrolling(originals.autoScrolling, 'internal'); 19415 setFitToSection(originals.autoScrolling, 'internal'); 19416 $(SECTION_NAV_SEL).show(); 19417 $body.removeClass(RESPONSIVE); 19418 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 19419 } 19420 } 19421 19422 if($(this).length){ 19423 //public functions 19424 FP.setAutoScrolling = setAutoScrolling; 19425 FP.setRecordHistory = setRecordHistory; 19426 FP.setScrollingSpeed = setScrollingSpeed; 19427 FP.setFitToSection = setFitToSection; 19428 FP.setLockAnchors = setLockAnchors; 19429 FP.setMouseWheelScrolling = setMouseWheelScrolling; 19430 FP.setAllowScrolling = setAllowScrolling; 19431 FP.setKeyboardScrolling = setKeyboardScrolling; 19432 FP.moveSectionUp = moveSectionUp; 19433 FP.moveSectionDown = moveSectionDown; 19434 FP.silentMoveTo = silentMoveTo; 19435 FP.moveTo = moveTo; 19436 FP.moveSlideRight = moveSlideRight; 19437 FP.moveSlideLeft = moveSlideLeft; 19438 FP.fitToSection = fitToSection; 19439 FP.reBuild = reBuild; 19440 FP.setResponsive = setResponsive; 19441 FP.destroy = destroy; 19442 19443 init(); 19444 19445 bindEvents(); 19446 } 19447
19448 function init(){ 19449 //if css3 is not supported, it will use jQuery animations 19450 if(options.css3){ 19451 options.css3 = support3d(); 19452 } 19453 19454 options.scrollBar = options.scrollBar || options.hybrid; 19455 19456 setOptionsFromDOM(); 19457 prepareDom(); 19458 setAllowScrolling(true); 19459 setAutoScrolling(options.autoScrolling, 'internal'); 19460 responsive(); 19461 19462 //setting the class for the body element 19463 setBodyClass(); 19464 19465 //Uncode addition 19466 // if(document.readyState === 'complete'){ 19467 // scrollToAnchor(); 19468 // } 19469 // $window.on('load', scrollToAnchor); 19470 } 19471 19472 function bindEvents(){ 19473 $window 19474 //when scrolling... 19475 //.on('scroll', scrollHandler) 19476 19477 //detecting any change on the URL to scroll to the given anchor link 19478 //(a way to detect back history button as we play with the hashes on the URL) 19479 .on('hashchange', hashChangeHandler) 19480 19481 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 19482 .blur(blurHandler) 19483 19484 //when resizing the site, we adjust the heights of the sections, slimScroll... 19485 .resize(resizeHandler); 19486 19487 $document 19488 //Sliding with arrow keys, both, vertical and horizontal 19489 .keydown(keydownHandler) 19490 19491 //to prevent scrolling while zooming 19492 .keyup(keyUpHandler) 19493 19494 //Scrolls to the section when clicking the navigation bullet 19495 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 19496 19497 //Scrolls the slider to the given slide destination for the given section 19498 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 19499 19500 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 19501 19502 //Scrolling horizontally when clicking on the slider controls. 19503 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 19504 19505 /** 19506 * Applying normalScroll elements. 19507 * Ignoring the scrolls over the specified selectors. 19508 */ 19509 if(options.normalScrollElements){ 19510 $document.on('mouseenter', options.normalScrollElements, function () { 19511 setMouseWheelScrolling(false); 19512 }); 19513 19514 $document.on('mouseleave', options.normalScrollElements, function(){ 19515 setMouseWheelScrolling(true); 19516 }); 19517 } 19518 } 19519 19520 /** 19521 * Setting options from DOM elements if they are not provided. 19522 */ 19523 function setOptionsFromDOM(){ 19524 var sections = container.find(options.sectionSelector); 19525 19526 //no anchors option? Checking for them in the DOM attributes 19527 if(!options.anchors.length){ 19528 options.anchors = sections.filter('[data-anchor]').map(function(){ 19529 return $(this).data('anchor').toString(); 19530 }).get(); 19531 } 19532 19533 //no tooltips option? Checking for them in the DOM attributes 19534 if(!options.navigationTooltips.length){ 19535 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 19536 return $(this).data('tooltip').toString(); 19537 }).get(); 19538 } 19539 } 19540 19541 /** 19542 * Works over the DOM structure to set it up for the current fullpage options. 19543 */ 19544 function prepareDom(){ 19545 container.css({ 19546 'height': '100%', 19547 'position': 'relative' 19548 }); 19549 19550 //adding a class to recognize the container internally in the code 19551 container.addClass(WRAPPER); 19552 $('html').addClass(ENABLED); 19553 19554 windowsHeight = $window.height(); 19555 19556 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 19557 19558 addInternalSelectors(); 19559 19560 //styling the sections / slides / menu 19561 $(SECTION_SEL).each(function(index){ 19562 var section = $(this); 19563 var slides = section.find(SLIDE_SEL); 19564 var numSlides = slides.length; 19565 19566 styleSection(section, index); 19567 styleMenu(section, index); 19568 19569 // if there's any slide 19570 if (numSlides > 0) { 19571 styleSlides(section, slides, numSlides); 19572 }else{ 19573 if(options.verticalCentered){ 19574 addTableClass(section); 19575 } 19576 } 19577 }); 19578 19579 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 19580 if(options.fixedElements && options.css3){ 19581 $(options.fixedElements).appendTo($body); 19582 } 19583 19584 //vertical centered of the navigation + active bullet 19585 if(options.navigation){ 19586 addVerticalNavigation(); 19587 } 19588 19589 enableYoutubeAPI(); 19590 19591 if(options.scrollOverflow){ 19592 if(document.readyState === 'complete'){ 19593 createScrollBarHandler(); 19594 } 19595 //after DOM and images are loaded 19596 $window.on('load', createScrollBarHandler); 19597 }else{ 19598 afterRenderActions(); 19599 } 19600 } 19601 19602 /** 19603 * Styles the horizontal slides for a section. 19604 */ 19605 function styleSlides(section, slides, numSlides){ 19606 var sliderWidth = numSlides * 100; 19607 var slideWidth = 100 / numSlides; 19608 19609 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 19610 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 19611 19612 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 19613 19614 if(numSlides > 1){ 19615 if(options.controlArrows){ 19616 createSlideArrows(section); 19617 } 19618 19619 if(options.slidesNavigation){ 19620 addSlidesNavigation(section, numSlides); 19621 } 19622 } 19623 19624 slides.each(function(index) { 19625 $(this).css('width', slideWidth + '%'); 19626 19627 if(options.verticalCentered){ 19628 addTableClass($(this)); 19629 } 19630 }); 19631 19632 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 19633 19634 //if the slide won't be an starting point, the default will be the first one 19635 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
19635ide by default. 19636 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 19637 silentLandscapeScroll(startingSlide, 'internal'); 19638 }else{ 19639 slides.eq(0).addClass(ACTIVE); 19640 } 19641 } 19642 19643 /** 19644 * Styling vertical sections 19645 */ 19646 function styleSection(section, index){ 19647 //if no active section is defined, the 1st one will be the default one 19648 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 19649 section.addClass(ACTIVE); 19650 } 19651 startingSection = $(SECTION_ACTIVE_SEL); 19652 19653 section.css('height', windowsHeight + 'px'); 19654 19655 if(options.paddingTop){ 19656 section.css('padding-top', options.paddingTop); 19657 } 19658 19659 if(options.paddingBottom){ 19660 section.css('padding-bottom', options.paddingBottom); 19661 } 19662 19663 if (typeof options.sectionsColor[index] !== 'undefined') { 19664 section.css('background-color', options.sectionsColor[index]); 19665 } 19666 19667 if (typeof options.anchors[index] !== 'undefined') { 19668 section.attr('data-anchor', options.anchors[index]); 19669 } 19670 } 19671 19672 /** 19673 * Sets the data-anchor attributes to the menu elements and activates the current one. 19674 */ 19675 function styleMenu(section, index){ 19676 if (typeof options.anchors[index] !== 'undefined') { 19677 //activating the menu / nav element on load 19678 if(section.hasClass(ACTIVE)){ 19679 activateMenuAndNav(options.anchors[index], index); 19680 } 19681 } 19682 19683 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 19684 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 19685 $(options.menu).appendTo($body); 19686 } 19687 } 19688 19689 /** 19690 * Adds internal classes to be able to provide customizable selectors 19691 * keeping the link with the style sheet. 19692 */ 19693 function addInternalSelectors(){ 19694 container.find(options.sectionSelector).addClass(SECTION); 19695 container.find(options.slideSelector).addClass(SLIDE); 19696 } 19697 19698 /** 19699 * Creates the control arrows for the given section 19700 */ 19701 function createSlideArrows(section){ 19702 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 19703 19704 if(options.controlArrowColor!='#fff'){ 19705 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 19706 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 19707 } 19708 19709 if(!options.loopHorizontal){ 19710 section.find(SLIDES_ARROW_PREV_SEL).hide(); 19711 } 19712 } 19713 19714 /** 19715 * Creates a vertical navigation bar. 19716 */ 19717 function addVerticalNavigation(){ 19718 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 19719 var nav = $(SECTION_NAV_SEL); 19720 19721 nav.addClass(function() { 19722 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 19723 }); 19724 19725 for (var i = 0; i < $(SECTION_SEL).length; i++) { 19726 var link = ''; 19727 if (options.anchors.length) { 19728 link = options.anchors[i]; 19729 } 19730 19731 var li = '<li><a href="#' + link + '"><span></span></a>'; 19732 19733 // Only add tooltip if needed (defined by user) 19734 var tooltip = options.navigationTooltips[i]; 19735 19736 if (typeof tooltip !== 'undefined' && tooltip !== '') { 19737 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 19738 } 19739 19740 li += '</li>'; 19741 19742 nav.find('ul').append(li); 19743 } 19744 19745 //centering it vertically 19746 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 19747 19748 //activating the current active section 19749 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 19750 } 19751 19752 /** 19753 * Creates the slim scroll scrollbar for the sections and slides inside them. 19754 */ 19755 function createScrollBarHandler(){ 19756 $(SECTION_SEL).each(function(){ 19757 var slides = $(this).find(SLIDE_SEL); 19758 19759 if(slides.length){ 19760 slides.each(function(){ 19761 createScrollBar($(this)); 19762 }); 19763 }else{ 19764 createScrollBar($(this)); 19765 } 19766 19767 }); 19768 afterRenderActions(); 19769 } 19770 19771 /*
19772 * Enables the Youtube videos API so we can control their flow if necessary. 19773 */ 19774 function enableYoutubeAPI(){ 19775 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 19776 addURLParam($(this), 'enablejsapi=1'); 19777 }); 19778 } 19779 19780 /** 19781 * Adds a new parameter and its value to the `src` of a given element 19782 */ 19783 function addURLParam(element, newParam){ 19784 var originalSrc = element.attr('src'); 19785 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 19786 } 19787 19788 /* 19789 * Returns the prefix sign to use for a new parameter in an existen URL. 19790 * 19791 * @return {String} ? | & 19792 */ 19793 function getUrlParamSign(url){ 19794 return ( !/\?/.test( url ) ) ? '?' : '&'; 19795 } 19796 19797 /** 19798 * Actions and callbacks to fire afterRender 19799 */ 19800 function afterRenderActions(){ 19801 var section = $(SECTION_ACTIVE_SEL); 19802 19803 section.addClass(COMPLETELY); 19804 19805 if(options.scrollOverflowHandler.afterRender){ 19806 options.scrollOverflowHandler.afterRender(section); 19807 } 19808 lazyLoad(section); 19809 playMedia(section); 19810 options.scrollOverflowHandler.afterLoad(); 19811 19812 if(isDestinyTheStartingSection()){ 19813 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 19814 } 19815 19816 $.isFunction( options.afterRender ) && options.afterRender.call(container); 19817 } 19818 19819 /** 19820 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 19821 */ 19822 function isDestinyTheStartingSection(){ 19823 var anchors = window.location.hash.replace('#', '').split('/'); 19824 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 19825 19826 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 19827 } 19828 19829 19830 var isScrolling = false; 19831 var lastScroll = 0; 19832 19833 //when scrolling... 19834 function scrollHandler(){ 19835 var currentSection; 19836 19837 if(!options.autoScrolling || options.scrollBar){ 19838 var currentScroll = $window.scrollTop(); 19839 var scrollDirection = getScrollDirection(currentScroll); 19840 var visibleSectionIndex = 0; 19841 var screen_mid = currentScroll + ($window.height() / 2.0); 19842 var isAtBottom = $body.height() - $window.height() === currentScroll; 19843 var sections = document.querySelectorAll(SECTION_SEL); 19844 19845 //when using `auto-height` for a small last section it won't be centered in the viewport 19846 if(isAtBottom){ 19847 visibleSectionIndex = sections.length - 1; 19848 } 19849 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 19850 else if(!currentScroll){ 19851 visibleSectionIndex = 0; 19852 } 19853 19854 //taking the section which is showing more content in the viewport 19855 else{ 19856 for (var i = 0; i < sections.length; ++i) { 19857 var section = sections[i]; 19858 19859 // Pick the the last section which passes the middle line of the screen. 19860 if (section.offsetTop <= screen_mid) 19861 { 19862 visibleSectionIndex = i; 19863 } 19864 } 19865 } 19866 19867 if(isCompletelyInViewPort(scrollDirection)){ 19868 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 19869 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 19870 } 19871 } 19872 19873 //geting the last one, the current one on the screen 19874 currentSection = $(sections).eq(visibleSectionIndex); 19875 19876 //setting the visible section as active when manually scrolling 19877 //executing only once the first time we reach the section 19878 if(!currentSection.hasClass(ACTIVE)){ 19879 isScrolling = true; 19880 var leavingSection = $(SECTION_ACTIVE_SEL); 19881 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 19882 var yMovement = getYmovement(currentSection); 19883 var anchorLink = currentSection.data('anchor'); 19884 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 19885 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 19886 var slideIndex; 19887 var slideAnchorLink; 19888 19889 if(activeSlide.length){ 19890 slideAnchorLink = activeSlide.data('anchor'); 19891 slideIndex = activeSlide.index(); 19892 } 19893 19894 if(canScroll){ 19895 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 19896 19897 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 19898 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 19899 19900 stopMedia(leavingSection); 19901 lazyLoad(currentSection); 19902 playMedia(currentSection); 19903 19904 activateMenuAndNav(anchorLink, sectionIndex - 1); 19905 19906 if(options.anchors.length){ 19907 //needed to enter in hashChange event when using the menu with anchor links 19908 lastScrolledDestiny = anchorLink; 19909 } 19910 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 19911 } 19912 19913 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 19914 clearTimeout(scrollId); 19915 scrollId = setTimeout(function(){ 19916 isScrolling = false;
19917 }, 100); 19918 } 19919 19920 if(options.fitToSection){ 19921 //for the auto adjust of the viewport to fit a whole section 19922 clearTimeout(scrollId2); 19923 19924 scrollId2 = setTimeout(function(){ 19925 //checking it again in case it changed during the delay 19926 if(options.fitToSection){ 19927 fitToSection(); 19928 } 19929 }, options.fitToSectionDelay); 19930 } 19931 } 19932 } 19933 19934 /** 19935 * Fits the site to the nearest active section 19936 */ 19937 function fitToSection(){ 19938 //checking fitToSection again in case it was set to false before the timeout delay 19939 if(canScroll){ 19940 //allows to scroll to an active section and 19941 //if the section is already active, we prevent firing callbacks 19942 isResizing = true; 19943 19944 scrollPage($(SECTION_ACTIVE_SEL)); 19945 isResizing = false; 19946 } 19947 } 19948 19949 /** 19950 * Determines whether the active section has seen in its whole or not. 19951 */ 19952 function isCompletelyInViewPort(movement){ 19953 var top = $(SECTION_ACTIVE_SEL).position().top; 19954 var bottom = top + $window.height(); 19955 19956 if(movement == 'up'){ 19957 return bottom >= ($window.scrollTop() + $window.height()); 19958 } 19959 return top <= $window.scrollTop(); 19960 } 19961 19962 /** 19963 * Gets the directon of the the scrolling fired by the scroll event. 19964 */ 19965 function getScrollDirection(currentScroll){ 19966 var direction = currentScroll > lastScroll ? 'down' : 'up'; 19967 19968 lastScroll = currentScroll; 19969 19970 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 19971 previousDestTop = currentScroll; 19972 19973 return direction; 19974 } 19975 19976 /** 19977 * Determines the way of scrolling up or down: 19978 * by 'automatically' scrolling a section or by using the default and normal scrolling. 19979 */ 19980 function scrolling(type, scrollable){ 19981 if (!isScrollAllowed.m[type]){ 19982 return; 19983 } 19984 var check = (type === 'down') ? 'bottom' : 'top'; 19985 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 19986 19987 if(scrollable.length > 0 ){ 19988 //is the scrollbar at the start/end of the scroll? 19989 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 19990 scrollSection(); 19991 }else{ 19992 return true; 19993 } 19994 }else{ 19995 // moved up/down 19996 scrollSection(); 19997 } 19998 } 19999 20000 /* 20001 * Preventing bouncing in iOS #2285 20002 */ 20003 function preventBouncing(event){ 20004 var e = event.originalEvent; 20005 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e)){ 20006 //preventing the easing on iOS devices 20007 event.preventDefault(); 20008 } 20009 } 20010 20011 var touchStartY = 0; 20012 var touchStartX = 0; 20013 var touchEndY = 0; 20014 var touchEndX = 0; 20015 20016 /* Detecting touch events 20017 20018 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 20019 * This way, the touchstart and the touch moves shows an small difference between them which is the 20020 * used one to determine the direction. 20021 */ 20022 function touchMoveHandler(event){ 20023 var e = event.originalEvent; 20024 var activeSection = $(e.target).closest(SECTION_SEL); 20025 20026 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 20027 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 20028 20029 if(options.autoScrolling){ 20030 //preventing the easing on iOS devices 20031 event.preventDefault(); 20032 } 20033 20034 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20035 var touchEvents = getEventsPage(e); 20036 20037 touchEndY = touchEvents.y; 20038 touchEndX = touchEvents.x; 20039 20040 //if movement in the X axys is greater than in the Y and the currect section has slides... 20041 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 20042 20043 //is the movement greater than the minimum resistance to scroll? 20044 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 20045 if (touchStartX > touchEndX) { 20046 if(isScrollAllowed.m.right){ 20047 moveSlideRight(activeSection); //next 20048 } 20049 } else { 20050 if(isScrollAllowed.m.left){ 20051 moveSlideLeft(activeSection); //prev 20052 } 20053 } 20054 } 20055 } 20056 20057 //vertical scrolling (only when autoScrolling is enabled) 20058 else if(options.autoScrolling && canScroll){ 20059 20060 //is the movement greater than the minimum resistance to scroll? 20061 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 20062 if (touchStartY > touchEndY) { 20063 scrolling('down', scrollable); 20064 } else if (touchEndY > touchStartY) { 20065 scrolling('up', scrollable); 20066 } 20067 } 20068 } 20069 } 20070 } 20071 20072 /** 20073 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 20074 * Currently works well for iOS - Android might need some testing 20075 * @param {Element} el target element / jquery selector (in subsequent nodes) 20076 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 20077 * @return {boolean} true if there is a match to options.normalScrollElements 20078 */ 20079 function checkParentForNormalScrollElement (el, hop) { 20080 hop = hop || 0; 20081 var parent = $(el).parent(); 20082 20083 if (hop < options.normalScrollElementTouchThreshold && 20084 parent.is(options.normalScrollElements) ) { 20085 return true; 20086 } else if (hop == options.normalScrollElementTouchThreshold) { 20087 return false;
20088 } else { 20089 return checkParentForNormalScrollElement(parent, ++hop); 20090 } 20091 } 20092 20093 /** 20094 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 20095 * this way we make sure that is really a touch event what IE is detecting. 20096 */ 20097 function isReallyTouch(e){ 20098 //if is not IE || IE is detecting `touch` or `pen` 20099 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 20100 } 20101 20102 /** 20103 * Handler for the touch start event. 20104 */ 20105 function touchStartHandler(event){ 20106 var e = event.originalEvent; 20107 20108 //stopping the auto scroll to adjust to a section 20109 if(options.fitToSection){ 20110 $htmlBody.stop(); 20111 } 20112 20113 if(isReallyTouch(e)){ 20114 var touchEvents = getEventsPage(e); 20115 touchStartY = touchEvents.y; 20116 touchStartX = touchEvents.x; 20117 } 20118 } 20119 20120 /** 20121 * Gets the average of the last `number` elements of the given array. 20122 */ 20123 function getAverage(elements, number){ 20124 var sum = 0; 20125 20126 //taking `number` elements from the end to make the average, if there are not enought, 1 20127 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 20128 20129 for(var i = 0; i < lastElements.length; i++){ 20130 sum = sum + lastElements[i]; 20131 } 20132 20133 return Math.ceil(sum/number); 20134 } 20135 20136 /** 20137 * Detecting mousewheel scrolling 20138 * 20139 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 20140 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 20141 */ 20142 var prevTime = new Date().getTime(); 20143 20144 function MouseWheelHandler(e) { 20145 var curTime = new Date().getTime(); 20146 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 20147 20148 //autoscrolling and not zooming? 20149 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 20150 // cross-browser wheel delta 20151 e = e || window.event; 20152 var value = e.wheelDelta || -e.deltaY || -e.detail; 20153 var delta = Math.max(-1, Math.min(1, value)); 20154 20155 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 20156 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 20157 20158 //Limiting the array to 150 (lets not waste memory!) 20159 if(scrollings.length > 149){ 20160 scrollings.shift(); 20161 } 20162 20163 //keeping record of the previous scrollings 20164 scrollings.push(Math.abs(value)); 20165 20166 //preventing to scroll the site on mouse wheel when scrollbar is present 20167 if(options.scrollBar){ 20168 e.preventDefault ? e.preventDefault() : e.returnValue = false; 20169 } 20170 20171 var activeSection = $(SECTION_ACTIVE_SEL); 20172 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 20173 20174 //time difference between the last scroll and the current one 20175 var timeDiff = curTime-prevTime; 20176 prevTime = curTime; 20177 20178 //haven't they scrolled in a while? 20179 //(enough to be consider a different scrolling action to scroll another section) 20180 if(timeDiff > 200){ 20181 //emptying the array, we dont care about old scrollings for our averages 20182 scrollings = []; 20183 } 20184 20185 if(canScroll){ 20186 var averageEnd = getAverage(scrollings, 10); 20187 var averageMiddle = getAverage(scrollings, 70); 20188 var isAccelerating = averageEnd >= averageMiddle; 20189 20190 //to avoid double swipes... 20191 if(isAccelerating && isScrollingVertically){ 20192 //scrolling down? 20193 if (delta < 0) { 20194 scrolling('down', scrollable); 20195 20196 //scrolling up? 20197 }else { 20198 scrolling('up', scrollable); 20199 } 20200 } 20201 } 20202 20203 return false; 20204 } 20205 20206 if(options.fitToSection){ 20207 //stopping the auto scroll to adjust to a section 20208 $htmlBody.stop(); 20209 } 20210 } 20211 20212 /** 20213 * Slides a slider to the given direction. 20214 * Optional `section` param. 20215 */ 20216 function moveSlide(direction, section){ 20217 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 20218 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 20219 var numSlides = slides.find(SLIDE_SEL).length; 20220 20221 // more than one slide needed and nothing should be sliding 20222 if (!slides.length || slideMoving || numSlides < 2) { 20223 return; 20224 } 20225 20226 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 20227 var destiny = null; 20228 20229 if(direction === 'left'){ 20230 destiny = currentSlide.prev(SLIDE_SEL); 20231 }else{ 20232 destiny = currentSlide.next(SLIDE_SEL); 20233 } 20234 20235 //isn't there a next slide in the secuence? 20236 if(!destiny.length){ 20237 //respect loopHorizontal settin 20238 if (!options.loopHorizontal) return; 20239 20240 if(direction === 'left'){ 20241 destiny = currentSlide.siblings(':last'); 20242 }else{ 20243 destiny = currentSlide.siblings(':first'); 20244 } 20245 } 20246 20247 slideMoving = true; 20248
20249 landscapeScroll(slides, destiny, direction); 20250 } 20251 20252 /** 20253 * Maintains the active slides in the viewport 20254 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 20255 */ 20256 function keepSlidesPosition(){ 20257 $(SLIDE_ACTIVE_SEL).each(function(){ 20258 silentLandscapeScroll($(this), 'internal'); 20259 }); 20260 } 20261 20262 var previousDestTop = 0; 20263 /** 20264 * Returns the destination Y position based on the scrolling direction and 20265 * the height of the section. 20266 */ 20267 function getDestinationPosition(element){ 20268 var elemPosition = element.position(); 20269 20270 //top of the desination will be at the top of the viewport 20271 var position = elemPosition.top; 20272 var isScrollingDown = elemPosition.top > previousDestTop; 20273 var sectionBottom = position - windowsHeight + element.outerHeight(); 20274 var bigSectionsDestination = options.bigSectionsDestination; 20275 20276 //Uncode addition 20277 var containerH = container.outerHeight(); 20278 var containerPosition = container.offset(); 20279 20280 //########### Commented by Uncode - START ########### 20281 //is the destination element bigger than the viewport? 20282 // if(element.outerHeight() > windowsHeight){ 20283 // //scrolling up? 20284 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 20285 // position = sectionBottom; 20286 // } 20287 // } 20288 20289 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 20290 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 20291 // //The bottom of the destination will be at the bottom of the viewport 20292 // position = sectionBottom; 20293 // } 20294 //########### Commented by Uncode - END ########### 20295 20296 //Uncode addition 20297 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 20298 position += 18; 20299 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 20300 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 20301 } 20302 20303 /* 20304 Keeping record of the last scrolled position to determine the scrolling direction. 20305 No conventional methods can be used as the scroll bar might not be present 20306 AND the section might not be active if it is auto-height and didnt reach the middle 20307 of the viewport. 20308 */ 20309 previousDestTop = position; 20310 return position; 20311 } 20312 20313 /** 20314 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 20315 */ 20316 function scrollPage(element, callback, isMovementUp){ 20317 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 20318 20319 var dtop = getDestinationPosition(element); 20320 var slideAnchorLink; 20321 var slideIndex; 20322 20323 //local variables 20324 var v = { 20325 element: element, 20326 callback: callback, 20327 isMovementUp: isMovementUp, 20328 dtop: dtop, 20329 yMovement: getYmovement(element), 20330 anchorLink: element.data('anchor'), 20331 sectionIndex: element.index(SECTION_SEL), 20332 activeSlide: element.find(SLIDE_ACTIVE_SEL), 20333 activeSection: $(SECTION_ACTIVE_SEL), 20334 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 20335 20336 //caching the value of isResizing at the momment the function is called 20337 //because it will be checked later inside a setTimeout and the value might change 20338 localIsResizing: isResizing 20339 }; 20340 20341 //quiting when destination scroll is the same as the current one 20342 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 20343 20344 if(v.activeSlide.length){ 20345 slideAnchorLink = v.activeSlide.data('anchor'); 20346 slideIndex = v.activeSlide.index(); 20347 } 20348 20349 // If continuousVertical && we need to wrap around 20350 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 20351 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 20352 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 20353 20354 v = createInfiniteSections(v); 20355 } 20356 20357 //callback (onLeave) if the site is not just resizing and readjusting the slides 20358 if($.isFunction(options.onLeave) && !v.localIsResizing){ 20359 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 20360 return; 20361 } 20362 } 20363 20364 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 20365 if(!v.localIsResizing){ 20366 stopMedia(v.activeSection); 20367 } 20368 20369 options.scrollOverflowHandler.beforeLeave(); 20370 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20371 lazyLoad(element); 20372 options.scrollOverflowHandler.onLeave(); 20373 20374 20375 //preventing from activating the MouseWheelHandler event 20376 //more than once if the page is scrolling 20377 canScroll = false;
20378 20379 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 20380 20381 performMovement(v); 20382 20383 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 20384 lastScrolledDestiny = v.anchorLink; 20385 20386 //avoid firing it twice (as it does also on scroll) 20387 activateMenuAndNav(v.anchorLink, v.sectionIndex); 20388 } 20389 20390 /** 20391 * Performs the vertical movement (by CSS3 or by jQuery) 20392 */ 20393 function performMovement(v){ 20394 // using CSS3 translate functionality 20395 if (options.css3 && options.autoScrolling && !options.scrollBar) { 20396 20397 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 20398 // that's why we round it to 0. 20399 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 20400 transformContainer(translate3d, true); 20401 20402 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 20403 //scrollingSpeed to change in case of using silentMoveTo(); 20404 if(options.scrollingSpeed){ 20405 clearTimeout(afterSectionLoadsId); 20406 afterSectionLoadsId = setTimeout(function () { 20407 afterSectionLoads(v); 20408 }, options.scrollingSpeed); 20409 }else{ 20410 afterSectionLoads(v); 20411 } 20412 } 20413 20414 // using jQuery animate 20415 else{ 20416 var scrollSettings = getScrollSettings(v); 20417 20418 $(scrollSettings.element).animate( 20419 scrollSettings.options, 20420 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 20421 if(options.scrollBar){ 20422 20423 /* Hack! 20424 The timeout prevents setting the most dominant section in the viewport as "active" when the user 20425 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 20426 20427 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 20428 */ 20429 setTimeout(function(){ 20430 afterSectionLoads(v); 20431 },30); 20432 }else{ 20433 afterSectionLoads(v); 20434 } 20435 }); 20436 } 20437 } 20438 20439 /** 20440 * Gets the scrolling settings depending on the plugin autoScrolling option 20441 */ 20442 function getScrollSettings(v){ 20443 var scroll = {}; 20444 20445 if(options.autoScrolling && !options.scrollBar){ 20446 scroll.options = { 'top': -v.dtop}; 20447 scroll.element = WRAPPER_SEL; 20448 }else{ 20449 scroll.options = { 'scrollTop': v.dtop}; 20450 scroll.element = 'html, body'; 20451 } 20452 20453 return scroll; 20454 } 20455 20456 /** 20457 * Adds sections before or after the current one to create the infinite effect. 20458 */ 20459 function createInfiniteSections(v){ 20460 // Scrolling down 20461 if (!v.isMovementUp) { 20462 // Move all previous sections to after the active section 20463 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 20464 } 20465 else { // Scrolling up 20466 // Move all next sections to before the active section 20467 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 20468 } 20469 20470 // Maintain the displayed position (now that we changed the element order) 20471 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20472 20473 // Maintain the active slides visible in the viewport 20474 keepSlidesPosition(); 20475 20476 // save for later the elements that still need to be reordered 20477 v.wrapAroundElements = v.activeSection; 20478 20479 // Recalculate animation variables 20480 v.dtop = v.element.position().top; 20481 v.yMovement = getYmovement(v.element); 20482 20483 return v; 20484 } 20485 20486 /** 20487 * Fix section order after continuousVertical changes have been animated 20488 */ 20489 function continuousVerticalFixSectionOrder (v) { 20490 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 20491 // finish moving the elements around so the direct navigation will function more simply 20492 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 20493 return; 20494 } 20495 20496 if (v.isMovementUp) { 20497 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 20498 } 20499 else { 20500 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 20501 } 20502 20503 silentScroll($(SECTION_ACTIVE_SEL).position().top); 20504 20505 // Maintain the active slides visible in the viewport 20506 keepSlidesPosition(); 20507 } 20508 20509 20510 /** 20511 * Actions to do once the section is loaded. 20512 */ 20513 function afterSectionLoads (v){ 20514 continuousVerticalFixSectionOrder(v); 20515 20516 //callback (afterLoad) if the site is not just resizing and readjusting the slides 20517 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 20518 options.scrollOverflowHandler.afterLoad(); 20519 20520 if(!v.localIsResizing){ 20521 playMedia(v.element); 20522 } 20523 20524 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 20525 20526 canScroll = true; 20527 20528 $.isFunction(v.callback) && v.callback.call(this); 20529 } 20530 20531 /** 20532 * Sets the value for the given attribute from the `data-` attribute with the same suffix 20533 * ie: data-srcset ==> srcset | data-src ==> src 20534 */ 20535 function setSrc(element, attribute){ 20536 element 20537 .attr(attribute, element.data(attribute)) 20538 .removeAttr('data-' + attribute); 20539 } 20540 20541 /** 20542 * Lazy loads image, video and audio elements. 20543 */ 20544 function lazyLoad(destiny){ 20545 if (!options.lazyLoading){ 20546 return; 20547 } 20548 20549 var panel = getSlideOrSection(destiny); 20550 var element; 20551 20552 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 20553 element = $(this); 20554 20555 $.each(['src', 'srcset'], function(index, type){ 20556 var attribute = element.attr('data-' + type); 20557 if(typeof attribute !== 'undefined' && attribute){ 20558 setSrc(element, type); 20559 } 20560 }); 20561 20562 if(element.is('source')){ 20563 element.closest('video').get(0).load(); 20564 } 20565 }); 20566 } 20567 20568 /** 20569 * Plays video and audio elements. 20570 */ 20571 function playMedia(destiny){ 20572 var panel = getSlideOrSection(destiny); 20573 20574 //playing HTML5 media elements 20575 panel.find('video, audio').each(function(){ 20576 var element = $(this).get(0); 20577 20578 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 20579 element.play(); 20580 } 20581 }); 20582 20583 //youtube videos 20584 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20585 var element = $(this).get(0); 20586 20587 if ( element.hasAttribute('data-autoplay') ){ 20588 playYoutube(element); 20589 } 20590 20591 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 20592 element.onload = function() { 20593 if ( element.hasAttribute('data-autoplay') ){ 20594 playYoutube(element); 20595 } 20596 }; 20597 }); 20598 } 20599 20600 /** 20601 * Plays a youtube video 20602 */ 20603 function playYoutube(element){ 20604 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 20605 } 20606 20607 /** 20608 * Stops video and audio elements. 20609 */ 20610 function stopMedia(destiny){ 20611 var panel = getSlideOrSection(destiny); 20612 20613 //stopping HTML5 media elements 20614 panel.find('video, audio').each(function(){ 20615 var element = $(this).get(0); 20616 20617 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 20618 element.pause(); 20619 } 20620 }); 20621 20622 //youtube videos 20623 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 20624 var element = $(this).get(0); 20625 20626 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 20627 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 20628 } 20629 }); 20630 } 20631 20632 /** 20633 * Gets the active slide (or section) for the given section 20634 */ 20635 function getSlideOrSection(destiny){ 20636 var slide = destiny.find(SLIDE_ACTIVE_SEL); 20637 if( slide.length ) { 20638 destiny = $(slide); 20639 } 20640 20641 return destiny; 20642 } 20643 20644 /**
20645 * Scrolls to the anchor in the URL when loading the site 20646 */ 20647 function scrollToAnchor(){ 20648 //getting the anchor link in the URL and deleting the `#` 20649 var value = window.location.hash.replace('#', '').split('/'); 20650 var sectionAnchor = decodeURIComponent(value[0]); 20651 var slideAnchor = decodeURIComponent(value[1]); 20652 20653 if(sectionAnchor){ //if theres any # 20654 if(options.animateAnchor){ 20655 scrollPageAndSlide(sectionAnchor, slideAnchor); 20656 }else{ 20657 silentMoveTo(sectionAnchor, slideAnchor); 20658 } 20659 } 20660 } 20661 20662 /** 20663 * Detecting any change on the URL to scroll to the given anchor link 20664 * (a way to detect back history button as we play with the hashes on the URL) 20665 */ 20666 function hashChangeHandler(){ 20667 if(!isScrolling && !options.lockAnchors){ 20668 var value = window.location.hash.replace('#', '').split('/'); 20669 var sectionAnchor = decodeURIComponent(value[0]); 20670 var slideAnchor = decodeURIComponent(value[1]); 20671 20672 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 20673 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 20674 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 20675 20676 20677 if(sectionAnchor.length){ 20678 /*in order to call scrollpage() only once for each destination at a time 20679 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 20680 event is fired on every scroll too.*/ 20681 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 20682 scrollPageAndSlide(sectionAnchor, slideAnchor); 20683 } 20684 } 20685 } 20686 } 20687 20688 //Sliding with arrow keys, both, vertical and horizontal 20689 function keydownHandler(e) { 20690 20691 clearTimeout(keydownId); 20692 20693 var activeElement = $(':focus'); 20694 20695 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 20696 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 20697 options.keyboardScrolling && options.autoScrolling){ 20698 var keyCode = e.which; 20699 20700 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 20701 var keyControls = [40, 38, 32, 33, 34]; 20702 if($.inArray(keyCode, keyControls) > -1){ 20703 e.preventDefault(); 20704 } 20705 20706 controlPressed = e.ctrlKey; 20707 20708 keydownId = setTimeout(function(){ 20709 onkeydown(e); 20710 },150); 20711 } 20712 } 20713 20714 function tooltipTextHandler(){ 20715 $(this).prev().trigger('click'); 20716 } 20717 20718 //to prevent scrolling while zooming 20719 function keyUpHandler(e){ 20720 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 20721 controlPressed = e.ctrlKey; 20722 } 20723 } 20724 20725 //binding the mousemove when the mouse's middle button is released 20726 function mouseDownHandler(e){ 20727 //middle button 20728 if (e.which == 2){ 20729 oldPageY = e.pageY; 20730 container.on('mousemove', mouseMoveHandler); 20731 } 20732 } 20733 20734 //unbinding the mousemove when the mouse's middle button is released 20735 function mouseUpHandler(e){ 20736 //middle button 20737 if (e.which == 2){ 20738 container.off('mousemove'); 20739 } 20740 } 20741 20742 //Scrolling horizontally when clicking on the slider controls. 20743 function slideArrowHandler(){ 20744 var section = $(this).closest(SECTION_SEL); 20745 20746 if ($(this).hasClass(SLIDES_PREV)) { 20747 if(isScrollAllowed.m.left){ 20748 moveSlideLeft(section); 20749 } 20750 } else { 20751 if(isScrollAllowed.m.right){ 20752 moveSlideRight(section); 20753 } 20754 } 20755 } 20756 20757 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 20758 function blurHandler(){ 20759 isWindowFocused = false; 20760 controlPressed = false; 20761 } 20762 20763 //Scrolls to the section when clicking the navigation bullet 20764 function sectionBulletHandler(e){ 20765 e.preventDefault(); 20766 var index = $(this).parent().index(); 20767 scrollPage($(SECTION_SEL).eq(index)); 20768 } 20769 20770 //Scrolls the slider to the given slide destination for the given section 20771 function slideBulletHandler(e){ 20772 e.preventDefault(); 20773 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 20774 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 20775
20776 landscapeScroll(slides, destiny); 20777 } 20778 20779 /** 20780 * Keydown event 20781 */ 20782 function onkeydown(e){ 20783 var shiftPressed = e.shiftKey; 20784 20785 //do nothing if we can not scroll or we are not using horizotnal key arrows. 20786 if(!canScroll && [37,39].indexOf(e.which) < 0){ 20787 return; 20788 } 20789 20790 switch (e.which) { 20791 //up 20792 case 38: 20793 case 33: 20794 if(isScrollAllowed.k.up){ 20795 moveSectionUp(); 20796 } 20797 break; 20798 20799 //down 20800 case 32: //spacebar 20801 if(shiftPressed && isScrollAllowed.k.up){ 20802 moveSectionUp(); 20803 break; 20804 } 20805 /* falls through */ 20806 case 40: 20807 case 34: 20808 if(isScrollAllowed.k.down){ 20809 moveSectionDown(); 20810 } 20811 break; 20812 20813 //Home 20814 case 36: 20815 if(isScrollAllowed.k.up){ 20816 moveTo(1); 20817 } 20818 break; 20819 20820 //End 20821 case 35: 20822 if(isScrollAllowed.k.down){ 20823 moveTo( $(SECTION_SEL).length ); 20824 } 20825 break; 20826 20827 //left 20828 case 37: 20829 if(isScrollAllowed.k.left){ 20830 moveSlideLeft(); 20831 } 20832 break; 20833 20834 //right 20835 case 39: 20836 if(isScrollAllowed.k.right){ 20837 moveSlideRight(); 20838 } 20839 break; 20840 20841 default: 20842 return; // exit this handler for other keys 20843 } 20844 } 20845 20846 /** 20847 * Detecting the direction of the mouse movement. 20848 * Used only for the middle button of the mouse. 20849 */ 20850 var oldPageY = 0; 20851 function mouseMoveHandler(e){ 20852 if(canScroll){ 20853 // moving up 20854 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 20855 moveSectionUp(); 20856 } 20857 20858 // moving down 20859 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 20860 moveSectionDown(); 20861 } 20862 } 20863 oldPageY = e.pageY; 20864 } 20865 20866 /** 20867 * Scrolls horizontal sliders. 20868 */ 20869 function landscapeScroll(slides, destiny, direction){ 20870 var section = slides.closest(SECTION_SEL); 20871 var v = { 20872 slides: slides, 20873 destiny: destiny, 20874 direction: direction, 20875 destinyPos: destiny.position(), 20876 slideIndex: destiny.index(), 20877 section: section, 20878 sectionIndex: section.index(SECTION_SEL), 20879 anchorLink: section.data('anchor'), 20880 slidesNav: section.find(SLIDES_NAV_SEL), 20881 slideAnchor: getAnchor(destiny), 20882 prevSlide: section.find(SLIDE_ACTIVE_SEL), 20883 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 20884 20885 //caching the value of isResizing at the momment the function is called 20886 //because it will be checked later inside a setTimeout and the value might change 20887 localIsResizing: isResizing 20888 }; 20889 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 20890 20891 //important!! Only do it when not resizing 20892 if(!v.localIsResizing){ 20893 //preventing from scrolling to the next/prev section when using scrollHorizontally 20894 canScroll = false; 20895 } 20896 20897 if(options.onSlideLeave){ 20898 20899 //if the site is not just resizing and readjusting the slides 20900 if(!v.localIsResizing && v.xMovement!=='none'){ 20901 if($.isFunction( options.onSlideLeave )){ 20902 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 20903 slideMoving = false; 20904 return; 20905 } 20906 } 20907 } 20908 } 20909 20910 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 20911 20912 if(!v.localIsResizing){ 20913 stopMedia(v.prevSlide); 20914 lazyLoad(destiny); 20915 } 20916 20917 if(!options.loopHorizontal && options.controlArrows){ 20918 //hidding it for the fist slide, showing for the rest 20919 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 20920 20921 //hidding it for the last slide, showing for the rest 20922 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 20923 } 20924 20925 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 20926 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 20927 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 20928 } 20929 20930 performHorizontalMove(slides, v, true); 20931 } 20932 20933 20934 function afterSlideLoads(v){ 20935 activeSlidesNavigation(v.slidesNav, v.slideIndex); 20936 20937 //if the site is not just resizing and readjusting the slides 20938 if(!v.localIsResizing){ 20939 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 20940 20941 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 20942 //and to prevent double scroll right after a windows resize 20943 canScroll = true; 20944 20945 playMedia(v.destiny); 20946 } 20947 20948 //letting them slide again 20949 slideMoving = false;
20950 } 20951 20952 /** 20953 * Performs the horizontal movement. (CSS3 or jQuery) 20954 * 20955 * @param fireCallback {Bool} - determines whether or not to fire the callback 20956 */ 20957 function performHorizontalMove(slides, v, fireCallback){ 20958 var destinyPos = v.destinyPos; 20959 20960 if(options.css3){ 20961 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 20962 20963 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 20964 20965 afterSlideLoadsId = setTimeout(function(){ 20966 fireCallback && afterSlideLoads(v); 20967 }, options.scrollingSpeed, options.easing); 20968 }else{ 20969 slides.animate({ 20970 scrollLeft : Math.round(destinyPos.left) 20971 }, options.scrollingSpeed, options.easing, function() { 20972 20973 fireCallback && afterSlideLoads(v); 20974 }); 20975 } 20976 } 20977 20978 /** 20979 * Sets the state for the horizontal bullet navigations. 20980 */ 20981 function activeSlidesNavigation(slidesNav, slideIndex){ 20982 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 20983 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 20984 } 20985 20986 var previousHeight = windowsHeight; 20987 20988 //when resizing the site, we adjust the heights of the sections, slimScroll... 20989 function resizeHandler(){ 20990 //checking if it needs to get responsive 20991 responsive(); 20992 20993 // rebuild immediately on touch devices 20994 if (isTouchDevice) { 20995 var activeElement = $(document.activeElement); 20996 20997 //if the keyboard is NOT visible 20998 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 20999 var currentHeight = $window.height(); 21000 21001 //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) 21002 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 21003 reBuild(true); 21004 previousHeight = currentHeight; 21005 } 21006 } 21007 }else{ 21008 //in order to call the functions only when the resize is finished 21009 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 21010 clearTimeout(resizeId); 21011 21012 resizeId = setTimeout(function(){ 21013 reBuild(true); 21014 }, 350); 21015 } 21016 } 21017 21018 /** 21019 * Checks if the site needs to get responsive and disables autoScrolling if so. 21020 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 21021 */ 21022 function responsive(){ 21023 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 21024 var heightLimit = options.responsiveHeight; 21025 21026 //only calculating what we need. Remember its called on the resize event. 21027 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 21028 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 21029 21030 if(widthLimit && heightLimit){ 21031 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 21032 } 21033 else if(widthLimit){ 21034 setResponsive(isBreakingPointWidth); 21035 } 21036 else if(heightLimit){ 21037 setResponsive(isBreakingPointHeight); 21038 } 21039 } 21040 21041 /** 21042 * Adds transition animations for the given element 21043 */ 21044 function addAnimation(container, element){ 21045 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 21046 21047 container.removeClass(NO_TRANSITION); 21048 return container.css({ 21049 '-webkit-transition': transition, 21050 'transition': transition 21051 }); 21052 } 21053 21054 /** 21055 * Remove transition animations for the given element 21056 */ 21057 function removeAnimation(element){ 21058 return element.addClass(NO_TRANSITION); 21059 } 21060 21061 /** 21062 * Activating the vertical navigation bullets according to the given slide name. 21063 */ 21064 function activateNavDots(name, sectionIndex){ 21065 if(options.navigation){ 21066 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 21067 if(name){
21068 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 21069 }else{ 21070 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 21071 } 21072 } 21073 } 21074 21075 /** 21076 * Activating the website main menu elements according to the given slide name. 21077 */ 21078 function activateMenuElement(name){ 21079 if(options.menu){ 21080 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 21081 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 21082 } 21083 } 21084 21085 /** 21086 * Sets to active the current menu and vertical nav items. 21087 */ 21088 function activateMenuAndNav(anchor, index){ 21089 activateMenuElement(anchor); 21090 activateNavDots(anchor, index); 21091 } 21092 21093 /** 21094 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 21095 * from the current section. 21096 */ 21097 function getYmovement(destiny){ 21098 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 21099 var toIndex = destiny.index(SECTION_SEL); 21100 if( fromIndex == toIndex){ 21101 return 'none'; 21102 } 21103 if(fromIndex > toIndex){ 21104 return 'up'; 21105 } 21106 return 'down'; 21107 } 21108 21109 /** 21110 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 21111 * from the current slide. 21112 */ 21113 function getXmovement(fromIndex, toIndex){ 21114 if( fromIndex == toIndex){ 21115 return 'none'; 21116 } 21117 if(fromIndex > toIndex){ 21118 return 'left'; 21119 } 21120 return 'right'; 21121 } 21122 21123 /** 21124 * Checks if the element needs scrollbar and if the user wants to apply it. 21125 * If so it creates it. 21126 * 21127 * @param {Object} element jQuery object of the section or slide 21128 */ 21129 function createScrollBar(element){ 21130 //User doesn't want scrollbar here? Sayonara baby! 21131 if(element.hasClass('fp-noscroll')) return; 21132 21133 //needed to make `scrollHeight` work under Opera 12 21134 element.css('overflow', 'hidden'); 21135 21136 var scrollOverflowHandler = options.scrollOverflowHandler; 21137 var wrap = scrollOverflowHandler.wrapContent(); 21138 //in case element is a slide 21139 var section = element.closest(SECTION_SEL); 21140 var scrollable = scrollOverflowHandler.scrollable(element); 21141 var contentHeight; 21142 21143 //if there was scroll, the contentHeight will be the one in the scrollable section 21144 if(scrollable.length){ 21145 contentHeight = scrollOverflowHandler.scrollHeight(element); 21146 }else{ 21147 contentHeight = element.get(0).scrollHeight; 21148 if(options.verticalCentered){ 21149 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 21150 } 21151 } 21152 21153 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 21154 //Uncode addition 21155 scrollHeight -= UNCODE.bodyBorder*2 + UNCODE.adminBarHeight; 21156 21157 //needs scroll? 21158 if ( contentHeight > scrollHeight) { 21159 //did we already have an scrollbar ? Updating it 21160 if(scrollable.length){ 21161 scrollOverflowHandler.update(element, scrollHeight); 21162 } 21163 //creating the scrolling 21164 else{ 21165 if(options.verticalCentered){ 21166 element.find(TABLE_CELL_SEL).wrapInner(wrap); 21167 }else{ 21168 element.wrapInner(wrap); 21169 } 21170 scrollOverflowHandler.create(element, scrollHeight); 21171 } 21172 } 21173 //removing the scrolling when it is not necessary anymore 21174 else{ 21175 scrollOverflowHandler.remove(element); 21176 } 21177 21178 //undo 21179 element.css('overflow', ''); 21180 } 21181 21182 function addTableClass(element){ 21183 //In case we are styling for the 2nd time as in with reponsiveSlides 21184 if(!element.hasClass(TABLE)){ 21185 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 21186 } 21187 } 21188 21189 function getTableHeight(element){ 21190 var sectionHeight = windowsHeight; 21191 21192 if(options.paddingTop || options.paddingBottom){ 21193 var section = element; 21194 if(!section.hasClass(SECTION)){ 21195 section = element.closest(SECTION_SEL); 21196 } 21197 21198 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 21199 sectionHeight = (windowsHeight - paddings); 21200 } 21201 21202 return sectionHeight; 21203 } 21204 21205 /** 21206 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 21207 */ 21208 function transformContainer(translate3d, animated){ 21209 if(animated){ 21210 addAnimation(container); 21211 }else{ 21212 removeAnimation(container); 21213 } 21214 21215 container.css(getTransforms(translate3d)); 21216 21217 //syncronously removing the class after the animation has been applied. 21218 setTimeout(function(){ 21219 container.removeClass(NO_TRANSITION); 21220 },10); 21221 } 21222 21223 /** 21224 * Gets a section by its anchor / index 21225 */ 21226 function getSectionByAnchor(sectionAnchor){ 21227 if(!sectionAnchor) return []; 21228 21229 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 21230 if(!section.length){ 21231 section = $(SECTION_SEL).eq( sectionAnchor -1); 21232 } 21233 21234 return section; 21235 } 21236 21237 /** 21238 * Gets a slide inside a given section by its anchor / index 21239 */ 21240 function getSlideByAnchor(slideAnchor, section){ 21241 var slides = section.find(SLIDES_WRAPPER_SEL); 21242 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 21243
21244 if(!slide.length){ 21245 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 21246 } 21247 21248 return slide; 21249 } 21250 21251 /** 21252 * Scrolls to the given section and slide anchors 21253 */ 21254 function scrollPageAndSlide(destiny, slide){ 21255 var section = getSectionByAnchor(destiny); 21256 21257 //do nothing if there's no section with the given anchor name 21258 if(!section.length) return; 21259 21260 //default slide 21261 if (typeof slide === 'undefined') { 21262 slide = 0; 21263 } 21264 21265 //we need to scroll to the section and then to the slide 21266 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 21267 scrollPage(section, function(){ 21268 scrollSlider(section, slide); 21269 }); 21270 } 21271 //if we were already in the section 21272 else{ 21273 scrollSlider(section, slide); 21274 } 21275 } 21276 21277 /** 21278 * Scrolls the slider to the given slide destination for the given section 21279 */ 21280 function scrollSlider(section, slideAnchor){ 21281 if(typeof slideAnchor !== 'undefined'){ 21282 var slides = section.find(SLIDES_WRAPPER_SEL); 21283 var destiny = getSlideByAnchor(slideAnchor, section); 21284 21285 if(destiny.length){ 21286 landscapeScroll(slides, destiny); 21287 } 21288 } 21289 } 21290 21291 /** 21292 * Creates a landscape navigation bar with dots for horizontal sliders. 21293 */ 21294 function addSlidesNavigation(section, numSlides){ 21295 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 21296 var nav = section.find(SLIDES_NAV_SEL); 21297 21298 //top or bottom 21299 nav.addClass(options.slidesNavPosition); 21300 21301 for(var i=0; i< numSlides; i++){ 21302 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 21303 } 21304 21305 //centering it 21306 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 21307 21308 nav.find('li').first().find('a').addClass(ACTIVE); 21309 } 21310 21311 21312 /** 21313 * Sets the state of the website depending on the active section/slide. 21314 * It changes the URL hash when needed and updates the body class. 21315 */ 21316 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 21317 var sectionHash = ''; 21318 21319 if(options.anchors.length && !options.lockAnchors){ 21320 21321 //isn't it the first slide? 21322 if(slideIndex){ 21323 if(typeof anchorLink !== 'undefined'){ 21324 sectionHash = anchorLink; 21325 } 21326 21327 //slide without anchor link? We take the index instead. 21328 if(typeof slideAnchor === 'undefined'){ 21329 slideAnchor = slideIndex; 21330 } 21331 21332 lastScrolledSlide = slideAnchor; 21333 setUrlHash(sectionHash + '/' + slideAnchor); 21334 21335 //first slide won't have slide anchor, just the section one 21336 }else if(typeof slideIndex !== 'undefined'){ 21337 lastScrolledSlide = slideAnchor; 21338 setUrlHash(anchorLink); 21339 } 21340 21341 //section without slides 21342 else{ 21343 setUrlHash(anchorLink); 21344 } 21345 } 21346 21347 setBodyClass(); 21348 } 21349 21350 /** 21351 * Sets the URL hash. 21352 */ 21353 function setUrlHash(url){ 21354 //Uncode addition 21355 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 21356 return false; 21357 21358 if(options.recordHistory){ 21359 location.hash = url; 21360 }else{ 21361 //Uncode addition 21362 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 21363 // if(isTouchDevice || isTouch){ 21364 // window.history.replaceState(undefined, undefined, '#' + url); 21365 // }else{ 21366 // var baseUrl = window.location.href.split('#')[0]; 21367 // window.location.replace( baseUrl + '#' + url ); 21368 // } 21369 return false; 21370 } 21371 } 21372 21373 /** 21374 * Gets the anchor for the given slide / section. Its index will be used if there's none. 21375 */ 21376 function getAnchor(element){ 21377 var anchor = element.data('anchor'); 21378 var index = element.index(); 21379 21380 //Slide without anchor link? We take the index instead. 21381 if(typeof anchor === 'undefined'){ 21382 anchor = index; 21383 } 21384 21385 return anchor; 21386 } 21387 21388 /** 21389 * Sets a class for the body of the page depending on the active section / slide 21390 */ 21391 function setBodyClass(){ 21392 var section = $(SECTION_ACTIVE_SEL); 21393 var slide = section.find(SLIDE_ACTIVE_SEL); 21394 21395 var sectionAnchor = getAnchor(section); 21396 var slideAnchor = getAnchor(slide); 21397 21398 var text = String(sectionAnchor); 21399 21400 if(slide.length){ 21401 text = text + '-' + slideAnchor; 21402 } 21403 21404 //changing slash for dash to make it a valid CSS style 21405 text = text.replace('/', '-').replace('#',''); 21406 21407 //removing previous anchor classes 21408 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 21409 $body[0].className = $body[0].className.replace(classRe, ''); 21410 21411 //adding the current anchor 21412 $body.addClass(VIEWING_PREFIX + '-' + text); 21413 } 21414 21415 /** 21416 * Checks for translate3d support 21417 * @return boolean 21418 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 21419 */ 21420 function support3d() { 21421 var el = document.createElement('p'), 21422 has3d, 21423 transforms = { 21424 'webkitTransform':'-webkit-transform', 21425 'OTransform':'-o-transform', 21426 'msTransform':'-ms-transform', 21427 'MozTransform':'-moz-transform', 21428 'transform':'transform' 21429 }; 21430 21431 // Add it to the body to get the computed style. 21432 document.body.insertBefore(el, null); 21433 21434 for (var t in transforms) { 21435 if (el.style[t] !== undefined) { 21436 el.style[t] = 'translate3d(1px,1px,1px)'; 21437 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 21438 } 21439 } 21440 21441 document.body.removeChild(el); 21442 21443 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 21444 } 21445 21446 /** 21447 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 21448 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 21449 */ 21450 function removeMouseWheelHandler(){ 21451 if (document.addEventListener) { 21452 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 21453 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 21454 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 21455 } else { 21456 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 21457 } 21458 } 21459 21460 /** 21461 * Adds the auto scrolling action for the mouse wheel and trackpad. 21462 * After this function is called, the mousewheel and trackpad movements will scroll through sections 21463 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 21464 */ 21465 function addMouseWheelHandler(){ 21466 var prefix = ''; 21467 var _addEventListener; 21468 21469 if (window.addEventListener){ 21470 _addEventListener = "addEventListener"; 21471 }else{ 21472 _addEventListener = "attachEvent"; 21473 prefix = 'on'; 21474 } 21475 21476 // detect available wheel event 21477 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 21478 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 21479 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 21480 21481 21482 if(support == 'DOMMouseScroll'){ 21483 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false); 21484 } 21485 21486 //handle MozMousePixelScroll in older Firefox 21487 else{ 21488 document[ _addEventListener ](prefix + support, MouseWheelHandler, false); 21489 } 21490 } 21491 21492 /** 21493 * Binding the mousemove when the mouse's middle button is pressed 21494 */ 21495 function addMiddleWheelHandler(){ 21496 container 21497 .on('mousedown', mouseDownHandler) 21498 .on('mouseup', mouseUpHandler); 21499 } 21500 21501 /** 21502 * Unbinding the mousemove when the mouse's middle button is released 21503 */ 21504 function removeMiddleWheelHandler(){ 21505 container 21506 .off('mousedown', mouseDownHandler) 21507 .off('mouseup', mouseUpHandler); 21508 } 21509 21510 /** 21511 * Adds the possibility to auto scroll through sections on touch devices. 21512 */ 21513 function addTouchHandler(){ 21514 if(isTouchDevice || isTouch){ 21515 if(options.autoScrolling){ 21516 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 21517 } 21518 21519 $(WRAPPER_SEL) 21520 .off(events.touchstart).on(events.touchstart, touchStartHandler) 21521 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 21522 } 21523 } 21524 21525 /** 21526 * Removes the auto scrolling for touch devices. 21527 */ 21528 function removeTouchHandler(){ 21529 if(isTouchDevice || isTouch){ 21530 $(WRAPPER_SEL) 21531 .off(events.touchstart) 21532 .off(events.touchmove); 21533 } 21534 } 21535 21536 /* 21537 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
21538 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 21539 */ 21540 function getMSPointer(){ 21541 var pointer; 21542 21543 //IE >= 11 & rest of browsers 21544 if(window.PointerEvent){ 21545 pointer = { down: 'pointerdown', move: 'pointermove'}; 21546 } 21547 21548 //IE < 11 21549 else{ 21550 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 21551 } 21552 21553 return pointer; 21554 } 21555 21556 /** 21557 * Gets the pageX and pageY properties depending on the browser. 21558 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 21559 */ 21560 function getEventsPage(e){ 21561 var events = []; 21562 21563 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 21564 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 21565 21566 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 21567 if(isTouch && isReallyTouch(e) && options.scrollBar){ 21568 events.y = e.touches[0].pageY; 21569 events.x = e.touches[0].pageX; 21570 } 21571 21572 return events; 21573 } 21574 21575 /** 21576 * Slides silently (with no animation) the active slider to the given slide. 21577 * @param noCallback {bool} true or defined -> no callbacks 21578 */ 21579 function silentLandscapeScroll(activeSlide, noCallbacks){ 21580 setScrollingSpeed (0, 'internal'); 21581 21582 if(typeof noCallbacks !== 'undefined'){ 21583 //preventing firing callbacks afterSlideLoad etc. 21584 isResizing = true; 21585 } 21586 21587 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 21588 21589 if(typeof noCallbacks !== 'undefined'){ 21590 isResizing = false; 21591 } 21592 21593 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 21594 } 21595 21596 /** 21597 * Scrolls silently (with no animation) the page to the given Y position. 21598 */ 21599 function silentScroll(top){ 21600 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 21601 // that's why we round it to 0. 21602 var roundedTop = Math.round(top); 21603 21604 if (options.css3 && options.autoScrolling && !options.scrollBar){ 21605 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 21606 transformContainer(translate3d, false); 21607 } 21608 else if(options.autoScrolling && !options.scrollBar){ 21609 container.css('top', -roundedTop); 21610 } 21611 else{ 21612 $htmlBody.scrollTop(roundedTop); 21613 } 21614 } 21615 21616 /** 21617 * Returns the cross-browser transform string. 21618 */ 21619 function getTransforms(translate3d){ 21620 return { 21621 '-webkit-transform': translate3d, 21622 '-moz-transform': translate3d, 21623 '-ms-transform':translate3d, 21624 'transform': translate3d 21625 }; 21626 } 21627 21628 /** 21629 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 21630 * @type m (mouse) or k (keyboard) 21631 */ 21632 function setIsScrollAllowed(value, direction, type){ 21633 switch (direction){ 21634 case 'up': isScrollAllowed[type].up = value; break; 21635 case 'down': isScrollAllowed[type].down = value; break; 21636 case 'left': isScrollAllowed[type].left = value; break; 21637 case 'right': isScrollAllowed[type].right = value; break; 21638 case 'all': 21639 if(type == 'm'){ 21640 setAllowScrolling(value); 21641 }else{ 21642 setKeyboardScrolling(value); 21643 } 21644 } 21645 } 21646 21647 /* 21648 * Destroys fullpage.js plugin events and optinally its html markup and styles 21649 */ 21650 function destroy(all){ 21651 setAutoScrolling(false, 'internal'); 21652 setAllowScrolling(false); 21653 setKeyboardScrolling(false); 21654 container.addClass(DESTROYED); 21655 21656 clearTimeout(afterSlideLoadsId); 21657 clearTimeout(afterSectionLoadsId); 21658 clearTimeout(resizeId); 21659 clearTimeout(scrollId); 21660 clearTimeout(scrollId2); 21661 21662 $window 21663 .off('scroll', scrollHandler) 21664 .off('hashchange', hashChangeHandler) 21665 .off('resize', resizeHandler); 21666 21667 $document 21668 .off('click touchstart', SECTION_NAV_SEL + ' a') 21669 .off('mouseenter', SECTION_NAV_SEL + ' li') 21670 .off('mouseleave', SECTION_NAV_SEL + ' li') 21671 .off('click touchstart', SLIDES_NAV_LINK_SEL) 21672 .off('mouseover', options.normalScrollElements) 21673 .off('mouseout', options.normalScrollElements); 21674 21675 $(SECTION_SEL) 21676 .off('click touchstart', SLIDES_ARROW_SEL); 21677 21678 clearTimeout(afterSlideLoadsId); 21679 clearTimeout(afterSectionLoadsId); 21680 21681 //lets make a mess! 21682 if(all){ 21683 destroyStructure(); 21684 } 21685 } 21686 21687 /* 21688 * Removes inline styles added by fullpage.js 21689 */ 21690 function destroyStructure(){ 21691 //reseting the `top` or `translate` properties to 0 21692 silentScroll(0); 21693 21694 //loading all the lazy load content 21695 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 21696 setSrc($(this), 'src'); 21697 }); 21698 21699 container.find('img[data-srcset]').each(function(){ 21700 setSrc($(this), 'srcset'); 21701 }); 21702 21703 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 21704 21705 //removing inline styles 21706 $(SECTION_SEL).css( { 21707 'height': '', 21708 'background-color' : '', 21709 'padding': '' 21710 }); 21711 21712 $(SLIDE_SEL).css( { 21713 'width': '' 21714 }); 21715 21716 container.css({ 21717 'height': '', 21718 'position': '', 21719 '-ms-touch-action': '', 21720 'touch-action': '' 21721 }); 21722 21723 $htmlBody.css({ 21724 'overflow': '', 21725 'height': '' 21726 }); 21727 21728 // remove .fp-enabled class 21729 $('html').removeClass(ENABLED); 21730 21731 // remove .fp-responsive class 21732 $body.removeClass(RESPONSIVE); 21733 21734 // remove all of the .fp-viewing- classes 21735 $.each($body.get(0).className.split(/\s+/), function (index, className) { 21736 if (className.indexOf(VIEWING_PREFIX) === 0) { 21737 $body.removeClass(className); 21738 } 21739 }); 21740 21741 //removing added classes 21742 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 21743 options.scrollOverflowHandler.remove($(this)); 21744 $(this).removeClass(TABLE + ' ' + ACTIVE); 21745 }); 21746 21747 removeAnimation(container); 21748 21749 //Unwrapping content 21750 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 21751 //unwrap not being use in case there's no child element inside and its just text 21752 $(this).replaceWith(this.childNodes); 21753 }); 21754 21755 //removing the applied transition from the fullpage wrapper 21756 container.css({ 21757 '-webkit-transition': 'none', 21758 'transition': 'none' 21759 }); 21760 21761 //scrolling the page to the top with no animation 21762 $htmlBody.scrollTop(0); 21763 21764 //removing selectors 21765 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 21766 $.each(usedSelectors, function(index, value){ 21767 $('.' + value).removeClass(value); 21768 }); 21769 } 21770 21771 /* 21772 * Sets the state for a variable with multiple states (original, and temporal) 21773 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 21774 * This function is used to keep track of both states, the original and the temporal one. 21775 * If type is not 'internal', then we assume the user is globally changing the variable. 21776 */ 21777 function setVariableState(variable, value, type){ 21778 options[variable] = value;
21779 if(type !== 'internal'){ 21780 originals[variable] = value; 21781 } 21782 } 21783 21784 /** 21785 * Displays warnings 21786 */ 21787 function displayWarnings(){ 21788 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 21789 //UNCODE.addition 21790 // if($('html').hasClass(ENABLED)){ 21791 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 21792 // return; 21793 // } 21794 21795 // Disable mutually exclusive settings 21796 //UNCODE.addition 21797 // if (options.continuousVertical && 21798 // (options.loopTop || options.loopBottom)) { 21799 // options.continuousVertical = false; 21800 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21801 // } 21802 21803 // if(options.scrollBar && options.scrollOverflow){ 21804 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 21805 // } 21806 21807 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 21808 // options.continuousVertical = false;
21809 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 21810 // } 21811 21812 //using extensions? Wrong file! 21813 $.each(extensions, function(index, extension){ 21814 //is the option set to true? 21815 if(options[extension]){ 21816 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 21817 } 21818 }); 21819 21820 //anchors can not have the same value as any element ID or NAME 21821 $.each(options.anchors, function(index, name){ 21822 21823 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 21824 var nameAttr = $document.find('[name]').filter(function() { 21825 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 21826 }); 21827 21828 var idAttr = $document.find('[id]').filter(function() { 21829 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 21830 }); 21831 21832 if(idAttr.length || nameAttr.length ){ 21833 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 21834 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 21835 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 21836 } 21837 }); 21838 } 21839 21840 /** 21841 * Shows a message in the console of the given type. 21842 */ 21843 function showError(type, text){ 21844 console && console[type] && console[type]('fullPage: ' + text); 21845 } 21846 21847 }; //end of $.fn.fullpage 21848 21849 if(typeof IScroll !== 'undefined'){ 21850 /* 21851 * Turns iScroll `mousewheel` option off dynamically 21852 * https://github.com/cubiq/iscroll/issues/1036 21853 */ 21854 IScroll.prototype.wheelOn = function () { 21855 this.wrapper.addEventListener('wheel', this); 21856 this.wrapper.addEventListener('mousewheel', this); 21857 this.wrapper.addEventListener('DOMMouseScroll', this); 21858 }; 21859 21860 /* 21861 * Turns iScroll `mousewheel` option on dynamically 21862 * https://github.com/cubiq/iscroll/issues/1036 21863 */ 21864 IScroll.prototype.wheelOff = function () { 21865 this.wrapper.removeEventListener('wheel', this); 21866 this.wrapper.removeEventListener('mousewheel', this); 21867 this.wrapper.removeEventListener('DOMMouseScroll', this); 21868 }; 21869 } 21870 21871 /** 21872 * An object to handle overflow scrolling. 21873 * This uses jquery.slimScroll to accomplish overflow scrolling. 21874 * It is possible to pass in an alternate scrollOverflowHandler 21875 * to the fullpage.js option that implements the same functions 21876 * as this handler. 21877 * 21878 * @type {Object} 21879 */ 21880 var iscrollHandler = { 21881 refreshId: null, 21882 iScrollInstances: [], 21883 21884 // Enables or disables the mouse wheel for the active section or all slides in it 21885 toggleWheel: function(value){ 21886 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 21887 scrollable.each(function(){ 21888 var iScrollInstance = $(this).data('iscrollInstance'); 21889 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 21890 if(value){ 21891 iScrollInstance.wheelOn(); 21892 } 21893 else{ 21894 iScrollInstance.wheelOff(); 21895 } 21896 } 21897 }); 21898 }, 21899 21900 /** 21901 * Turns off iScroll for the destination section. 21902 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would 21903 * scroll the destination section/slide before the sections animations ends. 21904 */ 21905 onLeave: function(){ 21906 iscrollHandler.toggleWheel(false); 21907 }, 21908 21909 // Turns off iScroll for the leaving section 21910 beforeLeave: function(){ 21911 iscrollHandler.onLeave() 21912 }, 21913 21914 // Turns on iScroll on section load 21915 afterLoad: function(){ 21916 iscrollHandler.toggleWheel(true); 21917 }, 21918 21919 /** 21920 * Called when overflow scrolling is needed for a section. 21921 * 21922 * @param {Object} element jQuery object containing current section 21923 * @param {Number} scrollHeight Current window height in pixels 21924 */ 21925 create: function(element, scrollHeight) { 21926 var scrollable = element.find(SCROLLABLE_SEL); 21927 21928 scrollable.height(scrollHeight); 21929 scrollable.each(function() { 21930 var $this = $(this); 21931 var iScrollInstance = $this.data('iscrollInstance'); 21932 if (iScrollInstance) { 21933 $.each(iscrollHandler.iScrollInstances, function(){ 21934 $(this).destroy(); 21935 }); 21936 } 21937 21938 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 21939 iscrollHandler.iScrollInstances.push(iScrollInstance); 21940 21941 //off by default until the section gets active 21942 iScrollInstance.wheelOff(); 21943 21944 $this.data('iscrollInstance', iScrollInstance); 21945 }); 21946 }, 21947 21948 /** 21949 * Return a boolean depending on whether the scrollable element is a 21950 * the end or at the start of the scrolling depending on the given type. 21951 * 21952 * @param {String} type Either 'top' or 'bottom' 21953 * @param {Object} scrollable jQuery object for the scrollable element 21954 * @return {Boolean} 21955 */ 21956 isScrolled: function(type, scrollable) { 21957 var scroller = scrollable.data('iscrollInstance'); 21958 21959 //no scroller? 21960 if (!scroller) { 21961 return true; 21962 } 21963 21964 if (type === 'top') { 21965 return scroller.y >= 0 && !scrollable.scrollTop(); 21966 } else if (type === 'bottom') { 21967 return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHe
21967ight() >= scrollable[0].scrollHeight; 21968 } 21969 }, 21970 21971 /** 21972 * Returns the scrollable element for the given section. 21973 * If there are landscape slides, will only return a scrollable element 21974 * if it is in the active slide. 21975 * 21976 * @param {Object} activeSection jQuery object containing current section 21977 * @return {Boolean} 21978 */ 21979 scrollable: function(activeSection){ 21980 // if there are landscape slides, we check if the scrolling bar is in the current one or not 21981 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 21982 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 21983 } 21984 return activeSection.find(SCROLLABLE_SEL); 21985 }, 21986 21987 /** 21988 * Returns the scroll height of the wrapped content. 21989 * If this is larger than the window height minus section padding, 21990 * overflow scrolling is needed. 21991 * 21992 * @param {Object} element jQuery object containing current section 21993 * @return {Number} 21994 */ 21995 scrollHeight: function(element) { 21996 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 21997 }, 21998 21999 /** 22000 * Called when overflow scrolling is no longer needed for a section. 22001 * 22002 * @param {Object} element jQuery object containing current section 22003 */ 22004 remove: function(element) { 22005 var scrollable = element.find(SCROLLABLE_SEL); 22006 if (scrollable.length) { 22007 var iScrollInstance = scrollable.data('iscrollInstance'); 22008 iScrollInstance.destroy(); 22009 22010 scrollable.data('iscrollInstance', null); 22011 } 22012 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 22013 }, 22014 22015 /** 22016 * Called when overflow scrolling has already been setup but the 22017 * window height has potentially changed. 22018 * 22019 * @param {Object} element jQuery object containing current section 22020 * @param {Number} scrollHeight Current window height in pixels 22021 */ 22022 update: function(element, scrollHeight) { 22023 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 22024 //short period of time. 22025 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 22026 clearTimeout(iscrollHandler.refreshId); 22027 iscrollHandler.refreshId = setTimeout(function(){ 22028 $.each(iscrollHandler.iScrollInstances, function(){ 22029 $(this).get(0).refresh(); 22030 }); 22031 }, 150); 22032 22033 //updating the wrappers height 22034 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 22035 }, 22036 22037 /** 22038 * Called to get any additional elements needed to wrap the section 22039 * content in order to facilitate overflow scrolling. 22040 * 22041 * @return {String|Object} Can be a string containing HTML, 22042 * a DOM element, or jQuery object. 22043 */ 22044 wrapContent: function() { 22045 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 22046 } 22047 }; 22048}); 22049 22050 22051 22052/* ======================================================================== 22053 * Bootstrap: collapse.js v3.1.1 22054 * http://getbootstrap.com/javascript/#collapse 22055 * ======================================================================== 22056 * Copyright 2011-2014 Twitter, Inc. 22057 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22058 * ======================================================================== */ 22059 22060 22061+function ($) { 22062 'use strict'; 22063 22064 // COLLAPSE PUBLIC CLASS DEFINITION 22065 // ================================ 22066 22067 var Collapse = function (element, options) { 22068 this.$element = $(element) 22069 this.options = $.extend({}, Collapse.DEFAULTS, options) 22070 this.transitioning = null 22071 22072 if (this.options.parent) this.$parent = $(this.options.parent) 22073 if (this.options.toggle) this.toggle() 22074 } 22075 22076 Collapse.DEFAULTS = { 22077 toggle: true 22078 } 22079 22080 Collapse.prototype.dimension = function () { 22081 var hasWidth = this.$element.hasClass('width') 22082 return hasWidth ? 'width' : 'height' 22083 } 22084 22085 Collapse.prototype.show = function () { 22086 if (this.transitioning || this.$element.hasClass('in')) return 22087 22088 var startEvent = $.Event('show.bs.collapse') 22089 this.$element.trigger(startEvent) 22090 if (startEvent.isDefaultPrevented()) return 22091 22092 var actives = this.$parent && this.$parent.find('> .panel > .in') 22093 22094 if (actives && actives.length) { 22095 var hasData = actives.data('bs.collapse') 22096 if (hasData && hasData.transitioning) return 22097 actives.collapse('hide') 22098 hasData || actives.data('bs.collapse', null) 22099 } 22100 22101 var dimension = this.dimension() 22102 22103 this.$element 22104 .removeClass('collapse') 22105 .addClass('collapsing')[dimension](0) 22106 22107 this.transitioning = 1 22108 22109 var complete = function (e) { 22110 if (e && e.target != this.$element[0]) return 22111 this.$element 22112 .removeClass('collapsing') 22113 .addClass('collapse in')[dimension]('auto') 22114 this.transitioning = 0 22115 this.$element.trigger('shown.bs.collapse') 22116 } 22117 22118 if (!$.support.transition) return complete.call(this) 22119 22120 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 22121 22122 this.$element 22123 .one($.support.transition.end, $.proxy(complete, this)) 22124 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 22125 } 22126 22127 Collapse.prototype.hide = function () { 22128 if (this.transitioning || !this.$element.hasClass('in')) return 22129 22130 var startEvent = $.Event('hide.bs.collapse') 22131 this.$element.trigger(startEvent) 22132 if (startEvent.isDefaultPrevented()) return 22133 22134 var dimension = this.dimension() 22135 22136 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 22137 22138 this.$element 22139 .addClass('collapsing') 22140 .removeClass('collapse') 22141 .removeClass('in') 22142 22143 this.transitioning = 1 22144 22145 var complete = function (e) { 22146 if (e && e.target != this.$element[0]) return 22147 this.transitioning = 0 22148 this.$element 22149 .trigger('hidden.bs.collapse') 22150 .removeClass('collapsing') 22151 .addClass('collapse') 22152 } 22153 22154 if (!$.support.transition) return complete.call(this) 22155 22156 this.$element 22157 [dimension](0) 22158 .one($.support.transition.end, $.proxy(complete, this)) 22159 .emulateTransitionEnd(350) 22160 } 22161 22162 Collapse.prototype.toggle = function () { 22163 this[this.$element.hasClass('in') ? 'hide' : 'show']() 22164 } 22165 22166 22167 // COLLAPSE PLUGIN DEFINITION 22168 // ========================== 22169 22170 var old = $.fn.collapse 22171 22172 $.fn.collapse = function (option) { 22173 return this.each(function () { 22174 var $this = $(this) 22175 var data = $this.data('bs.collapse') 22176 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 22177 22178 if (!data && options.toggle && option == 'show') option = !option 22179 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 22180 if (typeof option == 'string') data[option]() 22181 }) 22182 } 22183 22184 $.fn.collapse.Constructor = Collapse 22185 22186 22187 // COLLAPSE NO CONFLICT 22188 // ==================== 22189 22190 $.fn.collapse.noConflict = function () { 22191 $.fn.collapse = old 22192 return this 22193 } 22194 22195 22196 // COLLAPSE DATA-API 22197 // ================= 22198 22199 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 22200 var $this = $(this), href 22201 var target = $this.attr('data-target') 22202 || e.preventDefault() 22203 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 22204 //Edited by Uncode to replace ID in panel [START] 22205 var _target = href.replace(/^#/, ""); 22206 if ( $('[data-id="' + _target + '"]').length ) { 22207 var $target = $('[data-id="' + _target + '"]') 22208 } else { 22209 var $target = $(target) 22210 } 22211 //Edited by Uncode to replace ID in panel [END] 22212 var data = $target.data('bs.collapse') 22213 var option = data ? 'toggle' : $this.data() 22214 var parent = $this.attr('data-parent') 22215 var $parent = parent && $(parent) 22216 22217 if (!data || !data.transitioning) { 22218 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 22219 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 22220 } 22221 22222 $target.collapse(option) 22223 }) 22224 22225}(jQuery); 22226 22227 22228/* ======================================================================== 22229 * Bootstrap: tab.js v3.1.1 22230 * http://getbootstrap.com/javascript/#tabs 22231 * ======================================================================== 22232 * Copyright 2011-2014 Twitter, Inc. 22233 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22234 * ======================================================================== */ 22235 22236 22237+function ($) { 22238 'use strict'; 22239 22240 // TAB CLASS DEFINITION 22241 // ==================== 22242 22243 var Tab = function (element) { 22244 this.element = $(element) 22245 } 22246 22247 Tab.prototype.show = function () { 22248 var $this = this.element 22249 var $ul = $this.closest('ul:not(.dropdown-menu)') 22250 var selector = $this.data('target') 22251 22252 if (!selector) { 22253 selector = $this.attr('href') 22254 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 22255 } 22256 22257 if ($this.parent('li').hasClass('active')) return 22258 22259 var previous = $ul.find('.active:last a')[0] 22260 var e = $.Event('show.bs.tab', { 22261 relatedTarget: previous 22262 }) 22263 22264 $this.trigger(e) 22265 22266 if (e.isDefaultPrevented()) return 22267 22268 //Edited by Uncode to replace ID in panel [START] 22269 var _target = selector.replace(/^#/, ""); 22270 if ( $('[data-id="' + _target + '"]').length ) 22271 var $target = $('[data-id="' + _target + '"]') 22272 else 22273 var $target = $(selector) 22274 //Edited by Uncode to replace ID in panel [END] 22275 22276 this.activate($this.parent('li'), $ul) 22277 this.activate($target, $target.parent(), function () { 22278 $this.trigger({ 22279 type: 'shown.bs.tab', 22280 relatedTarget: previous 22281 }) 22282 }) 22283 } 22284 22285 Tab.prototype.activate = function (element, container, callback) { 22286 var $active = container.find('> .active') 22287 var transition = callback 22288 && $.support.transition 22289 && $active.hasClass('fade') 22290 22291 function next() { 22292 $active 22293 .removeClass('active') 22294 .find('> .dropdown-menu > .active') 22295 .removeClass('active') 22296 22297 element.addClass('active') 22298 22299 if (transition) { 22300 element[0].offsetWidth // reflow for transition 22301 element.addClass('in') 22302 } else { 22303 element.removeClass('fade') 22304 } 22305 22306 if (element.parent('.dropdown-menu')) { 22307 element.closest('li.dropdown').addClass('active') 22308 } 22309 22310 callback && callback() 22311 } 22312 22313 transition ? 22314 $active 22315 .one($.support.transition.end, next) 22316 .emulateTransitionEnd(150) : 22317 next() 22318 22319 $active.removeClass('in') 22320 } 22321 22322 22323 // TAB PLUGIN DEFINITION 22324 // ===================== 22325 22326 var old = $.fn.tab 22327 22328 $.fn.tab = function ( option ) { 22329 return this.each(function () { 22330 var $this = $(this) 22331 var data = $this.data('bs.tab') 22332 22333 if (!data) $this.data('bs.tab', (data = new Tab(this))) 22334 if (typeof option == 'string') data[option]() 22335 }) 22336 } 22337 22338 $.fn.tab.Constructor = Tab 22339 22340 22341 // TAB NO CONFLICT 22342 // =============== 22343 22344 $.fn.tab.noConflict = function () { 22345 $.fn.tab = old 22346 return this 22347 } 22348 22349 22350 // TAB DATA-API 22351 // ============ 22352 22353 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 22354 e.preventDefault() 22355 $(this).tab('show') 22356 }) 22357 22358}(jQuery); 22359 22360 22361/* ======================================================================== 22362 * Bootstrap: tooltip.js v3.1.1 22363 * http://getbootstrap.com/javascript/#tooltip 22364 * Inspired by the original jQuery.tipsy by Jason Frame 22365 * ======================================================================== 22366 * Copyright 2011-2014 Twitter, Inc. 22367 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22368 * ======================================================================== */ 22369 22370 22371+function ($) { 22372 'use strict'; 22373 22374 // TOOLTIP PUBLIC CLASS DEFINITION 22375 // =============================== 22376 22377 var Tooltip = function (element, options) { 22378 this.type = 22379 this.options = 22380 this.enabled = 22381 this.timeout = 22382 this.hoverState = 22383 this.$element = null 22384 22385 this.init('tooltip', element, options) 22386 } 22387 22388 Tooltip.DEFAULTS = { 22389 animation: true, 22390 placement: 'top', 22391 selector: false, 22392 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 22393 trigger: 'hover focus', 22394 title: '', 22395 delay: 0, 22396 html: false, 22397 container: false, 22398 viewport: { 22399 selector: 'body', 22400 padding: 0 22401 } 22402 } 22403 22404 Tooltip.prototype.init = function (type, element, options) { 22405 this.enabled = true 22406 this.type = type 22407 this.$element = $(element) 22408 this.options = this.getOptions(options) 22409 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 22410 22411 var triggers = this.options.trigger.split(' ') 22412 22413 for (var i = triggers.length; i--;) { 22414 var trigger = triggers[i] 22415 22416 if (trigger == 'click') { 22417 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 22418 } else if (trigger != 'manual') { 22419 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 22420 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 22421 22422 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 22423 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 22424 } 22425 } 22426 22427 this.options.selector ? 22428 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 22429 this.fixTitle() 22430 } 22431 22432 Tooltip.prototype.getDefaults = function () { 22433 return Tooltip.DEFAULTS 22434 } 22435 22436 Tooltip.prototype.getOptions = function (options) { 22437 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 22438 22439 if (options.delay && typeof options.delay == 'number') { 22440 options.delay = { 22441 show: options.delay, 22442 hide: options.delay 22443 } 22444 } 22445 22446 return options 22447 } 22448 22449 Tooltip.prototype.getDelegateOptions = function () { 22450 var options = {} 22451 var defaults = this.getDefaults() 22452 22453 this._options && $.each(this._options, function (key, value) { 22454 if (defaults[key] != value) options[key] = value 22455 }) 22456 22457 return options 22458 } 22459 22460 Tooltip.prototype.enter = function (obj) { 22461 var self = obj instanceof this.constructor ? 22462 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22463 22464 clearTimeout(self.timeout) 22465 22466 self.hoverState = 'in' 22467 22468 if (!self.options.delay || !self.options.delay.show) return self.show() 22469 22470 self.timeout = setTimeout(function () { 22471 if (self.hoverState == 'in') self.show() 22472 }, self.options.delay.show) 22473 } 22474 22475 Tooltip.prototype.leave = function (obj) { 22476 var self = obj instanceof this.constructor ? 22477 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 22478 22479 clearTimeout(self.timeout) 22480 22481 self.hoverState = 'out' 22482 22483 if (!self.options.delay || !self.options.delay.hide) return self.hide() 22484 22485 self.timeout = setTimeout(function () { 22486 if (self.hoverState == 'out') self.hide() 22487 }, self.options.delay.hide) 22488 } 22489 22490 Tooltip.prototype.show = function () { 22491 var e = $.Event('show.bs.' + this.type) 22492 22493 if (this.hasContent() && this.enabled) { 22494 this.$element.trigger(e) 22495 22496 if (e.isDefaultPrevented()) return 22497 var that = this; 22498 22499 var $tip = this.tip() 22500 22501 this.setContent() 22502 22503 if (this.options.animation) $tip.addClass('fade') 22504 22505 var placement = typeof this.options.placement == 'function' ? 22506 this.options.placement.call(this, $tip[0], this.$element[0]) : 22507 this.options.placement 22508 22509 var autoToken = /\s?auto?\s?/i 22510 var autoPlace = autoToken.test(placement)
22511 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 22512 22513 $tip 22514 .detach() 22515 .css({ top: 0, left: 0, display: 'block' }) 22516 .addClass(placement) 22517 22518 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 22519 22520 var pos = this.getPosition() 22521 var actualWidth = $tip[0].offsetWidth 22522 var actualHeight = $tip[0].offsetHeight 22523 22524 if (autoPlace) { 22525 var orgPlacement = placement 22526 var $parent = this.$element.parent() 22527 var parentDim = this.getPosition($parent) 22528 22529 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 22530 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 22531 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 22532 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 22533 placement 22534 22535 $tip 22536 .removeClass(orgPlacement) 22537 .addClass(placement) 22538 } 22539 22540 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 22541 22542 this.applyPlacement(calculatedOffset, placement) 22543 this.hoverState = null 22544 22545 var complete = function() { 22546 that.$element.trigger('shown.bs.' + that.type) 22547 } 22548 22549 $.support.transition && this.$tip.hasClass('fade') ? 22550 $tip 22551 .one($.support.transition.end, complete) 22552 .emulateTransitionEnd(150) : 22553 complete() 22554 } 22555 } 22556 22557 Tooltip.prototype.applyPlacement = function (offset, placement) { 22558 var $tip = this.tip() 22559 var width = $tip[0].offsetWidth 22560 var height = $tip[0].offsetHeight 22561 22562 // manually read margins because getBoundingClientRect includes difference 22563 var marginTop = parseInt($tip.css('margin-top'), 10) 22564 var marginLeft = parseInt($tip.css('margin-left'), 10) 22565 22566 // we must check for NaN for ie 8/9 22567 if (isNaN(marginTop)) marginTop = 0 22568 if (isNaN(marginLeft)) marginLeft = 0 22569 22570 offset.top = offset.top + marginTop 22571 offset.left = offset.left + marginLeft 22572 22573 // $.fn.offset doesn't round pixel values 22574 // so we use setOffset directly with our own function B-0 22575 $.offset.setOffset($tip[0], $.extend({ 22576 using: function (props) { 22577 $tip.css({ 22578 top: Math.round(props.top), 22579 left: Math.round(props.left) 22580 }) 22581 } 22582 }, offset), 0) 22583 22584 $tip.addClass('in') 22585 22586 // check to see if placing tip in new offset caused the tip to resize itself 22587 var actualWidth = $tip[0].offsetWidth 22588 var actualHeight = $tip[0].offsetHeight 22589 22590 if (placement == 'top' && actualHeight != height) { 22591 offset.top = offset.top + height - actualHeight 22592 } 22593 22594 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 22595 22596 if (delta.left) offset.left += delta.left 22597 else offset.top += delta.top 22598 22599 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 22600 var arrowPosition = delta.left ? 'left' : 'top' 22601 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 22602 22603 $tip.offset(offset) 22604 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 22605 } 22606 22607 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 22608 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 22609 } 22610 22611 Tooltip.prototype.setContent = function () { 22612 var $tip = this.tip() 22613 var title = this.getTitle() 22614 22615 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 22616 $tip.removeClass('fade in top bottom left right') 22617 } 22618 22619 Tooltip.prototype.hide = function () { 22620 var that = this 22621 var $tip = this.tip() 22622 var e = $.Event('hide.bs.' + this.type) 22623 22624 function complete() { 22625 if (that.hoverState != 'in') $tip.detach() 22626 that.$element.trigger('hidden.bs.' + that.type) 22627 } 22628 22629 this.$element.trigger(e) 22630 22631 if (e.isDefaultPrevented()) return 22632 22633 $tip.removeClass('in') 22634 22635 $.support.transition && this.$tip.hasClass('fade') ? 22636 $tip 22637 .one($.support.transition.end, complete) 22638 .emulateTransitionEnd(150) : 22639 complete() 22640 22641 this.hoverState = null 22642 22643 return this 22644 } 22645 22646 Tooltip.prototype.fixTitle = function () { 22647 var $e = this.$element 22648 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 22649 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 22650 } 22651 } 22652 22653 Tooltip.prototype.hasContent = function () { 22654 return this.getTitle() 22655 } 22656 22657 Tooltip.prototype.getPosition = function ($element) { 22658 $element = $element || this.$element 22659 var el = $element[0] 22660 var isBody = el.tagName == 'BODY' 22661 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 22662 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 22663 width: isBody ? $(window).width() : $element.outerWidth(), 22664 height: isBody ? $(window).height() : $element.outerHeight() 22665 }, isBody ? {top: 0, left: 0} : $element.offset()) 22666 } 22667 22668 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 22669 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22670 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 22671 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 22672 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 22673 22674 } 22675 22676 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 22677 var delta = { top: 0, left: 0 } 22678 if (!this.$viewport) return delta 22679 22680 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 22681 var viewportDimensions = this.getPosition(this.$viewport) 22682 22683 if (/right|left/.test(placement)) { 22684 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 22685 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 22686 if (topEdgeOffset < viewportDimensions.top) { // top overflow 22687 delta.top = viewportDimensions.top - topEdgeOffset 22688 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 22689 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
22689EdgeOffset 22690 } 22691 } else { 22692 var leftEdgeOffset = pos.left - viewportPadding 22693 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 22694 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 22695 delta.left = viewportDimensions.left - leftEdgeOffset 22696 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 22697 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 22698 } 22699 } 22700 22701 return delta 22702 } 22703 22704 Tooltip.prototype.getTitle = function () { 22705 var title 22706 var $e = this.$element 22707 var o = this.options 22708 22709 title = $e.attr('data-original-title') 22710 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 22711 22712 return title 22713 } 22714 22715 Tooltip.prototype.tip = function () { 22716 return this.$tip = this.$tip || $(this.options.template) 22717 } 22718 22719 Tooltip.prototype.arrow = function () { 22720 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 22721 } 22722 22723 Tooltip.prototype.validate = function () { 22724 if (!this.$element[0].parentNode) { 22725 this.hide() 22726 this.$element = null 22727 this.options = null 22728 } 22729 } 22730 22731 Tooltip.prototype.enable = function () { 22732 this.enabled = true 22733 } 22734 22735 Tooltip.prototype.disable = function () { 22736 this.enabled = false 22737 } 22738 22739 Tooltip.prototype.toggleEnabled = function () { 22740 this.enabled = !this.enabled 22741 } 22742 22743 Tooltip.prototype.toggle = function (e) { 22744 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 22745 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 22746 } 22747 22748 Tooltip.prototype.destroy = function () { 22749 clearTimeout(this.timeout) 22750 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 22751 } 22752 22753 22754 // TOOLTIP PLUGIN DEFINITION 22755 // ========================= 22756 22757 var old = $.fn.tooltip 22758 22759 $.fn.tooltip = function (option) { 22760 return this.each(function () { 22761 var $this = $(this) 22762 var data = $this.data('bs.tooltip') 22763 var options = typeof option == 'object' && option 22764 22765 if (!data && option == 'destroy') return 22766 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 22767 if (typeof option == 'string') data[option]() 22768 }) 22769 } 22770 22771 $.fn.tooltip.Constructor = Tooltip 22772 22773 22774 // TOOLTIP NO CONFLICT 22775 // =================== 22776 22777 $.fn.tooltip.noConflict = function () { 22778 $.fn.tooltip = old 22779 return this 22780 } 22781 22782}(jQuery); 22783 22784 22785/* ======================================================================== 22786 * Bootstrap: transition.js v3.1.1 22787 * http://getbootstrap.com/javascript/#transitions 22788 * ======================================================================== 22789 * Copyright 2011-2014 Twitter, Inc. 22790 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 22791 * ======================================================================== */ 22792 22793 22794+function ($) { 22795 'use strict'; 22796 22797 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 22798 // ============================================================ 22799 22800 function transitionEnd() { 22801 var el = document.createElement('bootstrap') 22802 22803 var transEndEventNames = { 22804 WebkitTransition : 'webkitTransitionEnd', 22805 MozTransition : 'transitionend', 22806 OTransition : 'oTransitionEnd otransitionend', 22807 transition : 'transitionend' 22808 } 22809 22810 for (var name in transEndEventNames) { 22811 if (el.style[name] !== undefined) { 22812 return { end: transEndEventNames[name] } 22813 } 22814 } 22815 22816 return false // explicit for ie8 ( ._.) 22817 } 22818 22819 // http://blog.alexmaccaw.com/css-transitions 22820 $.fn.emulateTransitionEnd = function (duration) { 22821 var called = false, $el = this 22822 $(this).one($.support.transition.end, function () { called = true }) 22823 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 22824 setTimeout(callback, duration) 22825 return this 22826 } 22827 22828 $(function () { 22829 $.support.transition = transitionEnd() 22830 }) 22831 22832}(jQuery);
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.