1/* ---------------------------------------------------------- 2 * Plugins 3 * ---------------------------------------------------------- */ 4 5(function(window, $) { 6 'use strict'; 7 var counter = 0, 8 $headCache = $('head'), 9 oldBigText = window.BigText, 10 oldjQueryMethod = $.fn.bigtext, 11 BigText = { 12 DEBUG_MODE: false, 13 DEFAULT_MIN_FONT_SIZE_PX: null, 14 DEFAULT_MAX_FONT_SIZE_PX: 528, 15 GLOBAL_STYLE_ID: 'bigtext-style', 16 STYLE_ID: 'bigtext-id', 17 LINE_CLASS_PREFIX: 'bigtext-line', 18 EXEMPT_CLASS: 'bigtext-exempt', 19 noConflict: function(restore) 20 { 21 if(restore) { 22 $.fn.bigtext = oldjQueryMethod; 23 window.BigText = oldBigText; 24 } 25 return BigText; 26 }, 27 supports: { 28 wholeNumberFontSizeOnly: (function() { 29 if( !( 'getComputedStyle' in window ) ) { 30 return true; 31 } 32 var test = $('<div/>').css({ 33 position: 'absolute', 34 'font-size': '14.1px' 35 }).insertBefore( $('script').eq(0) ), 36 computedStyle = window.getComputedStyle( test[0], null ); 37 38 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 39 test.remove(); 40 return ret; 41 })() 42 }, 43 init: function() { 44 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 45 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 46 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 47 } 48 }, 49 bindResize: function(eventName, resizeFunction) { 50 var timeoutId; 51 $(window).unbind(eventName).bind(eventName, function() { 52 if( timeoutId ) { 53 clearTimeout( timeoutId ); 54 } 55 timeoutId = setTimeout( resizeFunction, 300 ); 56 }); 57 }, 58 getStyleId: function(id) 59 { 60 return BigText.STYLE_ID + '-' + id; 61 }, 62 generateStyleTag: function(id, css) 63 { 64 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 65 }, 66 clearCss: function(id) 67 { 68 var styleId = BigText.getStyleId(id); 69 $('#' + styleId).remove(); 70 }, 71 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 72 { 73 var css = []; 74 75 BigText.clearCss(id); 76 77 for(var j=0, k=linesFontSizes.length; j<k; j++) { 78 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 79 (minFontSizes[j] ? ' white-space: normal;' : '') + 80 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 81 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 82 '}'); 83 } 84 85 return BigText.generateStyleTag(BigText.getStyleId(id), css); 86 }, 87 jQueryMethod: function(options) 88 { 89 BigText.init(); 90 91 options = $.extend({ 92 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 93 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 94 childSelector: '', 95 resize: true 96 }, options || {}); 97 98 this.each(function() 99 { 100 var $t = $(this).addClass('bigtext'), 101 maxWidth = $t.width(), 102 id = $t.attr('id'), 103 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 104 105 if(!id) { 106 id = 'bigtext-id' + (counter++); 107 $t.attr('id', id); 108 } 109 110 if(options.resize) { 111 BigText.bindResize('resize.bigtext-event-' + id, function() 112 { 113 // TODO only call this if the width has changed. 114 BigText.jQueryMethod.call($('#' + id), options); 115 }); 116 } 117 118 BigText.clearCss(id); 119 120 $children.addClass(function(lineNumber, className) 121 { 122 // remove existing line classes. 123 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 124 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 125 }); 126 127 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 128 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 129 }); 130 131 return this.trigger('bigtext:complete'); 132 } 133 }; 134 135 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 136 { 137 var width; 138 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 139 $line.css(property, size + units); 140 141 width = $line.width(); 142 143 if(width >= maxWidth) { 144 145 $line.css(property, ''); 146 147 if(width === maxWidth) { 148 return { 149 match: 'exact', 150 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 151 }; 152 } 153 154 // Since this is an estimate, we calculate how far over the width we went with the new value. 155 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 156 // Otherwise, we revert to the underestimate. 157 var under = maxWidth - previousWidth, 158 over = width - maxWidth; 159 160 return { 161 match: 'estimate', 162 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 163 }; 164 } 165 166 return width; 167 } 168 169 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 170 { 171 var $c = $t.clone(true) 172 .addClass('bigtext-cloned') 173 .css({ 174 fontFamily: $t.css('font-family'), 175 textTransform: $t.css('text-transform'), 176 wordSpacing: $t.css('word-spacing'), 177 letterSpacing: $t.css('letter-spacing'), 178 position: 'absolute', 179 left: BigText.DEBUG_MODE ? 0 : -9999, 180 top: BigText.DEBUG_MODE ? 0 : -9999
181 }) 182 .appendTo(document.body); 183 184 // font-size isn't the only thing we can modify, we can also mess with: 185 // word-spacing and letter-spacing. WebKit does not respect subpixel 186 // letter-spacing, word-spacing, or font-size. 187 // TODO try -webkit-transform: scale() as a workaround. 188 var fontSizes = [], 189 wordSpacings = [], 190 minFontSizes = [], 191 ratios = []; 192 193 $children.css('float', 'left').each(function() { 194 var $line = $(this), 195 // TODO replace 8, 4 with a proportional size to the calculated font-size. 196 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 197 lineMax, 198 newFontSize; 199 200 if($line.hasClass(BigText.EXEMPT_CLASS)) { 201 fontSizes.push(null); 202 ratios.push(null); 203 minFontSizes.push(false); 204 return; 205 } 206 207 // TODO we can cache this ratio? 208 var autoGuessSubtraction = 32, // font size in px 209 currentFontSize = parseFloat($line.css('font-size')), 210 ratio = ( $line.width() / currentFontSize ).toFixed(6); 211 212 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 213 214 outer: for(var m=0, n=intervals.length; m<n; m++) { 215 inner: for(var j=1, k=10; j<=k; j++) { 216 if(newFontSize + j*intervals[m] > maxFontSize) { 217 newFontSize = maxFontSize; 218 break outer; 219 } 220 221 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 222 if(typeof lineMax !== 'number') { 223 newFontSize = lineMax.size; 224 225 if(lineMax.match === 'exact') { 226 break outer; 227 } 228 break inner; 229 } 230 } 231 } 232 233 ratios.push(maxWidth / newFontSize); 234 235 if(newFontSize > maxFontSize) { 236 fontSizes.push(maxFontSize); 237 minFontSizes.push(false); 238 } else if(!!minFontSize && newFontSize < minFontSize) { 239 fontSizes.push(minFontSize); 240 minFontSizes.push(true); 241 } else { 242 fontSizes.push(newFontSize); 243 minFontSizes.push(false); 244 } 245 }).each(function(lineNumber) { 246 var $line = $(this), 247 wordSpacing = 0, 248 interval = 1, 249 maxWordSpacing; 250 251 if($line.hasClass(BigText.EXEMPT_CLASS)) { 252 wordSpacings.push(null); 253 return; 254 } 255 256 // must re-use font-size, even though it was removed above. 257 $line.css('font-size', fontSizes[lineNumber] + 'px'); 258 259 for(var m=1, n=3; m<n; m+=interval) { 260 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 261 if(typeof maxWordSpacing !== 'number') { 262 wordSpacing = maxWordSpacing.size; 263 break; 264 } 265 } 266 267 $line.css('font-size', ''); 268 wordSpacings.push(wordSpacing); 269 }).removeAttr('style'); 270 271 if( !BigText.DEBUG_MODE ) { 272 $c.remove(); 273 } else { 274 $c.css({ 275 'background-color': 'rgba(255,255,255,.4)' 276 }); 277 } 278 279 return { 280 fontSizes: fontSizes, 281 wordSpacings: wordSpacings, 282 ratios: ratios, 283 minFontSizes: minFontSizes 284 }; 285 } 286 287 $.fn.bigtext = BigText.jQueryMethod; 288 window.BigText = BigText; 289 290})(this, jQuery); 291 292/*! 293 * Isotope PACKAGED v2.2.2 294 * 295 * Licensed GPLv3 for open source use 296 * or Isotope Commercial License for commercial use 297 * 298 * http://isotope.metafizzy.co 299 * Copyright 2015 Metafizzy 300 */ 301 302/** 303 * Bridget makes jQuery widgets 304 * v1.1.0 305 * MIT license 306 */ 307 308( function( window ) { 309 310 311 312// -------------------------- utils -------------------------- // 313 314var slice = Array.prototype.slice; 315 316function noop() {} 317 318// -------------------------- definition -------------------------- // 319 320function defineBridget( $ ) { 321 322// bail if no jQuery 323if ( !$ ) { 324 return; 325} 326 327// -------------------------- addOptionMethod -------------------------- // 328 329/** 330 * adds option method -> $().plugin('option', {...}) 331 * @param {Function} PluginClass - constructor class 332 */ 333function addOptionMethod( PluginClass ) { 334 // don't overwrite original option method 335 if ( PluginClass.prototype.option ) { 336 return; 337 } 338 339 // option setter 340 PluginClass.prototype.option = function( opts ) { 341 // bail out if not an object 342 if ( !$.isPlainObject( opts ) ){ 343 return; 344 } 345 this.options = $.extend( true, this.options, opts ); 346 }; 347} 348 349// -------------------------- plugin bridge -------------------------- // 350 351// helper function for logging errors 352// $.error breaks jQuery chaining 353var logError = typeof console === 'undefined' ? noop : 354 function( message ) { 355 console.error( message ); 356 }; 357 358/** 359 * jQuery plugin bridge, access methods like $elem.plugin('method') 360 * @param {String} namespace - plugin name 361 * @param {Function} PluginClass - constructor class 362 */ 363function bridge( namespace, PluginClass ) { 364 // add to jQuery fn namespace 365 $.fn[ namespace ] = function( options ) { 366 if ( typeof options === 'string' ) { 367 // call plugin method when first argument is a string 368 // get arguments for method 369 var args = slice.call( arguments, 1 ); 370 371 for ( var i=0, len = this.length; i < len; i++ ) { 372 var elem = this[i]; 373 var instance = $.data( elem, namespace ); 374 if ( !instance ) { 375 logError( "cannot call methods on " + namespace + " prior to initialization; " + 376 "attempted to call '" + options + "'" ); 377 continue; 378 } 379 if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { 380 logError( "no such method '" + options + "' for " + namespace + " instance" ); 381 continue; 382 } 383 384 // trigger method with arguments 385 var returnValue = instance[ options ].apply( instance, args ); 386 387 // break look and return first value if provided 388 if ( returnValue !== undefined ) { 389 return returnValue; 390 } 391 } 392 // return this if no return value 393 return this; 394 } else { 395 return this.each( function() { 396 var instance = $.data( this, namespace ); 397 if ( instance ) { 398 // apply options & init 399 instance.option( options ); 400 instance._init(); 401 } else { 402 // initialize new instance 403 instance = new PluginClass( this, options ); 404 $.data( this, namespace, instance ); 405 } 406 }); 407 } 408 }; 409 410} 411 412// -------------------------- bridget -------------------------- // 413 414/** 415 * converts a Prototypical class into a proper jQuery plugin 416 * the class must have a ._init method 417 * @param {String} namespace - plugin name, used in $().pluginName 418 * @param {Function} PluginClass - constructor class 419 */ 420$.bridget = function( namespace, PluginClass ) { 421 addOptionMethod( PluginClass ); 422 bridge( namespace, PluginClass ); 423}; 424 425return $.bridget; 426 427} 428 429// transport 430if ( typeof define === 'function' && define.amd ) { 431 // AMD 432 define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget ); 433} else if ( typeof exports === 'object' ) { 434 defineBridget( require('jquery') ); 435} else { 436 // get jquery from browser global 437 defineBridget( window.jQuery ); 438} 439 440})( window ); 441 442/*! 443 * eventie v1.0.6 444 * event binding helper 445 * eventie.bind( elem, 'click', myFn ) 446 * eventie.unbind( elem, 'click', myFn ) 447 * MIT license 448 */ 449 450/*jshint browser: true, undef: true, unused: true */ 451/*global define: false, module: false */ 452 453( function( window ) { 454 455 456 457var docElem = document.documentElement; 458 459var bind = function() {}; 460 461function getIEEvent( obj ) { 462 var event = window.event; 463 // add event.target 464 event.target = event.target || event.srcElement || obj; 465 return event; 466} 467 468if ( docElem.addEventListener ) { 469 bind = function( obj, type, fn ) { 470 obj.addEventListener( type, fn, false ); 471 }; 472} else if ( docElem.attachEvent ) { 473 bind = function( obj, type, fn ) { 474 obj[ type + fn ] = fn.handleEvent ? 475 function() { 476 var event = getIEEvent( obj ); 477 fn.handleEvent.call( fn, event ); 478 } : 479 function() { 480 var event = getIEEvent( obj ); 481 fn.call( obj, event ); 482 }; 483 obj.attachEvent( "on" + type, obj[ type + fn ] ); 484 }; 485} 486 487var unbind = function() {}; 488 489if ( docElem.removeEventListener ) { 490 unbind = function( obj, type, fn ) { 491 obj.removeEventListener( type, fn, false ); 492 }; 493} else if ( docElem.detachEvent ) { 494 unbind = function( obj, type, fn ) { 495 obj.detachEvent( "on" + type, obj[ type + fn ] ); 496 try { 497 delete obj[ type + fn ]; 498 } catch ( err ) { 499 // can't delete window object properties 500 obj[ type + fn ] = undefined; 501 } 502 }; 503} 504 505var eventie = { 506 bind: bind, 507 unbind: unbind 508}; 509 510// ----- module definition ----- // 511 512if ( typeof define === 'function' && define.amd ) { 513 // AMD 514 define( 'eventie/eventie',eventie ); 515} else if ( typeof exports === 'object' ) { 516 // CommonJS 517 module.exports = eventie; 518} else { 519 // browser global 520 window.eventie = eventie; 521} 522 523})( window ); 524 525/*! 526 * EventEmitter v4.2.11 - git.io/ee 527 * Unlicense - http://unlicense.org/ 528 * Oliver Caldwell - http://oli.me.uk/ 529 * @preserve 530 */ 531 532;(function () { 533 'use strict'; 534 535 /** 536 * Class for managing events. 537 * Can be extended to provide event functionality in other classes. 538 * 539 * @class EventEmitter Manages event registering and emitting. 540 */ 541 function EventEmitter() {} 542 543 // Shortcuts to improve speed and size 544 var proto = EventEmitter.prototype; 545 var exports = this; 546 var originalGlobalValue = exports.EventEmitter; 547 548 /** 549 * Finds the index of the listener for the event in its storage array. 550 * 551 * @param {Function[]} listeners Array of listeners to search through. 552 * @param {Function} listener Method to look for. 553 * @return {Number} Index of the specified listener, -1 if not found 554 * @api private 555 */ 556 function indexOfListener(listeners, listener) { 557 var i = listeners.length; 558 while (i--) { 559 if (listeners[i].listener === listener) { 560 return i; 561 } 562 } 563 564 return -1; 565 } 566 567 /** 568 * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 568-971
568writing of target method. 569 * 570 * @param {String} name The name of the target method. 571 * @return {Function} The aliased method 572 * @api private 573 */ 574 function alias(name) { 575 return function aliasClosure() { 576 return this[name].apply(this, arguments); 577 }; 578 } 579 580 /** 581 * Returns the listener array for the specified event. 582 * Will initialise the event object and listener arrays if required. 583 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. 584 * Each property in the object response is an array of listener functions. 585 * 586 * @param {String|RegExp} evt Name of the event to return the listeners from. 587 * @return {Function[]|Object} All listener functions for the event. 588 */ 589 proto.getListeners = function getListeners(evt) { 590 var events = this._getEvents(); 591 var response; 592 var key; 593 594 // Return a concatenated array of all matching events if 595 // the selector is a regular expression. 596 if (evt instanceof RegExp) { 597 response = {}; 598 for (key in events) { 599 if (events.hasOwnProperty(key) && evt.test(key)) { 600 response[key] = events[key]; 601 } 602 } 603 } 604 else { 605 response = events[evt] || (events[evt] = []); 606 } 607 608 return response; 609 }; 610 611 /** 612 * Takes a list of listener objects and flattens it into a list of listener functions. 613 * 614 * @param {Object[]} listeners Raw listener objects. 615 * @return {Function[]} Just the listener functions. 616 */ 617 proto.flattenListeners = function flattenListeners(listeners) { 618 var flatListeners = []; 619 var i; 620 621 for (i = 0; i < listeners.length; i += 1) { 622 flatListeners.push(listeners[i].listener); 623 } 624 625 return flatListeners; 626 }; 627 628 /** 629 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. 630 * 631 * @param {String|RegExp} evt Name of the event to return the listeners from. 632 * @return {Object} All listener functions for an event in an object. 633 */ 634 proto.getListenersAsObject = function getListenersAsObject(evt) { 635 var listeners = this.getListeners(evt); 636 var response; 637 638 if (listeners instanceof Array) { 639 response = {}; 640 response[evt] = listeners; 641 } 642 643 return response || listeners; 644 }; 645 646 /** 647 * Adds a listener function to the specified event. 648 * The listener will not be added if it is a duplicate. 649 * If the listener returns true then it will be removed after it is called. 650 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 651 * 652 * @param {String|RegExp} evt Name of the event to attach the listener to. 653 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 654 * @return {Object} Current instance of EventEmitter for chaining. 655 */ 656 proto.addListener = function addListener(evt, listener) { 657 var listeners = this.getListenersAsObject(evt); 658 var listenerIsWrapped = typeof listener === 'object'; 659 var key; 660 661 for (key in listeners) { 662 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 663 listeners[key].push(listenerIsWrapped ? listener : { 664 listener: listener, 665 once: false 666 }); 667 } 668 } 669 670 return this; 671 }; 672 673 /** 674 * Alias of addListener 675 */ 676 proto.on = alias('addListener'); 677 678 /** 679 * Semi-alias of addListener. It will add a listener that will be 680 * automatically removed after its first execution. 681 * 682 * @param {String|RegExp} evt Name of the event to attach the listener to. 683 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 684 * @return {Object} Current instance of EventEmitter for chaining. 685 */ 686 proto.addOnceListener = function addOnceListener(evt, listener) { 687 return this.addListener(evt, { 688 listener: listener, 689 once: true 690 }); 691 }; 692 693 /** 694 * Alias of addOnceListener. 695 */ 696 proto.once = alias('addOnceListener'); 697 698 /** 699 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. 700 * You need to tell it what event names should be matched by a regex. 701 * 702 * @param {String} evt Name of the event to create. 703 * @return {Object} Current instance of EventEmitter for chaining. 704 */ 705 proto.defineEvent = function defineEvent(evt) { 706 this.getListeners(evt); 707 return this; 708 }; 709 710 /** 711 * Uses defineEvent to define multiple events. 712 * 713 * @param {String[]} evts An array of event names to define. 714 * @return {Object} Current instance of EventEmitter for chaining. 715 */ 716 proto.defineEvents = function defineEvents(evts) { 717 for (var i = 0; i < evts.length; i += 1) { 718 this.defineEvent(evts[i]); 719 } 720 return this; 721 }; 722 723 /** 724 * Removes a listener function from the specified event. 725 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 726 * 727 * @param {String|RegExp} evt Name of the event to remove the listener from. 728 * @param {Function} listener Method to remove from the event. 729 * @return {Object} Current instance of EventEmitter for chaining. 730 */ 731 proto.removeListener = function removeListener(evt, listener) { 732 var listeners = this.getListenersAsObject(evt); 733 var index; 734 var key; 735 736 for (key in listeners) { 737 if (listeners.hasOwnProperty(key)) { 738 index = indexOfListener(listeners[key], listener); 739 740 if (index !== -1) { 741 listeners[key].splice(index, 1); 742 } 743 } 744 } 745 746 return this; 747 }; 748 749 /** 750 * Alias of removeListener 751 */ 752 proto.off = alias('removeListener'); 753 754 /** 755 * Adds listeners in bulk using the manipulateListeners method. 756 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. 757 * You can also pass it a regular expression to add the array of listeners to all events that match it. 758 * Yeah, this function does quite a bit. That's probably a bad thing. 759 * 760 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. 761 * @param {Function[]} [listeners] An optional array of listener functions to add. 762 * @return {Object} Current instance of EventEmitter for chaining. 763 */ 764 proto.addListeners = function addListeners(evt, listeners) { 765 // Pass through to manipulateListeners 766 return this.manipulateListeners(false, evt, listeners); 767 }; 768 769 /** 770 * Removes listeners in bulk using the manipulateListeners method. 771 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 772 * You can also pass it an event name and an array of listeners to be removed. 773 * You can also pass it a regular expression to remove the listeners from all events that match it. 774 * 775 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. 776 * @param {Function[]} [listeners] An optional array of listener functions to remove. 777 * @return {Object} Current instance of EventEmitter for chaining. 778 */ 779 proto.removeListeners = function removeListeners(evt, listeners) { 780 // Pass through to manipulateListeners 781 return this.manipulateListeners(true, evt, listeners); 782 }; 783 784 /** 785 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. 786 * The first argument will determine if the listeners are removed (true) or added (false). 787 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 788 * You can also pass it an event name and an array of listeners to be added/removed. 789 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 790 * 791 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 792 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. 793 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 794 * @return {Object} Current instance of EventEmitter for chaining. 795 */ 796 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 797 var i; 798 var value; 799 var single = remove ? this.removeListener : this.addListener; 800 var multiple = remove ? this.removeListeners : this.addListeners; 801 802 // If evt is an object then pass each of its properties to this method 803 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 804 for (i in evt) { 805 if (evt.hasOwnProperty(i) && (value = evt[i])) { 806 // Pass the single listener straight through to the singular method 807 if (typeof value === 'function') { 808 single.call(this, i, value); 809 } 810 else { 811 // Otherwise pass back to the multiple function 812 multiple.call(this, i, value); 813 } 814 } 815 } 816 } 817 else { 818 // So evt must be a string 819 // And listeners must be an array of listeners 820 // Loop over it and pass each one to the multiple method 821 i = listeners.length; 822 while (i--) { 823 single.call(this, evt, listeners[i]); 824 } 825 } 826 827 return this; 828 }; 829 830 /** 831 * Removes all listeners from a specified event. 832 * If you do not specify an event then all listeners will be removed. 833 * That means every event will be emptied. 834 * You can also pass a regex to remove all events that match it. 835 * 836 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 837 * @return {Object} Current instance of EventEmitter for chaining. 838 */ 839 proto.removeEvent = function removeEvent(evt) { 840 var type = typeof evt; 841 var events = this._getEvents(); 842 var key; 843 844 // Remove different things depending on the state of evt 845 if (type === 'string') { 846 // Remove all listeners for the specified event 847 delete events[evt]; 848 } 849 else if (evt instanceof RegExp) { 850 // Remove all events matching the regex. 851 for (key in events) { 852 if (events.hasOwnProperty(key) && evt.test(key)) { 853 delete events[key]; 854 } 855 } 856 } 857 else { 858 // Remove all listeners in all events 859 delete this._events; 860 } 861 862 return this; 863 }; 864 865 /** 866 * Alias of removeEvent. 867 * 868 * Added to mirror the node API. 869 */ 870 proto.removeAllListeners = alias('removeEvent'); 871 872 /** 873 * Emits an event of your choice. 874 * When emitted, every listener attached to that event will be executed. 875 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 876 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. 877 * So they will not arrive within the array on the other side, they will be separate. 878 * You can also pass a regular expression to emit to all events that match it. 879 * 880 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 881 * @param {Array} [args] Optional array of arguments to be passed to each listener. 882 * @return {Object} Current instance of EventEmitter for chaining. 883 */ 884 proto.emitEvent = function emitEvent(evt, args) { 885 var listeners = this.getListenersAsObject(evt); 886 var listener; 887 var i; 888 var key; 889 var response; 890 891 for (key in listeners) { 892 if (listeners.hasOwnProperty(key)) { 893 i = listeners[key].length; 894 895 while (i--) { 896 // If the listener returns true then it shall be removed from the event 897 // The function is executed either with a basic call or an apply if there is an args array 898 listener = listeners[key][i]; 899 900 if (listener.once === true) { 901 this.removeListener(evt, listener.listener); 902 } 903 904 response = listener.listener.apply(this, args || []); 905 906 if (response === this._getOnceReturnValue()) { 907 this.removeListener(evt, listener.listener); 908 } 909 } 910 } 911 } 912 913 return this; 914 }; 915 916 /** 917 * Alias of emitEvent 918 */ 919 proto.trigger = alias('emitEvent'); 920 921 /** 922 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. 923 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 924 * 925 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 926 * @param {...*} Optional additional arguments to be passed to each listener. 927 * @return {Object} Current instance of EventEmitter for chaining. 928 */ 929 proto.emit = function emit(evt) { 930 var args = Array.prototype.slice.call(arguments, 1); 931 return this.emitEvent(evt, args); 932 }; 933 934 /** 935 * Sets the current value to check against when executing listeners. If a 936 * listeners return value matches the one set here then it will be removed 937 * after execution. This value defaults to true. 938 * 939 * @param {*} value The new value to check for when executing listeners. 940 * @return {Object} Current instance of EventEmitter for chaining. 941 */ 942 proto.setOnceReturnValue = function setOnceReturnValue(value) { 943 this._onceReturnValue = value; 944 return this; 945 }; 946 947 /** 948 * Fetches the current value to check against when executing listeners. If 949 * the listeners return value matches this one then it should be removed 950 * automatically. It will return true by default. 951 * 952 * @return {*|Boolean} The current value to check for or the default, true. 953 * @api private 954 */ 955 proto._getOnceReturnValue = function _getOnceReturnValue() { 956 if (this.hasOwnProperty('_onceReturnValue')) { 957 return this._onceReturnValue; 958 } 959 else { 960 return true; 961 } 962 }; 963 964 /** 965 * Fetches the events object and creates one if required. 966 * 967 * @return {Object} The events storage object. 968 * @api private 969 */ 970 proto._getEvents = function _getEvents() { 971 return this._events || (this
971._events = {}); 972 }; 973 974 /** 975 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. 976 * 977 * @return {Function} Non conflicting EventEmitter class. 978 */ 979 EventEmitter.noConflict = function noConflict() { 980 exports.EventEmitter = originalGlobalValue; 981 return EventEmitter; 982 }; 983 984 // Expose the class either via AMD, CommonJS or the global object 985 if (typeof define === 'function' && define.amd) { 986 define('eventEmitter/EventEmitter',[],function () { 987 return EventEmitter; 988 }); 989 } 990 else if (typeof module === 'object' && module.exports){ 991 module.exports = EventEmitter; 992 } 993 else { 994 exports.EventEmitter = EventEmitter; 995 } 996}.call(this)); 997 998/*! 999 * getStyleProperty v1.0.4 1000 * original by kangax 1001 * http://perfectionkills.com/feature-testing-css-properties/ 1002 * MIT license 1003 */ 1004 1005/*jshint browser: true, strict: true, undef: true */ 1006/*global define: false, exports: false, module: false */ 1007 1008( function( window ) { 1009 1010 1011 1012var prefixes = 'Webkit Moz ms Ms O'.split(' '); 1013var docElemStyle = document.documentElement.style; 1014 1015function getStyleProperty( propName ) { 1016 if ( !propName ) { 1017 return; 1018 } 1019 1020 // test standard property first 1021 if ( typeof docElemStyle[ propName ] === 'string' ) { 1022 return propName; 1023 } 1024 1025 // capitalize 1026 propName = propName.charAt(0).toUpperCase() + propName.slice(1); 1027 1028 // test vendor specific properties 1029 var prefixed; 1030 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1031 prefixed = prefixes[i] + propName; 1032 if ( typeof docElemStyle[ prefixed ] === 'string' ) { 1033 return prefixed; 1034 } 1035 } 1036} 1037 1038// transport 1039if ( typeof define === 'function' && define.amd ) { 1040 // AMD 1041 define( 'get-style-property/get-style-property',[],function() { 1042 return getStyleProperty; 1043 }); 1044} else if ( typeof exports === 'object' ) { 1045 // CommonJS for Component 1046 module.exports = getStyleProperty; 1047} else { 1048 // browser global 1049 window.getStyleProperty = getStyleProperty; 1050} 1051 1052})( window ); 1053 1054/*! 1055 * getSize v1.2.2 1056 * measure size of elements 1057 * MIT license 1058 */ 1059 1060/*jshint browser: true, strict: true, undef: true, unused: true */ 1061/*global define: false, exports: false, require: false, module: false, console: false */ 1062 1063( function( window, undefined ) { 1064 1065 1066 1067// -------------------------- helpers -------------------------- // 1068 1069// get a number from a string, not a percentage 1070function getStyleSize( value ) { 1071 var num = parseFloat( value ); 1072 // not a percent like '100%', and a number 1073 var isValid = value.indexOf('%') === -1 && !isNaN( num ); 1074 return isValid && num; 1075} 1076 1077function noop() {} 1078 1079var logError = typeof console === 'undefined' ? noop : 1080 function( message ) { 1081 console.error( message ); 1082 }; 1083 1084// -------------------------- measurements -------------------------- // 1085 1086var measurements = [ 1087 'paddingLeft', 1088 'paddingRight', 1089 'paddingTop', 1090 'paddingBottom', 1091 'marginLeft', 1092 'marginRight', 1093 'marginTop', 1094 'marginBottom', 1095 'borderLeftWidth', 1096 'borderRightWidth', 1097 'borderTopWidth', 1098 'borderBottomWidth' 1099]; 1100 1101function getZeroSize() { 1102 var size = { 1103 width: 0, 1104 height: 0, 1105 innerWidth: 0, 1106 innerHeight: 0, 1107 outerWidth: 0, 1108 outerHeight: 0 1109 }; 1110 for ( var i=0, len = measurements.length; i < len; i++ ) { 1111 var measurement = measurements[i]; 1112 size[ measurement ] = 0; 1113 } 1114 return size; 1115} 1116 1117 1118 1119function defineGetSize( getStyleProperty ) { 1120 1121// -------------------------- setup -------------------------- // 1122 1123var isSetup = false; 1124 1125var getStyle, boxSizingProp, isBoxSizeOuter; 1126 1127/** 1128 * setup vars and functions 1129 * do it on initial getSize(), rather than on script load 1130 * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397 1131 */ 1132function setup() { 1133 // setup once 1134 if ( isSetup ) { 1135 return; 1136 } 1137 isSetup = true; 1138 1139 var getComputedStyle = window.getComputedStyle; 1140 getStyle = ( function() { 1141 var getStyleFn = getComputedStyle ? 1142 function( elem ) { 1143 return getComputedStyle( elem, null ); 1144 } : 1145 function( elem ) { 1146 return elem.currentStyle; 1147 }; 1148 1149 return function getStyle( elem ) { 1150 var style = getStyleFn( elem ); 1151 if ( !style ) { 1152 logError( 'Style returned ' + style + 1153 '. Are you running this code in a hidden iframe on Firefox? ' + 1154 'See http://bit.ly/getsizebug1' ); 1155 } 1156 return style; 1157 }; 1158 })(); 1159 1160 // -------------------------- box sizing -------------------------- // 1161 1162 boxSizingProp = getStyleProperty('boxSizing'); 1163 1164 /** 1165 * WebKit measures the outer-width on style.width on border-box elems 1166 * IE & Firefox measures the inner-width 1167 */ 1168 if ( boxSizingProp ) { 1169 var div = document.createElement('div'); 1170 div.style.width = '200px'; 1171 div.style.padding = '1px 2px 3px 4px'; 1172 div.style.borderStyle = 'solid'; 1173 div.style.borderWidth = '1px 2px 3px 4px'; 1174 div.style[ boxSizingProp ] = 'border-box'; 1175 1176 var body = document.body || document.documentElement; 1177 body.appendChild( div ); 1178 var style = getStyle( div ); 1179 1180 isBoxSizeOuter = getStyleSize( style.width ) === 200; 1181 body.removeChild( div ); 1182 } 1183 1184} 1185 1186// -------------------------- getSize -------------------------- // 1187 1188function getSize( elem ) { 1189 setup(); 1190 1191 // use querySeletor if elem is string 1192 if ( typeof elem === 'string' ) { 1193 elem = document.querySelector( elem ); 1194 } 1195 1196 // do not proceed on non-objects 1197 if ( !elem || typeof elem !== 'object' || !elem.nodeType ) { 1198 return; 1199 } 1200 1201 var style = getStyle( elem ); 1202 1203 // if hidden, everything is 0 1204 if ( style.display === 'none' ) { 1205 return getZeroSize(); 1206 } 1207 1208 var size = {}; 1209 size.width = elem.offsetWidth; 1210 size.height = elem.offsetHeight; 1211 1212 var isBorderBox = size.isBorderBox = !!( boxSizingProp && 1213 style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' ); 1214 1215 // get all measurements 1216 for ( var i=0, len = measurements.length; i < len; i++ ) { 1217 var measurement = measurements[i]; 1218 var value = style[ measurement ]; 1219 value = mungeNonPixel( elem, value ); 1220 var num = parseFloat( value ); 1221 // any 'auto', 'medium' value will be 0 1222 size[ measurement ] = !isNaN( num ) ? num : 0; 1223 } 1224 1225 var paddingWidth = size.paddingLeft + size.paddingRight; 1226 var paddingHeight = size.paddingTop + size.paddingBottom; 1227 var marginWidth = size.marginLeft + size.marginRight; 1228 var marginHeight = size.marginTop + size.marginBottom; 1229 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 1230 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 1231 1232 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 1233 1234 // overwrite width and height if we can get it from style 1235 var styleWidth = getStyleSize( style.width ); 1236 if ( styleWidth !== false ) { 1237 size.width = styleWidth + 1238 // add padding and border unless it's already including it 1239 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 1240 } 1241 1242 var styleHeight = getStyleSize( style.height ); 1243 if ( styleHeight !== false ) { 1244 size.height = styleHeight + 1245 // add padding and border unless it's already including it 1246 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 1247 } 1248 1249 size.innerWidth = size.width - ( paddingWidth + borderWidth );
1250 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 1251 1252 size.outerWidth = size.width + marginWidth; 1253 size.outerHeight = size.height + marginHeight; 1254 1255 return size; 1256} 1257 1258// IE8 returns percent values, not pixels 1259// taken from jQuery's curCSS 1260function mungeNonPixel( elem, value ) { 1261 // IE8 and has percent value 1262 if ( window.getComputedStyle || value.indexOf('%') === -1 ) { 1263 return value; 1264 } 1265 var style = elem.style; 1266 // Remember the original values 1267 var left = style.left; 1268 var rs = elem.runtimeStyle; 1269 var rsLeft = rs && rs.left; 1270 1271 // Put in the new values to get a computed value out 1272 if ( rsLeft ) { 1273 rs.left = elem.currentStyle.left; 1274 } 1275 style.left = value; 1276 value = style.pixelLeft; 1277 1278 // Revert the changed values 1279 style.left = left; 1280 if ( rsLeft ) { 1281 rs.left = rsLeft; 1282 } 1283 1284 return value; 1285} 1286 1287return getSize; 1288 1289} 1290 1291// transport 1292if ( typeof define === 'function' && define.amd ) { 1293 // AMD for RequireJS 1294 define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize ); 1295} else if ( typeof exports === 'object' ) { 1296 // CommonJS for Component 1297 module.exports = defineGetSize( require('desandro-get-style-property') ); 1298} else { 1299 // browser global 1300 window.getSize = defineGetSize( window.getStyleProperty ); 1301} 1302 1303})( window ); 1304 1305/*! 1306 * docReady v1.0.4 1307 * Cross browser DOMContentLoaded event emitter 1308 * MIT license 1309 */ 1310 1311/*jshint browser: true, strict: true, undef: true, unused: true*/ 1312/*global define: false, require: false, module: false */ 1313 1314( function( window ) { 1315 1316 1317 1318var document = window.document; 1319// collection of functions to be triggered on ready 1320var queue = []; 1321 1322function docReady( fn ) { 1323 // throw out non-functions 1324 if ( typeof fn !== 'function' ) { 1325 return; 1326 } 1327 1328 if ( docReady.isReady ) { 1329 // ready now, hit it 1330 fn(); 1331 } else { 1332 // queue function when ready 1333 queue.push( fn ); 1334 } 1335} 1336 1337docReady.isReady = false; 1338 1339// triggered on various doc ready events 1340function onReady( event ) { 1341 // bail if already triggered or IE8 document is not ready just yet 1342 var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete'; 1343 if ( docReady.isReady || isIE8NotReady ) { 1344 return; 1345 } 1346 1347 trigger(); 1348} 1349 1350function trigger() { 1351 docReady.isReady = true; 1352 // process queue 1353 for ( var i=0, len = queue.length; i < len; i++ ) { 1354 var fn = queue[i]; 1355 fn(); 1356 } 1357} 1358 1359function defineDocReady( eventie ) { 1360 // trigger ready if page is ready 1361 if ( document.readyState === 'complete' ) { 1362 trigger(); 1363 } else { 1364 // listen for events 1365 eventie.bind( document, 'DOMContentLoaded', onReady ); 1366 eventie.bind( document, 'readystatechange', onReady ); 1367 eventie.bind( window, 'load', onReady ); 1368 } 1369 1370 return docReady; 1371} 1372 1373// transport 1374if ( typeof define === 'function' && define.amd ) { 1375 // AMD 1376 define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady ); 1377} else if ( typeof exports === 'object' ) { 1378 module.exports = defineDocReady( require('eventie') ); 1379} else { 1380 // browser global 1381 window.docReady = defineDocReady( window.eventie ); 1382} 1383 1384})( window ); 1385 1386/** 1387 * matchesSelector v1.0.3 1388 * matchesSelector( element, '.selector' ) 1389 * MIT license 1390 */ 1391 1392/*jshint browser: true, strict: true, undef: true, unused: true */ 1393/*global define: false, module: false */ 1394 1395( function( ElemProto ) { 1396 1397 'use strict'; 1398 1399 var matchesMethod = ( function() { 1400 // check for the standard method name first 1401 if ( ElemProto.matches ) { 1402 return 'matches'; 1403 } 1404 // check un-prefixed 1405 if ( ElemProto.matchesSelector ) { 1406 return 'matchesSelector'; 1407 } 1408 // check vendor prefixes 1409 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 1410 1411 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1412 var prefix = prefixes[i]; 1413 var method = prefix + 'MatchesSelector'; 1414 if ( ElemProto[ method ] ) { 1415 return method; 1416 } 1417 } 1418 })(); 1419 1420 // ----- match ----- // 1421 1422 function match( elem, selector ) { 1423 return elem[ matchesMethod ]( selector ); 1424 } 1425 1426 // ----- appendToFragment ----- // 1427 1428 function checkParent( elem ) { 1429 // not needed if already has parent 1430 if ( elem.parentNode ) { 1431 return; 1432 } 1433 var fragment = document.createDocumentFragment(); 1434 fragment.appendChild( elem ); 1435 } 1436 1437 // ----- query ----- // 1438 1439 // fall back to using QSA 1440 // thx @jonathantneal https://gist.github.com/3062955 1441 function query( elem, selector ) { 1442 // append to fragment if no parent 1443 checkParent( elem ); 1444 1445 // match elem with all selected elems of parent 1446 var elems = elem.parentNode.querySelectorAll( selector ); 1447 for ( var i=0, len = elems.length; i < len; i++ ) { 1448 // return true if match 1449 if ( elems[i] === elem ) { 1450 return true; 1451 } 1452 } 1453 // otherwise return false 1454 return false;
1455 } 1456 1457 // ----- matchChild ----- // 1458 1459 function matchChild( elem, selector ) { 1460 checkParent( elem ); 1461 return match( elem, selector ); 1462 } 1463 1464 // ----- matchesSelector ----- // 1465 1466 var matchesSelector; 1467 1468 if ( matchesMethod ) { 1469 // IE9 supports matchesSelector, but doesn't work on orphaned elems 1470 // check for that 1471 var div = document.createElement('div'); 1472 var supportsOrphans = match( div, 'div' ); 1473 matchesSelector = supportsOrphans ? match : matchChild; 1474 } else { 1475 matchesSelector = query; 1476 } 1477 1478 // transport 1479 if ( typeof define === 'function' && define.amd ) { 1480 // AMD 1481 define( 'matches-selector/matches-selector',[],function() { 1482 return matchesSelector; 1483 }); 1484 } else if ( typeof exports === 'object' ) { 1485 module.exports = matchesSelector; 1486 } 1487 else { 1488 // browser global 1489 window.matchesSelector = matchesSelector; 1490 } 1491 1492})( Element.prototype ); 1493 1494/** 1495 * Fizzy UI utils v1.0.1 1496 * MIT license 1497 */ 1498 1499/*jshint browser: true, undef: true, unused: true, strict: true */ 1500 1501( function( window, factory ) { 1502 /*global define: false, module: false, require: false */ 1503 'use strict'; 1504 // universal module definition 1505 1506 if ( typeof define == 'function' && define.amd ) { 1507 // AMD 1508 define( 'fizzy-ui-utils/utils',[ 1509 'doc-ready/doc-ready', 1510 'matches-selector/matches-selector' 1511 ], function( docReady, matchesSelector ) { 1512 return factory( window, docReady, matchesSelector ); 1513 }); 1514 } else if ( typeof exports == 'object' ) { 1515 // CommonJS 1516 module.exports = factory( 1517 window, 1518 require('doc-ready'), 1519 require('desandro-matches-selector') 1520 ); 1521 } else { 1522 // browser global 1523 window.fizzyUIUtils = factory( 1524 window, 1525 window.docReady, 1526 window.matchesSelector 1527 ); 1528 } 1529 1530}( window, function factory( window, docReady, matchesSelector ) { 1531 1532 1533 1534var utils = {}; 1535 1536// ----- extend ----- // 1537 1538// extends objects 1539utils.extend = function( a, b ) { 1540 for ( var prop in b ) { 1541 a[ prop ] = b[ prop ]; 1542 } 1543 return a; 1544}; 1545 1546// ----- modulo ----- // 1547 1548utils.modulo = function( num, div ) { 1549 return ( ( num % div ) + div ) % div; 1550}; 1551 1552// ----- isArray ----- // 1553 1554var objToString = Object.prototype.toString; 1555utils.isArray = function( obj ) { 1556 return objToString.call( obj ) == '[object Array]'; 1557}; 1558 1559// ----- makeArray ----- // 1560 1561// turn element or nodeList into an array 1562utils.makeArray = function( obj ) { 1563 var ary = []; 1564 if ( utils.isArray( obj ) ) { 1565 // use object if already an array 1566 ary = obj; 1567 } else if ( obj && typeof obj.length == 'number' ) { 1568 // convert nodeList to array 1569 for ( var i=0, len = obj.length; i < len; i++ ) { 1570 ary.push( obj[i] ); 1571 } 1572 } else { 1573 // array of single index 1574 ary.push( obj ); 1575 } 1576 return ary; 1577}; 1578 1579// ----- indexOf ----- // 1580 1581// index of helper cause IE8 1582utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) { 1583 return ary.indexOf( obj ); 1584 } : function( ary, obj ) { 1585 for ( var i=0, len = ary.length; i < len; i++ ) { 1586 if ( ary[i] === obj ) { 1587 return i; 1588 } 1589 } 1590 return -1; 1591 }; 1592 1593// ----- removeFrom ----- // 1594 1595utils.removeFrom = function( ary, obj ) { 1596 var index = utils.indexOf( ary, obj ); 1597 if ( index != -1 ) { 1598 ary.splice( index, 1 ); 1599 } 1600}; 1601 1602// ----- isElement ----- // 1603 1604// http://stackoverflow.com/a/384380/182183 1605utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ? 1606 function isElementDOM2( obj ) { 1607 return obj instanceof HTMLElement; 1608 } : 1609 function isElementQuirky( obj ) { 1610 return obj && typeof obj == 'object' && 1611 obj.nodeType == 1 && typeof obj.nodeName == 'string'; 1612 }; 1613 1614// ----- setText ----- // 1615 1616utils.setText = ( function() { 1617 var setTextProperty; 1618 function setText( elem, text ) { 1619 // only check setTextProperty once 1620 setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' ); 1621 elem[ setTextProperty ] = text; 1622 } 1623 return setText; 1624})(); 1625 1626// ----- getParent ----- // 1627 1628utils.getParent = function( elem, selector ) { 1629 while ( elem != document.body ) { 1630 elem = elem.parentNode; 1631 if ( matchesSelector( elem, selector ) ) { 1632 return elem; 1633 } 1634 } 1635}; 1636 1637// ----- getQueryElement ----- // 1638 1639// use element as selector string 1640utils.getQueryElement = function( elem ) { 1641 if ( typeof elem == 'string' ) { 1642 return document.querySelector( elem ); 1643 } 1644 return elem; 1645}; 1646 1647// ----- handleEvent ----- // 1648 1649// enable .ontype to trigger from .addEventListener( elem, 'type' ) 1650utils.handleEvent = function( event ) { 1651 var method = 'on' + event.type; 1652 if ( this[ method ] ) { 1653 this[ method ]( event ); 1654 } 1655}; 1656 1657// ----- filterFindElements ----- // 1658 1659utils.filterFindElements = function( elems, selector ) { 1660 // make array of elems 1661 elems = utils.makeArray( elems ); 1662 var ffElems = []; 1663 1664 for ( var i=0, len = elems.length; i < len; i++ ) { 1665 var elem = elems[i]; 1666 // check that elem is an actual element 1667 if ( !utils.isElement( elem ) ) { 1668 continue; 1669 } 1670 // filter & find items if we have a selector 1671 if ( selector ) { 1672 // filter siblings 1673 if ( matchesSelector( elem, selector ) ) { 1674 ffElems.push( elem ); 1675 } 1676 // find children 1677 var childElems = elem.querySelectorAll( selector ); 1678 // concat childElems to filterFound array 1679 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 1680 ffElems.push( childElems[j] ); 1681 } 1682 } else { 1683 ffElems.push( elem ); 1684 } 1685 } 1686 1687 return ffElems; 1688}; 1689 1690// ----- debounceMethod ----- // 1691 1692utils.debounceMethod = function( _class, methodName, threshold ) { 1693 // original method 1694 var method = _class.prototype[ methodName ]; 1695 var timeoutName = methodName + 'Timeout'; 1696 1697 _class.prototype[ methodName ] = function() { 1698 var timeout = this[ timeoutName ]; 1699 if ( timeout ) { 1700 clearTimeout( timeout ); 1701 } 1702 var args = arguments; 1703 1704 var _this = this; 1705 this[ timeoutName ] = setTimeout( function() { 1706 method.apply( _this, args ); 1707 delete _this[ timeoutName ]; 1708 }, threshold || 100 ); 1709 }; 1710}; 1711 1712// ----- htmlInit ----- // 1713 1714// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 1715utils.toDashed = function( str ) { 1716 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 1717 return $1 + '-' + $2; 1718 }).toLowerCase(); 1719}; 1720
1721var console = window.console; 1722/** 1723 * allow user to initialize classes via .js-namespace class 1724 * htmlInit( Widget, 'widgetName' ) 1725 * options are parsed from data-namespace-option attribute 1726 */ 1727utils.htmlInit = function( WidgetClass, namespace ) { 1728 docReady( function() { 1729 var dashedNamespace = utils.toDashed( namespace ); 1730 var elems = document.querySelectorAll( '.js-' + dashedNamespace ); 1731 var dataAttr = 'data-' + dashedNamespace + '-options'; 1732 1733 for ( var i=0, len = elems.length; i < len; i++ ) { 1734 var elem = elems[i]; 1735 var attr = elem.getAttribute( dataAttr ); 1736 var options; 1737 try { 1738 options = attr && JSON.parse( attr ); 1739 } catch ( error ) { 1740 // log error, do not initialize 1741 if ( console ) { 1742 console.error( 'Error parsing ' + dataAttr + ' on ' + 1743 elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' + 1744 error ); 1745 } 1746 continue; 1747 } 1748 // initialize 1749 var instance = new WidgetClass( elem, options ); 1750 // make available via $().data('layoutname') 1751 var jQuery = window.jQuery; 1752 if ( jQuery ) { 1753 jQuery.data( elem, namespace, instance ); 1754 } 1755 } 1756 }); 1757}; 1758 1759// ----- ----- // 1760 1761return utils; 1762 1763})); 1764 1765/** 1766 * Outlayer Item 1767 */ 1768 1769( function( window, factory ) { 1770 'use strict'; 1771 // universal module definition 1772 if ( typeof define === 'function' && define.amd ) { 1773 // AMD 1774 define( 'outlayer/item',[ 1775 'eventEmitter/EventEmitter', 1776 'get-size/get-size', 1777 'get-style-property/get-style-property', 1778 'fizzy-ui-utils/utils' 1779 ], 1780 function( EventEmitter, getSize, getStyleProperty, utils ) { 1781 return factory( window, EventEmitter, getSize, getStyleProperty, utils ); 1782 } 1783 ); 1784 } else if (typeof exports === 'object') { 1785 // CommonJS 1786 module.exports = factory( 1787 window, 1788 require('wolfy87-eventemitter'), 1789 require('get-size'), 1790 require('desandro-get-style-property'), 1791 require('fizzy-ui-utils') 1792 ); 1793 } else { 1794 // browser global 1795 window.Outlayer = {}; 1796 window.Outlayer.Item = factory( 1797 window, 1798 window.EventEmitter, 1799 window.getSize, 1800 window.getStyleProperty, 1801 window.fizzyUIUtils 1802 ); 1803 } 1804 1805}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) { 1806'use strict'; 1807 1808// ----- helpers ----- // 1809 1810var getComputedStyle = window.getComputedStyle; 1811var getStyle = getComputedStyle ? 1812 function( elem ) { 1813 return getComputedStyle( elem, null ); 1814 } : 1815 function( elem ) { 1816 return elem.currentStyle; 1817 }; 1818 1819 1820function isEmptyObj( obj ) { 1821 for ( var prop in obj ) { 1822 return false; 1823 } 1824 prop = null; 1825 return true; 1826} 1827 1828// -------------------------- CSS3 support -------------------------- // 1829 1830var transitionProperty = getStyleProperty('transition'); 1831var transformProperty = getStyleProperty('transform'); 1832var supportsCSS3 = transitionProperty && transformProperty; 1833var is3d = !!getStyleProperty('perspective'); 1834 1835var transitionEndEvent = { 1836 WebkitTransition: 'webkitTransitionEnd', 1837 MozTransition: 'transitionend', 1838 OTransition: 'otransitionend', 1839 transition: 'transitionend' 1840}[ transitionProperty ]; 1841 1842// properties that could have vendor prefix 1843var prefixableProperties = [ 1844 'transform', 1845 'transition', 1846 'transitionDuration', 1847 'transitionProperty' 1848]; 1849 1850// cache all vendor properties 1851var vendorProperties = ( function() { 1852 var cache = {}; 1853 for ( var i=0, len = prefixableProperties.length; i < len; i++ ) { 1854 var prop = prefixableProperties[i]; 1855 var supportedProp = getStyleProperty( prop ); 1856 if ( supportedProp && supportedProp !== prop ) { 1857 cache[ prop ] = supportedProp; 1858 } 1859 } 1860 return cache; 1861})(); 1862 1863// -------------------------- Item -------------------------- // 1864 1865function Item( element, layout ) { 1866 if ( !element ) { 1867 return; 1868 } 1869 1870 this.element = element; 1871 // parent layout class, i.e. Masonry, Isotope, or Packery 1872 this.layout = layout; 1873 this.position = { 1874 x: 0, 1875 y: 0 1876 }; 1877 1878 this._create(); 1879} 1880 1881// inherit EventEmitter 1882utils.extend( Item.prototype, EventEmitter.prototype ); 1883 1884Item.prototype._create = function() { 1885 // transition objects 1886 this._transn = { 1887 ingProperties: {}, 1888 clean: {}, 1889 onEnd: {} 1890 }; 1891 1892 this.css({ 1893 position: 'absolute' 1894 }); 1895}; 1896 1897// trigger specified handler for event type 1898Item.prototype.handleEvent = function( event ) { 1899 var method = 'on' + event.type; 1900 if ( this[ method ] ) { 1901 this[ method ]( event ); 1902 } 1903}; 1904 1905Item.prototype.getSize = function() { 1906 this.size = getSize( this.element ); 1907}; 1908 1909/** 1910 * apply CSS styles to element 1911 * @param {Object} style 1912 */ 1913Item.prototype.css = function( style ) { 1914 var elemStyle = this.element.style; 1915 1916 for ( var prop in style ) { 1917 // use vendor property if available
1918 var supportedProp = vendorProperties[ prop ] || prop; 1919 elemStyle[ supportedProp ] = style[ prop ]; 1920 } 1921}; 1922 1923 // measure position, and sets it 1924Item.prototype.getPosition = function() { 1925 var style = getStyle( this.element ); 1926 var layoutOptions = this.layout.options; 1927 var isOriginLeft = layoutOptions.isOriginLeft; 1928 var isOriginTop = layoutOptions.isOriginTop; 1929 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 1930 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 1931 // convert percent to pixels 1932 var layoutSize = this.layout.size; 1933 var x = xValue.indexOf('%') != -1 ? 1934 ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 ); 1935 var y = yValue.indexOf('%') != -1 ? 1936 ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 ); 1937 1938 // clean up 'auto' or other non-integer values 1939 x = isNaN( x ) ? 0 : x; 1940 y = isNaN( y ) ? 0 : y; 1941 // remove padding from measurement 1942 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 1943 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 1944 1945 this.position.x = x; 1946 this.position.y = y; 1947}; 1948 1949// set settled position, apply padding 1950Item.prototype.layoutPosition = function() { 1951 var layoutSize = this.layout.size; 1952 var layoutOptions = this.layout.options; 1953 var style = {}; 1954 1955 // x 1956 var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight'; 1957 var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right'; 1958 var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left'; 1959 1960 var x = this.position.x + layoutSize[ xPadding ]; 1961 // set in percentage or pixels 1962 style[ xProperty ] = this.getXValue( x ); 1963 // reset other property 1964 style[ xResetProperty ] = ''; 1965 1966 // y 1967 var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom'; 1968 var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom'; 1969 var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top'; 1970 1971 var y = this.position.y + layoutSize[ yPadding ]; 1972 // set in percentage or pixels 1973 style[ yProperty ] = this.getYValue( y ); 1974 // reset other property 1975 style[ yResetProperty ] = ''; 1976 1977 this.css( style ); 1978 this.emitEvent( 'layout', [ this ] ); 1979}; 1980 1981Item.prototype.getXValue = function( x ) { 1982 var layoutOptions = this.layout.options; 1983 return layoutOptions.percentPosition && !layoutOptions.isHorizontal ? 1984 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 1985}; 1986 1987Item.prototype.getYValue = function( y ) { 1988 var layoutOptions = this.layout.options; 1989 return layoutOptions.percentPosition && layoutOptions.isHorizontal ? 1990 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 1991}; 1992 1993 1994Item.prototype._transitionTo = function( x, y ) { 1995 this.getPosition(); 1996 // get current x & y from top/left 1997 var curX = this.position.x; 1998 var curY = this.position.y; 1999 2000 var compareX = parseInt( x, 10 ); 2001 var compareY = parseInt( y, 10 ); 2002 var didNotMove = compareX === this.position.x && compareY === this.position.y; 2003 2004 // save end position 2005 this.setPosition( x, y ); 2006 2007 // if did not move and not transitioning, just go to layout 2008 if ( didNotMove && !this.isTransitioning ) { 2009 this.layoutPosition(); 2010 return; 2011 } 2012 2013 var transX = x - curX; 2014 var transY = y - curY; 2015 var transitionStyle = {}; 2016 transitionStyle.transform = this.getTranslate( transX, transY ); 2017 2018 this.transition({ 2019 to: transitionStyle, 2020 onTransitionEnd: { 2021 transform: this.layoutPosition 2022 }, 2023 isCleaning: true 2024 }); 2025}; 2026 2027Item.prototype.getTranslate = function( x, y ) { 2028 // flip cooridinates if origin on right or bottom 2029 var layoutOptions = this.layout.options; 2030 x = layoutOptions.isOriginLeft ? x : -x; 2031 y = layoutOptions.isOriginTop ? y : -y; 2032 2033 if ( is3d ) { 2034 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 2035 } 2036 2037 return 'translate(' + x + 'px, ' + y + 'px)'; 2038}; 2039 2040// non transition + transform support 2041Item.prototype.goTo = function( x, y ) { 2042 this.setPosition( x, y ); 2043 this.layoutPosition(); 2044}; 2045 2046// use transition and transforms if supported 2047Item.prototype.moveTo = supportsCSS3 ? 2048 Item.prototype._transitionTo : Item.prototype.goTo; 2049 2050Item.prototype.setPosition = function( x, y ) { 2051 this.position.x = parseInt( x, 10 ); 2052 this.position.y = parseInt( y, 10 ); 2053}; 2054 2055// ----- transition ----- // 2056 2057/** 2058 * @param {Object} style - CSS 2059 * @param {Function} onTransitionEnd 2060 */ 2061 2062// non transition, just trigger callback 2063Item.prototype._nonTransition = function( args ) { 2064 this.css( args.to ); 2065 if ( args.isCleaning ) { 2066 this._removeStyles( args.to ); 2067 } 2068 for ( var prop in args.onTransitionEnd ) { 2069 args.onTransitionEnd[ prop ].call( this ); 2070 } 2071}; 2072 2073/** 2074 * proper transition 2075 * @param {Object} args - arguments 2076 * @param {Object} to - style to transition to 2077 * @param {Object} from - style to start transition from 2078 * @param {Boolean} isCleaning - removes transition styles after transition 2079 * @param {Function} onTransitionEnd - callback 2080 */ 2081Item.prototype._transition = function( args ) { 2082 // redirect to nonTransition if no transition duration 2083 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 2084 this._nonTransition( args ); 2085 return; 2086 } 2087 2088 var _transition = this._transn; 2089 // keep track of onTransitionEnd callback by css property 2090 for ( var prop in args.onTransitionEnd ) { 2091 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 2092 } 2093 // keep track of properties that are transitioning 2094 for ( prop in args.to ) { 2095 _transition.ingProperties[ prop ] = true; 2096 // keep track of properties to clean up when transition is done 2097 if ( args.isCleaning ) { 2098 _transition.clean[ prop ] = true; 2099 } 2100 } 2101 2102 // set from styles 2103 if ( args.from ) { 2104 this.css( args.from ); 2105 // force redraw. http://blog.alexmaccaw.com/css-transitions 2106 var h = this.element.offsetHeight; 2107 // hack for JSHint to hush about unused var 2108 h = null; 2109 } 2110 // enable transition 2111 this.enableTransition( args.to ); 2112 // set styles that are transitioning 2113 this.css( args.to ); 2114 2115 this.isTransitioning = true; 2116 2117}; 2118 2119// dash before all cap letters, including first for 2120// WebkitTransform => -webkit-transform 2121function toDashedAll( str ) { 2122 return str.replace( /([A-Z])/g, function( $1 ) { 2123 return '-' + $1.toLowerCase(); 2124 }); 2125} 2126 2127var transitionProps = 'opacity,' +
vendor: 11,190 bytes, lines 2128-2574
2128 toDashedAll( vendorProperties.transform || 'transform' ); 2129 2130Item.prototype.enableTransition = function(/* style */) { 2131 // HACK changing transitionProperty during a transition 2132 // will cause transition to jump 2133 if ( this.isTransitioning ) { 2134 return; 2135 } 2136 2137 // make `transition: foo, bar, baz` from style object 2138 // HACK un-comment this when enableTransition can work 2139 // while a transition is happening 2140 // var transitionValues = []; 2141 // for ( var prop in style ) { 2142 // // dash-ify camelCased properties like WebkitTransition 2143 // prop = vendorProperties[ prop ] || prop; 2144 // transitionValues.push( toDashedAll( prop ) ); 2145 // } 2146 // enable transition styles 2147 this.css({ 2148 transitionProperty: transitionProps, 2149 transitionDuration: this.layout.options.transitionDuration 2150 }); 2151 // listen for transition end event 2152 this.element.addEventListener( transitionEndEvent, this, false ); 2153}; 2154 2155Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ]; 2156 2157// ----- events ----- // 2158 2159Item.prototype.onwebkitTransitionEnd = function( event ) { 2160 this.ontransitionend( event ); 2161}; 2162 2163Item.prototype.onotransitionend = function( event ) { 2164 this.ontransitionend( event ); 2165}; 2166 2167// properties that I munge to make my life easier 2168var dashedVendorProperties = { 2169 '-webkit-transform': 'transform', 2170 '-moz-transform': 'transform', 2171 '-o-transform': 'transform' 2172}; 2173 2174Item.prototype.ontransitionend = function( event ) { 2175 // disregard bubbled events from children 2176 if ( event.target !== this.element ) { 2177 return; 2178 } 2179 var _transition = this._transn; 2180 // get property name of transitioned property, convert to prefix-free 2181 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 2182 2183 // remove property that has completed transitioning 2184 delete _transition.ingProperties[ propertyName ]; 2185 // check if any properties are still transitioning 2186 if ( isEmptyObj( _transition.ingProperties ) ) { 2187 // all properties have completed transitioning 2188 this.disableTransition(); 2189 } 2190 // clean style 2191 if ( propertyName in _transition.clean ) { 2192 // clean up style 2193 this.element.style[ event.propertyName ] = ''; 2194 delete _transition.clean[ propertyName ]; 2195 } 2196 // trigger onTransitionEnd callback 2197 if ( propertyName in _transition.onEnd ) { 2198 var onTransitionEnd = _transition.onEnd[ propertyName ]; 2199 onTransitionEnd.call( this ); 2200 delete _transition.onEnd[ propertyName ]; 2201 } 2202 2203 this.emitEvent( 'transitionEnd', [ this ] ); 2204}; 2205 2206Item.prototype.disableTransition = function() { 2207 this.removeTransitionStyles(); 2208 this.element.removeEventListener( transitionEndEvent, this, false ); 2209 this.isTransitioning = false; 2210}; 2211 2212/** 2213 * removes style property from element 2214 * @param {Object} style 2215**/ 2216Item.prototype._removeStyles = function( style ) { 2217 // clean up transition styles 2218 var cleanStyle = {}; 2219 for ( var prop in style ) { 2220 cleanStyle[ prop ] = ''; 2221 } 2222 this.css( cleanStyle ); 2223}; 2224 2225var cleanTransitionStyle = { 2226 transitionProperty: '', 2227 transitionDuration: '' 2228}; 2229 2230Item.prototype.removeTransitionStyles = function() { 2231 // remove transition 2232 this.css( cleanTransitionStyle ); 2233}; 2234 2235// ----- show/hide/remove ----- // 2236 2237// remove element from DOM 2238Item.prototype.removeElem = function() { 2239 this.element.parentNode.removeChild( this.element ); 2240 // remove display: none 2241 this.css({ display: '' }); 2242 this.emitEvent( 'remove', [ this ] ); 2243}; 2244 2245Item.prototype.remove = function() { 2246 // just remove element if no transition support or no transition 2247 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 2248 this.removeElem(); 2249 return; 2250 } 2251 2252 // start transition 2253 var _this = this; 2254 this.once( 'transitionEnd', function() { 2255 _this.removeElem(); 2256 }); 2257 this.hide(); 2258}; 2259 2260Item.prototype.reveal = function() { 2261 delete this.isHidden; 2262 // remove display: none 2263 this.css({ display: '' }); 2264 2265 var options = this.layout.options; 2266 2267 var onTransitionEnd = {}; 2268 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 2269 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 2270 2271 this.transition({ 2272 from: options.hiddenStyle, 2273 to: options.visibleStyle, 2274 isCleaning: true, 2275 onTransitionEnd: onTransitionEnd 2276 }); 2277}; 2278 2279Item.prototype.onRevealTransitionEnd = function() { 2280 // check if still visible 2281 // during transition, item may have been hidden 2282 if ( !this.isHidden ) { 2283 this.emitEvent('reveal'); 2284 } 2285}; 2286 2287/** 2288 * get style property use for hide/reveal transition end 2289 * @param {String} styleProperty - hiddenStyle/visibleStyle 2290 * @returns {String} 2291 */ 2292Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) { 2293 var optionStyle = this.layout.options[ styleProperty ]; 2294 // use opacity 2295 if ( optionStyle.opacity ) { 2296 return 'opacity'; 2297 } 2298 // get first property 2299 for ( var prop in optionStyle ) { 2300 return prop; 2301 } 2302}; 2303 2304Item.prototype.hide = function() { 2305 // set flag 2306 this.isHidden = true; 2307 // remove display: none 2308 this.css({ display: '' }); 2309 2310 var options = this.layout.options; 2311 2312 var onTransitionEnd = {}; 2313 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 2314 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 2315 2316 this.transition({ 2317 from: options.visibleStyle, 2318 to: options.hiddenStyle, 2319 // keep hidden stuff hidden 2320 isCleaning: true, 2321 onTransitionEnd: onTransitionEnd 2322 }); 2323}; 2324 2325Item.prototype.onHideTransitionEnd = function() { 2326 // check if still hidden 2327 // during transition, item may have been un-hidden 2328 if ( this.isHidden ) { 2329 this.css({ display: 'none' }); 2330 this.emitEvent('hide'); 2331 } 2332}; 2333 2334Item.prototype.destroy = function() { 2335 this.css({ 2336 position: '', 2337 left: '', 2338 right: '', 2339 top: '', 2340 bottom: '', 2341 transition: '', 2342 transform: '' 2343 }); 2344}; 2345 2346return Item; 2347 2348})); 2349 2350/*! 2351 * Outlayer v1.4.2 2352 * the brains and guts of a layout library 2353 * MIT license 2354 */ 2355 2356( function( window, factory ) { 2357 'use strict'; 2358 // universal module definition 2359 2360 if ( typeof define == 'function' && define.amd ) { 2361 // AMD 2362 define( 'outlayer/outlayer',[ 2363 'eventie/eventie', 2364 'eventEmitter/EventEmitter', 2365 'get-size/get-size', 2366 'fizzy-ui-utils/utils', 2367 './item' 2368 ], 2369 function( eventie, EventEmitter, getSize, utils, Item ) { 2370 return factory( window, eventie, EventEmitter, getSize, utils, Item); 2371 } 2372 ); 2373 } else if ( typeof exports == 'object' ) { 2374 // CommonJS 2375 module.exports = factory( 2376 window, 2377 require('eventie'), 2378 require('wolfy87-eventemitter'), 2379 require('get-size'), 2380 require('fizzy-ui-utils'), 2381 require('./item') 2382 ); 2383 } else { 2384 // browser global 2385 window.Outlayer = factory( 2386 window, 2387 window.eventie, 2388 window.EventEmitter, 2389 window.getSize, 2390 window.fizzyUIUtils, 2391 window.Outlayer.Item 2392 ); 2393 } 2394 2395}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) { 2396'use strict'; 2397 2398// ----- vars ----- // 2399 2400var console = window.console; 2401var jQuery = window.jQuery; 2402var noop = function() {}; 2403 2404// -------------------------- Outlayer -------------------------- // 2405 2406// globally unique identifiers 2407var GUID = 0; 2408// internal store of all Outlayer intances 2409var instances = {}; 2410 2411 2412/** 2413 * @param {Element, String} element 2414 * @param {Object} options 2415 * @constructor 2416 */ 2417function Outlayer( element, options ) { 2418 var queryElement = utils.getQueryElement( element ); 2419 if ( !queryElement ) { 2420 if ( console ) { 2421 console.error( 'Bad element for ' + this.constructor.namespace + 2422 ': ' + ( queryElement || element ) ); 2423 } 2424 return; 2425 } 2426 this.element = queryElement; 2427 // add jQuery 2428 if ( jQuery ) { 2429 this.$element = jQuery( this.element ); 2430 } 2431 2432 // options 2433 this.options = utils.extend( {}, this.constructor.defaults ); 2434 this.option( options ); 2435 2436 // add id for Outlayer.getFromElement 2437 var id = ++GUID; 2438 this.element.outlayerGUID = id; // expando 2439 instances[ id ] = this; // associate via id 2440 2441 // kick it off 2442 this._create(); 2443 2444 if ( this.options.isInitLayout ) { 2445 this.layout(); 2446 } 2447} 2448 2449// settings are for internal use only 2450Outlayer.namespace = 'outlayer'; 2451Outlayer.Item = Item; 2452 2453// default options 2454Outlayer.defaults = { 2455 containerStyle: { 2456 position: 'relative' 2457 }, 2458 isInitLayout: true, 2459 isOriginLeft: true, 2460 isOriginTop: true, 2461 isResizeBound: true, 2462 isResizingContainer: true, 2463 // item options 2464 transitionDuration: '0.4s', 2465 hiddenStyle: { 2466 opacity: 0, 2467 transform: 'scale(0.001)' 2468 }, 2469 visibleStyle: { 2470 opacity: 1, 2471 transform: 'scale(1)' 2472 } 2473}; 2474 2475// inherit EventEmitter 2476utils.extend( Outlayer.prototype, EventEmitter.prototype ); 2477 2478/** 2479 * set options 2480 * @param {Object} opts 2481 */ 2482Outlayer.prototype.option = function( opts ) { 2483 utils.extend( this.options, opts ); 2484}; 2485 2486Outlayer.prototype._create = function() { 2487 // get items from children 2488 this.reloadItems(); 2489 // elements that affect layout, but are not laid out 2490 this.stamps = []; 2491 this.stamp( this.options.stamp ); 2492 // set container style 2493 utils.extend( this.element.style, this.options.containerStyle ); 2494 2495 // bind resize method 2496 if ( this.options.isResizeBound ) { 2497 this.bindResize(); 2498 } 2499}; 2500 2501// goes through all children again and gets bricks in proper order 2502Outlayer.prototype.reloadItems = function() { 2503 // collection of item elements 2504 this.items = this._itemize( this.element.children ); 2505}; 2506 2507 2508/** 2509 * turn elements into Outlayer.Items to be used in layout 2510 * @param {Array or NodeList or HTMLElement} elems 2511 * @returns {Array} items - collection of new Outlayer Items 2512 */ 2513Outlayer.prototype._itemize = function( elems ) { 2514 2515 var itemElems = this._filterFindItemElements( elems ); 2516 var Item = this.constructor.Item; 2517 2518 // create new Outlayer Items for collection 2519 var items = []; 2520 for ( var i=0, len = itemElems.length; i < len; i++ ) { 2521 var elem = itemElems[i]; 2522 var item = new Item( elem, this ); 2523 items.push( item ); 2524 } 2525 2526 return items; 2527}; 2528 2529/** 2530 * get item elements to be used in layout 2531 * @param {Array or NodeList or HTMLElement} elems 2532 * @returns {Array} items - item elements 2533 */ 2534Outlayer.prototype._filterFindItemElements = function( elems ) { 2535 return utils.filterFindElements( elems, this.options.itemSelector ); 2536}; 2537 2538/** 2539 * getter method for getting item elements 2540 * @returns {Array} elems - collection of item elements 2541 */ 2542Outlayer.prototype.getItemElements = function() { 2543 var elems = []; 2544 for ( var i=0, len = this.items.length; i < len; i++ ) { 2545 elems.push( this.items[i].element ); 2546 } 2547 return elems; 2548}; 2549 2550// ----- init & layout ----- // 2551 2552/** 2553 * lays out all items 2554 */ 2555Outlayer.prototype.layout = function() { 2556 this._resetLayout(); 2557 this._manageStamps(); 2558 2559 // don't animate first layout 2560 var isInstant = this.options.isLayoutInstant !== undefined ? 2561 this.options.isLayoutInstant : !this._isLayoutInited; 2562 this.layoutItems( this.items, isInstant ); 2563 2564 // flag for initalized 2565 this._isLayoutInited = true; 2566}; 2567 2568// _init is alias for layout 2569Outlayer.prototype._init = Outlayer.prototype.layout; 2570 2571/** 2572 * logic before any new layout 2573 */ 2574Outlayer.prototype._resetLayout = function() {
2575 this.getSize(); 2576}; 2577 2578 2579Outlayer.prototype.getSize = function() { 2580 this.size = getSize( this.element ); 2581}; 2582 2583/** 2584 * get measurement from option, for columnWidth, rowHeight, gutter 2585 * if option is String -> get element from selector string, & get size of element 2586 * if option is Element -> get size of element 2587 * else use option as a number 2588 * 2589 * @param {String} measurement 2590 * @param {String} size - width or height 2591 * @private 2592 */ 2593Outlayer.prototype._getMeasurement = function( measurement, size ) { 2594 var option = this.options[ measurement ]; 2595 var elem; 2596 if ( !option ) { 2597 // default to 0 2598 this[ measurement ] = 0; 2599 } else { 2600 // use option as an element 2601 if ( typeof option === 'string' ) { 2602 elem = this.element.querySelector( option ); 2603 } else if ( utils.isElement( option ) ) { 2604 elem = option; 2605 } 2606 // use size of element, if element 2607 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 2608 } 2609}; 2610 2611/** 2612 * layout a collection of item elements 2613 * @api public 2614 */ 2615Outlayer.prototype.layoutItems = function( items, isInstant ) { 2616 items = this._getItemsForLayout( items ); 2617 2618 this._layoutItems( items, isInstant ); 2619 2620 this._postLayout(); 2621}; 2622 2623/** 2624 * get the items to be laid out 2625 * you may want to skip over some items 2626 * @param {Array} items 2627 * @returns {Array} items 2628 */ 2629Outlayer.prototype._getItemsForLayout = function( items ) { 2630 var layoutItems = []; 2631 for ( var i=0, len = items.length; i < len; i++ ) { 2632 var item = items[i]; 2633 if ( !item.isIgnored ) { 2634 layoutItems.push( item ); 2635 } 2636 } 2637 return layoutItems; 2638}; 2639 2640/** 2641 * layout items 2642 * @param {Array} items 2643 * @param {Boolean} isInstant 2644 */ 2645Outlayer.prototype._layoutItems = function( items, isInstant ) { 2646 this._emitCompleteOnItems( 'layout', items ); 2647 2648 if ( !items || !items.length ) { 2649 // no items, emit event with empty array 2650 return; 2651 } 2652 2653 var queue = []; 2654 2655 for ( var i=0, len = items.length; i < len; i++ ) { 2656 var item = items[i]; 2657 // get x/y object from method 2658 var position = this._getItemLayoutPosition( item ); 2659 // enqueue 2660 position.item = item; 2661 position.isInstant = isInstant || item.isLayoutInstant; 2662 queue.push( position ); 2663 } 2664 2665 this._processLayoutQueue( queue ); 2666}; 2667 2668/** 2669 * get item layout position 2670 * @param {Outlayer.Item} item 2671 * @returns {Object} x and y position 2672 */ 2673Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) { 2674 return { 2675 x: 0, 2676 y: 0 2677 }; 2678}; 2679 2680/** 2681 * iterate over array and position each item 2682 * Reason being - separating this logic prevents 'layout invalidation' 2683 * thx @paul_irish 2684 * @param {Array} queue 2685 */ 2686Outlayer.prototype._processLayoutQueue = function( queue ) { 2687 for ( var i=0, len = queue.length; i < len; i++ ) { 2688 var obj = queue[i]; 2689 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant ); 2690 } 2691}; 2692 2693/** 2694 * Sets position of item in DOM 2695 * @param {Outlayer.Item} item 2696 * @param {Number} x - horizontal position 2697 * @param {Number} y - vertical position 2698 * @param {Boolean} isInstant - disables transitions 2699 */ 2700Outlayer.prototype._positionItem = function( item, x, y, isInstant ) { 2701 if ( isInstant ) { 2702 // if not transition, just set CSS 2703 item.goTo( x, y ); 2704 } else { 2705 item.moveTo( x, y ); 2706 } 2707}; 2708 2709/** 2710 * Any logic you want to do after each layout, 2711 * i.e. size the container 2712 */ 2713Outlayer.prototype._postLayout = function() { 2714 this.resizeContainer(); 2715}; 2716 2717Outlayer.prototype.resizeContainer = function() { 2718 if ( !this.options.isResizingContainer ) { 2719 return; 2720 } 2721 var size = this._getContainerSize(); 2722 if ( size ) { 2723 this._setContainerMeasure( size.width, true ); 2724 this._setContainerMeasure( size.height, false ); 2725 } 2726}; 2727 2728/** 2729 * Sets width or height of container if returned 2730 * @returns {Object} size 2731 * @param {Number} width 2732 * @param {Number} height 2733 */ 2734Outlayer.prototype._getContainerSize = noop; 2735 2736/** 2737 * @param {Number} measure - size of width or height 2738 * @param {Boolean} isWidth 2739 */ 2740Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) { 2741 if ( measure === undefined ) { 2742 return; 2743 } 2744 2745 var elemSize = this.size; 2746 // add padding and border width if border box 2747 if ( elemSize.isBorderBox ) { 2748 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 2749 elemSize.borderLeftWidth + elemSize.borderRightWidth : 2750 elemSize.paddingBottom + elemSize.paddingTop + 2751 elemSize.borderTopWidth + elemSize.borderBottomWidth; 2752 } 2753 2754 measure = Math.max( measure, 0 ); 2755 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 2756}; 2757 2758/** 2759 * emit eventComplete on a collection of items events 2760 * @param {String} eventName 2761 * @param {Array} items - Outlayer.Items 2762 */ 2763Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) { 2764 var _this = this; 2765 function onComplete() { 2766 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 2767 } 2768 2769 var count = items.length; 2770 if ( !items || !count ) { 2771 onComplete(); 2772 return; 2773 } 2774 2775 var doneCount = 0; 2776 function tick() { 2777 doneCount++; 2778 if ( doneCount === count ) { 2779 onComplete(); 2780 } 2781 } 2782 2783 // bind callback 2784 for ( var i=0, len = items.length; i < len; i++ ) { 2785 var item = items[i]; 2786 item.once( eventName, tick ); 2787 } 2788}; 2789 2790/** 2791 * emits events via eventEmitter and jQuery events 2792 * @param {String} type - name of event 2793 * @param {Event} event - original event 2794 * @param {Array} args - extra arguments 2795 */ 2796Outlayer.prototype.dispatchEvent = function( type, event, args ) { 2797 // add original event to arguments 2798 var emitArgs = event ? [ event ].concat( args ) : args; 2799 this.emitEvent( type, emitArgs ); 2800 2801 if ( jQuery ) { 2802 // set this.$element 2803 this.$element = this.$element || jQuery( this.element ); 2804 if ( event ) { 2805 // create jQuery event 2806 var $event = jQuery.Event( event ); 2807 $event.type = type; 2808 this.$element.trigger( $event, args ); 2809 } else { 2810 // just trigger with type if no event available 2811 this.$element.trigger( type, args ); 2812 } 2813 } 2814}; 2815 2816// -------------------------- ignore & stamps -------------------------- // 2817 2818 2819/** 2820 * keep item in collection, but do not lay it out 2821 * ignored items do not get skipped in layout 2822 * @param {Element} elem 2823 */ 2824Outlayer.prototype.ignore = function( elem ) { 2825 var item = this.getItem( elem ); 2826 if ( item ) { 2827 item.isIgnored = true; 2828 } 2829}; 2830 2831/** 2832 * return item to layout collection 2833 * @param {Element} elem 2834 */ 2835Outlayer.prototype.unignore = function( elem ) { 2836 var item = this.getItem( elem ); 2837 if ( item ) { 2838 delete item.isIgnored; 2839 } 2840}; 2841 2842/** 2843 * adds elements to stamps 2844 * @param {NodeList, Array, Element, or String} elems 2845 */ 2846Outlayer.prototype.stamp = function( elems ) { 2847 elems = this._find( elems ); 2848 if ( !elems ) { 2849 return; 2850 } 2851
2852 this.stamps = this.stamps.concat( elems ); 2853 // ignore 2854 for ( var i=0, len = elems.length; i < len; i++ ) { 2855 var elem = elems[i]; 2856 this.ignore( elem ); 2857 } 2858}; 2859 2860/** 2861 * removes elements to stamps 2862 * @param {NodeList, Array, or Element} elems 2863 */ 2864Outlayer.prototype.unstamp = function( elems ) { 2865 elems = this._find( elems ); 2866 if ( !elems ){ 2867 return; 2868 } 2869 2870 for ( var i=0, len = elems.length; i < len; i++ ) { 2871 var elem = elems[i]; 2872 // filter out removed stamp elements 2873 utils.removeFrom( this.stamps, elem ); 2874 this.unignore( elem ); 2875 } 2876 2877}; 2878 2879/** 2880 * finds child elements 2881 * @param {NodeList, Array, Element, or String} elems 2882 * @returns {Array} elems 2883 */ 2884Outlayer.prototype._find = function( elems ) { 2885 if ( !elems ) { 2886 return; 2887 } 2888 // if string, use argument as selector string 2889 if ( typeof elems === 'string' ) { 2890 elems = this.element.querySelectorAll( elems ); 2891 } 2892 elems = utils.makeArray( elems ); 2893 return elems; 2894}; 2895 2896Outlayer.prototype._manageStamps = function() { 2897 if ( !this.stamps || !this.stamps.length ) { 2898 return; 2899 } 2900 2901 this._getBoundingRect(); 2902 2903 for ( var i=0, len = this.stamps.length; i < len; i++ ) { 2904 var stamp = this.stamps[i]; 2905 this._manageStamp( stamp ); 2906 } 2907}; 2908 2909// update boundingLeft / Top 2910Outlayer.prototype._getBoundingRect = function() { 2911 // get bounding rect for container element 2912 var boundingRect = this.element.getBoundingClientRect(); 2913 var size = this.size; 2914 this._boundingRect = { 2915 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 2916 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 2917 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 2918 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 2919 }; 2920}; 2921 2922/** 2923 * @param {Element} stamp 2924**/ 2925Outlayer.prototype._manageStamp = noop; 2926 2927/** 2928 * get x/y position of element relative to container element 2929 * @param {Element} elem 2930 * @returns {Object} offset - has left, top, right, bottom 2931 */ 2932Outlayer.prototype._getElementOffset = function( elem ) { 2933 var boundingRect = elem.getBoundingClientRect(); 2934 var thisRect = this._boundingRect; 2935 var size = getSize( elem ); 2936 var offset = { 2937 left: boundingRect.left - thisRect.left - size.marginLeft, 2938 top: boundingRect.top - thisRect.top - size.marginTop, 2939 right: thisRect.right - boundingRect.right - size.marginRight, 2940 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 2941 }; 2942 return offset; 2943}; 2944 2945// -------------------------- resize -------------------------- // 2946 2947// enable event handlers for listeners 2948// i.e. resize -> onresize 2949Outlayer.prototype.handleEvent = function( event ) { 2950 var method = 'on' + event.type; 2951 if ( this[ method ] ) { 2952 this[ method ]( event ); 2953 } 2954}; 2955 2956/** 2957 * Bind layout to window resizing 2958 */ 2959Outlayer.prototype.bindResize = function() { 2960 // bind just one listener 2961 if ( this.isResizeBound ) { 2962 return; 2963 } 2964 eventie.bind( window, 'resize', this ); 2965 this.isResizeBound = true; 2966}; 2967 2968/** 2969 * Unbind layout to window resizing 2970 */ 2971Outlayer.prototype.unbindResize = function() { 2972 if ( this.isResizeBound ) { 2973 eventie.unbind( window, 'resize', this ); 2974 } 2975 this.isResizeBound = false; 2976}; 2977 2978// original debounce by John Hann 2979// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 2980 2981// this fires every resize 2982Outlayer.prototype.onresize = function() { 2983 if ( this.resizeTimeout ) { 2984 clearTimeout( this.resizeTimeout ); 2985 } 2986 2987 var _this = this; 2988 function delayed() { 2989 _this.resize(); 2990 delete _this.resizeTimeout; 2991 } 2992 2993 this.resizeTimeout = setTimeout( delayed, 100 ); 2994}; 2995 2996// debounced, layout on resize 2997Outlayer.prototype.resize = function() { 2998 // don't trigger if size did not change 2999 // or if resize was unbound. See #9 3000 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 3001 return; 3002 } 3003 3004 this.layout(); 3005}; 3006 3007/** 3008 * check if layout is needed post layout 3009 * @returns Boolean 3010 */ 3011Outlayer.prototype.needsResizeLayout = function() { 3012 var size = getSize( this.element ); 3013 // check that this.size and size are there 3014 // IE8 triggers resize on body size change, so they might not be 3015 var hasSizes = this.size && size; 3016 return hasSizes && size.innerWidth !== this.size.innerWidth; 3017}; 3018 3019// -------------------------- methods -------------------------- // 3020 3021/** 3022 * add items to Outlayer instance 3023 * @param {Array or NodeList or Element} elems 3024 * @returns {Array} items - Outlayer.Items 3025**/ 3026Outlayer.prototype.addItems = function( elems ) { 3027 var items = this._itemize( elems ); 3028 // add items to collection 3029 if ( items.length ) { 3030 this.items = this.items.concat( items ); 3031 } 3032 return items; 3033}; 3034 3035/** 3036 * Layout newly-appended item elements 3037 * @param {Array or NodeList or Element} elems 3038 */ 3039Outlayer.prototype.appended = function( elems ) { 3040 var items = this.addItems( elems ); 3041 if ( !items.length ) { 3042 return; 3043 } 3044 // layout and reveal just the new items 3045 this.layoutItems( items, true ); 3046 this.reveal( items ); 3047}; 3048 3049/** 3050 * Layout prepended elements 3051 * @param {Array or NodeList or Element} elems 3052 */ 3053Outlayer.prototype.prepended = function( elems ) { 3054 var items = this._itemize( elems ); 3055 if ( !items.length ) { 3056 return; 3057 } 3058 // add items to beginning of collection 3059 var previousItems = this.items.slice(0); 3060 this.items = items.concat( previousItems ); 3061 // start new layout 3062 this._resetLayout(); 3063 this._manageStamps(); 3064 // layout new stuff without transition 3065 this.layoutItems( items, true ); 3066 this.reveal( items ); 3067 // layout previous items 3068 this.layoutItems( previousItems ); 3069}; 3070 3071/** 3072 * reveal a collection of items 3073 * @param {Array of Outlayer.Items} items 3074 */ 3075Outlayer.prototype.reveal = function( items ) { 3076 this._emitCompleteOnItems( 'reveal', items ); 3077 3078 var len = items && items.length; 3079 for ( var i=0; len && i < len; i++ ) { 3080 var item = items[i]; 3081 item.reveal(); 3082 } 3083}; 3084 3085/** 3086 * hide a collection of items 3087 * @param {Array of Outlayer.Items} items 3088 */ 3089Outlayer.prototype.hide = function( items ) { 3090 this._emitCompleteOnItems( 'hide', items ); 3091 3092 var len = items && items.length; 3093 for ( var i=0; len && i < len; i++ ) { 3094 var item = items[i]; 3095 item.hide(); 3096 } 3097}; 3098 3099/** 3100 * reveal item elements 3101 * @param {Array}, {Element}, {NodeList} items 3102 */ 3103Outlayer.prototype.revealItemElements = function( elems ) { 3104 var items = this.getItems( elems ); 3105 this.reveal( items ); 3106}; 3107 3108/** 3109 * hide item elements 3110 * @param {Array}, {Element}, {NodeList} items 3111 */ 3112Outlayer.prototype.hideItemElements = function( elems ) { 3113 var items = this.getItems( elems ); 3114 this.hide( items ); 3115}; 3116 3117/** 3118 * get Outlayer.Item, given an Element 3119 * @param {Element} elem 3120 * @param {Function} callback 3121 * @returns {Outlayer.Item} item 3122 */ 3123Outlayer.prototype.getItem = function( elem ) { 3124 // loop through items to get the one that matches 3125 for ( var i=0, len = this.items.length; i < len; i++ ) { 3126 var item = this.items[i]; 3127 if ( item.element === elem ) { 3128 // return item 3129 return item; 3130 } 3131 } 3132}; 3133 3134/** 3135 * get collection of Outlayer.Items, given Elements 3136 * @param {Array} elems 3137 * @returns {Array} items - Outlayer.Items 3138 */ 3139Outlayer.prototype.getItems = function( elems ) { 3140 elems = utils.makeArray( elems ); 3141 var items = []; 3142 for ( var i=0, len = elems.length; i < len; i++ ) { 3143 var elem = elems[i]; 3144 var item = this.getItem( elem ); 3145 if ( item ) { 3146 items.push( item ); 3147 } 3148 } 3149 3150 return items; 3151}; 3152 3153/**
3154 * remove element(s) from instance and DOM 3155 * @param {Array or NodeList or Element} elems 3156 */ 3157Outlayer.prototype.remove = function( elems ) { 3158 var removeItems = this.getItems( elems ); 3159 3160 this._emitCompleteOnItems( 'remove', removeItems ); 3161 3162 // bail if no items to remove 3163 if ( !removeItems || !removeItems.length ) { 3164 return; 3165 } 3166 3167 for ( var i=0, len = removeItems.length; i < len; i++ ) { 3168 var item = removeItems[i]; 3169 item.remove(); 3170 // remove item from collection 3171 utils.removeFrom( this.items, item ); 3172 } 3173}; 3174 3175// ----- destroy ----- // 3176 3177// remove and disable Outlayer instance 3178Outlayer.prototype.destroy = function() { 3179 // clean up dynamic styles 3180 var style = this.element.style; 3181 style.height = ''; 3182 style.position = ''; 3183 style.width = ''; 3184 // destroy items 3185 for ( var i=0, len = this.items.length; i < len; i++ ) { 3186 var item = this.items[i]; 3187 item.destroy(); 3188 } 3189 3190 this.unbindResize(); 3191 3192 var id = this.element.outlayerGUID; 3193 delete instances[ id ]; // remove reference to instance by id 3194 delete this.element.outlayerGUID; 3195 // remove data for jQuery 3196 if ( jQuery ) { 3197 jQuery.removeData( this.element, this.constructor.namespace ); 3198 } 3199 3200}; 3201 3202// -------------------------- data -------------------------- // 3203 3204/** 3205 * get Outlayer instance from element 3206 * @param {Element} elem 3207 * @returns {Outlayer} 3208 */ 3209Outlayer.data = function( elem ) { 3210 elem = utils.getQueryElement( elem ); 3211 var id = elem && elem.outlayerGUID; 3212 return id && instances[ id ]; 3213}; 3214 3215 3216// -------------------------- create Outlayer class -------------------------- // 3217 3218/** 3219 * create a layout class 3220 * @param {String} namespace 3221 */ 3222Outlayer.create = function( namespace, options ) { 3223 // sub-class Outlayer 3224 function Layout() { 3225 Outlayer.apply( this, arguments ); 3226 } 3227 // inherit Outlayer prototype, use Object.create if there 3228 if ( Object.create ) { 3229 Layout.prototype = Object.create( Outlayer.prototype ); 3230 } else { 3231 utils.extend( Layout.prototype, Outlayer.prototype ); 3232 } 3233 // set contructor, used for namespace and Item 3234 Layout.prototype.constructor = Layout; 3235 3236 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 3237 // apply new options 3238 utils.extend( Layout.defaults, options ); 3239 // keep prototype.settings for backwards compatibility (Packery v1.2.0) 3240 Layout.prototype.settings = {}; 3241 3242 Layout.namespace = namespace; 3243 3244 Layout.data = Outlayer.data; 3245 3246 // sub-class Item 3247 Layout.Item = function LayoutItem() { 3248 Item.apply( this, arguments ); 3249 }; 3250 3251 Layout.Item.prototype = new Item(); 3252 3253 // -------------------------- declarative -------------------------- // 3254 3255 utils.htmlInit( Layout, namespace ); 3256 3257 // -------------------------- jQuery bridge -------------------------- // 3258 3259 // make into jQuery plugin 3260 if ( jQuery && jQuery.bridget ) { 3261 jQuery.bridget( namespace, Layout ); 3262 } 3263 3264 return Layout; 3265}; 3266 3267// ----- fin ----- // 3268 3269// back in global 3270Outlayer.Item = Item; 3271 3272return Outlayer; 3273 3274})); 3275 3276 3277/** 3278 * Isotope Item 3279**/ 3280 3281( function( window, factory ) { 3282'use strict'; 3283 // universal module definition 3284 if ( typeof define == 'function' && define.amd ) { 3285 // AMD 3286 define( 'isotope/js/item',[ 3287 'outlayer/outlayer' 3288 ], 3289 factory ); 3290 } else if ( typeof exports == 'object' ) { 3291 // CommonJS 3292 module.exports = factory( 3293 require('outlayer') 3294 ); 3295 } else { 3296 // browser global 3297 window.Isotope = window.Isotope || {}; 3298 window.Isotope.Item = factory( 3299 window.Outlayer 3300 ); 3301 } 3302 3303}( window, function factory( Outlayer ) { 3304'use strict'; 3305 3306// -------------------------- Item -------------------------- // 3307 3308// sub-class Outlayer Item 3309function Item() { 3310 Outlayer.Item.apply( this, arguments ); 3311} 3312 3313Item.prototype = new Outlayer.Item(); 3314 3315Item.prototype._create = function() { 3316 // assign id, used for original-order sorting 3317 this.id = this.layout.itemGUID++; 3318 Outlayer.Item.prototype._create.call( this ); 3319 this.sortData = {}; 3320}; 3321 3322Item.prototype.updateSortData = function() { 3323 if ( this.isIgnored ) { 3324 return; 3325 } 3326 // default sorters 3327 this.sortData.id = this.id; 3328 // for backward compatibility 3329 this.sortData['original-order'] = this.id; 3330 this.sortData.random = Math.random(); 3331 // go thru getSortData obj and apply the sorters 3332 var getSortData = this.layout.options.getSortData; 3333 var sorters = this.layout._sorters; 3334 for ( var key in getSortData ) { 3335 var sorter = sorters[ key ]; 3336 this.sortData[ key ] = sorter( this.element, this ); 3337 } 3338}; 3339 3340var _destroy = Item.prototype.destroy; 3341Item.prototype.destroy = function() { 3342 // call super 3343 _destroy.apply( this, arguments ); 3344 // reset display, #741 3345 this.css({ 3346 display: '' 3347 }); 3348}; 3349 3350return Item; 3351 3352})); 3353 3354/** 3355 * Isotope LayoutMode 3356 */ 3357 3358( function( window, factory ) { 3359 'use strict'; 3360 // universal module definition 3361 3362 if ( typeof define == 'function' && define.amd ) { 3363 // AMD 3364 define( 'isotope/js/layout-mode',[ 3365 'get-size/get-size', 3366 'outlayer/outlayer' 3367 ], 3368 factory ); 3369 } else if ( typeof exports == 'object' ) { 3370 // CommonJS 3371 module.exports = factory( 3372 require('get-size'), 3373 require('outlayer') 3374 ); 3375 } else { 3376 // browser global 3377 window.Isotope = window.Isotope || {}; 3378 window.Isotope.LayoutMode = factory( 3379 window.getSize, 3380 window.Outlayer 3381 ); 3382 } 3383 3384}( window, function factory( getSize, Outlayer ) { 3385 'use strict'; 3386 3387 // layout mode class 3388 function LayoutMode( isotope ) { 3389 this.isotope = isotope; 3390 // link properties 3391 if ( isotope ) { 3392 this.options = isotope.options[ this.namespace ]; 3393 this.element = isotope.element; 3394 this.items = isotope.filteredItems; 3395 this.size = isotope.size; 3396 } 3397 } 3398 3399 /** 3400 * some methods should just defer to default Outlayer method 3401 * and reference the Isotope instance as `this` 3402 **/ 3403 ( function() { 3404 var facadeMethods = [ 3405 '_resetLayout', 3406 '_getItemLayoutPosition', 3407 '_manageStamp', 3408 '_getContainerSize', 3409 '_getElementOffset', 3410 'needsResizeLayout' 3411 ]; 3412 3413 for ( var i=0, len = facadeMethods.length; i < len; i++ ) { 3414 var methodName = facadeMethods[i]; 3415 LayoutMode.prototype[ methodName ] = getOutlayerMethod( methodName ); 3416 } 3417 3418 function getOutlayerMethod( methodName ) { 3419 return function() { 3420 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 3421 }; 3422 } 3423 })(); 3424 3425 // ----- ----- // 3426 3427 // for horizontal layout modes, check vertical size 3428 LayoutMode.prototype.needsVerticalResizeLayout = function() {
vendor: 20,029 bytes, lines 3429-4164
3429 // don't trigger if size did not change 3430 var size = getSize( this.isotope.element ); 3431 // check that this.size and size are there 3432 // IE8 triggers resize on body size change, so they might not be 3433 var hasSizes = this.isotope.size && size; 3434 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 3435 }; 3436 3437 // ----- measurements ----- // 3438 3439 LayoutMode.prototype._getMeasurement = function() { 3440 this.isotope._getMeasurement.apply( this, arguments ); 3441 }; 3442 3443 LayoutMode.prototype.getColumnWidth = function() { 3444 this.getSegmentSize( 'column', 'Width' ); 3445 }; 3446 3447 LayoutMode.prototype.getRowHeight = function() { 3448 this.getSegmentSize( 'row', 'Height' ); 3449 }; 3450 3451 /** 3452 * get columnWidth or rowHeight 3453 * segment: 'column' or 'row' 3454 * size 'Width' or 'Height' 3455 **/ 3456 LayoutMode.prototype.getSegmentSize = function( segment, size ) { 3457 var segmentName = segment + size; 3458 var outerSize = 'outer' + size; 3459 // columnWidth / outerWidth // rowHeight / outerHeight 3460 this._getMeasurement( segmentName, outerSize ); 3461 // got rowHeight or columnWidth, we can chill 3462 if ( this[ segmentName ] ) { 3463 return; 3464 } 3465 // fall back to item of first element 3466 var firstItemSize = this.getFirstItemSize(); 3467 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 3468 // or size of container 3469 this.isotope.size[ 'inner' + size ]; 3470 }; 3471 3472 LayoutMode.prototype.getFirstItemSize = function() { 3473 var firstItem = this.isotope.filteredItems[0]; 3474 return firstItem && firstItem.element && getSize( firstItem.element ); 3475 }; 3476 3477 // ----- methods that should reference isotope ----- // 3478 3479 LayoutMode.prototype.layout = function() { 3480 this.isotope.layout.apply( this.isotope, arguments ); 3481 }; 3482 3483 LayoutMode.prototype.getSize = function() { 3484 this.isotope.getSize(); 3485 this.size = this.isotope.size; 3486 }; 3487 3488 // -------------------------- create -------------------------- // 3489 3490 LayoutMode.modes = {}; 3491 3492 LayoutMode.create = function( namespace, options ) { 3493 3494 function Mode() { 3495 LayoutMode.apply( this, arguments ); 3496 } 3497 3498 Mode.prototype = new LayoutMode(); 3499 3500 // default options 3501 if ( options ) { 3502 Mode.options = options; 3503 } 3504 3505 Mode.prototype.namespace = namespace; 3506 // register in Isotope 3507 LayoutMode.modes[ namespace ] = Mode; 3508 3509 return Mode; 3510 }; 3511 3512 return LayoutMode; 3513 3514})); 3515 3516/*! 3517 * Masonry v3.3.1 3518 * Cascading grid layout library 3519 * http://masonry.desandro.com 3520 * MIT License 3521 * by David DeSandro 3522 */ 3523 3524( function( window, factory ) { 3525 'use strict'; 3526 // universal module definition 3527 if ( typeof define === 'function' && define.amd ) { 3528 // AMD 3529 define( 'masonry/masonry',[ 3530 'outlayer/outlayer', 3531 'get-size/get-size', 3532 'fizzy-ui-utils/utils' 3533 ], 3534 factory ); 3535 } else if ( typeof exports === 'object' ) { 3536 // CommonJS 3537 module.exports = factory( 3538 require('outlayer'), 3539 require('get-size'), 3540 require('fizzy-ui-utils') 3541 ); 3542 } else { 3543 // browser global 3544 window.Masonry = factory( 3545 window.Outlayer, 3546 window.getSize, 3547 window.fizzyUIUtils 3548 ); 3549 } 3550 3551}( window, function factory( Outlayer, getSize, utils ) { 3552 3553 3554 3555// -------------------------- masonryDefinition -------------------------- // 3556 3557 // create an Outlayer layout class 3558 var Masonry = Outlayer.create('masonry'); 3559 3560 Masonry.prototype._resetLayout = function() { 3561 this.getSize(); 3562 this._getMeasurement( 'columnWidth', 'outerWidth' ); 3563 this._getMeasurement( 'gutter', 'outerWidth' ); 3564 this.measureColumns(); 3565 3566 // reset column Y 3567 var i = this.cols; 3568 this.colYs = []; 3569 while (i--) { 3570 this.colYs.push( 0 ); 3571 } 3572 3573 this.maxY = 0; 3574 }; 3575 3576 Masonry.prototype.measureColumns = function() { 3577 this.getContainerWidth(); 3578 // if columnWidth is 0, default to outerWidth of first item 3579 if ( !this.columnWidth ) { 3580 var firstItem = this.items[0]; 3581 var firstItemElem = firstItem && firstItem.element; 3582 // columnWidth fall back to item of first element 3583 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 3584 // if first elem has no width, default to size of container 3585 this.containerWidth; 3586 } 3587 3588 var columnWidth = this.columnWidth += this.gutter; 3589 3590 // calculate columns 3591 var containerWidth = this.containerWidth + this.gutter; 3592 var cols = containerWidth / columnWidth; 3593 // fix rounding errors, typically with gutters 3594 var excess = columnWidth - containerWidth % columnWidth; 3595 // if overshoot is less than a pixel, round up, otherwise floor it 3596 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 3597 cols = Math[ mathMethod ]( cols ); 3598 this.cols = Math.max( cols, 1 ); 3599 }; 3600 3601 Masonry.prototype.getContainerWidth = function() { 3602 // container is parent if fit width 3603 var container = this.options.isFitWidth ? this.element.parentNode : this.element; 3604 // check that this.size and size are there 3605 // IE8 triggers resize on body size change, so they might not be 3606 var size = getSize( container ); 3607 this.containerWidth = size && size.innerWidth; 3608 }; 3609 3610 Masonry.prototype._getItemLayoutPosition = function( item ) { 3611 item.getSize(); 3612 // how many columns does this brick span 3613 var remainder = item.size.outerWidth % this.columnWidth; 3614 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 3615 // round if off by 1 pixel, otherwise use ceil 3616 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 3617 colSpan = Math.min( colSpan, this.cols ); 3618 3619 var colGroup = this._getColGroup( colSpan ); 3620 // get the minimum Y value from the columns 3621 var minimumY = Math.min.apply( Math, colGroup ); 3622 var shortColIndex = utils.indexOf( colGroup, minimumY ); 3623 3624 // position the brick 3625 var position = { 3626 x: this.columnWidth * shortColIndex, 3627 y: minimumY 3628 }; 3629 3630 // apply setHeight to necessary columns 3631 var setHeight = minimumY + item.size.outerHeight; 3632 var setSpan = this.cols + 1 - colGroup.length; 3633 for ( var i = 0; i < setSpan; i++ ) { 3634 this.colYs[ shortColIndex + i ] = setHeight; 3635 } 3636 3637 return position; 3638 }; 3639 3640 /** 3641 * @param {Number} colSpan - number of columns the element spans 3642 * @returns {Array} colGroup 3643 */ 3644 Masonry.prototype._getColGroup = function( colSpan ) { 3645 if ( colSpan < 2 ) { 3646 // if brick spans only one column, use all the column Ys 3647 return this.colYs; 3648 } 3649 3650 var colGroup = []; 3651 // how many different places could this brick fit horizontally 3652 var groupCount = this.cols + 1 - colSpan; 3653 // for each group potential horizontal position 3654 for ( var i = 0; i < groupCount; i++ ) { 3655 // make an array of colY values for that one group 3656 var groupColYs = this.colYs.slice( i, i + colSpan ); 3657 // and get the max value of the array 3658 colGroup[i] = Math.max.apply( Math, groupColYs ); 3659 } 3660 return colGroup; 3661 }; 3662 3663 Masonry.prototype._manageStamp = function( stamp ) { 3664 var stampSize = getSize( stamp ); 3665 var offset = this._getElementOffset( stamp ); 3666 // get the columns that this stamp affects 3667 var firstX = this.options.isOriginLeft ? offset.left : offset.right; 3668 var lastX = firstX + stampSize.outerWidth; 3669 var firstCol = Math.floor( firstX / this.columnWidth ); 3670 firstCol = Math.max( 0, firstCol ); 3671 var lastCol = Math.floor( lastX / this.columnWidth ); 3672 // lastCol should not go over if multiple of columnWidth #425 3673 lastCol -= lastX % this.columnWidth ? 0 : 1; 3674 lastCol = Math.min( this.cols - 1, lastCol ); 3675 // set colYs to bottom of the stamp 3676 var stampMaxY = ( this.options.isOriginTop ? offset.top : offset.bottom ) + 3677 stampSize.outerHeight; 3678 for ( var i = firstCol; i <= lastCol; i++ ) { 3679 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 3680 } 3681 }; 3682 3683 Masonry.prototype._getContainerSize = function() { 3684 this.maxY = Math.max.apply( Math, this.colYs ); 3685 var size = { 3686 height: this.maxY 3687 }; 3688 3689 if ( this.options.isFitWidth ) { 3690 size.width = this._getContainerFitWidth(); 3691 } 3692 3693 return size; 3694 }; 3695 3696 Masonry.prototype._getContainerFitWidth = function() { 3697 var unusedCols = 0; 3698 // count unused columns 3699 var i = this.cols; 3700 while ( --i ) { 3701 if ( this.colYs[i] !== 0 ) { 3702 break; 3703 } 3704 unusedCols++; 3705 } 3706 // fit container to columns that have been used 3707 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 3708 }; 3709 3710 Masonry.prototype.needsResizeLayout = function() { 3711 var previousWidth = this.containerWidth; 3712 this.getContainerWidth(); 3713 return previousWidth !== this.containerWidth; 3714 }; 3715 3716 return Masonry; 3717 3718})); 3719 3720/*! 3721 * Masonry layout mode 3722 * sub-classes Masonry 3723 * http://masonry.desandro.com 3724 */ 3725 3726( function( window, factory ) { 3727 'use strict'; 3728 // universal module definition 3729 if ( typeof define == 'function' && define.amd ) { 3730 // AMD 3731 define( 'isotope/js/layout-modes/masonry',[ 3732 '../layout-mode', 3733 'masonry/masonry' 3734 ], 3735 factory ); 3736 } else if ( typeof exports == 'object' ) { 3737 // CommonJS 3738 module.exports = factory( 3739 require('../layout-mode'), 3740 require('masonry-layout') 3741 ); 3742 } else { 3743 // browser global 3744 factory( 3745 window.Isotope.LayoutMode, 3746 window.Masonry 3747 ); 3748 } 3749 3750}( window, function factory( LayoutMode, Masonry ) { 3751'use strict'; 3752 3753// -------------------------- helpers -------------------------- // 3754 3755// extend objects 3756function extend( a, b ) { 3757 for ( var prop in b ) { 3758 a[ prop ] = b[ prop ]; 3759 } 3760 return a; 3761} 3762 3763// -------------------------- masonryDefinition -------------------------- // 3764 3765 // create an Outlayer layout class 3766 var MasonryMode = LayoutMode.create('masonry'); 3767 3768 // save on to these methods 3769 var _getElementOffset = MasonryMode.prototype._getElementOffset; 3770 var layout = MasonryMode.prototype.layout; 3771 var _getMeasurement = MasonryMode.prototype._getMeasurement; 3772 3773 // sub-class Masonry 3774 extend( MasonryMode.prototype, Masonry.prototype ); 3775 3776 // set back, as it was overwritten by Masonry 3777 MasonryMode.prototype._getElementOffset = _getElementOffset; 3778 MasonryMode.prototype.layout = layout; 3779 MasonryMode.prototype._getMeasurement = _getMeasurement; 3780 3781 var measureColumns = MasonryMode.prototype.measureColumns; 3782 MasonryMode.prototype.measureColumns = function() { 3783 // set items, used if measuring first item 3784 this.items = this.isotope.filteredItems; 3785 measureColumns.call( this ); 3786 }; 3787 3788 // HACK copy over isOriginLeft/Top options 3789 var _manageStamp = MasonryMode.prototype._manageStamp; 3790 MasonryMode.prototype._manageStamp = function() { 3791 this.options.isOriginLeft = this.isotope.options.isOriginLeft; 3792 this.options.isOriginTop = this.isotope.options.isOriginTop; 3793 _manageStamp.apply( this, arguments ); 3794 }; 3795 3796 return MasonryMode; 3797 3798})); 3799 3800/** 3801 * fitRows layout mode 3802 */ 3803 3804( function( window, factory ) { 3805 'use strict'; 3806 // universal module definition 3807 if ( typeof define == 'function' && define.amd ) { 3808 // AMD 3809 define( 'isotope/js/layout-modes/fit-rows',[ 3810 '../layout-mode' 3811 ], 3812 factory ); 3813 } else if ( typeof exports == 'object' ) { 3814 // CommonJS 3815 module.exports = factory( 3816 require('../layout-mode') 3817 ); 3818 } else { 3819 // browser global 3820 factory( 3821 window.Isotope.LayoutMode 3822 ); 3823 } 3824 3825}( window, function factory( LayoutMode ) { 3826'use strict'; 3827 3828var FitRows = LayoutMode.create('fitRows'); 3829 3830FitRows.prototype._resetLayout = function() { 3831 this.x = 0; 3832 this.y = 0; 3833 this.maxY = 0; 3834 this._getMeasurement( 'gutter', 'outerWidth' ); 3835}; 3836 3837FitRows.prototype._getItemLayoutPosition = function( item ) { 3838 item.getSize(); 3839 3840 var itemWidth = item.size.outerWidth + this.gutter; 3841 // if this element cannot fit in the current row 3842 var containerWidth = this.isotope.size.innerWidth + this.gutter; 3843 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 3844 this.x = 0; 3845 this.y = this.maxY; 3846 } 3847 3848 var position = { 3849 x: this.x, 3850 y: this.y 3851 }; 3852 3853 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 3854 this.x += itemWidth; 3855 3856 return position; 3857}; 3858 3859FitRows.prototype._getContainerSize = function() { 3860 return { height: this.maxY }; 3861}; 3862 3863return FitRows; 3864 3865})); 3866 3867/** 3868 * vertical layout mode 3869 */ 3870 3871( function( window, factory ) { 3872 'use strict'; 3873 // universal module definition 3874 if ( typeof define == 'function' && define.amd ) { 3875 // AMD 3876 define( 'isotope/js/layout-modes/vertical',[ 3877 '../layout-mode' 3878 ], 3879 factory ); 3880 } else if ( typeof exports == 'object' ) { 3881 // CommonJS 3882 module.exports = factory( 3883 require('../layout-mode') 3884 ); 3885 } else { 3886 // browser global 3887 factory( 3888 window.Isotope.LayoutMode 3889 ); 3890 } 3891 3892}( window, function factory( LayoutMode ) { 3893'use strict'; 3894 3895var Vertical = LayoutMode.create( 'vertical', { 3896 horizontalAlignment: 0 3897}); 3898 3899Vertical.prototype._resetLayout = function() { 3900 this.y = 0; 3901}; 3902 3903Vertical.prototype._getItemLayoutPosition = function( item ) { 3904 item.getSize(); 3905 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 3906 this.options.horizontalAlignment; 3907 var y = this.y; 3908 this.y += item.size.outerHeight; 3909 return { x: x, y: y }; 3910}; 3911 3912Vertical.prototype._getContainerSize = function() { 3913 return { height: this.y }; 3914}; 3915 3916return Vertical; 3917 3918})); 3919 3920/*! 3921 * Isotope v2.2.2 3922 * 3923 * Licensed GPLv3 for open source use 3924 * or Isotope Commercial License for commercial use 3925 * 3926 * http://isotope.metafizzy.co 3927 * Copyright 2015 Metafizzy 3928 */ 3929 3930( function( window, factory ) { 3931 'use strict'; 3932 // universal module definition 3933 3934 if ( typeof define == 'function' && define.amd ) { 3935 // AMD 3936 define( [ 3937 'outlayer/outlayer', 3938 'get-size/get-size', 3939 'matches-selector/matches-selector', 3940 'fizzy-ui-utils/utils', 3941 'isotope/js/item', 3942 'isotope/js/layout-mode', 3943 // include default layout modes 3944 'isotope/js/layout-modes/masonry', 3945 'isotope/js/layout-modes/fit-rows', 3946 'isotope/js/layout-modes/vertical' 3947 ], 3948 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 3949 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 3950 }); 3951 } else if ( typeof exports == 'object' ) { 3952 // CommonJS 3953 module.exports = factory( 3954 window, 3955 require('outlayer'), 3956 require('get-size'), 3957 require('desandro-matches-selector'), 3958 require('fizzy-ui-utils'), 3959 require('./item'), 3960 require('./layout-mode'), 3961 // include default layout modes 3962 require('./layout-modes/masonry'), 3963 require('./layout-modes/fit-rows'), 3964 require('./layout-modes/vertical') 3965 ); 3966 } else { 3967 // browser global 3968 window.Isotope = factory( 3969 window, 3970 window.Outlayer, 3971 window.getSize, 3972 window.matchesSelector, 3973 window.fizzyUIUtils, 3974 window.Isotope.Item, 3975 window.Isotope.LayoutMode 3976 ); 3977 } 3978 3979}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 3980 Item, LayoutMode ) { 3981 3982 3983 3984// -------------------------- vars -------------------------- // 3985 3986var jQuery = window.jQuery; 3987 3988// -------------------------- helpers -------------------------- // 3989 3990var trim = String.prototype.trim ? 3991 function( str ) { 3992 return str.trim(); 3993 } : 3994 function( str ) { 3995 return str.replace( /^\s+|\s+$/g, '' ); 3996 }; 3997 3998var docElem = document.documentElement; 3999 4000var getText = docElem.textContent ? 4001 function( elem ) { 4002 return elem.textContent; 4003 } : 4004 function( elem ) { 4005 return elem.innerText; 4006 }; 4007 4008// -------------------------- isotopeDefinition -------------------------- // 4009 4010 // create an Outlayer layout class 4011 var Isotope = Outlayer.create( 'isotope', { 4012 layoutMode: "masonry", 4013 isJQueryFiltering: true, 4014 sortAscending: true 4015 }); 4016 4017 Isotope.Item = Item; 4018 Isotope.LayoutMode = LayoutMode; 4019 4020 Isotope.prototype._create = function() { 4021 this.itemGUID = 0; 4022 // functions that sort items 4023 this._sorters = {}; 4024 this._getSorters(); 4025 // call super 4026 Outlayer.prototype._create.call( this ); 4027 4028 // create layout modes 4029 this.modes = {}; 4030 // start filteredItems with all items 4031 this.filteredItems = this.items; 4032 // keep of track of sortBys 4033 this.sortHistory = [ 'original-order' ]; 4034 // create from registered layout modes 4035 for ( var name in LayoutMode.modes ) { 4036 this._initLayoutMode( name ); 4037 } 4038 }; 4039 4040 Isotope.prototype.reloadItems = function() { 4041 // reset item ID counter 4042 this.itemGUID = 0; 4043 // call super 4044 Outlayer.prototype.reloadItems.call( this ); 4045 }; 4046 4047 Isotope.prototype._itemize = function() { 4048 var items = Outlayer.prototype._itemize.apply( this, arguments ); 4049 // assign ID for original-order 4050 for ( var i=0, len = items.length; i < len; i++ ) { 4051 var item = items[i]; 4052 item.id = this.itemGUID++; 4053 } 4054 this._updateItemsSortData( items ); 4055 return items; 4056 }; 4057 4058 4059 // -------------------------- layout -------------------------- // 4060 4061 Isotope.prototype._initLayoutMode = function( name ) { 4062 var Mode = LayoutMode.modes[ name ]; 4063 // set mode options 4064 // HACK extend initial options, back-fill in default options 4065 var initialOpts = this.options[ name ] || {}; 4066 this.options[ name ] = Mode.options ? 4067 utils.extend( Mode.options, initialOpts ) : initialOpts; 4068 // init layout mode instance 4069 this.modes[ name ] = new Mode( this ); 4070 }; 4071 4072 4073 Isotope.prototype.layout = function() { 4074 // if first time doing layout, do all magic 4075 if ( !this._isLayoutInited && this.options.isInitLayout ) { 4076 this.arrange(); 4077 return; 4078 } 4079 this._layout(); 4080 }; 4081 4082 // private method to be used in layout() & magic() 4083 Isotope.prototype._layout = function() { 4084 // don't animate first layout 4085 var isInstant = this._getIsInstant(); 4086 // layout flow 4087 this._resetLayout(); 4088 this._manageStamps(); 4089 this.layoutItems( this.filteredItems, isInstant ); 4090 4091 // flag for initalized 4092 this._isLayoutInited = true; 4093 }; 4094 4095 // filter + sort + layout 4096 Isotope.prototype.arrange = function( opts ) { 4097 // set any options pass 4098 this.option( opts ); 4099 this._getIsInstant(); 4100 // filter, sort, and layout 4101 4102 // filter 4103 var filtered = this._filter( this.items ); 4104 this.filteredItems = filtered.matches; 4105 4106 var _this = this; 4107 function hideReveal() { 4108 _this.reveal( filtered.needReveal ); 4109 _this.hide( filtered.needHide ); 4110 } 4111 4112 this._bindArrangeComplete(); 4113 4114 if ( this._isInstant ) { 4115 this._noTransition( hideReveal ); 4116 } else { 4117 hideReveal(); 4118 } 4119 4120 this._sort(); 4121 this._layout(); 4122 }; 4123 // alias to _init for main plugin method 4124 Isotope.prototype._init = Isotope.prototype.arrange; 4125 4126 // HACK 4127 // Don't animate/transition first layout 4128 // Or don't animate/transition other layouts 4129 Isotope.prototype._getIsInstant = function() { 4130 var isInstant = this.options.isLayoutInstant !== undefined ? 4131 this.options.isLayoutInstant : !this._isLayoutInited; 4132 this._isInstant = isInstant; 4133 return isInstant; 4134 }; 4135 4136 // listen for layoutComplete, hideComplete and revealComplete 4137 // to trigger arrangeComplete 4138 Isotope.prototype._bindArrangeComplete = function() { 4139 // listen for 3 events to trigger arrangeComplete 4140 var isLayoutComplete, isHideComplete, isRevealComplete; 4141 var _this = this; 4142 function arrangeParallelCallback() { 4143 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 4144 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 4145 } 4146 } 4147 this.once( 'layoutComplete', function() { 4148 isLayoutComplete = true; 4149 arrangeParallelCallback(); 4150 }); 4151 this.once( 'hideComplete', function() { 4152 isHideComplete = true; 4153 arrangeParallelCallback(); 4154 }); 4155 this.once( 'revealComplete', function() { 4156 isRevealComplete = true; 4157 arrangeParallelCallback(); 4158 }); 4159 }; 4160 4161 // -------------------------- filter -------------------------- // 4162 4163 Isotope.prototype._filter = function( items ) { 4164 var filter = this.options.filter;
4165 filter = filter || '*'; 4166 var matches = []; 4167 var hiddenMatched = []; 4168 var visibleUnmatched = []; 4169 4170 var test = this._getFilterTest( filter ); 4171 4172 // test each item 4173 for ( var i=0, len = items.length; i < len; i++ ) { 4174 var item = items[i]; 4175 if ( item.isIgnored ) { 4176 continue; 4177 } 4178 // add item to either matched or unmatched group 4179 var isMatched = test( item ); 4180 // item.isFilterMatched = isMatched; 4181 // add to matches if its a match 4182 if ( isMatched ) { 4183 matches.push( item ); 4184 } 4185 // add to additional group if item needs to be hidden or revealed 4186 if ( isMatched && item.isHidden ) { 4187 hiddenMatched.push( item ); 4188 } else if ( !isMatched && !item.isHidden ) { 4189 visibleUnmatched.push( item ); 4190 } 4191 } 4192 4193 // return collections of items to be manipulated 4194 return { 4195 matches: matches, 4196 needReveal: hiddenMatched, 4197 needHide: visibleUnmatched 4198 }; 4199 }; 4200 4201 // get a jQuery, function, or a matchesSelector test given the filter 4202 Isotope.prototype._getFilterTest = function( filter ) { 4203 if ( jQuery && this.options.isJQueryFiltering ) { 4204 // use jQuery 4205 return function( item ) { 4206 return jQuery( item.element ).is( filter ); 4207 }; 4208 } 4209 if ( typeof filter == 'function' ) { 4210 // use filter as function 4211 return function( item ) { 4212 return filter( item.element ); 4213 }; 4214 } 4215 // default, use filter as selector string 4216 return function( item ) { 4217 return matchesSelector( item.element, filter ); 4218 }; 4219 }; 4220 4221 // -------------------------- sorting -------------------------- // 4222 4223 /** 4224 * @params {Array} elems 4225 * @public 4226 */ 4227 Isotope.prototype.updateSortData = function( elems ) { 4228 // get items 4229 var items; 4230 if ( elems ) { 4231 elems = utils.makeArray( elems ); 4232 items = this.getItems( elems ); 4233 } else { 4234 // update all items if no elems provided 4235 items = this.items; 4236 } 4237 4238 this._getSorters(); 4239 this._updateItemsSortData( items ); 4240 }; 4241 4242 Isotope.prototype._getSorters = function() { 4243 var getSortData = this.options.getSortData; 4244 for ( var key in getSortData ) { 4245 var sorter = getSortData[ key ]; 4246 this._sorters[ key ] = mungeSorter( sorter ); 4247 } 4248 }; 4249 4250 /** 4251 * @params {Array} items - of Isotope.Items 4252 * @private 4253 */ 4254 Isotope.prototype._updateItemsSortData = function( items ) { 4255 // do not update if no items 4256 var len = items && items.length; 4257 4258 for ( var i=0; len && i < len; i++ ) { 4259 var item = items[i]; 4260 item.updateSortData(); 4261 } 4262 }; 4263 4264 // ----- munge sorter ----- // 4265 4266 // encapsulate this, as we just need mungeSorter 4267 // other functions in here are just for munging 4268 var mungeSorter = ( function() { 4269 // add a magic layer to sorters for convienent shorthands 4270 // `.foo-bar` will use the text of .foo-bar querySelector 4271 // `[foo-bar]` will use attribute 4272 // you can also add parser 4273 // `.foo-bar parseInt` will parse that as a number 4274 function mungeSorter( sorter ) { 4275 // if not a string, return function or whatever it is 4276 if ( typeof sorter != 'string' ) { 4277 return sorter; 4278 } 4279 // parse the sorter string 4280 var args = trim( sorter ).split(' '); 4281 var query = args[0]; 4282 // check if query looks like [an-attribute] 4283 var attrMatch = query.match( /^\[(.+)\]$/ ); 4284 var attr = attrMatch && attrMatch[1]; 4285 var getValue = getValueGetter( attr, query ); 4286 // use second argument as a parser 4287 var parser = Isotope.sortDataParsers[ args[1] ]; 4288 // parse the value, if there was a parser 4289 sorter = parser ? function( elem ) { 4290 return elem && parser( getValue( elem ) ); 4291 } : 4292 // otherwise just return value 4293 function( elem ) { 4294 return elem && getValue( elem ); 4295 }; 4296 4297 return sorter; 4298 } 4299 4300 // get an attribute getter, or get text of the querySelector 4301 function getValueGetter( attr, query ) { 4302 var getValue; 4303 // if query looks like [foo-bar], get attribute 4304 if ( attr ) { 4305 getValue = function( elem ) { 4306 return elem.getAttribute( attr ); 4307 }; 4308 } else { 4309 // otherwise, assume its a querySelector, and get its text 4310 getValue = function( elem ) { 4311 var child = elem.querySelector( query ); 4312 return child && getText( child ); 4313 }; 4314 } 4315 return getValue; 4316 } 4317 4318 return mungeSorter; 4319 })(); 4320 4321 // parsers used in getSortData shortcut strings 4322 Isotope.sortDataParsers = { 4323 'parseInt': function( val ) { 4324 return parseInt( val, 10 ); 4325 }, 4326 'parseFloat': function( val ) { 4327 return parseFloat( val ); 4328 } 4329 }; 4330 4331 // ----- sort method ----- // 4332 4333 // sort filteredItem order 4334 Isotope.prototype._sort = function() { 4335 var sortByOpt = this.options.sortBy; 4336 if ( !sortByOpt ) { 4337 return; 4338 } 4339 // concat all sortBy and sortHistory 4340 var sortBys = [].concat.apply( sortByOpt, this.sortHistory ); 4341 // sort magic 4342 var itemSorter = getItemSorter( sortBys, this.options.sortAscending ); 4343 this.filteredItems.sort( itemSorter ); 4344 // keep track of sortBy History 4345 if ( sortByOpt != this.sortHistory[0] ) { 4346 // add to front, oldest goes in last 4347 this.sortHistory.unshift( sortByOpt ); 4348 } 4349 }; 4350 4351 // returns a function used for sorting 4352 function getItemSorter( sortBys, sortAsc ) { 4353 return function sorter( itemA, itemB ) { 4354 // cycle through all sortKeys 4355 for ( var i = 0, len = sortBys.length; i < len; i++ ) { 4356 var sortBy = sortBys[i]; 4357 var a = itemA.sortData[ sortBy ]; 4358 var b = itemB.sortData[ sortBy ]; 4359 if ( a > b || a < b ) { 4360 // if sortAsc is an object, use the value given the sortBy key
4361 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 4362 var direction = isAscending ? 1 : -1; 4363 return ( a > b ? 1 : -1 ) * direction; 4364 } 4365 } 4366 return 0; 4367 }; 4368 } 4369 4370 // -------------------------- methods -------------------------- // 4371 4372 // get layout mode 4373 Isotope.prototype._mode = function() { 4374 var layoutMode = this.options.layoutMode; 4375 var mode = this.modes[ layoutMode ]; 4376 if ( !mode ) { 4377 // TODO console.error 4378 throw new Error( 'No layout mode: ' + layoutMode ); 4379 } 4380 // HACK sync mode's options 4381 // any options set after init for layout mode need to be synced 4382 mode.options = this.options[ layoutMode ]; 4383 return mode; 4384 }; 4385 4386 Isotope.prototype._resetLayout = function() { 4387 // trigger original reset layout 4388 Outlayer.prototype._resetLayout.call( this ); 4389 this._mode()._resetLayout(); 4390 }; 4391 4392 Isotope.prototype._getItemLayoutPosition = function( item ) { 4393 return this._mode()._getItemLayoutPosition( item ); 4394 }; 4395 4396 Isotope.prototype._manageStamp = function( stamp ) { 4397 this._mode()._manageStamp( stamp ); 4398 }; 4399 4400 Isotope.prototype._getContainerSize = function() { 4401 return this._mode()._getContainerSize(); 4402 }; 4403 4404 Isotope.prototype.needsResizeLayout = function() { 4405 return this._mode().needsResizeLayout(); 4406 }; 4407 4408 // -------------------------- adding & removing -------------------------- // 4409 4410 // HEADS UP overwrites default Outlayer appended 4411 Isotope.prototype.appended = function( elems ) { 4412 var items = this.addItems( elems ); 4413 if ( !items.length ) { 4414 return; 4415 } 4416 // filter, layout, reveal new items 4417 var filteredItems = this._filterRevealAdded( items ); 4418 // add to filteredItems 4419 this.filteredItems = this.filteredItems.concat( filteredItems ); 4420 }; 4421 4422 // HEADS UP overwrites default Outlayer prepended 4423 Isotope.prototype.prepended = function( elems ) { 4424 var items = this._itemize( elems ); 4425 if ( !items.length ) { 4426 return; 4427 } 4428 // start new layout 4429 this._resetLayout(); 4430 this._manageStamps(); 4431 // filter, layout, reveal new items 4432 var filteredItems = this._filterRevealAdded( items ); 4433 // layout previous items 4434 this.layoutItems( this.filteredItems ); 4435 // add to items and filteredItems 4436 this.filteredItems = filteredItems.concat( this.filteredItems ); 4437 this.items = items.concat( this.items ); 4438 }; 4439 4440 Isotope.prototype._filterRevealAdded = function( items ) { 4441 var filtered = this._filter( items ); 4442 this.hide( filtered.needHide ); 4443 // reveal all new items 4444 this.reveal( filtered.matches ); 4445 // layout new items, no transition 4446 this.layoutItems( filtered.matches, true ); 4447 return filtered.matches; 4448 }; 4449 4450 /** 4451 * Filter, sort, and layout newly-appended item elements 4452 * @param {Array or NodeList or Element} elems 4453 */ 4454 Isotope.prototype.insert = function( elems ) { 4455 var items = this.addItems( elems ); 4456 if ( !items.length ) { 4457 return; 4458 } 4459 // append item elements 4460 var i, item; 4461 var len = items.length; 4462 for ( i=0; i < len; i++ ) { 4463 item = items[i]; 4464 this.element.appendChild( item.element ); 4465 } 4466 // filter new stuff 4467 var filteredInsertItems = this._filter( items ).matches; 4468 // set flag 4469 for ( i=0; i < len; i++ ) { 4470 items[i].isLayoutInstant = true; 4471 } 4472 this.arrange(); 4473 // reset flag 4474 for ( i=0; i < len; i++ ) { 4475 delete items[i].isLayoutInstant; 4476 } 4477 this.reveal( filteredInsertItems ); 4478 }; 4479 4480 var _remove = Isotope.prototype.remove; 4481 Isotope.prototype.remove = function( elems ) { 4482 elems = utils.makeArray( elems ); 4483 var removeItems = this.getItems( elems ); 4484 // do regular thing 4485 _remove.call( this, elems ); 4486 // bail if no items to remove 4487 var len = removeItems && removeItems.length; 4488 if ( !len ) { 4489 return; 4490 } 4491 // remove elems from filteredItems 4492 for ( var i=0; i < len; i++ ) { 4493 var item = removeItems[i]; 4494 // remove item from collection 4495 utils.removeFrom( this.filteredItems, item ); 4496 } 4497 }; 4498 4499 Isotope.prototype.shuffle = function() { 4500 // update random sortData 4501 for ( var i=0, len = this.items.length; i < len; i++ ) { 4502 var item = this.items[i]; 4503 item.sortData.random = Math.random(); 4504 } 4505 this.options.sortBy = 'random'; 4506 this._sort(); 4507 this._layout(); 4508 }; 4509 4510 /** 4511 * trigger fn without transition 4512 * kind of hacky to have this in the first place 4513 * @param {Function} fn 4514 * @returns ret 4515 * @private 4516 */ 4517 Isotope.prototype._noTransition = function( fn ) { 4518 // save transitionDuration before disabling 4519 var transitionDuration = this.options.transitionDuration; 4520 // disable transition 4521 this.options.transitionDuration = 0; 4522 // do it 4523 var returnValue = fn.call( this ); 4524 // re-enable transition for reveal 4525 this.options.transitionDuration = transitionDuration; 4526 return returnValue; 4527 }; 4528 4529 // ----- helper methods ----- // 4530 4531 /** 4532 * getter method for getting filtered item elements 4533 * @returns {Array} elems - collection of item elements 4534 */ 4535 Isotope.prototype.getFilteredItemElements = function() { 4536 var elems = []; 4537 for ( var i=0, len = this.filteredItems.length; i < len; i++ ) { 4538 elems.push( this.filteredItems[i].element ); 4539 } 4540 return elems; 4541 }; 4542 4543 // ----- ----- // 4544 4545 return Isotope; 4546 4547})); 4548 4549 4550/*! 4551 * Packery layout mode PACKAGED v1.1.1 4552 * sub-classes Packery 4553 * http://packery.metafizzy.co 4554 */ 4555 4556!function(a){function b(a){return new RegExp("(^|\\s+)"+a+"(\\s+|$)")}function c(a,b){var c=d(a,b)?f:e;c(a,b)}var d,e,f;"classList"in document.documentElement?(d=function(a,b){return a.classList.contains(b)}
4556,e=function(a,b){a.classList.add(b)},f=function(a,b){a.classList.remove(b)}):(d=function(a,c){return b(c).test(a.className)},e=function(a,b){d(a,b)||(a.className=a.className+" "+b)},f=function(a,c){a.className=a.className.replace(b(c)," ")});var g={hasClass:d,addClass:e,removeClass:f,toggleClass:c,has:d,add:e,remove:f,toggle:c};"function"==typeof define&&define.amd?define("classie/classie",g):"object"==typeof exports?module.exports=g:a.classie=g}(window),function(a){function b(){function a(b){for(var c in a.defaults)this[c]=a.defaults[c];for(c in b)this[c]=b[c]}return c.Rect=a,a.defaults={x:0,y:0,width:0,height:0},a.prototype.contains=function(a){var b=a.width||0,c=a.height||0;return this.x<=a.x&&this.y<=a.y&&this.x+this.width>=a.x+b&&this.y+this.height>=a.y+c},a.prototype.overlaps=function(a){var b=this.x+this.width,c=this.y+this.height,d=a.x+a.width,e=a.y+a.height;return this.x<d&&b>a.x&&this.y<e&&c>a.y},a.prototype.getMaximalFreeRects=function(b){if(!this.overlaps(b))return!1;var c,d=[],e=this.x+this.width,f=this.y+this.height,g=b.x+b.width,h=b.y+b.height;return this.y<b.y&&(c=new a({x:this.x,y:this.y,width:this.width,height:b.y-this.y}),d.push(c)),e>g&&(c=new a({x:g,y:this.y,width:e-g,height:this.height}),d.push(c)),f>h&&(c=new a({x:this.x,y:h,width:this.width,height:f-h}),d.push(c)),this.x<b.x&&(c=new a({x:this.x,y:this.y,width:b.x-this.x,height:this.height}),d.push(c)),d},a.prototype.canFit=function(a){return this.width>=a.width&&this.height>=a.height},a}var c=a.Packery=function(){};"function"==typeof define&&define.amd?define("packery/js/rect",b):"object"==typeof exports?module.exports=b():(a.Packery=a.Packery||{},a.Packery.Rect=b())}(window),function(a){function b(a){function b(a,b,c){this.width=a||0,this.height=b||0,this.sortDirection=c||"downwardLeftToRight",this.reset()}b.prototype.reset=function(){this.spaces=[],this.newSpaces=[];var b=new a({x:0,y:0,width:this.width,height:this.height});this.spaces.push(b),this.sorter=c[this.sortDirection]||c.downwardLeftToRight},b.prototype.pack=function(a){for(var b=0,c=this.spaces.length;c>b;b++){var d=this.spaces[b];if(d.canFit(a)){this.placeInSpace(a,d);break}}},b.prototype.placeInSpace=function(a,b){a.x=b.x,a.y=b.y,this.placed(a)},b.prototype.placed=function(a){for(var b=[],c=0,d=this.spaces.length;d>c;c++){var e=this.spaces[c],f=e.getMaximalFreeRects(a);f?b.push.apply(b,f):b.push(e)}this.spaces=b,this.mergeSortSpaces()},b.prototype.mergeSortSpaces=function(){b.mergeRects(this.spaces),this.spaces.sort(this.sorter)},b.prototype.addSpace=function(a){this.spaces.push(a),this.mergeSortSpaces()},b.mergeRects=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];if(d){var e=a.slice(0);e.splice(b,1);for(var f=0,g=0,h=e.length;h>g;g++){var i=e[g],j=b>g?0:1;d.contains(i)&&(a.splice(g+j-f,1),f++)}}}return a};var c={downwardLeftToRight:function(a,b){return a.y-b.y||a.x-b.x},rightwardTopToBottom:function(a,b){return a.x-b.x||a.y-b.y}};return b}if("function"==typeof define&&define.amd)define("packery/js/packer",["./rect"],b);else if("object"==typeof exports)module.exports=b(require("./rect"));else{var c=a.Packery=a.Packery||{};c.Packer=b(c.Rect)}}(window),function(a){function b(a,b,c){var d=a("transform"),e=function(){b.Item.apply(this,arguments)};e.prototype=new b.Item;var f=e.prototype._create;return e.prototype._create=function(){f.call(this),this.rect=new c,this.placeRect=new c},e.prototype.dragStart=function(){this.getPosition(),this.removeTransitionStyles(),this.isTransitioning&&d&&(this.element.style[d]="none"),this.getSize(),this.isPlacing=!0,this.needsPositioning=!1,this.positionPlaceRect(this.position.x,this.position.y),this.isTransitioning=!1,this.didDrag=!1},e.prototype.dragMove=function(a,b){this.didDrag=!0;var c=this.layout.size;a-=c.paddingLeft,b-=c.paddingTop,this.positionPlaceRect(a,b)},e.prototype.dragStop=function(){this.getPosition();var a=this.position.x!==this.placeRect.x,b=this.position.y!==this.placeRect.y;this.needsPositioning=a||b,this.didDrag=!1},e.prototype.positionPlaceRect=function(a,b,c){this.placeRect.x=this.getPlaceRectCoord(a,!0),this.placeRect.y=this.getPlaceRectCoord(b,!1,c)},e.prototype.getPlaceRectCoord=function(a,b,c){var d=b?"Width":"Height",e=this.size["outer"+d],f=this.layout[b?"columnWidth":"rowHeight"],g=this.layout.size["inner"+d];b||(g=Math.max(g,this.layout.maxY),this.layout.rowHeight||(g-=this.layout.gutter));var h;if(f){f+=this.layout.gutter,g+=b?this.layout.gutter:0,a=Math.round(a/f);var i;i=this.layout.options.isHorizontal?b?"ceil":"floor":b?"floor":"ceil";var j=Math[i](g/f);j-=Math.ceil(e/f),h=j}else h=g-e;return a=c?a:Math.min(a,h),a*=f||1,Math.max(0,a)},e.prototype.copyPlaceRectPosition=function(){this.rect.x=this.placeRect.x,this.rect.y=this.placeRect.y},e.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.layout.packer.addSpace(this.rect),this.emitEvent("remove",[this])},e}"function"==typeof define&&define.amd?define("packery/js/item",["get-style-property/get-style-property","outlayer/outlayer","./rect"],b):"object"==typeof exports?module.exports=b(require("desandro-get-style-property"),require("outlayer"),require("./rect")):a.Packery.Item=b(a.getStyleProperty,a.Outlayer,a.Packery.Rect)}(window),function(a){function b(a,b,c,d,e,f){function g(a,b){return a.position.y-b.position.y||a.position.x-b.position.x}function h(a,b){return a.position.x-b.position.x||a.position.y-b.position.y}d.prototype.canFit=function(a){return this.width>=a.width-1&&this.height>=a.height-1};var i=c.create("packery");return i.Item=f,i.prototype._create=function(){c.prototype._create.call(this),this.packer=new e,this.stamp(this.options.stamped);var a=this;this.handleDraggabilly={dragStart:function(b){a.itemDragStart(b.element)},dragMove:function(b){a.itemDragMove(b.element,b.position.x,b.position.y)},dragEnd:function(b){a.itemDragEnd(b.element)}},this.handleUIDraggable={start:function(b){a.itemDragStart(b.currentTarget)},drag:function(b,c){a.itemDragMove(b.currentTarget,c.position.left,c.position.top)},stop:function(b){a.itemDragEnd(b.currentTarget)}}}
4556,i.prototype._resetLayout=function(){this.getSize(),this._getMeasurements();var a=this.packer;this.options.isHorizontal?(a.width=Number.POSITIVE_INFINITY,a.height=this.size.innerHeight+this.gutter,a.sortDirection="rightwardTopToBottom"):(a.width=this.size.innerWidth+this.gutter,a.height=Number.POSITIVE_INFINITY,a.sortDirection="downwardLeftToRight"),a.reset(),this.maxY=0,this.maxX=0},i.prototype._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},i.prototype._getItemLayoutPosition=function(a){return this._packItem(a),a.rect},i.prototype._packItem=function(a){this._setRectSize(a.element,a.rect),this.packer.pack(a.rect),this._setMaxXY(a.rect)},i.prototype._setMaxXY=function(a){this.maxX=Math.max(a.x+a.width,this.maxX),this.maxY=Math.max(a.y+a.height,this.maxY)},i.prototype._setRectSize=function(a,c){var d=b(a),e=d.outerWidth,f=d.outerHeight;(e||f)&&(e=this._applyGridGutter(e,this.columnWidth),f=this._applyGridGutter(f,this.rowHeight)),c.width=Math.min(e,this.packer.width),c.height=Math.min(f,this.packer.height)},i.prototype._applyGridGutter=function(a,b){if(!b)return a+this.gutter;b+=this.gutter;var c=a%b,d=c&&1>c?"round":"ceil";return a=Math[d](a/b)*b},i.prototype._getContainerSize=function(){return this.options.isHorizontal?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},i.prototype._manageStamp=function(a){var b,c=this.getItem(a);if(c&&c.isPlacing)b=c.placeRect;else{var e=this._getElementOffset(a);b=new d({x:this.options.isOriginLeft?e.left:e.right,y:this.options.isOriginTop?e.top:e.bottom})}this._setRectSize(a,b),this.packer.placed(b),this._setMaxXY(b)},i.prototype.sortItemsByPosition=function(){var a=this.options.isHorizontal?h:g;this.items.sort(a)},i.prototype.fit=function(a,b,c){var d=this.getItem(a);d&&(this._getMeasurements(),this.stamp(d.element),d.getSize(),d.isPlacing=!0,b=void 0===b?d.rect.x:b,c=void 0===c?d.rect.y:c,d.positionPlaceRect(b,c,!0),this._bindFitEvents(d),d.moveTo(d.placeRect.x,d.placeRect.y),this.layout(),this.unstamp(d.element),this.sortItemsByPosition(),d.isPlacing=!1,d.copyPlaceRectPosition())},i.prototype._bindFitEvents=function(a){function b(){d++,2===d&&c.emitEvent("fitComplete",[c,a])}var c=this,d=0;a.on("layout",function(){return b(),!0}),this.on("layoutComplete",function(){return b(),!0})},i.prototype.resize=function(){var a=b(this.element),c=this.size&&a,d=this.options.isHorizontal?"innerHeight":"innerWidth";c&&a[d]===this.size[d]||this.layout()},i.prototype.itemDragStart=function(a){this.stamp(a);var b=this.getItem(a);b&&b.dragStart()},i.prototype.itemDragMove=function(a,b,c){function d(){f.layout(),delete f.dragTimeout}var e=this.getItem(a);e&&e.dragMove(b,c);var f=this;this.clearDragTimeout(),this.dragTimeout=setTimeout(d,40)},i.prototype.clearDragTimeout=function(){this.dragTimeout&&clearTimeout(this.dragTimeout)},i.prototype.itemDragEnd=function(b){var c,d=this.getItem(b);if(d&&(c=d.didDrag,d.dragStop()),!d||!c&&!d.needsPositioning)return void this.unstamp(b);a.add(d.element,"is-positioning-post-drag");var e=this._getDragEndLayoutComplete(b,d);d.needsPositioning?(d.on("layout",e),d.moveTo(d.placeRect.x,d.placeRect.y)):d&&d.copyPlaceRectPosition(),this.clearDragTimeout(),this.on("layoutComplete",e),this.layout()},i.prototype._getDragEndLayoutComplete=function(b,c){var d=c&&c.needsPositioning,e=0,f=d?2:1,g=this;return function(){return e++,e!==f?!0:(c&&(a.remove(c.element,"is-positioning-post-drag"),c.isPlacing=!1,
4556c.copyPlaceRectPosition()),g.unstamp(b),g.sortItemsByPosition(),d&&g.emitEvent("dragItemPositioned",[g,c]),!0)}},i.prototype.bindDraggabillyEvents=function(a){a.on("dragStart",this.handleDraggabilly.dragStart),a.on("dragMove",this.handleDraggabilly.dragMove),a.on("dragEnd",this.handleDraggabilly.dragEnd)},i.prototype.bindUIDraggableEvents=function(a){a.on("dragstart",this.handleUIDraggable.start).on("drag",this.handleUIDraggable.drag).on("dragstop",this.handleUIDraggable.stop)},i.Rect=d,i.Packer=e,i}"function"==typeof define&&define.amd?define("packery/js/packery",["classie/classie","get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],b):"object"==typeof exports?module.exports=b(require("desandro-classie"),require("get-size"),require("outlayer"),require("./rect"),require("./packer"),require("./item")):a.Packery=b(a.classie,a.getSize,a.Outlayer,a.Packery.Rect,a.Packery.Packer,a.Packery.Item)}(window),function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}function c(a,c,d){var e=a.create("packery"),f=e.prototype._getElementOffset,g=e.prototype._getMeasurement;b(e.prototype,c.prototype),e.prototype._getElementOffset=f,e.prototype._getMeasurement=g;var h=e.prototype._resetLayout;e.prototype._resetLayout=function(){this.packer=this.packer||new c.Packer,h.apply(this,arguments)};var i=e.prototype._getItemLayoutPosition;e.prototype._getItemLayoutPosition=function(a){return a.rect=a.rect||new c.Rect,i.call(this,a)};var j=e.prototype._manageStamp;return e.prototype._manageStamp=function(){this.options.isOriginLeft=this.isotope.options.isOriginLeft,this.options.isOriginTop=this.isotope.options.isOriginTop,j.apply(this,arguments)},e.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a,c=this.options.isHorizontal?"innerHeight":"innerWidth";return b&&a[c]!==this.size[c]},e}"function"==typeof define&&define.amd?define(["isotope/js/layout-mode","packery/js/packery","get-size/get-size"],c):"object"==typeof exports?module.exports=c(require("isotope-layout/js/layout-mode"),require("packery"),require("get-size")):c(a.Isotope.LayoutMode,a.Packery,a.getSize)}(window); 4557 4558/*! 4559 * cellsByRows layout mode for Isotope 4560 * v1.1.2 4561 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 4562 */ 4563 4564/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 4565 4566( function( window ) { 4567 4568'use strict'; 4569 4570function cellsByRowDefinition( LayoutMode ) { 4571 4572 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 4573 4574 CellsByRow.prototype._resetLayout = function() { 4575 // reset properties 4576 this.itemIndex = 0; 4577 // measurements 4578 this.getColumnWidth(); 4579 this.getRowHeight(); 4580 // set cols 4581 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 4582 this.cols = Math.max( this.cols, 1 ); 4583 }; 4584 4585 CellsByRow.prototype._getItemLayoutPosition = function( item ) { 4586 item.getSize(); 4587 var col = this.itemIndex % this.cols; 4588 var row = Math.floor( this.itemIndex / this.cols ); 4589 // center item within cell 4590 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 4591 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 4592 this.itemIndex++; 4593 return { x: x, y: y }; 4594 }; 4595 4596 CellsByRow.prototype._getContainerSize = function() { 4597 return { 4598 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 4599 }; 4600 }; 4601 4602 return CellsByRow; 4603 4604} 4605 4606if ( typeof define === 'function' && define.amd ) { 4607 // AMD 4608 define( [ 4609 'isotope/js/layout-mode' 4610 ], 4611 cellsByRowDefinition ); 4612} else if ( typeof exports === 'object' ) { 4613 // CommonJS 4614 module.exports = cellsByRowDefinition( 4615 require('isotope-layout/js/layout-mode') 4616 ); 4617} else { 4618 // browser global 4619 cellsByRowDefinition( 4620 window.Isotope.LayoutMode 4621 ); 4622} 4623 4624})( window ); 4625 4626/*! 4627 -------------------------------- 4628 Infinite Scroll 4629 -------------------------------- 4630 + https://github.com/paulirish/infinite-scroll 4631 + version 2.1.0 4632 + Copyright 2011/12 Paul Irish & Luke Shumard 4633 + Licensed under the MIT license 4634 4635 + Documentation: http://infinite-scroll.com/ 4636*/ 4637;(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(jQuery)}})(function(e,t){"use strict";e.infinitescroll=function(n,r,i){this.element=e(i);if(!this._create(n,r)){this.failed=true}};e.infinitescroll.defaults={loading:{finished:t,finishedMsg:"<em>Congratulations, you've reached the end of the internet.</em>",img:"data:image/gif;
4637base64,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
4637MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
4637iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7",msg:null,msgText:"<em>Loading the next set of posts...</em>",selector:null,speed:"fast",start:t},state:{isDuringAjax:false,isInvalidPage:false,isDestroyed:false,isDone:false,isPaused:false,isBeyondMaxPage:false,currPage:1},debug:false,behavior:t,binder:e(window),nextSelector:"div.navigation a:first",navSelector:"div.navigation",contentSelector:null,extraScrollPx:150,itemSelector:"div.post",animate:false,pathParse:t,dataType:"html",appendCallback:true,bufferPx:40,errorCallback:function(){},infid:0,pixelsFromNavToBottom:t,path:t,prefill:false,maxPage:t};e.infinitescroll.prototype={_binding:function(n){var r=this,i=r.options;i.v="2.0b2.120520";if(!!i.behavior&&this["_binding_"+i.behavior]!==t){this["_binding_"+i.behavior].call(this);return}if(n!=="bind"&&n!=="unbind"){this._debug("Binding value "+n+" not valid");return false}if(n==="unbind"){this.options.binder.unbind("smartscroll.infscr."+r.options.infid)}else{this.options.binder[n]("smartscroll.infscr."+r.options.infid,function(){r.scroll()})}this._debug("Binding",n)},_create:function(r,i){var s=e.extend(true,{},e.infinitescroll.defaults,r);this.options=s;var o=e(window);var u=this;if(!u._validate(r)){return false}var a=e(s.nextSelector).attr("href");if(!a){this._debug("Navigation selector not found");return false}s.path=s.path||this._determinepath(a);s.contentSelector=s.contentSelector||this.element;s.loading.selector=s.loading.selector||s.contentSelector;s.loading.msg=s.loading.msg||e('<div id="infscr-loading"><img alt="Loading..." src="'+s.loading.img+'" /><div>'+s.loading.msgText+"</div></div>");(new Image).src=s.loading.img;if(s.pixelsFromNavToBottom===t){s.pixelsFromNavToBottom=e(document).height()-e(s.navSelector).offset().top;this._debug("pixelsFromNavToBottom: "+s.pixelsFromNavToBottom)}var f=this;s.loading.start=s.loading.start||function(){e(s.navSelector).hide();s.loading.msg.appendTo(s.loading.selector).show(s.loading.speed,e.proxy(function(){this.beginAjax(s)},f))};s.loading.finished=s.loading.finished||function(){if(!s.state.isBeyondMaxPage)s.loading.msg.fadeOut(s.loading.speed)};s.callback=function(n,r,u){if(!!s.behavior&&n["_callback_"+s.behavior]!==t){n["_callback_"+s.behavior].call(e(s.contentSelector)[0],r,u)}if(i){i.call(e(s.contentSelector)[0],r,s,u)}if(s.prefill){o.bind("resize.infinite-scroll",n._prefill)}};if(r.debug){if(Function.prototype.bind&&(typeof console==="object"||typeof console==="function")&&typeof console.log==="object"){["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function(e){console[e]=this.call(console[e],console)},Function.prototype.bind)}}this._setup();if(s.prefill){this._prefill()}return true},_prefill:function(){function i(){return e(n.options.contentSelector).height()<=r.height()}var n=this;var r=e(window);this._prefill=function(){if(i()){n.scroll()}r.bind("resize.infinite-scroll",function(){if(i()){r.unbind("resize.infinite-scroll");n.scroll()}})};this._prefill()},_debug:function(){if(true!==this.options.debug){return}if(typeof console!=="undefined"&&typeof console.log==="function"){if(Array.prototype.slice.call(arguments).length===1&&typeof Array.prototype.slice.call(arguments)[0]==="str
4637ing"){console.log(Array.prototype.slice.call(arguments).toString())}else{console.log(Array.prototype.slice.call(arguments))}}else if(!Function.prototype.bind&&typeof console!=="undefined"&&typeof console.log==="object"){Function.prototype.call.call(console.log,console,Array.prototype.slice.call(arguments))}},_determinepath:function(n){var r=this.options;if(!!r.behavior&&this["_determinepath_"+r.behavior]!==t){return this["_determinepath_"+r.behavior].call(this,n)}if(!!r.pathParse){this._debug("pathParse manual");return r.pathParse(n,this.options.state.currPage+1)}else if(n.match(/^(.*?)\b2\b(.*?$)/)){n=n.match(/^(.*?)\b2\b(.*?$)/).slice(1)}else if(n.match(/^(.*?)2(.*?$)/)){if(n.match(/^(.*?page=)2(\/.*|$)/)){n=n.match(/^(.*?page=)2(\/.*|$)/).slice(1);return n}n=n.match(/^(.*?)2(.*?$)/).slice(1)}else{if(n.match(/^(.*?page=)1(\/.*|$)/)){n=n.match(/^(.*?page=)1(\/.*|$)/).slice(1);return n}else{this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.");r.state.isInvalidPage=true}}this._debug("determinePath",n);return n},_error:function(n){var r=this.options;if(!!r.behavior&&this["_error_"+r.behavior]!==t){this["_error_"+r.behavior].call(this,n);return}if(n!=="destroy"&&n!=="end"){n="unknown"}this._debug("Error",n);if(n==="end"||r.state.isBeyondMaxPage){this._showdonemsg()}r.state.isDone=true;r.state.currPage=1;
4637r.state.isPaused=false;r.state.isBeyondMaxPage=false;this._binding("unbind")},_loadcallback:function(r,i,s){var o=this.options,u=this.options.callback,a=o.state.isDone?"done":!o.appendCallback?"no-append":"append",f;if(!!o.behavior&&this["_loadcallback_"+o.behavior]!==t){this["_loadcallback_"+o.behavior].call(this,r,i);return}switch(a){case"done":this._showdonemsg();return false;case"no-append":if(o.dataType==="html"){i="<div>"+i+"</div>";i=e(i).find(o.itemSelector)}if(i.length===0){return this._error("end")}break;case"append":var l=r.children();if(l.length===0){return this._error("end")}f=document.createDocumentFragment();while(r[0].firstChild){f.appendChild(r[0].firstChild)}this._debug("contentSelector",e(o.contentSelector)[0]);e(o.contentSelector)[0].appendChild(f);i=l.get();break}o.loading.finished.call(e(o.contentSelector)[0],o);if(o.animate){var c=e(window).scrollTop()+e(o.loading.msg).height()+o.extraScrollPx+"px";e("html,body").animate({scrollTop:c},800,function(){o.state.isDuringAjax=false})}if(!o.animate){o.state.isDuringAjax=false}u(this,i,s);if(o.prefill){this._prefill()}},_nearbottom:function(){var r=this.options,i=0+e(document).height()-r.binder.scrollTop()-e(window).height();if(!!r.behavior&&this["_nearbottom_"+r.behavior]!==t){return this["_nearbottom_"+r.behavior].call(this)}this._debug("math:",i,r.pixelsFromNavToBottom);return i-r.bufferPx<r.pixelsFromNavToBottom},_pausing:function(n){var r=this.options;if(!!r.behavior&&this["_pausing_"+r.behavior]!==t){this["_pausing_"+r.behavior].call(this,n);return}if(n!=="pause"&&n!=="resume"&&n!==null){this._debug("Invalid argument. Toggling pause value instead")}n=n&&(n==="pause"||n==="resume")?n:"toggle";
4637switch(n){case"pause":r.state.isPaused=true;break;case"resume":r.state.isPaused=false;break;case"toggle":r.state.isPaused=!r.state.isPaused;break}this._debug("Paused",r.state.isPaused);return false},_setup:function(){var n=this.options;if(!!n.behavior&&this["_setup_"+n.behavior]!==t){this["_setup_"+n.behavior].call(this);return}this._binding("bind");return false},_showdonemsg:function(){var r=this.options;if(!!r.behavior&&this["_showdonemsg_"+r.behavior]!==t){this["_showdonemsg_"+r.behavior].call(this);return}r.loading.msg.find("img").hide().parent().find("div").html(r.loading.finishedMsg).animate({opacity:1},2e3,function(){e(this).parent().fadeOut(r.loading.speed)});r.errorCallback.call(e(r.contentSelector)[0],"done")},_validate:function(n){for(var r in n){if(r.indexOf&&r.indexOf("Selector")>-1&&e(n[r]).length===0){this._debug("Your "+r+" found no elements.");return false}}return true},bind:function(){this._binding("bind")},destroy:function(){this.options.state.isDestroyed=true;this.options.loading.finished();return this._error("destroy")},pause:function(){this._pausing("pause")},resume:function(){this._pausing("resume")},beginAjax:function(r){var i=this,s=r.path,o,u,a,f;r.state.currPage++;if(r.maxPage!==t&&r.state.currPage>r.maxPage){r.state.isBeyondMaxPage=true;this.destroy();return}o=e(r.contentSelector).is("table, tbody")?e("<tbody/>"):e("<div/>");u=typeof s==="function"?s(r.state.currPage):s.join(r.state.currPage);i._debug("heading into ajax",u);a=r.dataType==="html"||r.dataType==="json"?r.dataType:"html+callback";if(r.appendCallback&&r.dataType==="html"){a+="+callback"}switch(a){case"html+callback":i._debug("Using HTML via .load() method");o.load(u+" "+r.itemSelector,t,function(t){i._loadcallback(o,t,u)});break;case"html":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({url:u,dataType:r.dataType,complete:function(t,n){f=typeof t.isResolved!=="undefined"?t.isResolved():n==="success"||n==="notmodified";if(f){i._loadcallback(o,t.responseText,u)}else{i._error("end")}}});break;case"json":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({dataType:"json",type:"GET",url:u,success:function(e,n,s){f=typeof s.isResolved!=="undefined"?s.isResolved():n==="success"||n==="notmodified";if(r.appendCallback){if(r.template!==t){var a=r.template(e);o.append(a);if(f){i._loadcallback(o,a)}else{i._error("end")}}else{i._debug("template must be defined.");i._error("end")}}else{if(f){i._loadcallback(o,e,u)}else{i._error("end")}}},error:function(){i._debug("JSON ajax request failed.");i._error("end")}});break}},retrieve:function(r){r=r||null;var i=this,s=i.options;if(!!s.behavior&&this["retrieve_"+s.behavior]!==t){this["retrieve_"+s.behavior].call(this,r);return}if(s.state.isDestroyed){this._debug("Instance is destroyed");return false}s.state.isDuringAjax=true;s.loading.start.call(e(s.contentSelector)[0],s)},scroll:function(){var n=this.options,r=n.state;if(!!n.behavior&&this["scroll_"+n.behavior]!==t){this["scroll_"+n.behavior].call(this);return}if(r.isDuringAjax||r.isInvalidPage||r.isDone||r.isDestroyed||r.isPaused){return}if(!this._nearbottom()){return}this.retrieve()},toggle:function(){this._pausing()},unbind:function(){this._binding("unbind")},update:function(n){if(e.isPlainObject(n)){this.options=e.extend(true,this.options,n)}}};e.fn.infinitescroll=function(n,r){var i=typeof n;switch(i){case"string":var s=Array.prototype.slice.call(arguments,1);this.each(function(){var t=e.data(this,"infinitescroll");if(!t){return false}if(!e.isFunction(t[n])||n.charAt(0)==="_"){return false}t[n].apply(t,s)});break;case"object":this.each(function(){var t=e.data(this,"infinitescroll");if(t){t.update(n)}else{t=new e.infinitescroll(n,r,this);if(!t.failed){e.data(this,"infinitescroll",t)}}});break}return this};var n=e.event,r;n.special.smartscroll={setup:function(){e(this).bind("scroll",n.special.smartscroll.handler)},teardown:function(){e(this).unbind("scroll",n.special.smartscroll.handler)},handler:function(t,n){var i=this,s=arguments;t.type="smartscroll";if(r){clearTimeout(r)}r=setTimeout(function(){e(i).trigger("smartscroll",s)},n==="execAsap"?0:100)}};e.fn.smartscroll=function(e){return e?this.bind("smartscroll",e):this.trigger("smartscroll",["execAsap"])}}); 4638 4639/*!
4640Waypoints - 4.0.0 4641Copyright © 2011-2015 Caleb Troughton 4642Licensed under the MIT license. 4643https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 4644*/ 4645(function() { 4646 'use strict' 4647 4648 var keyCounter = 0 4649 var allWaypoints = {} 4650 4651 /* http://imakewebthings.com/waypoints/api/waypoint */ 4652 function Waypoint(options) { 4653 if (!options) { 4654 throw new Error('No options passed to Waypoint constructor') 4655 } 4656 if (!options.element) { 4657 throw new Error('No element option passed to Waypoint constructor') 4658 } 4659 if (!options.handler) { 4660 throw new Error('No handler option passed to Waypoint constructor') 4661 } 4662 4663 this.key = 'waypoint-' + keyCounter 4664 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 4665 this.element = this.options.element 4666 this.adapter = new Waypoint.Adapter(this.element) 4667 this.callback = options.handler 4668 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 4669 this.enabled = this.options.enabled 4670 this.triggerPoint = null 4671 this.group = Waypoint.Group.findOrCreate({ 4672 name: this.options.group, 4673 axis: this.axis 4674 }) 4675 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 4676 4677 if (Waypoint.offsetAliases[this.options.offset]) { 4678 this.options.offset = Waypoint.offsetAliases[this.options.offset] 4679 } 4680 this.group.add(this) 4681 this.context.add(this) 4682 allWaypoints[this.key] = this 4683 keyCounter += 1 4684 } 4685 4686 /* Private */ 4687 Waypoint.prototype.queueTrigger = function(direction) { 4688 this.group.queueTrigger(this, direction) 4689 } 4690 4691 /* Private */ 4692 Waypoint.prototype.trigger = function(args) { 4693 if (!this.enabled) { 4694 return 4695 } 4696 if (this.callback) { 4697 this.callback.apply(this, args) 4698 } 4699 } 4700 4701 /* Public */ 4702 /* http://imakewebthings.com/waypoints/api/destroy */ 4703 Waypoint.prototype.destroy = function() { 4704 this.context.remove(this) 4705 this.group.remove(this) 4706 delete allWaypoints[this.key] 4707 } 4708 4709 /* Public */ 4710 /* http://imakewebthings.com/waypoints/api/disable */ 4711 Waypoint.prototype.disable = function() { 4712 this.enabled = false 4713 return this 4714 } 4715 4716 /* Public */ 4717 /* http://imakewebthings.com/waypoints/api/enable */ 4718 Waypoint.prototype.enable = function() { 4719 this.context.refresh() 4720 this.enabled = true 4721 return this 4722 } 4723 4724 /* Public */ 4725 /* http://imakewebthings.com/waypoints/api/next */ 4726 Waypoint.prototype.next = function() { 4727 return this.group.next(this) 4728 } 4729 4730 /* Public */ 4731 /* http://imakewebthings.com/waypoints/api/previous */ 4732 Waypoint.prototype.previous = function() { 4733 return this.group.previous(this) 4734 } 4735 4736 /* Private */ 4737 Waypoint.invokeAll = function(method) { 4738 var allWaypointsArray = []
4739 for (var waypointKey in allWaypoints) { 4740 allWaypointsArray.push(allWaypoints[waypointKey]) 4741 } 4742 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 4743 allWaypointsArray[i][method]() 4744 } 4745 } 4746 4747 /* Public */ 4748 /* http://imakewebthings.com/waypoints/api/destroy-all */ 4749 Waypoint.destroyAll = function() { 4750 Waypoint.invokeAll('destroy') 4751 } 4752 4753 /* Public */ 4754 /* http://imakewebthings.com/waypoints/api/disable-all */ 4755 Waypoint.disableAll = function() { 4756 Waypoint.invokeAll('disable') 4757 } 4758 4759 /* Public */ 4760 /* http://imakewebthings.com/waypoints/api/enable-all */ 4761 Waypoint.enableAll = function() { 4762 Waypoint.invokeAll('enable') 4763 } 4764 4765 /* Public */ 4766 /* http://imakewebthings.com/waypoints/api/refresh-all */ 4767 Waypoint.refreshAll = function() { 4768 Waypoint.Context.refreshAll() 4769 } 4770 4771 /* Public */ 4772 /* http://imakewebthings.com/waypoints/api/viewport-height */ 4773 Waypoint.viewportHeight = function() { 4774 return window.innerHeight || document.documentElement.clientHeight 4775 } 4776 4777 /* Public */ 4778 /* http://imakewebthings.com/waypoints/api/viewport-width */ 4779 Waypoint.viewportWidth = function() { 4780 return document.documentElement.clientWidth 4781 } 4782 4783 Waypoint.adapters = [] 4784 4785 Waypoint.defaults = { 4786 context: window, 4787 continuous: true, 4788 enabled: true, 4789 group: 'default', 4790 horizontal: false, 4791 offset: 0 4792 } 4793 4794 Waypoint.offsetAliases = { 4795 'bottom-in-view': function() { 4796 return this.context.innerHeight() - this.adapter.outerHeight() 4797 }, 4798 'right-in-view': function() { 4799 return this.context.innerWidth() - this.adapter.outerWidth() 4800 } 4801 } 4802 4803 window.Waypoint = Waypoint 4804}()) 4805;(function() { 4806 'use strict' 4807 4808 function requestAnimationFrameShim(callback) { 4809 window.setTimeout(callback, 1000 / 60) 4810 } 4811 4812 var keyCounter = 0 4813 var contexts = {} 4814 var Waypoint = window.Waypoint 4815 var oldWindowLoad = window.onload 4816 4817 /* http://imakewebthings.com/waypoints/api/context */ 4818 function Context(element) { 4819 this.element = element 4820 this.Adapter = Waypoint.Adapter 4821 this.adapter = new this.Adapter(element) 4822 this.key = 'waypoint-context-' + keyCounter 4823 this.didScroll = false 4824 this.didResize = false 4825 this.oldScroll = { 4826 x: this.adapter.scrollLeft(), 4827 y: this.adapter.scrollTop() 4828 } 4829 this.waypoints = { 4830 vertical: {}, 4831 horizontal: {} 4832 } 4833 4834 element.waypointContextKey = this.key 4835 contexts[element.waypointContextKey] = this 4836 keyCounter += 1 4837 4838 this.createThrottledScrollHandler() 4839 this.createThrottledResizeHandler() 4840 } 4841 4842 /* Private */ 4843 Context.prototype.add = function(waypoint) { 4844 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 4845 this.waypoints[axis][waypoint.key] = waypoint 4846 this.refresh() 4847 } 4848 4849 /* Private */ 4850 Context.prototype.checkEmpty = function() { 4851 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 4852 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 4853 if (horizontalEmpty && verticalEmpty) { 4854 this.adapter.off('.waypoints') 4855 delete contexts[this.key] 4856 } 4857 } 4858 4859 /* Private */ 4860 Context.prototype.createThrottledResizeHandler = function() { 4861 var self = this 4862 4863 function resizeHandler() { 4864 self.handleResize() 4865 self.didResize = false 4866 } 4867 4868 this.adapter.on('resize.waypoints', function() { 4869 if (!self.didResize) { 4870 self.didResize = true 4871 Waypoint.requestAnimationFrame(resizeHandler) 4872 } 4873 }) 4874 } 4875 4876 /* Private */ 4877 Context.prototype.createThrottledScrollHandler = function() { 4878 var self = this 4879 function scrollHandler() { 4880 self.handleScroll() 4881 self.didScroll = false 4882 } 4883 4884 this.adapter.on('scroll.waypoints', function() { 4885 if (!self.didScroll || Waypoint.isTouch) { 4886 self.didScroll = true 4887 Waypoint.requestAnimationFrame(scrollHandler) 4888 } 4889 }) 4890 } 4891 4892 /* Private */ 4893 Context.prototype.handleResize = function() { 4894 Waypoint.Context.refreshAll() 4895 } 4896 4897 /* Private */ 4898 Context.prototype.handleScroll = function() { 4899 var triggeredGroups = {} 4900 var axes = { 4901 horizontal: { 4902 newScroll: this.adapter.scrollLeft(), 4903 oldScroll: this.oldScroll.x, 4904 forward: 'right', 4905 backward: 'left' 4906 }, 4907 vertical: { 4908 newScroll: this.adapter.scrollTop(), 4909 oldScroll: this.oldScroll.y, 4910 forward: 'down', 4911 backward: 'up' 4912 } 4913 } 4914 4915 for (var axisKey in axes) { 4916 var axis = axes[axisKey] 4917 var isForward = axis.newScroll > axis.oldScroll 4918 var direction = isForward ? axis.forward : axis.backward 4919
4920 for (var waypointKey in this.waypoints[axisKey]) { 4921 var waypoint = this.waypoints[axisKey][waypointKey] 4922 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 4923 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 4924 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 4925 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 4926 if (crossedForward || crossedBackward) { 4927 waypoint.queueTrigger(direction) 4928 triggeredGroups[waypoint.group.id] = waypoint.group 4929 } 4930 } 4931 } 4932 4933 for (var groupKey in triggeredGroups) { 4934 triggeredGroups[groupKey].flushTriggers() 4935 } 4936 4937 this.oldScroll = { 4938 x: axes.horizontal.newScroll, 4939 y: axes.vertical.newScroll 4940 } 4941 } 4942 4943 /* Private */ 4944 Context.prototype.innerHeight = function() { 4945 /*eslint-disable eqeqeq */ 4946 if (this.element == this.element.window) { 4947 return Waypoint.viewportHeight() 4948 } 4949 /*eslint-enable eqeqeq */ 4950 return this.adapter.innerHeight() 4951 } 4952 4953 /* Private */ 4954 Context.prototype.remove = function(waypoint) { 4955 delete this.waypoints[waypoint.axis][waypoint.key] 4956 this.checkEmpty() 4957 } 4958 4959 /* Private */ 4960 Context.prototype.innerWidth = function() { 4961 /*eslint-disable eqeqeq */ 4962 if (this.element == this.element.window) { 4963 return Waypoint.viewportWidth() 4964 } 4965 /*eslint-enable eqeqeq */ 4966 return this.adapter.innerWidth() 4967 } 4968 4969 /* Public */ 4970 /* http://imakewebthings.com/waypoints/api/context-destroy */ 4971 Context.prototype.destroy = function() { 4972 var allWaypoints = [] 4973 for (var axis in this.waypoints) {
4974 for (var waypointKey in this.waypoints[axis]) { 4975 allWaypoints.push(this.waypoints[axis][waypointKey]) 4976 } 4977 } 4978 for (var i = 0, end = allWaypoints.length; i < end; i++) { 4979 allWaypoints[i].destroy() 4980 } 4981 } 4982 4983 /* Public */ 4984 /* http://imakewebthings.com/waypoints/api/context-refresh */ 4985 Context.prototype.refresh = function() { 4986 /*eslint-disable eqeqeq */ 4987 var isWindow = this.element == this.element.window 4988 /*eslint-enable eqeqeq */ 4989 var contextOffset = isWindow ? undefined : this.adapter.offset() 4990 var triggeredGroups = {} 4991 var axes 4992 4993 this.handleScroll() 4994 axes = { 4995 horizontal: { 4996 contextOffset: isWindow ? 0 : contextOffset.left, 4997 contextScroll: isWindow ? 0 : this.oldScroll.x, 4998 contextDimension: this.innerWidth(), 4999 oldScroll: this.oldScroll.x, 5000 forward: 'right', 5001 backward: 'left', 5002 offsetProp: 'left' 5003 }, 5004 vertical: { 5005 contextOffset: isWindow ? 0 : contextOffset.top, 5006 contextScroll: isWindow ? 0 : this.oldScroll.y, 5007 contextDimension: this.innerHeight(), 5008 oldScroll: this.oldScroll.y, 5009 forward: 'down', 5010 backward: 'up', 5011 offsetProp: 'top' 5012 } 5013 } 5014 5015 for (var axisKey in axes) { 5016 var axis = axes[axisKey]
5017 for (var waypointKey in this.waypoints[axisKey]) { 5018 var waypoint = this.waypoints[axisKey][waypointKey] 5019 var adjustment = waypoint.options.offset 5020 var oldTriggerPoint = waypoint.triggerPoint 5021 var elementOffset = 0 5022 var freshWaypoint = oldTriggerPoint == null 5023 var contextModifier, wasBeforeScroll, nowAfterScroll 5024 var triggeredBackward, triggeredForward 5025 5026 if (waypoint.element !== waypoint.element.window) { 5027 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 5028 } 5029 5030 if (typeof adjustment === 'function') { 5031 adjustment = adjustment.apply(waypoint) 5032 } 5033 else if (typeof adjustment === 'string') { 5034 adjustment = parseFloat(adjustment) 5035 if (waypoint.options.offset.indexOf('%') > - 1) { 5036 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 5037 } 5038 } 5039 5040 contextModifier = axis.contextScroll - axis.contextOffset 5041 waypoint.triggerPoint = elementOffset + contextModifier - adjustment 5042 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 5043 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 5044 triggeredBackward = wasBeforeScroll && nowAfterScroll 5045 triggeredForward = !wasBeforeScroll && !nowAfterScroll 5046 5047 if (!freshWaypoint && triggeredBackward) { 5048 waypoint.queueTrigger(axis.backward) 5049 triggeredGroups[waypoint.group.id] = waypoint.group 5050 } 5051 else if (!freshWaypoint && triggeredForward) { 5052 waypoint.queueTrigger(axis.forward) 5053 triggeredGroups[waypoint.group.id] = waypoint.group 5054 } 5055 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 5056 waypoint.queueTrigger(axis.forward) 5057 triggeredGroups[waypoint.group.id] = waypoint.group 5058 } 5059 } 5060 } 5061 5062 Waypoint.requestAnimationFrame(function() { 5063 for (var groupKey in triggeredGroups) { 5064 triggeredGroups[groupKey].flushTriggers() 5065 } 5066 }) 5067 5068 return this 5069 } 5070 5071 /* Private */ 5072 Context.findOrCreateByElement = function(element) { 5073 return Context.findByElement(element) || new Context(element) 5074 } 5075 5076 /* Private */ 5077 Context.refreshAll = function() { 5078 for (var contextId in contexts) { 5079 contexts[contextId].refresh() 5080 } 5081 } 5082 5083 /* Public */ 5084 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 5085 Context.findByElement = function(element) { 5086 return contexts[element.waypointContextKey] 5087 } 5088 5089 window.onload = function() { 5090 if (oldWindowLoad) { 5091 oldWindowLoad() 5092 } 5093 Context.refreshAll() 5094 } 5095 5096 Waypoint.requestAnimationFrame = function(callback) { 5097 var requestFn = window.requestAnimationFrame || 5098 window.mozRequestAnimationFrame || 5099 window.webkitRequestAnimationFrame || 5100 requestAnimationFrameShim 5101 requestFn.call(window, callback) 5102 } 5103 Waypoint.Context = Context 5104}()) 5105;(function() { 5106 'use strict' 5107 5108 function byTriggerPoint(a, b) { 5109 return a.triggerPoint - b.triggerPoint 5110 } 5111 5112 function byReverseTriggerPoint(a, b) { 5113 return b.triggerPoint - a.triggerPoint 5114 } 5115 5116 var groups = { 5117 vertical: {}, 5118 horizontal: {} 5119 } 5120 var Waypoint = window.Waypoint 5121 5122 /* http://imakewebthings.com/waypoints/api/group */ 5123 function Group(options) { 5124 this.name = options.name 5125 this.axis = options.axis 5126 this.id = this.name + '-' + this.axis 5127 this.waypoints = [] 5128 this.clearTriggerQueues() 5129 groups[this.axis][this.name] = this 5130 } 5131 5132 /* Private */ 5133 Group.prototype.add = function(waypoint) { 5134 this.waypoints.push(waypoint) 5135 } 5136 5137 /* Private */ 5138 Group.prototype.clearTriggerQueues = function() { 5139 this.triggerQueues = { 5140 up: [], 5141 down: [], 5142 left: [], 5143 right: [] 5144 } 5145 } 5146 5147 /* Private */ 5148 Group.prototype.flushTriggers = function() { 5149 for (var direction in this.triggerQueues) { 5150 var waypoints = this.triggerQueues[direction] 5151 var reverse = direction === 'up' || direction === 'left' 5152 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 5153 for (var i = 0, end = waypoints.length; i < end; i += 1) { 5154 var waypoint = waypoints[i] 5155 if (waypoint.options.continuous || i === waypoints.length - 1) { 5156 waypoint.trigger([direction]) 5157 } 5158 } 5159 } 5160 this.clearTriggerQueues() 5161 } 5162 5163 /* Private */ 5164 Group.prototype.next = function(waypoint) { 5165 this.waypoints.sort(byTriggerPoint) 5166 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5167 var isLast = index === this.waypoints.length - 1 5168 return isLast ? null : this.waypoints[index + 1] 5169 } 5170 5171 /* Private */ 5172 Group.prototype.previous = function(waypoint) { 5173 this.waypoints.sort(byTriggerPoint) 5174 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5175 return index ? this.waypoints[index - 1] : null 5176 } 5177 5178 /* Private */ 5179 Group.prototype.queueTrigger = function(waypoint, direction) { 5180 this.triggerQueues[direction].push(waypoint) 5181 } 5182 5183 /* Private */ 5184 Group.prototype.remove = function(waypoint) { 5185 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 5186 if (index > -1) { 5187 this.waypoints.splice(index, 1) 5188 } 5189 } 5190 5191 /* Public */ 5192 /* http://imakewebthings.com/waypoints/api/first */ 5193 Group.prototype.first = function() { 5194 return this.waypoints[0] 5195 } 5196 5197 /* Public */ 5198 /* http://imakewebthings.com/waypoints/api/last */ 5199 Group.prototype.last = function() { 5200 return this.waypoints[this.waypoints.length - 1] 5201 } 5202 5203 /* Private */ 5204 Group.findOrCreate = function(options) { 5205 return groups[options.axis][options.name] || new Group(options) 5206 } 5207 5208 Waypoint.Group = Group 5209}()) 5210;(function() { 5211 'use strict' 5212 5213 var $ = window.jQuery 5214 var Waypoint = window.Waypoint 5215 5216 function JQueryAdapter(element) { 5217 this.$element = $(element) 5218 } 5219 5220 $.each([
5221 'innerHeight', 5222 'innerWidth', 5223 'off', 5224 'offset', 5225 'on', 5226 'outerHeight', 5227 'outerWidth', 5228 'scrollLeft', 5229 'scrollTop' 5230 ], function(i, method) { 5231 JQueryAdapter.prototype[method] = function() { 5232 var args = Array.prototype.slice.call(arguments) 5233 return this.$element[method].apply(this.$element, args) 5234 } 5235 }) 5236 5237 $.each([ 5238 'extend', 5239 'inArray', 5240 'isEmptyObject' 5241 ], function(i, method) { 5242 JQueryAdapter[method] = $[method] 5243 }) 5244 5245 Waypoint.adapters.push({ 5246 name: 'jquery', 5247 Adapter: JQueryAdapter 5248 }) 5249 Waypoint.Adapter = JQueryAdapter 5250}()) 5251;(function() { 5252 'use strict' 5253 5254 var Waypoint = window.Waypoint 5255 5256 function createExtension(framework) { 5257 return function() { 5258 var waypoints = [] 5259 var overrides = arguments[0] 5260 5261 if (framework.isFunction(arguments[0])) { 5262 overrides = framework.extend({}, arguments[1]) 5263 overrides.handler = arguments[0] 5264 } 5265 5266 this.each(function() { 5267 var options = framework.extend({}, overrides, { 5268 element: this 5269 }) 5270 if (typeof options.context === 'string') { 5271 options.context = framework(this).closest(options.context)[0] 5272 } 5273 waypoints.push(new Waypoint(options)) 5274 }) 5275 5276 return waypoints 5277 } 5278 } 5279 5280 if (window.jQuery) { 5281 window.jQuery.fn.waypoint = createExtension(window.jQuery) 5282 } 5283 if (window.Zepto) { 5284 window.Zepto.fn.waypoint = createExtension(window.Zepto) 5285 } 5286}()) 5287; 5288 5289/*! 5290Waypoints Inview Shortcut - 4.0.0 5291Copyright © 2011-2015 Caleb Troughton 5292Licensed under the MIT license. 5293https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 5294*/ 5295(function() { 5296 'use strict' 5297 5298 function noop() {} 5299 5300 var Waypoint = window.Waypoint 5301 5302 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 5303 function Inview(options) { 5304 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 5305 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 5306 this.waypoints = [] 5307 this.element = this.options.element 5308 this.createWaypoints() 5309 } 5310 5311 /* Private */ 5312 Inview.prototype.createWaypoints = function() { 5313 var configs = { 5314 vertical: [{ 5315 down: 'enter', 5316 up: 'exited', 5317 offset: '100%' 5318 }, { 5319 down: 'entered', 5320 up: 'exit', 5321 offset: 'bottom-in-view' 5322 }, { 5323 down: 'exit', 5324 up: 'entered', 5325 offset: 0 5326 }, { 5327 down: 'exited', 5328 up: 'enter', 5329 offset: function() { 5330 return -this.adapter.outerHeight() 5331 } 5332 }], 5333 horizontal: [{ 5334 right: 'enter', 5335 left: 'exited', 5336 offset: '100%' 5337 }, { 5338 right: 'entered', 5339 left: 'exit', 5340 offset: 'right-in-view' 5341 }, { 5342 right: 'exit', 5343 left: 'entered', 5344 offset: 0 5345 }, { 5346 right: 'exited', 5347 left: 'enter', 5348 offset: function() { 5349 return -this.adapter.outerWidth() 5350 } 5351 }] 5352 } 5353 5354 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 5355 var config = configs[this.axis][i] 5356 this.createWaypoint(config) 5357 } 5358 } 5359 5360 /* Private */ 5361 Inview.prototype.createWaypoint = function(config) { 5362 var self = this 5363 this.waypoints.push(new Waypoint({ 5364 context: this.options.context, 5365 element: this.options.element, 5366 enabled: this.options.enabled, 5367 handler: (function(config) { 5368 return function(direction) { 5369 self.options[config[direction]].call(self, direction) 5370 } 5371 }(config)), 5372 offset: config.offset, 5373 horizontal: this.options.horizontal 5374 })) 5375 } 5376 5377 /* Public */ 5378 Inview.prototype.destroy = function() { 5379 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5380 this.waypoints[i].destroy() 5381 } 5382 this.waypoints = [] 5383 } 5384 5385 Inview.prototype.disable = function() { 5386 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5387 this.waypoints[i].disable() 5388 } 5389 } 5390 5391 Inview.prototype.enable = function() { 5392 for (var i = 0, end = this.waypoints.length; i < end; i++) { 5393 this.waypoints[i].enable() 5394 } 5395 } 5396 5397 Inview.defaults = { 5398 context: window, 5399 enabled: true, 5400 enter: noop, 5401 entered: noop,
5402 exit: noop, 5403 exited: noop 5404 } 5405 5406 Waypoint.Inview = Inview 5407}()) 5408; 5409 5410/* 5411 * SmartMenus jQuery v0.9.6 5412 * http://www.smartmenus.org/ 5413 * 5414 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 5415 * http://vadikom.com/ 5416 * 5417 * Released under the MIT license: 5418 * http://www.opensource.org/licenses/MIT 5419 */ 5420 5421(function($) { 5422 5423 var menuTrees = [], 5424 IE = !!window.createPopup, // we need to detect it, unfortunately 5425 IElt9 = IE && !document.defaultView, 5426 IElt8 = IE && !document.querySelector, 5427 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 5428 mouse = false, // optimize for touch by default - we will detect for mouse input 5429 mouseDetectionEnabled = false; 5430 5431 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 5432 function initMouseDetection(disable) { 5433 if (!mouseDetectionEnabled && !disable) { 5434 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 5435 // 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) 5436 var firstTime = true, 5437 lastMove = null; 5438 $(document).bind({ 5439 'mousemove.smartmenus_mouse': function(e) { 5440 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 5441 if (lastMove) { 5442 var deltaX = Math.abs(lastMove.x - thisMove.x), 5443 deltaY = Math.abs(lastMove.y - thisMove.y); 5444 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 5445 mouse = true; 5446 // 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 5447 if (firstTime) { 5448 var $a = $(e.target).closest('a'); 5449 if ($a.is('a')) { 5450 $.each(menuTrees, function() { 5451 if ($.contains(this.$root[0], $a[0])) { 5452 this.itemEnter({ currentTarget: $a[0] }); 5453 return false; 5454 } 5455 }); 5456 } 5457 firstTime = false; 5458 } 5459 } 5460 } 5461 lastMove = thisMove; 5462 }, 5463 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 5464 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 5465 mouse = false; 5466 } 5467 } 5468 }); 5469 mouseDetectionEnabled = true; 5470 } else if (mouseDetectionEnabled && disable) { 5471 $(document).unbind('.smartmenus_mouse'); 5472 mouseDetectionEnabled = false; 5473 } 5474 }; 5475 5476 $.SmartMenus = function(elm, options) { 5477 this.$root = $(elm); 5478 this.opts = options; 5479 this.rootId = ''; // internal 5480 this.$subArrow = null; 5481 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) 5482 this.activatedItems = []; // stores last activated A's for each level 5483 this.visibleSubMenus = []; // stores visible sub menus UL's 5484 this.showTimeout = 0; 5485 this.hideTimeout = 0; 5486 this.scrollTimeout = 0; 5487 this.clickActivated = false; 5488 this.zIndexInc = 0; 5489 this.$firstLink = null; // we'll use these for some tests 5490 this.$firstSub = null; // at runtime so we'll cache them 5491 this.disabled = false; 5492 this.$disableOverlay = null; 5493 this.init(); 5494 }; 5495 5496 $.extend($.SmartMenus, { 5497 hideAll: function() { 5498 $.each(menuTrees, function() { 5499 this.menuHideAll(); 5500 }); 5501 }, 5502 destroy: function() { 5503 while (menuTrees.length) { 5504 menuTrees[0].destroy(); 5505 } 5506 initMouseDetection(true); 5507 }, 5508 prototype: { 5509 init: function(refresh) { 5510 var self = this; 5511 5512 if (!refresh) { 5513 menuTrees.push(this); 5514 5515 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 5516 5517 if (this.$root.hasClass('sm-rtl')) { 5518 this.opts.rightToLeftSubMenus = true; 5519 } 5520 5521 // init root (main menu) 5522 this.$root 5523 .data('smartmenus', this) 5524 .attr('data-smartmenus-id', this.rootId) 5525 .dataSM('level', 1) 5526 .bind({ 5527 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
5528 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 5529 }) 5530 .delegate('a', { 5531 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 5532 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 5533 'mousedown.smartmenus': $.proxy(this.itemDown, this), 5534 'focus.smartmenus': $.proxy(this.itemFocus, this), 5535 'blur.smartmenus': $.proxy(this.itemBlur, this), 5536 'click.smartmenus': $.proxy(this.itemClick, this), 5537 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 5538 }); 5539 5540 var eNamespace = '.smartmenus' + this.rootId; 5541 // hide menus on tap or click outside the root UL 5542 if (this.opts.hideOnClick) { 5543 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 5544 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 5545 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 5546 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 5547 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 5548 } 5549 // hide sub menus on resize 5550 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5551 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 5552 5553 if (this.opts.subIndicators) { 5554 this.$subArrow = $('<span/>').addClass('sub-arrow'); 5555 if (this.opts.subIndicatorsText) { 5556 this.$subArrow.html(this.opts.subIndicatorsText); 5557 } 5558 } 5559 5560 // make sure mouse detection is enabled 5561 initMouseDetection(); 5562 } 5563 5564 // init sub menus 5565 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 5566 5567 this.$firstLink = this.$root.find('a').eq(0); 5568 5569 // find current item 5570 if (this.opts.markCurrentItem) { 5571 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 5572 reHash = /#.*/, 5573 locHref = window.location.href.replace(reDefaultDoc, ''), 5574 locHrefNoHash = locHref.replace(reHash, ''); 5575 this.$root.find('a').each(function() { 5576 var href = this.href.replace(reDefaultDoc, ''), 5577 $this = $(this); 5578 if (href == locHref || href == locHrefNoHash) { 5579 $this.addClass('current'); 5580 if (self.opts.markCurrentTree) { 5581 $this.parents('li').each(function() { 5582 var $this = $(this); 5583 if ($this.dataSM('sub')) { 5584 $this.children('a').addClass('current'); 5585 } 5586 }); 5587 } 5588 } 5589 }); 5590 } 5591 }, 5592 destroy: function() { 5593 this.menuHideAll(); 5594 this.$root 5595 .removeData('smartmenus') 5596 .removeAttr('data-smartmenus-id') 5597 .removeDataSM('level') 5598 .unbind('.smartmenus') 5599 .undelegate('.smartmenus'); 5600 var eNamespace = '.smartmenus' + this.rootId; 5601 $(document).unbind(eNamespace); 5602 $(window).unbind(eNamespace); 5603 if (this.opts.subIndicators) { 5604 this.$subArrow = null; 5605 } 5606 var self = this; 5607 $.each(this.subMenus, function() { 5608 if (this.hasClass('mega-menu')) { 5609 this.find('ul').removeDataSM('in-mega'); 5610 } 5611 if (this.dataSM('shown-before')) { 5612 if (IElt8) { 5613 this.children().css({ styleFloat: '', width: '' }); 5614 } 5615 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 5616 if (!IE6) { 5617 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 5618 } else { 5619 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 5620 } 5621 } 5622 if (this.dataSM('scroll-arrows')) { 5623 this.dataSM('scroll-arrows').remove(); 5624 } 5625 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 5626 } 5627 if (self.opts.subIndicators) { 5628 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 5629 } 5630 this.removeDataSM('shown-before') 5631 .removeDataSM('ie-shim') 5632 .removeDataSM('scroll-arrows') 5633 .removeDataSM('parent-a') 5634 .removeDataSM('level') 5635 .removeDataSM('beforefirstshowfired') 5636 .parent().removeDataSM('sub'); 5637 }); 5638 if (this.opts.markCurrentItem) { 5639 this.$root.find('a.current').removeClass('current'); 5640 } 5641 this.$root = null; 5642 this.$firstLink = null; 5643 this.$firstSub = null; 5644 if (this.$disableOverlay) { 5645 this.$disableOverlay.remove(); 5646 this.$disableOverlay = null; 5647 } 5648 menuTrees.splice($.inArray(this, menuTrees), 1); 5649 }, 5650 disable: function(noOverlay) { 5651 if (!this.disabled) { 5652 this.menuHideAll(); 5653 // display overlay over the menu to prevent interaction 5654 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 5655 var pos = this.$root.offset(); 5656 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 5657 position: 'absolute', 5658 top: pos.top, 5659 left: pos.left, 5660 width: this.$root.outerWidth(), 5661 height: this.$root.outerHeight(),
5662 zIndex: this.getStartZIndex() + 1, 5663 opacity: 0 5664 }).appendTo(document.body); 5665 } 5666 this.disabled = true; 5667 } 5668 }, 5669 docClick: function(e) { 5670 // hide on any click outside the menu or on a menu link 5671 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 5672 this.menuHideAll($(e.target)); 5673 } 5674 }, 5675 docTouchEnd: function(e) { 5676 if (!this.lastTouch) { 5677 return; 5678 } 5679 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))) { 5680 if (this.hideTimeout) { 5681 clearTimeout(this.hideTimeout); 5682 this.hideTimeout = 0; 5683 } 5684 // hide with a delay to prevent triggering accidental unwanted click on some page element 5685 var self = this; 5686 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 5687 } 5688 this.lastTouch = null; 5689 }, 5690 docTouchMove: function(e) { 5691 if (!this.lastTouch) { 5692 return; 5693 } 5694 var touchPoint = e.originalEvent.touches[0]; 5695 this.lastTouch.x2 = touchPoint.pageX; 5696 this.lastTouch.y2 = touchPoint.pageY; 5697 }, 5698 docTouchStart: function(e) { 5699 var touchPoint = e.originalEvent.touches[0]; 5700 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 5701 }, 5702 enable: function() { 5703 if (this.disabled) { 5704 if (this.$disableOverlay) { 5705 this.$disableOverlay.remove(); 5706 this.$disableOverlay = null; 5707 } 5708 this.disabled = false; 5709 } 5710 }, 5711 getHeight: function($elm) { 5712 return this.getOffset($elm, true); 5713 }, 5714 // returns precise width/height float values in IE9+, FF4+, recent WebKit 5715 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 5716 getOffset: function($elm, height) { 5717 var old; 5718 if ($elm.css('display') == 'none') { 5719 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 5720 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 5721 } 5722 var defaultView = $elm[0].ownerDocument.defaultView, 5723 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 5724 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 5725 if (val) { 5726 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 5727 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 5728 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 5729 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 5730 } else { 5731 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 5732 } 5733 if (old) { 5734 $elm.hide().css(old); 5735 } 5736 return val; 5737 }, 5738 getWidth: function($elm) { 5739 return this.getOffset($elm); 5740 }, 5741 getStartZIndex: function() { 5742 var zIndex = parseInt(this.$root.css('z-index')); 5743 return !isNaN(zIndex) ? zIndex : 1; 5744 }, 5745 handleEvents: function() { 5746 return !this.disabled && this.isCSSOn(); 5747 }, 5748 handleItemEvents: function($a) { 5749 return this.handleEvents() && !this.isLinkInMegaMenu($a); 5750 }, 5751 isCollapsible: function() { 5752 return this.$firstSub.css('position') == 'static'; 5753 }, 5754 isCSSOn: function() { 5755 return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'inline'; 5756 }, 5757 isFixed: function() { 5758 return this.$root.css('position') == 'fixed'; 5759 }, 5760 isLinkInMegaMenu: function($a) { 5761 return !$a.parent().parent().dataSM('level'); 5762 }, 5763 isTouchMode: function() { 5764 return !mouse || this.isCollapsible(); 5765 }, 5766 itemActivate: function($a) { 5767 var $li = $a.parent(), 5768 $ul = $li.parent(), 5769 level = $ul.dataSM('level'); 5770 // 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 5771 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 5772 var self = this; 5773 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 5774 self.itemActivate($(this).dataSM('parent-a')); 5775 }); 5776 } 5777 // hide any visible deeper level sub menus 5778 if (this.visibleSubMenus.length > level) { 5779 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--) { 5780 this.menuHide(this.visibleSubMenus[i]); 5781 } 5782 } 5783 // save new active item and sub menu for this level 5784 this.activatedItems[level - 1] = $a; 5785 this.visibleSubMenus[level - 1] = $ul; 5786 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 5787 return; 5788 } 5789 // show the sub menu if this item has one 5790 var $sub = $li.dataSM('sub'); 5791 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 5792 this.menuShow($sub); 5793 } 5794 }, 5795 itemBlur: function(e) { 5796 var $a = $(e.currentTarget); 5797 if (!this.handleItemEvents($a)) { 5798 return; 5799 } 5800 this.$root.triggerHandler('blur.smapi', $a[0]); 5801 }, 5802 itemClick: function(e) { 5803 var $a = $(e.currentTarget); 5804 5805 if (!this.handleItemEvents($a)) { 5806 return; 5807 } 5808 $a.removeDataSM('mousedown'); 5809 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 5810 return false;
5811 } 5812 var $sub = $a.parent().dataSM('sub'); 5813 if (this.isTouchMode()) { 5814 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 5815 if ($a.dataSM('href')) { 5816 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 5817 } 5818 // if the sub is not visible 5819 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5820 // try to activate the item and show the sub 5821 this.itemActivate($a); 5822 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 5823 // 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 5824 if ($sub.is(':visible')) { 5825 return false; 5826 } 5827 } 5828 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 5829 this.clickActivated = true; 5830 this.menuShow($sub); 5831 return false; 5832 } 5833 if ($a.hasClass('disabled')) { 5834 return false; 5835 } 5836 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 5837 return false; 5838 } 5839 }, 5840 itemDown: function(e) { 5841 var $a = $(e.currentTarget); 5842 if (!this.handleItemEvents($a)) { 5843 return; 5844 } 5845 $a.dataSM('mousedown', true); 5846 }, 5847 itemEnter: function(e) { 5848 var $a = $(e.currentTarget); 5849 if (!this.handleItemEvents($a)) { 5850 return; 5851 } 5852 if (!this.isTouchMode()) { 5853 if (this.showTimeout) { 5854 clearTimeout(this.showTimeout); 5855 this.showTimeout = 0; 5856 } 5857 var self = this; 5858 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 5859 } 5860 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 5861 }, 5862 itemFocus: function(e) { 5863 var $a = $(e.currentTarget); 5864 if (!this.handleItemEvents($a)) { 5865 return; 5866 } 5867 // 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 5868 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 5869 this.itemActivate($a); 5870 } 5871 this.$root.triggerHandler('focus.smapi', $a[0]); 5872 }, 5873 itemLeave: function(e) { 5874 var $a = $(e.currentTarget); 5875 if (!this.handleItemEvents($a)) { 5876 return; 5877 } 5878 if (!this.isTouchMode()) { 5879 if ($a[0].blur) { 5880 $a[0].blur(); 5881 } 5882 if (this.showTimeout) { 5883 clearTimeout(this.showTimeout); 5884 this.showTimeout = 0; 5885 } 5886 } 5887 $a.removeDataSM('mousedown'); 5888 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 5889 }, 5890 itemTouchEnd: function(e) { 5891 var $a = $(e.currentTarget); 5892 if (!this.handleItemEvents($a)) { 5893 return; 5894 } 5895 // prevent the address bar on iPhone from sliding down when expanding a sub menu 5896 var $sub = $a.parent().dataSM('sub'); 5897 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 5898 $a.dataSM('href', $a.attr('href')); 5899 $a.attr('href', '#'); 5900 } 5901 }, 5902 menuFixLayout: function($ul) { 5903 // fixes a menu that is being shown for the first time 5904 if (!$ul.dataSM('shown-before')) { 5905 $ul.hide().dataSM('shown-before', true); 5906 // fix the layout of the items in IE<8 5907 if (IElt8) { 5908 $ul.children().css({ styleFloat: 'left', width: '100%' }); 5909 } 5910 } 5911 }, 5912 menuHide: function($sub) { 5913 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 5914 return; 5915 } 5916 $sub.stop(true, true); 5917 if ($sub.is(':visible')) { 5918 var complete = function() { 5919 // unset z-index 5920 if (IElt9) { 5921 $sub.parent().css('z-index', ''); 5922 } else { 5923 $sub.css('z-index', ''); 5924 } 5925 }; 5926 // if sub is collapsible (mobile view) 5927 if (this.isCollapsible()) { 5928 if (this.opts.collapsibleHideFunction) { 5929 this.opts.collapsibleHideFunction.call(this, $sub, complete); 5930 } else { 5931 $sub.hide(this.opts.collapsibleHideDuration, complete); 5932 } 5933 } else { 5934 if (this.opts.hideFunction) { 5935 this.opts.hideFunction.call(this, $sub, complete); 5936 } else { 5937 $sub.hide(this.opts.hideDuration, complete); 5938 } 5939 } 5940 // remove IE iframe shim 5941 if ($sub.dataSM('ie-shim')) { 5942 $sub.dataSM('ie-shim').remove(); 5943 } 5944 // deactivate scrolling if it is activated for this sub 5945 if ($sub.dataSM('scroll')) { 5946 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 5947 } 5948 // unhighlight parent item 5949 $sub.dataSM('parent-a').removeClass('highlighted'); 5950 var level = $sub.dataSM('level'); 5951 this.activatedItems.splice(level - 1, 1); 5952 this.visibleSubMenus.splice(level - 1, 1); 5953 this.$root.triggerHandler('hide.smapi', $sub[0]); 5954 } 5955 }, 5956 menuHideAll: function($item) { 5957 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 5958 if (this.showTimeout) { 5959 clearTimeout(this.showTimeout); 5960 this.showTimeout = 0; 5961 } 5962 // hide all subs 5963 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 5964 this.menuHide(this.visibleSubMenus[i]); 5965 } 5966 // hide root if it's popup 5967 if (this.opts.isPopup) { 5968 this.$root.stop(true, true); 5969 if (this.$root.is(':visible')) { 5970 if (this.opts.hideFunction) { 5971 this.opts.hideFunction.call(this, this.$root); 5972 } else { 5973 this.$root.hide(this.opts.hideDuration); 5974 } 5975 // remove IE iframe shim 5976 if (this.$root.dataSM('ie-shim')) { 5977 this.$root.dataSM('ie-shim').remove(); 5978 } 5979 } 5980 } 5981 this.activatedItems = []; 5982 this.visibleSubMenus = []; 5983 this.clickActivated = false;
5984 // reset z-index increment 5985 this.zIndexInc = 0; 5986 }, 5987 menuIframeShim: function($ul) { 5988 // create iframe shim for the menu 5989 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 5990 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 5991 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 5992 ); 5993 } 5994 }, 5995 menuInit: function($ul) { 5996 if (!$ul.dataSM('in-mega')) { 5997 this.subMenus.push($ul); 5998 // mark UL's in mega drop downs (if any) so we can neglect them 5999 if ($ul.hasClass('mega-menu')) { 6000 $ul.find('ul').dataSM('in-mega', true); 6001 } 6002 // get level (much faster than, for example, using parentsUntil) 6003 var level = 2, 6004 par = $ul[0]; 6005 while ((par = par.parentNode.parentNode) != this.$root[0]) { 6006 level++; 6007 } 6008 // cache stuff 6009 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 6010 .dataSM('level', level) 6011 .parent().dataSM('sub', $ul); 6012 // add sub indicator to parent item 6013 if (this.opts.subIndicators) { 6014 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 6015 } 6016 } 6017 }, 6018 menuPosition: function($sub) { 6019 var fixIE = $('html.ie').length; 6020 // if (fixIE) { 6021 // var $rowParent = $($sub).closest('.main-menu-container'); 6022 // $rowParent.height($rowParent.height()); 6023 // } 6024 var $a = $sub.dataSM('parent-a'), 6025 $li = $sub.parent(), 6026 $ul = $sub.parent().parent(), 6027 $container = $ul.closest('.row-menu-inner'), 6028 level = $sub.dataSM('level'), 6029 subW = this.getWidth($sub), 6030 subH = this.getHeight($sub), 6031 itemOffset = $a.offset(), 6032 itemX = itemOffset.left, 6033 itemY = itemOffset.top, 6034 itemW = this.getWidth($a), 6035 itemH = this.getHeight($a), 6036 $win = $(window), 6037 winX = $win.scrollLeft(), 6038 winY = $win.scrollTop(), 6039 winW = $win.width(), 6040 winH = $win.height(), 6041 containerW = $container.width(), 6042 containerOffsetX = containerW + ((winW - containerW) / 2), 6043 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 6044 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 6045 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 6046 x, y, leftPos; 6047 if (horizontalParent) { 6048 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 6049 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 6050 } else { 6051 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX; 6052 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 6053 } 6054 if (this.opts.keepInViewport && !this.isCollapsible()) { 6055 if (this.isFixed()) { 6056 itemX -= winX; 6057 itemY -= winY; 6058 winX = winY = 0; 6059 } 6060 var absX = itemX + x, 6061 absY = itemY + y; 6062 if (this.opts.rightToLeftSubMenus && absX < winX) { 6063 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 6064 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 6065 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 6066 } 6067 if (!horizontalParent) { 6068 if (subH < winH && absY + subH > winY + winH) { 6069 y += winY + winH - subH - absY; 6070 } else if (subH >= winH || absY < winY) { 6071 y += winY - absY; 6072 } 6073 } 6074 // do we need scrolling? 6075 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 6076 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 6077 var self = this; 6078 if (!$sub.dataSM('scroll-arrows')) { 6079 $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]]) 6080 .bind({ 6081 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 6082 mouseleave: function(e) { 6083 self.menuScrollStop($sub); 6084 self.menuScrollOut($sub, e); 6085 }, 6086 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 6087 }) 6088 .insertAfter($sub) 6089 ); 6090 } 6091 // bind events to show/hide arrows on hover and save scrolling data for this sub 6092 var vportY = winY - (itemY + itemH); 6093 $sub.dataSM('scroll', { 6094 vportY: vportY, 6095 subH: subH, 6096 winH: winH, 6097 step: 1 6098 }) 6099 .bind({ 6100 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 6101 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 6102 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 6103 }) 6104 .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
6104StartZIndex() + this.zIndexInc }) 6105 .eq(0).css('margin-top', vportY).end() 6106 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 6107 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 6108 } 6109 } 6110 // if ($sub.hasClass('mega-menu-inner')) { 6111 // if ($('.menu-wrapper .megamenu-diff').length > 0) { 6112 // leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth()); 6113 // leftPos = -leftPos; 6114 // } else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft')); 6115 6116 // if ($('body.header-full-width').length > 0) { 6117 // $sub.css({ width: $('.box-container').width()}); 6118 // leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft'))); 6119 // } else $sub.css({ width: containerW}); 6120 // leftPos = leftPos + 'px'; 6121 6122 // } else { 6123 // leftPos = $li.position().left + 'px'; 6124 // } 6125 if ($sub.hasClass('mega-menu-inner')) { 6126 $sub.css({ width: containerW}); 6127 if ($('body.hmenu-center-split').length > 0) { 6128 leftPos = - ($sub.closest('#menu-main-menu')[0].offsetLeft) + 'px'; 6129 } else { 6130 if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0) { 6131 leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px'; 6132 } else { 6133 leftPos = '0px'; 6134 } 6135 } 6136 } else { 6137 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 6138 x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1; 6139 } 6140 6141 $sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) }); 6142 // IE iframe shim 6143 this.menuIframeShim($sub); 6144 if ($sub.dataSM('ie-shim')) { 6145 $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) }); 6146 } 6147 }, 6148 menuScroll: function($sub, up, wheel) { 6149 var y = parseFloat($sub.css('margin-top')), 6150 scroll = $sub.dataSM('scroll'), 6151 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 6152 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 6153 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 6154 y = parseFloat($sub.css('margin-top')); 6155 // show opposite arrow if appropriate 6156 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 6157 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 6158 } 6159 // accelerate when not using mousewheel to scroll 6160 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 6161 $sub.dataSM('scroll').step += 0.5; 6162 } 6163 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 6164 if (Math.abs(y - end) < 1) { 6165 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 6166 $sub.dataSM('scroll').step = 1; 6167 } else if (!wheel) { 6168 var self = this; 6169 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 6170 } 6171 }, 6172 menuScrollMousewheel: function($sub, e) { 6173 var $closestSub = $(e.target).closest('ul'); 6174 while ($closestSub.dataSM('in-mega')) { 6175 $closestSub = $closestSub.parent().closest('ul'); 6176 } 6177 if ($closestSub[0] == $sub[0]) { 6178 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 6179 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 6180 this.menuScroll($sub, up, true); 6181 } 6182 } 6183 e.preventDefault(); 6184 }, 6185 menuScrollOut: function($sub, e) { 6186 var reClass = /^scroll-(up|down)/, 6187 $closestSub = $(e.relatedTarget).closest('ul'); 6188 while ($closestSub.dataSM('in-mega')) { 6189 $closestSub = $closestSub.parent().closest('ul'); 6190 } 6191 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 6192 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 6193 } 6194 }, 6195 menuScrollOver: function($sub, e) { 6196 var reClass = /^scroll-(up|down)/, 6197 $closestSub = $(e.target).closest('ul'); 6198 while ($closestSub.dataSM('in-mega')) { 6199 $closestSub = $closestSub.parent().closest('ul'); 6200 } 6201 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 6202 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 6203 } 6204 }, 6205 menuScrollStop: function($sub) { 6206 if (this.scrollTimeout) { 6207 clearTimeout(this.scrollTimeout); 6208 this.scrollTimeout = 0; 6209 $sub.dataSM('scroll').step = 1; 6210 } 6211 }, 6212 menuShow: function($sub) { 6213 if (!$sub.dataSM('beforefirstshowfired')) { 6214 $sub.dataSM('beforefirstshowfired', true); 6215 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 6216 return; 6217 } 6218 } 6219 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 6220 return; 6221 } 6222 this.menuFixLayout($sub); 6223 $sub.stop(true, true); 6224 if (!$sub.is(':visible')) { 6225 // set z-index - for IE < 9 set it to the parent LI
6226 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 6227 if (IElt9) { 6228 $sub.parent().css('z-index', zIndex); 6229 } else { 6230 $sub.css('z-index', zIndex); 6231 } 6232 // highlight parent item 6233 if (this.opts.keepHighlighted || this.isCollapsible()) { 6234 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 6235 $sub.dataSM('parent-a').addClass('highlighted'); 6236 } 6237 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 6238 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 6239 if (!IElt8) { 6240 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6241 if (this.opts.subMenusMinWidth) { 6242 $sub.css('min-width', this.opts.subMenusMinWidth); 6243 } 6244 if (this.opts.subMenusMaxWidth) { 6245 var noMaxWidth = this.getWidth($sub); 6246 $sub.css('max-width', this.opts.subMenusMaxWidth); 6247 if (noMaxWidth > this.getWidth($sub)) { 6248 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6249 } 6250 } 6251 // IE6,7 6252 } else { 6253 $sub.children().css('styleFloat', 'none'); 6254 if (IE6) { 6255 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 6256 .children().children('a').css('white-space', 'nowrap'); 6257 } else { // IE7 6258 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 6259 if (this.opts.subMenusMinWidth) { 6260 $sub.css('min-width', this.opts.subMenusMinWidth); 6261 } 6262 } 6263 if (this.opts.subMenusMaxWidth) { 6264 var noMaxWidth = $sub.width(); 6265 if (IE6) { 6266 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 6267 if (noMaxWidth > maxWidth) { 6268 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 6269 } else { 6270 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 6271 } 6272 } else { // IE7 6273 $sub.css('max-width', this.opts.subMenusMaxWidth); 6274 if (noMaxWidth > $sub.width()) { 6275 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 6276 } else { 6277 $sub.width(noMaxWidth); 6278 } 6279 } 6280 } else { 6281 $sub.width($sub.width()); 6282 } 6283 $sub.children().css('styleFloat', 'left'); 6284 } 6285 } 6286 this.menuPosition($sub); 6287 // insert IE iframe shim 6288 if ($sub.dataSM('ie-shim')) { 6289 $sub.dataSM('ie-shim').insertBefore($sub); 6290 } 6291 var complete = function() { 6292 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 6293 $sub.css('overflow', ''); 6294 }; 6295 // if sub is collapsible (mobile view) 6296 if (this.isCollapsible()) { 6297 if (this.opts.collapsibleShowFunction) { 6298 this.opts.collapsibleShowFunction.call(this, $sub, complete); 6299 } else { 6300 $sub.show(this.opts.collapsibleShowDuration, complete); 6301 } 6302 } else { 6303 if (this.opts.showFunction) { 6304 this.opts.showFunction.call(this, $sub, complete); 6305 } else { 6306 $sub.show(this.opts.showDuration, complete); 6307 } 6308 } 6309 // save new sub menu for this level 6310 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 6311 this.$root.triggerHandler('show.smapi', $sub[0]); 6312 } 6313 }, 6314 popupHide: function(noHideTimeout) { 6315 if (this.hideTimeout) { 6316 clearTimeout(this.hideTimeout); 6317 this.hideTimeout = 0; 6318 } 6319 var self = this; 6320 this.hideTimeout = setTimeout(function() { 6321 self.menuHideAll(); 6322 }, noHideTimeout ? 1 : this.opts.hideTimeout); 6323 }, 6324 popupShow: function(left, top) { 6325 if (!this.opts.isPopup) { 6326 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 6327 return; 6328 } 6329 if (this.hideTimeout) { 6330 clearTimeout(this.hideTimeout); 6331 this.hideTimeout = 0; 6332 } 6333 this.menuFixLayout(this.$root); 6334 this.$root.stop(true, true); 6335 if (!this.$root.is(':visible')) { 6336 this.$root.css({ left: left, top: top }); 6337 // IE iframe shim 6338 this.menuIframeShim(this.$root); 6339 if (this.$root.dataSM('ie-shim')) { 6340 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6340: left, top: top }).insertBefore(this.$root); 6341 } 6342 // show menu 6343 if (this.opts.showFunction) { 6344 this.opts.showFunction.call(this, this.$root); 6345 } else { 6346 this.$root.show(this.opts.showDuration); 6347 } 6348 this.visibleSubMenus[0] = this.$root; 6349 } 6350 }, 6351 refresh: function() { 6352 this.menuHideAll(); 6353 this.$root.find('ul').each(function() { 6354 var $this = $(this); 6355 if ($this.dataSM('scroll-arrows')) { 6356 $this.dataSM('scroll-arrows').remove(); 6357 } 6358 }) 6359 .removeDataSM('in-mega') 6360 .removeDataSM('shown-before') 6361 .removeDataSM('ie-shim') 6362 .removeDataSM('scroll-arrows') 6363 .removeDataSM('parent-a') 6364 .removeDataSM('level') 6365 .removeDataSM('beforefirstshowfired'); 6366 this.$root.find('a.has-submenu').removeClass('has-submenu') 6367 .parent().removeDataSM('sub'); 6368 if (this.opts.subIndicators) { 6369 this.$root.find('span.sub-arrow').remove(); 6370 } 6371 if (this.opts.markCurrentItem) { 6372 this.$root.find('a.current').removeClass('current'); 6373 } 6374 this.subMenus = []; 6375 this.init(true); 6376 }, 6377 rootOut: function(e) { 6378 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6379 return; 6380 } 6381 if (this.hideTimeout) { 6382 clearTimeout(this.hideTimeout); 6383 this.hideTimeout = 0; 6384 } 6385 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 6386 var self = this; 6387 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 6388 } 6389 }, 6390 rootOver: function(e) { 6391 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 6392 return; 6393 } 6394 if (this.hideTimeout) { 6395 clearTimeout(this.hideTimeout); 6396 this.hideTimeout = 0; 6397 } 6398 }, 6399 winResize: function(e) { 6400 if (!this.handleEvents()) { 6401 // we still need to resize the disable overlay if it's visible 6402 if (this.$disableOverlay) { 6403 var pos = this.$root.offset(); 6404 this.$disableOverlay.css({ 6405 top: pos.top, 6406 left: pos.left, 6407 width: this.$root.outerWidth(), 6408 height: this.$root.outerHeight() 6409 }); 6410 } 6411 return; 6412 } 6413 // hide sub menus on resize - on mobile do it only on orientation change 6414 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 6415 if (this.activatedItems.length) { 6416 this.activatedItems[this.activatedItems.length - 1][0].blur(); 6417 } 6418 this.menuHideAll(); 6419 } 6420 } 6421 } 6422 }); 6423 6424 $.fn.dataSM = function(key, val) { 6425 if (val) { 6426 return this.data(key + '_smartmenus', val); 6427 } 6428 return this.data(key + '_smartmenus'); 6429 } 6430 6431 $.fn.removeDataSM = function(key) { 6432 return this.removeData(key + '_smartmenus'); 6433 } 6434 6435 $.fn.smartmenus = function(options) { 6436 if (typeof options == 'string') { 6437 var args = arguments, 6438 method = options; 6439 Array.prototype.shift.call(args); 6440 return this.each(function() { 6441 var smartmenus = $(this).data('smartmenus'); 6442 if (smartmenus && smartmenus[method]) { 6443 smartmenus[method].apply(smartmenus, args); 6444 } 6445 }); 6446 } 6447 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 6448 return this.each(function() { 6449 new $.SmartMenus(this, opts); 6450 }); 6451 } 6452 6453 // default settings 6454 $.fn.smartmenus.defaults = { 6455 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 6456 mainMenuSubOffsetX: 0, // pixels offset from default position
6457 mainMenuSubOffsetY: 0, // pixels offset from default position 6458 subMenusSubOffsetX: 0, // pixels offset from default position 6459 subMenusSubOffsetY: 0, // pixels offset from default position 6460 subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6461 subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 6462 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 6463 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 6464 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 6465 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 6466 scrollInterval: 30, // interval between each scrolling step 6467 scrollAccelerate: true, // accelerate scrolling or use a fixed step 6468 showTimeout: 250, // timeout before showing the sub menus 6469 hideTimeout: 500, // timeout before hiding the sub menus 6470 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 6471 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 6472 // don't forget to call complete() at the end of whatever you do 6473 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 6474 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 6475 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 6476 // don't forget to call complete() at the end of whatever you do 6477 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 6478 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 6479 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 6480 // (i.e. when mobile styles are used to make the sub menus collapsible) 6481 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 6482 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 6483 // (i.e. when mobile styles are used to make the sub menus collapsible) 6484 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 6485 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 6486 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 6487 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 6488 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 6489 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 6490 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 6491 bottomToTopSubMenus: false, // bottom to top display of the sub menus 6492 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 6493 }; 6494 6495})(jQuery); 6496 6497/* 6498 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 6499 * 6500 * Uses the built in easing capabilities added In jQuery 1.1 6501 * to offer multiple easing options 6502 * 6503 * TERMS OF USE - jQuery Easing 6504 * 6505 * Open source under the BSD License. 6506 * 6507 * Copyright © 2008 George McGinley Smith 6508 * All rights reserved. 6509 * 6510 * Redistribution and use in source and binary forms, with or without modification, 6511 * are permitted provided that the following conditions are met: 6512 * 6513 * Redistributions of source code must retain the above copyright notice, this list of 6514 * conditions and the following disclaimer. 6515 * Redistributions in binary form must reproduce the above copyright notice, this list 6516 * of conditions and the following disclaimer in the documentation and/or other materials 6517 * provided with the distribution. 6518 * 6519 * Neither the name of the author nor the names of contributors may be used to endorse 6520 * or promote products derived from this software without specific prior written permission. 6521 * 6522 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6523 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6524 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6525 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6526-6671
6526 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6527 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6528 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6529 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6530 * OF THE POSSIBILITY OF SUCH DAMAGE. 6531 * 6532*/ 6533 6534// t: current time, b: begInnIng value, c: change In value, d: duration 6535jQuery.easing['jswing'] = jQuery.easing['swing']; 6536 6537jQuery.extend( jQuery.easing, 6538{ 6539 def: 'easeOutQuad', 6540 swing: function (x, t, b, c, d) { 6541 //alert(jQuery.easing.default); 6542 return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 6543 }, 6544 easeInQuad: function (x, t, b, c, d) { 6545 return c*(t/=d)*t + b; 6546 }, 6547 easeOutQuad: function (x, t, b, c, d) { 6548 return -c *(t/=d)*(t-2) + b; 6549 }, 6550 easeInOutQuad: function (x, t, b, c, d) { 6551 if ((t/=d/2) < 1) return c/2*t*t + b; 6552 return -c/2 * ((--t)*(t-2) - 1) + b; 6553 }, 6554 easeInCubic: function (x, t, b, c, d) { 6555 return c*(t/=d)*t*t + b; 6556 }, 6557 easeOutCubic: function (x, t, b, c, d) { 6558 return c*((t=t/d-1)*t*t + 1) + b; 6559 }, 6560 easeInOutCubic: function (x, t, b, c, d) { 6561 if ((t/=d/2) < 1) return c/2*t*t*t + b; 6562 return c/2*((t-=2)*t*t + 2) + b; 6563 }, 6564 easeInQuart: function (x, t, b, c, d) { 6565 return c*(t/=d)*t*t*t + b; 6566 }, 6567 easeOutQuart: function (x, t, b, c, d) { 6568 return -c * ((t=t/d-1)*t*t*t - 1) + b; 6569 }, 6570 easeInOutQuart: function (x, t, b, c, d) { 6571 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 6572 return -c/2 * ((t-=2)*t*t*t - 2) + b; 6573 }, 6574 easeInQuint: function (x, t, b, c, d) { 6575 return c*(t/=d)*t*t*t*t + b; 6576 }, 6577 easeOutQuint: function (x, t, b, c, d) { 6578 return c*((t=t/d-1)*t*t*t*t + 1) + b; 6579 }, 6580 easeInOutQuint: function (x, t, b, c, d) { 6581 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 6582 return c/2*((t-=2)*t*t*t*t + 2) + b; 6583 }, 6584 easeInSine: function (x, t, b, c, d) { 6585 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 6586 }, 6587 easeOutSine: function (x, t, b, c, d) { 6588 return c * Math.sin(t/d * (Math.PI/2)) + b; 6589 }, 6590 easeInOutSine: function (x, t, b, c, d) { 6591 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 6592 }, 6593 easeInExpo: function (x, t, b, c, d) { 6594 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 6595 }, 6596 easeOutExpo: function (x, t, b, c, d) { 6597 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 6598 }, 6599 easeInOutExpo: function (x, t, b, c, d) { 6600 if (t==0) return b; 6601 if (t==d) return b+c; 6602 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 6603 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 6604 }, 6605 easeInCirc: function (x, t, b, c, d) { 6606 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 6607 }, 6608 easeOutCirc: function (x, t, b, c, d) { 6609 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 6610 }, 6611 easeInOutCirc: function (x, t, b, c, d) { 6612 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 6613 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 6614 }, 6615 easeInElastic: function (x, t, b, c, d) { 6616 var s=1.70158;var p=0;var a=c; 6617 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6618 if (a < Math.abs(c)) { a=c; var s=p/4; } 6619 else var s = p/(2*Math.PI) * Math.asin (c/a); 6620 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6621 }, 6622 easeOutElastic: function (x, t, b, c, d) { 6623 var s=1.70158;var p=0;var a=c; 6624 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 6625 if (a < Math.abs(c)) { a=c; var s=p/4; } 6626 else var s = p/(2*Math.PI) * Math.asin (c/a); 6627 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 6628 }, 6629 easeInOutElastic: function (x, t, b, c, d) { 6630 var s=1.70158;var p=0;var a=c; 6631 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 6632 if (a < Math.abs(c)) { a=c; var s=p/4; } 6633 else var s = p/(2*Math.PI) * Math.asin (c/a); 6634 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 6635 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 6636 }, 6637 easeInBack: function (x, t, b, c, d, s) { 6638 if (s == undefined) s = 1.70158; 6639 return c*(t/=d)*t*((s+1)*t - s) + b; 6640 }, 6641 easeOutBack: function (x, t, b, c, d, s) { 6642 if (s == undefined) s = 1.70158; 6643 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 6644 }, 6645 easeInOutBack: function (x, t, b, c, d, s) { 6646 if (s == undefined) s = 1.70158; 6647 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 6648 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 6649 }, 6650 easeInBounce: function (x, t, b, c, d) { 6651 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 6652 }, 6653 easeOutBounce: function (x, t, b, c, d) { 6654 if ((t/=d) < (1/2.75)) { 6655 return c*(7.5625*t*t) + b; 6656 } else if (t < (2/2.75)) { 6657 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 6658 } else if (t < (2.5/2.75)) { 6659 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 6660 } else { 6661 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 6662 } 6663 }, 6664 easeInOutBounce: function (x, t, b, c, d) { 6665 if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 6666 return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 6667 } 6668}); 6669 6670/* 6671 *
6672 * TERMS OF USE - EASING EQUATIONS 6673 * 6674 * Open source under the BSD License. 6675 * 6676 * Copyright © 2001 Robert Penner 6677 * All rights reserved. 6678 * 6679 * Redistribution and use in source and binary forms, with or without modification, 6680 * are permitted provided that the following conditions are met: 6681 * 6682 * Redistributions of source code must retain the above copyright notice, this list of 6683 * conditions and the following disclaimer. 6684 * Redistributions in binary form must reproduce the above copyright notice, this list 6685 * of conditions and the following disclaimer in the documentation and/or other materials 6686 * provided with the distribution. 6687 * 6688 * Neither the name of the author nor the names of contributors may be used to endorse 6689 * or promote products derived from this software without specific prior written permission. 6690 * 6691 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 6692 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6693 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6694 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 6695 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6696 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 6697 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 6698 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6699 * OF THE POSSIBILITY OF SUCH DAMAGE. 6700 * 6701 */ 6702 6703(function($, window, undefined) { 6704 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 6705 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 6706 6707 // requestAnimationFrame polyfill by Erik Möller 6708 // fixes from Paul Irish and Tino Zijdel 6709 6710 var lastTime = 0, 6711 running, 6712 animate = function (elem) { 6713 if (running) { 6714 window.requestAnimationFrame(animate, elem); 6715 jQuery.fx.tick(); 6716 } 6717 }, 6718 vendors = ['ms', 'moz', 'webkit', 'o']; 6719 6720 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 6721 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 6722 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 6723 || window[vendors[x]+'CancelRequestAnimationFrame']; 6724 } 6725 6726 if (!window.requestAnimationFrame) 6727 window.requestAnimationFrame = function(fn, element) { 6728 var currTime = new Date().getTime(), 6729 delta = currTime - lastTime, 6730 timeToCall = Math.max(0, 16 - delta); 6731 6732 var id = window.setTimeout(function() { 6733 fn(currTime + timeToCall); 6734 }, 6735 timeToCall 6736 ); 6737 6738 lastTime = currTime + timeToCall; 6739 6740 return id; 6741 }; 6742 6743 if (!window.cancelAnimationFrame) { 6744 window.cancelAnimationFrame = function(id) { 6745 clearTimeout(id); 6746 }; 6747 } 6748 6749 jQuery.fx.timer = function (timer) { 6750 if (timer() && jQuery.timers.push(timer) && !running) { 6751 running = true; 6752 animate(timer.elem); 6753 } 6754 }; 6755 6756 jQuery.fx.stop = function() { 6757 running = false; 6758 }; 6759 6760}(jQuery, this)); 6761 6762/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 6763 * Licensed under the MIT License (LICENSE.txt). 6764 * 6765 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 6766 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6767 * Thanks to: Seamus Leahy for adding deltaX and deltaY 6768 * 6769 * Version: 3.0.6 6770 * 6771 * Requires: 1.2.2+ 6772 */ 6773(function($) { 6774 var types = ['DOMMouseScroll', 'mousewheel']; 6775 if ($.event.fixHooks) { 6776 for (var i = types.length; i;) { 6777 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 6778 } 6779 } 6780 $.event.special.mousewheel = { 6781 setup: function() { 6782 if (this.addEventListener) { 6783 for (var i = types.length; i;) { 6784 this.addEventListener(types[--i], handler, false); 6785 } 6786 } else { 6787 this.onmousewheel = handler; 6788 } 6789 }, 6790 teardown: function() { 6791 if (this.removeEventListener) { 6792 for (var i = types.length; i;) { 6793 this.removeEventListener(types[--i], handler, false); 6794 } 6795 } else { 6796 this.onmousewheel = null; 6797 } 6798 } 6799 }; 6800 $.fn.extend({ 6801 mousewheel: function(fn) { 6802 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 6803 }, 6804 unmousewheel: function(fn) { 6805 return this.unbind("mousewheel", fn); 6806 } 6807 }); 6808 6809 function handler(event) { 6810 var orgEvent = event || window.event, 6811 args = [].slice.call(arguments, 1), 6812 delta = 0, 6813 returnValue = true, 6814 deltaX = 0, 6815 deltaY = 0; 6816 event = $.event.fix(orgEvent); 6817 event.type = "mousewheel"; 6818 // Old school scrollwheel delta 6819 if (orgEvent.wheelDelta) { 6820 delta = orgEvent.wheelDelta / 120; 6821 } 6822 if (orgEvent.detail) { 6823 delta = -orgEvent.detail / 3; 6824 } 6825 // New school multidimensional scroll (touchpads) deltas 6826 deltaY = delta; 6827 // Gecko 6828 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 6829 deltaY = 0; 6830 deltaX = -1 * delta; 6831 } 6832 // Webkit 6833 if (orgEvent.wheelDeltaY !== undefined) { 6834 deltaY = orgEvent.wheelDeltaY / 120; 6835 } 6836 if (orgEvent.wheelDeltaX !== undefined) { 6837 deltaX = -1 * orgEvent.wheelDeltaX / 120; 6838 } 6839 // Add event and delta to the front of the arguments 6840 args.unshift(event, delta, deltaX, deltaY); 6841 return ($.event.dispatch || $.event.handle).apply(this, args); 6842 } 6843})(jQuery); 6844 6845/** 6846 * jQuery iLightBox - Revolutionary Lightbox Plugin 6847 * http://www.ilightbox.net/ 6848 * 6849 * @version: 2.2.0 - September 23, 2014 6850 * 6851 * @author: Hemn Chawroka 6852 * http://www.iprodev.com/ 6853 * 6854 */ 6855(function($, window, undefined) { 6856 6857 var extensions = { 6858 flash: ['swf'], 6859 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'], 6860 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 6861 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 6862 }, 6863 6864 // Global DOM elements 6865 $win = $(window), 6866 $doc = $(document), 6867
6868 // Support indicators 6869 browser, 6870 transform, 6871 gpuAcceleration, 6872 fullScreenApi = '', 6873 supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)), 6874 6875 // Events 6876 clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox", 6877 touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 6878 touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 6879 touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 6880 6881 // Math shorthands 6882 abs = Math.abs, 6883 sqrt = Math.sqrt, 6884 round = Math.round, 6885 max = Math.max, 6886 min = Math.min, 6887 floor = Math.floor, 6888 random = Math.random, 6889 6890 pluginspages = { 6891 quicktime: 'http://www.apple.com/quicktime/download', 6892 flash: 'http://www.adobe.com/go/getflash' 6893 }, 6894 6895 iLightBox = function(el, options, items, instant) { 6896 var iL = this; 6897 6898 iL.options = options, 6899 iL.selector = el.selector || el, 6900 iL.context = el.context, 6901 iL.instant = instant; 6902 6903 if (items.length < 1) iL.attachItems(); 6904 else iL.items = items; 6905 6906 iL.vars = { 6907 total: iL.items.length, 6908 start: 0, 6909 current: null, 6910 next: null, 6911 prev: null, 6912 BODY: $('body'), 6913 loadRequests: 0, 6914 overlay: $('<div class="ilightbox-overlay"></div>'), 6915 loader: $('<div class="ilightbox-loader"><div></div></div>'), 6916 toolbar: $('<div class="ilightbox-toolbar"></div>'), 6917 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 6918 title: $('<div class="ilightbox-title"></div>'), 6919 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 6920 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 6921 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 6922 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 6923 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 6924 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6925 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6926 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 6927 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 6928 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'), 6929 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>'), 6930 thumbs: false, 6931 nextLock: false, 6932 prevLock: false, 6933 hashLock: false, 6934 isMobile: false, 6935 mobileMaxWidth: 980, 6936 isInFullScreen: false, 6937 isSwipe: false, 6938 mouseID: 0, 6939 cycleID: 0, 6940 isPaused: 0 6941 }; 6942 6943 // Hideable elements with mousemove event 6944 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 6945 6946 iL.normalizeItems(); 6947 6948 //Check necessary plugins 6949 iL.availPlugins(); 6950 6951 //Set startFrom 6952 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 6953 6954 //If randomStart 6955 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 6956 iL.vars.start = iL.options.startFrom; 6957 6958 if (instant) iL.instantCall(); 6959 else iL.patchItemsEvents(); 6960 6961 if (iL.options.linkId) { 6962 iL.hashChangeHandler(); 6963 $win.iLightBoxHashChange(function() { 6964 iL.hashChangeHandler(); 6965 }); 6966 } 6967 6968 if (supportTouch) {
6969 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 6970 replace = "itap"; 6971 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 6972 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 6973 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 6974 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 6975 } 6976 6977 if (iL.options.controls.arrows) { 6978 $.extend(iL.options.styles, { 6979 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6980 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 6981 nextOpacity: 0, 6982 prevOpacity: 0 6983 }); 6984 } 6985 }; 6986 6987 //iLightBox helpers 6988 iLightBox.prototype = { 6989 showLoader: function() { 6990 var iL = this; 6991 iL.vars.loadRequests += 1; 6992 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.stop().animate({ 6993 //top: '2px' 6994 opacity: '1' 6995 }, iL.options.show.speed, 'easeOutCirc'); 6996 else iL.vars.loader.stop().animate({ 6997 // left: '2px' 6998 opacity: '1' 6999 }, iL.options.show.speed, 'easeOutCirc'); 7000 }, 7001 7002 hideLoader: function() { 7003 var iL = this; 7004 iL.vars.loadRequests -= 1; 7005 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 7006 if (iL.options.path.toLowerCase() == "horizontal") { 7007 if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({ 7008 //top: '-20px' 7009 opacity: '0' 7010 }, iL.options.show.speed, 'easeInCirc'); 7011 } else { 7012 if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({ 7013 //left: '-20px' 7014 opacity: '0' 7015 }, iL.options.show.speed, 'easeInCirc'); 7016 } 7017 }, 7018 7019 createUI: function() { 7020 var iL = this; 7021 7022 iL.ui = { 7023 currentElement: iL.vars.holder, 7024 nextElement: iL.vars.nextPhoto, 7025 prevElement: iL.vars.prevPhoto, 7026 currentItem: iL.vars.current, 7027 nextItem: iL.vars.next, 7028 prevItem: iL.vars.prev, 7029 hide: function() { 7030 iL.closeAction(); 7031 }, 7032 refresh: function() { 7033 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7034 }, 7035 fullscreen: function() { 7036 iL.fullScreenAction(); 7037 } 7038 }; 7039 }, 7040 7041 attachItems: function() { 7042 var iL = this, 7043 itemsObject = new Array(), 7044 items = new Array(); 7045 7046 $(iL.selector, iL.context).each(function() { 7047 var t = $(this), 7048 URL = t.attr(iL.options.attr) || null, 7049 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 7050 caption = t.data('caption'), 7051 title = t.data('title'), 7052 type = t.data('type') || getTypeByExtension(URL); 7053 7054 items.push({ 7055 URL: URL, 7056 caption: caption, 7057 title: title, 7058 type: type, 7059 options: options 7060 }); 7061 7062 if (!iL.instant) itemsObject.push(t); 7063 }); 7064 7065 if (iL.vars != undefined) iL.vars.total = items.length; 7066 7067 iL.items = items, 7068 iL.itemsObject = itemsObject; 7069 }, 7070 7071 normalizeItems: function() { 7072 var iL = this, 7073 newItems = new Array(); 7074 7075 $.each(iL.items, function(key, val) { 7076 7077 if (typeof val == "string") val = { 7078 url: val 7079 }; 7080 7081 var URL = val.url || val.URL || null, 7082 options = val.options || {}, 7083 caption = val.caption || null, 7084 title = val.title || null, 7085 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 7086 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 7087 7088 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null), 7089 options.videoType = options.videoType || null, 7090 options.skin = options.skin || iL.options.skin, 7091 options.width = options.width || null, 7092 options.height = options.height || null, 7093 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 7094 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 7095 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 7096 7097 if (type == "video") { 7098 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 7099 7100 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 7101 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 7102 options.html5video.preload = options.html5video.preload || "metadata"; 7103 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
7104 } 7105 7106 if (!options.width || !options.height) { 7107 if (type == "video") options.width = 1280, options.height = 720; 7108 else if (type == "iframe") options.width = '100%', options.height = '90%'; 7109 else if (type == "flash") options.width = 1280, options.height = 720; 7110 } 7111 7112 delete val.url; 7113 val.index = key; 7114 val.URL = URL; 7115 val.caption = caption; 7116 val.title = title; 7117 val.type = type; 7118 val.options = options; 7119 val.ext = ext; 7120 7121 newItems.push(val); 7122 }); 7123 7124 iL.items = newItems; 7125 }, 7126 7127 instantCall: function() { 7128 var iL = this, 7129 key = iL.vars.start; 7130 7131 iL.vars.current = key; 7132 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 7133 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 7134 7135 iL.addContents(); 7136 iL.patchEvents(); 7137 }, 7138 7139 addContents: function() { 7140 var iL = this, 7141 vars = iL.vars, 7142 opts = iL.options, 7143 viewport = getViewport(), 7144 path = opts.path.toLowerCase(), 7145 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 7146 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 7147 }), 7148 needRecognition = recognizingItems.length > 0; 7149 7150 if (opts.mobileOptimizer && !opts.innerToolbar) 7151 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7152 7153 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 7154 7155 if (opts.linkId) 7156 vars.overlay[0].setAttribute('linkid', opts.linkId); 7157 7158 //Add Toolbar Buttons 7159 if (opts.controls.toolbar) { 7160 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 7161 if (opts.controls.fullscreen) 7162 vars.toolbar.append(vars.fullScreenButton); 7163 if (opts.controls.slideshow) 7164 vars.toolbar.append(vars.innerPlayButton); 7165 if (vars.total > 1) 7166 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 7167 } 7168 7169 //Append elements to body 7170 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 7171 7172 if (!opts.innerToolbar) 7173 vars.BODY.append(vars.toolbar); 7174 if (opts.controls.arrows) 7175 vars.BODY.append(vars.nextButton).append(vars.prevButton); 7176 7177 if (opts.controls.thumbnail && vars.total > 1) { 7178 vars.BODY.append(vars.thumbnails); 7179 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 7180 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 7181 vars.thumbs = true; 7182 } 7183 7184 //Configure loader and arrows 7185 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 7186 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 7187 } : { 7188 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 7189 }; 7190 vars.loader.addClass(opts.skin).css(loaderCss); 7191 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 7192 if (path == "horizontal") 7193 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 7194 7195 // Configure arrow buttons 7196 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7197 7198 if (!opts.infinite) { 7199 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.nextButton).add(vars.innerNextButton).removeClass('disabled'); 7200 7201 if (vars.current == 0) 7202 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 7203 7204 if (vars.current >= vars.total - 1) 7205 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 7206 } 7207 7208 if (opts.show.effect) { 7209 vars.overlay.stop().fadeIn(opts.show.speed); 7210 vars.toolbar.stop().fadeIn(opts.show.speed); 7211 } else { 7212 vars.overlay.show(); 7213 vars.toolbar.show(); 7214 } 7215 7216 var length = recognizingItems.length; 7217 if (needRecognition) { 7218 iL.showLoader(); 7219 7220 $.each(recognizingItems, function(key, val) { 7221 var resultFnc = function(result) { 7222 var key = -1, 7223 filter = iL.items.filter(function(e, i, arr) { 7224 if (e.URL == result.url) 7225 key = i; 7226 7227 return e.URL == result.url; 7228 }), 7229 self = iL.items[key]; 7230 7231 if (result) 7232 $.extend(true, self, { 7233 URL: result.source, 7234 type: result.type, 7235 recognized: true, 7236 options: { 7237 html5video: result.html5video, 7238 width: (result.type == "image") ? 0 : (result.width || self.width), 7239 height: (result.type == "image") ? 0 : (result.height || self.height), 7240 thumbnail: self.options.thumbnail || result.thumbnail 7241 } 7242 }); 7243 7244 length--; 7245 7246 if (length == 0) { 7247 iL.hideLoader(); 7248 7249 vars.dontGenerateThumbs = false;
7250 iL.generateThumbnails(); 7251 7252 if (opts.show.effect) 7253 setTimeout(function() { 7254 iL.generateBoxes(); 7255 }, opts.show.speed); 7256 else 7257 iL.generateBoxes(); 7258 } 7259 }; 7260 7261 iL.ogpRecognition(this, resultFnc); 7262 }); 7263 } 7264 else { 7265 if (opts.show.effect) 7266 setTimeout(function() { 7267 iL.generateBoxes(); 7268 }, opts.show.speed); 7269 else 7270 iL.generateBoxes(); 7271 } 7272 7273 iL.createUI(); 7274 7275 window.iLightBox = { 7276 close: function() { 7277 iL.closeAction(); 7278 }, 7279 fullscreen: function() { 7280 iL.fullScreenAction(); 7281 }, 7282 moveNext: function() { 7283 iL.moveTo('next'); 7284 }, 7285 movePrev: function() { 7286 iL.moveTo('prev'); 7287 }, 7288 goTo: function(index) { 7289 iL.goTo(index); 7290 }, 7291 refresh: function() { 7292 iL.refresh(); 7293 }, 7294 reposition: function() { 7295 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 7296 }, 7297 setOption: function(options) { 7298 iL.setOption(options); 7299 }, 7300 destroy: function() { 7301 iL.closeAction(); 7302 iL.dispatchItemsEvents(); 7303 } 7304 }; 7305 7306 if (opts.linkId) { 7307 vars.hashLock = true; 7308 window.location.hash = opts.linkId + '/' + vars.current; 7309 setTimeout(function() { 7310 vars.hashLock = false; 7311 }, 55); 7312 } 7313 7314 if (!opts.slideshow.startPaused) { 7315 iL.resume(); 7316 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 7317 } 7318 7319 //Trigger the onOpen callback 7320 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 7321 7322 }, 7323 7324 loadContent: function(obj, opt, speed) { 7325 var iL = this, 7326 holder, item; 7327 7328 iL.createUI(); 7329 7330 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 7331 7332 if (opt == 'current') { 7333 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 7334 else iL.vars.lockWheel = false; 7335 7336 if (!obj.options.swipe) iL.vars.lockSwipe = true; 7337 else iL.vars.lockSwipe = false; 7338 } 7339 7340 switch (opt) { 7341 case 'current': 7342 holder = iL.vars.holder, item = iL.vars.current; 7343 break; 7344 case 'next': 7345 holder = iL.vars.nextPhoto, item = iL.vars.next; 7346 break; 7347 case 'prev': 7348 holder = iL.vars.prevPhoto, item = iL.vars.prev; 7349 break; 7350 } 7351 7352 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 7353 $('div.ilightbox-inner-toolbar', holder).remove(); 7354 7355 if (obj.title || iL.options.innerToolbar) { 7356 var innerToolbar = iL.vars.innerToolbar.clone(); 7357 if (obj.title && iL.options.show.title) { 7358 var title = iL.vars.title.clone(); 7359 title.empty().html(obj.title); 7360 innerToolbar.append(title); 7361 } 7362 if (iL.options.innerToolbar) { 7363 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 7364 } 7365 holder.prepend(innerToolbar); 7366 } 7367 7368 iL.loadSwitcher(obj, holder, item, opt); 7369 }, 7370 7371 loadSwitcher: function(obj, holder, item, opt) { 7372 var iL = this, 7373 opts = iL.options, 7374 api = { 7375 element: holder, 7376 position: item 7377 }; 7378 7379 switch (obj.type) { 7380 case 'image': 7381 //Trigger the onBeforeLoad callback 7382 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7383 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7384 7385 iL.loadImage(obj.URL, function(img) { 7386 //Trigger the onAfterLoad callback 7387 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7388 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7389 7390 var width = (img) ? img.width : 400, 7391 height = (img) ? img.height : 200; 7392 7393 holder.data({ 7394 naturalWidth: width, 7395 naturalHeight: height 7396 }); 7397 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 7398 7399 //Trigger the onRender callback 7400 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7401 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7402 7403 iL.configureHolder(obj, opt, holder); 7404 }); 7405 7406 break; 7407
7408 case 'video': 7409 holder.data({ 7410 naturalWidth: obj.options.width, 7411 naturalHeight: obj.options.height 7412 }); 7413 7414 iL.addContent(holder, obj); 7415 7416 //Trigger the onRender callback 7417 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7418 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7419 7420 iL.configureHolder(obj, opt, holder); 7421 7422 break; 7423 7424 case 'iframe': 7425 iL.showLoader(); 7426 holder.data({ 7427 naturalWidth: obj.options.width, 7428 naturalHeight: obj.options.height 7429 }); 7430 var el = iL.addContent(holder, obj); 7431 7432 //Trigger the onRender callback 7433 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7434 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7435 7436 //Trigger the onBeforeLoad callback 7437 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7438 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7439 7440 el.bind('load', function() { 7441 //Trigger the onAfterLoad callback 7442 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7443 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7444 7445 iL.hideLoader(); 7446 iL.configureHolder(obj, opt, holder); 7447 el.unbind('load'); 7448 }); 7449 7450 break; 7451 7452 case 'inline': 7453 var el = $(obj.URL), 7454 content = iL.addContent(holder, obj), 7455 images = findImageInElement(holder); 7456 7457 holder.data({ 7458 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7459 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7460 }); 7461 content.children().eq(0).show(); 7462 7463 //Trigger the onRender callback 7464 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7465 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7466 7467 //Trigger the onBeforeLoad callback 7468 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7469 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7470 7471 iL.loadImage(images, function() { 7472 //Trigger the onAfterLoad callback 7473 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7474 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7475 7476 iL.configureHolder(obj, opt, holder); 7477 }); 7478 7479 break; 7480 7481 case 'flash': 7482 var el = iL.addContent(holder, obj); 7483 7484 holder.data({ 7485 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 7486 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 7487 }); 7488 7489 //Trigger the onRender callback 7490 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7491 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7492 7493 iL.configureHolder(obj, opt, holder); 7494 7495 break; 7496 7497 case 'ajax': 7498 var ajax = obj.options.ajax || {}; 7499 //Trigger the onBeforeLoad callback 7500 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7501 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7502 7503 iL.showLoader(); 7504 $.ajax({ 7505 url: obj.URL || opts.ajaxSetup.url, 7506 data: ajax.data || null, 7507 dataType: ajax.dataType || "html", 7508 type: ajax.type || opts.ajaxSetup.type, 7509 cache: ajax.cache || opts.ajaxSetup.cache, 7510 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 7511 global: ajax.global || opts.ajaxSetup.global, 7512 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 7513 username: ajax.username || opts.ajaxSetup.username, 7514 password: ajax.password || opts.ajaxSetup.password, 7515 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 7516 complete: ajax.complete || opts.ajaxSetup.complete, 7517 success: function(data, textStatus, jqXHR) { 7518 iL.hideLoader(); 7519 7520 var el = $(data), 7521 container = $('div.ilightbox-container', holder), 7522 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 7523 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 7524 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 7525 'overflow': 'hidden' 7526 } : {}; 7527 7528 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 7529 holder.show().data({
7530 naturalWidth: (elWidth || container.outerWidth()), 7531 naturalHeight: (elHeight || container.outerHeight()) 7532 }).hide(); 7533 7534 //Trigger the onRender callback 7535 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7536 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7537 7538 var images = findImageInElement(holder); 7539 iL.loadImage(images, function() { 7540 //Trigger the onAfterLoad callback 7541 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7542 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7543 7544 iL.configureHolder(obj, opt, holder); 7545 }); 7546 7547 opts.ajaxSetup.success(data, textStatus, jqXHR); 7548 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 7549 }, 7550 error: function(jqXHR, textStatus, errorThrown) { 7551 //Trigger the onAfterLoad callback 7552 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7553 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7554 7555 iL.hideLoader(); 7556 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 7557 iL.configureHolder(obj, opt, holder); 7558 7559 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 7560 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 7561 } 7562 }); 7563 7564 break; 7565 7566 case 'html': 7567 var object = obj.URL, 7568 el 7569 container = $('div.ilightbox-container', holder); 7570 7571 if (object[0].nodeName) el = object.clone(); 7572 else { 7573 var dom = $(object); 7574 if (dom.selector) el = $('<div>' + dom + '</div>'); 7575 else el = dom; 7576 } 7577 7578 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 7579 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 7580 7581 iL.addContent(holder, obj); 7582 7583 el.appendTo(document.documentElement).hide(); 7584 7585 //Trigger the onRender callback 7586 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 7587 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 7588 7589 var images = findImageInElement(holder); 7590 7591 //Trigger the onBeforeLoad callback 7592 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 7593 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 7594 7595 iL.loadImage(images, function() { 7596 //Trigger the onAfterLoad callback 7597 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 7598 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 7599 7600 holder.show().data({ 7601 naturalWidth: (elWidth || container.outerWidth()), 7602 naturalHeight: (elHeight || container.outerHeight()) 7603 }).hide(); 7604 el.remove(); 7605 7606 iL.configureHolder(obj, opt, holder); 7607 }); 7608 7609 break; 7610 } 7611 }, 7612 7613 configureHolder: function(obj, opt, holder) { 7614 var iL = this, 7615 vars = iL.vars, 7616 opts = iL.options; 7617 7618 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 7619 7620 if (opt == "current") 7621 var item = vars.current; 7622 else if (opt == "next") 7623 var opacity = opts.styles.nextOpacity, 7624 item = vars.next; 7625 else 7626 var opacity = opts.styles.prevOpacity, 7627 item = vars.prev; 7628 7629 var api = { 7630 element: holder, 7631 position: item 7632 }; 7633 7634 iL.items[item].options.width = iL.items[item].options.width || 0, 7635 iL.items[item].options.height = iL.items[item].options.height || 0; 7636 7637 if (opt == "current") { 7638 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 7639 holder.css(transform, ''); 7640 if (obj.caption) { 7641 iL.setCaption(obj, holder); 7642 var caption = $('div.ilightbox-caption', holder), 7643 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 7644 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7644Speed); 7645 } 7646 7647 var social = obj.options.social; 7648 if (social) { 7649 iL.setSocial(social, obj.URL, holder); 7650 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 7651 } 7652 7653 //Generate thumbnails 7654 iL.generateThumbnails(); 7655 7656 //Trigger the onShow callback 7657 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7658 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7659 }); 7660 else { 7661 holder.show(); 7662 7663 //Generate thumbnails 7664 iL.generateThumbnails(); 7665 7666 //Trigger the onShow callback 7667 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7668 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7669 } 7670 } else { 7671 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 7672 if (opt == "next") vars.nextLock = false; 7673 else vars.prevLock = false; 7674 7675 //Generate thumbnails 7676 iL.generateThumbnails(); 7677 7678 //Trigger the onShow callback 7679 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7680 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7681 }); 7682 else { 7683 holder.css({ 7684 opacity: opacity 7685 }).show(); 7686 if (opt == "next") vars.nextLock = false; 7687 else vars.prevLock = false; 7688 7689 //Generate thumbnails 7690 iL.generateThumbnails(); 7691 7692 //Trigger the onShow callback 7693 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 7694 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 7695 } 7696 } 7697 7698 setTimeout(function() { 7699 iL.repositionPhoto(); 7700 }, 0); 7701 }, 7702 7703 generateBoxes: function() { 7704 var iL = this, 7705 vars = iL.vars, 7706 opts = iL.options; 7707 7708 if (opts.infinite && vars.total >= 3) { 7709 if (vars.current == vars.total - 1) vars.next = 0; 7710 if (vars.current == 0) vars.prev = vars.total - 1; 7711 } else opts.infinite = false; 7712 7713 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 7714 7715 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 7716 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 7717 }, 7718 7719 generateThumbnails: function() { 7720 var iL = this, 7721 vars = iL.vars, 7722 opts = iL.options, 7723 timeOut = null; 7724 7725 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 7726 var thumbnails = vars.thumbnails, 7727 container = $('div.ilightbox-thumbnails-container', thumbnails), 7728 grid = $('div.ilightbox-thumbnails-grid', container), 7729 i = 0; 7730 7731 grid.removeAttr('style').empty(); 7732 7733 $.each(iL.items, function(key, val) { 7734 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 7735 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 7736 thumb = val.options.thumbnail, 7737 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 7738 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 7739 7740 thumbnail.css({ 7741 opacity: 0 7742 }).addClass(isActive); 7743 7744 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 7745 icon.addClass('ilightbox-thumbnail-video'); 7746 thumbnail.append(icon); 7747 } else if (val.options.icon) { 7748 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 7749 thumbnail.append(icon); 7750 } 7751 7752 if (thumb) iL.loadImage(thumb, function(img) { 7753 i++; 7754 if (img) thumbnail.data({ 7755 naturalWidth: img.width, 7756 naturalHeight: img.height 7757 }).append('<img src="' + thumb + '" border="0" />'); 7758 else thumbnail.data({ 7759 naturalWidth: opts.thumbnails.maxWidth, 7760 naturalHeight: opts.thumbnails.maxHeight 7761 }); 7762 7763 clearTimeout(timeOut); 7764 timeOut = setTimeout(function() { 7765 iL.positionThumbnails(thumbnails, container, grid); 7766 }, 20); 7767 setTimeout(function() { 7768 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 7769 }, i * 20); 7770 }); 7771 7772 grid.append(thumbnail); 7773 }); 7774 iL.vars.dontGenerateThumbs = true; 7775 } 7776 }, 7777
7778 positionThumbnails: function(thumbnails, container, grid) { 7779 var iL = this, 7780 vars = iL.vars, 7781 opts = iL.options, 7782 viewport = getViewport(), 7783 path = opts.path.toLowerCase(); 7784 7785 if (!thumbnails) thumbnails = vars.thumbnails; 7786 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 7787 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 7788 7789 var thumbs = $('.ilightbox-thumbnail', grid), 7790 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 7791 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 7792 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 7793 gridHeight = (path == 'horizontal') ? heightAvail : 0, 7794 active = $('.ilightbox-active', grid), 7795 gridCss = {}, 7796 css = {}; 7797 7798 if (arguments.length < 3) { 7799 thumbs.css({ 7800 opacity: opts.thumbnails.normalOpacity 7801 }); 7802 active.css({ 7803 opacity: opts.thumbnails.activeOpacity 7804 }); 7805 } 7806 7807 thumbs.each(function(i) { 7808 var t = $(this), 7809 data = t.data(), 7810 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 7811 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 7812 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 7813 7814 t.css({ 7815 width: dims.width, 7816 height: dims.height 7817 }); 7818 if (path == 'horizontal') t.css({ 7819 'float': 'left' 7820 }); 7821 7822 (path == 'horizontal') ? ( 7823 gridWidth += t.outerWidth() 7824 ) : ( 7825 gridHeight += t.outerHeight() 7826 ); 7827 }); 7828 7829 gridCss = { 7830 width: gridWidth, 7831 height: gridHeight 7832 }; 7833 7834 grid.css(gridCss); 7835 7836 gridCss = {}; 7837 7838 var gridOffset = grid.offset(), 7839 activeOffset = (active.length) ? active.offset() : { 7840 top: parseInt(heightAvail / 2), 7841 left: parseInt(widthAvail / 2) 7842 }; 7843 7844 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 7845 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 7846 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 7847 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 7848 7849 (path == 'horizontal') ? ( 7850 gridCss.top = 0, 7851 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 7852 ) : ( 7853 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 7854 gridCss.left = 0 7855 ); 7856 7857 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 7858 else grid.css(gridCss); 7859 }, 7860 7861 loadImage: function(image, callback) { 7862 if (!$.isArray(image)) image = [image]; 7863 7864 var iL = this, 7865 length = image.length; 7866 7867 if (length > 0) { 7868 iL.showLoader(); 7869 $.each(image, function(index, value) { 7870 var img = new Image(); 7871 img.onload = function() { 7872 length -= 1; 7873 if (length == 0) { 7874 iL.hideLoader(); 7875 callback(img); 7876 } 7877 }; 7878 img.onerror = img.onabort = function() { 7879 length -= 1; 7880 if (length == 0) { 7881 iL.hideLoader(); 7882 callback(false); 7883 } 7884 }; 7885 img.src = image[index]; 7886 }); 7887 } else callback(false); 7888 }, 7889 7890 patchItemsEvents: function() { 7891 var iL = this, 7892 vars = iL.vars, 7893 clickEvent = supportTouch ? "itap.iL" : "click.iL", 7894 vEvent = supportTouch ? "click.iL" : "itap.iL"; 7895 7896 if (iL.context && iL.selector) { 7897 var $items = $(iL.selector, iL.context); 7898 $(iL.context).on(clickEvent, iL.selector, function() { 7899 7900 var $this = $(this), 7901 key = $items.index($this); 7902 if (UNCODE.isMobile) { 7903 var isCarousel = $this.closest('.owl-carousel'); 7904 if (isCarousel.length) { 7905 if (isCarousel.hasClass('owl-translating')) return false; 7906 } 7907 } 7908 7909 vars.current = key; 7910 vars.next = iL.items[key + 1] ? key + 1 : null; 7911 vars.prev = iL.items[key - 1] ? key - 1 : null; 7912 7913 iL.addContents(); 7914 iL.patchEvents(); 7915 7916 return false; 7917 }).on(vEvent, iL.selector, function() { 7918 return false; 7919 }); 7920 } else 7921 $.each(iL.itemsObject, function(key, val) { 7922 val.on(clickEvent, function() { 7923 vars.current = key; 7924 vars.next = iL.items[key + 1] ? key + 1 : null; 7925 vars.prev = iL.items[key - 1] ? key - 1 : null; 7926 7927 iL.addContents(); 7928 iL.patchEvents(); 7929 7930 return false;
7931 }).on(vEvent, function() { 7932 return false; 7933 }); 7934 }); 7935 }, 7936 7937 dispatchItemsEvents: function() { 7938 var iL = this, 7939 vars = iL.vars, 7940 opts = iL.options; 7941 7942 if (iL.context && iL.selector) 7943 $(iL.context).off('.iL', iL.selector); 7944 else 7945 $.each(iL.itemsObject, function(key, val) { 7946 val.off('.iL'); 7947 }); 7948 }, 7949 7950 refresh: function() { 7951 var iL = this; 7952 7953 iL.dispatchItemsEvents(); 7954 iL.attachItems(); 7955 iL.normalizeItems(); 7956 iL.patchItemsEvents(); 7957 }, 7958 7959 patchEvents: function() { 7960 var iL = this, 7961 vars = iL.vars, 7962 opts = iL.options, 7963 path = opts.path.toLowerCase(), 7964 holders = $('.ilightbox-holder'), 7965 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 7966 durationThreshold = 1000, 7967 horizontalDistanceThreshold = 7968 verticalDistanceThreshold = 100, 7969 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 7970 7971 $win.bind('resize.iLightBox', function() { 7972 var viewport = getViewport(); 7973 7974 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 7975 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 7976 7977 iL.repositionPhoto(null); 7978 if (supportTouch) { 7979 clearTimeout(vars.setTime); 7980 vars.setTime = setTimeout(function() { 7981 var scrollTop = getScrollXY().y; 7982 window.scrollTo(0, scrollTop - 30); 7983 window.scrollTo(0, scrollTop + 30); 7984 window.scrollTo(0, scrollTop); 7985 }, 2000); 7986 } 7987 if (vars.thumbs) iL.positionThumbnails(); 7988 }).bind('keydown.iLightBox', function(event) { 7989 if (opts.controls.keyboard) { 7990 switch (event.keyCode) { 7991 case 13: 7992 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 7993 break; 7994 case 27: 7995 if (opts.keyboard.esc) iL.closeAction(); 7996 break; 7997 case 37: 7998 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 7999 break; 8000 case 38: 8001 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 8002 break; 8003 case 39: 8004 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 8005 break; 8006 case 40: 8007 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 8008 break; 8009 } 8010 } 8011 }); 8012 8013 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 8014 iL.doFullscreen(); 8015 }); 8016 8017 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 8018 return arr.lastIndexOf(e) === i; 8019 }), 8020 holderEvents = ""; 8021 8022 $.each(holderEventsArr, function(key, val) { 8023 if (key != 0) holderEvents += ' '; 8024 holderEvents += val; 8025 }); 8026 8027 $doc.on(clickEvent, '.ilightbox-overlay', function() { 8028 if (opts.overlay.blur) iL.closeAction(); 8029 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 8030 iL.moveTo('next'); 8031 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 8032 iL.moveTo('prev'); 8033 }).on(clickEvent, '.ilightbox-thumbnail', function() { 8034 var t = $(this), 8035 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 8036 index = thumbs.index(t); 8037 8038 if (index != vars.current) iL.goTo(index); 8039 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8040 var caption = $('div.ilightbox-caption', vars.holder), 8041 social = $('div.ilightbox-social', vars.holder), 8042 fadeSpeed = opts.effects.fadeSpeed; 8043 8044 if (vars.nextLock || vars.prevLock) { 8045 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 8046 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 8047 8048 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 8049 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 8050 } else { 8051 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 8052 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 8053 8054 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 8055 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 8056 } 8057 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 8058 if (e.type == 'mouseenter') vars.lockWheel = true; 8059 else vars.lockWheel = false;
8060 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 8061 var t = $(this); 8062 8063 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 8064 else if (t.hasClass('ilightbox-play')) { 8065 iL.resume(); 8066 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 8067 } else if (t.hasClass('ilightbox-pause')) { 8068 iL.pause(); 8069 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 8070 } else iL.closeAction(); 8071 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 8072 // prevent scrolling 8073 e.preventDefault(); 8074 }); 8075 8076 function mouseMoveHandler(e) { 8077 if (!vars.isMobile) { 8078 if (!vars.mouseID) { 8079 vars.hideableElements.show(); 8080 } 8081 8082 vars.mouseID = clearTimeout(vars.mouseID); 8083 8084 if (buttonsArray.indexOf(e.target) === -1) 8085 vars.mouseID = setTimeout(function() { 8086 vars.hideableElements.hide(); 8087 vars.mouseID = clearTimeout(vars.mouseID); 8088 }, 3000); 8089 } 8090 } 8091 8092 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 8093 8094 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 8095 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 8096 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 8097 }); 8098 8099 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'); 8100 8101 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 8102 if (!vars.lockWheel) { 8103 event.preventDefault(); 8104 if (delta < 0) iL.moveTo('next'); 8105 else if (delta > 0) iL.moveTo('prev'); 8106 } 8107 }); 8108 8109 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 8110 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 8111 8112 vars.BODY.addClass('ilightbox-closedhand'); 8113 8114 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 8115 scrollTop = $doc.scrollTop(), 8116 scrollLeft = $doc.scrollLeft(), 8117 offsets = [ 8118 holders.eq(0).offset(), 8119 holders.eq(1).offset(), 8120 holders.eq(2).offset() 8121 ], 8122 offSet = [{ 8123 top: offsets[0].top - scrollTop, 8124 left: offsets[0].left - scrollLeft 8125 }, { 8126 top: offsets[1].top - scrollTop, 8127 left: offsets[1].left - scrollLeft 8128 }, { 8129 top: offsets[2].top - scrollTop, 8130 left: offsets[2].left - scrollLeft 8131 }], 8132 start = { 8133 time: (new Date()).getTime(), 8134 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8135 }, 8136 stop; 8137 8138 function moveEachHandler(i) { 8139 var t = $(this), 8140 offset = offSet[i], 8141 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 8142 8143 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 8144 } 8145 8146 function moveHandler(event) { 8147 8148 if (!start) return; 8149 8150 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 8151 8152 stop = { 8153 time: (new Date()).getTime(), 8154 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 8155 }; 8156 8157 holders.each(moveEachHandler); 8158 8159 // prevent scrolling 8160 event.preventDefault(); 8161 } 8162 8163 function repositionHolders() { 8164 holders.each(function() { 8165 var t = $(this), 8166 offset = t.data('offset') || { 8167 top: t.offset().top - scrollTop, 8168 left: t.offset().left - scrollLeft 8169 }, 8170 top = offset.top, 8171 left = offset.left; 8172 8173 t.css(transform, gpuAcceleration).stop().animate({ 8174 top: top, 8175 left: left 8176 }, 500, 'easeOutCirc', function() { 8177 t.css(transform, ''); 8178 }); 8179 }); 8180 } 8181 8182 holders.bind(touchMoveEvent, moveHandler); 8183 $doc.one(touchStopEvent, function(event) { 8184 holders.unbind(touchMoveEvent, moveHandler); 8185 8186 vars.BODY.removeClass('ilightbox-closedhand'); 8187 8188 if (start && stop) { 8189 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 8190 if (start.coords[0] > stop.coords[0]) { 8191 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8192 else { 8193 vars.isSwipe = true; 8194 iL.moveTo('next'); 8195 } 8196 } else { 8197 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8198 else { 8199 vars.isSwipe = true; 8200 iL.moveTo('prev'); 8201 } 8202 } 8203 } 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) { 8204 if (start.coords[1] > stop.coords[1]) { 8205 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 8206 else { 8207 vars.isSwipe = true; 8208 iL.moveTo('next'); 8209 } 8210 } else { 8211 if (vars.current == 0 && !opts.infinite) repositionHolders(); 8212 else { 8213 vars.isSwipe = true; 8214 iL.moveTo('prev'); 8215 } 8216 } 8217 } else repositionHolders(); 8218 } 8219 start = stop = undefined; 8220 }); 8221 }); 8222 8223 }, 8224 8225 goTo: function(index) { 8226 var iL = this, 8227 vars = iL.vars, 8228 opts = iL.options, 8229 diff = (index - vars.current); 8230 8231 if (opts.infinite) { 8232 if (index == vars.total - 1 && vars.current == 0) diff = -1; 8233 if (vars.current == vars.total - 1 && index == 0) diff = 1; 8234 } 8235 8236 if (diff == 1) iL.moveTo('next'); 8237 else if (diff == -1) iL.moveTo('prev'); 8238 else { 8239 8240 if (vars.nextLock || vars.prevLock) return false;
8241 8242 //Trigger the onBeforeChange callback 8243 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 8244 8245 if (opts.linkId) { 8246 vars.hashLock = true; 8247 window.location.hash = opts.linkId + '/' + index; 8248 } 8249 8250 if (iL.items[index]) { 8251 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 8252 else iL.vars.lockWheel = false; 8253 8254 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 8255 else vars.lockSwipe = false; 8256 } 8257 8258 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 8259 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 8260 }); 8261 8262 vars.current = index; 8263 vars.next = index + 1; 8264 vars.prev = index - 1; 8265 8266 iL.createUI(); 8267 8268 setTimeout(function() { 8269 iL.generateBoxes(); 8270 }, opts.effects.loadedFadeSpeed + 50); 8271 8272 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 8273 iL.positionThumbnails(); 8274 8275 if (opts.linkId) setTimeout(function() { 8276 vars.hashLock = false; 8277 }, 55); 8278 8279 // Configure arrow buttons 8280 if (!opts.infinite) { 8281 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8282 8283 if (vars.current == 0) { 8284 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8285 } 8286 if (vars.current >= vars.total - 1) { 8287 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8288 } 8289 } 8290 8291 // Reset next cycle timeout 8292 iL.resetCycle(); 8293 8294 //Trigger the onAfterChange callback 8295 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 8296 } 8297 }, 8298 8299 moveTo: function(side) { 8300 var iL = this, 8301 vars = iL.vars, 8302 opts = iL.options, 8303 path = opts.path.toLowerCase(), 8304 viewport = getViewport(), 8305 switchSpeed = opts.effects.switchSpeed; 8306 8307 if (vars.nextLock || vars.prevLock) return false; 8308 else { 8309 8310 var item = (side == "next") ? vars.next : vars.prev; 8311 8312 if (opts.linkId) { 8313 vars.hashLock = true; 8314 window.location.hash = opts.linkId + '/' + item; 8315 } 8316 8317 if (side == "next") { 8318 if (!iL.items[item]) return false; 8319 var firstHolder = vars.nextPhoto, 8320 secondHolder = vars.holder, 8321 lastHolder = vars.prevPhoto, 8322 firstClass = 'ilightbox-prev', 8323 secondClass = 'ilightbox-next'; 8324 } else if (side == "prev") { 8325 if (!iL.items[item]) return false; 8326 var firstHolder = vars.prevPhoto, 8327 secondHolder = vars.holder, 8328 lastHolder = vars.nextPhoto, 8329 firstClass = 'ilightbox-next', 8330 secondClass = 'ilightbox-prev'; 8331 } 8332 8333 //Trigger the onBeforeChange callback 8334 if (typeof opts.callback.onBeforeChange == 'function') 8335 opts.callback.onBeforeChange.call(iL, iL.ui); 8336 8337 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 8338 8339 var captionFirst = $('div.ilightbox-caption', secondHolder), 8340 socialFirst = $('div.ilightbox-social', secondHolder); 8341 8342 if (captionFirst.length) 8343 captionFirst.stop().fadeOut(switchSpeed, function() { 8344 $(this).remove(); 8345 }); 8346 if (socialFirst.length) 8347 socialFirst.stop().fadeOut(switchSpeed, function() { 8348 $(this).remove(); 8349 }); 8350 8351 if (iL.items[item].caption) { 8352 iL.setCaption(iL.items[item], firstHolder); 8353 var caption = $('div.ilightbox-caption', firstHolder), 8354 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 8355 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 8356 } 8357 8358 var social = iL.items[item].options.social; 8359 if (social) { 8360 iL.setSocial(social, iL.items[item].URL, firstHolder); 8361 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 8362 } 8363 8364 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 8365 val.removeClass('ilightbox-next ilightbox-prev'); 8366 }); 8367 8368 var firstOffset = firstHolder.data('offset'), 8369 winW = (viewport.width - (opts.styles.pageOffsetX)), 8370 winH = (viewport.height - (opts.styles.pageOffsetY)), 8371 width = firstOffset.newDims.width, 8372 height = firstOffset.newDims.height, 8373 thumbsOffset = firstOffset.thumbsOffset, 8374 diff = firstOffset.diff, 8375 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 8376 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8377 8378 firstHolder.css(transform, gpuAcceleration).animate({ 8379 top: top, 8380 left: left, 8381 opacity: 1 8382 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8383 firstHolder.css(transform, ''); 8384 }); 8385 8386 $('div.ilightbox-container', firstHolder).animate({ 8387 width: width, 8388 height: height 8389 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8390 8391 var secondOffset = secondHolder.data('offset'), 8392 object = secondOffset.object; 8393 8394 diff = secondOffset.diff; 8395 8396 width = secondOffset.newDims.width, 8397 height = secondOffset.newDims.height; 8398 8399 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8400 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 8401 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 8402 8403 if (side == 'prev') 8404 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 8405 else { 8406 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 8407 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 8408 } 8409 8410 $('div.ilightbox-container', secondHolder).animate({ 8411 width: width, 8412 height: height 8413 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 8414 8415 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 8416 top: top, 8417 left: left, 8418 opacity: opts.styles.prevOpacity 8419 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8420 secondHolder.css(transform, ''); 8421
8422 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 8423 iL.positionThumbnails(); 8424 8425 if (iL.items[item]) { 8426 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 8427 else vars.lockWheel = false; 8428 8429 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 8430 else vars.lockSwipe = false; 8431 } 8432 8433 vars.isSwipe = false; 8434 8435 if (side == "next") { 8436 vars.nextPhoto = lastHolder, 8437 vars.prevPhoto = secondHolder, 8438 vars.holder = firstHolder; 8439 8440 vars.nextPhoto.hide(); 8441 8442 vars.next = vars.next + 1, 8443 vars.prev = vars.current, 8444 vars.current = vars.current + 1; 8445 8446 if (opts.infinite) { 8447 if (vars.current > vars.total - 1) vars.current = 0; 8448 if (vars.current == vars.total - 1) vars.next = 0; 8449 if (vars.current == 0) vars.prev = vars.total - 1; 8450 } 8451 8452 iL.createUI(); 8453 8454 if (!iL.items[vars.next]) 8455 vars.nextLock = false; 8456 else 8457 iL.loadContent(iL.items[vars.next], 'next'); 8458 } else { 8459 vars.prevPhoto = lastHolder; 8460 vars.nextPhoto = secondHolder; 8461 vars.holder = firstHolder; 8462 8463 vars.prevPhoto.hide(); 8464 8465 vars.next = vars.current; 8466 vars.current = vars.prev; 8467 vars.prev = vars.current - 1; 8468 8469 if (opts.infinite) { 8470 if (vars.current == vars.total - 1) vars.next = 0; 8471 if (vars.current == 0) vars.prev = vars.total - 1; 8472 } 8473 8474 iL.createUI(); 8475 8476 if (!iL.items[vars.prev]) 8477 vars.prevLock = false; 8478 else 8479 iL.loadContent(iL.items[vars.prev], 'prev'); 8480 } 8481 8482 if (opts.linkId) setTimeout(function() { 8483 vars.hashLock = false; 8484 }, 55); 8485 8486 // Configure arrow buttons 8487 if (!opts.infinite) { 8488 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 8489 8490 if (vars.current == 0) 8491 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 8492 if (vars.current >= vars.total - 1) 8493 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 8494 } 8495 8496 iL.repositionPhoto(); 8497 8498 // Reset next cycle timeout 8499 iL.resetCycle(); 8500 8501 //Trigger the onAfterChange callback 8502 if (typeof opts.callback.onAfterChange == 'function') 8503 opts.callback.onAfterChange.call(iL, iL.ui); 8504 }); 8505 8506 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 8507 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 8508 8509 lastHolder.css(transform, gpuAcceleration).animate({ 8510 top: top, 8511 left: left, 8512 opacity: opts.styles.nextOpacity 8513 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 8514 lastHolder.css(transform, ''); 8515 }).addClass(secondClass); 8516 8517 } 8518 }, 8519 8520 setCaption: function(obj, target) { 8521 var iL = this, 8522 caption = $('<div class="ilightbox-caption"></div>'); 8523 8524 if (obj.caption) { 8525 caption.html(obj.caption); 8526 $('div.ilightbox-container', target).append(caption); 8527 } 8528 }, 8529 8530 normalizeSocial: function(obj, url) { 8531 var iL = this, 8532 vars = iL.vars, 8533 opts = iL.options, 8534 baseURL = window.location.href; 8535 8536 $.each(obj, function(key, value) { 8537 if (!value) 8538 return true; 8539 8540 var item = key.toLowerCase(), 8541 source, text; 8542 8543 switch (item) { 8544 case 'facebook': 8545 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 8546 text = "Share on Facebook"; 8547 break; 8548 case 'twitter': 8549 source = "http://twitter.com/home?status={URL}", 8550 text = "Share on Twitter"; 8551 break; 8552 case 'googleplus': 8553 source = "https://plus.google.com/share?url={URL}", 8554 text = "Share on Google+"; 8555 break; 8556 case 'delicious': 8557 source = "http://delicious.com/post?url={URL}", 8558 text = "Share on Delicious"; 8559 break; 8560 case 'digg': 8561 source = "http://digg.com/submit?phase=2&url={URL}", 8562 text = "Share on Digg"; 8563 break; 8564 case 'reddit': 8565 source = "http://reddit.com/submit?url={URL}", 8566 text = "Share on reddit"; 8567 break; 8568 } 8569 8570 obj[key] = { 8571 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 8572 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 8573 text: value.text || text || "Share on " + key, 8574 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 8575 height: value.height || 360 8576 }; 8577 8578 }); 8579 8580 return obj; 8581 }, 8582 8583 setSocial: function(obj, url, target) { 8584 var iL = this, 8585 socialBar = $('<div class="ilightbox-social"></div>'), 8586 buttons = '<ul>'; 8587 8588 obj = iL.normalizeSocial(obj, url); 8589 8590 $.each(obj, function(key, value) { 8591 var item = key.toLowerCase(), 8592 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, '+')); 8593 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>'; 8594 }); 8595 8596 buttons += '</ul>'; 8597 8598 socialBar.html(buttons); 8599 $('div.ilightbox-container', target).append(socialBar); 8600 }, 8601 8602 fullScreenAction: function() { 8603 var iL = this, 8604 vars = iL.vars; 8605 8606 if (fullScreenApi.supportsFullScreen) { 8607 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 8608 else fullScreenApi.requestFullScreen(document.documentElement); 8609 } else { 8610 iL.doFullscreen(); 8611 } 8612 }, 8613 8614 doFullscreen: function() { 8615 var iL = this, 8616 vars = iL.vars, 8617 viewport = getViewport(), 8618 opts = iL.options; 8619 8620 if (opts.fullAlone) { 8621 var currentHolder = vars.holder, 8622 current = iL.items[vars.current], 8623 windowWidth = viewport.width, 8624 windowHeight = viewport.height, 8625 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 8626 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8627 8628 if (!vars.isInFullScreen) { 8629 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 8630 vars.overlay.css({ 8631 opacity: 1 8632 }); 8633 8634 $.each(hideElements, function(i, element) { 8635 element.hide(); 8636 }); 8637 8638 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 8639 8640 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8641 naturalWidthOld: currentHolder.data('naturalWidth'), 8642 naturalHeightOld: currentHolder.data('naturalHeight'), 8643 naturalWidth: windowWidth, 8644 naturalHeight: windowHeight 8645 }); 8646 else { 8647 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 8648 newWidth = windowWidth, 8649 newHeight = windowHeight, 8650 width = currentHolder.data('naturalWidth'), 8651 height = currentHolder.data('naturalHeight'); 8652 8653 if (viewport.toLowerCase() == 'fill') { 8654 newHeight = (newWidth / width) * height; 8655 8656 if (newHeight < windowHeight) { 8657 newWidth = (windowHeight / height) * width, 8658 newHeight = windowHeight; 8659 } 8660 } else if (viewport.toLowerCase() == 'fit') { 8661 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 8662 8663 newWidth = dims.width, 8664 newHeight = dims.height; 8665 } else if (viewport.toLowerCase() == 'stretch') { 8666 newWidth = newWidth, 8667 newHeight = newHeight; 8668 } else { 8669 var scale = (width > newWidth || height > newHeight) ? true : false, 8670 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 8671 newWidth = dims.width, 8672 newHeight = dims.height; 8673 } 8674 8675 currentHolder.data({ 8676 naturalWidthOld: currentHolder.data('naturalWidth'), 8677 naturalHeightOld: currentHolder.data('naturalHeight'), 8678 naturalWidth: newWidth, 8679 naturalHeight: newHeight 8680 }); 8681 } 8682 8683 $.each(elements, function(key, val) { 8684 val.addClass('ilightbox-fullscreen'); 8685 }); 8686 8687 //Trigger the onEnterFullScreen callback 8688 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 8689 } else { 8690 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 8691 vars.overlay.css({ 8692 opacity: iL.options.overlay.opacity 8693 }); 8694 8695 $.each(hideElements, function(i, element) { 8696 element.show(); 8697 }); 8698 8699 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 8700 8701 currentHolder.data({ 8702 naturalWidth: currentHolder.data('naturalWidthOld'), 8703 naturalHeight: currentHolder.data('naturalHeightOld'), 8704 naturalWidthOld: null, 8705 naturalHeightOld: null 8706 }); 8707 8708 $.each(elements, function(key, val) { 8709 val.removeClass('ilightbox-fullscreen'); 8710 }); 8711 8712 //Trigger the onExitFullScreen callback 8713 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 8714 } 8715 } else { 8716 if (!vars.isInFullScreen) vars.isInFullScreen = true; 8717 else vars.isInFullScreen = false; 8718 } 8719 iL.repositionPhoto(true); 8720 }, 8721 8722 closeAction: function() { 8723 var iL = this, 8724 vars = iL.vars, 8725 opts = iL.options; 8726 8727 $win.unbind('.iLightBox'); 8728 $doc.off('.iLightBox'); 8729 8730 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 8731 8732 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 8733 8734 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 8735 vars.overlay.remove(); 8736 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8737 }); 8738 else { 8739 vars.overlay.remove(); 8740 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 8741 } 8742 8743 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 8744 8745 $.each(fadeOuts, function(i, element) { 8746 element.removeAttr('style').remove(); 8747 }); 8748 8749 vars.dontGenerateThumbs = vars.isInFullScreen = false; 8750 8751 window.iLightBox = null; 8752 8753 if (opts.linkId) { 8754 vars.hashLock = true; 8755 removeHash(); 8756 setTimeout(function() { 8757 vars.hashLock = false; 8758 }, 55); 8759 } 8760 8761 //Trigger the onHide callback 8762 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 8763 }, 8764 8765 repositionPhoto: function() { 8766 var iL = this, 8767 vars = iL.vars, 8768 opts = iL.options, 8769 path = opts.path.toLowerCase(), 8770 viewport = getViewport(), 8771 winWidth = viewport.width, 8772 winHeight = viewport.height; 8773 8774 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 8775 8776 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 8777 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 8778 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 8779 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 8780 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, 8781 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))); 8782 8783 var elObject = { 8784 type: 'current', 8785 width: width, 8786 height: height, 8787 item: iL.items[vars.current], 8788 offsetW: offsetW, 8789 offsetH: offsetH,
8790 thumbsOffsetW: thumbsOffsetW, 8791 thumbsOffsetH: thumbsOffsetH, 8792 animate: arguments.length, 8793 holder: vars.holder 8794 }; 8795 8796 iL.repositionEl(elObject); 8797 if (iL.items[vars.next]) { 8798 elObject = $.extend(elObject, { 8799 type: 'next', 8800 item: iL.items[vars.next], 8801 offsetX: (viewport.width > UNCODE.mediaQuery) ? opts.styles.nextOffsetX : 0, 8802 offsetY: opts.styles.nextOffsetY, 8803 holder: vars.nextPhoto 8804 }); 8805 8806 iL.repositionEl(elObject); 8807 } 8808 8809 if (iL.items[vars.prev]) { 8810 elObject = $.extend(elObject, { 8811 type: 'prev', 8812 item: iL.items[vars.prev], 8813 offsetX: (viewport.width > UNCODE.mediaQuery) ? opts.styles.prevOffsetX : 0, 8814 offsetY: opts.styles.prevOffsetY, 8815 holder: vars.prevPhoto 8816 }); 8817 8818 iL.repositionEl(elObject); 8819 } 8820 8821 var loaderCss = (path == "horizontal") ? { 8822 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 8823 } : { 8824 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 8825 }; 8826 vars.loader.css(loaderCss); 8827 }, 8828 8829 repositionEl: function(obj) { 8830 var iL = this, 8831 vars = iL.vars, 8832 opts = iL.options, 8833 path = opts.path.toLowerCase(), 8834 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 8835 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 8836 itemParent = obj.item, 8837 item = obj.item.options, 8838 holder = obj.holder, 8839 offsetX = obj.offsetX || 0, 8840 offsetY = obj.offsetY || 0, 8841 thumbsOffsetW = obj.thumbsOffsetW, 8842 thumbsOffsetH = obj.thumbsOffsetH; 8843 8844 if (obj.type == 'current') { 8845 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); 8846 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); 8847 } else { 8848 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 8849 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 8850 } 8851 8852 heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 8853 8854 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 8855 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 8856 8857 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 8858 width: width, 8859 height: height 8860 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 8861 newDims = $.extend({}, dims, {}); 8862 8863 if (obj.type == 'prev' || obj.type == 'next') 8864 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 8865 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 8866 else 8867 width = dims.width, 8868 height = dims.height; 8869 8870 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 8871 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()) / 2); 8872 8873 switch (obj.type) { 8874 case 'current': 8875 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 8876 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8877 break; 8878
8879 case 'next': 8880 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 8881 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 8882 break; 8883 8884 case 'prev': 8885 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 8886 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 8887 break; 8888 } 8889 8890 holder.data('offset', { 8891 top: top, 8892 left: left, 8893 newDims: newDims, 8894 diff: { 8895 W: widthDiff, 8896 H: heightDiff 8897 }, 8898 thumbsOffset: { 8899 W: thumbsOffsetW, 8900 H: thumbsOffsetH 8901 }, 8902 object: obj 8903 }); 8904 8905 if (obj.animate > 0 && opts.effects.reposition) { 8906 holder.css(transform, gpuAcceleration).stop().animate({ 8907 top: top, 8908 left: left 8909 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 8910 holder.css(transform, ''); 8911 }); 8912 $('div.ilightbox-container', holder).stop().animate({ 8913 width: width, 8914 height: height 8915 }, opts.effects.repositionSpeed, 'easeOutCirc'); 8916 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 8917 width: width 8918 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 8919 $(this).css('overflow', 'visible'); 8920 }); 8921 } else { 8922 holder.css({ 8923 top: top, 8924 left: left 8925 }); 8926 $('div.ilightbox-container', holder).css({ 8927 width: width, 8928 height: height 8929 }); 8930 $('div.ilightbox-inner-toolbar', holder).css({ 8931 width: width 8932 }); 8933 } 8934 }, 8935 8936 resume: function(priority) { 8937 var iL = this, 8938 vars = iL.vars, 8939 opts = iL.options; 8940 8941 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 8942 return; 8943 } 8944 8945 vars.isPaused = 0; 8946 8947 if (vars.cycleID) { 8948 vars.cycleID = clearTimeout(vars.cycleID); 8949 } 8950 8951 vars.cycleID = setTimeout(function() { 8952 if (vars.current == vars.total - 1) iL.goTo(0); 8953 else iL.moveTo('next'); 8954 }, opts.slideshow.pauseTime); 8955 }, 8956 8957 pause: function(priority) { 8958 var iL = this, 8959 vars = iL.vars, 8960 opts = iL.options; 8961 8962 if (priority < vars.isPaused) { 8963 return; 8964 } 8965 8966 vars.isPaused = priority || 100; 8967 8968 if (vars.cycleID) { 8969 vars.cycleID = clearTimeout(vars.cycleID); 8970 } 8971 }, 8972 8973 resetCycle: function() { 8974 var iL = this, 8975 vars = iL.vars, 8976 opts = iL.options; 8977 8978 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 8979 iL.resume(); 8980 } 8981 }, 8982 8983 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 8984 var iL = this; 8985 8986 if (!width) factor = height / height_old; 8987 else if (!height) factor = width / width_old; 8988 else factor = min(width / width_old, height / height_old); 8989 8990 if (!thumb) { 8991 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 8992 else if (factor < iL.options.minScale) factor = iL.options.minScale; 8993 } 8994 8995 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 8996 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 8997 8998 return { 8999 width: final_width, 9000 height: final_height, 9001 ratio: factor 9002 }; 9003 }, 9004 9005 setOption: function(options) { 9006 var iL = this; 9007 9008 iL.options = $.extend(true, iL.options, options || {}); 9009 iL.refresh(); 9010 }, 9011 9012 availPlugins: function() { 9013 var iL = this, 9014 testEl = document.createElement("video"); 9015 9016 iL.plugins = { 9017 flash: false, 9018 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 9019 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 9020 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 9021 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 9022 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 9023 }; 9024 }, 9025 9026 addContent: function(element, obj) { 9027 var iL = this, 9028 el; 9029 9030 switch (obj.type) { 9031 case 'video': 9032 var HTML5 = false, 9033 videoType = obj.videoType, 9034 html5video = obj.options.html5video; 9035 9036 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 9037 obj.ext = 'mp4', 9038 obj.URL = html5video.h264 || obj.URL; 9039 else if (html5video.webm && iL.plugins.html5WebM) 9040 obj.ext = 'webm', 9041 obj.URL = html5video.webm || obj.URL; 9042 else if (html5video.ogg && iL.plugins.html5Vorbis) 9043 obj.ext = 'ogv', 9044 obj.URL = html5video.ogg || obj.URL; 9045 9046 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 9047 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 9048 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 9049 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 9050 9051 if (HTML5) { 9052 el = $('<video />
9052', { 9053 "width": "100%", 9054 "height": "100%", 9055 "preload": html5video.preload, 9056 "autoplay": html5video.autoplay, 9057 "poster": html5video.poster, 9058 "controls": html5video.controls 9059 }).append($('<source />', { 9060 "src": obj.URL, 9061 "type": videoType 9062 })); 9063 } else { 9064 if (!iL.plugins.quicktime) el = $('<span />', { 9065 "class": "ilightbox-alert", 9066 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 9067 }); 9068 else { 9069 9070 el = $('<object />', { 9071 "type": "video/quicktime", 9072 "pluginspage": pluginspages.quicktime 9073 }).attr({ 9074 "data": obj.URL, 9075 "width": "100%", 9076 "height": "100%" 9077 }).append($('<param />', { 9078 "name": "src", 9079 "value": obj.URL 9080 })).append($('<param />', { 9081 "name": "autoplay", 9082 "value": "false" 9083 })).append($('<param />', { 9084 "name": "loop", 9085 "value": "false" 9086 })).append($('<param />', { 9087 "name": "scale", 9088 "value": "tofit" 9089 })); 9090 9091 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 9092 } 9093 } 9094 9095 break; 9096 9097 case 'flash': 9098 if (!iL.plugins.flash) el = $('<span />', { 9099 "class": "ilightbox-alert", 9100 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 9101 }); 9102 else { 9103 var flashvars = "", 9104 i = 0; 9105 9106 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 9107 if (i != 0) flashvars += "&"; 9108 flashvars += k + "=" + encodeURIComponent(v); 9109 i++; 9110 }); 9111 else flashvars = null; 9112 9113 el = $('<embed />').attr({ 9114 "type": "application/x-shockwave-flash", 9115 "src": obj.URL, 9116 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9117 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9118 "quality": "high", 9119 "bgcolor": "#000000", 9120 "play": "true", 9121 "loop": "true", 9122 "menu": "true", 9123 "wmode": "transparent", 9124 "scale": "showall", 9125 "allowScriptAccess": "always", 9126 "allowFullScreen": "true", 9127 "flashvars": flashvars, 9128 "fullscreen": "yes" 9129 }); 9130 } 9131 9132 break; 9133 9134 case 'iframe': 9135 el = $('<iframe />').attr({ 9136 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 9137 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 9138 src: obj.URL, 9139 frameborder: 0, 9140 'hspace': 0, 9141 'vspace': 0, 9142 'scrolling': supportTouch ? 'auto' : 'scroll', 9143 'webkitAllowFullScreen': '', 9144 'mozallowfullscreen': '', 9145 'allowFullScreen': '' 9146 }); 9147 9148 break; 9149 9150 case 'inline': 9151 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 9152 9153 break; 9154 9155 case 'html': 9156 var object = obj.URL, 9157 el; 9158 9159 if (object[0].nodeName) { 9160 el = $('<div class="ilightbox-wrapper"></div>').html(object); 9161 } else { 9162 var dom = $(obj.URL), 9163 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 9164 el = $('<div class="ilightbox-wrapper"></div>').html(html); 9165 } 9166 9167 break; 9168 } 9169 9170 $('div.ilightbox-container', element).empty().html(el); 9171 9172 // For fixing Chrome about just playing the video for first time 9173 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 9174 var src = el[0].currentSrc + '?' + floor(random() * 30000); 9175 el[0].currentSrc = src; 9176 el[0].src = src; 9177 }); 9178 9179 return el; 9180 }, 9181 9182 ogpRecognition: function(obj, callback) { 9183 var iL = this, 9184 url = obj.URL; 9185 9186 iL.showLoader(); 9187 doAjax(url, function(data) { 9188 iL.hideLoader(); 9189 9190 if (data) { 9191 var object = new Object(); 9192 9193 object.length = false, 9194 object.url = data.url; 9195 9196 if (data.status == 200) { 9197 var result = data.results, 9198 type = result.type, 9199 source = result.source; 9200 9201 object.source = source.src, 9202 object.width = source.width && parseInt(source.width) || 0, 9203 object.height = source.height && parseInt(source.height) || 0, 9204 object.type = type, 9205 object.thumbnail = source.thumbnail || result.images[0], 9206 object.html5video = result.html5video || {}, 9207 object.length = true; 9208 9209 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 9210 else if (source.type.indexOf("video/") != -1) object.type = "video"; 9211 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 9212 else if (source.type.indexOf("image/") != -1) object.type = "image"; 9213 9214 } else if (typeof data.response != 'undefined') 9215 throw data.response; 9216 9217 callback.call(this, object.length ? object : false); 9218 } 9219 }); 9220 }, 9221 9222 hashChangeHandler: function(url) { 9223 var iL = this, 9224 vars = iL.vars, 9225 opts = iL.options, 9226 URL = url || window.location.href, 9227 hash = parseURI(URL).hash, 9228 split = hash.split('/'), 9229 index = split[1]; 9230 9231 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 9232 9233 if (index) { 9234 var target = split[1] || 0; 9235 if (iL.items[target]) {
9236 var overlay = $('.ilightbox-overlay'); 9237 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 9238 iL.goTo(target); 9239 } else { 9240 iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click'); 9241 } 9242 } else { 9243 var overlay = $('.ilightbox-overlay'); 9244 if (overlay.length) iL.closeAction(); 9245 } 9246 } else { 9247 var overlay = $('.ilightbox-overlay'); 9248 if (overlay.length) iL.closeAction(); 9249 } 9250 } 9251 }; 9252 9253 /** 9254 * Parse style to pixels. 9255 * 9256 * @param {Object} $element jQuery object with element. 9257 * @param {Property} property CSS property to get the pixels from. 9258 * 9259 * @return {Int} 9260 */ 9261 function getPixel($element, property) { 9262 return parseInt($element.css(property), 10) || 0; 9263 } 9264 9265 /** 9266 * Make sure that number is within the limits. 9267 * 9268 * @param {Number} number 9269 * @param {Number} min 9270 * @param {Number} max 9271 * 9272 * @return {Number} 9273 */ 9274 function within(number, min, max) { 9275 return number < min ? min : number > max ? max : number; 9276 } 9277 9278 /** 9279 * Get viewport/window size (width and height). 9280 * 9281 * @return {Object} 9282 */ 9283 function getViewport() { 9284 var e = window, 9285 a = 'inner'; 9286 if (!('innerWidth' in window)) { 9287 a = 'client'; 9288 e = document.documentElement || document.body; 9289 } 9290 return { 9291 width: e[a + 'Width'], 9292 height: e[a + 'Height'] 9293 } 9294 } 9295 9296 /** 9297 * Remove hash tag from the URL 9298 * 9299 * @return {Void} 9300 */ 9301 function removeHash() { 9302 var scroll = getScrollXY(); 9303 9304 window.location.hash = ""; 9305 9306 // Restore the scroll offset, should be flicker free 9307 window.scrollTo(scroll.x, scroll.y); 9308 } 9309 9310 /** 9311 * Do the ajax requests with callback. 9312 * 9313 * @param {String} url 9314 * @param {Function} callback 9315 * 9316 * @return {Void} 9317 */ 9318 function doAjax(url, callback) { 9319 var url = "http://ilightbox.net/getSource/jsonp.php?url=" + encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A'); 9320 $.ajax({ 9321 url: url, 9322 dataType: 'jsonp' 9323 }); 9324 9325 iLCallback = function(data) { 9326 callback.call(this, data); 9327 }; 9328 } 9329 9330 /** 9331 * Find image from DOM elements 9332 * 9333 * @param {Element} element 9334 * 9335 * @return {Void} 9336 */ 9337 function findImageInElement(element) { 9338 var elements = $('*', element), 9339 imagesArr = new Array(); 9340 9341 elements.each(function() { 9342 var url = "", 9343 element = this; 9344 9345 if ($(element).css("background-image") != "none") { 9346 url = $(element).css("background-image"); 9347 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 9348 url = $(element).attr("src"); 9349 } 9350 9351 if (url.indexOf("gradient") == -1) { 9352 url = url.replace(/url\(\"/g, ""); 9353 url = url.replace(/url\(/g, ""); 9354 url = url.replace(/\"\)/g, ""); 9355 url = url.replace(/\)/g, ""); 9356 9357 var urls = url.split(","); 9358 9359 for (var i = 0; i < urls.length; i++) { 9360 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 9361 var extra = ""; 9362 if (browser.msie && browser.version < 9) { 9363 extra = "?" + floor(random() * 3000); 9364 } 9365 imagesArr.push(urls[i] + extra); 9366 } 9367 } 9368 } 9369 }); 9370 9371 return imagesArr; 9372 } 9373 9374 /** 9375 * Get file extension. 9376 * 9377 * @param {String} URL 9378 * 9379 * @return {String} 9380 */ 9381 function getExtension(URL) { 9382 if (URL !== null) { 9383 var ext = URL.split('.').pop().toLowerCase(), 9384 extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : ''; 9385 9386 return ext.replace(extra, ''); 9387 } 9388 } 9389 9390 /** 9391 * Get type via extension. 9392 * 9393 * @param {String} URL 9394 * 9395 * @return {String} 9396 */ 9397 function getTypeByExtension(URL) { 9398 var type, 9399 ext = getExtension(URL); 9400 9401 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 9402 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 9403 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 9404 else type = 'iframe'; 9405 9406 return type; 9407 } 9408 9409 /** 9410 * Return value from percent of a number. 9411 * 9412 * @param {Number} percent 9413 * @param {Number} total 9414 * 9415 * @return {Number} 9416 */ 9417 function percentToValue(percent, total) { 9418 return parseInt((total / 100) * percent); 9419 } 9420 9421 /** 9422 * A JavaScript equivalent of PHP’s parse_url. 9423 * 9424 * @param {String} url The URL to parse. 9425 * 9426 * @return {Mixed} 9427 */ 9428 function parseURI(url) { 9429 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 9430 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 9431 return (m ? { 9432 href: m[0] || '', 9433 protocol: m[1] || '', 9434 authority: m[2] || '', 9435 host: m[3] || '', 9436 hostname: m[4] || '', 9437 port: m[5] || '', 9438 pathname: m[6] || '', 9439 search: m[7] || '', 9440 hash: m[8] || '' 9441 } : null); 9442 } 9443 9444 /** 9445 * Gets the absolute URI. 9446 * 9447 * @param {String} href The relative URL. 9448 * @param {String} base The base URL. 9449 * 9450 * @return {String} The absolute URL. 9451 */ 9452 function absolutizeURI(base, href) { // RFC 3986 9453 var iL = this; 9454 9455 function removeDotSegments(input) { 9456 var output = []; 9457 input.replace(/^(\.\.?(\/|$))+/, '') 9458 .replace(/\/(\.(\/|$))+/g, '/') 9459 .replace(/\/\.\.$/, '/../') 9460 .replace(/\/?[^\/]*/g, function(p) { 9461 if (p === '/..') { 9462 output.pop(); 9463 } else { 9464 output.push(p); 9465 } 9466 }); 9467 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 9468 } 9469 9470 href = parseURI(href || ''); 9471 base = parseURI(base || ''); 9472 9473 return !href || !base ? null : (href.protocol || base.protocol) + 9474 (href.protocol || href.authority ? href.authority : base.authority) + 9475 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)) + 9476 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 9477 href.hash; 9478 } 9479 9480 /** 9481 * A JavaScript equivalent of PHP’s version_compare. 9482 * 9483 * @param {String} v1 9484 * @param {String} v2 9485 * @param {String} operator
9486 * 9487 * @return {Boolean} 9488 */ 9489 function version_compare(v1, v2, operator) { 9490 this.php_js = this.php_js || {}; 9491 this.php_js.ENV = this.php_js.ENV || {}; 9492 var i = 0, 9493 x = 0, 9494 compare = 0, 9495 vm = { 9496 'dev': -6, 9497 'alpha': -5, 9498 'a': -5, 9499 'beta': -4, 9500 'b': -4, 9501 'RC': -3, 9502 'rc': -3, 9503 '#': -2, 9504 'p': 1, 9505 'pl': 1 9506 }, 9507 prepVersion = function(v) { 9508 v = ('' + v).replace(/[_\-+]/g, '.'); 9509 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 9510 return (!v.length ? [-8] : v.split('.')); 9511 }, 9512 numVersion = function(v) { 9513 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 9514 }; 9515 v1 = prepVersion(v1); 9516 v2 = prepVersion(v2); 9517 x = max(v1.length, v2.length); 9518 for (i = 0; i < x; i++) { 9519 if (v1[i] == v2[i]) { 9520 continue; 9521 } 9522 v1[i] = numVersion(v1[i]); 9523 v2[i] = numVersion(v2[i]); 9524 if (v1[i] < v2[i]) { 9525 compare = -1; 9526 break; 9527 } else if (v1[i] > v2[i]) { 9528 compare = 1; 9529 break; 9530 } 9531 } 9532 if (!operator) { 9533 return compare; 9534 } 9535 9536 switch (operator) { 9537 case '>': 9538 case 'gt': 9539 return (compare > 0); 9540 case '>=': 9541 case 'ge': 9542 return (compare >= 0); 9543 case '<=': 9544 case 'le': 9545 return (compare <= 0); 9546 case '==': 9547 case '=': 9548 case 'eq': 9549 return (compare === 0); 9550 case '<>': 9551 case '!=': 9552 case 'ne': 9553 return (compare !== 0); 9554 case '': 9555 case '<': 9556 case 'lt': 9557 return (compare < 0); 9558 default: 9559 return null; 9560 } 9561 } 9562 9563 9564 // Begin the iLightBox plugin 9565 $.fn.iLightBox = function() { 9566 9567 var args = arguments, 9568 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 9569 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 9570 9571 if (!opt) opt = {}; 9572 9573 // Default options. Play carefully. 9574 var options = $.extend(true, { 9575 attr: 'href', 9576 path: 'vertical', 9577 skin: 'dark', 9578 linkId: false, 9579 infinite: false, 9580 startFrom: 0, 9581 randomStart: false, 9582 keepAspectRatio: true, 9583 maxScale: 1, 9584 minScale: .2, 9585 innerToolbar: false, 9586 smartRecognition: false, 9587 mobileOptimizer: true, 9588 fullAlone: true, 9589 fullViewPort: null, 9590 fullStretchTypes: 'flash, video', 9591 overlay: { 9592 blur: true, 9593 opacity: .85 9594 }, 9595 controls: { 9596 arrows: false, 9597 slideshow: false, 9598 toolbar: true, 9599 fullscreen: true, 9600 thumbnail: true, 9601 keyboard: true, 9602 mousewheel: true, 9603 swipe: true 9604 }, 9605 keyboard: { 9606 left: true, // previous 9607 right: true, // next 9608 up: true, // previous 9609 down: true, // next 9610 esc: true, // close 9611 shift_enter: true // fullscreen 9612 }, 9613 show: { 9614 effect: true, 9615 speed: 300, 9616 title: true 9617 }, 9618 hide: { 9619 effect: true, 9620 speed: 300 9621 }, 9622 caption: { 9623 start: true, 9624 show: 'mouseenter', 9625 hide: 'mouseleave' 9626 }, 9627 social: { 9628 start: true, 9629 show: 'mouseenter', 9630 hide: 'mouseleave',
9631 buttons: false 9632 }, 9633 styles: { 9634 pageOffsetX: 0, 9635 pageOffsetY: 0, 9636 nextOffsetX: 45, 9637 nextOffsetY: 0, 9638 nextOpacity: 1, 9639 nextScale: 1, 9640 prevOffsetX: 45, 9641 prevOffsetY: 0, 9642 prevOpacity: 1, 9643 prevScale: 1 9644 }, 9645 thumbnails: { 9646 maxWidth: 120, 9647 maxHeight: 80, 9648 normalOpacity: 1, 9649 activeOpacity: .6 9650 }, 9651 effects: { 9652 reposition: true, 9653 repositionSpeed: 200, 9654 switchSpeed: 500, 9655 loadedFadeSpeed: 180, 9656 fadeSpeed: 200 9657 }, 9658 slideshow: { 9659 pauseTime: 5000, 9660 pauseOnHover: false, 9661 startPaused: true 9662 }, 9663 text: { 9664 close: "Press Esc to close", 9665 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 9666 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 9667 slideShow: "Slideshow", 9668 next: "Next", 9669 previous: "Previous" 9670 }, 9671 errors: { 9672 loadImage: "An error occurred when trying to load photo.", 9673 loadContents: "An error occurred when trying to load contents.", 9674 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 9675 }, 9676 ajaxSetup: { 9677 url: '', 9678 beforeSend: function(jqXHR, settings) {}, 9679 cache: false, 9680 complete: function(jqXHR, textStatus) {}, 9681 crossDomain: false, 9682 error: function(jqXHR, textStatus, errorThrown) {}, 9683 success: function(data, textStatus, jqXHR) {}, 9684 global: true, 9685 ifModified: false, 9686 username: null, 9687 password: null, 9688 type: 'GET' 9689 }, 9690 callback: {} 9691 }, opt); 9692 9693 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 9694 9695 items = $.isArray(items) ? items : new Array(); 9696 9697 if (typeof args[0] == 'string') items[0] = args[0]; 9698 9699 if (version_compare($.fn.jquery, '1.8', '>=')) { 9700 var iLB = new iLightBox($(this), options, items, instant); 9701 return { 9702 close: function() { 9703 iLB.closeAction(); 9704 }, 9705 fullscreen: function() { 9706 iLB.fullScreenAction(); 9707 }, 9708 moveNext: function() { 9709 iLB.moveTo('next'); 9710 }, 9711 movePrev: function() { 9712 iLB.moveTo('prev'); 9713 }, 9714 goTo: function(index) { 9715 iLB.goTo(index); 9716 }, 9717 refresh: function() { 9718 iLB.refresh(); 9719 }, 9720 reposition: function() { 9721 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 9722 }, 9723 setOption: function(options) { 9724 iLB.setOption(options); 9725 }, 9726 destroy: function() { 9727 iLB.closeAction(); 9728 iLB.dispatchItemsEvents(); 9729 } 9730 }; 9731 } else { 9732 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 9733 } 9734 9735 }; 9736 9737 9738 $.iLightBox = function() { 9739 return $.fn.iLightBox(arguments[0], arguments[1]); 9740 }; 9741 9742 9743 $.extend($.easing, { 9744 easeInCirc: function(x, t, b, c, d) { 9745 return -c * (sqrt(1 - (t /= d) * t) - 1) + b; 9746 }, 9747 easeOutCirc: function(x, t, b, c, d) { 9748 return c * sqrt(1 - (t = t / d - 1) * t) + b; 9749 }, 9750 easeInOutCirc: function(x, t, b, c, d) { 9751 if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; 9752 return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b; 9753 } 9754 }); 9755 9756 function getScrollXY() { 9757 var scrOfX = 0, 9758 scrOfY = 0; 9759 if (typeof(window.pageYOffset) == 'number') { 9760 //Netscape compliant 9761 scrOfY = window.pageYOffset; 9762 scrOfX = window.pageXOffset; 9763 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 9764 //DOM compliant 9765 scrOfY = document.body.scrollTop; 9766 scrOfX = document.body.scrollLeft; 9767 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 9768 //IE6 standards compliant mode 9769 scrOfY = document.documentElement.scrollTop; 9770 scrOfX = document.documentElement.scrollLeft; 9771 } 9772 return { 9773 x: scrOfX, 9774 y: scrOfY 9775 }; 9776 } 9777 9778 (function() { 9779 // add new event shortcuts 9780 $.each(("touchstart touchmove touchend " + 9781 "tap taphold " + 9782 "swipe swipeleft swiperight " + 9783 "scrollstart scrollstop").split(" "), function(i, name) { 9784 9785 $.fn[name] = function(fn) { 9786 return fn ? this.bind(name, fn) : this.trigger(name); 9787 }; 9788 9789 // jQuery < 1.8 9790 // if ($.attrFn) { 9791 // $.attrFn[name] = true; 9792 // } 9793 }); 9794 9795 var tapSettings = { 9796 startEvent: 'touchstart.iTap', 9797 endEvent: 'touchend.iTap' 9798 }; 9799 9800 // tap Event: 9801 $.event.special.itap = { 9802 setup: function() { 9803 9804 var self = this, 9805 $self = $(this), 9806 start, stop; 9807 9808 $self.bind(tapSettings.startEvent, function(event) { 9809 start = getScrollXY(); 9810 9811 $self.one(tapSettings.endEvent, function(event) { 9812 stop = getScrollXY(); 9813 9814 var orgEvent = event || window.event; 9815 event = $.event.fix(orgEvent); 9816 event.type = "itap"; 9817 9818 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 9819 9820 start = stop = undefined; 9821 }); 9822 }); 9823 }, 9824 9825 teardown: function() { 9826 $(this).unbind(tapSettings.startEvent); 9827 } 9828 }; 9829 }()); 9830 9831 9832 //Fullscreen API 9833 (function() { 9834 fullScreenApi = { 9835 supportsFullScreen: false, 9836 isFullScreen: function() { 9837 return false;
9838 }, 9839 requestFullScreen: function() {}, 9840 cancelFullScreen: function() {}, 9841 fullScreenEventName: '', 9842 prefix: '' 9843 }, 9844 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 9845 9846 // check for native support 9847 if (typeof document.cancelFullScreen != 'undefined') { 9848 fullScreenApi.supportsFullScreen = true; 9849 } else { 9850 // check for fullscreen support by vendor prefix 9851 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 9852 fullScreenApi.prefix = browserPrefixes[i]; 9853 9854 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 9855 fullScreenApi.supportsFullScreen = true; 9856 9857 break; 9858 } 9859 } 9860 } 9861 9862 // update methods to do something useful 9863 if (fullScreenApi.supportsFullScreen) { 9864 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 9865 9866 fullScreenApi.isFullScreen = function() { 9867 switch (this.prefix) { 9868 case '': 9869 return document.fullScreen; 9870 case 'webkit': 9871 return document.webkitIsFullScreen; 9872 default: 9873 return document[this.prefix + 'FullScreen']; 9874 } 9875 } 9876 fullScreenApi.requestFullScreen = function(el) { 9877 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 9878 } 9879 fullScreenApi.cancelFullScreen = function(el) { 9880 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 9881 } 9882 } 9883 }()); 9884 9885 // Browser detect 9886 (function() { 9887 function uaMatch(ua) { 9888 ua = ua.toLowerCase(); 9889 9890 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 9891 /(webkit)[ \/]([\w.]+)/.exec(ua) || 9892 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 9893 /(msie) ([\w.]+)/.exec(ua) || 9894 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 9895 9896 return { 9897 browser: match[1] || "", 9898 version: match[2] || "0" 9899 }; 9900 } 9901 9902 var matched = uaMatch(navigator.userAgent); 9903 browser = {}; 9904 9905 if (matched.browser) { 9906 browser[matched.browser] = true; 9907 browser.version = matched.version; 9908 } 9909 9910 // Chrome is Webkit, but Webkit is also Safari. 9911 if (browser.chrome) { 9912 browser.webkit = true; 9913 } else if (browser.webkit) { 9914 browser.safari = true; 9915 } 9916 }()); 9917 9918 // Feature detects 9919 (function() { 9920 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 9921 var el = document.createElement('div'); 9922 9923 function testProp(prop) { 9924 for (var p = 0, pl = prefixes.length; p < pl; p++) { 9925 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 9926 if (el.style[prefixedProp] !== undefined) { 9927 return prefixedProp; 9928 } 9929 } 9930 } 9931 9932 // Global support indicators 9933 transform = testProp('transform') || ''; 9934 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 9935 }()); 9936 9937 9938 /* 9939 PluginDetect v0.7.9 9940 www.pinlady.net/PluginDetect/license/ 9941 [ getVersion onWindowLoaded BetterIE ] 9942 [ Flash QuickTime Shockwave ] 9943 */ 9944 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;
9944d++){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);
9944d.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)}
9944c.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;
9944if(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(); 9945 9946 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)}; 9947 9948 9949 /* 9950 jQuery hashchange event v1.3 9951 https://github.com/cowboy/jquery-hashchange 9952 Copyright (c) 2010 "Cowboy" Ben Alman 9953 Dual licensed under the MIT and GPL licenses. 9954 */ 9955 (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= 9956 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|| 9957 "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;
9957a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 9958 9959 if (!Array.prototype.filter) { 9960 Array.prototype.filter = function(fun /*, thisp */ ) { 9961 "use strict"; 9962 9963 if (this == null) 9964 throw new TypeError(); 9965 9966 var t = Object(this); 9967 var len = t.length >>> 0; 9968 if (typeof fun != "function") 9969 throw new TypeError(); 9970 9971 var res = []; 9972 var thisp = arguments[1]; 9973 for (var i = 0; i < len; i++) { 9974 if (i in t) { 9975 var val = t[i]; // in case fun mutates this 9976 if (fun.call(thisp, val, i, t)) 9977 res.push(val); 9978 } 9979 } 9980 9981 return res; 9982 }; 9983 } 9984 9985 if (!Array.prototype.indexOf) { 9986 Array.prototype.indexOf = function(searchElement, fromIndex) { 9987 var k; 9988 9989 if (this == null) { 9990 throw new TypeError('"this" is null or not defined'); 9991 } 9992 9993 var O = Object(this); 9994 9995 var len = O.length >>> 0; 9996 9997 if (len === 0) { 9998 return -1; 9999 } 10000 10001 var n = +fromIndex || 0; 10002 10003 if (abs(n) === Infinity) { 10004 n = 0; 10005 } 10006 10007 if (n >= len) { 10008 return -1; 10009 } 10010 10011 k = max(n >= 0 ? n : len - abs(n), 0); 10012 10013 while (k < len) { 10014 var kValue; 10015 if (k in O && O[k] === searchElement) { 10016 return k; 10017 } 10018 k++; 10019 } 10020 return -1; 10021 }; 10022 } 10023 10024 if (!Array.prototype.lastIndexOf) { 10025 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 10026 "use strict"; 10027 10028 if (this == null) 10029 throw new TypeError(); 10030 10031 var t = Object(this); 10032 var len = t.length >>> 0; 10033 if (len === 0) 10034 return -1; 10035 10036 var n = len; 10037 if (arguments.length > 1) { 10038 n = Number(arguments[1]); 10039 if (n != n) 10040 n = 0; 10041 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 10042 n = (n > 0 || -1) * floor(abs(n)); 10043 } 10044 10045 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 10046 10047 for (; k >= 0; k--) { 10048 if (k in t && t[k] === searchElement) 10049 return k; 10050 } 10051 return -1; 10052 }; 10053 } 10054})(jQuery, this); 10055 10056 10057/** 10058 * Owl carousel
vendor: 25,822 bytes, lines 10059-11083
10059 * @version 2.0.0-beta.3 10060 * @author Bartosz Wojciechowski 10061 * @license The MIT License (MIT) 10062 * @todo Lazy Load Icon 10063 * @todo prevent animationend bubling 10064 * @todo itemsScaleUp 10065 * @todo Test Zepto 10066 * @todo stagePadding calculate wrong active classes 10067 */ 10068;(function($, window, document, undefined) { 10069 10070 /** 10071 * Creates a carousel. 10072 * @class The Owl Carousel. 10073 * @public 10074 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 10075 * @param {Object} [options] - The options 10076 */ 10077 function Owl(element, options) { 10078 10079 /** 10080 * Current settings for the carousel. 10081 * @public 10082 */ 10083 this.settings = null; 10084 10085 /** 10086 * Current options set by the caller including defaults. 10087 * @public 10088 */ 10089 this.options = $.extend({}, Owl.Defaults, options); 10090 10091 /** 10092 * Plugin element. 10093 * @public 10094 */ 10095 this.$element = $(element); 10096 10097 /** 10098 * Proxied event handlers. 10099 * @protected 10100 */ 10101 this._handlers = {}; 10102 10103 /** 10104 * References to the running plugins of this carousel. 10105 * @protected 10106 */ 10107 this._plugins = {}; 10108 10109 /** 10110 * Currently suppressed events to prevent them from beeing retriggered. 10111 * @protected 10112 */ 10113 this._supress = {}; 10114 10115 /** 10116 * Absolute current position. 10117 * @protected 10118 */ 10119 this._current = null; 10120 10121 /** 10122 * Animation speed in milliseconds. 10123 * @protected 10124 */ 10125 this._speed = null; 10126 10127 /** 10128 * Coordinates of all items in pixel. 10129 * @todo The name of this member is missleading. 10130 * @protected 10131 */ 10132 this._coordinates = []; 10133 10134 /** 10135 * Current breakpoint. 10136 * @todo Real media queries would be nice. 10137 * @protected 10138 */ 10139 this._breakpoint = null; 10140 10141 /** 10142 * Current width of the plugin element. 10143 */ 10144 this._width = null; 10145 10146 /** 10147 * All real items. 10148 * @protected 10149 */ 10150 this._items = []; 10151 10152 /** 10153 * All cloned items. 10154 * @protected 10155 */ 10156 this._clones = []; 10157 10158 /** 10159 * Merge values of all items. 10160 * @todo Maybe this could be part of a plugin. 10161 * @protected 10162 */ 10163 this._mergers = []; 10164 10165 /** 10166 * Widths of all items. 10167 */ 10168 this._widths = []; 10169 10170 /** 10171 * Invalidated parts within the update process. 10172 * @protected 10173 */ 10174 this._invalidated = {}; 10175 10176 /** 10177 * Ordered list of workers for the update process. 10178 * @protected 10179 */ 10180 this._pipe = []; 10181 10182 /** 10183 * Current state information for the drag operation. 10184 * @todo #261 10185 * @protected 10186 */ 10187 this._drag = { 10188 time: null, 10189 target: null, 10190 pointer: null, 10191 stage: { 10192 start: null, 10193 current: null 10194 }, 10195 direction: null 10196 }; 10197 10198 /** 10199 * Current state information and their tags. 10200 * @type {Object} 10201 * @protected 10202 */ 10203 this._states = { 10204 current: {}, 10205 tags: { 10206 'initializing': [ 'busy' ], 10207 'animating': [ 'busy' ], 10208 'dragging': [ 'interacting' ] 10209 } 10210 }; 10211 10212 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 10213 this._handlers[handler] = $.proxy(this[handler], this); 10214 }, this)); 10215 10216 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 10217 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 10218 = new plugin(this); 10219 }, this)); 10220 10221 $.each(Owl.Workers, $.proxy(function(priority, worker) { 10222 this._pipe.push({ 10223 'filter': worker.filter, 10224 'run': $.proxy(worker.run, this) 10225 }); 10226 }, this)); 10227 10228 this.setup(); 10229 this.initialize(); 10230 } 10231 10232 /** 10233 * Default options for the carousel. 10234 * @public 10235 */ 10236 Owl.Defaults = { 10237 items: 3, 10238 loop: false, 10239 center: false, 10240 rewind: false, 10241 10242 mouseDrag: true, 10243 touchDrag: true, 10244 pullDrag: true, 10245 freeDrag: false, 10246 10247 margin: 0, 10248 stagePadding: 0, 10249 10250 merge: false, 10251 mergeFit: true, 10252 autoWidth: false, 10253 10254 startPosition: 0, 10255 rtl: false, 10256 10257 smartSpeed: 250, 10258 fluidSpeed: false, 10259 dragEndSpeed: false, 10260 10261 responsive: {}, 10262 responsiveRefreshRate: 200, 10263 responsiveBaseElement: window, 10264 10265 fallbackEasing: 'swing', 10266 10267 info: false, 10268 10269 nestedItemSelector: false, 10270 itemElement: 'div', 10271 stageElement: 'div', 10272 10273 refreshClass: 'owl-refresh', 10274 loadedClass: 'owl-loaded', 10275 loadingClass: 'owl-loading', 10276 rtlClass: 'owl-rtl', 10277 responsiveClass: 'owl-responsive', 10278 dragClass: 'owl-drag', 10279 itemClass: 'owl-item', 10280 stageClass: 'owl-stage', 10281 stageOuterClass: 'owl-stage-outer', 10282 grabClass: 'owl-grab' 10283 }; 10284 10285 /** 10286 * Enumeration for width. 10287 * @public 10288 * @readonly 10289 * @enum {String} 10290 */ 10291 Owl.Width = { 10292 Default: 'default', 10293 Inner: 'inner', 10294 Outer: 'outer' 10295 }; 10296 10297 /** 10298 * Enumeration for types. 10299 * @public 10300 * @readonly 10301 * @enum {String} 10302 */ 10303 Owl.Type = { 10304 Event: 'event', 10305 State: 'state' 10306 }; 10307 10308 /** 10309 * Contains all registered plugins. 10310 * @public 10311 */ 10312 Owl.Plugins = {}; 10313 10314 /** 10315 * List of workers involved in the update process. 10316 */ 10317 Owl.Workers = [ { 10318 filter: [ 'width', 'settings' ], 10319 run: function() { 10320 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 10321 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 10322 } 10323 }, { 10324 filter: [ 'width', 'items', 'settings' ], 10325 run: function(cache) { 10326 cache.current = this._items && this._items[this.relative(this._current)]; 10327 } 10328 }, { 10329 filter: [ 'items', 'settings' ], 10330 run: function() { 10331 this.$stage.children('.cloned').remove(); 10332 } 10333 }, { 10334 filter: [ 'width', 'items', 'settings' ], 10335 run: function(cache) { 10336 var margin = this.settings.margin || '', 10337 grid = !this.settings.autoWidth, 10338 rtl = this.settings.rtl, 10339 css = { 10340 'width': 'auto', 10341 'margin-left': rtl ? margin : '', 10342 'margin-right': rtl ? '' : margin 10343 }; 10344 10345 !grid && this.$stage.children().css(css); 10346 10347 cache.css = css; 10348 } 10349 }, { 10350 filter: [ 'width', 'items', 'settings' ], 10351 run: function(cache) { 10352 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 10353 merge = null, 10354 iterator = this._items.length, 10355 grid = !this.settings.autoWidth, 10356 widths = []; 10357 10358 cache.items = { 10359 merge: false, 10360 width: width 10361 }; 10362 10363 while (iterator--) { 10364 merge = this._mergers[iterator]; 10365 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 10366 10367 cache.items.merge = merge > 1 || cache.items.merge; 10368 10369 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 10370 } 10371 10372 this._widths = widths; 10373 } 10374 }, { 10375 filter: [ 'items', 'settings' ], 10376 run: function() { 10377 var clones = [], 10378 items = this._items, 10379 settings = this.settings, 10380 view = Math.max(settings.items * 2, 4), 10381 size = Math.ceil(items.length / 2) * 2, 10382 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 10383 append = '', 10384 prepend = ''; 10385 10386 repeat /= 2; 10387 10388 while (repeat--) { 10389 clones.push(this.normalize(clones.length / 2, true)); 10390 append = append + items[clones[clones.length - 1]][0].outerHTML; 10391 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 10392 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 10393 } 10394 10395 this._clones = clones; 10396 10397 // var appendVideo = $(append).find('.uncode-video-container'); 10398 // if (appendVideo.length) { 10399 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 10400 // } 10401 // var prependVideo = $(prepend).find('.uncode-video-container'); 10402 // if (prependVideo.length) { 10403 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 10404 // } 10405 $(append).addClass('cloned').appendTo(this.$stage); 10406 $(prepend).addClass('cloned').prependTo(this.$stage); 10407 } 10408 }, { 10409 filter: [ 'width', 'items', 'settings' ], 10410 run: function() { 10411 var rtl = this.settings.rtl ? 1 : -1, 10412 size = this._clones.length + this._items.length, 10413 iterator = -1, 10414 previous = 0, 10415 current = 0, 10416 coordinates = []; 10417 10418 while (++iterator < size) { 10419 previous = coordinates[iterator - 1] || 0; 10420 current = this._widths[this.relative(iterator)] + this.settings.margin; 10421 coordinates.push(previous + current * rtl); 10422 } 10423 10424 this._coordinates = coordinates; 10425 } 10426 }, { 10427 filter: [ 'width', 'items', 'settings' ], 10428 run: function() { 10429 var padding = this.settings.stagePadding, 10430 coordinates = this._coordinates, 10431 css = { 10432 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 10433 'padding-left': padding || '', 10434 'padding-right': padding || '' 10435 }; 10436 10437 this.$stage.css(css); 10438 } 10439 }, { 10440 filter: [ 'width', 'items', 'settings' ], 10441 run: function(cache) { 10442 var iterator = this._coordinates.length, 10443 grid = !this.settings.autoWidth, 10444 items = this.$stage.children(); 10445 10446 if (grid && cache.items.merge) { 10447 while (iterator--) { 10448 cache.css.width = this._widths[this.relative(iterator)]; 10449 items.eq(iterator).css(cache.css); 10450 } 10451 } else if (grid) { 10452 cache.css.width = cache.items.width; 10453 items.css(cache.css); 10454 } 10455 } 10456 }, { 10457 filter: [ 'items' ], 10458 run: function() { 10459 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 10460 } 10461 }, { 10462 filter: [ 'width', 'items', 'settings' ], 10463 run: function(cache) { 10464 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 10465 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 10466 this.reset(cache.current); 10467 } 10468 }, { 10469 filter: [ 'position' ], 10470 run: function() { 10471 this.animate(this.coordinates(this._current)); 10472 } 10473 }, { 10474 filter: [ 'width', 'position', 'items', 'settings' ], 10475 run: function() { 10476 var rtl = this.settings.rtl ? 1 : -1, 10477 padding = this.settings.stagePadding * 2, 10478 begin = this.coordinates(this.current()) + padding, 10479 end = begin + this.width() * rtl, 10480 inner, outer, matches = [], i, n; 10481 10482 for (i = 0, n = this._coordinates.length; i < n; i++) { 10483 inner = this._coordinates[i - 1] || 0; 10484 outer = Math.abs(this._coordinates[i]) + padding * rtl; 10485 10486 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 10487 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 10488 matches.push(i); 10489 } 10490 } 10491 10492 this.$stage.children('.active').removeClass('active'); 10493 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 10494 10495 if (this.settings.center) { 10496 this.$stage.children('.center').removeClass('center'); 10497 this.$stage.children().eq(this.current()).addClass('center'); 10498 } 10499 } 10500 } ]; 10501 10502 /** 10503 * Initializes the carousel. 10504 * @protected 10505 */ 10506 Owl.prototype.initialize = function() { 10507 this.enter('initializing'); 10508 this.trigger('initialize'); 10509 10510 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 10511 10512 if (this.settings.autoWidth && !this.is('pre-loading')) { 10513 var imgs, nestedSelector, width; 10514 imgs = this.$element.find('img'); 10515 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 10516 width = this.$element.children(nestedSelector).width(); 10517 10518 if (imgs.length && width <= 0) { 10519 this.preloadAutoWidthImages(imgs); 10520 } 10521 } 10522 10523 this.$element.addClass(this.options.loadingClass); 10524 10525 // create stage 10526 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 10527 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 10528 10529 // append stage 10530 this.$element.append(this.$stage.parent()); 10531 10532 // append content 10533 this.replace(this.$element.children().not(this.$stage.parent())); 10534 10535 // check visibility 10536 if (this.$element.is(':visible')) { 10537 // update view 10538 this.refresh(); 10539 } else { 10540 // invalidate width 10541 this.invalidate('width'); 10542 } 10543 10544 this.$element 10545 .removeClass(this.options.loadingClass) 10546 .addClass(this.options.loadedClass); 10547 10548 // register event handlers 10549 this.registerEventHandlers(); 10550 10551 this.leave('initializing'); 10552 this.trigger('initialized'); 10553 }; 10554 10555 /** 10556 * Setups the current settings. 10557 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 10558 * @todo Support for media queries by using `matchMedia` would be nice. 10559 * @public 10560 */ 10561 Owl.prototype.setup = function() { 10562 var viewport = this.viewport(), 10563 overwrites = this.options.responsive, 10564 match = -1, 10565 settings = null; 10566 10567 if (!overwrites) { 10568 settings = $.extend({}, this.options); 10569 } else { 10570 $.each(overwrites, function(breakpoint) { 10571 if (breakpoint <= viewport && breakpoint > match) { 10572 match = Number(breakpoint); 10573 } 10574 }); 10575 10576 settings = $.extend({}, this.options, overwrites[match]); 10577 delete settings.responsive; 10578 10579 // responsive class 10580 if (settings.responsiveClass) { 10581 this.$element.attr('class', 10582 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 10583 ); 10584 } 10585 } 10586 10587 if (this.settings === null || this._breakpoint !== match) { 10588 this.trigger('change', { property: { name: 'settings', value: settings } }); 10589 this._breakpoint = match; 10590 this.settings = settings; 10591 this.invalidate('settings'); 10592 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 10593 } 10594 }; 10595 10596 /** 10597 * Updates option logic if necessery. 10598 * @protected 10599 */ 10600 Owl.prototype.optionsLogic = function() { 10601 if (this.settings.autoWidth) { 10602 this.settings.stagePadding = false; 10603 this.settings.merge = false; 10604 } 10605 }; 10606 10607 /** 10608 * Prepares an item before add. 10609 * @todo Rename event parameter `content` to `item`. 10610 * @protected 10611 * @returns {jQuery|HTMLElement} - The item container. 10612 */ 10613 Owl.prototype.prepare = function(item, index) { 10614 var event = this.trigger('prepare', { content: item }); 10615 if (!event.data) { 10616 event.data = $('<' + this.settings.itemElement + '/>') 10617 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 10618 } 10619 10620 this.trigger('prepared', { content: event.data }); 10621 10622 return event.data; 10623 }; 10624 10625 /** 10626 * Updates the view. 10627 * @public 10628 */ 10629 Owl.prototype.update = function() { 10630 var i = 0, 10631 n = this._pipe.length, 10632 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 10633 cache = {}; 10634 10635 while (i < n) { 10636 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 10637 this._pipe[i].run(cache); 10638 } 10639 i++; 10640 } 10641 10642 this._invalidated = {}; 10643 10644 !this.is('valid') && this.enter('valid'); 10645 }; 10646 10647 /** 10648 * Gets the width of the view. 10649 * @public 10650 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 10651 * @returns {Number} - The width of the view in pixel. 10652 */ 10653 Owl.prototype.width = function(dimension) { 10654 dimension = dimension || Owl.Width.Default; 10655 switch (dimension) { 10656 case Owl.Width.Inner: 10657 case Owl.Width.Outer: 10658 return this._width; 10659 default: 10660 return this._width - this.settings.stagePadding * 2 + this.settings.margin; 10661 } 10662 }; 10663 10664 /** 10665 * Refreshes the carousel primarily for adaptive purposes. 10666 * @public 10667 */ 10668 Owl.prototype.refresh = function() { 10669 this.enter('refreshing'); 10670 this.trigger('refresh'); 10671 10672 this.setup(); 10673 10674 this.optionsLogic(); 10675 10676 this.$element.addClass(this.options.refreshClass); 10677 10678 this.update(); 10679 10680 this.$element.removeClass(this.options.refreshClass); 10681 10682 this.leave('refreshing'); 10683 this.trigger('refreshed'); 10684 }; 10685 10686 /** 10687 * Checks window `resize` event. 10688 * @protected 10689 */ 10690 Owl.prototype.onThrottledResize = function() { 10691 window.clearTimeout(this.resizeTimer); 10692 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 10693 }; 10694 10695 /** 10696 * Checks window `resize` event. 10697 * @protected 10698 */ 10699 Owl.prototype.onResize = function() { 10700 if (!this._items.length) { 10701 return false; 10702 } 10703 10704 if (this._width === this.$element.width()) { 10705 return false; 10706 } 10707 10708 if (!this.$element.is(':visible')) { 10709 return false; 10710 } 10711 10712 this.enter('resizing'); 10713 10714 if (this.trigger('resize').isDefaultPrevented()) { 10715 this.leave('resizing'); 10716 return false; 10717 } 10718 10719 this.invalidate('width'); 10720 10721 this.refresh(); 10722 10723 this.leave('resizing'); 10724 this.trigger('resized'); 10725 }; 10726 10727 /** 10728 * Registers event handlers. 10729 * @todo Check `msPointerEnabled` 10730 * @todo #261 10731 * @protected 10732 */ 10733 Owl.prototype.registerEventHandlers = function() { 10734 if ($.support.transition) { 10735 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 10736 } 10737 10738 if (this.settings.responsive !== false) { 10739 this.on(window, 'resize', this._handlers.onThrottledResize); 10740 } 10741 10742 if (this.settings.mouseDrag) { 10743 this.$element.addClass(this.options.dragClass); 10744 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 10745 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 10746 } 10747 10748 if (this.settings.touchDrag){ 10749 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 10750 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 10751 } 10752 }; 10753 10754 /** 10755 * Handles `touchstart` and `mousedown` events. 10756 * @todo Horizontal swipe threshold as option 10757 * @todo #261 10758 * @protected 10759 * @param {Event} event - The event arguments. 10760 */ 10761 Owl.prototype.onDragStart = function(event) { 10762 var stage = null; 10763 10764 if (event.which === 3) { 10765 return; 10766 } 10767 10768 if ($.support.transform) { 10769 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 10770 stage = { 10771 x: stage[stage.length === 16 ? 12 : 4], 10772 y: stage[stage.length === 16 ? 13 : 5] 10773 }; 10774 } else { 10775 stage = this.$stage.position(); 10776 stage = { 10777 x: this.settings.rtl ? 10778 stage.left + this.$stage.width() - this.width() + this.settings.margin : 10779 stage.left, 10780 y: stage.top 10781 }; 10782 } 10783 10784 if (this.is('animating')) { 10785 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 10786 this.invalidate('position'); 10787 } 10788 10789 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 10790 10791 this.speed(0); 10792 10793 this._drag.time = new Date().getTime(); 10794 this._drag.target = $(event.target); 10795 this._drag.stage.start = stage; 10796 this._drag.stage.current = stage; 10797 this._drag.pointer = this.pointer(event); 10798 10799 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 10800 10801 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 10802 var delta = this.difference(this._drag.pointer, this.pointer(event)); 10803 10804 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 10805 10806 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 10807 return; 10808 } 10809 10810 event.preventDefault(); 10811 10812 this.enter('dragging'); 10813 this.trigger('drag'); 10814 }, this)); 10815 }; 10816 10817 /** 10818 * Handles the `touchmove` and `mousemove` events. 10819 * @todo #261 10820 * @protected 10821 * @param {Event} event - The event arguments. 10822 */ 10823 Owl.prototype.onDragMove = function(event) { 10824 var minimum = null, 10825 maximum = null, 10826 pull = null, 10827 delta = this.difference(this._drag.pointer, this.pointer(event)), 10828 stage = this.difference(this._drag.stage.start, delta); 10829 10830 if (!this.is('dragging')) { 10831 return; 10832 } 10833 10834 event.preventDefault(); 10835 10836 if (this.settings.loop) { 10837 minimum = this.coordinates(this.minimum()); 10838 maximum = this.coordinates(this.maximum() + 1) - minimum; 10839 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 10840 } else { 10841 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 10842 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 10843 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 10844 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 10845 } 10846 10847 this._drag.stage.current = stage; 10848 10849 this.animate(stage.x); 10850 }; 10851 10852 /** 10853 * Handles the `touchend` and `mouseup` events. 10854 * @todo #261 10855 * @todo Threshold for click event 10856 * @protected 10857 * @param {Event} event - The event arguments. 10858 */ 10859 Owl.prototype.onDragEnd = function(event) { 10860 var delta = this.difference(this._drag.pointer, this.pointer(event)), 10861 stage = this._drag.stage.current, 10862 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 10863 10864 $(document).off('.owl.core'); 10865 10866 this.$element.removeClass(this.options.grabClass); 10867 10868 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 10869 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 10870 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 10871 this.invalidate('position'); 10872 this.update(); 10873 10874 this._drag.direction = direction; 10875 10876 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 10877 this._drag.target.one('click.owl.core', function() { return false; }); 10878 } 10879 } 10880 10881 if (!this.is('dragging')) { 10882 return; 10883 } 10884 10885 this.leave('dragging'); 10886 this.trigger('dragged'); 10887 }; 10888 10889 /** 10890 * Gets absolute position of the closest item for a coordinate. 10891 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 10892 * @protected 10893 * @param {Number} coordinate - The coordinate in pixel. 10894 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 10895 * @return {Number} - The absolute position of the closest item. 10896 */ 10897 Owl.prototype.closest = function(coordinate, direction) { 10898 var position = -1, 10899 pull = 30, 10900 width = this.width(), 10901 coordinates = this.coordinates(); 10902 10903 if (!this.settings.freeDrag) { 10904 // check closest item 10905 $.each(coordinates, $.proxy(function(index, value) { 10906 if (coordinate > value - pull && coordinate < value + pull) { 10907 position = index; 10908 } else if (this.op(coordinate, '<', value) 10909 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 10910 position = direction === 'left' ? index + 1 : index; 10911 } 10912 return position === -1; 10913 }, this)); 10914 } 10915 10916 if (!this.settings.loop) { 10917 // non loop boundries 10918 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 10919 position = coordinate = this.minimum(); 10920 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 10921 position = coordinate = this.maximum(); 10922 } 10923 } 10924 10925 return position; 10926 }; 10927 10928 /** 10929 * Animates the stage. 10930 * @todo #270 10931 * @public 10932 * @param {Number} coordinate - The coordinate in pixels. 10933 */ 10934 Owl.prototype.animate = function(coordinate) { 10935 var animate = this.speed() > 0; 10936 10937 this.is('animating') && this.onTransitionEnd(); 10938 10939 if (animate) { 10940 this.enter('animating'); 10941 this.trigger('translate'); 10942 } 10943 10944 if ($.support.transform3d && $.support.transition) { 10945 this.$stage.css({ 10946 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 10947 transition: (this.speed() / 1000) + 's' 10948 }); 10949 } else if (animate) { 10950 this.$stage.animate({ 10951 left: coordinate + 'px' 10952 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 10953 } else { 10954 this.$stage.css({ 10955 left: coordinate + 'px' 10956 }); 10957 } 10958 }; 10959 10960 /** 10961 * Checks whether the carousel is in a specific state or not. 10962 * @param {String} state - The state to check. 10963 * @returns {Boolean} - The flag which indicates if the carousel is busy. 10964 */ 10965 Owl.prototype.is = function(state) { 10966 return this._states.current[state] && this._states.current[state] > 0; 10967 }; 10968 10969 /** 10970 * Sets the absolute position of the current item. 10971 * @public 10972 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 10973 * @returns {Number} - The absolute position of the current item. 10974 */ 10975 Owl.prototype.current = function(position) { 10976 if (position === undefined) { 10977 return this._current; 10978 } 10979 10980 if (this._items.length === 0) { 10981 return undefined; 10982 } 10983 10984 position = this.normalize(position); 10985 10986 if (this._current !== position) { 10987 var event = this.trigger('change', { property: { name: 'position', value: position } }); 10988 10989 if (event.data !== undefined) { 10990 position = this.normalize(event.data); 10991 } 10992 10993 this._current = position; 10994 10995 this.invalidate('position'); 10996 10997 this.trigger('changed', { property: { name: 'position', value: this._current } }); 10998 } 10999 11000 return this._current; 11001 }; 11002 11003 /** 11004 * Invalidates the given part of the update routine. 11005 * @param {String} [part] - The part to invalidate. 11006 * @returns {Array.<String>} - The invalidated parts. 11007 */ 11008 Owl.prototype.invalidate = function(part) { 11009 if ($.type(part) === 'string') { 11010 this._invalidated[part] = true; 11011 this.is('valid') && this.leave('valid'); 11012 } 11013 return $.map(this._invalidated, function(v, i) { return i }); 11014 }; 11015 11016 /** 11017 * Resets the absolute position of the current item. 11018 * @public 11019 * @param {Number} position - The absolute position of the new item. 11020 */ 11021 Owl.prototype.reset = function(position) { 11022 position = this.normalize(position); 11023 11024 if (position === undefined) { 11025 return; 11026 } 11027 11028 this._speed = 0; 11029 this._current = position; 11030 11031 this.suppress([ 'translate', 'translated' ]); 11032 11033 this.animate(this.coordinates(position)); 11034 11035 this.release([ 'translate', 'translated' ]); 11036 }; 11037 11038 /** 11039 * Normalizes an absolute or a relative position of an item. 11040 * @public 11041 * @param {Number} position - The absolute or relative position to normalize. 11042 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 11043 * @returns {Number} - The normalized position. 11044 */ 11045 Owl.prototype.normalize = function(position, relative) { 11046 var n = this._items.length, 11047 m = relative ? 0 : this._clones.length; 11048 11049 if (!$.isNumeric(position) || n < 1) { 11050 position = undefined; 11051 } else if (position < 0 || position >= n + m) { 11052 position = ((position - m / 2) % n + n) % n + m / 2; 11053 } 11054 11055 return position; 11056 }; 11057 11058 /** 11059 * Converts an absolute position of an item into a relative one. 11060 * @public 11061 * @param {Number} position - The absolute position to convert. 11062 * @returns {Number} - The converted position. 11063 */ 11064 Owl.prototype.relative = function(position) { 11065 position -= this._clones.length / 2; 11066 return this.normalize(position, true); 11067 }; 11068 11069 /** 11070 * Gets the maximum position for the current item. 11071 * @public 11072 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11073 * @returns {Number} 11074 */ 11075 Owl.prototype.maximum = function(relative) { 11076 var settings = this.settings, 11077 maximum = this._coordinates.length, 11078 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 11079 i = -1, j; 11080 11081 if (settings.loop) { 11082 maximum = this._clones.length / 2 + this._items.length - 1; 11083 } else if (settings.autoWidth || settings.merge) {
11084 // binary search 11085 while (maximum - i > 1) { 11086 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 11087 ? i = j : maximum = j; 11088 } 11089 } else if (settings.center) { 11090 maximum = this._items.length - 1; 11091 } else { 11092 maximum = this._items.length - settings.items; 11093 } 11094 11095 if (relative) { 11096 maximum -= this._clones.length / 2; 11097 } 11098 11099 return Math.max(maximum, 0); 11100 }; 11101 11102 /** 11103 * Gets the minimum position for the current item. 11104 * @public 11105 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 11106 * @returns {Number} 11107 */ 11108 Owl.prototype.minimum = function(relative) { 11109 return relative ? 0 : this._clones.length / 2; 11110 }; 11111 11112 /** 11113 * Gets an item at the specified relative position. 11114 * @public 11115 * @param {Number} [position] - The relative position of the item. 11116 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11117 */ 11118 Owl.prototype.items = function(position) { 11119 if (position === undefined) { 11120 return this._items.slice(); 11121 } 11122 11123 position = this.normalize(position, true); 11124 return this._items[position]; 11125 }; 11126 11127 /** 11128 * Gets an item at the specified relative position. 11129 * @public 11130 * @param {Number} [position] - The relative position of the item. 11131 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 11132 */ 11133 Owl.prototype.mergers = function(position) { 11134 if (position === undefined) { 11135 return this._mergers.slice(); 11136 } 11137 11138 position = this.normalize(position, true); 11139 return this._mergers[position]; 11140 }; 11141 11142 /** 11143 * Gets the absolute positions of clones for an item. 11144 * @public 11145 * @param {Number} [position] - The relative position of the item. 11146 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 11147 */ 11148 Owl.prototype.clones = function(position) { 11149 var odd = this._clones.length / 2, 11150 even = odd + this._items.length, 11151 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 11152 11153 if (position === undefined) { 11154 return $.map(this._clones, function(v, i) { return map(i) }); 11155 } 11156 11157 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 11158 }; 11159 11160 /** 11161 * Sets the current animation speed. 11162 * @public 11163 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 11164 * @returns {Number} - The current animation speed in milliseconds. 11165 */ 11166 Owl.prototype.speed = function(speed) { 11167 if (speed !== undefined) { 11168 this._speed = speed; 11169 } 11170 11171 return this._speed; 11172 }; 11173 11174 /** 11175 * Gets the coordinate of an item. 11176 * @todo The name of this method is missleanding. 11177 * @public 11178 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 11179 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 11180 */ 11181 Owl.prototype.coordinates = function(position) { 11182 var coordinate = null; 11183 11184 if (position === undefined) { 11185 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 11186 return this.coordinates(index); 11187 }, this)); 11188 } 11189 11190 if (this.settings.center) { 11191 coordinate = this._coordinates[position]; 11192 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 11193 } else { 11194 coordinate = this._coordinates[position - 1] || 0; 11195 } 11196 11197 return coordinate; 11198 }; 11199 11200 /** 11201 * Calculates the speed for a translation. 11202 * @protected 11203 * @param {Number} from - The absolute position of the start item. 11204 * @param {Number} to - The absolute position of the target item. 11205 * @param {Number} [factor=undefined] - The time factor in milliseconds. 11206 * @returns {Number} - The time in milliseconds for the translation. 11207 */ 11208 Owl.prototype.duration = function(from, to, factor) { 11209 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 11210 }; 11211 11212 /** 11213 * Slides to the specified item. 11214 * @public 11215 * @param {Number} position - The position of the item. 11216 * @param {Number} [speed] - The time in milliseconds for the transition. 11217 */ 11218 Owl.prototype.to = function(position, speed) { 11219 var current = this.current(), 11220 revert = null, 11221 distance = position - this.relative(current), 11222 direction = (distance > 0) - (distance < 0), 11223 items = this._items.length, 11224 minimum = this.minimum(), 11225 maximum = this.maximum(); 11226 11227 if (this.settings.loop) { 11228 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 11229 distance += direction * -1 * items; 11230 } 11231 11232 position = current + distance; 11233 revert = ((position - minimum) % items + items) % items + minimum; 11234 11235 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 11236 current = revert - distance; 11237 position = revert; 11238 this.reset(current); 11239 } 11240 } else if (this.settings.rewind) { 11241 maximum += 1; 11242 position = (position % maximum + maximum) % maximum; 11243 } else { 11244 position = Math.max(minimum, Math.min(maximum, position)); 11245 } 11246 11247 this.speed(this.duration(current, position, speed)); 11248 this.current(position); 11249 11250 if (this.$element.is(':visible')) { 11251 this.update(); 11252 } 11253 }; 11254 11255 /** 11256 * Slides to the next item. 11257 * @public 11258 * @param {Number}
vendor: 12,284 bytes, lines 11258-11678
11258 [speed] - The time in milliseconds for the transition. 11259 */ 11260 Owl.prototype.next = function(speed) { 11261 speed = speed || false; 11262 this.to(this.relative(this.current()) + 1, speed); 11263 }; 11264 11265 /** 11266 * Slides to the previous item. 11267 * @public 11268 * @param {Number} [speed] - The time in milliseconds for the transition. 11269 */ 11270 Owl.prototype.prev = function(speed) { 11271 speed = speed || false; 11272 this.to(this.relative(this.current()) - 1, speed); 11273 }; 11274 11275 /** 11276 * Handles the end of an animation. 11277 * @protected 11278 * @param {Event} event - The event arguments. 11279 */ 11280 Owl.prototype.onTransitionEnd = function(event) { 11281 11282 // if css2 animation then event object is undefined 11283 if (event !== undefined) { 11284 event.stopPropagation(); 11285 11286 // Catch only owl-stage transitionEnd event 11287 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 11288 return false; 11289 } 11290 } 11291 11292 this.leave('animating'); 11293 this.trigger('translated'); 11294 }; 11295 11296 /** 11297 * Gets viewport width. 11298 * @protected 11299 * @return {Number} - The width in pixel. 11300 */ 11301 Owl.prototype.viewport = function() { 11302 var width; 11303 if (this.options.responsiveBaseElement !== window) { 11304 width = $(this.options.responsiveBaseElement).width(); 11305 } else if (window.innerWidth) { 11306 width = window.innerWidth; 11307 } else if (document.documentElement && document.documentElement.clientWidth) { 11308 width = document.documentElement.clientWidth; 11309 } else { 11310 throw 'Can not detect viewport width.'; 11311 } 11312 11313 return width; 11314 }; 11315 11316 /** 11317 * Replaces the current content. 11318 * @public 11319 * @param {HTMLElement|jQuery|String} content - The new content. 11320 */ 11321 Owl.prototype.replace = function(content) { 11322 this.$stage.empty(); 11323 this._items = []; 11324 11325 if (content) { 11326 content = (content instanceof jQuery) ? content : $(content); 11327 } 11328 11329 if (this.settings.nestedItemSelector) { 11330 content = content.find('.' + this.settings.nestedItemSelector); 11331 } 11332 11333 content.filter(function() { 11334 return this.nodeType === 1; 11335 }).each($.proxy(function(index, item) { 11336 item = this.prepare(item, index); 11337 this.$stage.append(item); 11338 this._items.push(item); 11339 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 11340 }, this)); 11341 11342 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 11343 11344 this.invalidate('items'); 11345 }; 11346 11347 /** 11348 * Adds an item. 11349 * @todo Use `item` instead of `content` for the event arguments. 11350 * @public 11351 * @param {HTMLElement|jQuery|String} content - The item content to add. 11352 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 11353 */ 11354 Owl.prototype.add = function(content, position) { 11355 var current = this.relative(this._current); 11356 11357 position = position === undefined ? this._items.length : this.normalize(position, true); 11358 content = content instanceof jQuery ? content : $(content); 11359 11360 this.trigger('add', { content: content, position: position }); 11361 11362 content = this.prepare(content, this._items[current].index()); 11363 11364 if (this._items.length === 0 || position === this._items.length) { 11365 this._items.length === 0 && this.$stage.append(content); 11366 this._items.length !== 0 && this._items[position - 1].after(content); 11367 this._items.push(content); 11368 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11369 } else { 11370 this._items[position].before(content); 11371 this._items.splice(position, 0, content); 11372 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 11373 } 11374 11375 this._items[current] && this.reset(this._items[current].index()); 11376 11377 this.invalidate('items'); 11378 11379 this.trigger('added', { content: content, position: position }); 11380 }; 11381 11382 /** 11383 * Removes an item by its position. 11384 * @todo Use `item` instead of `content` for the event arguments. 11385 * @public 11386 * @param {Number} position - The relative position of the item to remove. 11387 */ 11388 Owl.prototype.remove = function(position) { 11389 position = this.normalize(position, true); 11390 11391 if (position === undefined) { 11392 return; 11393 } 11394 11395 this.trigger('remove', { content: this._items[position], position: position }); 11396 11397 this._items[position].remove(); 11398 this._items.splice(position, 1); 11399 this._mergers.splice(position, 1); 11400 11401 this.invalidate('items'); 11402 11403 this.trigger('removed', { content: null, position: position }); 11404 }; 11405 11406 /** 11407 * Preloads images with auto width. 11408 * @todo Replace by a more generic approach 11409 * @protected 11410 */ 11411 Owl.prototype.preloadAutoWidthImages = function(images) { 11412 images.each($.proxy(function(i, element) { 11413 this.enter('pre-loading'); 11414 element = $(element); 11415 $(new Image()).one('load', $.proxy(function(e) { 11416 element.attr('src', e.target.src); 11417 element.css('opacity', 1); 11418 this.leave('pre-loading'); 11419 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 11420 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 11421 }, this)); 11422 }; 11423 11424 /** 11425 * Destroys the carousel. 11426 * @public 11427 */ 11428 Owl.prototype.destroy = function() { 11429 11430 this.$element.off('.owl.core'); 11431 this.$stage.off('.owl.core'); 11432 $(document).off('.owl.core'); 11433 11434 if (this.settings.responsive !== false) { 11435 window.clearTimeout(this.resizeTimer); 11436 this.off(window, 'resize', this._handlers.onThrottledResize); 11437 } 11438 11439 for (var i in this._plugins) { 11440 this._plugins[i].destroy(); 11441 } 11442 11443 this.$stage.children('.cloned').remove(); 11444 11445 this.$stage.unwrap(); 11446 this.$stage.children().contents().unwrap(); 11447 this.$stage.children().unwrap(); 11448 11449 this.$element 11450 .removeClass(this.options.refreshClass) 11451 .removeClass(this.options.loadingClass) 11452 .removeClass(this.options.loadedClass) 11453 .removeClass(this.options.rtlClass) 11454 .removeClass(this.options.dragClass) 11455 .removeClass(this.options.grabClass) 11456 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 11457 .removeData('owl.carousel'); 11458 }; 11459 11460 /** 11461 * Operators to calculate right-to-left and left-to-right. 11462 * @protected 11463 * @param {Number} [a] - The left side operand. 11464 * @param {String} [o] - The operator. 11465 * @param {Number} [b] - The right side operand. 11466 */ 11467 Owl.prototype.op = function(a, o, b) { 11468 var rtl = this.settings.rtl; 11469 switch (o) { 11470 case '<': 11471 return rtl ? a > b : a < b; 11472 case '>': 11473 return rtl ? a < b : a > b; 11474 case '>=': 11475 return rtl ? a <= b : a >= b; 11476 case '<=': 11477 return rtl ? a >= b : a <= b; 11478 default: 11479 break; 11480 } 11481 }; 11482 11483 /** 11484 * Attaches to an internal event. 11485 * @protected 11486 * @param {HTMLElement} element - The event source. 11487 * @param {String} event - The event name. 11488 * @param {Function} listener - The event handler to attach. 11489 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 11490 */ 11491 Owl.prototype.on = function(element, event, listener, capture) { 11492 if (element.addEventListener) { 11493 element.addEventListener(event, listener, capture); 11494 } else if (element.attachEvent) { 11495 element.attachEvent('on' + event, listener); 11496 } 11497 }; 11498 11499 /** 11500 * Detaches from an internal event. 11501 * @protected 11502 * @param {HTMLElement} element - The event source. 11503 * @param {String} event - The event name. 11504 * @param {Function} listener - The attached event handler to detach. 11505 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 11506 */ 11507 Owl.prototype.off = function(element, event, listener, capture) { 11508 if (element.removeEventListener) { 11509 element.removeEventListener(event, listener, capture); 11510 } else if (element.detachEvent) { 11511 element.detachEvent('on' + event, listener); 11512 } 11513 }; 11514 11515 /** 11516 * Triggers a public event. 11517 * @todo Remove `status`, `relatedTarget` should be used instead. 11518 * @protected 11519 * @param {String} name - The event name. 11520 * @param {*} [data=null] - The event data. 11521 * @param {String} [namespace=carousel] - The event namespace. 11522 * @param {String} [state] - The state which is associated with the event. 11523 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 11524 * @returns {Event} - The event arguments. 11525 */ 11526 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 11527 var status = { 11528 item: { count: this._items.length, index: this.current() } 11529 }, handler = $.camelCase( 11530 $.grep([ 'on', name, namespace ], function(v) { return v }) 11531 .join('-').toLowerCase() 11532 ), event = $.Event( 11533 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 11534 $.extend({ relatedTarget: this }, status, data) 11535 ); 11536 11537 if (!this._supress[name]) { 11538 $.each(this._plugins, function(name, plugin) { 11539 if (plugin.onTrigger) { 11540 plugin.onTrigger(event); 11541 } 11542 }); 11543 11544 this.register({ type: Owl.Type.Event, name: name }); 11545 this.$element.trigger(event); 11546 11547 if (this.settings && typeof this.settings[handler] === 'function') { 11548 this.settings[handler].call(this, event); 11549 } 11550 } 11551 11552 return event; 11553 }; 11554 11555 /** 11556 * Enters a state. 11557 * @param name - The state name. 11558 */ 11559 Owl.prototype.enter = function(name) { 11560 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11561 if (this._states.current[name] === undefined) { 11562 this._states.current[name] = 0; 11563 } 11564 11565 this._states.current[name]++; 11566 }, this)); 11567 }; 11568 11569 /** 11570 * Leaves a state. 11571 * @param name - The state name. 11572 */ 11573 Owl.prototype.leave = function(name) { 11574 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 11575 this._states.current[name]--; 11576 }, this)); 11577 }; 11578 11579 /** 11580 * Registers an event or state. 11581 * @public 11582 * @param {Object} object - The event or state to register. 11583 */ 11584 Owl.prototype.register = function(object) { 11585 if (object.type === Owl.Type.Event) { 11586 if (!$.event.special[object.name]) { 11587 $.event.special[object.name] = {}; 11588 } 11589 11590 if (!$.event.special[object.name].owl) { 11591 var _default = $.event.special[object.name]._default; 11592 $.event.special[object.name]._default = function(e) { 11593 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 11594 return _default.apply(this, arguments); 11595 } 11596 return e.namespace && e.namespace.indexOf('owl') > -1; 11597 }; 11598 $.event.special[object.name].owl = true; 11599 } 11600 } else if (object.type === Owl.Type.State) { 11601 if (!this._states.tags[object.name]) { 11602 this._states.tags[object.name] = object.tags; 11603 } else { 11604 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 11605 } 11606 11607 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 11608 return $.inArray(tag, this._states.tags[object.name]) === i; 11609 }, this)); 11610 } 11611 }; 11612 11613 /** 11614 * Suppresses events. 11615 * @protected 11616 * @param {Array.<String>} events - The events to suppress. 11617 */ 11618 Owl.prototype.suppress = function(events) { 11619 $.each(events, $.proxy(function(index, event) { 11620 this._supress[event] = true; 11621 }, this)); 11622 }; 11623 11624 /** 11625 * Releases suppressed events. 11626 * @protected 11627 * @param {Array.<String>} events - The events to release. 11628 */ 11629 Owl.prototype.release = function(events) { 11630 $.each(events, $.proxy(function(index, event) { 11631 delete this._supress[event]; 11632 }, this)); 11633 }; 11634 11635 /** 11636 * Gets unified pointer coordinates from event. 11637 * @todo #261 11638 * @protected 11639 * @param {Event} - The `mousedown` or `touchstart` event. 11640 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 11641 */ 11642 Owl.prototype.pointer = function(event) { 11643 var result = { x: null, y: null }; 11644 11645 event = event.originalEvent || event || window.event; 11646 11647 event = event.touches && event.touches.length ? 11648 event.touches[0] : event.changedTouches && event.changedTouches.length ? 11649 event.changedTouches[0] : event; 11650 11651 if (event.pageX) { 11652 result.x = event.pageX; 11653 result.y = event.pageY; 11654 } else { 11655 result.x = event.clientX; 11656 result.y = event.clientY; 11657 } 11658 11659 return result; 11660 }; 11661 11662 /** 11663 * Gets the difference of two vectors. 11664 * @todo #261 11665 * @protected 11666 * @param {Object} - The first vector. 11667 * @param {Object} - The second vector. 11668 * @returns {Object} - The difference. 11669 */ 11670 Owl.prototype.difference = function(first, second) { 11671 return { 11672 x: first.x - second.x, 11673 y: first.y - second.y 11674 }; 11675 }; 11676 11677 /** 11678 * The jQuery Plugin for the Owl Carousel
vendor: 32,236 bytes, lines 11679-12961
11679 * @todo Navigation plugin `next` and `prev` 11680 * @public 11681 */ 11682 $.fn.owlCarousel = function(option) { 11683 var args = Array.prototype.slice.call(arguments, 1); 11684 11685 return this.each(function() { 11686 var $this = $(this), 11687 data = $this.data('owl.carousel'); 11688 11689 if (!data) { 11690 data = new Owl(this, typeof option == 'object' && option); 11691 $this.data('owl.carousel', data); 11692 11693 $.each([ 11694 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 11695 ], function(i, event) { 11696 data.register({ type: Owl.Type.Event, name: event }); 11697 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 11698 if (e.namespace && e.relatedTarget !== this) { 11699 this.suppress([ event ]); 11700 data[event].apply(this, [].slice.call(arguments, 1)); 11701 this.release([ event ]); 11702 } 11703 }, data)); 11704 }); 11705 } 11706 11707 if (typeof option == 'string' && option.charAt(0) !== '_') { 11708 data[option].apply(data, args); 11709 } 11710 }); 11711 }; 11712 11713 /** 11714 * The constructor for the jQuery Plugin 11715 * @public 11716 */ 11717 $.fn.owlCarousel.Constructor = Owl; 11718 11719})(window.Zepto || window.jQuery, window, document); 11720 11721/** 11722 * AutoRefresh Plugin 11723 * @version 2.0.0-beta.3 11724 * @author Artus Kolanowski 11725 * @license The MIT License (MIT) 11726 */ 11727;(function($, window, document, undefined) { 11728 11729 /** 11730 * Creates the auto refresh plugin. 11731 * @class The Auto Refresh Plugin 11732 * @param {Owl} carousel - The Owl Carousel 11733 */ 11734 var AutoRefresh = function(carousel) { 11735 /** 11736 * Reference to the core. 11737 * @protected 11738 * @type {Owl} 11739 */ 11740 this._core = carousel; 11741 11742 /** 11743 * Refresh interval. 11744 * @protected 11745 * @type {number} 11746 */ 11747 this._interval = null; 11748 11749 /** 11750 * Whether the element is currently visible or not. 11751 * @protected 11752 * @type {Boolean} 11753 */ 11754 this._visible = null; 11755 11756 /** 11757 * All event handlers. 11758 * @protected 11759 * @type {Object} 11760 */ 11761 this._handlers = { 11762 'initialized.owl.carousel': $.proxy(function(e) { 11763 if (e.namespace && this._core.settings.autoRefresh) { 11764 this.watch(); 11765 } 11766 }, this) 11767 }; 11768 11769 // set default options 11770 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 11771 11772 // register event handlers 11773 this._core.$element.on(this._handlers); 11774 }; 11775 11776 /** 11777 * Default options. 11778 * @public 11779 */ 11780 AutoRefresh.Defaults = { 11781 autoRefresh: true, 11782 autoRefreshInterval: 500 11783 }; 11784 11785 /** 11786 * Watches the element. 11787 */ 11788 AutoRefresh.prototype.watch = function() { 11789 if (this._interval) { 11790 return; 11791 } 11792 11793 this._visible = this._core.$element.is(':visible'); 11794 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 11795 }; 11796 11797 /** 11798 * Refreshes the element. 11799 */ 11800 AutoRefresh.prototype.refresh = function() { 11801 if (this._core.$element.is(':visible') === this._visible) { 11802 return; 11803 } 11804 11805 this._visible = !this._visible; 11806 11807 this._core.$element.toggleClass('owl-hidden', !this._visible); 11808 11809 this._visible && (this._core.invalidate('width') && this._core.refresh()); 11810 }; 11811 11812 /** 11813 * Destroys the plugin. 11814 */ 11815 AutoRefresh.prototype.destroy = function() { 11816 var handler, property; 11817 11818 window.clearInterval(this._interval); 11819 11820 for (handler in this._handlers) { 11821 this._core.$element.off(handler, this._handlers[handler]); 11822 } 11823 for (property in Object.getOwnPropertyNames(this)) { 11824 typeof this[property] != 'function' && (this[property] = null); 11825 } 11826 }; 11827 11828 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 11829 11830})(window.Zepto || window.jQuery, window, document); 11831 11832/** 11833 * Lazy Plugin 11834 * @version 2.0.0-beta.3 11835 * @author Bartosz Wojciechowski 11836 * @license The MIT License (MIT) 11837 */ 11838;(function($, window, document, undefined) { 11839 11840 /** 11841 * Creates the lazy plugin. 11842 * @class The Lazy Plugin 11843 * @param {Owl} carousel - The Owl Carousel 11844 */ 11845 var Lazy = function(carousel) { 11846 11847 /** 11848 * Reference to the core. 11849 * @protected 11850 * @type {Owl} 11851 */ 11852 this._core = carousel; 11853 11854 /** 11855 * Already loaded items. 11856 * @protected 11857 * @type {Array.<jQuery>} 11858 */ 11859 this._loaded = []; 11860 11861 /** 11862 * Event handlers. 11863 * @protected 11864 * @type {Object} 11865 */ 11866 this._handlers = { 11867 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 11868 if (!e.namespace) { 11869 return; 11870 } 11871 11872 if (!this._core.settings || !this._core.settings.lazyLoad) { 11873 return; 11874 } 11875 11876 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 11877 var settings = this._core.settings, 11878 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 11879 i = ((settings.center && n * -1) || 0), 11880 position = ((e.property && e.property.value) || this._core.current()) + i, 11881 clones = this._core.clones().length, 11882 load = $.proxy(function(i, v) { this.load(v) }, this); 11883 11884 while (i++ < n) { 11885 this.load(clones / 2 + this._core.relative(position)); 11886 clones && $.each(this._core.clones(this._core.relative(position)), load); 11887 position++; 11888 } 11889 } 11890 }, this) 11891 }; 11892 11893 // set the default options 11894 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 11895 11896 // register event handler 11897 this._core.$element.on(this._handlers); 11898 } 11899 11900 /** 11901 * Default options. 11902 * @public 11903 */ 11904 Lazy.Defaults = { 11905 lazyLoad: false 11906 } 11907 11908 /** 11909 * Loads all resources of an item at the specified position. 11910 * @param {Number} position - The absolute position of the item. 11911 * @protected 11912 */ 11913 Lazy.prototype.load = function(position) { 11914 var $item = this._core.$stage.children().eq(position), 11915 $elements = $item && $item.find('.owl-lazy'); 11916 11917 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 11918 return; 11919 } 11920 11921 $elements.each($.proxy(function(index, element) { 11922 var $element = $(element), image, 11923 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 11924 11925 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 11926 11927 if ($element.is('img')) { 11928 $element.one('load.owl.lazy', $.proxy(function() { 11929 $element.css('opacity', 1); 11930 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 11931 }, this)).attr('src', url); 11932 } else { 11933 image = new Image(); 11934 image.onload = $.proxy(function() { 11935 $element.css({ 11936 'background-image': 'url(' + url + ')', 11937 'opacity': '1' 11938 }); 11939 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 11940 }, this); 11941 image.src = url; 11942 } 11943 }, this)); 11944 11945 this._loaded.push($item.get(0)); 11946 } 11947 11948 /** 11949 * Destroys the plugin. 11950 * @public 11951 */ 11952 Lazy.prototype.destroy = function() { 11953 var handler, property; 11954 11955 for (handler in this.handlers) { 11956 this._core.$element.off(handler, this.handlers[handler]); 11957 } 11958 for (property in Object.getOwnPropertyNames(this)) { 11959 typeof this[property] != 'function' && (this[property] = null); 11960 } 11961 }; 11962 11963 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 11964 11965})(window.Zepto || window.jQuery, window, document); 11966 11967/** 11968 * AutoHeight Plugin 11969 * @version 2.0.0-beta.3 11970 * @author Bartosz Wojciechowski 11971 * @license The MIT License (MIT) 11972 */ 11973;(function($, window, document, undefined) { 11974 11975 /** 11976 * Creates the auto height plugin. 11977 * @class The Auto Height Plugin 11978 * @param {Owl} carousel - The Owl Carousel 11979 */ 11980 var AutoHeight = function(carousel) { 11981 /** 11982 * Reference to the core. 11983 * @protected 11984 * @type {Owl} 11985 */ 11986 this._core = carousel; 11987 11988 /** 11989 * All event handlers. 11990 * @protected 11991 * @type {Object} 11992 */ 11993 this._handlers = { 11994 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 11995 if (e.namespace && this._core.settings.autoHeight) { 11996 this.update(); 11997 } 11998 }, this), 11999 'changed.owl.carousel': $.proxy(function(e) { 12000 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 12001 this.update(); 12002 } 12003 }, this), 12004 'loaded.owl.lazy': $.proxy(function(e) { 12005 if (e.namespace && this._core.settings.autoHeight 12006 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 12007 this.update(); 12008 } 12009 }, this) 12010 }; 12011 12012 // set default options 12013 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 12014 12015 // register event handlers 12016 this._core.$element.on(this._handlers); 12017 }; 12018 12019 /** 12020 * Default options. 12021 * @public 12022 */ 12023 AutoHeight.Defaults = { 12024 autoHeight: false, 12025 autoHeightClass: 'owl-height' 12026 }; 12027 12028 /** 12029 * Updates the view. 12030 */ 12031 AutoHeight.prototype.update = function() { 12032 var start = this._core._current, 12033 end = start + this._core.settings.items, 12034 visible = this._core.$stage.children().toArray().slice(start, end); 12035 heights = [], 12036 maxheight = 0; 12037 12038 $.each(visible, function(index, item) { 12039 heights.push($(item).height()); 12040 }); 12041 12042 maxheight = Math.max.apply(null, heights); 12043 12044 this._core.$stage.parent() 12045 .height(maxheight) 12046 .addClass(this._core.settings.autoHeightClass); 12047 }; 12048 12049 AutoHeight.prototype.destroy = function() { 12050 var handler, property; 12051 12052 for (handler in this._handlers) { 12053 this._core.$element.off(handler, this._handlers[handler]); 12054 } 12055 for (property in Object.getOwnPropertyNames(this)) { 12056 typeof this[property] != 'function' && (this[property] = null); 12057 } 12058 }; 12059 12060 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 12061 12062})(window.Zepto || window.jQuery, window, document); 12063 12064/** 12065 * Video Plugin 12066 * @version 2.0.0-beta.3 12067 * @author Bartosz Wojciechowski 12068 * @license The MIT License (MIT) 12069 */ 12070;(function($, window, document, undefined) { 12071 12072 /** 12073 * Creates the video plugin. 12074 * @class The Video Plugin 12075 * @param {Owl} carousel - The Owl Carousel 12076 */ 12077 var Video = function(carousel) { 12078 /** 12079 * Reference to the core. 12080 * @protected 12081 * @type {Owl} 12082 */ 12083 this._core = carousel; 12084 12085 /** 12086 * Cache all video URLs. 12087 * @protected 12088 * @type {Object} 12089 */ 12090 this._videos = {}; 12091 12092 /** 12093 * Current playing item. 12094 * @protected 12095 * @type {jQuery} 12096 */ 12097 this._playing = null; 12098 12099 /** 12100 * All event handlers. 12101 * @todo The cloned content removale is too late 12102 * @protected 12103 * @type {Object} 12104 */ 12105 this._handlers = { 12106 'initialized.owl.carousel': $.proxy(function(e) { 12107 if (e.namespace) { 12108 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 12109 } 12110 }, this), 12111 'resize.owl.carousel': $.proxy(function(e) { 12112 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 12113 e.preventDefault(); 12114 } 12115 }, this), 12116 'refreshed.owl.carousel': $.proxy(function(e) { 12117 if (e.namespace && this._core.is('resizing')) { 12118 this._core.$stage.find('.cloned .owl-video-frame').remove(); 12119 } 12120 }, this), 12121 'changed.owl.carousel': $.proxy(function(e) { 12122 if (e.namespace && e.property.name === 'position' && this._playing) { 12123 this.stop(); 12124 } 12125 }, this), 12126 'prepared.owl.carousel': $.proxy(function(e) { 12127 if (!e.namespace) { 12128 return; 12129 } 12130 12131 var $element = $(e.content).find('.owl-video'); 12132 12133 if ($element.length) { 12134 $element.css('display', 'none'); 12135 this.fetch($element, $(e.content)); 12136 } 12137 }, this) 12138 }; 12139 12140 // set default options 12141 this._core.options = $.extend({}, Video.Defaults, this._core.options); 12142 12143 // register event handlers 12144 this._core.$element.on(this._handlers); 12145 12146 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 12147 this.play(e); 12148 }, this)); 12149 }; 12150 12151 /** 12152 * Default options. 12153 * @public 12154 */ 12155 Video.Defaults = { 12156 video: false, 12157 videoHeight: false, 12158 videoWidth: false 12159 }; 12160 12161 /** 12162 * Gets the video ID and the type (YouTube/Vimeo only). 12163 * @protected 12164 * @param {jQuery} target - The target containing the video data. 12165 * @param {jQuery} item - The item containing the video. 12166 */ 12167 Video.prototype.fetch = function(target, item) { 12168 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 12169 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 12170 width = target.attr('data-width') || this._core.settings.videoWidth, 12171 height = target.attr('data-height') || this._core.settings.videoHeight, 12172 url = target.attr('href'); 12173 12174 if (url) { 12175 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+)?/); 12176 12177 if (id[3].indexOf('youtu') > -1) { 12178 type = 'youtube'; 12179 } else if (id[3].indexOf('vimeo') > -1) { 12180 type = 'vimeo'; 12181 } else { 12182 throw new Error('Video URL not supported.'); 12183 } 12184 id = id[6]; 12185 } else { 12186 throw new Error('Missing video URL.'); 12187 } 12188 12189 this._videos[url] = { 12190 type: type, 12191 id: id, 12192 width: width, 12193 height: height 12194 }; 12195 12196 item.attr('data-video', url); 12197 12198 this.thumbnail(target, this._videos[url]); 12199 }; 12200 12201 /** 12202 * Creates video thumbnail. 12203 * @protected 12204 * @param {jQuery} target - The target containing the video data. 12205 * @param {Object} info - The video info object. 12206 * @see `fetch` 12207 */ 12208 Video.prototype.thumbnail = function(target, video) { 12209 var tnLink, 12210 icon, 12211 path, 12212 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 12213 customTn = target.find('img'), 12214 srcType = 'src', 12215 lazyClass = '', 12216 settings = this._core.settings, 12217 create = function(path) { 12218 icon = '<div class="owl-video-play-icon"></div>'; 12219 12220 if (settings.lazyLoad) { 12221 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 12222 } else { 12223 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 12224 } 12225 target.after(tnLink); 12226 target.after(icon); 12227 }; 12228 12229 // wrap video content into owl-video-wrapper div 12230 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 12231 12232 if (this._core.settings.lazyLoad) { 12233 srcType = 'data-src'; 12234 lazyClass = 'owl-lazy'; 12235 } 12236 12237 // custom thumbnail 12238 if (customTn.length) { 12239 create(customTn.attr(srcType)); 12240 customTn.remove(); 12241 return false; 12242 } 12243 12244 if (video.type === 'youtube') { 12245 path = "http://img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 12246 create(path); 12247 } else if (video.type === 'vimeo') { 12248 $.ajax({ 12249 type: 'GET', 12250 url: 'http://vimeo.com/api/v2/video/' + video.id + '.json', 12251 jsonp: 'callback', 12252 dataType: 'jsonp', 12253 success: function(data) { 12254 path = data[0].thumbnail_large; 12255 create(path); 12256 } 12257 }); 12258 } 12259 }; 12260 12261 /** 12262 * Stops the current video. 12263 * @public 12264 */ 12265 Video.prototype.stop = function() { 12266 this._core.trigger('stop', null, 'video'); 12267 this._playing.find('.owl-video-frame').remove(); 12268 this._playing.removeClass('owl-video-playing'); 12269 this._playing = null; 12270 this._core.leave('playing'); 12271 this._core.trigger('stopped', null, 'video'); 12272 }; 12273 12274 /** 12275 * Starts the current video. 12276 * @public 12277 * @param {Event} event - The event arguments. 12278 */ 12279 Video.prototype.play = function(event) { 12280 var target = $(event.target), 12281 item = target.closest('.' + this._core.settings.itemClass), 12282 video = this._videos[item.attr('data-video')], 12283 width = video.width || '100%', 12284 height = video.height || this._core.$stage.height(), 12285 html; 12286 12287 if (this._playing) { 12288 return; 12289 } 12290 12291 this._core.enter('playing'); 12292 this._core.trigger('play', null, 'video'); 12293 12294 item = this._core.items(this._core.relative(item.index())); 12295 12296 this._core.reset(item.index()); 12297 12298 if (video.type === 'youtube') { 12299 html = '<iframe width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/' + 12300 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 12301 } else if (video.type === 'vimeo') { 12302 html = '<iframe src="http://player.vimeo.com/video/' + video.id + 12303 '?autoplay=1" width="' + width + '" height="' + height + 12304 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 12305 } 12306 12307 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 12308 12309 this._playing = item.addClass('owl-video-playing'); 12310 }; 12311 12312 /** 12313 * Checks whether an video is currently in full screen mode or not. 12314 * @todo Bad style because looks like a readonly method but changes members. 12315 * @protected 12316 * @returns {Boolean} 12317 */ 12318 Video.prototype.isInFullScreen = function() { 12319 var element = document.fullscreenElement || document.mozFullScreenElement || 12320 document.webkitFullscreenElement; 12321 12322 return element && $(element).parent().hasClass('owl-video-frame'); 12323 }; 12324 12325 /** 12326 * Destroys the plugin. 12327 */ 12328 Video.prototype.destroy = function() { 12329 var handler, property; 12330 12331 this._core.$element.off('click.owl.video'); 12332 12333 for (handler in this._handlers) { 12334 this._core.$element.off(handler, this._handlers[handler]); 12335 } 12336 for (property in Object.getOwnPropertyNames(this)) { 12337 typeof this[property] != 'function' && (this[property] = null); 12338 } 12339 }; 12340 12341 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 12342 12343})(window.Zepto || window.jQuery, window, document); 12344 12345/** 12346 * Animate Plugin 12347 * @version 2.0.0-beta.3 12348 * @author Bartosz Wojciechowski 12349 * @license The MIT License (MIT) 12350 */ 12351;(function($, window, document, undefined) { 12352 12353 /** 12354 * Creates the animate plugin. 12355 * @class The Navigation Plugin 12356 * @param {Owl} scope - The Owl Carousel 12357 */ 12358 var Animate = function(scope) { 12359 this.core = scope; 12360 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 12361 this.swapping = true; 12362 this.previous = undefined; 12363 this.next = undefined; 12364 12365 this.handlers = { 12366 'change.owl.carousel': $.proxy(function(e) { 12367 if (e.namespace && e.property.name == 'position') { 12368 this.previous = this.core.current(); 12369 this.next = e.property.value; 12370 } 12371 }, this), 12372 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 12373 if (e.namespace) { 12374 this.swapping = e.type == 'translated'; 12375 } 12376 }, this), 12377 'translate.owl.carousel': $.proxy(function(e) { 12378 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 12379 this.swap(); 12380 } 12381 }, this) 12382 }; 12383 12384 this.core.$element.on(this.handlers); 12385 }; 12386 12387 /** 12388 * Default options. 12389 * @public 12390 */ 12391 Animate.Defaults = { 12392 animateOut: false, 12393 animateIn: false 12394 }; 12395 12396 /** 12397 * Toggles the animation classes whenever an translations starts. 12398 * @protected 12399 * @returns {Boolean|undefined} 12400 */ 12401 Animate.prototype.swap = function() { 12402 12403 if (this.core.settings.items !== 1) { 12404 return; 12405 } 12406 12407 if (!$.support.animation || !$.support.transition) { 12408 return; 12409 } 12410 12411 this.core.speed(0); 12412 12413 var left, 12414 clear = $.proxy(this.clear, this), 12415 previous = this.core.$stage.children().eq(this.previous), 12416 next = this.core.$stage.children().eq(this.next), 12417 incoming = this.core.settings.animateIn, 12418 outgoing = this.core.settings.animateOut; 12419 12420 if (this.core.current() === this.previous) { 12421 return; 12422 } 12423 12424 if (outgoing) { 12425 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 12426 previous.css( { 'left': left + 'px' } ) 12427 .addClass('animated owl-animated-out') 12428 .addClass(outgoing) 12429 .on($.support.animation.end, clear); 12430 } 12431 12432 if (incoming) { 12433 next.addClass('animated owl-animated-in') 12434 .addClass(incoming) 12435 .on($.support.animation.end, clear); 12436 } 12437 }; 12438 12439 Animate.prototype.clear = function(e) { 12440 if ($(e.target).hasClass('animated')) { 12441 $(e.target).css( { 'left': '' } ) 12442 .removeClass('animated owl-animated-out owl-animated-in') 12443 .removeClass(this.core.settings.animateIn) 12444 .removeClass(this.core.settings.animateOut); 12445 this.core.onTransitionEnd(); 12446 } 12447 }; 12448 12449 /** 12450 * Destroys the plugin. 12451 * @public 12452 */ 12453 Animate.prototype.destroy = function() { 12454 var handler, property; 12455 12456 for (handler in this.handlers) { 12457 this.core.$element.off(handler, this.handlers[handler]); 12458 } 12459 for (property in Object.getOwnPropertyNames(this)) { 12460 typeof this[property] != 'function' && (this[property] = null); 12461 } 12462 }; 12463 12464 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 12465 12466})(window.Zepto || window.jQuery, window, document); 12467 12468/** 12469 * Autoplay Plugin 12470 * @version 2.0.0-beta.3 12471 * @author Bartosz Wojciechowski 12472 * @author Artus Kolanowski 12473 * @license The MIT License (MIT) 12474 */ 12475;(function($, window, document, undefined) { 12476 12477 /** 12478 * Creates the autoplay plugin. 12479 * @class The Autoplay Plugin 12480 * @param {Owl} scope - The Owl Carousel 12481 */ 12482 var Autoplay = function(carousel) { 12483 /** 12484 * Reference to the core. 12485 * @protected 12486 * @type {Owl} 12487 */ 12488 this._core = carousel; 12489 12490 /** 12491 * The autoplay interval. 12492 * @type {Number} 12493 */ 12494 this._interval = null; 12495 12496 /** 12497 * Indicates whenever the autoplay is paused. 12498 * @type {Boolean} 12499 */ 12500 this._paused = false; 12501 12502 /** 12503 * All event handlers. 12504 * @protected 12505 * @type {Object} 12506 */ 12507 this._handlers = { 12508 'changed.owl.carousel': $.proxy(function(e) { 12509 if (e.namespace && e.property.name === 'settings') { 12510 if (this._core.settings.autoplay) { 12511 this.play(); 12512 } else { 12513 this.stop(); 12514 } 12515 } 12516 }, this), 12517 'initialized.owl.carousel': $.proxy(function(e) { 12518 if (e.namespace && this._core.settings.autoplay) { 12519 this.play(); 12520 } 12521 }, this), 12522 'play.owl.autoplay': $.proxy(function(e, t, s) { 12523 if (e.namespace) { 12524 this.play(t, s); 12525 } 12526 }, this), 12527 'stop.owl.autoplay': $.proxy(function(e) { 12528 if (e.namespace) { 12529 this.stop(); 12530 } 12531 }, this), 12532 'mouseover.owl.autoplay': $.proxy(function() { 12533 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12534 this.pause(); 12535 } 12536 }, this), 12537 'mouseleave.owl.autoplay': $.proxy(function() { 12538 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 12539 this.play(); 12540 } 12541 }, this) 12542 }; 12543 12544 // register event handlers 12545 this._core.$element.on(this._handlers); 12546 12547 // set default options 12548 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 12549 }; 12550 12551 /** 12552 * Default options. 12553 * @public 12554 */ 12555 Autoplay.Defaults = { 12556 autoplay: false, 12557 autoplayTimeout: 5000, 12558 autoplayHoverPause: false, 12559 autoplaySpeed: false 12560 }; 12561 12562 /** 12563 * Starts the autoplay. 12564 * @public 12565 * @param {Number} [timeout] - The interval before the next animation starts. 12566 * @param {Number} [speed] - The animation speed for the animations. 12567 */ 12568 Autoplay.prototype.play = function(timeout, speed) { 12569 this._paused = false; 12570 12571 if (this._core.is('rotating')) { 12572 return; 12573 } 12574 12575 this._core.enter('rotating'); 12576 12577 this._interval = window.setInterval($.proxy(function() { 12578 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 12579 return; 12580 } 12581 this._core.next(speed || this._core.settings.autoplaySpeed); 12582 }, this), timeout || this._core.settings.autoplayTimeout); 12583 }; 12584 12585 /** 12586 * Stops the autoplay. 12587 * @public 12588 */ 12589 Autoplay.prototype.stop = function() { 12590 if (!this._core.is('rotating')) { 12591 return; 12592 } 12593 12594 window.clearInterval(this._interval); 12595 this._core.leave('rotating'); 12596 }; 12597 12598 /** 12599 * Stops the autoplay. 12600 * @public 12601 */ 12602 Autoplay.prototype.pause = function() { 12603 if (!this._core.is('rotating')) { 12604 return; 12605 } 12606 12607 this._paused = true; 12608 }; 12609 12610 /** 12611 * Destroys the plugin. 12612 */ 12613 Autoplay.prototype.destroy = function() { 12614 var handler, property; 12615 12616 this.stop(); 12617 12618 for (handler in this._handlers) { 12619 this._core.$element.off(handler, this._handlers[handler]); 12620 } 12621 for (property in Object.getOwnPropertyNames(this)) { 12622 typeof this[property] != 'function' && (this[property] = null); 12623 } 12624 }; 12625 12626 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 12627 12628})(window.Zepto || window.jQuery, window, document); 12629 12630/** 12631 * Navigation Plugin 12632 * @version 2.0.0-beta.3 12633 * @author Artus Kolanowski 12634 * @license The MIT License (MIT) 12635 */ 12636;(function($, window, document, undefined) { 12637 'use strict'; 12638 12639 /** 12640 * Creates the navigation plugin. 12641 * @class The Navigation Plugin 12642 * @param {Owl} carousel - The Owl Carousel. 12643 */ 12644 var Navigation = function(carousel) { 12645 /** 12646 * Reference to the core. 12647 * @protected 12648 * @type {Owl} 12649 */ 12650 this._core = carousel; 12651 12652 /** 12653 * Indicates whether the plugin is initialized or not. 12654 * @protected 12655 * @type {Boolean} 12656 */ 12657 this._initialized = false; 12658 12659 /** 12660 * The current paging indexes. 12661 * @protected 12662 * @type {Array} 12663 */ 12664 this._pages = []; 12665 12666 /** 12667 * All DOM elements of the user interface. 12668 * @protected 12669 * @type {Object} 12670 */ 12671 this._controls = {}; 12672 12673 /** 12674 * Markup for an indicator. 12675 * @protected 12676 * @type {Array.<String>} 12677 */ 12678 this._templates = []; 12679 12680 /** 12681 * The carousel element. 12682 * @type {jQuery} 12683 */ 12684 this.$element = this._core.$element; 12685 12686 /** 12687 * Overridden methods of the carousel. 12688 * @protected 12689 * @type {Object} 12690 */ 12691 this._overrides = { 12692 next: this._core.next, 12693 prev: this._core.prev, 12694 to: this._core.to 12695 }; 12696 12697 /** 12698 * All event handlers. 12699 * @protected 12700 * @type {Object} 12701 */ 12702 this._handlers = { 12703 'prepared.owl.carousel': $.proxy(function(e) { 12704 if (e.namespace && this._core.settings.dotsData) { 12705 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 12706 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 12707 } 12708 }, this), 12709 'added.owl.carousel': $.proxy(function(e) { 12710 if (e.namespace && this._core.settings.dotsData) { 12711 this._templates.splice(e.position, 0, this._templates.pop()); 12712 } 12713 }, this), 12714 'remove.owl.carousel': $.proxy(function(e) { 12715 if (e.namespace && this._core.settings.dotsData) { 12716 this._templates.splice(e.position, 1); 12717 } 12718 }, this), 12719 'changed.owl.carousel': $.proxy(function(e) { 12720 if (e.namespace && e.property.name == 'position') { 12721 this.draw(); 12722 } 12723 }, this), 12724 'initialized.owl.carousel': $.proxy(function(e) { 12725 if (e.namespace && !this._initialized) { 12726 this._core.trigger('initialize', null, 'navigation'); 12727 this.initialize(); 12728 this.update(); 12729 this.draw(); 12730 this._initialized = true; 12731 this._core.trigger('initialized', null, 'navigation'); 12732 } 12733 }, this), 12734 'refreshed.owl.carousel': $.proxy(function(e) { 12735 if (e.namespace && this._initialized) { 12736 this._core.trigger('refresh', null, 'navigation'); 12737 this.update(); 12738 this.draw(); 12739 this._core.trigger('refreshed', null, 'navigation'); 12740 } 12741 }, this) 12742 }; 12743 12744 // set default options 12745 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 12746 12747 // register event handlers 12748 this.$element.on(this._handlers); 12749 }; 12750 12751 /** 12752 * Default options. 12753 * @public 12754 * @todo Rename `slideBy` to `navBy` 12755 */ 12756 Navigation.Defaults = { 12757 nav: false, 12758 navText: [ 'prev', 'next' ], 12759 navSpeed: false, 12760 navElement: 'div', 12761 navContainer: false, 12762 navContainerClass: 'owl-nav', 12763 navClass: [ 'owl-prev', 'owl-next' ], 12764 slideBy: 1, 12765 dotClass: 'owl-dot', 12766 dotsClass: 'owl-dots', 12767 dots: true, 12768 dotsEach: false, 12769 dotsData: false, 12770 dotsSpeed: false, 12771 dotsContainer: false 12772 }; 12773 12774 /** 12775 * Initializes the layout of the plugin and extends the carousel. 12776 * @protected 12777 */ 12778 Navigation.prototype.initialize = function() { 12779 var override, 12780 settings = this._core.settings; 12781 12782 // create DOM structure for relative navigation 12783 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 12784 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 12785 12786 this._controls.$previous = $('<' + settings.navElement + '>') 12787 .addClass(settings.navClass[0]) 12788 .html(settings.navText[0]) 12789 .prependTo(this._controls.$relative) 12790 .on('click', $.proxy(function(e) { 12791 this.prev(settings.navSpeed); 12792 }, this)); 12793 this._controls.$next = $('<' + settings.navElement + '>') 12794 .addClass(settings.navClass[1]) 12795 .html(settings.navText[1]) 12796 .appendTo(this._controls.$relative) 12797 .on('click', $.proxy(function(e) { 12798 this.next(settings.navSpeed); 12799 }, this)); 12800 12801 // create DOM structure for absolute navigation 12802 if (!settings.dotsData) { 12803 this._templates = [ $('<div>') 12804 .addClass(settings.dotClass) 12805 .append($('<span>')) 12806 .prop('outerHTML') ]; 12807 } 12808 12809 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 12810 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 12811 12812 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 12813 var index = $(e.target).parent().is(this._controls.$absolute) 12814 ? $(e.target).index() : $(e.target).parent().index(); 12815 12816 e.preventDefault(); 12817 12818 this.to(index, settings.dotsSpeed); 12819 }, this)); 12820 12821 // override public methods of the carousel 12822 for (override in this._overrides) { 12823 this._core[override] = $.proxy(this[override], this); 12824 } 12825 }; 12826 12827 /** 12828 * Destroys the plugin. 12829 * @protected 12830 */ 12831 Navigation.prototype.destroy = function() { 12832 var handler, control, property, override; 12833 12834 for (handler in this._handlers) { 12835 this.$element.off(handler, this._handlers[handler]); 12836 } 12837 for (control in this._controls) { 12838 this._controls[control].remove(); 12839 } 12840 for (override in this.overides) { 12841 this._core[override] = this._overrides[override]; 12842 } 12843 for (property in Object.getOwnPropertyNames(this)) { 12844 typeof this[property] != 'function' && (this[property] = null); 12845 } 12846 }; 12847 12848 /** 12849 * Updates the internal state. 12850 * @protected 12851 */ 12852 Navigation.prototype.update = function() { 12853 var i, j, k, 12854 lower = this._core.clones().length / 2, 12855 upper = lower + this._core.items().length, 12856 maximum = this._core.maximum(true), 12857 settings = this._core.settings, 12858 size = settings.center || settings.autoWidth || settings.dotsData 12859 ? 1 : settings.dotsEach || settings.items; 12860 12861 if (settings.slideBy !== 'page') { 12862 settings.slideBy = Math.min(settings.slideBy, settings.items); 12863 } 12864 12865 if (settings.dots || settings.slideBy == 'page') { 12866 this._pages = []; 12867 12868 for (i = lower, j = 0, k = 0; i < upper; i++) { 12869 if (j >= size || j === 0) { 12870 this._pages.push({ 12871 start: Math.min(maximum, i - lower), 12872 end: i - lower + size - 1 12873 }); 12874 if (Math.min(maximum, i - lower) === maximum) { 12875 break; 12876 } 12877 j = 0, ++k; 12878 } 12879 j += this._core.mergers(this._core.relative(i)); 12880 } 12881 } 12882 }; 12883 12884 /** 12885 * Draws the user interface. 12886 * @todo The option `dotsData` wont work. 12887 * @protected 12888 */ 12889 Navigation.prototype.draw = function() { 12890 var difference, 12891 settings = this._core.settings, 12892 disabled = this._core.items().length <= settings.items, 12893 index = this._core.relative(this._core.current()), 12894 loop = settings.loop || settings.rewind; 12895 12896 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 12897 12898 if (settings.nav) { 12899 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 12900 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 12901 } 12902 12903 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 12904 12905 if (settings.dots) { 12906 difference = this._pages.length - this._controls.$absolute.children().length; 12907 12908 if (settings.dotsData && difference !== 0) { 12909 this._controls.$absolute.html(this._templates.join('')); 12910 } else if (difference > 0) { 12911 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 12912 } else if (difference < 0) { 12913 this._controls.$absolute.children().slice(difference).remove(); 12914 } 12915 12916 this._controls.$absolute.find('.active').removeClass('active'); 12917 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 12918 } 12919 }; 12920 12921 /** 12922 * Extends event data. 12923 * @protected 12924 * @param {Event} event - The event object which gets thrown. 12925 */ 12926 Navigation.prototype.onTrigger = function(event) { 12927 var settings = this._core.settings; 12928 12929 event.page = { 12930 index: $.inArray(this.current(), this._pages), 12931 count: this._pages.length, 12932 size: settings && (settings.center || settings.autoWidth || settings.dotsData 12933 ? 1 : settings.dotsEach || settings.items) 12934 }; 12935 }; 12936 12937 /** 12938 * Gets the current page position of the carousel. 12939 * @protected 12940 * @returns {Number} 12941 */ 12942 Navigation.prototype.current = function() { 12943 var current = this._core.relative(this._core.current()); 12944 return $.grep(this._pages, $.proxy(function(page, index) { 12945 return page.start <= current && page.end >= current; 12946 }, this)).pop(); 12947 }; 12948 12949 /** 12950 * Gets the current succesor/predecessor position. 12951 * @protected 12952 * @returns {Number} 12953 */ 12954 Navigation.prototype.getPosition = function(successor) { 12955 var position, length, 12956 settings = this._core.settings; 12957 12958 if (settings.slideBy == 'page') { 12959 position = $.inArray(this.current(), this._pages); 12960 length = this._pages.length; 12961 successor ? ++position : --position;
vendor: 5,670 bytes, lines 12962-13186
12962 position = this._pages[((position % length) + length) % length].start; 12963 } else { 12964 position = this._core.relative(this._core.current()); 12965 length = this._core.items().length; 12966 successor ? position += settings.slideBy : position -= settings.slideBy; 12967 } 12968 12969 return position; 12970 }; 12971 12972 /** 12973 * Slides to the next item or page. 12974 * @public 12975 * @param {Number} [speed=false] - The time in milliseconds for the transition. 12976 */ 12977 Navigation.prototype.next = function(speed) { 12978 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 12979 }; 12980 12981 /** 12982 * Slides to the previous item or page. 12983 * @public 12984 * @param {Number} [speed=false] - The time in milliseconds for the transition. 12985 */ 12986 Navigation.prototype.prev = function(speed) { 12987 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 12988 }; 12989 12990 /** 12991 * Slides to the specified item or page. 12992 * @public 12993 * @param {Number} position - The position of the item or page. 12994 * @param {Number} [speed] - The time in milliseconds for the transition. 12995 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 12996 */ 12997 Navigation.prototype.to = function(position, speed, standard) { 12998 var length; 12999 13000 if (!standard) { 13001 length = this._pages.length; 13002 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 13003 } else { 13004 $.proxy(this._overrides.to, this._core)(position, speed); 13005 } 13006 }; 13007 13008 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 13009 13010})(window.Zepto || window.jQuery, window, document); 13011 13012/** 13013 * Hash Plugin 13014 * @version 2.0.0-beta.3 13015 * @author Artus Kolanowski 13016 * @license The MIT License (MIT) 13017 */ 13018;(function($, window, document, undefined) { 13019 'use strict'; 13020 13021 /** 13022 * Creates the hash plugin. 13023 * @class The Hash Plugin 13024 * @param {Owl} carousel - The Owl Carousel 13025 */ 13026 var Hash = function(carousel) { 13027 /** 13028 * Reference to the core. 13029 * @protected 13030 * @type {Owl} 13031 */ 13032 this._core = carousel; 13033 13034 /** 13035 * Hash index for the items. 13036 * @protected 13037 * @type {Object} 13038 */ 13039 this._hashes = {}; 13040 13041 /** 13042 * The carousel element. 13043 * @type {jQuery} 13044 */ 13045 this.$element = this._core.$element; 13046 13047 /** 13048 * All event handlers. 13049 * @protected 13050 * @type {Object} 13051 */ 13052 this._handlers = { 13053 'initialized.owl.carousel': $.proxy(function(e) { 13054 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 13055 $(window).trigger('hashchange.owl.navigation'); 13056 } 13057 }, this), 13058 'prepared.owl.carousel': $.proxy(function(e) { 13059 if (e.namespace) { 13060 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 13061 13062 if (!hash) { 13063 return; 13064 } 13065 13066 this._hashes[hash] = e.content; 13067 } 13068 }, this), 13069 'changed.owl.carousel': $.proxy(function(e) { 13070 if (e.namespace && e.property.name === 'position') { 13071 var current = this._core.items(this._core.relative(this._core.current())), 13072 hash = $.map(this._hashes, function(item, hash) { 13073 return item === current ? hash : null; 13074 }).join(); 13075 13076 if (!hash || window.location.hash.slice(1) === hash) { 13077 return; 13078 } 13079 13080 window.location.hash = hash; 13081 } 13082 }, this) 13083 }; 13084 13085 // set default options 13086 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 13087 13088 // register the event handlers 13089 this.$element.on(this._handlers); 13090 13091 // register event listener for hash navigation 13092 $(window).on('hashchange.owl.navigation', $.proxy(function(e) { 13093 var hash = window.location.hash.substring(1), 13094 items = this._core.$stage.children(), 13095 position = this._hashes[hash] && items.index(this._hashes[hash]); 13096 13097 if (position === undefined || position === this._core.current()) { 13098 return; 13099 } 13100 13101 this._core.to(this._core.relative(position), false, true); 13102 }, this)); 13103 }; 13104 13105 /** 13106 * Default options. 13107 * @public 13108 */ 13109 Hash.Defaults = { 13110 URLhashListener: false 13111 }; 13112 13113 /** 13114 * Destroys the plugin. 13115 * @public 13116 */ 13117 Hash.prototype.destroy = function() { 13118 var handler, property; 13119 13120 $(window).off('hashchange.owl.navigation'); 13121 13122 for (handler in this._handlers) { 13123 this._core.$element.off(handler, this._handlers[handler]); 13124 } 13125 for (property in Object.getOwnPropertyNames(this)) { 13126 typeof this[property] != 'function' && (this[property] = null); 13127 } 13128 }; 13129 13130 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 13131 13132})(window.Zepto || window.jQuery, window, document); 13133 13134/** 13135 * Support Plugin 13136 * 13137 * @version 2.0.0-beta.3 13138 * @author Vivid Planet Software GmbH 13139 * @author Artus Kolanowski 13140 * @license The MIT License (MIT) 13141 */ 13142;(function($, window, document, undefined) { 13143 13144 var style = $('<support>').get(0).style, 13145 prefixes = 'Webkit Moz O ms'.split(' '), 13146 events = { 13147 transition: { 13148 end: { 13149 WebkitTransition: 'webkitTransitionEnd', 13150 MozTransition: 'transitionend', 13151 OTransition: 'oTransitionEnd', 13152 transition: 'transitionend' 13153 } 13154 }, 13155 animation: { 13156 end: { 13157 WebkitAnimation: 'webkitAnimationEnd', 13158 MozAnimation: 'animationend', 13159 OAnimation: 'oAnimationEnd', 13160 animation: 'animationend' 13161 } 13162 } 13163 }, 13164 tests = { 13165 csstransforms: function() { 13166 return !!test('transform'); 13167 }, 13168 csstransforms3d: function() { 13169 return !!test('perspective'); 13170 }, 13171 csstransitions: function() { 13172 return !!test('transition'); 13173 }, 13174 cssanimations: function() { 13175 return !!test('animation'); 13176 } 13177 }; 13178 13179 function test(property, prefixed) { 13180 var result = false, 13181 upper = property.charAt(0).toUpperCase() + property.slice(1); 13182 13183 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 13184 if (style[property] !== undefined) { 13185 result = prefixed ? property : true; 13186 return false;
13187 } 13188 }); 13189 13190 return result; 13191 } 13192 13193 function prefixed(property) { 13194 return test(property, true); 13195 } 13196 13197 if (tests.csstransitions()) { 13198 /* jshint -W053 */ 13199 $.support.transition = new String(prefixed('transition')) 13200 $.support.transition.end = events.transition.end[ $.support.transition ]; 13201 } 13202 13203 if (tests.cssanimations()) { 13204 /* jshint -W053 */ 13205 $.support.animation = new String(prefixed('animation')) 13206 $.support.animation.end = events.animation.end[ $.support.animation ]; 13207 } 13208 13209 if (tests.csstransforms()) { 13210 /* jshint -W053 */ 13211 $.support.transform = new String(prefixed('transform')); 13212 $.support.transform3d = tests.csstransforms3d(); 13213 } 13214 13215})(window.Zepto || window.jQuery, window, document); 13216 13217(function(window, document, undefined) { 13218 13219 /** 13220 * Find the absolute position of an element 13221 */ 13222 var absPos = function(element) { 13223 var offsetLeft, offsetTop; 13224 offsetLeft = offsetTop = 0; 13225 if (element.offsetParent) { 13226 do { 13227 offsetLeft += element.offsetLeft; 13228 offsetTop += element.offsetTop; 13229 } while (element = element.offsetParent); 13230 } 13231 return [offsetLeft, offsetTop]; 13232 }; 13233 13234 /** 13235 * @constructor Progress Circle class 13236 * @param params.canvas Canvas on which the circles will be drawn. 13237 * @param params.minRadius Inner radius of the innermost circle, in px. 13238 * @param params.arcWidth Width of each circle(to be more accurate, ring). 13239 * @param params.gapWidth Space between each circle. 13240 * @param params.centerX X coordinate of the center of circles. 13241 * @param params.centerY Y coordinate of the center of circles. 13242 * @param params.infoLineBaseAngle Base angle of the info line. 13243 * @param params.infoLineAngleInterval Angles between the info lines. 13244 */ 13245 var ProgressCircle = function(params) { 13246 this.canvas = params.canvas; 13247 this.minRadius = params.minRadius || 15; 13248 this.arcWidth = params.arcWidth || 5; 13249 this.gapWidth = params.gapWidth || 3; 13250 this.centerX = params.centerX || this.canvas.width / 2; 13251 this.centerY = params.centerY || this.canvas.height / 2;
13252 this.infoLineLength = params.infoLineLength || 60; 13253 this.horizLineLength = params.horizLineLength || 10; 13254 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 13255 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 13256 13257 this.context = this.canvas.getContext('2d'); 13258 13259 this.width = this.canvas.width; 13260 this.height = this.canvas.height; 13261 13262 this.circles = []; 13263 this.runningCount = 0; 13264 }; 13265 13266 ProgressCircle.prototype = { 13267 constructor: ProgressCircle, 13268 13269 /** 13270 * @method Adds an progress monitor entry. 13271 * @param params.fillColor Color to fill in the circle. 13272 * @param params.outlineColor Color to outline the circle. 13273 * @param params.progressListener Callback function to fetch the progress. 13274 * @param params.infoListener Callback function to fetch the info. 13275 * @returns this 13276 */ 13277 addEntry: function(params) { 13278 this.circles.push(new Circle({ 13279 canvas: this.canvas, 13280 context: this.context, 13281 centerX: this.centerX, 13282 centerY: this.centerY, 13283 innerRadius: this.minRadius + this.circles.length * 13284 (this.gapWidth + this.arcWidth), 13285 arcWidth: this.arcWidth,
13286 infoLineLength: this.infoLineLength, 13287 horizLineLength: this.horizLineLength, 13288 13289 id: this.circles.length, 13290 fillColor: params.fillColor, 13291 outlineColor: params.outlineColor, 13292 progressListener: params.progressListener, 13293 infoListener: params.infoListener, 13294 infoLineAngle: this.infoLineBaseAngle + 13295 this.circles.length * this.infoLineAngleInterval, 13296 })); 13297 13298 return this; 13299 }, 13300 13301 /** 13302 * @method Starts the monitor and updates with the given interval. 13303 * @param interval Interval between updates, in millisecond. 13304 * @returns this 13305 */ 13306 start: function(interval) { 13307 var self = this; 13308 this.timer = setInterval(function() { 13309 self._update(); 13310 }, interval || 33); 13311 13312 return this; 13313 }, 13314 13315 /** 13316 * @method Stop the animation. 13317 */ 13318 stop: function() { 13319 clearTimeout(this.timer); 13320 }, 13321 13322 /** 13323 * @private 13324 * @method Call update on each circle and redraw them. 13325 * @returns this 13326 */ 13327 _update: function() { 13328 this._clear(); 13329 this.circles.forEach(function(circle, idx, array) { 13330 circle.update(); 13331 }); 13332 13333 return this; 13334 }, 13335 13336 /** 13337 * @private 13338 * @method Clear the canvas. 13339 * @returns this 13340 */ 13341 _clear: function() { 13342 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 13343 13344 return this; 13345 }, 13346 13347 }; 13348 13349 /** 13350 * @private 13351 * @class Individual progress circle. 13352 * @param params.canvas Canvas on which the circle will be drawn. 13353 * @param params.context Context of the canvas. 13354 * @param params.innerRadius Inner radius of the circle, in px. 13355 * @param params.arcWidth Width of each arc(circle). 13356 * @param params.gapWidth Distance between each arc. 13357 * @param params.centerX X coordinate of the center of circles. 13358 * @param params.centerY Y coordinate of the center of circles. 13359 * @param params.fillColor Color to fill in the circle. 13360 * @param params.outlineColor Color to outline the circle. 13361 * @param params.progressListener Callback function to fetch the progress. 13362 * @param params.infoListener Callback function to fetch the info. 13363 * @param params.infoLineAngle Angle of info line. 13364 */ 13365 var Circle = function(params) { 13366 this.id = params.id; 13367 this.canvas = params.canvas; 13368 this.context = params.context; 13369 this.centerX = params.centerX; 13370 this.centerY = params.centerY; 13371 this.arcWidth = params.arcWidth; 13372 this.innerRadius = params.innerRadius || 0; 13373 this.fillColor = params.fillColor || '#fff'; 13374 this.outlineColor = params.outlineColor || this.fillColor; 13375 this.progressListener = params.progressListener;
13376 this.infoLineLength = params.infoLineLength || 250; 13377 this.horizLineLength = params.horizLineLength || 50; 13378 this.infoListener = params.infoListener; 13379 this.infoLineAngle = params.infoLineAngle; 13380 13381 this.outerRadius = this.innerRadius + this.arcWidth; 13382 13383 // If the info listener is not registered, then don't calculate 13384 // the related coordinates 13385 if (!this.infoListener) return; 13386 13387 // calculate the info-line turning points 13388 var angle = this.infoLineAngle, 13389 arcDistance = (this.innerRadius + this.outerRadius) / 2, 13390 13391 sinA = Math.sin(angle), 13392 cosA = Math.cos(angle); 13393 13394 this.infoLineStartX = this.centerX + sinA * arcDistance; 13395 this.infoLineStartY = this.centerY - cosA * arcDistance; 13396 13397 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 13398 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 13399 13400 this.infoLineEndX = this.infoLineMidX + 13401 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 13402 this.infoLineEndY = this.infoLineMidY; 13403 13404 var infoText = document.createElement('div'), 13405 style = infoText.style; 13406 13407 style.color = this.fillColor; 13408 style.position = 'absolute'; 13409 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 13410 // style.top will be calculated in the `drawInfo` method. Since 13411 // user may want to change the size of the font, so the top offset 13412 // must be updated in each loop. 13413 infoText.className = 'ProgressCircleInfo'; // For css styling 13414 infoText.id = 'progress_circle_info_' + this.id; 13415 document.body.appendChild(infoText); 13416 this.infoText = infoText; 13417 }; 13418 13419 Circle.prototype = { 13420 constructor: Circle, 13421 13422 update: function() { 13423 this.progress = this.progressListener(); 13424 this._draw(); 13425 13426 if (this.infoListener) { 13427 this.info = this.infoListener(); 13428 this._drawInfo(); 13429 } 13430 }, 13431 13432 /** 13433 * @private 13434 * @method Draw the circle on the canvas. 13435 * @returns this 13436 */ 13437 _draw: function() { 13438 var ctx = this.context, 13439 13440 ANGLE_OFFSET = -Math.PI / 2, 13441 13442 startAngle = 0 + ANGLE_OFFSET, 13443 endAngle= startAngle + this.progress * Math.PI * 2, 13444 13445 x = this.centerX, 13446 y = this.centerY, 13447 13448 innerRadius = this.innerRadius - this.arcWidth - 1, 13449 outerRadius = this.outerRadius - this.arcWidth - 1; 13450 13451 ctx.fillStyle = this.fillColor; 13452 ctx.strokeStyle = this.outlineColor; 13453 13454 ctx.beginPath(); 13455 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 13456 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 13457 ctx.closePath(); 13458 ctx.stroke(); 13459 ctx.fill(); 13460 13461 return this; 13462 }, 13463 13464 /** 13465 * @private 13466 * @method Draw the info lines and info text. 13467 * @returns this 13468 */ 13469 _drawInfo: function() { 13470 13471 var pointList, lineHeight; 13472 13473 pointList = [ 13474 [this.infoLineStartX, this.infoLineStartY], 13475 [this.infoLineMidX, this.infoLineMidY], 13476 [this.infoLineEndX, this.infoLineEndY], 13477 ]; 13478 this._drawSegments(pointList, false); 13479 13480 this.infoText.innerHTML = this.info; 13481 13482 lineHeight = this.infoText.offsetHeight; 13483 this.infoText.style.top = this.infoLineEndY + 13484 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 13485 13486 return this; 13487 }, 13488 13489 /** 13490 * @private 13491 * @method Helper function to draw the segments 13492 * @param pointList An array of points in the form of [x, y]. 13493 * @param close Whether to connect the first and last point. 13494 */ 13495 _drawSegments: function(pointList, close) { 13496 var ctx = this.context; 13497 13498 ctx.beginPath(); 13499 ctx.moveTo(pointList[0][0], pointList[0][1]); 13500 for (var i = 1; i < pointList.length; ++i) { 13501 ctx.lineTo(pointList[i][0], pointList[i][1]); 13502 } 13503 13504 if (close) { 13505 ctx.closePath(); 13506 } 13507 ctx.stroke(); 13508 }, 13509 }; 13510 13511 window.ProgressCircle = ProgressCircle; 13512 13513})(window, document); 13514 13515 13516 13517 13518/* ========================================================= 13519 * jquery.vc_chart.js v1.0 13520 * ========================================================= 13521 * Copyright 2013 Wpbakery 13522 * 13523 * Jquery chart plugin for the Visual Composer.
13524 * ========================================================= */ 13525(function($){ 13526 /** 13527 * Pie chart animated. 13528 * @param element - DOM element 13529 * @param options - settings object. 13530 * @constructor 13531 */ 13532 var VcChart = function(element, options) { 13533 this.el = element; 13534 this.$el = $(this.el); 13535 this.options = $.extend({ 13536 color: 'wpb_button', 13537 units: '', 13538 width: '', 13539 label_selector: '.vc_pie_chart_value', 13540 back_selector: '.vc_pie_chart_back', 13541 responsive: true 13542 }, options); 13543 this.init(); 13544 }; 13545 VcChart.prototype = { 13546 constructor: VcChart, 13547 _progress_v: 0, 13548 animated: false, 13549 colors: { 13550 'wpb_button': 'rgba(247, 247, 247, 1)', 13551 'btn-primary': 'rgba(0, 136, 204, 1)', 13552 'btn-info': 'rgba(88, 185, 218, 1)', 13553 'btn-success': 'rgba(106, 177, 101, 1)', 13554 'btn-warning': 'rgba(255, 153, 0, 1)', 13555 'btn-danger': 'rgba(255, 103, 91, 1)', 13556 'btn-inverse': 'rgba(85, 85, 85, 1)' 13557 }, 13558 init: function() { 13559 this.setupColor(); 13560 this.value = this.$el.data('pie-value')/100; 13561 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 13562 this.$wrapper = $('.vc_pie_wrapper', this.$el); 13563 this.$label = $(this.options.label_selector, this.$el); 13564 this.$back = $(this.options.back_selector, this.$el); 13565 this.$canvas = this.$el.find('canvas'); 13566 this.arcWidth = this.$el.data('pie-width') * 2; 13567 this.draw(); 13568 this.setWayPoint(); 13569 if(this.options.responsive === true) this.setResponsive(); 13570 if (UNCODE.isMobile) this._progress_v = this.value; 13571 }, 13572 setupColor: function() { 13573 // if(typeof this.colors[this.options.color] !== 'undefined') { 13574 // this.color = this.colors[this.options.color]; 13575 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 13576 // this.color = this.options.color; 13577 // } else { 13578 // this.color = 'rgba(247, 247, 247, 0.2)'; 13579 // } 13580 if(typeof this.options.color !== 'undefined') { 13581 this.color = this.options.color; 13582 } else this.color = 'rgba(247, 247, 247, 0.2)'; 13583 13584 }, 13585 setResponsive: function() { 13586 var that = this; 13587 if (!UNCODE.isMobile) { 13588 $(window).resize(function(){ 13589 if(that.animated === true) that.circle.stop(); 13590 that.draw(true); 13591 }); 13592 } 13593 }, 13594 draw: function(redraw) { 13595 var w = this.$el.addClass('vc_ready').width() * 2, 13596 border_w = this.arcWidth, 13597 radius; 13598 if(!w) w = this.$el.parents(':visible').first().width()-2; 13599 //w = Math.round(w/100*80); 13600 //if (w < 250) w = 250; 13601 radius = w/2; 13602 this.$wrapper.css({"width" : (w / 2) + "px"}); 13603 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 13604 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 13605 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 13606 this.$el.addClass('vc_ready'); 13607 this.circle = new ProgressCircle({ 13608 canvas: this.$canvas.get(0), 13609 minRadius: radius, 13610 arcWidth: border_w 13611 }); 13612 if(redraw === true && this.animated === true) { 13613 this._progress_v = this.value; 13614 this.circle.addEntry({ 13615 fillColor: this.color, 13616 progressListener: $.proxy(this.setProgress, this) 13617 }).start(); 13618 } 13619 }, 13620 setProgress: function() { 13621 if (this._progress_v >= this.value) { 13622 this.circle.stop(); 13623 this.$label.html(this.label_value + this.options.units); 13624 return this._progress_v; 13625 } 13626 this._progress_v += 0.01; 13627 if (!isNaN(this.label_value)) { 13628 var label_value = this._progress_v/this.value*this.label_value; 13629 var val = Math.round(label_value) + this.options.units; 13630 this.$label.html(val); 13631 } else this.$label.html(this.label_value + this.options.units); 13632 return this._progress_v; 13633 }, 13634 animate: function() { 13635 if(this.animated !== true) { 13636 this.animated = true; 13637 this.circle.addEntry({ 13638 fillColor: this.color, 13639 progressListener: $.proxy(this.setProgress, this) 13640 }).start(5); 13641 } 13642 }, 13643 setWayPoint: function() { 13644 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 13645 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 13646 } else { 13647 this.animate(); 13648 } 13649 } 13650 }; 13651 /** 13652 * jQuery plugin 13653 * @param option - object with settings 13654 * @return {*} 13655 */ 13656 $.fn.vcChat = function(option, value) { 13657 return this.each(function () { 13658 var $this = $(this), 13659 data = $this.data('vc_chart'), 13660 options = typeof option === 'object' ? option : { 13661 color: $this.data('pie-color'), 13662 units: $this.data('pie-units') 13663 }; 13664 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 13665 if (typeof option == 'string') data[option](value); 13666 }); 13667 }; 13668 /** 13669 * Allows users to rewrite function inside theme. 13670 */ 13671 if ( typeof window['vc_pieChart'] !== 'function' ) { 13672 window.vc_pieChart = function() { 13673 $('.vc_pie_chart:visible').vcChat(); 13674 } 13675 } 13676 $(document).ready(function(){ 13677 !window.vc_iframe && vc_pieChart(); 13678 }); 13679 13680})(window.jQuery); 13681 13682 13683/* Progress bar 13684 ---------------------------------------------------------- */ 13685function uncode_progress_bar() {    13686 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 13687 if (!UNCODE.isMobile) { 13688 new Waypoint({ 13689 element: val, 13690 handler: function() { 13691 var element = jQuery(this.element); 13692 element.find('.vc_single_bar').each(function(index) {          13693 var $this = jQuery(this), 13694             bar = $this.find('.vc_bar'), 13695             val = bar.data('percentage-value');          13696 setTimeout(function() {            13697 bar.css({ 13698 "width": val + '%' 13699 });          13700 }, index * 200);        13701 }); 13702 }, 13703 offset: '80%' 13704 }); 13705 } else { 13706 var element = jQuery(val); 13707 element.find('.vc_single_bar').each(function(index) {          13708 var $this = jQuery(this), 13709             bar = $this.find('.vc_bar'), 13710             val = bar.data('percentage-value');          13711 setTimeout(function() {            13712 bar.css({ 13713 "width": val + '%' 13714 });          13715 }, index * 200);        13716 }); 13717 } 13718 }); 13719}; 13720uncode_progress_bar(); 13721 13722/*! 13723 * jquery.counterup.js 1.0 13724 * 13725 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 13726 * Released under the GPL v2 License 13727 * 13728 * Date: Nov 26, 2013 13729 */ 13730(function($) { 13731 "use strict"; 13732 $.fn.counterUp = function(options) { 13733 // Defaults 13734 var settings = $.extend({ 13735 'time': 400, 13736 'delay': 10 13737 }, options); 13738 return this.each(function() { 13739 // Store the object 13740 var $this = $(this); 13741 var $settings = settings; 13742 var counterUpper = function() { 13743 var nums = []; 13744 var divisions = $settings.time / $settings.delay; 13745 var numReal = $this.text(), 13746 num = numReal; 13747 var isComma = /[0-9]+,[0-9]+/.test(num); 13748 num = num.replace(/,/g, ''); 13749 var isInt = /^[0-9]+$/.test(num); 13750 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 13751 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 13752 // Generate list of incremental numbers to display 13753 for (var i = divisions; i >= 1; i--) { 13754 // Preserve as int if input was int 13755 var newNum = parseInt(num / divisions * i); 13756 // Preserve float if input was float 13757 if (isFloat) { 13758 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 13759 } 13760 // Preserve commas if input had commas 13761 if (isComma) { 13762 while (/(\d+)(\d{3})/.test(newNum.toString())) { 13763 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 13764 } 13765 } 13766 nums.unshift(newNum); 13767 } 13768 nums.push(numReal); 13769 $this.data('counterup-nums', nums); 13770 $this.text('0'); 13771 // Updates the number until we're done 13772 var f = function() { 13773 if ($this.data('counterup-nums') != null) { 13774 $this.text($this.data('counterup-nums').shift()); 13775 if ($this.data('counterup-nums').length) { 13776 setTimeout($this.data('counterup-func'), $settings.delay); 13777 } else { 13778 delete $this.data('counterup-nums'); 13779 $this.data('counterup-nums', null); 13780 $this.data('counterup-func', null); 13781 } 13782 } 13783 }; 13784 $this.data('counterup-func', f); 13785 // Start the count up 13786 setTimeout($this.data('counterup-func'), $settings.delay); 13787 }; 13788 // Perform counts when the element gets into view 13789 if (!UNCODE.isMobile) { 13790 new Waypoint({ 13791 element: this, 13792 handler: function() { 13793 counterUpper(); 13794 this.destroy(); 13795 }, 13796 offset: '80%' 13797 }); 13798 } 13799 }); 13800 }; 13801})(jQuery); 13802 13803/*! 13804 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 13805 * Copyright (c) 2014 Edson Hilios 13806 * 13807 * Permission is hereby granted, free of charge, to any person obtaining a copy of 13808 * this software and associated documentation files (the "Software"), to deal in 13809 * the Software without restriction, including without limitation the rights to 13810 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13811 * the Software, and to permit persons to whom the Software is furnished to do so, 13812 * subject to the following conditions: 13813 * 13814 * The above copyright notice and this permission notice shall be included in all 13815 * copies or substantial portions of the Software. 13816 * 13817 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13818 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13819 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13820 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13821 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 13822 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13823 */ 13824!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){"use strict";function b(a){if(a instanceof Date)return a;
13824if(String(a).match(h))return String(a).match(/^[0-9]*$/)&&(a=Number(a)),String(a).match(/\-/)&&(a=String(a).replace(/\-/g,"/")),new Date(a);throw new Error("Couldn't cast `"+a+"` to a date object.")}function c(a){var b=a.toString().replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1");return new RegExp(b)}function d(a){return function(b){var d=b.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);if(d)for(var f=0,g=d.length;g>f;++f){var h=d[f].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/),j=c(h[0]),k=h[1]||"",l=h[3]||"",m=null;h=h[2],i.hasOwnProperty(h)&&(m=i[h],m=Number(a[m])),null!==m&&("!"===k&&(m=e(l,m)),""===k&&10>m&&(m="0"+m.toString()),b=b.replace(j,m.toString()))}return b=b.replace(/%%/,"%")}}function e(a,b){var c="s",d="";return a&&(a=a.replace(/(:|;|\s)/gi,"").split(/\,/),1===a.length?c=a[0]:(d=a[0],c=a[1])),1===Math.abs(b)?d:c}var f=100,g=[],h=[];h.push(/^[0-9]*$/.source),h.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),h.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),h=new RegExp(h.join("|"));var i={Y:"years",m:"months",w:"weeks",d:"days",D:"totalDays",H:"hours",M:"minutes",S:"seconds"},j=function(b,c,d){this.el=b,this.$el=a(b),this.interval=null,this.offset={},this.instanceNumber=g.length,g.push(this),this.$el.data("countdown-instance",this.instanceNumber),d&&(this.$el.on("update.countdown",d),this.$el.on("stoped.countdown",d),this.$el.on("finish.countdown",d)),this.setFinalDate(c),this.start()};a.extend(j.prototype,{start:function(){null!==this.interval&&clearInterval(this.interval);var a=this;this.update(),this.interval=setInterval(function(){a.update.call(a)},f)},stop:function(){clearInterval(this.interval),this.interval=null,this.dispatchEvent("stoped")},toggle:function(){this.interval?this.stop():this.start()},pause:function(){this.stop()},resume:function(){this.start()},remove:function(){this.stop.call(this),g[this.instanceNumber]=null,delete this.$el.data().countdownInstance},setFinalDate:function(a){this.finalDate=b(a)},update:function(){return 0===this.$el.closest("html").length?void this.remove():(this.totalSecsLeft=this.finalDate.getTime()-(new Date).getTime(),this.totalSecsLeft=Math.ceil(this.totalSecsLeft/1e3),this.totalSecsLeft=this.totalSecsLeft<0?0:this.totalSecsLeft,this.offset={seconds:this.totalSecsLeft%60,minutes:Math.floor(this.totalSecsLeft/60)%60,hours:Math.floor(this.totalSecsLeft/60/60)%24,days:Math.floor(this.totalSecsLeft/60/60/24)%7,totalDays:Math.floor(this.totalSecsLeft/60/60/24),weeks:Math.floor(this.totalSecsLeft/60/60/24/7),months:Math.floor(this.totalSecsLeft/60/60/24/30),years:Math.floor(this.totalSecsLeft/60/60/24/365)},void(0===this.totalSecsLeft?(this.stop(),this.dispatchEvent("finish")):this.dispatchEvent("update")))},dispatchEvent:function(b){var c=a.Event(b+".countdown");c.finalDate=this.finalDate,c.offset=a.extend({},this.offset),c.strftime=d(this.offset),this.$el.trigger(c)}}),a.fn.countdown=function(){var b=Array.prototype.slice.call(arguments,0);return this.each(function(){var c=a(this).data("countdown-instance");if(void 0!==c){var d=g[c],e=b[0];j.prototype.hasOwnProperty(e)?d[e].apply(d,b.slice(1)):null===String(e).match(/^[$A-Z_][0-9A-Z_$]*$/i)?(d.setFinalDate.call(d,e),d.start()):a.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi,e))}else new j(this,b[0],b[1])})}}); 13825 13826/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05 13827* https://github.com/alexanderdickson/waitForImages 13828* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 13829;(function (factory) { 13830 if (typeof define === 'function' && define.amd) { 13831 // AMD. Register as an anonymous module. 13832 define(['jquery'], factory); 13833 } else if (typeof exports === 'object') { 13834 // CommonJS / nodejs module 13835 module.exports = factory(require('jquery')); 13836 } else { 13837 // Browser globals 13838 factory(jQuery); 13839 } 13840}(function ($) { 13841 // Namespace all events. 13842 var eventNamespace = 'waitForImages'; 13843 13844 // CSS properties which contain references to images. 13845 $.waitForImages = { 13846 hasImageProperties: [ 13847 'backgroundImage', 13848 'listStyleImage', 13849 'borderImage', 13850 'borderCornerImage', 13851 'cursor' 13852 ], 13853 hasImageAttributes: ['srcset'] 13854 }; 13855 13856 // Custom selector to find `img` elements that have a valid `src` 13857 // attribute and have not already loaded. 13858 $.expr[':'].uncached = function (obj) { 13859 // Ensure we are dealing with an `img` element with a valid 13860 // `src` attribute. 13861 if (!$(obj).is('img[src][src!=""]')) { 13862 return false;
13863 } 13864 13865 return !obj.complete; 13866 }; 13867 13868 $.fn.waitForImages = function () { 13869 13870 var allImgsLength = 0; 13871 var allImgsLoaded = 0; 13872 var deferred = $.Deferred(); 13873 13874 var finishedCallback; 13875 var eachCallback; 13876 var waitForAll; 13877 13878 // Handle options object (if passed). 13879 if ($.isPlainObject(arguments[0])) { 13880 13881 waitForAll = arguments[0].waitForAll; 13882 eachCallback = arguments[0].each; 13883 finishedCallback = arguments[0].finished; 13884 13885 } else { 13886 13887 // Handle if using deferred object and only one param was passed in. 13888 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 13889 waitForAll = arguments[0]; 13890 } else { 13891 finishedCallback = arguments[0]; 13892 eachCallback = arguments[1]; 13893 waitForAll = arguments[2]; 13894 } 13895 13896 } 13897 13898 // Handle missing callbacks. 13899 finishedCallback = finishedCallback || $.noop; 13900 eachCallback = eachCallback || $.noop; 13901 13902 // Convert waitForAll to Boolean 13903 waitForAll = !! waitForAll; 13904 13905 // Ensure callbacks are functions. 13906 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 13907 throw new TypeError('An invalid callback was supplied.'); 13908 } 13909 13910 this.each(function () { 13911 // Build a list of all imgs, dependent on what images will 13912 // be considered. 13913 var obj = $(this); 13914 var allImgs = []; 13915 // CSS properties which may contain an image. 13916 var hasImgProperties = $.waitForImages.hasImageProperties || []; 13917 // Element attributes which may contain an image. 13918 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 13919 // To match `url()` references. 13920 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 13921 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 13922 13923 if (waitForAll) { 13924 13925 // Get all elements (including the original), as any one of 13926 // them could have a background image. 13927 obj.find('*').addBack().each(function () { 13928 var element = $(this); 13929 13930 // If an `img` element, add it. But keep iterating in 13931 // case it has a background image too. 13932 if (element.is('img:uncached')) { 13933 allImgs.push({ 13934 src: element.attr('src'), 13935 element: element[0] 13936 }); 13937 } 13938 13939 $.each(hasImgProperties, function (i, property) { 13940 var propertyValue = element.css(property); 13941 var match; 13942 13943 // If it doesn't contain this property, skip. 13944 if (!propertyValue) { 13945 return true; 13946 } 13947 13948 // Get all url() of this element. 13949 while (match = matchUrl.exec(propertyValue)) { 13950 allImgs.push({ 13951 src: match[2], 13952 element: element[0] 13953 }); 13954 } 13955 }); 13956 13957 $.each(hasImageAttributes, function (i, attribute) { 13958 var attributeValue = element.attr(attribute); 13959 var attributeValues; 13960 13961 // If it doesn't contain this property, skip. 13962 if (!attributeValue) { 13963 return true; 13964 } 13965 13966 // Check for multiple comma separated images 13967 attributeValues = attributeValue.split(','); 13968 13969 $.each(attributeValues, function(i, value) { 13970 // Trim value and get string before first 13971 // whitespace (for use with srcset). 13972 value = $.trim(value).split(' ')[0]; 13973 allImgs.push({ 13974 src: value, 13975 element: element[0] 13976 }); 13977 }); 13978 }); 13979 }); 13980 } else { 13981 // For images only, the task is simpler. 13982 obj.find('img:uncached') 13983 .each(function () { 13984 allImgs.push({ 13985 src: this.src, 13986 element: this 13987 }); 13988 }); 13989 } 13990 13991 allImgsLength = allImgs.length; 13992 allImgsLoaded = 0; 13993 13994 // If no images found, don't bother. 13995 if (allImgsLength === 0) { 13996 finishedCallback.call(obj[0]); 13997 deferred.resolveWith(obj[0]); 13998 } 13999 14000 $.each(allImgs, function (i, img) { 14001 14002 var image = new Image(); 14003 var events = 14004 'load.' + eventNamespace + ' error.' + eventNamespace; 14005 14006 // Handle the image loading and error with the same callback. 14007 $(image).one(events, function me (event) { 14008 // If an error occurred with loading the image, set the 14009 // third argument accordingly. 14010 var eachArguments = [ 14011 allImgsLoaded, 14012 allImgsLength,
14013 event.type == 'load' 14014 ]; 14015 allImgsLoaded++; 14016 14017 eachCallback.apply(img.element, eachArguments); 14018 deferred.notifyWith(img.element, eachArguments); 14019 14020 // Unbind the event listeners. I use this in addition to 14021 // `one` as one of those events won't be called (either 14022 // 'load' or 'error' will be called). 14023 $(this).off(events, me); 14024 14025 if (allImgsLoaded == allImgsLength) { 14026 finishedCallback.call(obj[0]); 14027 deferred.resolveWith(obj[0]); 14028 return false; 14029 } 14030 14031 }); 14032 14033 image.src = img.src; 14034 }); 14035 }); 14036 14037 return deferred.promise(); 14038 14039 }; 14040})); 14041 14042/** 14043 * @preserve textfill 14044 * @name jquery.textfill.js 14045 * @author Russ Painter 14046 * @author Yu-Jie Lin 14047 * @author Alexandre Dantas 14048 * @version 0.6.0 14049 * @date 2014-08-19 14050 * @copyright (c) 2014 Alexandre Dantas 14051 * @copyright (c) 2012-2013 Yu-Jie Lin 14052 * @copyright (c) 2009 Russ Painter 14053 * @license MIT License 14054 * @homepage https://github.com/jquery-textfill/jquery-textfill 14055 * @example http://jquery-textfill.github.io/jquery-textfill/index.html 14056 */ 14057; (function($) { 14058 14059 /** 14060 * Resizes an inner element's font so that the 14061 * inner element completely fills the outer element. 14062 * 14063 * @param {Object} options User options that take 14064 * higher precedence when 14065 * merging with the default ones. 14066 * 14067 * @return All outer elements processed 14068 */ 14069 $.fn.textfill = function(options) { 14070 14071 // ______ _______ _______ _______ _ _ _______ _______ 14072 // | \ |______ |______ |_____| | | | | |______ 14073 // |_____/ |______ | | | |_____| |_____ | ______| 14074 // 14075 // Merging user options with the default values 14076 14077 var defaults = { 14078 debug : false, 14079 maxFontPixels : 40, 14080 minFontPixels : 4, 14081 innerTag : 'span', 14082 widthOnly : false, 14083 success : null, // callback when a resizing is done 14084 callback : null, // callback when a resizing is done (deprecated, use success) 14085 fail : null, // callback when a resizing is failed 14086 complete : null, // callback when all is done 14087 explicitWidth : null, 14088 explicitHeight : null, 14089 changeLineHeight : false 14090 }; 14091 14092 var Opts = $.extend(defaults, options); 14093 14094 // _______ _ _ __ _ _______ _______ _____ _____ __ _ _______ 14095 // |______ | | | \ | | | | | | | \ | |______ 14096 // | |_____| | \_| |_____ | __|__ |_____| | \_| ______| 14097 // 14098 // Predefining the awesomeness 14099 14100 // Output arguments to the Debug console 14101 // if "Debug Mode" is enabled 14102 function _debug() { 14103 if (!Opts.debug 14104 || typeof console == 'undefined' 14105 || typeof console.debug == 'undefined') { 14106 return; 14107 } 14108 console.debug.apply(console, arguments); 14109 } 14110 14111 // Output arguments to the Warning console 14112 function _warn() { 14113 if (typeof console == 'undefined' || 14114 typeof console.warn == 'undefined') { 14115 return; 14116 } 14117 console.warn.apply(console, arguments); 14118 } 14119 14120 // Outputs all information on the current sizing 14121 // of the font. 14122 function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14123 14124 function _m(v1, v2) { 14125 14126 var marker = ' / '; 14127 14128 if (v1 > v2) 14129 marker = ' > '; 14130 14131 else if (v1 == v2) 14132 marker = ' = '; 14133 14134 return marker; 14135 } 14136 14137 _debug( 14138 '[TextFill] ' + prefix + ' { ' + 14139 'font-size: ' + ourText.css('font-size') + ',' +
14140 'Height: ' + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' + 14141 'Width: ' + ourText.width() + _m(ourText.width() , maxWidth) + maxWidth + ',' + 14142 'minFontPixels: ' + minFontPixels + 'px, ' + 14143 'maxFontPixels: ' + maxFontPixels + 'px }' 14144 ); 14145 } 14146 14147 /** 14148 * Calculates which size the font can get resized, 14149 * according to constrains. 14150 * 14151 * @param {String} prefix Gets shown on the console before 14152 * all the arguments, if debug mode is on. 14153 * @param {Object} ourText The DOM element to resize, 14154 * that contains the text. 14155 * @param {function} func Function called on `ourText` that's 14156 * used to compare with `max`. 14157 * @param {number} max Maximum value, that gets compared with 14158 * `func` called on `ourText`. 14159 * @param {number} minFontPixels Minimum value the font can 14160 * get resized to (in pixels). 14161 * @param {number} maxFontPixels Maximum value the font can 14162 * get resized to (in pixels). 14163 * 14164 * @return Size (in pixels) that the font can be resized. 14165 */ 14166 function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) { 14167 14168 _debug_sizing( 14169 prefix, ourText, 14170 maxHeight, maxWidth, 14171 minFontPixels, maxFontPixels 14172 ); 14173 14174 // The kernel of the whole plugin, take most attention 14175 // on this part. 14176 // 14177 // This is a loop that keeps increasing the `font-size` 14178 // until it fits the parent element. 14179 // 14180 // - Start from the minimal allowed value (`minFontPixels`) 14181 // - Guesses an average font size (in pixels) for the font, 14182 // - Resizes the text and sees if its size is within the 14183 // boundaries (`minFontPixels` and `maxFontPixels`). 14184 // - If so, keep guessing until we break. 14185 // - If not, return the last calculated size. 14186 // 14187 // I understand this is not optimized and we should 14188 // consider implementing something akin to 14189 // Daniel Hoffmann's answer here: 14190 // 14191 // http://stackoverflow.com/a/17433451/1094964 14192 // 14193 14194 while (minFontPixels < (maxFontPixels - 1)) { 14195 14196 var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2); 14197 ourText.css('font-size', fontSize); 14198 14199 if (func.call(ourText) <= max) { 14200 minFontPixels = fontSize; 14201 14202 if (func.call(ourText) == max) 14203 break; 14204 } 14205 else 14206 maxFontPixels = fontSize; 14207 14208 _debug_sizing( 14209 prefix, ourText, 14210 maxHeight, maxWidth, 14211 minFontPixels, maxFontPixels 14212 ); 14213 } 14214 14215 ourText.css('font-size', maxFontPixels); 14216 14217 if (func.call(ourText) <= max) { 14218 minFontPixels = maxFontPixels; 14219 14220 _debug_sizing( 14221 prefix + '* ', ourText, 14222 maxHeight, maxWidth, 14223 minFontPixels, maxFontPixels 14224 ); 14225 } 14226 return minFontPixels; 14227 } 14228 14229 // _______ _______ _______ ______ _______ 14230 // |______ | |_____| |_____/ | 14231 // ______| | | | | \_ | 14232 // 14233 // Let's get it started (yeah)! 14234 14235 _debug('[TextFill] Start Debug'); 14236 14237 this.each(function() { 14238 14239 // Contains the child element we will resize. 14240 // $(this) means the parent container 14241 var ourText = $(Opts.innerTag + ':visible:first', this); 14242 14243 // Will resize to this dimensions. 14244 // Use explicit dimensions when specified 14245 var maxHeight = Opts.explicitHeight || $(this).height(); 14246 var maxWidth = Opts.explicitWidth || $(this).width(); 14247 14248 var oldFontSize = ourText.css('font-size'); 14249 14250 var lineHeight = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize); 14251 14252 _debug('[TextFill] Inner text: ' + ourText.text()); 14253 _debug('[TextFill] All options: ', Opts); 14254 _debug('[TextFill] Maximum sizes: { ' + 14255 'Height: ' + maxHeight + 'px, ' + 14256 'Width: ' + maxWidth + 'px' + ' }' 14257 ); 14258 14259 var minFontPixels = Opts.minFontPixels; 14260 14261 // Remember, if this `maxFontPixels` is negative, 14262 // the text will resize to as long as the container 14263 // can accomodate 14264 var maxFontPixels = (Opts.maxFontPixels <= 0 ? 14265 maxHeight : 14266 Opts.maxFontPixels); 14267 14268 14269 // Let's start it all! 14270 14271 // 1. Calculate which `font-size` would 14272 // be best for the Height 14273 var fontSizeHeight = undefined; 14274 14275 if (! Opts.widthOnly) 14276 fontSizeHeight = _sizing( 14277 'Height', ourText, 14278 $.fn.height, maxHeight, 14279 maxHeight, maxWidth, 14280 minFontPixels, maxFontPixels 14281 ); 14282 14283 // 2. Calculate which `font-size` would 14284 // be best for the Width 14285 var fontSizeWidth = undefined; 14286 14287 fontSizeWidth = _sizing( 14288 'Width', ourText, 14289 $.fn.width, maxWidth, 14290 maxHeight, maxWidth, 14291 minFontPixels, maxFontPixels 14292 ); 14293 14294 // 3. Actually resize the text! 14295 14296 if (Opts.widthOnly) { 14297 ourText.css({ 14298 'font-size' : fontSizeWidth, 14299 'white-space': 'nowrap' 14300 }); 14301 14302 if (Opts.changeLineHeight) 14303 ourText.parent().css( 14304 'line-height', 14305 (lineHeight * fontSizeWidth + 'px') 14306 ); 14307 } 14308 else { 14309 var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth); 14310 14311 ourText.css('font-size', fontSizeFinal); 14312 14313 if (Opts.changeLineHeight) 14314 ourText.parent().css( 14315 'line-height', 14316 (lineHeight * fontSizeFinal) + 'px' 14317 ); 14318 } 14319 14320 _debug( 14321 '[TextFill] Finished { ' + 14322 'Old font-size: ' + oldFontSize + ', ' + 14323 'New font-size: ' + ourText.css('font-size') + ' }' 14324 ); 14325 14326 // Oops, something wrong happened! 14327 // We weren't supposed to exceed the original size 14328 if ((ourText.width() > maxWidth) ||
14329 (ourText.height() > maxHeight && !Opts.widthOnly)) { 14330 14331 ourText.css('font-size', oldFontSize); 14332 14333 // Failure callback 14334 if (Opts.fail) 14335 Opts.fail(this); 14336 14337 _debug( 14338 '[TextFill] Failure { ' + 14339 'Current Width: ' + ourText.width() + ', ' + 14340 'Maximum Width: ' + maxWidth + ', ' + 14341 'Current Height: ' + ourText.height() + ', ' + 14342 'Maximum Height: ' + maxHeight + ' }' 14343 ); 14344 } 14345 else if (Opts.success) { 14346 Opts.success(this); 14347 } 14348 else if (Opts.callback) { 14349 _warn('callback is deprecated, use success, instead'); 14350 14351 // Success callback 14352 Opts.callback(this); 14353 } 14354 }); 14355 14356 // Complete callback 14357 if (Opts.complete) 14358 Opts.complete(this); 14359 14360 _debug('[TextFill] End Debug'); 14361 return this; 14362 }; 14363 14364})(window.jQuery); 14365 14366 14367!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; 14368function getStyles(config){ 14369 // 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;
14369left: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+"}" 14370}; 14371 var ShareUtils; 14372 14373if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 14374 Object.defineProperty(HTMLElement.prototype, "classList", { 14375 get: function() { 14376 var ret, self, update; 14377 update = function(fn) { 14378 return function(value) { 14379 var classes, index; 14380 classes = self.className.split(/\s+/); 14381 index = classes.indexOf(value); 14382 fn(classes, index, value); 14383 self.className = classes.join(" "); 14384 }; 14385 }; 14386 self = this; 14387 ret = { 14388 add: update(function(classes, index, value) { 14389 ~index || classes.push(value); 14390 }), 14391 remove: update(function(classes, index) { 14392 ~index && classes.splice(index, 1); 14393 }), 14394 toggle: update(function(classes, index, value) { 14395 if (~index) { 14396 classes.splice(index, 1); 14397 } else { 14398 classes.push(value); 14399 } 14400 }), 14401 contains: function(value) { 14402 return !!~self.className.split(/\s+/).indexOf(value); 14403 }, 14404 item: function(i) { 14405 return self.className.split(/\s+/)[i] || null; 14406 } 14407 }; 14408 Object.defineProperty(ret, "length", { 14409 get: function() { 14410 return self.className.split(/\s+/).length; 14411 } 14412 }); 14413 return ret; 14414 } 14415 }); 14416} 14417 14418String.prototype.to_rfc3986 = function() { 14419 var tmp; 14420 tmp = encodeURIComponent(this); 14421 return tmp.replace(/[!'()*]/g, function(c) { 14422 return "%" + c.charCodeAt(0).toString(16); 14423 }); 14424}; 14425 14426ShareUtils = (function() { 14427 function ShareUtils() {} 14428 14429 ShareUtils.prototype.extend = function(to, from, overwrite) { 14430 var hasProp, prop; 14431 for (prop in from) { 14432 hasProp = to[prop] !== undefined; 14433 if (hasProp && typeof from[prop] === "object") { 14434 this.extend(to[prop], from[prop], overwrite); 14435 } else { 14436 if (overwrite || !hasProp) { 14437 to[prop] = from[prop]; 14438 } 14439 } 14440 } 14441 }; 14442 14443 ShareUtils.prototype.hide = function(el) { 14444 return el.style.display = "none"; 14445 }; 14446 14447 ShareUtils.prototype.show = function(el) { 14448 return el.style.display = "block"; 14449 }; 14450 14451 ShareUtils.prototype.has_class = function(el, class_name) { 14452 return el.classList.contains(class_name); 14453 }; 14454 14455 ShareUtils.prototype.add_class = function(el, class_name) { 14456 return el.classList.add(class_name); 14457 }; 14458 14459 ShareUtils.prototype.remove_class = function(el, class_name) { 14460 return el.classList.remove(class_name); 14461 }; 14462 14463 ShareUtils.prototype.is_encoded = function(str) { 14464 str = str.to_rfc3986(); 14465 return decodeURIComponent(str) !== str; 14466 }; 14467 14468 ShareUtils.prototype.encode = function(str) { 14469 if (typeof str === "undefined" || this.is_encoded(str)) { 14470 return str; 14471 } else { 14472 return str.to_rfc3986(); 14473 } 14474 }; 14475 14476 ShareUtils.prototype.popup = function(url, params) { 14477 var k, popup, qs, v; 14478 if (params == null) { 14479 params = {}; 14480 } 14481 popup = { 14482 width: 500, 14483 height: 350 14484 }; 14485 popup.top = (screen.height / 2) - (popup.height / 2); 14486 popup.left = (screen.width / 2) - (popup.width / 2); 14487 qs = ((function() { 14488 var _results; 14489 _results = []; 14490 for (k in params) { 14491 v = params[k]; 14492 _results.push("" + k + "=" + (this.encode(v))); 14493 } 14494 return _results; 14495 }).call(this)).join('&'); 14496 if (qs) { 14497 qs = "?" + qs; 14498 } 14499 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="
14499+ popup.width + ",height=" + popup.height); 14500 }; 14501 14502 return ShareUtils; 14503 14504})(); 14505var Share, 14506 __hasProp = {}.hasOwnProperty, 14507 __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; }; 14508 14509Share = (function(_super) { 14510 __extends(Share, _super); 14511 14512 function Share(element, options) { 14513 this.element = element; 14514 this.el = { 14515 head: document.getElementsByTagName('head')[0], 14516 body: document.getElementsByTagName('body')[0] 14517 }; 14518 this.config = { 14519 enabled_networks: 0, 14520 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 14521 url: window.location.href, 14522 caption: null, 14523 title: this.default_title(), 14524 image: this.default_image(), 14525 description: this.default_description(), 14526 ui: { 14527 flyout: 'top center', 14528 button_text: 'Share', 14529 button_font: true, 14530 icon_font: true 14531 }, 14532 networks: { 14533 google_plus: { 14534 enabled: true, 14535 url: null 14536 }, 14537 twitter: { 14538 enabled: true, 14539 url: null, 14540 title: null, 14541 description: null 14542 }, 14543 facebook: { 14544 enabled: true, 14545 load_sdk: true, 14546 url: null, 14547 app_id: null, 14548 title: null, 14549 caption: null, 14550 description: null, 14551 image: null 14552 }, 14553 pinterest: { 14554 enabled: true, 14555 url: null, 14556 image: null, 14557 description: null 14558 }, 14559 reddit: { 14560 enabled: true, 14561 url: null, 14562 title: null 14563 }, 14564 linkedin: { 14565 enabled: true, 14566 url: null, 14567 title: null, 14568 description: null 14569 }, 14570 xing: { 14571 enabled: true, 14572 url: null, 14573 title: null, 14574 image: null, 14575 description: null 14576 }, 14577 whatsapp: { 14578 enabled: true, 14579 description: null, 14580 url: null 14581 }, 14582 email: { 14583 enabled: true, 14584 title: null, 14585 description: null, 14586 url: null 14587 } 14588 } 14589 }; 14590 this.setup(element, options); 14591 return this; 14592 } 14593 14594 Share.prototype.setup = function(element, opts) { 14595 var index, instance, instances, _i, _len; 14596 instances = document.querySelectorAll(element); 14597 this.extend(this.config, opts, true); 14598 this.set_global_configuration(); 14599 this.normalize_network_configuration(); 14600 if (this.config.ui.icon_font) { 14601 this.inject_icons(); 14602 } 14603 if (this.config.ui.button_font) { 14604 this.inject_fonts(); 14605 } 14606 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 14607 this.inject_facebook_sdk(); 14608 } 14609 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 14610 instance = instances[index]; 14611 this.setup_instance(element, index); 14612 } 14613 }; 14614 14615 Share.prototype.setup_instance = function(element, index) { 14616 var button, instance, label, network, networks, _i, _len, _results, 14617 _this = this; 14618 instance = document.querySelectorAll(element)[index]; 14619 this.hide(instance); 14620 this.add_class(instance, "sharer-" + index); 14621 instance = document.querySelectorAll(element)[index]; 14622 this.inject_css(instance); 14623 this.inject_html(instance); 14624 this.show(instance); 14625 label = instance.getElementsByTagName("label")[0]; 14626 button = instance.getElementsByClassName("social")[0]; 14627 networks = instance.getElementsByTagName('li'); 14628 this.add_class(button, "networks-" + this.config.enabled_networks); 14629 label.addEventListener("click", function() { 14630 return _this.event_toggle(button); 14631 }); 14632 _this = this; 14633 _results = []; 14634 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 14635 network = networks[index]; 14636 _results.push(network.addEventListener("click", function() { 14637 _this.event_network(instance, this); 14638 return _this.event_close(button); 14639 })); 14640 } 14641 return _results; 14642 }; 14643 14644 Share.prototype.event_toggle = function(button) { 14645 if (this.has_class(button, "active")) { 14646 return this.event_close(button); 14647 } else { 14648 return this.event_open(button); 14649 } 14650 }; 14651 14652 Share.prototype.event_open = function(button) { 14653 if (this.has_class(button, "load")) { 14654 this.remove_class(button, "load"); 14655 } 14656 return this.add_class(button, "active"); 14657 }; 14658 14659 Share.prototype.event_close = function(button) { 14660 return this.remove_class(button, "active"); 14661 }; 14662 14663 Share.prototype.event_network = function(instance, network) { 14664 var name; 14665 name = network.getAttribute("data-network"); 14666 this.hook("before", name, instance);
14667 this["network_" + name](); 14668 return this.hook("after", name, instance); 14669 }; 14670 14671 Share.prototype.open = function() { 14672 return this["public"]("open"); 14673 }; 14674 14675 Share.prototype.close = function() { 14676 return this["public"]("close"); 14677 }; 14678 14679 Share.prototype.toggle = function() { 14680 return this["public"]("toggle"); 14681 }; 14682 14683 Share.prototype["public"] = function(action) { 14684 var button, index, instance, _i, _len, _ref, _results; 14685 _ref = document.querySelectorAll(this.element); 14686 _results = []; 14687 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 14688 instance = _ref[index]; 14689 button = instance.getElementsByClassName("social")[0]; 14690 _results.push(this["event_" + action](button)); 14691 } 14692 return _results; 14693 }; 14694 14695 Share.prototype.network_facebook = function() { 14696 if (this.config.networks.facebook.load_sdk) { 14697 if (!window.FB) { 14698 return console.error("The Facebook JS SDK hasn't loaded yet."); 14699 } 14700 return FB.ui({ 14701 method: 'feed', 14702 name: this.config.networks.facebook.title, 14703 link: this.config.networks.facebook.url, 14704 picture: this.config.networks.facebook.image, 14705 caption: this.config.networks.facebook.caption, 14706 description: this.config.networks.facebook.description 14707 }); 14708 } else { 14709 return this.popup('https://www.facebook.com/sharer/sharer.php', { 14710 u: this.config.networks.facebook.url 14711 }); 14712 } 14713 }; 14714 14715 Share.prototype.network_twitter = function() { 14716 return this.popup('https://twitter.com/intent/tweet', { 14717 text: this.config.networks.twitter.title, 14718 url: this.config.networks.twitter.url 14719 }); 14720 }; 14721 14722 Share.prototype.network_google_plus = function() { 14723 return this.popup('https://plus.google.com/share', { 14724 url: this.config.networks.google_plus.url 14725 }); 14726 }; 14727 14728 Share.prototype.network_pinterest = function() { 14729 return this.popup('https://www.pinterest.com/pin/create/button', { 14730 url: this.config.networks.pinterest.url, 14731 media: this.config.networks.pinterest.image, 14732 description: this.config.networks.pinterest.description 14733 }); 14734 }; 14735 14736 Share.prototype.network_linkedin = function() { 14737 return this.popup('https://www.linkedin.com/shareArticle', { 14738 url: this.config.networks.linkedin.url, 14739 title: this.config.networks.linkedin.title, 14740 summary: this.config.networks.linkedin.description 14741 }); 14742 } 14743 14744 Share.prototype.network_xing = function() { 14745 return this.popup('https://www.xing.com/spi/shares/new', { 14746 url: this.config.networks.xing.url, 14747 image: this.config.networks.xing.image, 14748 title: this.config.networks.xing.title, 14749 summary: this.config.networks.xing.description 14750 }); 14751 } 14752 14753 Share.prototype.network_email = function() { 14754 return this.popup('mailto:', { 14755 subject: this.config.networks.email.title, 14756 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 14757 }); 14758 }; 14759 14760 Share.prototype.inject_icons = function() { 14761 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 14762 }; 14763 14764 Share.prototype.inject_fonts = function() { 14765 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 14766 }; 14767 14768 Share.prototype.inject_stylesheet = function(url) { 14769 var link; 14770 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 14771 link = document.createElement("link"); 14772 link.setAttribute("rel", "stylesheet"); 14773 link.setAttribute("href", url); 14774 return this.el.head.appendChild(link); 14775 } 14776 }; 14777 14778 Share.prototype.inject_css = function(instance) { 14779 var css, meta, selector, style; 14780 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 14781 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 14782 this.config.selector = selector; 14783 css = getStyles(this.config); 14784 style = document.createElement("style"); 14785 style.type = "text/css"; 14786 if (style.styleSheet) { 14787 style.styleSheet.cssText = css; 14788 } else { 14789 style.appendChild(document.createTextNode(css)); 14790 } 14791 this.el.head.appendChild(style); 14792 delete this.config.selector; 14793 meta = document.createElement("meta"); 14794 meta.setAttribute("name", "sharer" + selector); 14795 return this.el.head.appendChild(meta); 14796 } 14797 }; 14798 14799 Share.prototype.inject_html = function(instance) { 14800 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>"; 14801 }; 14802 14803 Share.prototype.inject_facebook_sdk = function() { 14804 var fb_root, script; 14805 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 14806 script = document.createElement("script"); 14807 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')"; 14808 fb_root = document.createElement("div"); 14809 fb_root.id = "fb-root"; 14810 this.el.body.appendChild(fb_root); 14811 return this.el.body.appendChild(script); 14812 } 14813 }; 14814 14815 Share.prototype.hook = function(type, network, instance) { 14816 var fn, opts; 14817 fn = this.config.networks[network][type]; 14818 if (typeof fn === "function") { 14819 opts = fn.call(this.config.networks[network], instance); 14820 if (opts !== void 0) { 14821 opts = this.normalize_filter_config_updates(opts); 14822 this.extend(this.config.networks[network], opts, true); 14823 this.normalize_network_configuration(); 14824 } 14825 } 14826 }; 14827 14828 Share.prototype.default_title = function() { 14829 var content; 14830 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 14831 return encodeURIComponent(content.getAttribute('content')); 14832 } else if (content = document.querySelector('title')) { 14833 return encodeURIComponent(content.innerText); 14834 } 14835 }; 14836 14837 Share.prototype.default_image = function() { 14838 var content; 14839 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 14840 return content.getAttribute('content'); 14841 } 14842 }; 14843 14844 Share.prototype.default_description = function() { 14845 var content; 14846 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 14847 return content.getAttribute('content'); 14848 } else { 14849 return ''; 14850 } 14851 }; 14852 14853 Share.prototype.set_global_configuration = function() { 14854 var display, network, option, options, _ref, _results; 14855 _ref = this.config.networks; 14856 _results = []; 14857 for (network in _ref) { 14858 options = _ref[network]; 14859 for (option in options) { 14860 if (this.config.networks[network][option] == null) { 14861 this.config.networks[network][option] = this.config[option]; 14862 } 14863 } 14864 if (this.config.networks[network].enabled) { 14865 display = 'block'; 14866 this.config.enabled_networks += 1; 14867 } else { 14868 display = 'none'; 14869 } 14870 _results.push(this.config.networks[network].display = display); 14871 } 14872 return _results; 14873 }; 14874 14875 Share.prototype.normalize_network_configuration = function() { 14876 if (!this.config.networks.facebook.app_id) { 14877 this.config.networks.facebook.load_sdk = false;
14878 } 14879 if (!this.is_encoded(this.config.networks.twitter.description)) { 14880 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 14881 } 14882 if (typeof this.config.networks.facebook.app_id === 'number') { 14883 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 14884 } 14885 }; 14886 14887 Share.prototype.normalize_filter_config_updates = function(opts) { 14888 if (this.config.networks.facebook.app_id !== opts.app_id) { 14889 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."); 14890 delete opts.app_id; 14891 } 14892 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 14893 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."); 14894 delete opts.app_id; 14895 } 14896 return opts; 14897 }; 14898 14899 return Share; 14900 14901})(ShareUtils); 14902 return Share; 14903}); 14904 14905 14906// Generated by CoffeeScript 1.9.2 14907 14908// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 14909 14910(function() { 14911 var $, win; 14912 14913 $ = this.jQuery || window.jQuery; 14914 14915 win = $(window); 14916 14917 $.fn.stick_in_parent = function(opts) { 14918 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 14919 if (opts == null) { 14920 opts = {}; 14921 } 14922 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; 14923 if (offset_top == null) { 14924 offset_top = 0; 14925 } 14926 if (parent_selector == null) { 14927 parent_selector = void 0; 14928 } 14929 if (inner_scrolling == null) { 14930 inner_scrolling = true; 14931 } 14932 if (sticky_class == null) { 14933 sticky_class = "is_stuck"; 14934 } 14935 doc = $(document); 14936 if (enable_bottoming == null) { 14937 enable_bottoming = true; 14938 } 14939 outer_width = function(el) { 14940 var _el, computed, w; 14941 if (window.getComputedStyle) { 14942 _el = el[0]; 14943 computed = window.getComputedStyle(el[0]); 14944 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 14945 if (computed.getPropertyValue("box-sizing") !== "border-box") { 14946 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 14947 } 14948 return w; 14949 } else { 14950 return el.outerWidth(true); 14951 } 14952 }; 14953 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 14954 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 14955 if (elm.data("sticky_kit")) { 14956 return; 14957 } 14958 elm.data("sticky_kit", true); 14959 last_scroll_height = doc.height(); 14960 parent = elm.parent(); 14961 if (parent_selector != null) { 14962 parent = parent.closest(parent_selector); 14963 } 14964 if (!parent.length) { 14965 throw "failed to find stick parent"; 14966 } 14967 fixed = false; 14968 bottomed = false; 14969 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 14970 if (spacer) { 14971 spacer.css('position', elm.css('position')); 14972 } 14973 recalc = function() { 14974 var border_top, padding_top, restore; 14975 if (detached) { 14976 return; 14977 } 14978 last_scroll_height = doc.height(); 14979 border_top = parseInt(parent.css("border-top-width"), 10); 14980 padding_top = parseInt(parent.css("padding-top"), 10); 14981 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 14982 parent_top = parent.offset().top + border_top + padding_top; 14983 parent_height = parent.height(); 14984 if (fixed) { 14985 fixed = false;
14986 bottomed = false; 14987 if (manual_spacer == null) { 14988 elm.insertAfter(spacer); 14989 spacer.detach(); 14990 } 14991 elm.css({ 14992 position: "", 14993 top: "", 14994 width: "", 14995 bottom: "" 14996 }).removeClass(sticky_class); 14997 restore = true; 14998 } 14999 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 15000 height = elm.outerHeight(true); 15001 el_float = elm.css("float"); 15002 if (spacer) { 15003 spacer.css({ 15004 width: outer_width(elm), 15005 height: height, 15006 display: elm.css("display"), 15007 "vertical-align": elm.css("vertical-align"), 15008 "float": el_float 15009 }); 15010 } 15011 if (restore) { 15012 return tick(); 15013 } 15014 }; 15015 recalc(); 15016 if (height === parent_height) { 15017 return; 15018 } 15019 last_pos = void 0; 15020 offset = offset_top; 15021 recalc_counter = recalc_every; 15022 tick = function() { 15023 var css, delta, recalced, scroll, will_bottom, win_height; 15024 if (detached) { 15025 return; 15026 } 15027 recalced = false; 15028 if (recalc_counter != null) { 15029 recalc_counter -= 1; 15030 if (recalc_counter <= 0) { 15031 recalc_counter = recalc_every; 15032 recalc(); 15033 recalced = true; 15034 } 15035 } 15036 if (!recalced && doc.height() !== last_scroll_height) { 15037 recalc(); 15038 recalced = true; 15039 } 15040 scroll = win.scrollTop(); 15041 if (last_pos != null) { 15042 delta = scroll - last_pos; 15043 } 15044 last_pos = scroll; 15045 if (fixed) { 15046 if (enable_bottoming) { 15047 will_bottom = scroll + height + offset > parent_height + parent_top; 15048 if (bottomed && !will_bottom) { 15049 bottomed = false; 15050 elm.css({ 15051 position: "fixed", 15052 bottom: "", 15053 top: offset 15054 }).trigger("sticky_kit:unbottom"); 15055 } 15056 } 15057 if (scroll < top) { 15058 fixed = false; 15059 offset = offset_top; 15060 if (manual_spacer == null) { 15061 if (el_float === "left" || el_float === "right") { 15062 elm.insertAfter(spacer); 15063 } 15064 spacer.detach(); 15065 } 15066 css = { 15067 position: "", 15068 width: "", 15069 top: "" 15070 }; 15071 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 15072 } 15073 if (inner_scrolling) { 15074 win_height = win.height(); 15075 if (height + offset_top > win_height) { 15076 if (!bottomed) { 15077 offset -= delta; 15078 offset = Math.max(win_height - height, offset); 15079 offset = Math.min(offset_top, offset); 15080 if (fixed) { 15081 elm.css({ 15082 top: offset + "px" 15083 }); 15084 } 15085 } 15086 } 15087 } 15088 } else { 15089 if (scroll > top) { 15090 fixed = true; 15091 css = { 15092 position: "fixed", 15093 top: offset 15094 }; 15095 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 15096 elm.css(css).addClass(sticky_class); 15097 if (manual_spacer == null) { 15098 elm.after(spacer); 15099 if (el_float === "left" || el_float === "right") { 15100 spacer.append(elm); 15101 } 15102 } 15103 elm.trigger("sticky_kit:stick"); 15104 } 15105 } 15106 if (fixed && enable_bottoming) { 15107 if (will_bottom == null) { 15108 will_bottom = scroll + height + offset > parent_height + parent_top; 15109 } 15110 if (!bottomed && will_bottom) { 15111 bottomed = true; 15112 if (parent.css("position") === "static") { 15113 parent.css({ 15114 position: "relative" 15115 }); 15116 } 15117 return elm.css({ 15118 position: "absolute", 15119 bottom: padding_bottom, 15120 top: "auto" 15121 }).trigger("sticky_kit:bottom"); 15122 } 15123 } 15124 }; 15125 recalc_and_tick = function() { 15126 recalc(); 15127 return tick(); 15128 }; 15129 detach = function() { 15130 detached = true; 15131 win.off("touchmove", tick); 15132 win.off("scroll", tick); 15133 win.off("resize", recalc_and_tick); 15134 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 15135 elm.off("sticky_kit:detach", detach); 15136 elm.removeData("sticky_kit"); 15137 elm.css({ 15138 position: "", 15139 bottom: "", 15140 top: "", 15141 width: "" 15142 }); 15143 parent.position("position", ""); 15144 if (fixed) { 15145 if (manual_spacer == null) { 15146 if (el_float === "left" || el_float === "right") { 15147 elm.insertAfter(spacer); 15148 } 15149 spacer.remove(); 15150 } 15151 return elm.removeClass(sticky_class); 15152 } 15153 }; 15154 win.on("touchmove", tick); 15155 win.on("scroll", tick); 15156 win.on("resize", recalc_and_tick); 15157 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 15158 elm.on("sticky_kit:detach", detach); 15159 return setTimeout(tick, 0); 15160 }; 15161 for (i = 0, len = this.length; i < len; i++) { 15162 elm = this[i]; 15163 fn($(elm)); 15164 } 15165 return this; 15166 }; 15167 15168}).call(this); 15169 15170 15171 15172/* ======================================================================== 15173 * Bootstrap: collapse.js v3.1.1 15174 * http://getbootstrap.com/javascript/#collapse 15175 * ======================================================================== 15176 * Copyright 2011-2014 Twitter, Inc. 15177 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15178 * ======================================================================== */ 15179 15180 15181+function ($) { 15182 'use strict'; 15183 15184 // COLLAPSE PUBLIC CLASS DEFINITION 15185 // ================================ 15186 15187 var Collapse = function (element, options) { 15188 this.$element = $(element) 15189 this.options = $.extend({}, Collapse.DEFAULTS, options) 15190 this.transitioning = null 15191 15192 if (this.options.parent) this.$parent = $(this.options.parent) 15193 if (this.options.toggle) this.toggle() 15194 } 15195 15196 Collapse.DEFAULTS = { 15197 toggle: true 15198 } 15199 15200 Collapse.prototype.dimension = function () { 15201 var hasWidth = this.$element.hasClass('width') 15202 return hasWidth ? 'width' : 'height' 15203 } 15204 15205 Collapse.prototype.show = function () { 15206 if (this.transitioning || this.$element.hasClass('in')) return 15207 15208 var startEvent = $.Event('show.bs.collapse') 15209 this.$element.trigger(startEvent) 15210 if (startEvent.isDefaultPrevented()) return 15211 15212 var actives = this.$parent && this.$parent.find('> .panel > .in') 15213 15214 if (actives && actives.length) { 15215 var hasData = actives.data('bs.collapse') 15216 if (hasData && hasData.transitioning) return 15217 actives.collapse('hide') 15218 hasData || actives.data('bs.collapse', null) 15219 } 15220 15221 var dimension = this.dimension() 15222 15223 this.$element 15224 .removeClass('collapse') 15225 .addClass('collapsing')[dimension](0) 15226 15227 this.transitioning = 1 15228 15229 var complete = function (e) { 15230 if (e && e.target != this.$element[0]) return 15231 this.$element 15232 .removeClass('collapsing') 15233 .addClass('collapse in')[dimension]('auto') 15234 this.transitioning = 0 15235 this.$element.trigger('shown.bs.collapse') 15236 } 15237 15238 if (!$.support.transition) return complete.call(this) 15239 15240 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 15241 15242 this.$element 15243 .one($.support.transition.end, $.proxy(complete, this)) 15244 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 15245 } 15246 15247 Collapse.prototype.hide = function () { 15248 if (this.transitioning || !this.$element.hasClass('in')) return 15249 15250 var startEvent = $.Event('hide.bs.collapse') 15251 this.$element.trigger(startEvent) 15252 if (startEvent.isDefaultPrevented()) return 15253 15254 var dimension = this.dimension() 15255 15256 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 15257 15258 this.$element 15259 .addClass('collapsing') 15260 .removeClass('collapse') 15261 .removeClass('in') 15262 15263 this.transitioning = 1 15264 15265 var complete = function (e) { 15266 if (e && e.target != this.$element[0]) return 15267 this.transitioning = 0 15268 this.$element 15269 .trigger('hidden.bs.collapse') 15270 .removeClass('collapsing') 15271 .addClass('collapse') 15272 } 15273 15274 if (!$.support.transition) return complete.call(this) 15275 15276 this.$element 15277 [dimension](0) 15278 .one($.support.transition.end, $.proxy(complete, this)) 15279 .emulateTransitionEnd(350) 15280 } 15281 15282 Collapse.prototype.toggle = function () { 15283 this[this.$element.hasClass('in') ? 'hide' : 'show']() 15284 } 15285 15286 15287 // COLLAPSE PLUGIN DEFINITION 15288 // ========================== 15289 15290 var old = $.fn.collapse 15291 15292 $.fn.collapse = function (option) { 15293 return this.each(function () { 15294 var $this = $(this) 15295 var data = $this.data('bs.collapse') 15296 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 15297 15298 if (!data && options.toggle && option == 'show') option = !option 15299 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 15300 if (typeof option == 'string') data[option]() 15301 }) 15302 } 15303 15304 $.fn.collapse.Constructor = Collapse 15305 15306 15307 // COLLAPSE NO CONFLICT 15308 // ==================== 15309 15310 $.fn.collapse.noConflict = function () { 15311 $.fn.collapse = old 15312 return this 15313 } 15314 15315 15316 // COLLAPSE DATA-API 15317 // ================= 15318 15319 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 15320 var $this = $(this), href 15321 var target = $this.attr('data-target') 15322 || e.preventDefault() 15323 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 15324 var $target = $(target) 15325 var data = $target.data('bs.collapse') 15326 var option = data ? 'toggle' : $this.data() 15327 var parent = $this.attr('data-parent') 15328 var $parent = parent && $(parent) 15329 15330 if (!data || !data.transitioning) { 15331 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 15332 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 15333 } 15334 15335 $target.collapse(option) 15336 }) 15337 15338}(jQuery); 15339 15340 15341/* ======================================================================== 15342 * Bootstrap: tab.js v3.1.1 15343 * http://getbootstrap.com/javascript/#tabs 15344 * ======================================================================== 15345 * Copyright 2011-2014 Twitter, Inc. 15346 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15347 * ======================================================================== */ 15348 15349 15350+function ($) { 15351 'use strict'; 15352 15353 // TAB CLASS DEFINITION 15354 // ==================== 15355 15356 var Tab = function (element) { 15357 this.element = $(element) 15358 } 15359 15360 Tab.prototype.show = function () { 15361 var $this = this.element 15362 var $ul = $this.closest('ul:not(.dropdown-menu)') 15363 var selector = $this.data('target') 15364 15365 if (!selector) { 15366 selector = $this.attr('href') 15367 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 15368 } 15369 15370 if ($this.parent('li').hasClass('active')) return 15371 15372 var previous = $ul.find('.active:last a')[0] 15373 var e = $.Event('show.bs.tab', { 15374 relatedTarget: previous 15375 }) 15376 15377 $this.trigger(e) 15378 15379 if (e.isDefaultPrevented()) return 15380 15381 var $target = $(selector) 15382 15383 this.activate($this.parent('li'), $ul) 15384 this.activate($target, $target.parent(), function () { 15385 $this.trigger({ 15386 type: 'shown.bs.tab', 15387 relatedTarget: previous 15388 }) 15389 }) 15390 } 15391 15392 Tab.prototype.activate = function (element, container, callback) { 15393 var $active = container.find('> .active') 15394 var transition = callback 15395 && $.support.transition 15396 && $active.hasClass('fade') 15397 15398 function next() { 15399 $active 15400 .removeClass('active') 15401 .find('> .dropdown-menu > .active') 15402 .removeClass('active') 15403 15404 element.addClass('active') 15405 15406 if (transition) { 15407 element[0].offsetWidth // reflow for transition 15408 element.addClass('in') 15409 } else { 15410 element.removeClass('fade') 15411 } 15412 15413 if (element.parent('.dropdown-menu')) { 15414 element.closest('li.dropdown').addClass('active') 15415 } 15416 15417 callback && callback() 15418 } 15419 15420 transition ? 15421 $active 15422 .one($.support.transition.end, next) 15423 .emulateTransitionEnd(150) : 15424 next() 15425 15426 $active.removeClass('in') 15427 } 15428 15429 15430 // TAB PLUGIN DEFINITION 15431 // ===================== 15432 15433 var old = $.fn.tab 15434 15435 $.fn.tab = function ( option ) { 15436 return this.each(function () { 15437 var $this = $(this) 15438 var data = $this.data('bs.tab') 15439 15440 if (!data) $this.data('bs.tab', (data = new Tab(this))) 15441 if (typeof option == 'string') data[option]() 15442 }) 15443 } 15444 15445 $.fn.tab.Constructor = Tab 15446 15447 15448 // TAB NO CONFLICT 15449 // =============== 15450 15451 $.fn.tab.noConflict = function () { 15452 $.fn.tab = old 15453 return this 15454 } 15455 15456 15457 // TAB DATA-API 15458 // ============ 15459 15460 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 15461 e.preventDefault() 15462 $(this).tab('show') 15463 }) 15464 15465}(jQuery); 15466 15467 15468/* ======================================================================== 15469 * Bootstrap: tooltip.js v3.1.1 15470 * http://getbootstrap.com/javascript/#tooltip 15471 * Inspired by the original jQuery.tipsy by Jason Frame 15472 * ======================================================================== 15473 * Copyright 2011-2014 Twitter, Inc. 15474 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15475 * ======================================================================== */ 15476 15477 15478+function ($) { 15479 'use strict'; 15480 15481 // TOOLTIP PUBLIC CLASS DEFINITION 15482 // =============================== 15483 15484 var Tooltip = function (element, options) { 15485 this.type = 15486 this.options = 15487 this.enabled = 15488 this.timeout = 15489 this.hoverState = 15490 this.$element = null 15491 15492 this.init('tooltip', element, options) 15493 } 15494 15495 Tooltip.DEFAULTS = { 15496 animation: true, 15497 placement: 'top', 15498 selector: false, 15499 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 15500 trigger: 'hover focus', 15501 title: '', 15502 delay: 0, 15503 html: false, 15504 container: false, 15505 viewport: { 15506 selector: 'body', 15507 padding: 0 15508 } 15509 } 15510 15511 Tooltip.prototype.init = function (type, element, options) { 15512 this.enabled = true 15513 this.type = type 15514 this.$element = $(element) 15515 this.options = this.getOptions(options) 15516 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 15517 15518 var triggers = this.options.trigger.split(' ') 15519 15520 for (var i = triggers.length; i--;) { 15521 var trigger = triggers[i] 15522 15523 if (trigger == 'click') { 15524 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 15525 } else if (trigger != 'manual') { 15526 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 15527 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 15528 15529 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 15530 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 15531 } 15532 } 15533 15534 this.options.selector ? 15535 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 15536 this.fixTitle() 15537 } 15538 15539 Tooltip.prototype.getDefaults = function () { 15540 return Tooltip.DEFAULTS 15541 } 15542 15543 Tooltip.prototype.getOptions = function (options) { 15544 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 15545 15546 if (options.delay && typeof options.delay == 'number') { 15547 options.delay = { 15548 show: options.delay, 15549 hide: options.delay 15550 } 15551 } 15552 15553 return options 15554 } 15555 15556 Tooltip.prototype.getDelegateOptions = function () { 15557 var options = {} 15558 var defaults = this.getDefaults() 15559 15560 this._options && $.each(this._options, function (key, value) { 15561 if (defaults[key] != value) options[key] = value 15562 }) 15563 15564 return options 15565 } 15566 15567 Tooltip.prototype.enter = function (obj) { 15568 var self = obj instanceof this.con
15568structor ? 15569 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 15570 15571 clearTimeout(self.timeout) 15572 15573 self.hoverState = 'in' 15574 15575 if (!self.options.delay || !self.options.delay.show) return self.show() 15576 15577 self.timeout = setTimeout(function () { 15578 if (self.hoverState == 'in') self.show() 15579 }, self.options.delay.show) 15580 } 15581 15582 Tooltip.prototype.leave = function (obj) { 15583 var self = obj instanceof this.constructor ? 15584 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 15585 15586 clearTimeout(self.timeout) 15587 15588 self.hoverState = 'out' 15589 15590 if (!self.options.delay || !self.options.delay.hide) return self.hide() 15591 15592 self.timeout = setTimeout(function () { 15593 if (self.hoverState == 'out') self.hide() 15594 }, self.options.delay.hide) 15595 } 15596 15597 Tooltip.prototype.show = function () { 15598 var e = $.Event('show.bs.' + this.type) 15599 15600 if (this.hasContent() && this.enabled) { 15601 this.$element.trigger(e) 15602 15603 if (e.isDefaultPrevented()) return 15604 var that = this; 15605 15606 var $tip = this.tip() 15607 15608 this.setContent() 15609 15610 if (this.options.animation) $tip.addClass('fade') 15611 15612 var placement = typeof this.options.placement == 'function' ? 15613 this.options.placement.call(this, $tip[0], this.$element[0]) : 15614 this.options.placement 15615 15616 var autoToken = /\s?auto?\s?/i 15617 var autoPlace = autoToken.test(placement) 15618 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 15619 15620 $tip 15621 .detach() 15622 .css({ top: 0, left: 0, display: 'block' }) 15623 .addClass(placement) 15624 15625 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 15626 15627 var pos = this.getPosition() 15628 var actualWidth = $tip[0].offsetWidth 15629 var actualHeight = $tip[0].offsetHeight 15630 15631 if (autoPlace) { 15632 var orgPlacement = placement 15633 var $parent = this.$element.parent() 15634 var parentDim = this.getPosition($parent) 15635 15636 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 15637 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 15638 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 15639 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 15640 placement 15641 15642 $tip 15643 .removeClass(orgPlacement) 15644 .addClass(placement) 15645 } 15646 15647 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 15648 15649 this.applyPlacement(calculatedOffset, placement) 15650 this.hoverState = null 15651 15652 var complete = function() { 15653 that.$element.trigger('shown.bs.' + that.type) 15654 } 15655 15656 $.support.transition && this.$tip.hasClass('fade') ? 15657 $tip 15658 .one($.support.transition.end, complete) 15659 .emulateTransitionEnd(150) : 15660 complete() 15661 } 15662 } 15663 15664 Tooltip.prototype.applyPlacement = function (offset, placement) { 15665 var $tip = this.tip() 15666 var width = $tip[0].offsetWidth 15667 var height = $tip[0].offsetHeight 15668 15669 // manually read margins because getBoundingClientRect includes difference 15670 var marginTop = parseInt($tip.css('margin-top'), 10) 15671 var marginLeft = parseInt($tip.css('margin-left'), 10) 15672 15673 // we must check for NaN for ie 8/9 15674 if (isNaN(marginTop)) marginTop = 0 15675 if (isNaN(marginLeft)) marginLeft = 0 15676 15677 offset.top = offset.top + marginTop 15678 offset.left = offset.left + marginLeft 15679 15680 // $.fn.offset doesn't round pixel values 15681 // so we use setOffset directly with our own function B-0 15682 $.offset.setOffset($tip[0], $.extend({ 15683 using: function (props) { 15684 $tip.css({ 15685 top: Math.round(props.top), 15686 left: Math.round(props.left) 15687 }) 15688 } 15689 }, offset), 0) 15690 15691 $tip.addClass('in') 15692 15693 // check to see if placing tip in new offset caused the tip to resize itself 15694 var actualWidth = $tip[0].offsetWidth 15695 var actualHeight = $tip[0].offsetHeight 15696 15697 if (placement == 'top' && actualHeight != height) { 15698 offset.top = offset.top + height - actualHeight 15699 } 15700 15701 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 15702 15703 if (delta.left) offset.left += delta.left 15704 else offset.top += delta.top 15705 15706 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 15707 var arrowPosition = delta.left ? 'left' : 'top' 15708 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 15709 15710 $tip.offset(offset) 15711 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 15712 } 15713 15714 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 15715 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 15716 } 15717 15718 Tooltip.prototype.setContent = function () { 15719 var $tip = this.tip() 15720 var title = this.getTitle() 15721 15722 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 15723 $tip.removeClass('fade in top bottom left right') 15724 } 15725 15726 Tooltip.prototype.hide = function () { 15727 var that = this 15728 var $tip = this.tip() 15729 var e = $.Event('hide.bs.' + this.type) 15730 15731 function complete() { 15732 if (that.hoverState != 'in') $tip.detach() 15733 that.$element.trigger('hidden.bs.' + that.type) 15734 } 15735 15736 this.$element.trigger(e) 15737 15738 if (e.isDefaultPrevented()) return 15739 15740 $tip.removeClass('in') 15741 15742 $.support.transition && this.$tip.hasClass('fade') ? 15743 $tip 15744 .one($.support.transition.end, complete) 15745 .emulateTransitionEnd(150) : 15746 complete() 15747 15748 this.hoverState = null 15749 15750 return this 15751 } 15752 15753 Tooltip.prototype.fixTitle = function () { 15754 var $e = this.$element 15755 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 15756 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 15757 } 15758 } 15759 15760 Tooltip.prototype.hasContent = function () { 15761 return this.getTitle() 15762 } 15763 15764 Tooltip.prototype.getPosition = function ($element) { 15765 $element = $element || this.$element 15766 var el = $element[0] 15767 var isBody = el.tagName == 'BODY' 15768 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 15769 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 15770 width: isBody ? $(window).width() : $element.outerWidth(), 15771 height: isBody ? $(window).height() : $element.outerHeight() 15772 }, isBody ? {top: 0, left: 0} : $element.offset()) 15773 } 15774 15775 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 15776 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 15777 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 15778 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 15779 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 15780 15781 } 15782 15783 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 15784 var delta = { top: 0, left: 0 } 15785 if (!this.$viewport) return delta 15786 15787 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 15788 var viewportDimensions = this.getPosition(this.$viewport) 15789 15790 if (/right|left/.test(placement)) { 15791 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 15792 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 15793 if (topEdgeOffset < viewportDimensions.top) { // top overflow 15794 delta.top = viewportDimensions.top - topEdgeOffset 15795 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 15796 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
15796EdgeOffset 15797 } 15798 } else { 15799 var leftEdgeOffset = pos.left - viewportPadding 15800 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 15801 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 15802 delta.left = viewportDimensions.left - leftEdgeOffset 15803 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 15804 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 15805 } 15806 } 15807 15808 return delta 15809 } 15810 15811 Tooltip.prototype.getTitle = function () { 15812 var title 15813 var $e = this.$element 15814 var o = this.options 15815 15816 title = $e.attr('data-original-title') 15817 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 15818 15819 return title 15820 } 15821 15822 Tooltip.prototype.tip = function () { 15823 return this.$tip = this.$tip || $(this.options.template) 15824 } 15825 15826 Tooltip.prototype.arrow = function () { 15827 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 15828 } 15829 15830 Tooltip.prototype.validate = function () { 15831 if (!this.$element[0].parentNode) { 15832 this.hide() 15833 this.$element = null 15834 this.options = null 15835 } 15836 } 15837 15838 Tooltip.prototype.enable = function () { 15839 this.enabled = true 15840 } 15841 15842 Tooltip.prototype.disable = function () { 15843 this.enabled = false 15844 } 15845 15846 Tooltip.prototype.toggleEnabled = function () { 15847 this.enabled = !this.enabled 15848 } 15849 15850 Tooltip.prototype.toggle = function (e) { 15851 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 15852 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 15853 } 15854 15855 Tooltip.prototype.destroy = function () { 15856 clearTimeout(this.timeout) 15857 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 15858 } 15859 15860 15861 // TOOLTIP PLUGIN DEFINITION 15862 // ========================= 15863 15864 var old = $.fn.tooltip 15865 15866 $.fn.tooltip = function (option) { 15867 return this.each(function () { 15868 var $this = $(this) 15869 var data = $this.data('bs.tooltip') 15870 var options = typeof option == 'object' && option 15871 15872 if (!data && option == 'destroy') return 15873 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 15874 if (typeof option == 'string') data[option]() 15875 }) 15876 } 15877 15878 $.fn.tooltip.Constructor = Tooltip 15879 15880 15881 // TOOLTIP NO CONFLICT 15882 // =================== 15883 15884 $.fn.tooltip.noConflict = function () { 15885 $.fn.tooltip = old 15886 return this 15887 } 15888 15889}(jQuery); 15890 15891 15892/* ======================================================================== 15893 * Bootstrap: transition.js v3.1.1 15894 * http://getbootstrap.com/javascript/#transitions 15895 * ======================================================================== 15896 * Copyright 2011-2014 Twitter, Inc. 15897 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15898 * ======================================================================== */ 15899 15900 15901+function ($) { 15902 'use strict'; 15903 15904 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 15905 // ============================================================ 15906 15907 function transitionEnd() { 15908 var el = document.createElement('bootstrap') 15909 15910 var transEndEventNames = { 15911 WebkitTransition : 'webkitTransitionEnd', 15912 MozTransition : 'transitionend', 15913 OTransition : 'oTransitionEnd otransitionend', 15914 transition : 'transitionend' 15915 } 15916 15917 for (var name in transEndEventNames) { 15918 if (el.style[name] !== undefined) { 15919 return { end: transEndEventNames[name] } 15920 } 15921 } 15922 15923 return false // explicit for ie8 ( ._.) 15924 } 15925 15926 // http://blog.alexmaccaw.com/css-transitions 15927 $.fn.emulateTransitionEnd = function (duration) { 15928 var called = false, $el = this 15929 $(this).one($.support.transition.end, function () { called = true }) 15930 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 15931 setTimeout(callback, duration) 15932 return this 15933 } 15934 15935 $(function () { 15936 $.support.transition = transitionEnd() 15937 }) 15938 15939}(jQuery); 15940 15941
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.