1/* ---------------------------------------------------------- 2 * Plugins 3 * ---------------------------------------------------------- */ 4 5(function(window, $) { 6 'use strict'; 7 var counter = 0, 8 $headCache = $('head'), 9 oldBigText = window.BigText, 10 oldjQueryMethod = $.fn.bigtext, 11 BigText = { 12 DEBUG_MODE: false, 13 DEFAULT_MIN_FONT_SIZE_PX: null, 14 DEFAULT_MAX_FONT_SIZE_PX: 528, 15 GLOBAL_STYLE_ID: 'bigtext-style', 16 STYLE_ID: 'bigtext-id', 17 LINE_CLASS_PREFIX: 'bigtext-line', 18 EXEMPT_CLASS: 'bigtext-exempt', 19 noConflict: function(restore) 20 { 21 if(restore) { 22 $.fn.bigtext = oldjQueryMethod; 23 window.BigText = oldBigText; 24 } 25 return BigText; 26 }, 27 supports: { 28 wholeNumberFontSizeOnly: (function() { 29 if( !( 'getComputedStyle' in window ) ) { 30 return true; 31 } 32 var test = $('<div/>').css({ 33 position: 'absolute', 34 'font-size': '14.1px' 35 }).insertBefore( $('script').eq(0) ), 36 computedStyle = window.getComputedStyle( test[0], null ); 37 38 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 39 test.remove(); 40 return ret; 41 })() 42 }, 43 init: function() { 44 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 45 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 46 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 47 } 48 }, 49 bindResize: function(eventName, resizeFunction) { 50 var timeoutId; 51 $(window).unbind(eventName).bind(eventName, function() { 52 if( timeoutId ) { 53 clearTimeout( timeoutId ); 54 } 55 timeoutId = setTimeout( resizeFunction, 300 ); 56 }); 57 }, 58 getStyleId: function(id) 59 { 60 return BigText.STYLE_ID + '-' + id; 61 }, 62 generateStyleTag: function(id, css) 63 { 64 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 65 }, 66 clearCss: function(id) 67 { 68 var styleId = BigText.getStyleId(id); 69 $('#' + styleId).remove(); 70 }, 71 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 72 { 73 var css = []; 74 75 BigText.clearCss(id); 76 77 for(var j=0, k=linesFontSizes.length; j<k; j++) { 78 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 79 (minFontSizes[j] ? ' white-space: normal;' : '') + 80 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 81 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 82 '}'); 83 } 84 85 return BigText.generateStyleTag(BigText.getStyleId(id), css); 86 }, 87 jQueryMethod: function(options) 88 { 89 BigText.init(); 90 91 options = $.extend({ 92 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 93 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 94 childSelector: '', 95 resize: true 96 }, options || {}); 97 98 this.each(function() 99 { 100 var $t = $(this).addClass('bigtext'), 101 maxWidth = $t.width(), 102 id = $t.attr('id'), 103 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 104 105 if(!id) { 106 id = 'bigtext-id' + (counter++); 107 $t.attr('id', id); 108 } 109 110 if(options.resize) { 111 BigText.bindResize('resize.bigtext-event-' + id, function() 112 { 113 // TODO only call this if the width has changed. 114 BigText.jQueryMethod.call($('#' + id), options); 115 }); 116 } 117 118 BigText.clearCss(id); 119 120 $children.addClass(function(lineNumber, className) 121 { 122 // remove existing line classes. 123 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 124 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 125 }); 126 127 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 128 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 129 }); 130 131 return this.trigger('bigtext:complete'); 132 } 133 }; 134 135 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 136 { 137 var width; 138 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 139 $line.css(property, size + units); 140 141 width = $line.width(); 142 143 if(width >= maxWidth) { 144 145 $line.css(property, ''); 146 147 if(width === maxWidth) { 148 return { 149 match: 'exact', 150 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 151 }; 152 } 153 154 // Since this is an estimate, we calculate how far over the width we went with the new value. 155 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 156 // Otherwise, we revert to the underestimate. 157 var under = maxWidth - previousWidth, 158 over = width - maxWidth; 159 160 return { 161 match: 'estimate', 162 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 163 }; 164 } 165 166 return width; 167 } 168 169 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 170 { 171 var $c = $t.clone(true) 172 .addClass('bigtext-cloned') 173 .css({ 174 fontFamily: $t.css('font-family'), 175 textTransform: $t.css('text-transform'), 176 wordSpacing: $t.css('word-spacing'), 177 letterSpacing: $t.css('letter-spacing'), 178 position: 'absolute', 179 left: BigText.DEBUG_MODE ? 0 : -9999, 180 top: BigText.DEBUG_MODE ? 0 : -9999
181 }) 182 .appendTo(document.body); 183 184 // font-size isn't the only thing we can modify, we can also mess with: 185 // word-spacing and letter-spacing. WebKit does not respect subpixel 186 // letter-spacing, word-spacing, or font-size. 187 // TODO try -webkit-transform: scale() as a workaround. 188 var fontSizes = [], 189 wordSpacings = [], 190 minFontSizes = [], 191 ratios = []; 192 193 $children.css('float', 'left').each(function() { 194 var $line = $(this), 195 // TODO replace 8, 4 with a proportional size to the calculated font-size. 196 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 197 lineMax, 198 newFontSize; 199 200 if($line.hasClass(BigText.EXEMPT_CLASS)) { 201 fontSizes.push(null); 202 ratios.push(null); 203 minFontSizes.push(false); 204 return; 205 } 206 207 // TODO we can cache this ratio? 208 var autoGuessSubtraction = 32, // font size in px 209 currentFontSize = parseFloat($line.css('font-size')), 210 ratio = ( $line.width() / currentFontSize ).toFixed(6); 211 212 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 213 214 outer: for(var m=0, n=intervals.length; m<n; m++) { 215 inner: for(var j=1, k=10; j<=k; j++) { 216 if(newFontSize + j*intervals[m] > maxFontSize) { 217 newFontSize = maxFontSize; 218 break outer; 219 } 220 221 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 222 if(typeof lineMax !== 'number') { 223 newFontSize = lineMax.size; 224 225 if(lineMax.match === 'exact') { 226 break outer; 227 } 228 break inner; 229 } 230 } 231 } 232 233 ratios.push(maxWidth / newFontSize); 234 235 if(newFontSize > maxFontSize) { 236 fontSizes.push(maxFontSize); 237 minFontSizes.push(false); 238 } else if(!!minFontSize && newFontSize < minFontSize) { 239 fontSizes.push(minFontSize); 240 minFontSizes.push(true); 241 } else { 242 fontSizes.push(newFontSize); 243 minFontSizes.push(false); 244 } 245 }).each(function(lineNumber) { 246 var $line = $(this), 247 wordSpacing = 0, 248 interval = 1, 249 maxWordSpacing; 250 251 if($line.hasClass(BigText.EXEMPT_CLASS)) { 252 wordSpacings.push(null); 253 return; 254 } 255 256 // must re-use font-size, even though it was removed above. 257 $line.css('font-size', fontSizes[lineNumber] + 'px'); 258 259 for(var m=1, n=3; m<n; m+=interval) { 260 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 261 if(typeof maxWordSpacing !== 'number') { 262 wordSpacing = maxWordSpacing.size; 263 break; 264 } 265 } 266 267 $line.css('font-size', ''); 268 wordSpacings.push(wordSpacing); 269 }).removeAttr('style'); 270 271 if( !BigText.DEBUG_MODE ) { 272 $c.remove(); 273 } else { 274 $c.css({ 275 'background-color': 'rgba(255,255,255,.4)' 276 }); 277 } 278 279 return { 280 fontSizes: fontSizes, 281 wordSpacings: wordSpacings, 282 ratios: ratios, 283 minFontSizes: minFontSizes 284 }; 285 } 286 287 $.fn.bigtext = BigText.jQueryMethod; 288 window.BigText = BigText; 289 290})(this, jQuery); 291/*! 292 * Isotope PACKAGED v3.0.6 293 * 294 * Licensed GPLv3 for open source use 295 * or Isotope Commercial License for commercial use 296 * 297 * https://isotope.metafizzy.co 298 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 298-948
298 299 */ 300 301/** 302 * Bridget makes jQuery widgets 303 * v2.0.1 304 * MIT license 305 */ 306 307/* jshint browser: true, strict: true, undef: true, unused: true */ 308 309( function( window, factory ) { 310 // universal module definition 311 /*jshint strict: false */ /* globals define, module, require */ 312 if ( typeof define == 'function' && define.amd ) { 313 // AMD 314 define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) { 315 return factory( window, jQuery ); 316 }); 317 } else if ( typeof module == 'object' && module.exports ) { 318 // CommonJS 319 module.exports = factory( 320 window, 321 require('jquery') 322 ); 323 } else { 324 // browser global 325 window.jQueryBridget = factory( 326 window, 327 window.jQuery 328 ); 329 } 330 331}( window, function factory( window, jQuery ) { 332'use strict'; 333 334// ----- utils ----- // 335 336var arraySlice = Array.prototype.slice; 337 338// helper function for logging errors 339// $.error breaks jQuery chaining 340var console = window.console; 341var logError = typeof console == 'undefined' ? function() {} : 342 function( message ) { 343 console.error( message ); 344 }; 345 346// ----- jQueryBridget ----- // 347 348function jQueryBridget( namespace, PluginClass, $ ) { 349 $ = $ || jQuery || window.jQuery; 350 if ( !$ ) { 351 return; 352 } 353 354 // add option method -> $().plugin('option', {...}) 355 if ( !PluginClass.prototype.option ) { 356 // option setter 357 PluginClass.prototype.option = function( opts ) { 358 // bail out if not an object 359 if ( !$.isPlainObject( opts ) ){ 360 return; 361 } 362 this.options = $.extend( true, this.options, opts ); 363 }; 364 } 365 366 // make jQuery plugin 367 $.fn[ namespace ] = function( arg0 /*, arg1 */ ) { 368 if ( typeof arg0 == 'string' ) { 369 // method call $().plugin( 'methodName', { options } ) 370 // shift arguments by 1 371 var args = arraySlice.call( arguments, 1 ); 372 return methodCall( this, arg0, args ); 373 } 374 // just $().plugin({ options }) 375 plainCall( this, arg0 ); 376 return this; 377 }; 378 379 // $().plugin('methodName') 380 function methodCall( $elems, methodName, args ) { 381 var returnValue; 382 var pluginMethodStr = '$().' + namespace + '("' + methodName + '")'; 383 384 $elems.each( function( i, elem ) { 385 // get instance 386 var instance = $.data( elem, namespace ); 387 if ( !instance ) { 388 logError( namespace + ' not initialized. Cannot call methods, i.e. ' + 389 pluginMethodStr ); 390 return; 391 } 392 393 var method = instance[ methodName ]; 394 if ( !method || methodName.charAt(0) == '_' ) { 395 logError( pluginMethodStr + ' is not a valid method' ); 396 return; 397 } 398 399 // apply method, get return value 400 var value = method.apply( instance, args ); 401 // set return value if value is returned, use only first value 402 returnValue = returnValue === undefined ? value : returnValue; 403 }); 404 405 return returnValue !== undefined ? returnValue : $elems; 406 } 407 408 function plainCall( $elems, options ) { 409 $elems.each( function( i, elem ) { 410 var instance = $.data( elem, namespace ); 411 if ( instance ) { 412 // set options & init 413 instance.option( options ); 414 instance._init(); 415 } else { 416 // initialize new instance 417 instance = new PluginClass( elem, options ); 418 $.data( elem, namespace, instance ); 419 } 420 }); 421 } 422 423 updateJQuery( $ ); 424 425} 426 427// ----- updateJQuery ----- // 428 429// set $.bridget for v1 backwards compatibility 430function updateJQuery( $ ) { 431 if ( !$ || ( $ && $.bridget ) ) { 432 return; 433 } 434 $.bridget = jQueryBridget; 435} 436 437updateJQuery( jQuery || window.jQuery ); 438 439// ----- ----- // 440 441return jQueryBridget; 442 443})); 444 445/** 446 * EvEmitter v1.1.0 447 * Lil' event emitter 448 * MIT License 449 */ 450 451/* jshint unused: true, undef: true, strict: true */ 452 453( function( global, factory ) { 454 // universal module definition 455 /* jshint strict: false */ /* globals define, module, window */ 456 if ( typeof define == 'function' && define.amd ) { 457 // AMD - RequireJS 458 define( 'ev-emitter/ev-emitter',factory ); 459 } else if ( typeof module == 'object' && module.exports ) { 460 // CommonJS - Browserify, Webpack 461 module.exports = factory(); 462 } else { 463 // Browser globals 464 global.EvEmitter = factory(); 465 } 466 467}( typeof window != 'undefined' ? window : this, function() { 468 469 470 471function EvEmitter() {} 472 473var proto = EvEmitter.prototype; 474 475proto.on = function( eventName, listener ) { 476 if ( !eventName || !listener ) { 477 return; 478 } 479 // set events hash 480 var events = this._events = this._events || {}; 481 // set listeners array 482 var listeners = events[ eventName ] = events[ eventName ] || []; 483 // only add once 484 if ( listeners.indexOf( listener ) == -1 ) { 485 listeners.push( listener ); 486 } 487 488 return this; 489}; 490 491proto.once = function( eventName, listener ) { 492 if ( !eventName || !listener ) { 493 return; 494 } 495 // add event 496 this.on( eventName, listener ); 497 // set once flag 498 // set onceEvents hash 499 var onceEvents = this._onceEvents = this._onceEvents || {}; 500 // set onceListeners object 501 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 502 // set flag 503 onceListeners[ listener ] = true; 504 505 return this; 506}; 507 508proto.off = function( eventName, listener ) { 509 var listeners = this._events && this._events[ eventName ]; 510 if ( !listeners || !listeners.length ) { 511 return; 512 } 513 var index = listeners.indexOf( listener ); 514 if ( index != -1 ) { 515 listeners.splice( index, 1 ); 516 } 517 518 return this; 519}; 520 521proto.emitEvent = function( eventName, args ) { 522 var listeners = this._events && this._events[ eventName ]; 523 if ( !listeners || !listeners.length ) { 524 return; 525 } 526 // copy over to avoid interference if .off() in listener 527 listeners = listeners.slice(0); 528 args = args || []; 529 // once stuff 530 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 531 532 for ( var i=0; i < listeners.length; i++ ) { 533 var listener = listeners[i] 534 var isOnce = onceListeners && onceListeners[ listener ]; 535 if ( isOnce ) { 536 // remove listener 537 // remove before trigger to prevent recursion 538 this.off( eventName, listener ); 539 // unset once flag 540 delete onceListeners[ listener ]; 541 } 542 // trigger listener 543 listener.apply( this, args ); 544 } 545 546 return this; 547}; 548 549proto.allOff = function() { 550 delete this._events; 551 delete this._onceEvents; 552}; 553 554return EvEmitter; 555 556})); 557 558/*! 559 * getSize v2.0.3 560 * measure size of elements 561 * MIT license 562 */ 563 564/* jshint browser: true, strict: true, undef: true, unused: true */ 565/* globals console: false */ 566 567( function( window, factory ) { 568 /* jshint strict: false */ /* globals define, module */ 569 if ( typeof define == 'function' && define.amd ) { 570 // AMD 571 define( 'get-size/get-size',factory ); 572 } else if ( typeof module == 'object' && module.exports ) { 573 // CommonJS 574 module.exports = factory(); 575 } else { 576 // browser global 577 window.getSize = factory(); 578 } 579 580})( window, function factory() { 581'use strict'; 582 583// -------------------------- helpers -------------------------- // 584 585// get a number from a string, not a percentage 586function getStyleSize( value ) { 587 var num = parseFloat( value ); 588 // not a percent like '100%', and a number 589 var isValid = value.indexOf('%') == -1 && !isNaN( num ); 590 return isValid && num; 591} 592 593function noop() {} 594 595var logError = typeof console == 'undefined' ? noop : 596 function( message ) { 597 console.error( message ); 598 }; 599 600// -------------------------- measurements -------------------------- // 601 602var measurements = [ 603 'paddingLeft', 604 'paddingRight', 605 'paddingTop', 606 'paddingBottom', 607 'marginLeft', 608 'marginRight', 609 'marginTop', 610 'marginBottom', 611 'borderLeftWidth', 612 'borderRightWidth', 613 'borderTopWidth', 614 'borderBottomWidth' 615]; 616 617var measurementsLength = measurements.length; 618 619function getZeroSize() { 620 var size = { 621 width: 0, 622 height: 0, 623 innerWidth: 0, 624 innerHeight: 0, 625 outerWidth: 0, 626 outerHeight: 0 627 }; 628 for ( var i=0; i < measurementsLength; i++ ) { 629 var measurement = measurements[i]; 630 size[ measurement ] = 0; 631 } 632 return size; 633} 634 635// -------------------------- getStyle -------------------------- // 636 637/** 638 * getStyle, get style of element, check for Firefox bug 639 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 640 */ 641function getStyle( elem ) { 642 var style = getComputedStyle( elem ); 643 if ( !style ) { 644 logError( 'Style returned ' + style + 645 '. Are you running this code in a hidden iframe on Firefox? ' + 646 'See https://bit.ly/getsizebug1' ); 647 } 648 return style; 649} 650 651// -------------------------- setup -------------------------- // 652 653var isSetup = false; 654 655var isBoxSizeOuter; 656 657/** 658 * setup 659 * check isBoxSizerOuter 660 * do on first getSize() rather than on page load for Firefox bug 661 */ 662function setup() { 663 // setup once 664 if ( isSetup ) { 665 return; 666 } 667 isSetup = true; 668 669 // -------------------------- box sizing -------------------------- // 670 671 /** 672 * Chrome & Safari measure the outer-width on style.width on border-box elems 673 * IE11 & Firefox<29 measures the inner-width 674 */ 675 var div = document.createElement('div'); 676 div.style.width = '200px'; 677 div.style.padding = '1px 2px 3px 4px'; 678 div.style.borderStyle = 'solid'; 679 div.style.borderWidth = '1px 2px 3px 4px'; 680 div.style.boxSizing = 'border-box'; 681 682 var body = document.body || document.documentElement; 683 body.appendChild( div ); 684 var style = getStyle( div ); 685 // round value for browser zoom. desandro/masonry#928 686 isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200; 687 getSize.isBoxSizeOuter = isBoxSizeOuter; 688 689 body.removeChild( div ); 690} 691 692// -------------------------- getSize -------------------------- // 693 694function getSize( elem ) { 695 setup(); 696 697 // use querySeletor if elem is string 698 if ( typeof elem == 'string' ) { 699 elem = document.querySelector( elem ); 700 } 701 702 // do not proceed on non-objects 703 if ( !elem || typeof elem != 'object' || !elem.nodeType ) { 704 return; 705 } 706 707 var style = getStyle( elem ); 708 709 // if hidden, everything is 0 710 if ( style.display == 'none' ) { 711 return getZeroSize(); 712 } 713 714 var size = {}; 715 size.width = elem.offsetWidth; 716 size.height = elem.offsetHeight; 717 718 var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; 719 720 // get all measurements 721 for ( var i=0; i < measurementsLength; i++ ) { 722 var measurement = measurements[i]; 723 var value = style[ measurement ]; 724 var num = parseFloat( value ); 725 // any 'auto', 'medium' value will be 0 726 size[ measurement ] = !isNaN( num ) ? num : 0; 727 } 728 729 var paddingWidth = size.paddingLeft + size.paddingRight; 730 var paddingHeight = size.paddingTop + size.paddingBottom; 731 var marginWidth = size.marginLeft + size.marginRight; 732 var marginHeight = size.marginTop + size.marginBottom; 733 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 734 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 735 736 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 737 738 // overwrite width and height if we can get it from style 739 var styleWidth = getStyleSize( style.width ); 740 if ( styleWidth !== false ) { 741 size.width = styleWidth + 742 // add padding and border unless it's already including it 743 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 744 } 745 746 var styleHeight = getStyleSize( style.height ); 747 if ( styleHeight !== false ) { 748 size.height = styleHeight + 749 // add padding and border unless it's already including it 750 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 751 } 752 753 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 754 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 755 756 size.outerWidth = size.width + marginWidth; 757 size.outerHeight = size.height + marginHeight; 758 759 return size; 760} 761 762return getSize; 763 764}); 765 766/** 767 * matchesSelector v2.0.2 768 * matchesSelector( element, '.selector' ) 769 * MIT license 770 */ 771 772/*jshint browser: true, strict: true, undef: true, unused: true */ 773 774( function( window, factory ) { 775 /*global define: false, module: false */ 776 'use strict'; 777 // universal module definition 778 if ( typeof define == 'function' && define.amd ) { 779 // AMD 780 define( 'desandro-matches-selector/matches-selector',factory ); 781 } else if ( typeof module == 'object' && module.exports ) { 782 // CommonJS 783 module.exports = factory(); 784 } else { 785 // browser global 786 window.matchesSelector = factory(); 787 } 788 789}( window, function factory() { 790 'use strict'; 791 792 var matchesMethod = ( function() { 793 var ElemProto = window.Element.prototype; 794 // check for the standard method name first 795 if ( ElemProto.matches ) { 796 return 'matches'; 797 } 798 // check un-prefixed 799 if ( ElemProto.matchesSelector ) { 800 return 'matchesSelector'; 801 } 802 // check vendor prefixes 803 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 804 805 for ( var i=0; i < prefixes.length; i++ ) { 806 var prefix = prefixes[i]; 807 var method = prefix + 'MatchesSelector'; 808 if ( ElemProto[ method ] ) { 809 return method; 810 } 811 } 812 })(); 813 814 return function matchesSelector( elem, selector ) { 815 return elem[ matchesMethod ]( selector ); 816 }; 817 818})); 819 820/** 821 * Fizzy UI utils v2.0.7 822 * MIT license 823 */ 824 825/*jshint browser: true, undef: true, unused: true, strict: true */ 826 827( function( window, factory ) { 828 // universal module definition 829 /*jshint strict: false */ /*globals define, module, require */ 830 831 if ( typeof define == 'function' && define.amd ) { 832 // AMD 833 define( 'fizzy-ui-utils/utils',[ 834 'desandro-matches-selector/matches-selector' 835 ], function( matchesSelector ) { 836 return factory( window, matchesSelector ); 837 }); 838 } else if ( typeof module == 'object' && module.exports ) { 839 // CommonJS 840 module.exports = factory( 841 window, 842 require('desandro-matches-selector') 843 ); 844 } else { 845 // browser global 846 window.fizzyUIUtils = factory( 847 window, 848 window.matchesSelector 849 ); 850 } 851 852}( window, function factory( window, matchesSelector ) { 853 854 855 856var utils = {}; 857 858// ----- extend ----- // 859 860// extends objects 861utils.extend = function( a, b ) { 862 for ( var prop in b ) { 863 a[ prop ] = b[ prop ]; 864 } 865 return a; 866}; 867 868// ----- modulo ----- // 869 870utils.modulo = function( num, div ) { 871 return ( ( num % div ) + div ) % div; 872}; 873 874// ----- makeArray ----- // 875 876var arraySlice = Array.prototype.slice; 877 878// turn element or nodeList into an array 879utils.makeArray = function( obj ) { 880 if ( Array.isArray( obj ) ) { 881 // use object if already an array 882 return obj; 883 } 884 // return empty array if undefined or null. #6 885 if ( obj === null || obj === undefined ) { 886 return []; 887 } 888 889 var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; 890 if ( isArrayLike ) { 891 // convert nodeList to array 892 return arraySlice.call( obj ); 893 } 894 895 // array of single index 896 return [ obj ]; 897}; 898 899// ----- removeFrom ----- // 900 901utils.removeFrom = function( ary, obj ) { 902 var index = ary.indexOf( obj ); 903 if ( index != -1 ) { 904 ary.splice( index, 1 ); 905 } 906}; 907 908// ----- getParent ----- // 909 910utils.getParent = function( elem, selector ) { 911 while ( elem.parentNode && elem != document.body ) { 912 elem = elem.parentNode; 913 if ( matchesSelector( elem, selector ) ) { 914 return elem; 915 } 916 } 917}; 918 919// ----- getQueryElement ----- // 920 921// use element as selector string 922utils.getQueryElement = function( elem ) { 923 if ( typeof elem == 'string' ) { 924 return document.querySelector( elem ); 925 } 926 return elem; 927}; 928 929// ----- handleEvent ----- // 930 931// enable .ontype to trigger from .addEventListener( elem, 'type' ) 932utils.handleEvent = function( event ) { 933 var method = 'on' + event.type; 934 if ( this[ method ] ) { 935 this[ method ]( event ); 936 } 937}; 938 939// ----- filterFindElements ----- // 940 941utils.filterFindElements = function( elems, selector ) { 942 // make array of elems 943 elems = utils.makeArray( elems ); 944 var ffElems = []; 945 946 elems.forEach( function( elem ) { 947 // check that elem is an actual element 948
948// START UNCODE EDIT 949 // if ( !( elem instanceof HTMLElement ) ) { 950 if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) { 951 // END UNCODE EDIT
vendor: 23,480 bytes, lines 951-1863
951 952 return; 953 } 954 // add elem if no selector 955 if ( !selector ) { 956 ffElems.push( elem ); 957 return; 958 } 959 // filter & find items if we have a selector 960 // filter 961 if ( matchesSelector( elem, selector ) ) { 962 ffElems.push( elem ); 963 } 964 // find children 965 var childElems = elem.querySelectorAll( selector ); 966 // concat childElems to filterFound array 967 for ( var i=0; i < childElems.length; i++ ) { 968 ffElems.push( childElems[i] ); 969 } 970 }); 971 972 return ffElems; 973}; 974 975// ----- debounceMethod ----- // 976 977utils.debounceMethod = function( _class, methodName, threshold ) { 978 threshold = threshold || 100; 979 // original method 980 var method = _class.prototype[ methodName ]; 981 var timeoutName = methodName + 'Timeout'; 982 983 _class.prototype[ methodName ] = function() { 984 var timeout = this[ timeoutName ]; 985 clearTimeout( timeout ); 986 987 var args = arguments; 988 var _this = this; 989 this[ timeoutName ] = setTimeout( function() { 990 method.apply( _this, args ); 991 delete _this[ timeoutName ]; 992 }, threshold ); 993 }; 994}; 995 996// ----- docReady ----- // 997 998utils.docReady = function( callback ) { 999 var readyState = document.readyState; 1000 if ( readyState == 'complete' || readyState == 'interactive' ) { 1001 // do async to allow for other scripts to run. metafizzy/flickity#441 1002 setTimeout( callback ); 1003 } else { 1004 document.addEventListener( 'DOMContentLoaded', callback ); 1005 } 1006}; 1007 1008// ----- htmlInit ----- // 1009 1010// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 1011utils.toDashed = function( str ) { 1012 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 1013 return $1 + '-' + $2; 1014 }).toLowerCase(); 1015}; 1016 1017var console = window.console; 1018/** 1019 * allow user to initialize classes via [data-namespace] or .js-namespace class 1020 * htmlInit( Widget, 'widgetName' ) 1021 * options are parsed from data-namespace-options 1022 */ 1023utils.htmlInit = function( WidgetClass, namespace ) { 1024 utils.docReady( function() { 1025 var dashedNamespace = utils.toDashed( namespace ); 1026 var dataAttr = 'data-' + dashedNamespace; 1027 var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); 1028 var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); 1029 var elems = utils.makeArray( dataAttrElems ) 1030 .concat( utils.makeArray( jsDashElems ) ); 1031 var dataOptionsAttr = dataAttr + '-options'; 1032 var jQuery = window.jQuery; 1033 1034 elems.forEach( function( elem ) { 1035 var attr = elem.getAttribute( dataAttr ) || 1036 elem.getAttribute( dataOptionsAttr ); 1037 var options; 1038 try { 1039 options = attr && JSON.parse( attr ); 1040 } catch ( error ) { 1041 // log error, do not initialize 1042 if ( console ) { 1043 console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + 1044 ': ' + error ); 1045 } 1046 return; 1047 } 1048 // initialize 1049 var instance = new WidgetClass( elem, options ); 1050 // make available via $().data('namespace') 1051 if ( jQuery ) { 1052 jQuery.data( elem, namespace, instance ); 1053 } 1054 }); 1055 1056 }); 1057}; 1058 1059// ----- ----- // 1060 1061return utils; 1062 1063})); 1064 1065/** 1066 * Outlayer Item 1067 */ 1068 1069( function( window, factory ) { 1070 // universal module definition 1071 /* jshint strict: false */ /* globals define, module, require */ 1072 if ( typeof define == 'function' && define.amd ) { 1073 // AMD - RequireJS 1074 define( 'outlayer/item',[ 1075 'ev-emitter/ev-emitter', 1076 'get-size/get-size' 1077 ], 1078 factory 1079 ); 1080 } else if ( typeof module == 'object' && module.exports ) { 1081 // CommonJS - Browserify, Webpack 1082 module.exports = factory( 1083 require('ev-emitter'), 1084 require('get-size') 1085 ); 1086 } else { 1087 // browser global 1088 window.Outlayer = {}; 1089 window.Outlayer.Item = factory( 1090 window.EvEmitter, 1091 window.getSize 1092 ); 1093 } 1094 1095}( window, function factory( EvEmitter, getSize ) { 1096'use strict'; 1097 1098// ----- helpers ----- // 1099 1100function isEmptyObj( obj ) { 1101 for ( var prop in obj ) { 1102 return false; 1103 } 1104 prop = null; 1105 return true; 1106} 1107 1108// -------------------------- CSS3 support -------------------------- // 1109 1110 1111var docElemStyle = document.documentElement.style; 1112 1113var transitionProperty = typeof docElemStyle.transition == 'string' ? 1114 'transition' : 'WebkitTransition'; 1115var transformProperty = typeof docElemStyle.transform == 'string' ? 1116 'transform' : 'WebkitTransform'; 1117 1118var transitionEndEvent = { 1119 WebkitTransition: 'webkitTransitionEnd', 1120 transition: 'transitionend' 1121}[ transitionProperty ]; 1122 1123// cache all vendor properties that could have vendor prefix 1124var vendorProperties = { 1125 transform: transformProperty, 1126 transition: transitionProperty, 1127 transitionDuration: transitionProperty + 'Duration', 1128 transitionProperty: transitionProperty + 'Property', 1129 transitionDelay: transitionProperty + 'Delay' 1130}; 1131 1132// -------------------------- Item -------------------------- // 1133 1134function Item( element, layout ) { 1135 if ( !element ) { 1136 return; 1137 } 1138 1139 this.element = element; 1140 // parent layout class, i.e. Masonry, Isotope, or Packery 1141 this.layout = layout; 1142 this.position = { 1143 x: 0, 1144 y: 0 1145 }; 1146 1147 this._create(); 1148} 1149 1150// inherit EvEmitter 1151var proto = Item.prototype = Object.create( EvEmitter.prototype ); 1152proto.constructor = Item; 1153 1154proto._create = function() { 1155 // transition objects 1156 this._transn = { 1157 ingProperties: {}, 1158 clean: {}, 1159 onEnd: {} 1160 }; 1161 1162 this.css({ 1163 position: 'absolute' 1164 }); 1165}; 1166 1167// trigger specified handler for event type 1168proto.handleEvent = function( event ) { 1169 var method = 'on' + event.type; 1170 if ( this[ method ] ) { 1171 this[ method ]( event ); 1172 } 1173}; 1174 1175proto.getSize = function() { 1176 this.size = getSize( this.element ); 1177}; 1178 1179/** 1180 * apply CSS styles to element 1181 * @param {Object} style 1182 */ 1183proto.css = function( style ) { 1184 var elemStyle = this.element.style; 1185 1186 for ( var prop in style ) { 1187 // use vendor property if available 1188 var supportedProp = vendorProperties[ prop ] || prop; 1189 elemStyle[ supportedProp ] = style[ prop ]; 1190 } 1191}; 1192 1193 // measure position, and sets it 1194proto.getPosition = function() { 1195 var style = getComputedStyle( this.element ); 1196 var isOriginLeft = this.layout._getOption('originLeft'); 1197 var isOriginTop = this.layout._getOption('originTop'); 1198 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 1199 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 1200 var x = parseFloat( xValue ); 1201 var y = parseFloat( yValue ); 1202 // convert percent to pixels 1203 var layoutSize = this.layout.size; 1204 if ( xValue.indexOf('%') != -1 ) { 1205 x = ( x / 100 ) * layoutSize.width; 1206 } 1207 if ( yValue.indexOf('%') != -1 ) { 1208 y = ( y / 100 ) * layoutSize.height; 1209 } 1210 // clean up 'auto' or other non-integer values 1211 x = isNaN( x ) ? 0 : x; 1212 y = isNaN( y ) ? 0 : y; 1213 // remove padding from measurement 1214 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 1215 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 1216 1217 this.position.x = x; 1218 this.position.y = y; 1219}; 1220 1221// set settled position, apply padding 1222proto.layoutPosition = function() { 1223 var layoutSize = this.layout.size; 1224 var style = {}; 1225 var isOriginLeft = this.layout._getOption('originLeft'); 1226 var isOriginTop = this.layout._getOption('originTop'); 1227 1228 // x 1229 var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; 1230 var xProperty = isOriginLeft ? 'left' : 'right'; 1231 var xResetProperty = isOriginLeft ? 'right' : 'left'; 1232 1233 var x = this.position.x + layoutSize[ xPadding ]; 1234 // set in percentage or pixels 1235 style[ xProperty ] = this.getXValue( x ); 1236 // reset other property 1237 style[ xResetProperty ] = ''; 1238 1239 // y 1240 var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; 1241 var yProperty = isOriginTop ? 'top' : 'bottom'; 1242 var yResetProperty = isOriginTop ? 'bottom' : 'top'; 1243 1244 var y = this.position.y + layoutSize[ yPadding ]; 1245 // set in percentage or pixels 1246 style[ yProperty ] = this.getYValue( y ); 1247 // reset other property 1248 style[ yResetProperty ] = ''; 1249 1250 this.css( style ); 1251 this.emitEvent( 'layout', [ this ] ); 1252}; 1253 1254proto.getXValue = function( x ) { 1255 var isHorizontal = this.layout._getOption('horizontal'); 1256 return this.layout.options.percentPosition && !isHorizontal ? 1257 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 1258}; 1259 1260proto.getYValue = function( y ) { 1261 var isHorizontal = this.layout._getOption('horizontal'); 1262 return this.layout.options.percentPosition && isHorizontal ? 1263 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 1264}; 1265 1266proto._transitionTo = function( x, y ) { 1267 this.getPosition(); 1268 // get current x & y from top/left 1269 var curX = this.position.x; 1270 var curY = this.position.y; 1271 1272 var didNotMove = x == this.position.x && y == this.position.y; 1273 1274 // save end position 1275 this.setPosition( x, y ); 1276 1277 // if did not move and not transitioning, just go to layout 1278 if ( didNotMove && !this.isTransitioning ) { 1279 this.layoutPosition(); 1280 return; 1281 } 1282 1283 var transX = x - curX; 1284 var transY = y - curY; 1285 var transitionStyle = {}; 1286 transitionStyle.transform = this.getTranslate( transX, transY ); 1287 1288 this.transition({ 1289 to: transitionStyle, 1290 onTransitionEnd: { 1291 transform: this.layoutPosition 1292 }, 1293 isCleaning: true 1294 }); 1295}; 1296 1297proto.getTranslate = function( x, y ) { 1298 // flip cooridinates if origin on right or bottom 1299 var isOriginLeft = this.layout._getOption('originLeft'); 1300 var isOriginTop = this.layout._getOption('originTop'); 1301 x = isOriginLeft ? x : -x; 1302 y = isOriginTop ? y : -y; 1303 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 1304}; 1305 1306// non transition + transform support 1307proto.goTo = function( x, y ) { 1308 this.setPosition( x, y ); 1309 this.layoutPosition(); 1310}; 1311 1312proto.moveTo = proto._transitionTo; 1313 1314proto.setPosition = function( x, y ) { 1315 this.position.x = parseFloat( x ); 1316 this.position.y = parseFloat( y ); 1317}; 1318 1319// ----- transition ----- // 1320 1321/** 1322 * @param {Object} style - CSS 1323 * @param {Function} onTransitionEnd 1324 */ 1325 1326// non transition, just trigger callback 1327proto._nonTransition = function( args ) { 1328 this.css( args.to ); 1329 if ( args.isCleaning ) { 1330 this._removeStyles( args.to ); 1331 } 1332 for ( var prop in args.onTransitionEnd ) { 1333 args.onTransitionEnd[ prop ].call( this ); 1334 } 1335}; 1336 1337/** 1338 * proper transition 1339 * @param {Object} args - arguments 1340 * @param {Object} to - style to transition to 1341 * @param {Object} from - style to start transition from 1342 * @param {Boolean} isCleaning - removes transition styles after transition 1343 * @param {Function} onTransitionEnd - callback 1344 */ 1345proto.transition = function( args ) { 1346 // redirect to nonTransition if no transition duration 1347 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 1348 this._nonTransition( args ); 1349 return; 1350 } 1351 1352 var _transition = this._transn; 1353 // keep track of onTransitionEnd callback by css property 1354 for ( var prop in args.onTransitionEnd ) { 1355 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 1356 } 1357 // keep track of properties that are transitioning 1358 for ( prop in args.to ) { 1359 _transition.ingProperties[ prop ] = true; 1360 // keep track of properties to clean up when transition is done 1361 if ( args.isCleaning ) { 1362 _transition.clean[ prop ] = true; 1363 } 1364 } 1365 1366 // set from styles 1367 if ( args.from ) { 1368 this.css( args.from ); 1369 // force redraw. http://blog.alexmaccaw.com/css-transitions 1370 var h = this.element.offsetHeight; 1371 // hack for JSHint to hush about unused var 1372 h = null; 1373 } 1374 // enable transition 1375 this.enableTransition( args.to ); 1376 // set styles that are transitioning 1377 this.css( args.to ); 1378 1379 this.isTransitioning = true; 1380 1381}; 1382 1383// dash before all cap letters, including first for 1384// WebkitTransform => -webkit-transform 1385function toDashedAll( str ) { 1386 return str.replace( /([A-Z])/g, function( $1 ) { 1387 return '-' + $1.toLowerCase(); 1388 }); 1389} 1390 1391var transitionProps = 'opacity,' + toDashedAll( transformProperty ); 1392 1393proto.enableTransition = function(/* style */) { 1394 // HACK changing transitionProperty during a transition 1395 // will cause transition to jump 1396 if ( this.isTransitioning ) { 1397 return; 1398 } 1399 1400 // make `transition: foo, bar, baz` from style object 1401 // HACK un-comment this when enableTransition can work 1402 // while a transition is happening 1403 // var transitionValues = []; 1404 // for ( var prop in style ) { 1405 // // dash-ify camelCased properties like WebkitTransition 1406 // prop = vendorProperties[ prop ] || prop; 1407 // transitionValues.push( toDashedAll( prop ) ); 1408 // } 1409 // munge number to millisecond, to match stagger 1410 var duration = this.layout.options.transitionDuration; 1411 duration = typeof duration == 'number' ? duration + 'ms' : duration; 1412 // enable transition styles 1413 this.css({ 1414 transitionProperty: transitionProps, 1415 transitionDuration: duration, 1416 transitionDelay: this.staggerDelay || 0 1417 }); 1418 // listen for transition end event 1419 this.element.addEventListener( transitionEndEvent, this, false ); 1420}; 1421 1422// ----- events ----- // 1423 1424proto.onwebkitTransitionEnd = function( event ) { 1425 this.ontransitionend( event ); 1426}; 1427 1428proto.onotransitionend = function( event ) { 1429 this.ontransitionend( event ); 1430}; 1431 1432// properties that I munge to make my life easier 1433var dashedVendorProperties = { 1434 '-webkit-transform': 'transform' 1435}; 1436 1437proto.ontransitionend = function( event ) { 1438 // disregard bubbled events from children 1439 if ( event.target !== this.element ) { 1440 return; 1441 } 1442 var _transition = this._transn; 1443 // get property name of transitioned property, convert to prefix-free 1444 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 1445 1446 // remove property that has completed transitioning 1447 delete _transition.ingProperties[ propertyName ]; 1448 // check if any properties are still transitioning 1449 if ( isEmptyObj( _transition.ingProperties ) ) { 1450 // all properties have completed transitioning 1451 this.disableTransition(); 1452 } 1453 // clean style 1454 if ( propertyName in _transition.clean ) { 1455 // clean up style 1456 this.element.style[ event.propertyName ] = ''; 1457 delete _transition.clean[ propertyName ]; 1458 } 1459 // trigger onTransitionEnd callback 1460 if ( propertyName in _transition.onEnd ) { 1461 var onTransitionEnd = _transition.onEnd[ propertyName ]; 1462 onTransitionEnd.call( this ); 1463 delete _transition.onEnd[ propertyName ]; 1464 } 1465 1466 this.emitEvent( 'transitionEnd', [ this ] ); 1467}; 1468 1469proto.disableTransition = function() { 1470 this.removeTransitionStyles(); 1471 this.element.removeEventListener( transitionEndEvent, this, false ); 1472 this.isTransitioning = false; 1473}; 1474 1475/** 1476 * removes style property from element 1477 * @param {Object} style 1478**/ 1479proto._removeStyles = function( style ) { 1480 // clean up transition styles 1481 var cleanStyle = {}; 1482 for ( var prop in style ) { 1483 cleanStyle[ prop ] = ''; 1484 } 1485 this.css( cleanStyle ); 1486}; 1487 1488var cleanTransitionStyle = { 1489 transitionProperty: '', 1490 transitionDuration: '', 1491 transitionDelay: '' 1492}; 1493 1494proto.removeTransitionStyles = function() { 1495 // remove transition 1496 this.css( cleanTransitionStyle ); 1497}; 1498 1499// ----- stagger ----- // 1500 1501proto.stagger = function( delay ) { 1502 delay = isNaN( delay ) ? 0 : delay; 1503 this.staggerDelay = delay + 'ms'; 1504}; 1505 1506// ----- show/hide/remove ----- // 1507 1508// remove element from DOM 1509proto.removeElem = function() { 1510 this.element.parentNode.removeChild( this.element ); 1511 // remove display: none 1512 this.css({ display: '' }); 1513 this.emitEvent( 'remove', [ this ] ); 1514}; 1515 1516proto.remove = function() { 1517 // just remove element if no transition support or no transition 1518 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 1519 this.removeElem(); 1520 return; 1521 } 1522 1523 // start transition 1524 this.once( 'transitionEnd', function() { 1525 this.removeElem(); 1526 }); 1527 this.hide(); 1528}; 1529 1530proto.reveal = function() { 1531 delete this.isHidden; 1532 // remove display: none 1533 this.css({ display: '' }); 1534 1535 var options = this.layout.options; 1536 1537 var onTransitionEnd = {}; 1538 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 1539 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 1540 1541 this.transition({ 1542 from: options.hiddenStyle, 1543 to: options.visibleStyle, 1544 isCleaning: true, 1545 onTransitionEnd: onTransitionEnd 1546 }); 1547}; 1548 1549proto.onRevealTransitionEnd = function() { 1550 // check if still visible 1551 // during transition, item may have been hidden 1552 if ( !this.isHidden ) { 1553 this.emitEvent('reveal'); 1554 } 1555}; 1556 1557/** 1558 * get style property use for hide/reveal transition end 1559 * @param {String} styleProperty - hiddenStyle/visibleStyle 1560 * @returns {String} 1561 */ 1562proto.getHideRevealTransitionEndProperty = function( styleProperty ) { 1563 var optionStyle = this.layout.options[ styleProperty ]; 1564 // use opacity 1565 if ( optionStyle.opacity ) { 1566 return 'opacity'; 1567 } 1568 // get first property 1569 for ( var prop in optionStyle ) { 1570 return prop; 1571 } 1572}; 1573 1574proto.hide = function() { 1575 // set flag 1576 this.isHidden = true; 1577 // remove display: none 1578 this.css({ display: '' }); 1579 1580 var options = this.layout.options; 1581 1582 var onTransitionEnd = {}; 1583 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 1584 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 1585 1586 this.transition({ 1587 from: options.visibleStyle, 1588 to: options.hiddenStyle, 1589 // keep hidden stuff hidden 1590 isCleaning: true, 1591 onTransitionEnd: onTransitionEnd 1592 }); 1593}; 1594 1595proto.onHideTransitionEnd = function() { 1596 // check if still hidden 1597 // during transition, item may have been un-hidden 1598 if ( this.isHidden ) { 1599 this.css({ display: 'none' }); 1600 this.emitEvent('hide'); 1601 } 1602}; 1603 1604proto.destroy = function() { 1605 this.css({ 1606 position: '', 1607 left: '', 1608 right: '', 1609 top: '', 1610 bottom: '', 1611 transition: '', 1612 transform: '' 1613 }); 1614}; 1615 1616return Item; 1617 1618})); 1619 1620/*! 1621 * Outlayer v2.1.1 1622 * the brains and guts of a layout library 1623 * MIT license 1624 */ 1625 1626( function( window, factory ) { 1627 'use strict'; 1628 // universal module definition 1629 /* jshint strict: false */ /* globals define, module, require */ 1630 if ( typeof define == 'function' && define.amd ) { 1631 // AMD - RequireJS 1632 define( 'outlayer/outlayer',[ 1633 'ev-emitter/ev-emitter', 1634 'get-size/get-size', 1635 'fizzy-ui-utils/utils', 1636 './item' 1637 ], 1638 function( EvEmitter, getSize, utils, Item ) { 1639 return factory( window, EvEmitter, getSize, utils, Item); 1640 } 1641 ); 1642 } else if ( typeof module == 'object' && module.exports ) { 1643 // CommonJS - Browserify, Webpack 1644 module.exports = factory( 1645 window, 1646 require('ev-emitter'), 1647 require('get-size'), 1648 require('fizzy-ui-utils'), 1649 require('./item') 1650 ); 1651 } else { 1652 // browser global 1653 window.Outlayer = factory( 1654 window, 1655 window.EvEmitter, 1656 window.getSize, 1657 window.fizzyUIUtils, 1658 window.Outlayer.Item 1659 ); 1660 } 1661 1662}( window, function factory( window, EvEmitter, getSize, utils, Item ) { 1663'use strict'; 1664 1665// ----- vars ----- // 1666 1667var console = window.console; 1668var jQuery = window.jQuery; 1669var noop = function() {}; 1670 1671// -------------------------- Outlayer -------------------------- // 1672 1673// globally unique identifiers 1674var GUID = 0; 1675// internal store of all Outlayer intances 1676var instances = {}; 1677 1678 1679/** 1680 * @param {Element, String} element 1681 * @param {Object} options 1682 * @constructor 1683 */ 1684function Outlayer( element, options ) { 1685 var queryElement = utils.getQueryElement( element ); 1686 if ( !queryElement ) { 1687 if ( console ) { 1688 console.error( 'Bad element for ' + this.constructor.namespace + 1689 ': ' + ( queryElement || element ) ); 1690 } 1691 return; 1692 } 1693 this.element = queryElement; 1694 // add jQuery 1695 if ( jQuery ) { 1696 this.$element = jQuery( this.element ); 1697 } 1698 1699 // options 1700 this.options = utils.extend( {}, this.constructor.defaults ); 1701 this.option( options ); 1702 1703 // add id for Outlayer.getFromElement 1704 var id = ++GUID; 1705 this.element.outlayerGUID = id; // expando 1706 instances[ id ] = this; // associate via id 1707 1708 // kick it off 1709 this._create(); 1710 1711 var isInitLayout = this._getOption('initLayout'); 1712 if ( isInitLayout ) { 1713 this.layout(); 1714 } 1715} 1716 1717// settings are for internal use only 1718Outlayer.namespace = 'outlayer'; 1719Outlayer.Item = Item; 1720 1721// default options 1722Outlayer.defaults = { 1723 containerStyle: { 1724 position: 'relative' 1725 }, 1726 initLayout: true, 1727 originLeft: true, 1728 originTop: true, 1729 resize: true, 1730 resizeContainer: true, 1731 // item options 1732 transitionDuration: '0.4s', 1733 hiddenStyle: { 1734 opacity: 0, 1735 transform: 'scale(0.001)' 1736 }, 1737 visibleStyle: { 1738 opacity: 1, 1739 transform: 'scale(1)' 1740 } 1741}; 1742 1743var proto = Outlayer.prototype; 1744// inherit EvEmitter 1745utils.extend( proto, EvEmitter.prototype ); 1746 1747/** 1748 * set options 1749 * @param {Object} opts 1750 */ 1751proto.option = function( opts ) { 1752 utils.extend( this.options, opts ); 1753}; 1754 1755/** 1756 * get backwards compatible option value, check old name 1757 */ 1758proto._getOption = function( option ) { 1759 var oldOption = this.constructor.compatOptions[ option ]; 1760 return oldOption && this.options[ oldOption ] !== undefined ? 1761 this.options[ oldOption ] : this.options[ option ]; 1762}; 1763 1764Outlayer.compatOptions = { 1765 // currentName: oldName 1766 initLayout: 'isInitLayout', 1767 horizontal: 'isHorizontal', 1768 layoutInstant: 'isLayoutInstant', 1769 originLeft: 'isOriginLeft', 1770 originTop: 'isOriginTop', 1771 resize: 'isResizeBound', 1772 resizeContainer: 'isResizingContainer' 1773}; 1774 1775proto._create = function() { 1776 // get items from children 1777 this.reloadItems(); 1778 // elements that affect layout, but are not laid out 1779 this.stamps = []; 1780 this.stamp( this.options.stamp ); 1781 // set container style 1782 utils.extend( this.element.style, this.options.containerStyle ); 1783 1784 // bind resize method 1785 var canBindResize = this._getOption('resize'); 1786 if ( canBindResize ) { 1787 this.bindResize(); 1788 } 1789}; 1790 1791// goes through all children again and gets bricks in proper order 1792proto.reloadItems = function() { 1793 // collection of item elements 1794 this.items = this._itemize( this.element.children ); 1795}; 1796 1797 1798/** 1799 * turn elements into Outlayer.Items to be used in layout 1800 * @param {Array or NodeList or HTMLElement} elems 1801 * @returns {Array} items - collection of new Outlayer Items 1802 */ 1803proto._itemize = function( elems ) { 1804 1805 var itemElems = this._filterFindItemElements( elems ); 1806 var Item = this.constructor.Item; 1807 1808 // create new Outlayer Items for collection 1809 var items = []; 1810 for ( var i=0; i < itemElems.length; i++ ) { 1811 var elem = itemElems[i]; 1812 var item = new Item( elem, this ); 1813 items.push( item ); 1814 } 1815 1816 return items; 1817}; 1818 1819/** 1820 * get item elements to be used in layout 1821 * @param {Array or NodeList or HTMLElement} elems 1822 * @returns {Array} items - item elements 1823 */ 1824proto._filterFindItemElements = function( elems ) { 1825 return utils.filterFindElements( elems, this.options.itemSelector ); 1826}; 1827 1828/** 1829 * getter method for getting item elements 1830 * @returns {Array} elems - collection of item elements 1831 */ 1832proto.getItemElements = function() { 1833 return this.items.map( function( item ) { 1834 return item.element; 1835 }); 1836}; 1837 1838// ----- init & layout ----- // 1839 1840/** 1841 * lays out all items 1842 */ 1843proto.layout = function() { 1844 this._resetLayout(); 1845 this._manageStamps(); 1846 1847 // don't animate first layout 1848 var layoutInstant = this._getOption('layoutInstant'); 1849 var isInstant = layoutInstant !== undefined ? 1850 layoutInstant : !this._isLayoutInited; 1851 this.layoutItems( this.items, isInstant ); 1852 1853 // flag for initalized 1854 this._isLayoutInited = true; 1855}; 1856 1857// _init is alias for layout 1858proto._init = proto.layout; 1859 1860/** 1861 * logic before any new layout 1862 */ 1863proto._resetLayout = function() {
vendor: 13,499 bytes, lines 1864-2432
1864 this.getSize(); 1865}; 1866 1867 1868proto.getSize = function() { 1869 this.size = getSize( this.element ); 1870}; 1871 1872/** 1873 * get measurement from option, for columnWidth, rowHeight, gutter 1874 * if option is String -> get element from selector string, & get size of element 1875 * if option is Element -> get size of element 1876 * else use option as a number 1877 * 1878 * @param {String} measurement 1879 * @param {String} size - width or height 1880 * @private 1881 */ 1882proto._getMeasurement = function( measurement, size ) { 1883 var option = this.options[ measurement ]; 1884 var elem; 1885 if ( !option ) { 1886 // default to 0 1887 this[ measurement ] = 0; 1888 } else { 1889 // use option as an element 1890 if ( typeof option == 'string' ) { 1891 elem = this.element.querySelector( option ); 1892 } else if ( option instanceof HTMLElement ) { 1893 elem = option; 1894 } 1895 // use size of element, if element 1896 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 1897 } 1898}; 1899 1900/** 1901 * layout a collection of item elements 1902 * @api public 1903 */ 1904proto.layoutItems = function( items, isInstant ) { 1905 items = this._getItemsForLayout( items ); 1906 1907 this._layoutItems( items, isInstant ); 1908 1909 this._postLayout(); 1910}; 1911 1912/** 1913 * get the items to be laid out 1914 * you may want to skip over some items 1915 * @param {Array} items 1916 * @returns {Array} items 1917 */ 1918proto._getItemsForLayout = function( items ) { 1919 return items.filter( function( item ) { 1920 return !item.isIgnored; 1921 }); 1922}; 1923 1924/** 1925 * layout items 1926 * @param {Array} items 1927 * @param {Boolean} isInstant 1928 */ 1929proto._layoutItems = function( items, isInstant ) { 1930 this._emitCompleteOnItems( 'layout', items ); 1931 1932 if ( !items || !items.length ) { 1933 // no items, emit event with empty array 1934 return; 1935 } 1936 1937 var queue = []; 1938 1939 items.forEach( function( item ) { 1940 // get x/y object from method 1941 var position = this._getItemLayoutPosition( item ); 1942 // enqueue 1943 position.item = item; 1944 position.isInstant = isInstant || item.isLayoutInstant; 1945 queue.push( position ); 1946 }, this ); 1947 1948 this._processLayoutQueue( queue ); 1949}; 1950 1951/** 1952 * get item layout position 1953 * @param {Outlayer.Item} item 1954 * @returns {Object} x and y position 1955 */ 1956proto._getItemLayoutPosition = function( /* item */ ) { 1957 return { 1958 x: 0, 1959 y: 0 1960 }; 1961}; 1962 1963/** 1964 * iterate over array and position each item 1965 * Reason being - separating this logic prevents 'layout invalidation' 1966 * thx @paul_irish 1967 * @param {Array} queue 1968 */ 1969proto._processLayoutQueue = function( queue ) { 1970 this.updateStagger(); 1971 queue.forEach( function( obj, i ) { 1972 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); 1973 }, this ); 1974}; 1975 1976// set stagger from option in milliseconds number 1977proto.updateStagger = function() { 1978 var stagger = this.options.stagger; 1979 if ( stagger === null || stagger === undefined ) { 1980 this.stagger = 0; 1981 return; 1982 } 1983 this.stagger = getMilliseconds( stagger ); 1984 return this.stagger; 1985}; 1986 1987/** 1988 * Sets position of item in DOM 1989 * @param {Outlayer.Item} item 1990 * @param {Number} x - horizontal position 1991 * @param {Number} y - vertical position 1992 * @param {Boolean} isInstant - disables transitions 1993 */ 1994proto._positionItem = function( item, x, y, isInstant, i ) { 1995 if ( isInstant ) { 1996 // if not transition, just set CSS 1997 item.goTo( x, y ); 1998 } else { 1999 item.stagger( i * this.stagger ); 2000 item.moveTo( x, y ); 2001 } 2002}; 2003 2004/** 2005 * Any logic you want to do after each layout, 2006 * i.e. size the container 2007 */ 2008proto._postLayout = function() { 2009 this.resizeContainer(); 2010}; 2011 2012proto.resizeContainer = function() { 2013 var isResizingContainer = this._getOption('resizeContainer'); 2014 if ( !isResizingContainer ) { 2015 return; 2016 } 2017 var size = this._getContainerSize(); 2018 if ( size ) { 2019 this._setContainerMeasure( size.width, true ); 2020 this._setContainerMeasure( size.height, false ); 2021 } 2022}; 2023 2024/** 2025 * Sets width or height of container if returned 2026 * @returns {Object} size 2027 * @param {Number} width 2028 * @param {Number} height 2029 */ 2030proto._getContainerSize = noop; 2031 2032/** 2033 * @param {Number} measure - size of width or height 2034 * @param {Boolean} isWidth 2035 */ 2036proto._setContainerMeasure = function( measure, isWidth ) { 2037 if ( measure === undefined ) { 2038 return; 2039 } 2040 2041 var elemSize = this.size; 2042 // add padding and border width if border box 2043 if ( elemSize.isBorderBox ) { 2044 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 2045 elemSize.borderLeftWidth + elemSize.borderRightWidth : 2046 elemSize.paddingBottom + elemSize.paddingTop + 2047 elemSize.borderTopWidth + elemSize.borderBottomWidth; 2048 } 2049 2050 measure = Math.max( measure, 0 ); 2051 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 2052}; 2053 2054/** 2055 * emit eventComplete on a collection of items events 2056 * @param {String} eventName 2057 * @param {Array} items - Outlayer.Items 2058 */ 2059proto._emitCompleteOnItems = function( eventName, items ) { 2060 var _this = this; 2061 function onComplete() { 2062 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 2063 } 2064 2065 var count = items.length; 2066 if ( !items || !count ) { 2067 onComplete(); 2068 return; 2069 } 2070 2071 var doneCount = 0; 2072 function tick() { 2073 doneCount++; 2074 if ( doneCount == count ) { 2075 onComplete(); 2076 } 2077 } 2078 2079 // bind callback 2080 items.forEach( function( item ) { 2081 item.once( eventName, tick ); 2082 }); 2083}; 2084 2085/** 2086 * emits events via EvEmitter and jQuery events 2087 * @param {String} type - name of event 2088 * @param {Event} event - original event 2089 * @param {Array} args - extra arguments 2090 */ 2091proto.dispatchEvent = function( type, event, args ) { 2092 // add original event to arguments 2093 var emitArgs = event ? [ event ].concat( args ) : args; 2094 this.emitEvent( type, emitArgs ); 2095 2096 if ( jQuery ) { 2097 // set this.$element 2098 this.$element = this.$element || jQuery( this.element ); 2099 if ( event ) { 2100 // create jQuery event 2101 var $event = jQuery.Event( event ); 2102 $event.type = type; 2103 this.$element.trigger( $event, args ); 2104 } else { 2105 // just trigger with type if no event available 2106 this.$element.trigger( type, args ); 2107 } 2108 } 2109}; 2110 2111// -------------------------- ignore & stamps -------------------------- // 2112 2113 2114/** 2115 * keep item in collection, but do not lay it out 2116 * ignored items do not get skipped in layout 2117 * @param {Element} elem 2118 */ 2119proto.ignore = function( elem ) { 2120 var item = this.getItem( elem ); 2121 if ( item ) { 2122 item.isIgnored = true; 2123 } 2124}; 2125 2126/** 2127 * return item to layout collection 2128 * @param {Element} elem 2129 */ 2130proto.unignore = function( elem ) { 2131 var item = this.getItem( elem ); 2132 if ( item ) { 2133 delete item.isIgnored; 2134 } 2135}; 2136 2137/** 2138 * adds elements to stamps 2139 * @param {NodeList, Array, Element, or String} elems 2140 */ 2141proto.stamp = function( elems ) { 2142 elems = this._find( elems ); 2143 if ( !elems ) { 2144 return; 2145 } 2146 2147 this.stamps = this.stamps.concat( elems ); 2148 // ignore 2149 elems.forEach( this.ignore, this ); 2150}; 2151 2152/** 2153 * removes elements to stamps 2154 * @param {NodeList, Array, or Element} elems 2155 */ 2156proto.unstamp = function( elems ) { 2157 elems = this._find( elems ); 2158 if ( !elems ){ 2159 return; 2160 } 2161 2162 elems.forEach( function( elem ) { 2163 // filter out removed stamp elements 2164 utils.removeFrom( this.stamps, elem ); 2165 this.unignore( elem ); 2166 }, this ); 2167}; 2168 2169/** 2170 * finds child elements 2171 * @param {NodeList, Array, Element, or String} elems 2172 * @returns {Array} elems 2173 */ 2174proto._find = function( elems ) { 2175 if ( !elems ) { 2176 return; 2177 } 2178 // if string, use argument as selector string 2179 if ( typeof elems == 'string' ) { 2180 elems = this.element.querySelectorAll( elems ); 2181 } 2182 elems = utils.makeArray( elems ); 2183 return elems; 2184}; 2185 2186proto._manageStamps = function() { 2187 if ( !this.stamps || !this.stamps.length ) { 2188 return; 2189 } 2190 2191 this._getBoundingRect(); 2192 2193 this.stamps.forEach( this._manageStamp, this ); 2194}; 2195 2196// update boundingLeft / Top 2197proto._getBoundingRect = function() { 2198 // get bounding rect for container element 2199 var boundingRect = this.element.getBoundingClientRect(); 2200 var size = this.size; 2201 this._boundingRect = { 2202 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 2203 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 2204 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 2205 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 2206 }; 2207}; 2208 2209/** 2210 * @param {Element} stamp 2211**/ 2212proto._manageStamp = noop; 2213 2214/** 2215 * get x/y position of element relative to container element 2216 * @param {Element} elem 2217 * @returns {Object} offset - has left, top, right, bottom 2218 */ 2219proto._getElementOffset = function( elem ) { 2220 var boundingRect = elem.getBoundingClientRect(); 2221 var thisRect = this._boundingRect; 2222 var size = getSize( elem ); 2223 var offset = { 2224 left: boundingRect.left - thisRect.left - size.marginLeft, 2225 top: boundingRect.top - thisRect.top - size.marginTop, 2226 right: thisRect.right - boundingRect.right - size.marginRight, 2227 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 2228 }; 2229 return offset; 2230}; 2231 2232// -------------------------- resize -------------------------- // 2233 2234// enable event handlers for listeners 2235// i.e. resize -> onresize 2236proto.handleEvent = utils.handleEvent; 2237 2238/** 2239 * Bind layout to window resizing 2240 */ 2241proto.bindResize = function() { 2242 window.addEventListener( 'resize', this ); 2243 this.isResizeBound = true; 2244}; 2245 2246/** 2247 * Unbind layout to window resizing 2248 */ 2249proto.unbindResize = function() { 2250 window.removeEventListener( 'resize', this ); 2251 this.isResizeBound = false; 2252}; 2253 2254proto.onresize = function() { 2255 this.resize(); 2256}; 2257 2258utils.debounceMethod( Outlayer, 'onresize', 100 ); 2259 2260proto.resize = function() { 2261 // don't trigger if size did not change 2262 // or if resize was unbound. See #9 2263 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 2264 return; 2265 } 2266 2267 this.layout(); 2268}; 2269 2270/** 2271 * check if layout is needed post layout 2272 * @returns Boolean 2273 */ 2274proto.needsResizeLayout = function() { 2275 var size = getSize( this.element ); 2276 // check that this.size and size are there 2277 // IE8 triggers resize on body size change, so they might not be 2278 var hasSizes = this.size && size; 2279 return hasSizes && size.innerWidth !== this.size.innerWidth; 2280}; 2281 2282// -------------------------- methods -------------------------- // 2283 2284/** 2285 * add items to Outlayer instance 2286 * @param {Array or NodeList or Element} elems 2287 * @returns {Array} items - Outlayer.Items 2288**/ 2289proto.addItems = function( elems ) { 2290 var items = this._itemize( elems ); 2291 // add items to collection 2292 if ( items.length ) { 2293 this.items = this.items.concat( items ); 2294 } 2295 return items; 2296}; 2297 2298/** 2299 * Layout newly-appended item elements 2300 * @param {Array or NodeList or Element} elems 2301 */ 2302proto.appended = function( elems ) { 2303 var items = this.addItems( elems ); 2304 if ( !items.length ) { 2305 return; 2306 } 2307 // layout and reveal just the new items 2308 this.layoutItems( items, true ); 2309 this.reveal( items ); 2310}; 2311 2312/** 2313 * Layout prepended elements 2314 * @param {Array or NodeList or Element} elems 2315 */ 2316proto.prepended = function( elems ) { 2317 var items = this._itemize( elems ); 2318 if ( !items.length ) { 2319 return; 2320 } 2321 // add items to beginning of collection 2322 var previousItems = this.items.slice(0); 2323 this.items = items.concat( previousItems ); 2324 // start new layout 2325 this._resetLayout(); 2326 this._manageStamps(); 2327 // layout new stuff without transition 2328 this.layoutItems( items, true ); 2329 this.reveal( items ); 2330 // layout previous items 2331 this.layoutItems( previousItems ); 2332}; 2333 2334/** 2335 * reveal a collection of items 2336 * @param {Array of Outlayer.Items} items 2337 */ 2338proto.reveal = function( items ) { 2339 this._emitCompleteOnItems( 'reveal', items ); 2340 if ( !items || !items.length ) { 2341 return; 2342 } 2343 var stagger = this.updateStagger(); 2344 items.forEach( function( item, i ) { 2345 item.stagger( i * stagger ); 2346 item.reveal(); 2347 }); 2348}; 2349 2350/** 2351 * hide a collection of items 2352 * @param {Array of Outlayer.Items} items 2353 */ 2354proto.hide = function( items ) { 2355 this._emitCompleteOnItems( 'hide', items ); 2356 if ( !items || !items.length ) { 2357 return; 2358 } 2359 var stagger = this.updateStagger(); 2360 items.forEach( function( item, i ) { 2361 item.stagger( i * stagger ); 2362 item.hide(); 2363 }); 2364}; 2365 2366/** 2367 * reveal item elements 2368 * @param {Array}, {Element}, {NodeList} items 2369 */ 2370proto.revealItemElements = function( elems ) { 2371 var items = this.getItems( elems ); 2372 this.reveal( items ); 2373}; 2374 2375/** 2376 * hide item elements 2377 * @param {Array}, {Element}, {NodeList} items 2378 */ 2379proto.hideItemElements = function( elems ) { 2380 var items = this.getItems( elems ); 2381 this.hide( items ); 2382}; 2383 2384/** 2385 * get Outlayer.Item, given an Element 2386 * @param {Element} elem 2387 * @param {Function} callback 2388 * @returns {Outlayer.Item} item 2389 */ 2390proto.getItem = function( elem ) { 2391 // loop through items to get the one that matches 2392 for ( var i=0; i < this.items.length; i++ ) { 2393 var item = this.items[i]; 2394 if ( item.element == elem ) { 2395 // return item 2396 return item; 2397 } 2398 } 2399}; 2400 2401/** 2402 * get collection of Outlayer.Items, given Elements 2403 * @param {Array} elems 2404 * @returns {Array} items - Outlayer.Items 2405 */ 2406proto.getItems = function( elems ) { 2407 elems = utils.makeArray( elems ); 2408 var items = []; 2409 elems.forEach( function( elem ) { 2410 var item = this.getItem( elem ); 2411 if ( item ) { 2412 items.push( item ); 2413 } 2414 }, this ); 2415 2416 return items; 2417}; 2418 2419/** 2420 * remove element(s) from instance and DOM 2421 * @param {Array or NodeList or Element} elems 2422 */ 2423proto.remove = function( elems ) { 2424 var removeItems = this.getItems( elems ); 2425 2426 this._emitCompleteOnItems( 'remove', removeItems ); 2427 2428 // bail if no items to remove 2429 if ( !removeItems || !removeItems.length ) { 2430 return; 2431 } 2432
vendor: 38,285 bytes, lines 2433-3856
2433 removeItems.forEach( function( item ) { 2434 item.remove(); 2435 // remove item from collection 2436 utils.removeFrom( this.items, item ); 2437 }, this ); 2438}; 2439 2440// ----- destroy ----- // 2441 2442// remove and disable Outlayer instance 2443proto.destroy = function() { 2444 // clean up dynamic styles 2445 var style = this.element.style; 2446 style.height = ''; 2447 style.position = ''; 2448 style.width = ''; 2449 // destroy items 2450 this.items.forEach( function( item ) { 2451 item.destroy(); 2452 }); 2453 2454 this.unbindResize(); 2455 2456 var id = this.element.outlayerGUID; 2457 delete instances[ id ]; // remove reference to instance by id 2458 delete this.element.outlayerGUID; 2459 // remove data for jQuery 2460 if ( jQuery ) { 2461 jQuery.removeData( this.element, this.constructor.namespace ); 2462 } 2463 2464}; 2465 2466// -------------------------- data -------------------------- // 2467 2468/** 2469 * get Outlayer instance from element 2470 * @param {Element} elem 2471 * @returns {Outlayer} 2472 */ 2473Outlayer.data = function( elem ) { 2474 elem = utils.getQueryElement( elem ); 2475 var id = elem && elem.outlayerGUID; 2476 return id && instances[ id ]; 2477}; 2478 2479 2480// -------------------------- create Outlayer class -------------------------- // 2481 2482/** 2483 * create a layout class 2484 * @param {String} namespace 2485 */ 2486Outlayer.create = function( namespace, options ) { 2487 // sub-class Outlayer 2488 var Layout = subclass( Outlayer ); 2489 // apply new options and compatOptions 2490 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 2491 utils.extend( Layout.defaults, options ); 2492 Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); 2493 2494 Layout.namespace = namespace; 2495 2496 Layout.data = Outlayer.data; 2497 2498 // sub-class Item 2499 Layout.Item = subclass( Item ); 2500 2501 // -------------------------- declarative -------------------------- // 2502 2503 utils.htmlInit( Layout, namespace ); 2504 2505 // -------------------------- jQuery bridge -------------------------- // 2506 2507 // make into jQuery plugin 2508 if ( jQuery && jQuery.bridget ) { 2509 jQuery.bridget( namespace, Layout ); 2510 } 2511 2512 return Layout; 2513}; 2514 2515function subclass( Parent ) { 2516 function SubClass() { 2517 Parent.apply( this, arguments ); 2518 } 2519 2520 SubClass.prototype = Object.create( Parent.prototype ); 2521 SubClass.prototype.constructor = SubClass; 2522 2523 return SubClass; 2524} 2525 2526// ----- helpers ----- // 2527 2528// how many milliseconds are in each unit 2529var msUnits = { 2530 ms: 1, 2531 s: 1000 2532}; 2533 2534// munge time-like parameter into millisecond number 2535// '0.4s' -> 40 2536function getMilliseconds( time ) { 2537 if ( typeof time == 'number' ) { 2538 return time; 2539 } 2540 var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); 2541 var num = matches && matches[1]; 2542 var unit = matches && matches[2]; 2543 if ( !num.length ) { 2544 return 0; 2545 } 2546 num = parseFloat( num ); 2547 var mult = msUnits[ unit ] || 1; 2548 return num * mult; 2549} 2550 2551// ----- fin ----- // 2552 2553// back in global 2554Outlayer.Item = Item; 2555 2556return Outlayer; 2557 2558})); 2559 2560/** 2561 * Isotope Item 2562**/ 2563 2564( function( window, factory ) { 2565 // universal module definition 2566 /* jshint strict: false */ /*globals define, module, require */ 2567 if ( typeof define == 'function' && define.amd ) { 2568 // AMD 2569 define( 'isotope-layout/js/item',[ 2570 'outlayer/outlayer' 2571 ], 2572 factory ); 2573 } else if ( typeof module == 'object' && module.exports ) { 2574 // CommonJS 2575 module.exports = factory( 2576 require('outlayer') 2577 ); 2578 } else { 2579 // browser global 2580 window.Isotope = window.Isotope || {}; 2581 window.Isotope.Item = factory( 2582 window.Outlayer 2583 ); 2584 } 2585 2586}( window, function factory( Outlayer ) { 2587'use strict'; 2588 2589// -------------------------- Item -------------------------- // 2590 2591// sub-class Outlayer Item 2592function Item() { 2593 Outlayer.Item.apply( this, arguments ); 2594} 2595 2596var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 2597 2598var _create = proto._create; 2599proto._create = function() { 2600 // assign id, used for original-order sorting 2601 this.id = this.layout.itemGUID++; 2602 _create.call( this ); 2603 this.sortData = {}; 2604}; 2605 2606proto.updateSortData = function() { 2607 if ( this.isIgnored ) { 2608 return; 2609 } 2610 // default sorters 2611 this.sortData.id = this.id; 2612 // for backward compatibility 2613 this.sortData['original-order'] = this.id; 2614 this.sortData.random = Math.random(); 2615 // go thru getSortData obj and apply the sorters 2616 var getSortData = this.layout.options.getSortData; 2617 var sorters = this.layout._sorters; 2618 for ( var key in getSortData ) { 2619 var sorter = sorters[ key ]; 2620 this.sortData[ key ] = sorter( this.element, this ); 2621 } 2622}; 2623 2624var _destroy = proto.destroy; 2625proto.destroy = function() { 2626 // call super 2627 _destroy.apply( this, arguments ); 2628 // reset display, #741 2629 this.css({ 2630 display: '' 2631 }); 2632}; 2633 2634return Item; 2635 2636})); 2637 2638/** 2639 * Isotope LayoutMode 2640 */ 2641 2642( function( window, factory ) { 2643 // universal module definition 2644 /* jshint strict: false */ /*globals define, module, require */ 2645 if ( typeof define == 'function' && define.amd ) { 2646 // AMD 2647 define( 'isotope-layout/js/layout-mode',[ 2648 'get-size/get-size', 2649 'outlayer/outlayer' 2650 ], 2651 factory ); 2652 } else if ( typeof module == 'object' && module.exports ) { 2653 // CommonJS 2654 module.exports = factory( 2655 require('get-size'), 2656 require('outlayer') 2657 ); 2658 } else { 2659 // browser global 2660 window.Isotope = window.Isotope || {}; 2661 window.Isotope.LayoutMode = factory( 2662 window.getSize, 2663 window.Outlayer 2664 ); 2665 } 2666 2667}( window, function factory( getSize, Outlayer ) { 2668 'use strict'; 2669 2670 // layout mode class 2671 function LayoutMode( isotope ) { 2672 this.isotope = isotope; 2673 // link properties 2674 if ( isotope ) { 2675 this.options = isotope.options[ this.namespace ]; 2676 this.element = isotope.element; 2677 this.items = isotope.filteredItems; 2678 this.size = isotope.size; 2679 } 2680 } 2681 2682 var proto = LayoutMode.prototype; 2683 2684 /** 2685 * some methods should just defer to default Outlayer method 2686 * and reference the Isotope instance as `this` 2687 **/ 2688 var facadeMethods = [ 2689 '_resetLayout', 2690 '_getItemLayoutPosition', 2691 '_manageStamp', 2692 '_getContainerSize', 2693 '_getElementOffset', 2694 'needsResizeLayout', 2695 '_getOption' 2696 ]; 2697 2698 facadeMethods.forEach( function( methodName ) { 2699 proto[ methodName ] = function() { 2700 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 2701 }; 2702 }); 2703 2704 // ----- ----- // 2705 2706 // for horizontal layout modes, check vertical size 2707 proto.needsVerticalResizeLayout = function() { 2708 // don't trigger if size did not change 2709 var size = getSize( this.isotope.element ); 2710 // check that this.size and size are there 2711 // IE8 triggers resize on body size change, so they might not be 2712 var hasSizes = this.isotope.size && size; 2713 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 2714 }; 2715 2716 // ----- measurements ----- // 2717 2718 proto._getMeasurement = function() { 2719 this.isotope._getMeasurement.apply( this, arguments ); 2720 }; 2721 2722 proto.getColumnWidth = function() { 2723 this.getSegmentSize( 'column', 'Width' ); 2724 }; 2725 2726 proto.getRowHeight = function() { 2727 this.getSegmentSize( 'row', 'Height' ); 2728 }; 2729 2730 /** 2731 * get columnWidth or rowHeight 2732 * segment: 'column' or 'row' 2733 * size 'Width' or 'Height' 2734 **/ 2735 proto.getSegmentSize = function( segment, size ) { 2736 var segmentName = segment + size; 2737 var outerSize = 'outer' + size; 2738 // columnWidth / outerWidth // rowHeight / outerHeight 2739 this._getMeasurement( segmentName, outerSize ); 2740 // got rowHeight or columnWidth, we can chill 2741 if ( this[ segmentName ] ) { 2742 return; 2743 } 2744 // fall back to item of first element 2745 var firstItemSize = this.getFirstItemSize(); 2746 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 2747 // or size of container 2748 this.isotope.size[ 'inner' + size ]; 2749 }; 2750 2751 proto.getFirstItemSize = function() { 2752 var firstItem = this.isotope.filteredItems[0]; 2753 return firstItem && firstItem.element && getSize( firstItem.element ); 2754 }; 2755 2756 // ----- methods that should reference isotope ----- // 2757 2758 proto.layout = function() { 2759 this.isotope.layout.apply( this.isotope, arguments ); 2760 }; 2761 2762 proto.getSize = function() { 2763 this.isotope.getSize(); 2764 this.size = this.isotope.size; 2765 }; 2766 2767 // -------------------------- create -------------------------- // 2768 2769 LayoutMode.modes = {}; 2770 2771 LayoutMode.create = function( namespace, options ) { 2772 2773 function Mode() { 2774 LayoutMode.apply( this, arguments ); 2775 } 2776 2777 Mode.prototype = Object.create( proto ); 2778 Mode.prototype.constructor = Mode; 2779 2780 // default options 2781 if ( options ) { 2782 Mode.options = options; 2783 } 2784 2785 Mode.prototype.namespace = namespace; 2786 // register in Isotope 2787 LayoutMode.modes[ namespace ] = Mode; 2788 2789 return Mode; 2790 }; 2791 2792 return LayoutMode; 2793 2794})); 2795 2796/*! 2797 * Masonry v4.2.1 2798 * Cascading grid layout library 2799 * https://masonry.desandro.com 2800 * MIT License 2801 * by David DeSandro 2802 */ 2803 2804( function( window, factory ) { 2805 // universal module definition 2806 /* jshint strict: false */ /*globals define, module, require */ 2807 if ( typeof define == 'function' && define.amd ) { 2808 // AMD 2809 define( 'masonry-layout/masonry',[ 2810 'outlayer/outlayer', 2811 'get-size/get-size' 2812 ], 2813 factory ); 2814 } else if ( typeof module == 'object' && module.exports ) { 2815 // CommonJS 2816 module.exports = factory( 2817 require('outlayer'), 2818 require('get-size') 2819 ); 2820 } else { 2821 // browser global 2822 window.Masonry = factory( 2823 window.Outlayer, 2824 window.getSize 2825 ); 2826 } 2827 2828}( window, function factory( Outlayer, getSize ) { 2829 2830 2831 2832// -------------------------- masonryDefinition -------------------------- // 2833 2834 // create an Outlayer layout class 2835 var Masonry = Outlayer.create('masonry'); 2836 // isFitWidth -> fitWidth 2837 Masonry.compatOptions.fitWidth = 'isFitWidth'; 2838 2839 var proto = Masonry.prototype; 2840 2841 proto._resetLayout = function() { 2842 this.getSize(); 2843 this._getMeasurement( 'columnWidth', 'outerWidth' ); 2844 this._getMeasurement( 'gutter', 'outerWidth' ); 2845 this.measureColumns(); 2846 2847 // reset column Y 2848 this.colYs = []; 2849 for ( var i=0; i < this.cols; i++ ) { 2850 this.colYs.push( 0 ); 2851 } 2852 2853 this.maxY = 0; 2854 this.horizontalColIndex = 0; 2855 }; 2856 2857 proto.measureColumns = function() { 2858 this.getContainerWidth(); 2859 // if columnWidth is 0, default to outerWidth of first item 2860 if ( !this.columnWidth ) { 2861 var firstItem = this.items[0]; 2862 var firstItemElem = firstItem && firstItem.element; 2863 // columnWidth fall back to item of first element 2864 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 2865 // if first elem has no width, default to size of container 2866 this.containerWidth; 2867 } 2868 2869 var columnWidth = this.columnWidth += this.gutter; 2870 2871 // calculate columns 2872 var containerWidth = this.containerWidth + this.gutter; 2873 var cols = containerWidth / columnWidth; 2874 // fix rounding errors, typically with gutters 2875 var excess = columnWidth - containerWidth % columnWidth; 2876 // if overshoot is less than a pixel, round up, otherwise floor it 2877 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 2878 cols = Math[ mathMethod ]( cols ); 2879 this.cols = Math.max( cols, 1 ); 2880 }; 2881 2882 proto.getContainerWidth = function() { 2883 // container is parent if fit width 2884 var isFitWidth = this._getOption('fitWidth'); 2885 var container = isFitWidth ? this.element.parentNode : this.element; 2886 // check that this.size and size are there 2887 // IE8 triggers resize on body size change, so they might not be 2888 var size = getSize( container ); 2889 this.containerWidth = size && size.innerWidth; 2890 }; 2891 2892 proto._getItemLayoutPosition = function( item ) { 2893 item.getSize(); 2894 // how many columns does this brick span 2895 var remainder = item.size.outerWidth % this.columnWidth; 2896 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 2897 // round if off by 1 pixel, otherwise use ceil 2898 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 2899 colSpan = Math.min( colSpan, this.cols ); 2900 // use horizontal or top column position 2901 var colPosMethod = this.options.horizontalOrder ? 2902 '_getHorizontalColPosition' : '_getTopColPosition'; 2903 var colPosition = this[ colPosMethod ]( colSpan, item ); 2904 // position the brick 2905 var position = { 2906 x: this.columnWidth * colPosition.col, 2907 y: colPosition.y 2908 }; 2909 // apply setHeight to necessary columns 2910 var setHeight = colPosition.y + item.size.outerHeight; 2911 var setMax = colSpan + colPosition.col; 2912 for ( var i = colPosition.col; i < setMax; i++ ) { 2913 this.colYs[i] = setHeight; 2914 } 2915 2916 return position; 2917 }; 2918 2919 proto._getTopColPosition = function( colSpan ) { 2920 var colGroup = this._getTopColGroup( colSpan ); 2921 // get the minimum Y value from the columns 2922 var minimumY = Math.min.apply( Math, colGroup ); 2923 2924 return { 2925 col: colGroup.indexOf( minimumY ), 2926 y: minimumY, 2927 }; 2928 }; 2929 2930 /** 2931 * @param {Number} colSpan - number of columns the element spans 2932 * @returns {Array} colGroup 2933 */ 2934 proto._getTopColGroup = function( colSpan ) { 2935 if ( colSpan < 2 ) { 2936 // if brick spans only one column, use all the column Ys 2937 return this.colYs; 2938 } 2939 2940 var colGroup = []; 2941 // how many different places could this brick fit horizontally 2942 var groupCount = this.cols + 1 - colSpan; 2943 // for each group potential horizontal position 2944 for ( var i = 0; i < groupCount; i++ ) { 2945 colGroup[i] = this._getColGroupY( i, colSpan ); 2946 } 2947 return colGroup; 2948 }; 2949 2950 proto._getColGroupY = function( col, colSpan ) { 2951 if ( colSpan < 2 ) { 2952 return this.colYs[ col ]; 2953 } 2954 // make an array of colY values for that one group 2955 var groupColYs = this.colYs.slice( col, col + colSpan ); 2956 // and get the max value of the array 2957 return Math.max.apply( Math, groupColYs ); 2958 }; 2959 2960 // get column position based on horizontal index. #873 2961 proto._getHorizontalColPosition = function( colSpan, item ) { 2962 var col = this.horizontalColIndex % this.cols; 2963 var isOver = colSpan > 1 && col + colSpan > this.cols; 2964 // shift to next row if item can't fit on current row 2965 col = isOver ? 0 : col; 2966 // don't let zero-size items take up space 2967 var hasSize = item.size.outerWidth && item.size.outerHeight; 2968 this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex; 2969 2970 return { 2971 col: col, 2972 y: this._getColGroupY( col, colSpan ), 2973 }; 2974 }; 2975 2976 proto._manageStamp = function( stamp ) { 2977 var stampSize = getSize( stamp ); 2978 var offset = this._getElementOffset( stamp ); 2979 // get the columns that this stamp affects 2980 var isOriginLeft = this._getOption('originLeft'); 2981 var firstX = isOriginLeft ? offset.left : offset.right; 2982 var lastX = firstX + stampSize.outerWidth; 2983 var firstCol = Math.floor( firstX / this.columnWidth ); 2984 firstCol = Math.max( 0, firstCol ); 2985 var lastCol = Math.floor( lastX / this.columnWidth ); 2986 // lastCol should not go over if multiple of columnWidth #425 2987 lastCol -= lastX % this.columnWidth ? 0 : 1; 2988 lastCol = Math.min( this.cols - 1, lastCol ); 2989 // set colYs to bottom of the stamp 2990 2991 var isOriginTop = this._getOption('originTop'); 2992 var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + 2993 stampSize.outerHeight; 2994 for ( var i = firstCol; i <= lastCol; i++ ) { 2995 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 2996 } 2997 }; 2998 2999 proto._getContainerSize = function() { 3000 this.maxY = Math.max.apply( Math, this.colYs ); 3001 var size = { 3002 height: this.maxY 3003 }; 3004 3005 if ( this._getOption('fitWidth') ) { 3006 size.width = this._getContainerFitWidth(); 3007 } 3008 3009 return size; 3010 }; 3011 3012 proto._getContainerFitWidth = function() { 3013 var unusedCols = 0; 3014 // count unused columns 3015 var i = this.cols; 3016 while ( --i ) { 3017 if ( this.colYs[i] !== 0 ) { 3018 break; 3019 } 3020 unusedCols++; 3021 } 3022 // fit container to columns that have been used 3023 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 3024 }; 3025 3026 proto.needsResizeLayout = function() { 3027 var previousWidth = this.containerWidth; 3028 this.getContainerWidth(); 3029 return previousWidth != this.containerWidth; 3030 }; 3031 3032 return Masonry; 3033 3034})); 3035 3036/*! 3037 * Masonry layout mode 3038 * sub-classes Masonry 3039 * https://masonry.desandro.com 3040 */ 3041 3042( function( window, factory ) { 3043 // universal module definition 3044 /* jshint strict: false */ /*globals define, module, require */ 3045 if ( typeof define == 'function' && define.amd ) { 3046 // AMD 3047 define( 'isotope-layout/js/layout-modes/masonry',[ 3048 '../layout-mode', 3049 'masonry-layout/masonry' 3050 ], 3051 factory ); 3052 } else if ( typeof module == 'object' && module.exports ) { 3053 // CommonJS 3054 module.exports = factory( 3055 require('../layout-mode'), 3056 require('masonry-layout') 3057 ); 3058 } else { 3059 // browser global 3060 factory( 3061 window.Isotope.LayoutMode, 3062 window.Masonry 3063 ); 3064 } 3065 3066}( window, function factory( LayoutMode, Masonry ) { 3067'use strict'; 3068 3069// -------------------------- masonryDefinition -------------------------- // 3070 3071 // create an Outlayer layout class 3072 var MasonryMode = LayoutMode.create('masonry'); 3073 3074 var proto = MasonryMode.prototype; 3075 3076 var keepModeMethods = { 3077 _getElementOffset: true, 3078 layout: true, 3079 _getMeasurement: true 3080 }; 3081 3082 // inherit Masonry prototype 3083 for ( var method in Masonry.prototype ) { 3084 // do not inherit mode methods 3085 if ( !keepModeMethods[ method ] ) { 3086 proto[ method ] = Masonry.prototype[ method ]; 3087 } 3088 } 3089 3090 var measureColumns = proto.measureColumns; 3091 proto.measureColumns = function() { 3092 // set items, used if measuring first item 3093 this.items = this.isotope.filteredItems; 3094 measureColumns.call( this ); 3095 }; 3096 3097 // point to mode options for fitWidth 3098 var _getOption = proto._getOption; 3099 proto._getOption = function( option ) { 3100 if ( option == 'fitWidth' ) { 3101 return this.options.isFitWidth !== undefined ? 3102 this.options.isFitWidth : this.options.fitWidth; 3103 } 3104 return _getOption.apply( this.isotope, arguments ); 3105 }; 3106 3107 return MasonryMode; 3108 3109})); 3110 3111/** 3112 * fitRows layout mode 3113 */ 3114 3115( function( window, factory ) { 3116 // universal module definition 3117 /* jshint strict: false */ /*globals define, module, require */ 3118 if ( typeof define == 'function' && define.amd ) { 3119 // AMD 3120 define( 'isotope-layout/js/layout-modes/fit-rows',[ 3121 '../layout-mode' 3122 ], 3123 factory ); 3124 } else if ( typeof exports == 'object' ) { 3125 // CommonJS 3126 module.exports = factory( 3127 require('../layout-mode') 3128 ); 3129 } else { 3130 // browser global 3131 factory( 3132 window.Isotope.LayoutMode 3133 ); 3134 } 3135 3136}( window, function factory( LayoutMode ) { 3137'use strict'; 3138 3139var FitRows = LayoutMode.create('fitRows'); 3140 3141var proto = FitRows.prototype; 3142 3143proto._resetLayout = function() { 3144 this.x = 0; 3145 this.y = 0; 3146 this.maxY = 0; 3147 this._getMeasurement( 'gutter', 'outerWidth' ); 3148}; 3149 3150proto._getItemLayoutPosition = function( item ) { 3151 item.getSize(); 3152 3153 var itemWidth = item.size.outerWidth + this.gutter; 3154 // if this element cannot fit in the current row 3155 var containerWidth = this.isotope.size.innerWidth + this.gutter; 3156 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 3157 this.x = 0; 3158 this.y = this.maxY; 3159 } 3160 3161 var position = { 3162 x: this.x, 3163 y: this.y 3164 }; 3165 3166 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 3167 this.x += itemWidth; 3168 3169 return position; 3170}; 3171 3172proto._getContainerSize = function() { 3173 return { height: this.maxY }; 3174}; 3175 3176return FitRows; 3177 3178})); 3179 3180/** 3181 * vertical layout mode 3182 */ 3183 3184( function( window, factory ) { 3185 // universal module definition 3186 /* jshint strict: false */ /*globals define, module, require */ 3187 if ( typeof define == 'function' && define.amd ) { 3188 // AMD 3189 define( 'isotope-layout/js/layout-modes/vertical',[ 3190 '../layout-mode' 3191 ], 3192 factory ); 3193 } else if ( typeof module == 'object' && module.exports ) { 3194 // CommonJS 3195 module.exports = factory( 3196 require('../layout-mode') 3197 ); 3198 } else { 3199 // browser global 3200 factory( 3201 window.Isotope.LayoutMode 3202 ); 3203 } 3204 3205}( window, function factory( LayoutMode ) { 3206'use strict'; 3207 3208var Vertical = LayoutMode.create( 'vertical', { 3209 horizontalAlignment: 0 3210}); 3211 3212var proto = Vertical.prototype; 3213 3214proto._resetLayout = function() { 3215 this.y = 0; 3216}; 3217 3218proto._getItemLayoutPosition = function( item ) { 3219 item.getSize(); 3220 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 3221 this.options.horizontalAlignment; 3222 var y = this.y; 3223 this.y += item.size.outerHeight; 3224 return { x: x, y: y }; 3225}; 3226 3227proto._getContainerSize = function() { 3228 return { height: this.y }; 3229}; 3230 3231return Vertical; 3232 3233})); 3234 3235/*! 3236 * Isotope v3.0.6 3237 * 3238 * Licensed GPLv3 for open source use 3239 * or Isotope Commercial License for commercial use 3240 * 3241 * https://isotope.metafizzy.co 3242 * Copyright 2010-2018 Metafizzy 3243 */ 3244 3245( function( window, factory ) { 3246 // universal module definition 3247 /* jshint strict: false */ /*globals define, module, require */ 3248 if ( typeof define == 'function' && define.amd ) { 3249 // AMD 3250 define( [ 3251 'outlayer/outlayer', 3252 'get-size/get-size', 3253 'desandro-matches-selector/matches-selector', 3254 'fizzy-ui-utils/utils', 3255 'isotope-layout/js/item', 3256 'isotope-layout/js/layout-mode', 3257 // include default layout modes 3258 'isotope-layout/js/layout-modes/masonry', 3259 'isotope-layout/js/layout-modes/fit-rows', 3260 'isotope-layout/js/layout-modes/vertical' 3261 ], 3262 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 3263 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 3264 }); 3265 } else if ( typeof module == 'object' && module.exports ) { 3266 // CommonJS 3267 module.exports = factory( 3268 window, 3269 require('outlayer'), 3270 require('get-size'), 3271 require('desandro-matches-selector'), 3272 require('fizzy-ui-utils'), 3273 require('isotope-layout/js/item'), 3274 require('isotope-layout/js/layout-mode'), 3275 // include default layout modes 3276 require('isotope-layout/js/layout-modes/masonry'), 3277 require('isotope-layout/js/layout-modes/fit-rows'), 3278 require('isotope-layout/js/layout-modes/vertical') 3279 ); 3280 } else { 3281 // browser global 3282 window.Isotope = factory( 3283 window, 3284 window.Outlayer, 3285 window.getSize, 3286 window.matchesSelector, 3287 window.fizzyUIUtils, 3288 window.Isotope.Item, 3289 window.Isotope.LayoutMode 3290 ); 3291 } 3292 3293}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 3294 Item, LayoutMode ) { 3295 3296 3297 3298// -------------------------- vars -------------------------- // 3299 3300var jQuery = window.jQuery; 3301 3302// -------------------------- helpers -------------------------- // 3303 3304var trim = String.prototype.trim ? 3305 function( str ) { 3306 return str.trim(); 3307 } : 3308 function( str ) { 3309 return str.replace( /^\s+|\s+$/g, '' ); 3310 }; 3311 3312// -------------------------- isotopeDefinition -------------------------- // 3313 3314 // create an Outlayer layout class 3315 var Isotope = Outlayer.create( 'isotope', { 3316 layoutMode: 'masonry', 3317 isJQueryFiltering: true, 3318 sortAscending: true 3319 }); 3320 3321 Isotope.Item = Item; 3322 Isotope.LayoutMode = LayoutMode; 3323 3324 var proto = Isotope.prototype; 3325 3326 proto._create = function() { 3327 this.itemGUID = 0; 3328 // functions that sort items 3329 this._sorters = {}; 3330 this._getSorters(); 3331 // call super 3332 Outlayer.prototype._create.call( this ); 3333 3334 // create layout modes 3335 this.modes = {}; 3336 // start filteredItems with all items 3337 this.filteredItems = this.items; 3338 // keep of track of sortBys 3339 this.sortHistory = [ 'original-order' ]; 3340 // create from registered layout modes 3341 for ( var name in LayoutMode.modes ) { 3342 this._initLayoutMode( name ); 3343 } 3344 }; 3345 3346 proto.reloadItems = function() { 3347 // reset item ID counter 3348 this.itemGUID = 0; 3349 // call super 3350 Outlayer.prototype.reloadItems.call( this ); 3351 }; 3352 3353 proto._itemize = function() { 3354 var items = Outlayer.prototype._itemize.apply( this, arguments ); 3355 // assign ID for original-order 3356 for ( var i=0; i < items.length; i++ ) { 3357 var item = items[i]; 3358 item.id = this.itemGUID++; 3359 } 3360 this._updateItemsSortData( items ); 3361 return items; 3362 }; 3363 3364 3365 // -------------------------- layout -------------------------- // 3366 3367 proto._initLayoutMode = function( name ) { 3368 var Mode = LayoutMode.modes[ name ]; 3369 // set mode options 3370 // HACK extend initial options, back-fill in default options 3371 var initialOpts = this.options[ name ] || {}; 3372 this.options[ name ] = Mode.options ? 3373 utils.extend( Mode.options, initialOpts ) : initialOpts; 3374 // init layout mode instance 3375 this.modes[ name ] = new Mode( this ); 3376 }; 3377 3378 3379 proto.layout = function() { 3380 // if first time doing layout, do all magic 3381 if ( !this._isLayoutInited && this._getOption('initLayout') ) { 3382 this.arrange(); 3383 return; 3384 } 3385 this._layout(); 3386 }; 3387 3388 // private method to be used in layout() & magic() 3389 proto._layout = function() { 3390 // don't animate first layout 3391 var isInstant = this._getIsInstant(); 3392 // layout flow 3393 this._resetLayout(); 3394 this._manageStamps(); 3395 this.layoutItems( this.filteredItems, isInstant ); 3396 3397 // flag for initalized 3398 this._isLayoutInited = true; 3399 }; 3400 3401 // filter + sort + layout 3402 proto.arrange = function( opts ) { 3403 // set any options pass 3404 this.option( opts ); 3405 this._getIsInstant(); 3406 // filter, sort, and layout 3407 3408 // filter 3409 var filtered = this._filter( this.items ); 3410 this.filteredItems = filtered.matches; 3411 3412 this._bindArrangeComplete(); 3413 3414 if ( this._isInstant ) { 3415 this._noTransition( this._hideReveal, [ filtered ] ); 3416 } else { 3417 this._hideReveal( filtered ); 3418 } 3419 3420 this._sort(); 3421 this._layout(); 3422 }; 3423 // alias to _init for main plugin method 3424 proto._init = proto.arrange; 3425 3426 proto._hideReveal = function( filtered ) { 3427 this.reveal( filtered.needReveal ); 3428 this.hide( filtered.needHide ); 3429 }; 3430 3431 // HACK 3432 // Don't animate/transition first layout 3433 // Or don't animate/transition other layouts 3434 proto._getIsInstant = function() { 3435 var isLayoutInstant = this._getOption('layoutInstant'); 3436 var isInstant = isLayoutInstant !== undefined ? isLayoutInstant : 3437 !this._isLayoutInited; 3438 this._isInstant = isInstant; 3439 return isInstant; 3440 }; 3441 3442 // listen for layoutComplete, hideComplete and revealComplete 3443 // to trigger arrangeComplete 3444 proto._bindArrangeComplete = function() { 3445 // listen for 3 events to trigger arrangeComplete 3446 var isLayoutComplete, isHideComplete, isRevealComplete; 3447 var _this = this; 3448 function arrangeParallelCallback() { 3449 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 3450 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 3451 } 3452 } 3453 this.once( 'layoutComplete', function() { 3454 isLayoutComplete = true; 3455 arrangeParallelCallback(); 3456 }); 3457 this.once( 'hideComplete', function() { 3458 isHideComplete = true; 3459 arrangeParallelCallback(); 3460 }); 3461 this.once( 'revealComplete', function() { 3462 isRevealComplete = true; 3463 arrangeParallelCallback(); 3464 }); 3465 }; 3466 3467 // -------------------------- filter -------------------------- // 3468 3469 proto._filter = function( items ) { 3470 var filter = this.options.filter; 3471 filter = filter || '*'; 3472 var matches = []; 3473 var hiddenMatched = []; 3474 var visibleUnmatched = []; 3475 3476 var test = this._getFilterTest( filter ); 3477 3478 // test each item 3479 for ( var i=0; i < items.length; i++ ) { 3480 var item = items[i]; 3481 if ( item.isIgnored ) { 3482 continue; 3483 } 3484 // add item to either matched or unmatched group 3485 var isMatched = test( item ); 3486 // item.isFilterMatched = isMatched; 3487 // add to matches if its a match 3488 if ( isMatched ) { 3489 matches.push( item ); 3490 } 3491 // add to additional group if item needs to be hidden or revealed 3492 if ( isMatched && item.isHidden ) { 3493 hiddenMatched.push( item ); 3494 } else if ( !isMatched && !item.isHidden ) { 3495 visibleUnmatched.push( item ); 3496 } 3497 } 3498 3499 // return collections of items to be manipulated 3500 return { 3501 matches: matches, 3502 needReveal: hiddenMatched, 3503 needHide: visibleUnmatched 3504 }; 3505 }; 3506 3507 // get a jQuery, function, or a matchesSelector test given the filter 3508 proto._getFilterTest = function( filter ) { 3509 if ( jQuery && this.options.isJQueryFiltering ) { 3510 // use jQuery 3511 return function( item ) { 3512 return jQuery( item.element ).is( filter ); 3513 }; 3514 } 3515 if ( typeof filter == 'function' ) { 3516 // use filter as function 3517 return function( item ) { 3518 return filter( item.element ); 3519 }; 3520 } 3521 // default, use filter as selector string 3522 return function( item ) { 3523 return matchesSelector( item.element, filter ); 3524 }; 3525 }; 3526 3527 // -------------------------- sorting -------------------------- // 3528 3529 /** 3530 * @params {Array} elems 3531 * @public 3532 */ 3533 proto.updateSortData = function( elems ) { 3534 // get items 3535 var items; 3536 if ( elems ) { 3537 elems = utils.makeArray( elems ); 3538 items = this.getItems( elems ); 3539 } else { 3540 // update all items if no elems provided 3541 items = this.items; 3542 } 3543 3544 this._getSorters(); 3545 this._updateItemsSortData( items ); 3546 }; 3547 3548 proto._getSorters = function() { 3549 var getSortData = this.options.getSortData; 3550 for ( var key in getSortData ) { 3551 var sorter = getSortData[ key ]; 3552 this._sorters[ key ] = mungeSorter( sorter ); 3553 } 3554 }; 3555 3556 /** 3557 * @params {Array} items - of Isotope.Items 3558 * @private 3559 */ 3560 proto._updateItemsSortData = function( items ) { 3561 // do not update if no items 3562 var len = items && items.length; 3563 3564 for ( var i=0; len && i < len; i++ ) { 3565 var item = items[i]; 3566 item.updateSortData(); 3567 } 3568 }; 3569 3570 // ----- munge sorter ----- // 3571 3572 // encapsulate this, as we just need mungeSorter 3573 // other functions in here are just for munging 3574 var mungeSorter = ( function() { 3575 // add a magic layer to sorters for convienent shorthands 3576 // `.foo-bar` will use the text of .foo-bar querySelector 3577 // `[foo-bar]` will use attribute 3578 // you can also add parser 3579 // `.foo-bar parseInt` will parse that as a number 3580 function mungeSorter( sorter ) { 3581 // if not a string, return function or whatever it is 3582 if ( typeof sorter != 'string' ) { 3583 return sorter; 3584 } 3585 // parse the sorter string 3586 var args = trim( sorter ).split(' '); 3587 var query = args[0]; 3588 // check if query looks like [an-attribute] 3589 var attrMatch = query.match( /^\[(.+)\]$/ ); 3590 var attr = attrMatch && attrMatch[1]; 3591 var getValue = getValueGetter( attr, query ); 3592 // use second argument as a parser 3593 var parser = Isotope.sortDataParsers[ args[1] ]; 3594 // parse the value, if there was a parser 3595 sorter = parser ? function( elem ) { 3596 return elem && parser( getValue( elem ) ); 3597 } : 3598 // otherwise just return value 3599 function( elem ) { 3600 return elem && getValue( elem ); 3601 }; 3602 3603 return sorter; 3604 } 3605 3606 // get an attribute getter, or get text of the querySelector 3607 function getValueGetter( attr, query ) { 3608 // if query looks like [foo-bar], get attribute 3609 if ( attr ) { 3610 return function getAttribute( elem ) { 3611 return elem.getAttribute( attr ); 3612 }; 3613 } 3614 3615 // otherwise, assume its a querySelector, and get its text 3616 return function getChildText( elem ) { 3617 var child = elem.querySelector( query ); 3618 return child && child.textContent; 3619 }; 3620 } 3621 3622 return mungeSorter; 3623 })(); 3624 3625 // parsers used in getSortData shortcut strings 3626 Isotope.sortDataParsers = { 3627 'parseInt': function( val ) { 3628 return parseInt( val, 10 ); 3629 }, 3630 'parseFloat': function( val ) { 3631 return parseFloat( val ); 3632 } 3633 }; 3634 3635 // ----- sort method ----- // 3636 3637 // sort filteredItem order 3638 proto._sort = function() { 3639 if ( !this.options.sortBy ) { 3640 return; 3641 } 3642 // keep track of sortBy History 3643 var sortBys = utils.makeArray( this.options.sortBy ); 3644 if ( !this._getIsSameSortBy( sortBys ) ) { 3645 // concat all sortBy and sortHistory, add to front, oldest goes in last 3646 this.sortHistory = sortBys.concat( this.sortHistory ); 3647 } 3648 // sort magic 3649 var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending ); 3650 this.filteredItems.sort( itemSorter ); 3651 }; 3652 3653 // check if sortBys is same as start of sortHistory 3654 proto._getIsSameSortBy = function( sortBys ) { 3655 for ( var i=0; i < sortBys.length; i++ ) { 3656 if ( sortBys[i] != this.sortHistory[i] ) { 3657 return false; 3658 } 3659 } 3660 return true; 3661 }; 3662 3663 // returns a function used for sorting 3664 function getItemSorter( sortBys, sortAsc ) { 3665 return function sorter( itemA, itemB ) { 3666 // cycle through all sortKeys 3667 for ( var i = 0; i < sortBys.length; i++ ) { 3668 var sortBy = sortBys[i]; 3669 var a = itemA.sortData[ sortBy ]; 3670 var b = itemB.sortData[ sortBy ]; 3671 if ( a > b || a < b ) { 3672 // if sortAsc is an object, use the value given the sortBy key 3673 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 3674 var direction = isAscending ? 1 : -1; 3675 return ( a > b ? 1 : -1 ) * direction; 3676 } 3677 } 3678 return 0; 3679 }; 3680 } 3681 3682 // -------------------------- methods -------------------------- // 3683 3684 // get layout mode 3685 proto._mode = function() { 3686 var layoutMode = this.options.layoutMode; 3687 var mode = this.modes[ layoutMode ]; 3688 if ( !mode ) { 3689 // TODO console.error 3690 throw new Error( 'No layout mode: ' + layoutMode ); 3691 } 3692 // HACK sync mode's options 3693 // any options set after init for layout mode need to be synced 3694 mode.options = this.options[ layoutMode ]; 3695 return mode; 3696 }; 3697 3698 proto._resetLayout = function() { 3699 // trigger original reset layout 3700 Outlayer.prototype._resetLayout.call( this ); 3701 this._mode()._resetLayout(); 3702 }; 3703 3704 proto._getItemLayoutPosition = function( item ) { 3705 return this._mode()._getItemLayoutPosition( item ); 3706 }; 3707 3708 proto._manageStamp = function( stamp ) { 3709 this._mode()._manageStamp( stamp ); 3710 }; 3711 3712 proto._getContainerSize = function() { 3713 return this._mode()._getContainerSize(); 3714 }; 3715 3716 proto.needsResizeLayout = function() { 3717 return this._mode().needsResizeLayout(); 3718 }; 3719 3720 // -------------------------- adding & removing -------------------------- // 3721 3722 // HEADS UP overwrites default Outlayer appended 3723 proto.appended = function( elems ) { 3724 var items = this.addItems( elems ); 3725 if ( !items.length ) { 3726 return; 3727 } 3728 // filter, layout, reveal new items 3729 var filteredItems = this._filterRevealAdded( items ); 3730 // add to filteredItems 3731 this.filteredItems = this.filteredItems.concat( filteredItems ); 3732 }; 3733 3734 // HEADS UP overwrites default Outlayer prepended 3735 proto.prepended = function( elems ) { 3736 var items = this._itemize( elems ); 3737 if ( !items.length ) { 3738 return; 3739 } 3740 // start new layout 3741 this._resetLayout(); 3742 this._manageStamps(); 3743 // filter, layout, reveal new items 3744 var filteredItems = this._filterRevealAdded( items ); 3745 // layout previous items 3746 this.layoutItems( this.filteredItems ); 3747 // add to items and filteredItems 3748 this.filteredItems = filteredItems.concat( this.filteredItems ); 3749 this.items = items.concat( this.items ); 3750 }; 3751 3752 proto._filterRevealAdded = function( items ) { 3753 var filtered = this._filter( items ); 3754 this.hide( filtered.needHide ); 3755 // reveal all new items 3756 this.reveal( filtered.matches ); 3757 // layout new items, no transition 3758 this.layoutItems( filtered.matches, true ); 3759 return filtered.matches; 3760 }; 3761 3762 /** 3763 * Filter, sort, and layout newly-appended item elements 3764 * @param {Array or NodeList or Element} elems 3765 */ 3766 proto.insert = function( elems ) { 3767 var items = this.addItems( elems ); 3768 if ( !items.length ) { 3769 return; 3770 } 3771 // append item elements 3772 var i, item; 3773 var len = items.length; 3774 for ( i=0; i < len; i++ ) { 3775 item = items[i]; 3776 this.element.appendChild( item.element ); 3777 } 3778 // filter new stuff 3779 var filteredInsertItems = this._filter( items ).matches; 3780 // set flag 3781 for ( i=0; i < len; i++ ) { 3782 items[i].isLayoutInstant = true; 3783 } 3784 this.arrange(); 3785 // reset flag 3786 for ( i=0; i < len; i++ ) { 3787 delete items[i].isLayoutInstant; 3788 } 3789 this.reveal( filteredInsertItems ); 3790 }; 3791 3792 var _remove = proto.remove; 3793 proto.remove = function( elems ) { 3794 elems = utils.makeArray( elems ); 3795 var removeItems = this.getItems( elems ); 3796 // do regular thing 3797 _remove.call( this, elems ); 3798 // bail if no items to remove 3799 var len = removeItems && removeItems.length; 3800 // remove elems from filteredItems 3801 for ( var i=0; len && i < len; i++ ) { 3802 var item = removeItems[i]; 3803 // remove item from collection 3804 utils.removeFrom( this.filteredItems, item ); 3805 } 3806 }; 3807 3808 proto.shuffle = function() { 3809 // update random sortData 3810 for ( var i=0; i < this.items.length; i++ ) { 3811 var item = this.items[i]; 3812 item.sortData.random = Math.random(); 3813 } 3814 this.options.sortBy = 'random'; 3815 this._sort(); 3816 this._layout(); 3817 }; 3818 3819 /** 3820 * trigger fn without transition 3821 * kind of hacky to have this in the first place 3822 * @param {Function} fn 3823 * @param {Array} args 3824 * @returns ret 3825 * @private 3826 */ 3827 proto._noTransition = function( fn, args ) { 3828 // save transitionDuration before disabling 3829 var transitionDuration = this.options.transitionDuration; 3830 // disable transition 3831 this.options.transitionDuration = 0; 3832 // do it 3833 var returnValue = fn.apply( this, args ); 3834 // re-enable transition for reveal 3835 this.options.transitionDuration = transitionDuration; 3836 return returnValue; 3837 }; 3838 3839 // ----- helper methods ----- // 3840 3841 /** 3842 * getter method for getting filtered item elements 3843 * @returns {Array} elems - collection of item elements 3844 */ 3845 proto.getFilteredItemElements = function() { 3846 return this.filteredItems.map( function( item ) { 3847 return item.element; 3848 }); 3849 }; 3850 3851 // ----- ----- // 3852 3853 return Isotope; 3854 3855})); 3856
vendor: 29,252 bytes, lines 3857-5013
3857/*! 3858 * Packery layout mode PACKAGED v2.0.1 3859 * sub-classes Packery 3860 */ 3861 3862/** 3863 * Rect 3864 * low-level utility class for basic geometry 3865 */ 3866 3867( function( window, factory ) { 3868 // universal module definition 3869 /* jshint strict: false */ /* globals define, module */ 3870 if ( typeof define == 'function' && define.amd ) { 3871 // AMD 3872 define( 'packery/js/rect',factory ); 3873 } else if ( typeof module == 'object' && module.exports ) { 3874 // CommonJS 3875 module.exports = factory(); 3876 } else { 3877 // browser global 3878 window.Packery = window.Packery || {}; 3879 window.Packery.Rect = factory(); 3880 } 3881 3882}( window, function factory() { 3883 3884 3885// -------------------------- Rect -------------------------- // 3886 3887function Rect( props ) { 3888 // extend properties from defaults 3889 for ( var prop in Rect.defaults ) { 3890 this[ prop ] = Rect.defaults[ prop ]; 3891 } 3892 3893 for ( prop in props ) { 3894 this[ prop ] = props[ prop ]; 3895 } 3896 3897} 3898 3899Rect.defaults = { 3900 x: 0, 3901 y: 0, 3902 width: 0, 3903 height: 0 3904}; 3905 3906var proto = Rect.prototype; 3907 3908/** 3909 * Determines whether or not this rectangle wholly encloses another rectangle or point. 3910 * @param {Rect} rect 3911 * @returns {Boolean} 3912**/ 3913proto.contains = function( rect ) { 3914 // points don't have width or height 3915 var otherWidth = rect.width || 0; 3916 var otherHeight = rect.height || 0; 3917 return this.x <= rect.x && 3918 this.y <= rect.y && 3919 this.x + this.width >= rect.x + otherWidth && 3920 this.y + this.height >= rect.y + otherHeight; 3921}; 3922 3923/** 3924 * Determines whether or not the rectangle intersects with another. 3925 * @param {Rect} rect 3926 * @returns {Boolean} 3927**/ 3928proto.overlaps = function( rect ) { 3929 var thisRight = this.x + this.width; 3930 var thisBottom = this.y + this.height; 3931 var rectRight = rect.x + rect.width; 3932 var rectBottom = rect.y + rect.height; 3933 3934 // http://stackoverflow.com/a/306332 3935 return this.x < rectRight && 3936 thisRight > rect.x && 3937 this.y < rectBottom && 3938 thisBottom > rect.y; 3939}; 3940 3941/** 3942 * @param {Rect} rect - the overlapping rect 3943 * @returns {Array} freeRects - rects representing the area around the rect 3944**/ 3945proto.getMaximalFreeRects = function( rect ) { 3946 3947 // if no intersection, return false 3948 if ( !this.overlaps( rect ) ) { 3949 return false; 3950 } 3951 3952 var freeRects = []; 3953 var freeRect; 3954 3955 var thisRight = this.x + this.width; 3956 var thisBottom = this.y + this.height; 3957 var rectRight = rect.x + rect.width; 3958 var rectBottom = rect.y + rect.height; 3959 3960 // top 3961 if ( this.y < rect.y ) { 3962 freeRect = new Rect({ 3963 x: this.x, 3964 y: this.y, 3965 width: this.width, 3966 height: rect.y - this.y 3967 }); 3968 freeRects.push( freeRect ); 3969 } 3970 3971 // right 3972 if ( thisRight > rectRight ) { 3973 freeRect = new Rect({ 3974 x: rectRight, 3975 y: this.y, 3976 width: thisRight - rectRight, 3977 height: this.height 3978 }); 3979 freeRects.push( freeRect ); 3980 } 3981 3982 // bottom 3983 if ( thisBottom > rectBottom ) { 3984 freeRect = new Rect({ 3985 x: this.x, 3986 y: rectBottom, 3987 width: this.width, 3988 height: thisBottom - rectBottom 3989 }); 3990 freeRects.push( freeRect ); 3991 } 3992 3993 // left 3994 if ( this.x < rect.x ) { 3995 freeRect = new Rect({ 3996 x: this.x, 3997 y: this.y, 3998 width: rect.x - this.x, 3999 height: this.height 4000 }); 4001 freeRects.push( freeRect ); 4002 } 4003 4004 return freeRects; 4005}; 4006 4007proto.canFit = function( rect ) { 4008 return this.width >= rect.width && this.height >= rect.height; 4009}; 4010 4011return Rect; 4012 4013})); 4014 4015/** 4016 * Packer 4017 * bin-packing algorithm 4018 */ 4019 4020( function( window, factory ) { 4021 // universal module definition 4022 /* jshint strict: false */ /* globals define, module, require */ 4023 if ( typeof define == 'function' && define.amd ) { 4024 // AMD 4025 define( 'packery/js/packer',[ './rect' ], factory ); 4026 } else if ( typeof module == 'object' && module.exports ) { 4027 // CommonJS 4028 module.exports = factory( 4029 require('./rect') 4030 ); 4031 } else { 4032 // browser global 4033 var Packery = window.Packery = window.Packery || {}; 4034 Packery.Packer = factory( Packery.Rect ); 4035 } 4036 4037}( window, function factory( Rect ) { 4038 4039 4040// -------------------------- Packer -------------------------- // 4041 4042/** 4043 * @param {Number} width 4044 * @param {Number} height 4045 * @param {String} sortDirection 4046 * topLeft for vertical, leftTop for horizontal 4047 */ 4048function Packer( width, height, sortDirection ) { 4049 this.width = width || 0; 4050 this.height = height || 0; 4051 this.sortDirection = sortDirection || 'downwardLeftToRight'; 4052 4053 this.reset(); 4054} 4055 4056var proto = Packer.prototype; 4057 4058proto.reset = function() { 4059 this.spaces = []; 4060 4061 var initialSpace = new Rect({ 4062 x: 0, 4063 y: 0, 4064 width: this.width, 4065 height: this.height 4066 }); 4067 4068 this.spaces.push( initialSpace ); 4069 // set sorter 4070 this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight; 4071}; 4072 4073// change x and y of rect to fit with in Packer's available spaces 4074proto.pack = function( rect ) { 4075 for ( var i=0; i < this.spaces.length; i++ ) { 4076 var space = this.spaces[i]; 4077 if ( space.canFit( rect ) ) { 4078 this.placeInSpace( rect, space ); 4079 break; 4080 } 4081 } 4082}; 4083 4084proto.columnPack = function( rect ) { 4085 for ( var i=0; i < this.spaces.length; i++ ) { 4086 var space = this.spaces[i]; 4087 var canFitInSpaceColumn = space.x <= rect.x && 4088 space.x + space.width >= rect.x + rect.width && 4089 space.height >= rect.height - 0.01; // fudge number for rounding error 4090 if ( canFitInSpaceColumn ) { 4091 rect.y = space.y; 4092 this.placed( rect ); 4093 break; 4094 } 4095 } 4096}; 4097 4098proto.rowPack = function( rect ) { 4099 for ( var i=0; i < this.spaces.length; i++ ) { 4100 var space = this.spaces[i]; 4101 var canFitInSpaceRow = space.y <= rect.y && 4102 space.y + space.height >= rect.y + rect.height && 4103 space.width >= rect.width - 0.01; // fudge number for rounding error 4104 if ( canFitInSpaceRow ) { 4105 rect.x = space.x; 4106 this.placed( rect ); 4107 break; 4108 } 4109 } 4110}; 4111 4112proto.placeInSpace = function( rect, space ) { 4113 // place rect in space 4114 rect.x = space.x; 4115 rect.y = space.y; 4116 4117 this.placed( rect ); 4118}; 4119 4120// update spaces with placed rect 4121proto.placed = function( rect ) { 4122 // update spaces 4123 var revisedSpaces = []; 4124 for ( var i=0; i < this.spaces.length; i++ ) { 4125 var space = this.spaces[i]; 4126 var newSpaces = space.getMaximalFreeRects( rect ); 4127 // add either the original space or the new spaces to the revised spaces 4128 if ( newSpaces ) { 4129 revisedSpaces.push.apply( revisedSpaces, newSpaces ); 4130 } else { 4131 revisedSpaces.push( space ); 4132 } 4133 } 4134 4135 this.spaces = revisedSpaces; 4136 4137 this.mergeSortSpaces(); 4138}; 4139 4140proto.mergeSortSpaces = function() { 4141 // remove redundant spaces 4142 Packer.mergeRects( this.spaces ); 4143 this.spaces.sort( this.sorter ); 4144}; 4145 4146// add a space back 4147proto.addSpace = function( rect ) { 4148 this.spaces.push( rect ); 4149 this.mergeSortSpaces(); 4150}; 4151 4152// -------------------------- utility functions -------------------------- // 4153 4154/** 4155 * Remove redundant rectangle from array of rectangles 4156 * @param {Array} rects: an array of Rects 4157 * @returns {Array} rects: an array of Rects 4158**/ 4159Packer.mergeRects = function( rects ) { 4160 var i = 0; 4161 var rect = rects[i]; 4162 4163 rectLoop: 4164 while ( rect ) { 4165 var j = 0; 4166 var compareRect = rects[ i + j ]; 4167 4168 while ( compareRect ) { 4169 if ( compareRect == rect ) { 4170 j++; // next 4171 } else if ( compareRect.contains( rect ) ) { 4172 // remove rect 4173 rects.splice( i, 1 ); 4174 rect = rects[i]; // set next rect 4175 continue rectLoop; // bail on compareLoop 4176 } else if ( rect.contains( compareRect ) ) { 4177 // remove compareRect 4178 rects.splice( i + j, 1 ); 4179 } else { 4180 j++; 4181 } 4182 compareRect = rects[ i + j ]; // set next compareRect 4183 } 4184 i++; 4185 rect = rects[i]; 4186 } 4187 4188 return rects; 4189}; 4190 4191 4192// -------------------------- sorters -------------------------- // 4193 4194// functions for sorting rects in order 4195var sorters = { 4196 // top down, then left to right 4197 downwardLeftToRight: function( a, b ) { 4198 return a.y - b.y || a.x - b.x; 4199 }, 4200 // left to right, then top down 4201 rightwardTopToBottom: function( a, b ) { 4202 return a.x - b.x || a.y - b.y; 4203 } 4204}; 4205 4206 4207// -------------------------- -------------------------- // 4208 4209return Packer; 4210 4211})); 4212 4213/** 4214 * Packery Item Element 4215**/ 4216 4217( function( window, factory ) { 4218 // universal module definition 4219 /* jshint strict: false */ /* globals define, module, require */ 4220 if ( typeof define == 'function' && define.amd ) { 4221 // AMD 4222 define( 'packery/js/item',[ 4223 'outlayer/outlayer', 4224 './rect' 4225 ], 4226 factory ); 4227 } else if ( typeof module == 'object' && module.exports ) { 4228 // CommonJS 4229 module.exports = factory( 4230 require('outlayer'), 4231 require('./rect') 4232 ); 4233 } else { 4234 // browser global 4235 window.Packery.Item = factory( 4236 window.Outlayer, 4237 window.Packery.Rect 4238 ); 4239 } 4240 4241}( window, function factory( Outlayer, Rect ) { 4242 4243 4244// -------------------------- Item -------------------------- // 4245 4246var docElemStyle = document.documentElement.style; 4247 4248var transformProperty = typeof docElemStyle.transform == 'string' ? 4249 'transform' : 'WebkitTransform'; 4250 4251// sub-class Item 4252var Item = function PackeryItem() { 4253 Outlayer.Item.apply( this, arguments ); 4254}; 4255 4256var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 4257 4258var __create = proto._create; 4259proto._create = function() { 4260 // call default _create logic 4261 __create.call( this ); 4262 this.rect = new Rect(); 4263}; 4264 4265var _moveTo = proto.moveTo; 4266proto.moveTo = function( x, y ) { 4267 // don't shift 1px while dragging 4268 var dx = Math.abs( this.position.x - x ); 4269 var dy = Math.abs( this.position.y - y ); 4270 4271 var canHackGoTo = this.layout.dragItemCount && !this.isPlacing && 4272 !this.isTransitioning && dx < 1 && dy < 1; 4273 if ( canHackGoTo ) { 4274 this.goTo( x, y ); 4275 return; 4276 } 4277 _moveTo.apply( this, arguments ); 4278}; 4279 4280// -------------------------- placing -------------------------- // 4281 4282proto.enablePlacing = function() { 4283 this.removeTransitionStyles(); 4284 // remove transform property from transition 4285 if ( this.isTransitioning && transformProperty ) { 4286 this.element.style[ transformProperty ] = 'none'; 4287 } 4288 this.isTransitioning = false; 4289 this.getSize(); 4290 this.layout._setRectSize( this.element, this.rect ); 4291 this.isPlacing = true; 4292}; 4293 4294proto.disablePlacing = function() { 4295 this.isPlacing = false; 4296}; 4297 4298// ----- ----- // 4299 4300// remove element from DOM 4301proto.removeElem = function() { 4302 this.element.parentNode.removeChild( this.element ); 4303 // add space back to packer 4304 this.layout.packer.addSpace( this.rect ); 4305 this.emitEvent( 'remove', [ this ] ); 4306}; 4307 4308// ----- dropPlaceholder ----- // 4309 4310proto.showDropPlaceholder = function() { 4311 var dropPlaceholder = this.dropPlaceholder; 4312 if ( !dropPlaceholder ) { 4313 // create dropPlaceholder 4314 dropPlaceholder = this.dropPlaceholder = document.createElement('div'); 4315 dropPlaceholder.className = 'packery-drop-placeholder'; 4316 dropPlaceholder.style.position = 'absolute'; 4317 } 4318 4319 dropPlaceholder.style.width = this.size.width + 'px'; 4320 dropPlaceholder.style.height = this.size.height + 'px'; 4321 this.positionDropPlaceholder(); 4322 this.layout.element.appendChild( dropPlaceholder ); 4323}; 4324 4325proto.positionDropPlaceholder = function() { 4326 this.dropPlaceholder.style[ transformProperty ] = 'translate(' + 4327 this.rect.x + 'px, ' + this.rect.y + 'px)'; 4328}; 4329 4330proto.hideDropPlaceholder = function() { 4331 this.layout.element.removeChild( this.dropPlaceholder ); 4332}; 4333 4334// ----- ----- // 4335 4336return Item; 4337 4338})); 4339 4340/*! 4341 * Packery v2.0.0 4342 * Gapless, draggable grid layouts 4343 * 4344 * Licensed GPLv3 for open source use 4345 * or Packery Commercial License for commercial use 4346 * 4347 * http://packery.metafizzy.co 4348 * Copyright 2016 Metafizzy 4349 */ 4350 4351( function( window, factory ) { 4352 // universal module definition 4353 /* jshint strict: false */ /* globals define, module, require */ 4354 if ( typeof define == 'function' && define.amd ) { 4355 // AMD 4356 define( 'packery/js/packery',[ 4357 'get-size/get-size', 4358 'outlayer/outlayer', 4359 './rect', 4360 './packer', 4361 './item' 4362 ], 4363 factory ); 4364 } else if ( typeof module == 'object' && module.exports ) { 4365 // CommonJS 4366 module.exports = factory( 4367 require('get-size'), 4368 require('outlayer'), 4369 require('./rect'), 4370 require('./packer'), 4371 require('./item') 4372 ); 4373 } else { 4374 // browser global 4375 window.Packery = factory( 4376 window.getSize, 4377 window.Outlayer, 4378 window.Packery.Rect, 4379 window.Packery.Packer, 4380 window.Packery.Item 4381 ); 4382 } 4383 4384}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) { 4385 4386 4387// ----- Rect ----- // 4388 4389// allow for pixel rounding errors IE8-IE11 & Firefox; #227 4390Rect.prototype.canFit = function( rect ) { 4391 return this.width >= rect.width - 1 && this.height >= rect.height - 1; 4392}; 4393 4394// -------------------------- Packery -------------------------- // 4395 4396// create an Outlayer layout class 4397var Packery = Outlayer.create('packery'); 4398Packery.Item = Item; 4399 4400var proto = Packery.prototype; 4401 4402proto._create = function() { 4403 // call super 4404 Outlayer.prototype._create.call( this ); 4405 4406 // initial properties 4407 this.packer = new Packer(); 4408 // packer for drop targets 4409 this.shiftPacker = new Packer(); 4410 this.isEnabled = true; 4411 4412 this.dragItemCount = 0; 4413 4414 // create drag handlers 4415 var _this = this; 4416 this.handleDraggabilly = { 4417 dragStart: function() { 4418 _this.itemDragStart( this.element ); 4419 }, 4420 dragMove: function() { 4421 _this.itemDragMove( this.element, this.position.x, this.position.y ); 4422 }, 4423 dragEnd: function() { 4424 _this.itemDragEnd( this.element ); 4425 } 4426 }; 4427 4428 this.handleUIDraggable = { 4429 start: function handleUIDraggableStart( event, ui ) { 4430 // HTML5 may trigger dragstart, dismiss HTML5 dragging 4431 if ( !ui ) { 4432 return; 4433 } 4434 _this.itemDragStart( event.currentTarget ); 4435 }, 4436 drag: function handleUIDraggableDrag( event, ui ) { 4437 if ( !ui ) { 4438 return; 4439 } 4440 _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top ); 4441 }, 4442 stop: function handleUIDraggableStop( event, ui ) { 4443 if ( !ui ) { 4444 return; 4445 } 4446 _this.itemDragEnd( event.currentTarget ); 4447 } 4448 }; 4449 4450}; 4451 4452 4453// ----- init & layout ----- // 4454 4455/** 4456 * logic before any new layout 4457 */ 4458proto._resetLayout = function() { 4459 this.getSize(); 4460 4461 this._getMeasurements(); 4462 4463 // reset packer 4464 var width, height, sortDirection; 4465 // packer settings, if horizontal or vertical 4466 if ( this._getOption('horizontal') ) { 4467 width = Infinity; 4468 height = this.size.innerHeight + this.gutter; 4469 sortDirection = 'rightwardTopToBottom'; 4470 } else { 4471 width = this.size.innerWidth + this.gutter; 4472 height = Infinity; 4473 sortDirection = 'downwardLeftToRight'; 4474 } 4475 4476 this.packer.width = this.shiftPacker.width = width; 4477 this.packer.height = this.shiftPacker.height = height; 4478 this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection; 4479 4480 this.packer.reset(); 4481 4482 // layout 4483 this.maxY = 0; 4484 this.maxX = 0; 4485}; 4486 4487/** 4488 * update columnWidth, rowHeight, & gutter 4489 * @private 4490 */ 4491proto._getMeasurements = function() { 4492 this._getMeasurement( 'columnWidth', 'width' ); 4493 this._getMeasurement( 'rowHeight', 'height' ); 4494 this._getMeasurement( 'gutter', 'width' ); 4495}; 4496 4497proto._getItemLayoutPosition = function( item ) { 4498 this._setRectSize( item.element, item.rect ); 4499 if ( this.isShifting || this.dragItemCount > 0 ) { 4500 var packMethod = this._getPackMethod(); 4501 this.packer[ packMethod ]( item.rect ); 4502 } else { 4503 this.packer.pack( item.rect ); 4504 } 4505 4506 this._setMaxXY( item.rect ); 4507 return item.rect; 4508}; 4509 4510proto.shiftLayout = function() { 4511 this.isShifting = true; 4512 this.layout(); 4513 delete this.isShifting; 4514}; 4515 4516proto._getPackMethod = function() { 4517 return this._getOption('horizontal') ? 'rowPack' : 'columnPack'; 4518}; 4519 4520 4521/** 4522 * set max X and Y value, for size of container 4523 * @param {Packery.Rect} rect 4524 * @private 4525 */ 4526proto._setMaxXY = function( rect ) { 4527 this.maxX = Math.max( rect.x + rect.width, this.maxX ); 4528 this.maxY = Math.max( rect.y + rect.height, this.maxY ); 4529}; 4530 4531/** 4532 * set the width and height of a rect, applying columnWidth and rowHeight 4533 * @param {Element} elem 4534 * @param {Packery.Rect} rect 4535 */ 4536proto._setRectSize = function( elem, rect ) { 4537 var size = getSize( elem ); 4538 var w = size.outerWidth; 4539 var h = size.outerHeight; 4540 // size for columnWidth and rowHeight, if available 4541 // only check if size is non-zero, #177 4542 if ( w || h ) { 4543 w = this._applyGridGutter( w, this.columnWidth ); 4544 h = this._applyGridGutter( h, this.rowHeight ); 4545 } 4546 // rect must fit in packer 4547 rect.width = Math.min( w, this.packer.width ); 4548 rect.height = Math.min( h, this.packer.height ); 4549}; 4550 4551/** 4552 * fits item to columnWidth/rowHeight and adds gutter 4553 * @param {Number} measurement - item width or height 4554 * @param {Number} gridSize - columnWidth or rowHeight 4555 * @returns measurement 4556 */ 4557proto._applyGridGutter = function( measurement, gridSize ) { 4558 // just add gutter if no gridSize 4559 if ( !gridSize ) { 4560 return measurement + this.gutter; 4561 } 4562 gridSize += this.gutter; 4563 // fit item to columnWidth/rowHeight 4564 var remainder = measurement % gridSize; 4565 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 4566 measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize; 4567 return measurement; 4568}; 4569 4570proto._getContainerSize = function() { 4571 if ( this._getOption('horizontal') ) { 4572 return { 4573 width: this.maxX - this.gutter 4574 }; 4575 } else { 4576 return { 4577 height: this.maxY - this.gutter 4578 }; 4579 } 4580}; 4581 4582 4583// -------------------------- stamp -------------------------- // 4584 4585/** 4586 * makes space for element 4587 * @param {Element} elem 4588 */ 4589proto._manageStamp = function( elem ) { 4590 4591 var item = this.getItem( elem ); 4592 var rect; 4593 if ( item && item.isPlacing ) { 4594 rect = item.rect; 4595 } else { 4596 var offset = this._getElementOffset( elem ); 4597 rect = new Rect({ 4598 x: this._getOption('originLeft') ? offset.left : offset.right, 4599 y: this._getOption('originTop') ? offset.top : offset.bottom 4600 }); 4601 } 4602 4603 this._setRectSize( elem, rect ); 4604 // save its space in the packer 4605 this.packer.placed( rect ); 4606 this._setMaxXY( rect ); 4607}; 4608 4609// -------------------------- methods -------------------------- // 4610 4611function verticalSorter( a, b ) { 4612 return a.position.y - b.position.y || a.position.x - b.position.x; 4613} 4614 4615function horizontalSorter( a, b ) { 4616 return a.position.x - b.position.x || a.position.y - b.position.y; 4617} 4618 4619proto.sortItemsByPosition = function() { 4620 var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter; 4621 this.items.sort( sorter ); 4622}; 4623 4624/** 4625 * Fit item element in its current position 4626 * Packery will position elements around it 4627 * useful for expanding elements 4628 * 4629 * @param {Element} elem 4630 * @param {Number} x - horizontal destination position, optional 4631 * @param {Number} y - vertical destination position, optional 4632 */ 4633proto.fit = function( elem, x, y ) { 4634 var item = this.getItem( elem ); 4635 if ( !item ) { 4636 return; 4637 } 4638 4639 // stamp item to get it out of layout 4640 this.stamp( item.element ); 4641 // set placing flag 4642 item.enablePlacing(); 4643 this.updateShiftTargets( item ); 4644 // fall back to current position for fitting 4645 x = x === undefined ? item.rect.x: x; 4646 y = y === undefined ? item.rect.y: y; 4647 // position it best at its destination 4648 this.shift( item, x, y ); 4649 this._bindFitEvents( item ); 4650 item.moveTo( item.rect.x, item.rect.y ); 4651 // layout everything else 4652 this.shiftLayout(); 4653 // return back to regularly scheduled programming 4654 this.unstamp( item.element ); 4655 this.sortItemsByPosition(); 4656 item.disablePlacing(); 4657}; 4658 4659/** 4660 * emit event when item is fit and other items are laid out 4661 * @param {Packery.Item} item 4662 * @private 4663 */ 4664proto._bindFitEvents = function( item ) { 4665 var _this = this; 4666 var ticks = 0; 4667 function onLayout() { 4668 ticks++; 4669 if ( ticks != 2 ) { 4670 return; 4671 } 4672 _this.dispatchEvent( 'fitComplete', null, [ item ] ); 4673 } 4674 // when item is laid out 4675 item.once( 'layout', onLayout ); 4676 // when all items are laid out 4677 this.once( 'layoutComplete', onLayout ); 4678}; 4679 4680// -------------------------- resize -------------------------- // 4681 4682// debounced, layout on resize 4683proto.resize = function() { 4684 // don't trigger if size did not change 4685 // or if resize was unbound. See #285, outlayer#9 4686 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 4687 return; 4688 } 4689 4690 if ( this.options.shiftPercentResize ) { 4691 this.resizeShiftPercentLayout(); 4692 } else { 4693 this.layout(); 4694 } 4695}; 4696 4697/** 4698 * check if layout is needed post layout 4699 * @returns Boolean 4700 */ 4701proto.needsResizeLayout = function() { 4702 var size = getSize( this.element ); 4703 var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth'; 4704 return size[ innerSize ] != this.size[ innerSize ]; 4705}; 4706 4707proto.resizeShiftPercentLayout = function() { 4708 var items = this._getItemsForLayout( this.items ); 4709 4710 var isHorizontal = this._getOption('horizontal'); 4711 var coord = isHorizontal ? 'y' : 'x'; 4712 var measure = isHorizontal ? 'height' : 'width'; 4713 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 4714 var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth'; 4715 4716 // proportional re-align items 4717 var previousSegment = this[ segmentName ]; 4718 previousSegment = previousSegment && previousSegment + this.gutter; 4719 4720 if ( previousSegment ) { 4721 this._getMeasurements(); 4722 var currentSegment = this[ segmentName ] + this.gutter; 4723 items.forEach( function( item ) { 4724 var seg = Math.round( item.rect[ coord ] / previousSegment ); 4725 item.rect[ coord ] = seg * currentSegment; 4726 }); 4727 } else { 4728 var currentSize = getSize( this.element )[ innerSize ] + this.gutter; 4729 var previousSize = this.packer[ measure ]; 4730 items.forEach( function( item ) { 4731 item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize; 4732 }); 4733 } 4734 4735 this.shiftLayout(); 4736}; 4737 4738// -------------------------- drag -------------------------- // 4739 4740/** 4741 * handle an item drag start event 4742 * @param {Element} elem 4743 */ 4744proto.itemDragStart = function( elem ) { 4745 if ( !this.isEnabled ) { 4746 return; 4747 } 4748 this.stamp( elem ); 4749 // this.ignore( elem ); 4750 var item = this.getItem( elem ); 4751 if ( !item ) { 4752 return; 4753 } 4754 4755 item.enablePlacing(); 4756 item.showDropPlaceholder(); 4757 this.dragItemCount++; 4758 this.updateShiftTargets( item ); 4759}; 4760 4761proto.updateShiftTargets = function( dropItem ) { 4762 this.shiftPacker.reset(); 4763 4764 // pack stamps 4765 this._getBoundingRect(); 4766 var isOriginLeft = this._getOption('originLeft'); 4767 var isOriginTop = this._getOption('originTop'); 4768 this.stamps.forEach( function( stamp ) { 4769 // ignore dragged item 4770 var item = this.getItem( stamp ); 4771 if ( item && item.isPlacing ) { 4772 return; 4773 } 4774 var offset = this._getElementOffset( stamp ); 4775 var rect = new Rect({ 4776 x: isOriginLeft ? offset.left : offset.right, 4777 y: isOriginTop ? offset.top : offset.bottom 4778 }); 4779 this._setRectSize( stamp, rect ); 4780 // save its space in the packer 4781 this.shiftPacker.placed( rect ); 4782 }, this ); 4783 4784 // reset shiftTargets 4785 var isHorizontal = this._getOption('horizontal'); 4786 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 4787 var measure = isHorizontal ? 'height' : 'width'; 4788 4789 this.shiftTargetKeys = []; 4790 this.shiftTargets = []; 4791 var boundsSize; 4792 var segment = this[ segmentName ]; 4793 segment = segment && segment + this.gutter; 4794 4795 if ( segment ) { 4796 var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment ); 4797 var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment ); 4798 boundsSize = ( segs - segmentSpan ) * segment; 4799 // add targets on top 4800 for ( var i=0; i < segs; i++ ) { 4801 this._addShiftTarget( i * segment, 0, boundsSize ); 4802 } 4803 } else { 4804 boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ]; 4805 this._addShiftTarget( 0, 0, boundsSize ); 4806 } 4807 4808 // pack each item to measure where shiftTargets are 4809 var items = this._getItemsForLayout( this.items ); 4810 var packMethod = this._getPackMethod(); 4811 items.forEach( function( item ) { 4812 var rect = item.rect; 4813 this._setRectSize( item.element, rect ); 4814 this.shiftPacker[ packMethod ]( rect ); 4815 4816 // add top left corner 4817 this._addShiftTarget( rect.x, rect.y, boundsSize ); 4818 // add bottom left / top right corner 4819 var cornerX = isHorizontal ? rect.x + rect.width : rect.x; 4820 var cornerY = isHorizontal ? rect.y : rect.y + rect.height; 4821 this._addShiftTarget( cornerX, cornerY, boundsSize ); 4822 4823 if ( segment ) { 4824 // add targets for each column on bottom / row on right 4825 var segSpan = Math.round( rect[ measure ] / segment ); 4826 for ( var i=1; i < segSpan; i++ ) { 4827 var segX = isHorizontal ? cornerX : rect.x + segment * i; 4828 var segY = isHorizontal ? rect.y + segment * i : cornerY; 4829 this._addShiftTarget( segX, segY, boundsSize ); 4830 } 4831 } 4832 }, this ); 4833 4834}; 4835 4836proto._addShiftTarget = function( x, y, boundsSize ) { 4837 var checkCoord = this._getOption('horizontal') ? y : x; 4838 if ( checkCoord !== 0 && checkCoord > boundsSize ) { 4839 return; 4840 } 4841 // create string for a key, easier to keep track of what targets 4842 var key = x + ',' + y; 4843 var hasKey = this.shiftTargetKeys.indexOf( key ) != -1; 4844 if ( hasKey ) { 4845 return; 4846 } 4847 this.shiftTargetKeys.push( key ); 4848 this.shiftTargets.push({ x: x, y: y }); 4849}; 4850 4851// -------------------------- drop -------------------------- // 4852 4853proto.shift = function( item, x, y ) { 4854 var shiftPosition; 4855 var minDistance = Infinity; 4856 var position = { x: x, y: y }; 4857 this.shiftTargets.forEach( function( target ) { 4858 var distance = getDistance( target, position ); 4859 if ( distance < minDistance ) { 4860 shiftPosition = target; 4861 minDistance = distance; 4862 } 4863 }); 4864 item.rect.x = shiftPosition.x; 4865 item.rect.y = shiftPosition.y; 4866}; 4867 4868function getDistance( a, b ) { 4869 var dx = b.x - a.x; 4870 var dy = b.y - a.y; 4871 return Math.sqrt( dx * dx + dy * dy ); 4872} 4873 4874// -------------------------- drag move -------------------------- // 4875 4876var DRAG_THROTTLE_TIME = 120; 4877 4878/** 4879 * handle an item drag move event 4880 * @param {Element} elem 4881 * @param {Number} x - horizontal change in position 4882 * @param {Number} y - vertical change in position 4883 */ 4884proto.itemDragMove = function( elem, x, y ) { 4885 var item = this.isEnabled && this.getItem( elem ); 4886 if ( !item ) { 4887 return; 4888 } 4889 4890 x -= this.size.paddingLeft; 4891 y -= this.size.paddingTop; 4892 4893 var _this = this; 4894 function onDrag() { 4895 _this.shift( item, x, y ); 4896 item.positionDropPlaceholder(); 4897 _this.layout(); 4898 } 4899 4900 // throttle 4901 var now = new Date(); 4902 if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) { 4903 clearTimeout( this.dragTimeout ); 4904 this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME ); 4905 } else { 4906 onDrag(); 4907 this._itemDragTime = now; 4908 } 4909}; 4910 4911// -------------------------- drag end -------------------------- // 4912 4913/** 4914 * handle an item drag end event 4915 * @param {Element} elem 4916 */ 4917proto.itemDragEnd = function( elem ) { 4918 var item = this.isEnabled && this.getItem( elem ); 4919 if ( !item ) { 4920 return; 4921 } 4922 4923 clearTimeout( this.dragTimeout ); 4924 item.element.classList.add('is-positioning-post-drag'); 4925 4926 var completeCount = 0; 4927 var _this = this; 4928 function onDragEndLayoutComplete() { 4929 completeCount++; 4930 if ( completeCount != 2 ) { 4931 return; 4932 } 4933 // reset drag item 4934 item.element.classList.remove('is-positioning-post-drag'); 4935 item.hideDropPlaceholder(); 4936 _this.dispatchEvent( 'dragItemPositioned', null, [ item ] ); 4937 } 4938 4939 item.once( 'layout', onDragEndLayoutComplete ); 4940 this.once( 'layoutComplete', onDragEndLayoutComplete ); 4941 item.moveTo( item.rect.x, item.rect.y ); 4942 this.layout(); 4943 this.dragItemCount = Math.max( 0, this.dragItemCount - 1 ); 4944 this.sortItemsByPosition(); 4945 item.disablePlacing(); 4946 this.unstamp( item.element ); 4947}; 4948 4949/** 4950 * binds Draggabilly events 4951 * @param {Draggabilly} draggie 4952 */ 4953proto.bindDraggabillyEvents = function( draggie ) { 4954 this._bindDraggabillyEvents( draggie, 'on' ); 4955}; 4956 4957proto.unbindDraggabillyEvents = function( draggie ) { 4958 this._bindDraggabillyEvents( draggie, 'off' ); 4959}; 4960 4961proto._bindDraggabillyEvents = function( draggie, method ) { 4962 var handlers = this.handleDraggabilly; 4963 draggie[ method ]( 'dragStart', handlers.dragStart ); 4964 draggie[ method ]( 'dragMove', handlers.dragMove ); 4965 draggie[ method ]( 'dragEnd', handlers.dragEnd ); 4966}; 4967 4968/** 4969 * binds jQuery UI Draggable events 4970 * @param {jQuery} $elems 4971 */ 4972proto.bindUIDraggableEvents = function( $elems ) { 4973 this._bindUIDraggableEvents( $elems, 'on' ); 4974}; 4975 4976proto.unbindUIDraggableEvents = function( $elems ) { 4977 this._bindUIDraggableEvents( $elems, 'off' ); 4978}; 4979 4980proto._bindUIDraggableEvents = function( $elems, method ) { 4981 var handlers = this.handleUIDraggable; 4982 $elems 4983 [ method ]( 'dragstart', handlers.start ) 4984 [ method ]( 'drag', handlers.drag ) 4985 [ method ]( 'dragstop', handlers.stop ); 4986}; 4987 4988// ----- destroy ----- // 4989 4990var _destroy = proto.destroy; 4991proto.destroy = function() { 4992 _destroy.apply( this, arguments ); 4993 // disable flag; prevent drag events from triggering. #72 4994 this.isEnabled = false; 4995}; 4996 4997// ----- ----- // 4998 4999Packery.Rect = Rect; 5000Packery.Packer = Packer; 5001 5002return Packery; 5003 5004})); 5005 5006/*! 5007 * Packery layout mode v2.0.1 5008 * sub-classes Packery 5009 */ 5010 5011/*jshint browser: true, strict: true, undef: true, unused: true */ 5012 5013( function( window, factory ) {
5014 5015 // universal module definition 5016 if ( typeof define == 'function' && define.amd ) { 5017 // AMD 5018 define( [ 5019 'isotope-layout/js/layout-mode', 5020 'packery/js/packery' 5021 ], 5022 factory ); 5023 } else if ( typeof module == 'object' && module.exports ) { 5024 // CommonJS 5025 module.exports = factory( 5026 require('isotope-layout/js/layout-mode'), 5027 require('packery') 5028 ); 5029 } else { 5030 // browser global 5031 factory( 5032 window.Isotope.LayoutMode, 5033 window.Packery 5034 ); 5035 } 5036 5037}( window, function factor( LayoutMode, Packery ) { 5038 5039 5040 // create an Outlayer layout class 5041 var PackeryMode = LayoutMode.create('packery'); 5042 var proto = PackeryMode.prototype; 5043 5044 var keepModeMethods = { 5045 _getElementOffset: true, 5046 _getMeasurement: true 5047 }; 5048 5049 // inherit Packery prototype 5050 for ( var method in Packery.prototype ) { 5051 // do not inherit mode methods 5052 if ( !keepModeMethods[ method ] ) { 5053 proto[ method ] = Packery.prototype[ method ]; 5054 } 5055 } 5056 5057 // set packer in _resetLayout 5058 var _resetLayout = proto._resetLayout; 5059 proto._resetLayout = function() { 5060 this.packer = this.packer || new Packery.Packer(); 5061 this.shiftPacker = this.shiftPacker || new Packery.Packer(); 5062 _resetLayout.apply( this, arguments ); 5063 }; 5064 5065 var _getItemLayoutPosition = proto._getItemLayoutPosition; 5066 proto._getItemLayoutPosition = function( item ) { 5067 // set packery rect 5068 item.rect = item.rect || new Packery.Rect(); 5069 return _getItemLayoutPosition.call( this, item ); 5070 }; 5071 5072 // needsResizeLayout for vertical or horizontal 5073 var _needsResizeLayout = proto.needsResizeLayout; 5074 proto.needsResizeLayout = function() { 5075 if ( this._getOption('horizontal') ) { 5076 return this.needsVerticalResizeLayout(); 5077 } else { 5078 return _needsResizeLayout.call( this ); 5079 } 5080 }; 5081 5082 // point to mode options for horizontal 5083 var _getOption = proto._getOption; 5084 proto._getOption = function( option ) { 5085 if ( option == 'horizontal' ) { 5086 return this.options.isHorizontal !== undefined ? 5087 this.options.isHorizontal : this.options.horizontal; 5088 } 5089 return _getOption.apply( this.isotope, arguments ); 5090 }; 5091 5092 return PackeryMode; 5093 5094})); 5095 5096/*! 5097 * cellsByRows layout mode for Isotope 5098 * v1.1.3 5099 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 5100 */ 5101 5102/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 5103 5104( function( window, factory ) { 5105 // universal module definition 5106 /* jshint strict: false */ /*globals define, module, require */ 5107 if ( typeof define === 'function' && define.amd ) { 5108 // AMD 5109 define( [ 5110 'isotope/js/layout-mode' 5111 ], 5112 factory ); 5113 } else if ( typeof exports === 'object' ) { 5114 // CommonJS 5115 module.exports = factory( 5116 require('isotope-layout/js/layout-mode') 5117 ); 5118 } else { 5119 // browser global 5120 factory( 5121 window.Isotope.LayoutMode 5122 ); 5123 } 5124 5125}( window, function factory( LayoutMode ) { 5126 'use strict'; 5127 5128 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 5129 var proto = CellsByRow.prototype; 5130 5131 proto._resetLayout = function() { 5132 // reset properties 5133 this.itemIndex = 0; 5134 // measurements 5135 this.getColumnWidth(); 5136 this.getRowHeight(); 5137 // set cols 5138 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 5139 this.cols = Math.max( this.cols, 1 ); 5140 }; 5141 5142 proto._getItemLayoutPosition = function( item ) { 5143 item.getSize(); 5144 var col = this.itemIndex % this.cols; 5145 var row = Math.floor( this.itemIndex / this.cols ); 5146 // center item within cell 5147 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 5148 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 5149 this.itemIndex++; 5150 return { x: x, y: y }; 5151 }; 5152 5153 proto._getContainerSize = function() { 5154 return { 5155 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 5156 }; 5157 }; 5158 5159 return CellsByRow; 5160 5161})); 5162/*global jQuery: true */ 5163 5164/*! 5165 -------------------------------- 5166 Infinite Scroll 5167 -------------------------------- 5168 + https://github.com/paulirish/infinite-scroll 5169 + version 2.1.0 5170 + Copyright 2011/12 Paul Irish & Luke Shumard 5171 + Licensed under the MIT license 5172 5173 + Documentation: http://infinite-scroll.com/ 5174*/ 5175 5176// Uses AMD or browser globals to create a jQuery plugin. 5177(function (factory) { 5178 if (typeof define === 'function' && define.amd) { 5179 // AMD. Register as an anonymous module. 5180 define(['jquery'], factory); 5181 } else { 5182 // Browser globals 5183 factory(jQuery); 5184 } 5185}(function ($, undefined) { 5186 'use strict'; 5187
5188 $.infinitescroll = function infscr(options, callback, element) { 5189 this.element = $(element); 5190 5191 // Flag the object in the event of a failed creation 5192 if (!this._create(options, callback)) { 5193 this.failed = true; 5194 } 5195 }; 5196 5197 $.infinitescroll.defaults = { 5198 loading: { 5199 finished: undefined, 5200 finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>", 5201 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/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSH
5201MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
5201iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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', 5202 msg: null, 5203 msgText: '<em>Loading the next set of posts...</em>', 5204 selector: null, 5205 speed: 'fast', 5206 start: undefined 5207 }, 5208 state: { 5209 isDuringAjax: false, 5210 isInvalidPage: false,
5211 isDestroyed: false, 5212 isDone: false, // For when it goes all the way through the archive. 5213 isPaused: false, 5214 isBeyondMaxPage: false, 5215 currPage: 1 5216 }, 5217 debug: false, 5218 behavior: undefined, 5219 binder: $(window), // used to cache the selector 5220 nextSelector: 'div.navigation a:first', 5221 navSelector: 'div.navigation', 5222 contentSelector: null, // rename to pageFragment 5223 extraScrollPx: 150, 5224 itemSelector: 'div.post', 5225 animate: false, 5226 pathParse: undefined, 5227 dataType: 'html', 5228 appendCallback: true, 5229 bufferPx: 40, 5230 errorCallback: function () { }, 5231 infid: 0, //Instance ID 5232 pixelsFromNavToBottom: undefined, 5233 path: undefined, // Either parts of a URL as an array (e.g. ["/page/", "/"] or a function that takes in the page number and returns a URL 5234 prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted 5235 maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work) 5236 }; 5237 5238 $.infinitescroll.prototype = { 5239 5240 /* 5241 ---------------------------- 5242 Private methods 5243 ---------------------------- 5244 */ 5245 5246 // Bind or unbind from scroll 5247 _binding: function infscr_binding(binding) { 5248 5249 var instance = this, 5250 opts = instance.options; 5251 5252 opts.v = '2.0b2.120520'; 5253 5254 // if behavior is defined and this function is extended, call that instead of default 5255 if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) { 5256 this['_binding_'+opts.behavior].call(this); 5257 return; 5258 } 5259 5260 if (binding !== 'bind' && binding !== 'unbind') { 5261 this._debug('Binding value ' + binding + ' not valid'); 5262 return false; 5263 } 5264 5265 if (binding === 'unbind') { 5266 (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid); 5267 } else { 5268 (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () { 5269 instance.scroll(); 5270 }); 5271 } 5272 5273 this._debug('Binding', binding); 5274 }, 5275 5276 // Fundamental aspects of the plugin are initialized 5277 _create: function infscr_create(options, callback) { 5278 5279 // Add custom options to defaults 5280 var opts = $.extend(true, {}, $.infinitescroll.defaults, options); 5281 this.options = opts; 5282 var $window = $(window); 5283 var instance = this; 5284 5285 // Validate selectors 5286 if (!instance._validate(options)) { 5287 return false; 5288 } 5289 5290 // Validate page fragment path 5291 var path = $(opts.nextSelector).attr('href'); 5292 if (!path) { 5293 this._debug('Navigation selector not found'); 5294 return false; 5295 } 5296 5297 // Set the path to be a relative URL from root. 5298 opts.path = opts.path || this._determinepath(path); 5299 5300 // contentSelector is 'page fragment' option for .load() / .ajax() calls 5301 opts.contentSelector = opts.contentSelector || this.element; 5302 5303 // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector 5304 opts.loading.selector = opts.loading.selector || opts.contentSelector; 5305 5306 // Define loading.msg 5307 opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>'); 5308 5309 // Preload loading.img 5310 (new Image()).src = opts.loading.img; 5311 5312 // distance from nav links to bottom 5313 // computed as: height of the document + top offset of container - top offset of nav link 5314 if(opts.pixelsFromNavToBottom === undefined) { 5315 opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top; 5316 this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom); 5317 } 5318 5319 var self = this; 5320 5321 // determine loading.start actions 5322 opts.loading.start = opts.loading.start || function() { 5323 $(opts.navSelector).hide(); 5324 opts.loading.msg 5325 .appendTo(opts.loading.selector) 5326 .show(opts.loading.speed, $.proxy(function() { 5327 this.beginAjax(opts); 5328 }, self)); 5329 }; 5330 5331 // determine loading.finished actions 5332 opts.loading.finished = opts.loading.finished || function() { 5333 if (!opts.state.isBeyondMaxPage) 5334 opts.loading.msg.fadeOut(opts.loading.speed); 5335 }; 5336 5337 // callback loading 5338 opts.callback = function(instance, data, url) { 5339 if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) { 5340 instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url); 5341 } 5342 5343 if (callback) { 5344 callback.call($(opts.contentSelector)[0], data, opts, url); 5345 } 5346 5347 if (opts.prefill) { 5348 $window.bind('resize.infinite-scroll', instance._prefill); 5349 } 5350 }; 5351 5352 if (options.debug) { 5353 // Tell IE9 to use its built-in console 5354 if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') { 5355 ['log','info','warn','error','assert','dir','clear','profile','profileEnd'] 5356 .forEach(function (method) { 5357 console[method] = this.call(console[method], console); 5358 }, Function.prototype.bind); 5359 } 5360 } 5361 5362 this._setup(); 5363 5364 // Setups the prefill method for use 5365 if (opts.prefill) { 5366 this._prefill(); 5367 } 5368 5369 // Return true to indicate successful creation 5370 return true; 5371 }, 5372 5373 _prefill: function infscr_prefill() { 5374 var instance = this; 5375 var $window = $(window); 5376 5377 function needsPrefill() { 5378 return ( $(instance.options.contentSelector).height() <= $window.height() ); 5379 } 5380 5381 this._prefill = function() { 5382 if (needsPrefill()) { 5383 instance.scroll(); 5384 } 5385 5386 $window.bind('resize.infinite-scroll', function() { 5387 if (needsPrefill()) { 5388 $window.unbind('resize.infinite-scroll'); 5389 instance.scroll(); 5390 } 5391 }); 5392 }; 5393 5394 // Call self after setting up the new function 5395 this._prefill(); 5396 }, 5397 5398 // Console log wrapper 5399 _debug: function infscr_debug() { 5400 if (true !== this.options.debug) { 5401 return; 5402 } 5403 5404 if (typeof console !== 'undefined' && typeof console.log === 'function') { 5405 // Modern browsers 5406 // Single argument, which is a string 5407 if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') { 5408 console.log( (Array.prototype.slice.call(arguments)).toString() ); 5409 } else { 5410 console.log( Array.prototype.slice.call(arguments) ); 5411 } 5412 } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') { 5413 // IE8 5414 Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments)); 5415 } 5416 }, 5417 5418 // find the number to increment in the path.
5419 _determinepath: function infscr_determinepath(path) { 5420 5421 var opts = this.options; 5422 5423 // if behavior is defined and this function is extended, call that instead of default 5424 if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) { 5425 return this['_determinepath_'+opts.behavior].call(this,path); 5426 } 5427 5428 if (!!opts.pathParse) { 5429 5430 this._debug('pathParse manual'); 5431 return opts.pathParse(path, this.options.state.currPage+1); 5432 5433 } else if (path.match(/^(.*?)\b2\b(.*?$)/)) { 5434 path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 5435 5436 // if there is any 2 in the url at all. 5437 } else if (path.match(/^(.*?)2(.*?$)/)) { 5438 5439 // page= is used in django: 5440 // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127 5441 if (path.match(/^(.*?page=)2(\/.*|$)/)) { 5442 path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 5443 return path; 5444 } 5445 5446 path = path.match(/^(.*?)2(.*?$)/).slice(1); 5447 5448 } else { 5449 5450 // page= is used in drupal too but second page is page=1 not page=2: 5451 // thx Jerod Fritz, vladikoff 5452 if (path.match(/^(.*?page=)1(\/.*|$)/)) { 5453 path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 5454 return path; 5455 } else { 5456 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."); 5457 // Get rid of isInvalidPage to allow permalink to state 5458 opts.state.isInvalidPage = true; //prevent it from running on this page. 5459 } 5460 } 5461 this._debug('determinePath', path); 5462 return path; 5463 5464 }, 5465 5466 // Custom error 5467 _error: function infscr_error(xhr) { 5468 5469 var opts = this.options; 5470 5471 // if behavior is defined and this function is extended, call that instead of default 5472 if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) { 5473 this['_error_'+opts.behavior].call(this,xhr); 5474 return; 5475 } 5476 5477 if (xhr !== 'destroy' && xhr !== 'end') { 5478 xhr = 'unknown'; 5479 } 5480 5481 this._debug('Error', xhr); 5482 5483 if (xhr === 'end' || opts.state.isBeyondMaxPage) { 5484 this._showdonemsg(); 5485 } 5486 5487 opts.state.isDone = true; 5488 opts.state.currPage = 1; // if you need to go back to this instance 5489 opts.state.isPaused = false; 5490 opts.state.isBeyondMaxPage = false; 5491 this._binding('unbind'); 5492 5493 }, 5494 5495 // Load Callback 5496 _loadcallback: function infscr_loadcallback(box, data, url) { 5497 var opts = this.options, 5498 callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK 5499 result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append', 5500 frag; 5501 5502 // if behavior is defined and this function is extended, call that instead of default 5503 if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) { 5504 this['_loadcallback_'+opts.behavior].call(this,box,data); 5505 return; 5506 } 5507 5508 switch (result) { 5509 case 'done': 5510 this._showdonemsg(); 5511 return false; 5512 5513 case 'no-append': 5514 if (opts.dataType === 'html') { 5515 data = '<div>' + data + '</div>'; 5516 data = $(data).find(opts.itemSelector); 5517 } 5518 5519 // if it didn't return anything 5520 if (data.length === 0) { 5521 return this._error('end'); 5522 } 5523 5524 break; 5525 5526 case 'append': 5527 var children = box.children(); 5528 // if it didn't return anything 5529 if (children.length === 0) { 5530 return this._error('end'); 5531 } 5532 5533 // use a documentFragment because it works when content is going into a table or UL 5534 frag = document.createDocumentFragment(); 5535 while (box[0].firstChild) { 5536 frag.appendChild(box[0].firstChild); 5537 } 5538 5539 this._debug('contentSelector', $(opts.contentSelector)[0]); 5540 $(opts.contentSelector)[0].appendChild(frag); 5541 // previously, we would pass in the new DOM element as context for the callback 5542 // however we're now using a documentfragment, which doesn't have parents or children, 5543 // so the context is the contentContainer guy, and we pass in an array 5544 // of the elements collected as the first argument. 5545 5546 data = children.get(); 5547 break; 5548 } 5549 5550 // loadingEnd function 5551 opts.loading.finished.call($(opts.contentSelector)[0],opts); 5552 5553 // smooth scroll to ease in the new content 5554 if (opts.animate) { 5555 var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px'; 5556 $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; }); 5557 } 5558 5559 if (!opts.animate) { 5560 // once the call is done, we can allow it again. 5561 opts.state.isDuringAjax = false;
5562 } 5563 5564 callback(this, data, url); 5565 5566 if (opts.prefill) { 5567 this._prefill(); 5568 } 5569 }, 5570 5571 _nearbottom: function infscr_nearbottom() { 5572 5573 var opts = this.options, 5574 pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height(); 5575 5576 // if behavior is defined and this function is extended, call that instead of default 5577 if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) { 5578 return this['_nearbottom_'+opts.behavior].call(this); 5579 } 5580 5581 this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom); 5582 5583 // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom.... 5584 return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom); 5585 5586 }, 5587 5588 // Pause / temporarily disable plugin from firing 5589 _pausing: function infscr_pausing(pause) { 5590 5591 var opts = this.options; 5592 5593 // if behavior is defined and this function is extended, call that instead of default 5594 if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) { 5595 this['_pausing_'+opts.behavior].call(this,pause); 5596 return; 5597 } 5598 5599 // If pause is not 'pause' or 'resume', toggle it's value 5600 if (pause !== 'pause' && pause !== 'resume' && pause !== null) { 5601 this._debug('Invalid argument. Toggling pause value instead'); 5602 } 5603 5604 pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle'; 5605 5606 switch (pause) { 5607 case 'pause': 5608 opts.state.isPaused = true; 5609 break; 5610 5611 case 'resume': 5612 opts.state.isPaused = false; 5613 break; 5614 5615 case 'toggle': 5616 opts.state.isPaused = !opts.state.isPaused; 5617 break; 5618 } 5619 5620 this._debug('Paused', opts.state.isPaused); 5621 return false; 5622 5623 }, 5624 5625 // Behavior is determined 5626 // If the behavior option is undefined, it will set to default and bind to scroll 5627 _setup: function infscr_setup() { 5628 5629 var opts = this.options; 5630 5631 // if behavior is defined and this function is extended, call that instead of default 5632 if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) { 5633 this['_setup_'+opts.behavior].call(this); 5634 return; 5635 } 5636 5637 this._binding('bind'); 5638 5639 return false; 5640 5641 }, 5642 5643 // Show done message 5644 _showdonemsg: function infscr_showdonemsg() { 5645 5646 var opts = this.options; 5647 5648 // if behavior is defined and this function is extended, call that instead of default 5649 if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) { 5650 this['_showdonemsg_'+opts.behavior].call(this); 5651 return; 5652 } 5653 5654 opts.loading.msg 5655 .find('img') 5656 .hide() 5657 .parent() 5658 .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () { 5659 $(this).parent().fadeOut(opts.loading.speed); 5660 }); 5661 5662 // user provided callback when done 5663 opts.errorCallback.call($(opts.contentSelector)[0],'done'); 5664 }, 5665 5666 // grab each selector option and see if any fail 5667 _validate: function infscr_validate(opts) { 5668 for (var key in opts) { 5669 if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) { 5670 this._debug('Your ' + key + ' found no elements.'); 5671 return false; 5672 } 5673 } 5674 5675 return true; 5676 }, 5677 5678 /* 5679 ---------------------------- 5680 Public methods 5681 ---------------------------- 5682 */ 5683 5684 // Bind to scroll 5685 bind: function infscr_bind() { 5686 this._binding('bind'); 5687 }, 5688 5689 // Destroy current instance of plugin 5690 destroy: function infscr_destroy() { 5691 this.options.state.isDestroyed = true; 5692 this.options.loading.finished(); 5693 return this._error('destroy'); 5694 }, 5695 5696 // Set pause value to false 5697 pause: function infscr_pause() { 5698 this._pausing('pause'); 5699 }, 5700 5701 // Set pause value to false 5702 resume: function infscr_resume() { 5703 this._pausing('resume'); 5704 }, 5705 5706 beginAjax: function infscr_ajax(opts) { 5707 var instance = this, 5708 path = opts.path, 5709 box, desturl, method, condition; 5710 5711 // increment the URL bit. e.g. /page/3/ 5712 opts.state.currPage++; 5713 5714 // Manually control maximum page 5715 if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){ 5716 opts.state.isBeyondMaxPage = true; 5717 this.destroy(); 5718 return; 5719 } 5720 5721 // if we're dealing with a table we can't use DIVs 5722 box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>'); 5723 5724 desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage); 5725 instance._debug('heading into ajax', desturl); 5726 5727 method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback'; 5728 if (opts.appendCallback && opts.dataType === 'html') { 5729 method += '+callback'; 5730 } 5731 5732 switch (method) { 5733 case 'html+callback': 5734 instance._debug('Using HTML via .load() method'); 5735 box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) { 5736 instance._loadcallback(box, responseText, desturl); 5737 }); 5738 5739 break; 5740 5741 case 'html': 5742 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 5743 $.ajax({ 5744 // params 5745 url: desturl, 5746 dataType: opts.dataType, 5747 complete: function infscr_ajax_callback(jqXHR, textStatus) { 5748 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 5749 if (condition) { 5750 instance._loadcallback(box, jqXHR.responseText, desturl); 5751 } else { 5752 instance._error('end'); 5753 } 5754 } 5755 }); 5756 5757 break; 5758 case 'json': 5759 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 5760 $.ajax({ 5761 dataType: 'json', 5762 type: 'GET', 5763 url: desturl, 5764 success: function (data, textStatus, jqXHR) { 5765 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 5766 if (opts.appendCallback) { 5767 // if appendCallback is true, you must defined template in options. 5768 // note that data passed into _loadcallback is already an html (after processed in opts.template(data)). 5769 if (opts.template !== undefined) { 5770 var theData = opts.template(data); 5771 box.append(theData); 5772 if (condition) { 5773 instance._loadcallback(box, theData); 5774 } else { 5775 instance._error('end'); 5776 } 5777 } else { 5778 instance._debug('template must be defined.'); 5779 instance._error('end'); 5780 } 5781 } else { 5782 // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback. 5783 if (condition) { 5784 instance._loadcallback(box, data, desturl); 5785 } else { 5786 instance._error('end'); 5787 } 5788 } 5789 }, 5790 error: function() { 5791 instance._debug('JSON ajax request failed.'); 5792 instance._error('end'); 5793 } 5794 }); 5795 5796 break; 5797 } 5798 }, 5799 5800 // Retrieve next set of content items 5801 retrieve: function infscr_retrieve(pageNum) { 5802 pageNum = pageNum || null; 5803 5804 var instance = this, 5805 opts = instance.options; 5806 5807 // if behavior is defined and this function is extended, call that instead of default 5808 if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) { 5809 this['retrieve_'+opts.behavior].call(this,pageNum); 5810 return; 5811 } 5812 5813 // for manual triggers, if destroyed, get out of here 5814 if (opts.state.isDestroyed) { 5815 this._debug('Instance is destroyed'); 5816 return false;
5817 } 5818 5819 // we dont want to fire the ajax multiple times 5820 opts.state.isDuringAjax = true; 5821 5822 opts.loading.start.call($(opts.contentSelector)[0],opts); 5823 }, 5824 5825 // Check to see next page is needed 5826 scroll: function infscr_scroll() { 5827 5828 var opts = this.options, 5829 state = opts.state; 5830 5831 // if behavior is defined and this function is extended, call that instead of default 5832 if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) { 5833 this['scroll_'+opts.behavior].call(this); 5834 return; 5835 } 5836 5837 if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) { 5838 return; 5839 } 5840 5841 if (!this._nearbottom()) { 5842 return; 5843 } 5844 5845 this.retrieve(); 5846 5847 }, 5848 5849 // Toggle pause value 5850 toggle: function infscr_toggle() { 5851 this._pausing(); 5852 }, 5853 5854 // Unbind from scroll 5855 unbind: function infscr_unbind() { 5856 this._binding('unbind'); 5857 }, 5858 5859 // update options 5860 update: function infscr_options(key) { 5861 if ($.isPlainObject(key)) { 5862 this.options = $.extend(true,this.options,key); 5863 } 5864 } 5865 }; 5866 5867 5868 /* 5869 ---------------------------- 5870 Infinite Scroll function 5871 ---------------------------- 5872 5873 Borrowed logic from the following... 5874 5875 jQuery UI 5876 - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js 5877 5878 jCarousel 5879 - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js 5880 5881 Masonry 5882 - https://github.com/desandro/masonry/blob/master/jquery.masonry.js 5883 5884*/ 5885 5886 $.fn.infinitescroll = function infscr_init(options, callback) { 5887 5888 5889 var thisCall = typeof options; 5890 5891 switch (thisCall) { 5892 5893 // method 5894 case 'string': 5895 var args = Array.prototype.slice.call(arguments, 1); 5896 5897 this.each(function () { 5898 var instance = $.data(this, 'infinitescroll'); 5899 5900 if (!instance) { 5901 // not setup yet 5902 // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup'); 5903 return false; 5904 } 5905 5906 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') { 5907 // return $.error('No such method ' + options + ' for Infinite Scroll'); 5908 return false; 5909 } 5910 5911 // no errors! 5912 instance[options].apply(instance, args); 5913 }); 5914 5915 break; 5916 5917 // creation 5918 case 'object': 5919 5920 this.each(function () { 5921 5922 var instance = $.data(this, 'infinitescroll'); 5923 5924 if (instance) { 5925 5926 // update options of current instance 5927 instance.update(options); 5928 5929 } else { 5930 5931 // initialize new instance 5932 instance = new $.infinitescroll(options, callback, this); 5933 5934 // don't attach if instantiation failed 5935 if (!instance.failed) { 5936 $.data(this, 'infinitescroll', instance); 5937 } 5938 5939 } 5940 5941 }); 5942 5943 break; 5944 5945 } 5946 5947 return this; 5948 }; 5949 5950 5951 5952 /* 5953 * smartscroll: debounced scroll event for jQuery * 5954 * https://github.com/lukeshumard/smartscroll 5955 * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js * 5956 * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. * 5957 */ 5958 5959 var event = $.event, 5960 scrollTimeout; 5961 5962 event.special.smartscroll = { 5963 setup: function () { 5964 $(this).bind('scroll', event.special.smartscroll.handler); 5965 }, 5966 teardown: function () { 5967 $(this).unbind('scroll', event.special.smartscroll.handler); 5968 }, 5969 handler: function (event, execAsap) { 5970 // Save the context 5971 var context = this, 5972 args = arguments; 5973 5974 // set correct event type 5975 event.type = 'smartscroll'; 5976 5977 if (scrollTimeout) { clearTimeout(scrollTimeout); } 5978 scrollTimeout = setTimeout(function () { 5979 $(context).trigger('smartscroll', args); 5980 }, execAsap === 'execAsap' ? 0 : 100); 5981 } 5982 }; 5983 5984 $.fn.smartscroll = function (fn) {
5985 return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']); 5986 }; 5987 5988})); 5989 5990/*! 5991Waypoints - 4.0.1 5992Copyright © 2011-2016 Caleb Troughton 5993Licensed under the MIT license. 5994https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 5995*/ 5996(function() { 5997 'use strict' 5998 5999 var keyCounter = 0 6000 var allWaypoints = {} 6001 6002 /* http://imakewebthings.com/waypoints/api/waypoint */ 6003 function Waypoint(options) { 6004 if (!options) { 6005 throw new Error('No options passed to Waypoint constructor') 6006 } 6007 if (!options.element) { 6008 throw new Error('No element option passed to Waypoint constructor') 6009 } 6010 if (!options.handler) { 6011 throw new Error('No handler option passed to Waypoint constructor') 6012 } 6013 6014 this.key = 'waypoint-' + keyCounter 6015 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 6016 this.element = this.options.element 6017 this.adapter = new Waypoint.Adapter(this.element) 6018 this.callback = options.handler 6019 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 6020 this.enabled = this.options.enabled 6021 this.triggerPoint = null 6022 this.group = Waypoint.Group.findOrCreate({ 6023 name: this.options.group, 6024 axis: this.axis 6025 }) 6026 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 6027 6028 if (Waypoint.offsetAliases[this.options.offset]) { 6029 this.options.offset = Waypoint.offsetAliases[this.options.offset] 6030 } 6031 this.group.add(this) 6032 this.context.add(this) 6033 allWaypoints[this.key] = this 6034 keyCounter += 1 6035 } 6036 6037 /* Private */ 6038 Waypoint.prototype.queueTrigger = function(direction) { 6039 this.group.queueTrigger(this, direction) 6040 } 6041 6042 /* Private */ 6043 Waypoint.prototype.trigger = function(args) { 6044 if (!this.enabled) { 6045 return 6046 } 6047 if (this.callback) { 6048 this.callback.apply(this, args) 6049 } 6050 } 6051 6052 /* Public */ 6053 /* http://imakewebthings.com/waypoints/api/destroy */ 6054 Waypoint.prototype.destroy = function() { 6055 this.context.remove(this) 6056 this.group.remove(this) 6057 delete allWaypoints[this.key] 6058 } 6059 6060 /* Public */ 6061 /* http://imakewebthings.com/waypoints/api/disable */ 6062 Waypoint.prototype.disable = function() { 6063 this.enabled = false 6064 return this 6065 } 6066 6067 /* Public */ 6068 /* http://imakewebthings.com/waypoints/api/enable */ 6069 Waypoint.prototype.enable = function() { 6070 this.context.refresh() 6071 this.enabled = true 6072 return this 6073 } 6074 6075 /* Public */ 6076 /* http://imakewebthings.com/waypoints/api/next */ 6077 Waypoint.prototype.next = function() { 6078 return this.group.next(this) 6079 } 6080 6081 /* Public */ 6082 /* http://imakewebthings.com/waypoints/api/previous */ 6083 Waypoint.prototype.previous = function() { 6084 return this.group.previous(this) 6085 } 6086 6087 /* Private */ 6088 Waypoint.invokeAll = function(method) { 6089 var allWaypointsArray = []
6090 for (var waypointKey in allWaypoints) { 6091 allWaypointsArray.push(allWaypoints[waypointKey]) 6092 } 6093 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 6094 allWaypointsArray[i][method]() 6095 } 6096 } 6097 6098 /* Public */ 6099 /* http://imakewebthings.com/waypoints/api/destroy-all */ 6100 Waypoint.destroyAll = function() { 6101 Waypoint.invokeAll('destroy') 6102 } 6103 6104 /* Public */ 6105 /* http://imakewebthings.com/waypoints/api/disable-all */ 6106 Waypoint.disableAll = function() { 6107 Waypoint.invokeAll('disable') 6108 } 6109 6110 /* Public */ 6111 /* http://imakewebthings.com/waypoints/api/enable-all */ 6112 Waypoint.enableAll = function() { 6113 Waypoint.Context.refreshAll() 6114 for (var waypointKey in allWaypoints) { 6115 allWaypoints[waypointKey].enabled = true 6116 } 6117 return this 6118 } 6119 6120 /* Public */ 6121 /* http://imakewebthings.com/waypoints/api/refresh-all */ 6122 Waypoint.refreshAll = function() { 6123 Waypoint.Context.refreshAll() 6124 } 6125 6126 /* Public */ 6127 /* http://imakewebthings.com/waypoints/api/viewport-height */ 6128 Waypoint.viewportHeight = function() { 6129 return window.innerHeight || document.documentElement.clientHeight 6130 } 6131 6132 /* Public */ 6133 /* http://imakewebthings.com/waypoints/api/viewport-width */ 6134 Waypoint.viewportWidth = function() { 6135 return document.documentElement.clientWidth 6136 } 6137 6138 Waypoint.adapters = [] 6139 6140 Waypoint.defaults = { 6141 context: window, 6142 continuous: true, 6143 enabled: true, 6144 group: 'default', 6145 horizontal: false, 6146 offset: 0 6147 } 6148 6149 Waypoint.offsetAliases = { 6150 'bottom-in-view': function() { 6151 return this.context.innerHeight() - this.adapter.outerHeight() 6152 }, 6153 'right-in-view': function() { 6154 return this.context.innerWidth() - this.adapter.outerWidth() 6155 } 6156 } 6157 6158 window.Waypoint = Waypoint 6159}()) 6160;(function() { 6161 'use strict' 6162 6163 function requestAnimationFrameShim(callback) { 6164 window.setTimeout(callback, 1000 / 60) 6165 } 6166 6167 var keyCounter = 0 6168 var contexts = {} 6169 var Waypoint = window.Waypoint 6170 var oldWindowLoad = window.onload 6171 6172 /* http://imakewebthings.com/waypoints/api/context */ 6173 function Context(element) { 6174 this.element = element 6175 this.Adapter = Waypoint.Adapter 6176 this.adapter = new this.Adapter(element) 6177 this.key = 'waypoint-context-' + keyCounter 6178 this.didScroll = false 6179 this.didResize = false 6180 this.oldScroll = { 6181 x: this.adapter.scrollLeft(), 6182 y: this.adapter.scrollTop() 6183 } 6184 this.waypoints = { 6185 vertical: {}, 6186 horizontal: {} 6187 } 6188 6189 element.waypointContextKey = this.key 6190 contexts[element.waypointContextKey] = this 6191 keyCounter += 1 6192 if (!Waypoint.windowContext) { 6193 Waypoint.windowContext = true 6194 Waypoint.windowContext = new Context(window) 6195 } 6196 6197 this.createThrottledScrollHandler() 6198 this.createThrottledResizeHandler() 6199 } 6200 6201 /* Private */ 6202 Context.prototype.add = function(waypoint) { 6203 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 6204 this.waypoints[axis][waypoint.key] = waypoint 6205 this.refresh() 6206 } 6207 6208 /* Private */ 6209 Context.prototype.checkEmpty = function() { 6210 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 6211 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 6212 var isWindow = this.element == this.element.window 6213 if (horizontalEmpty && verticalEmpty && !isWindow) { 6214 this.adapter.off('.waypoints') 6215 delete contexts[this.key] 6216 } 6217 } 6218 6219 /* Private */ 6220 Context.prototype.createThrottledResizeHandler = function() { 6221 var self = this 6222 6223 function resizeHandler() { 6224 self.handleResize() 6225 self.didResize = false 6226 } 6227 6228 this.adapter.on('resize.waypoints', function() { 6229 if (!self.didResize) { 6230 self.didResize = true 6231 Waypoint.requestAnimationFrame(resizeHandler) 6232 } 6233 }) 6234 } 6235 6236 /* Private */ 6237 Context.prototype.createThrottledScrollHandler = function() { 6238 var self = this 6239 function scrollHandler() { 6240 self.handleScroll() 6241 self.didScroll = false 6242 } 6243 6244 this.adapter.on('scroll.waypoints', function() { 6245 if (!self.didScroll || Waypoint.isTouch) { 6246 self.didScroll = true 6247 Waypoint.requestAnimationFrame(scrollHandler) 6248 } 6249 }) 6250 } 6251 6252 /* Private */ 6253 Context.prototype.handleResize = function() { 6254 Waypoint.Context.refreshAll() 6255 } 6256 6257 /* Private */ 6258 Context.prototype.handleScroll = function() { 6259 var triggeredGroups = {} 6260 var axes = { 6261 horizontal: { 6262 newScroll: this.adapter.scrollLeft(), 6263 oldScroll: this.oldScroll.x, 6264 forward: 'right', 6265 backward: 'left' 6266 }, 6267 vertical: { 6268 newScroll: this.adapter.scrollTop(), 6269 oldScroll: this.oldScroll.y, 6270 forward: 'down', 6271 backward: 'up' 6272 } 6273 } 6274 6275 for (var axisKey in axes) { 6276 var axis = axes[axisKey] 6277 var isForward = axis.newScroll > axis.oldScroll 6278 var direction = isForward ? axis.forward : axis.backward 6279
6280 for (var waypointKey in this.waypoints[axisKey]) { 6281 var waypoint = this.waypoints[axisKey][waypointKey] 6282 if (waypoint.triggerPoint === null) { 6283 continue 6284 } 6285 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 6286 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 6287 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 6288 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 6289 if (crossedForward || crossedBackward) { 6290 waypoint.queueTrigger(direction) 6291 triggeredGroups[waypoint.group.id] = waypoint.group 6292 } 6293 } 6294 } 6295 6296 for (var groupKey in triggeredGroups) { 6297 triggeredGroups[groupKey].flushTriggers() 6298 } 6299 6300 this.oldScroll = { 6301 x: axes.horizontal.newScroll, 6302 y: axes.vertical.newScroll 6303 } 6304 } 6305 6306 /* Private */ 6307 Context.prototype.innerHeight = function() { 6308 /*eslint-disable eqeqeq */ 6309 if (this.element == this.element.window) { 6310 return Waypoint.viewportHeight() 6311 } 6312 /*eslint-enable eqeqeq */ 6313 return this.adapter.innerHeight() 6314 } 6315 6316 /* Private */ 6317 Context.prototype.remove = function(waypoint) { 6318 delete this.waypoints[waypoint.axis][waypoint.key] 6319 this.checkEmpty() 6320 } 6321 6322 /* Private */ 6323 Context.prototype.innerWidth = function() { 6324 /*eslint-disable eqeqeq */ 6325 if (this.element == this.element.window) { 6326 return Waypoint.viewportWidth() 6327 } 6328 /*eslint-enable eqeqeq */ 6329 return this.adapter.innerWidth() 6330 } 6331 6332 /* Public */ 6333 /* http://imakewebthings.com/waypoints/api/context-destroy */ 6334 Context.prototype.destroy = function() { 6335 var allWaypoints = [] 6336 for (var axis in this.waypoints) {
6337 for (var waypointKey in this.waypoints[axis]) { 6338 allWaypoints.push(this.waypoints[axis][waypointKey]) 6339 } 6340 } 6341 for (var i = 0, end = allWaypoints.length; i < end; i++) { 6342 allWaypoints[i].destroy() 6343 } 6344 } 6345 6346 /* Public */ 6347 /* http://imakewebthings.com/waypoints/api/context-refresh */ 6348 Context.prototype.refresh = function() { 6349 /*eslint-disable eqeqeq */ 6350 var isWindow = this.element == this.element.window 6351 /*eslint-enable eqeqeq */ 6352 var contextOffset = isWindow ? undefined : this.adapter.offset() 6353 var triggeredGroups = {} 6354 var axes 6355 6356 this.handleScroll() 6357 axes = { 6358 horizontal: { 6359 contextOffset: isWindow ? 0 : contextOffset.left, 6360 contextScroll: isWindow ? 0 : this.oldScroll.x, 6361 contextDimension: this.innerWidth(), 6362 oldScroll: this.oldScroll.x, 6363 forward: 'right', 6364 backward: 'left', 6365 offsetProp: 'left' 6366 }, 6367 vertical: { 6368 contextOffset: isWindow ? 0 : contextOffset.top, 6369 contextScroll: isWindow ? 0 : this.oldScroll.y, 6370 contextDimension: this.innerHeight(), 6371 oldScroll: this.oldScroll.y, 6372 forward: 'down', 6373 backward: 'up', 6374 offsetProp: 'top' 6375 } 6376 } 6377 6378 for (var axisKey in axes) { 6379 var axis = axes[axisKey]
6380 for (var waypointKey in this.waypoints[axisKey]) { 6381 var waypoint = this.waypoints[axisKey][waypointKey] 6382 var adjustment = waypoint.options.offset 6383 var oldTriggerPoint = waypoint.triggerPoint 6384 var elementOffset = 0 6385 var freshWaypoint = oldTriggerPoint == null 6386 var contextModifier, wasBeforeScroll, nowAfterScroll 6387 var triggeredBackward, triggeredForward 6388 6389 if (waypoint.element !== waypoint.element.window) { 6390 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 6391 } 6392 6393 if (typeof adjustment === 'function') { 6394 adjustment = adjustment.apply(waypoint) 6395 } 6396 else if (typeof adjustment === 'string') { 6397 adjustment = parseFloat(adjustment) 6398 if (waypoint.options.offset.indexOf('%') > - 1) { 6399 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 6400 } 6401 } 6402 6403 contextModifier = axis.contextScroll - axis.contextOffset 6404 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 6405 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 6406 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 6407 triggeredBackward = wasBeforeScroll && nowAfterScroll 6408 triggeredForward = !wasBeforeScroll && !nowAfterScroll 6409 6410 if (!freshWaypoint && triggeredBackward) { 6411 waypoint.queueTrigger(axis.backward) 6412 triggeredGroups[waypoint.group.id] = waypoint.group 6413 } 6414 else if (!freshWaypoint && triggeredForward) { 6415 waypoint.queueTrigger(axis.forward) 6416 triggeredGroups[waypoint.group.id] = waypoint.group 6417 } 6418 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 6419 waypoint.queueTrigger(axis.forward) 6420 triggeredGroups[waypoint.group.id] = waypoint.group 6421 } 6422 } 6423 } 6424 6425 Waypoint.requestAnimationFrame(function() { 6426 for (var groupKey in triggeredGroups) { 6427 triggeredGroups[groupKey].flushTriggers() 6428 } 6429 }) 6430 6431 return this 6432 } 6433 6434 /* Private */ 6435 Context.findOrCreateByElement = function(element) { 6436 return Context.findByElement(element) || new Context(element) 6437 } 6438 6439 /* Private */ 6440 Context.refreshAll = function() { 6441 for (var contextId in contexts) { 6442 contexts[contextId].refresh() 6443 } 6444 } 6445 6446 /* Public */ 6447 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 6448 Context.findByElement = function(element) { 6449 return contexts[element.waypointContextKey] 6450 } 6451 6452 window.onload = function() { 6453 if (oldWindowLoad) { 6454 oldWindowLoad() 6455 } 6456 Context.refreshAll() 6457 } 6458 6459 6460 Waypoint.requestAnimationFrame = function(callback) { 6461 var requestFn = window.requestAnimationFrame || 6462 window.mozRequestAnimationFrame || 6463 window.webkitRequestAnimationFrame || 6464 requestAnimationFrameShim 6465 requestFn.call(window, callback) 6466 } 6467 Waypoint.Context = Context 6468}()) 6469;(function() { 6470 'use strict' 6471 6472 function byTriggerPoint(a, b) { 6473 return a.triggerPoint - b.triggerPoint 6474 } 6475 6476 function byReverseTriggerPoint(a, b) { 6477 return b.triggerPoint - a.triggerPoint 6478 } 6479 6480 var groups = { 6481 vertical: {}, 6482 horizontal: {} 6483 } 6484 var Waypoint = window.Waypoint 6485 6486 /* http://imakewebthings.com/waypoints/api/group */ 6487 function Group(options) { 6488 this.name = options.name 6489 this.axis = options.axis 6490 this.id = this.name + '-' + this.axis 6491 this.waypoints = [] 6492 this.clearTriggerQueues() 6493 groups[this.axis][this.name] = this 6494 } 6495 6496 /* Private */ 6497 Group.prototype.add = function(waypoint) { 6498 this.waypoints.push(waypoint) 6499 } 6500 6501 /* Private */ 6502 Group.prototype.clearTriggerQueues = function() { 6503 this.triggerQueues = { 6504 up: [], 6505 down: [], 6506 left: [], 6507 right: [] 6508 } 6509 } 6510 6511 /* Private */ 6512 Group.prototype.flushTriggers = function() { 6513 for (var direction in this.triggerQueues) { 6514 var waypoints = this.triggerQueues[direction] 6515 var reverse = direction === 'up' || direction === 'left' 6516 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 6517 for (var i = 0, end = waypoints.length; i < end; i += 1) { 6518 var waypoint = waypoints[i] 6519 if (waypoint.options.continuous || i === waypoints.length - 1) { 6520 waypoint.trigger([direction]) 6521 } 6522 } 6523 } 6524 this.clearTriggerQueues() 6525 } 6526 6527 /* Private */ 6528 Group.prototype.next = function(waypoint) { 6529 this.waypoints.sort(byTriggerPoint) 6530 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 6531 var isLast = index === this.waypoints.length - 1 6532 return isLast ? null : this.waypoints[index + 1] 6533 } 6534 6535 /* Private */ 6536 Group.prototype.previous = function(waypoint) { 6537 this.waypoints.sort(byTriggerPoint) 6538 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 6539 return index ? this.waypoints[index - 1] : null 6540 } 6541 6542 /* Private */ 6543 Group.prototype.queueTrigger = function(waypoint, direction) { 6544 this.triggerQueues[direction].push(waypoint) 6545 } 6546 6547 /* Private */ 6548 Group.prototype.remove = function(waypoint) { 6549 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 6550 if (index > -1) { 6551 this.waypoints.splice(index, 1) 6552 } 6553 } 6554 6555 /* Public */ 6556 /* http://imakewebthings.com/waypoints/api/first */ 6557 Group.prototype.first = function() { 6558 return this.waypoints[0] 6559 } 6560 6561 /* Public */ 6562 /* http://imakewebthings.com/waypoints/api/last */ 6563 Group.prototype.last = function() { 6564 return this.waypoints[this.waypoints.length - 1] 6565 } 6566 6567 /* Private */ 6568 Group.findOrCreate = function(options) { 6569 return groups[options.axis][options.name] || new Group(options) 6570 } 6571 6572 Waypoint.Group = Group 6573}()) 6574;(function() { 6575 'use strict' 6576 6577 var $ = window.jQuery 6578 var Waypoint = window.Waypoint 6579 6580 function JQueryAdapter(element) { 6581 this.$element = $(element) 6582 } 6583 6584 $.each([
6585 'innerHeight', 6586 'innerWidth', 6587 'off', 6588 'offset', 6589 'on', 6590 'outerHeight', 6591 'outerWidth', 6592 'scrollLeft', 6593 'scrollTop' 6594 ], function(i, method) { 6595 JQueryAdapter.prototype[method] = function() { 6596 var args = Array.prototype.slice.call(arguments) 6597 return this.$element[method].apply(this.$element, args) 6598 } 6599 }) 6600 6601 $.each([ 6602 'extend', 6603 'inArray', 6604 'isEmptyObject' 6605 ], function(i, method) { 6606 JQueryAdapter[method] = $[method] 6607 }) 6608 6609 Waypoint.adapters.push({ 6610 name: 'jquery', 6611 Adapter: JQueryAdapter 6612 }) 6613 Waypoint.Adapter = JQueryAdapter 6614}()) 6615;(function() { 6616 'use strict' 6617 6618 var Waypoint = window.Waypoint 6619 6620 function createExtension(framework) { 6621 return function() { 6622 var waypoints = [] 6623 var overrides = arguments[0] 6624 6625 if (framework.isFunction(arguments[0])) { 6626 overrides = framework.extend({}, arguments[1]) 6627 overrides.handler = arguments[0] 6628 } 6629 6630 this.each(function() { 6631 var options = framework.extend({}, overrides, { 6632 element: this 6633 }) 6634 if (typeof options.context === 'string') { 6635 options.context = framework(this).closest(options.context)[0] 6636 } 6637 waypoints.push(new Waypoint(options)) 6638 }) 6639 6640 return waypoints 6641 } 6642 } 6643 6644 if (window.jQuery) { 6645 window.jQuery.fn.waypoint = createExtension(window.jQuery) 6646 } 6647 if (window.Zepto) { 6648 window.Zepto.fn.waypoint = createExtension(window.Zepto) 6649 } 6650}()) 6651; 6652/*! 6653Waypoints Inview Shortcut - 4.0.1 6654Copyright © 2011-2016 Caleb Troughton 6655Licensed under the MIT license. 6656https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 6657*/ 6658(function() { 6659 'use strict' 6660 6661 function noop() {} 6662 6663 var Waypoint = window.Waypoint 6664 6665 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 6666 function Inview(options) { 6667 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 6668 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 6669 this.waypoints = [] 6670 this.element = this.options.element 6671 this.createWaypoints() 6672 } 6673 6674 /* Private */ 6675 Inview.prototype.createWaypoints = function() { 6676 var configs = { 6677 vertical: [{ 6678 down: 'enter', 6679 up: 'exited', 6680 offset: '100%' 6681 }, { 6682 down: 'entered', 6683 up: 'exit', 6684 offset: 'bottom-in-view' 6685 }, { 6686 down: 'exit', 6687 up: 'entered', 6688 offset: 0 6689 }, { 6690 down: 'exited', 6691 up: 'enter', 6692 offset: function() { 6693 return -this.adapter.outerHeight() 6694 } 6695 }], 6696 horizontal: [{ 6697 right: 'enter', 6698 left: 'exited', 6699 offset: '100%' 6700 }, { 6701 right: 'entered', 6702 left: 'exit', 6703 offset: 'right-in-view' 6704 }, { 6705 right: 'exit', 6706 left: 'entered', 6707 offset: 0 6708 }, { 6709 right: 'exited', 6710 left: 'enter', 6711 offset: function() { 6712 return -this.adapter.outerWidth() 6713 } 6714 }] 6715 } 6716 6717 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 6718 var config = configs[this.axis][i] 6719 this.createWaypoint(config) 6720 } 6721 } 6722 6723 /* Private */ 6724 Inview.prototype.createWaypoint = function(config) { 6725 var self = this 6726 this.waypoints.push(new Waypoint({ 6727 context: this.options.context, 6728 element: this.options.element, 6729 enabled: this.options.enabled, 6730 handler: (function(config) { 6731 return function(direction) { 6732 self.options[config[direction]].call(self, direction) 6733 } 6734 }(config)), 6735 offset: config.offset, 6736 horizontal: this.options.horizontal 6737 })) 6738 } 6739 6740 /* Public */ 6741 Inview.prototype.destroy = function() { 6742 for (var i = 0, end = this.waypoints.length; i < end; i++) { 6743 this.waypoints[i].destroy() 6744 } 6745 this.waypoints = [] 6746 } 6747 6748 Inview.prototype.disable = function() { 6749 for (var i = 0, end = this.waypoints.length; i < end; i++) { 6750 this.waypoints[i].disable() 6751 } 6752 } 6753 6754 Inview.prototype.enable = function() { 6755 for (var i = 0, end = this.waypoints.length; i < end; i++) { 6756 this.waypoints[i].enable() 6757 } 6758 } 6759 6760 Inview.defaults = { 6761 context: window, 6762 enabled: true, 6763 enter: noop, 6764 entered: noop,
6765 exit: noop, 6766 exited: noop 6767 } 6768 6769 Waypoint.Inview = Inview 6770}()) 6771; 6772 6773/* 6774 * SmartMenus jQuery v0.9.6 6775 * http://www.smartmenus.org/ 6776 * 6777 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 6778 * http://vadikom.com/ 6779 * 6780 * Released under the MIT license: 6781 * http://www.opensource.org/licenses/MIT 6782 */ 6783 6784(function($) { 6785 6786 var menuTrees = [], 6787 IE = !!window.createPopup, // we need to detect it, unfortunately 6788 IElt9 = IE && !document.defaultView, 6789 IElt8 = IE && !document.querySelector, 6790 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 6791 mouse = false, // optimize for touch by default - we will detect for mouse input 6792 mouseDetectionEnabled = false; 6793 6794 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 6795 function initMouseDetection(disable) { 6796 if (!mouseDetectionEnabled && !disable) { 6797 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 6798 // 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) 6799 var firstTime = true, 6800 lastMove = null; 6801 $(document).bind({ 6802 'mousemove.smartmenus_mouse': function(e) { 6803 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 6804 if (lastMove) { 6805 var deltaX = Math.abs(lastMove.x - thisMove.x), 6806 deltaY = Math.abs(lastMove.y - thisMove.y); 6807 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 6808 mouse = true; 6809 // 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 6810 if (firstTime) { 6811 var $a = $(e.target).closest('a'); 6812 if ($a.is('a')) { 6813 $.each(menuTrees, function() { 6814 if ($.contains(this.$root[0], $a[0])) { 6815 this.itemEnter({ currentTarget: $a[0] }); 6816 return false; 6817 } 6818 }); 6819 } 6820 firstTime = false; 6821 } 6822 } 6823 } 6824 lastMove = thisMove; 6825 }, 6826 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 6827 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 6828 mouse = false; 6829 } 6830 } 6831 }); 6832 mouseDetectionEnabled = true; 6833 } else if (mouseDetectionEnabled && disable) { 6834 $(document).unbind('.smartmenus_mouse'); 6835 mouseDetectionEnabled = false; 6836 } 6837 }; 6838 6839 $.SmartMenus = function(elm, options) { 6840 this.$root = $(elm); 6841 this.opts = options; 6842 this.rootId = ''; // internal 6843 this.$subArrow = null; 6844 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) 6845 this.activatedItems = []; // stores last activated A's for each level 6846 this.visibleSubMenus = []; // stores visible sub menus UL's 6847 this.showTimeout = 0; 6848 this.hideTimeout = 0; 6849 this.scrollTimeout = 0; 6850 this.clickActivated = false; 6851 this.zIndexInc = 0; 6852 this.$firstLink = null; // we'll use these for some tests 6853 this.$firstSub = null; // at runtime so we'll cache them 6854 this.disabled = false; 6855 this.$disableOverlay = null; 6856 this.init(); 6857 }; 6858 6859 $.extend($.SmartMenus, { 6860 hideAll: function() { 6861 $.each(menuTrees, function() { 6862 this.menuHideAll(); 6863 }); 6864 }, 6865 destroy: function() { 6866 while (menuTrees.length) { 6867 menuTrees[0].destroy(); 6868 } 6869 initMouseDetection(true); 6870 }, 6871 prototype: { 6872 init: function(refresh) { 6873 var self = this; 6874 6875 if (!refresh) { 6876 menuTrees.push(this); 6877 6878 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 6879 6880 if (this.$root.hasClass('sm-rtl')) { 6881 this.opts.rightToLeftSubMenus = true; 6882 } 6883 6884 // init root (main menu) 6885 this.$root 6886 .data('smartmenus', this) 6887 .attr('data-smartmenus-id', this.rootId) 6888 .dataSM('level', 1) 6889 .bind({ 6890 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
6891 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 6892 }) 6893 .delegate('a', { 6894 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 6895 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 6896 'mousedown.smartmenus': $.proxy(this.itemDown, this), 6897 'focus.smartmenus': $.proxy(this.itemFocus, this), 6898 'blur.smartmenus': $.proxy(this.itemBlur, this), 6899 'click.smartmenus': $.proxy(this.itemClick, this), 6900 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 6901 }); 6902 6903 var eNamespace = '.smartmenus' + this.rootId; 6904 // hide menus on tap or click outside the root UL 6905 if (this.opts.hideOnClick) { 6906 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 6907 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 6908 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 6909 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 6910 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 6911 } 6912 // hide sub menus on resize 6913 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 6914 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 6915 6916 if (this.opts.subIndicators) { 6917 this.$subArrow = $('<span/>').addClass('sub-arrow'); 6918 if (this.opts.subIndicatorsText) { 6919 this.$subArrow.html(this.opts.subIndicatorsText); 6920 } 6921 } 6922 6923 // make sure mouse detection is enabled 6924 initMouseDetection(); 6925 } 6926 6927 // init sub menus 6928 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 6929 6930 this.$firstLink = this.$root.find('a').eq(0); 6931 6932 // find current item 6933 if (this.opts.markCurrentItem) { 6934 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 6935 reHash = /#.*/, 6936 locHref = window.location.href.replace(reDefaultDoc, ''), 6937 locHrefNoHash = locHref.replace(reHash, ''); 6938 this.$root.find('a').each(function() { 6939 var href = this.href.replace(reDefaultDoc, ''), 6940 $this = $(this); 6941 if (href == locHref || href == locHrefNoHash) { 6942 $this.addClass('current'); 6943 if (self.opts.markCurrentTree) { 6944 $this.parents('li').each(function() { 6945 var $this = $(this); 6946 if ($this.dataSM('sub')) { 6947 $this.children('a').addClass('current'); 6948 } 6949 }); 6950 } 6951 } 6952 }); 6953 } 6954 }, 6955 destroy: function() { 6956 this.menuHideAll(); 6957 this.$root 6958 .removeData('smartmenus') 6959 .removeAttr('data-smartmenus-id') 6960 .removeDataSM('level') 6961 .unbind('.smartmenus') 6962 .undelegate('.smartmenus'); 6963 var eNamespace = '.smartmenus' + this.rootId; 6964 $(document).unbind(eNamespace); 6965 $(window).unbind(eNamespace); 6966 if (this.opts.subIndicators) { 6967 this.$subArrow = null; 6968 } 6969 var self = this; 6970 $.each(this.subMenus, function() { 6971 if (this.hasClass('mega-menu')) { 6972 this.find('ul').removeDataSM('in-mega'); 6973 } 6974 if (this.dataSM('shown-before')) { 6975 if (IElt8) { 6976 this.children().css({ styleFloat: '', width: '' }); 6977 } 6978 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 6979 if (!IE6) { 6980 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 6981 } else { 6982 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 6983 } 6984 } 6985 if (this.dataSM('scroll-arrows')) { 6986 this.dataSM('scroll-arrows').remove(); 6987 } 6988 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 6989 } 6990 if (self.opts.subIndicators) { 6991 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 6992 } 6993 this.removeDataSM('shown-before') 6994 .removeDataSM('ie-shim') 6995 .removeDataSM('scroll-arrows') 6996 .removeDataSM('parent-a') 6997 .removeDataSM('level') 6998 .removeDataSM('beforefirstshowfired') 6999 .parent().removeDataSM('sub'); 7000 }); 7001 if (this.opts.markCurrentItem) { 7002 this.$root.find('a.current').removeClass('current'); 7003 } 7004 this.$root = null; 7005 this.$firstLink = null; 7006 this.$firstSub = null; 7007 if (this.$disableOverlay) { 7008 this.$disableOverlay.remove(); 7009 this.$disableOverlay = null; 7010 } 7011 menuTrees.splice($.inArray(this, menuTrees), 1); 7012 }, 7013 disable: function(noOverlay) { 7014 if (!this.disabled) { 7015 this.menuHideAll(); 7016 // display overlay over the menu to prevent interaction 7017 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 7018 var pos = this.$root.offset(); 7019 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 7020 position: 'absolute', 7021 top: pos.top, 7022 left: pos.left, 7023 width: this.$root.outerWidth(), 7024 height: this.$root.outerHeight(),
7025 zIndex: this.getStartZIndex() + 1, 7026 opacity: 0 7027 }).appendTo(document.body); 7028 } 7029 this.disabled = true; 7030 } 7031 }, 7032 docClick: function(e) { 7033 // hide on any click outside the menu or on a menu link 7034 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 7035 this.menuHideAll($(e.target)); 7036 } 7037 }, 7038 docTouchEnd: function(e) { 7039 if (!this.lastTouch) { 7040 return; 7041 } 7042 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))) { 7043 if (this.hideTimeout) { 7044 clearTimeout(this.hideTimeout); 7045 this.hideTimeout = 0; 7046 } 7047 // hide with a delay to prevent triggering accidental unwanted click on some page element 7048 var self = this; 7049 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 7050 } 7051 this.lastTouch = null; 7052 }, 7053 docTouchMove: function(e) { 7054 if (!this.lastTouch) { 7055 return; 7056 } 7057 var touchPoint = e.originalEvent.touches[0]; 7058 this.lastTouch.x2 = touchPoint.pageX; 7059 this.lastTouch.y2 = touchPoint.pageY; 7060 }, 7061 docTouchStart: function(e) { 7062 var touchPoint = e.originalEvent.touches[0]; 7063 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 7064 }, 7065 enable: function() { 7066 if (this.disabled) { 7067 if (this.$disableOverlay) { 7068 this.$disableOverlay.remove(); 7069 this.$disableOverlay = null; 7070 } 7071 this.disabled = false; 7072 } 7073 }, 7074 getHeight: function($elm) { 7075 return this.getOffset($elm, true); 7076 }, 7077 // returns precise width/height float values in IE9+, FF4+, recent WebKit 7078 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 7079 getOffset: function($elm, height) { 7080 var old; 7081 if ($elm.css('display') == 'none') { 7082 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 7083 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 7084 } 7085 var defaultView = $elm[0].ownerDocument.defaultView, 7086 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 7087 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 7088 if (val) { 7089 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 7090 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 7091 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 7092 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 7093 } else { 7094 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 7095 } 7096 if (old) { 7097 $elm.hide().css(old); 7098 } 7099 return val; 7100 }, 7101 getWidth: function($elm) { 7102 return this.getOffset($elm); 7103 }, 7104 getStartZIndex: function() { 7105 var zIndex = parseInt(this.$root.css('z-index')); 7106 return !isNaN(zIndex) ? zIndex : 1; 7107 }, 7108 handleEvents: function() { 7109 return !this.disabled && this.isCSSOn(); 7110 }, 7111 handleItemEvents: function($a) { 7112 return this.handleEvents() && !this.isLinkInMegaMenu($a); 7113 }, 7114 isCollapsible: function() { 7115 return this.$firstSub.css('position') == 'static'; 7116 }, 7117 isCSSOn: function() { 7118 return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'inline'; 7119 }, 7120 isFixed: function() { 7121 return this.$root.css('position') == 'fixed'; 7122 }, 7123 isLinkInMegaMenu: function($a) { 7124 return !$a.parent().parent().dataSM('level'); 7125 }, 7126 isTouchMode: function() { 7127 return !mouse || this.isCollapsible(); 7128 }, 7129 itemActivate: function($a) { 7130 var $li = $a.parent(), 7131 $ul = $li.parent(), 7132 level = $ul.dataSM('level'); 7133 // 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 7134 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 7135 var self = this; 7136 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 7137 self.itemActivate($(this).dataSM('parent-a')); 7138 }); 7139 } 7140 // hide any visible deeper level sub menus 7141 if (this.visibleSubMenus.length > level) { 7142 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--) { 7143 this.menuHide(this.visibleSubMenus[i]); 7144 } 7145 } 7146 // save new active item and sub menu for this level 7147 this.activatedItems[level - 1] = $a; 7148 this.visibleSubMenus[level - 1] = $ul; 7149 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 7150 return; 7151 } 7152 // show the sub menu if this item has one 7153 var $sub = $li.dataSM('sub'); 7154 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 7155 this.menuShow($sub); 7156 } 7157 }, 7158 itemBlur: function(e) { 7159 var $a = $(e.currentTarget); 7160 if (!this.handleItemEvents($a)) { 7161 return; 7162 } 7163 this.$root.triggerHandler('blur.smapi', $a[0]); 7164 }, 7165 itemClick: function(e) { 7166 var $a = $(e.currentTarget); 7167 7168 if (!this.handleItemEvents($a)) { 7169 return; 7170 } 7171 $a.removeDataSM('mousedown'); 7172 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 7173 return false;
7174 } 7175 var $sub = $a.parent().dataSM('sub'); 7176 if (this.isTouchMode()) { 7177 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 7178 if ($a.dataSM('href')) { 7179 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 7180 } 7181 // if the sub is not visible 7182 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 7183 // try to activate the item and show the sub 7184 this.itemActivate($a); 7185 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 7186 // 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 7187 if ($sub.is(':visible')) { 7188 return false; 7189 } 7190 } 7191 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 7192 this.clickActivated = true; 7193 this.menuShow($sub); 7194 return false; 7195 } 7196 if ($a.hasClass('disabled')) { 7197 return false; 7198 } 7199 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 7200 return false; 7201 } 7202 }, 7203 itemDown: function(e) { 7204 var $a = $(e.currentTarget); 7205 if (!this.handleItemEvents($a)) { 7206 return; 7207 } 7208 $a.dataSM('mousedown', true); 7209 }, 7210 itemEnter: function(e) { 7211 var $a = $(e.currentTarget); 7212 if (!this.handleItemEvents($a)) { 7213 return; 7214 } 7215 if (!this.isTouchMode()) { 7216 if (this.showTimeout) { 7217 clearTimeout(this.showTimeout); 7218 this.showTimeout = 0; 7219 } 7220 var self = this; 7221 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 7222 } 7223 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 7224 }, 7225 itemFocus: function(e) { 7226 var $a = $(e.currentTarget); 7227 if (!this.handleItemEvents($a)) { 7228 return; 7229 } 7230 // 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 7231 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 7232 this.itemActivate($a); 7233 } 7234 this.$root.triggerHandler('focus.smapi', $a[0]); 7235 }, 7236 itemLeave: function(e) { 7237 var $a = $(e.currentTarget); 7238 if (!this.handleItemEvents($a)) { 7239 return; 7240 } 7241 if (!this.isTouchMode()) { 7242 if ($a[0].blur) { 7243 $a[0].blur(); 7244 } 7245 if (this.showTimeout) { 7246 clearTimeout(this.showTimeout); 7247 this.showTimeout = 0; 7248 } 7249 } 7250 $a.removeDataSM('mousedown'); 7251 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 7252 }, 7253 itemTouchEnd: function(e) { 7254 var $a = $(e.currentTarget); 7255 if (!this.handleItemEvents($a)) { 7256 return; 7257 } 7258 // prevent the address bar on iPhone from sliding down when expanding a sub menu 7259 var $sub = $a.parent().dataSM('sub'); 7260 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 7261 $a.dataSM('href', $a.attr('href')); 7262 $a.attr('href', '#'); 7263 } 7264 }, 7265 menuFixLayout: function($ul) { 7266 // fixes a menu that is being shown for the first time 7267 if (!$ul.dataSM('shown-before')) { 7268 $ul.hide().dataSM('shown-before', true); 7269 // fix the layout of the items in IE<8 7270 if (IElt8) { 7271 $ul.children().css({ styleFloat: 'left', width: '100%' }); 7272 } 7273 } 7274 }, 7275 menuHide: function($sub) { 7276 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 7277 return; 7278 } 7279 $sub.stop(true, true); 7280 if ($sub.is(':visible')) { 7281 var complete = function() { 7282 // unset z-index 7283 if (IElt9) { 7284 $sub.parent().css('z-index', ''); 7285 } else { 7286 $sub.css('z-index', ''); 7287 } 7288 }; 7289 // if sub is collapsible (mobile view) 7290 if (this.isCollapsible()) { 7291 if (this.opts.collapsibleHideFunction) { 7292 this.opts.collapsibleHideFunction.call(this, $sub, complete); 7293 } else { 7294 $sub.hide(this.opts.collapsibleHideDuration, complete); 7295 } 7296 } else { 7297 if (this.opts.hideFunction) { 7298 this.opts.hideFunction.call(this, $sub, complete); 7299 } else { 7300 $sub.hide(this.opts.hideDuration, complete); 7301 } 7302 } 7303 // remove IE iframe shim 7304 if ($sub.dataSM('ie-shim')) { 7305 $sub.dataSM('ie-shim').remove(); 7306 } 7307 // deactivate scrolling if it is activated for this sub 7308 if ($sub.dataSM('scroll')) { 7309 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 7310 } 7311 // unhighlight parent item 7312 $sub.dataSM('parent-a').removeClass('highlighted'); 7313 var level = $sub.dataSM('level'); 7314 this.activatedItems.splice(level - 1, 1); 7315 this.visibleSubMenus.splice(level - 1, 1); 7316 this.$root.triggerHandler('hide.smapi', $sub[0]); 7317 } 7318 }, 7319 menuHideAll: function($item) { 7320 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 7321 var $win = $(window), 7322 winW = $win.width(); 7323 if ( $('body').hasClass('vmenu') && winW >= 560 ) { 7324 return; 7325 } 7326 if (this.showTimeout) { 7327 clearTimeout(this.showTimeout); 7328 this.showTimeout = 0; 7329 } 7330 // hide all subs 7331 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 7332 this.menuHide(this.visibleSubMenus[i]); 7333 } 7334 // hide root if it's popup 7335 if (this.opts.isPopup) { 7336 this.$root.stop(true, true); 7337 if (this.$root.is(':visible')) { 7338 if (this.opts.hideFunction) { 7339 this.opts.hideFunction.call(this, this.$root); 7340 } else { 7341 this.$root.hide(this.opts.hideDuration); 7342 } 7343 // remove IE iframe shim 7344 if (this.$root.dataSM('ie-shim')) { 7345 this.$root.dataSM('ie-shim').remove(); 7346 } 7347 } 7348 } 7349 this.activatedItems = []; 7350 this.visibleSubMenus = []; 7351 this.clickActivated = false;
7352 // reset z-index increment 7353 this.zIndexInc = 0; 7354 }, 7355 menuIframeShim: function($ul) { 7356 // create iframe shim for the menu 7357 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 7358 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 7359 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 7360 ); 7361 } 7362 }, 7363 menuInit: function($ul) { 7364 if (!$ul.dataSM('in-mega')) { 7365 this.subMenus.push($ul); 7366 // mark UL's in mega drop downs (if any) so we can neglect them 7367 if ($ul.hasClass('mega-menu')) { 7368 $ul.find('ul').dataSM('in-mega', true); 7369 } 7370 // get level (much faster than, for example, using parentsUntil) 7371 var level = 2, 7372 par = $ul[0]; 7373 while ((par = par.parentNode.parentNode) != this.$root[0]) { 7374 level++; 7375 } 7376 // cache stuff 7377 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 7378 .dataSM('level', level) 7379 .parent().dataSM('sub', $ul); 7380 // add sub indicator to parent item 7381 if (this.opts.subIndicators) { 7382 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 7383 } 7384 } 7385 }, 7386 menuPosition: function($sub) { 7387 var fixIE = $('html.ie').length; 7388 // if (fixIE) { 7389 // var $rowParent = $($sub).closest('.main-menu-container'); 7390 // $rowParent.height($rowParent.height()); 7391 // } 7392 var $a = $sub.dataSM('parent-a'), 7393 $li = $sub.parent(), 7394 $ul = $sub.parent().parent(), 7395 $container = $ul.closest('.row-menu-inner').length ? $ul.closest('.row-menu-inner') : $ul.closest('.uncol'), 7396 level = $sub.dataSM('level'), 7397 subW = this.getWidth($sub), 7398 subH = this.getHeight($sub), 7399 itemOffset = $a.offset(), 7400 itemX = itemOffset.left, 7401 itemY = itemOffset.top, 7402 itemW = this.getWidth($a), 7403 itemH = this.getHeight($a), 7404 $win = $(window), 7405 winX = $win.scrollLeft(), 7406 winY = $win.scrollTop(), 7407 winW = $win.width(), 7408 winH = $win.height(), 7409 containerW = $container.width(), 7410 containerOffsetX = containerW + ((winW - containerW) / 2), 7411 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 7412 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 7413 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 7414 x, y, leftPos; 7415 if (horizontalParent) { 7416 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 7417 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 7418 } else { 7419 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX; 7420 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 7421 } 7422 if (this.opts.keepInViewport && !this.isCollapsible()) { 7423 if (this.isFixed()) { 7424 itemX -= winX; 7425 itemY -= winY; 7426 winX = winY = 0; 7427 } 7428 var absX = itemX + x, 7429 absY = itemY + y; 7430 if (this.opts.rightToLeftSubMenus && absX < winX) { 7431 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 7432 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 7433 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 7434 } 7435 if (!horizontalParent) { 7436 if (subH < winH && absY + subH > winY + winH) { 7437 y += winY + winH - subH - absY; 7438 } else if (subH >= winH || absY < winY) { 7439 y += winY - absY; 7440 } 7441 } 7442 // do we need scrolling? 7443 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 7444 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 7445 var self = this; 7446 if (!$sub.dataSM('scroll-arrows')) { 7447 $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]]) 7448 .bind({ 7449 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 7450 mouseleave: function(e) { 7451 self.menuScrollStop($sub); 7452 self.menuScrollOut($sub, e); 7453 }, 7454 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 7455 }) 7456 .insertAfter($sub) 7457 ); 7458 } 7459 // bind events to show/hide arrows on hover and save scrolling data for this sub 7460 var vportY = winY - (itemY + itemH); 7461 $sub.dataSM('scroll', { 7462 vportY: vportY, 7463 subH: subH, 7464 winH: winH, 7465 step: 1 7466 }) 7467 .bind({ 7468 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 7469 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 7470 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 7471 }) 7472 .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
7472StartZIndex() + this.zIndexInc }) 7473 .eq(0).css('margin-top', vportY).end() 7474 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 7475 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 7476 } 7477 } 7478 // if ($sub.hasClass('mega-menu-inner')) { 7479 // if ($('.menu-wrapper .megamenu-diff').length > 0) { 7480 // leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth()); 7481 // leftPos = -leftPos; 7482 // } else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft')); 7483 7484 // if ($('body.header-full-width').length > 0) { 7485 // $sub.css({ width: $('.box-container').width()}); 7486 // leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft'))); 7487 // } else $sub.css({ width: containerW}); 7488 // leftPos = leftPos + 'px'; 7489 7490 // } else { 7491 // leftPos = $li.position().left + 'px'; 7492 // } 7493 var rightPos = 'auto'; 7494 if ( $sub.parents('.isotope-filters').length ) { 7495 if ( $sub.parents('.text-right').eq(0).length ) { 7496 leftPos = '0px'; 7497 rightPos = 'auto'; 7498 } else { 7499 leftPos = 'auto'; 7500 rightPos = '0px'; 7501 } 7502 x = 0; 7503 } else { 7504 if ($sub.hasClass('mega-menu-inner')) { 7505 $sub.css({ width: containerW}); 7506 if ( $('body.hmenu-center-double').length ) { 7507 leftPos = '0px'; 7508 } else { 7509 if ( $('body.hmenu-center-split').length > 0 && !$sub.closest('.navbar-cta').length && ! $('body.hormenu-position-right').length ) { 7510 leftPos = - ($sub.closest('.menu-primary-inner')[0].offsetLeft) + 'px'; 7511 } else { 7512 if ( $sub.closest('.navbar-cta').length && !$('body.hmenu').length && !$('body.hmenu-center').length ) { 7513 leftPos = - ( parseFloat($sub.closest('.navbar-cta').offset().left) - parseFloat($sub.closest('.row-menu-inner').find('.logo-container').offset().left) ) + 'px'; 7514 } else if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0 && !$('body.hmenu-center-split').length) { 7515 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 7516 } else { 7517 leftPos = '0px'; 7518 } 7519 } 7520 } 7521 } else { 7522 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 7523 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 7524 } 7525 } 7526 7527 7528 $sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, right: rightPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) }); 7529 // IE iframe shim 7530 this.menuIframeShim($sub); 7531 if ($sub.dataSM('ie-shim')) { 7532 $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) }); 7533 } 7534 }, 7535 menuScroll: function($sub, up, wheel) { 7536 var y = parseFloat($sub.css('margin-top')), 7537 scroll = $sub.dataSM('scroll'), 7538 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 7539 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 7540 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 7541 y = parseFloat($sub.css('margin-top')); 7542 // show opposite arrow if appropriate 7543 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 7544 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 7545 } 7546 // accelerate when not using mousewheel to scroll 7547 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 7548 $sub.dataSM('scroll').step += 0.5; 7549 } 7550 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 7551 if (Math.abs(y - end) < 1) { 7552 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 7553 $sub.dataSM('scroll').step = 1; 7554 } else if (!wheel) { 7555 var self = this; 7556 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 7557 } 7558 }, 7559 menuScrollMousewheel: function($sub, e) { 7560 var $closestSub = $(e.target).closest('ul'); 7561 while ($closestSub.dataSM('in-mega')) { 7562 $closestSub = $closestSub.parent().closest('ul'); 7563 } 7564 if ($closestSub[0] == $sub[0]) { 7565 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 7566 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 7567 this.menuScroll($sub, up, true); 7568 } 7569 } 7570 e.preventDefault(); 7571 }, 7572 menuScrollOut: function($sub, e) { 7573 var reClass = /^scroll-(up|down)/, 7574 $closestSub = $(e.relatedTarget).closest('ul'); 7575 while ($closestSub.dataSM('in-mega')) { 7576 $closestSub = $closestSub.parent().closest('ul'); 7577 } 7578 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 7579 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 7580 } 7581 }, 7582 menuScrollOver: function($sub, e) { 7583 var reClass = /^scroll-(up|down)/, 7584 $closestSub = $(e.target).closest('ul'); 7585 while ($closestSub.dataSM('in-mega')) { 7586 $closestSub = $closestSub.parent().closest('ul'); 7587 } 7588 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 7589 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 7590 } 7591 }, 7592 menuScrollStop: function($sub) { 7593 if (this.scrollTimeout) { 7594 clearTimeout(this.scrollTimeout); 7595 this.scrollTimeout = 0; 7596 $sub.dataSM('scroll').step = 1; 7597 } 7598 }, 7599 menuShow: function($sub) { 7600 if (!$sub.dataSM('beforefirstshowfired')) { 7601 $sub.dataSM('beforefirstshowfired', true); 7602 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 7603 return; 7604 } 7605 } 7606 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 7607 return; 7608 } 7609 this.menuFixLayout($sub); 7610 $sub.stop(true, true); 7611 if (!$sub.is(':visible')) { 7612 $sub.css({ 7613 'visibility': 'visible', 7614 'pointer-events': 'auto', 7615 }); 7616 // set z-index - for IE < 9 set it to the parent LI
7617 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 7618 if (IElt9) { 7619 $sub.parent().css('z-index', zIndex); 7620 } else { 7621 $sub.css('z-index', zIndex); 7622 } 7623 // highlight parent item 7624 if (this.opts.keepHighlighted || this.isCollapsible()) { 7625 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 7626 $sub.dataSM('parent-a').addClass('highlighted'); 7627 } 7628 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 7629 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 7630 if (!IElt8) { 7631 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 7632 if (this.opts.subMenusMinWidth) { 7633 $sub.css('min-width', this.opts.subMenusMinWidth); 7634 } 7635 if (this.opts.subMenusMaxWidth) { 7636 var noMaxWidth = this.getWidth($sub); 7637 $sub.css('max-width', this.opts.subMenusMaxWidth); 7638 if (noMaxWidth > this.getWidth($sub)) { 7639 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 7640 } 7641 } 7642 // IE6,7 7643 } else { 7644 $sub.children().css('styleFloat', 'none'); 7645 if (IE6) { 7646 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 7647 .children().children('a').css('white-space', 'nowrap'); 7648 } else { // IE7 7649 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 7650 if (this.opts.subMenusMinWidth) { 7651 $sub.css('min-width', this.opts.subMenusMinWidth); 7652 } 7653 } 7654 if (this.opts.subMenusMaxWidth) { 7655 var noMaxWidth = $sub.width(); 7656 if (IE6) { 7657 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 7658 if (noMaxWidth > maxWidth) { 7659 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 7660 } else { 7661 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 7662 } 7663 } else { // IE7 7664 $sub.css('max-width', this.opts.subMenusMaxWidth); 7665 if (noMaxWidth > $sub.width()) { 7666 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 7667 } else { 7668 $sub.width(noMaxWidth); 7669 } 7670 } 7671 } else { 7672 $sub.width($sub.width()); 7673 } 7674 $sub.children().css('styleFloat', 'left'); 7675 } 7676 } 7677 this.menuPosition($sub); 7678 // insert IE iframe shim 7679 if ($sub.dataSM('ie-shim')) { 7680 $sub.dataSM('ie-shim').insertBefore($sub); 7681 } 7682 var complete = function() { 7683 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 7684 $sub.css('overflow', ''); 7685 }; 7686 // if sub is collapsible (mobile view) 7687 if (this.isCollapsible()) { 7688 if (this.opts.collapsibleShowFunction) { 7689 this.opts.collapsibleShowFunction.call(this, $sub, complete); 7690 } else { 7691 $sub.show(this.opts.collapsibleShowDuration, complete); 7692 } 7693 } else { 7694 if (this.opts.showFunction) { 7695 this.opts.showFunction.call(this, $sub, complete); 7696 } else { 7697 $sub.show(this.opts.showDuration, complete); 7698 } 7699 } 7700 // save new sub menu for this level 7701 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 7702 this.$root.triggerHandler('show.smapi', $sub[0]); 7703 } 7704 }, 7705 popupHide: function(noHideTimeout) { 7706 if (this.hideTimeout) { 7707 clearTimeout(this.hideTimeout); 7708 this.hideTimeout = 0; 7709 } 7710 var self = this; 7711 this.hideTimeout = setTimeout(function() { 7712 self.menuHideAll(); 7713 }, noHideTimeout ? 1 : this.opts.hideTimeout); 7714 }, 7715 popupShow: function(left, top) { 7716 if (!this.opts.isPopup) { 7717 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 7718 return; 7719 } 7720 if (this.hideTimeout) { 7721 clearTimeout(this.hideTimeout); 7722 this.hideTimeout = 0; 7723 } 7724 this.menuFixLayout(this.$root); 7725 this.$root.stop(true, true); 7726 if (!this.$root.is(':visible')) { 7727 this.$root.css({ left: left, top: top }); 7728 // IE iframe shim 7729 this.menuIframeShim(this.$root); 7730 if (this.$root.dataSM('ie-shim')) { 7731 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
7731: left, top: top }).insertBefore(this.$root); 7732 } 7733 // show menu 7734 if (this.opts.showFunction) { 7735 this.opts.showFunction.call(this, this.$root); 7736 } else { 7737 this.$root.show(this.opts.showDuration); 7738 } 7739 this.visibleSubMenus[0] = this.$root; 7740 } 7741 }, 7742 refresh: function() { 7743 this.menuHideAll(); 7744 this.$root.find('ul').each(function() { 7745 var $this = $(this); 7746 if ($this.dataSM('scroll-arrows')) { 7747 $this.dataSM('scroll-arrows').remove(); 7748 } 7749 }) 7750 .removeDataSM('in-mega') 7751 .removeDataSM('shown-before') 7752 .removeDataSM('ie-shim') 7753 .removeDataSM('scroll-arrows') 7754 .removeDataSM('parent-a') 7755 .removeDataSM('level') 7756 .removeDataSM('beforefirstshowfired'); 7757 this.$root.find('a.has-submenu').removeClass('has-submenu') 7758 .parent().removeDataSM('sub'); 7759 if (this.opts.subIndicators) { 7760 this.$root.find('span.sub-arrow').remove(); 7761 } 7762 if (this.opts.markCurrentItem) { 7763 this.$root.find('a.current').removeClass('current'); 7764 } 7765 this.subMenus = []; 7766 this.init(true); 7767 }, 7768 rootOut: function(e) { 7769 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 7770 return; 7771 } 7772 if (this.hideTimeout) { 7773 clearTimeout(this.hideTimeout); 7774 this.hideTimeout = 0; 7775 } 7776 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 7777 var self = this; 7778 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 7779 } 7780 }, 7781 rootOver: function(e) { 7782 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 7783 return; 7784 } 7785 if (this.hideTimeout) { 7786 clearTimeout(this.hideTimeout); 7787 this.hideTimeout = 0; 7788 } 7789 }, 7790 winResize: function(e) { 7791 if (!this.handleEvents()) { 7792 // we still need to resize the disable overlay if it's visible 7793 if (this.$disableOverlay) { 7794 var pos = this.$root.offset(); 7795 this.$disableOverlay.css({ 7796 top: pos.top, 7797 left: pos.left, 7798 width: this.$root.outerWidth(), 7799 height: this.$root.outerHeight() 7800 }); 7801 } 7802 return; 7803 } 7804 // hide sub menus on resize - on mobile do it only on orientation change 7805 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 7806 if (this.activatedItems.length) { 7807 this.activatedItems[this.activatedItems.length - 1][0].blur(); 7808 } 7809 this.menuHideAll(); 7810 } 7811 } 7812 } 7813 }); 7814 7815 $.fn.dataSM = function(key, val) { 7816 if (val) { 7817 return this.data(key + '_smartmenus', val); 7818 } 7819 return this.data(key + '_smartmenus'); 7820 } 7821 7822 $.fn.removeDataSM = function(key) { 7823 return this.removeData(key + '_smartmenus'); 7824 } 7825 7826 $.fn.smartmenus = function(options) { 7827 if (typeof options == 'string') { 7828 var args = arguments, 7829 method = options; 7830 Array.prototype.shift.call(args); 7831 return this.each(function() { 7832 var smartmenus = $(this).data('smartmenus'); 7833 if (smartmenus && smartmenus[method]) { 7834 smartmenus[method].apply(smartmenus, args); 7835 } 7836 }); 7837 } 7838 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 7839 return this.each(function() { 7840 new $.SmartMenus(this, opts); 7841 }); 7842 } 7843 7844 // default settings 7845 $.fn.smartmenus.defaults = { 7846 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 7847 mainMenuSubOffsetX: 0, // pixels offset from default position
7848 mainMenuSubOffsetY: 0, // pixels offset from default position 7849 subMenusSubOffsetX: 0, // pixels offset from default position 7850 subMenusSubOffsetY: 0, // pixels offset from default position 7851 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 7852 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 7853 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 7854 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 7855 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 7856 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 7857 scrollInterval: 30, // interval between each scrolling step 7858 scrollAccelerate: true, // accelerate scrolling or use a fixed step 7859 showTimeout: 250, // timeout before showing the sub menus 7860 hideTimeout: 500, // timeout before hiding the sub menus 7861 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 7862 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 7863 // don't forget to call complete() at the end of whatever you do 7864 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 7865 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 7866 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 7867 // don't forget to call complete() at the end of whatever you do 7868 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 7869 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 7870 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 7871 // (i.e. when mobile styles are used to make the sub menus collapsible) 7872 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 7873 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 7874 // (i.e. when mobile styles are used to make the sub menus collapsible) 7875 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 7876 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 7877 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 7878 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 7879 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 7880 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 7881 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 7882 bottomToTopSubMenus: false, // bottom to top display of the sub menus 7883 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 7884 }; 7885 7886})(jQuery); 7887 7888/* 7889 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/ 7890 * Open source under the BSD License. 7891 * Copyright © 2008 George McGinley Smith 7892 * All rights reserved. 7893 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE 7894*/ 7895 7896/* globals jQuery, define, module, require */ 7897(function (factory) { 7898 if (typeof define === "function" && define.amd) { 7899 define(['jquery'], function ($) { 7900 return factory($); 7901 }); 7902 } else if (typeof module === "object" && typeof module.exports === "object") { 7903 module.exports = factory(require('jquery')); 7904 } else { 7905 factory(jQuery); 7906 } 7907})(function($){ 7908 7909 // Preserve the original jQuery "swing" easing as "jswing" 7910 if (typeof $.easing !== 'undefined') { 7911 $.easing['jswing'] = $.easing['swing']; 7912 } 7913 7914 var pow = Math.pow, 7915 sqrt = Math.sqrt, 7916 sin = Math.sin, 7917 cos = Math.cos, 7918 PI = Math.PI,
7919 c1 = 1.70158, 7920 c2 = c1 * 1.525, 7921 c3 = c1 + 1, 7922 c4 = ( 2 * PI ) / 3, 7923 c5 = ( 2 * PI ) / 4.5; 7924 7925 // x is the fraction of animation progress, in the range 0..1 7926 function bounceOut(x) { 7927 var n1 = 7.5625, 7928 d1 = 2.75; 7929 if ( x < 1/d1 ) { 7930 return n1*x*x; 7931 } else if ( x < 2/d1 ) { 7932 return n1*(x-=(1.5/d1))*x + .75; 7933 } else if ( x < 2.5/d1 ) { 7934 return n1*(x-=(2.25/d1))*x + .9375; 7935 } else { 7936 return n1*(x-=(2.625/d1))*x + .984375; 7937 } 7938 } 7939 7940 $.extend( $.easing, { 7941 def: 'easeOutQuad', 7942 swing: function (x) { 7943 return $.easing[$.easing.def](x); 7944 }, 7945 easeInQuad: function (x) { 7946 return x * x; 7947 }, 7948 easeOutQuad: function (x) { 7949 return 1 - ( 1 - x ) * ( 1 - x ); 7950 }, 7951 easeInOutQuad: function (x) { 7952 return x < 0.5 ? 7953 2 * x * x : 7954 1 - pow( -2 * x + 2, 2 ) / 2; 7955 }, 7956 easeInCubic: function (x) { 7957 return x * x * x; 7958 }, 7959 easeOutCubic: function (x) { 7960 return 1 - pow( 1 - x, 3 ); 7961 }, 7962 easeInOutCubic: function (x) { 7963 return x < 0.5 ? 7964 4 * x * x * x : 7965 1 - pow( -2 * x + 2, 3 ) / 2; 7966 }, 7967 easeInQuart: function (x) { 7968 return x * x * x * x; 7969 }, 7970 easeOutQuart: function (x) { 7971 return 1 - pow( 1 - x, 4 ); 7972 }, 7973 easeInOutQuart: function (x) { 7974 return x < 0.5 ? 7975 8 * x * x * x * x : 7976 1 - pow( -2 * x + 2, 4 ) / 2; 7977 }, 7978 easeInQuint: function (x) { 7979 return x * x * x * x * x; 7980 }, 7981 easeOutQuint: function (x) { 7982 return 1 - pow( 1 - x, 5 ); 7983 }, 7984 easeInOutQuint: function (x) { 7985 return x < 0.5 ? 7986 16 * x * x * x * x * x : 7987 1 - pow( -2 * x + 2, 5 ) / 2; 7988 }, 7989 easeInSine: function (x) { 7990 return 1 - cos( x * PI/2 ); 7991 }, 7992 easeOutSine: function (x) { 7993 return sin( x * PI/2 ); 7994 }, 7995 easeInOutSine: function (x) { 7996 return -( cos( PI * x ) - 1 ) / 2; 7997 }, 7998 easeInExpo: function (x) { 7999 return x === 0 ? 0 : pow( 2, 10 * x - 10 ); 8000 }, 8001 easeOutExpo: function (x) { 8002 return x === 1 ? 1 : 1 - pow( 2, -10 * x ); 8003 }, 8004 easeInOutExpo: function (x) { 8005 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 8006 pow( 2, 20 * x - 10 ) / 2 : 8007 ( 2 - pow( 2, -20 * x + 10 ) ) / 2; 8008 }, 8009 easeInCirc: function (x) { 8010 return 1 - sqrt( 1 - pow( x, 2 ) ); 8011 }, 8012 easeOutCirc: function (x) { 8013 return sqrt( 1 - pow( x - 1, 2 ) ); 8014 }, 8015 easeInOutCirc: function (x) { 8016 return x < 0.5 ? 8017 ( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 : 8018 ( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2; 8019 }, 8020 easeInElastic: function (x) { 8021 return x === 0 ? 0 : x === 1 ? 1 : 8022 -pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 ); 8023 }, 8024 easeOutElastic: function (x) { 8025 return x === 0 ? 0 : x === 1 ? 1 : 8026 pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1; 8027 }, 8028 easeInOutElastic: function (x) { 8029 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 8030 -( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 : 8031 pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1; 8032 }, 8033 easeInBack: function (x) { 8034 return c3 * x * x * x - c1 * x * x; 8035 }, 8036 easeOutBack: function (x) { 8037 return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 ); 8038 }, 8039 easeInOutBack: function (x) { 8040 return x < 0.5 ? 8041 ( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 : 8042 ( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2; 8043 }, 8044 easeInBounce: function (x) { 8045 return 1 - bounceOut( 1 - x ); 8046 }, 8047 easeOutBounce: bounceOut, 8048 easeInOutBounce: function (x) { 8049 return x < 0.5 ? 8050 ( 1 - bounceOut( 1 - 2 * x ) ) / 2 : 8051 ( 1 + bounceOut( 2 * x - 1 ) ) / 2; 8052 } 8053 }); 8054 return $; 8055}); 8056 8057(function($, window, undefined) { 8058 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 8059 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 8060 8061 // requestAnimationFrame polyfill by Erik Möller 8062 // fixes from Paul Irish and Tino Zijdel 8063 8064 var lastTime = 0, 8065 running, 8066 animate = function (elem) { 8067 if (running) { 8068 window.requestAnimationFrame(animate, elem); 8069 jQuery.fx.tick(); 8070 } 8071 }, 8072 vendors = ['ms', 'moz', 'webkit', 'o']; 8073 8074 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 8075 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 8076 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 8077 || window[vendors[x]+'CancelRequestAnimationFrame']; 8078 } 8079 8080 if (!window.requestAnimationFrame) 8081 window.requestAnimationFrame = function(fn, element) { 8082 var currTime = new Date().getTime(), 8083 delta = currTime - lastTime, 8084 timeToCall = Math.max(0, 16 - delta); 8085 8086 var id = window.setTimeout(function() { 8087 fn(currTime + timeToCall); 8088 }, 8089 timeToCall 8090 ); 8091 8092 lastTime = currTime + timeToCall; 8093 8094 return id; 8095 }; 8096 8097 if (!window.cancelAnimationFrame) { 8098 window.cancelAnimationFrame = function(id) { 8099 clearTimeout(id); 8100 }; 8101 } 8102 8103 jQuery.fx.timer = function (timer) { 8104 if (timer() && jQuery.timers.push(timer) && !running) { 8105 running = true; 8106 animate(timer.elem); 8107 } 8108 }; 8109 8110 jQuery.fx.stop = function() { 8111 running = false;
8112 }; 8113 8114}(jQuery, this)); 8115/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 8116 * Licensed under the MIT License (LICENSE.txt). 8117 * 8118 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 8119 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 8120 * Thanks to: Seamus Leahy for adding deltaX and deltaY 8121 * 8122 * Version: 3.0.6 8123 * 8124 * Requires: 1.2.2+ 8125 */ 8126(function($) { 8127 var types = ['DOMMouseScroll', 'mousewheel']; 8128 if ($.event.fixHooks) { 8129 for (var i = types.length; i;) { 8130 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 8131 } 8132 } 8133 $.event.special.mousewheel = { 8134 setup: function() { 8135 if (this.addEventListener) { 8136 for (var i = types.length; i;) { 8137 this.addEventListener(types[--i], handler, false); 8138 } 8139 } else { 8140 this.onmousewheel = handler; 8141 } 8142 }, 8143 teardown: function() { 8144 if (this.removeEventListener) { 8145 for (var i = types.length; i;) { 8146 this.removeEventListener(types[--i], handler, false); 8147 } 8148 } else { 8149 this.onmousewheel = null; 8150 } 8151 } 8152 }; 8153 $.fn.extend({ 8154 mousewheel: function(fn) { 8155 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 8156 }, 8157 unmousewheel: function(fn) { 8158 return this.unbind("mousewheel", fn); 8159 } 8160 }); 8161 8162 function handler(event) { 8163 var orgEvent = event || window.event, 8164 args = [].slice.call(arguments, 1), 8165 delta = 0, 8166 returnValue = true, 8167 deltaX = 0, 8168 deltaY = 0; 8169 event = $.event.fix(orgEvent); 8170 event.type = "mousewheel"; 8171 // Old school scrollwheel delta 8172 if (orgEvent.wheelDelta) { 8173 delta = orgEvent.wheelDelta / 120; 8174 } 8175 if (orgEvent.detail) { 8176 delta = -orgEvent.detail / 3; 8177 } 8178 // New school multidimensional scroll (touchpads) deltas 8179 deltaY = delta; 8180 // Gecko 8181 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 8182 deltaY = 0; 8183 deltaX = -1 * delta; 8184 } 8185 // Webkit 8186 if (orgEvent.wheelDeltaY !== undefined) { 8187 deltaY = orgEvent.wheelDeltaY / 120; 8188 } 8189 if (orgEvent.wheelDeltaX !== undefined) { 8190 deltaX = -1 * orgEvent.wheelDeltaX / 120; 8191 } 8192 // Add event and delta to the front of the arguments 8193 args.unshift(event, delta, deltaX, deltaY); 8194 return ($.event.dispatch || $.event.handle).apply(this, args); 8195 } 8196})(jQuery); 8197/** 8198 * jQuery iLightBox - Revolutionary Lightbox Plugin 8199 * http://www.ilightbox.net/ 8200 * 8201 * @version: 2.2.4 - October 14, 2017 8202 * 8203 * @author: iProDev (Hemn Chawroka) 8204 * http://www.iprodev.com/ 8205 * 8206 */ 8207(function($, window, undefined) { 8208 8209 var extensions = { 8210 flash: ['swf'], 8211 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 8212 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 8213 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 8214 }, 8215 8216 // Global DOM elements 8217 $win = $(window), 8218 $doc = $(document), 8219 8220 // Support indicators 8221 browser, 8222 transform, 8223 gpuAcceleration, 8224 fullScreenApi = '', 8225 userAgent = navigator.userAgent || navigator.vendor || window.opera, 8226 supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1), 8227 ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1, 8228 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 )|
8228sy(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)), 8229 8230 // Events 8231 clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox", 8232 touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 8233 touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 8234 touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 8235 8236 // Math shorthands 8237 abs = Math.abs, 8238 sqrt = Math.sqrt, 8239 round = Math.round, 8240 max = Math.max, 8241 min = Math.min, 8242 floor = Math.floor, 8243 random = Math.random, 8244 8245 pluginspages = { 8246 quicktime: 'http://www.apple.com/quicktime/download', 8247 flash: 'http://www.adobe.com/go/getflash' 8248 }, 8249 8250 iLightBox = function(el, options, items, instant) { 8251 var iL = this; 8252 8253 iL.options = options, 8254 iL.selector = options.selector || el, 8255 iL.context = document, 8256 iL.instant = instant; 8257 8258 if (items.length < 1) iL.attachItems(); 8259 else iL.items = items; 8260 8261 iL.vars = { 8262 total: iL.items.length, 8263 start: 0, 8264 current: null, 8265 next: null, 8266 prev: null, 8267 BODY: $('body'), 8268 loadRequests: 0, 8269 overlay: $('<div class="ilightbox-overlay"></div>'), 8270 loader: $('<div class="ilightbox-loader"><div></div></div>'), 8271 toolbar: $('<div class="ilightbox-toolbar"></div>'), 8272 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 8273 title: $('<div class="ilightbox-title"></div>'), 8274 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 8275 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 8276 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 8277 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 8278 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 8279 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 8280 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 8281 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 8282 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 8283 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'), 8284 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>'), 8285 thumbs: false, 8286 nextLock: false, 8287 prevLock: false, 8288 hashLock: false, 8289 isMobile: false, 8290 mobileMaxWidth: 980, 8291 isInFullScreen: false, 8292 isSwipe: false, 8293 mouseID: 0, 8294 cycleID: 0, 8295 isPaused: 0, 8296 captionHeight: 39, 8297 }; 8298 8299 // Hideable elements with mousemove event 8300 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 8301 8302 iL.normalizeItems(); 8303 8304 //Check necessary plugins 8305 iL.availPlugins(); 8306 8307 //Set startFrom 8308 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 8309 8310 //If randomStart 8311 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 8312 iL.vars.start = iL.options.startFrom; 8313 8314 if (instant) iL.instantCall(); 8315 else iL.patchItemsEvents(); 8316 8317 if (iL.options.linkId) { 8318 iL.hashChangeHandler(); 8319 $win.iLightBoxHashChange(function() { 8320 iL.hashChangeHandler(); 8321 }); 8322 } 8323 8324 if (supportTouch) {
8325 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 8326 replace = "itap"; 8327 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 8328 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 8329 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 8330 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 8331 } 8332 8333 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 8334 $.extend(iL.options.styles, { 8335 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 8336 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 8337 nextOpacity: 0, 8338 prevOpacity: 0 8339 }); 8340 } 8341 }; 8342 8343 //iLightBox helpers 8344 iLightBox.prototype = { 8345 showLoader: function() { 8346 var iL = this; 8347 iL.vars.loadRequests += 1; 8348 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 8349 //top: '-30px' 8350 opacity: '1' 8351 }, iL.options.show.speed, 'easeOutCirc'); 8352 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 8353 //left: '-30px' 8354 opacity: '1' 8355 }, iL.options.show.speed, 'easeOutCirc'); 8356 }, 8357 8358 hideLoader: function() { 8359 var iL = this; 8360 iL.vars.loadRequests -= 1; 8361 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 8362 if (iL.options.path.toLowerCase() == "horizontal") { 8363 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 8364 //top: '-192px' 8365 opacity: '0' 8366 }, iL.options.show.speed, 'easeInCirc'); 8367 } else { 8368 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 8369 //left: '-192px' 8370 opacity: '0' 8371 }, iL.options.show.speed, 'easeInCirc'); 8372 } 8373 }, 8374 8375 createUI: function() { 8376 var iL = this; 8377 8378 iL.ui = { 8379 currentElement: iL.vars.holder, 8380 nextElement: iL.vars.nextPhoto, 8381 prevElement: iL.vars.prevPhoto, 8382 currentItem: iL.vars.current, 8383 nextItem: iL.vars.next, 8384 prevItem: iL.vars.prev, 8385 hide: function() { 8386 iL.closeAction(); 8387 }, 8388 refresh: function() { 8389 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 8390 }, 8391 fullscreen: function() { 8392 iL.fullScreenAction(); 8393 } 8394 }; 8395 }, 8396 8397 attachItems: function() { 8398 var iL = this, 8399 itemsObject = new Array(), 8400 items = new Array(); 8401 8402 $(iL.selector, iL.context).each(function() { 8403 var t = $(this), 8404 URL = t.attr(iL.options.attr) || null, 8405 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 8406 caption = t.data('caption'), 8407 title = t.data('title'), 8408 type = t.data('type') || getTypeByExtension(URL), 8409 clone = t.data('lbox-clone') || false; 8410 8411 //Uncode addition ##START## 8412 if (type === false) { 8413 return; 8414 } 8415 //Uncode addition ##END## 8416 8417 if (t.data('lbox-clone') != undefined) return; 8418 8419 //Uncode addition ##START## 8420 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 8421 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 8422 URL_i, 8423 URLS_LENGHT = ALBUM_URLS.length; 8424 8425 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 8426 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 8427 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 8428 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 8429 items.push({ 8430 URL: ALBUM_URLS[URL_i].url, 8431 caption: ALBUM_URLS[URL_i].caption, 8432 title: ALBUM_URLS[URL_i].title, 8433 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 8434 options: item_opts, 8435 clone: clone 8436 }); 8437 var newT = t; 8438 newT.attr('href',ALBUM_URLS[URL_i].url); 8439 if (!iL.instant) itemsObject.push(newT); 8440 } 8441 } 8442 } else { 8443 //Uncode addition ##END## 8444 items.push({ 8445 URL: URL, 8446 caption: caption, 8447 title: title, 8448 type: type, 8449 options: options, 8450 clone: clone 8451 }); 8452 } 8453 8454 8455 if (iL.vars != undefined) iL.vars.total = items.length; 8456 8457 if (!iL.instant) itemsObject.push(t); 8458 }); 8459 8460 iL.items = items, 8461 iL.itemsObject = itemsObject; 8462 8463 }, 8464 8465 normalizeItems: function() { 8466 var iL = this, 8467 newItems = new Array(); 8468 8469 $.each(iL.items, function(key, val) { 8470 8471 if (typeof val == "string") val = { 8472 url: val 8473 }; 8474 8475 var URL = val.url || val.URL || null, 8476 options = val.options || {}, 8477 caption = val.caption || null, 8478 title = val.title || null, 8479 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 8480 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 8481 8482 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
8483 options.videoType = options.videoType || null, 8484 options.skin = options.skin || iL.options.skin, 8485 options.width = options.width || null, 8486 options.height = options.height || null, 8487 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 8488 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 8489 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 8490 8491 if (type == "video") { 8492 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 8493 8494 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 8495 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 8496 options.html5video.preload = options.html5video.preload || "metadata"; 8497 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 8498 //UNCODE addition 8499 options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false; 8500 } 8501 8502 if (!options.width || !options.height) { 8503 if (type == "video") options.width = 1280, options.height = 720; 8504 else if (type == "iframe") options.width = '100%', options.height = '90%'; 8505 else if (type == "flash") options.width = 1280, options.height = 720; 8506 } 8507 8508 delete val.url; 8509 val.index = key; 8510 val.URL = URL; 8511 val.caption = caption; 8512 val.title = title; 8513 val.type = type; 8514 val.options = options; 8515 val.ext = ext; 8516 8517 newItems.push(val); 8518 }); 8519 8520 iL.items = newItems; 8521 }, 8522 8523 instantCall: function() { 8524 var iL = this, 8525 key = iL.vars.start; 8526 8527 iL.vars.current = key; 8528 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 8529 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 8530 8531 iL.addContents(); 8532 iL.patchEvents(); 8533 }, 8534 8535 addContents: function() { 8536 var iL = this, 8537 vars = iL.vars, 8538 opts = iL.options, 8539 viewport = getViewport(), 8540 path = opts.path.toLowerCase(), 8541 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 8542 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 8543 }), 8544 needRecognition = recognizingItems.length > 0; 8545 8546 if (opts.mobileOptimizer && !opts.innerToolbar) 8547 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 8548 8549 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 8550 8551 if (opts.linkId) 8552 vars.overlay[0].setAttribute('linkid', opts.linkId); 8553 8554 //Add Toolbar Buttons 8555 if (opts.controls.toolbar) { 8556 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 8557 if (opts.controls.fullscreen) 8558 vars.toolbar.append(vars.fullScreenButton); 8559 if (opts.controls.slideshow) 8560 vars.toolbar.append(vars.innerPlayButton); 8561 if (vars.total > 1) 8562 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 8563 } 8564 8565 //Append elements to body 8566 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 8567 8568 if (!opts.innerToolbar) 8569 vars.BODY.append(vars.toolbar); 8570 if (opts.controls.arrows) 8571 vars.BODY.append(vars.nextButton).append(vars.prevButton); 8572 8573 if (opts.controls.thumbnail && vars.total > 1) { 8574 vars.BODY.append(vars.thumbnails); 8575 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 8576 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 8577 vars.thumbs = true; 8578 } 8579 8580 //Configure loader and arrows 8581 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 8582 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 8583 } : { 8584 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 8585 }; 8586 vars.loader.addClass(opts.skin).css(loaderCss); 8587 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 8588 if (path == "horizontal") 8589 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 8590 8591 // Configure arrow buttons 8592 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 8593 8594 if (!opts.infinite) { 8595 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8596 8597 if (vars.current == 0) 8598 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8599 if (vars.current >= vars.total - 1) 8600 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8601 } 8602 8603 if (opts.show.effect) { 8604 vars.overlay.stop().fadeIn(opts.show.speed); 8605 vars.toolbar.stop().fadeIn(opts.show.speed); 8606 } else { 8607 vars.overlay.show(); 8608 vars.toolbar.show(); 8609 } 8610 8611 var length = recognizingItems.length; 8612 if (needRecognition) { 8613 iL.showLoader(); 8614 8615 $.each(recognizingItems, function(key, val) { 8616 var resultFnc = function(result) { 8617 var key = -1, 8618 filter = iL.items.filter(function(e, i, arr) { 8619 if (e.URL == result.url) 8620 key = i; 8621 8622 return e.URL == result.url; 8623 }), 8624 self = iL.items[key]; 8625 8626 if (result) 8627 $.extend(true, self, { 8628 URL: result.source, 8629 type: result.type, 8630 recognized: true, 8631 options: { 8632 html5video: result.html5video, 8633 width: (result.type == "image") ? 0 : (result.width || self.width), 8634 height: (result.type == "image") ? 0 : (result.height || self.height), 8635 thumbnail: self.options.thumbnail || result.thumbnail 8636 } 8637 }); 8638 8639 length--; 8640 8641 if (length == 0) { 8642 iL.hideLoader(); 8643 8644 vars.dontGenerateThumbs = false;
8645 iL.generateThumbnails(); 8646 8647 if (opts.show.effect) 8648 setTimeout(function() { 8649 iL.generateBoxes(); 8650 }, opts.show.speed); 8651 else 8652 iL.generateBoxes(); 8653 } 8654 }; 8655 8656 iL.ogpRecognition(this, resultFnc); 8657 }); 8658 } 8659 else { 8660 if (opts.show.effect) 8661 setTimeout(function() { 8662 iL.generateBoxes(); 8663 }, opts.show.speed); 8664 else 8665 iL.generateBoxes(); 8666 } 8667 8668 iL.createUI(); 8669 8670 window.iLightBox = { 8671 close: function() { 8672 iL.closeAction(); 8673 }, 8674 fullscreen: function() { 8675 iL.fullScreenAction(); 8676 }, 8677 moveNext: function() { 8678 iL.moveTo('next'); 8679 }, 8680 movePrev: function() { 8681 iL.moveTo('prev'); 8682 }, 8683 goTo: function(index) { 8684 iL.goTo(index); 8685 }, 8686 refresh: function() { 8687 iL.refresh(); 8688 }, 8689 reposition: function() { 8690 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 8691 }, 8692 setOption: function(options) { 8693 iL.setOption(options); 8694 }, 8695 destroy: function() { 8696 iL.closeAction(); 8697 iL.dispatchItemsEvents(); 8698 } 8699 }; 8700 8701 if (opts.linkId) { 8702 vars.hashLock = true; 8703 window.location.hash = opts.linkId + '/' + vars.current; 8704 setTimeout(function() { 8705 vars.hashLock = false; 8706 }, 55); 8707 } 8708 8709 if (!opts.slideshow.startPaused) { 8710 iL.resume(); 8711 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 8712 } 8713 8714 //Trigger the onOpen callback 8715 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 8716 }, 8717 8718 loadContent: function(obj, opt, speed) { 8719 var iL = this, 8720 holder, item; 8721 8722 iL.createUI(); 8723 8724 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 8725 8726 if (opt == 'current') { 8727 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 8728 else iL.vars.lockWheel = false; 8729 8730 if (!obj.options.swipe) iL.vars.lockSwipe = true; 8731 else iL.vars.lockSwipe = false; 8732 } 8733 8734 switch (opt) { 8735 case 'current': 8736 holder = iL.vars.holder, item = iL.vars.current; 8737 break; 8738 case 'next': 8739 holder = iL.vars.nextPhoto, item = iL.vars.next; 8740 break; 8741 case 'prev': 8742 holder = iL.vars.prevPhoto, item = iL.vars.prev; 8743 break; 8744 } 8745 8746 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 8747 $('div.ilightbox-inner-toolbar', holder).remove(); 8748 8749 if (obj.title || iL.options.innerToolbar) { 8750 var innerToolbar = iL.vars.innerToolbar.clone(); 8751 if (obj.title && iL.options.show.title) { 8752 var title = iL.vars.title.clone(); 8753 title.empty().html(obj.title); 8754 innerToolbar.append(title); 8755 } 8756 if (iL.options.innerToolbar) { 8757 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 8758 } 8759 holder.prepend(innerToolbar); 8760 } 8761 8762 //console.warn('loadContent', arguments); 8763 8764 iL.loadSwitcher(obj, holder, item, opt); 8765 }, 8766 8767 loadSwitcher: function(obj, holder, item, opt) { 8768 var iL = this, 8769 opts = iL.options, 8770 api = { 8771 element: holder, 8772 position: item 8773 }; 8774 8775 switch (obj.type) { 8776 case 'image': 8777 //Trigger the onBeforeLoad callback 8778 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 8779 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 8780 8781 iL.loadImage(obj.URL, function(img) { 8782 //Trigger the onAfterLoad callback 8783 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 8784 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 8785 8786 var width = (img) ? img.width : 400, 8787 height = (img) ? img.height : 200; 8788 8789 holder.data({ 8790 naturalWidth: width, 8791 naturalHeight: height 8792 }); 8793 8794 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 8795 8796 //Trigger the onRender callback 8797 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 8798 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 8799 8800 iL.configureHolder(obj, opt, holder); 8801 }); 8802 8803 break; 8804
8805 case 'video': 8806 holder.data({ 8807 naturalWidth: obj.options.width, 8808 naturalHeight: obj.options.height 8809 }); 8810 8811 if (opt === 'current') { 8812 iL.addContent(holder, obj); 8813 8814 //Trigger the onRender callback 8815 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 8816 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 8817 } else { 8818 $('div.ilightbox-container', holder).empty(); 8819 } 8820 8821 iL.configureHolder(obj, opt, holder); 8822 8823 break; 8824 8825 case 'iframe': 8826 //iL.showLoader(); 8827 holder.data({ 8828 naturalWidth: obj.options.width, 8829 naturalHeight: obj.options.height 8830 }); 8831 8832 iL.configureHolder(obj, opt, holder); 8833 8834 if (opt === 'current') { 8835 var el = iL.addContent(holder, obj); 8836 8837 //Trigger the onRender callback 8838 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 8839 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 8840 8841 //Trigger the onBeforeLoad callback 8842 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 8843 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 8844 8845 el.bind('load', function() { 8846 //Trigger the onAfterLoad callback 8847 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 8848 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 8849 8850 //iL.hideLoader(); 8851 el.unbind('load'); 8852 }); 8853 } else { 8854 $('div.ilightbox-container', holder).empty(); 8855 } 8856 8857 break; 8858 8859 case 'inline': 8860 var el = $(obj.URL), 8861 content = iL.addContent(holder, obj), 8862 images = findImageInElement(holder); 8863 8864 holder.data({ 8865 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 8866 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 8867 }); 8868 content.children().eq(0).show(); 8869 8870 //Trigger the onRender callback 8871 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 8872 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 8873 8874 //Trigger the onBeforeLoad callback 8875 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 8876 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 8877 8878 iL.loadImage(images, function() { 8879 //Trigger the onAfterLoad callback 8880 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 8881 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 8882 8883 iL.configureHolder(obj, opt, holder); 8884 }); 8885 8886 break; 8887 8888 case 'flash': 8889 var el = iL.addContent(holder, obj); 8890 8891 holder.data({ 8892 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 8893 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 8894 }); 8895 8896 //Trigger the onRender callback 8897 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 8898 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 8899 8900 iL.configureHolder(obj, opt, holder); 8901 8902 break; 8903 8904 case 'ajax': 8905 var ajax = obj.options.ajax || {}; 8906 //Trigger the onBeforeLoad callback 8907 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 8908 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 8909 8910 iL.showLoader(); 8911 $.ajax({ 8912 url: obj.URL || opts.ajaxSetup.url, 8913 data: ajax.data || null, 8914 dataType: ajax.dataType || "html", 8915 type: ajax.type || opts.ajaxSetup.type, 8916 cache: ajax.cache || opts.ajaxSetup.cache, 8917 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 8918 global: ajax.global || opts.ajaxSetup.global, 8919 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 8920 username: ajax.username || opts.ajaxSetup.username, 8921 password: ajax.password || opts.ajaxSetup.password, 8922 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 8923 complete: ajax.complete || opts.ajaxSetup.complete, 8924 success: function(data, textStatus, jqXHR) { 8925 iL.hideLoader(); 8926 8927 var el = $(data), 8928 container = $('div.ilightbox-container', holder), 8929 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 8930 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 8931 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 8932 'overflow': 'hidden' 8933 } : {}; 8934 8935 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 8936 holder.show().data({
8937 naturalWidth: (elWidth || container.outerWidth()), 8938 naturalHeight: (elHeight || container.outerHeight()) 8939 }).hide(); 8940 8941 //Trigger the onRender callback 8942 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 8943 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 8944 8945 var images = findImageInElement(holder); 8946 iL.loadImage(images, function() { 8947 //Trigger the onAfterLoad callback 8948 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 8949 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 8950 8951 iL.configureHolder(obj, opt, holder); 8952 }); 8953 8954 opts.ajaxSetup.success(data, textStatus, jqXHR); 8955 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 8956 }, 8957 error: function(jqXHR, textStatus, errorThrown) { 8958 //Trigger the onAfterLoad callback 8959 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 8960 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 8961 8962 iL.hideLoader(); 8963 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 8964 iL.configureHolder(obj, opt, holder); 8965 8966 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 8967 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 8968 } 8969 }); 8970 8971 break; 8972 8973 case 'html': 8974 var object = obj.URL, 8975 el 8976 container = $('div.ilightbox-container', holder); 8977 8978 if (object[0].nodeName) el = object.clone(); 8979 else { 8980 var dom = $(object); 8981 if (dom.selector) el = $('<div>' + dom + '</div>'); 8982 else el = dom; 8983 } 8984 8985 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 8986 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 8987 8988 iL.addContent(holder, obj); 8989 8990 el.appendTo(document.documentElement).hide(); 8991 8992 //Trigger the onRender callback 8993 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 8994 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 8995 8996 var images = findImageInElement(holder); 8997 8998 //Trigger the onBeforeLoad callback 8999 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 9000 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 9001 9002 iL.loadImage(images, function() { 9003 //Trigger the onAfterLoad callback 9004 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 9005 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 9006 9007 holder.show().data({ 9008 naturalWidth: (elWidth || container.outerWidth()), 9009 naturalHeight: (elHeight || container.outerHeight()) 9010 }).hide(); 9011 el.remove(); 9012 9013 iL.configureHolder(obj, opt, holder); 9014 }); 9015 9016 break; 9017 } 9018 }, 9019 9020 configureHolder: function(obj, opt, holder) { 9021 var iL = this, 9022 vars = iL.vars, 9023 opts = iL.options; 9024 9025 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 9026 9027 if (opt == "current") 9028 var item = vars.current; 9029 else if (opt == "next") 9030 var opacity = opts.styles.nextOpacity, 9031 item = vars.next; 9032 else 9033 var opacity = opts.styles.prevOpacity, 9034 item = vars.prev; 9035 9036 var api = { 9037 element: holder, 9038 position: item 9039 }; 9040 9041 iL.items[item].options.width = iL.items[item].options.width || 0, 9042 iL.items[item].options.height = iL.items[item].options.height || 0; 9043 9044 if (opt == "current") { 9045 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 9046 holder.css(transform, ''); 9047 if (obj.caption) { 9048 iL.setCaption(obj, holder); 9049 var caption = $('div.ilightbox-caption', holder), 9050 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 9051 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
9051Speed); 9052 } 9053 9054 var social = obj.options.social; 9055 if (social) { 9056 iL.setSocial(social, obj.URL, holder); 9057 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 9058 } 9059 9060 //Generate thumbnails 9061 iL.generateThumbnails(); 9062 9063 //Trigger the onShow callback 9064 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 9065 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 9066 }); 9067 else { 9068 holder.show(); 9069 9070 //Generate thumbnails 9071 iL.generateThumbnails(); 9072 9073 //Trigger the onShow callback 9074 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 9075 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 9076 } 9077 } else { 9078 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 9079 if (opt == "next") vars.nextLock = false; 9080 else vars.prevLock = false; 9081 9082 //Generate thumbnails 9083 iL.generateThumbnails(); 9084 9085 //Trigger the onShow callback 9086 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 9087 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 9088 }); 9089 else { 9090 holder.css({ 9091 opacity: opacity 9092 }).show(); 9093 if (opt == "next") vars.nextLock = false; 9094 else vars.prevLock = false; 9095 9096 //Generate thumbnails 9097 iL.generateThumbnails(); 9098 9099 //Trigger the onShow callback 9100 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 9101 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 9102 } 9103 } 9104 9105 setTimeout(function() { 9106 iL.repositionPhoto(); 9107 }, 0); 9108 }, 9109 9110 generateBoxes: function() { 9111 var iL = this, 9112 vars = iL.vars, 9113 opts = iL.options; 9114 9115 if (opts.infinite && vars.total >= 3) { 9116 if (vars.current == vars.total - 1) vars.next = 0; 9117 if (vars.current == 0) vars.prev = vars.total - 1; 9118 } else opts.infinite = false; 9119 9120 //UNCODE addition 9121 if ( typeof iL.items[vars.current] == 'undefined' ) 9122 vars.current = 0; 9123 9124 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 9125 9126 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 9127 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 9128 }, 9129 9130 generateThumbnails: function() { 9131 var iL = this, 9132 vars = iL.vars, 9133 opts = iL.options, 9134 timeOut = null; 9135 9136 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 9137 var thumbnails = vars.thumbnails, 9138 container = $('div.ilightbox-thumbnails-container', thumbnails), 9139 grid = $('div.ilightbox-thumbnails-grid', container), 9140 i = 0; 9141 9142 grid.removeAttr('style').empty(); 9143 9144 $.each(iL.items, function(key, val) { 9145 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 9146 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 9147 thumb = val.options.thumbnail, 9148 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 9149 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 9150 9151 thumbnail.css({ 9152 opacity: 0 9153 }).addClass(isActive); 9154 9155 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 9156 icon.addClass('ilightbox-thumbnail-video'); 9157 thumbnail.append(icon); 9158 } else if (val.options.icon) { 9159 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 9160 thumbnail.append(icon); 9161 } 9162 9163 if (thumb) iL.loadImage(thumb, function(img) { 9164 i++; 9165 if (img) thumbnail.data({ 9166 naturalWidth: img.width, 9167 naturalHeight: img.height 9168 }).append('<img src="' + thumb + '" border="0" />'); 9169 else thumbnail.data({ 9170 naturalWidth: opts.thumbnails.maxWidth, 9171 naturalHeight: opts.thumbnails.maxHeight 9172 }); 9173 9174 clearTimeout(timeOut); 9175 timeOut = setTimeout(function() { 9176 iL.positionThumbnails(thumbnails, container, grid); 9177 }, 20); 9178 setTimeout(function() { 9179 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 9180 }, i * 20); 9181 }); 9182 9183 grid.append(thumbnail); 9184 }); 9185 iL.vars.dontGenerateThumbs = true; 9186 } 9187 }, 9188
9189 positionThumbnails: function(thumbnails, container, grid) { 9190 var iL = this, 9191 vars = iL.vars, 9192 opts = iL.options, 9193 viewport = getViewport(), 9194 path = opts.path.toLowerCase(); 9195 9196 if (!thumbnails) thumbnails = vars.thumbnails; 9197 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 9198 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 9199 9200 var thumbs = $('.ilightbox-thumbnail', grid), 9201 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 9202 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 9203 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 9204 gridHeight = (path == 'horizontal') ? heightAvail : 0, 9205 active = $('.ilightbox-active', grid), 9206 gridCss = {}, 9207 css = {}; 9208 9209 if (arguments.length < 3) { 9210 thumbs.css({ 9211 opacity: opts.thumbnails.normalOpacity 9212 }); 9213 active.css({ 9214 opacity: opts.thumbnails.activeOpacity 9215 }); 9216 } 9217 9218 thumbs.each(function(i) { 9219 var t = $(this), 9220 data = t.data(), 9221 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 9222 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 9223 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 9224 9225 t.css({ 9226 width: dims.width, 9227 height: dims.height 9228 }); 9229 if (path == 'horizontal') t.css({ 9230 'float': 'left' 9231 }); 9232 9233 (path == 'horizontal') ? ( 9234 gridWidth += t.outerWidth() 9235 ) : ( 9236 gridHeight += t.outerHeight() 9237 ); 9238 }); 9239 9240 gridCss = { 9241 width: gridWidth, 9242 height: gridHeight 9243 }; 9244 9245 grid.css(gridCss); 9246 9247 gridCss = {}; 9248 9249 var gridOffset = grid.offset(), 9250 activeOffset = (active.length) ? active.offset() : { 9251 top: parseInt(heightAvail / 2), 9252 left: parseInt(widthAvail / 2) 9253 }; 9254 9255 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 9256 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 9257 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 9258 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 9259 9260 (path == 'horizontal') ? ( 9261 gridCss.top = 0, 9262 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 9263 ) : ( 9264 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 9265 gridCss.left = 0 9266 ); 9267 9268 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 9269 else grid.css(gridCss); 9270 }, 9271 9272 loadImage: function(image, callback) { 9273 if (!$.isArray(image)) image = [image]; 9274 9275 var iL = this, 9276 length = image.length; 9277 9278 if (length > 0) { 9279 iL.showLoader(); 9280 $.each(image, function(index, value) { 9281 var img = new Image(); 9282 img.onload = function() { 9283 length -= 1; 9284 if (length == 0) { 9285 iL.hideLoader(); 9286 callback(img); 9287 } 9288 }; 9289 img.onerror = img.onabort = function() { 9290 length -= 1; 9291 if (length == 0) { 9292 iL.hideLoader(); 9293 callback(false); 9294 } 9295 }; 9296 img.src = image[index]; 9297 }); 9298 } else callback(false); 9299 }, 9300 9301 patchItemsEvents: function() { 9302 var iL = this, 9303 vars = iL.vars, 9304 clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL", 9305 vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL"; 9306 9307 if (iL.context && iL.selector) { 9308 var $items = $(iL.selector, iL.context); 9309 9310 $(iL.context).on(clickEvent, iL.selector, function() { 9311 var $this = $(this), 9312 //UNCODE addition 9313 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 9314 if (UNCODE.isMobile) { 9315 var isCarousel = $this.closest('.owl-carousel'); 9316 if (isCarousel.length) { 9317 if (isCarousel.hasClass('owl-translating')) return false; 9318 } 9319 } 9320 9321 vars.current = key; 9322 vars.next = iL.items[key + 1] ? key + 1 : null; 9323 vars.prev = iL.items[key - 1] ? key - 1 : null; 9324 9325 //UNCODE addition 9326 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 9327 return false;
9328 9329 iL.addContents(); 9330 iL.patchEvents(); 9331 9332 return false; 9333 }).on(vEvent, iL.selector, function() { 9334 return false; 9335 }); 9336 } else 9337 $.each(iL.itemsObject, function(key, val) { 9338 val.on(clickEvent, function() { 9339 vars.current = key; 9340 vars.next = iL.items[key + 1] ? key + 1 : null; 9341 vars.prev = iL.items[key - 1] ? key - 1 : null; 9342 9343 iL.addContents(); 9344 iL.patchEvents(); 9345 9346 return false; 9347 }).on(vEvent, function() { 9348 return false; 9349 }); 9350 }); 9351 }, 9352 9353 dispatchItemsEvents: function() { 9354 var iL = this, 9355 vars = iL.vars, 9356 opts = iL.options; 9357 9358 if (iL.context && iL.selector) 9359 $(iL.context).off('.iL', iL.selector); 9360 else 9361 $.each(iL.itemsObject, function(key, val) { 9362 val.off('.iL'); 9363 }); 9364 }, 9365 9366 refresh: function() { 9367 var iL = this; 9368 9369 iL.dispatchItemsEvents(); 9370 iL.attachItems(); 9371 iL.normalizeItems(); 9372 iL.patchItemsEvents(); 9373 }, 9374 9375 patchEvents: function() { 9376 var iL = this, 9377 vars = iL.vars, 9378 opts = iL.options, 9379 path = opts.path.toLowerCase(), 9380 holders = $('.ilightbox-holder'), 9381 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 9382 durationThreshold = 1000, 9383 horizontalDistanceThreshold = 9384 verticalDistanceThreshold = 100, 9385 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 9386 9387 $win.bind('resize.iLightBox', function() { 9388 var viewport = getViewport(); 9389 9390 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 9391 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 9392 9393 iL.repositionPhoto(null); 9394 if (supportTouch) { 9395 clearTimeout(vars.setTime); 9396 vars.setTime = setTimeout(function() { 9397 var scrollTop = getScrollXY().y; 9398 window.scrollTo(0, scrollTop - 30); 9399 window.scrollTo(0, scrollTop + 30); 9400 window.scrollTo(0, scrollTop); 9401 }, 2000); 9402 } 9403 if (vars.thumbs) iL.positionThumbnails(); 9404 }).bind('keydown.iLightBox', function(event) { 9405 if (opts.controls.keyboard) { 9406 switch (event.keyCode) { 9407 case 13: 9408 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 9409 break; 9410 case 27: 9411 if (opts.keyboard.esc) iL.closeAction(); 9412 break; 9413 case 37: 9414 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 9415 break; 9416 case 38: 9417 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 9418 break; 9419 case 39: 9420 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 9421 break; 9422 case 40: 9423 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 9424 break; 9425 } 9426 } 9427 }); 9428 9429 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 9430 iL.doFullscreen(); 9431 }); 9432 9433 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 9434 return arr.lastIndexOf(e) === i; 9435 }), 9436 holderEvents = ""; 9437 9438 $.each(holderEventsArr, function(key, val) { 9439 if (key != 0) holderEvents += ' '; 9440 holderEvents += val; 9441 }); 9442 9443 $doc.on(clickEvent, '.ilightbox-overlay', function() { 9444 if (opts.overlay.blur) iL.closeAction(); 9445 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 9446 iL.moveTo('next'); 9447 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 9448 iL.moveTo('prev'); 9449 }).on(clickEvent, '.ilightbox-thumbnail', function() { 9450 var t = $(this), 9451 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 9452 index = thumbs.index(t); 9453 9454 if (index != vars.current) iL.goTo(index); 9455 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 9456 var caption = $('div.ilightbox-caption', vars.holder), 9457 social = $('div.ilightbox-social', vars.holder), 9458 fadeSpeed = opts.effects.fadeSpeed; 9459 9460 if (vars.nextLock || vars.prevLock) { 9461 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 9462 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 9463 9464 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 9465 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 9466 } else { 9467 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 9468 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 9469 9470 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 9471 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 9472 } 9473 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 9474 if (e.type == 'mouseenter') vars.lockWheel = true; 9475 else vars.lockWheel = false;
9476 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 9477 var t = $(this); 9478 9479 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 9480 else if (t.hasClass('ilightbox-play')) { 9481 iL.resume(); 9482 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 9483 } else if (t.hasClass('ilightbox-pause')) { 9484 iL.pause(); 9485 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 9486 } else iL.closeAction(); 9487 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 9488 // prevent scrolling 9489 e.preventDefault(); 9490 }); 9491 9492 function mouseMoveHandler(e) { 9493 if (!vars.isMobile) { 9494 if (!vars.mouseID) { 9495 vars.hideableElements.show(); 9496 } 9497 9498 vars.mouseID = clearTimeout(vars.mouseID); 9499 9500 if (buttonsArray.indexOf(e.target) === -1) 9501 vars.mouseID = setTimeout(function() { 9502 vars.hideableElements.hide(); 9503 vars.mouseID = clearTimeout(vars.mouseID); 9504 }, 3000); 9505 } 9506 } 9507 9508 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 9509 9510 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 9511 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 9512 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 9513 }); 9514 9515 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'), 9516 delay = false; 9517 9518 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 9519 event.preventDefault(); 9520 if (delay) return; 9521 delay = true; 9522 if (!vars.lockWheel) { 9523 event.preventDefault(); 9524 if (delta < 0) { 9525 iL.moveTo('next'); 9526 } else if (delta > 0) { 9527 iL.moveTo('prev'); 9528 } 9529 } 9530 setTimeout(function(){
9531 delay = false; 9532 }, 2000); 9533 }); 9534 9535 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 9536 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 9537 9538 vars.BODY.addClass('ilightbox-closedhand'); 9539 9540 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 9541 scrollTop = $doc.scrollTop(), 9542 scrollLeft = $doc.scrollLeft(), 9543 offsets = [ 9544 holders.eq(0).offset(), 9545 holders.eq(1).offset(), 9546 holders.eq(2).offset() 9547 ], 9548 offSet = [{ 9549 top: offsets[0].top - scrollTop, 9550 left: offsets[0].left - scrollLeft 9551 }, { 9552 top: offsets[1].top - scrollTop, 9553 left: offsets[1].left - scrollLeft 9554 }, { 9555 top: offsets[2].top - scrollTop, 9556 left: offsets[2].left - scrollLeft 9557 }], 9558 start = { 9559 time: (new Date()).getTime(), 9560 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 9561 }, 9562 stop; 9563 9564 function moveEachHandler(i) { 9565 var t = $(this), 9566 offset = offSet[i], 9567 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 9568 9569 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 9570 } 9571 9572 function moveHandler(event) { 9573 9574 if (!start) return; 9575 9576 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 9577 9578 stop = { 9579 time: (new Date()).getTime(), 9580 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 9581 }; 9582 9583 holders.each(moveEachHandler); 9584 9585 // prevent scrolling 9586 event.preventDefault(); 9587 } 9588 9589 function repositionHolders() { 9590 holders.each(function() { 9591 var t = $(this), 9592 offset = t.data('offset') || { 9593 top: t.offset().top - scrollTop, 9594 left: t.offset().left - scrollLeft 9595 }, 9596 top = offset.top, 9597 left = offset.left; 9598 9599 t.css(transform, gpuAcceleration).stop().animate({ 9600 top: top, 9601 left: left 9602 }, 500, 'easeOutCirc', function() { 9603 t.css(transform, ''); 9604 }); 9605 }); 9606 } 9607 9608 holders.bind(touchMoveEvent, moveHandler); 9609 $doc.one(touchStopEvent, function(event) { 9610 holders.unbind(touchMoveEvent, moveHandler); 9611 9612 vars.BODY.removeClass('ilightbox-closedhand'); 9613 9614 if (start && stop) { 9615 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 9616 if (start.coords[0] > stop.coords[0]) { 9617 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 9618 else { 9619 vars.isSwipe = true; 9620 iL.moveTo('next'); 9621 } 9622 } else { 9623 if (vars.current == 0 && !opts.infinite) repositionHolders(); 9624 else { 9625 vars.isSwipe = true; 9626 iL.moveTo('prev'); 9627 } 9628 } 9629 } 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) { 9630 if (start.coords[1] > stop.coords[1]) { 9631 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 9632 else { 9633 vars.isSwipe = true; 9634 iL.moveTo('next'); 9635 } 9636 } else { 9637 if (vars.current == 0 && !opts.infinite) repositionHolders(); 9638 else { 9639 vars.isSwipe = true; 9640 iL.moveTo('prev'); 9641 } 9642 } 9643 } else repositionHolders(); 9644 } 9645 start = stop = undefined; 9646 }); 9647 }); 9648 9649 }, 9650 9651 goTo: function(index) { 9652 var iL = this, 9653 vars = iL.vars, 9654 opts = iL.options, 9655 diff = (index - vars.current); 9656 9657 if (opts.infinite) { 9658 if (index == vars.total - 1 && vars.current == 0) diff = -1; 9659 if (vars.current == vars.total - 1 && index == 0) diff = 1; 9660 } 9661 9662 if (diff == 1) iL.moveTo('next'); 9663 else if (diff == -1) iL.moveTo('prev'); 9664 else { 9665 9666 if (vars.nextLock || vars.prevLock) return false; 9667 9668 //Trigger the onBeforeChange callback 9669 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 9670 9671 if (opts.linkId) { 9672 vars.hashLock = true; 9673 window.location.hash = opts.linkId + '/' + index; 9674 } 9675 9676 if (iL.items[index]) { 9677 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 9678 else iL.vars.lockWheel = false;
9679 9680 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 9681 else vars.lockSwipe = false; 9682 } 9683 9684 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 9685 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 9686 }); 9687 9688 vars.current = index; 9689 vars.next = index + 1; 9690 vars.prev = index - 1; 9691 9692 iL.createUI(); 9693 9694 setTimeout(function() { 9695 iL.generateBoxes(); 9696 }, opts.effects.loadedFadeSpeed + 50); 9697 9698 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 9699 iL.positionThumbnails(); 9700 9701 if (opts.linkId) setTimeout(function() { 9702 vars.hashLock = false; 9703 }, 55); 9704 9705 // Configure arrow buttons 9706 if (!opts.infinite) { 9707 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 9708 9709 if (vars.current == 0) { 9710 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 9711 } 9712 if (vars.current >= vars.total - 1) { 9713 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 9714 } 9715 } 9716 9717 // Reset next cycle timeout 9718 iL.resetCycle(); 9719 9720 //Trigger the onAfterChange callback 9721 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 9722 } 9723 }, 9724 9725 moveTo: function(side) { 9726 var iL = this, 9727 vars = iL.vars, 9728 opts = iL.options, 9729 path = opts.path.toLowerCase(), 9730 viewport = getViewport(), 9731 switchSpeed = opts.effects.switchSpeed; 9732 9733 if (vars.nextLock || vars.prevLock) return false; 9734 else { 9735 9736 var item = (side == "next") ? vars.next : vars.prev; 9737 9738 if (opts.linkId) { 9739 vars.hashLock = true; 9740 window.location.hash = opts.linkId + '/' + item; 9741 } 9742 9743 if (side == "next") { 9744 if (!iL.items[item]) return false; 9745 var firstHolder = vars.nextPhoto, 9746 secondHolder = vars.holder, 9747 lastHolder = vars.prevPhoto, 9748 firstClass = 'ilightbox-prev', 9749 secondClass = 'ilightbox-next'; 9750 } else if (side == "prev") { 9751 if (!iL.items[item]) return false; 9752 var firstHolder = vars.prevPhoto, 9753 secondHolder = vars.holder, 9754 lastHolder = vars.nextPhoto, 9755 firstClass = 'ilightbox-next', 9756 secondClass = 'ilightbox-prev'; 9757 } 9758 9759 //Trigger the onBeforeChange callback 9760 if (typeof opts.callback.onBeforeChange == 'function') 9761 opts.callback.onBeforeChange.call(iL, iL.ui); 9762 9763 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 9764 9765 var captionFirst = $('div.ilightbox-caption', secondHolder), 9766 socialFirst = $('div.ilightbox-social', secondHolder); 9767 9768 if (captionFirst.length) 9769 captionFirst.stop().fadeOut(switchSpeed, function() { 9770 $(this).remove(); 9771 }); 9772 if (socialFirst.length) 9773 socialFirst.stop().fadeOut(switchSpeed, function() { 9774 $(this).remove(); 9775 }); 9776 9777 if (iL.items[item].caption) { 9778 iL.setCaption(iL.items[item], firstHolder); 9779 var caption = $('div.ilightbox-caption', firstHolder), 9780 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 9781 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 9782 } 9783 9784 var social = iL.items[item].options.social; 9785 if (social) { 9786 iL.setSocial(social, iL.items[item].URL, firstHolder); 9787 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 9788 } 9789 9790 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 9791 val.removeClass('ilightbox-next ilightbox-prev'); 9792 }); 9793 9794 var firstOffset = firstHolder.data('offset'), 9795 winW = (viewport.width - (opts.styles.pageOffsetX)), 9796 winH = (viewport.height - (opts.styles.pageOffsetY)), 9797 width = firstOffset.newDims.width, 9798 height = firstOffset.newDims.height, 9799 thumbsOffset = firstOffset.thumbsOffset, 9800 diff = firstOffset.diff, 9801 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 9802 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 9803 9804 var secondOffset = secondHolder.data('offset'), 9805 object = secondOffset.object; 9806 9807 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 9808 var objRatio = width / height; 9809 height = height - vars.captionHeight; 9810 width = height * objRatio; 9811 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 9812 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 9813 }*/ 9814 9815 firstHolder.show().css(transform, gpuAcceleration).animate({ 9816 top: top, 9817 left: left, 9818 opacity: 1 9819 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 9820 firstHolder.css(transform, ''); 9821 }); 9822 9823 $('div.ilightbox-container', firstHolder).animate({ 9824 width: width, 9825 height: height 9826 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 9827 9828 diff = secondOffset.diff; 9829 9830 width = secondOffset.newDims.width, 9831 height = secondOffset.newDims.height; 9832 9833 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 9834 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 9835 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 9836 9837 if (side == 'prev') 9838 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 9839 else { 9840 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 9841 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 9842 } 9843 9844 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 9845 var objRatio = width / height; 9846 height = height - vars.captionHeight; 9847 width = height * objRatio; 9848 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 9849 }*/ 9850 9851 $('div.ilightbox-container', secondHolder).animate({ 9852 width: width, 9853 height: height 9854 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 9855 9856 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 9857 top: top, 9858 left: left, 9859 opacity: opts.styles.prevOpacity, 9860 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 9861 secondHolder.css(transform, ''); 9862
9863 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 9864 iL.positionThumbnails(); 9865 9866 if (iL.items[item]) { 9867 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 9868 else vars.lockWheel = false; 9869 9870 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 9871 else vars.lockSwipe = false; 9872 } 9873 9874 vars.isSwipe = false; 9875 9876 // Remove iframe & video from previous slide 9877 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 9878 $('div.ilightbox-container', secondHolder).empty(); 9879 } 9880 9881 if (side == "next") { 9882 vars.nextPhoto = lastHolder, 9883 vars.prevPhoto = secondHolder, 9884 vars.holder = firstHolder; 9885 9886 vars.nextPhoto.hide(); 9887 9888 vars.next = vars.next + 1, 9889 vars.prev = vars.current, 9890 vars.current = vars.current + 1; 9891 9892 if (opts.infinite) { 9893 if (vars.current > vars.total - 1) vars.current = 0; 9894 if (vars.current == vars.total - 1) vars.next = 0; 9895 if (vars.current == 0) vars.prev = vars.total - 1; 9896 } 9897 9898 iL.createUI(); 9899 9900 if (!iL.items[vars.next]) 9901 vars.nextLock = false; 9902 else 9903 iL.loadContent(iL.items[vars.next], 'next'); 9904 } else { 9905 vars.prevPhoto = lastHolder; 9906 vars.nextPhoto = secondHolder; 9907 vars.holder = firstHolder; 9908 9909 vars.prevPhoto.hide(); 9910 9911 vars.next = vars.current; 9912 vars.current = vars.prev; 9913 vars.prev = vars.current - 1; 9914 9915 if (opts.infinite) { 9916 if (vars.current == vars.total - 1) vars.next = 0; 9917 if (vars.current == 0) vars.prev = vars.total - 1; 9918 } 9919 9920 iL.createUI(); 9921 9922 if (!iL.items[vars.prev]) 9923 vars.prevLock = false; 9924 else 9925 iL.loadContent(iL.items[vars.prev], 'prev'); 9926 } 9927 9928 // Add iframe & video content for current slide 9929 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 9930 iL.loadContent(iL.items[vars.current], 'current'); 9931 } 9932 9933 if (opts.linkId) setTimeout(function() { 9934 vars.hashLock = false; 9935 }, 55); 9936 9937 // Configure arrow buttons 9938 if (!opts.infinite) { 9939 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 9940 9941 if (vars.current == 0) 9942 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 9943 if (vars.current >= vars.total - 1) 9944 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 9945 } 9946 9947 iL.repositionPhoto(); 9948 9949 // Reset next cycle timeout 9950 iL.resetCycle(); 9951 9952 //Trigger the onAfterChange callback 9953 if (typeof opts.callback.onAfterChange == 'function') 9954 opts.callback.onAfterChange.call(iL, iL.ui); 9955 }); 9956 9957 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 9958 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 9959 9960 lastHolder.css(transform, gpuAcceleration).animate({ 9961 top: top, 9962 left: left, 9963 opacity: opts.styles.nextOpacity 9964 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 9965 lastHolder.css(transform, ''); 9966 }).addClass(secondClass); 9967 } 9968 }, 9969 9970 setCaption: function(obj, target) { 9971 var iL = this, 9972 caption = $('<div class="ilightbox-caption"></div>'); 9973 9974 if (obj.caption) { 9975 caption.html(obj.caption); 9976 $('div.ilightbox-container', target).append(caption); 9977 } 9978 }, 9979 9980 normalizeSocial: function(obj, url) { 9981 var iL = this, 9982 vars = iL.vars, 9983 opts = iL.options, 9984 baseURL = window.location.href; 9985 9986 $.each(obj, function(key, value) { 9987 if (!value) 9988 return true; 9989 9990 var item = key.toLowerCase(), 9991 source, text; 9992 9993 switch (item) { 9994 case 'facebook': 9995 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 9996 text = "Share on Facebook"; 9997 break; 9998 case 'twitter': 9999 source = "http://twitter.com/home?status={URL}", 10000 text = "Share on Twitter"; 10001 break; 10002 case 'googleplus': 10003 source = "https://plus.google.com/share?url={URL}", 10004 text = "Share on Google+"; 10005 break; 10006 case 'delicious': 10007 source = "http://delicious.com/post?url={URL}", 10008 text = "Share on Delicious"; 10009 break; 10010 case 'digg': 10011 source = "http://digg.com/submit?phase=2&url={URL}", 10012 text = "Share on Digg"; 10013 break; 10014 case 'reddit': 10015 source = "http://reddit.com/submit?url={URL}", 10016 text = "Share on reddit"; 10017 break; 10018 } 10019 10020 obj[key] = { 10021 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 10022 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 10023 text: value.text || text || "Share on " + key, 10024 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 10025 height: value.height || 360 10026 }; 10027 10028 }); 10029 10030 return obj; 10031 }, 10032 10033 setSocial: function(obj, url, target) { 10034 var iL = this, 10035 socialBar = $('<div class="ilightbox-social"></div>'), 10036 buttons = '<ul>'; 10037 10038 obj = iL.normalizeSocial(obj, url); 10039 10040 $.each(obj, function(key, value) { 10041 var item = key.toLowerCase(), 10042 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, '+')); 10043 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>'; 10044 }); 10045 10046 buttons += '</ul>'; 10047 10048 socialBar.html(buttons); 10049 $('div.ilightbox-container', target).append(socialBar); 10050 }, 10051 10052 fullScreenAction: function() { 10053 var iL = this, 10054 vars = iL.vars; 10055 10056 if (fullScreenApi.supportsFullScreen) { 10057 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 10058 else fullScreenApi.requestFullScreen(document.documentElement); 10059 } else { 10060 iL.doFullscreen(); 10061 } 10062 }, 10063 10064 doFullscreen: function() { 10065 var iL = this, 10066 vars = iL.vars, 10067 viewport = getViewport(), 10068 opts = iL.options; 10069 10070 if (opts.fullAlone) { 10071 var currentHolder = vars.holder, 10072 current = iL.items[vars.current], 10073 windowWidth = viewport.width, 10074 windowHeight = viewport.height, 10075 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 10076 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 10077 10078 if (!vars.isInFullScreen) { 10079 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 10080 vars.overlay.css({ 10081 opacity: 1 10082 }); 10083 10084 $.each(hideElements, function(i, element) { 10085 element.hide(); 10086 }); 10087 10088 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 10089 10090 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
10091 naturalWidthOld: currentHolder.data('naturalWidth'), 10092 naturalHeightOld: currentHolder.data('naturalHeight'), 10093 naturalWidth: windowWidth, 10094 naturalHeight: windowHeight 10095 }); 10096 else { 10097 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 10098 newWidth = windowWidth, 10099 newHeight = windowHeight, 10100 width = currentHolder.data('naturalWidth'), 10101 height = currentHolder.data('naturalHeight'); 10102 10103 if (viewport.toLowerCase() == 'fill') { 10104 newHeight = (newWidth / width) * height; 10105 10106 if (newHeight < windowHeight) { 10107 newWidth = (windowHeight / height) * width, 10108 newHeight = windowHeight; 10109 } 10110 } else if (viewport.toLowerCase() == 'fit') { 10111 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 10112 10113 newWidth = dims.width, 10114 newHeight = dims.height; 10115 } else if (viewport.toLowerCase() == 'stretch') { 10116 newWidth = newWidth, 10117 newHeight = newHeight; 10118 } else { 10119 var scale = (width > newWidth || height > newHeight) ? true : false, 10120 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 10121 newWidth = dims.width, 10122 newHeight = dims.height; 10123 } 10124 10125 currentHolder.data({ 10126 naturalWidthOld: currentHolder.data('naturalWidth'), 10127 naturalHeightOld: currentHolder.data('naturalHeight'), 10128 naturalWidth: newWidth, 10129 naturalHeight: newHeight 10130 }); 10131 } 10132 10133 $.each(elements, function(key, val) { 10134 val.addClass('ilightbox-fullscreen'); 10135 }); 10136 10137 //Trigger the onEnterFullScreen callback 10138 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 10139 } else { 10140 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 10141 vars.overlay.css({ 10142 opacity: iL.options.overlay.opacity 10143 }); 10144 10145 $.each(hideElements, function(i, element) { 10146 element.show(); 10147 }); 10148 10149 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 10150 10151 currentHolder.data({ 10152 naturalWidth: currentHolder.data('naturalWidthOld'), 10153 naturalHeight: currentHolder.data('naturalHeightOld'), 10154 naturalWidthOld: null, 10155 naturalHeightOld: null 10156 }); 10157 10158 $.each(elements, function(key, val) { 10159 val.removeClass('ilightbox-fullscreen'); 10160 }); 10161 10162 //Trigger the onExitFullScreen callback 10163 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 10164 } 10165 } else { 10166 if (!vars.isInFullScreen) vars.isInFullScreen = true; 10167 else vars.isInFullScreen = false; 10168 } 10169 iL.repositionPhoto(true); 10170 }, 10171 10172 closeAction: function() { 10173 var iL = this, 10174 vars = iL.vars, 10175 opts = iL.options; 10176 10177 $win.unbind('.iLightBox'); 10178 $doc.off('.iLightBox'); 10179 10180 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 10181 10182 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 10183 10184 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 10185 vars.overlay.remove(); 10186 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 10187 }); 10188 else { 10189 vars.overlay.remove(); 10190 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 10191 } 10192 10193 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 10194 10195 $.each(fadeOuts, function(i, element) { 10196 element.removeAttr('style').remove(); 10197 }); 10198 10199 vars.dontGenerateThumbs = vars.isInFullScreen = false; 10200 10201 window.iLightBox = null; 10202 10203 if (opts.linkId) { 10204 vars.hashLock = true; 10205 removeHash(); 10206 setTimeout(function() { 10207 vars.hashLock = false; 10208 }, 55); 10209 } 10210 10211 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 10212 10213 //Trigger the onHide callback 10214 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 10215 }, 10216 10217 repositionPhoto: function() { 10218 var iL = this, 10219 vars = iL.vars, 10220 opts = iL.options, 10221 path = opts.path.toLowerCase(), 10222 viewport = getViewport(), 10223 winWidth = viewport.width, 10224 winHeight = viewport.height; 10225 10226 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 10227 10228 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 10229 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 10230 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 10231 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 10232 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, 10233 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))); 10234 10235 var elObject = { 10236 type: 'current', 10237 width: width, 10238 height: height, 10239 item: iL.items[vars.current], 10240 offsetW: offsetW, 10241 offsetH: offsetH,
10242 thumbsOffsetW: thumbsOffsetW, 10243 thumbsOffsetH: thumbsOffsetH, 10244 animate: arguments.length, 10245 holder: vars.holder 10246 }; 10247 10248 iL.repositionEl(elObject); 10249 10250 if (iL.items[vars.next]) { 10251 elObject = $.extend(elObject, { 10252 type: 'next', 10253 item: iL.items[vars.next], 10254 offsetX: opts.styles.nextOffsetX, 10255 offsetY: opts.styles.nextOffsetY, 10256 holder: vars.nextPhoto 10257 }); 10258 10259 iL.repositionEl(elObject); 10260 } 10261 10262 if (iL.items[vars.prev]) { 10263 elObject = $.extend(elObject, { 10264 type: 'prev', 10265 item: iL.items[vars.prev], 10266 offsetX: opts.styles.nextOffsetX, 10267 offsetY: opts.styles.prevOffsetY, 10268 holder: vars.prevPhoto 10269 }); 10270 10271 iL.repositionEl(elObject); 10272 } 10273 10274 var loaderCss = (path == "horizontal") ? { 10275 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 10276 } : { 10277 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 10278 }; 10279 vars.loader.css(loaderCss); 10280 }, 10281 10282 repositionEl: function(obj) { 10283 var iL = this, 10284 vars = iL.vars, 10285 opts = iL.options, 10286 path = opts.path.toLowerCase(), 10287 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 10288 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 10289 itemParent = obj.item, 10290 item = obj.item.options, 10291 holder = obj.holder, 10292 offsetX = obj.offsetX || 0, 10293 offsetY = obj.offsetY || 0, 10294 //Uncode change ##START## 10295 toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0, 10296 //Uncode change ##END## 10297 thumbsOffsetW = obj.thumbsOffsetW, 10298 thumbsOffsetH = obj.thumbsOffsetH; 10299 10300 if (obj.type == 'current') { 10301 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); 10302 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); 10303 } else { 10304 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 10305 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 10306 } 10307 10308 10309 //Uncode change ##START## 10310 heightAvail = parseInt(heightAvail - toolbarHeight); 10311 // heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 10312 //Uncode change ##END## 10313 10314 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 10315 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 10316 10317 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 10318 width: width, 10319 height: height 10320 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 10321 newDims = $.extend({}, dims, {}); 10322 10323 if (obj.type == 'prev' || obj.type == 'next') 10324 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 10325 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 10326 else 10327 width = dims.width, 10328 height = dims.height; 10329 10330 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 10331 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); 10332 10333 switch (obj.type) { 10334 case 'current': 10335 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 10336 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 10337 break; 10338
10339 case 'next': 10340 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 10341 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 10342 break; 10343 10344 case 'prev': 10345 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 10346 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 10347 break; 10348 } 10349 10350 holder.data('offset', { 10351 top: top, 10352 left: left, 10353 newDims: newDims, 10354 diff: { 10355 W: widthDiff, 10356 H: heightDiff 10357 }, 10358 thumbsOffset: { 10359 W: thumbsOffsetW, 10360 H: thumbsOffsetH 10361 }, 10362 object: obj 10363 }); 10364 10365 var opacityMobile; 10366 if ( isMobile ) { 10367 opacityMobile = { 10368 opacity: 1, 10369 top: top, 10370 left: left 10371 }; 10372 } else { 10373 opacityMobile = { 10374 top: top, 10375 left: left 10376 }; 10377 } 10378 10379 if (obj.animate > 0 && opts.effects.reposition) { 10380 holder.css(transform, gpuAcceleration).stop().animate( 10381 opacityMobile, 10382 opts.effects.repositionSpeed, 'easeOutCirc', function() { 10383 holder.css(transform, ''); 10384 }); 10385 $('div.ilightbox-container', holder).stop().animate({ 10386 width: width, 10387 height: height 10388 }, opts.effects.repositionSpeed, 'easeOutCirc'); 10389 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 10390 width: width 10391 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 10392 $(this).css('overflow', 'visible'); 10393 }); 10394 } else { 10395 holder.css(opacityMobile); 10396 $('div.ilightbox-container', holder).css({ 10397 width: width, 10398 height: height 10399 }); 10400 $('div.ilightbox-inner-toolbar', holder).css({ 10401 width: width 10402 }); 10403 } 10404 }, 10405 10406 10407 resume: function(priority) { 10408 var iL = this, 10409 vars = iL.vars, 10410 opts = iL.options; 10411 10412 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 10413 return; 10414 } 10415 10416 vars.isPaused = 0; 10417 10418 if (vars.cycleID) { 10419 vars.cycleID = clearTimeout(vars.cycleID); 10420 } 10421 10422 vars.cycleID = setTimeout(function() { 10423 if (vars.current == vars.total - 1) iL.goTo(0); 10424 else iL.moveTo('next'); 10425 }, opts.slideshow.pauseTime); 10426 }, 10427 10428 pause: function(priority) { 10429 var iL = this, 10430 vars = iL.vars, 10431 opts = iL.options; 10432 10433 if (priority < vars.isPaused) { 10434 return; 10435 } 10436 10437 vars.isPaused = priority || 100; 10438 10439 if (vars.cycleID) { 10440 vars.cycleID = clearTimeout(vars.cycleID); 10441 } 10442 }, 10443 10444 resetCycle: function() { 10445 var iL = this, 10446 vars = iL.vars, 10447 opts = iL.options; 10448 10449 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 10450 iL.resume(); 10451 } 10452 }, 10453 10454 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 10455 var iL = this; 10456 10457 if (!width) factor = height / height_old; 10458 else if (!height) factor = width / width_old; 10459 else factor = min(width / width_old, height / height_old); 10460 10461 if (!thumb) { 10462 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 10463 else if (factor < iL.options.minScale) factor = iL.options.minScale; 10464 } 10465 10466 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 10467 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 10468 10469 return { 10470 width: final_width, 10471 height: final_height, 10472 ratio: factor 10473 }; 10474 }, 10475 10476 setOption: function(options) { 10477 var iL = this; 10478 10479 iL.options = $.extend(true, iL.options, options || {}); 10480 iL.refresh(); 10481 }, 10482 10483 availPlugins: function() { 10484 var iL = this, 10485 testEl = document.createElement("video"); 10486 10487 iL.plugins = { 10488 flash: !isMobile, 10489 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 10490 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 10491 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 10492 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 10493 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 10494 }; 10495 }, 10496 10497 addContent: function(element, obj) { 10498 var iL = this, 10499 el; 10500 10501 switch (obj.type) { 10502 case 'video': 10503 var HTML5 = false, 10504 videoType = obj.videoType, 10505 html5video = obj.options.html5video; 10506 10507 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 10508 obj.ext = 'mp4', 10509 obj.URL = html5video.h264 || obj.URL; 10510 else if (html5video.webm && iL.plugins.html5WebM) 10511 obj.ext = 'webm', 10512 obj.URL = html5video.webm || obj.URL; 10513 else if (html5video.ogg && iL.plugins.html5Vorbis) 10514 obj.ext = 'ogv', 10515 obj.URL = html5video.ogg || obj.URL; 10516 10517 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 10518 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 10519 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 10520 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 10521 10522 if (HTML5) { 10523 el = $('<video />
10523', { 10524 "width": "100%", 10525 "height": "100%", 10526 "preload": html5video.preload, 10527 "autoplay": html5video.autoplay, 10528 "loop": html5video.loop, 10529 "poster": html5video.poster, 10530 "controls": html5video.controls, 10531 "controlslist": "nodownload" 10532 }).append($('<source />', { 10533 "src": obj.URL, 10534 "type": videoType 10535 })); 10536 } else { 10537 if (!iL.plugins.quicktime) el = $('<span />', { 10538 "class": "ilightbox-alert", 10539 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 10540 }); 10541 else { 10542 10543 el = $('<object />', { 10544 "type": "video/quicktime", 10545 "pluginspage": pluginspages.quicktime 10546 }).attr({ 10547 "data": obj.URL, 10548 "width": "100%", 10549 "height": "100%" 10550 }).append($('<param />', { 10551 "name": "src", 10552 "value": obj.URL 10553 })).append($('<param />', { 10554 "name": "autoplay", 10555 "value": "false" 10556 })).append($('<param />', { 10557 "name": "loop", 10558 "value": "false" 10559 })).append($('<param />', { 10560 "name": "scale", 10561 "value": "tofit" 10562 })); 10563 10564 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 10565 } 10566 } 10567 10568 break; 10569 10570 case 'flash': 10571 if (!iL.plugins.flash) el = $('<span />', { 10572 "class": "ilightbox-alert", 10573 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 10574 }); 10575 else { 10576 var flashvars = "", 10577 i = 0; 10578 10579 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 10580 if (i != 0) flashvars += "&"; 10581 flashvars += k + "=" + encodeURIComponent(v); 10582 i++; 10583 }); 10584 else flashvars = null; 10585 10586 el = $('<embed />').attr({ 10587 "type": "application/x-shockwave-flash", 10588 "src": obj.URL, 10589 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 10590 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 10591 "quality": "high", 10592 "bgcolor": "#000000", 10593 "play": "true", 10594 "loop": "true", 10595 "menu": "true", 10596 "wmode": "transparent", 10597 "scale": "showall", 10598 "allowScriptAccess": "always", 10599 "allowFullScreen": "true", 10600 "flashvars": flashvars, 10601 "fullscreen": "yes" 10602 }); 10603 } 10604 10605 break; 10606 10607 case 'iframe': 10608 el = $('<iframe />').attr({ 10609 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 10610 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 10611 src: obj.URL, 10612 frameborder: 0, 10613 'hspace': 0, 10614 'vspace': 0, 10615 'scrolling': supportTouch ? 'auto' : 'scroll', 10616 'webkitAllowFullScreen': '', 10617 'mozallowfullscreen': '', 10618 'allowFullScreen': '' 10619 }); 10620 10621 break; 10622 10623 case 'inline': 10624 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 10625 10626 break; 10627 10628 case 'html': 10629 var object = obj.URL, 10630 el; 10631 10632 if (object[0].nodeName) { 10633 el = $('<div class="ilightbox-wrapper"></div>').html(object); 10634 } else { 10635 var dom = $(obj.URL), 10636 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 10637 el = $('<div class="ilightbox-wrapper"></div>').html(html); 10638 } 10639 10640 break; 10641 } 10642 10643 $('div.ilightbox-container', element).empty().html(el); 10644 10645 // For fixing Chrome about just playing the video for first time 10646 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 10647 var src = el[0].currentSrc + '?' + floor(random() * 30000); 10648 el[0].currentSrc = src; 10649 el[0].src = src; 10650 }); 10651 10652 return el; 10653 }, 10654 10655 ogpRecognition: function(obj, callback) { 10656 var iL = this, 10657 url = obj.URL; 10658 10659 iL.showLoader(); 10660 doAjax(url, function(data) { 10661 iL.hideLoader(); 10662 if (data) { 10663 var object = new Object(); 10664 10665 object.length = false, 10666 object.url = data.url; 10667 10668 if (data.status == 200) { 10669 var result = data.results, 10670 type = result.type, 10671 source = result.source; 10672 10673 object.source = source.src, 10674 object.width = source.width && parseInt(source.width) || 0, 10675 object.height = source.height && parseInt(source.height) || 0, 10676 object.type = type, 10677 object.thumbnail = source.thumbnail || result.images && result.images[0], 10678 object.html5video = result.html5video || {}, 10679 object.length = true; 10680 10681 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 10682 else if (source.type.indexOf("video/") != -1) object.type = "video"; 10683 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 10684 else if (source.type.indexOf("image/") != -1) object.type = "image"; 10685 10686 } else if (typeof data.response != 'undefined') 10687 throw data.response; 10688 10689 callback.call(this, object.length ? object : false); 10690 } 10691 }); 10692 }, 10693 10694 hashChangeHandler: function(url) { 10695 var iL = this, 10696 vars = iL.vars, 10697 opts = iL.options, 10698 URL = url || window.location.href, 10699 hash = parseURI(URL).hash, 10700 split = hash.split('/'), 10701 index = split[1]; 10702 10703 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 10704 10705 if (index) { 10706 var target = split[1] || 0; 10707 if (iL.items[target]) {
10708 var overlay = $('.ilightbox-overlay'); 10709 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 10710 iL.goTo(target); 10711 } else { 10712 iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click'); 10713 //iL.goTo(target); 10714 } 10715 } else { 10716 var overlay = $('.ilightbox-overlay'); 10717 if (overlay.length) iL.closeAction(); 10718 } 10719 } else { 10720 var overlay = $('.ilightbox-overlay'); 10721 if (overlay.length) iL.closeAction(); 10722 } 10723 } 10724 }; 10725 10726 /** 10727 * Parse style to pixels. 10728 * 10729 * @param {Object} $element jQuery object with element. 10730 * @param {Property} property CSS property to get the pixels from. 10731 * 10732 * @return {Int} 10733 */ 10734 function getPixel($element, property) { 10735 return parseInt($element.css(property), 10) || 0; 10736 } 10737 10738 /** 10739 * Make sure that number is within the limits. 10740 * 10741 * @param {Number} number 10742 * @param {Number} min 10743 * @param {Number} max 10744 * 10745 * @return {Number} 10746 */ 10747 function within(number, min, max) { 10748 return number < min ? min : number > max ? max : number; 10749 } 10750 10751 /** 10752 * Get viewport/window size (width and height). 10753 * 10754 * @return {Object} 10755 */ 10756 function getViewport() { 10757 var e = window, 10758 a = 'inner'; 10759 if (!('innerWidth' in window)) { 10760 a = 'client'; 10761 e = document.documentElement || document.body; 10762 } 10763 return { 10764 width: e[a + 'Width'], 10765 height: e[a + 'Height'] 10766 } 10767 } 10768 10769 /** 10770 * Remove hash tag from the URL 10771 * 10772 * @return {Void} 10773 */ 10774 function removeHash() { 10775 var scroll = getScrollXY(); 10776 10777 //UNCODE change 10778 //window.location.hash = ""; 10779 history.pushState("", document.title, window.location.pathname + window.location.search); 10780 10781 // Restore the scroll offset, should be flicker free 10782 window.scrollTo(scroll.x, scroll.y); 10783 } 10784 10785 /** 10786 * Do the ajax requests with callback. 10787 * 10788 * @param {String} url 10789 * @param {Function} callback 10790 * 10791 * @return {Void} 10792 */ 10793 function doAjax(url, callback) { 10794 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'); 10795 $.ajax({ 10796 url: url, 10797 dataType: 'jsonp' 10798 }); 10799 10800 iLCallback = function(data) { 10801 callback.call(this, data); 10802 }; 10803 } 10804 10805 /** 10806 * Find image from DOM elements 10807 * 10808 * @param {Element} element 10809 * 10810 * @return {Void} 10811 */ 10812 function findImageInElement(element) { 10813 var elements = $('*', element), 10814 imagesArr = new Array(); 10815 10816 elements.each(function() { 10817 var url = "", 10818 element = this; 10819 10820 if ($(element).css("background-image") != "none") { 10821 url = $(element).css("background-image"); 10822 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 10823 url = $(element).attr("src"); 10824 } 10825 10826 if (url.indexOf("gradient") == -1) { 10827 url = url.replace(/url\(\"/g, ""); 10828 url = url.replace(/url\(/g, ""); 10829 url = url.replace(/\"\)/g, ""); 10830 url = url.replace(/\)/g, ""); 10831 10832 var urls = url.split(","); 10833 10834 for (var i = 0; i < urls.length; i++) { 10835 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 10836 var extra = ""; 10837 if (browser.msie && browser.version < 9) { 10838 extra = "?" + floor(random() * 3000); 10839 } 10840 imagesArr.push(urls[i] + extra); 10841 } 10842 } 10843 } 10844 }); 10845 10846 return imagesArr; 10847 } 10848 10849 /** 10850 * Get file extension. 10851 * 10852 * @param {String} URL 10853 * 10854 * @return {String} 10855 */ 10856 function getExtension(URL) { 10857 if (URL !== null) { 10858 //UNCODE: fix issue to detect media type with query strings 10859 var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL; 10860 ext = ext.split('.').pop().toLowerCase(); 10861 10862 return ext; 10863 } 10864 } 10865 10866 /** 10867 * Get type via extension. 10868 * 10869 * @param {String} URL 10870 * 10871 * @return {String} 10872 */ 10873 function getTypeByExtension(URL) { 10874 var type, 10875 ext = getExtension(URL); 10876 10877 //Uncode addition ##START## 10878 if (URL == undefined) { 10879 return false; 10880 } 10881 //Uncode addition ##END## 10882 10883 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 10884 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 10885 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 10886 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 10887 else type = 'iframe'; 10888 10889 return type; 10890 } 10891 10892 /** 10893 * Return value from percent of a number. 10894 * 10895 * @param {Number} percent 10896 * @param {Number} total 10897 * 10898 * @return {Number} 10899 */ 10900 function percentToValue(percent, total) { 10901 return parseInt((total / 100) * percent); 10902 } 10903 10904 /** 10905 * A JavaScript equivalent of PHP’s parse_url. 10906 * 10907 * @param {String} url The URL to parse. 10908 * 10909 * @return {Mixed} 10910 */ 10911 function parseURI(url) { 10912 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 10913 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 10914 return (m ? { 10915 href: m[0] || '', 10916 protocol: m[1] || '', 10917 authority: m[2] || '', 10918 host: m[3] || '', 10919 hostname: m[4] || '', 10920 port: m[5] || '', 10921 pathname: m[6] || '', 10922 search: m[7] || '', 10923 hash: m[8] || '' 10924 } : null); 10925 } 10926 10927 /** 10928 * Gets the absolute URI. 10929 * 10930 * @param {String} href The relative URL. 10931 * @param {String} base The base URL. 10932 * 10933 * @return {String} The absolute URL. 10934 */ 10935 function absolutizeURI(base, href) { // RFC 3986 10936 var iL = this; 10937 10938 function removeDotSegments(input) { 10939 var output = []; 10940 input.replace(/^(\.\.?(\/|$))+/, '') 10941 .replace(/\/(\.(\/|$))+/g, '/') 10942 .replace(/\/\.\.$/, '/../') 10943 .replace(/\/?[^\/]*/g, function(p) { 10944 if (p === '/..') { 10945 output.pop(); 10946 } else { 10947 output.push(p); 10948 } 10949 }); 10950 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 10951 } 10952 10953 href = parseURI(href || ''); 10954 base = parseURI(base || ''); 10955 10956 return !href || !base ? null : (href.protocol || base.protocol) + 10957 (href.protocol || href.authority ? href.authority : base.authority) + 10958 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)) + 10959 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 10960 href.hash; 10961 } 10962 10963 /** 10964 * A JavaScript equivalent of PHP’s version_compare. 10965 * 10966 * @param {String} v1 10967 * @param {String} v2 10968 * @param {String} operator
10969 * 10970 * @return {Boolean} 10971 */ 10972 function version_compare(v1, v2, operator) { 10973 this.php_js = this.php_js || {}; 10974 this.php_js.ENV = this.php_js.ENV || {}; 10975 var i = 0, 10976 x = 0, 10977 compare = 0, 10978 vm = { 10979 'dev': -6, 10980 'alpha': -5, 10981 'a': -5, 10982 'beta': -4, 10983 'b': -4, 10984 'RC': -3, 10985 'rc': -3, 10986 '#': -2, 10987 'p': 1, 10988 'pl': 1 10989 }, 10990 prepVersion = function(v) { 10991 v = ('' + v).replace(/[_\-+]/g, '.'); 10992 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 10993 return (!v.length ? [-8] : v.split('.')); 10994 }, 10995 numVersion = function(v) { 10996 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 10997 }; 10998 v1 = prepVersion(v1); 10999 v2 = prepVersion(v2); 11000 x = max(v1.length, v2.length); 11001 for (i = 0; i < x; i++) { 11002 if (v1[i] == v2[i]) { 11003 continue; 11004 } 11005 v1[i] = numVersion(v1[i]); 11006 v2[i] = numVersion(v2[i]); 11007 if (v1[i] < v2[i]) { 11008 compare = -1; 11009 break; 11010 } else if (v1[i] > v2[i]) { 11011 compare = 1; 11012 break; 11013 } 11014 } 11015 if (!operator) { 11016 return compare; 11017 } 11018 11019 switch (operator) { 11020 case '>': 11021 case 'gt': 11022 return (compare > 0); 11023 case '>=': 11024 case 'ge': 11025 return (compare >= 0); 11026 case '<=': 11027 case 'le': 11028 return (compare <= 0); 11029 case '==': 11030 case '=': 11031 case 'eq': 11032 return (compare === 0); 11033 case '<>': 11034 case '!=': 11035 case 'ne': 11036 return (compare !== 0); 11037 case '': 11038 case '<': 11039 case 'lt': 11040 return (compare < 0); 11041 default: 11042 return null; 11043 } 11044 } 11045 11046 11047 // Begin the iLightBox plugin 11048 $.fn.iLightBox = function() { 11049 11050 var args = arguments, 11051 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 11052 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 11053 11054 if (!opt) opt = {}; 11055 11056 // Default options. Play carefully. 11057 var options = $.extend(true, { 11058 attr: 'href', 11059 path: 'vertical', 11060 skin: 'dark', 11061 linkId: false, 11062 infinite: false, 11063 startFrom: 0, 11064 randomStart: false, 11065 keepAspectRatio: true, 11066 maxScale: 1, 11067 minScale: .2, 11068 innerToolbar: false, 11069 smartRecognition: false, 11070 mobileOptimizer: true, 11071 fullAlone: true, 11072 fullViewPort: null, 11073 fullStretchTypes: 'flash, video', 11074 overlay: { 11075 blur: true, 11076 opacity: .85 11077 }, 11078 controls: { 11079 arrows: false, 11080 slideshow: false, 11081 toolbar: true, 11082 fullscreen: true, 11083 thumbnail: true, 11084 keyboard: true, 11085 mousewheel: true, 11086 swipe: true 11087 }, 11088 keyboard: { 11089 left: true, // previous 11090 right: true, // next 11091 up: true, // previous 11092 down: true, // next 11093 esc: true, // close 11094 shift_enter: true // fullscreen 11095 }, 11096 show: { 11097 effect: true, 11098 speed: 300, 11099 title: true 11100 }, 11101 hide: { 11102 effect: true, 11103 speed: 300 11104 }, 11105 caption: { 11106 start: true, 11107 show: 'mouseenter', 11108 hide: 'mouseleave' 11109 }, 11110 social: { 11111 start: true, 11112 show: 'mouseenter', 11113 hide: 'mouseleave',
11114 buttons: false 11115 }, 11116 styles: { 11117 pageOffsetX: 0, 11118 pageOffsetY: 0, 11119 nextOffsetX: 45, 11120 nextOffsetY: 0, 11121 nextOpacity: 1, 11122 nextScale: 1, 11123 prevOffsetX: 45, 11124 prevOffsetY: 0, 11125 prevOpacity: 1, 11126 prevScale: 1 11127 }, 11128 thumbnails: { 11129 maxWidth: 120, 11130 maxHeight: 80, 11131 normalOpacity: 1, 11132 activeOpacity: .6 11133 }, 11134 effects: { 11135 reposition: true, 11136 repositionSpeed: 200, 11137 switchSpeed: 500, 11138 loadedFadeSpeed: 180, 11139 fadeSpeed: 200 11140 }, 11141 slideshow: { 11142 pauseTime: 5000, 11143 pauseOnHover: false, 11144 startPaused: true 11145 }, 11146 text: { 11147 close: "Press Esc to close", 11148 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 11149 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 11150 slideShow: "Slideshow", 11151 next: "Next", 11152 previous: "Previous" 11153 }, 11154 errors: { 11155 loadImage: "An error occurred when trying to load photo.", 11156 loadContents: "An error occurred when trying to load contents.", 11157 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 11158 }, 11159 ajaxSetup: { 11160 url: '', 11161 beforeSend: function(jqXHR, settings) {}, 11162 cache: false, 11163 complete: function(jqXHR, textStatus) {}, 11164 crossDomain: false, 11165 error: function(jqXHR, textStatus, errorThrown) {}, 11166 success: function(data, textStatus, jqXHR) {}, 11167 global: true, 11168 ifModified: false, 11169 username: null, 11170 password: null, 11171 type: 'GET' 11172 }, 11173 callback: {} 11174 }, opt); 11175 11176 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 11177 11178 items = $.isArray(items) ? items : new Array(); 11179 11180 if (typeof args[0] == 'string') items[0] = args[0]; 11181 11182 if (version_compare($.fn.jquery, '1.8', '>=')) { 11183 var iLB = new iLightBox($(this), options, items, instant); 11184 return { 11185 close: function() { 11186 iLB.closeAction(); 11187 }, 11188 fullscreen: function() { 11189 iLB.fullScreenAction(); 11190 }, 11191 moveNext: function() { 11192 iLB.moveTo('next'); 11193 }, 11194 movePrev: function() { 11195 iLB.moveTo('prev'); 11196 }, 11197 goTo: function(index) { 11198 iLB.goTo(index); 11199 }, 11200 refresh: function() { 11201 iLB.refresh(); 11202 }, 11203 reposition: function() { 11204 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 11205 }, 11206 setOption: function(options) { 11207 iLB.setOption(options); 11208 }, 11209 destroy: function() { 11210 iLB.closeAction(); 11211 iLB.dispatchItemsEvents(); 11212 } 11213 }; 11214 } else { 11215 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 11216 } 11217 11218 }; 11219 11220 11221 $.iLightBox = function() { 11222 return $.fn.iLightBox(arguments[0], arguments[1]); 11223 }; 11224 11225 function getScrollXY() { 11226 var scrOfX = 0, 11227 scrOfY = 0; 11228 if (typeof(window.pageYOffset) == 'number') { 11229 //Netscape compliant 11230 scrOfY = window.pageYOffset; 11231 scrOfX = window.pageXOffset; 11232 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 11233 //DOM compliant 11234 scrOfY = document.body.scrollTop; 11235 scrOfX = document.body.scrollLeft; 11236 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 11237 //IE6 standards compliant mode 11238 scrOfY = document.documentElement.scrollTop; 11239 scrOfX = document.documentElement.scrollLeft; 11240 } 11241 return { 11242 x: scrOfX, 11243 y: scrOfY 11244 }; 11245 } 11246 11247 (function() { 11248 // add new event shortcuts 11249 $.each(("touchstart touchmove touchend " + 11250 "tap taphold " + 11251 "swipe swipeleft swiperight " + 11252 "scrollstart scrollstop").split(" "), function(i, name) { 11253 11254 $.fn[name] = function(fn) { 11255 return fn ? this.bind(name, fn) : this.trigger(name); 11256 }; 11257 11258 // jQuery < 1.8 11259 // if ($.attrFn) { 11260 // $.attrFn[name] = true; 11261 // } 11262 }); 11263 11264 var tapSettings = { 11265 startEvent: 'touchstart.iTap', 11266 endEvent: 'touchend.iTap' 11267 }; 11268 11269 // tap Event: 11270 $.event.special.itap = { 11271 setup: function() { 11272 11273 var self = this, 11274 $self = $(this), 11275 start, stop; 11276 11277 $self.bind(tapSettings.startEvent, function(event) { 11278 start = getScrollXY(); 11279 11280 $self.one(tapSettings.endEvent, function(event) { 11281 stop = getScrollXY(); 11282 11283 var orgEvent = event || window.event; 11284 event = $.event.fix(orgEvent); 11285 event.type = "itap"; 11286 11287 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 11288 11289 start = stop = undefined; 11290 }); 11291 }); 11292 }, 11293 11294 teardown: function() { 11295 $(this).unbind(tapSettings.startEvent); 11296 } 11297 }; 11298 }()); 11299 11300 11301 //Fullscreen API 11302 (function() { 11303 fullScreenApi = { 11304 supportsFullScreen: false, 11305 isFullScreen: function() { 11306 return false;
11307 }, 11308 requestFullScreen: function() {}, 11309 cancelFullScreen: function() {}, 11310 fullScreenEventName: '', 11311 prefix: '' 11312 }, 11313 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 11314 11315 // check for native support 11316 if (typeof document.cancelFullScreen != 'undefined') { 11317 fullScreenApi.supportsFullScreen = true; 11318 } else { 11319 // check for fullscreen support by vendor prefix 11320 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 11321 fullScreenApi.prefix = browserPrefixes[i]; 11322 11323 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 11324 fullScreenApi.supportsFullScreen = true; 11325 11326 break; 11327 } 11328 } 11329 } 11330 11331 // update methods to do something useful 11332 if (fullScreenApi.supportsFullScreen) { 11333 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 11334 11335 fullScreenApi.isFullScreen = function() { 11336 switch (this.prefix) { 11337 case '': 11338 return document.fullScreen; 11339 case 'webkit': 11340 return document.webkitIsFullScreen; 11341 default: 11342 return document[this.prefix + 'FullScreen']; 11343 } 11344 } 11345 fullScreenApi.requestFullScreen = function(el) { 11346 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 11347 } 11348 fullScreenApi.cancelFullScreen = function(el) { 11349 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 11350 } 11351 } 11352 }()); 11353 11354 // Browser detect 11355 (function() { 11356 function uaMatch(ua) { 11357 ua = ua.toLowerCase(); 11358 11359 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 11360 /(webkit)[ \/]([\w.]+)/.exec(ua) || 11361 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 11362 /(msie) ([\w.]+)/.exec(ua) || 11363 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 11364 11365 return { 11366 browser: match[1] || "", 11367 version: match[2] || "0" 11368 }; 11369 } 11370 11371 var matched = uaMatch(navigator.userAgent); 11372 browser = {}; 11373 11374 if (matched.browser) { 11375 browser[matched.browser] = true; 11376 browser.version = matched.version; 11377 } 11378 11379 // Chrome is Webkit, but Webkit is also Safari. 11380 if (browser.chrome) { 11381 browser.webkit = true; 11382 } else if (browser.webkit) { 11383 browser.safari = true; 11384 } 11385 }()); 11386 11387 // Feature detects 11388 (function() { 11389 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 11390 var el = document.createElement('div'); 11391 11392 function testProp(prop) { 11393 for (var p = 0, pl = prefixes.length; p < pl; p++) { 11394 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 11395 if (el.style[prefixedProp] !== undefined) { 11396 return prefixedProp; 11397 } 11398 } 11399 } 11400 11401 // Global support indicators 11402 transform = testProp('transform') || ''; 11403 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 11404 }()); 11405 11406 11407 /* 11408 PluginDetect v0.7.9 11409 www.pinlady.net/PluginDetect/license/ 11410 [ getVersion onWindowLoaded BetterIE ] 11411 [ Flash QuickTime Shockwave ] 11412 */ 11413 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;
11413d++){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);
11413d.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)}
11413c.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;
11413if(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(); 11414 11415 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)}; 11416 11417 11418 /* 11419 jQuery hashchange event v1.3 11420 https://github.com/cowboy/jquery-hashchange 11421 Copyright (c) 2010 "Cowboy" Ben Alman 11422 Dual licensed under the MIT and GPL licenses. 11423 */ 11424 (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= 11425 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|| 11426 "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;
11426a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 11427 11428 if (!Array.prototype.filter) { 11429 Array.prototype.filter = function(fun /*, thisp */ ) { 11430 "use strict"; 11431 11432 if (this == null) 11433 throw new TypeError(); 11434 11435 var t = Object(this); 11436 var len = t.length >>> 0; 11437 if (typeof fun != "function") 11438 throw new TypeError(); 11439 11440 var res = []; 11441 var thisp = arguments[1]; 11442 for (var i = 0; i < len; i++) { 11443 if (i in t) { 11444 var val = t[i]; // in case fun mutates this 11445 if (fun.call(thisp, val, i, t)) 11446 res.push(val); 11447 } 11448 } 11449 11450 return res; 11451 }; 11452 } 11453 11454 if (!Array.prototype.indexOf) { 11455 Array.prototype.indexOf = function(searchElement, fromIndex) { 11456 var k; 11457 11458 if (this == null) { 11459 throw new TypeError('"this" is null or not defined'); 11460 } 11461 11462 var O = Object(this); 11463 11464 var len = O.length >>> 0; 11465 11466 if (len === 0) { 11467 return -1; 11468 } 11469 11470 var n = +fromIndex || 0; 11471 11472 if (abs(n) === Infinity) { 11473 n = 0; 11474 } 11475 11476 if (n >= len) { 11477 return -1; 11478 } 11479 11480 k = max(n >= 0 ? n : len - abs(n), 0); 11481 11482 while (k < len) { 11483 var kValue; 11484 if (k in O && O[k] === searchElement) { 11485 return k; 11486 } 11487 k++; 11488 } 11489 return -1; 11490 }; 11491 } 11492 11493 if (!Array.prototype.lastIndexOf) { 11494 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 11495 "use strict"; 11496 11497 if (this == null) 11498 throw new TypeError(); 11499 11500 var t = Object(this); 11501 var len = t.length >>> 0; 11502 if (len === 0) 11503 return -1; 11504 11505 var n = len; 11506 if (arguments.length > 1) { 11507 n = Number(arguments[1]); 11508 if (n != n) 11509 n = 0; 11510 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 11511 n = (n > 0 || -1) * floor(abs(n)); 11512 } 11513 11514 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 11515 11516 for (; k >= 0; k--) { 11517 if (k in t && t[k] === searchElement) 11518 return k; 11519 } 11520 return -1; 11521 }; 11522 } 11523})(jQuery, this); 11524 11525/** 11526 * Owl carousel
vendor: 12,108 bytes, lines 11527-12033
11527 * @version 2.0.0-beta.3 11528 * @author Bartosz Wojciechowski 11529 * @license The MIT License (MIT) 11530 * @todo Lazy Load Icon 11531 * @todo prevent animationend bubling 11532 * @todo itemsScaleUp 11533 * @todo Test Zepto 11534 * @todo stagePadding calculate wrong active classes 11535 */ 11536;(function($, window, document, undefined) { 11537 11538 /** 11539 * Creates a carousel. 11540 * @class The Owl Carousel. 11541 * @public 11542 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 11543 * @param {Object} [options] - The options 11544 */ 11545 function Owl(element, options) { 11546 11547 /** 11548 * Current settings for the carousel. 11549 * @public 11550 */ 11551 this.settings = null; 11552 11553 /** 11554 * Current options set by the caller including defaults. 11555 * @public 11556 */ 11557 this.options = $.extend({}, Owl.Defaults, options); 11558 11559 /** 11560 * Plugin element. 11561 * @public 11562 */ 11563 this.$element = $(element); 11564 11565 /** 11566 * Proxied event handlers. 11567 * @protected 11568 */ 11569 this._handlers = {}; 11570 11571 /** 11572 * References to the running plugins of this carousel. 11573 * @protected 11574 */ 11575 this._plugins = {}; 11576 11577 /** 11578 * Currently suppressed events to prevent them from beeing retriggered. 11579 * @protected 11580 */ 11581 this._supress = {}; 11582 11583 /** 11584 * Absolute current position. 11585 * @protected 11586 */ 11587 this._current = null; 11588 11589 /** 11590 * Animation speed in milliseconds. 11591 * @protected 11592 */ 11593 this._speed = null; 11594 11595 /** 11596 * Coordinates of all items in pixel. 11597 * @todo The name of this member is missleading. 11598 * @protected 11599 */ 11600 this._coordinates = []; 11601 11602 /** 11603 * Current breakpoint. 11604 * @todo Real media queries would be nice. 11605 * @protected 11606 */ 11607 this._breakpoint = null; 11608 11609 /** 11610 * Current width of the plugin element. 11611 */ 11612 this._width = null; 11613 11614 /** 11615 * All real items. 11616 * @protected 11617 */ 11618 this._items = []; 11619 11620 /** 11621 * All cloned items. 11622 * @protected 11623 */ 11624 this._clones = []; 11625 11626 /** 11627 * Merge values of all items. 11628 * @todo Maybe this could be part of a plugin. 11629 * @protected 11630 */ 11631 this._mergers = []; 11632 11633 /** 11634 * Widths of all items. 11635 */ 11636 this._widths = []; 11637 11638 /** 11639 * Invalidated parts within the update process. 11640 * @protected 11641 */ 11642 this._invalidated = {}; 11643 11644 /** 11645 * Ordered list of workers for the update process. 11646 * @protected 11647 */ 11648 this._pipe = []; 11649 11650 /** 11651 * Current state information for the drag operation. 11652 * @todo #261 11653 * @protected 11654 */ 11655 this._drag = { 11656 time: null, 11657 target: null, 11658 pointer: null, 11659 stage: { 11660 start: null, 11661 current: null 11662 }, 11663 direction: null 11664 }; 11665 11666 /** 11667 * Current state information and their tags. 11668 * @type {Object} 11669 * @protected 11670 */ 11671 this._states = { 11672 current: {}, 11673 tags: { 11674 'initializing': [ 'busy' ], 11675 'animating': [ 'busy' ], 11676 'dragging': [ 'interacting' ] 11677 } 11678 }; 11679 11680 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 11681 this._handlers[handler] = $.proxy(this[handler], this); 11682 }, this)); 11683 11684 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 11685 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 11686 = new plugin(this); 11687 }, this)); 11688 11689 $.each(Owl.Workers, $.proxy(function(priority, worker) { 11690 this._pipe.push({ 11691 'filter': worker.filter, 11692 'run': $.proxy(worker.run, this) 11693 }); 11694 }, this)); 11695 11696 this.setup(); 11697 this.initialize(); 11698 } 11699 11700 /** 11701 * Default options for the carousel. 11702 * @public 11703 */ 11704 Owl.Defaults = { 11705 items: 3, 11706 loop: false, 11707 center: false, 11708 rewind: false, 11709 11710 mouseDrag: true, 11711 touchDrag: true, 11712 pullDrag: true, 11713 freeDrag: false, 11714 11715 margin: 0, 11716 stagePadding: 0, 11717 11718 merge: false, 11719 mergeFit: true, 11720 autoWidth: false, 11721 11722 startPosition: 0, 11723 rtl: false, 11724 11725 smartSpeed: 250, 11726 fluidSpeed: false, 11727 dragEndSpeed: false, 11728 11729 responsive: {}, 11730 responsiveRefreshRate: 200, 11731 responsiveBaseElement: window, 11732 11733 fallbackEasing: 'swing', 11734 11735 info: false, 11736 11737 nestedItemSelector: false, 11738 itemElement: 'div', 11739 stageElement: 'div', 11740 11741 refreshClass: 'owl-refresh', 11742 loadedClass: 'owl-loaded', 11743 loadingClass: 'owl-loading', 11744 rtlClass: 'owl-rtl', 11745 responsiveClass: 'owl-responsive', 11746 dragClass: 'owl-drag', 11747 itemClass: 'owl-item', 11748 stageClass: 'owl-stage', 11749 stageOuterClass: 'owl-stage-outer', 11750 grabClass: 'owl-grab' 11751 }; 11752 11753 /** 11754 * Enumeration for width. 11755 * @public 11756 * @readonly 11757 * @enum {String} 11758 */ 11759 Owl.Width = { 11760 Default: 'default', 11761 Inner: 'inner', 11762 Outer: 'outer' 11763 }; 11764 11765 /** 11766 * Enumeration for types. 11767 * @public 11768 * @readonly 11769 * @enum {String} 11770 */ 11771 Owl.Type = { 11772 Event: 'event', 11773 State: 'state' 11774 }; 11775 11776 /** 11777 * Contains all registered plugins. 11778 * @public 11779 */ 11780 Owl.Plugins = {}; 11781 11782 /** 11783 * List of workers involved in the update process. 11784 */ 11785 Owl.Workers = [ { 11786 filter: [ 'width', 'settings' ], 11787 run: function() { 11788 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 11789 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 11790 } 11791 }, { 11792 filter: [ 'width', 'items', 'settings' ], 11793 run: function(cache) { 11794 cache.current = this._items && this._items[this.relative(this._current)]; 11795 } 11796 }, { 11797 filter: [ 'items', 'settings' ], 11798 run: function() { 11799 this.$stage.children('.cloned').remove(); 11800 } 11801 }, { 11802 filter: [ 'width', 'items', 'settings' ], 11803 run: function(cache) { 11804 var margin = this.settings.margin || '', 11805 grid = !this.settings.autoWidth, 11806 rtl = this.settings.rtl, 11807 css = { 11808 'width': 'auto', 11809 'margin-left': rtl ? margin : '', 11810 'margin-right': rtl ? '' : margin 11811 }; 11812 11813 !grid && this.$stage.children().css(css); 11814 11815 cache.css = css; 11816 } 11817 }, { 11818 filter: [ 'width', 'items', 'settings' ], 11819 run: function(cache) { 11820 //UNCODE edit to fix Chrome stage padding issue 11821 var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin), 11822 merge = null, 11823 iterator = this._items.length, 11824 grid = !this.settings.autoWidth, 11825 widths = []; 11826 11827 cache.items = { 11828 merge: false, 11829 width: width 11830 }; 11831 11832 while (iterator--) { 11833 merge = this._mergers[iterator]; 11834 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 11835 11836 cache.items.merge = merge > 1 || cache.items.merge; 11837 11838 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 11839 } 11840 11841 this._widths = widths; 11842 } 11843 }, { 11844 filter: [ 'items', 'settings' ], 11845 run: function() { 11846 var clones = [], 11847 items = this._items, 11848 settings = this.settings, 11849 view = Math.max(settings.items * 2, 4), 11850 size = Math.ceil(items.length / 2) * 2, 11851 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 11852 append = '', 11853 prepend = ''; 11854 11855 repeat /= 2; 11856 11857 while (repeat--) { 11858 clones.push(this.normalize(clones.length / 2, true)); 11859 append = append + items[clones[clones.length - 1]][0].outerHTML; 11860 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 11861 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 11862 } 11863 11864 this._clones = clones; 11865 11866 // var appendVideo = $(append).find('.uncode-video-container'); 11867 // if (appendVideo.length) { 11868 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 11869 // } 11870 // var prependVideo = $(prepend).find('.uncode-video-container'); 11871 // if (prependVideo.length) { 11872 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 11873 // } 11874 $(append).addClass('cloned').appendTo(this.$stage); 11875 $(prepend).addClass('cloned').prependTo(this.$stage); 11876 } 11877 }, { 11878 filter: [ 'width', 'items', 'settings' ], 11879 run: function() { 11880 var rtl = this.settings.rtl ? 1 : -1, 11881 size = this._clones.length + this._items.length, 11882 iterator = -1, 11883 previous = 0, 11884 current = 0, 11885 coordinates = []; 11886 11887 while (++iterator < size) { 11888 previous = coordinates[iterator - 1] || 0; 11889 current = this._widths[this.relative(iterator)] + this.settings.margin; 11890 coordinates.push(previous + current * rtl); 11891 } 11892 11893 this._coordinates = coordinates; 11894 } 11895 }, { 11896 filter: [ 'width', 'items', 'settings' ], 11897 run: function() { 11898 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 11899 padding = stagePadding, 11900 coordinates = this._coordinates, 11901 css = { 11902 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 11903 'padding-left': padding || '', 11904 'padding-right': padding || '' 11905 }; 11906 11907 this.$stage.css(css); 11908 } 11909 }, { 11910 filter: [ 'width', 'items', 'settings' ], 11911 run: function(cache) { 11912 var iterator = this._coordinates.length, 11913 grid = !this.settings.autoWidth, 11914 items = this.$stage.children(); 11915 11916 if (grid && cache.items.merge) { 11917 while (iterator--) { 11918 cache.css.width = this._widths[this.relative(iterator)]; 11919 items.eq(iterator).css(cache.css); 11920 } 11921 } else if (grid) { 11922 cache.css.width = cache.items.width; 11923 items.css(cache.css); 11924 } 11925 } 11926 }, { 11927 filter: [ 'items' ], 11928 run: function() { 11929 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 11930 } 11931 }, { 11932 filter: [ 'width', 'items', 'settings' ], 11933 run: function(cache) { 11934 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 11935 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 11936 this.reset(cache.current); 11937 } 11938 }, { 11939 filter: [ 'position' ], 11940 run: function() { 11941 this.animate(this.coordinates(this._current)); 11942 } 11943 }, { 11944 filter: [ 'width', 'position', 'items', 'settings' ], 11945 run: function() { 11946 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 11947 rtl = this.settings.rtl ? 1 : -1, 11948 padding = this.settings.stagePadding * 2, 11949 begin = this.coordinates(this.current()) + padding, 11950 end = begin + this.width() * rtl, 11951 inner, outer, matches = [], i, n; 11952 11953 for (i = 0, n = this._coordinates.length; i < n; i++) { 11954 inner = this._coordinates[i - 1] || 0; 11955 outer = Math.abs(this._coordinates[i]) + padding * rtl; 11956 11957 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 11958 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 11959 matches.push(i); 11960 } 11961 } 11962 11963 this.$stage.children('.active').removeClass('active'); 11964 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 11965 11966 if (this.settings.center) { 11967 this.$stage.children('.center').removeClass('center'); 11968 this.$stage.children().eq(this.current()).addClass('center'); 11969 } 11970 } 11971 } ]; 11972 11973 /** 11974 * Initializes the carousel. 11975 * @protected 11976 */ 11977 Owl.prototype.initialize = function() { 11978 this.enter('initializing'); 11979 this.trigger('initialize'); 11980 11981 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 11982 11983 if (this.settings.autoWidth && !this.is('pre-loading')) { 11984 var imgs, nestedSelector, width; 11985 imgs = this.$element.find('img'); 11986 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 11987 width = this.$element.children(nestedSelector).width(); 11988 11989 if (imgs.length && width <= 0) { 11990 this.preloadAutoWidthImages(imgs); 11991 } 11992 } 11993 11994 this.$element.addClass(this.options.loadingClass); 11995 11996 // create stage 11997 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 11998 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 11999 12000 // append stage 12001 this.$element.append(this.$stage.parent()); 12002 12003 // append content 12004 this.replace(this.$element.children().not(this.$stage.parent())); 12005 12006 // check visibility 12007 if (this.$element.is(':visible')) { 12008 // update view 12009 this.refresh(); 12010 } else { 12011 // invalidate width 12012 this.invalidate('width'); 12013 } 12014 12015 this.$element 12016 .removeClass(this.options.loadingClass) 12017 .addClass(this.options.loadedClass); 12018 12019 // register event handlers 12020 this.registerEventHandlers(); 12021 12022 this.leave('initializing'); 12023 this.trigger('initialized'); 12024 }; 12025 12026 /** 12027 * Setups the current settings. 12028 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 12029 * @todo Support for media queries by using `matchMedia` would be nice. 12030 * @public 12031 */ 12032 Owl.prototype.setup = function() { 12033 var viewport = this.viewport(),
12034 overwrites = this.options.responsive, 12035 match = -1, 12036 settings = null; 12037 12038 if (!overwrites) { 12039 settings = $.extend({}, this.options); 12040 } else { 12041 $.each(overwrites, function(breakpoint) { 12042 if (breakpoint <= viewport && breakpoint > match) { 12043 match = Number(breakpoint); 12044 } 12045 }); 12046 12047 settings = $.extend({}, this.options, overwrites[match]); 12048 delete settings.responsive; 12049 12050 // responsive class 12051 if (settings.responsiveClass) { 12052 this.$element.attr('class', 12053 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 12054 ); 12055 } 12056 } 12057 12058 if (this.settings === null || this._breakpoint !== match) { 12059 this.trigger('change', { property: { name: 'settings', value: settings } }); 12060 this._breakpoint = match; 12061 this.settings = settings; 12062 this.invalidate('settings'); 12063 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 12064 } 12065 }; 12066 12067 /** 12068 * Updates option logic if necessery. 12069 * @protected 12070 */ 12071 Owl.prototype.optionsLogic = function() { 12072 if (this.settings.autoWidth) { 12073 this.settings.stagePadding = false; 12074 this.settings.merge = false; 12075 } 12076 }; 12077 12078 /** 12079 * Prepares an item before add. 12080 * @todo Rename event parameter `content` to `item`. 12081 * @protected 12082 * @returns {jQuery|HTMLElement} - The item container. 12083 */ 12084 Owl.prototype.prepare = function(item, index) { 12085 var event = this.trigger('prepare', { content: item }); 12086 if (!event.data) { 12087 event.data = $('<' + this.settings.itemElement + '/>') 12088 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 12089 } 12090 12091 this.trigger('prepared', { content: event.data }); 12092 12093 return event.data; 12094 }; 12095 12096 /** 12097 * Updates the view. 12098 * @public 12099 */ 12100 Owl.prototype.update = function() { 12101 var i = 0, 12102 n = this._pipe.length, 12103 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 12104 cache = {}; 12105 12106 while (i < n) { 12107 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 12108 this._pipe[i].run(cache); 12109 } 12110 i++; 12111 } 12112 12113 this._invalidated = {}; 12114 12115 !this.is('valid') && this.enter('valid'); 12116 }; 12117 12118 /** 12119 * Gets the width of the view. 12120 * @public 12121 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 12122 * @returns {Number} - The width of the view in pixel. 12123 */ 12124 Owl.prototype.width = function(dimension) { 12125 dimension = dimension || Owl.Width.Default; 12126 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 12127 switch (dimension) { 12128 case Owl.Width.Inner: 12129 case Owl.Width.Outer: 12130 return this._width; 12131 default: 12132 return this._width - stagePadding * 2 + this.settings.margin; 12133 } 12134 }; 12135 12136 /** 12137 * Refreshes the carousel primarily for adaptive purposes. 12138 * @public 12139 */ 12140 Owl.prototype.refresh = function() { 12141 this.enter('refreshing'); 12142 this.trigger('refresh'); 12143 12144 this.setup(); 12145 12146 this.optionsLogic(); 12147 12148 this.$element.addClass(this.options.refreshClass); 12149 12150 this.update(); 12151 12152 this.$element.removeClass(this.options.refreshClass); 12153 12154 this.leave('refreshing'); 12155 this.trigger('refreshed'); 12156 }; 12157 12158 /** 12159 * Checks window `resize` event. 12160 * @protected 12161 */ 12162 Owl.prototype.onThrottledResize = function() { 12163 window.clearTimeout(this.resizeTimer); 12164 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 12165 }; 12166 12167 /** 12168 * Checks window `resize` event. 12169 * @protected 12170 */ 12171 Owl.prototype.onResize = function() { 12172 if (!this._items.length) { 12173 return false; 12174 } 12175 12176 if (this._width === this.$element.width()) { 12177 return false; 12178 } 12179 12180 if (!this.$element.is(':visible')) { 12181 return false; 12182 } 12183 12184 this.enter('resizing'); 12185 12186 if (this.trigger('resize').isDefaultPrevented()) { 12187 this.leave('resizing'); 12188 return false; 12189 } 12190 12191 this.invalidate('width'); 12192 12193 this.refresh(); 12194 12195 this.leave('resizing'); 12196 this.trigger('resized'); 12197 }; 12198 12199 /** 12200 * Registers event handlers. 12201 * @todo Check `msPointerEnabled` 12202 * @todo #261 12203 * @protected 12204 */ 12205 Owl.prototype.registerEventHandlers = function() { 12206 if ($.support.transition) { 12207 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 12208 } 12209 12210 if (this.settings.responsive !== false) { 12211 this.on(window, 'resize', this._handlers.onThrottledResize); 12212 } 12213 12214 if (this.settings.mouseDrag) { 12215 this.$element.addClass(this.options.dragClass); 12216 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 12217 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 12218 } 12219 12220 if (this.settings.touchDrag){ 12221 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 12222 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 12223 } 12224 }; 12225 12226 /** 12227 * Handles `touchstart` and `mousedown` events. 12228 * @todo Horizontal swipe threshold as option 12229 * @todo #261 12230 * @protected 12231 * @param {Event} event - The event arguments. 12232 */ 12233 Owl.prototype.onDragStart = function(event) { 12234 var stage = null; 12235 12236 if (event.which === 3) { 12237 return; 12238 } 12239
vendor: 9,106 bytes, lines 12240-12555
12240 if ($.support.transform) { 12241 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 12242 stage = { 12243 x: stage[stage.length === 16 ? 12 : 4], 12244 y: stage[stage.length === 16 ? 13 : 5] 12245 }; 12246 } else { 12247 stage = this.$stage.position(); 12248 stage = { 12249 x: this.settings.rtl ? 12250 stage.left + this.$stage.width() - this.width() + this.settings.margin : 12251 stage.left, 12252 y: stage.top 12253 }; 12254 } 12255 12256 if (this.is('animating')) { 12257 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 12258 this.invalidate('position'); 12259 } 12260 12261 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 12262 12263 this.speed(0); 12264 12265 this._drag.time = new Date().getTime(); 12266 this._drag.target = $(event.target); 12267 this._drag.stage.start = stage; 12268 this._drag.stage.current = stage; 12269 this._drag.pointer = this.pointer(event); 12270 12271 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 12272 12273 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 12274 var delta = this.difference(this._drag.pointer, this.pointer(event)); 12275 12276 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 12277 12278 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 12279 return; 12280 } 12281 12282 event.preventDefault(); 12283 12284 this.enter('dragging'); 12285 this.trigger('drag'); 12286 }, this)); 12287 }; 12288 12289 /** 12290 * Handles the `touchmove` and `mousemove` events. 12291 * @todo #261 12292 * @protected 12293 * @param {Event} event - The event arguments. 12294 */ 12295 Owl.prototype.onDragMove = function(event) { 12296 var minimum = null, 12297 maximum = null, 12298 pull = null, 12299 delta = this.difference(this._drag.pointer, this.pointer(event)), 12300 stage = this.difference(this._drag.stage.start, delta); 12301 12302 if (!this.is('dragging')) { 12303 return; 12304 } 12305 12306 event.preventDefault(); 12307 12308 if (this.settings.loop) { 12309 minimum = this.coordinates(this.minimum()); 12310 maximum = this.coordinates(this.maximum() + 1) - minimum; 12311 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 12312 } else { 12313 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 12314 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 12315 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 12316 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 12317 } 12318 12319 this._drag.stage.current = stage; 12320 12321 this.animate(stage.x); 12322 }; 12323 12324 /** 12325 * Handles the `touchend` and `mouseup` events. 12326 * @todo #261 12327 * @todo Threshold for click event 12328 * @protected 12329 * @param {Event} event - The event arguments. 12330 */ 12331 Owl.prototype.onDragEnd = function(event) { 12332 var delta = this.difference(this._drag.pointer, this.pointer(event)), 12333 stage = this._drag.stage.current, 12334 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 12335 12336 $(document).off('.owl.core'); 12337 12338 this.$element.removeClass(this.options.grabClass); 12339 12340 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 12341 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 12342 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 12343 this.invalidate('position'); 12344 this.update(); 12345 12346 this._drag.direction = direction; 12347 12348 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 12349 this._drag.target.one('click.owl.core', function() { return false; }); 12350 } 12351 } 12352 12353 if (!this.is('dragging')) { 12354 return; 12355 } 12356 12357 this.leave('dragging'); 12358 this.trigger('dragged'); 12359 }; 12360 12361 /** 12362 * Gets absolute position of the closest item for a coordinate. 12363 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 12364 * @protected 12365 * @param {Number} coordinate - The coordinate in pixel. 12366 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 12367 * @return {Number} - The absolute position of the closest item. 12368 */ 12369 Owl.prototype.closest = function(coordinate, direction) { 12370 var position = -1, 12371 pull = 30, 12372 width = this.width(), 12373 coordinates = this.coordinates(); 12374 12375 if (!this.settings.freeDrag) { 12376 // check closest item 12377 $.each(coordinates, $.proxy(function(index, value) { 12378 if (coordinate > value - pull && coordinate < value + pull) { 12379 position = index; 12380 } else if (this.op(coordinate, '<', value) 12381 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 12382 position = direction === 'left' ? index + 1 : index; 12383 } 12384 return position === -1; 12385 }, this)); 12386 } 12387 12388 if (!this.settings.loop) { 12389 // non loop boundries 12390 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 12391 position = coordinate = this.minimum(); 12392 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 12393 position = coordinate = this.maximum(); 12394 } 12395 } 12396 12397 return position; 12398 }; 12399 12400 /** 12401 * Animates the stage. 12402 * @todo #270 12403 * @public 12404 * @param {Number} coordinate - The coordinate in pixels. 12405 */ 12406 Owl.prototype.animate = function(coordinate) { 12407 var animate = this.speed() > 0; 12408 12409 this.is('animating') && this.onTransitionEnd(); 12410 12411 if (animate) { 12412 this.enter('animating'); 12413 this.trigger('translate'); 12414 } 12415 12416 if ($.support.transform3d && $.support.transition) { 12417 this.$stage.css({ 12418 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 12419 transition: (this.speed() / 1000) + 's' 12420 }); 12421 } else if (animate) { 12422 this.$stage.animate({ 12423 left: coordinate + 'px' 12424 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 12425 } else { 12426 this.$stage.css({ 12427 left: coordinate + 'px' 12428 }); 12429 } 12430 }; 12431 12432 /** 12433 * Checks whether the carousel is in a specific state or not. 12434 * @param {String} state - The state to check. 12435 * @returns {Boolean} - The flag which indicates if the carousel is busy. 12436 */ 12437 Owl.prototype.is = function(state) { 12438 return this._states.current[state] && this._states.current[state] > 0; 12439 }; 12440 12441 /** 12442 * Sets the absolute position of the current item. 12443 * @public 12444 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 12445 * @returns {Number} - The absolute position of the current item. 12446 */ 12447 Owl.prototype.current = function(position) { 12448 if (position === undefined) { 12449 return this._current; 12450 } 12451 12452 if (this._items.length === 0) { 12453 return undefined; 12454 } 12455 12456 position = this.normalize(position); 12457 12458 if (this._current !== position) { 12459 var event = this.trigger('change', { property: { name: 'position', value: position } }); 12460 12461 if (event.data !== undefined) { 12462 position = this.normalize(event.data); 12463 } 12464 12465 this._current = position; 12466 12467 this.invalidate('position'); 12468 12469 this.trigger('changed', { property: { name: 'position', value: this._current } }); 12470 } 12471 12472 return this._current; 12473 }; 12474 12475 /** 12476 * Invalidates the given part of the update routine. 12477 * @param {String} [part] - The part to invalidate. 12478 * @returns {Array.<String>} - The invalidated parts. 12479 */ 12480 Owl.prototype.invalidate = function(part) { 12481 if ($.type(part) === 'string') { 12482 this._invalidated[part] = true; 12483 this.is('valid') && this.leave('valid'); 12484 } 12485 return $.map(this._invalidated, function(v, i) { return i }); 12486 }; 12487 12488 /** 12489 * Resets the absolute position of the current item. 12490 * @public 12491 * @param {Number} position - The absolute position of the new item. 12492 */ 12493 Owl.prototype.reset = function(position) { 12494 position = this.normalize(position); 12495 12496 if (position === undefined) { 12497 return; 12498 } 12499 12500 this._speed = 0; 12501 this._current = position; 12502 12503 this.suppress([ 'translate', 'translated' ]); 12504 12505 this.animate(this.coordinates(position)); 12506 12507 this.release([ 'translate', 'translated' ]); 12508 }; 12509 12510 /** 12511 * Normalizes an absolute or a relative position of an item. 12512 * @public 12513 * @param {Number} position - The absolute or relative position to normalize. 12514 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 12515 * @returns {Number} - The normalized position. 12516 */ 12517 Owl.prototype.normalize = function(position, relative) { 12518 var n = this._items.length, 12519 m = relative ? 0 : this._clones.length; 12520 12521 if (!$.isNumeric(position) || n < 1) { 12522 position = undefined; 12523 } else if (position < 0 || position >= n + m) { 12524 position = ((position - m / 2) % n + n) % n + m / 2; 12525 } 12526 12527 return position; 12528 }; 12529 12530 /** 12531 * Converts an absolute position of an item into a relative one. 12532 * @public 12533 * @param {Number} position - The absolute position to convert. 12534 * @returns {Number} - The converted position. 12535 */ 12536 Owl.prototype.relative = function(position) { 12537 position -= this._clones.length / 2; 12538 return this.normalize(position, true); 12539 }; 12540 12541 /** 12542 * Gets the maximum position for the current item. 12543 * @public 12544 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 12545 * @returns {Number} 12546 */ 12547 Owl.prototype.maximum = function(relative) { 12548 var settings = this.settings, 12549 maximum = this._coordinates.length, 12550 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 12551 i = -1, j; 12552 12553 if (settings.loop) { 12554 maximum = this._clones.length / 2 + this._items.length - 1; 12555 } else if (settings.autoWidth || settings.merge) {
12556 // binary search 12557 while (maximum - i > 1) { 12558 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 12559 ? i = j : maximum = j; 12560 } 12561 } else if (settings.center) { 12562 maximum = this._items.length - 1; 12563 } else { 12564 maximum = this._items.length - settings.items; 12565 } 12566 12567 if (relative) { 12568 maximum -= this._clones.length / 2; 12569 } 12570 12571 return Math.max(maximum, 0); 12572 }; 12573 12574 /** 12575 * Gets the minimum position for the current item. 12576 * @public 12577 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 12578 * @returns {Number} 12579 */ 12580 Owl.prototype.minimum = function(relative) { 12581 return relative ? 0 : this._clones.length / 2; 12582 }; 12583 12584 /** 12585 * Gets an item at the specified relative position. 12586 * @public 12587 * @param {Number} [position] - The relative position of the item. 12588 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 12589 */ 12590 Owl.prototype.items = function(position) { 12591 if (position === undefined) { 12592 return this._items.slice(); 12593 } 12594 12595 position = this.normalize(position, true); 12596 return this._items[position]; 12597 }; 12598 12599 /** 12600 * Gets an item at the specified relative position. 12601 * @public 12602 * @param {Number} [position] - The relative position of the item. 12603 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 12604 */ 12605 Owl.prototype.mergers = function(position) { 12606 if (position === undefined) { 12607 return this._mergers.slice(); 12608 } 12609 12610 position = this.normalize(position, true); 12611 return this._mergers[position]; 12612 }; 12613 12614 /** 12615 * Gets the absolute positions of clones for an item. 12616 * @public 12617 * @param {Number} [position] - The relative position of the item. 12618 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 12619 */ 12620 Owl.prototype.clones = function(position) { 12621 var odd = this._clones.length / 2, 12622 even = odd + this._items.length, 12623 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 12624 12625 if (position === undefined) { 12626 return $.map(this._clones, function(v, i) { return map(i) }); 12627 } 12628 12629 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 12630 }; 12631 12632 /** 12633 * Sets the current animation speed. 12634 * @public 12635 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 12636 * @returns {Number} - The current animation speed in milliseconds. 12637 */ 12638 Owl.prototype.speed = function(speed) { 12639 if (speed !== undefined) { 12640 this._speed = speed; 12641 } 12642 12643 return this._speed; 12644 }; 12645 12646 /** 12647 * Gets the coordinate of an item. 12648 * @todo The name of this method is missleanding. 12649 * @public 12650 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 12651 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 12652 */ 12653 Owl.prototype.coordinates = function(position) { 12654 var coordinate = null; 12655 12656 if (position === undefined) { 12657 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 12658 return this.coordinates(index); 12659 }, this)); 12660 } 12661 12662 if (this.settings.center) { 12663 coordinate = this._coordinates[position]; 12664 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 12665 } else { 12666 coordinate = this._coordinates[position - 1] || 0; 12667 } 12668 12669 return coordinate; 12670 }; 12671 12672 /** 12673 * Calculates the speed for a translation. 12674 * @protected 12675 * @param {Number} from - The absolute position of the start item. 12676 * @param {Number} to - The absolute position of the target item. 12677 * @param {Number} [factor=undefined] - The time factor in milliseconds. 12678 * @returns {Number} - The time in milliseconds for the translation. 12679 */ 12680 Owl.prototype.duration = function(from, to, factor) { 12681 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 12682 }; 12683 12684 /** 12685 * Slides to the specified item. 12686 * @public 12687 * @param {Number} position - The position of the item. 12688 * @param {Number} [speed] - The time in milliseconds for the transition. 12689 */ 12690 Owl.prototype.to = function(position, speed) { 12691 var current = this.current(), 12692 revert = null, 12693 distance = position - this.relative(current), 12694 direction = (distance > 0) - (distance < 0), 12695 items = this._items.length, 12696 minimum = this.minimum(), 12697 maximum = this.maximum(); 12698 12699 if (this.settings.loop) { 12700 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 12701 distance += direction * -1 * items; 12702 } 12703 12704 position = current + distance; 12705 revert = ((position - minimum) % items + items) % items + minimum; 12706 12707 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 12708 current = revert - distance; 12709 position = revert; 12710 this.reset(current); 12711 } 12712 } else if (this.settings.rewind) { 12713 maximum += 1; 12714 position = (position % maximum + maximum) % maximum; 12715 } else { 12716 position = Math.max(minimum, Math.min(maximum, position)); 12717 } 12718 12719 this.speed(this.duration(current, position, speed)); 12720 this.current(position); 12721 12722 if (this.$element.is(':visible')) { 12723 this.update(); 12724 } 12725 }; 12726 12727 /** 12728 * Slides to the next item. 12729 * @public 12730 * @param {Number}
vendor: 12,284 bytes, lines 12730-13150
12730 [speed] - The time in milliseconds for the transition. 12731 */ 12732 Owl.prototype.next = function(speed) { 12733 speed = speed || false; 12734 this.to(this.relative(this.current()) + 1, speed); 12735 }; 12736 12737 /** 12738 * Slides to the previous item. 12739 * @public 12740 * @param {Number} [speed] - The time in milliseconds for the transition. 12741 */ 12742 Owl.prototype.prev = function(speed) { 12743 speed = speed || false; 12744 this.to(this.relative(this.current()) - 1, speed); 12745 }; 12746 12747 /** 12748 * Handles the end of an animation. 12749 * @protected 12750 * @param {Event} event - The event arguments. 12751 */ 12752 Owl.prototype.onTransitionEnd = function(event) { 12753 12754 // if css2 animation then event object is undefined 12755 if (event !== undefined) { 12756 event.stopPropagation(); 12757 12758 // Catch only owl-stage transitionEnd event 12759 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 12760 return false; 12761 } 12762 } 12763 12764 this.leave('animating'); 12765 this.trigger('translated'); 12766 }; 12767 12768 /** 12769 * Gets viewport width. 12770 * @protected 12771 * @return {Number} - The width in pixel. 12772 */ 12773 Owl.prototype.viewport = function() { 12774 var width; 12775 if (this.options.responsiveBaseElement !== window) { 12776 width = $(this.options.responsiveBaseElement).width(); 12777 } else if (window.innerWidth) { 12778 width = window.innerWidth; 12779 } else if (document.documentElement && document.documentElement.clientWidth) { 12780 width = document.documentElement.clientWidth; 12781 } else { 12782 throw 'Can not detect viewport width.'; 12783 } 12784 12785 return width; 12786 }; 12787 12788 /** 12789 * Replaces the current content. 12790 * @public 12791 * @param {HTMLElement|jQuery|String} content - The new content. 12792 */ 12793 Owl.prototype.replace = function(content) { 12794 this.$stage.empty(); 12795 this._items = []; 12796 12797 if (content) { 12798 content = (content instanceof jQuery) ? content : $(content); 12799 } 12800 12801 if (this.settings.nestedItemSelector) { 12802 content = content.find('.' + this.settings.nestedItemSelector); 12803 } 12804 12805 content.filter(function() { 12806 return this.nodeType === 1; 12807 }).each($.proxy(function(index, item) { 12808 item = this.prepare(item, index); 12809 this.$stage.append(item); 12810 this._items.push(item); 12811 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 12812 }, this)); 12813 12814 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 12815 12816 this.invalidate('items'); 12817 }; 12818 12819 /** 12820 * Adds an item. 12821 * @todo Use `item` instead of `content` for the event arguments. 12822 * @public 12823 * @param {HTMLElement|jQuery|String} content - The item content to add. 12824 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 12825 */ 12826 Owl.prototype.add = function(content, position) { 12827 var current = this.relative(this._current); 12828 12829 position = position === undefined ? this._items.length : this.normalize(position, true); 12830 content = content instanceof jQuery ? content : $(content); 12831 12832 this.trigger('add', { content: content, position: position }); 12833 12834 content = this.prepare(content, this._items[current].index()); 12835 12836 if (this._items.length === 0 || position === this._items.length) { 12837 this._items.length === 0 && this.$stage.append(content); 12838 this._items.length !== 0 && this._items[position - 1].after(content); 12839 this._items.push(content); 12840 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 12841 } else { 12842 this._items[position].before(content); 12843 this._items.splice(position, 0, content); 12844 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 12845 } 12846 12847 this._items[current] && this.reset(this._items[current].index()); 12848 12849 this.invalidate('items'); 12850 12851 this.trigger('added', { content: content, position: position }); 12852 }; 12853 12854 /** 12855 * Removes an item by its position. 12856 * @todo Use `item` instead of `content` for the event arguments. 12857 * @public 12858 * @param {Number} position - The relative position of the item to remove. 12859 */ 12860 Owl.prototype.remove = function(position) { 12861 position = this.normalize(position, true); 12862 12863 if (position === undefined) { 12864 return; 12865 } 12866 12867 this.trigger('remove', { content: this._items[position], position: position }); 12868 12869 this._items[position].remove(); 12870 this._items.splice(position, 1); 12871 this._mergers.splice(position, 1); 12872 12873 this.invalidate('items'); 12874 12875 this.trigger('removed', { content: null, position: position }); 12876 }; 12877 12878 /** 12879 * Preloads images with auto width. 12880 * @todo Replace by a more generic approach 12881 * @protected 12882 */ 12883 Owl.prototype.preloadAutoWidthImages = function(images) { 12884 images.each($.proxy(function(i, element) { 12885 this.enter('pre-loading'); 12886 element = $(element); 12887 $(new Image()).one('load', $.proxy(function(e) { 12888 element.attr('src', e.target.src); 12889 element.css('opacity', 1); 12890 this.leave('pre-loading'); 12891 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 12892 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 12893 }, this)); 12894 }; 12895 12896 /** 12897 * Destroys the carousel. 12898 * @public 12899 */ 12900 Owl.prototype.destroy = function() { 12901 12902 this.$element.off('.owl.core'); 12903 this.$stage.off('.owl.core'); 12904 $(document).off('.owl.core'); 12905 12906 if (this.settings.responsive !== false) { 12907 window.clearTimeout(this.resizeTimer); 12908 this.off(window, 'resize', this._handlers.onThrottledResize); 12909 } 12910 12911 for (var i in this._plugins) { 12912 this._plugins[i].destroy(); 12913 } 12914 12915 this.$stage.children('.cloned').remove(); 12916 12917 this.$stage.unwrap(); 12918 this.$stage.children().contents().unwrap(); 12919 this.$stage.children().unwrap(); 12920 12921 this.$element 12922 .removeClass(this.options.refreshClass) 12923 .removeClass(this.options.loadingClass) 12924 .removeClass(this.options.loadedClass) 12925 .removeClass(this.options.rtlClass) 12926 .removeClass(this.options.dragClass) 12927 .removeClass(this.options.grabClass) 12928 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 12929 .removeData('owl.carousel'); 12930 }; 12931 12932 /** 12933 * Operators to calculate right-to-left and left-to-right. 12934 * @protected 12935 * @param {Number} [a] - The left side operand. 12936 * @param {String} [o] - The operator. 12937 * @param {Number} [b] - The right side operand. 12938 */ 12939 Owl.prototype.op = function(a, o, b) { 12940 var rtl = this.settings.rtl; 12941 switch (o) { 12942 case '<': 12943 return rtl ? a > b : a < b; 12944 case '>': 12945 return rtl ? a < b : a > b; 12946 case '>=': 12947 return rtl ? a <= b : a >= b; 12948 case '<=': 12949 return rtl ? a >= b : a <= b; 12950 default: 12951 break; 12952 } 12953 }; 12954 12955 /** 12956 * Attaches to an internal event. 12957 * @protected 12958 * @param {HTMLElement} element - The event source. 12959 * @param {String} event - The event name. 12960 * @param {Function} listener - The event handler to attach. 12961 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 12962 */ 12963 Owl.prototype.on = function(element, event, listener, capture) { 12964 if (element.addEventListener) { 12965 element.addEventListener(event, listener, capture); 12966 } else if (element.attachEvent) { 12967 element.attachEvent('on' + event, listener); 12968 } 12969 }; 12970 12971 /** 12972 * Detaches from an internal event. 12973 * @protected 12974 * @param {HTMLElement} element - The event source. 12975 * @param {String} event - The event name. 12976 * @param {Function} listener - The attached event handler to detach. 12977 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 12978 */ 12979 Owl.prototype.off = function(element, event, listener, capture) { 12980 if (element.removeEventListener) { 12981 element.removeEventListener(event, listener, capture); 12982 } else if (element.detachEvent) { 12983 element.detachEvent('on' + event, listener); 12984 } 12985 }; 12986 12987 /** 12988 * Triggers a public event. 12989 * @todo Remove `status`, `relatedTarget` should be used instead. 12990 * @protected 12991 * @param {String} name - The event name. 12992 * @param {*} [data=null] - The event data. 12993 * @param {String} [namespace=carousel] - The event namespace. 12994 * @param {String} [state] - The state which is associated with the event. 12995 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 12996 * @returns {Event} - The event arguments. 12997 */ 12998 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 12999 var status = { 13000 item: { count: this._items.length, index: this.current() } 13001 }, handler = $.camelCase( 13002 $.grep([ 'on', name, namespace ], function(v) { return v }) 13003 .join('-').toLowerCase() 13004 ), event = $.Event( 13005 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 13006 $.extend({ relatedTarget: this }, status, data) 13007 ); 13008 13009 if (!this._supress[name]) { 13010 $.each(this._plugins, function(name, plugin) { 13011 if (plugin.onTrigger) { 13012 plugin.onTrigger(event); 13013 } 13014 }); 13015 13016 this.register({ type: Owl.Type.Event, name: name }); 13017 this.$element.trigger(event); 13018 13019 if (this.settings && typeof this.settings[handler] === 'function') { 13020 this.settings[handler].call(this, event); 13021 } 13022 } 13023 13024 return event; 13025 }; 13026 13027 /** 13028 * Enters a state. 13029 * @param name - The state name. 13030 */ 13031 Owl.prototype.enter = function(name) { 13032 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 13033 if (this._states.current[name] === undefined) { 13034 this._states.current[name] = 0; 13035 } 13036 13037 this._states.current[name]++; 13038 }, this)); 13039 }; 13040 13041 /** 13042 * Leaves a state. 13043 * @param name - The state name. 13044 */ 13045 Owl.prototype.leave = function(name) { 13046 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 13047 this._states.current[name]--; 13048 }, this)); 13049 }; 13050 13051 /** 13052 * Registers an event or state. 13053 * @public 13054 * @param {Object} object - The event or state to register. 13055 */ 13056 Owl.prototype.register = function(object) { 13057 if (object.type === Owl.Type.Event) { 13058 if (!$.event.special[object.name]) { 13059 $.event.special[object.name] = {}; 13060 } 13061 13062 if (!$.event.special[object.name].owl) { 13063 var _default = $.event.special[object.name]._default; 13064 $.event.special[object.name]._default = function(e) { 13065 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 13066 return _default.apply(this, arguments); 13067 } 13068 return e.namespace && e.namespace.indexOf('owl') > -1; 13069 }; 13070 $.event.special[object.name].owl = true; 13071 } 13072 } else if (object.type === Owl.Type.State) { 13073 if (!this._states.tags[object.name]) { 13074 this._states.tags[object.name] = object.tags; 13075 } else { 13076 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 13077 } 13078 13079 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 13080 return $.inArray(tag, this._states.tags[object.name]) === i; 13081 }, this)); 13082 } 13083 }; 13084 13085 /** 13086 * Suppresses events. 13087 * @protected 13088 * @param {Array.<String>} events - The events to suppress. 13089 */ 13090 Owl.prototype.suppress = function(events) { 13091 $.each(events, $.proxy(function(index, event) { 13092 this._supress[event] = true; 13093 }, this)); 13094 }; 13095 13096 /** 13097 * Releases suppressed events. 13098 * @protected 13099 * @param {Array.<String>} events - The events to release. 13100 */ 13101 Owl.prototype.release = function(events) { 13102 $.each(events, $.proxy(function(index, event) { 13103 delete this._supress[event]; 13104 }, this)); 13105 }; 13106 13107 /** 13108 * Gets unified pointer coordinates from event. 13109 * @todo #261 13110 * @protected 13111 * @param {Event} - The `mousedown` or `touchstart` event. 13112 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 13113 */ 13114 Owl.prototype.pointer = function(event) { 13115 var result = { x: null, y: null }; 13116 13117 event = event.originalEvent || event || window.event; 13118 13119 event = event.touches && event.touches.length ? 13120 event.touches[0] : event.changedTouches && event.changedTouches.length ? 13121 event.changedTouches[0] : event; 13122 13123 if (event.pageX) { 13124 result.x = event.pageX; 13125 result.y = event.pageY; 13126 } else { 13127 result.x = event.clientX; 13128 result.y = event.clientY; 13129 } 13130 13131 return result; 13132 }; 13133 13134 /** 13135 * Gets the difference of two vectors. 13136 * @todo #261 13137 * @protected 13138 * @param {Object} - The first vector. 13139 * @param {Object} - The second vector. 13140 * @returns {Object} - The difference. 13141 */ 13142 Owl.prototype.difference = function(first, second) { 13143 return { 13144 x: first.x - second.x, 13145 y: first.y - second.y 13146 }; 13147 }; 13148 13149 /** 13150 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 13151-14433
13151 * @todo Navigation plugin `next` and `prev` 13152 * @public 13153 */ 13154 $.fn.owlCarousel = function(option) { 13155 var args = Array.prototype.slice.call(arguments, 1); 13156 13157 return this.each(function() { 13158 var $this = $(this), 13159 data = $this.data('owl.carousel'); 13160 13161 if (!data) { 13162 data = new Owl(this, typeof option == 'object' && option); 13163 $this.data('owl.carousel', data); 13164 13165 $.each([ 13166 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 13167 ], function(i, event) { 13168 data.register({ type: Owl.Type.Event, name: event }); 13169 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 13170 if (e.namespace && e.relatedTarget !== this) { 13171 this.suppress([ event ]); 13172 data[event].apply(this, [].slice.call(arguments, 1)); 13173 this.release([ event ]); 13174 } 13175 }, data)); 13176 }); 13177 } 13178 13179 if (typeof option == 'string' && option.charAt(0) !== '_') { 13180 data[option].apply(data, args); 13181 } 13182 }); 13183 }; 13184 13185 /** 13186 * The constructor for the jQuery Plugin 13187 * @public 13188 */ 13189 $.fn.owlCarousel.Constructor = Owl; 13190 13191})(window.Zepto || window.jQuery, window, document); 13192 13193/** 13194 * AutoRefresh Plugin 13195 * @version 2.0.0-beta.3 13196 * @author Artus Kolanowski 13197 * @license The MIT License (MIT) 13198 */ 13199;(function($, window, document, undefined) { 13200 13201 /** 13202 * Creates the auto refresh plugin. 13203 * @class The Auto Refresh Plugin 13204 * @param {Owl} carousel - The Owl Carousel 13205 */ 13206 var AutoRefresh = function(carousel) { 13207 /** 13208 * Reference to the core. 13209 * @protected 13210 * @type {Owl} 13211 */ 13212 this._core = carousel; 13213 13214 /** 13215 * Refresh interval. 13216 * @protected 13217 * @type {number} 13218 */ 13219 this._interval = null; 13220 13221 /** 13222 * Whether the element is currently visible or not. 13223 * @protected 13224 * @type {Boolean} 13225 */ 13226 this._visible = null; 13227 13228 /** 13229 * All event handlers. 13230 * @protected 13231 * @type {Object} 13232 */ 13233 this._handlers = { 13234 'initialized.owl.carousel': $.proxy(function(e) { 13235 if (e.namespace && this._core.settings.autoRefresh) { 13236 this.watch(); 13237 } 13238 }, this) 13239 }; 13240 13241 // set default options 13242 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 13243 13244 // register event handlers 13245 this._core.$element.on(this._handlers); 13246 }; 13247 13248 /** 13249 * Default options. 13250 * @public 13251 */ 13252 AutoRefresh.Defaults = { 13253 autoRefresh: true, 13254 autoRefreshInterval: 500 13255 }; 13256 13257 /** 13258 * Watches the element. 13259 */ 13260 AutoRefresh.prototype.watch = function() { 13261 if (this._interval) { 13262 return; 13263 } 13264 13265 this._visible = this._core.$element.is(':visible'); 13266 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 13267 }; 13268 13269 /** 13270 * Refreshes the element. 13271 */ 13272 AutoRefresh.prototype.refresh = function() { 13273 if (this._core.$element.is(':visible') === this._visible) { 13274 return; 13275 } 13276 13277 this._visible = !this._visible; 13278 13279 this._core.$element.toggleClass('owl-hidden', !this._visible); 13280 13281 this._visible && (this._core.invalidate('width') && this._core.refresh()); 13282 }; 13283 13284 /** 13285 * Destroys the plugin. 13286 */ 13287 AutoRefresh.prototype.destroy = function() { 13288 var handler, property; 13289 13290 window.clearInterval(this._interval); 13291 13292 for (handler in this._handlers) { 13293 this._core.$element.off(handler, this._handlers[handler]); 13294 } 13295 for (property in Object.getOwnPropertyNames(this)) { 13296 typeof this[property] != 'function' && (this[property] = null); 13297 } 13298 }; 13299 13300 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 13301 13302})(window.Zepto || window.jQuery, window, document); 13303 13304/** 13305 * Lazy Plugin 13306 * @version 2.0.0-beta.3 13307 * @author Bartosz Wojciechowski 13308 * @license The MIT License (MIT) 13309 */ 13310;(function($, window, document, undefined) { 13311 13312 /** 13313 * Creates the lazy plugin. 13314 * @class The Lazy Plugin 13315 * @param {Owl} carousel - The Owl Carousel 13316 */ 13317 var Lazy = function(carousel) { 13318 13319 /** 13320 * Reference to the core. 13321 * @protected 13322 * @type {Owl} 13323 */ 13324 this._core = carousel; 13325 13326 /** 13327 * Already loaded items. 13328 * @protected 13329 * @type {Array.<jQuery>} 13330 */ 13331 this._loaded = []; 13332 13333 /** 13334 * Event handlers. 13335 * @protected 13336 * @type {Object} 13337 */ 13338 this._handlers = { 13339 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 13340 if (!e.namespace) { 13341 return; 13342 } 13343 13344 if (!this._core.settings || !this._core.settings.lazyLoad) { 13345 return; 13346 } 13347 13348 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 13349 var settings = this._core.settings, 13350 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 13351 i = ((settings.center && n * -1) || 0), 13352 position = ((e.property && e.property.value) || this._core.current()) + i, 13353 clones = this._core.clones().length, 13354 load = $.proxy(function(i, v) { this.load(v) }, this); 13355 13356 while (i++ < n) { 13357 this.load(clones / 2 + this._core.relative(position)); 13358 clones && $.each(this._core.clones(this._core.relative(position)), load); 13359 position++; 13360 } 13361 } 13362 }, this) 13363 }; 13364 13365 // set the default options 13366 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 13367 13368 // register event handler 13369 this._core.$element.on(this._handlers); 13370 } 13371 13372 /** 13373 * Default options. 13374 * @public 13375 */ 13376 Lazy.Defaults = { 13377 lazyLoad: false 13378 } 13379 13380 /** 13381 * Loads all resources of an item at the specified position. 13382 * @param {Number} position - The absolute position of the item. 13383 * @protected 13384 */ 13385 Lazy.prototype.load = function(position) { 13386 var $item = this._core.$stage.children().eq(position), 13387 $elements = $item && $item.find('.owl-lazy'); 13388 13389 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 13390 return; 13391 } 13392 13393 $elements.each($.proxy(function(index, element) { 13394 var $element = $(element), image, 13395 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 13396 13397 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 13398 13399 if ($element.is('img')) { 13400 $element.one('load.owl.lazy', $.proxy(function() { 13401 $element.css('opacity', 1); 13402 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 13403 }, this)).attr('src', url); 13404 } else { 13405 image = new Image(); 13406 image.onload = $.proxy(function() { 13407 $element.css({ 13408 'background-image': 'url(' + url + ')', 13409 'opacity': '1' 13410 }); 13411 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 13412 }, this); 13413 image.src = url; 13414 } 13415 }, this)); 13416 13417 this._loaded.push($item.get(0)); 13418 } 13419 13420 /** 13421 * Destroys the plugin. 13422 * @public 13423 */ 13424 Lazy.prototype.destroy = function() { 13425 var handler, property; 13426 13427 for (handler in this.handlers) { 13428 this._core.$element.off(handler, this.handlers[handler]); 13429 } 13430 for (property in Object.getOwnPropertyNames(this)) { 13431 typeof this[property] != 'function' && (this[property] = null); 13432 } 13433 }; 13434 13435 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 13436 13437})(window.Zepto || window.jQuery, window, document); 13438 13439/** 13440 * AutoHeight Plugin 13441 * @version 2.0.0-beta.3 13442 * @author Bartosz Wojciechowski 13443 * @license The MIT License (MIT) 13444 */ 13445;(function($, window, document, undefined) { 13446 13447 /** 13448 * Creates the auto height plugin. 13449 * @class The Auto Height Plugin 13450 * @param {Owl} carousel - The Owl Carousel 13451 */ 13452 var AutoHeight = function(carousel) { 13453 /** 13454 * Reference to the core. 13455 * @protected 13456 * @type {Owl} 13457 */ 13458 this._core = carousel; 13459 13460 /** 13461 * All event handlers. 13462 * @protected 13463 * @type {Object} 13464 */ 13465 this._handlers = { 13466 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 13467 if (e.namespace && this._core.settings.autoHeight) { 13468 this.update(); 13469 } 13470 }, this), 13471 'changed.owl.carousel': $.proxy(function(e) { 13472 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 13473 this.update(); 13474 } 13475 }, this), 13476 'loaded.owl.lazy': $.proxy(function(e) { 13477 if (e.namespace && this._core.settings.autoHeight 13478 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 13479 this.update(); 13480 } 13481 }, this) 13482 }; 13483 13484 // set default options 13485 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 13486 13487 // register event handlers 13488 this._core.$element.on(this._handlers); 13489 }; 13490 13491 /** 13492 * Default options. 13493 * @public 13494 */ 13495 AutoHeight.Defaults = { 13496 autoHeight: false, 13497 autoHeightClass: 'owl-height' 13498 }; 13499 13500 /** 13501 * Updates the view. 13502 */ 13503 AutoHeight.prototype.update = function() { 13504 var start = this._core._current, 13505 end = start + this._core.settings.items, 13506 visible = this._core.$stage.children().toArray().slice(start, end); 13507 heights = [], 13508 maxheight = 0; 13509 13510 $.each(visible, function(index, item) { 13511 heights.push($(item).height()); 13512 }); 13513 13514 maxheight = Math.max.apply(null, heights); 13515 13516 this._core.$stage.parent() 13517 .height(maxheight) 13518 .addClass(this._core.settings.autoHeightClass); 13519 }; 13520 13521 AutoHeight.prototype.destroy = function() { 13522 var handler, property; 13523 13524 for (handler in this._handlers) { 13525 this._core.$element.off(handler, this._handlers[handler]); 13526 } 13527 for (property in Object.getOwnPropertyNames(this)) { 13528 typeof this[property] != 'function' && (this[property] = null); 13529 } 13530 }; 13531 13532 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 13533 13534})(window.Zepto || window.jQuery, window, document); 13535 13536/** 13537 * Video Plugin 13538 * @version 2.0.0-beta.3 13539 * @author Bartosz Wojciechowski 13540 * @license The MIT License (MIT) 13541 */ 13542;(function($, window, document, undefined) { 13543 13544 /** 13545 * Creates the video plugin. 13546 * @class The Video Plugin 13547 * @param {Owl} carousel - The Owl Carousel 13548 */ 13549 var Video = function(carousel) { 13550 /** 13551 * Reference to the core. 13552 * @protected 13553 * @type {Owl} 13554 */ 13555 this._core = carousel; 13556 13557 /** 13558 * Cache all video URLs. 13559 * @protected 13560 * @type {Object} 13561 */ 13562 this._videos = {}; 13563 13564 /** 13565 * Current playing item. 13566 * @protected 13567 * @type {jQuery} 13568 */ 13569 this._playing = null; 13570 13571 /** 13572 * All event handlers. 13573 * @todo The cloned content removale is too late 13574 * @protected 13575 * @type {Object} 13576 */ 13577 this._handlers = { 13578 'initialized.owl.carousel': $.proxy(function(e) { 13579 if (e.namespace) { 13580 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 13581 } 13582 }, this), 13583 'resize.owl.carousel': $.proxy(function(e) { 13584 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 13585 e.preventDefault(); 13586 } 13587 }, this), 13588 'refreshed.owl.carousel': $.proxy(function(e) { 13589 if (e.namespace && this._core.is('resizing')) { 13590 this._core.$stage.find('.cloned .owl-video-frame').remove(); 13591 } 13592 }, this), 13593 'changed.owl.carousel': $.proxy(function(e) { 13594 if (e.namespace && e.property.name === 'position' && this._playing) { 13595 this.stop(); 13596 } 13597 }, this), 13598 'prepared.owl.carousel': $.proxy(function(e) { 13599 if (!e.namespace) { 13600 return; 13601 } 13602 13603 var $element = $(e.content).find('.owl-video'); 13604 13605 if ($element.length) { 13606 $element.css('display', 'none'); 13607 this.fetch($element, $(e.content)); 13608 } 13609 }, this) 13610 }; 13611 13612 // set default options 13613 this._core.options = $.extend({}, Video.Defaults, this._core.options); 13614 13615 // register event handlers 13616 this._core.$element.on(this._handlers); 13617 13618 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 13619 this.play(e); 13620 }, this)); 13621 }; 13622 13623 /** 13624 * Default options. 13625 * @public 13626 */ 13627 Video.Defaults = { 13628 video: false, 13629 videoHeight: false, 13630 videoWidth: false 13631 }; 13632 13633 /** 13634 * Gets the video ID and the type (YouTube/Vimeo only). 13635 * @protected 13636 * @param {jQuery} target - The target containing the video data. 13637 * @param {jQuery} item - The item containing the video. 13638 */ 13639 Video.prototype.fetch = function(target, item) { 13640 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 13641 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 13642 width = target.attr('data-width') || this._core.settings.videoWidth, 13643 height = target.attr('data-height') || this._core.settings.videoHeight, 13644 url = target.attr('href'); 13645 13646 if (url) { 13647 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+)?/); 13648 13649 if (id[3].indexOf('youtu') > -1) { 13650 type = 'youtube'; 13651 } else if (id[3].indexOf('vimeo') > -1) { 13652 type = 'vimeo'; 13653 } else { 13654 throw new Error('Video URL not supported.'); 13655 } 13656 id = id[6]; 13657 } else { 13658 throw new Error('Missing video URL.'); 13659 } 13660 13661 this._videos[url] = { 13662 type: type, 13663 id: id, 13664 width: width, 13665 height: height 13666 }; 13667 13668 item.attr('data-video', url); 13669 13670 this.thumbnail(target, this._videos[url]); 13671 }; 13672 13673 /** 13674 * Creates video thumbnail. 13675 * @protected 13676 * @param {jQuery} target - The target containing the video data. 13677 * @param {Object} info - The video info object. 13678 * @see `fetch` 13679 */ 13680 Video.prototype.thumbnail = function(target, video) { 13681 var tnLink, 13682 icon, 13683 path, 13684 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 13685 customTn = target.find('img'), 13686 srcType = 'src', 13687 lazyClass = '', 13688 settings = this._core.settings, 13689 create = function(path) { 13690 icon = '<div class="owl-video-play-icon"></div>'; 13691 13692 if (settings.lazyLoad) { 13693 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 13694 } else { 13695 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 13696 } 13697 target.after(tnLink); 13698 target.after(icon); 13699 }; 13700 13701 // wrap video content into owl-video-wrapper div 13702 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 13703 13704 if (this._core.settings.lazyLoad) { 13705 srcType = 'data-src'; 13706 lazyClass = 'owl-lazy'; 13707 } 13708 13709 // custom thumbnail 13710 if (customTn.length) { 13711 create(customTn.attr(srcType)); 13712 customTn.remove(); 13713 return false; 13714 } 13715 13716 if (video.type === 'youtube') { 13717 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 13718 create(path); 13719 } else if (video.type === 'vimeo') { 13720 $.ajax({ 13721 type: 'GET', 13722 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 13723 jsonp: 'callback', 13724 dataType: 'jsonp', 13725 success: function(data) { 13726 path = data[0].thumbnail_large; 13727 create(path); 13728 } 13729 }); 13730 } 13731 }; 13732 13733 /** 13734 * Stops the current video. 13735 * @public 13736 */ 13737 Video.prototype.stop = function() { 13738 this._core.trigger('stop', null, 'video'); 13739 this._playing.find('.owl-video-frame').remove(); 13740 this._playing.removeClass('owl-video-playing'); 13741 this._playing = null; 13742 this._core.leave('playing'); 13743 this._core.trigger('stopped', null, 'video'); 13744 }; 13745 13746 /** 13747 * Starts the current video. 13748 * @public 13749 * @param {Event} event - The event arguments. 13750 */ 13751 Video.prototype.play = function(event) { 13752 var target = $(event.target), 13753 item = target.closest('.' + this._core.settings.itemClass), 13754 video = this._videos[item.attr('data-video')], 13755 width = video.width || '100%', 13756 height = video.height || this._core.$stage.height(), 13757 html; 13758 13759 if (this._playing) { 13760 return; 13761 } 13762 13763 this._core.enter('playing'); 13764 this._core.trigger('play', null, 'video'); 13765 13766 item = this._core.items(this._core.relative(item.index())); 13767 13768 this._core.reset(item.index()); 13769 13770 if (video.type === 'youtube') { 13771 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 13772 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 13773 } else if (video.type === 'vimeo') { 13774 html = '<iframe src="//player.vimeo.com/video/' + video.id + 13775 '?autoplay=1" width="' + width + '" height="' + height + 13776 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 13777 } 13778 13779 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 13780 13781 this._playing = item.addClass('owl-video-playing'); 13782 }; 13783 13784 /** 13785 * Checks whether an video is currently in full screen mode or not. 13786 * @todo Bad style because looks like a readonly method but changes members. 13787 * @protected 13788 * @returns {Boolean} 13789 */ 13790 Video.prototype.isInFullScreen = function() { 13791 var element = document.fullscreenElement || document.mozFullScreenElement || 13792 document.webkitFullscreenElement; 13793 13794 return element && $(element).parent().hasClass('owl-video-frame'); 13795 }; 13796 13797 /** 13798 * Destroys the plugin. 13799 */ 13800 Video.prototype.destroy = function() { 13801 var handler, property; 13802 13803 this._core.$element.off('click.owl.video'); 13804 13805 for (handler in this._handlers) { 13806 this._core.$element.off(handler, this._handlers[handler]); 13807 } 13808 for (property in Object.getOwnPropertyNames(this)) { 13809 typeof this[property] != 'function' && (this[property] = null); 13810 } 13811 }; 13812 13813 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 13814 13815})(window.Zepto || window.jQuery, window, document); 13816 13817/** 13818 * Animate Plugin 13819 * @version 2.0.0-beta.3 13820 * @author Bartosz Wojciechowski 13821 * @license The MIT License (MIT) 13822 */ 13823;(function($, window, document, undefined) { 13824 13825 /** 13826 * Creates the animate plugin. 13827 * @class The Navigation Plugin 13828 * @param {Owl} scope - The Owl Carousel 13829 */ 13830 var Animate = function(scope) { 13831 this.core = scope; 13832 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 13833 this.swapping = true; 13834 this.previous = undefined; 13835 this.next = undefined; 13836 13837 this.handlers = { 13838 'change.owl.carousel': $.proxy(function(e) { 13839 if (e.namespace && e.property.name == 'position') { 13840 this.previous = this.core.current(); 13841 this.next = e.property.value; 13842 } 13843 }, this), 13844 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 13845 if (e.namespace) { 13846 this.swapping = e.type == 'translated'; 13847 } 13848 }, this), 13849 'translate.owl.carousel': $.proxy(function(e) { 13850 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 13851 this.swap(); 13852 } 13853 }, this) 13854 }; 13855 13856 this.core.$element.on(this.handlers); 13857 }; 13858 13859 /** 13860 * Default options. 13861 * @public 13862 */ 13863 Animate.Defaults = { 13864 animateOut: false, 13865 animateIn: false 13866 }; 13867 13868 /** 13869 * Toggles the animation classes whenever an translations starts. 13870 * @protected 13871 * @returns {Boolean|undefined} 13872 */ 13873 Animate.prototype.swap = function() { 13874 13875 if (this.core.settings.items !== 1) { 13876 return; 13877 } 13878 13879 if (!$.support.animation || !$.support.transition) { 13880 return; 13881 } 13882 13883 this.core.speed(0); 13884 13885 var left, 13886 clear = $.proxy(this.clear, this), 13887 previous = this.core.$stage.children().eq(this.previous), 13888 next = this.core.$stage.children().eq(this.next), 13889 incoming = this.core.settings.animateIn, 13890 outgoing = this.core.settings.animateOut; 13891 13892 if (this.core.current() === this.previous) { 13893 return; 13894 } 13895 13896 if (outgoing) { 13897 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 13898 previous.css( { 'left': left + 'px' } ) 13899 .addClass('animated owl-animated-out') 13900 .addClass(outgoing) 13901 .on($.support.animation.end, clear); 13902 } 13903 13904 if (incoming) { 13905 next.addClass('animated owl-animated-in') 13906 .addClass(incoming) 13907 .on($.support.animation.end, clear); 13908 } 13909 }; 13910 13911 Animate.prototype.clear = function(e) { 13912 if ($(e.target).hasClass('animated')) { 13913 $(e.target).css( { 'left': '' } ) 13914 .removeClass('animated owl-animated-out owl-animated-in') 13915 .removeClass(this.core.settings.animateIn) 13916 .removeClass(this.core.settings.animateOut); 13917 this.core.onTransitionEnd(); 13918 } 13919 }; 13920 13921 /** 13922 * Destroys the plugin. 13923 * @public 13924 */ 13925 Animate.prototype.destroy = function() { 13926 var handler, property; 13927 13928 for (handler in this.handlers) { 13929 this.core.$element.off(handler, this.handlers[handler]); 13930 } 13931 for (property in Object.getOwnPropertyNames(this)) { 13932 typeof this[property] != 'function' && (this[property] = null); 13933 } 13934 }; 13935 13936 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 13937 13938})(window.Zepto || window.jQuery, window, document); 13939 13940/** 13941 * Autoplay Plugin 13942 * @version 2.0.0-beta.3 13943 * @author Bartosz Wojciechowski 13944 * @author Artus Kolanowski 13945 * @license The MIT License (MIT) 13946 */ 13947;(function($, window, document, undefined) { 13948 13949 /** 13950 * Creates the autoplay plugin. 13951 * @class The Autoplay Plugin 13952 * @param {Owl} scope - The Owl Carousel 13953 */ 13954 var Autoplay = function(carousel) { 13955 /** 13956 * Reference to the core. 13957 * @protected 13958 * @type {Owl} 13959 */ 13960 this._core = carousel; 13961 13962 /** 13963 * The autoplay interval. 13964 * @type {Number} 13965 */ 13966 this._interval = null; 13967 13968 /** 13969 * Indicates whenever the autoplay is paused. 13970 * @type {Boolean} 13971 */ 13972 this._paused = false; 13973 13974 /** 13975 * All event handlers. 13976 * @protected 13977 * @type {Object} 13978 */ 13979 this._handlers = { 13980 'changed.owl.carousel': $.proxy(function(e) { 13981 if (e.namespace && e.property.name === 'settings') { 13982 if (this._core.settings.autoplay) { 13983 this.play(); 13984 } else { 13985 this.stop(); 13986 } 13987 } 13988 }, this), 13989 'initialized.owl.carousel': $.proxy(function(e) { 13990 if (e.namespace && this._core.settings.autoplay) { 13991 this.play(); 13992 } 13993 }, this), 13994 'play.owl.autoplay': $.proxy(function(e, t, s) { 13995 if (e.namespace) { 13996 this.play(t, s); 13997 } 13998 }, this), 13999 'stop.owl.autoplay': $.proxy(function(e) { 14000 if (e.namespace) { 14001 this.stop(); 14002 } 14003 }, this), 14004 'mouseover.owl.autoplay': $.proxy(function() { 14005 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 14006 this.pause(); 14007 } 14008 }, this), 14009 'mouseleave.owl.autoplay': $.proxy(function() { 14010 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 14011 this.play(); 14012 } 14013 }, this) 14014 }; 14015 14016 // register event handlers 14017 this._core.$element.on(this._handlers); 14018 14019 // set default options 14020 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 14021 }; 14022 14023 /** 14024 * Default options. 14025 * @public 14026 */ 14027 Autoplay.Defaults = { 14028 autoplay: false, 14029 autoplayTimeout: 5000, 14030 autoplayHoverPause: false, 14031 autoplaySpeed: false 14032 }; 14033 14034 /** 14035 * Starts the autoplay. 14036 * @public 14037 * @param {Number} [timeout] - The interval before the next animation starts. 14038 * @param {Number} [speed] - The animation speed for the animations. 14039 */ 14040 Autoplay.prototype.play = function(timeout, speed) { 14041 this._paused = false; 14042 14043 if (this._core.is('rotating')) { 14044 return; 14045 } 14046 14047 this._core.enter('rotating'); 14048 14049 this._interval = window.setInterval($.proxy(function() { 14050 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 14051 return; 14052 } 14053 this._core.next(speed || this._core.settings.autoplaySpeed); 14054 }, this), timeout || this._core.settings.autoplayTimeout); 14055 }; 14056 14057 /** 14058 * Stops the autoplay. 14059 * @public 14060 */ 14061 Autoplay.prototype.stop = function() { 14062 if (!this._core.is('rotating')) { 14063 return; 14064 } 14065 14066 window.clearInterval(this._interval); 14067 this._core.leave('rotating'); 14068 }; 14069 14070 /** 14071 * Stops the autoplay. 14072 * @public 14073 */ 14074 Autoplay.prototype.pause = function() { 14075 if (!this._core.is('rotating')) { 14076 return; 14077 } 14078 14079 this._paused = true; 14080 }; 14081 14082 /** 14083 * Destroys the plugin. 14084 */ 14085 Autoplay.prototype.destroy = function() { 14086 var handler, property; 14087 14088 this.stop(); 14089 14090 for (handler in this._handlers) { 14091 this._core.$element.off(handler, this._handlers[handler]); 14092 } 14093 for (property in Object.getOwnPropertyNames(this)) { 14094 typeof this[property] != 'function' && (this[property] = null); 14095 } 14096 }; 14097 14098 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 14099 14100})(window.Zepto || window.jQuery, window, document); 14101 14102/** 14103 * Navigation Plugin 14104 * @version 2.0.0-beta.3 14105 * @author Artus Kolanowski 14106 * @license The MIT License (MIT) 14107 */ 14108;(function($, window, document, undefined) { 14109 'use strict'; 14110 14111 /** 14112 * Creates the navigation plugin. 14113 * @class The Navigation Plugin 14114 * @param {Owl} carousel - The Owl Carousel. 14115 */ 14116 var Navigation = function(carousel) { 14117 /** 14118 * Reference to the core. 14119 * @protected 14120 * @type {Owl} 14121 */ 14122 this._core = carousel; 14123 14124 /** 14125 * Indicates whether the plugin is initialized or not. 14126 * @protected 14127 * @type {Boolean} 14128 */ 14129 this._initialized = false; 14130 14131 /** 14132 * The current paging indexes. 14133 * @protected 14134 * @type {Array} 14135 */ 14136 this._pages = []; 14137 14138 /** 14139 * All DOM elements of the user interface. 14140 * @protected 14141 * @type {Object} 14142 */ 14143 this._controls = {}; 14144 14145 /** 14146 * Markup for an indicator. 14147 * @protected 14148 * @type {Array.<String>} 14149 */ 14150 this._templates = []; 14151 14152 /** 14153 * The carousel element. 14154 * @type {jQuery} 14155 */ 14156 this.$element = this._core.$element; 14157 14158 /** 14159 * Overridden methods of the carousel. 14160 * @protected 14161 * @type {Object} 14162 */ 14163 this._overrides = { 14164 next: this._core.next, 14165 prev: this._core.prev, 14166 to: this._core.to 14167 }; 14168 14169 /** 14170 * All event handlers. 14171 * @protected 14172 * @type {Object} 14173 */ 14174 this._handlers = { 14175 'prepared.owl.carousel': $.proxy(function(e) { 14176 if (e.namespace && this._core.settings.dotsData) { 14177 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 14178 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 14179 } 14180 }, this), 14181 'added.owl.carousel': $.proxy(function(e) { 14182 if (e.namespace && this._core.settings.dotsData) { 14183 this._templates.splice(e.position, 0, this._templates.pop()); 14184 } 14185 }, this), 14186 'remove.owl.carousel': $.proxy(function(e) { 14187 if (e.namespace && this._core.settings.dotsData) { 14188 this._templates.splice(e.position, 1); 14189 } 14190 }, this), 14191 'changed.owl.carousel': $.proxy(function(e) { 14192 if (e.namespace && e.property.name == 'position') { 14193 this.draw(); 14194 } 14195 }, this), 14196 'initialized.owl.carousel': $.proxy(function(e) { 14197 if (e.namespace && !this._initialized) { 14198 this._core.trigger('initialize', null, 'navigation'); 14199 this.initialize(); 14200 this.update(); 14201 this.draw(); 14202 this._initialized = true; 14203 this._core.trigger('initialized', null, 'navigation'); 14204 } 14205 }, this), 14206 'refreshed.owl.carousel': $.proxy(function(e) { 14207 if (e.namespace && this._initialized) { 14208 this._core.trigger('refresh', null, 'navigation'); 14209 this.update(); 14210 this.draw(); 14211 this._core.trigger('refreshed', null, 'navigation'); 14212 } 14213 }, this) 14214 }; 14215 14216 // set default options 14217 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 14218 14219 // register event handlers 14220 this.$element.on(this._handlers); 14221 }; 14222 14223 /** 14224 * Default options. 14225 * @public 14226 * @todo Rename `slideBy` to `navBy` 14227 */ 14228 Navigation.Defaults = { 14229 nav: false, 14230 navText: [ 'prev', 'next' ], 14231 navSpeed: false, 14232 navElement: 'div', 14233 navContainer: false, 14234 navContainerClass: 'owl-nav', 14235 navClass: [ 'owl-prev', 'owl-next' ], 14236 slideBy: 1, 14237 dotClass: 'owl-dot', 14238 dotsClass: 'owl-dots', 14239 dots: true, 14240 dotsEach: false, 14241 dotsData: false, 14242 dotsSpeed: false, 14243 dotsContainer: false 14244 }; 14245 14246 /** 14247 * Initializes the layout of the plugin and extends the carousel. 14248 * @protected 14249 */ 14250 Navigation.prototype.initialize = function() { 14251 var override, 14252 settings = this._core.settings; 14253 14254 // create DOM structure for relative navigation 14255 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 14256 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 14257 14258 this._controls.$previous = $('<' + settings.navElement + '>') 14259 .addClass(settings.navClass[0]) 14260 .html(settings.navText[0]) 14261 .prependTo(this._controls.$relative) 14262 .on('click', $.proxy(function(e) { 14263 this.prev(settings.navSpeed); 14264 }, this)); 14265 this._controls.$next = $('<' + settings.navElement + '>') 14266 .addClass(settings.navClass[1]) 14267 .html(settings.navText[1]) 14268 .appendTo(this._controls.$relative) 14269 .on('click', $.proxy(function(e) { 14270 this.next(settings.navSpeed); 14271 }, this)); 14272 14273 // create DOM structure for absolute navigation 14274 if (!settings.dotsData) { 14275 this._templates = [ $('<div>') 14276 .addClass(settings.dotClass) 14277 .append($('<span>')) 14278 .prop('outerHTML') ]; 14279 } 14280 14281 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 14282 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 14283 14284 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 14285 var index = $(e.target).parent().is(this._controls.$absolute) 14286 ? $(e.target).index() : $(e.target).parent().index(); 14287 14288 e.preventDefault(); 14289 14290 this.to(index, settings.dotsSpeed); 14291 }, this)); 14292 14293 // override public methods of the carousel 14294 for (override in this._overrides) { 14295 this._core[override] = $.proxy(this[override], this); 14296 } 14297 }; 14298 14299 /** 14300 * Destroys the plugin. 14301 * @protected 14302 */ 14303 Navigation.prototype.destroy = function() { 14304 var handler, control, property, override; 14305 14306 for (handler in this._handlers) { 14307 this.$element.off(handler, this._handlers[handler]); 14308 } 14309 for (control in this._controls) { 14310 this._controls[control].remove(); 14311 } 14312 for (override in this.overides) { 14313 this._core[override] = this._overrides[override]; 14314 } 14315 for (property in Object.getOwnPropertyNames(this)) { 14316 typeof this[property] != 'function' && (this[property] = null); 14317 } 14318 }; 14319 14320 /** 14321 * Updates the internal state. 14322 * @protected 14323 */ 14324 Navigation.prototype.update = function() { 14325 var i, j, k, 14326 lower = this._core.clones().length / 2, 14327 upper = lower + this._core.items().length, 14328 maximum = this._core.maximum(true), 14329 settings = this._core.settings, 14330 size = settings.center || settings.autoWidth || settings.dotsData 14331 ? 1 : settings.dotsEach || settings.items; 14332 14333 if (settings.slideBy !== 'page') { 14334 settings.slideBy = Math.min(settings.slideBy, settings.items); 14335 } 14336 14337 if (settings.dots || settings.slideBy == 'page') { 14338 this._pages = []; 14339 14340 for (i = lower, j = 0, k = 0; i < upper; i++) { 14341 if (j >= size || j === 0) { 14342 this._pages.push({ 14343 start: Math.min(maximum, i - lower), 14344 end: i - lower + size - 1 14345 }); 14346 if (Math.min(maximum, i - lower) === maximum) { 14347 break; 14348 } 14349 j = 0, ++k; 14350 } 14351 j += this._core.mergers(this._core.relative(i)); 14352 } 14353 } 14354 }; 14355 14356 /** 14357 * Draws the user interface. 14358 * @todo The option `dotsData` wont work. 14359 * @protected 14360 */ 14361 Navigation.prototype.draw = function() { 14362 var difference, 14363 settings = this._core.settings, 14364 disabled = this._core.items().length <= settings.items, 14365 index = this._core.relative(this._core.current()), 14366 loop = settings.loop || settings.rewind; 14367 14368 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 14369 14370 if (settings.nav) { 14371 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 14372 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 14373 } 14374 14375 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 14376 14377 if (settings.dots) { 14378 difference = this._pages.length - this._controls.$absolute.children().length; 14379 14380 if (settings.dotsData && difference !== 0) { 14381 this._controls.$absolute.html(this._templates.join('')); 14382 } else if (difference > 0) { 14383 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 14384 } else if (difference < 0) { 14385 this._controls.$absolute.children().slice(difference).remove(); 14386 } 14387 14388 this._controls.$absolute.find('.active').removeClass('active'); 14389 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 14390 } 14391 }; 14392 14393 /** 14394 * Extends event data. 14395 * @protected 14396 * @param {Event} event - The event object which gets thrown. 14397 */ 14398 Navigation.prototype.onTrigger = function(event) { 14399 var settings = this._core.settings; 14400 14401 event.page = { 14402 index: $.inArray(this.current(), this._pages), 14403 count: this._pages.length, 14404 size: settings && (settings.center || settings.autoWidth || settings.dotsData 14405 ? 1 : settings.dotsEach || settings.items) 14406 }; 14407 }; 14408 14409 /** 14410 * Gets the current page position of the carousel. 14411 * @protected 14412 * @returns {Number} 14413 */ 14414 Navigation.prototype.current = function() { 14415 var current = this._core.relative(this._core.current()); 14416 return $.grep(this._pages, $.proxy(function(page, index) { 14417 return page.start <= current && page.end >= current; 14418 }, this)).pop(); 14419 }; 14420 14421 /** 14422 * Gets the current succesor/predecessor position. 14423 * @protected 14424 * @returns {Number} 14425 */ 14426 Navigation.prototype.getPosition = function(successor) { 14427 var position, length, 14428 settings = this._core.settings; 14429 14430 if (settings.slideBy == 'page') { 14431 position = $.inArray(this.current(), this._pages); 14432 length = this._pages.length; 14433 successor ? ++position : --position;
vendor: 5,678 bytes, lines 14434-14658
14434 position = this._pages[((position % length) + length) % length].start; 14435 } else { 14436 position = this._core.relative(this._core.current()); 14437 length = this._core.items().length; 14438 successor ? position += settings.slideBy : position -= settings.slideBy; 14439 } 14440 14441 return position; 14442 }; 14443 14444 /** 14445 * Slides to the next item or page. 14446 * @public 14447 * @param {Number} [speed=false] - The time in milliseconds for the transition. 14448 */ 14449 Navigation.prototype.next = function(speed) { 14450 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 14451 }; 14452 14453 /** 14454 * Slides to the previous item or page. 14455 * @public 14456 * @param {Number} [speed=false] - The time in milliseconds for the transition. 14457 */ 14458 Navigation.prototype.prev = function(speed) { 14459 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 14460 }; 14461 14462 /** 14463 * Slides to the specified item or page. 14464 * @public 14465 * @param {Number} position - The position of the item or page. 14466 * @param {Number} [speed] - The time in milliseconds for the transition. 14467 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 14468 */ 14469 Navigation.prototype.to = function(position, speed, standard) { 14470 var length; 14471 14472 if (!standard) { 14473 length = this._pages.length; 14474 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 14475 } else { 14476 $.proxy(this._overrides.to, this._core)(position, speed); 14477 } 14478 }; 14479 14480 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 14481 14482})(window.Zepto || window.jQuery, window, document); 14483 14484/** 14485 * Hash Plugin 14486 * @version 2.0.0-beta.3 14487 * @author Artus Kolanowski 14488 * @license The MIT License (MIT) 14489 */ 14490;(function($, window, document, undefined) { 14491 'use strict'; 14492 14493 /** 14494 * Creates the hash plugin. 14495 * @class The Hash Plugin 14496 * @param {Owl} carousel - The Owl Carousel 14497 */ 14498 var Hash = function(carousel) { 14499 /** 14500 * Reference to the core. 14501 * @protected 14502 * @type {Owl} 14503 */ 14504 this._core = carousel; 14505 14506 /** 14507 * Hash index for the items. 14508 * @protected 14509 * @type {Object} 14510 */ 14511 this._hashes = {}; 14512 14513 /** 14514 * The carousel element. 14515 * @type {jQuery} 14516 */ 14517 this.$element = this._core.$element; 14518 14519 /** 14520 * All event handlers. 14521 * @protected 14522 * @type {Object} 14523 */ 14524 this._handlers = { 14525 /*'initialized.owl.carousel': $.proxy(function(e) { 14526 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 14527 $(window).trigger('hashchange.owl.navigation'); 14528 } 14529 }, this),*/ 14530 'prepared.owl.carousel': $.proxy(function(e) { 14531 if (e.namespace) { 14532 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 14533 14534 if (!hash) { 14535 return; 14536 } 14537 14538 this._hashes[hash] = e.content; 14539 } 14540 }, this), 14541 'changed.owl.carousel': $.proxy(function(e) { 14542 if (e.namespace && e.property.name === 'position') { 14543 var current = this._core.items(this._core.relative(this._core.current())), 14544 hash = $.map(this._hashes, function(item, hash) { 14545 return item === current ? hash : null; 14546 }).join(); 14547 14548 if (!hash || window.location.hash.slice(1) === hash) { 14549 return; 14550 } 14551 14552 window.location.hash = hash; 14553 } 14554 }, this) 14555 }; 14556 14557 // set default options 14558 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 14559 14560 // register the event handlers 14561 this.$element.on(this._handlers); 14562 14563 // register event listener for hash navigation 14564 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 14565 var hash = window.location.hash.substring(1), 14566 items = this._core.$stage.children(), 14567 position = this._hashes[hash] && items.index(this._hashes[hash]); 14568 14569 if (position === undefined || position === this._core.current()) { 14570 return; 14571 } 14572 14573 this._core.to(this._core.relative(position), false, true); 14574 }, this));*/ 14575 }; 14576 14577 /** 14578 * Default options. 14579 * @public 14580 */ 14581 Hash.Defaults = { 14582 URLhashListener: false 14583 }; 14584 14585 /** 14586 * Destroys the plugin. 14587 * @public 14588 */ 14589 Hash.prototype.destroy = function() { 14590 var handler, property; 14591 14592 $(window).off('hashchange.owl.navigation'); 14593 14594 for (handler in this._handlers) { 14595 this._core.$element.off(handler, this._handlers[handler]); 14596 } 14597 for (property in Object.getOwnPropertyNames(this)) { 14598 typeof this[property] != 'function' && (this[property] = null); 14599 } 14600 }; 14601 14602 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 14603 14604})(window.Zepto || window.jQuery, window, document); 14605 14606/** 14607 * Support Plugin 14608 * 14609 * @version 2.0.0-beta.3 14610 * @author Vivid Planet Software GmbH 14611 * @author Artus Kolanowski 14612 * @license The MIT License (MIT) 14613 */ 14614;(function($, window, document, undefined) { 14615 14616 var style = $('<support>').get(0).style, 14617 prefixes = 'Webkit Moz O ms'.split(' '), 14618 events = { 14619 transition: { 14620 end: { 14621 WebkitTransition: 'webkitTransitionEnd', 14622 MozTransition: 'transitionend', 14623 OTransition: 'oTransitionEnd', 14624 transition: 'transitionend' 14625 } 14626 }, 14627 animation: { 14628 end: { 14629 WebkitAnimation: 'webkitAnimationEnd', 14630 MozAnimation: 'animationend', 14631 OAnimation: 'oAnimationEnd', 14632 animation: 'animationend' 14633 } 14634 } 14635 }, 14636 tests = { 14637 csstransforms: function() { 14638 return !!test('transform'); 14639 }, 14640 csstransforms3d: function() { 14641 return !!test('perspective'); 14642 }, 14643 csstransitions: function() { 14644 return !!test('transition'); 14645 }, 14646 cssanimations: function() { 14647 return !!test('animation'); 14648 } 14649 }; 14650 14651 function test(property, prefixed) { 14652 var result = false, 14653 upper = property.charAt(0).toUpperCase() + property.slice(1); 14654 14655 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 14656 if (style[property] !== undefined) { 14657 result = prefixed ? property : true; 14658 return false;
14659 } 14660 }); 14661 14662 return result; 14663 } 14664 14665 function prefixed(property) { 14666 return test(property, true); 14667 } 14668 14669 if (tests.csstransitions()) { 14670 /* jshint -W053 */ 14671 $.support.transition = new String(prefixed('transition')) 14672 $.support.transition.end = events.transition.end[ $.support.transition ]; 14673 } 14674 14675 if (tests.cssanimations()) { 14676 /* jshint -W053 */ 14677 $.support.animation = new String(prefixed('animation')) 14678 $.support.animation.end = events.animation.end[ $.support.animation ]; 14679 } 14680 14681 if (tests.csstransforms()) { 14682 /* jshint -W053 */ 14683 $.support.transform = new String(prefixed('transform')); 14684 $.support.transform3d = tests.csstransforms3d(); 14685 } 14686 14687})(window.Zepto || window.jQuery, window, document); 14688 14689(function(window, document, undefined) { 14690 14691 /** 14692 * Find the absolute position of an element 14693 */ 14694 var absPos = function(element) { 14695 var offsetLeft, offsetTop; 14696 offsetLeft = offsetTop = 0; 14697 if (element.offsetParent) { 14698 do { 14699 offsetLeft += element.offsetLeft; 14700 offsetTop += element.offsetTop; 14701 } while (element = element.offsetParent); 14702 } 14703 return [offsetLeft, offsetTop]; 14704 }; 14705 14706 /** 14707 * @constructor Progress Circle class 14708 * @param params.canvas Canvas on which the circles will be drawn. 14709 * @param params.minRadius Inner radius of the innermost circle, in px. 14710 * @param params.arcWidth Width of each circle(to be more accurate, ring). 14711 * @param params.gapWidth Space between each circle. 14712 * @param params.centerX X coordinate of the center of circles. 14713 * @param params.centerY Y coordinate of the center of circles. 14714 * @param params.infoLineBaseAngle Base angle of the info line. 14715 * @param params.infoLineAngleInterval Angles between the info lines. 14716 */ 14717 var ProgressCircle = function(params) { 14718 this.canvas = params.canvas; 14719 this.minRadius = params.minRadius || 15; 14720 this.arcWidth = params.arcWidth || 5; 14721 this.gapWidth = params.gapWidth || 3; 14722 this.centerX = params.centerX || this.canvas.width / 2; 14723 this.centerY = params.centerY || this.canvas.height / 2;
14724 this.infoLineLength = params.infoLineLength || 60; 14725 this.horizLineLength = params.horizLineLength || 10; 14726 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 14727 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 14728 14729 this.context = this.canvas.getContext('2d'); 14730 14731 this.width = this.canvas.width; 14732 this.height = this.canvas.height; 14733 14734 this.circles = []; 14735 this.runningCount = 0; 14736 }; 14737 14738 ProgressCircle.prototype = { 14739 constructor: ProgressCircle, 14740 14741 /** 14742 * @method Adds an progress monitor entry. 14743 * @param params.fillColor Color to fill in the circle. 14744 * @param params.outlineColor Color to outline the circle. 14745 * @param params.progressListener Callback function to fetch the progress. 14746 * @param params.infoListener Callback function to fetch the info. 14747 * @returns this 14748 */ 14749 addEntry: function(params) { 14750 this.circles.push(new Circle({ 14751 canvas: this.canvas, 14752 context: this.context, 14753 centerX: this.centerX, 14754 centerY: this.centerY, 14755 innerRadius: this.minRadius + this.circles.length * 14756 (this.gapWidth + this.arcWidth), 14757 arcWidth: this.arcWidth,
14758 infoLineLength: this.infoLineLength, 14759 horizLineLength: this.horizLineLength, 14760 14761 id: this.circles.length, 14762 fillColor: params.fillColor, 14763 outlineColor: params.outlineColor, 14764 progressListener: params.progressListener, 14765 infoListener: params.infoListener, 14766 infoLineAngle: this.infoLineBaseAngle + 14767 this.circles.length * this.infoLineAngleInterval, 14768 })); 14769 14770 return this; 14771 }, 14772 14773 /** 14774 * @method Starts the monitor and updates with the given interval. 14775 * @param interval Interval between updates, in millisecond. 14776 * @returns this 14777 */ 14778 start: function(interval) { 14779 var self = this; 14780 this.timer = setInterval(function() { 14781 self._update(); 14782 }, interval || 33); 14783 14784 return this; 14785 }, 14786 14787 /** 14788 * @method Stop the animation. 14789 */ 14790 stop: function() { 14791 clearTimeout(this.timer); 14792 }, 14793 14794 /** 14795 * @private 14796 * @method Call update on each circle and redraw them. 14797 * @returns this 14798 */ 14799 _update: function() { 14800 this._clear(); 14801 this.circles.forEach(function(circle, idx, array) { 14802 circle.update(); 14803 }); 14804 14805 return this; 14806 }, 14807 14808 /** 14809 * @private 14810 * @method Clear the canvas. 14811 * @returns this 14812 */ 14813 _clear: function() { 14814 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 14815 14816 return this; 14817 }, 14818 14819 }; 14820 14821 /** 14822 * @private 14823 * @class Individual progress circle. 14824 * @param params.canvas Canvas on which the circle will be drawn. 14825 * @param params.context Context of the canvas. 14826 * @param params.innerRadius Inner radius of the circle, in px. 14827 * @param params.arcWidth Width of each arc(circle). 14828 * @param params.gapWidth Distance between each arc. 14829 * @param params.centerX X coordinate of the center of circles. 14830 * @param params.centerY Y coordinate of the center of circles. 14831 * @param params.fillColor Color to fill in the circle. 14832 * @param params.outlineColor Color to outline the circle. 14833 * @param params.progressListener Callback function to fetch the progress. 14834 * @param params.infoListener Callback function to fetch the info. 14835 * @param params.infoLineAngle Angle of info line. 14836 */ 14837 var Circle = function(params) { 14838 this.id = params.id; 14839 this.canvas = params.canvas; 14840 this.context = params.context; 14841 this.centerX = params.centerX; 14842 this.centerY = params.centerY; 14843 this.arcWidth = params.arcWidth; 14844 this.innerRadius = params.innerRadius || 0; 14845 this.fillColor = params.fillColor || '#fff'; 14846 this.outlineColor = params.outlineColor || this.fillColor; 14847 this.progressListener = params.progressListener;
14848 this.infoLineLength = params.infoLineLength || 250; 14849 this.horizLineLength = params.horizLineLength || 50; 14850 this.infoListener = params.infoListener; 14851 this.infoLineAngle = params.infoLineAngle; 14852 14853 this.outerRadius = this.innerRadius + this.arcWidth; 14854 14855 // If the info listener is not registered, then don't calculate 14856 // the related coordinates 14857 if (!this.infoListener) return; 14858 14859 // calculate the info-line turning points 14860 var angle = this.infoLineAngle, 14861 arcDistance = (this.innerRadius + this.outerRadius) / 2, 14862 14863 sinA = Math.sin(angle), 14864 cosA = Math.cos(angle); 14865 14866 this.infoLineStartX = this.centerX + sinA * arcDistance; 14867 this.infoLineStartY = this.centerY - cosA * arcDistance; 14868 14869 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 14870 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 14871 14872 this.infoLineEndX = this.infoLineMidX + 14873 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 14874 this.infoLineEndY = this.infoLineMidY; 14875 14876 var infoText = document.createElement('div'), 14877 style = infoText.style; 14878 14879 style.color = this.fillColor; 14880 style.position = 'absolute'; 14881 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 14882 // style.top will be calculated in the `drawInfo` method. Since 14883 // user may want to change the size of the font, so the top offset 14884 // must be updated in each loop. 14885 infoText.className = 'ProgressCircleInfo'; // For css styling 14886 infoText.id = 'progress_circle_info_' + this.id; 14887 document.body.appendChild(infoText); 14888 this.infoText = infoText; 14889 }; 14890 14891 Circle.prototype = { 14892 constructor: Circle, 14893 14894 update: function() { 14895 this.progress = this.progressListener(); 14896 this._draw(); 14897 14898 if (this.infoListener) { 14899 this.info = this.infoListener(); 14900 this._drawInfo(); 14901 } 14902 }, 14903 14904 /** 14905 * @private 14906 * @method Draw the circle on the canvas. 14907 * @returns this 14908 */ 14909 _draw: function() { 14910 var ctx = this.context, 14911 14912 ANGLE_OFFSET = -Math.PI / 2, 14913 14914 startAngle = 0 + ANGLE_OFFSET, 14915 endAngle= startAngle + this.progress * Math.PI * 2, 14916 14917 x = this.centerX, 14918 y = this.centerY, 14919 14920 innerRadius = this.innerRadius - this.arcWidth - 1, 14921 outerRadius = this.outerRadius - this.arcWidth - 1; 14922 14923 if ( innerRadius < 0 ) 14924 return; 14925 14926 ctx.fillStyle = this.fillColor; 14927 ctx.strokeStyle = this.outlineColor; 14928 14929 ctx.beginPath(); 14930 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 14931 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 14932 ctx.closePath(); 14933 ctx.stroke(); 14934 ctx.fill(); 14935 14936 return this; 14937 }, 14938 14939 /** 14940 * @private 14941 * @method Draw the info lines and info text. 14942 * @returns this 14943 */ 14944 _drawInfo: function() { 14945 14946 var pointList, lineHeight; 14947 14948 pointList = [ 14949 [this.infoLineStartX, this.infoLineStartY], 14950 [this.infoLineMidX, this.infoLineMidY], 14951 [this.infoLineEndX, this.infoLineEndY], 14952 ]; 14953 this._drawSegments(pointList, false); 14954 14955 this.infoText.innerHTML = this.info; 14956 14957 lineHeight = this.infoText.offsetHeight; 14958 this.infoText.style.top = this.infoLineEndY + 14959 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 14960 14961 return this; 14962 }, 14963 14964 /** 14965 * @private 14966 * @method Helper function to draw the segments 14967 * @param pointList An array of points in the form of [x, y]. 14968 * @param close Whether to connect the first and last point. 14969 */ 14970 _drawSegments: function(pointList, close) { 14971 var ctx = this.context; 14972 14973 ctx.beginPath(); 14974 ctx.moveTo(pointList[0][0], pointList[0][1]); 14975 for (var i = 1; i < pointList.length; ++i) { 14976 ctx.lineTo(pointList[i][0], pointList[i][1]); 14977 } 14978 14979 if (close) { 14980 ctx.closePath(); 14981 } 14982 ctx.stroke(); 14983 }, 14984 }; 14985 14986 window.ProgressCircle = ProgressCircle; 14987 14988})(window, document); 14989 14990 14991 14992 14993/* ========================================================= 14994 * jquery.vc_chart.js v1.0 14995 * ========================================================= 14996 * Copyright 2013 Wpbakery 14997 * 14998 * Jquery chart plugin for the Visual Composer. 14999 * ========================================================= */ 15000(function($){ 15001 /** 15002 * Pie chart animated. 15003 * @param element - DOM element 15004 * @param options - settings object. 15005 * @constructor 15006 */ 15007 var VcChart = function(element, options) { 15008 this.el = element; 15009 this.$el = $(this.el); 15010 var $this = this; 15011 $this.options = $.extend({ 15012 color: 'wpb_button', 15013 units: '', 15014 width: '', 15015 label_selector: '.vc_pie_chart_value', 15016 back_selector: '.vc_pie_chart_back', 15017 responsive: true 15018 }, options); 15019 $this.init(); 15020 }; 15021 VcChart.prototype = { 15022 constructor: VcChart, 15023 _progress_v: 0, 15024 animated: false, 15025 colors: { 15026 'wpb_button': 'rgba(247, 247, 247, 1)', 15027 'btn-primary': 'rgba(0, 136, 204, 1)', 15028 'btn-info': 'rgba(88, 185, 218, 1)', 15029 'btn-success': 'rgba(106, 177, 101, 1)', 15030 'btn-warning': 'rgba(255, 153, 0, 1)', 15031 'btn-danger': 'rgba(255, 103, 91, 1)', 15032 'btn-inverse': 'rgba(85, 85, 85, 1)' 15033 }, 15034 init: function() { 15035 this.setupColor(); 15036 this.value = this.$el.data('pie-value')/100; 15037 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 15038 this.$wrapper = $('.vc_pie_wrapper', this.$el); 15039 this.$label = $(this.options.label_selector, this.$el); 15040 this.$back = $(this.options.back_selector, this.$el); 15041 this.$canvas = this.$el.find('canvas'); 15042 this.arcWidth = this.$el.data('pie-width') * 2; 15043 this.draw(); 15044 this.setWayPoint(); 15045 if(this.options.responsive === true) this.setResponsive(); 15046 if (UNCODE.isMobile) this._progress_v = this.value; 15047 }, 15048 setupColor: function() { 15049 // if(typeof this.colors[this.options.color] !== 'undefined') { 15050 // this.color = this.colors[this.options.color]; 15051 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 15052 // this.color = this.options.color; 15053 // } else { 15054 // this.color = 'rgba(247, 247, 247, 0.2)'; 15055 // } 15056 if(typeof this.options.color !== 'undefined') { 15057 this.color = this.options.color; 15058 } else this.color = 'rgba(247, 247, 247, 0.2)'; 15059 15060 }, 15061 setResponsive: function() { 15062 var that = this; 15063 if (!UNCODE.isMobile) { 15064 $(window).resize(function(){ 15065 if(that.animated === true) that.circle.stop(); 15066 that.draw(true); 15067 }); 15068 } 15069 }, 15070 draw: function(redraw) { 15071 var w = this.$el.addClass('vc_ready').width() * 2, 15072 border_w = this.arcWidth, 15073 radius; 15074 if(!w) w = this.$el.parents(':visible').first().width()-2; 15075 //w = Math.round(w/100*80); 15076 //if (w < 250) w = 250; 15077 radius = w/2; 15078 this.$wrapper.css({"width" : (w / 2) + "px"}); 15079 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 15080 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 15081 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 15082 this.$el.addClass('vc_ready'); 15083 this.circle = new ProgressCircle({ 15084 canvas: this.$canvas.get(0), 15085 minRadius: radius, 15086 arcWidth: border_w 15087 }); 15088 if(redraw === true && this.animated === true) { 15089 this._progress_v = this.value; 15090 this.circle.addEntry({ 15091 fillColor: this.color, 15092 progressListener: $.proxy(this.setProgress, this) 15093 }).start(); 15094 } 15095 }, 15096 setProgress: function() { 15097 if (this._progress_v >= this.value) { 15098 this.circle.stop(); 15099 this.animated = true; 15100 this.$label.html(this.label_value + this.options.units); 15101 return this._progress_v; 15102 } 15103 this._progress_v += 0.01; 15104 if (!isNaN(this.label_value)) { 15105 var label_value = this._progress_v/this.value*this.label_value; 15106 var val = Math.round(label_value) + this.options.units; 15107 this.$label.html(val); 15108 } else this.$label.html(this.label_value + this.options.units); 15109 return this._progress_v; 15110 }, 15111 animate: function() { 15112 if(this.animated !== true) { 15113 this.circle.addEntry({ 15114 fillColor: this.color, 15115 progressListener: $.proxy(this.setProgress, this) 15116 }).start(10); 15117 } 15118 }, 15119 setWayPoint: function() { 15120 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 15121 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 15122 } else { 15123 this.animate(); 15124 } 15125 } 15126 }; 15127 /** 15128 * jQuery plugin 15129 * @param option - object with settings 15130 * @return {*} 15131 */ 15132 $.fn.vcChat = function(option, value) { 15133 return this.each(function () { 15134 var $this = $(this), 15135 data = $this.data('vc_chart'), 15136 options = typeof option === 'object' ? option : { 15137 color: $this.data('pie-color'), 15138 units: $this.data('pie-units') 15139 }; 15140 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 15141 if (typeof option == 'string') data[option](value); 15142 }); 15143 }; 15144 /** 15145 * Allows users to rewrite function inside theme. 15146 */ 15147 if ( typeof window['vc_pieChart'] !== 'function' ) { 15148 window.vc_pieChart = function() { 15149 $('.vc_pie_chart:visible:not(.vc_ready)').vcChat(); 15150 } 15151 } 15152 $(document).ready(function(){ 15153 !window.vc_iframe && vc_pieChart(); 15154 15155 /** 15156 * Tab and collapse integration. 15157 */ 15158 $('.nav-tabs a').on('shown.bs.tab', function(e){ 15159 var $cont = $(e.target).closest('.tab-container'), 15160 $active = $('.tab-pane.active', $cont); 15161 $('.vc_pie_chart:not(.vc_ready)', $active).vcChat(); 15162 }); 15163 15164 $('.panel-collapse').on('shown.bs.collapse', function (e) { 15165 $('.vc_pie_chart:not(.vc_ready)', e.target).vcChat(); 15166 }) 15167 }); 15168 15169})(window.jQuery); 15170 15171/* Progress bar 15172 ---------------------------------------------------------- */ 15173function uncode_progress_bar() {    15174 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 15175 if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) { 15176 return; 15177 } 15178 if (!UNCODE.isMobile) { 15179 new Waypoint({ 15180 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 15181 element: val, 15182 handler: function() { 15183 var element = jQuery(this.element); 15184 element.find('.vc_single_bar').each(function(index) {          15185 var $this = jQuery(this), 15186             bar = $this.find('.vc_bar'), 15187             val = bar.data('percentage-value');          15188 setTimeout(function() {            15189 bar.css({ 15190 "width": val + '%' 15191 });          15192 }, index * 200);        15193 }); 15194 }, 15195 offset: '80%' 15196 }); 15197 } else { 15198 var element = jQuery(val); 15199 element.find('.vc_single_bar').each(function(index) {          15200 var $this = jQuery(this), 15201             bar = $this.find('.vc_bar'), 15202             val = bar.data('percentage-value');          15203 setTimeout(function() {            15204 bar.css({ 15205 "width": val + '%' 15206 });          15207 }, index * 200);        15208 }); 15209 } 15210 }); 15211}; 15212uncode_progress_bar(); 15213 15214/*! 15215 * jquery.counterup.js 1.0 15216 * 15217 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 15218 * Released under the GPL v2 License 15219 * 15220 * Date: Nov 26, 2013 15221 */ 15222(function($) { 15223 "use strict"; 15224 $.fn.counterUp = function(options) { 15225 // Defaults 15226 var settings = $.extend({ 15227 'time': 400, 15228 'delay': 10 15229 }, options); 15230 return this.each(function() { 15231 // Store the object 15232 var $this = $(this); 15233 var $settings = settings; 15234 var counterUpper = function() { 15235 var nums = []; 15236 var divisions = $settings.time / $settings.delay; 15237 var numReal = $this.attr('data-val'), 15238 num = numReal; 15239 var isComma = /[0-9]+,[0-9]+/.test(num); 15240 num = num.replace(/,/g, ''); 15241 var isInt = /^[0-9]+$/.test(num); 15242 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 15243 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 15244 // Generate list of incremental numbers to display 15245 for (var i = divisions; i >= 1; i--) { 15246 // Preserve as int if input was int 15247 var newNum = parseInt(num / divisions * i); 15248 // Preserve float if input was float 15249 if (isFloat) { 15250 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 15251 } 15252 // Preserve commas if input had commas 15253 if (isComma) { 15254 while (/(\d+)(\d{3})/.test(newNum.toString())) { 15255 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 15256 } 15257 } 15258 nums.unshift(newNum); 15259 } 15260 nums.push(numReal); 15261 $this.data('counterup-nums', nums); 15262 $this.text('0'); 15263 // Updates the number until we're done 15264 var f = function() { 15265 if ($this.data('counterup-nums') != null) { 15266 $this.text($this.data('counterup-nums').shift()); 15267 if ($this.data('counterup-nums').length) { 15268 setTimeout($this.data('counterup-func'), $settings.delay); 15269 } else { 15270 delete $this.data('counterup-nums'); 15271 $this.data('counterup-nums', null); 15272 $this.data('counterup-func', null); 15273 } 15274 } 15275 }; 15276 $this.data('counterup-func', f); 15277 // Start the count up 15278 setTimeout($this.data('counterup-func'), $settings.delay); 15279 }; 15280 // Perform counts when the element gets into view 15281 new Waypoint({ 15282 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 15283 element: this, 15284 handler: function() { 15285 counterUpper(); 15286 if (!UNCODE.isUnmodalOpen) { 15287 this.destroy(); 15288 } 15289 }, 15290 offset: '100%' 15291 }); 15292 }); 15293 }; 15294})(jQuery); 15295 15296/*! 15297 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/) 15298 * Copyright (c) 2016 Edson Hilios 15299 * 15300 * Permission is hereby granted, free of charge, to any person obtaining a copy of 15301 * this software and associated documentation files (the "Software"), to deal in 15302 * the Software without restriction, including without limitation the rights to 15303 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 15304 * the Software, and to permit persons to whom the Software is furnished to do so, 15305 * subject to the following conditions: 15306 * 15307 * The above copyright notice and this permission notice shall be included in all 15308 * copies or substantial portions of the Software. 15309 * 15310 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15311 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15312 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15313 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 15314 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 15315 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15316 */ 15317(function(factory) { 15318 "use strict"; 15319 if (typeof define === "function" && define.amd) { 15320 define([ "jquery" ], factory); 15321 } else { 15322 factory(jQuery); 15323 } 15324})(function($) { 15325 "use strict"; 15326 var instances = [], matchers = [], defaultOptions = { 15327 precision: 100, 15328 elapse: false, 15329 defer: false 15330 }; 15331 matchers.push(/^[0-9]*$/.source); 15332 matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 15333 matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 15334 matchers = new RegExp(matchers.join("|")); 15335 function parseDateString(dateString) { 15336 if (dateString instanceof Date) { 15337 return dateString; 15338 } 15339 if (String(dateString).match(matchers)) { 15340 if (String(dateString).match(/^[0-9]*$/)) { 15341 dateString = Number(dateString); 15342 } 15343 if (String(dateString).match(/\-/)) { 15344 dateString = String(dateString).replace(/\-/g, "/"); 15345 } 15346 return new Date(dateString); 15347 } else { 15348 throw new Error("Couldn't cast `" + dateString + "` to a date object."); 15349 } 15350 } 15351 var DIRECTIVE_KEY_MAP = { 15352 Y: "years", 15353 m: "months", 15354 n: "daysToMonth", 15355 d: "daysToWeek", 15356 w: "weeks", 15357 W: "weeksToMonth", 15358 H: "hours", 15359 M: "minutes", 15360 S: "seconds", 15361 D: "totalDays", 15362 I: "totalHours", 15363 N: "totalMinutes", 15364 T: "totalSeconds" 15365 }; 15366 function escapedRegExp(str) { 15367 var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); 15368 return new RegExp(sanitize); 15369 } 15370 function strftime(offsetObject) { 15371 return function(format) { 15372 var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi); 15373 if (directives) { 15374 for (var i = 0, len = directives.length; i < len; ++i) { 15375 var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null; 15376 directive = directive[2]; 15377 if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) { 15378 value = DIRECTIVE_KEY_MAP[directive]; 15379 value = Number(offsetObject[value]); 15380 } 15381 if (value !== null) { 15382 if (modifier === "!") { 15383 value = pluralize(plural, value); 15384 } 15385 if (modifier === "") { 15386 if (value < 10) { 15387
vendor: 4,091 bytes, lines 15387-15524
15387 value = "0" + value.toString(); 15388 } 15389 } 15390 format = format.replace(regexp, value.toString()); 15391 } 15392 } 15393 } 15394 format = format.replace(/%%/, "%"); 15395 return format; 15396 }; 15397 } 15398 function pluralize(format, count) { 15399 var plural = "s", singular = ""; 15400 if (format) { 15401 format = format.replace(/(:|;|\s)/gi, "").split(/\,/); 15402 if (format.length === 1) { 15403 plural = format[0]; 15404 } else { 15405 singular = format[0]; 15406 plural = format[1]; 15407 } 15408 } 15409 if (Math.abs(count) > 1) { 15410 return plural; 15411 } else { 15412 return singular; 15413 } 15414 } 15415 var Countdown = function(el, finalDate, options) { 15416 this.el = el; 15417 this.$el = $(el); 15418 this.interval = null; 15419 this.offset = {}; 15420 this.options = $.extend({}, defaultOptions); 15421 this.instanceNumber = instances.length; 15422 instances.push(this); 15423 this.$el.data("countdown-instance", this.instanceNumber); 15424 if (options) { 15425 if (typeof options === "function") { 15426 this.$el.on("update.countdown", options); 15427 this.$el.on("stoped.countdown", options); 15428 this.$el.on("finish.countdown", options); 15429 } else { 15430 this.options = $.extend({}, defaultOptions, options); 15431 } 15432 } 15433 this.setFinalDate(finalDate); 15434 if (this.options.defer === false) { 15435 this.start(); 15436 } 15437 }; 15438 $.extend(Countdown.prototype, { 15439 start: function() { 15440 if (this.interval !== null) { 15441 clearInterval(this.interval); 15442 } 15443 var self = this; 15444 this.update(); 15445 this.interval = setInterval(function() { 15446 self.update.call(self); 15447 }, this.options.precision); 15448 }, 15449 stop: function() { 15450 clearInterval(this.interval); 15451 this.interval = null; 15452 this.dispatchEvent("stoped"); 15453 }, 15454 toggle: function() { 15455 if (this.interval) { 15456 this.stop(); 15457 } else { 15458 this.start(); 15459 } 15460 }, 15461 pause: function() { 15462 this.stop(); 15463 }, 15464 resume: function() { 15465 this.start(); 15466 }, 15467 remove: function() { 15468 this.stop.call(this); 15469 instances[this.instanceNumber] = null; 15470 delete this.$el.data().countdownInstance; 15471 }, 15472 setFinalDate: function(value) { 15473 this.finalDate = parseDateString(value); 15474 }, 15475 update: function() { 15476 if (this.$el.closest("html").length === 0) { 15477 this.remove(); 15478 return; 15479 } 15480 var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft; 15481 newTotalSecsLeft = this.finalDate.getTime() - now.getTime(); 15482 newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3); 15483 newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft); 15484 if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) { 15485 return; 15486 } else { 15487 this.totalSecsLeft = newTotalSecsLeft; 15488 } 15489 this.elapsed = now >= this.finalDate; 15490 this.offset = { 15491 seconds: this.totalSecsLeft % 60, 15492 minutes: Math.floor(this.totalSecsLeft / 60) % 60, 15493 hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24, 15494 days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 15495 daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 15496 daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368), 15497 weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7), 15498 weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4, 15499 months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368), 15500 years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()), 15501 totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24), 15502 totalHours: Math.floor(this.totalSecsLeft / 60 / 60), 15503 totalMinutes: Math.floor(this.totalSecsLeft / 60), 15504 totalSeconds: this.totalSecsLeft 15505 }; 15506 if (!this.options.elapse && this.totalSecsLeft === 0) { 15507 this.stop(); 15508 this.dispatchEvent("finish"); 15509 } else { 15510 this.dispatchEvent("update"); 15511 } 15512 }, 15513 dispatchEvent: function(eventName) { 15514 var event = $.Event(eventName + ".countdown"); 15515 event.finalDate = this.finalDate; 15516 event.elapsed = this.elapsed; 15517 event.offset = $.extend({}, this.offset); 15518 event.strftime = strftime(this.offset); 15519 this.$el.trigger(event); 15520 } 15521 }); 15522 $.fn.countdown = function() { 15523 var argumentsArray = Array.prototype.slice.call(arguments, 0); 15524 return this.each(function() {
15525 var instanceNumber = $(this).data("countdown-instance"); 15526 if (instanceNumber !== undefined) { 15527 var instance = instances[instanceNumber], method = argumentsArray[0]; 15528 if (Countdown.prototype.hasOwnProperty(method)) { 15529 instance[method].apply(instance, argumentsArray.slice(1)); 15530 } else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) { 15531 instance.setFinalDate.call(instance, method); 15532 instance.start(); 15533 } else { 15534 $.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method)); 15535 } 15536 } else { 15537 new Countdown(this, argumentsArray[0], argumentsArray[1]); 15538 } 15539 }); 15540 }; 15541}); 15542 15543/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 15544* https://github.com/alexanderdickson/waitForImages 15545* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 15546;(function (factory) { 15547 if (typeof define === 'function' && define.amd) { 15548 // AMD. Register as an anonymous module. 15549 define(['jquery'], factory); 15550 } else if (typeof exports === 'object') { 15551 // CommonJS / nodejs module 15552 module.exports = factory(require('jquery')); 15553 } else { 15554 // Browser globals 15555 factory(jQuery); 15556 } 15557}(function ($) { 15558 // Namespace all events. 15559 var eventNamespace = 'waitForImages'; 15560 15561 // CSS properties which contain references to images. 15562 $.waitForImages = { 15563 hasImageProperties: [ 15564 'backgroundImage', 15565 'listStyleImage', 15566 'borderImage', 15567 'borderCornerImage', 15568 'cursor' 15569 ], 15570 hasImageAttributes: ['srcset'] 15571 }; 15572 15573 // Custom selector to find `img` elements that have a valid `src` 15574 // attribute and have not already loaded. 15575 $.expr[':'].uncached = function (obj) { 15576 // Ensure we are dealing with an `img` element with a valid 15577 // `src` attribute. 15578 if (!$(obj).is('img[src][src!=""]')) { 15579 return false; 15580 } 15581 15582 return !obj.complete; 15583 }; 15584 15585 $.fn.waitForImages = function () { 15586 15587 var allImgsLength = 0; 15588 var allImgsLoaded = 0; 15589 var deferred = $.Deferred(); 15590 15591 var finishedCallback; 15592 var eachCallback; 15593 var waitForAll; 15594 15595 // Handle options object (if passed). 15596 if ($.isPlainObject(arguments[0])) { 15597 15598 waitForAll = arguments[0].waitForAll; 15599 eachCallback = arguments[0].each; 15600 finishedCallback = arguments[0].finished; 15601 15602 } else { 15603 15604 // Handle if using deferred object and only one param was passed in. 15605 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 15606 waitForAll = arguments[0]; 15607 } else { 15608 finishedCallback = arguments[0]; 15609 eachCallback = arguments[1]; 15610 waitForAll = arguments[2]; 15611 } 15612 15613 } 15614 15615 // Handle missing callbacks. 15616 finishedCallback = finishedCallback || $.noop; 15617 eachCallback = eachCallback || $.noop; 15618 15619 // Convert waitForAll to Boolean 15620 waitForAll = !! waitForAll; 15621 15622 // Ensure callbacks are functions. 15623 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 15624 throw new TypeError('An invalid callback was supplied.'); 15625 } 15626 15627 this.each(function () { 15628 // Build a list of all imgs, dependent on what images will 15629 // be considered. 15630 var obj = $(this); 15631 var allImgs = []; 15632 // CSS properties which may contain an image. 15633 var hasImgProperties = $.waitForImages.hasImageProperties || []; 15634 // Element attributes which may contain an image. 15635 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 15636 // To match `url()` references. 15637 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 15638 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 15639 15640 if (waitForAll) { 15641 15642 // Get all elements (including the original), as any one of 15643 // them could have a background image. 15644 obj.find('*').addBack().each(function () { 15645 var element = $(this); 15646 15647 // If an `img` element, add it. But keep iterating in 15648 // case it has a background image too. 15649 if (element.is('img:uncached')) { 15650 allImgs.push({ 15651 src: element.attr('src'), 15652 element: element[0] 15653 }); 15654 } 15655 15656 $.each(hasImgProperties, function (i, property) { 15657 var propertyValue = element.css(property); 15658 var match; 15659 15660 // If it doesn't contain this property, skip. 15661 if (!propertyValue) { 15662 return true; 15663 } 15664 15665 // Get all url() of this element. 15666 while (match = matchUrl.exec(propertyValue)) { 15667 allImgs.push({ 15668 src: match[2], 15669 element: element[0] 15670 }); 15671 } 15672 }); 15673 15674 $.each(hasImageAttributes, function (i, attribute) { 15675 var attributeValue = element.attr(attribute); 15676 var attributeValues; 15677 15678 // If it doesn't contain this property, skip. 15679 if (!attributeValue) { 15680 return true; 15681 } 15682 15683 // Check for multiple comma separated images 15684 attributeValues = attributeValue.split(','); 15685 15686 $.each(attributeValues, function(i, value) { 15687 // Trim value and get string before first 15688 // whitespace (for use with srcset). 15689 value = $.trim(value).split(' ')[0]; 15690 allImgs.push({ 15691 src: value, 15692 element: element[0] 15693 }); 15694 }); 15695 }); 15696 }); 15697 } else { 15698 // For images only, the task is simpler. 15699 obj.find('img:uncached') 15700 .each(function () { 15701 allImgs.push({ 15702 src: this.src, 15703 element: this 15704 }); 15705 }); 15706 } 15707 15708 allImgsLength = allImgs.length; 15709 allImgsLoaded = 0; 15710 15711 // If no images found, don't bother. 15712 if (allImgsLength === 0) { 15713 finishedCallback.call(obj[0]); 15714 deferred.resolveWith(obj[0]); 15715 } 15716 15717 $.each(allImgs, function (i, img) { 15718 15719 var image = new Image(); 15720 var events = 15721 'load.' + eventNamespace + ' error.' + eventNamespace; 15722 15723 // Handle the image loading and error with the same callback. 15724 $(image).one(events, function me (event) { 15725 // If an error occurred with loading the image, set the 15726 // third argument accordingly. 15727 var eachArguments = [ 15728 allImgsLoaded, 15729 allImgsLength,
15730 event.type == 'load' 15731 ]; 15732 allImgsLoaded++; 15733 15734 eachCallback.apply(img.element, eachArguments); 15735 deferred.notifyWith(img.element, eachArguments); 15736 15737 // Unbind the event listeners. I use this in addition to 15738 // `one` as one of those events won't be called (either 15739 // 'load' or 'error' will be called). 15740 $(this).off(events, me); 15741 15742 if (allImgsLoaded == allImgsLength) { 15743 finishedCallback.call(obj[0]); 15744 deferred.resolveWith(obj[0]); 15745 return false; 15746 } 15747 15748 }); 15749 15750 image.src = img.src; 15751 }); 15752 }); 15753 15754 return deferred.promise(); 15755 15756 }; 15757})); 15758 15759/** 15760 * @preserve textfill 15761 * @name jquery.textfill.js 15762 * @author Russ Painter 15763 * @author Yu-Jie Lin 15764 * @author Alexandre Dantas 15765 * @version 0.6.0 15766 * @date 2014-08-19 15767 * @copyright (c) 2014 Alexandre Dantas 15768 * @copyright (c) 2012-2013 Yu-Jie Lin 15769 * @copyright (c) 2009 Russ Painter 15770 * @license MIT License 15771 * @homepage https://github.com/jquery-textfill/jquery-textfill 15772 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 15773 */ 15774; (function($) { 15775 15776 /** 15777 * Resizes an inner element's font so that the 15778 * inner element completely fills the outer element. 15779 * 15780 * @param {Object} options User options that take 15781 * higher precedence when 15782 * merging with the default ones. 15783 * 15784 * @return All outer elements processed 15785 */ 15786 $.fn.textfill = function(options) { 15787 15788 // ______ _______ _______ _______ _ _ _______ _______ 15789 // | \ |______ |______ |_____| | | | | |______ 15790 // |_____/ |______ | | | |_____| |_____ | ______| 15791 // 15792 // Merging user options with the default values 15793 15794 var defaults = { 15795 debug : false, 15796 maxFontPixels : 40, 15797 minFontPixels : 4, 15798 innerTag : 'span', 15799 widthOnly : false, 15800 success : null, // callback when a resizing is done 15801 callback : null, // callback when a resizing is done (deprecated, use success) 15802 fail : null, // callback when a resizing is failed 15803 complete : null, // callback when all is done 15804 explicitWidth : null, 15805 explicitHeight : null, 15806 changeLineHeight : false 15807 }; 15808 15809 var Opts = $.extend(defaults, options); 15810 15811 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 15812 // |______ | | | \ | | | | | | | \ | |______ 15813 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 15814 // 15815 // Predefining the awesomeness 15816 15817 // Output arguments to the Debug console 15818 // if "Debug Mode" is enabled 15819 function _debug() { 15820 if (!Opts.debug 15821 || typeof console == 'undefined' 15822 || typeof console.debug == 'undefined') { 15823 return; 15824 } 15825 console.debug.apply(console, arguments); 15826 } 15827 15828 // Output arguments to the Warning console 15829 function _warn() { 15830 if (typeof console == 'undefined' || 15831 typeof console.warn == 'undefined') { 15832 return; 15833 } 15834 console.warn.apply(console, arguments); 15835 } 15836 15837 // Outputs all information on the current sizing 15838 // of the font. 15839 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 15840 15841 function _m(v1, v2) { 15842 15843 var marker = ' / '; 15844 15845 if (v1 > v2) 15846 marker = ' > '; 15847 15848 else if (v1 == v2) 15849 marker = ' = '; 15850 15851 return marker; 15852 } 15853 15854 _debug( 15855 '[TextFill] ' + prefix + ' { ' + 15856 'font-size: ' + ourText.css('font-size') + ',' +
15857 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 15858 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 15859 'minFontPixels: ' + minFontPixels + 'px, ' + 15860 'maxFontPixels: ' + maxFontPixels + 'px }' 15861 ); 15862 } 15863 15864 /** 15865 * Calculates which size the font can get resized, 15866 * according to constrains. 15867 * 15868 * @param {String} prefix Gets shown on the console before 15869 * all the arguments, if debug mode is on. 15870 * @param {Object} ourText The DOM element to resize, 15871 * that contains the text. 15872 * @param {function} func Function called on `ourText` that's 15873 * used to compare with `max`. 15874 * @param {number} max Maximum value, that gets compared with 15875 * `func` called on `ourText`. 15876 * @param {number} minFontPixels Minimum value the font can 15877 * get resized to (in pixels). 15878 * @param {number} maxFontPixels Maximum value the font can 15879 * get resized to (in pixels). 15880 * 15881 * @return Size (in pixels) that the font can be resized. 15882 */ 15883 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 15884 15885 _debug_sizing( 15886 prefix, ourText, 15887 maxHeight, maxWidth, 15888 minFontPixels, maxFontPixels 15889 ); 15890 15891 // The kernel of the whole plugin, take most attention 15892 // on this part. 15893 // 15894 // This is a loop that keeps increasing the `font-size` 15895 // until it fits the parent element. 15896 // 15897 // - Start from the minimal allowed value (`minFontPixels`) 15898 // - Guesses an average font size (in pixels) for the font, 15899 // - Resizes the text and sees if its size is within the 15900 // boundaries (`minFontPixels` and `maxFontPixels`). 15901 // - If so, keep guessing until we break. 15902 // - If not, return the last calculated size. 15903 // 15904 // I understand this is not optimized and we should 15905 // consider implementing something akin to 15906 // Daniel Hoffmann's answer here: 15907 // 15908 // http://stackoverflow.com/a/17433451/1094964 15909 // 15910 15911 while (minFontPixels < (maxFontPixels - 1)) { 15912 15913 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 15914 ourText.css('font-size', fontSize); 15915 15916 if (func.call(ourText) <= max) { 15917 minFontPixels = fontSize; 15918 15919 if (func.call(ourText) == max) 15920 break; 15921 } 15922 else 15923 maxFontPixels = fontSize; 15924 15925 _debug_sizing( 15926 prefix, ourText, 15927 maxHeight, maxWidth, 15928 minFontPixels, maxFontPixels 15929 ); 15930 } 15931 15932 ourText.css('font-size', maxFontPixels); 15933 15934 if (func.call(ourText) <= max) { 15935 minFontPixels = maxFontPixels; 15936 15937 _debug_sizing( 15938 prefix + '* ', ourText, 15939 maxHeight, maxWidth, 15940 minFontPixels, maxFontPixels 15941 ); 15942 } 15943 return minFontPixels; 15944 } 15945 15946 // _______ _______ _______ ______ _______ 15947 // |______ | |_____| |_____/ | 15948 // ______| | | | | \_ | 15949 // 15950 // Let's get it started (yeah)! 15951 15952 _debug('[TextFill] Start Debug'); 15953 15954 this.each(function() { 15955 15956 // Contains the child element we will resize. 15957 // $(this) means the parent container 15958 var ourText = $(Opts.innerTag + ':visible:first', this); 15959 15960 // Will resize to this dimensions. 15961 // Use explicit dimensions when specified 15962 var maxHeight = Opts.explicitHeight || $(this).height(); 15963 var maxWidth = Opts.explicitWidth || $(this).width(); 15964 15965 var oldFontSize = ourText.css('font-size'); 15966 15967 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 15968 15969 _debug('[TextFill] Inner text: ' + ourText.text()); 15970 _debug('[TextFill] All options: ', Opts); 15971 _debug('[TextFill] Maximum sizes: { ' + 15972 'Height: ' + maxHeight + 'px, ' + 15973 'Width: ' + maxWidth + 'px' + ' }' 15974 ); 15975 15976 var minFontPixels = Opts.minFontPixels; 15977 15978 // Remember, if this `maxFontPixels` is negative, 15979 // the text will resize to as long as the container 15980 // can accomodate 15981 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 15982 maxHeight : 15983 Opts.maxFontPixels); 15984 15985 15986 // Let's start it all! 15987 15988 // 1. Calculate which `font-size` would 15989 // be best for the Height 15990 var fontSizeHeight = undefined; 15991 15992 if (! Opts.widthOnly) 15993 fontSizeHeight = _sizing( 15994 'Height', ourText, 15995 $.fn.height, maxHeight, 15996 maxHeight, maxWidth, 15997 minFontPixels, maxFontPixels 15998 ); 15999 16000 // 2. Calculate which `font-size` would 16001 // be best for the Width 16002 var fontSizeWidth = undefined; 16003 16004 fontSizeWidth = _sizing( 16005 'Width', ourText, 16006 $.fn.width, maxWidth, 16007 maxHeight, maxWidth, 16008 minFontPixels, maxFontPixels 16009 ); 16010 16011 // 3. Actually resize the text! 16012 16013 if (Opts.widthOnly) { 16014 ourText.css({ 16015 'font-size' : fontSizeWidth, 16016 'white-space': 'nowrap' 16017 }); 16018 16019 if (Opts.changeLineHeight) 16020 ourText.parent().css( 16021 'line-height', 16022 (lineHeight * fontSizeWidth + 'px') 16023 ); 16024 } 16025 else { 16026 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 16027 16028 ourText.css('font-size', fontSizeFinal); 16029 16030 if (Opts.changeLineHeight) 16031 ourText.parent().css( 16032 'line-height', 16033 (lineHeight * fontSizeFinal) + 'px' 16034 ); 16035 } 16036 16037 _debug( 16038 '[TextFill] Finished { ' + 16039 'Old font-size: ' + oldFontSize + ', ' + 16040 'New font-size: ' + ourText.css('font-size') + ' }' 16041 ); 16042 16043 // Oops, something wrong happened! 16044 // We weren't supposed to exceed the original size 16045 if ((ourText.width() > maxWidth) ||
16046 (ourText.height() > maxHeight && !Opts.widthOnly)) { 16047 16048 ourText.css('font-size', oldFontSize); 16049 16050 // Failure callback 16051 if (Opts.fail) 16052 Opts.fail(this); 16053 16054 _debug( 16055 '[TextFill] Failure { ' + 16056 'Current Width: ' + ourText.width() + ', ' + 16057 'Maximum Width: ' + maxWidth + ', ' + 16058 'Current Height: ' + ourText.height() + ', ' + 16059 'Maximum Height: ' + maxHeight + ' }' 16060 ); 16061 } 16062 else if (Opts.success) { 16063 Opts.success(this); 16064 } 16065 else if (Opts.callback) { 16066 _warn('callback is deprecated, use success, instead'); 16067 16068 // Success callback 16069 Opts.callback(this); 16070 } 16071 }); 16072 16073 // Complete callback 16074 if (Opts.complete) 16075 Opts.complete(this); 16076 16077 _debug('[TextFill] End Debug'); 16078 return this; 16079 }; 16080 16081})(window.jQuery); 16082 16083!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; 16084function getStyles(config){ 16085 // 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;
16085left: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+"}" 16086}; 16087 var ShareUtils; 16088 16089if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 16090 Object.defineProperty(HTMLElement.prototype, "classList", { 16091 get: function() { 16092 var ret, self, update; 16093 update = function(fn) { 16094 return function(value) { 16095 var classes, index; 16096 classes = self.className.split(/\s+/); 16097 index = classes.indexOf(value); 16098 fn(classes, index, value); 16099 self.className = classes.join(" "); 16100 }; 16101 }; 16102 self = this; 16103 ret = { 16104 add: update(function(classes, index, value) { 16105 ~index || classes.push(value); 16106 }), 16107 remove: update(function(classes, index) { 16108 ~index && classes.splice(index, 1); 16109 }), 16110 toggle: update(function(classes, index, value) { 16111 if (~index) { 16112 classes.splice(index, 1); 16113 } else { 16114 classes.push(value); 16115 } 16116 }), 16117 contains: function(value) { 16118 return !!~self.className.split(/\s+/).indexOf(value); 16119 }, 16120 item: function(i) { 16121 return self.className.split(/\s+/)[i] || null; 16122 } 16123 }; 16124 Object.defineProperty(ret, "length", { 16125 get: function() { 16126 return self.className.split(/\s+/).length; 16127 } 16128 }); 16129 return ret; 16130 } 16131 }); 16132} 16133 16134String.prototype.to_rfc3986 = function() { 16135 var tmp; 16136 tmp = encodeURIComponent(this); 16137 return tmp.replace(/[!'()*]/g, function(c) { 16138 return "%" + c.charCodeAt(0).toString(16); 16139 }); 16140}; 16141 16142ShareUtils = (function() { 16143 function ShareUtils() {} 16144 16145 ShareUtils.prototype.extend = function(to, from, overwrite) { 16146 var hasProp, prop; 16147 for (prop in from) { 16148 hasProp = to[prop] !== undefined; 16149 if (hasProp && typeof from[prop] === "object") { 16150 this.extend(to[prop], from[prop], overwrite); 16151 } else { 16152 if (overwrite || !hasProp) { 16153 to[prop] = from[prop]; 16154 } 16155 } 16156 } 16157 }; 16158 16159 ShareUtils.prototype.hide = function(el) { 16160 return el.style.display = "none"; 16161 }; 16162 16163 ShareUtils.prototype.show = function(el) { 16164 return el.style.display = "block"; 16165 }; 16166 16167 ShareUtils.prototype.has_class = function(el, class_name) { 16168 return el.classList.contains(class_name); 16169 }; 16170 16171 ShareUtils.prototype.add_class = function(el, class_name) { 16172 return el.classList.add(class_name); 16173 }; 16174 16175 ShareUtils.prototype.remove_class = function(el, class_name) { 16176 return el.classList.remove(class_name); 16177 }; 16178 16179 ShareUtils.prototype.is_encoded = function(str) { 16180 str = str.to_rfc3986(); 16181 return decodeURIComponent(str) !== str; 16182 }; 16183 16184 ShareUtils.prototype.encode = function(str) { 16185 if (typeof str === "undefined" || this.is_encoded(str)) { 16186 return str; 16187 } else { 16188 return str.to_rfc3986(); 16189 } 16190 }; 16191 16192 ShareUtils.prototype.popup = function(url, params) { 16193 var k, popup, qs, v; 16194 if (params == null) { 16195 params = {}; 16196 } 16197 popup = { 16198 width: 500, 16199 height: 350 16200 }; 16201 popup.top = (screen.height / 2) - (popup.height / 2); 16202 popup.left = (screen.width / 2) - (popup.width / 2); 16203 qs = ((function() { 16204 var _results; 16205 _results = []; 16206 for (k in params) { 16207 v = params[k]; 16208 _results.push("" + k + "=" + (this.encode(v))); 16209 } 16210 return _results; 16211 }).call(this)).join('&'); 16212 if (qs) { 16213 qs = "?" + qs; 16214 } 16215 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="
16215+ popup.width + ",height=" + popup.height); 16216 }; 16217 16218 return ShareUtils; 16219 16220})(); 16221var Share, 16222 __hasProp = {}.hasOwnProperty, 16223 __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; }; 16224 16225Share = (function(_super) { 16226 __extends(Share, _super); 16227 16228 function Share(element, options) { 16229 this.element = element; 16230 this.el = { 16231 head: document.getElementsByTagName('head')[0], 16232 body: document.getElementsByTagName('body')[0] 16233 }; 16234 this.config = { 16235 enabled_networks: 0, 16236 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 16237 url: window.location.href.replace("&", "%26"), 16238 caption: null, 16239 title: this.default_title(), 16240 image: this.default_image(), 16241 description: this.default_description(), 16242 ui: { 16243 flyout: 'top center', 16244 button_text: 'Share', 16245 button_font: true, 16246 icon_font: true 16247 }, 16248 networks: { 16249 google_plus: { 16250 enabled: true, 16251 url: null 16252 }, 16253 twitter: { 16254 enabled: true, 16255 url: null, 16256 title: null, 16257 description: null 16258 }, 16259 facebook: { 16260 enabled: true, 16261 load_sdk: true, 16262 url: null, 16263 app_id: null, 16264 title: null, 16265 caption: null, 16266 description: null, 16267 image: null 16268 }, 16269 pinterest: { 16270 enabled: true, 16271 url: null, 16272 image: null, 16273 description: null 16274 }, 16275 reddit: { 16276 enabled: true, 16277 url: null, 16278 title: null 16279 }, 16280 linkedin: { 16281 enabled: true, 16282 url: null, 16283 title: null, 16284 description: null 16285 }, 16286 xing: { 16287 enabled: true, 16288 url: null, 16289 title: null, 16290 image: null, 16291 description: null 16292 }, 16293 whatsapp: { 16294 enabled: true, 16295 description: null, 16296 url: null 16297 }, 16298 email: { 16299 enabled: true, 16300 title: null, 16301 description: null, 16302 url: null 16303 } 16304 } 16305 }; 16306 this.setup(element, options); 16307 return this; 16308 } 16309 16310 Share.prototype.setup = function(element, opts) { 16311 var index, instance, instances, _i, _len; 16312 instances = document.querySelectorAll(element); 16313 this.extend(this.config, opts, true); 16314 this.set_global_configuration(); 16315 this.normalize_network_configuration(); 16316 if (this.config.ui.icon_font) { 16317 this.inject_icons(); 16318 } 16319 if (this.config.ui.button_font) { 16320 this.inject_fonts(); 16321 } 16322 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 16323 this.inject_facebook_sdk(); 16324 } 16325 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 16326 instance = instances[index]; 16327 this.setup_instance(element, index); 16328 } 16329 }; 16330 16331 Share.prototype.setup_instance = function(element, index) { 16332 var button, instance, label, network, networks, _i, _len, _results, 16333 _this = this; 16334 instance = document.querySelectorAll(element)[index]; 16335 this.hide(instance); 16336 this.add_class(instance, "sharer-" + index); 16337 instance = document.querySelectorAll(element)[index]; 16338 this.inject_css(instance); 16339 this.inject_html(instance); 16340 this.show(instance); 16341 label = instance.getElementsByTagName("label")[0]; 16342 button = instance.getElementsByClassName("social")[0]; 16343 networks = instance.getElementsByTagName('li'); 16344 this.add_class(button, "networks-" + this.config.enabled_networks); 16345 label.addEventListener("click", function() { 16346 return _this.event_toggle(button); 16347 }); 16348 _this = this; 16349 _results = []; 16350 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 16351 network = networks[index]; 16352 _results.push(network.addEventListener("click", function() { 16353 _this.event_network(instance, this); 16354 return _this.event_close(button); 16355 })); 16356 } 16357 return _results; 16358 }; 16359 16360 Share.prototype.event_toggle = function(button) { 16361 if (this.has_class(button, "active")) { 16362 return this.event_close(button); 16363 } else { 16364 return this.event_open(button); 16365 } 16366 }; 16367 16368 Share.prototype.event_open = function(button) { 16369 if (this.has_class(button, "load")) { 16370 this.remove_class(button, "load"); 16371 } 16372 return this.add_class(button, "active"); 16373 }; 16374 16375 Share.prototype.event_close = function(button) { 16376 return this.remove_class(button, "active"); 16377 }; 16378 16379 Share.prototype.event_network = function(instance, network) { 16380 var name; 16381 name = network.getAttribute("data-network"); 16382 this.hook("before", name, instance);
16383 this["network_" + name](); 16384 return this.hook("after", name, instance); 16385 }; 16386 16387 Share.prototype.open = function() { 16388 return this["public"]("open"); 16389 }; 16390 16391 Share.prototype.close = function() { 16392 return this["public"]("close"); 16393 }; 16394 16395 Share.prototype.toggle = function() { 16396 return this["public"]("toggle"); 16397 }; 16398 16399 Share.prototype["public"] = function(action) { 16400 var button, index, instance, _i, _len, _ref, _results; 16401 _ref = document.querySelectorAll(this.element); 16402 _results = []; 16403 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 16404 instance = _ref[index]; 16405 button = instance.getElementsByClassName("social")[0]; 16406 _results.push(this["event_" + action](button)); 16407 } 16408 return _results; 16409 }; 16410 16411 Share.prototype.network_facebook = function() { 16412 if (this.config.networks.facebook.load_sdk) { 16413 if (!window.FB) { 16414 return console.error("The Facebook JS SDK hasn't loaded yet."); 16415 } 16416 return FB.ui({ 16417 method: 'feed', 16418 name: this.config.networks.facebook.title, 16419 link: this.config.networks.facebook.url, 16420 picture: this.config.networks.facebook.image, 16421 caption: this.config.networks.facebook.caption, 16422 description: this.config.networks.facebook.description 16423 }); 16424 } else { 16425 return this.popup('https://www.facebook.com/sharer/sharer.php', { 16426 u: this.config.networks.facebook.url 16427 }); 16428 } 16429 }; 16430 16431 Share.prototype.network_twitter = function() { 16432 return this.popup('https://twitter.com/intent/tweet', { 16433 text: this.config.networks.twitter.title, 16434 url: this.config.networks.twitter.url 16435 }); 16436 }; 16437 16438 Share.prototype.network_google_plus = function() { 16439 return this.popup('https://plus.google.com/share', { 16440 url: this.config.networks.google_plus.url 16441 }); 16442 }; 16443 16444 Share.prototype.network_pinterest = function() { 16445 return this.popup('https://www.pinterest.com/pin/create/button', { 16446 url: this.config.networks.pinterest.url, 16447 media: this.config.networks.pinterest.image, 16448 description: this.config.networks.pinterest.description 16449 }); 16450 }; 16451 16452 Share.prototype.network_linkedin = function() { 16453 return this.popup('https://www.linkedin.com/shareArticle', { 16454 url: this.config.networks.linkedin.url, 16455 title: this.config.networks.linkedin.title, 16456 summary: this.config.networks.linkedin.description 16457 }); 16458 } 16459 16460 Share.prototype.network_xing = function() { 16461 return this.popup('https://www.xing.com/spi/shares/new', { 16462 url: this.config.networks.xing.url, 16463 image: this.config.networks.xing.image, 16464 title: this.config.networks.xing.title, 16465 summary: this.config.networks.xing.description 16466 }); 16467 } 16468 16469 Share.prototype.network_email = function() { 16470 return this.popup('mailto:', { 16471 subject: this.config.networks.email.title, 16472 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 16473 }); 16474 }; 16475 16476 Share.prototype.inject_icons = function() { 16477 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 16478 }; 16479 16480 Share.prototype.inject_fonts = function() { 16481 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 16482 }; 16483 16484 Share.prototype.inject_stylesheet = function(url) { 16485 var link; 16486 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 16487 link = document.createElement("link"); 16488 link.setAttribute("rel", "stylesheet"); 16489 link.setAttribute("href", url); 16490 return this.el.head.appendChild(link); 16491 } 16492 }; 16493 16494 Share.prototype.inject_css = function(instance) { 16495 var css, meta, selector, style; 16496 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 16497 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 16498 this.config.selector = selector; 16499 css = getStyles(this.config); 16500 style = document.createElement("style"); 16501 style.type = "text/css"; 16502 if (style.styleSheet) { 16503 style.styleSheet.cssText = css; 16504 } else { 16505 style.appendChild(document.createTextNode(css)); 16506 } 16507 this.el.head.appendChild(style); 16508 delete this.config.selector; 16509 meta = document.createElement("meta"); 16510 meta.setAttribute("name", "sharer" + selector); 16511 return this.el.head.appendChild(meta); 16512 } 16513 }; 16514 16515 Share.prototype.inject_html = function(instance) { 16516 //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>"; 16517 return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>"; 16518 }; 16519 16520 Share.prototype.inject_facebook_sdk = function() { 16521 var fb_root, script; 16522 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 16523 script = document.createElement("script"); 16524 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')"; 16525 fb_root = document.createElement("div"); 16526 fb_root.id = "fb-root"; 16527 this.el.body.appendChild(fb_root); 16528 return this.el.body.appendChild(script); 16529 } 16530 }; 16531 16532 Share.prototype.hook = function(type, network, instance) { 16533 var fn, opts; 16534 fn = this.config.networks[network][type]; 16535 if (typeof fn === "function") { 16536 opts = fn.call(this.config.networks[network], instance); 16537 if (opts !== void 0) { 16538 opts = this.normalize_filter_config_updates(opts); 16539 this.extend(this.config.networks[network], opts, true); 16540 this.normalize_network_configuration(); 16541 } 16542 } 16543 }; 16544 16545 Share.prototype.default_title = function() { 16546 var content; 16547 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 16548 return encodeURIComponent(content.getAttribute('content')); 16549 } else if (content = document.querySelector('title')) { 16550 return encodeURIComponent(content.innerText); 16551 } 16552 }; 16553 16554 Share.prototype.default_image = function() { 16555 var content; 16556 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 16557 return content.getAttribute('content'); 16558 } 16559 }; 16560 16561 Share.prototype.default_description = function() { 16562 var content; 16563 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 16564 return encodeURIComponent(content.getAttribute('content')); 16565 } else { 16566 return ''; 16567 } 16568 }; 16569 16570 Share.prototype.set_global_configuration = function() { 16571 var display, network, option, options, _ref, _results; 16572 _ref = this.config.networks; 16573 _results = []; 16574 for (network in _ref) { 16575 options = _ref[network]; 16576 for (option in options) { 16577 if (this.config.networks[network][option] == null) { 16578 this.config.networks[network][option] = this.config[option]; 16579 } 16580 } 16581 if (this.config.networks[network].enabled) { 16582 display = 'block'; 16583 this.config.enabled_networks += 1; 16584 } else { 16585 display = 'none'; 16586 } 16587 _results.push(this.config.networks[network].display = display); 16588 } 16589 return _results; 16590 }; 16591 16592 Share.prototype.normalize_network_configuration = function() { 16593 if (!this.config.networks.facebook.app_id) { 16594 this.config.networks.facebook.load_sdk = false;
16595 } 16596 if (!this.is_encoded(this.config.networks.twitter.description)) { 16597 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 16598 } 16599 if (typeof this.config.networks.facebook.app_id === 'number') { 16600 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 16601 } 16602 }; 16603 16604 Share.prototype.normalize_filter_config_updates = function(opts) { 16605 if (this.config.networks.facebook.app_id !== opts.app_id) { 16606 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."); 16607 delete opts.app_id; 16608 } 16609 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 16610 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."); 16611 delete opts.app_id; 16612 } 16613 return opts; 16614 }; 16615 16616 return Share; 16617 16618})(ShareUtils); 16619 return Share; 16620}); 16621 16622// Generated by CoffeeScript 1.9.2 16623 16624// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 16625 16626(function() { 16627 var $, win; 16628 16629 $ = this.jQuery || window.jQuery; 16630 16631 win = $(window); 16632 16633 $.fn.stick_in_parent = function(opts) { 16634 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 16635 if (opts == null) { 16636 opts = {}; 16637 } 16638 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; 16639 if (offset_top == null) { 16640 offset_top = 0; 16641 } 16642 if (parent_selector == null) { 16643 parent_selector = void 0; 16644 } 16645 if (inner_scrolling == null) { 16646 inner_scrolling = true; 16647 } 16648 if (sticky_class == null) { 16649 sticky_class = "is_stuck"; 16650 } 16651 doc = $(document); 16652 if (enable_bottoming == null) { 16653 enable_bottoming = true; 16654 } 16655 outer_width = function(el) { 16656 var _el, computed, w; 16657 if (window.getComputedStyle) { 16658 _el = el[0]; 16659 computed = window.getComputedStyle(el[0]); 16660 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 16661 if (computed.getPropertyValue("box-sizing") !== "border-box") { 16662 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 16663 } 16664 return w; 16665 } else { 16666 return el.outerWidth(true); 16667 } 16668 }; 16669 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 16670 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 16671 if (elm.data("sticky_kit")) { 16672 return; 16673 } 16674 elm.data("sticky_kit", true); 16675 last_scroll_height = doc.height(); 16676 parent = elm.parent(); 16677 if (parent_selector != null) { 16678 parent = parent.closest(parent_selector); 16679 } 16680 if (!parent.length) { 16681 throw "failed to find stick parent"; 16682 } 16683 fixed = false; 16684 bottomed = false; 16685 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 16686 if (spacer) { 16687 spacer.css('position', elm.css('position')); 16688 } 16689 recalc = function() { 16690 var border_top, padding_top, restore; 16691 if (detached) { 16692 return; 16693 } 16694 last_scroll_height = doc.height(); 16695 border_top = parseInt(parent.css("border-top-width"), 10); 16696 padding_top = parseInt(parent.css("padding-top"), 10); 16697 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 16698 parent_top = parent.offset().top + border_top + padding_top; 16699 parent_height = parent.height(); 16700 if (fixed) { 16701 fixed = false;
vendor: 6,068 bytes, lines 16702-16896
16702 bottomed = false; 16703 if (manual_spacer == null) { 16704 elm.insertAfter(spacer); 16705 spacer.detach(); 16706 } 16707 elm.css({ 16708 position: "", 16709 top: "", 16710 width: "", 16711 bottom: "" 16712 }).removeClass(sticky_class); 16713 restore = true; 16714 } 16715 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 16716 height = elm.outerHeight(true); 16717 el_float = elm.css("float"); 16718 if (spacer) { 16719 spacer.css({ 16720 width: outer_width(elm), 16721 height: height, 16722 display: elm.css("display"), 16723 "vertical-align": elm.css("vertical-align"), 16724 "float": el_float 16725 }); 16726 } 16727 if (restore) { 16728 return tick(); 16729 } 16730 }; 16731 recalc(); 16732 if (height === parent_height) { 16733 return; 16734 } 16735 last_pos = void 0; 16736 offset = offset_top; 16737 recalc_counter = recalc_every; 16738 tick = function() { 16739 var css, delta, recalced, scroll, will_bottom, win_height; 16740 if (detached) { 16741 return; 16742 } 16743 recalced = false; 16744 if (recalc_counter != null) { 16745 recalc_counter -= 1; 16746 if (recalc_counter <= 0) { 16747 recalc_counter = recalc_every; 16748 recalc(); 16749 recalced = true; 16750 } 16751 } 16752 if (!recalced && doc.height() !== last_scroll_height) { 16753 recalc(); 16754 recalced = true; 16755 } 16756 scroll = win.scrollTop(); 16757 if (last_pos != null) { 16758 delta = scroll - last_pos; 16759 } 16760 last_pos = scroll; 16761 if (fixed) { 16762 if (enable_bottoming) { 16763 will_bottom = scroll + height + offset > parent_height + parent_top; 16764 if (bottomed && !will_bottom) { 16765 bottomed = false; 16766 elm.css({ 16767 position: "fixed", 16768 bottom: "", 16769 top: offset 16770 }).trigger("sticky_kit:unbottom"); 16771 } 16772 } 16773 if (scroll < top) { 16774 fixed = false; 16775 offset = offset_top; 16776 if (manual_spacer == null) { 16777 if (el_float === "left" || el_float === "right") { 16778 elm.insertAfter(spacer); 16779 } 16780 spacer.detach(); 16781 } 16782 css = { 16783 position: "", 16784 width: "", 16785 top: "" 16786 }; 16787 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 16788 } 16789 if (inner_scrolling) { 16790 win_height = win.height(); 16791 if (height + offset_top > win_height) { 16792 if (!bottomed) { 16793 offset -= delta; 16794 offset = Math.max(win_height - height, offset); 16795 offset = Math.min(offset_top, offset); 16796 if (fixed) { 16797 elm.css({ 16798 top: offset + "px" 16799 }); 16800 } 16801 } 16802 } 16803 } 16804 } else { 16805 if (scroll > top) { 16806 fixed = true; 16807 css = { 16808 position: "fixed", 16809 top: offset 16810 }; 16811 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 16812 elm.css(css).addClass(sticky_class); 16813 if (manual_spacer == null) { 16814 elm.after(spacer); 16815 if (el_float === "left" || el_float === "right") { 16816 spacer.append(elm); 16817 } 16818 } 16819 elm.trigger("sticky_kit:stick"); 16820 } 16821 } 16822 if (fixed && enable_bottoming) { 16823 if (will_bottom == null) { 16824 will_bottom = scroll + height + offset > parent_height + parent_top; 16825 } 16826 if (!bottomed && will_bottom) { 16827 bottomed = true; 16828 if (parent.css("position") === "static") { 16829 parent.css({ 16830 position: "relative" 16831 }); 16832 } 16833 return elm.css({ 16834 position: "absolute", 16835 bottom: padding_bottom, 16836 top: "auto" 16837 }).trigger("sticky_kit:bottom"); 16838 } 16839 } 16840 }; 16841 recalc_and_tick = function() { 16842 recalc(); 16843 return tick(); 16844 }; 16845 detach = function() { 16846 detached = true; 16847 win.off("touchmove", tick); 16848 win.off("scroll", tick); 16849 win.off("resize", recalc_and_tick); 16850 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 16851 elm.off("sticky_kit:detach", detach); 16852 elm.removeData("sticky_kit"); 16853 elm.css({ 16854 position: "", 16855 bottom: "", 16856 top: "", 16857 width: "" 16858 }); 16859 parent.position("position", ""); 16860 if (fixed) { 16861 if (manual_spacer == null) { 16862 if (el_float === "left" || el_float === "right") { 16863 elm.insertAfter(spacer); 16864 } 16865 spacer.remove(); 16866 } 16867 return elm.removeClass(sticky_class); 16868 } 16869 }; 16870 win.on("touchmove", tick); 16871 win.on("scroll", tick); 16872 win.on("resize", recalc_and_tick); 16873 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 16874 elm.on("sticky_kit:detach", detach); 16875 return setTimeout(tick, 0); 16876 }; 16877 for (i = 0, len = this.length; i < len; i++) { 16878 elm = this[i]; 16879 fn($(elm)); 16880 } 16881 return this; 16882 }; 16883 16884}).call(this); 16885/* ========================================================================== 16886 * bootstrap-tab-history.js 16887 * Author: Michael Narayan <[email protected]> 16888 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 16889 * ========================================================================== 16890 * Licensed under the Apache License, Version 2.0 (the "License"); you may 16891 * not use this file except in compliance with the License. You may obtain a 16892 * copy of the License at 16893 * 16894 * http://www.apache.org/licenses/LICENSE-2.0 16895 * 16896 * Unless required by applicable law or agreed to in writing, softw
16896are 16897 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16898 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16899 * License for the specific language governing permissions and limitations 16900 * under the License. 16901 * ========================================================================== */ 16902 16903/* ========================================================================== */ 16904/* JSHint directives */ 16905/* */ 16906/* global BootstrapTabHistory: true */ 16907/* */ 16908/* global document */ 16909/* global jQuery */ 16910/* global history */ 16911/* global window */ 16912/* ========================================================================== */ 16913 16914/** 16915 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 16916 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 16917 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 16918 * 16919 * See the README for additional information. 16920 * 16921 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 16922 */ 16923 16924BootstrapTabHistory = { 16925 options: { 16926 /** 16927 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 16928 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 16929 * 16930 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 16931 * 16932 * @public 16933 * @type {?number} 16934 */ 16935 defaultAnchorYOffset: 0, 16936 /** 16937 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 16938 * 16939 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 16940 * 16941 * @public 16942 * @type {string} 16943 */ 16944 defaultChanger: 'replace', 16945 /** 16946 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 16947 * `null` is passed as the third parameter to these calls. 16948 * 16949 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 16950 * 16951 * @public 16952 * @type {boolean} 16953 */ 16954 defaultUpdateURL: false, 16955 /** 16956 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 16957 * load. 16958 * 16959 * @public 16960 * @type {boolean} 16961 */ 16962 showTabsBasedOnAnchor: true 16963 } 16964}; 16965 16966(function () { 16967 'use strict'; 16968 16969 jQuery(function () { 16970 if(history && history.pushState && history.replaceState) { 16971 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 16972 16973 if(bootstrapTabHistory) { 16974 showTabsBasedOnState(bootstrapTabHistory); 16975 } else { 16976 showTabsBasedOnAnchor(); 16977 } 16978 16979 backfillHistoryState(); 16980 16981 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 16982 jQuery(window).on('popstate', onPopState); 16983 } else { 16984 showTabsBasedOnAnchor(); 16985 } 16986 }); 16987 16988 /** 16989 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 16990 * 16991 * @type {boolean} 16992 */ 16993 var showingTabsBasedOnState = false; 16994 16995 /** 16996 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 16997 * `history.back` handling when `data-tab-history-update-url` is true. 16998 */ 16999 function backfillHistoryState() { 17000 var newState = null; 17001 17002 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 17003 var $activeTabElement = jQuery(this); 17004 var selector = getTabSelector($activeTabElement); 17005 17006 if(selector) { 17007 var tabGroup = getTabGroup($activeTabElement); 17008 17009 if(tabGroup) { 17010 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 17011 } 17012 } 17013 }); 17014 17015 if(newState) { 17016 history.replaceState(newState, '', null); 17017 } 17018 } 17019 17020 /** 17021 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 17022 * said bootstrapTabHistory attribute. 17023 * 17024 * @param {?object} existingState 17025 * @param {!string} tabGroup 17026 * @param {!string} selector 17027 * @returns {!object} 17028 */ 17029 function createNewHistoryState(existingState, tabGroup, selector) { 17030 // Clone history.state and ensure it has a bootstrapTabHistory entry. 17031 var newState = jQuery.extend(true, {}, existingState, { 17032 bootstrapTabHistory: {} 17033 }); 17034 17035 newState.bootstrapTabHistory[tabGroup] = selector; 17036 17037 return newState; 17038 } 17039 17040 /** 17041 * @param {jQuery} $tab
17042 * @returns {?string} 17043 */ 17044 function getTabGroup($tab) { 17045 return parseTruthyAttributeValue($tab.data('tab-history')); 17046 } 17047 17048 /** 17049 * @param {jQuery} $tab 17050 * @returns {?string} 17051 */ 17052 function getTabSelector($tab) { 17053 return $tab.data('target') || $tab.attr('href'); 17054 } 17055 17056 /** 17057 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 17058 * 17059 * @param {jQuery.Event} shownEvt 17060 */ 17061 function onShownTab(shownEvt) { 17062 if(!showingTabsBasedOnState) { 17063 var $activatedTab = jQuery(shownEvt.target); 17064 if ( $activatedTab.hasClass('panel-collapse') ) 17065 $activatedTab = $activatedTab.closest('.panel').find('a'); 17066 var selector = getTabSelector($activatedTab); 17067 17068 if(selector) { 17069 var tabGroup = getTabGroup($activatedTab); 17070 17071 if(tabGroup) { 17072 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 17073 var newState = createNewHistoryState(history.state, tabGroup, selector); 17074 var updateURL = (function ($activatedTab) { 17075 if(selector[0] === '#') { 17076 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 17077 17078 if(elementUpdateURLOption === undefined) { 17079 return BootstrapTabHistory.options.defaultUpdateURL; 17080 } else { 17081 return elementUpdateURLOption; 17082 } 17083 } else { 17084 return false; 17085 } 17086 })($activatedTab); 17087 17088 switch(historyChanger) { 17089 case 'push': 17090 history.pushState(newState, '', updateURL ? selector : null); 17091 break; 17092 case 'replace': 17093 history.replaceState(newState, '', updateURL ? selector : null); 17094 break; 17095 default: 17096 throw new Error('Unknown tab-history-changer: ' + historyChanger); 17097 } 17098 } 17099 } 17100 } 17101 } 17102 17103 /** 17104 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 17105 */ 17106 function onPopState() { 17107 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 17108 17109 if(bootstrapTabHistory) { 17110 showTabsBasedOnState(bootstrapTabHistory); 17111 } 17112 } 17113 17114 /** 17115 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 17116 * 17117 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 17118 * 17119 * @param {*} value 17120 * @returns {*} 17121 */ 17122 function parseTruthyAttributeValue(value) { 17123 if(value) { 17124 return value; 17125 } else if(value === '') { 17126 return true; 17127 } else { 17128 return value; 17129 } 17130 } 17131 17132 /** 17133 * Show tabs based upon the anchor component of `window.location`. 17134 */ 17135 function showTabsBasedOnAnchor() { 17136 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 17137 var anchor = window.location && window.location.hash; 17138 17139 if(anchor) { 17140 var $tabElement = showTabForSelector(anchor); 17141 17142 if($tabElement && window.addEventListener && window.removeEventListener) { 17143 var anchorYOffset = (function ($tabElement) { 17144 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 17145 17146 if(elementSetting === undefined) { 17147 return BootstrapTabHistory.options.defaultAnchorYOffset; 17148 } else { 17149 return elementSetting; 17150 } 17151 })($tabElement); 17152 17153 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 17154 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 17155 // `history.state` object should have been used (unless the browser did not support the modern History API). 17156 if(anchorYOffset || anchorYOffset === 0) { 17157 var scrollListener = function resetAnchorScroll () { 17158 window.removeEventListener('scroll', scrollListener); 17159 window.scrollTo(0, anchorYOffset); 17160 }; 17161 17162 window.addEventListener('scroll', scrollListener); 17163 } 17164 } 17165 } 17166 } 17167 } 17168 17169 /** 17170 * Show a tab which corresponds to the provided selector. 17171 * 17172 * @param {string} selector - A CSS selector. 17173 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 17174 */ 17175 function showTabForSelector(selector) { 17176 var $tabElement = (function (selector) { 17177 var $ret = null; 17178 17179 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 17180 var $potentialTab = jQuery(this); 17181 17182 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 17183 $ret = $potentialTab; 17184 return false;
vendor: 4,522 bytes, lines 17185-17334
17185 } else { 17186 return null; 17187 } 17188 }); 17189 17190 return $ret; 17191 })(selector); 17192 17193 if($tabElement) { 17194 $tabElement.trigger('click'); 17195 //$tabElement.tab('show'); 17196 } 17197 17198 return $tabElement; 17199 } 17200 17201 /** 17202 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 17203 * 17204 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 17205 */ 17206 function showTabsBasedOnState(bootstrapTabHistory) { 17207 showingTabsBasedOnState = true; 17208 17209 try { 17210 for(var k in bootstrapTabHistory) { 17211 if(bootstrapTabHistory.hasOwnProperty(k)) { 17212 showTabForSelector(bootstrapTabHistory[k]); 17213 } 17214 } 17215 } finally { 17216 showingTabsBasedOnState = false; 17217 } 17218 } 17219})(); 17220 17221/*! 17222 * Justified Gallery - v3.6.3 17223 * http://miromannino.github.io/Justified-Gallery/ 17224 * Copyright (c) 2016 Miro Mannino 17225 * Licensed under the MIT license. 17226 */ 17227(function($) { 17228 17229 function hasScrollBar() { 17230 return $("body").height() > $(window).height(); 17231 } 17232 /** 17233 * Justified Gallery controller constructor 17234 * 17235 * @param $gallery the gallery to build 17236 * @param settings the settings (the defaults are in $.fn.justifiedGallery.defaults) 17237 * @constructor 17238 */ 17239 var JustifiedGallery = function ($gallery, settings) { 17240 17241 this.settings = settings; 17242 this.checkSettings(); 17243 17244 this.imgAnalyzerTimeout = null; 17245 this.entries = null; 17246 this.buildingRow = { 17247 entriesBuff : [], 17248 width : 0, 17249 height : 0, 17250 aspectRatio : 0 17251 }; 17252 this.lastFetchedEntry = null; 17253 this.lastAnalyzedIndex = -1; 17254 this.yield = { 17255 every : 2, // do a flush every n flushes (must be greater than 1) 17256 flushed : 0 // flushed rows without a yield 17257 }; 17258 this.border = settings.border >= 0 ? settings.border : settings.margins; 17259 this.maxRowHeight = this.retrieveMaxRowHeight(); 17260 this.suffixRanges = this.retrieveSuffixRanges(); 17261 this.offY = this.border; 17262 this.rows = 0; 17263 this.spinner = { 17264 phase : 0, 17265 timeSlot : 150, 17266 $el : $('<div class="spinner"><span></span><span></span><span></span></div>'), 17267 intervalId : null 17268 }; 17269 this.checkWidthIntervalId = null; 17270 this.galleryWidth = $gallery.width(); 17271 this.$gallery = $gallery; 17272 17273 }; 17274 17275 /** @returns {String} the best suffix given the width and the height */ 17276 JustifiedGallery.prototype.getSuffix = function (width, height) { 17277 var longestSide, i; 17278 longestSide = (width > height) ? width : height; 17279 for (i = 0; i < this.suffixRanges.length; i++) { 17280 if (longestSide <= this.suffixRanges[i]) { 17281 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 17282 } 17283 } 17284 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 17285 }; 17286 17287 /** 17288 * Remove the suffix from the string 17289 * 17290 * @returns {string} a new string without the suffix 17291 */ 17292 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 17293 return str.substring(0, str.length - suffix.length); 17294 }; 17295 17296 /** 17297 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 17298 */ 17299 JustifiedGallery.prototype.endsWith = function (str, suffix) { 17300 return str.indexOf(suffix, str.length - suffix.length) !== -1; 17301 }; 17302 17303 /** 17304 * Get the used suffix of a particular url 17305 * 17306 * @param str 17307 * @returns {String} return the used suffix 17308 */ 17309 JustifiedGallery.prototype.getUsedSuffix = function (str) { 17310 for (var si in this.settings.sizeRangeSuffixes) { 17311 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 17312 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 17313 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 17314 } 17315 } 17316 return ''; 17317 }; 17318 17319 /** 17320 * Given an image src, with the width and the height, returns the new image src with the 17321 * best suffix to show the best quality thumbnail. 17322 * 17323 * @returns {String} the suffix to use 17324 */ 17325 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 17326 var newImageSrc; 17327 17328 if (this.settings.thumbnailPath) { 17329 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 17330 } else { 17331 var matchRes = imageSrc.match(this.settings.extension); 17332 var ext = (matchRes !== null) ? matchRes[0] : ''; 17333 newImageSrc = imageSrc.replace(this.settings.extension, ''); 17334 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
17335 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 17336 } 17337 17338 return newImageSrc; 17339 }; 17340 17341 /** 17342 * Shows the images that is in the given entry 17343 * 17344 * @param $entry the entry 17345 * @param callback the callback that is called when the show animation is finished 17346 */ 17347 JustifiedGallery.prototype.showImg = function ($entry, callback) { 17348 if (this.settings.cssAnimation) { 17349 $entry.addClass('entry-visible'); 17350 if (callback) callback(); 17351 } else { 17352 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 17353 $entry.find('> img, > a > img').stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 17354 } 17355 }; 17356 17357 /** 17358 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 17359 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 17360 * 17361 * @param $image the image to analyze 17362 * @returns {String} the extracted src 17363 */ 17364 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 17365 var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src'); 17366 $image.data('jg.originalSrc', imageSrc); 17367 return imageSrc; 17368 }; 17369 17370 /** @returns {jQuery} the image in the given entry */ 17371 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 17372 var $img = $entry.find('> img'); 17373 if ($img.length === 0) $img = $entry.find('> a > img'); 17374 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 17375 return $img.length === 0 ? null : $img; 17376 }; 17377 17378 /** @returns {jQuery} the caption in the given entry */ 17379 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 17380 var $caption = $entry.find('> .caption'); 17381 return $caption.length === 0 ? null : $caption; 17382 }; 17383 17384 /** 17385 * Display the entry 17386 * 17387 * @param {jQuery} $entry the entry to display 17388 * @param {int} x the x position where the entry must be positioned 17389 * @param y the y position where the entry must be positioned 17390 * @param imgWidth the image width 17391 * @param imgHeight the image height 17392 * @param rowHeight the row height of the row that owns the entry 17393 */ 17394 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 17395 $entry.width(imgWidth); 17396 $entry.height(Math.floor(rowHeight));//hacked by Uncode 17397 $entry.css('top', Math.floor(y));//hacked by Uncode 17398 $entry.css('left', x); 17399 17400 var $image = this.imgFromEntry($entry); 17401 if ($image !== null) { 17402 $image.css('width', imgWidth); 17403 $image.css('height', imgHeight); 17404 $image.css('margin-left', - imgWidth / 2); 17405 $image.css('margin-top', - imgHeight / 2); 17406 17407 // Image reloading for an high quality of thumbnails 17408 var imageSrc = $image.attr('src'); 17409 var newImageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 17410 17411 $image.one('error', function () { 17412 $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it. 17413 }); 17414 17415 var loadNewImage = function () { 17416 if (imageSrc !== newImageSrc) { //load the new image after the fadeIn 17417 $image.attr('src', newImageSrc); 17418 } 17419 }; 17420 17421 if ($entry.data('jg.loaded') === 'skipped') { 17422 this.onImageEvent(imageSrc, $.proxy(function() { 17423 this.showImg($entry, loadNewImage); 17424 $entry.data('jg.loaded', true); 17425 }, this)); 17426 } else { 17427 this.showImg($entry, loadNewImage); 17428 } 17429 17430 } else { 17431 this.showImg($entry); 17432 } 17433 17434 this.displayEntryCaption($entry); 17435 }; 17436 17437 /** 17438 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 17439 * or the 'title' attributes. 17440 * 17441 * @param {jQuery} $entry the entry to process 17442 */ 17443 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 17444 var $image = this.imgFromEntry($entry); 17445 if ($image !== null && this.settings.captions) { 17446 var $imgCaption = this.captionFromEntry($entry); 17447 17448 // Create it if it doesn't exists 17449 if ($imgCaption === null) { 17450 var caption = $image.attr('alt'); 17451 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 17452 if (this.isValidCaption(caption)) { // Create only we found something 17453 $imgCaption = $('<div class="caption">' + caption + '</div>'); 17454 $entry.append($imgCaption); 17455 $entry.data('jg.createdCaption', true); 17456 } 17457 } 17458 17459 // Create events (we check again the $imgCaption because it can be still inexistent) 17460 if ($imgCaption !== null) { 17461 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 17462 this.addCaptionEventsHandlers($entry); 17463 } 17464 } else { 17465 this.removeCaptionEventsHandlers($entry); 17466 } 17467 }; 17468 17469 /** 17470 * Validates the caption 17471 * 17472 * @param caption The caption that should be validated 17473 * @return {boolean} Validation result 17474 */ 17475 JustifiedGallery.prototype.isValidCaption = function (caption) { 17476 return (typeof caption !== 'undefined' && caption.length > 0); 17477 }; 17478 17479 /** 17480 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 17481 * It shows the caption using jQuery (or using CSS if it is configured so) 17482 * 17483 * @param {Event} eventObject the event object 17484 */ 17485 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 17486 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 17487 if (this.settings.cssAnimation) { 17488 $caption.addClass('caption-visible').removeClass('caption-hidden'); 17489 } else { 17490 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 17491 this.settings.captionSettings.visibleOpacity); 17492 } 17493 }; 17494 17495 /** 17496 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 17497 * It hides the caption using jQuery (or using CSS if it is configured so) 17498 * 17499 * @param {Event} eventObject the event object 17500 */ 17501 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 17502 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 17503 if (this.settings.cssAnimation) { 17504 $caption.removeClass('caption-visible').removeClass('caption-hidden'); 17505 } else { 17506 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 17507 this.settings.captionSettings.nonVisibleOpacity); 17508 } 17509 }; 17510 17511 /** 17512 * Add the handlers of the entry for the caption 17513 * 17514 * @param $entry the entry to modify 17515 */ 17516 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 17517 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 17518 if (typeof captionMouseEvents === 'undefined') { 17519 captionMouseEvents = { 17520 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 17521 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 17522 }; 17523 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 17524 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 17525 $entry.data('jg.captionMouseEvents', captionMouseEvents); 17526 } 17527 }; 17528 17529 /** 17530 * Remove the handlers of the entry for the caption 17531 * 17532 * @param $entry the entry to modify 17533 */ 17534 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 17535 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 17536 if (typeof captionMouseEvents !== 'undefined') { 17537 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 17538 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 17539 $entry.removeData('jg.captionMouseEvents'); 17540 } 17541 }; 17542 17543 /** 17544 * Justify the building row, preparing it to 17545 * 17546 * @param isLastRow 17547 * @returns a boolean to know if the row has been justified or not 17548 */ 17549 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow) { 17550 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 17551 var minHeight = 0; 17552 var availableWidth = this.galleryWidth - 2 * this.border - ( 17553 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 17554 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 17555 var defaultRowHeight = this.settings.rowHeight; 17556 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 17557 17558 //Skip the last row if we can't justify it and the lastRow == 'hide' 17559 if (isLastRow && this.settings.lastRow === 'hide' && !justifiable) { 17560 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 17561 $entry = this.buildingRow.entriesBuff[i]; 17562 if (this.settings.cssAnimation) 17563 $entry.removeClass('entry-visible'); 17564 else { 17565 $entry.stop().fadeTo(0, 0.1); 17566 $entry.find('> img, > a > img').fadeTo(0, 0); 17567 } 17568 } 17569 return -1; 17570 } 17571 17572 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 17573 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 17574 justify = false;
17575 17576 if (this.rows > 0) { 17577 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 17578 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 17579 } 17580 } 17581 17582 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 17583 $entry = this.buildingRow.entriesBuff[i]; 17584 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 17585 17586 if (justify) { 17587 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 17588 newImgH = rowHeight; 17589 } else { 17590 newImgW = defaultRowHeight * imgAspectRatio; 17591 newImgH = defaultRowHeight; 17592 } 17593 17594 availableWidth -= Math.round(newImgW); 17595 $entry.data('jg.jwidth', Math.round(newImgW)); 17596 $entry.data('jg.jheight', Math.ceil(newImgH)); 17597 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 17598 } 17599 17600 this.buildingRow.height = minHeight; 17601 return justify; 17602 }; 17603 17604 /** 17605 * Clear the building row data to be used for a new row 17606 */ 17607 JustifiedGallery.prototype.clearBuildingRow = function () { 17608 this.buildingRow.entriesBuff = []; 17609 this.buildingRow.aspectRatio = 0; 17610 this.buildingRow.width = 0; 17611 }; 17612 17613 /** 17614 * Flush a row: justify it, modify the gallery height accordingly to the row height 17615 * 17616 * @param isLastRow 17617 */ 17618 JustifiedGallery.prototype.flushRow = function (isLastRow) { 17619 var settings = this.settings; 17620 var $entry, buildingRowRes, offX = this.border, i; 17621 17622 buildingRowRes = this.prepareBuildingRow(isLastRow); 17623 if (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1) { 17624 this.clearBuildingRow(); 17625 return; 17626 } 17627 17628 if (this.maxRowHeight) { 17629 if (this.maxRowHeight.isPercentage && this.maxRowHeight.value * settings.rowHeight < this.buildingRow.height) { 17630 this.buildingRow.height = this.maxRowHeight.value * settings.rowHeight; 17631 } else if (this.maxRowHeight.value >= settings.rowHeight && this.maxRowHeight.value < this.buildingRow.height) { 17632 this.buildingRow.height = this.maxRowHeight.value; 17633 } 17634 } 17635 17636 //Align last (unjustified) row 17637 if (settings.lastRow === 'center' || settings.lastRow === 'right') { 17638 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 17639 17640 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 17641 $entry = this.buildingRow.entriesBuff[i]; 17642 availableWidth -= $entry.data('jg.jwidth'); 17643 } 17644 17645 if (settings.lastRow === 'center') 17646 offX += availableWidth / 2; 17647 else if (settings.lastRow === 'right') 17648 offX += availableWidth; 17649 } 17650 17651 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 17652 $entry = this.buildingRow.entriesBuff[i]; 17653 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 17654 offX += $entry.data('jg.jwidth') + settings.margins; 17655 } 17656 17657 //Gallery Height 17658 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 17659 this.$gallery.height(this.galleryHeightToSet + this.getSpinnerHeight()); 17660 17661 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 17662 //Ready for a new row 17663 this.offY += this.buildingRow.height + settings.margins; 17664 this.rows += 1; 17665 this.clearBuildingRow(); 17666 this.$gallery.trigger('jg.rowflush'); 17667 } 17668 }; 17669 17670 /** 17671 * Checks the width of the gallery container, to know if a new justification is needed 17672 */ 17673 var scrollBarOn = false; 17674 JustifiedGallery.prototype.checkWidth = function () { 17675 this.checkWidthIntervalId = setInterval($.proxy(function () { 17676 var galleryWidth = parseFloat(this.$gallery.width()); 17677 if (hasScrollBar() === scrollBarOn) { 17678 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 17679 this.galleryWidth = galleryWidth; 17680 this.rewind(); 17681 17682 // Restart to analyze 17683 this.startImgAnalyzer(true); 17684 } 17685 } else { 17686 scrollBarOn = hasScrollBar(); 17687 this.galleryWidth = galleryWidth; 17688 } 17689 }, this), this.settings.refreshTime); 17690 }; 17691 17692 /** 17693 * @returns {boolean} a boolean saying if the spinner is active or not 17694 */ 17695 JustifiedGallery.prototype.isSpinnerActive = function () { 17696 return this.spinner.intervalId !== null; 17697 }; 17698 17699 /** 17700 * @returns {int} the spinner height 17701 */ 17702 JustifiedGallery.prototype.getSpinnerHeight = function () {
17703 return this.spinner.$el.innerHeight(); 17704 }; 17705 17706 /** 17707 * Stops the spinner animation and modify the gallery height to exclude the spinner 17708 */ 17709 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 17710 clearInterval(this.spinner.intervalId); 17711 this.spinner.intervalId = null; 17712 this.$gallery.height(this.$gallery.height() - this.getSpinnerHeight()); 17713 this.spinner.$el.detach(); 17714 }; 17715 17716 /** 17717 * Starts the spinner animation 17718 */ 17719 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 17720 var spinnerContext = this.spinner; 17721 var $spinnerPoints = spinnerContext.$el.find('span'); 17722 clearInterval(spinnerContext.intervalId); 17723 this.$gallery.append(spinnerContext.$el); 17724 this.$gallery.height(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 17725 spinnerContext.intervalId = setInterval(function () { 17726 if (spinnerContext.phase < $spinnerPoints.length) { 17727 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 17728 } else {
vendor: 4,333 bytes, lines 17729-17873
17729 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 17730 } 17731 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 17732 }, spinnerContext.timeSlot); 17733 }; 17734 17735 /** 17736 * Rewind the image analysis to start from the first entry. 17737 */ 17738 JustifiedGallery.prototype.rewind = function () { 17739 this.lastFetchedEntry = null; 17740 this.lastAnalyzedIndex = -1; 17741 this.offY = this.border; 17742 this.rows = 0; 17743 this.clearBuildingRow(); 17744 }; 17745 17746 /** 17747 * Update the entries searching it from the justified gallery HTML element 17748 * 17749 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 17750 * @returns {boolean} true if some entries has been founded 17751 */ 17752 JustifiedGallery.prototype.updateEntries = function (norewind) { 17753 var newEntries; 17754 17755 if (norewind && this.lastFetchedEntry != null) { 17756 newEntries = $(this.lastFetchedEntry).nextAll(this.settings.selector).toArray(); 17757 } else { 17758 this.entries = []; 17759 newEntries = this.$gallery.children(this.settings.selector).toArray(); 17760 } 17761 17762 if (newEntries.length > 0) { 17763 17764 // Sort or randomize 17765 if ($.isFunction(this.settings.sort)) { 17766 newEntries = this.sortArray(newEntries); 17767 } else if (this.settings.randomize) { 17768 newEntries = this.shuffleArray(newEntries); 17769 } 17770 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 17771 17772 // Filter 17773 if (this.settings.filter) { 17774 newEntries = this.filterArray(newEntries); 17775 } else { 17776 this.resetFilters(newEntries); 17777 } 17778 17779 } 17780 17781 this.entries = this.entries.concat(newEntries); 17782 return true; 17783 }; 17784 17785 /** 17786 * Apply the entries order to the DOM, iterating the entries and appending the images 17787 * 17788 * @param entries the entries that has been modified and that must be re-ordered in the DOM 17789 */ 17790 JustifiedGallery.prototype.insertToGallery = function (entries) { 17791 var that = this; 17792 $.each(entries, function () { 17793 $(this).appendTo(that.$gallery); 17794 }); 17795 }; 17796 17797 /** 17798 * Shuffle the array using the Fisher-Yates shuffle algorithm 17799 * 17800 * @param a the array to shuffle 17801 * @return the shuffled array 17802 */ 17803 JustifiedGallery.prototype.shuffleArray = function (a) { 17804 var i, j, temp; 17805 for (i = a.length - 1; i > 0; i--) { 17806 j = Math.floor(Math.random() * (i + 1)); 17807 temp = a[i]; 17808 a[i] = a[j]; 17809 a[j] = temp; 17810 } 17811 this.insertToGallery(a); 17812 return a; 17813 }; 17814 17815 /** 17816 * Sort the array using settings.comparator as comparator 17817 * 17818 * @param a the array to sort (it is sorted) 17819 * @return the sorted array 17820 */ 17821 JustifiedGallery.prototype.sortArray = function (a) { 17822 a.sort(this.settings.sort); 17823 this.insertToGallery(a); 17824 return a; 17825 }; 17826 17827 /** 17828 * Reset the filters removing the 'jg-filtered' class from all the entries 17829 * 17830 * @param a the array to reset 17831 */ 17832 JustifiedGallery.prototype.resetFilters = function (a) { 17833 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 17834 }; 17835 17836 /** 17837 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 17838 * 17839 * @param a the array to filter 17840 * @return the filtered array 17841 */ 17842 JustifiedGallery.prototype.filterArray = function (a) { 17843 var settings = this.settings; 17844 if ($.type(settings.filter) === 'string') { 17845 // Filter only keeping the entries passed in the string 17846 return a.filter(function (el) { 17847 var $el = $(el); 17848 if ($el.is(settings.filter)) { 17849 $el.removeClass('jg-filtered'); 17850 return true; 17851 } else { 17852 $el.addClass('jg-filtered').removeClass('jg-visible'); 17853 return false; 17854 } 17855 }); 17856 } else if ($.isFunction(settings.filter)) { 17857 // Filter using the passed function 17858 var filteredArr = a.filter(settings.filter); 17859 for (var i = 0; i < a.length; i++) { 17860 if (filteredArr.indexOf(a[i]) == -1) { 17861 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 17862 } else { 17863 $(a[i]).removeClass('jg-filtered'); 17864 } 17865 } 17866 return filteredArr; 17867 } 17868 }; 17869 17870 /** 17871 * Destroy the Justified Gallery instance. 17872 * 17873 * It clears all the css properties added in the style attributes. We doesn't backup the original
17874 * values for those css attributes, because it costs (performance) and because in general one 17875 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 17876 * classes). Creating a backup is also difficult because JG could be called multiple times and 17877 * with different style attributes. 17878 */ 17879 JustifiedGallery.prototype.destroy = function () { 17880 clearInterval(this.checkWidthIntervalId); 17881 17882 $.each(this.entries, $.proxy(function(_, entry) { 17883 var $entry = $(entry); 17884 17885 // Reset entry style 17886 $entry.css('width', ''); 17887 $entry.css('height', ''); 17888 $entry.css('top', ''); 17889 $entry.css('left', ''); 17890 $entry.data('jg.loaded', undefined); 17891 $entry.removeClass('jg-entry'); 17892 17893 // Reset image style 17894 var $img = this.imgFromEntry($entry); 17895 $img.css('width', ''); 17896 $img.css('height', ''); 17897 $img.css('margin-left', ''); 17898 $img.css('margin-top', ''); 17899 $img.attr('src', $img.data('jg.originalSrc')); 17900 $img.data('jg.originalSrc', undefined); 17901 17902 // Remove caption 17903 this.removeCaptionEventsHandlers($entry); 17904 var $caption = this.captionFromEntry($entry); 17905 if ($entry.data('jg.createdCaption')) { 17906 // remove also the caption element (if created by jg) 17907 $entry.data('jg.createdCaption', undefined); 17908 if ($caption !== null) $caption.remove(); 17909 } else { 17910 if ($caption !== null) $caption.fadeTo(0, 1); 17911 } 17912 17913 }, this)); 17914 17915 this.$gallery.css('height', ''); 17916 this.$gallery.removeClass('justified-gallery'); 17917 this.$gallery.data('jg.controller', undefined); 17918 }; 17919 17920 /** 17921 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 17922 * 17923 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 17924 */ 17925 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 17926 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 17927 var $entry = $(this.entries[i]); 17928 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 17929 var availableWidth = this.galleryWidth - 2 * this.border - ( 17930 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 17931 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 17932 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 17933 this.flushRow(false); 17934 if(++this.yield.flushed >= this.yield.every) { 17935 this.startImgAnalyzer(isForResize); 17936 return; 17937 } 17938 } 17939 17940 this.buildingRow.entriesBuff.push($entry); 17941 this.buildingRow.aspectRatio += imgAspectRatio; 17942 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 17943 this.lastAnalyzedIndex = i; 17944 17945 } else if ($entry.data('jg.loaded') !== 'error') { 17946 return; 17947 } 17948 } 17949 17950 // Last row flush (the row is not full) 17951 if (this.buildingRow.entriesBuff.length > 0) this.flushRow(true); 17952 17953 if (this.isSpinnerActive()) { 17954 this.stopLoadingSpinnerAnimation(); 17955 } 17956 17957 /* Stop, if there is, the timeout to start the analyzeImages. 17958 This is because an image can be set loaded, and the timeout can be set, 17959 but this image can be analyzed yet. 17960 */ 17961 this.stopImgAnalyzerStarter(); 17962 17963 //On complete callback 17964 this.$gallery.trigger(isForResize ? 'jg.resize' : 'jg.complete'); 17965 this.$gallery.height(this.galleryHeightToSet); 17966 }; 17967 17968 /** 17969 * Stops any ImgAnalyzer starter (that has an assigned timeout) 17970 */ 17971 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 17972 this.yield.flushed = 0; 17973 if (this.imgAnalyzerTimeout !== null) clearTimeout(this.imgAnalyzerTimeout); 17974 }; 17975 17976 /** 17977 * Starts the image analyzer. It is not immediately called to let the browser to update the view 17978 * 17979 * @param isForResize specifies if the image analyzer must be called for resizing or not 17980 */ 17981 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 17982 var that = this; 17983 this.stopImgAnalyzerStarter(); 17984 this.imgAnalyzerTimeout = setTimeout(function () { 17985 that.analyzeImages(isForResize); 17986 }, 0.001); // we can't start it immediately due to a IE different behaviour 17987 }; 17988 17989 /** 17990 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 17991 * because some browsers, with a 404 set complete = true. 17992 * 17993 * @param imageSrc the image src to load 17994 * @param onLoad callback that is called when the image has been loaded
vendor: 13,320 bytes, lines 17995-18345
17995 * @param onError callback that is called in case of an error 17996 */ 17997 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 17998 if (!onLoad && !onError) return; 17999 18000 var memImage = new Image(); 18001 var $memImage = $(memImage); 18002 if (onLoad) { 18003 $memImage.one('load', function () { 18004 $memImage.off('load error'); 18005 onLoad(memImage); 18006 }); 18007 } 18008 if (onError) { 18009 $memImage.one('error', function() { 18010 $memImage.off('load error'); 18011 onError(memImage); 18012 }); 18013 } 18014 memImage.src = imageSrc; 18015 }; 18016 18017 /** 18018 * Init of Justified Gallery controlled 18019 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 18020 */ 18021 JustifiedGallery.prototype.init = function () { 18022 var imagesToLoad = false, skippedImages = false, that = this; 18023 $.each(this.entries, function (index, entry) { 18024 var $entry = $(entry); 18025 var $image = that.imgFromEntry($entry); 18026 18027 $entry.addClass('jg-entry'); 18028 18029 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 18030 18031 // Link Rel global overwrite 18032 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 18033 18034 // Link Target global overwrite 18035 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 18036 18037 if ($image !== null) { 18038 18039 // Image src 18040 var imageSrc = that.extractImgSrcFromImage($image); 18041 $image.attr('src', imageSrc); 18042 18043 /* If we have the height and the width, we don't wait that the image is loaded, but we start directly 18044 * with the justification */ 18045 if (that.settings.waitThumbnailsLoad === false) { 18046 var width = parseFloat($image.attr('width')); 18047 var height = parseFloat($image.attr('height')); 18048 if (!isNaN(width) && !isNaN(height)) { 18049 $entry.data('jg.width', width); 18050 $entry.data('jg.height', height); 18051 $entry.data('jg.loaded', 'skipped'); 18052 skippedImages = true; 18053 that.startImgAnalyzer(false); 18054 return true; // continue 18055 } 18056 } 18057 18058 $entry.data('jg.loaded', false); 18059 imagesToLoad = true; 18060 18061 // Spinner start 18062 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 18063 18064 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 18065 $entry.data('jg.width', loadImg.width); 18066 $entry.data('jg.height', loadImg.height); 18067 $entry.data('jg.loaded', true); 18068 that.startImgAnalyzer(false); 18069 }, function () { // image load error 18070 $entry.data('jg.loaded', 'error'); 18071 that.startImgAnalyzer(false); 18072 }); 18073 18074 } else { 18075 $entry.data('jg.loaded', true); 18076 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 18077 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 18078 } 18079 18080 } 18081 18082 }); 18083 18084 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 18085 this.checkWidth(); 18086 }; 18087 18088 /** 18089 * Checks that it is a valid number. If a string is passed it is converted to a number 18090 * 18091 * @param settingContainer the object that contains the setting (to allow the conversion) 18092 * @param settingName the setting name 18093 */ 18094 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 18095 if ($.type(settingContainer[settingName]) === 'string') { 18096 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 18097 } 18098 18099 if ($.type(settingContainer[settingName]) === 'number') { 18100 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 18101 } else { 18102 throw settingName + ' must be a number'; 18103 } 18104 }; 18105 18106 /** 18107 * Checks the sizeRangeSuffixes and, if necessary, converts 18108 * its keys from string (e.g. old settings with 'lt100') to int. 18109 */ 18110 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 18111 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 18112 throw 'sizeRangeSuffixes must be defined and must be an object'; 18113 } 18114 18115 var suffixRanges = []; 18116 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 18117 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 18118 } 18119 18120 var newSizeRngSuffixes = {0: ''}; 18121 for (var i = 0; i < suffixRanges.length; i++) { 18122 if ($.type(suffixRanges[i]) === 'string') { 18123 try { 18124 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 18125 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 18126 } catch (e) { 18127 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 18128 } 18129 } else { 18130 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 18131 } 18132 } 18133 18134 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 18135 }; 18136 18137 /** 18138 * check and convert the maxRowHeight setting 18139 */ 18140 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 18141 var newMaxRowHeight = { }; 18142 18143 if ($.type(this.settings.maxRowHeight) === 'string') { 18144 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 18145 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 18146 newMaxRowHeight.isPercentage = false; 18147 } else { 18148 newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight); 18149 newMaxRowHeight.isPercentage = true; 18150 } 18151 } else if ($.type(this.settings.maxRowHeight) === 'number') { 18152 newMaxRowHeight.value = this.settings.maxRowHeight; 18153 newMaxRowHeight.isPercentage = false; 18154 } else if (this.settings.maxRowHeight === false || 18155 this.settings.maxRowHeight === null || 18156 typeof this.settings.maxRowHeight == 'undefined') { 18157 return null; 18158 } else { 18159 throw 'maxRowHeight must be a number or a percentage'; 18160 } 18161 18162 // check if the converted value is not a number 18163 if (isNaN(newMaxRowHeight.value)) throw 'invalid number for maxRowHeight'; 18164 18165 // check values 18166 if (newMaxRowHeight.isPercentage) { 18167 if (newMaxRowHeight.value < 100) newMaxRowHeight.value = 100; 18168 } 18169 18170 return newMaxRowHeight; 18171 }; 18172 18173 /** 18174 * Checks the settings 18175 */ 18176 JustifiedGallery.prototype.checkSettings = function () { 18177 this.checkSizeRangesSuffixes(); 18178 18179 this.checkOrConvertNumber(this.settings, 'rowHeight'); 18180 this.checkOrConvertNumber(this.settings, 'margins'); 18181 this.checkOrConvertNumber(this.settings, 'border'); 18182 18183 var lastRowModes = [ 18184 'justify', 18185 'nojustify', 18186 'left', 18187 'center', 18188 'right', 18189 'hide' 18190 ]; 18191 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 18192 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 18193 } 18194 18195 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 18196 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 18197 throw 'justifyThreshold must be in the interval [0,1]'; 18198 } 18199 if ($.type(this.settings.cssAnimation) !== 'boolean') { 18200 throw 'cssAnimation must be a boolean'; 18201 } 18202 18203 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 18204 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 18205 18206 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 18207 if (this.settings.captionSettings.visibleOpacity < 0 || 18208 this.settings.captionSettings.visibleOpacity > 1) { 18209 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 18210 } 18211 18212 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 18213 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 18214 this.settings.captionSettings.nonVisibleOpacity > 1) { 18215 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 18216 } 18217 18218 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 18219 this.checkOrConvertNumber(this.settings, 'refreshTime'); 18220 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 18221 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 18222 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 18223 18224 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 18225 throw 'sort must be false or a comparison function'; 18226 } 18227 18228 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 18229 $.type(this.settings.filter) !== 'string') { 18230 throw 'filter must be false, a string or a filter function'; 18231 } 18232 }; 18233 18234 /** 18235 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 18236 * @returns {Array} sorted suffix ranges 18237 */ 18238 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 18239 var suffixRanges = []; 18240 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 18241 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 18242 } 18243 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 18244 return suffixRanges; 18245 }; 18246 18247 /** 18248 * Update the existing settings only changing some of them 18249 * 18250 * @param newSettings the new settings (or a subgroup of them) 18251 */ 18252 JustifiedGallery.prototype.updateSettings = function (newSettings) { 18253 // In this case Justified Gallery has been called again changing only some options 18254 this.settings = $.extend({}, this.settings, newSettings); 18255 this.checkSettings(); 18256 18257 // As reported in the settings: negative value = same as margins, 0 = disabled 18258 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 18259 18260 this.maxRowHeight = this.retrieveMaxRowHeight(); 18261 this.suffixRanges = this.retrieveSuffixRanges(); 18262 }; 18263 18264 /** 18265 * Justified Gallery plugin for jQuery 18266 * 18267 * Events 18268 * - jg.complete : called when all the gallery has been created 18269 * - jg.resize : called when the gallery has been resized 18270 * - jg.rowflush : when a new row appears 18271 * 18272 * @param arg the action (or the settings) passed when the plugin is called 18273 * @returns {*} the object itself 18274 */ 18275 $.fn.justifiedGallery = function (arg) { 18276 return this.each(function (index, gallery) { 18277 18278 var $gallery = $(gallery); 18279 $gallery.addClass('justified-gallery'); 18280 18281 var controller = $gallery.data('jg.controller'); 18282 if (typeof controller === 'undefined') { 18283 // Create controller and assign it to the object data 18284 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 18285 if (arg === 'destroy') return; // Just a call to an unexisting object 18286 throw 'The argument must be an object'; 18287 } 18288 controller = new JustifiedGallery($gallery, $.extend({}, $.fn.justifiedGallery.defaults, arg)); 18289 $gallery.data('jg.controller', controller); 18290 } else if (arg === 'norewind') { 18291 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 18292 // ... left to be more readable 18293 } else if (arg === 'destroy') { 18294 controller.destroy(); 18295 return; 18296 } else { 18297 // In this case Justified Gallery has been called again changing only some options 18298 controller.updateSettings(arg); 18299 controller.rewind(); 18300 } 18301 18302 // Update the entries list 18303 if (!controller.updateEntries(arg === 'norewind')) return; 18304 18305 // Init justified gallery 18306 controller.init(); 18307 18308 }); 18309 }; 18310 18311 // Default options 18312 $.fn.justifiedGallery.defaults = { 18313 sizeRangeSuffixes: { }, /* e.g. Flickr configuration 18314 { 18315 100: '_t', // used when longest is less than 100px 18316 240: '_m', // used when longest is between 101px and 240px 18317 320: '_n', // ... 18318 500: '', 18319 640: '_z', 18320 1024: '_b' // used as else case because it is the last 18321 } 18322 */ 18323 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 18324 path relative to a specific thumbnail size. The function should accept respectively three arguments: 18325 current path, width and height */ 18326 rowHeight: 120, 18327 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 18328 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 18329 // can't exceed 3 * rowHeight) 18330 margins: 1, 18331 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 18332 18333 lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 18334 18335 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 18336 * (i.e. lastRow setting is not considered) */ 18337 waitThumbnailsLoad: true, 18338 captions: true, 18339 cssAnimation: true, 18340 imagesAnimationDuration: 500, // ignored with css animations 18341 captionSettings: { // ignored with css animations 18342 animationDuration: 500, 18343 visibleOpacity: 0.7, 18344 nonVisibleOpacity: 0.0 18345 },
vendor: 5,759 bytes, lines 18346-18488
18346 rel: null, // rewrite the rel of each analyzed links 18347 target: null, // rewrite the target of all links 18348 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 18349 refreshTime: 200, // time interval (in ms) to check if the page changes its width 18350 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 18351 randomize: false, 18352 sort: false, /* 18353 - false: to do not sort 18354 - function: to sort them using the function as comparator (see Array.prototype.sort()) 18355 */ 18356 filter: false, /* 18357 - false, null or undefined: for a disabled filter 18358 - a string: an entry is kept if entry.is(filter string) returns true 18359 see jQuery's .is() function for further information 18360 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 18361 It follows the specifications of the Array.prototype.filter() function of JavaScript. 18362 */ 18363 selector: 'a, div:not(.spinner)' // The selector that is used to know what are the entries of the gallery 18364 }; 18365 18366}(jQuery)); 18367/*! 18368* Customized version of iScroll.js 0.0.1 18369* It fixes bugs affecting its integration with fullpage.js 18370*/ 18371/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 18372(function (window, document, Math) { 18373var rAF = window.requestAnimationFrame || 18374 window.webkitRequestAnimationFrame || 18375 window.mozRequestAnimationFrame || 18376 window.oRequestAnimationFrame || 18377 window.msRequestAnimationFrame || 18378 function (callback) { window.setTimeout(callback, 1000 / 60); }; 18379 18380var utils = (function () { 18381 var me = {}; 18382 18383 var _elementStyle = document.createElement('div').style; 18384 var _vendor = (function () { 18385 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 18386 transform, 18387 i = 0, 18388 l = vendors.length; 18389 18390 for ( ; i < l; i++ ) { 18391 transform = vendors[i] + 'ransform'; 18392 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 18393 } 18394 18395 return false; 18396 })(); 18397 18398 function _prefixStyle (style) { 18399 if ( _vendor === false ) return false; 18400 if ( _vendor === '' ) return style; 18401 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 18402 } 18403 18404 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 18405 18406 me.extend = function (target, obj) { 18407 for ( var i in obj ) { 18408 target[i] = obj[i]; 18409 } 18410 }; 18411 18412 me.addEvent = function (el, type, fn, capture) { 18413 el.addEventListener(type, fn, !!capture); 18414 }; 18415 18416 me.removeEvent = function (el, type, fn, capture) { 18417 el.removeEventListener(type, fn, !!capture); 18418 }; 18419 18420 me.prefixPointerEvent = function (pointerEvent) { 18421 return window.MSPointerEvent ? 18422 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 18423 pointerEvent; 18424 }; 18425 18426 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 18427 var distance = current - start, 18428 speed = Math.abs(distance) / time, 18429 destination, 18430 duration; 18431 18432 deceleration = deceleration === undefined ? 0.0006 : deceleration; 18433 18434 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 18435 duration = speed / deceleration; 18436 18437 if ( destination < lowerMargin ) { 18438 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 18439 distance = Math.abs(destination - current); 18440 duration = distance / speed; 18441 } else if ( destination > 0 ) { 18442 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 18443 distance = Math.abs(current) + destination; 18444 duration = distance / speed; 18445 } 18446 18447 return { 18448 destination: Math.round(destination), 18449 duration: duration 18450 }; 18451 }; 18452 18453 var _transform = _prefixStyle('transform'); 18454 18455 me.extend(me, { 18456 hasTransform: _transform !== false, 18457 hasPerspective: _prefixStyle('perspective') in _elementStyle, 18458 hasTouch: 'ontouchstart' in window, 18459 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 18460 hasTransition: _prefixStyle('transition') in _elementStyle 18461 }); 18462 18463 /* 18464 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 18465 - galaxy S2 is ok 18466 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 18467 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 18468 - galaxy S3 is badAndroid (stock brower, webview) 18469 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 18470 - galaxy S4 is badAndroid (stock brower, webview) 18471 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 18472 - galaxy S5 is OK 18473 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 18474 - galaxy S6 is OK 18475 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 18476 */ 18477 me.isBadAndroid = (function() { 18478 var appVersion = window.navigator.appVersion; 18479 // Android browser is not a chrome browser. 18480 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 18481 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 18482 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 18483 return parseFloat(safariVersion[1]) < 535.19; 18484 } else { 18485 return true; 18486 } 18487 } else { 18488 return false;
vendor: 5,536 bytes, lines 18489-18681
18489 } 18490 })(); 18491 18492 me.extend(me.style = {}, { 18493 transform: _transform, 18494 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 18495 transitionDuration: _prefixStyle('transitionDuration'), 18496 transitionDelay: _prefixStyle('transitionDelay'), 18497 transformOrigin: _prefixStyle('transformOrigin') 18498 }); 18499 18500 me.hasClass = function (e, c) { 18501 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 18502 return re.test(e.className); 18503 }; 18504 18505 me.addClass = function (e, c) { 18506 if ( me.hasClass(e, c) ) { 18507 return; 18508 } 18509 18510 var newclass = e.className.split(' '); 18511 newclass.push(c); 18512 e.className = newclass.join(' '); 18513 }; 18514 18515 me.removeClass = function (e, c) { 18516 if ( !me.hasClass(e, c) ) { 18517 return; 18518 } 18519 18520 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 18521 e.className = e.className.replace(re, ' '); 18522 }; 18523 18524 me.offset = function (el) { 18525 var left = -el.offsetLeft, 18526 top = -el.offsetTop; 18527 18528 // jshint -W084 18529 while (el = el.offsetParent) { 18530 left -= el.offsetLeft; 18531 top -= el.offsetTop; 18532 } 18533 // jshint +W084 18534 18535 return { 18536 left: left, 18537 top: top 18538 }; 18539 }; 18540 18541 me.preventDefaultException = function (el, exceptions) { 18542 for ( var i in exceptions ) { 18543 if ( exceptions[i].test(el[i]) ) { 18544 return true; 18545 } 18546 } 18547 18548 return false; 18549 }; 18550 18551 me.extend(me.eventType = {}, { 18552 touchstart: 1, 18553 touchmove: 1, 18554 touchend: 1, 18555 18556 mousedown: 2, 18557 mousemove: 2, 18558 mouseup: 2, 18559 18560 pointerdown: 3, 18561 pointermove: 3, 18562 pointerup: 3, 18563 18564 MSPointerDown: 3, 18565 MSPointerMove: 3, 18566 MSPointerUp: 3 18567 }); 18568 18569 me.extend(me.ease = {}, { 18570 quadratic: { 18571 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 18572 fn: function (k) { 18573 return k * ( 2 - k ); 18574 } 18575 }, 18576 circular: { 18577 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) 18578 fn: function (k) { 18579 return Math.sqrt( 1 - ( --k * k ) ); 18580 } 18581 }, 18582 back: { 18583 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 18584 fn: function (k) { 18585 var b = 4; 18586 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 18587 } 18588 }, 18589 bounce: { 18590 style: '', 18591 fn: function (k) { 18592 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 18593 return 7.5625 * k * k; 18594 } else if ( k < ( 2 / 2.75 ) ) { 18595 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 18596 } else if ( k < ( 2.5 / 2.75 ) ) { 18597 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 18598 } else { 18599 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 18600 } 18601 } 18602 }, 18603 elastic: { 18604 style: '', 18605 fn: function (k) { 18606 var f = 0.22, 18607 e = 0.4; 18608 18609 if ( k === 0 ) { return 0; } 18610 if ( k == 1 ) { return 1; } 18611 18612 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 18613 } 18614 } 18615 }); 18616 18617 me.tap = function (e, eventName) { 18618 var ev = document.createEvent('Event'); 18619 ev.initEvent(eventName, true, true); 18620 ev.pageX = e.pageX; 18621 ev.pageY = e.pageY; 18622 e.target.dispatchEvent(ev); 18623 }; 18624 18625 me.click = function (e) { 18626 var target = e.target, 18627 ev; 18628 18629 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 18630 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 18631 // initMouseEvent is deprecated. 18632 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 18633 ev.initEvent('click', true, true); 18634 ev.view = e.view || window; 18635 ev.detail = 1; 18636 ev.screenX = target.screenX || 0; 18637 ev.screenY = target.screenY || 0; 18638 ev.clientX = target.clientX || 0; 18639 ev.clientY = target.clientY || 0; 18640 ev.ctrlKey = !!e.ctrlKey; 18641 ev.altKey = !!e.altKey; 18642 ev.shiftKey = !!e.shiftKey; 18643 ev.metaKey = !!e.metaKey; 18644 ev.button = 0; 18645 ev.relatedTarget = null; 18646 ev._constructed = true; 18647 target.dispatchEvent(ev); 18648 } 18649 }; 18650 18651 return me; 18652})(); 18653function IScroll (el, options) { 18654 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 18655 this.scroller = this.wrapper.children[0]; 18656 this.scrollerStyle = this.scroller.style; // cache style for better performance 18657 18658 this.options = { 18659 18660 resizeScrollbars: true, 18661 18662 mouseWheelSpeed: 20, 18663 18664 snapThreshold: 0.334, 18665 18666// INSERT POINT: OPTIONS 18667 disablePointer : !utils.hasPointer, 18668 disableTouch : utils.hasPointer || !utils.hasTouch, 18669 disableMouse : utils.hasPointer || utils.hasTouch, 18670 startX: 0, 18671 startY: 0, 18672 scrollY: true, 18673 directionLockThreshold: 5, 18674 momentum: true, 18675 18676 bounce: true, 18677 bounceTime: 600, 18678 bounceEasing: '', 18679 18680 preventDefault: true, 18681 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|
vendor: 4,420 bytes, lines 18681-18825
18681SELECT|LABEL)$/ }, 18682 18683 HWCompositing: true, 18684 useTransition: true, 18685 useTransform: true, 18686 bindToWrapper: typeof window.onmousedown === "undefined" 18687 }; 18688 18689 for ( var i in options ) { 18690 this.options[i] = options[i]; 18691 } 18692 18693 // Normalize options 18694 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 18695 18696 this.options.useTransition = utils.hasTransition && this.options.useTransition; 18697 this.options.useTransform = utils.hasTransform && this.options.useTransform; 18698 18699 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 18700 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 18701 18702 // If you want eventPassthrough I have to lock one of the axes 18703 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 18704 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 18705 18706 // With eventPassthrough we also need lockDirection mechanism 18707 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 18708 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 18709 18710 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 18711 18712 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 18713 18714 if ( this.options.tap === true ) { 18715 this.options.tap = 'tap'; 18716 } 18717 18718 // https://github.com/cubiq/iscroll/issues/1029 18719 if (!this.options.useTransition && !this.options.useTransform) { 18720 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 18721 this.scrollerStyle.position = "relative"; 18722 } 18723 } 18724 18725 if ( this.options.shrinkScrollbars == 'scale' ) { 18726 this.options.useTransition = false; 18727 } 18728 18729 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 18730 18731// INSERT POINT: NORMALIZATION 18732 18733 // Some defaults 18734 this.x = 0; 18735 this.y = 0; 18736 this.directionX = 0; 18737 this.directionY = 0; 18738 this._events = {}; 18739 18740// INSERT POINT: DEFAULTS 18741 18742 this._init(); 18743 this.refresh(); 18744 18745 this.scrollTo(this.options.startX, this.options.startY); 18746 this.enable(); 18747} 18748 18749IScroll.prototype = { 18750 version: '5.2.0', 18751 18752 _init: function () { 18753 this._initEvents(); 18754 18755 if ( this.options.scrollbars || this.options.indicators ) { 18756 this._initIndicators(); 18757 } 18758 18759 if ( this.options.mouseWheel ) { 18760 this._initWheel(); 18761 } 18762 18763 if ( this.options.snap ) { 18764 this._initSnap(); 18765 } 18766 18767 if ( this.options.keyBindings ) { 18768 this._initKeys(); 18769 } 18770 18771// INSERT POINT: _init 18772 18773 }, 18774 18775 destroy: function () { 18776 this._initEvents(true); 18777 clearTimeout(this.resizeTimeout); 18778 this.resizeTimeout = null; 18779 this._execEvent('destroy'); 18780 }, 18781 18782 _transitionEnd: function (e) { 18783 if ( e.target != this.scroller || !this.isInTransition ) { 18784 return; 18785 } 18786 18787 this._transitionTime(); 18788 if ( !this.resetPosition(this.options.bounceTime) ) { 18789 this.isInTransition = false; 18790 this._execEvent('scrollEnd'); 18791 } 18792 }, 18793 18794 _start: function (e) { 18795 // React to left mouse button only 18796 if ( utils.eventType[e.type] != 1 ) { 18797 // for button property 18798 // http://unixpapa.com/js/mouse.html 18799 var button; 18800 if (!e.which) { 18801 /* IE case */ 18802 button = (e.button < 2) ? 0 : 18803 ((e.button == 4) ? 1 : 2); 18804 } else { 18805 /* All others */ 18806 button = e.button; 18807 } 18808 if ( button !== 0 ) { 18809 return; 18810 } 18811 } 18812 18813 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 18814 return; 18815 } 18816 18817 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 18818 e.preventDefault(); 18819 } 18820 18821 var point = e.touches ? e.touches[0] : e, 18822 pos; 18823 18824 this.initiated = utils.eventType[e.type]; 18825 this.moved = false;
vendor: 5,928 bytes, lines 18826-19004
18826 this.distX = 0; 18827 this.distY = 0; 18828 this.directionX = 0; 18829 this.directionY = 0; 18830 this.directionLocked = 0; 18831 18832 this.startTime = utils.getTime(); 18833 18834 if ( this.options.useTransition && this.isInTransition ) { 18835 this._transitionTime(); 18836 this.isInTransition = false; 18837 pos = this.getComputedPosition(); 18838 this._translate(Math.round(pos.x), Math.round(pos.y)); 18839 this._execEvent('scrollEnd'); 18840 } else if ( !this.options.useTransition && this.isAnimating ) { 18841 this.isAnimating = false; 18842 this._execEvent('scrollEnd'); 18843 } 18844 18845 this.startX = this.x; 18846 this.startY = this.y; 18847 this.absStartX = this.x; 18848 this.absStartY = this.y; 18849 this.pointX = point.pageX; 18850 this.pointY = point.pageY; 18851 18852 this._execEvent('beforeScrollStart'); 18853 }, 18854 18855 _move: function (e) { 18856 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 18857 return; 18858 } 18859 18860 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 18861 e.preventDefault(); 18862 } 18863 18864 var point = e.touches ? e.touches[0] : e, 18865 deltaX = point.pageX - this.pointX, 18866 deltaY = point.pageY - this.pointY, 18867 timestamp = utils.getTime(), 18868 newX, newY, 18869 absDistX, absDistY; 18870 18871 this.pointX = point.pageX; 18872 this.pointY = point.pageY; 18873 18874 this.distX += deltaX; 18875 this.distY += deltaY; 18876 absDistX = Math.abs(this.distX); 18877 absDistY = Math.abs(this.distY); 18878 18879 // We need to move at least 10 pixels for the scrolling to initiate 18880 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 18881 return; 18882 } 18883 18884 // If you are scrolling in one direction lock the other 18885 if ( !this.directionLocked && !this.options.freeScroll ) { 18886 if ( absDistX > absDistY + this.options.directionLockThreshold ) { 18887 this.directionLocked = 'h'; // lock horizontally 18888 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 18889 this.directionLocked = 'v'; // lock vertically 18890 } else { 18891 this.directionLocked = 'n'; // no lock 18892 } 18893 } 18894 18895 if ( this.directionLocked == 'h' ) { 18896 if ( this.options.eventPassthrough == 'vertical' ) { 18897 e.preventDefault(); 18898 } else if ( this.options.eventPassthrough == 'horizontal' ) { 18899 this.initiated = false; 18900 return; 18901 } 18902 18903 deltaY = 0; 18904 } else if ( this.directionLocked == 'v' ) { 18905 if ( this.options.eventPassthrough == 'horizontal' ) { 18906 e.preventDefault(); 18907 } else if ( this.options.eventPassthrough == 'vertical' ) { 18908 this.initiated = false; 18909 return; 18910 } 18911 18912 deltaX = 0; 18913 } 18914 18915 deltaX = this.hasHorizontalScroll ? deltaX : 0; 18916 deltaY = this.hasVerticalScroll ? deltaY : 0; 18917 18918 newX = this.x + deltaX; 18919 newY = this.y + deltaY; 18920 18921 // Slow down if outside of the boundaries 18922 if ( newX > 0 || newX < this.maxScrollX ) { 18923 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 18924 } 18925 if ( newY > 0 || newY < this.maxScrollY ) { 18926 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 18927 } 18928 18929 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 18930 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 18931 18932 if ( !this.moved ) { 18933 this._execEvent('scrollStart'); 18934 } 18935 18936 this.moved = true; 18937 18938 this._translate(newX, newY); 18939 18940/* REPLACE START: _move */ 18941 18942 if ( timestamp - this.startTime > 300 ) { 18943 this.startTime = timestamp; 18944 this.startX = this.x; 18945 this.startY = this.y; 18946 } 18947 18948/* REPLACE END: _move */ 18949 18950 }, 18951 18952 _end: function (e) { 18953 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 18954 return; 18955 } 18956 18957 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 18958 e.preventDefault(); 18959 } 18960 18961 var point = e.changedTouches ? e.changedTouches[0] : e, 18962 momentumX, 18963 momentumY, 18964 duration = utils.getTime() - this.startTime, 18965 newX = Math.round(this.x), 18966 newY = Math.round(this.y), 18967 distanceX = Math.abs(newX - this.startX), 18968 distanceY = Math.abs(newY - this.startY), 18969 time = 0, 18970 easing = ''; 18971 18972 this.isInTransition = 0; 18973 this.initiated = 0; 18974 this.endTime = utils.getTime(); 18975 18976 // reset if we are outside of the boundaries 18977 if ( this.resetPosition(this.options.bounceTime) ) { 18978 return; 18979 } 18980 18981 this.scrollTo(newX, newY); // ensures that the last position is rounded 18982 18983 // we scrolled less than 10 pixels 18984 if ( !this.moved ) { 18985 if ( this.options.tap ) { 18986 utils.tap(e, this.options.tap); 18987 } 18988 18989 if ( this.options.click ) { 18990 utils.click(e); 18991 } 18992 18993 this._execEvent('scrollCancel'); 18994 return; 18995 } 18996 18997 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 18998 this._execEvent('flick'); 18999 return; 19000 } 19001 19002 // start momentum animation if needed 19003 if ( this.options.momentum && duration < 300 ) { 19004 momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperW
vendor: 7,740 bytes, lines 19004-19277
19004idth : 0, this.options.deceleration) : { destination: newX, duration: 0 }; 19005 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 }; 19006 newX = momentumX.destination; 19007 newY = momentumY.destination; 19008 time = Math.max(momentumX.duration, momentumY.duration); 19009 this.isInTransition = 1; 19010 } 19011 19012 19013 if ( this.options.snap ) { 19014 var snap = this._nearestSnap(newX, newY); 19015 this.currentPage = snap; 19016 time = this.options.snapSpeed || Math.max( 19017 Math.max( 19018 Math.min(Math.abs(newX - snap.x), 1000), 19019 Math.min(Math.abs(newY - snap.y), 1000) 19020 ), 300); 19021 newX = snap.x; 19022 newY = snap.y; 19023 19024 this.directionX = 0; 19025 this.directionY = 0; 19026 easing = this.options.bounceEasing; 19027 } 19028 19029// INSERT POINT: _end 19030 19031 if ( newX != this.x || newY != this.y ) { 19032 // change easing function when scroller goes out of the boundaries 19033 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 19034 easing = utils.ease.quadratic; 19035 } 19036 19037 this.scrollTo(newX, newY, time, easing); 19038 return; 19039 } 19040 19041 this._execEvent('scrollEnd'); 19042 }, 19043 19044 _resize: function () { 19045 var that = this; 19046 19047 clearTimeout(this.resizeTimeout); 19048 19049 this.resizeTimeout = setTimeout(function () { 19050 that.refresh(); 19051 }, this.options.resizePolling); 19052 }, 19053 19054 resetPosition: function (time) { 19055 var x = this.x, 19056 y = this.y; 19057 19058 time = time || 0; 19059 19060 if ( !this.hasHorizontalScroll || this.x > 0 ) { 19061 x = 0; 19062 } else if ( this.x < this.maxScrollX ) { 19063 x = this.maxScrollX; 19064 } 19065 19066 if ( !this.hasVerticalScroll || this.y > 0 ) { 19067 y = 0; 19068 } else if ( this.y < this.maxScrollY ) { 19069 y = this.maxScrollY; 19070 } 19071 19072 if ( x == this.x && y == this.y ) { 19073 return false; 19074 } 19075 19076 this.scrollTo(x, y, time, this.options.bounceEasing); 19077 19078 return true; 19079 }, 19080 19081 disable: function () { 19082 this.enabled = false; 19083 }, 19084 19085 enable: function () { 19086 this.enabled = true; 19087 }, 19088 19089 refresh: function () { 19090 var rf = this.wrapper.offsetHeight; // Force reflow 19091 19092 this.wrapperWidth = this.wrapper.clientWidth; 19093 this.wrapperHeight = this.wrapper.clientHeight; 19094 19095/* REPLACE START: refresh */ 19096 19097 this.scrollerWidth = this.scroller.offsetWidth; 19098 this.scrollerHeight = this.scroller.offsetHeight; 19099 19100 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 19101 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 19102 19103/* REPLACE END: refresh */ 19104 19105 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 19106 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 19107 19108 if ( !this.hasHorizontalScroll ) { 19109 this.maxScrollX = 0; 19110 this.scrollerWidth = this.wrapperWidth; 19111 } 19112 19113 if ( !this.hasVerticalScroll ) { 19114 this.maxScrollY = 0; 19115 this.scrollerHeight = this.wrapperHeight; 19116 } 19117 19118 this.endTime = 0; 19119 this.directionX = 0; 19120 this.directionY = 0; 19121 19122 this.wrapperOffset = utils.offset(this.wrapper); 19123 19124 this._execEvent('refresh'); 19125 19126 this.resetPosition(); 19127 19128// INSERT POINT: _refresh 19129 19130 }, 19131 19132 on: function (type, fn) { 19133 if ( !this._events[type] ) { 19134 this._events[type] = []; 19135 } 19136 19137 this._events[type].push(fn); 19138 }, 19139 19140 off: function (type, fn) { 19141 if ( !this._events[type] ) { 19142 return; 19143 } 19144 19145 var index = this._events[type].indexOf(fn); 19146 19147 if ( index > -1 ) { 19148 this._events[type].splice(index, 1); 19149 } 19150 }, 19151 19152 _execEvent: function (type) { 19153 if ( !this._events[type] ) { 19154 return; 19155 } 19156 19157 var i = 0, 19158 l = this._events[type].length; 19159 19160 if ( !l ) { 19161 return; 19162 } 19163 19164 for ( ; i < l; i++ ) { 19165 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 19166 } 19167 }, 19168 19169 scrollBy: function (x, y, time, easing) { 19170 x = this.x + x; 19171 y = this.y + y; 19172 time = time || 0; 19173 19174 this.scrollTo(x, y, time, easing); 19175 }, 19176 19177 scrollTo: function (x, y, time, easing) { 19178 easing = easing || utils.ease.circular; 19179 19180 this.isInTransition = this.options.useTransition && time > 0; 19181 var transitionType = this.options.useTransition && easing.style; 19182 if ( !time || transitionType ) { 19183 if(transitionType) { 19184 this._transitionTimingFunction(easing.style); 19185 this._transitionTime(time); 19186 } 19187 this._translate(x, y); 19188 } else { 19189 this._animate(x, y, time, easing.fn); 19190 } 19191 }, 19192 19193 scrollToElement: function (el, time, offsetX, offsetY, easing) { 19194 el = el.nodeType ? el : this.scroller.querySelector(el); 19195 19196 if ( !el ) { 19197 return; 19198 } 19199 19200 var pos = utils.offset(el); 19201 19202 pos.left -= this.wrapperOffset.left; 19203 pos.top -= this.wrapperOffset.top; 19204 19205 // if offsetX/Y are true we center the element to the screen 19206 if ( offsetX === true ) { 19207 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 19208 } 19209 if ( offsetY === true ) { 19210 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 19211 } 19212 19213 pos.left -= offsetX || 0; 19214 pos.top -= offsetY || 0; 19215 19216 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 19217 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 19218 19219 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 19220 19221 this.scrollTo(pos.left, pos.top, time, easing); 19222 }, 19223 19224 _transitionTime: function (time) { 19225 if (!this.options.useTransition) { 19226 return; 19227 } 19228 time = time || 0; 19229 var durationProp = utils.style.transitionDuration; 19230 if(!durationProp) { 19231 return; 19232 } 19233 19234 this.scrollerStyle[durationProp] = time + 'ms'; 19235 19236 if ( !time && utils.isBadAndroid ) { 19237 this.scrollerStyle[durationProp] = '0.0001ms'; 19238 // remove 0.0001ms 19239 var self = this; 19240 rAF(function() { 19241 if(self.scrollerStyle[durationProp] === '0.0001ms') { 19242 self.scrollerStyle[durationProp] = '0s'; 19243 } 19244 }); 19245 } 19246 19247 19248 if ( this.indicators ) { 19249 for ( var i = this.indicators.length; i--; ) { 19250 this.indicators[i].transitionTime(time); 19251 } 19252 } 19253 19254 19255// INSERT POINT: _transitionTime 19256 19257 }, 19258 19259 _transitionTimingFunction: function (easing) { 19260 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 19261 19262 19263 if ( this.indicators ) { 19264 for ( var i = this.indicators.length; i--; ) { 19265 this.indicators[i].transitionTimingFunction(easing); 19266 } 19267 } 19268 19269 19270// INSERT POINT: _transitionTimingFunction 19271 19272 }, 19273 19274 _translate: function (x, y) { 19275 //Uncode addition 19276 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 19277 return false;
vendor: 9,939 bytes, lines 19278-19589
19278 19279 if ( this.options.useTransform ) { 19280 19281/* REPLACE START: _translate */ 19282 19283 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 19284 19285/* REPLACE END: _translate */ 19286 19287 } else { 19288 x = Math.round(x); 19289 y = Math.round(y); 19290 this.scrollerStyle.left = x + 'px'; 19291 this.scrollerStyle.top = y + 'px'; 19292 } 19293 19294 this.x = x; 19295 this.y = y; 19296 19297 19298 if ( this.indicators ) { 19299 for ( var i = this.indicators.length; i--; ) { 19300 this.indicators[i].updatePosition(); 19301 } 19302 } 19303 19304 //Uncode addition 19305 var uncodevent = new CustomEvent('fp-slide-scroll'); 19306 window.dispatchEvent(uncodevent); 19307 19308// INSERT POINT: _translate 19309 19310 }, 19311 19312 _initEvents: function (remove) { 19313 var eventType = remove ? utils.removeEvent : utils.addEvent, 19314 target = this.options.bindToWrapper ? this.wrapper : window; 19315 19316 eventType(window, 'orientationchange', this); 19317 eventType(window, 'resize', this); 19318 19319 if ( this.options.click ) { 19320 eventType(this.wrapper, 'click', this, true); 19321 } 19322 19323 if ( !this.options.disableMouse ) { 19324 eventType(this.wrapper, 'mousedown', this); 19325 eventType(target, 'mousemove', this); 19326 eventType(target, 'mousecancel', this); 19327 eventType(target, 'mouseup', this); 19328 } 19329 19330 if ( utils.hasPointer && !this.options.disablePointer ) { 19331 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 19332 eventType(target, utils.prefixPointerEvent('pointermove'), this); 19333 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 19334 eventType(target, utils.prefixPointerEvent('pointerup'), this); 19335 } 19336 19337 if ( utils.hasTouch && !this.options.disableTouch ) { 19338 eventType(this.wrapper, 'touchstart', this); 19339 eventType(target, 'touchmove', this); 19340 eventType(target, 'touchcancel', this); 19341 eventType(target, 'touchend', this); 19342 } 19343 19344 eventType(this.scroller, 'transitionend', this); 19345 eventType(this.scroller, 'webkitTransitionEnd', this); 19346 eventType(this.scroller, 'oTransitionEnd', this); 19347 eventType(this.scroller, 'MSTransitionEnd', this); 19348 }, 19349 19350 getComputedPosition: function () { 19351 var matrix = window.getComputedStyle(this.scroller, null), 19352 x, y; 19353 19354 if ( this.options.useTransform ) { 19355 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 19356 x = +(matrix[12] || matrix[4]); 19357 y = +(matrix[13] || matrix[5]); 19358 } else { 19359 x = +matrix.left.replace(/[^-\d.]/g, ''); 19360 y = +matrix.top.replace(/[^-\d.]/g, ''); 19361 } 19362 19363 return { x: x, y: y }; 19364 }, 19365 _initIndicators: function () { 19366 var interactive = this.options.interactiveScrollbars, 19367 customStyle = typeof this.options.scrollbars != 'string', 19368 indicators = [], 19369 indicator; 19370 19371 var that = this; 19372 19373 this.indicators = []; 19374 19375 if ( this.options.scrollbars ) { 19376 // Vertical scrollbar 19377 if ( this.options.scrollY ) { 19378 indicator = { 19379 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 19380 interactive: interactive, 19381 defaultScrollbars: true, 19382 customStyle: customStyle, 19383 resize: this.options.resizeScrollbars, 19384 shrink: this.options.shrinkScrollbars, 19385 fade: this.options.fadeScrollbars, 19386 listenX: false 19387 }; 19388 19389 this.wrapper.appendChild(indicator.el); 19390 indicators.push(indicator); 19391 } 19392 19393 // Horizontal scrollbar 19394 if ( this.options.scrollX ) { 19395 indicator = { 19396 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 19397 interactive: interactive, 19398 defaultScrollbars: true, 19399 customStyle: customStyle, 19400 resize: this.options.resizeScrollbars, 19401 shrink: this.options.shrinkScrollbars, 19402 fade: this.options.fadeScrollbars, 19403 listenY: false 19404 }; 19405 19406 this.wrapper.appendChild(indicator.el); 19407 indicators.push(indicator); 19408 } 19409 } 19410 19411 if ( this.options.indicators ) { 19412 // TODO: check concat compatibility 19413 indicators = indicators.concat(this.options.indicators); 19414 } 19415 19416 for ( var i = indicators.length; i--; ) { 19417 this.indicators.push( new Indicator(this, indicators[i]) ); 19418 } 19419 19420 // TODO: check if we can use array.map (wide compatibility and performance issues) 19421 function _indicatorsMap (fn) { 19422 if (that.indicators) { 19423 for ( var i = that.indicators.length; i--; ) { 19424 fn.call(that.indicators[i]); 19425 } 19426 } 19427 } 19428 19429 if ( this.options.fadeScrollbars ) { 19430 this.on('scrollEnd', function () { 19431 _indicatorsMap(function () { 19432 this.fade(); 19433 }); 19434 }); 19435 19436 this.on('scrollCancel', function () { 19437 _indicatorsMap(function () { 19438 this.fade(); 19439 }); 19440 }); 19441 19442 this.on('scrollStart', function () { 19443 _indicatorsMap(function () { 19444 this.fade(1); 19445 }); 19446 }); 19447 19448 this.on('beforeScrollStart', function () { 19449 _indicatorsMap(function () { 19450 this.fade(1, true); 19451 }); 19452 }); 19453 } 19454 19455 19456 this.on('refresh', function () { 19457 _indicatorsMap(function () { 19458 this.refresh(); 19459 }); 19460 }); 19461 19462 this.on('destroy', function () { 19463 _indicatorsMap(function () { 19464 this.destroy(); 19465 }); 19466 19467 delete this.indicators; 19468 }); 19469 }, 19470 19471 _initWheel: function () { 19472 utils.addEvent(this.wrapper, 'wheel', this); 19473 utils.addEvent(this.wrapper, 'mousewheel', this); 19474 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 19475 19476 this.on('destroy', function () { 19477 clearTimeout(this.wheelTimeout); 19478 this.wheelTimeout = null; 19479 utils.removeEvent(this.wrapper, 'wheel', this); 19480 utils.removeEvent(this.wrapper, 'mousewheel', this); 19481 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 19482 }); 19483 }, 19484 19485 _wheel: function (e) { 19486 if ( !this.enabled ) { 19487 return; 19488 } 19489 19490 var wheelDeltaX, wheelDeltaY, 19491 newX, newY, 19492 that = this; 19493 19494 if ( this.wheelTimeout === undefined ) { 19495 that._execEvent('scrollStart'); 19496 } 19497 19498 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 19499 clearTimeout(this.wheelTimeout); 19500 this.wheelTimeout = setTimeout(function () { 19501 if(!that.options.snap) { 19502 that._execEvent('scrollEnd'); 19503 } 19504 that.wheelTimeout = undefined; 19505 }, 400); 19506 19507 if ( 'deltaX' in e ) { 19508 if (e.deltaMode === 1) { 19509 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 19510 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 19511 } else { 19512 wheelDeltaX = -e.deltaX; 19513 wheelDeltaY = -e.deltaY; 19514 } 19515 } else if ( 'wheelDeltaX' in e ) { 19516 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 19517 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 19518 } else if ( 'wheelDelta' in e ) { 19519 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 19520 } else if ( 'detail' in e ) { 19521 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 19522 } else { 19523 return; 19524 } 19525 19526 wheelDeltaX *= this.options.invertWheelDirection; 19527 wheelDeltaY *= this.options.invertWheelDirection; 19528 19529 if ( !this.hasVerticalScroll ) { 19530 wheelDeltaX = wheelDeltaY; 19531 wheelDeltaY = 0; 19532 } 19533 19534 if ( this.options.snap ) { 19535 newX = this.currentPage.pageX; 19536 newY = this.currentPage.pageY; 19537 19538 if ( wheelDeltaX > 0 ) { 19539 newX--; 19540 } else if ( wheelDeltaX < 0 ) { 19541 newX++; 19542 } 19543 19544 if ( wheelDeltaY > 0 ) { 19545 newY--; 19546 } else if ( wheelDeltaY < 0 ) { 19547 newY++; 19548 } 19549 19550 this.goToPage(newX, newY); 19551 19552 return; 19553 } 19554 19555 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 19556 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 19557 19558 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 19559 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 19560 19561 if ( newX > 0 ) { 19562 newX = 0; 19563 } else if ( newX < this.maxScrollX ) { 19564 newX = this.maxScrollX; 19565 } 19566 19567 if ( newY > 0 ) { 19568 newY = 0; 19569 } else if ( newY < this.maxScrollY ) { 19570 newY = this.maxScrollY; 19571 } 19572 19573 this.scrollTo(newX, newY, 0); 19574 19575// INSERT POINT: _wheel 19576 }, 19577 19578 _initSnap: function () { 19579 this.currentPage = {}; 19580 19581 if ( typeof this.options.snap == 'string' ) { 19582 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 19583 } 19584 19585 this.on('refresh', function () { 19586 var i = 0, l, 19587 m = 0, n, 19588 cx, cy, 19589 x = 0, y,
vendor: 7,339 bytes, lines 19590-19843
19590 stepX = this.options.snapStepX || this.wrapperWidth, 19591 stepY = this.options.snapStepY || this.wrapperHeight, 19592 el; 19593 19594 this.pages = []; 19595 19596 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 19597 return; 19598 } 19599 19600 if ( this.options.snap === true ) { 19601 cx = Math.round( stepX / 2 ); 19602 cy = Math.round( stepY / 2 ); 19603 19604 while ( x > -this.scrollerWidth ) { 19605 this.pages[i] = []; 19606 l = 0; 19607 y = 0; 19608 19609 while ( y > -this.scrollerHeight ) { 19610 this.pages[i][l] = { 19611 x: Math.max(x, this.maxScrollX), 19612 y: Math.max(y, this.maxScrollY), 19613 width: stepX, 19614 height: stepY, 19615 cx: x - cx, 19616 cy: y - cy 19617 }; 19618 19619 y -= stepY; 19620 l++; 19621 } 19622 19623 x -= stepX; 19624 i++; 19625 } 19626 } else { 19627 el = this.options.snap; 19628 l = el.length; 19629 n = -1; 19630 19631 for ( ; i < l; i++ ) { 19632 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 19633 m = 0; 19634 n++; 19635 } 19636 19637 if ( !this.pages[m] ) { 19638 this.pages[m] = []; 19639 } 19640 19641 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 19642 y = Math.max(-el[i].offsetTop, this.maxScrollY); 19643 cx = x - Math.round(el[i].offsetWidth / 2); 19644 cy = y - Math.round(el[i].offsetHeight / 2); 19645 19646 this.pages[m][n] = { 19647 x: x, 19648 y: y, 19649 width: el[i].offsetWidth, 19650 height: el[i].offsetHeight, 19651 cx: cx, 19652 cy: cy 19653 }; 19654 19655 if ( x > this.maxScrollX ) { 19656 m++; 19657 } 19658 } 19659 } 19660 19661 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 19662 19663 // Update snap threshold if needed 19664 if ( this.options.snapThreshold % 1 === 0 ) { 19665 this.snapThresholdX = this.options.snapThreshold; 19666 this.snapThresholdY = this.options.snapThreshold; 19667 } else { 19668 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 19669 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 19670 } 19671 }); 19672 19673 this.on('flick', function () { 19674 var time = this.options.snapSpeed || Math.max( 19675 Math.max( 19676 Math.min(Math.abs(this.x - this.startX), 1000), 19677 Math.min(Math.abs(this.y - this.startY), 1000) 19678 ), 300); 19679 19680 this.goToPage( 19681 this.currentPage.pageX + this.directionX, 19682 this.currentPage.pageY + this.directionY, 19683 time 19684 ); 19685 }); 19686 }, 19687 19688 _nearestSnap: function (x, y) { 19689 if ( !this.pages.length ) { 19690 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 19691 } 19692 19693 var i = 0, 19694 l = this.pages.length, 19695 m = 0; 19696 19697 // Check if we exceeded the snap threshold 19698 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 19699 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 19700 return this.currentPage; 19701 } 19702 19703 if ( x > 0 ) { 19704 x = 0; 19705 } else if ( x < this.maxScrollX ) { 19706 x = this.maxScrollX; 19707 } 19708 19709 if ( y > 0 ) { 19710 y = 0; 19711 } else if ( y < this.maxScrollY ) { 19712 y = this.maxScrollY; 19713 } 19714 19715 for ( ; i < l; i++ ) { 19716 if ( x >= this.pages[i][0].cx ) { 19717 x = this.pages[i][0].x; 19718 break; 19719 } 19720 } 19721 19722 l = this.pages[i].length; 19723 19724 for ( ; m < l; m++ ) { 19725 if ( y >= this.pages[0][m].cy ) { 19726 y = this.pages[0][m].y; 19727 break; 19728 } 19729 } 19730 19731 if ( i == this.currentPage.pageX ) { 19732 i += this.directionX; 19733 19734 if ( i < 0 ) { 19735 i = 0; 19736 } else if ( i >= this.pages.length ) { 19737 i = this.pages.length - 1; 19738 } 19739 19740 x = this.pages[i][0].x; 19741 } 19742 19743 if ( m == this.currentPage.pageY ) { 19744 m += this.directionY; 19745 19746 if ( m < 0 ) { 19747 m = 0; 19748 } else if ( m >= this.pages[0].length ) { 19749 m = this.pages[0].length - 1; 19750 } 19751 19752 y = this.pages[0][m].y; 19753 } 19754 19755 return { 19756 x: x, 19757 y: y, 19758 pageX: i, 19759 pageY: m 19760 }; 19761 }, 19762 19763 goToPage: function (x, y, time, easing) { 19764 easing = easing || this.options.bounceEasing; 19765 19766 if ( x >= this.pages.length ) { 19767 x = this.pages.length - 1; 19768 } else if ( x < 0 ) { 19769 x = 0; 19770 } 19771 19772 if ( y >= this.pages[x].length ) { 19773 y = this.pages[x].length - 1; 19774 } else if ( y < 0 ) { 19775 y = 0; 19776 } 19777 19778 var posX = this.pages[x][y].x, 19779 posY = this.pages[x][y].y; 19780 19781 time = time === undefined ? this.options.snapSpeed || Math.max( 19782 Math.max( 19783 Math.min(Math.abs(posX - this.x), 1000), 19784 Math.min(Math.abs(posY - this.y), 1000) 19785 ), 300) : time; 19786 19787 this.currentPage = { 19788 x: posX, 19789 y: posY, 19790 pageX: x, 19791 pageY: y 19792 }; 19793 19794 this.scrollTo(posX, posY, time, easing); 19795 }, 19796 19797 next: function (time, easing) { 19798 var x = this.currentPage.pageX, 19799 y = this.currentPage.pageY; 19800 19801 x++; 19802 19803 if ( x >= this.pages.length && this.hasVerticalScroll ) { 19804 x = 0; 19805 y++; 19806 } 19807 19808 this.goToPage(x, y, time, easing); 19809 }, 19810 19811 prev: function (time, easing) { 19812 var x = this.currentPage.pageX, 19813 y = this.currentPage.pageY; 19814 19815 x--; 19816 19817 if ( x < 0 && this.hasVerticalScroll ) { 19818 x = 0; 19819 y--; 19820 } 19821 19822 this.goToPage(x, y, time, easing); 19823 }, 19824 19825 _initKeys: function (e) { 19826 // default key bindings 19827 var keys = { 19828 pageUp: 33, 19829 pageDown: 34, 19830 end: 35, 19831 home: 36, 19832 left: 37, 19833 up: 38, 19834 right: 39, 19835 down: 40 19836 }; 19837 var i; 19838 19839 // if you give me characters I give you keycode 19840 if ( typeof this.options.keyBindings == 'object' ) { 19841 for ( i in this.options.keyBindings ) { 19842 if ( typeof this.options.keyBindings[i] == 'string' ) { 19843 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 19843-20196
19843deAt(0); 19844 } 19845 } 19846 } else { 19847 this.options.keyBindings = {}; 19848 } 19849 19850 for ( i in keys ) { 19851 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 19852 } 19853 19854 utils.addEvent(window, 'keydown', this); 19855 19856 this.on('destroy', function () { 19857 utils.removeEvent(window, 'keydown', this); 19858 }); 19859 }, 19860 19861 _key: function (e) { 19862 if ( !this.enabled ) { 19863 return; 19864 } 19865 19866 var snap = this.options.snap, // we are using this alot, better to cache it 19867 newX = snap ? this.currentPage.pageX : this.x, 19868 newY = snap ? this.currentPage.pageY : this.y, 19869 now = utils.getTime(), 19870 prevTime = this.keyTime || 0, 19871 acceleration = 0.250, 19872 pos; 19873 19874 if ( this.options.useTransition && this.isInTransition ) { 19875 pos = this.getComputedPosition(); 19876 19877 this._translate(Math.round(pos.x), Math.round(pos.y)); 19878 this.isInTransition = false; 19879 } 19880 19881 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 19882 19883 switch ( e.keyCode ) { 19884 case this.options.keyBindings.pageUp: 19885 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 19886 newX += snap ? 1 : this.wrapperWidth; 19887 } else { 19888 newY += snap ? 1 : this.wrapperHeight; 19889 } 19890 break; 19891 case this.options.keyBindings.pageDown: 19892 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 19893 newX -= snap ? 1 : this.wrapperWidth; 19894 } else { 19895 newY -= snap ? 1 : this.wrapperHeight; 19896 } 19897 break; 19898 case this.options.keyBindings.end: 19899 newX = snap ? this.pages.length-1 : this.maxScrollX; 19900 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 19901 break; 19902 case this.options.keyBindings.home: 19903 newX = 0; 19904 newY = 0; 19905 break; 19906 case this.options.keyBindings.left: 19907 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 19908 break; 19909 case this.options.keyBindings.up: 19910 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 19911 break; 19912 case this.options.keyBindings.right: 19913 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 19914 break; 19915 case this.options.keyBindings.down: 19916 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 19917 break; 19918 default: 19919 return; 19920 } 19921 19922 if ( snap ) { 19923 this.goToPage(newX, newY); 19924 return; 19925 } 19926 19927 if ( newX > 0 ) { 19928 newX = 0; 19929 this.keyAcceleration = 0; 19930 } else if ( newX < this.maxScrollX ) { 19931 newX = this.maxScrollX; 19932 this.keyAcceleration = 0; 19933 } 19934 19935 if ( newY > 0 ) { 19936 newY = 0; 19937 this.keyAcceleration = 0; 19938 } else if ( newY < this.maxScrollY ) { 19939 newY = this.maxScrollY; 19940 this.keyAcceleration = 0; 19941 } 19942 19943 this.scrollTo(newX, newY, 0); 19944 19945 this.keyTime = now; 19946 }, 19947 19948 _animate: function (destX, destY, duration, easingFn) { 19949 var that = this, 19950 startX = this.x, 19951 startY = this.y, 19952 startTime = utils.getTime(), 19953 destTime = startTime + duration; 19954 19955 function step () { 19956 var now = utils.getTime(), 19957 newX, newY, 19958 easing; 19959 19960 if ( now >= destTime ) { 19961 that.isAnimating = false; 19962 that._translate(destX, destY); 19963 19964 if ( !that.resetPosition(that.options.bounceTime) ) { 19965 that._execEvent('scrollEnd'); 19966 } 19967 19968 return; 19969 } 19970 19971 now = ( now - startTime ) / duration; 19972 easing = easingFn(now); 19973 newX = ( destX - startX ) * easing + startX; 19974 newY = ( destY - startY ) * easing + startY; 19975 that._translate(newX, newY); 19976 19977 if ( that.isAnimating ) { 19978 rAF(step); 19979 } 19980 } 19981 19982 this.isAnimating = true; 19983 step(); 19984 }, 19985 handleEvent: function (e) { 19986 switch ( e.type ) { 19987 case 'touchstart': 19988 case 'pointerdown': 19989 case 'MSPointerDown': 19990 case 'mousedown': 19991 this._start(e); 19992 break; 19993 case 'touchmove': 19994 case 'pointermove': 19995 case 'MSPointerMove': 19996 case 'mousemove': 19997 this._move(e); 19998 break; 19999 case 'touchend': 20000 case 'pointerup': 20001 case 'MSPointerUp': 20002 case 'mouseup': 20003 case 'touchcancel': 20004 case 'pointercancel': 20005 case 'MSPointerCancel': 20006 case 'mousecancel': 20007 this._end(e); 20008 break; 20009 case 'orientationchange': 20010 case 'resize': 20011 this._resize(); 20012 break; 20013 case 'transitionend': 20014 case 'webkitTransitionEnd': 20015 case 'oTransitionEnd': 20016 case 'MSTransitionEnd': 20017 this._transitionEnd(e); 20018 break; 20019 case 'wheel': 20020 case 'DOMMouseScroll': 20021 case 'mousewheel': 20022 this._wheel(e); 20023 break; 20024 case 'keydown': 20025 this._key(e); 20026 break; 20027 case 'click': 20028 if ( this.enabled && !e._constructed ) { 20029 e.preventDefault(); 20030 e.stopPropagation(); 20031 } 20032 break; 20033 } 20034 } 20035}; 20036function createDefaultScrollbar (direction, interactive, type) { 20037 var scrollbar = document.createElement('div'), 20038 indicator = document.createElement('div'); 20039 20040 if ( type === true ) { 20041 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 20042 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'; 20043 } 20044 20045 indicator.className = 'iScrollIndicator'; 20046 20047 if ( direction == 'h' ) { 20048 if ( type === true ) { 20049 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 20050 indicator.style.height = '100%'; 20051 } 20052 scrollbar.className = 'iScrollHorizontalScrollbar'; 20053 } else { 20054 if ( type === true ) { 20055 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 20056 indicator.style.width = '100%'; 20057 } 20058 scrollbar.className = 'iScrollVerticalScrollbar'; 20059 } 20060 20061 scrollbar.style.cssText += ';overflow:hidden'; 20062 20063 if ( !interactive ) { 20064 scrollbar.style.pointerEvents = 'none'; 20065 } 20066 20067 scrollbar.appendChild(indicator); 20068 20069 return scrollbar; 20070} 20071 20072function Indicator (scroller, options) { 20073 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 20074 this.wrapperStyle = this.wrapper.style; 20075 this.indicator = this.wrapper.children[0]; 20076 this.indicatorStyle = this.indicator.style; 20077 this.scroller = scroller; 20078 20079 this.options = { 20080 listenX: true, 20081 listenY: true, 20082 interactive: false, 20083 resize: true, 20084 defaultScrollbars: false, 20085 shrink: false, 20086 fade: false, 20087 speedRatioX: 0, 20088 speedRatioY: 0 20089 }; 20090 20091 for ( var i in options ) { 20092 this.options[i] = options[i]; 20093 } 20094 20095 this.sizeRatioX = 1; 20096 this.sizeRatioY = 1; 20097 this.maxPosX = 0; 20098 this.maxPosY = 0; 20099 20100 if ( this.options.interactive ) { 20101 if ( !this.options.disableTouch ) { 20102 utils.addEvent(this.indicator, 'touchstart', this); 20103 utils.addEvent(window, 'touchend', this); 20104 } 20105 if ( !this.options.disablePointer ) { 20106 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 20107 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 20108 } 20109 if ( !this.options.disableMouse ) { 20110 utils.addEvent(this.indicator, 'mousedown', this); 20111 utils.addEvent(window, 'mouseup', this); 20112 } 20113 } 20114 20115 if ( this.options.fade ) { 20116 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 20117 var durationProp = utils.style.transitionDuration; 20118 if(!durationProp) { 20119 return; 20120 } 20121 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 20122 // remove 0.0001ms 20123 var self = this; 20124 if(utils.isBadAndroid) { 20125 rAF(function() { 20126 if(self.wrapperStyle[durationProp] === '0.0001ms') { 20127 self.wrapperStyle[durationProp] = '0s'; 20128 } 20129 }); 20130 } 20131 this.wrapperStyle.opacity = '0'; 20132 } 20133} 20134 20135Indicator.prototype = { 20136 handleEvent: function (e) { 20137 switch ( e.type ) { 20138 case 'touchstart': 20139 case 'pointerdown': 20140 case 'MSPointerDown': 20141 case 'mousedown': 20142 this._start(e); 20143 break; 20144 case 'touchmove': 20145 case 'pointermove': 20146 case 'MSPointerMove': 20147 case 'mousemove': 20148 this._move(e); 20149 break; 20150 case 'touchend': 20151 case 'pointerup': 20152 case 'MSPointerUp': 20153 case 'mouseup': 20154 case 'touchcancel': 20155 case 'pointercancel': 20156 case 'MSPointerCancel': 20157 case 'mousecancel': 20158 this._end(e); 20159 break; 20160 } 20161 }, 20162 20163 destroy: function () { 20164 if ( this.options.fadeScrollbars ) { 20165 clearTimeout(this.fadeTimeout); 20166 this.fadeTimeout = null; 20167 } 20168 if ( this.options.interactive ) { 20169 utils.removeEvent(this.indicator, 'touchstart', this); 20170 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 20171 utils.removeEvent(this.indicator, 'mousedown', this); 20172 20173 utils.removeEvent(window, 'touchmove', this); 20174 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 20175 utils.removeEvent(window, 'mousemove', this); 20176 20177 utils.removeEvent(window, 'touchend', this); 20178 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 20179 utils.removeEvent(window, 'mouseup', this); 20180 } 20181 20182 if ( this.options.defaultScrollbars ) { 20183 this.wrapper.parentNode.removeChild(this.wrapper); 20184 } 20185 }, 20186 20187 _start: function (e) { 20188 var point = e.touches ? e.touches[0] : e; 20189 20190 e.preventDefault(); 20191 e.stopPropagation(); 20192 20193 this.transitionTime(); 20194 20195 this.initiated = true; 20196 this.moved = false;
vendor: 9,615 bytes, lines 20197-20455
20197 this.lastPointX = point.pageX; 20198 this.lastPointY = point.pageY; 20199 20200 this.startTime = utils.getTime(); 20201 20202 if ( !this.options.disableTouch ) { 20203 utils.addEvent(window, 'touchmove', this); 20204 } 20205 if ( !this.options.disablePointer ) { 20206 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 20207 } 20208 if ( !this.options.disableMouse ) { 20209 utils.addEvent(window, 'mousemove', this); 20210 } 20211 20212 this.scroller._execEvent('beforeScrollStart'); 20213 }, 20214 20215 _move: function (e) { 20216 var point = e.touches ? e.touches[0] : e, 20217 deltaX, deltaY, 20218 newX, newY, 20219 timestamp = utils.getTime(); 20220 20221 if ( !this.moved ) { 20222 this.scroller._execEvent('scrollStart'); 20223 } 20224 20225 this.moved = true; 20226 20227 deltaX = point.pageX - this.lastPointX; 20228 this.lastPointX = point.pageX; 20229 20230 deltaY = point.pageY - this.lastPointY; 20231 this.lastPointY = point.pageY; 20232 20233 newX = this.x + deltaX; 20234 newY = this.y + deltaY; 20235 20236 this._pos(newX, newY); 20237 20238// INSERT POINT: indicator._move 20239 20240 e.preventDefault(); 20241 e.stopPropagation(); 20242 }, 20243 20244 _end: function (e) { 20245 if ( !this.initiated ) { 20246 return; 20247 } 20248 20249 this.initiated = false; 20250 20251 e.preventDefault(); 20252 e.stopPropagation(); 20253 20254 utils.removeEvent(window, 'touchmove', this); 20255 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 20256 utils.removeEvent(window, 'mousemove', this); 20257 20258 if ( this.scroller.options.snap ) { 20259 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 20260 20261 var time = this.options.snapSpeed || Math.max( 20262 Math.max( 20263 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 20264 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 20265 ), 300); 20266 20267 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 20268 this.scroller.directionX = 0; 20269 this.scroller.directionY = 0; 20270 this.scroller.currentPage = snap; 20271 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 20272 } 20273 } 20274 20275 if ( this.moved ) { 20276 this.scroller._execEvent('scrollEnd'); 20277 } 20278 }, 20279 20280 transitionTime: function (time) { 20281 time = time || 0; 20282 var durationProp = utils.style.transitionDuration; 20283 if(!durationProp) { 20284 return; 20285 } 20286 20287 this.indicatorStyle[durationProp] = time + 'ms'; 20288 20289 if ( !time && utils.isBadAndroid ) { 20290 this.indicatorStyle[durationProp] = '0.0001ms'; 20291 // remove 0.0001ms 20292 var self = this; 20293 rAF(function() { 20294 if(self.indicatorStyle[durationProp] === '0.0001ms') { 20295 self.indicatorStyle[durationProp] = '0s'; 20296 } 20297 }); 20298 } 20299 }, 20300 20301 transitionTimingFunction: function (easing) { 20302 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 20303 }, 20304 20305 refresh: function () { 20306 this.transitionTime(); 20307 20308 if ( this.options.listenX && !this.options.listenY ) { 20309 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 20310 } else if ( this.options.listenY && !this.options.listenX ) { 20311 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 20312 } else { 20313 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 20314 } 20315 20316 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 20317 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 20318 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 20319 20320 if ( this.options.defaultScrollbars && this.options.customStyle ) { 20321 if ( this.options.listenX ) { 20322 this.wrapper.style.right = '8px'; 20323 } else { 20324 this.wrapper.style.bottom = '8px'; 20325 } 20326 } 20327 } else { 20328 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 20329 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 20330 20331 if ( this.options.defaultScrollbars && this.options.customStyle ) { 20332 if ( this.options.listenX ) { 20333 this.wrapper.style.right = '2px'; 20334 } else { 20335 this.wrapper.style.bottom = '2px'; 20336 } 20337 } 20338 } 20339 20340 var r = this.wrapper.offsetHeight; // force refresh 20341 20342 if ( this.options.listenX ) { 20343 this.wrapperWidth = this.wrapper.clientWidth; 20344 if ( this.options.resize ) { 20345 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 20346 this.indicatorStyle.width = this.indicatorWidth + 'px'; 20347 } else { 20348 this.indicatorWidth = this.indicator.clientWidth; 20349 } 20350 20351 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 20352 20353 if ( this.options.shrink == 'clip' ) { 20354 this.minBoundaryX = -this.indicatorWidth + 8; 20355 this.maxBoundaryX = this.wrapperWidth - 8; 20356 } else { 20357 this.minBoundaryX = 0; 20358 this.maxBoundaryX = this.maxPosX; 20359 } 20360 20361 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 20362 } 20363 20364 if ( this.options.listenY ) { 20365 this.wrapperHeight = this.wrapper.clientHeight; 20366 if ( this.options.resize ) { 20367 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 20368 this.indicatorStyle.height = this.indicatorHeight + 'px'; 20369 } else { 20370 this.indicatorHeight = this.indicator.clientHeight; 20371 } 20372 20373 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 20374 20375 if ( this.options.shrink == 'clip' ) { 20376 this.minBoundaryY = -this.indicatorHeight + 8; 20377 this.maxBoundaryY = this.wrapperHeight - 8; 20378 } else { 20379 this.minBoundaryY = 0; 20380 this.maxBoundaryY = this.maxPosY; 20381 } 20382 20383 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 20384 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 20385 } 20386 20387 this.updatePosition(); 20388 }, 20389 20390 updatePosition: function () { 20391 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 20392 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 20393 20394 if ( !this.options.ignoreBoundaries ) { 20395 if ( x < this.minBoundaryX ) { 20396 if ( this.options.shrink == 'scale' ) { 20397 this.width = Math.max(this.indicatorWidth + x, 8); 20398 this.indicatorStyle.width = this.width + 'px'; 20399 } 20400 x = this.minBoundaryX; 20401 } else if ( x > this.maxBoundaryX ) { 20402 if ( this.options.shrink == 'scale' ) { 20403 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 20404 this.indicatorStyle.width = this.width + 'px'; 20405 x = this.maxPosX + this.indicatorWidth - this.width; 20406 } else { 20407 x = this.maxBoundaryX; 20408 } 20409 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 20410 this.width = this.indicatorWidth; 20411 this.indicatorStyle.width = this.width + 'px'; 20412 } 20413 20414 if ( y < this.minBoundaryY ) { 20415 if ( this.options.shrink == 'scale' ) { 20416 this.height = Math.max(this.indicatorHeight + y * 3, 8); 20417 this.indicatorStyle.height = this.height + 'px'; 20418 } 20419 y = this.minBoundaryY; 20420 } else if ( y > this.maxBoundaryY ) { 20421 if ( this.options.shrink == 'scale' ) { 20422 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 20423 this.indicatorStyle.height = this.height + 'px'; 20424 y = this.maxPosY + this.indicatorHeight - this.height; 20425 } else { 20426 y = this.maxBoundaryY; 20427 } 20428 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 20429 this.height = this.indicatorHeight; 20430 this.indicatorStyle.height = this.height + 'px'; 20431 } 20432 } 20433 20434 this.x = x; 20435 this.y = y; 20436 20437 if ( this.scroller.options.useTransform ) { 20438 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 20439 } else { 20440 this.indicatorStyle.left = x + 'px'; 20441 this.indicatorStyle.top = y + 'px'; 20442 } 20443 }, 20444 20445 _pos: function (x, y) { 20446 if ( x < 0 ) { 20447 x = 0; 20448 } else if ( x > this.maxPosX ) { 20449 x = this.maxPosX; 20450 } 20451 20452 if ( y < 0 ) { 20453 y = 0; 20454 } else if ( y > this.maxPosY ) { 20455 y = this.maxPosY;
20456 } 20457 20458 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 20459 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 20460 20461 this.scroller.scrollTo(x, y); 20462 }, 20463 20464 fade: function (val, hold) { 20465 if ( hold && !this.visible ) { 20466 return; 20467 } 20468 20469 clearTimeout(this.fadeTimeout); 20470 this.fadeTimeout = null; 20471 20472 var time = val ? 250 : 500, 20473 delay = val ? 0 : 300; 20474 20475 val = val ? '1' : '0'; 20476 20477 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 20478 20479 this.fadeTimeout = setTimeout((function (val) { 20480 this.wrapperStyle.opacity = val; 20481 this.visible = +val; 20482 }).bind(this, val), delay); 20483 } 20484}; 20485 20486IScroll.utils = utils; 20487 20488if ( typeof module != 'undefined' && module.exports ) { 20489 module.exports = IScroll; 20490} else if ( typeof define == 'function' && define.amd ) { 20491 define( function () { return IScroll; } ); 20492} else { 20493 window.IScroll = IScroll; 20494} 20495 20496})(window, document, Math); 20497/*! 20498 * fullPage 2.9.4 20499 * https://github.com/alvarotrigo/fullPage.js 20500 * @license MIT licensed 20501 * 20502 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 20503 */ 20504(function(global, factory) { 20505 'use strict'; 20506 if (typeof define === 'function' && define.amd) { 20507 define(['jquery'], function($) { 20508 return factory($, global, global.document, global.Math); 20509 }); 20510 } else if (typeof exports === "object" && exports) { 20511 module.exports = factory(require('jquery'), global, global.document, global.Math); 20512 } else { 20513 factory(jQuery, global, global.document, global.Math); 20514 } 20515})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 20516 'use strict'; 20517 20518 // keeping central set of classnames and selectors 20519 var WRAPPER = 'fullpage-wrapper'; 20520 var WRAPPER_SEL = '.' + WRAPPER; 20521 20522 // slimscroll 20523 var SCROLLABLE = 'fp-scrollable'; 20524 var SCROLLABLE_SEL = '.' + SCROLLABLE; 20525 20526 // util 20527 var RESPONSIVE = 'fp-responsive'; 20528 var NO_TRANSITION = 'fp-notransition'; 20529 var DESTROYED = 'fp-destroyed'; 20530 var ENABLED = 'fp-enabled'; 20531 var VIEWING_PREFIX = 'fp-viewing'; 20532 var ACTIVE = 'active'; 20533 var ACTIVE_SEL = '.' + ACTIVE; 20534 var COMPLETELY = 'fp-completely'; 20535 var COMPLETELY_SEL = '.' + COMPLETELY; 20536 20537 // section 20538 var SECTION_DEFAULT_SEL = '.section'; 20539 var SECTION = 'fp-section'; 20540 var SECTION_SEL = '.' + SECTION; 20541 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 20542 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 20543 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 20544 var TABLE_CELL = 'fp-tableCell'; 20545 var TABLE_CELL_SEL = '.' + TABLE_CELL; 20546 var AUTO_HEIGHT = 'fp-auto-height'; 20547 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 20548 var NORMAL_SCROLL = 'fp-normal-scroll'; 20549 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 20550 20551 // section nav 20552 var SECTION_NAV = 'fp-nav'; 20553 var SECTION_NAV_SEL = '#' + SECTION_NAV; 20554 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 20555 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 20556 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 20557 20558 // slide 20559 var SLIDE_DEFAULT_SEL = '.slide'; 20560 var SLIDE = 'fp-slide'; 20561 var SLIDE_SEL = '.' + SLIDE; 20562 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 20563 var SLIDES_WRAPPER = 'fp-slides'; 20564 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 20565 var SLIDES_CONTAINER = 'fp-slidesContainer'; 20566 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 20567 var TABLE = 'fp-table'; 20568 20569 // slide nav 20570 var SLIDES_NAV = 'fp-slidesNav'; 20571 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 20572 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 20573 var SLIDES_ARROW = 'fp-controlArrow'; 20574 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 20575 var SLIDES_PREV = 'fp-prev'; 20576 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 20577 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 20578 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 20579 var SLIDES_NEXT = 'fp-next';
20580 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 20581 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 20582 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 20583 20584 var $window = $(window); 20585 var $document = $(document); 20586 20587 // Default options for iScroll.js used when using scrollOverflow 20588 var iscrollOptions = { 20589 scrollbars: true, 20590 mouseWheel: true, 20591 hideScrollbars: false, 20592 fadeScrollbars: false, 20593 disableMouse: true, 20594 interactiveScrollbars: true, 20595 bounce: false, 20596 }; 20597 20598 $.fn.fullpage = function(options) { 20599 //only once my friend! 20600 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 20601 20602 // common jQuery objects 20603 var $htmlBody = $('html, body'); 20604 var $body = $('body'); 20605 20606 var FP = $.fn.fullpage; 20607 20608 // Creating some defaults, extending them with any options that were provided 20609 options = $.extend({ 20610 //navigation 20611 menu: false, 20612 anchors:[], 20613 lockAnchors: false, 20614 navigation: false, 20615 navigationPosition: 'right', 20616 navigationTooltips: [], 20617 showActiveTooltip: false, 20618 slidesNavigation: false, 20619 slidesNavPosition: 'bottom', 20620 scrollBar: false, 20621 hybrid: false, 20622 20623 //scrolling 20624 css3: true, 20625 scrollingSpeed: 700, 20626 autoScrolling: true, 20627 fitToSection: true, 20628 fitToSectionDelay: 1000, 20629 easing: 'easeInOutCubic', 20630 easingcss3: 'ease', 20631 loopBottom: false, 20632 loopTop: false, 20633 loopHorizontal: true, 20634 continuousVertical: false, 20635 continuousHorizontal: false, 20636 scrollHorizontally: false, 20637 interlockedSlides: false, 20638 dragAndMove: false, 20639 offsetSections: false, 20640 resetSliders: false, 20641 fadingEffect: false, 20642 normalScrollElements: null, 20643 scrollOverflow: false, 20644 scrollOverflowReset: false, 20645 scrollOverflowHandler: iscrollHandler, 20646 scrollOverflowOptions: null, 20647 touchSensitivity: 5, 20648 normalScrollElementTouchThreshold: 5, 20649 bigSectionsDestination: null, 20650 20651 //Accessibility 20652 keyboardScrolling: true, 20653 animateAnchor: true, 20654 recordHistory: true, 20655 20656 //design 20657 controlArrows: true, 20658 controlArrowColor: '#fff', 20659 verticalCentered: true, 20660 sectionsColor : [], 20661 paddingTop: 0, 20662 paddingBottom: 0, 20663 fixedElements: null, 20664 responsive: 0, //backwards compabitility with responsiveWiddth 20665 responsiveWidth: 0, 20666 responsiveHeight: 0, 20667 responsiveSlides: false, 20668 parallax: false, 20669 parallaxOptions: { 20670 type: 'reveal', 20671 percentage: 62, 20672 property: 'translate' 20673 }, 20674 20675 //Custom selectors 20676 sectionSelector: SECTION_DEFAULT_SEL, 20677 slideSelector: SLIDE_DEFAULT_SEL, 20678 20679 //events 20680 afterLoad: null, 20681 onLeave: null, 20682 afterRender: null, 20683 afterResize: null, 20684 afterReBuild: null, 20685 afterSlideLoad: null, 20686 onSlideLeave: null, 20687 afterResponsive: null, 20688 20689 lazyLoading: true 20690 }, options); 20691 20692 //flag to avoid very fast sliding for landscape sliders 20693 var slideMoving = false; 20694 20695 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 20696 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 20697 var container = $(this); 20698 var windowsHeight = $window.height(); 20699 var isResizing = false; 20700 var isWindowFocused = true; 20701 var lastScrolledDestiny; 20702 var lastScrolledSlide; 20703 var canScroll = true; 20704 var scrollings = []; 20705 var controlPressed; 20706 var startingSection; 20707 var isScrollAllowed = {}; 20708 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 20709 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 20710 var MSPointer = getMSPointer(); 20711 var events = { 20712 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 20713 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 20714 }; 20715 20716 //cheks for passive event support 20717 //added by Uncode from new fullPage updates 20718 var g_supportsPassive = false;
20719 try { 20720 var opts = Object.defineProperty({}, 'passive', { 20721 get: function() { 20722 g_supportsPassive = true; 20723 } 20724 }); 20725 window.addEventListener("testPassive", null, opts); 20726 window.removeEventListener("testPassive", null, opts); 20727 } catch (e) {} 20728 20729 //timeouts 20730 var resizeId; 20731 var afterSectionLoadsId; 20732 var afterSlideLoadsId; 20733 var scrollId; 20734 var scrollId2; 20735 var keydownId; 20736 var originals = $.extend(true, {}, options); //deep copy 20737 20738 //Uncode addition 20739 var $masthead = $('#masthead'); 20740 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 20741 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 20742 var bodyBorder = UNCODE.bodyBorder; 20743 var adminBarHeight = UNCODE.adminBarHeight; 20744 20745 displayWarnings(); 20746 20747 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 20748 iscrollOptions.click = isTouch; // see #2035 20749 20750 //extending iScroll options with the user custom ones 20751 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 20752 20753 //easeInOutCubic animation included in the plugin 20754 $.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;}}); 20755 20756 /** 20757 * Sets the autoScroll option. 20758 * It changes the scroll bar visibility and the history of the site as a result. 20759 */ 20760 function setAutoScrolling(value, type){ 20761 //removing the transformation 20762 if(!value){ 20763 silentScroll(0); 20764 } 20765 20766 setVariableState('autoScrolling', value, type); 20767 20768 var element = $(SECTION_ACTIVE_SEL); 20769 20770 if(options.autoScrolling && !options.scrollBar){ 20771 $htmlBody.css({ 20772 'overflow' : 'hidden !important', 20773 'height' : '100%' 20774 }); 20775 20776 //Uncode addition 20777 //setRecordHistory(originals.recordHistory, 'internal'); 20778 20779 //for IE touch devices 20780 container.css({ 20781 '-ms-touch-action': 'none', 20782 'touch-action': 'none' 20783 }); 20784 20785 if(element.length){ 20786 //moving the container up 20787 silentScroll(element.position().top); 20788 } 20789 20790 }else{ 20791 $htmlBody.css({ 20792 'overflow' : 'visible !important', 20793 'height' : 'initial' 20794 }); 20795 20796 //Uncode addition 20797 //setRecordHistory(false, 'internal'); 20798 20799 //for IE touch devices 20800 container.css({ 20801 '-ms-touch-action': '', 20802 'touch-action': '' 20803 }); 20804 20805 //scrolling the page to the section with no animation 20806 if (element.length) { 20807 $htmlBody.scrollTop(element.position().top); 20808 } 20809 } 20810 } 20811 20812 /** 20813 * Defines wheter to record the history for each hash change in the URL. 20814 */ 20815 function setRecordHistory(value, type){ 20816 setVariableState('recordHistory', value, type); 20817 } 20818 20819 /** 20820 * Defines the scrolling speed 20821 */ 20822 function setScrollingSpeed(value, type){ 20823 setVariableState('scrollingSpeed', value, type); 20824 } 20825 20826 /** 20827 * Sets fitToSection 20828 */ 20829 function setFitToSection(value, type){ 20830 setVariableState('fitToSection', value, type); 20831 } 20832 20833 /** 20834 * Sets lockAnchors 20835 */ 20836 function setLockAnchors(value){ 20837 options.lockAnchors = value; 20838 } 20839 20840 /** 20841 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 20842 */ 20843 function setMouseWheelScrolling(value){ 20844 if(value){ 20845 addMouseWheelHandler(); 20846 addMiddleWheelHandler(); 20847 }else{ 20848 removeMouseWheelHandler(); 20849 removeMiddleWheelHandler(); 20850 } 20851 } 20852 20853 /** 20854 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 20855 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 20856 * 20857 * @param directions string containing the direction or directions separated by comma. 20858 */ 20859 function setAllowScrolling(value, directions){ 20860 if(typeof directions !== 'undefined'){ 20861 directions = directions.replace(/ /g,'').split(','); 20862 20863 $.each(directions, function (index, direction){ 20864 setIsScrollAllowed(value, direction, 'm'); 20865 }); 20866 } 20867 else if(value){ 20868 setMouseWheelScrolling(true); 20869 addTouchHandler(); 20870 }else{ 20871 setMouseWheelScrolling(false); 20872 removeTouchHandler(); 20873 } 20874 } 20875 20876 /** 20877 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 20878 */ 20879 function setKeyboardScrolling(value, directions){ 20880 if(typeof directions !== 'undefined'){ 20881 directions = directions.replace(/ /g,'').split(','); 20882 20883 $.each(directions, function (index, direction){ 20884 setIsScrollAllowed(value, direction, 'k'); 20885 }); 20886 }else{ 20887 options.keyboardScrolling = value; 20888 } 20889 } 20890 20891 /** 20892 * Moves the page up one section. 20893 */ 20894 function moveSectionUp(){ 20895 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 20896 20897 //looping to the bottom if there's no more sections above 20898 if (!prev.length && (options.loopTop || options.continuousVertical)) {
20899 prev = $(SECTION_SEL).last(); 20900 } 20901 20902 if (prev.length) { 20903 scrollPage(prev, null, true); 20904 } 20905 } 20906 20907 /** 20908 * Moves the page down one section. 20909 */ 20910 function moveSectionDown(){ 20911 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 20912 20913 //looping to the top if there's no more sections below 20914 if(!next.length && 20915 (options.loopBottom || options.continuousVertical)){ 20916 next = $(SECTION_SEL).first(); 20917 } 20918 20919 if(next.length){ 20920 scrollPage(next, null, false); 20921 } 20922 } 20923 20924 /** 20925 * Moves the page to the given section and slide with no animation. 20926 * Anchors or index positions can be used as params. 20927 */ 20928 function silentMoveTo(sectionAnchor, slideAnchor){ 20929 setScrollingSpeed (0, 'internal'); 20930 moveTo(sectionAnchor, slideAnchor); 20931 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 20932 } 20933 20934 /** 20935 * Moves the page to the given section and slide. 20936 * Anchors or index positions can be used as params. 20937 */ 20938 function moveTo(sectionAnchor, slideAnchor){ 20939 var destiny = getSectionByAnchor(sectionAnchor); 20940 20941 if (typeof slideAnchor !== 'undefined'){ 20942 scrollPageAndSlide(sectionAnchor, slideAnchor); 20943 }else if(destiny.length > 0){ 20944 scrollPage(destiny); 20945 } 20946 } 20947 20948 /** 20949 * Slides right the slider of the active section. 20950 * Optional `section` param. 20951 */ 20952 function moveSlideRight(section){ 20953 moveSlide('right', section); 20954 } 20955 20956 /** 20957 * Slides left the slider of the active section. 20958 * Optional `section` param. 20959 */ 20960 function moveSlideLeft(section){ 20961 moveSlide('left', section); 20962 } 20963 20964 /** 20965 * When resizing is finished, we adjust the slides sizes and positions 20966 */ 20967 function reBuild(resizing){ 20968 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 20969 20970 isResizing = true; 20971 20972 windowsHeight = $window.height(); //updating global var 20973 20974 $(SECTION_SEL).each(function(){ 20975 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 20976 var slides = $(this).find(SLIDE_SEL); 20977 20978 //adjusting the height of the table-cell for IE and Firefox 20979 if(options.verticalCentered){ 20980 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 20981 } 20982 20983 $(this).css('height', windowsHeight + 'px'); 20984 20985 //resizing the scrolling divs 20986 if(options.scrollOverflow){ 20987 if(slides.length){ 20988 slides.each(function(){ 20989 createScrollBar($(this)); 20990 }); 20991 }else{ 20992 createScrollBar($(this)); 20993 } 20994 } 20995 20996 //adjusting the position fo the FULL WIDTH slides... 20997 if (slides.length > 1) { 20998 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 20999 } 21000 }); 21001 21002 var activeSection = $(SECTION_ACTIVE_SEL); 21003 var sectionIndex = activeSection.index(SECTION_SEL); 21004 21005 //isn't it the first section? 21006 if(sectionIndex){ 21007 //adjusting the position for the current section 21008 silentMoveTo(sectionIndex + 1); 21009 } 21010 21011 isResizing = false; 21012 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 21013 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 21014 } 21015 21016 /** 21017 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 21018 * are smaller than the set limit values. 21019 */ 21020 function setResponsive(active){ 21021 var isResponsive = $body.hasClass(RESPONSIVE); 21022 21023 if(active){ 21024 if(!isResponsive){ 21025 setAutoScrolling(false, 'internal'); 21026 setFitToSection(false, 'internal'); 21027 $(SECTION_NAV_SEL).hide(); 21028 $body.addClass(RESPONSIVE); 21029 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 21030 } 21031 } 21032 else if(isResponsive){ 21033 setAutoScrolling(originals.autoScrolling, 'internal'); 21034 setFitToSection(originals.autoScrolling, 'internal'); 21035 $(SECTION_NAV_SEL).show(); 21036 $body.removeClass(RESPONSIVE); 21037 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 21038 } 21039 } 21040 21041 if($(this).length){ 21042 //public functions 21043 FP.setAutoScrolling = setAutoScrolling; 21044 FP.setRecordHistory = setRecordHistory; 21045 FP.setScrollingSpeed = setScrollingSpeed; 21046 FP.setFitToSection = setFitToSection; 21047 FP.setLockAnchors = setLockAnchors; 21048 FP.setMouseWheelScrolling = setMouseWheelScrolling; 21049 FP.setAllowScrolling = setAllowScrolling; 21050 FP.setKeyboardScrolling = setKeyboardScrolling; 21051 FP.moveSectionUp = moveSectionUp; 21052 FP.moveSectionDown = moveSectionDown; 21053 FP.silentMoveTo = silentMoveTo; 21054 FP.moveTo = moveTo; 21055 FP.moveSlideRight = moveSlideRight; 21056 FP.moveSlideLeft = moveSlideLeft; 21057 FP.fitToSection = fitToSection; 21058 FP.reBuild = reBuild; 21059 FP.setResponsive = setResponsive; 21060 FP.destroy = destroy; 21061 21062 init(); 21063 21064 bindEvents(); 21065 } 21066
21067 function init(){ 21068 //if css3 is not supported, it will use jQuery animations 21069 if(options.css3){ 21070 options.css3 = support3d(); 21071 } 21072 21073 options.scrollBar = options.scrollBar || options.hybrid; 21074 21075 setOptionsFromDOM(); 21076 prepareDom(); 21077 setAllowScrolling(true); 21078 setAutoScrolling(options.autoScrolling, 'internal'); 21079 responsive(); 21080 21081 //setting the class for the body element 21082 setBodyClass(); 21083 21084 //Uncode addition 21085 // if(document.readyState === 'complete'){ 21086 // scrollToAnchor(); 21087 // } 21088 // $window.on('load', scrollToAnchor); 21089 } 21090 21091 function bindEvents(){ 21092 $window 21093 //when scrolling... 21094 //.on('scroll', scrollHandler) 21095 21096 //detecting any change on the URL to scroll to the given anchor link 21097 //(a way to detect back history button as we play with the hashes on the URL) 21098 .on('hashchange', hashChangeHandler) 21099 21100 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 21101 .blur(blurHandler) 21102 21103 //when resizing the site, we adjust the heights of the sections, slimScroll... 21104 .resize(resizeHandler); 21105 21106 $document 21107 //Sliding with arrow keys, both, vertical and horizontal 21108 .keydown(keydownHandler) 21109 21110 //to prevent scrolling while zooming 21111 .keyup(keyUpHandler) 21112 21113 //Scrolls to the section when clicking the navigation bullet 21114 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 21115 21116 //Scrolls the slider to the given slide destination for the given section 21117 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 21118 21119 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 21120 21121 //Scrolling horizontally when clicking on the slider controls. 21122 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 21123 21124 /** 21125 * Applying normalScroll elements. 21126 * Ignoring the scrolls over the specified selectors. 21127 */ 21128 if(options.normalScrollElements){ 21129 $document.on('mouseenter', options.normalScrollElements, function () { 21130 setMouseWheelScrolling(false); 21131 }); 21132 21133 $document.on('mouseleave', options.normalScrollElements, function(){ 21134 setMouseWheelScrolling(true); 21135 }); 21136 } 21137 } 21138 21139 /** 21140 * Setting options from DOM elements if they are not provided. 21141 */ 21142 function setOptionsFromDOM(){ 21143 var sections = container.find(options.sectionSelector); 21144 21145 //no anchors option? Checking for them in the DOM attributes 21146 if(!options.anchors.length){ 21147 options.anchors = sections.filter('[data-anchor]').map(function(){ 21148 return $(this).data('anchor').toString(); 21149 }).get(); 21150 } 21151 21152 //no tooltips option? Checking for them in the DOM attributes 21153 if(!options.navigationTooltips.length){ 21154 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 21155 return $(this).data('tooltip').toString(); 21156 }).get(); 21157 } 21158 } 21159 21160 /** 21161 * Works over the DOM structure to set it up for the current fullpage options. 21162 */ 21163 function prepareDom(){ 21164 container.css({ 21165 'height': '100%', 21166 'position': 'relative' 21167 }); 21168 21169 //adding a class to recognize the container internally in the code 21170 container.addClass(WRAPPER); 21171 $('html').addClass(ENABLED); 21172 21173 windowsHeight = $window.height(); 21174 21175 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 21176 21177 addInternalSelectors(); 21178 21179 //styling the sections / slides / menu 21180 $(SECTION_SEL).each(function(index){ 21181 var section = $(this); 21182 var slides = section.find(SLIDE_SEL); 21183 var numSlides = slides.length; 21184 21185 styleSection(section, index); 21186 styleMenu(section, index); 21187 21188 // if there's any slide 21189 if (numSlides > 0) { 21190 styleSlides(section, slides, numSlides); 21191 }else{ 21192 if(options.verticalCentered){ 21193 addTableClass(section); 21194 } 21195 } 21196 }); 21197 21198 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 21199 if(options.fixedElements && options.css3){ 21200 $(options.fixedElements).appendTo($body); 21201 } 21202 21203 //vertical centered of the navigation + active bullet 21204 if(options.navigation){ 21205 addVerticalNavigation(); 21206 } 21207 21208 enableYoutubeAPI(); 21209 21210 if(options.scrollOverflow){ 21211 if(document.readyState === 'complete'){ 21212 createScrollBarHandler(); 21213 } 21214 //after DOM and images are loaded 21215 $window.on('load', createScrollBarHandler); 21216 }else{ 21217 afterRenderActions(); 21218 } 21219 } 21220 21221 /** 21222 * Styles the horizontal slides for a section. 21223 */ 21224 function styleSlides(section, slides, numSlides){ 21225 var sliderWidth = numSlides * 100; 21226 var slideWidth = 100 / numSlides; 21227 21228 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 21229 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 21230 21231 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 21232 21233 if(numSlides > 1){ 21234 if(options.controlArrows){ 21235 createSlideArrows(section); 21236 } 21237 21238 if(options.slidesNavigation){ 21239 addSlidesNavigation(section, numSlides); 21240 } 21241 } 21242 21243 slides.each(function(index) { 21244 $(this).css('width', slideWidth + '%'); 21245 21246 if(options.verticalCentered){ 21247 addTableClass($(this)); 21248 } 21249 }); 21250 21251 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 21252 21253 //if the slide won't be an starting point, the default will be the first one 21254 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
21254ide by default. 21255 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 21256 silentLandscapeScroll(startingSlide, 'internal'); 21257 }else{ 21258 slides.eq(0).addClass(ACTIVE); 21259 } 21260 } 21261 21262 /** 21263 * Styling vertical sections 21264 */ 21265 function styleSection(section, index){ 21266 //if no active section is defined, the 1st one will be the default one 21267 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 21268 section.addClass(ACTIVE); 21269 } 21270 startingSection = $(SECTION_ACTIVE_SEL); 21271 21272 section.css('height', windowsHeight + 'px'); 21273 21274 if(options.paddingTop){ 21275 section.css('padding-top', options.paddingTop); 21276 } 21277 21278 if(options.paddingBottom){ 21279 section.css('padding-bottom', options.paddingBottom); 21280 } 21281 21282 if (typeof options.sectionsColor[index] !== 'undefined') { 21283 section.css('background-color', options.sectionsColor[index]); 21284 } 21285 21286 if (typeof options.anchors[index] !== 'undefined') { 21287 section.attr('data-anchor', options.anchors[index]); 21288 } 21289 } 21290 21291 /** 21292 * Sets the data-anchor attributes to the menu elements and activates the current one. 21293 */ 21294 function styleMenu(section, index){ 21295 if (typeof options.anchors[index] !== 'undefined') { 21296 //activating the menu / nav element on load 21297 if(section.hasClass(ACTIVE)){ 21298 activateMenuAndNav(options.anchors[index], index); 21299 } 21300 } 21301 21302 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 21303 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 21304 $(options.menu).appendTo($body); 21305 } 21306 } 21307 21308 /** 21309 * Adds internal classes to be able to provide customizable selectors 21310 * keeping the link with the style sheet. 21311 */ 21312 function addInternalSelectors(){ 21313 container.find(options.sectionSelector).addClass(SECTION); 21314 container.find(options.slideSelector).addClass(SLIDE); 21315 } 21316 21317 /** 21318 * Creates the control arrows for the given section 21319 */ 21320 function createSlideArrows(section){ 21321 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 21322 21323 if(options.controlArrowColor!='#fff'){ 21324 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 21325 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 21326 } 21327 21328 if(!options.loopHorizontal){ 21329 section.find(SLIDES_ARROW_PREV_SEL).hide(); 21330 } 21331 } 21332 21333 /** 21334 * Creates a vertical navigation bar. 21335 */ 21336 function addVerticalNavigation(){ 21337 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 21338 var nav = $(SECTION_NAV_SEL); 21339 21340 nav.addClass(function() { 21341 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 21342 }); 21343 21344 for (var i = 0; i < $(SECTION_SEL).length; i++) { 21345 var link = ''; 21346 if (options.anchors.length) { 21347 link = options.anchors[i]; 21348 } 21349 21350 var li = '<li><a href="#' + link + '"><span></span></a>'; 21351 21352 // Only add tooltip if needed (defined by user) 21353 var tooltip = options.navigationTooltips[i]; 21354 21355 if (typeof tooltip !== 'undefined' && tooltip !== '') { 21356 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 21357 } 21358 21359 li += '</li>'; 21360 21361 nav.find('ul').append(li); 21362 } 21363 21364 //centering it vertically 21365 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 21366 21367 //activating the current active section 21368 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 21369 } 21370 21371 /** 21372 * Creates the slim scroll scrollbar for the sections and slides inside them. 21373 */ 21374 function createScrollBarHandler(){ 21375 $(SECTION_SEL).each(function(){ 21376 var slides = $(this).find(SLIDE_SEL); 21377 21378 if(slides.length){ 21379 slides.each(function(){ 21380 createScrollBar($(this)); 21381 }); 21382 }else{ 21383 createScrollBar($(this)); 21384 } 21385 21386 }); 21387 afterRenderActions(); 21388 } 21389 21390 /*
21391 * Enables the Youtube videos API so we can control their flow if necessary. 21392 */ 21393 function enableYoutubeAPI(){ 21394 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 21395 addURLParam($(this), 'enablejsapi=1'); 21396 }); 21397 } 21398 21399 /** 21400 * Adds a new parameter and its value to the `src` of a given element 21401 */ 21402 function addURLParam(element, newParam){ 21403 var originalSrc = element.attr('src'); 21404 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 21405 } 21406 21407 /* 21408 * Returns the prefix sign to use for a new parameter in an existen URL. 21409 * 21410 * @return {String} ? | & 21411 */ 21412 function getUrlParamSign(url){ 21413 return ( !/\?/.test( url ) ) ? '?' : '&'; 21414 } 21415 21416 /** 21417 * Actions and callbacks to fire afterRender 21418 */ 21419 function afterRenderActions(){ 21420 var section = $(SECTION_ACTIVE_SEL); 21421 21422 section.addClass(COMPLETELY); 21423 21424 if(options.scrollOverflowHandler.afterRender){ 21425 options.scrollOverflowHandler.afterRender(section); 21426 } 21427 lazyLoad(section); 21428 playMedia(section); 21429 options.scrollOverflowHandler.afterLoad(); 21430 21431 if(isDestinyTheStartingSection()){ 21432 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 21433 } 21434 21435 $.isFunction( options.afterRender ) && options.afterRender.call(container); 21436 } 21437 21438 /** 21439 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 21440 */ 21441 function isDestinyTheStartingSection(){ 21442 var anchors = window.location.hash.replace('#', '').split('/'); 21443 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 21444 21445 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 21446 } 21447 21448 21449 var isScrolling = false; 21450 var lastScroll = 0; 21451 21452 //when scrolling... 21453 function scrollHandler(){ 21454 var currentSection; 21455 21456 if(!options.autoScrolling || options.scrollBar){ 21457 var currentScroll = $window.scrollTop(); 21458 var scrollDirection = getScrollDirection(currentScroll); 21459 var visibleSectionIndex = 0; 21460 var screen_mid = currentScroll + ($window.height() / 2.0); 21461 var isAtBottom = $body.height() - $window.height() === currentScroll; 21462 var sections = document.querySelectorAll(SECTION_SEL); 21463 21464 //when using `auto-height` for a small last section it won't be centered in the viewport 21465 if(isAtBottom){ 21466 visibleSectionIndex = sections.length - 1; 21467 } 21468 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 21469 else if(!currentScroll){ 21470 visibleSectionIndex = 0; 21471 } 21472 21473 //taking the section which is showing more content in the viewport 21474 else{ 21475 for (var i = 0; i < sections.length; ++i) { 21476 var section = sections[i]; 21477 21478 // Pick the the last section which passes the middle line of the screen. 21479 if (section.offsetTop <= screen_mid) 21480 { 21481 visibleSectionIndex = i; 21482 } 21483 } 21484 } 21485 21486 if(isCompletelyInViewPort(scrollDirection)){ 21487 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 21488 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 21489 } 21490 } 21491 21492 //geting the last one, the current one on the screen 21493 currentSection = $(sections).eq(visibleSectionIndex); 21494 21495 //setting the visible section as active when manually scrolling 21496 //executing only once the first time we reach the section 21497 if(!currentSection.hasClass(ACTIVE)){ 21498 isScrolling = true; 21499 var leavingSection = $(SECTION_ACTIVE_SEL); 21500 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 21501 var yMovement = getYmovement(currentSection); 21502 var anchorLink = currentSection.data('anchor'); 21503 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 21504 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 21505 var slideIndex; 21506 var slideAnchorLink; 21507 21508 if(activeSlide.length){ 21509 slideAnchorLink = activeSlide.data('anchor'); 21510 slideIndex = activeSlide.index(); 21511 } 21512 21513 if(canScroll){ 21514 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 21515 21516 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 21517 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 21518 21519 stopMedia(leavingSection); 21520 lazyLoad(currentSection); 21521 playMedia(currentSection); 21522 21523 activateMenuAndNav(anchorLink, sectionIndex - 1); 21524 21525 if(options.anchors.length){ 21526 //needed to enter in hashChange event when using the menu with anchor links 21527 lastScrolledDestiny = anchorLink; 21528 } 21529 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 21530 } 21531 21532 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 21533 clearTimeout(scrollId); 21534 scrollId = setTimeout(function(){ 21535 isScrolling = false;
21536 }, 100); 21537 } 21538 21539 if(options.fitToSection){ 21540 //for the auto adjust of the viewport to fit a whole section 21541 clearTimeout(scrollId2); 21542 21543 scrollId2 = setTimeout(function(){ 21544 //checking it again in case it changed during the delay 21545 if(options.fitToSection){ 21546 fitToSection(); 21547 } 21548 }, options.fitToSectionDelay); 21549 } 21550 } 21551 } 21552 21553 /** 21554 * Fits the site to the nearest active section 21555 */ 21556 function fitToSection(){ 21557 //checking fitToSection again in case it was set to false before the timeout delay 21558 if(canScroll){ 21559 //allows to scroll to an active section and 21560 //if the section is already active, we prevent firing callbacks 21561 isResizing = true; 21562 21563 scrollPage($(SECTION_ACTIVE_SEL)); 21564 isResizing = false; 21565 } 21566 } 21567 21568 /** 21569 * Determines whether the active section has seen in its whole or not. 21570 */ 21571 function isCompletelyInViewPort(movement){ 21572 var top = $(SECTION_ACTIVE_SEL).position().top; 21573 var bottom = top + $window.height(); 21574 21575 if(movement == 'up'){ 21576 return bottom >= ($window.scrollTop() + $window.height()); 21577 } 21578 return top <= $window.scrollTop(); 21579 } 21580 21581 /** 21582 * Gets the directon of the the scrolling fired by the scroll event. 21583 */ 21584 function getScrollDirection(currentScroll){ 21585 var direction = currentScroll > lastScroll ? 'down' : 'up'; 21586 21587 lastScroll = currentScroll; 21588 21589 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 21590 previousDestTop = currentScroll; 21591 21592 return direction; 21593 } 21594 21595 /** 21596 * Determines the way of scrolling up or down: 21597 * by 'automatically' scrolling a section or by using the default and normal scrolling. 21598 */ 21599 function scrolling(type, scrollable){ 21600 if (!isScrollAllowed.m[type]){ 21601 return; 21602 } 21603 var check = (type === 'down') ? 'bottom' : 'top'; 21604 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 21605 21606 if(scrollable.length > 0 ){ 21607 //is the scrollbar at the start/end of the scroll? 21608 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 21609 scrollSection(); 21610 }else{ 21611 return true; 21612 } 21613 }else{ 21614 // moved up/down 21615 scrollSection(); 21616 } 21617 } 21618 21619 /* 21620 * Preventing bouncing in iOS #2285 21621 */ 21622 function preventBouncing(event){ 21623 var e = event.originalEvent; 21624 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){ 21625 //preventing the easing on iOS devices 21626 event.preventDefault(); 21627 } 21628 } 21629 21630 var touchStartY = 0; 21631 var touchStartX = 0; 21632 var touchEndY = 0; 21633 var touchEndX = 0; 21634 21635 /* Detecting touch events 21636 21637 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 21638 * This way, the touchstart and the touch moves shows an small difference between them which is the 21639 * used one to determine the direction. 21640 */ 21641 function touchMoveHandler(event){ 21642 var e = event.originalEvent; 21643 var activeSection = $(e.target).closest(SECTION_SEL); 21644 21645 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 21646 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 21647 21648 if(options.autoScrolling){ 21649 //preventing the easing on iOS devices 21650 event.preventDefault(); 21651 } 21652 21653 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 21654 var touchEvents = getEventsPage(e); 21655 21656 touchEndY = touchEvents.y; 21657 touchEndX = touchEvents.x; 21658 21659 //if movement in the X axys is greater than in the Y and the currect section has slides... 21660 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 21661 21662 //is the movement greater than the minimum resistance to scroll? 21663 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 21664 if (touchStartX > touchEndX) { 21665 if(isScrollAllowed.m.right){ 21666 moveSlideRight(activeSection); //next 21667 } 21668 } else { 21669 if(isScrollAllowed.m.left){ 21670 moveSlideLeft(activeSection); //prev 21671 } 21672 } 21673 } 21674 } 21675 21676 //vertical scrolling (only when autoScrolling is enabled) 21677 else if(options.autoScrolling && canScroll){ 21678 21679 //is the movement greater than the minimum resistance to scroll? 21680 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 21681 if (touchStartY > touchEndY) { 21682 scrolling('down', scrollable); 21683 } else if (touchEndY > touchStartY) { 21684 scrolling('up', scrollable); 21685 } 21686 } 21687 } 21688 } 21689 } 21690 21691 /** 21692 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 21693 * Currently works well for iOS - Android might need some testing 21694 * @param {Element} el target element / jquery selector (in subsequent nodes) 21695 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 21696 * @return {boolean} true if there is a match to options.normalScrollElements 21697 */ 21698 function checkParentForNormalScrollElement (el, hop) { 21699 hop = hop || 0; 21700 var parent = $(el).parent(); 21701 21702 if (hop < options.normalScrollElementTouchThreshold && 21703 parent.is(options.normalScrollElements) ) { 21704 return true; 21705 } else if (hop == options.normalScrollElementTouchThreshold) { 21706 return false;
21707 } else { 21708 return checkParentForNormalScrollElement(parent, ++hop); 21709 } 21710 } 21711 21712 /** 21713 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 21714 * this way we make sure that is really a touch event what IE is detecting. 21715 */ 21716 function isReallyTouch(e){ 21717 //if is not IE || IE is detecting `touch` or `pen` 21718 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 21719 } 21720 21721 /** 21722 * Handler for the touch start event. 21723 */ 21724 function touchStartHandler(event){ 21725 var e = event.originalEvent; 21726 21727 //stopping the auto scroll to adjust to a section 21728 if(options.fitToSection){ 21729 $htmlBody.stop(); 21730 } 21731 21732 if(isReallyTouch(e)){ 21733 var touchEvents = getEventsPage(e); 21734 touchStartY = touchEvents.y; 21735 touchStartX = touchEvents.x; 21736 } 21737 } 21738 21739 /** 21740 * Gets the average of the last `number` elements of the given array. 21741 */ 21742 function getAverage(elements, number){ 21743 var sum = 0; 21744 21745 //taking `number` elements from the end to make the average, if there are not enought, 1 21746 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 21747 21748 for(var i = 0; i < lastElements.length; i++){ 21749 sum = sum + lastElements[i]; 21750 } 21751 21752 return Math.ceil(sum/number); 21753 } 21754 21755 /** 21756 * Detecting mousewheel scrolling 21757 * 21758 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 21759 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 21760 */ 21761 var prevTime = new Date().getTime(); 21762 21763 function MouseWheelHandler(e) { 21764 var curTime = new Date().getTime(); 21765 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 21766 21767 //autoscrolling and not zooming? 21768 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 21769 // cross-browser wheel delta 21770 e = e || window.event; 21771 var value = e.wheelDelta || -e.deltaY || -e.detail; 21772 var delta = Math.max(-1, Math.min(1, value)); 21773 21774 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 21775 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 21776 21777 //Limiting the array to 150 (lets not waste memory!) 21778 if(scrollings.length > 149){ 21779 scrollings.shift(); 21780 } 21781 21782 //keeping record of the previous scrollings 21783 scrollings.push(Math.abs(value)); 21784 21785 //preventing to scroll the site on mouse wheel when scrollbar is present 21786 if(options.scrollBar){ 21787 e.preventDefault ? e.preventDefault() : e.returnValue = false; 21788 } 21789 21790 var activeSection = $(SECTION_ACTIVE_SEL); 21791 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 21792 21793 //time difference between the last scroll and the current one 21794 var timeDiff = curTime-prevTime; 21795 prevTime = curTime; 21796 21797 //haven't they scrolled in a while? 21798 //(enough to be consider a different scrolling action to scroll another section) 21799 if(timeDiff > 200){ 21800 //emptying the array, we dont care about old scrollings for our averages 21801 scrollings = []; 21802 } 21803 21804 if(canScroll){ 21805 var averageEnd = getAverage(scrollings, 10); 21806 var averageMiddle = getAverage(scrollings, 70); 21807 var isAccelerating = averageEnd >= averageMiddle; 21808 21809 //to avoid double swipes... 21810 if(isAccelerating && isScrollingVertically){ 21811 //scrolling down? 21812 if (delta < 0) { 21813 scrolling('down', scrollable); 21814 21815 //scrolling up? 21816 }else { 21817 scrolling('up', scrollable); 21818 } 21819 } 21820 } 21821 21822 return false;
21823 } 21824 21825 if(options.fitToSection){ 21826 //stopping the auto scroll to adjust to a section 21827 $htmlBody.stop(); 21828 } 21829 } 21830 21831 /** 21832 * Slides a slider to the given direction. 21833 * Optional `section` param. 21834 */ 21835 function moveSlide(direction, section){ 21836 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 21837 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 21838 var numSlides = slides.find(SLIDE_SEL).length; 21839 21840 // more than one slide needed and nothing should be sliding 21841 if (!slides.length || slideMoving || numSlides < 2) { 21842 return; 21843 } 21844 21845 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 21846 var destiny = null; 21847 21848 if(direction === 'left'){ 21849 destiny = currentSlide.prev(SLIDE_SEL); 21850 }else{ 21851 destiny = currentSlide.next(SLIDE_SEL); 21852 } 21853 21854 //isn't there a next slide in the secuence? 21855 if(!destiny.length){ 21856 //respect loopHorizontal settin 21857 if (!options.loopHorizontal) return; 21858 21859 if(direction === 'left'){ 21860 destiny = currentSlide.siblings(':last'); 21861 }else{ 21862 destiny = currentSlide.siblings(':first'); 21863 } 21864 } 21865 21866 slideMoving = true; 21867 21868 landscapeScroll(slides, destiny, direction); 21869 } 21870 21871 /** 21872 * Maintains the active slides in the viewport 21873 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 21874 */ 21875 function keepSlidesPosition(){ 21876 $(SLIDE_ACTIVE_SEL).each(function(){ 21877 silentLandscapeScroll($(this), 'internal'); 21878 }); 21879 } 21880 21881 var previousDestTop = 0; 21882 /** 21883 * Returns the destination Y position based on the scrolling direction and 21884 * the height of the section. 21885 */ 21886 function getDestinationPosition(element){ 21887 var elemPosition = element.position(); 21888 21889 //top of the desination will be at the top of the viewport 21890 var position = elemPosition.top; 21891 var isScrollingDown = elemPosition.top > previousDestTop; 21892 var sectionBottom = position - windowsHeight + element.outerHeight(); 21893 var bigSectionsDestination = options.bigSectionsDestination; 21894 21895 //Uncode addition 21896 var containerH = container.outerHeight(); 21897 var containerPosition = container.offset(); 21898 21899 //########### Commented by Uncode - START ########### 21900 //is the destination element bigger than the viewport? 21901 // if(element.outerHeight() > windowsHeight){ 21902 // //scrolling up? 21903 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 21904 // position = sectionBottom; 21905 // } 21906 // } 21907 21908 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 21909 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 21910 // //The bottom of the destination will be at the bottom of the viewport 21911 // position = sectionBottom; 21912 // } 21913 //########### Commented by Uncode - END ########### 21914 21915 //Uncode addition 21916 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 21917 position += 18; 21918 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 21919 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 21920 } 21921 21922 /* 21923 Keeping record of the last scrolled position to determine the scrolling direction. 21924 No conventional methods can be used as the scroll bar might not be present 21925 AND the section might not be active if it is auto-height and didnt reach the middle 21926 of the viewport. 21927 */ 21928 previousDestTop = position; 21929 return position; 21930 } 21931 21932 /** 21933 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 21934 */ 21935 function scrollPage(element, callback, isMovementUp){ 21936 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 21937 21938 var dtop = getDestinationPosition(element); 21939 var slideAnchorLink; 21940 var slideIndex; 21941 21942 //local variables 21943 var v = { 21944 element: element, 21945 callback: callback, 21946 isMovementUp: isMovementUp, 21947 dtop: dtop, 21948 yMovement: getYmovement(element), 21949 anchorLink: element.data('anchor'), 21950 sectionIndex: element.index(SECTION_SEL), 21951 activeSlide: element.find(SLIDE_ACTIVE_SEL), 21952 activeSection: $(SECTION_ACTIVE_SEL), 21953 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 21954 21955 //caching the value of isResizing at the momment the function is called 21956 //because it will be checked later inside a setTimeout and the value might change 21957 localIsResizing: isResizing 21958 }; 21959 21960 //quiting when destination scroll is the same as the current one 21961 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 21962 21963 if(v.activeSlide.length){ 21964 slideAnchorLink = v.activeSlide.data('anchor'); 21965 slideIndex = v.activeSlide.index(); 21966 } 21967 21968 // If continuousVertical && we need to wrap around 21969 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 21970 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 21971 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 21972 21973 v = createInfiniteSections(v); 21974 } 21975 21976 //callback (onLeave) if the site is not just resizing and readjusting the slides 21977 if($.isFunction(options.onLeave) && !v.localIsResizing){ 21978 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 21979 return; 21980 } 21981 } 21982 21983 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 21984 if(!v.localIsResizing){ 21985 stopMedia(v.activeSection); 21986 } 21987 21988 options.scrollOverflowHandler.beforeLeave(); 21989 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 21990 lazyLoad(element); 21991 options.scrollOverflowHandler.onLeave(); 21992 21993 21994 //preventing from activating the MouseWheelHandler event 21995 //more than once if the page is scrolling 21996 canScroll = false;
21997 21998 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 21999 22000 performMovement(v); 22001 22002 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 22003 lastScrolledDestiny = v.anchorLink; 22004 22005 //avoid firing it twice (as it does also on scroll) 22006 activateMenuAndNav(v.anchorLink, v.sectionIndex); 22007 } 22008 22009 /** 22010 * Performs the vertical movement (by CSS3 or by jQuery) 22011 */ 22012 function performMovement(v){ 22013 // using CSS3 translate functionality 22014 if (options.css3 && options.autoScrolling && !options.scrollBar) { 22015 22016 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 22017 // that's why we round it to 0. 22018 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 22019 transformContainer(translate3d, true); 22020 22021 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 22022 //scrollingSpeed to change in case of using silentMoveTo(); 22023 if(options.scrollingSpeed){ 22024 clearTimeout(afterSectionLoadsId); 22025 afterSectionLoadsId = setTimeout(function () { 22026 afterSectionLoads(v); 22027 }, options.scrollingSpeed); 22028 }else{ 22029 afterSectionLoads(v); 22030 } 22031 } 22032 22033 // using jQuery animate 22034 else{ 22035 var scrollSettings = getScrollSettings(v); 22036 22037 $(scrollSettings.element).animate( 22038 scrollSettings.options, 22039 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 22040 if(options.scrollBar){ 22041 22042 /* Hack! 22043 The timeout prevents setting the most dominant section in the viewport as "active" when the user 22044 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 22045 22046 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 22047 */ 22048 setTimeout(function(){ 22049 afterSectionLoads(v); 22050 },30); 22051 }else{ 22052 afterSectionLoads(v); 22053 } 22054 }); 22055 } 22056 } 22057 22058 /** 22059 * Gets the scrolling settings depending on the plugin autoScrolling option 22060 */ 22061 function getScrollSettings(v){ 22062 var scroll = {}; 22063 22064 if(options.autoScrolling && !options.scrollBar){ 22065 scroll.options = { 'top': -v.dtop}; 22066 scroll.element = WRAPPER_SEL; 22067 }else{ 22068 scroll.options = { 'scrollTop': v.dtop}; 22069 scroll.element = 'html, body'; 22070 } 22071 22072 return scroll; 22073 } 22074 22075 /** 22076 * Adds sections before or after the current one to create the infinite effect. 22077 */ 22078 function createInfiniteSections(v){ 22079 // Scrolling down 22080 if (!v.isMovementUp) { 22081 // Move all previous sections to after the active section 22082 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 22083 } 22084 else { // Scrolling up 22085 // Move all next sections to before the active section 22086 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 22087 } 22088 22089 // Maintain the displayed position (now that we changed the element order) 22090 silentScroll($(SECTION_ACTIVE_SEL).position().top); 22091 22092 // Maintain the active slides visible in the viewport 22093 keepSlidesPosition(); 22094 22095 // save for later the elements that still need to be reordered 22096 v.wrapAroundElements = v.activeSection; 22097 22098 // Recalculate animation variables 22099 v.dtop = v.element.position().top; 22100 v.yMovement = getYmovement(v.element); 22101 22102 return v; 22103 } 22104 22105 /** 22106 * Fix section order after continuousVertical changes have been animated 22107 */ 22108 function continuousVerticalFixSectionOrder (v) {
22109 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 22110 // finish moving the elements around so the direct navigation will function more simply 22111 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 22112 return; 22113 } 22114 22115 if (v.isMovementUp) { 22116 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 22117 } 22118 else { 22119 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 22120 } 22121 22122 silentScroll($(SECTION_ACTIVE_SEL).position().top); 22123 22124 // Maintain the active slides visible in the viewport 22125 keepSlidesPosition(); 22126 } 22127 22128 22129 /** 22130 * Actions to do once the section is loaded. 22131 */ 22132 function afterSectionLoads (v){ 22133 continuousVerticalFixSectionOrder(v); 22134 22135 //callback (afterLoad) if the site is not just resizing and readjusting the slides 22136 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 22137 options.scrollOverflowHandler.afterLoad(); 22138 22139 if(!v.localIsResizing){ 22140 playMedia(v.element); 22141 } 22142 22143 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 22144 22145 canScroll = true; 22146 22147 $.isFunction(v.callback) && v.callback.call(this); 22148 } 22149 22150 /** 22151 * Sets the value for the given attribute from the `data-` attribute with the same suffix 22152 * ie: data-srcset ==> srcset | data-src ==> src 22153 */ 22154 function setSrc(element, attribute){ 22155 element 22156 .attr(attribute, element.data(attribute)) 22157 .removeAttr('data-' + attribute); 22158 } 22159 22160 /** 22161 * Lazy loads image, video and audio elements. 22162 */ 22163 function lazyLoad(destiny){ 22164 if (!options.lazyLoading){ 22165 return; 22166 } 22167 22168 var panel = getSlideOrSection(destiny); 22169 var element; 22170 22171 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 22172 element = $(this); 22173 22174 $.each(['src', 'srcset'], function(index, type){ 22175 var attribute = element.attr('data-' + type); 22176 if(typeof attribute !== 'undefined' && attribute){ 22177 setSrc(element, type); 22178 } 22179 }); 22180 22181 if(element.is('source')){ 22182 element.closest('video').get(0).load(); 22183 } 22184 }); 22185 } 22186 22187 /** 22188 * Plays video and audio elements. 22189 */ 22190 function playMedia(destiny){ 22191 var panel = getSlideOrSection(destiny); 22192 22193 //playing HTML5 media elements 22194 panel.find('video, audio').each(function(){ 22195 var element = $(this).get(0); 22196 22197 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 22198 element.play(); 22199 } 22200 }); 22201 22202 //youtube videos 22203 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 22204 var element = $(this).get(0); 22205 22206 if ( element.hasAttribute('data-autoplay') ){ 22207 playYoutube(element); 22208 } 22209 22210 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 22211 element.onload = function() { 22212 if ( element.hasAttribute('data-autoplay') ){ 22213 playYoutube(element); 22214 } 22215 }; 22216 }); 22217 } 22218 22219 /** 22220 * Plays a youtube video 22221 */ 22222 function playYoutube(element){ 22223 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 22224 } 22225 22226 /** 22227 * Stops video and audio elements. 22228 */ 22229 function stopMedia(destiny){ 22230 var panel = getSlideOrSection(destiny); 22231 22232 //stopping HTML5 media elements 22233 panel.find('video, audio').each(function(){ 22234 var element = $(this).get(0); 22235 22236 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 22237 element.pause(); 22238 } 22239 }); 22240 22241 //youtube videos 22242 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 22243 var element = $(this).get(0); 22244 22245 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 22246 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 22247 } 22248 }); 22249 } 22250 22251 /** 22252 * Gets the active slide (or section) for the given section 22253 */ 22254 function getSlideOrSection(destiny){ 22255 var slide = destiny.find(SLIDE_ACTIVE_SEL); 22256 if( slide.length ) { 22257 destiny = $(slide); 22258 } 22259 22260 return destiny; 22261 } 22262 22263 /**
22264 * Scrolls to the anchor in the URL when loading the site 22265 */ 22266 function scrollToAnchor(){ 22267 //getting the anchor link in the URL and deleting the `#` 22268 var value = window.location.hash.replace('#', '').split('/'); 22269 var sectionAnchor = decodeURIComponent(value[0]); 22270 var slideAnchor = decodeURIComponent(value[1]); 22271 22272 if(sectionAnchor){ //if theres any # 22273 if(options.animateAnchor){ 22274 scrollPageAndSlide(sectionAnchor, slideAnchor); 22275 }else{ 22276 silentMoveTo(sectionAnchor, slideAnchor); 22277 } 22278 } 22279 } 22280 22281 /** 22282 * Detecting any change on the URL to scroll to the given anchor link 22283 * (a way to detect back history button as we play with the hashes on the URL) 22284 */ 22285 function hashChangeHandler(){ 22286 if(!isScrolling && !options.lockAnchors){ 22287 var value = window.location.hash.replace('#', '').split('/'); 22288 var sectionAnchor = decodeURIComponent(value[0]); 22289 var slideAnchor = decodeURIComponent(value[1]); 22290 22291 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 22292 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 22293 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 22294 22295 22296 if(sectionAnchor.length){ 22297 /*in order to call scrollpage() only once for each destination at a time 22298 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 22299 event is fired on every scroll too.*/ 22300 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 22301 scrollPageAndSlide(sectionAnchor, slideAnchor); 22302 } 22303 } 22304 } 22305 } 22306 22307 //Sliding with arrow keys, both, vertical and horizontal 22308 function keydownHandler(e) { 22309 22310 clearTimeout(keydownId); 22311 22312 var activeElement = $(':focus'); 22313 22314 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 22315 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 22316 options.keyboardScrolling && options.autoScrolling){ 22317 var keyCode = e.which; 22318 22319 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 22320 var keyControls = [40, 38, 32, 33, 34]; 22321 if($.inArray(keyCode, keyControls) > -1){ 22322 e.preventDefault(); 22323 } 22324 22325 controlPressed = e.ctrlKey; 22326 22327 keydownId = setTimeout(function(){ 22328 onkeydown(e); 22329 },150); 22330 } 22331 } 22332 22333 function tooltipTextHandler(){ 22334 $(this).prev().trigger('click'); 22335 } 22336 22337 //to prevent scrolling while zooming 22338 function keyUpHandler(e){ 22339 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 22340 controlPressed = e.ctrlKey; 22341 } 22342 } 22343 22344 //binding the mousemove when the mouse's middle button is released 22345 function mouseDownHandler(e){ 22346 //middle button 22347 if (e.which == 2){ 22348 oldPageY = e.pageY; 22349 container.on('mousemove', mouseMoveHandler); 22350 } 22351 } 22352 22353 //unbinding the mousemove when the mouse's middle button is released 22354 function mouseUpHandler(e){ 22355 //middle button 22356 if (e.which == 2){ 22357 container.off('mousemove'); 22358 } 22359 } 22360 22361 //Scrolling horizontally when clicking on the slider controls. 22362 function slideArrowHandler(){ 22363 var section = $(this).closest(SECTION_SEL); 22364 22365 if ($(this).hasClass(SLIDES_PREV)) { 22366 if(isScrollAllowed.m.left){ 22367 moveSlideLeft(section); 22368 } 22369 } else { 22370 if(isScrollAllowed.m.right){ 22371 moveSlideRight(section); 22372 } 22373 } 22374 } 22375 22376 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 22377 function blurHandler(){ 22378 isWindowFocused = false;
22379 controlPressed = false; 22380 } 22381 22382 //Scrolls to the section when clicking the navigation bullet 22383 function sectionBulletHandler(e){ 22384 e.preventDefault(); 22385 var index = $(this).parent().index(); 22386 scrollPage($(SECTION_SEL).eq(index)); 22387 } 22388 22389 //Scrolls the slider to the given slide destination for the given section 22390 function slideBulletHandler(e){ 22391 e.preventDefault(); 22392 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 22393 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 22394 22395 landscapeScroll(slides, destiny); 22396 } 22397 22398 /** 22399 * Keydown event 22400 */ 22401 function onkeydown(e){ 22402 var shiftPressed = e.shiftKey; 22403 22404 //do nothing if we can not scroll or we are not using horizotnal key arrows. 22405 if(!canScroll && [37,39].indexOf(e.which) < 0){ 22406 return; 22407 } 22408 22409 switch (e.which) { 22410 //up 22411 case 38: 22412 case 33: 22413 if(isScrollAllowed.k.up){ 22414 moveSectionUp(); 22415 } 22416 break; 22417 22418 //down 22419 case 32: //spacebar 22420 if(shiftPressed && isScrollAllowed.k.up){ 22421 moveSectionUp(); 22422 break; 22423 } 22424 /* falls through */ 22425 case 40: 22426 case 34: 22427 if(isScrollAllowed.k.down){ 22428 moveSectionDown(); 22429 } 22430 break; 22431 22432 //Home 22433 case 36: 22434 if(isScrollAllowed.k.up){ 22435 moveTo(1); 22436 } 22437 break; 22438 22439 //End 22440 case 35: 22441 if(isScrollAllowed.k.down){ 22442 moveTo( $(SECTION_SEL).length ); 22443 } 22444 break; 22445 22446 //left 22447 case 37: 22448 if(isScrollAllowed.k.left){ 22449 moveSlideLeft(); 22450 } 22451 break; 22452 22453 //right 22454 case 39: 22455 if(isScrollAllowed.k.right){ 22456 moveSlideRight(); 22457 } 22458 break; 22459 22460 default: 22461 return; // exit this handler for other keys 22462 } 22463 } 22464 22465 /** 22466 * Detecting the direction of the mouse movement. 22467 * Used only for the middle button of the mouse. 22468 */ 22469 var oldPageY = 0; 22470 function mouseMoveHandler(e){ 22471 if(canScroll){ 22472 // moving up 22473 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 22474 moveSectionUp(); 22475 } 22476 22477 // moving down 22478 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 22479 moveSectionDown(); 22480 } 22481 } 22482 oldPageY = e.pageY; 22483 } 22484 22485 /** 22486 * Scrolls horizontal sliders. 22487 */ 22488 function landscapeScroll(slides, destiny, direction){ 22489 var section = slides.closest(SECTION_SEL); 22490 var v = { 22491 slides: slides, 22492 destiny: destiny, 22493 direction: direction, 22494 destinyPos: destiny.position(), 22495 slideIndex: destiny.index(), 22496 section: section, 22497 sectionIndex: section.index(SECTION_SEL), 22498 anchorLink: section.data('anchor'), 22499 slidesNav: section.find(SLIDES_NAV_SEL), 22500 slideAnchor: getAnchor(destiny), 22501 prevSlide: section.find(SLIDE_ACTIVE_SEL), 22502 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 22503 22504 //caching the value of isResizing at the momment the function is called 22505 //because it will be checked later inside a setTimeout and the value might change 22506 localIsResizing: isResizing 22507 }; 22508 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 22509 v.direction = v.direction ? v.direction : v.xMovement; 22510 22511 //important!! Only do it when not resizing 22512 if(!v.localIsResizing){ 22513 //preventing from scrolling to the next/prev section when using scrollHorizontally 22514 canScroll = false;
22515 } 22516 22517 if(options.onSlideLeave){ 22518 22519 //if the site is not just resizing and readjusting the slides 22520 if(!v.localIsResizing && v.xMovement!=='none'){ 22521 if($.isFunction( options.onSlideLeave )){ 22522 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 22523 slideMoving = false; 22524 return; 22525 } 22526 } 22527 } 22528 } 22529 22530 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 22531 22532 if(!v.localIsResizing){ 22533 stopMedia(v.prevSlide); 22534 lazyLoad(destiny); 22535 } 22536 22537 if(!options.loopHorizontal && options.controlArrows){ 22538 //hidding it for the fist slide, showing for the rest 22539 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 22540 22541 //hidding it for the last slide, showing for the rest 22542 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 22543 } 22544 22545 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 22546 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 22547 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 22548 } 22549 22550 performHorizontalMove(slides, v, true); 22551 } 22552 22553 22554 function afterSlideLoads(v){ 22555 activeSlidesNavigation(v.slidesNav, v.slideIndex); 22556 22557 //if the site is not just resizing and readjusting the slides 22558 if(!v.localIsResizing){ 22559 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 22560 22561 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 22562 //and to prevent double scroll right after a windows resize 22563 canScroll = true; 22564 22565 playMedia(v.destiny); 22566 } 22567 22568 //letting them slide again 22569 slideMoving = false; 22570 } 22571 22572 /** 22573 * Performs the horizontal movement. (CSS3 or jQuery) 22574 * 22575 * @param fireCallback {Bool} - determines whether or not to fire the callback 22576 */ 22577 function performHorizontalMove(slides, v, fireCallback){ 22578 var destinyPos = v.destinyPos; 22579 22580 if(options.css3){ 22581 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 22582 22583 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 22584 22585 afterSlideLoadsId = setTimeout(function(){ 22586 fireCallback && afterSlideLoads(v); 22587 }, options.scrollingSpeed, options.easing); 22588 }else{ 22589 slides.animate({ 22590 scrollLeft : Math.round(destinyPos.left) 22591 }, options.scrollingSpeed, options.easing, function() { 22592 22593 fireCallback && afterSlideLoads(v); 22594 }); 22595 } 22596 } 22597 22598 /** 22599 * Sets the state for the horizontal bullet navigations. 22600 */ 22601 function activeSlidesNavigation(slidesNav, slideIndex){ 22602 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 22603 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 22604 } 22605 22606 var previousHeight = windowsHeight; 22607 22608 //when resizing the site, we adjust the heights of the sections, slimScroll... 22609 function resizeHandler(){ 22610 //checking if it needs to get responsive 22611 responsive(); 22612 22613 // rebuild immediately on touch devices 22614 if (isTouchDevice) { 22615 var activeElement = $(document.activeElement); 22616 22617 //if the keyboard is NOT visible 22618 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 22619 var currentHeight = $window.height(); 22620 22621 //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) 22622 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 22623 reBuild(true); 22624 previousHeight = currentHeight; 22625 } 22626 } 22627 }else{ 22628 //in order to call the functions only when the resize is finished 22629 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 22630 clearTimeout(resizeId); 22631 22632 resizeId = setTimeout(function(){ 22633 reBuild(true); 22634 }, 350); 22635 } 22636 } 22637 22638 /** 22639 * Checks if the site needs to get responsive and disables autoScrolling if so. 22640 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 22641 */ 22642 function responsive(){ 22643 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 22644 var heightLimit = options.responsiveHeight; 22645 22646 //only calculating what we need. Remember its called on the resize event. 22647 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 22648 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 22649 22650 if(widthLimit && heightLimit){ 22651 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 22652 } 22653 else if(widthLimit){ 22654 setResponsive(isBreakingPointWidth); 22655 } 22656 else if(heightLimit){ 22657 setResponsive(isBreakingPointHeight); 22658 } 22659 } 22660 22661 /** 22662 * Adds transition animations for the given element 22663 */ 22664 function addAnimation(container, element){ 22665 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 22666 22667 container.removeClass(NO_TRANSITION); 22668 return container.css({
22669 '-webkit-transition': transition, 22670 'transition': transition 22671 }); 22672 } 22673 22674 /** 22675 * Remove transition animations for the given element 22676 */ 22677 function removeAnimation(element){ 22678 return element.addClass(NO_TRANSITION); 22679 } 22680 22681 /** 22682 * Activating the vertical navigation bullets according to the given slide name. 22683 */ 22684 function activateNavDots(name, sectionIndex){ 22685 if(options.navigation){ 22686 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 22687 if(name){ 22688 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 22689 }else{ 22690 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 22691 } 22692 } 22693 } 22694 22695 /** 22696 * Activating the website main menu elements according to the given slide name. 22697 */ 22698 function activateMenuElement(name){ 22699 if(options.menu){ 22700 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 22701 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 22702 } 22703 } 22704 22705 /** 22706 * Sets to active the current menu and vertical nav items. 22707 */ 22708 function activateMenuAndNav(anchor, index){ 22709 activateMenuElement(anchor); 22710 activateNavDots(anchor, index); 22711 } 22712 22713 /** 22714 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 22715 * from the current section. 22716 */ 22717 function getYmovement(destiny){ 22718 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 22719 var toIndex = destiny.index(SECTION_SEL); 22720 if( fromIndex == toIndex){ 22721 return 'none'; 22722 } 22723 if(fromIndex > toIndex){ 22724 return 'up'; 22725 } 22726 return 'down'; 22727 } 22728 22729 /** 22730 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 22731 * from the current slide. 22732 */ 22733 function getXmovement(fromIndex, toIndex){ 22734 if( fromIndex == toIndex){ 22735 return 'none'; 22736 } 22737 if(fromIndex > toIndex){ 22738 return 'left'; 22739 } 22740 return 'right'; 22741 } 22742 22743 /** 22744 * Checks if the element needs scrollbar and if the user wants to apply it. 22745 * If so it creates it. 22746 * 22747 * @param {Object} element jQuery object of the section or slide 22748 */ 22749 function createScrollBar(element){ 22750 //User doesn't want scrollbar here? Sayonara baby! 22751 if(element.hasClass('fp-noscroll')) return; 22752 22753 //needed to make `scrollHeight` work under Opera 12 22754 element.css('overflow', 'hidden'); 22755 22756 var scrollOverflowHandler = options.scrollOverflowHandler; 22757 var wrap = scrollOverflowHandler.wrapContent(); 22758 //in case element is a slide 22759 var section = element.closest(SECTION_SEL); 22760 var scrollable = scrollOverflowHandler.scrollable(element); 22761 var contentHeight; 22762 22763 //if there was scroll, the contentHeight will be the one in the scrollable section 22764 if(scrollable.length){ 22765 contentHeight = scrollOverflowHandler.scrollHeight(element); 22766 }else{ 22767 contentHeight = element.get(0).scrollHeight; 22768 if(options.verticalCentered){ 22769 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 22770 } 22771 } 22772 22773 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 22774 22775 //needs scroll? 22776 if ( contentHeight > scrollHeight) { 22777 //did we already have an scrollbar ? Updating it 22778 if(scrollable.length){ 22779 scrollOverflowHandler.update(element, scrollHeight); 22780 } 22781 //creating the scrolling 22782 else{ 22783 if(options.verticalCentered){ 22784 element.find(TABLE_CELL_SEL).wrapInner(wrap); 22785 }else{ 22786 element.wrapInner(wrap); 22787 } 22788 scrollOverflowHandler.create(element, scrollHeight); 22789 } 22790 } 22791 //removing the scrolling when it is not necessary anymore 22792 else{ 22793 scrollOverflowHandler.remove(element); 22794 } 22795 22796 //undo 22797 element.css('overflow', ''); 22798 } 22799 22800 function addTableClass(element){ 22801 //In case we are styling for the 2nd time as in with reponsiveSlides 22802 if(!element.hasClass(TABLE)){ 22803 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 22804 } 22805 } 22806 22807 function getTableHeight(element){ 22808 var sectionHeight = windowsHeight; 22809 22810 if(options.paddingTop || options.paddingBottom){ 22811 var section = element; 22812 if(!section.hasClass(SECTION)){ 22813 section = element.closest(SECTION_SEL); 22814 } 22815 22816 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 22817 sectionHeight = (windowsHeight - paddings); 22818 } 22819 22820 return sectionHeight; 22821 } 22822 22823 /** 22824 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 22825 */ 22826 function transformContainer(translate3d, animated){ 22827 if(animated){ 22828 addAnimation(container); 22829 }else{ 22830 removeAnimation(container); 22831 } 22832 22833 container.css(getTransforms(translate3d)); 22834 22835 //syncronously removing the class after the animation has been applied. 22836 setTimeout(function(){ 22837 container.removeClass(NO_TRANSITION); 22838 },10); 22839 } 22840 22841 /** 22842 * Gets a section by its anchor / index 22843 */ 22844 function getSectionByAnchor(sectionAnchor){ 22845 if(!sectionAnchor) return []; 22846 22847 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 22848 if(!section.length){ 22849 section = $(SECTION_SEL).eq( sectionAnchor -1); 22850 } 22851 22852 return section; 22853 } 22854 22855 /** 22856 * Gets a slide inside a given section by its anchor / index 22857 */ 22858 function getSlideByAnchor(slideAnchor, section){ 22859 var slides = section.find(SLIDES_WRAPPER_SEL); 22860 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 22861
22862 if(!slide.length){ 22863 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 22864 } 22865 22866 return slide; 22867 } 22868 22869 /** 22870 * Scrolls to the given section and slide anchors 22871 */ 22872 function scrollPageAndSlide(destiny, slide){ 22873 var section = getSectionByAnchor(destiny); 22874 22875 //do nothing if there's no section with the given anchor name 22876 if(!section.length) return; 22877 22878 //default slide 22879 if (typeof slide === 'undefined') { 22880 slide = 0; 22881 } 22882 22883 //we need to scroll to the section and then to the slide 22884 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 22885 scrollPage(section, function(){ 22886 scrollSlider(section, slide); 22887 }); 22888 } 22889 //if we were already in the section 22890 else{ 22891 scrollSlider(section, slide); 22892 } 22893 } 22894 22895 /** 22896 * Scrolls the slider to the given slide destination for the given section 22897 */ 22898 function scrollSlider(section, slideAnchor){ 22899 if(typeof slideAnchor !== 'undefined'){ 22900 var slides = section.find(SLIDES_WRAPPER_SEL); 22901 var destiny = getSlideByAnchor(slideAnchor, section); 22902 22903 if(destiny.length){ 22904 landscapeScroll(slides, destiny); 22905 } 22906 } 22907 } 22908 22909 /** 22910 * Creates a landscape navigation bar with dots for horizontal sliders. 22911 */ 22912 function addSlidesNavigation(section, numSlides){ 22913 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 22914 var nav = section.find(SLIDES_NAV_SEL); 22915 22916 //top or bottom 22917 nav.addClass(options.slidesNavPosition); 22918 22919 for(var i=0; i< numSlides; i++){ 22920 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 22921 } 22922 22923 //centering it 22924 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 22925 22926 nav.find('li').first().find('a').addClass(ACTIVE); 22927 } 22928 22929 22930 /** 22931 * Sets the state of the website depending on the active section/slide. 22932 * It changes the URL hash when needed and updates the body class. 22933 */ 22934 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 22935 var sectionHash = ''; 22936 22937 if(options.anchors.length && !options.lockAnchors){ 22938 22939 //isn't it the first slide? 22940 if(slideIndex){ 22941 if(typeof anchorLink !== 'undefined'){ 22942 sectionHash = anchorLink; 22943 } 22944 22945 //slide without anchor link? We take the index instead. 22946 if(typeof slideAnchor === 'undefined'){ 22947 slideAnchor = slideIndex; 22948 } 22949 22950 lastScrolledSlide = slideAnchor; 22951 setUrlHash(sectionHash + '/' + slideAnchor); 22952 22953 //first slide won't have slide anchor, just the section one 22954 }else if(typeof slideIndex !== 'undefined'){ 22955 lastScrolledSlide = slideAnchor; 22956 setUrlHash(anchorLink); 22957 } 22958 22959 //section without slides 22960 else{ 22961 setUrlHash(anchorLink); 22962 } 22963 } 22964 22965 setBodyClass(); 22966 } 22967 22968 /** 22969 * Sets the URL hash. 22970 */ 22971 function setUrlHash(url){ 22972 //Uncode addition 22973 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 22974 return false; 22975 22976 if(options.recordHistory){ 22977 location.hash = url; 22978 }else{ 22979 //Uncode addition 22980 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 22981 // if(isTouchDevice || isTouch){ 22982 // window.history.replaceState(undefined, undefined, '#' + url); 22983 // }else{ 22984 // var baseUrl = window.location.href.split('#')[0]; 22985 // window.location.replace( baseUrl + '#' + url ); 22986 // } 22987 return false;
22988 } 22989 } 22990 22991 /** 22992 * Gets the anchor for the given slide / section. Its index will be used if there's none. 22993 */ 22994 function getAnchor(element){ 22995 var anchor = element.data('anchor'); 22996 var index = element.index(); 22997 22998 //Slide without anchor link? We take the index instead. 22999 if(typeof anchor === 'undefined'){ 23000 anchor = index; 23001 } 23002 23003 return anchor; 23004 } 23005 23006 /** 23007 * Sets a class for the body of the page depending on the active section / slide 23008 */ 23009 function setBodyClass(){ 23010 var section = $(SECTION_ACTIVE_SEL); 23011 var slide = section.find(SLIDE_ACTIVE_SEL); 23012 23013 var sectionAnchor = getAnchor(section); 23014 var slideAnchor = getAnchor(slide); 23015 23016 var text = String(sectionAnchor); 23017 23018 if(slide.length){ 23019 text = text + '-' + slideAnchor; 23020 } 23021 23022 //changing slash for dash to make it a valid CSS style 23023 text = text.replace('/', '-').replace('#',''); 23024 23025 //removing previous anchor classes 23026 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 23027 $body[0].className = $body[0].className.replace(classRe, ''); 23028 23029 //adding the current anchor 23030 $body.addClass(VIEWING_PREFIX + '-' + text); 23031 } 23032 23033 /** 23034 * Checks for translate3d support 23035 * @return boolean 23036 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 23037 */ 23038 function support3d() { 23039 var el = document.createElement('p'), 23040 has3d, 23041 transforms = { 23042 'webkitTransform':'-webkit-transform', 23043 'OTransform':'-o-transform', 23044 'msTransform':'-ms-transform', 23045 'MozTransform':'-moz-transform', 23046 'transform':'transform' 23047 }; 23048 23049 // Add it to the body to get the computed style. 23050 document.body.insertBefore(el, null); 23051 23052 for (var t in transforms) { 23053 if (el.style[t] !== undefined) { 23054 el.style[t] = 'translate3d(1px,1px,1px)'; 23055 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 23056 } 23057 } 23058 23059 document.body.removeChild(el); 23060 23061 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 23062 } 23063 23064 /** 23065 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 23066 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 23067 */ 23068 function removeMouseWheelHandler(){ 23069 if (document.addEventListener) { 23070 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 23071 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 23072 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 23073 } else { 23074 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 23075 } 23076 } 23077 23078 /** 23079 * Adds the auto scrolling action for the mouse wheel and trackpad. 23080 * After this function is called, the mousewheel and trackpad movements will scroll through sections 23081 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 23082 */ 23083 function addMouseWheelHandler(){ 23084 var prefix = ''; 23085 var _addEventListener; 23086 23087 if (window.addEventListener){ 23088 _addEventListener = "addEventListener"; 23089 }else{ 23090 _addEventListener = "attachEvent"; 23091 prefix = 'on'; 23092 } 23093 23094 // detect available wheel event 23095 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 23096 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 23097 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 23098 var passiveEvent = g_supportsPassive ? {passive: false }
23098: false; 23099 23100 23101 if(support == 'DOMMouseScroll'){ 23102 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent); 23103 } 23104 23105 //handle MozMousePixelScroll in older Firefox 23106 else{ 23107 document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent); 23108 } 23109 } 23110 23111 /** 23112 * Binding the mousemove when the mouse's middle button is pressed 23113 */ 23114 function addMiddleWheelHandler(){ 23115 container 23116 .on('mousedown', mouseDownHandler) 23117 .on('mouseup', mouseUpHandler); 23118 } 23119 23120 /** 23121 * Unbinding the mousemove when the mouse's middle button is released 23122 */ 23123 function removeMiddleWheelHandler(){ 23124 container 23125 .off('mousedown', mouseDownHandler) 23126 .off('mouseup', mouseUpHandler); 23127 } 23128 23129 /** 23130 * Adds the possibility to auto scroll through sections on touch devices. 23131 */ 23132 function addTouchHandler(){ 23133 if(isTouchDevice || isTouch){ 23134 if(options.autoScrolling){ 23135 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 23136 } 23137 23138 $(WRAPPER_SEL) 23139 .off(events.touchstart).on(events.touchstart, touchStartHandler) 23140 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 23141 } 23142 } 23143 23144 /** 23145 * Removes the auto scrolling for touch devices. 23146 */ 23147 function removeTouchHandler(){ 23148 if(isTouchDevice || isTouch){ 23149 $(WRAPPER_SEL) 23150 .off(events.touchstart) 23151 .off(events.touchmove); 23152 } 23153 } 23154 23155 /* 23156 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11) 23157 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 23158 */ 23159 function getMSPointer(){ 23160 var pointer; 23161 23162 //IE >= 11 & rest of browsers 23163 if(window.PointerEvent){ 23164 pointer = { down: 'pointerdown', move: 'pointermove'}; 23165 } 23166 23167 //IE < 11 23168 else{ 23169 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 23170 } 23171 23172 return pointer; 23173 } 23174 23175 /** 23176 * Gets the pageX and pageY properties depending on the browser. 23177 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 23178 */ 23179 function getEventsPage(e){ 23180 var events = []; 23181 23182 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 23183 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 23184 23185 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 23186 if(isTouch && isReallyTouch(e) && options.scrollBar){ 23187 events.y = e.touches[0].pageY; 23188 events.x = e.touches[0].pageX; 23189 } 23190 23191 return events; 23192 } 23193 23194 /** 23195 * Slides silently (with no animation) the active slider to the given slide. 23196 * @param noCallback {bool} true or defined -> no callbacks 23197 */ 23198 function silentLandscapeScroll(activeSlide, noCallbacks){ 23199 setScrollingSpeed (0, 'internal'); 23200 23201 if(typeof noCallbacks !== 'undefined'){ 23202 //preventing firing callbacks afterSlideLoad etc. 23203 isResizing = true; 23204 } 23205 23206 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 23207 23208 if(typeof noCallbacks !== 'undefined'){ 23209 isResizing = false; 23210 } 23211 23212 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 23213 } 23214 23215 /** 23216 * Scrolls silently (with no animation) the page to the given Y position. 23217 */ 23218 function silentScroll(top){ 23219 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 23220 // that's why we round it to 0. 23221 var roundedTop = Math.round(top); 23222 23223 if (options.css3 && options.autoScrolling && !options.scrollBar){ 23224 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 23225 transformContainer(translate3d, false); 23226 } 23227 else if(options.autoScrolling && !options.scrollBar){ 23228 container.css('top', -roundedTop); 23229 } 23230 else{ 23231 $htmlBody.scrollTop(roundedTop); 23232 } 23233 } 23234 23235 /** 23236 * Returns the cross-browser transform string. 23237 */ 23238 function getTransforms(translate3d){ 23239 return {
23240 '-webkit-transform': translate3d, 23241 '-moz-transform': translate3d, 23242 '-ms-transform':translate3d, 23243 'transform': translate3d 23244 }; 23245 } 23246 23247 /** 23248 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 23249 * @type m (mouse) or k (keyboard) 23250 */ 23251 function setIsScrollAllowed(value, direction, type){ 23252 switch (direction){ 23253 case 'up': isScrollAllowed[type].up = value; break; 23254 case 'down': isScrollAllowed[type].down = value; break; 23255 case 'left': isScrollAllowed[type].left = value; break; 23256 case 'right': isScrollAllowed[type].right = value; break; 23257 case 'all': 23258 if(type == 'm'){ 23259 setAllowScrolling(value); 23260 }else{ 23261 setKeyboardScrolling(value); 23262 } 23263 } 23264 } 23265 23266 /* 23267 * Destroys fullpage.js plugin events and optinally its html markup and styles 23268 */ 23269 function destroy(all){ 23270 setAutoScrolling(false, 'internal'); 23271 setAllowScrolling(false); 23272 setKeyboardScrolling(false); 23273 container.addClass(DESTROYED); 23274 23275 clearTimeout(afterSlideLoadsId); 23276 clearTimeout(afterSectionLoadsId); 23277 clearTimeout(resizeId); 23278 clearTimeout(scrollId); 23279 clearTimeout(scrollId2); 23280 23281 $window 23282 .off('scroll', scrollHandler) 23283 .off('hashchange', hashChangeHandler) 23284 .off('resize', resizeHandler); 23285 23286 $document 23287 .off('click touchstart', SECTION_NAV_SEL + ' a') 23288 .off('mouseenter', SECTION_NAV_SEL + ' li') 23289 .off('mouseleave', SECTION_NAV_SEL + ' li') 23290 .off('click touchstart', SLIDES_NAV_LINK_SEL) 23291 .off('mouseover', options.normalScrollElements) 23292 .off('mouseout', options.normalScrollElements); 23293 23294 $(SECTION_SEL) 23295 .off('click touchstart', SLIDES_ARROW_SEL); 23296 23297 clearTimeout(afterSlideLoadsId); 23298 clearTimeout(afterSectionLoadsId); 23299 23300 //lets make a mess! 23301 if(all){ 23302 destroyStructure(); 23303 } 23304 } 23305 23306 /* 23307 * Removes inline styles added by fullpage.js 23308 */ 23309 function destroyStructure(){ 23310 //reseting the `top` or `translate` properties to 0 23311 silentScroll(0); 23312 23313 //loading all the lazy load content 23314 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 23315 setSrc($(this), 'src'); 23316 }); 23317 23318 container.find('img[data-srcset]').each(function(){ 23319 setSrc($(this), 'srcset'); 23320 }); 23321 23322 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 23323 23324 //removing inline styles 23325 $(SECTION_SEL).css( { 23326 'height': '', 23327 'background-color' : '', 23328 'padding': '' 23329 }); 23330 23331 $(SLIDE_SEL).css( { 23332 'width': '' 23333 }); 23334 23335 container.css({ 23336 'height': '', 23337 'position': '', 23338 '-ms-touch-action': '', 23339 'touch-action': '' 23340 }); 23341 23342 $htmlBody.css({ 23343 'overflow': '', 23344 'height': '' 23345 }); 23346 23347 // remove .fp-enabled class 23348 $('html').removeClass(ENABLED); 23349 23350 // remove .fp-responsive class 23351 $body.removeClass(RESPONSIVE); 23352 23353 // remove all of the .fp-viewing- classes 23354 $.each($body.get(0).className.split(/\s+/), function (index, className) { 23355 if (className.indexOf(VIEWING_PREFIX) === 0) { 23356 $body.removeClass(className); 23357 } 23358 }); 23359 23360 //removing added classes 23361 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 23362 options.scrollOverflowHandler.remove($(this)); 23363 $(this).removeClass(TABLE + ' ' + ACTIVE); 23364 }); 23365 23366 removeAnimation(container); 23367 23368 //Unwrapping content 23369 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 23370 //unwrap not being use in case there's no child element inside and its just text 23371 $(this).replaceWith(this.childNodes); 23372 }); 23373 23374 //removing the applied transition from the fullpage wrapper 23375 container.css({
23376 '-webkit-transition': 'none', 23377 'transition': 'none' 23378 }); 23379 23380 //scrolling the page to the top with no animation 23381 $htmlBody.scrollTop(0); 23382 23383 //removing selectors 23384 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 23385 $.each(usedSelectors, function(index, value){ 23386 $('.' + value).removeClass(value); 23387 }); 23388 } 23389 23390 /* 23391 * Sets the state for a variable with multiple states (original, and temporal) 23392 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 23393 * This function is used to keep track of both states, the original and the temporal one. 23394 * If type is not 'internal', then we assume the user is globally changing the variable. 23395 */ 23396 function setVariableState(variable, value, type){ 23397 options[variable] = value; 23398 if(type !== 'internal'){ 23399 originals[variable] = value; 23400 } 23401 } 23402 23403 /** 23404 * Displays warnings 23405 */ 23406 function displayWarnings(){ 23407 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 23408 //UNCODE.addition 23409 // if($('html').hasClass(ENABLED)){ 23410 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 23411 // return; 23412 // } 23413 23414 // Disable mutually exclusive settings 23415 //UNCODE.addition 23416 // if (options.continuousVertical && 23417 // (options.loopTop || options.loopBottom)) { 23418 // options.continuousVertical = false;
23419 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 23420 // } 23421 23422 // if(options.scrollBar && options.scrollOverflow){ 23423 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 23424 // } 23425 23426 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 23427 // options.continuousVertical = false; 23428 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 23429 // } 23430 23431 //using extensions? Wrong file! 23432 $.each(extensions, function(index, extension){ 23433 //is the option set to true? 23434 if(options[extension]){ 23435 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 23436 } 23437 }); 23438 23439 //anchors can not have the same value as any element ID or NAME 23440 $.each(options.anchors, function(index, name){ 23441 23442 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 23443 var nameAttr = $document.find('[name]').filter(function() { 23444 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 23445 }); 23446 23447 var idAttr = $document.find('[id]').filter(function() { 23448 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 23449 }); 23450 23451 if(idAttr.length || nameAttr.length ){ 23452 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 23453 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 23454 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 23455 } 23456 }); 23457 } 23458 23459 /** 23460 * Shows a message in the console of the given type. 23461 */ 23462 function showError(type, text){ 23463 console && console[type] && console[type]('fullPage: ' + text); 23464 } 23465 23466 }; //end of $.fn.fullpage 23467 23468 if(typeof IScroll !== 'undefined'){ 23469 /* 23470 * Turns iScroll `mousewheel` option off dynamically 23471 * https://github.com/cubiq/iscroll/issues/1036 23472 */ 23473 IScroll.prototype.wheelOn = function () { 23474 this.wrapper.addEventListener('wheel', this); 23475 this.wrapper.addEventListener('mousewheel', this); 23476 this.wrapper.addEventListener('DOMMouseScroll', this); 23477 }; 23478 23479 /* 23480 * Turns iScroll `mousewheel` option on dynamically 23481 * https://github.com/cubiq/iscroll/issues/1036 23482 */ 23483 IScroll.prototype.wheelOff = function () { 23484 this.wrapper.removeEventListener('wheel', this); 23485 this.wrapper.removeEventListener('mousewheel', this); 23486 this.wrapper.removeEventListener('DOMMouseScroll', this); 23487 }; 23488 } 23489 23490 /** 23491 * An object to handle overflow scrolling. 23492 * This uses jquery.slimScroll to accomplish overflow scrolling. 23493 * It is possible to pass in an alternate scrollOverflowHandler 23494 * to the fullpage.js option that implements the same functions 23495 * as this handler. 23496 * 23497 * @type {Object} 23498 */ 23499 var iscrollHandler = { 23500 refreshId: null, 23501 iScrollInstances: [], 23502 23503 // Enables or disables the mouse wheel for the active section or all slides in it 23504 toggleWheel: function(value){ 23505 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 23506 scrollable.each(function(){ 23507 var iScrollInstance = $(this).data('iscrollInstance'); 23508 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 23509 if(value){ 23510 iScrollInstance.wheelOn(); 23511 } 23512 else{ 23513 iScrollInstance.wheelOff(); 23514 } 23515 } 23516 }); 23517 }, 23518 23519 /** 23520 * Turns off iScroll for the destination section. 23521 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
23522 * scroll the destination section/slide before the sections animations ends. 23523 */ 23524 onLeave: function(){ 23525 iscrollHandler.toggleWheel(false); 23526 }, 23527 23528 // Turns off iScroll for the leaving section 23529 beforeLeave: function(){ 23530 iscrollHandler.onLeave() 23531 }, 23532 23533 // Turns on iScroll on section load 23534 afterLoad: function(){ 23535 iscrollHandler.toggleWheel(true); 23536 }, 23537 23538 /** 23539 * Called when overflow scrolling is needed for a section. 23540 * 23541 * @param {Object} element jQuery object containing current section 23542 * @param {Number} scrollHeight Current window height in pixels 23543 */ 23544 create: function(element, scrollHeight) { 23545 var scrollable = element.find(SCROLLABLE_SEL); 23546 23547 scrollable.height(scrollHeight); 23548 scrollable.each(function() { 23549 var $this = $(this); 23550 var iScrollInstance = $this.data('iscrollInstance'); 23551 if (iScrollInstance) { 23552 $.each(iscrollHandler.iScrollInstances, function(){ 23553 $(this).destroy(); 23554 }); 23555 } 23556 23557 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 23558 iscrollHandler.iScrollInstances.push(iScrollInstance); 23559 23560 //off by default until the section gets active 23561 iScrollInstance.wheelOff(); 23562 23563 $this.data('iscrollInstance', iScrollInstance); 23564 }); 23565 }, 23566 23567 /** 23568 * Return a boolean depending on whether the scrollable element is a 23569 * the end or at the start of the scrolling depending on the given type. 23570 * 23571 * @param {String} type Either 'top' or 'bottom' 23572 * @param {Object} scrollable jQuery object for the scrollable element 23573 * @return {Boolean} 23574 */ 23575 isScrolled: function(type, scrollable) { 23576 var scroller = scrollable.data('iscrollInstance'); 23577 23578 //no scroller? 23579 if (!scroller) { 23580 return true; 23581 } 23582 23583 if (type === 'top') { 23584 return scroller.y >= 0 && !scrollable.scrollTop(); 23585 } else if (type === 'bottom') { 23586 return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight; 23587 } 23588 }, 23589 23590 /** 23591 * Returns the scrollable element for the given section. 23592 * If there are landscape slides, will only return a scrollable element 23593 * if it is in the active slide. 23594 * 23595 * @param {Object} activeSection jQuery object containing current section 23596 * @return {Boolean} 23597 */ 23598 scrollable: function(activeSection){ 23599 // if there are landscape slides, we check if the scrolling bar is in the current one or not 23600 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 23601 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 23602 } 23603 return activeSection.find(SCROLLABLE_SEL); 23604 }, 23605 23606 /** 23607 * Returns the scroll height of the wrapped content. 23608 * If this is larger than the window height minus section padding, 23609 * overflow scrolling is needed. 23610 * 23611 * @param {Object} element jQuery object containing current section 23612 * @return {Number} 23613 */ 23614 scrollHeight: function(element) { 23615 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 23616 }, 23617 23618 /** 23619 * Called when overflow scrolling is no longer needed for a section. 23620 * 23621 * @param {Object} element jQuery object containing current section 23622 */ 23623 remove: function(element) { 23624 var scrollable = element.find(SCROLLABLE_SEL); 23625 if (scrollable.length) { 23626 var iScrollInstance = scrollable.data('iscrollInstance'); 23627 iScrollInstance.destroy(); 23628 23629 scrollable.data('iscrollInstance', null); 23630 } 23631 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 23632 }, 23633 23634 /** 23635 * Called when overflow scrolling has already been setup but the 23636 * window height has potentially changed. 23637 * 23638 * @param {Object}
vendor: 16,384 bytes, lines 23638-24189
23638 element jQuery object containing current section 23639 * @param {Number} scrollHeight Current window height in pixels 23640 */ 23641 update: function(element, scrollHeight) { 23642 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 23643 //short period of time. 23644 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 23645 clearTimeout(iscrollHandler.refreshId); 23646 iscrollHandler.refreshId = setTimeout(function(){ 23647 $.each(iscrollHandler.iScrollInstances, function(){ 23648 $(this).get(0).refresh(); 23649 }); 23650 }, 150); 23651 23652 //updating the wrappers height 23653 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 23654 }, 23655 23656 /** 23657 * Called to get any additional elements needed to wrap the section 23658 * content in order to facilitate overflow scrolling. 23659 * 23660 * @return {String|Object} Can be a string containing HTML, 23661 * a DOM element, or jQuery object. 23662 */ 23663 wrapContent: function() { 23664 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 23665 } 23666 }; 23667}); 23668 23669/* ======================================================================== 23670 * Bootstrap: collapse.js v3.1.1 23671 * http://getbootstrap.com/javascript/#collapse 23672 * ======================================================================== 23673 * Copyright 2011-2014 Twitter, Inc. 23674 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 23675 * ======================================================================== */ 23676 23677 23678+function ($) { 23679 'use strict'; 23680 23681 // COLLAPSE PUBLIC CLASS DEFINITION 23682 // ================================ 23683 23684 var Collapse = function (element, options) { 23685 this.$element = $(element) 23686 this.options = $.extend({}, Collapse.DEFAULTS, options) 23687 this.transitioning = null 23688 23689 if (this.options.parent) this.$parent = $(this.options.parent) 23690 if (this.options.toggle) this.toggle() 23691 } 23692 23693 Collapse.DEFAULTS = { 23694 toggle: true 23695 } 23696 23697 Collapse.prototype.dimension = function () { 23698 var hasWidth = this.$element.hasClass('width') 23699 return hasWidth ? 'width' : 'height' 23700 } 23701 23702 Collapse.prototype.show = function () { 23703 if (this.transitioning || this.$element.hasClass('in')) return 23704 23705 var startEvent = $.Event('show.bs.collapse') 23706 this.$element.trigger(startEvent) 23707 if (startEvent.isDefaultPrevented()) return 23708 23709 var actives = this.$parent && this.$parent.find('> .panel > .in') 23710 23711 if (actives && actives.length) { 23712 var hasData = actives.data('bs.collapse') 23713 if (hasData && hasData.transitioning) return 23714 actives.collapse('hide') 23715 hasData || actives.data('bs.collapse', null) 23716 } 23717 23718 var dimension = this.dimension() 23719 23720 this.$element 23721 .removeClass('collapse') 23722 .addClass('collapsing')[dimension](0) 23723 23724 this.transitioning = 1 23725 23726 var complete = function (e) { 23727 if (e && e.target != this.$element[0]) return 23728 this.$element 23729 .removeClass('collapsing') 23730 .addClass('collapse in')[dimension]('auto') 23731 this.transitioning = 0 23732 this.$element.trigger('shown.bs.collapse') 23733 } 23734 23735 if (!$.support.transition) return complete.call(this) 23736 23737 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 23738 23739 this.$element 23740 .one($.support.transition.end, $.proxy(complete, this)) 23741 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 23742 } 23743 23744 Collapse.prototype.hide = function () { 23745 if (this.transitioning || !this.$element.hasClass('in')) return 23746 23747 var startEvent = $.Event('hide.bs.collapse') 23748 this.$element.trigger(startEvent) 23749 if (startEvent.isDefaultPrevented()) return 23750 23751 var dimension = this.dimension() 23752 23753 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 23754 23755 this.$element 23756 .addClass('collapsing') 23757 .removeClass('collapse') 23758 .removeClass('in') 23759 23760 this.transitioning = 1 23761 23762 var complete = function (e) { 23763 if (e && e.target != this.$element[0]) return 23764 this.transitioning = 0 23765 this.$element 23766 .trigger('hidden.bs.collapse') 23767 .removeClass('collapsing') 23768 .addClass('collapse') 23769 } 23770 23771 if (!$.support.transition) return complete.call(this) 23772 23773 this.$element 23774 [dimension](0) 23775 .one($.support.transition.end, $.proxy(complete, this)) 23776 .emulateTransitionEnd(350) 23777 } 23778 23779 Collapse.prototype.toggle = function () { 23780 this[this.$element.hasClass('in') ? 'hide' : 'show']() 23781 } 23782 23783 23784 // COLLAPSE PLUGIN DEFINITION 23785 // ========================== 23786 23787 var old = $.fn.collapse 23788 23789 $.fn.collapse = function (option) { 23790 return this.each(function () { 23791 var $this = $(this) 23792 var data = $this.data('bs.collapse') 23793 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 23794 23795 if (!data && options.toggle && option == 'show') option = !option 23796 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 23797 if (typeof option == 'string') data[option]() 23798 }) 23799 } 23800 23801 $.fn.collapse.Constructor = Collapse 23802 23803 23804 // COLLAPSE NO CONFLICT 23805 // ==================== 23806 23807 $.fn.collapse.noConflict = function () { 23808 $.fn.collapse = old 23809 return this 23810 } 23811 23812 23813 // COLLAPSE DATA-API 23814 // ================= 23815 23816 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 23817 var $this = $(this), href 23818 var target = $this.attr('data-target') 23819 || e.preventDefault() 23820 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 23821 //Edited by Uncode to replace ID in panel [START] 23822 var _target = href.replace(/^#/, ""); 23823 if ( $('[data-id="' + _target + '"]').length ) { 23824 var $target = $('[data-id="' + _target + '"]') 23825 } else { 23826 var $target = $(target) 23827 } 23828 //Edited by Uncode to replace ID in panel [END] 23829 var data = $target.data('bs.collapse') 23830 var option = data ? 'toggle' : $this.data() 23831 var parent = $this.attr('data-parent') 23832 var $parent = parent && $(parent) 23833 23834 if (!data || !data.transitioning) { 23835 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 23836 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 23837 } 23838 23839 $target.collapse(option) 23840 }) 23841 23842}(jQuery); 23843 23844/* ======================================================================== 23845 * Bootstrap: tab.js v3.1.1 23846 * http://getbootstrap.com/javascript/#tabs 23847 * ======================================================================== 23848 * Copyright 2011-2014 Twitter, Inc. 23849 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 23850 * ======================================================================== */ 23851 23852 23853+function ($) { 23854 'use strict'; 23855 23856 // TAB CLASS DEFINITION 23857 // ==================== 23858 23859 var Tab = function (element) { 23860 this.element = $(element) 23861 } 23862 23863 Tab.prototype.show = function () { 23864 var $this = this.element 23865 var $ul = $this.closest('ul:not(.dropdown-menu)') 23866 var selector = $this.data('target') 23867 23868 if (!selector) { 23869 selector = $this.attr('href') 23870 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 23871 } 23872 23873 if ($this.parent('li').hasClass('active')) return 23874 23875 var previous = $ul.find('.active:last a')[0] 23876 var e = $.Event('show.bs.tab', { 23877 relatedTarget: previous 23878 }) 23879 23880 $this.trigger(e) 23881 23882 if (e.isDefaultPrevented()) return 23883 23884 //Edited by Uncode to replace ID in panel [START] 23885 var _target = selector.replace(/^#/, ""); 23886 if ( $('[data-id="' + _target + '"]').length ) 23887 var $target = $('[data-id="' + _target + '"]') 23888 else 23889 var $target = $(selector) 23890 //Edited by Uncode to replace ID in panel [END] 23891 23892 this.activate($this.parent('li'), $ul) 23893 this.activate($target, $target.parent(), function () { 23894 $this.trigger({ 23895 type: 'shown.bs.tab', 23896 relatedTarget: previous 23897 }) 23898 }) 23899 } 23900 23901 Tab.prototype.activate = function (element, container, callback) { 23902 var $active = container.find('> .active') 23903 var transition = callback 23904 && $.support.transition 23905 && $active.hasClass('fade') 23906 23907 function next() { 23908 $active 23909 .removeClass('active') 23910 .find('> .dropdown-menu > .active') 23911 .removeClass('active') 23912 23913 element.addClass('active') 23914 23915 if (transition) { 23916 element[0].offsetWidth // reflow for transition 23917 element.addClass('in') 23918 } else { 23919 element.removeClass('fade') 23920 } 23921 23922 if (element.parent('.dropdown-menu')) { 23923 element.closest('li.dropdown').addClass('active') 23924 } 23925 23926 callback && callback() 23927 } 23928 23929 transition ? 23930 $active 23931 .one($.support.transition.end, next) 23932 .emulateTransitionEnd(150) : 23933 next() 23934 23935 $active.removeClass('in') 23936 } 23937 23938 23939 // TAB PLUGIN DEFINITION 23940 // ===================== 23941 23942 var old = $.fn.tab 23943 23944 $.fn.tab = function ( option ) { 23945 return this.each(function () { 23946 var $this = $(this) 23947 var data = $this.data('bs.tab') 23948 23949 if (!data) $this.data('bs.tab', (data = new Tab(this))) 23950 if (typeof option == 'string') data[option]() 23951 }) 23952 } 23953 23954 $.fn.tab.Constructor = Tab 23955 23956 23957 // TAB NO CONFLICT 23958 // =============== 23959 23960 $.fn.tab.noConflict = function () { 23961 $.fn.tab = old 23962 return this 23963 } 23964 23965 23966 // TAB DATA-API 23967 // ============ 23968 23969 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 23970 e.preventDefault() 23971 $(this).tab('show') 23972 }) 23973 23974}(jQuery); 23975 23976/* ======================================================================== 23977 * Bootstrap: tooltip.js v3.1.1 23978 * http://getbootstrap.com/javascript/#tooltip 23979 * Inspired by the original jQuery.tipsy by Jason Frame 23980 * ======================================================================== 23981 * Copyright 2011-2014 Twitter, Inc. 23982 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 23983 * ======================================================================== */ 23984 23985 23986+function ($) { 23987 'use strict'; 23988 23989 // TOOLTIP PUBLIC CLASS DEFINITION 23990 // =============================== 23991 23992 var Tooltip = function (element, options) { 23993 this.type = 23994 this.options = 23995 this.enabled = 23996 this.timeout = 23997 this.hoverState = 23998 this.$element = null 23999 24000 this.init('tooltip', element, options) 24001 } 24002 24003 Tooltip.DEFAULTS = { 24004 animation: true, 24005 placement: 'top', 24006 selector: false, 24007 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 24008 trigger: 'hover focus', 24009 title: '', 24010 delay: 0, 24011 html: false, 24012 container: false, 24013 viewport: { 24014 selector: 'body', 24015 padding: 0 24016 } 24017 } 24018 24019 Tooltip.prototype.init = function (type, element, options) { 24020 this.enabled = true 24021 this.type = type 24022 this.$element = $(element) 24023 this.options = this.getOptions(options) 24024 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 24025 24026 var triggers = this.options.trigger.split(' ') 24027 24028 for (var i = triggers.length; i--;) { 24029 var trigger = triggers[i] 24030 24031 if (trigger == 'click') { 24032 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 24033 } else if (trigger != 'manual') { 24034 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 24035 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 24036 24037 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 24038 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 24039 } 24040 } 24041 24042 this.options.selector ? 24043 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 24044 this.fixTitle() 24045 } 24046 24047 Tooltip.prototype.getDefaults = function () { 24048 return Tooltip.DEFAULTS 24049 } 24050 24051 Tooltip.prototype.getOptions = function (options) { 24052 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 24053 24054 if (options.delay && typeof options.delay == 'number') { 24055 options.delay = { 24056 show: options.delay, 24057 hide: options.delay 24058 } 24059 } 24060 24061 return options 24062 } 24063 24064 Tooltip.prototype.getDelegateOptions = function () { 24065 var options = {} 24066 var defaults = this.getDefaults() 24067 24068 this._options && $.each(this._options, function (key, value) { 24069 if (defaults[key] != value) options[key] = value 24070 }) 24071 24072 return options 24073 } 24074 24075 Tooltip.prototype.enter = function (obj) { 24076 var self = obj instanceof this.constructor ? 24077 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 24078 24079 clearTimeout(self.timeout) 24080 24081 self.hoverState = 'in' 24082 24083 if (!self.options.delay || !self.options.delay.show) return self.show() 24084 24085 self.timeout = setTimeout(function () { 24086 if (self.hoverState == 'in') self.show() 24087 }, self.options.delay.show) 24088 } 24089 24090 Tooltip.prototype.leave = function (obj) { 24091 var self = obj instanceof this.constructor ? 24092 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 24093 24094 clearTimeout(self.timeout) 24095 24096 self.hoverState = 'out' 24097 24098 if (!self.options.delay || !self.options.delay.hide) return self.hide() 24099 24100 self.timeout = setTimeout(function () { 24101 if (self.hoverState == 'out') self.hide() 24102 }, self.options.delay.hide) 24103 } 24104 24105 Tooltip.prototype.show = function () { 24106 var e = $.Event('show.bs.' + this.type) 24107 24108 if (this.hasContent() && this.enabled) { 24109 this.$element.trigger(e) 24110 24111 if (e.isDefaultPrevented()) return 24112 var that = this; 24113 24114 var $tip = this.tip() 24115 24116 this.setContent() 24117 24118 if (this.options.animation) $tip.addClass('fade') 24119 24120 var placement = typeof this.options.placement == 'function' ? 24121 this.options.placement.call(this, $tip[0], this.$element[0]) : 24122 this.options.placement 24123 24124 var autoToken = /\s?auto?\s?/i 24125 var autoPlace = autoToken.test(placement) 24126 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 24127 24128 $tip 24129 .detach() 24130 .css({ top: 0, left: 0, display: 'block' }) 24131 .addClass(placement) 24132 24133 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 24134 24135 var pos = this.getPosition() 24136 var actualWidth = $tip[0].offsetWidth 24137 var actualHeight = $tip[0].offsetHeight 24138 24139 if (autoPlace) { 24140 var orgPlacement = placement 24141 var $parent = this.$element.parent() 24142 var parentDim = this.getPosition($parent) 24143 24144 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 24145 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 24146 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 24147 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 24148 placement 24149 24150 $tip 24151 .removeClass(orgPlacement) 24152 .addClass(placement) 24153 } 24154 24155 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 24156 24157 this.applyPlacement(calculatedOffset, placement) 24158 this.hoverState = null 24159 24160 var complete = function() { 24161 that.$element.trigger('shown.bs.' + that.type) 24162 } 24163 24164 $.support.transition && this.$tip.hasClass('fade') ? 24165 $tip 24166 .one($.support.transition.end, complete) 24167 .emulateTransitionEnd(150) : 24168 complete() 24169 } 24170 } 24171 24172 Tooltip.prototype.applyPlacement = function (offset, placement) { 24173 var $tip = this.tip() 24174 var width = $tip[0].offsetWidth 24175 var height = $tip[0].offsetHeight 24176 24177 // manually read margins because getBoundingClientRect includes difference 24178 var marginTop = parseInt($tip.css('margin-top'), 10) 24179 var marginLeft = parseInt($tip.css('margin-left'), 10) 24180 24181 // we must check for NaN for ie 8/9 24182 if (isNaN(marginTop)) marginTop = 0 24183 if (isNaN(marginLeft)) marginLeft = 0 24184 24185 offset.top = offset.top + marginTop 24186 offset.left = offset.left + marginLeft 24187 24188 // $.fn.offset doesn't round pixel values 24189 // so we use setOff
24189set directly with our own function B-0 24190 $.offset.setOffset($tip[0], $.extend({ 24191 using: function (props) { 24192 $tip.css({ 24193 top: Math.round(props.top), 24194 left: Math.round(props.left) 24195 }) 24196 } 24197 }, offset), 0) 24198 24199 $tip.addClass('in') 24200 24201 // check to see if placing tip in new offset caused the tip to resize itself 24202 var actualWidth = $tip[0].offsetWidth 24203 var actualHeight = $tip[0].offsetHeight 24204 24205 if (placement == 'top' && actualHeight != height) { 24206 offset.top = offset.top + height - actualHeight 24207 } 24208 24209 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 24210 24211 if (delta.left) offset.left += delta.left 24212 else offset.top += delta.top 24213 24214 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 24215 var arrowPosition = delta.left ? 'left' : 'top' 24216 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 24217 24218 $tip.offset(offset) 24219 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 24220 } 24221 24222 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 24223 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 24224 } 24225 24226 Tooltip.prototype.setContent = function () { 24227 var $tip = this.tip() 24228 var title = this.getTitle() 24229 24230 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 24231 $tip.removeClass('fade in top bottom left right') 24232 } 24233 24234 Tooltip.prototype.hide = function () { 24235 var that = this 24236 var $tip = this.tip() 24237 var e = $.Event('hide.bs.' + this.type) 24238 24239 function complete() { 24240 if (that.hoverState != 'in') $tip.detach() 24241 that.$element.trigger('hidden.bs.' + that.type) 24242 } 24243 24244 this.$element.trigger(e) 24245 24246 if (e.isDefaultPrevented()) return 24247 24248 $tip.removeClass('in') 24249 24250 $.support.transition && this.$tip.hasClass('fade') ? 24251 $tip 24252 .one($.support.transition.end, complete) 24253 .emulateTransitionEnd(150) : 24254 complete() 24255 24256 this.hoverState = null 24257 24258 return this 24259 } 24260 24261 Tooltip.prototype.fixTitle = function () { 24262 var $e = this.$element 24263 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 24264 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 24265 } 24266 } 24267 24268 Tooltip.prototype.hasContent = function () { 24269 return this.getTitle() 24270 } 24271 24272 Tooltip.prototype.getPosition = function ($element) { 24273 $element = $element || this.$element 24274 var el = $element[0] 24275 var isBody = el.tagName == 'BODY' 24276 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 24277 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 24278 width: isBody ? $(window).width() : $element.outerWidth(), 24279 height: isBody ? $(window).height() : $element.outerHeight() 24280 }, isBody ? {top: 0, left: 0} : $element.offset()) 24281 } 24282 24283 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 24284 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 24285 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 24286 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 24287 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 24288 24289 } 24290 24291 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 24292 var delta = { top: 0, left: 0 } 24293 if (!this.$viewport) return delta 24294 24295 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 24296 var viewportDimensions = this.getPosition(this.$viewport) 24297 24298 if (/right|left/.test(placement)) { 24299 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 24300 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 24301 if (topEdgeOffset < viewportDimensions.top) { // top overflow 24302 delta.top = viewportDimensions.top - topEdgeOffset 24303 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 24304 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
24304EdgeOffset 24305 } 24306 } else { 24307 var leftEdgeOffset = pos.left - viewportPadding 24308 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 24309 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 24310 delta.left = viewportDimensions.left - leftEdgeOffset 24311 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 24312 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 24313 } 24314 } 24315 24316 return delta 24317 } 24318 24319 Tooltip.prototype.getTitle = function () { 24320 var title 24321 var $e = this.$element 24322 var o = this.options 24323 24324 title = $e.attr('data-original-title') 24325 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 24326 24327 return title 24328 } 24329 24330 Tooltip.prototype.tip = function () { 24331 return this.$tip = this.$tip || $(this.options.template) 24332 } 24333 24334 Tooltip.prototype.arrow = function () { 24335 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 24336 } 24337 24338 Tooltip.prototype.validate = function () { 24339 if (!this.$element[0].parentNode) { 24340 this.hide() 24341 this.$element = null 24342 this.options = null 24343 } 24344 } 24345 24346 Tooltip.prototype.enable = function () { 24347 this.enabled = true 24348 } 24349 24350 Tooltip.prototype.disable = function () { 24351 this.enabled = false 24352 } 24353 24354 Tooltip.prototype.toggleEnabled = function () { 24355 this.enabled = !this.enabled 24356 } 24357 24358 Tooltip.prototype.toggle = function (e) { 24359 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 24360 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 24361 } 24362 24363 Tooltip.prototype.destroy = function () { 24364 clearTimeout(this.timeout) 24365 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 24366 } 24367 24368 24369 // TOOLTIP PLUGIN DEFINITION 24370 // ========================= 24371 24372 var old = $.fn.tooltip 24373 24374 $.fn.tooltip = function (option) { 24375 return this.each(function () { 24376 var $this = $(this) 24377 var data = $this.data('bs.tooltip') 24378 var options = typeof option == 'object' && option 24379 24380 if (!data && option == 'destroy') return 24381 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 24382 if (typeof option == 'string') data[option]() 24383 }) 24384 } 24385 24386 $.fn.tooltip.Constructor = Tooltip 24387 24388 24389 // TOOLTIP NO CONFLICT 24390 // =================== 24391 24392 $.fn.tooltip.noConflict = function () { 24393 $.fn.tooltip = old 24394 return this 24395 } 24396 24397}(jQuery); 24398 24399/* ======================================================================== 24400 * Bootstrap: transition.js v3.1.1 24401 * http://getbootstrap.com/javascript/#transitions 24402 * ======================================================================== 24403 * Copyright 2011-2014 Twitter, Inc. 24404 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 24405 * ======================================================================== */ 24406 24407 24408+function ($) { 24409 'use strict'; 24410 24411 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 24412 // ============================================================ 24413 24414 function transitionEnd() { 24415 var el = document.createElement('bootstrap') 24416 24417 var transEndEventNames = { 24418 WebkitTransition : 'webkitTransitionEnd', 24419 MozTransition : 'transitionend', 24420 OTransition : 'oTransitionEnd otransitionend', 24421 transition : 'transitionend' 24422 } 24423 24424 for (var name in transEndEventNames) { 24425 if (el.style[name] !== undefined) { 24426 return { end: transEndEventNames[name] } 24427 } 24428 } 24429 24430 return false // explicit for ie8 ( ._.) 24431 } 24432 24433 // http://blog.alexmaccaw.com/css-transitions 24434 $.fn.emulateTransitionEnd = function (duration) { 24435 var called = false, $el = this 24436 $(this).one($.support.transition.end, function () { called = true }) 24437 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 24438 setTimeout(callback, duration) 24439 return this 24440 } 24441 24442 $(function () { 24443 $.support.transition = transitionEnd() 24444 }) 24445 24446}(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.