vendor: 7,057 bytes, lines 1-245
1/*! 2 * Fotorama 4.6.3 | http://fotorama.io/license/ 3 */ 4fotoramaVersion = '4.6.3'; 5(function (window, document, location, $, undefined) { 6 "use strict"; 7var _fotoramaClass = 'fotorama', 8 _fullscreenClass = 'fullscreen', 9 10 wrapClass = _fotoramaClass + '__wrap', 11 wrapCss2Class = wrapClass + '--css2', 12 wrapCss3Class = wrapClass + '--css3', 13 wrapVideoClass = wrapClass + '--video', 14 wrapFadeClass = wrapClass + '--fade', 15 wrapSlideClass = wrapClass + '--slide', 16 wrapNoControlsClass = wrapClass + '--no-controls', 17 wrapNoShadowsClass = wrapClass + '--no-shadows', 18 wrapPanYClass = wrapClass + '--pan-y', 19 wrapRtlClass = wrapClass + '--rtl', 20 wrapOnlyActiveClass = wrapClass + '--only-active', 21 wrapNoCaptionsClass = wrapClass + '--no-captions', 22 wrapToggleArrowsClass = wrapClass + '--toggle-arrows', 23 24 stageClass = _fotoramaClass + '__stage', 25 stageFrameClass = stageClass + '__frame', 26 stageFrameVideoClass = stageFrameClass + '--video', 27 stageShaftClass = stageClass + '__shaft', 28 29 grabClass = _fotoramaClass + '__grab', 30 pointerClass = _fotoramaClass + '__pointer', 31 32 arrClass = _fotoramaClass + '__arr', 33 arrDisabledClass = arrClass + '--disabled', 34 arrPrevClass = arrClass + '--prev', 35 arrNextClass = arrClass + '--next', 36 arrArrClass = arrClass + '__arr', 37 38 navClass = _fotoramaClass + '__nav', 39 navWrapClass = navClass + '-wrap', 40 navShaftClass = navClass + '__shaft', 41 navDotsClass = navClass + '--dots', 42 navThumbsClass = navClass + '--thumbs', 43 navFrameClass = navClass + '__frame', 44 navFrameDotClass = navFrameClass + '--dot', 45 navFrameThumbClass = navFrameClass + '--thumb', 46 47 fadeClass = _fotoramaClass + '__fade', 48 fadeFrontClass = fadeClass + '-front', 49 fadeRearClass = fadeClass + '-rear', 50 51 shadowClass = _fotoramaClass + '__shadow', 52 shadowsClass = shadowClass + 's', 53 shadowsLeftClass = shadowsClass + '--left', 54 shadowsRightClass = shadowsClass + '--right', 55 56 activeClass = _fotoramaClass + '__active', 57 selectClass = _fotoramaClass + '__select', 58 59 hiddenClass = _fotoramaClass + '--hidden', 60 61 fullscreenClass = _fotoramaClass + '--fullscreen', 62 fullscreenIconClass = _fotoramaClass + '__fullscreen-icon', 63 64 errorClass = _fotoramaClass + '__error', 65 loadingClass = _fotoramaClass + '__loading', 66 loadedClass = _fotoramaClass + '__loaded', 67 loadedFullClass = loadedClass + '--full', 68 loadedImgClass = loadedClass + '--img', 69 70 grabbingClass = _fotoramaClass + '__grabbing', 71 72 imgClass = _fotoramaClass + '__img', 73 imgFullClass = imgClass + '--full', 74 75 dotClass = _fotoramaClass + '__dot', 76 thumbClass = _fotoramaClass + '__thumb', 77 thumbBorderClass = thumbClass + '-border', 78 79 htmlClass = _fotoramaClass + '__html', 80 81 videoClass = _fotoramaClass + '__video', 82 videoPlayClass = videoClass + '-play', 83 videoCloseClass = videoClass + '-close', 84 85 captionClass = _fotoramaClass + '__caption', 86 captionWrapClass = _fotoramaClass + '__caption__wrap', 87 88 spinnerClass = _fotoramaClass + '__spinner', 89 90 buttonAttributes = '" tabindex="0" role="button'; 91var JQUERY_VERSION = $ && $.fn.jquery.split('.'); 92 93if (!JQUERY_VERSION 94 || JQUERY_VERSION[0] < 1 95 || (JQUERY_VERSION[0] == 1 && JQUERY_VERSION[1] < 8)) { 96 throw 'Fotorama requires jQuery 1.8 or later and will not run without it.'; 97} 98// My Underscore :-) 99var _ = {}; 100/* Modernizr 2.6.2 (Custom Build) | MIT & BSD 101 * Build: http://modernizr.com/download/#-csstransforms3d-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes 102 */ 103 104var Modernizr = (function (window, document, undefined) { 105 106 var version = '2.6.2', 107 108 Modernizr = {}, 109 110 docElement = document.documentElement, 111 112 mod = 'modernizr', 113 modElem = document.createElement(mod), 114 mStyle = modElem.style, 115 116 inputElem, 117 118 toString = {}.toString, 119 120 prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), 121 122 omPrefixes = 'Webkit Moz O ms', 123 124 cssomPrefixes = omPrefixes.split(' '), 125 126 domPrefixes = omPrefixes.toLowerCase().split(' '), 127 128 tests = {}, 129 inputs = {}, 130 attrs = {}, 131 132 classes = [], 133 134 slice = classes.slice, 135 136 featureName, 137 138 injectElementWithStyles = function (rule, callback, nodes, testnames) { 139 140 var style, ret, node, docOverflow, 141 div = document.createElement('div'), 142 body = document.body, 143 fakeBody = body || document.createElement('body'); 144 145 if (parseInt(nodes, 10)) { 146 while (nodes--) { 147 node = document.createElement('div'); 148 node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 149 div.appendChild(node); 150 } 151 } 152 153 style = ['­', '<style id="s', mod, '">', rule, '</style>'].join(''); 154 div.id = mod; 155 (body ? div : fakeBody).innerHTML += style; 156 fakeBody.appendChild(div); 157 if (!body) { 158 fakeBody.style.background = ''; 159 fakeBody.style.overflow = 'hidden'; 160 docOverflow = docElement.style.overflow; 161 docElement.style.overflow = 'hidden'; 162 docElement.appendChild(fakeBody); 163 } 164 165 ret = callback(div, rule); 166 if (!body) { 167 fakeBody.parentNode.removeChild(fakeBody); 168 docElement.style.overflow = docOverflow; 169 } else { 170 div.parentNode.removeChild(div); 171 } 172 173 return !!ret; 174 175 }, 176 _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; 177 178 if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) { 179 hasOwnProp = function (object, property) { 180 return _hasOwnProperty.call(object, property); 181 }; 182 } 183 else { 184 hasOwnProp = function (object, property) { 185 return ((property in object) && is(object.constructor.prototype[property], 'undefined')); 186 }; 187 } 188 189 190 if (!Function.prototype.bind) { 191 Function.prototype.bind = function bind (that) { 192 193 var target = this; 194 195 if (typeof target != "function") { 196 throw new TypeError(); 197 } 198 199 var args = slice.call(arguments, 1), 200 bound = function () { 201 202 if (this instanceof bound) { 203 204 var F = function () { 205 }; 206 F.prototype = target.prototype; 207 var self = new F(); 208 209 var result = target.apply( 210 self, 211 args.concat(slice.call(arguments)) 212 ); 213 if (Object(result) === result) { 214 return result; 215 } 216 return self; 217 218 } else { 219 220 return target.apply( 221 that, 222 args.concat(slice.call(arguments)) 223 ); 224 225 } 226 227 }; 228 229 return bound; 230 }; 231 } 232 233 function setCss (str) { 234 mStyle.cssText = str; 235 } 236 237 function setCssAll (str1, str2) { 238 return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); 239 } 240 241 function is (obj, type) { 242 return typeof obj === type; 243 } 244 245 function contains (str, substr) {
246 return !!~('' + str).indexOf(substr); 247 } 248 249 function testProps (props, prefixed) { 250 for (var i in props) { 251 var prop = props[i]; 252 if (!contains(prop, "-") && mStyle[prop] !== undefined) { 253 return prefixed == 'pfx' ? prop : true; 254 } 255 } 256 return false; 257 } 258 259 function testDOMProps (props, obj, elem) { 260 for (var i in props) { 261 var item = obj[props[i]]; 262 if (item !== undefined) { 263 264 if (elem === false) return props[i]; 265 266 if (is(item, 'function')) { 267 return item.bind(elem || obj); 268 } 269 270 return item; 271 } 272 } 273 return false; 274 } 275 276 function testPropsAll (prop, prefixed, elem) { 277 278 var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 279 props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); 280 281 if (is(prefixed, "string") || is(prefixed, "undefined")) { 282 return testProps(props, prefixed); 283 284 } else { 285 props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); 286 return testDOMProps(props, prefixed, elem); 287 } 288 } 289 290 tests['csstransforms3d'] = function () { 291 292 var ret = !!testPropsAll('perspective'); 293 294// Chrome fails that test, ignore 295// if (ret && 'webkitPerspective' in docElement.style) { 296// 297// injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function (node, rule) { 298// ret = node.offsetLeft === 9 && node.offsetHeight === 3; 299// }); 300// } 301 return ret; 302 }; 303 304 for (var feature in tests) { 305 if (hasOwnProp(tests, feature)) { 306 featureName = feature.toLowerCase(); 307 Modernizr[featureName] = tests[feature](); 308 309 classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); 310 } 311 } 312 313 Modernizr.addTest = function (feature, test) { 314 if (typeof feature == 'object') { 315 for (var key in feature) { 316 if (hasOwnProp(feature, key)) { 317 Modernizr.addTest(key, feature[ key ]); 318 } 319 } 320 } else { 321 322 feature = feature.toLowerCase(); 323 324 if (Modernizr[feature] !== undefined) { 325 return Modernizr; 326 } 327 328 test = typeof test == 'function' ? test() : test; 329 330 if (typeof enableClasses !== "undefined" && enableClasses) { 331 docElement.className += ' ' + (test ? '' : 'no-') + feature; 332 } 333 Modernizr[feature] = test; 334 335 } 336 337 return Modernizr; 338 }; 339 340 341 setCss(''); 342 modElem = inputElem = null; 343 344 345 Modernizr._version = version; 346 347 Modernizr._prefixes = prefixes; 348 Modernizr._domPrefixes = domPrefixes; 349 Modernizr._cssomPrefixes = cssomPrefixes; 350 351 Modernizr.testProp = function (prop) { 352 return testProps([prop]); 353 }; 354 355 Modernizr.testAllProps = testPropsAll; 356 357 Modernizr.testStyles = injectElementWithStyles; 358 Modernizr.prefixed = function (prop, obj, elem) { 359 if (!obj) { 360 return testPropsAll(prop, 'pfx'); 361 } else { 362 return testPropsAll(prop, obj, elem); 363 } 364 }; 365 366 return Modernizr; 367})(window, document); 368var fullScreenApi = { 369 ok: false, 370 is: function () { 371 return false; 372 }, 373 request: function () { 374 }, 375 cancel: function () { 376 }, 377 event: '', 378 prefix: '' 379 }, 380 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 381 382// check for native support 383if (typeof document.cancelFullScreen != 'undefined') { 384 fullScreenApi.ok = true; 385} else { 386 // check for fullscreen support by vendor prefix 387 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 388 fullScreenApi.prefix = browserPrefixes[i]; 389 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen' ] != 'undefined') { 390 fullScreenApi.ok = true; 391 break; 392 } 393 } 394} 395 396// update methods to do something useful 397if (fullScreenApi.ok) { 398 fullScreenApi.event = fullScreenApi.prefix + 'fullscreenchange'; 399 fullScreenApi.is = function () { 400 switch (this.prefix) { 401 case '': 402 return document.fullScreen; 403 case 'webkit': 404 return document.webkitIsFullScreen; 405 default: 406 return document[this.prefix + 'FullScreen']; 407 } 408 }; 409 fullScreenApi.request = function (el) { 410 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 411 }; 412 fullScreenApi.cancel = function (el) { 413 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 414 }; 415} 416//fgnass.github.com/spin.js#v1.3.2 417 418/** 419 * Copyright (c) 2011-2013 Felix Gnass 420 * Licensed under the MIT license 421 */ 422 423var Spinner, 424 spinnerDefaults = { 425 lines: 12, // The number of lines to draw 426 length: 5, // The length of each line 427 width: 2, // The line thickness 428 radius: 7, // The radius of the inner circle 429 corners: 1, // Corner roundness (0..1) 430 rotate: 15, // The rotation offset 431 color: 'rgba(128, 128, 128, .75)', 432 hwaccel: true 433 }, 434 spinnerOverride = { 435 top: 'auto', 436 left: 'auto', 437 className: '' 438 }; 439 440(function(root, factory) { 441 442 /* CommonJS */ 443 //if (typeof exports == 'object') module.exports = factory() 444 445 /* AMD module */ 446 //else if (typeof define == 'function' && define.amd) define(factory) 447 448 /* Browser global */ 449 //else root.Spinner = factory() 450 451 Spinner = factory(); 452} 453(this, function() { 454 "use strict"; 455 456 var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */ 457 , animations = {} /* Animation rules keyed by their name */ 458 , useCssAnimations /* Whether to use CSS animations or setTimeout */ 459 460 /** 461 * Utility function to create elements. If no tag name is given, 462 * a DIV is created. Optionally properties can be passed. 463 */ 464 function createEl(tag, prop) { 465 var el = document.createElement(tag || 'div') 466 , n 467 468 for(n in prop) el[n] = prop[n] 469 return el 470 } 471 472 /** 473 * Appends children and returns the parent. 474 */ 475 function ins(parent /* child1, child2, ...*/) { 476 for (var i=1, n=arguments.length; i<n; i++) 477 parent.appendChild(arguments[i]) 478 479 return parent 480 } 481 482 /** 483 * Insert a new stylesheet to hold the @keyframe or VML rules. 484 */ 485 var sheet = (function() { 486 var el = createEl('style', {type : 'text/css'}) 487 ins(document.getElementsByTagName('head')[0], el) 488 return el.sheet || el.styleSheet 489 }()) 490 491 /** 492 * Creates an opacity keyframe animation rule and returns its name. 493 * Since most mobile Webkits have timing issues with animation-delay, 494 * we create separate rules for each line/segment. 495 */ 496 function addAnimation(alpha, trail, i, lines) { 497 var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-') 498 , start = 0.01 + i/lines * 100 499 , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha) 500 , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase() 501 , pre = prefix && '-' + prefix + '-' || '' 502 503 if (!animations[name]) { 504 sheet.insertRule( 505 '@' + pre + 'keyframes ' + name + '{' + 506 '0%{opacity:' + z + '}' + 507 start + '%{opacity:' + alpha + '}' + 508 (start+0.01) + '%{opacity:1}' + 509 (start+trail) % 100 + '%{opacity:' + alpha + '}' + 510 '100%{opacity:' + z + '}' + 511 '}', sheet.cssRules.length) 512 513 animations[name] = 1 514 } 515 516 return name 517 } 518 519 /**
520 * Tries various vendor prefixes and returns the first supported property. 521 */ 522 function vendor(el, prop) { 523 var s = el.style 524 , pp 525 , i 526 527 prop = prop.charAt(0).toUpperCase() + prop.slice(1) 528 for(i=0; i<prefixes.length; i++) { 529 pp = prefixes[i]+prop 530 if(s[pp] !== undefined) return pp 531 } 532 if(s[prop] !== undefined) return prop 533 } 534 535 /** 536 * Sets multiple style properties at once. 537 */ 538 function css(el, prop) { 539 for (var n in prop) 540 el.style[vendor(el, n)||n] = prop[n] 541 542 return el 543 } 544 545 /** 546 * Fills in default values. 547 */ 548 function merge(obj) { 549 for (var i=1; i < arguments.length; i++) { 550 var def = arguments[i] 551 for (var n in def) 552 if (obj[n] === undefined) obj[n] = def[n] 553 } 554 return obj 555 } 556 557 /** 558 * Returns the absolute page-offset of the given element. 559 */ 560 function pos(el) { 561 var o = { x:el.offsetLeft, y:el.offsetTop } 562 while((el = el.offsetParent)) 563 o.x+=el.offsetLeft, o.y+=el.offsetTop 564 565 return o 566 } 567 568 /** 569 * Returns the line color from the given string or array. 570 */ 571 function getColor(color, idx) { 572 return typeof color == 'string' ? color : color[idx % color.length] 573 } 574 575 // Built-in defaults 576 577 var defaults = { 578 lines: 12, // The number of lines to draw 579 length: 7, // The length of each line 580 width: 5, // The line thickness 581 radius: 10, // The radius of the inner circle 582 rotate: 0, // Rotation offset 583 corners: 1, // Roundness (0..1) 584 color: '#000', // #rgb or #rrggbb 585 direction: 1, // 1: clockwise, -1: counterclockwise 586 speed: 1, // Rounds per second 587 trail: 100, // Afterglow percentage 588 opacity: 1/4, // Opacity of the lines 589 fps: 20, // Frames per second when using setTimeout() 590 zIndex: 2e9, // Use a high z-index by default 591 className: 'spinner', // CSS class to assign to the element 592 top: 'auto', // center vertically 593 left: 'auto', // center horizontally 594 position: 'relative' // element position 595 } 596 597 /** The constructor */ 598 function Spinner(o) { 599 if (typeof this == 'undefined') return new Spinner(o) 600 this.opts = merge(o || {}, Spinner.defaults, defaults) 601 } 602 603 // Global defaults that override the built-ins: 604 Spinner.defaults = {} 605 606 merge(Spinner.prototype, { 607 608 /** 609 * Adds the spinner to the given target element. If this instance is already 610 * spinning, it is automatically removed from its previous target b calling 611 * stop() internally. 612 */ 613 spin: function(target) { 614 this.stop() 615 616 var self = this 617 , o = self.opts 618 , el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex}) 619 , mid = o.radius+o.length+o.width 620 , ep // element position 621 , tp // target position 622 623 if (target) { 624 target.insertBefore(el, target.firstChild||null) 625 tp = pos(target) 626 ep = pos(el) 627 css(el, { 628 left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : parseInt(o.left, 10) + mid) + 'px', 629 top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px' 630 }) 631 } 632 633 el.setAttribute('role', 'progressbar') 634 self.lines(el, self.opts) 635 636 if (!useCssAnimations) { 637 // No CSS animation support, use setTimeout() instead 638 var i = 0 639 , start = (o.lines - 1) * (1 - o.direction) / 2 640 , alpha 641 , fps = o.fps 642 , f = fps/o.speed 643 , ostep = (1-o.opacity) / (f*o.trail / 100) 644 , astep = f/o.lines 645 646 ;(function anim() { 647 i++; 648 for (var j = 0; j < o.lines; j++) { 649 alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity) 650 651 self.opacity(el, j * o.direction + start, alpha, o) 652 } 653 self.timeout = self.el && setTimeout(anim, ~~(1000/fps)) 654 })() 655 } 656 return self 657 }, 658 659 /** 660 * Stops and removes the Spinner. 661 */ 662 stop: function() { 663 var el = this.el 664 if (el) { 665 clearTimeout(this.timeout) 666 if (el.parentNode) el.parentNode.removeChild(el) 667 this.el = undefined 668 } 669 return this 670 }, 671 672 /** 673 * Internal method that draws the individual lines. Will be overwritten 674 * in VML fallback mode below. 675 */ 676 lines: function(el, o) { 677 var i = 0 678 , start = (o.lines - 1) * (1 - o.direction) / 2 679 , seg 680 681 function fill(color, shadow) { 682 return css(createEl(), { 683 position: 'absolute', 684 width: (o.length+o.width) + 'px', 685 height: o.width + 'px', 686 background: color, 687 boxShadow: shadow, 688 transformOrigin: 'left', 689 transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)', 690 borderRadius: (o.corners * o.width>>1) + 'px' 691 }) 692 } 693 694 for (; i < o.lines; i++) { 695 seg = css(createEl(), { 696 position: 'absolute', 697 top: 1+~(o.width/2) + 'px',
698 transform: o.hwaccel ? 'translate3d(0,0,0)' : '', 699 opacity: o.opacity, 700 animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite' 701 }) 702 703 if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'})) 704 ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)'))) 705 } 706 return el 707 }, 708 709 /** 710 * Internal method that adjusts the opacity of a single line. 711 * Will be overwritten in VML fallback mode below. 712 */ 713 opacity: function(el, i, val) { 714 if (i < el.childNodes.length) el.childNodes[i].style.opacity = val 715 } 716 717 }) 718 719 720 function initVML() { 721 722 /* Utility function to create a VML tag */ 723 function vml(tag, attr) { 724 return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr) 725 } 726 727 // No CSS transforms but VML support, add a CSS rule for VML elements: 728 sheet.addRule('.spin-vml', 'behavior:url(#default#VML)') 729 730 Spinner.prototype.lines = function(el, o) { 731 var r = o.length+o.width 732 , s = 2*r 733 734 function grp() { 735 return css( 736 vml('group', { 737 coordsize: s + ' ' + s, 738 coordorigin: -r + ' ' + -r 739 }), 740 { width: s, height: s } 741 ) 742 } 743 744 var margin = -(o.width+o.length)*2 + 'px' 745 , g = css(grp(), {position: 'absolute', top: margin, left: margin}) 746 , i 747 748 function seg(i, dx, filter) { 749 ins(g, 750 ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}), 751 ins(css(vml('roundrect', {arcsize: o.corners}), { 752 width: r, 753 height: o.width, 754 left: o.radius, 755 top: -o.width>>1, 756 filter: filter 757 }), 758 vml('fill', {color: getColor(o.color, i), opacity: o.opacity}), 759 vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change 760 ) 761 ) 762 ) 763 } 764 765 if (o.shadow) 766 for (i = 1; i <= o.lines; i++) 767 seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)') 768 769 for (i = 1; i <= o.lines; i++) seg(i) 770 return ins(el, g) 771 } 772 773 Spinner.prototype.opacity = function(el, i, val, o) { 774 var c = el.firstChild 775 o = o.shadow && o.lines || 0 776 if (c && i+o < c.childNodes.length) { 777 c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild 778 if (c) c.opacity = val 779 } 780 } 781 } 782 783 var probe = css(createEl('group'), {behavior: 'url(#default#VML)'}) 784 785 if (!vendor(probe, 'transform') && probe.adj) initVML() 786 else useCssAnimations = vendor(probe, 'animation') 787 788 return Spinner 789 790})); 791 792/* Bez v1.0.10-g5ae0136 793 * http://github.com/rdallasgray/bez 794 * 795 * A plugin to convert CSS3 cubic-bezier co-ordinates to jQuery-compatible easing functions 796 * 797 * With thanks to Nikolay Nemshilov for clarification on the cubic-bezier maths 798 * See http://st-on-it.blogspot.com/2011/05/calculating-cubic-bezier-function.html 799 * 800 * Copyright 2011 Robert Dallas Gray. All rights reserved. 801 * Provided under the FreeBSD license: https://github.com/rdallasgray/bez/blob/master/LICENSE.txt 802 */ 803function bez (coOrdArray) { 804 var encodedFuncName = "bez_" + $.makeArray(arguments).join("_").replace(".", "p"); 805 if (typeof $['easing'][encodedFuncName] !== "function") { 806 var polyBez = function (p1, p2) { 807 var A = [null, null], 808 B = [null, null], 809 C = [null, null], 810 bezCoOrd = function (t, ax) { 811 C[ax] = 3 * p1[ax]; 812 B[ax] = 3 * (p2[ax] - p1[ax]) - C[ax]; 813 A[ax] = 1 - C[ax] - B[ax]; 814 return t * (C[ax] + t * (B[ax] + t * A[ax])); 815 }, 816 xDeriv = function (t) { 817 return C[0] + t * (2 * B[0] + 3 * A[0] * t); 818 }, 819 xForT = function (t) { 820 var x = t, i = 0, z; 821 while (++i < 14) { 822 z = bezCoOrd(x, 0) - t; 823 if (Math.abs(z) < 1e-3) break; 824 x -= z / xDeriv(x); 825 } 826 return x; 827 }; 828 return function (t) { 829 return bezCoOrd(xForT(t), 1); 830 } 831 }; 832 $['easing'][encodedFuncName] = function (x, t, b, c, d) { 833 return c * polyBez([coOrdArray[0], coOrdArray[1]], [coOrdArray[2], coOrdArray[3]])(t / d) + b; 834 } 835 } 836 return encodedFuncName; 837} 838var $WINDOW = $(window), 839 $DOCUMENT = $(document), 840 $HTML, 841 $BODY, 842 843 QUIRKS_FORCE = location.hash.replace('#', '') === 'quirks', 844 TRANSFORMS3D = Modernizr.csstransforms3d, 845 CSS3 = TRANSFORMS3D && !QUIRKS_FORCE, 846 COMPAT = TRANSFORMS3D || document.compatMode === 'CSS1Compat', 847 FULLSCREEN = fullScreenApi.ok, 848 849 MOBILE = navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|W
849indows Phone/i), 850 SLOW = !CSS3 || MOBILE, 851 852 MS_POINTER = navigator.msPointerEnabled, 853 854 WHEEL = "onwheel" in document.createElement("div") ? "wheel" : document.onmousewheel !== undefined ? "mousewheel" : "DOMMouseScroll", 855 856 TOUCH_TIMEOUT = 250, 857 TRANSITION_DURATION = 300, 858 859 SCROLL_LOCK_TIMEOUT = 1400, 860 861 AUTOPLAY_INTERVAL = 5000, 862 MARGIN = 2, 863 THUMB_SIZE = 64, 864 865 WIDTH = 500, 866 HEIGHT = 333, 867 868 STAGE_FRAME_KEY = '$stageFrame', 869 NAV_DOT_FRAME_KEY = '$navDotFrame', 870 NAV_THUMB_FRAME_KEY = '$navThumbFrame', 871 872 AUTO = 'auto', 873 874 BEZIER = bez([.1, 0, .25, 1]), 875 876 MAX_WIDTH = 99999, 877 878 FIFTYFIFTY = '50%', 879 880 OPTIONS = { 881 // dimensions 882 width: null, // 500 || '100%' 883 minwidth: null, 884 maxwidth: '100%', // '100%' 885 height: null, 886 minheight: null, 887 maxheight: null, 888 889 ratio: null, // '16/9' || 500/333 || 1.5 890 891 margin: MARGIN, 892 glimpse: 0, 893 894 fit: 'contain', // 'cover' || 'scaledown' || 'none' 895 896 position: FIFTYFIFTY, 897 thumbposition: FIFTYFIFTY, 898 899 // navigation, thumbs 900 nav: 'dots', // 'thumbs' || false 901 navposition: 'bottom', // 'top' 902 navwidth: null, 903 thumbwidth: THUMB_SIZE, 904 thumbheight: THUMB_SIZE, 905 thumbmargin: MARGIN, 906 thumbborderwidth: MARGIN, 907 thumbfit: 'cover', // 'contain' || 'scaledown' || 'none' 908
909 allowfullscreen: false, // true || 'native' 910 911 transition: 'slide', // 'crossfade' || 'dissolve' 912 clicktransition: null, 913 transitionduration: TRANSITION_DURATION, 914 915 captions: true, 916 917 hash: false, 918 startindex: 0, 919 920 loop: false, 921 922 autoplay: false, 923 stopautoplayontouch: true, 924 925 keyboard: false, 926 927 arrows: true, 928 click: true, 929 swipe: true, 930 trackpad: false, 931 932 enableifsingleframe: false, 933 934 controlsonstart: true, 935 936 shuffle: false, 937 938 direction: 'ltr', // 'rtl' 939 940 shadows: true, 941 spinner: null 942 }, 943 944 KEYBOARD_OPTIONS = { 945 left: true, 946 right: true, 947 down: false, 948 up: false, 949 space: false, 950 home: false, 951 end: false 952 }; 953function noop () {} 954 955function minMaxLimit (value, min, max) { 956 return Math.max(isNaN(min) ? -Infinity : min, Math.min(isNaN(max) ? Infinity : max, value)); 957} 958 959function readTransform (css) { 960 return css.match(/ma/) && css.match(/-?\d+(?!d)/g)[css.match(/3d/) ? 12 : 4]; 961} 962 963function readPosition ($el) { 964 if (CSS3) { 965 return +readTransform($el.css('transform')); 966 } else { 967 return +$el.css('left').replace('px', ''); 968 } 969} 970 971function getTranslate (pos/*, _001*/) { 972 var obj = {}; 973 if (CSS3) { 974 obj.transform = 'translate3d(' + (pos/* + (_001 ? 0.001 : 0)*/) + 'px,0,0)'; // 0.001 to remove Retina artifacts 975 } else { 976 obj.left = pos; 977 } 978 return obj; 979} 980 981function getDuration (time) { 982 return {'transition-duration': time + 'ms'}; 983} 984 985function unlessNaN (value, alternative) { 986 return isNaN(value) ? alternative : value; 987} 988 989function numberFromMeasure (value, measure) { 990 return unlessNaN(+String(value).replace(measure || 'px', '')); 991} 992 993function numberFromPercent (value) { 994 return /%$/.test(value) ? numberFromMeasure(value, '%') : undefined; 995} 996 997function numberFromWhatever (value, whole) { 998 return unlessNaN(numberFromPercent(value) / 100 * whole, numberFromMeasure(value)); 999} 1000 1001function measureIsValid (value) { 1002 return (!isNaN(numberFromMeasure(value)) || !isNaN(numberFromMeasure(value, '%'))) && value; 1003} 1004 1005function getPosByIndex (index, side, margin, baseIndex) { 1006 ////console.log('getPosByIndex', index, side, margin, baseIndex); 1007 ////console.log((index - (baseIndex || 0)) * (side + (margin || 0))); 1008 1009 return (index - (baseIndex || 0)) * (side + (margin || 0)); 1010} 1011 1012function getIndexByPos (pos, side, margin, baseIndex) { 1013 return -Math.round(pos / (side + (margin || 0)) - (baseIndex || 0)); 1014} 1015 1016function bindTransitionEnd ($el) { 1017 var elData = $el.data(); 1018 1019 if (elData.tEnd) return; 1020 1021 var el = $el[0], 1022 transitionEndEvent = { 1023 WebkitTransition: 'webkitTransitionEnd', 1024 MozTransition: 'transitionend', 1025 OTransition: 'oTransitionEnd otransitionend', 1026 msTransition: 'MSTransitionEnd', 1027 transition: 'transitionend' 1028 }; 1029 addEvent(el, transitionEndEvent[Modernizr.prefixed('transition')], function (e) { 1030 elData.tProp && e.propertyName.match(elData.tProp) && elData.onEndFn(); 1031 }); 1032 elData.tEnd = true; 1033} 1034 1035function afterTransition ($el, property, fn, time) { 1036 var ok, 1037 elData = $el.data(); 1038 1039 if (elData) { 1040 elData.onEndFn = function () { 1041 if (ok) return; 1042 ok = true; 1043 clearTimeout(elData.tT); 1044 fn(); 1045 }; 1046 elData.tProp = property; 1047 1048 // Passive call, just in case of fail of native transition-end event 1049 clearTimeout(elData.tT); 1050 elData.tT = setTimeout(function () { 1051 elData.onEndFn(); 1052 }, time * 1.5); 1053 1054 bindTransitionEnd($el); 1055 } 1056} 1057 1058 1059function stop ($el, left/*, _001*/) { 1060 if ($el.length) { 1061 var elData = $el.data(); 1062 if (CSS3) { 1063 $el.css(getDuration(0)); 1064 elData.onEndFn = noop; 1065 clearTimeout(elData.tT); 1066 } else { 1067 $el.stop(); 1068 } 1069 var lockedLeft = getNumber(left, function () { 1070 return readPosition($el); 1071 }); 1072 1073 $el.css(getTranslate(lockedLeft/*, _001*/));//.width(); // `.width()` for reflow 1074 return lockedLeft; 1075 } 1076} 1077 1078function getNumber () { 1079 var number; 1080 for (var _i = 0, _l = arguments.length; _i < _l; _i++) { 1081 number = _i ? arguments[_i]() : arguments[_i]; 1082 if (typeof number === 'number') { 1083 break; 1084 } 1085 } 1086 1087 return number; 1088} 1089 1090function edgeResistance (pos, edge) { 1091 return Math.round(pos + ((edge - pos) / 1.5)); 1092} 1093 1094function getProtocol () { 1095 getProtocol.p = getProtocol.p || (location.protocol === 'https:' ? 'https://' : 'http://'); 1096 return getProtocol.p; 1097} 1098 1099function parseHref (href) { 1100 var a = document.createElement('a'); 1101 a.href = href; 1102 return a; 1103} 1104 1105function findVideoId (href, forceVideo) { 1106 if (typeof href !== 'string') return href; 1107 href = parseHref(href); 1108 1109 var id, 1110 type; 1111 1112 if (href.host.match(/youtube\.com/) && href.search) { 1113 //.log(); 1114 id = href.search.split('v=')[1]; 1115 if (id) { 1116 var ampersandPosition = id.indexOf('&'); 1117 if (ampersandPosition !== -1) { 1118 id = id.substring(0, ampersandPosition); 1119 } 1120 type = 'youtube'; 1121 } 1122 } else if (href.host.match(/youtube\.com|youtu\.be/)) { 1123 id = href.pathname.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, ''); 1124 type = 'youtube'; 1125 } else if (href.host.match(/vimeo\.com/)) { 1126 type = 'vimeo'; 1127 id = href.pathname.replace(/^\/(video\/)?/, '').replace(/\/.*/, ''); 1128 } 1129 1130 if ((!id || !type) && forceVideo) { 1131 id = href.href; 1132 type = 'custom'; 1133 } 1134 1135 return id ? {id: id, type: type, s: href.search.replace(/^\?/, ''), p: getProtocol()} : false;
1136} 1137 1138function getVideoThumbs (dataFrame, data, fotorama) { 1139 var img, thumb, video = dataFrame.video; 1140 if (video.type === 'youtube') { 1141 thumb = getProtocol() + 'img.youtube.com/vi/' + video.id + '/default.jpg'; 1142 img = thumb.replace(/\/default.jpg$/, '/hqdefault.jpg'); 1143 dataFrame.thumbsReady = true; 1144 } else if (video.type === 'vimeo') { 1145 $.ajax({ 1146 url: getProtocol() + 'vimeo.com/api/v2/video/' + video.id + '.json', 1147 dataType: 'jsonp', 1148 success: function (json) { 1149 dataFrame.thumbsReady = true; 1150 updateData(data, {img: json[0].thumbnail_large, thumb: json[0].thumbnail_small}, dataFrame.i, fotorama); 1151 } 1152 }); 1153 } else { 1154 dataFrame.thumbsReady = true; 1155 } 1156 1157 return { 1158 img: img, 1159 thumb: thumb 1160 } 1161} 1162 1163function updateData (data, _dataFrame, i, fotorama) { 1164 for (var _i = 0, _l = data.length; _i < _l; _i++) { 1165 var dataFrame = data[_i]; 1166 1167 if (dataFrame.i === i && dataFrame.thumbsReady) { 1168 var clear = {videoReady: true}; 1169 clear[STAGE_FRAME_KEY] = clear[NAV_THUMB_FRAME_KEY] = clear[NAV_DOT_FRAME_KEY] = false; 1170 1171 fotorama.splice(_i, 1, $.extend( 1172 {}, 1173 dataFrame, 1174 clear, 1175 _dataFrame 1176 )); 1177 1178 break; 1179 } 1180 } 1181} 1182 1183function getDataFromHtml ($el) { 1184 var data = []; 1185 1186 function getDataFromImg ($img, imgData, checkVideo) { 1187 var $child = $img.children('img').eq(0), 1188 _imgHref = $img.attr('href'), 1189 _imgSrc = $img.attr('src'), 1190 _thumbSrc = $child.attr('src'), 1191 _video = imgData.video, 1192 video = checkVideo ? findVideoId(_imgHref, _video === true) : false; 1193 1194 if (video) { 1195 _imgHref = false;
1196 } else { 1197 video = _video; 1198 } 1199 1200 getDimensions($img, $child, $.extend(imgData, { 1201 video: video, 1202 img: imgData.img || _imgHref || _imgSrc || _thumbSrc, 1203 thumb: imgData.thumb || _thumbSrc || _imgSrc || _imgHref 1204 })); 1205 } 1206 1207 function getDimensions ($img, $child, imgData) { 1208 var separateThumbFLAG = imgData.thumb && imgData.img !== imgData.thumb, 1209 width = numberFromMeasure(imgData.width || $img.attr('width')), 1210 height = numberFromMeasure(imgData.height || $img.attr('height')); 1211 1212 $.extend(imgData, { 1213 width: width, 1214 height: height, 1215 thumbratio: getRatio(imgData.thumbratio || (numberFromMeasure(imgData.thumbwidth || ($child && $child.attr('width')) || separateThumbFLAG || width) / numberFromMeasure(imgData.thumbheight || ($child && $child.attr('height')) || separateThumbFLAG || height))) 1216 }); 1217 } 1218 1219 $el.children().each(function () { 1220 var $this = $(this), 1221 dataFrame = optionsToLowerCase($.extend($this.data(), {id: $this.attr('id')})); 1222 if ($this.is('a, img')) { 1223 getDataFromImg($this, dataFrame, true); 1224 } else if (!$this.is(':empty')) { 1225 getDimensions($this, null, $.extend(dataFrame, { 1226 html: this, 1227 _html: $this.html() // Because of IE 1228 })); 1229 } else return; 1230 1231 data.push(dataFrame); 1232 }); 1233 1234 return data; 1235} 1236 1237function isHidden (el) { 1238 return el.offsetWidth === 0 && el.offsetHeight === 0; 1239} 1240 1241function isDetached (el) { 1242 return !$.contains(document.documentElement, el); 1243} 1244 1245function waitFor (test, fn, timeout, i) { 1246 if (!waitFor.i) { 1247 waitFor.i = 1; 1248 waitFor.ii = [true]; 1249 } 1250 1251 i = i || waitFor.i; 1252 1253 if (typeof waitFor.ii[i] === 'undefined') { 1254 waitFor.ii[i] = true; 1255 } 1256 1257 if (test()) { 1258 fn(); 1259 } else { 1260 waitFor.ii[i] && setTimeout(function () { 1261 waitFor.ii[i] && waitFor(test, fn, timeout, i); 1262 }, timeout || 100); 1263 } 1264 1265 return waitFor.i++; 1266} 1267 1268waitFor.stop = function (i) { 1269 waitFor.ii[i] = false; 1270}; 1271 1272function setHash (hash) { 1273 //////console.time('setHash ' + hash); 1274 location.replace(location.protocol 1275 + '//' 1276 + location.host 1277 + location.pathname.replace(/^\/?/, '/') 1278 + location.search 1279 + '#' + hash); 1280 //////console.timeEnd('setHash ' + hash); 1281} 1282 1283function fit ($el, measuresToFit, method, position) { 1284 var elData = $el.data(), 1285 measures = elData.measures; 1286 1287 if (measures && (!elData.l || 1288 elData.l.W !== measures.width || 1289 elData.l.H !== measures.height || 1290 elData.l.r !== measures.ratio || 1291 elData.l.w !== measuresToFit.w || 1292 elData.l.h !== measuresToFit.h || 1293 elData.l.m !== method || 1294 elData.l.p !== position)) { 1295 1296 //console.log('fit'); 1297 1298 var width = measures.width, 1299 height = measures.height, 1300 ratio = measuresToFit.w / measuresToFit.h, 1301 biggerRatioFLAG = measures.ratio >= ratio, 1302 fitFLAG = method === 'scaledown', 1303 containFLAG = method === 'contain', 1304 coverFLAG = method === 'cover', 1305 pos = parsePosition(position); 1306 1307 if (biggerRatioFLAG && (fitFLAG || containFLAG) || !biggerRatioFLAG && coverFLAG) { 1308 width = minMaxLimit(measuresToFit.w, 0, fitFLAG ? width : Infinity); 1309 height = width / measures.ratio; 1310 } else if (biggerRatioFLAG && coverFLAG || !biggerRatioFLAG && (fitFLAG || containFLAG)) { 1311 height = minMaxLimit(measuresToFit.h, 0, fitFLAG ? height : Infinity); 1312 width = height * measures.ratio; 1313 } 1314 1315 $el.css({ 1316 width: width, 1317 height: height, 1318 left: numberFromWhatever(pos.x, measuresToFit.w - width), 1319 top: numberFromWhatever(pos.y, measuresToFit.h- height) 1320 }); 1321 1322 elData.l = { 1323 W: measures.width, 1324 H: measures.height, 1325 r: measures.ratio, 1326 w: measuresToFit.w, 1327 h: measuresToFit.h, 1328 m: method, 1329 p: position 1330 }; 1331 } 1332 1333 return true; 1334} 1335 1336function setStyle ($el, style) { 1337 var el = $el[0]; 1338 if (el.styleSheet) { 1339 el.styleSheet.cssText = style; 1340 } else { 1341 $el.html(style); 1342 } 1343} 1344 1345function findShadowEdge (pos, min, max) { 1346 return min === max ? false : pos <= min ? 'left' : pos >= max ? 'right' : 'left right';
1347} 1348 1349function getIndexFromHash (hash, data, ok, startindex) { 1350 if (!ok) return false; 1351 if (!isNaN(hash)) return hash - (startindex ? 0 : 1); 1352 1353 var index; 1354 1355 for (var _i = 0, _l = data.length; _i < _l; _i++) { 1356 var dataFrame = data[_i]; 1357 1358 if (dataFrame.id === hash) { 1359 index = _i; 1360 break; 1361 } 1362 } 1363 1364 return index; 1365} 1366 1367function smartClick ($el, fn, _options) { 1368 _options = _options || {}; 1369 1370 $el.each(function () { 1371 var $this = $(this), 1372 thisData = $this.data(), 1373 startEvent; 1374 1375 if (thisData.clickOn) return; 1376 1377 thisData.clickOn = true; 1378 1379 $.extend(touch($this, { 1380 onStart: function (e) { 1381 startEvent = e; 1382 (_options.onStart || noop).call(this, e); 1383 }, 1384 onMove: _options.onMove || noop, 1385 onTouchEnd: _options.onTouchEnd || noop, 1386 onEnd: function (result) { 1387 ////console.log('smartClick → result.moved', result.moved); 1388 if (result.moved) return; 1389 fn.call(this, startEvent); 1390 } 1391 }), {noMove: true}); 1392 }); 1393} 1394 1395function div (classes, child) { 1396 return '<div class="' + classes + '">' + (child || '') + '</div>'; 1397} 1398 1399// Fisher–Yates Shuffle 1400// http://bost.ocks.org/mike/shuffle/ 1401function shuffle (array) { 1402 // While there remain elements to shuffle 1403 var l = array.length; 1404 while (l) { 1405 // Pick a remaining element 1406 var i = Math.floor(Math.random() * l--); 1407 1408 // And swap it with the current element 1409 var t = array[l]; 1410 array[l] = array[i]; 1411 array[i] = t; 1412 } 1413 1414 return array; 1415} 1416 1417function clone (array) { 1418 return Object.prototype.toString.call(array) == '[object Array]' 1419 && $.map(array, function (frame) { 1420 return $.extend({}, frame); 1421 }); 1422} 1423 1424function lockScroll ($el, left, top) { 1425 $el 1426 .scrollLeft(left || 0) 1427 .scrollTop(top || 0); 1428} 1429 1430function optionsToLowerCase (options) { 1431 if (options) { 1432 var opts = {}; 1433 $.each(options, function (key, value) { 1434 opts[key.toLowerCase()] = value; 1435 }); 1436 1437 return opts; 1438 } 1439} 1440 1441function getRatio (_ratio) { 1442 if (!_ratio) return; 1443 var ratio = +_ratio; 1444 if (!isNaN(ratio)) { 1445 return ratio; 1446 } else { 1447 ratio = _ratio.split('/'); 1448 return +ratio[0] / +ratio[1] || undefined; 1449 } 1450} 1451 1452function addEvent (el, e, fn, bool) { 1453 if (!e) return; 1454 el.addEventListener ? el.addEventListener(e, fn, !!bool) : el.attachEvent('on'+e, fn); 1455} 1456 1457function elIsDisabled (el) { 1458 return !!el.getAttribute('disabled'); 1459} 1460 1461function disableAttr (FLAG) { 1462 return {tabindex: FLAG * -1 + '', disabled: FLAG}; 1463} 1464 1465function addEnterUp (el, fn) { 1466 addEvent(el, 'keyup', function (e) { 1467 elIsDisabled(el) || e.keyCode == 13 && fn.call(el, e); 1468 }); 1469} 1470 1471function addFocus (el, fn) { 1472 addEvent(el, 'focus', el.onfocusin = function (e) { 1473 fn.call(el, e); 1474 }, true); 1475} 1476 1477function stopEvent (e, stopPropagation) { 1478 e.preventDefault ? e.preventDefault() : (e.returnValue = false); 1479 stopPropagation && e.stopPropagation && e.stopPropagation(); 1480} 1481 1482function getDirectionSign (forward) { 1483 return forward ? '>' : '<'; 1484} 1485 1486function parsePosition (rule) { 1487 rule = (rule + '').split(/\s+/); 1488 return { 1489 x: measureIsValid(rule[0]) || FIFTYFIFTY, 1490 y: measureIsValid(rule[1]) || FIFTYFIFTY 1491 } 1492} 1493function slide ($el, options) { 1494 var elData = $el.data(), 1495 elPos = Math.round(options.pos), 1496 onEndFn = function () { 1497 elData.sliding = false; 1498 (options.onEnd || noop)(); 1499 }; 1500 1501 if (typeof options.overPos !== 'undefined' && options.overPos !== options.pos) { 1502 elPos = options.overPos; 1503 onEndFn = function () { 1504 slide($el, $.extend({}, options, {overPos: options.pos, time: Math.max(TRANSITION_DURATION, options.time / 2)})) 1505 }; 1506 } 1507 1508 ////////console.time('var translate = $.extend'); 1509 var translate = $.extend(getTranslate(elPos/*, options._001*/), options.width && {width: options.width}); 1510 ////////console.timeEnd('var translate = $.extend'); 1511 1512 elData.sliding = true; 1513 1514 if (CSS3) { 1515 $el.css($.extend(getDuration(options.time), translate)); 1516 if (options.time > 10) { 1517 ////////console.time('afterTransition'); 1518 afterTransition($el, 'transform', onEndFn, options.time);
1519 ////////console.timeEnd('afterTransition'); 1520 } else { 1521 onEndFn(); 1522 } 1523 } else { 1524 $el.stop().animate(translate, options.time, BEZIER, onEndFn); 1525 } 1526} 1527 1528function fade ($el1, $el2, $frames, options, fadeStack, chain) { 1529 var chainedFLAG = typeof chain !== 'undefined'; 1530 if (!chainedFLAG) { 1531 fadeStack.push(arguments); 1532 Array.prototype.push.call(arguments, fadeStack.length); 1533 if (fadeStack.length > 1) return; 1534 } 1535 1536 $el1 = $el1 || $($el1); 1537 $el2 = $el2 || $($el2); 1538 1539 var _$el1 = $el1[0], 1540 _$el2 = $el2[0], 1541 crossfadeFLAG = options.method === 'crossfade', 1542 onEndFn = function () { 1543 if (!onEndFn.done) { 1544 onEndFn.done = true; 1545 var args = (chainedFLAG || fadeStack.shift()) && fadeStack.shift(); 1546 args && fade.apply(this, args); 1547 (options.onEnd || noop)(!!args); 1548 } 1549 }, 1550 time = options.time / (chain || 1); 1551 1552 $frames.removeClass(fadeRearClass + ' ' + fadeFrontClass); 1553 1554 $el1 1555 .stop() 1556 .addClass(fadeRearClass); 1557 $el2 1558 .stop() 1559 .addClass(fadeFrontClass); 1560 1561 crossfadeFLAG && _$el2 && $el1.fadeTo(0, 0); 1562 1563 $el1.fadeTo(crossfadeFLAG ? time : 0, 1, crossfadeFLAG && onEndFn); 1564 $el2.fadeTo(time, 0, onEndFn); 1565 1566 (_$el1 && crossfadeFLAG) || _$el2 || onEndFn(); 1567} 1568var lastEvent, 1569 moveEventType, 1570 preventEvent, 1571 preventEventTimeout; 1572 1573function extendEvent (e) { 1574 var touch = (e.touches || [])[0] || e; 1575 e._x = touch.pageX; 1576 e._y = touch.clientY; 1577 e._now = $.now(); 1578} 1579 1580function touch ($el, options) { 1581 var el = $el[0], 1582 tail = {}, 1583 touchEnabledFLAG, 1584 startEvent, 1585 $target, 1586 controlTouch, 1587 touchFLAG, 1588 targetIsSelectFLAG, 1589 targetIsLinkFlag, 1590 tolerance, 1591 moved; 1592 1593 function onStart (e) { 1594 $target = $(e.target); 1595 tail.checked = targetIsSelectFLAG = targetIsLinkFlag = moved = false; 1596 1597 if (touchEnabledFLAG 1598 || tail.flow 1599 || (e.touches && e.touches.length > 1) 1600 || e.which > 1 1601 || (lastEvent && lastEvent.type !== e.type && preventEvent) 1602 || (targetIsSelectFLAG = options.select && $target.is(options.select, el))) return targetIsSelectFLAG; 1603 1604 touchFLAG = e.type === 'touchstart'; 1605 targetIsLinkFlag = $target.is('a, a *', el); 1606 controlTouch = tail.control; 1607 1608 tolerance = (tail.noMove || tail.noSwipe || controlTouch) ? 16 : !tail.snap ? 4 : 0; 1609 1610 extendEvent(e); 1611 1612 startEvent = lastEvent = e; 1613 moveEventType = e.type.replace(/down|start/, 'move').replace(/Down/, 'Move'); 1614 1615 (options.onStart || noop).call(el, e, {control: controlTouch, $target: $target}); 1616 1617 touchEnabledFLAG = tail.flow = true; 1618 1619 if (!touchFLAG || tail.go) stopEvent(e); 1620 } 1621 1622 function onMove (e) { 1623 if ((e.touches && e.touches.length > 1) 1624 || (MS_POINTER && !e.isPrimary) 1625 || moveEventType !== e.type 1626 || !touchEnabledFLAG) { 1627 touchEnabledFLAG && onEnd(); 1628 (options.onTouchEnd || noop)(); 1629 return; 1630 } 1631 1632 extendEvent(e); 1633 1634 var xDiff = Math.abs(e._x - startEvent._x), // opt _x → _pageX 1635 yDiff = Math.abs(e._y - startEvent._y), 1636 xyDiff = xDiff - yDiff, 1637 xWin = (tail.go || tail.x || xyDiff >= 0) && !tail.noSwipe, 1638 yWin = xyDiff < 0; 1639 1640 if (touchFLAG && !tail.checked) { 1641 if (touchEnabledFLAG = xWin) { 1642 stopEvent(e); 1643 } 1644 } else { 1645 ////console.log('onMove e.preventDefault'); 1646 stopEvent(e); 1647 (options.onMove || noop).call(el, e, {touch: touchFLAG}); 1648 } 1649 1650 if (!moved && Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)) > tolerance) { 1651 moved = true; 1652 } 1653 1654 tail.checked = tail.checked || xWin || yWin; 1655 } 1656 1657 function onEnd (e) { 1658 //////console.time('touch.js onEnd'); 1659 1660 (options.onTouchEnd || noop)(); 1661 1662 var _touchEnabledFLAG = touchEnabledFLAG; 1663 tail.control = touchEnabledFLAG = false; 1664 1665 if (_touchEnabledFLAG) { 1666 tail.flow = false; 1667 } 1668 1669 if (!_touchEnabledFLAG || (targetIsLinkFlag && !tail.checked)) return; 1670 1671 e && stopEvent(e); 1672 1673 preventEvent = true; 1674 clearTimeout(preventEventTimeout); 1675 preventEventTimeout = setTimeout(function () { 1676 preventEvent = false;
1677 }, 1000); 1678 1679 (options.onEnd || noop).call(el, {moved: moved, $target: $target, control: controlTouch, touch: touchFLAG, startEvent: startEvent, aborted: !e || e.type === 'MSPointerCancel'}); 1680 //////console.timeEnd('touch.js onEnd'); 1681 } 1682 1683 function onOtherStart () { 1684 if (tail.flow) return; 1685 setTimeout(function () { 1686 tail.flow = true; 1687 }, 10); 1688 } 1689 1690 function onOtherEnd () { 1691 if (!tail.flow) return; 1692 setTimeout(function () { 1693 tail.flow = false; 1694 }, TOUCH_TIMEOUT); 1695 } 1696 1697 if (MS_POINTER) { 1698 addEvent(el, 'MSPointerDown', onStart); 1699 addEvent(document, 'MSPointerMove', onMove); 1700 addEvent(document,'MSPointerCancel', onEnd); 1701 addEvent(document, 'MSPointerUp', onEnd); 1702 } else { 1703 addEvent(el, 'touchstart', onStart); 1704 addEvent(el, 'touchmove', onMove); 1705 addEvent(el, 'touchend', onEnd); 1706 1707 addEvent(document, 'touchstart', onOtherStart); 1708 addEvent(document, 'touchend', onOtherEnd); 1709 addEvent(document, 'touchcancel', onOtherEnd); 1710 1711 $WINDOW.on('scroll', onOtherEnd); 1712 1713 $el.on('mousedown', onStart); 1714 $DOCUMENT 1715 .on('mousemove', onMove) 1716 .on('mouseup', onEnd); 1717 } 1718 1719 $el.on('click', 'a', function (e) { 1720 tail.checked && stopEvent(e); 1721 }); 1722 1723 return tail; 1724} 1725 1726function moveOnTouch ($el, options) { 1727 var el = $el[0], 1728 elData = $el.data(), 1729 tail = {}, 1730 startCoo, 1731 coo, 1732 startElPos, 1733 moveElPos, 1734 edge, 1735 moveTrack, 1736 startTime, 1737 endTime, 1738 min, 1739 max, 1740 snap, 1741 slowFLAG, 1742 controlFLAG, 1743 moved, 1744 tracked; 1745 1746 function startTracking (e, noStop) { 1747 tracked = true; 1748 startCoo = coo = e._x; 1749 startTime = e._now; 1750 1751 moveTrack = [ 1752 [startTime, startCoo] 1753 ]; 1754 1755 startElPos = moveElPos = tail.noMove || noStop ? 0 : stop($el, (options.getPos || noop)()/*, options._001*/); 1756 1757 (options.onStart || noop).call(el, e); 1758 } 1759 1760 function onStart (e, result) { 1761 min = tail.min; 1762 max = tail.max; 1763 snap = tail.snap; 1764 1765 slowFLAG = e.altKey; 1766 tracked = moved = false; 1767 1768 controlFLAG = result.control; 1769 1770 if (!controlFLAG && !elData.sliding) { 1771 startTracking(e); 1772 } 1773 } 1774 1775 function onMove (e, result) { 1776 if (!tail.noSwipe) { 1777 if (!tracked) { 1778 startTracking(e); 1779 } 1780 1781 coo = e._x; 1782 1783 moveTrack.push([e._now, coo]); 1784 1785 moveElPos = startElPos - (startCoo - coo); 1786 1787 edge = findShadowEdge(moveElPos, min, max); 1788 1789 if (moveElPos <= min) { 1790 moveElPos = edgeResistance(moveElPos, min); 1791 } else if (moveElPos >= max) { 1792 moveElPos = edgeResistance(moveElPos, max); 1793 } 1794 1795 if (!tail.noMove) { 1796 $el.css(getTranslate(moveElPos/*, options._001*/)); 1797 if (!moved) { 1798 moved = true; 1799 // only for mouse 1800 result.touch || MS_POINTER || $el.addClass(grabbingClass); 1801 } 1802 1803 (options.onMove || noop).call(el, e, {pos: moveElPos, edge: edge}); 1804 } 1805 } 1806 } 1807 1808 function onEnd (result) { 1809 //////console.time('moveontouch.js onEnd'); 1810 if (tail.noSwipe && result.moved) return; 1811 1812 if (!tracked) { 1813 startTracking(result.startEvent, true); 1814 } 1815 1816 ////console.log('onEnd'); 1817 1818 result.touch || MS_POINTER || $el.removeClass(grabbingClass); 1819 1820 endTime = $.now(); 1821 1822 var _backTimeIdeal = endTime - TOUCH_TIMEOUT, 1823 _backTime, 1824 _timeDiff, 1825 _timeDiffLast, 1826 backTime = null, 1827 backCoo, 1828 virtualPos, 1829 limitPos, 1830 newPos, 1831 overPos, 1832 time = TRANSITION_DURATION, 1833 speed, 1834 friction = options.friction; 1835 1836 for (var _i = moveTrack.length - 1; _i >= 0; _i--) { 1837 _backTime = moveTrack[_i][0]; 1838 _timeDiff = Math.abs(_backTime - _backTimeIdeal); 1839 if (backTime === null || _timeDiff < _timeDiffLast) { 1840 backTime = _backTime; 1841 backCoo = moveTrack[_i][1]; 1842 } else if (backTime === _backTimeIdeal || _timeDiff > _timeDiffLast) { 1843 break; 1844 } 1845 _timeDiffLast = _timeDiff; 1846 } 1847 1848 newPos = minMaxLimit(moveElPos, min, max); 1849 1850 var cooDiff = backCoo - coo, 1851 forwardFLAG = cooDiff >= 0, 1852 timeDiff = endTime - backTime, 1853 longTouchFLAG = timeDiff > TOUCH_TIMEOUT, 1854 swipeFLAG = !longTouchFLAG && moveElPos !== startElPos && newPos === moveElPos; 1855 1856 if (snap) { 1857 newPos = minMaxLimit(Math[swipeFLAG ? (forwardFLAG ? 'floor' : 'ceil') : 'round'](moveElPos / snap) * snap, min, max); 1858 min = max = newPos; 1859 } 1860 1861 if (swipeFLAG && (snap || newPos === moveElPos)) { 1862 speed = -(cooDiff / timeDiff); 1863 time *= minMaxLimit(Math.abs(speed), options.timeLow, options.timeHigh); 1864 virtualPos = Math.round(moveElPos + speed * time / friction); 1865 1866 if (!snap) { 1867 newPos = virtualPos; 1868 } 1869 1870 if (!forwardFLAG && virtualPos > max || forwardFLAG && virtualPos < min) { 1871 limitPos = forwardFLAG ? min : max; 1872 overPos = virtualPos - limitPos; 1873 if (!snap) { 1874 newPos = limitPos; 1875 } 1876 overPos = minMaxLimit(newPos + overPos * .03, limitPos - 50, limitPos + 50); 1877 time = Math.abs((moveElPos - overPos) / (speed / friction)); 1878 } 1879 } 1880 1881 time *= slowFLAG ? 10 : 1; 1882 1883 (options.onEnd || noop).call(el, $.extend(result, {moved: result.moved || longTouchFLAG && snap, pos: moveElPos, newPos: newPos, overPos: overPos, time: time})); 1884 } 1885 1886 tail = $.extend(touch(options.$wrap, $.extend({}, options, { 1887 onStart: onStart, 1888 onMove: onMove, 1889 onEnd: onEnd 1890 })), tail); 1891 1892 return tail; 1893} 1894function wheel ($el, options) { 1895 var el = $el[0], 1896 lockFLAG, 1897 lastDirection, 1898 lastNow, 1899 tail = { 1900 prevent: {} 1901 }; 1902 1903 addEvent(el, WHEEL, function (e) { 1904 var yDelta = e.wheelDeltaY || -1 * e.deltaY || 0, 1905 xDelta = e.wheelDeltaX || -1 * e.deltaX || 0, 1906 xWin = Math.abs(xDelta) && !Math.abs(yDelta), 1907 direction = getDirectionSign(xDelta < 0), 1908 sameDirection = lastDirection === direction, 1909 now = $.now(),
1910 tooFast = now - lastNow < TOUCH_TIMEOUT; 1911 1912 lastDirection = direction; 1913 lastNow = now; 1914 1915 if (!xWin || !tail.ok || tail.prevent[direction] && !lockFLAG) { 1916 return; 1917 } else { 1918 stopEvent(e, true); 1919 if (lockFLAG && sameDirection && tooFast) { 1920 return; 1921 } 1922 } 1923 1924 if (options.shift) { 1925 lockFLAG = true; 1926 clearTimeout(tail.t); 1927 tail.t = setTimeout(function () { 1928 lockFLAG = false; 1929 }, SCROLL_LOCK_TIMEOUT); 1930 } 1931 1932 (options.onEnd || noop)(e, options.shift ? direction : xDelta); 1933 1934 }); 1935 1936 return tail; 1937} 1938jQuery.Fotorama = function ($fotorama, opts) { 1939 $HTML = $('html'); 1940 $BODY = $('body'); 1941 1942 var that = this, 1943 stamp = $.now(), 1944 stampClass = _fotoramaClass + stamp, 1945 fotorama = $fotorama[0], 1946 data, 1947 dataFrameCount = 1, 1948 fotoramaData = $fotorama.data(), 1949 size, 1950 1951 $style = $('<style></style>'), 1952 1953 $anchor = $(div(hiddenClass)), 1954 $wrap = $(div(wrapClass)), 1955 $stage = $(div(stageClass)).appendTo($wrap), 1956 stage = $stage[0], 1957 1958 $stageShaft = $(div(stageShaftClass)).appendTo($stage), 1959 $stageFrame = $(), 1960 $arrPrev = $(div(arrClass + ' ' + arrPrevClass + buttonAttributes)), 1961 $arrNext = $(div(arrClass + ' ' + arrNextClass + buttonAttributes)), 1962 $arrs = $arrPrev.add($arrNext).appendTo($stage), 1963 $navWrap = $(div(navWrapClass)), 1964 $nav = $(div(navClass)).appendTo($navWrap), 1965 $navShaft = $(div(navShaftClass)).appendTo($nav), 1966 $navFrame, 1967 $navDotFrame = $(), 1968 $navThumbFrame = $(), 1969 1970 stageShaftData = $stageShaft.data(), 1971 navShaftData = $navShaft.data(), 1972 1973 $thumbBorder = $(div(thumbBorderClass)).appendTo($navShaft), 1974 1975 $fullscreenIcon = $(div(fullscreenIconClass + buttonAttributes)), 1976 fullscreenIcon = $fullscreenIcon[0], 1977 $videoPlay = $(div(videoPlayClass)), 1978 $videoClose = $(div(videoCloseClass)).appendTo($stage), 1979 videoClose = $videoClose[0], 1980 1981 spinner, 1982 $spinner = $(div(spinnerClass)), 1983 1984 $videoPlaying, 1985 1986 activeIndex = false, 1987 activeFrame, 1988 activeIndexes, 1989 repositionIndex, 1990 dirtyIndex, 1991 lastActiveIndex, 1992 prevIndex, 1993 nextIndex, 1994 nextAutoplayIndex, 1995 startIndex, 1996 1997 o_loop, 1998 o_nav, 1999 o_navThumbs, 2000 o_navTop, 2001 o_allowFullScreen, 2002 o_nativeFullScreen, 2003 o_fade, 2004 o_thumbSide, 2005 o_thumbSide2, 2006 o_transitionDuration, 2007 o_transition, 2008 o_shadows, 2009 o_rtl, 2010 o_keyboard, 2011 lastOptions = {}, 2012 2013 measures = {}, 2014 measuresSetFLAG, 2015 2016 stageShaftTouchTail = {}, 2017 stageWheelTail = {}, 2018 navShaftTouchTail = {}, 2019 navWheelTail = {}, 2020 2021 scrollTop, 2022 scrollLeft, 2023 2024 showedFLAG, 2025 pausedAutoplayFLAG, 2026 stoppedAutoplayFLAG, 2027 2028 toDeactivate = {}, 2029 toDetach = {}, 2030 2031 measuresStash, 2032 2033 touchedFLAG, 2034 2035 hoverFLAG, 2036 2037 navFrameKey, 2038 stageLeft = 0, 2039 2040 fadeStack = []; 2041 2042 $wrap[STAGE_FRAME_KEY] = $(div(stageFrameClass)); 2043 $wrap[NAV_THUMB_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameThumbClass + buttonAttributes, div(thumbClass))); 2044 $wrap[NAV_DOT_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameDotClass + buttonAttributes, div(dotClass))); 2045 2046 toDeactivate[STAGE_FRAME_KEY] = []; 2047 toDeactivate[NAV_THUMB_FRAME_KEY] = []; 2048 toDeactivate[NAV_DOT_FRAME_KEY] = []; 2049 toDetach[STAGE_FRAME_KEY] = {}; 2050 2051 $wrap 2052 .addClass(CSS3 ? wrapCss3Class : wrapCss2Class)
2053 .toggleClass(wrapNoControlsClass, !opts.controlsonstart); 2054 2055 fotoramaData.fotorama = this; 2056 2057 function checkForVideo () { 2058 $.each(data, function (i, dataFrame) { 2059 if (!dataFrame.i) { 2060 dataFrame.i = dataFrameCount++; 2061 var video = findVideoId(dataFrame.video, true); 2062 if (video) { 2063 var thumbs = {}; 2064 dataFrame.video = video; 2065 if (!dataFrame.img && !dataFrame.thumb) { 2066 thumbs = getVideoThumbs(dataFrame, data, that); 2067 } else { 2068 dataFrame.thumbsReady = true; 2069 } 2070 updateData(data, {img: thumbs.img, thumb: thumbs.thumb}, dataFrame.i, that); 2071 } 2072 } 2073 }); 2074 } 2075 2076 function allowKey (key) { 2077 return o_keyboard[key] || that.fullScreen; 2078 } 2079 2080 function bindGlobalEvents (FLAG) { 2081 var keydownCommon = 'keydown.' + _fotoramaClass, 2082 localStamp = _fotoramaClass + stamp, 2083 keydownLocal = 'keydown.' + localStamp, 2084 resizeLocal = 'resize.' + localStamp + ' ' + 'orientationchange.' + localStamp; 2085 2086 if (FLAG) { 2087 $DOCUMENT 2088 .on(keydownLocal, function (e) { 2089 var catched, 2090 index; 2091 2092 if ($videoPlaying && e.keyCode === 27) { 2093 catched = true; 2094 unloadVideo($videoPlaying, true, true); 2095 } else if (that.fullScreen || (opts.keyboard && !that.index)) { 2096 if (e.keyCode === 27) { 2097 catched = true; 2098 that.cancelFullScreen(); 2099 } else if ((e.shiftKey && e.keyCode === 32 && allowKey('space')) || (e.keyCode === 37 && allowKey('left')) || (e.keyCode === 38 && allowKey('up'))) { 2100 index = '<'; 2101 } else if ((e.keyCode === 32 && allowKey('space')) || (e.keyCode === 39 && allowKey('right')) || (e.keyCode === 40 && allowKey('down'))) { 2102 index = '>'; 2103 } else if (e.keyCode === 36 && allowKey('home')) { 2104 index = '<<'; 2105 } else if (e.keyCode === 35 && allowKey('end')) { 2106 index = '>>'; 2107 } 2108 } 2109 2110 (catched || index) && stopEvent(e); 2111 index && that.show({index: index, slow: e.altKey, user: true}); 2112 }); 2113 2114 if (!that.index) { 2115 $DOCUMENT 2116 .off(keydownCommon) 2117 .on(keydownCommon, 'textarea, input, select', function (e) { 2118 !$BODY.hasClass(_fullscreenClass) && e.stopPropagation(); 2119 }); 2120 } 2121 2122 $WINDOW.on(resizeLocal, that.resize); 2123 } else { 2124 $DOCUMENT.off(keydownLocal); 2125 $WINDOW.off(resizeLocal); 2126 } 2127 } 2128 2129 function appendElements (FLAG) { 2130 if (FLAG === appendElements.f) return; 2131 2132 if (FLAG) { 2133 $fotorama 2134 .html('') 2135 .addClass(_fotoramaClass + ' ' + stampClass) 2136 .append($wrap) 2137 .before($style) 2138 .before($anchor); 2139 2140 addInstance(that); 2141 } else { 2142 $wrap.detach(); 2143 $style.detach(); 2144 $anchor.detach(); 2145 $fotorama 2146 .html(fotoramaData.urtext) 2147 .removeClass(stampClass); 2148 2149 hideInstance(that); 2150 } 2151 2152 bindGlobalEvents(FLAG); 2153 appendElements.f = FLAG; 2154 } 2155 2156 function setData () { 2157 data = that.data = data || clone(opts.data) || getDataFromHtml($fotorama); 2158 size = that.size = data.length; 2159 2160 !ready.ok && opts.shuffle && shuffle(data); 2161 2162 checkForVideo(); 2163 2164 activeIndex = limitIndex(activeIndex); 2165 2166 size && appendElements(true); 2167 } 2168 2169 function stageNoMove () { 2170 var _noMove = (size < 2 && !opts.enableifsingleframe) || $videoPlaying; 2171 stageShaftTouchTail.noMove = _noMove || o_fade; 2172 stageShaftTouchTail.noSwipe = _noMove || !opts.swipe; 2173 2174 !o_transition && $stageShaft.toggleClass(grabClass, !opts.click && !stageShaftTouchTail.noMove && !stageShaftTouchTail.noSwipe); 2175 MS_POINTER && $wrap.toggleClass(wrapPanYClass, !stageShaftTouchTail.noSwipe); 2176 } 2177 2178 function setAutoplayInterval (interval) { 2179 if (interval === true) interval = ''; 2180 opts.autoplay = Math.max(+interval || AUTOPLAY_INTERVAL, o_transitionDuration * 1.5); 2181 } 2182 2183 /** 2184 * Options on the fly 2185 * */ 2186 function setOptions () { 2187 that.options = opts = optionsToLowerCase(opts); 2188 2189 o_fade = (opts.transition === 'crossfade' || opts.transition === 'dissolve'); 2190 2191 o_loop = opts.loop && (size > 2 || (o_fade && (!o_transition || o_transition !== 'slide'))); 2192 2193 o_transitionDuration = +opts.transitionduration || TRANSITION_DURATION; 2194 2195 o_rtl = opts.direction === 'rtl'; 2196 2197 o_keyboard = $.extend({}, opts.keyboard && KEYBOARD_OPTIONS, opts.keyboard); 2198 2199 var classes = {add: [], remove: []}; 2200 2201 function addOrRemoveClass (FLAG, value) { 2202 classes[FLAG ? 'add' : 'remove'].push(value); 2203 } 2204 2205 if (size > 1 || opts.enableifsingleframe) { 2206 o_nav = opts.nav; 2207 o_navTop = opts.navposition === 'top'; 2208 classes.remove.push(selectClass); 2209 2210 $arrs.toggle(!!opts.arrows); 2211 } else { 2212 o_nav = false;
2213 $arrs.hide(); 2214 } 2215 2216 spinnerStop(); 2217 spinner = new Spinner($.extend(spinnerDefaults, opts.spinner, spinnerOverride, {direction: o_rtl ? -1 : 1})); 2218 2219 arrsUpdate(); 2220 stageWheelUpdate(); 2221 2222 if (opts.autoplay) setAutoplayInterval(opts.autoplay); 2223 2224 o_thumbSide = numberFromMeasure(opts.thumbwidth) || THUMB_SIZE; 2225 o_thumbSide2 = numberFromMeasure(opts.thumbheight) || THUMB_SIZE; 2226 2227 stageWheelTail.ok = navWheelTail.ok = opts.trackpad && !SLOW; 2228 2229 stageNoMove(); 2230 2231 extendMeasures(opts, [measures]); 2232 2233 o_navThumbs = o_nav === 'thumbs'; 2234 2235 if (o_navThumbs) { 2236 frameDraw(size, 'navThumb'); 2237 2238 $navFrame = $navThumbFrame; 2239 navFrameKey = NAV_THUMB_FRAME_KEY; 2240 2241 setStyle($style, $.Fotorama.jst.style({w: o_thumbSide, h: o_thumbSide2, b: opts.thumbborderwidth, m: opts.thumbmargin, s: stamp, q: !COMPAT})); 2242 2243 $nav 2244 .addClass(navThumbsClass) 2245 .removeClass(navDotsClass); 2246 } else if (o_nav === 'dots') { 2247 frameDraw(size, 'navDot'); 2248 2249 $navFrame = $navDotFrame; 2250 navFrameKey = NAV_DOT_FRAME_KEY; 2251 2252 $nav 2253 .addClass(navDotsClass) 2254 .removeClass(navThumbsClass); 2255 } else { 2256 o_nav = false; 2257 $nav.removeClass(navThumbsClass + ' ' + navDotsClass); 2258 } 2259 2260 if (o_nav) { 2261 if (o_navTop) { 2262 $navWrap.insertBefore($stage); 2263 } else { 2264 $navWrap.insertAfter($stage); 2265 } 2266 frameAppend.nav = false; 2267 frameAppend($navFrame, $navShaft, 'nav'); 2268 } 2269 2270 o_allowFullScreen = opts.allowfullscreen; 2271 2272 if (o_allowFullScreen) { 2273 $fullscreenIcon.prependTo($stage); 2274 o_nativeFullScreen = FULLSCREEN && o_allowFullScreen === 'native'; 2275 } else { 2276 $fullscreenIcon.detach(); 2277 o_nativeFullScreen = false; 2278 } 2279 2280 addOrRemoveClass(o_fade, wrapFadeClass); 2281 addOrRemoveClass(!o_fade, wrapSlideClass); 2282 addOrRemoveClass(!opts.captions, wrapNoCaptionsClass); 2283 addOrRemoveClass(o_rtl, wrapRtlClass); 2284 addOrRemoveClass(opts.arrows !== 'always', wrapToggleArrowsClass); 2285 2286 o_shadows = opts.shadows && !SLOW; 2287 addOrRemoveClass(!o_shadows, wrapNoShadowsClass); 2288 2289 $wrap
2290 .addClass(classes.add.join(' ')) 2291 .removeClass(classes.remove.join(' ')); 2292 2293 lastOptions = $.extend({}, opts); 2294 } 2295 2296 function normalizeIndex (index) { 2297 return index < 0 ? (size + (index % size)) % size : index >= size ? index % size : index; 2298 } 2299 2300 function limitIndex (index) { 2301 return minMaxLimit(index, 0, size - 1); 2302 } 2303 2304 function edgeIndex (index) { 2305 return o_loop ? normalizeIndex(index) : limitIndex(index); 2306 } 2307 2308 function getPrevIndex (index) { 2309 return index > 0 || o_loop ? index - 1 : false; 2310 } 2311 2312 function getNextIndex (index) { 2313 return index < size - 1 || o_loop ? index + 1 : false; 2314 } 2315 2316 function setStageShaftMinmaxAndSnap () { 2317 stageShaftTouchTail.min = o_loop ? -Infinity : -getPosByIndex(size - 1, measures.w, opts.margin, repositionIndex); 2318 stageShaftTouchTail.max = o_loop ? Infinity : -getPosByIndex(0, measures.w, opts.margin, repositionIndex); 2319 stageShaftTouchTail.snap = measures.w + opts.margin; 2320 } 2321 2322 function setNavShaftMinMax () { 2323 ////////console.log('setNavShaftMinMax', measures.nw); 2324 navShaftTouchTail.min = Math.min(0, measures.nw - $navShaft.width()); 2325 navShaftTouchTail.max = 0; 2326 $navShaft.toggleClass(grabClass, !(navShaftTouchTail.noMove = navShaftTouchTail.min === navShaftTouchTail.max)); 2327 } 2328 2329 function eachIndex (indexes, type, fn) { 2330 if (typeof indexes === 'number') { 2331 indexes = new Array(indexes); 2332 var rangeFLAG = true; 2333 } 2334 return $.each(indexes, function (i, index) { 2335 if (rangeFLAG) index = i; 2336 if (typeof index === 'number') { 2337 var dataFrame = data[normalizeIndex(index)]; 2338 2339 if (dataFrame) { 2340 var key = '$' + type + 'Frame', 2341 $frame = dataFrame[key]; 2342 2343 fn.call(this, i, index, dataFrame, $frame, key, $frame && $frame.data()); 2344 } 2345 } 2346 }); 2347 } 2348 2349 function setMeasures (width, height, ratio, index) { 2350 if (!measuresSetFLAG || (measuresSetFLAG === '*' && index === startIndex)) { 2351 2352 //////console.log('setMeasures', index, opts.width, opts.height); 2353 2354 width = measureIsValid(opts.width) || measureIsValid(width) || WIDTH;
2355 height = measureIsValid(opts.height) || measureIsValid(height) || HEIGHT; 2356 that.resize({ 2357 width: width, 2358 ratio: opts.ratio || ratio || width / height 2359 }, 0, index !== startIndex && '*'); 2360 } 2361 } 2362 2363 function loadImg (indexes, type, specialMeasures, method, position, again) { 2364 eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) { 2365 2366 if (!$frame) return; 2367 2368 var fullFLAG = that.fullScreen && dataFrame.full && dataFrame.full !== dataFrame.img && !frameData.$full && type === 'stage'; 2369 2370 if (frameData.$img && !again && !fullFLAG) return; 2371 2372 var img = new Image(), 2373 $img = $(img), 2374 imgData = $img.data(); 2375 2376 frameData[fullFLAG ? '$full' : '$img'] = $img; 2377 2378 var srcKey = type === 'stage' ? (fullFLAG ? 'full' : 'img') : 'thumb', 2379 src = dataFrame[srcKey], 2380 dummy = fullFLAG ? null : dataFrame[type === 'stage' ? 'thumb' : 'img']; 2381 2382 if (type === 'navThumb') $frame = frameData.$wrap; 2383 2384 function triggerTriggerEvent (event) { 2385 var _index = normalizeIndex(index); 2386 triggerEvent(event, { 2387 index: _index, 2388 src: src, 2389 frame: data[_index] 2390 }); 2391 } 2392 2393 function error () { 2394 $img.remove(); 2395 2396 $.Fotorama.cache[src] = 'error'; 2397 2398 if ((!dataFrame.html || type !== 'stage') && dummy && dummy !== src) { 2399 dataFrame[srcKey] = src = dummy; 2400 loadImg([index], type, specialMeasures, method, position, true); 2401 } else { 2402 if (src && !dataFrame.html && !fullFLAG) { 2403 $frame 2404 .trigger('f:error') 2405 .removeClass(loadingClass) 2406 .addClass(errorClass); 2407 2408 triggerTriggerEvent('error'); 2409 } else if (type === 'stage') { 2410 $frame 2411 .trigger('f:load') 2412 .removeClass(loadingClass + ' ' + errorClass) 2413 .addClass(loadedClass); 2414 2415 triggerTriggerEvent('load'); 2416 setMeasures(); 2417 } 2418 2419 frameData.state = 'error'; 2420 2421 if (size > 1 && data[index] === dataFrame && !dataFrame.html && !dataFrame.deleted && !dataFrame.video && !fullFLAG) { 2422 dataFrame.deleted = true; 2423 that.splice(index, 1); 2424 } 2425 } 2426 } 2427 2428 function loaded () { 2429 //////console.log('loaded: ' + src); 2430 2431 ////console.log('$.Fotorama.measures[src]', $.Fotorama.measures[src]); 2432 2433 $.Fotorama.measures[src] = imgData.measures = $.Fotorama.measures[src] || { 2434 width: img.width, 2435 height: img.height, 2436 ratio: img.width / img.height 2437 }; 2438 2439 setMeasures(imgData.measures.width, imgData.measures.height, imgData.measures.ratio, index); 2440 2441 $img 2442 .off('load error') 2443 .addClass(imgClass + (fullFLAG ? ' ' + imgFullClass : '')) 2444 .prependTo($frame); 2445 2446 fit($img, ($.isFunction(specialMeasures) ? specialMeasures() : specialMeasures) || measures, method || dataFrame.fit || opts.fit, position || dataFrame.position || opts.position); 2447 2448 $.Fotorama.cache[src] = frameData.state = 'loaded'; 2449 2450 setTimeout(function () { 2451 $frame 2452 .trigger('f:load') 2453 .removeClass(loadingClass + ' ' + errorClass) 2454 .addClass(loadedClass + ' ' + (fullFLAG ? loadedFullClass : loadedImgClass)); 2455 2456 if (type === 'stage') { 2457 triggerTriggerEvent('load'); 2458 } else if (dataFrame.thumbratio === AUTO || !dataFrame.thumbratio && opts.thumbratio === AUTO) { 2459 // danger! reflow for all thumbnails 2460 dataFrame.thumbratio = imgData.measures.ratio; 2461 reset(); 2462 } 2463 }, 0); 2464 } 2465 2466 if (!src) { 2467 error(); 2468 return; 2469 } 2470 2471 function waitAndLoad () { 2472 var _i = 10; 2473 waitFor(function () { 2474 return !touchedFLAG || !_i-- && !SLOW; 2475 }, function () { 2476 loaded(); 2477 }); 2478 } 2479 2480 if (!$.Fotorama.cache[src]) { 2481 $.Fotorama.cache[src] = '*'; 2482 2483 $img 2484 .on('load', waitAndLoad) 2485 .on('error', error); 2486 } else { 2487 (function justWait () { 2488 if ($.Fotorama.cache[src] === 'error') { 2489 error(); 2490 } else if ($.Fotorama.cache[src] === 'loaded') { 2491 ////console.log('take from cache: ' + src);
2492 setTimeout(waitAndLoad, 0); 2493 } else { 2494 setTimeout(justWait, 100); 2495 } 2496 })(); 2497 } 2498 2499 frameData.state = ''; 2500 img.src = src; 2501 }); 2502 } 2503 2504 function spinnerSpin ($el) { 2505 $spinner.append(spinner.spin().el).appendTo($el); 2506 } 2507 2508 function spinnerStop () { 2509 $spinner.detach(); 2510 spinner && spinner.stop(); 2511 } 2512 2513 function updateFotoramaState () { 2514 var $frame = activeFrame[STAGE_FRAME_KEY]; 2515 2516 if ($frame && !$frame.data().state) { 2517 spinnerSpin($frame); 2518 $frame.on('f:load f:error', function () { 2519 $frame.off('f:load f:error'); 2520 spinnerStop(); 2521 }); 2522 } 2523 } 2524 2525 function addNavFrameEvents (frame) { 2526 addEnterUp(frame, onNavFrameClick); 2527 addFocus(frame, function () { 2528 2529 setTimeout(function () { 2530 lockScroll($nav); 2531 }, 0); 2532 slideNavShaft({time: o_transitionDuration, guessIndex: $(this).data().eq, minMax: navShaftTouchTail}); 2533 }); 2534 } 2535 2536 function frameDraw (indexes, type) { 2537 eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) { 2538 if ($frame) return; 2539 2540 $frame = dataFrame[key] = $wrap[key].clone(); 2541 frameData = $frame.data(); 2542 frameData.data = dataFrame; 2543 var frame = $frame[0]; 2544 2545 if (type === 'stage') { 2546 2547 if (dataFrame.html) { 2548 $('<div class="' + htmlClass + '"></div>') 2549 .append( 2550 dataFrame._html ? $(dataFrame.html) 2551 .removeAttr('id') 2552 .html(dataFrame._html) // Because of IE 2553 : dataFrame.html 2554 ) 2555 .appendTo($frame); 2556 } 2557 2558 dataFrame.caption && $(div(captionClass, div(captionWrapClass, dataFrame.caption))).appendTo($frame); 2559 2560 dataFrame.video && $frame 2561 .addClass(stageFrameVideoClass) 2562 .append($videoPlay.clone()); 2563 2564 // This solves tabbing problems 2565 addFocus(frame, function () { 2566 setTimeout(function () { 2567 lockScroll($stage); 2568 }, 0); 2569 clickToShow({index: frameData.eq, user: true}); 2570 }); 2571 2572 $stageFrame = $stageFrame.add($frame); 2573 } else if (type === 'navDot') { 2574 addNavFrameEvents(frame); 2575 $navDotFrame = $navDotFrame.add($frame); 2576 } else if (type === 'navThumb') { 2577 addNavFrameEvents(frame); 2578 frameData.$wrap = $frame.children(':first'); 2579 $navThumbFrame = $navThumbFrame.add($frame); 2580 if (dataFrame.video) { 2581 frameData.$wrap.append($videoPlay.clone()); 2582 } 2583 } 2584 }); 2585 } 2586 2587 function callFit ($img, measuresToFit, method, position) { 2588 return $img && $img.length && fit($img, measuresToFit, method, position); 2589 } 2590 2591 function stageFramePosition (indexes) { 2592 eachIndex(indexes, 'stage', function (i, index, dataFrame, $frame, key, frameData) { 2593 if (!$frame) return; 2594 2595 var normalizedIndex = normalizeIndex(index), 2596 method = dataFrame.fit || opts.fit, 2597 position = dataFrame.position || opts.position; 2598 frameData.eq = normalizedIndex; 2599 2600 toDetach[STAGE_FRAME_KEY][normalizedIndex] = $frame.css($.extend({left: o_fade ? 0 : getPosByIndex(index, measures.w, opts.margin, repositionIndex)}, o_fade && getDuration(0))); 2601 2602 if (isDetached($frame[0])) { 2603 $frame.appendTo($stageShaft); 2604 unloadVideo(dataFrame.$video); 2605 } 2606 2607 callFit(frameData.$img, measures, method, position); 2608 callFit(frameData.$full, measures, method, position); 2609 }); 2610 } 2611 2612 function thumbsDraw (pos, loadFLAG) { 2613 if (o_nav !== 'thumbs' || isNaN(pos)) return; 2614 2615 var leftLimit = -pos, 2616 rightLimit = -pos + measures.nw; 2617 2618 $navThumbFrame.each(function () { 2619 var $this = $(this), 2620 thisData = $this.data(), 2621 eq = thisData.eq, 2622 getSpecialMeasures = function () { 2623 return { 2624 h: o_thumbSide2, 2625 w: thisData.w 2626 } 2627 }, 2628 specialMeasures = getSpecialMeasures(), 2629 dataFrame = data[eq] || {}, 2630 method = dataFrame.thumbfit || opts.thumbfit, 2631 position = dataFrame.thumbposition || opts.thumbposition; 2632 2633 specialMeasures.w = thisData.w; 2634 2635 if (thisData.l + thisData.w < leftLimit 2636 || thisData.l > rightLimit 2637 || callFit(thisData.$img, specialMeasures, method, position)) return; 2638 2639 loadFLAG && loadImg([eq], 'navThumb', getSpecialMeasures, method, position); 2640 }); 2641 } 2642 2643 function frameAppend ($frames, $shaft, type) {
2644 if (!frameAppend[type]) { 2645 2646 var thumbsFLAG = type === 'nav' && o_navThumbs, 2647 left = 0; 2648 2649 $shaft.append( 2650 $frames 2651 .filter(function () { 2652 var actual, 2653 $this = $(this), 2654 frameData = $this.data(); 2655 for (var _i = 0, _l = data.length; _i < _l; _i++) { 2656 if (frameData.data === data[_i]) { 2657 actual = true; 2658 frameData.eq = _i; 2659 break; 2660 } 2661 } 2662 return actual || $this.remove() && false; 2663 }) 2664 .sort(function (a, b) { 2665 return $(a).data().eq - $(b).data().eq; 2666 }) 2667 .each(function () { 2668 2669 if (!thumbsFLAG) return; 2670 2671 var $this = $(this), 2672 frameData = $this.data(), 2673 thumbwidth = Math.round(o_thumbSide2 * frameData.data.thumbratio) || o_thumbSide; 2674 2675 frameData.l = left; 2676 frameData.w = thumbwidth; 2677 2678 $this.css({width: thumbwidth}); 2679 2680 left += thumbwidth + opts.thumbmargin; 2681 }) 2682 ); 2683 2684 frameAppend[type] = true; 2685 } 2686 } 2687 2688 function getDirection (x) { 2689 return x - stageLeft > measures.w / 3; 2690 } 2691 2692 function disableDirrection (i) { 2693 return !o_loop && (!(activeIndex + i) || !(activeIndex - size + i)) && !$videoPlaying; 2694 } 2695 2696 function arrsUpdate () { 2697 var disablePrev = disableDirrection(0), 2698 disableNext = disableDirrection(1); 2699 $arrPrev 2700 .toggleClass(arrDisabledClass, disablePrev) 2701 .attr(disableAttr(disablePrev)); 2702 $arrNext 2703 .toggleClass(arrDisabledClass, disableNext) 2704 .attr(disableAttr(disableNext)); 2705 } 2706 2707 function stageWheelUpdate () { 2708 if (stageWheelTail.ok) { 2709 stageWheelTail.prevent = {'<': disableDirrection(0), '>': disableDirrection(1)}; 2710 } 2711 } 2712 2713 function getNavFrameBounds ($navFrame) { 2714 var navFrameData = $navFrame.data(), 2715 left, 2716 width; 2717 2718 if (o_navThumbs) { 2719 left = navFrameData.l; 2720 width = navFrameData.w; 2721 } else { 2722 left = $navFrame.position().left; 2723 width = $navFrame.width(); 2724 } 2725 2726 return { 2727 c: left + width / 2, 2728 min: -left + opts.thumbmargin * 10, 2729 max: -left + measures.w - width - opts.thumbmargin * 10 2730 }; 2731 } 2732 2733 function slideThumbBorder (time) { 2734 var navFrameData = activeFrame[navFrameKey].data(); 2735 slide($thumbBorder, { 2736 time: time * 1.2, 2737 pos: navFrameData.l, 2738 width: navFrameData.w - opts.thumbborderwidth * 2 2739 }); 2740 } 2741 2742 function slideNavShaft (options) { 2743 ////console.log('slideNavShaft', options.guessIndex, options.keep, slideNavShaft.l); 2744 var $guessNavFrame = data[options.guessIndex][navFrameKey]; 2745 if ($guessNavFrame) { 2746 var overflowFLAG = navShaftTouchTail.min !== navShaftTouchTail.max, 2747 minMax = options.minMax || overflowFLAG && getNavFrameBounds(activeFrame[navFrameKey]), 2748 l = overflowFLAG && (options.keep && slideNavShaft.l ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max)), 2749 pos = overflowFLAG && minMaxLimit(l, navShaftTouchTail.min, navShaftTouchTail.max), 2750 time = options.time * 1.1; 2751 2752 slide($navShaft, { 2753 time: time, 2754 pos: pos || 0, 2755 onEnd: function () { 2756 thumbsDraw(pos, true); 2757 } 2758 }); 2759 2760 //if (time) thumbsDraw(pos); 2761 2762 setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max)); 2763 slideNavShaft.l = l; 2764 } 2765 } 2766 2767 function navUpdate () { 2768 deactivateFrames(navFrameKey); 2769 toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass)); 2770 } 2771 2772 function deactivateFrames (key) { 2773 var _toDeactivate = toDeactivate[key]; 2774 2775 while (_toDeactivate.length) { 2776 _toDeactivate.shift().removeClass(activeClass); 2777 } 2778 } 2779 2780 function detachFrames (key) { 2781 var _toDetach = toDetach[key]; 2782 2783 //////console.log('_toDetach', _toDetach); 2784 //////console.log('activeIndexes', activeIndexes); 2785 2786 $.each(activeIndexes, function (i, index) { 2787 delete _toDetach[normalizeIndex(index)]; 2788 }); 2789 2790 $.each(_toDetach, function (index, $frame) { 2791 delete _toDetach[index]; 2792 //////console.log('Detach', index); 2793 $frame.detach(); 2794 }); 2795 } 2796 2797 function stageShaftReposition (skipOnEnd) { 2798 2799 repositionIndex = dirtyIndex = activeIndex; 2800 2801 var $frame = activeFrame[STAGE_FRAME_KEY]; 2802 2803 if ($frame) { 2804 deactivateFrames(STAGE_FRAME_KEY); 2805 toDeactivate[STAGE_FRAME_KEY].push($frame.addClass(activeClass)); 2806 2807 skipOnEnd || that.show.onEnd(true); 2808 stop($stageShaft, 0, true); 2809 2810 detachFrames(STAGE_FRAME_KEY); 2811 stageFramePosition(activeIndexes); 2812 setStageShaftMinmaxAndSnap(); 2813 setNavShaftMinMax(); 2814 } 2815 } 2816 2817 function extendMeasures (options, measuresArray) { 2818 if (!options) return; 2819 2820 $.each(measuresArray, function (i, measures) { 2821 if (!measures) return; 2822 2823 $.extend(measures, { 2824 width: options.width || measures.width, 2825 height: options.height, 2826 minwidth: options.minwidth, 2827 maxwidth: options.maxwidth, 2828 minheight: options.minheight, 2829 maxheight: options.maxheight, 2830 ratio: getRatio(options.ratio) 2831 }) 2832 }); 2833 } 2834 2835 function triggerEvent (event, extra) { 2836 $fotorama.trigger(_fotoramaClass + ':' + event, [that, extra]); 2837 } 2838 2839 function onTouchStart () { 2840 clearTimeout(onTouchEnd.t); 2841 touchedFLAG = 1; 2842
2843 if (opts.stopautoplayontouch) { 2844 that.stopAutoplay(); 2845 } else { 2846 pausedAutoplayFLAG = true; 2847 } 2848 } 2849 2850 function onTouchEnd () { 2851 if (!touchedFLAG) return; 2852 if (!opts.stopautoplayontouch) { 2853 releaseAutoplay(); 2854 changeAutoplay(); 2855 } 2856 2857 onTouchEnd.t = setTimeout(function () { 2858 touchedFLAG = 0; 2859 }, TRANSITION_DURATION + TOUCH_TIMEOUT); 2860 //////console.timeEnd('onTouchEnd'); 2861 } 2862 2863 function releaseAutoplay () { 2864 ////console.log('releaseAutoplay'); 2865 pausedAutoplayFLAG = !!($videoPlaying || stoppedAutoplayFLAG); 2866 } 2867 2868 function changeAutoplay () { 2869 ////console.log('changeAutoplay'); 2870 2871 clearTimeout(changeAutoplay.t); 2872 waitFor.stop(changeAutoplay.w); 2873 2874 if (!opts.autoplay || pausedAutoplayFLAG) { 2875 if (that.autoplay) { 2876 that.autoplay = false; 2877 triggerEvent('stopautoplay'); 2878 } 2879 2880 return; 2881 } 2882 2883 ////console.log('changeAutoplay continue'); 2884 2885 if (!that.autoplay) { 2886 that.autoplay = true; 2887 triggerEvent('startautoplay'); 2888 } 2889 2890 var _activeIndex = activeIndex; 2891 2892 2893 var frameData = activeFrame[STAGE_FRAME_KEY].data(); 2894 changeAutoplay.w = waitFor(function () { 2895 ////console.log('wait for the state of the current frame'); 2896 return frameData.state || _activeIndex !== activeIndex; 2897 }, function () { 2898 ////console.log('the current frame is ready'); 2899 changeAutoplay.t = setTimeout(function () { 2900 ////console.log('changeAutoplay.t setTimeout', pausedAutoplayFLAG, _activeIndex !== activeIndex); 2901 if (pausedAutoplayFLAG || _activeIndex !== activeIndex) return; 2902 2903 var _nextAutoplayIndex = nextAutoplayIndex, 2904 nextFrameData = data[_nextAutoplayIndex][STAGE_FRAME_KEY].data(); 2905 2906 changeAutoplay.w = waitFor(function () { 2907 ////console.log('wait for the state of the next frame'); 2908 return nextFrameData.state || _nextAutoplayIndex !== nextAutoplayIndex; 2909 }, function () { 2910 if (pausedAutoplayFLAG || _nextAutoplayIndex !== nextAutoplayIndex) return; 2911 that.show(o_loop ? getDirectionSign(!o_rtl) : nextAutoplayIndex); 2912 }); 2913 }, opts.autoplay); 2914 }); 2915 2916 } 2917 2918 that.startAutoplay = function (interval) { 2919 if (that.autoplay) return this; 2920 pausedAutoplayFLAG = stoppedAutoplayFLAG = false; 2921 setAutoplayInterval(interval || opts.autoplay); 2922 changeAutoplay(); 2923 2924 return this; 2925 }; 2926 2927 that.stopAutoplay = function () { 2928 if (that.autoplay) { 2929 pausedAutoplayFLAG = stoppedAutoplayFLAG = true; 2930 changeAutoplay(); 2931 } 2932 return this; 2933 }; 2934 2935 that.show = function (options) { 2936 ////console.log('that.show'); 2937 //////console.time('that.show prepare'); 2938 var index; 2939 2940 if (typeof options !== 'object') { 2941 index = options; 2942 options = {}; 2943 } else { 2944 index = options.index; 2945 } 2946 2947 index = index === '>' ? dirtyIndex + 1 : index === '<' ? dirtyIndex - 1 : index === '<<' ? 0 : index === '>>' ? size - 1 : index; 2948 index = isNaN(index) ? getIndexFromHash(index, data, true) : index; 2949 index = typeof index === 'undefined' ? activeIndex || 0 : index; 2950 2951 that.activeIndex = activeIndex = edgeIndex(index); 2952 prevIndex = getPrevIndex(activeIndex); 2953 nextIndex = getNextIndex(activeIndex); 2954 nextAutoplayIndex = normalizeIndex(activeIndex + (o_rtl ? -1 : 1)); 2955 activeIndexes = [activeIndex, prevIndex, nextIndex]; 2956 2957 dirtyIndex = o_loop ? index : activeIndex; 2958 2959 var diffIndex = Math.abs(lastActiveIndex - dirtyIndex), 2960 time = getNumber(options.time, function () { 2961 return Math.min(o_transitionDuration * (1 + (diffIndex - 1) / 12), o_transitionDuration * 2); 2962 }), 2963 overPos = options.overPos; 2964 2965 if (options.slow) time *= 10; 2966 2967 var _activeFrame = activeFrame; 2968 that.activeFrame = activeFrame = data[activeIndex]; 2969 //////console.timeEnd('that.show prepare'); 2970 2971 var silent = _activeFrame === activeFrame && !options.user; 2972 2973 //setTimeout(function () { 2974 //////console.time('unloadVideo'); 2975 unloadVideo($videoPlaying, activeFrame.i !== data[normalizeIndex(repositionIndex)].i); 2976 //////console.timeEnd('unloadVideo'); 2977 //////console.time('frameDraw'); 2978 frameDraw(activeIndexes, 'stage'); 2979 //////console.timeEnd('frameDraw'); 2980 //////console.time('stageFramePosition'); 2981 stageFramePosition(SLOW ? [dirtyIndex] : [dirtyIndex, getPrevIndex(dirtyIndex), getNextIndex(dirtyIndex)]); 2982 //////console.timeEnd('stageFramePosition'); 2983 //////console.time('updateTouchTails'); 2984 updateTouchTails('go', true); 2985 //////console.timeEnd('updateTouchTails'); 2986 //////console.time('triggerEvent'); 2987 2988 silent || triggerEvent('show', { 2989 user: options.user, 2990 time: time 2991 }); 2992 //////console.timeEnd('triggerEvent'); 2993 //}, 0); 2994 2995 //////console.time('bind onEnd'); 2996 2997 pausedAutoplayFLAG = true; 2998 2999 var onEnd = that.show.onEnd = function (skipReposition) { 3000 if (onEnd.ok) return; 3001 onEnd.ok = true; 3002 3003 skipReposition || stageShaftReposition(true); 3004 3005 if (!silent) {
3006 triggerEvent('showend', { 3007 user: options.user 3008 }); 3009 } 3010 3011 ////console.log('o_transition', o_transition); 3012 3013 if (!skipReposition && o_transition && o_transition !== opts.transition) { 3014 ////console.log('set transition back to: ' + o_transition); 3015 that.setOptions({transition: o_transition}); 3016 o_transition = false; 3017 return; 3018 } 3019 3020 updateFotoramaState(); 3021 loadImg(activeIndexes, 'stage'); 3022 3023 updateTouchTails('go', false); 3024 stageWheelUpdate(); 3025 3026 stageCursor(); 3027 releaseAutoplay(); 3028 changeAutoplay(); 3029 }; 3030 //////console.timeEnd('bind onEnd'); 3031 3032 if (!o_fade) { 3033 //////console.time('slide'); 3034 slide($stageShaft, { 3035 pos: -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex), 3036 overPos: overPos, 3037 time: time, 3038 onEnd: onEnd/*, 3039 _001: true*/ 3040 }); 3041 //////console.timeEnd('slide'); 3042 } else { 3043 var $activeFrame = activeFrame[STAGE_FRAME_KEY], 3044 $prevActiveFrame = activeIndex !== lastActiveIndex ? data[lastActiveIndex][STAGE_FRAME_KEY] : null; 3045 3046 fade($activeFrame, $prevActiveFrame, $stageFrame, { 3047 time: time, 3048 method: opts.transition, 3049 onEnd: onEnd 3050 }, fadeStack); 3051 } 3052 3053 //////console.time('arrsUpdate'); 3054 arrsUpdate(); 3055 //////console.timeEnd('arrsUpdate'); 3056 3057 if (o_nav) { 3058 //////console.time('navUpdate'); 3059 navUpdate(); 3060 //////console.timeEnd('navUpdate'); 3061 3062 //////console.time('slideNavShaft'); 3063 var guessIndex = limitIndex(activeIndex + minMaxLimit(dirtyIndex - lastActiveIndex, -1, 1)); 3064 slideNavShaft({time: time, coo: guessIndex !== activeIndex && options.coo, guessIndex: typeof options.coo !== 'undefined' ? guessIndex : activeIndex, keep: silent}); 3065 //////console.timeEnd('slideNavShaft'); 3066 3067 //////console.time('slideThumbBorder'); 3068 if (o_navThumbs) slideThumbBorder(time); 3069 //////console.timeEnd('slideThumbBorder'); 3070 } 3071 3072 //////console.time('that.show end'); 3073 showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex; 3074 lastActiveIndex = activeIndex; 3075 opts.hash && showedFLAG && !that.eq && setHash(activeFrame.id || activeIndex + 1); 3076 //////console.timeEnd('that.show end'); 3077 3078 //////console.timeEnd('that.show'); 3079 3080 return this; 3081 }; 3082 3083 that.requestFullScreen = function () { 3084 if (o_allowFullScreen && !that.fullScreen) { 3085 scrollTop = $WINDOW.scrollTop(); 3086 scrollLeft = $WINDOW.scrollLeft(); 3087 3088 lockScroll($WINDOW); 3089 3090 updateTouchTails('x', true); 3091 3092 measuresStash = $.extend({}, measures); 3093 3094 $fotorama 3095 .addClass(fullscreenClass) 3096 .appendTo($BODY.addClass(_fullscreenClass)); 3097 3098 $HTML.addClass(_fullscreenClass); 3099 3100 unloadVideo($videoPlaying, true, true); 3101 3102 that.fullScreen = true; 3103 3104 if (o_nativeFullScreen) { 3105 fullScreenApi.request(fotorama); 3106 } 3107 3108 that.resize(); 3109 loadImg(activeIndexes, 'stage'); 3110 updateFotoramaState(); 3111 3112 triggerEvent('fullscreenenter'); 3113 } 3114 3115 return this; 3116 }; 3117 3118 function cancelFullScreen () { 3119 if (that.fullScreen) { 3120 that.fullScreen = false; 3121 3122 if (FULLSCREEN) { 3123 fullScreenApi.cancel(fotorama); 3124 } 3125 3126 $BODY.removeClass(_fullscreenClass); 3127 $HTML.removeClass(_fullscreenClass); 3128 3129 $fotorama 3130 .removeClass(fullscreenClass) 3131 .insertAfter($anchor); 3132 3133 measures = $.extend({}, measuresStash); 3134 3135 unloadVideo($videoPlaying, true, true); 3136 3137 updateTouchTails('x', false); 3138 3139 that.resize(); 3140 loadImg(activeIndexes, 'stage'); 3141 3142 lockScroll($WINDOW, scrollLeft, scrollTop); 3143 3144 triggerEvent('fullscreenexit'); 3145 } 3146 } 3147 3148 that.cancelFullScreen = function () { 3149 if (o_nativeFullScreen && fullScreenApi.is()) { 3150 fullScreenApi.cancel(document); 3151 } else { 3152 cancelFullScreen(); 3153 } 3154 3155 return this; 3156 }; 3157 3158 that.toggleFullScreen = function () { 3159 return that[(that.fullScreen ? 'cancel' : 'request') + 'FullScreen'](); 3160 }; 3161 3162 addEvent(document, fullScreenApi.event, function () { 3163 if (data && !fullScreenApi.is() && !$videoPlaying) { 3164 cancelFullScreen(); 3165 } 3166 }); 3167 3168 that.resize = function (options) { 3169 if (!data) return this; 3170 3171 var time = arguments[1] || 0, 3172 setFLAG = arguments[2]; 3173 3174 extendMeasures(!that.fullScreen ? optionsToLowerCase(options) : {width: '100%', maxwidth: null, minwidth: null, height: '100%', maxheight: null, minheight: null}, [measures, setFLAG || that.fullScreen || opts]); 3175 3176 var width = measures.width, 3177 height = measures.height, 3178 ratio = measures.ratio,
3179 windowHeight = $WINDOW.height() - (o_nav ? $nav.height() : 0); 3180 3181 if (measureIsValid(width)) { 3182 $wrap 3183 .addClass(wrapOnlyActiveClass) 3184 .css({width: width, minWidth: measures.minwidth || 0, maxWidth: measures.maxwidth || MAX_WIDTH}); 3185 3186 width = measures.W = measures.w = $wrap.width(); 3187 measures.nw = o_nav && numberFromWhatever(opts.navwidth, width) || width; 3188 3189 if (opts.glimpse) { 3190 // Glimpse 3191 measures.w -= Math.round((numberFromWhatever(opts.glimpse, width) || 0) * 2); 3192 } 3193 3194 $stageShaft.css({width: measures.w, marginLeft: (measures.W - measures.w) / 2}); 3195 3196 //////console.log('measures.W', measures.W); 3197 //////console.log('measures.w', measures.w); 3198 3199 height = numberFromWhatever(height, windowHeight); 3200 3201 height = height || (ratio && width / ratio); 3202 3203 if (height) { 3204 width = Math.round(width); 3205 height = measures.h = Math.round(minMaxLimit(height, numberFromWhatever(measures.minheight, windowHeight), numberFromWhatever(measures.maxheight, windowHeight))); 3206 3207 $stage 3208 .stop() 3209 .animate({width: width, height: height}, time, function () { 3210 $wrap.removeClass(wrapOnlyActiveClass); 3211 }); 3212 3213 stageShaftReposition(); 3214 3215 if (o_nav) { 3216 $nav 3217 .stop() 3218 .animate({width: measures.nw}, time); 3219 3220 slideNavShaft({guessIndex: activeIndex, time: time, keep: true}); 3221 if (o_navThumbs && frameAppend.nav) slideThumbBorder(time); 3222 } 3223 3224 measuresSetFLAG = setFLAG || true; 3225 3226 ready(); 3227 } 3228 } 3229 3230 stageLeft = $stage.offset().left; 3231 3232 return this; 3233 }; 3234 3235 that.setOptions = function (options) { 3236 $.extend(opts, options); 3237 reset(); 3238 return this; 3239 }; 3240 3241 that.shuffle = function () { 3242 data && shuffle(data) && reset(); 3243 return this; 3244 }; 3245 3246 function setShadow ($el, edge) { 3247 //////console.time('setShadow'); 3248 if (o_shadows) { 3249 $el.removeClass(shadowsLeftClass + ' ' + shadowsRightClass); 3250 edge && !$videoPlaying && $el.addClass(edge.replace(/^|\s/g, ' ' + shadowsClass + '--')); 3251 } 3252 //////console.timeEnd('setShadow'); 3253 } 3254 3255 that.destroy = function () { 3256 that.cancelFullScreen(); 3257 that.stopAutoplay(); 3258 3259 data = that.data = null; 3260 3261 appendElements(); 3262 3263 activeIndexes = []; 3264 detachFrames(STAGE_FRAME_KEY); 3265 3266 reset.ok = false; 3267 3268 return this; 3269 }; 3270 3271 that.playVideo = function () { 3272 var dataFrame = activeFrame, 3273 video = dataFrame.video, 3274 _activeIndex = activeIndex; 3275 3276 if (typeof video === 'object' && dataFrame.videoReady) { 3277 o_nativeFullScreen && that.fullScreen && that.cancelFullScreen(); 3278 3279 waitFor(function () { 3280 return !fullScreenApi.is() || _activeIndex !== activeIndex; 3281 }, function () { 3282 if (_activeIndex === activeIndex) { 3283 dataFrame.$video = dataFrame.$video || $($.Fotorama.jst.video(video)); 3284 dataFrame.$video.appendTo(dataFrame[STAGE_FRAME_KEY]); 3285 3286 $wrap.addClass(wrapVideoClass); 3287 $videoPlaying = dataFrame.$video; 3288 3289 stageNoMove(); 3290 3291 $arrs.blur(); 3292 $fullscreenIcon.blur(); 3293 3294 triggerEvent('loadvideo'); 3295 } 3296 }); 3297 } 3298 3299 return this; 3300 }; 3301 3302 that.stopVideo = function () { 3303 unloadVideo($videoPlaying, true, true); 3304 return this; 3305 }; 3306 3307 function unloadVideo ($video, unloadActiveFLAG, releaseAutoplayFLAG) { 3308 if (unloadActiveFLAG) { 3309 $wrap.removeClass(wrapVideoClass); 3310 $videoPlaying = false; 3311 3312 stageNoMove(); 3313 } 3314 3315 if ($video && $video !== $videoPlaying) { 3316 $video.remove(); 3317 triggerEvent('unloadvideo'); 3318 } 3319 3320 if (releaseAutoplayFLAG) { 3321 releaseAutoplay(); 3322 changeAutoplay(); 3323 } 3324 } 3325 3326 function toggleControlsClass (FLAG) {
3327 $wrap.toggleClass(wrapNoControlsClass, FLAG); 3328 } 3329 3330 function stageCursor (e) { 3331 if (stageShaftTouchTail.flow) return; 3332 3333 var x = e ? e.pageX : stageCursor.x, 3334 pointerFLAG = x && !disableDirrection(getDirection(x)) && opts.click; 3335 3336 if (stageCursor.p !== pointerFLAG 3337 && $stage.toggleClass(pointerClass, pointerFLAG)) { 3338 stageCursor.p = pointerFLAG; 3339 stageCursor.x = x; 3340 } 3341 } 3342 3343 $stage.on('mousemove', stageCursor); 3344 3345 function clickToShow (showOptions) { 3346 clearTimeout(clickToShow.t); 3347 3348 if (opts.clicktransition && opts.clicktransition !== opts.transition) { 3349 ////console.log('change transition to: ' + opts.clicktransition); 3350 3351 // this timeout is for yield events flow 3352 setTimeout(function () { 3353 // save original transition for later 3354 var _o_transition = opts.transition; 3355 3356 that.setOptions({transition: opts.clicktransition}); 3357 3358 // now safe to pass base transition to o_transition, so that.show will restor it 3359 o_transition = _o_transition; 3360 // this timeout is here to prevent jerking in some browsers 3361 clickToShow.t = setTimeout(function () { 3362 that.show(showOptions); 3363 }, 10); 3364 }, 0); 3365 } else { 3366 that.show(showOptions); 3367 } 3368 } 3369 3370 function onStageTap (e, toggleControlsFLAG) { 3371 //////console.time('onStageTap'); 3372 var target = e.target, 3373 $target = $(target); 3374 3375 if ($target.hasClass(videoPlayClass)) { 3376 that.playVideo(); 3377 } else if (target === fullscreenIcon) { 3378 that.toggleFullScreen(); 3379 } else if ($videoPlaying) { 3380 target === videoClose && unloadVideo($videoPlaying, true, true); 3381 } else { 3382 if (toggleControlsFLAG) { 3383 toggleControlsClass(); 3384 } else if (opts.click) { 3385 3386 clickToShow({index: e.shiftKey || getDirectionSign(getDirection(e._x)), slow: e.altKey, user: true}); 3387 } 3388 } 3389 //////console.timeEnd('onStageTap'); 3390 } 3391 3392 function updateTouchTails (key, value) { 3393 stageShaftTouchTail[key] = navShaftTouchTail[key] = value; 3394 } 3395 3396 stageShaftTouchTail = moveOnTouch($stageShaft, { 3397 onStart: onTouchStart, 3398 onMove: function (e, result) { 3399 setShadow($stage, result.edge); 3400 }, 3401 onTouchEnd: onTouchEnd, 3402 onEnd: function (result) { 3403 //////console.time('stageShaftTouchTail.onEnd'); 3404 setShadow($stage); 3405 3406 //////console.log('result', result); 3407 3408 var toggleControlsFLAG = (MS_POINTER && !hoverFLAG || result.touch) && opts.arrows && opts.arrows !== 'always'; 3409 3410 if (result.moved || (toggleControlsFLAG && result.pos !== result.newPos && !result.control)) { 3411 var index = getIndexByPos(result.newPos, measures.w, opts.margin, repositionIndex); 3412 that.show({ 3413 index: index, 3414 time: o_fade ? o_transitionDuration : result.time, 3415 overPos: result.overPos, 3416 user: true 3417 }); 3418 } else if (!result.aborted && !result.control) { 3419 onStageTap(result.startEvent, toggleControlsFLAG); 3420 } 3421 //////console.timeEnd('stageShaftTouchTail.onEnd'); 3422 }, 3423// getPos: function () { 3424// return -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex); 3425// }, 3426 //_001: true, 3427 timeLow: 1, 3428 timeHigh: 1, 3429 friction: 2, 3430 select: '.' + selectClass + ', .' + selectClass + ' *', 3431 $wrap: $stage 3432 }); 3433 3434 navShaftTouchTail = moveOnTouch($navShaft, { 3435 onStart: onTouchStart, 3436 onMove: function (e, result) { 3437 setShadow($nav, result.edge); 3438 }, 3439 onTouchEnd: onTouchEnd, 3440 onEnd: function (result) { 3441 3442 function onEnd () { 3443 slideNavShaft.l = result.newPos; 3444 releaseAutoplay(); 3445 changeAutoplay(); 3446 thumbsDraw(result.newPos, true); 3447 } 3448 3449 if (!result.moved) { 3450 var target = result.$target.closest('.' + navFrameClass, $navShaft)[0]; 3451 target && onNavFrameClick.call(target, result.startEvent); 3452 } else if (result.pos !== result.newPos) { 3453 pausedAutoplayFLAG = true; 3454 slide($navShaft, { 3455 time: result.time, 3456 pos: result.newPos, 3457 overPos: result.overPos, 3458 onEnd: onEnd 3459 }); 3460 thumbsDraw(result.newPos); 3461 o_shadows && setShadow($nav, findShadowEdge(result.newPos, navShaftTouchTail.min, navShaftTouchTail.max)); 3462 } else { 3463 onEnd(); 3464 } 3465 }, 3466 timeLow: .5, 3467 timeHigh: 2, 3468 friction: 5, 3469 $wrap: $nav 3470 }); 3471 3472 stageWheelTail = wheel($stage, { 3473 shift: true, 3474 onEnd: function (e, direction) { 3475 //////console.log('wheel $stage onEnd', direction); 3476 onTouchStart(); 3477 onTouchEnd(); 3478 that.show({index: direction, slow: e.altKey}) 3479 } 3480 }); 3481 3482 navWheelTail = wheel($nav, { 3483 onEnd: function (e, direction) { 3484 //////console.log('wheel $nav onEnd', direction); 3485 onTouchStart(); 3486 onTouchEnd(); 3487 var newPos = stop($navShaft) + direction * .25; 3488 $navShaft.css(getTranslate(minMaxLimit(newPos, navShaftTouchTail.min, navShaftTouchTail.max))); 3489 o_shadows && setShadow($nav, findShadowEdge(newPos, navShaftTouchTail.min, navShaftTouchTail.max)); 3490 navWheelTail.prevent = {'<': newPos >= navShaftTouchTail.max, '>': newPos <= navShaftTouchTail.min}; 3491 clearTimeout(navWheelTail.t); 3492 navWheelTail.t = setTimeout(function () { 3493 slideNavShaft.l = newPos; 3494 thumbsDraw(newPos, true) 3495 }, TOUCH_TIMEOUT); 3496 thumbsDraw(newPos); 3497 } 3498 }); 3499 3500 $wrap.hover( 3501 function () { 3502 setTimeout(function () { 3503 if (touchedFLAG) return; 3504 toggleControlsClass(!(hoverFLAG = true)); 3505 }, 0); 3506 }, function () { 3507 if (!hoverFLAG) return; 3508 toggleControlsClass(!(hoverFLAG = false)); 3509 } 3510 ); 3511 3512 function onNavFrameClick (e) { 3513 var index = $(this).data().eq; 3514 clickToShow({index: index, slow: e.altKey, user: true, coo: e._x - $nav.offset().left}); 3515 } 3516 3517 function onArrClick (e) { 3518 clickToShow({index: $arrs.index(this) ? '>' : '<', slow: e.altKey, user: true}); 3519 } 3520 3521 smartClick($arrs, function (e) { 3522 stopEvent(e); 3523 onArrClick.call(this, e); 3524 }, { 3525 onStart: function () { 3526 onTouchStart(); 3527 stageShaftTouchTail.control = true; 3528 }, 3529 onTouchEnd: onTouchEnd 3530 }); 3531
3532 function addFocusOnControls (el) { 3533 addFocus(el, function () { 3534 setTimeout(function () { 3535 lockScroll($stage); 3536 }, 0); 3537 toggleControlsClass(false); 3538 }); 3539 } 3540 3541 $arrs.each(function () { 3542 addEnterUp(this, function (e) { 3543 onArrClick.call(this, e); 3544 }); 3545 addFocusOnControls(this); 3546 }); 3547 3548 addEnterUp(fullscreenIcon, that.toggleFullScreen); 3549 addFocusOnControls(fullscreenIcon); 3550 3551 function reset () { 3552 setData(); 3553 setOptions(); 3554 3555 if (!reset.i) { 3556 reset.i = true; 3557 // Only once 3558 var _startindex = opts.startindex; 3559 if (_startindex || opts.hash && location.hash) { 3560 startIndex = getIndexFromHash(_startindex || location.hash.replace(/^#/, ''), data, that.index === 0 || _startindex, _startindex); 3561 } 3562 activeIndex = repositionIndex = dirtyIndex = lastActiveIndex = startIndex = edgeIndex(startIndex) || 0;/*(o_rtl ? size - 1 : 0)*///; 3563 } 3564 3565 if (size) { 3566 if (changeToRtl()) return; 3567 3568 if ($videoPlaying) { 3569 unloadVideo($videoPlaying, true); 3570 } 3571 3572 activeIndexes = []; 3573 detachFrames(STAGE_FRAME_KEY); 3574 3575 reset.ok = true; 3576 3577 that.show({index: activeIndex, time: 0}); 3578 that.resize(); 3579 } else { 3580 that.destroy(); 3581 } 3582 } 3583 3584 function changeToRtl () { 3585 //////console.log('changeToRtl'); 3586 if (!changeToRtl.f === o_rtl) { 3587 changeToRtl.f = o_rtl; 3588 activeIndex = size - 1 - activeIndex; 3589 //////console.log('changeToRtl execute, activeIndex is', activeIndex); 3590 that.reverse(); 3591 3592 return true; 3593 } 3594 } 3595 3596 $.each('load push pop shift unshift reverse sort splice'.split(' '), function (i, method) { 3597 that[method] = function () { 3598 data = data || []; 3599 if (method !== 'load') { 3600 Array.prototype[method].apply(data, arguments); 3601 } else if (arguments[0] && typeof arguments[0] === 'object' && arguments[0].length) { 3602 data = clone(arguments[0]); 3603 } 3604 reset(); 3605 return that; 3606 } 3607 }); 3608 3609 function ready () { 3610 if (!ready.ok) { 3611 ready.ok = true; 3612 triggerEvent('ready'); 3613 } 3614 } 3615 3616 reset(); 3617}; 3618 3619 3620$.fn.fotorama = function (opts) { 3621 return this.each(function () { 3622 var that = this, 3623 $fotorama = $(this), 3624 fotoramaData = $fotorama.data(), 3625 fotorama = fotoramaData.fotorama; 3626 3627 if (!fotorama) { 3628 waitFor(function () { 3629 return !isHidden(that); 3630 }, function () { 3631 fotoramaData.urtext = $fotorama.html(); 3632 new $.Fotorama($fotorama, 3633 /* Priority for options: 3634 * 1. <div data-loop="true"></div> 3635 * 2. $('div').fotorama({loop: false}) 3636 * 3. Defaults */ 3637 $.extend( 3638 {}, 3639 OPTIONS, 3640 window.fotoramaDefaults, 3641 opts, 3642 fotoramaData 3643 ) 3644 ); 3645 }); 3646 } else { 3647 fotorama.setOptions(opts, true); 3648 } 3649 }); 3650}; 3651$.Fotorama.instances = []; 3652 3653function calculateIndexes () { 3654 $.each($.Fotorama.instances, function (index, instance) { 3655 instance.index = index; 3656 }); 3657} 3658 3659function addInstance (instance) { 3660 $.Fotorama.instances.push(instance); 3661 calculateIndexes(); 3662} 3663 3664function hideInstance (instance) { 3665 $.Fotorama.instances.splice(instance.index, 1); 3666 calculateIndexes(); 3667} 3668$.Fotorama.cache = {}; 3669$.Fotorama.measures = {}; 3670$ = $ || {}; 3671$.Fotorama = $.Fotorama || {}; 3672$.Fotorama.jst = $.Fotorama.jst || {}; 3673 3674$.Fotorama.jst.style = function(v) { 3675var __t, __p = '', __e = _.escape; 3676__p += '.fotorama' + 3677((__t = ( v.s )) == null ? '' : __t) + 3678' .fotorama__nav--thumbs .fotorama__nav__frame{\npadding:' + 3679((__t = ( v.m )) == null ? '' : __t) + 3680'px;\nheight:' + 3681((__t = ( v.h )) == null ? '' : __t) + 3682'px}\n.fotorama' + 3683((__t = ( v.s )) == null ? '' : __t) + 3684' .fotorama__thumb-border{\nheight:' + 3685((__t = ( v.h - v.b * (v.q ? 0 : 2) )) == null ? '' : __t) + 3686'px;\nborder-width:' + 3687((__t = ( v.b )) == null ? '' : __t) + 3688'px;\nmargin-top:' + 3689((__t = ( v.m )) == null ? '' : __t) + 3690'px}'; 3691return __p 3692}; 3693 3694$.Fotorama.jst.video = function(v) { 3695var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 3696function print() { __p += __j.call(arguments, '') } 3697__p += '<div class="fotorama__video"><iframe src="'; 3698 print((v.type == 'youtube' ? v.p + 'youtube.com/embed/' + v.id +'?autoplay=1' : v.type == 'vimeo' ? v.p + 'player.vimeo.com/video/' + v.id + '?autoplay=1&badge=0' : v.id) + (v.s && v.type != 'custom' ? '&' + v.s : '')) ; 3699__p += '" frameborder="0" allowfullscreen></iframe></div>\n'; 3700return __p 3701}; 3702$(function () { 3703 $('.' + _fotoramaClass + ':not([data-auto="false"])').fotorama(); 3704}); 3705})(window, document, location, typeof jQuery !== 'undefined' && jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.