vendor: 7,057 bytes, lines 1-245
1/*! 2 * Fotorama 4.6.4 | http://fotorama.io/license/ 3 */ 4fotoramaVersion = '4.6.4'; 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 alt = $child.attr('alt'), 1212 title = $child.attr('title'); 1213 1214 if (alt) { $.extend(imgData, { alt: alt }); } 1215 if (title) { $.extend(imgData, { title: title }); } 1216 1217 $.extend(imgData, { 1218 width: width, 1219 height: height, 1220 thumbratio: getRatio(imgData.thumbratio || (numberFromMeasure(imgData.thumbwidth || ($child && $child.attr('width')) || separateThumbFLAG || width) / numberFromMeasure(imgData.thumbheight || ($child && $child.attr('height')) || separateThumbFLAG || height))) 1221 }); 1222 } 1223 1224 $el.children().each(function () { 1225 var $this = $(this), 1226 dataFrame = optionsToLowerCase($.extend($this.data(), {id: $this.attr('id')})); 1227 if ($this.is('a, img')) { 1228 getDataFromImg($this, dataFrame, true); 1229 } else if (!$this.is(':empty')) { 1230 getDimensions($this, null, $.extend(dataFrame, { 1231 html: this, 1232 _html: $this.html() // Because of IE 1233 })); 1234 } else return; 1235 1236 data.push(dataFrame); 1237 }); 1238 1239 return data; 1240} 1241 1242function isHidden (el) { 1243 return el.offsetWidth === 0 && el.offsetHeight === 0; 1244} 1245 1246function isDetached (el) { 1247 return !$.contains(document.documentElement, el); 1248} 1249 1250function waitFor (test, fn, timeout, i) { 1251 if (!waitFor.i) { 1252 waitFor.i = 1; 1253 waitFor.ii = [true]; 1254 } 1255 1256 i = i || waitFor.i; 1257 1258 if (typeof waitFor.ii[i] === 'undefined') { 1259 waitFor.ii[i] = true; 1260 } 1261 1262 if (test()) { 1263 fn(); 1264 } else { 1265 waitFor.ii[i] && setTimeout(function () { 1266 waitFor.ii[i] && waitFor(test, fn, timeout, i); 1267 }, timeout || 100); 1268 } 1269 1270 return waitFor.i++; 1271} 1272 1273waitFor.stop = function (i) { 1274 waitFor.ii[i] = false; 1275}; 1276 1277function setHash (hash) { 1278 //////console.time('setHash ' + hash); 1279 location.replace(location.protocol 1280 + '//' 1281 + location.host 1282 + location.pathname.replace(/^\/?/, '/') 1283 + location.search 1284 + '#' + hash); 1285 //////console.timeEnd('setHash ' + hash); 1286} 1287 1288function fit ($el, measuresToFit, method, position) { 1289 var elData = $el.data(), 1290 measures = elData.measures; 1291 1292 if (measures && (!elData.l || 1293 elData.l.W !== measures.width || 1294 elData.l.H !== measures.height || 1295 elData.l.r !== measures.ratio || 1296 elData.l.w !== measuresToFit.w || 1297 elData.l.h !== measuresToFit.h || 1298 elData.l.m !== method || 1299 elData.l.p !== position)) { 1300 1301 //console.log('fit'); 1302 1303 var width = measures.width, 1304 height = measures.height, 1305 ratio = measuresToFit.w / measuresToFit.h, 1306 biggerRatioFLAG = measures.ratio >= ratio, 1307 fitFLAG = method === 'scaledown', 1308 containFLAG = method === 'contain', 1309 coverFLAG = method === 'cover', 1310 pos = parsePosition(position); 1311 1312 if (biggerRatioFLAG && (fitFLAG || containFLAG) || !biggerRatioFLAG && coverFLAG) { 1313 width = minMaxLimit(measuresToFit.w, 0, fitFLAG ? width : Infinity); 1314 height = width / measures.ratio; 1315 } else if (biggerRatioFLAG && coverFLAG || !biggerRatioFLAG && (fitFLAG || containFLAG)) { 1316 height = minMaxLimit(measuresToFit.h, 0, fitFLAG ? height : Infinity); 1317 width = height * measures.ratio; 1318 } 1319 1320 $el.css({ 1321 width: width, 1322 height: height, 1323 left: numberFromWhatever(pos.x, measuresToFit.w - width), 1324 top: numberFromWhatever(pos.y, measuresToFit.h- height) 1325 }); 1326 1327 elData.l = { 1328 W: measures.width, 1329 H: measures.height, 1330 r: measures.ratio, 1331 w: measuresToFit.w, 1332 h: measuresToFit.h, 1333 m: method, 1334 p: position 1335 }; 1336 } 1337 1338 return true; 1339} 1340 1341function setStyle ($el, style) { 1342 var el = $el[0]; 1343 if (el.styleSheet) { 1344 el.styleSheet.cssText = style; 1345 } else { 1346 $el.html(style); 1347 } 1348} 1349 1350function findShadowEdge (pos, min, max) { 1351 return min === max ? false : pos <= min ? 'left' : pos >= max ? 'right' : 'left right';
1352} 1353 1354function getIndexFromHash (hash, data, ok, startindex) { 1355 if (!ok) return false; 1356 if (!isNaN(hash)) return hash - (startindex ? 0 : 1); 1357 1358 var index; 1359 1360 for (var _i = 0, _l = data.length; _i < _l; _i++) { 1361 var dataFrame = data[_i]; 1362 1363 if (dataFrame.id === hash) { 1364 index = _i; 1365 break; 1366 } 1367 } 1368 1369 return index; 1370} 1371 1372function smartClick ($el, fn, _options) { 1373 _options = _options || {}; 1374 1375 $el.each(function () { 1376 var $this = $(this), 1377 thisData = $this.data(), 1378 startEvent; 1379 1380 if (thisData.clickOn) return; 1381 1382 thisData.clickOn = true; 1383 1384 $.extend(touch($this, { 1385 onStart: function (e) { 1386 startEvent = e; 1387 (_options.onStart || noop).call(this, e); 1388 }, 1389 onMove: _options.onMove || noop, 1390 onTouchEnd: _options.onTouchEnd || noop, 1391 onEnd: function (result) { 1392 ////console.log('smartClick → result.moved', result.moved); 1393 if (result.moved) return; 1394 fn.call(this, startEvent); 1395 } 1396 }), {noMove: true}); 1397 }); 1398} 1399 1400function div (classes, child) { 1401 return '<div class="' + classes + '">' + (child || '') + '</div>'; 1402} 1403 1404// Fisher–Yates Shuffle 1405// http://bost.ocks.org/mike/shuffle/ 1406function shuffle (array) { 1407 // While there remain elements to shuffle 1408 var l = array.length; 1409 while (l) { 1410 // Pick a remaining element 1411 var i = Math.floor(Math.random() * l--); 1412 1413 // And swap it with the current element 1414 var t = array[l]; 1415 array[l] = array[i]; 1416 array[i] = t; 1417 } 1418 1419 return array; 1420} 1421 1422function clone (array) { 1423 return Object.prototype.toString.call(array) == '[object Array]' 1424 && $.map(array, function (frame) { 1425 return $.extend({}, frame); 1426 }); 1427} 1428 1429function lockScroll ($el, left, top) { 1430 $el 1431 .scrollLeft(left || 0) 1432 .scrollTop(top || 0); 1433} 1434 1435function optionsToLowerCase (options) { 1436 if (options) { 1437 var opts = {}; 1438 $.each(options, function (key, value) { 1439 opts[key.toLowerCase()] = value; 1440 }); 1441 1442 return opts; 1443 } 1444} 1445 1446function getRatio (_ratio) { 1447 if (!_ratio) return; 1448 var ratio = +_ratio; 1449 if (!isNaN(ratio)) { 1450 return ratio; 1451 } else { 1452 ratio = _ratio.split('/'); 1453 return +ratio[0] / +ratio[1] || undefined; 1454 } 1455} 1456 1457function addEvent (el, e, fn, bool) { 1458 if (!e) return; 1459 el.addEventListener ? el.addEventListener(e, fn, !!bool) : el.attachEvent('on'+e, fn); 1460} 1461 1462function elIsDisabled (el) { 1463 return !!el.getAttribute('disabled'); 1464} 1465 1466function disableAttr (FLAG) { 1467 return {tabindex: FLAG * -1 + '', disabled: FLAG}; 1468} 1469 1470function addEnterUp (el, fn) { 1471 addEvent(el, 'keyup', function (e) { 1472 elIsDisabled(el) || e.keyCode == 13 && fn.call(el, e); 1473 }); 1474} 1475 1476function addFocus (el, fn) { 1477 addEvent(el, 'focus', el.onfocusin = function (e) { 1478 fn.call(el, e); 1479 }, true); 1480} 1481 1482function stopEvent (e, stopPropagation) { 1483 e.preventDefault ? e.preventDefault() : (e.returnValue = false); 1484 stopPropagation && e.stopPropagation && e.stopPropagation(); 1485} 1486 1487function getDirectionSign (forward) { 1488 return forward ? '>' : '<'; 1489} 1490 1491function parsePosition (rule) { 1492 rule = (rule + '').split(/\s+/); 1493 return { 1494 x: measureIsValid(rule[0]) || FIFTYFIFTY, 1495 y: measureIsValid(rule[1]) || FIFTYFIFTY 1496 } 1497} 1498function slide ($el, options) { 1499 var elData = $el.data(), 1500 elPos = Math.round(options.pos), 1501 onEndFn = function () { 1502 elData.sliding = false; 1503 (options.onEnd || noop)(); 1504 }; 1505 1506 if (typeof options.overPos !== 'undefined' && options.overPos !== options.pos) { 1507 elPos = options.overPos; 1508 onEndFn = function () { 1509 slide($el, $.extend({}, options, {overPos: options.pos, time: Math.max(TRANSITION_DURATION, options.time / 2)})) 1510 }; 1511 } 1512 1513 ////////console.time('var translate = $.extend'); 1514 var translate = $.extend(getTranslate(elPos/*, options._001*/), options.width && {width: options.width}); 1515 ////////console.timeEnd('var translate = $.extend'); 1516 1517 elData.sliding = true; 1518 1519 if (CSS3) { 1520 $el.css($.extend(getDuration(options.time), translate)); 1521 if (options.time > 10) { 1522 ////////console.time('afterTransition'); 1523 afterTransition($el, 'transform', onEndFn, options.time);
1524 ////////console.timeEnd('afterTransition'); 1525 } else { 1526 onEndFn(); 1527 } 1528 } else { 1529 $el.stop().animate(translate, options.time, BEZIER, onEndFn); 1530 } 1531} 1532 1533function fade ($el1, $el2, $frames, options, fadeStack, chain) { 1534 var chainedFLAG = typeof chain !== 'undefined'; 1535 if (!chainedFLAG) { 1536 fadeStack.push(arguments); 1537 Array.prototype.push.call(arguments, fadeStack.length); 1538 if (fadeStack.length > 1) return; 1539 } 1540 1541 $el1 = $el1 || $($el1); 1542 $el2 = $el2 || $($el2); 1543 1544 var _$el1 = $el1[0], 1545 _$el2 = $el2[0], 1546 crossfadeFLAG = options.method === 'crossfade', 1547 onEndFn = function () { 1548 if (!onEndFn.done) { 1549 onEndFn.done = true; 1550 var args = (chainedFLAG || fadeStack.shift()) && fadeStack.shift(); 1551 args && fade.apply(this, args); 1552 (options.onEnd || noop)(!!args); 1553 } 1554 }, 1555 time = options.time / (chain || 1); 1556 1557 $frames.removeClass(fadeRearClass + ' ' + fadeFrontClass); 1558 1559 $el1 1560 .stop() 1561 .addClass(fadeRearClass); 1562 $el2 1563 .stop() 1564 .addClass(fadeFrontClass); 1565 1566 crossfadeFLAG && _$el2 && $el1.fadeTo(0, 0); 1567 1568 $el1.fadeTo(crossfadeFLAG ? time : 0, 1, crossfadeFLAG && onEndFn); 1569 $el2.fadeTo(time, 0, onEndFn); 1570 1571 (_$el1 && crossfadeFLAG) || _$el2 || onEndFn(); 1572} 1573var lastEvent, 1574 moveEventType, 1575 preventEvent, 1576 preventEventTimeout; 1577 1578function extendEvent (e) { 1579 var touch = (e.touches || [])[0] || e; 1580 e._x = touch.pageX; 1581 e._y = touch.clientY; 1582 e._now = $.now(); 1583} 1584 1585function touch ($el, options) { 1586 var el = $el[0], 1587 tail = {}, 1588 touchEnabledFLAG, 1589 startEvent, 1590 $target, 1591 controlTouch, 1592 touchFLAG, 1593 targetIsSelectFLAG, 1594 targetIsLinkFlag, 1595 tolerance, 1596 moved; 1597 1598 function onStart (e) { 1599 $target = $(e.target); 1600 tail.checked = targetIsSelectFLAG = targetIsLinkFlag = moved = false; 1601 1602 if (touchEnabledFLAG 1603 || tail.flow 1604 || (e.touches && e.touches.length > 1) 1605 || e.which > 1 1606 || (lastEvent && lastEvent.type !== e.type && preventEvent) 1607 || (targetIsSelectFLAG = options.select && $target.is(options.select, el))) return targetIsSelectFLAG; 1608 1609 touchFLAG = e.type === 'touchstart'; 1610 targetIsLinkFlag = $target.is('a, a *', el); 1611 controlTouch = tail.control; 1612 1613 tolerance = (tail.noMove || tail.noSwipe || controlTouch) ? 16 : !tail.snap ? 4 : 0; 1614 1615 extendEvent(e); 1616 1617 startEvent = lastEvent = e; 1618 moveEventType = e.type.replace(/down|start/, 'move').replace(/Down/, 'Move'); 1619 1620 (options.onStart || noop).call(el, e, {control: controlTouch, $target: $target}); 1621 1622 touchEnabledFLAG = tail.flow = true; 1623 1624 if (!touchFLAG || tail.go) stopEvent(e); 1625 } 1626 1627 function onMove (e) { 1628 if ((e.touches && e.touches.length > 1) 1629 || (MS_POINTER && !e.isPrimary) 1630 || moveEventType !== e.type 1631 || !touchEnabledFLAG) { 1632 touchEnabledFLAG && onEnd(); 1633 (options.onTouchEnd || noop)(); 1634 return; 1635 } 1636 1637 extendEvent(e); 1638 1639 var xDiff = Math.abs(e._x - startEvent._x), // opt _x → _pageX 1640 yDiff = Math.abs(e._y - startEvent._y), 1641 xyDiff = xDiff - yDiff, 1642 xWin = (tail.go || tail.x || xyDiff >= 0) && !tail.noSwipe, 1643 yWin = xyDiff < 0; 1644 1645 if (touchFLAG && !tail.checked) { 1646 if (touchEnabledFLAG = xWin) { 1647 stopEvent(e); 1648 } 1649 } else { 1650 ////console.log('onMove e.preventDefault'); 1651 stopEvent(e); 1652 (options.onMove || noop).call(el, e, {touch: touchFLAG}); 1653 } 1654 1655 if (!moved && Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)) > tolerance) { 1656 moved = true; 1657 } 1658 1659 tail.checked = tail.checked || xWin || yWin; 1660 } 1661 1662 function onEnd (e) { 1663 //////console.time('touch.js onEnd'); 1664 1665 (options.onTouchEnd || noop)(); 1666 1667 var _touchEnabledFLAG = touchEnabledFLAG; 1668 tail.control = touchEnabledFLAG = false; 1669 1670 if (_touchEnabledFLAG) { 1671 tail.flow = false; 1672 } 1673 1674 if (!_touchEnabledFLAG || (targetIsLinkFlag && !tail.checked)) return; 1675 1676 e && stopEvent(e); 1677 1678 preventEvent = true; 1679 clearTimeout(preventEventTimeout); 1680 preventEventTimeout = setTimeout(function () { 1681 preventEvent = false;
1682 }, 1000); 1683 1684 (options.onEnd || noop).call(el, {moved: moved, $target: $target, control: controlTouch, touch: touchFLAG, startEvent: startEvent, aborted: !e || e.type === 'MSPointerCancel'}); 1685 //////console.timeEnd('touch.js onEnd'); 1686 } 1687 1688 function onOtherStart () { 1689 if (tail.flow) return; 1690 setTimeout(function () { 1691 tail.flow = true; 1692 }, 10); 1693 } 1694 1695 function onOtherEnd () { 1696 if (!tail.flow) return; 1697 setTimeout(function () { 1698 tail.flow = false; 1699 }, TOUCH_TIMEOUT); 1700 } 1701 1702 if (MS_POINTER) { 1703 addEvent(el, 'MSPointerDown', onStart); 1704 addEvent(document, 'MSPointerMove', onMove); 1705 addEvent(document,'MSPointerCancel', onEnd); 1706 addEvent(document, 'MSPointerUp', onEnd); 1707 } else { 1708 addEvent(el, 'touchstart', onStart); 1709 addEvent(el, 'touchmove', onMove); 1710 addEvent(el, 'touchend', onEnd); 1711 1712 addEvent(document, 'touchstart', onOtherStart); 1713 addEvent(document, 'touchend', onOtherEnd); 1714 addEvent(document, 'touchcancel', onOtherEnd); 1715 1716 $WINDOW.on('scroll', onOtherEnd); 1717 1718 $el.on('mousedown', onStart); 1719 $DOCUMENT 1720 .on('mousemove', onMove) 1721 .on('mouseup', onEnd); 1722 } 1723 1724 $el.on('click', 'a', function (e) { 1725 tail.checked && stopEvent(e); 1726 }); 1727 1728 return tail; 1729} 1730 1731function moveOnTouch ($el, options) { 1732 var el = $el[0], 1733 elData = $el.data(), 1734 tail = {}, 1735 startCoo, 1736 coo, 1737 startElPos, 1738 moveElPos, 1739 edge, 1740 moveTrack, 1741 startTime, 1742 endTime, 1743 min, 1744 max, 1745 snap, 1746 slowFLAG, 1747 controlFLAG, 1748 moved, 1749 tracked; 1750 1751 function startTracking (e, noStop) { 1752 tracked = true; 1753 startCoo = coo = e._x; 1754 startTime = e._now; 1755 1756 moveTrack = [ 1757 [startTime, startCoo] 1758 ]; 1759 1760 startElPos = moveElPos = tail.noMove || noStop ? 0 : stop($el, (options.getPos || noop)()/*, options._001*/); 1761 1762 (options.onStart || noop).call(el, e); 1763 } 1764 1765 function onStart (e, result) { 1766 min = tail.min; 1767 max = tail.max; 1768 snap = tail.snap; 1769 1770 slowFLAG = e.altKey; 1771 tracked = moved = false; 1772 1773 controlFLAG = result.control; 1774 1775 if (!controlFLAG && !elData.sliding) { 1776 startTracking(e); 1777 } 1778 } 1779 1780 function onMove (e, result) { 1781 if (!tail.noSwipe) { 1782 if (!tracked) { 1783 startTracking(e); 1784 } 1785 1786 coo = e._x; 1787 1788 moveTrack.push([e._now, coo]); 1789 1790 moveElPos = startElPos - (startCoo - coo); 1791 1792 edge = findShadowEdge(moveElPos, min, max); 1793 1794 if (moveElPos <= min) { 1795 moveElPos = edgeResistance(moveElPos, min); 1796 } else if (moveElPos >= max) { 1797 moveElPos = edgeResistance(moveElPos, max); 1798 } 1799 1800 if (!tail.noMove) { 1801 $el.css(getTranslate(moveElPos/*, options._001*/)); 1802 if (!moved) { 1803 moved = true; 1804 // only for mouse 1805 result.touch || MS_POINTER || $el.addClass(grabbingClass); 1806 } 1807 1808 (options.onMove || noop).call(el, e, {pos: moveElPos, edge: edge}); 1809 } 1810 } 1811 } 1812 1813 function onEnd (result) { 1814 //////console.time('moveontouch.js onEnd'); 1815 if (tail.noSwipe && result.moved) return; 1816 1817 if (!tracked) { 1818 startTracking(result.startEvent, true); 1819 } 1820 1821 ////console.log('onEnd'); 1822 1823 result.touch || MS_POINTER || $el.removeClass(grabbingClass); 1824 1825 endTime = $.now(); 1826 1827 var _backTimeIdeal = endTime - TOUCH_TIMEOUT, 1828 _backTime, 1829 _timeDiff, 1830 _timeDiffLast, 1831 backTime = null, 1832 backCoo, 1833 virtualPos, 1834 limitPos, 1835 newPos, 1836 overPos, 1837 time = TRANSITION_DURATION, 1838 speed, 1839 friction = options.friction; 1840 1841 for (var _i = moveTrack.length - 1; _i >= 0; _i--) { 1842 _backTime = moveTrack[_i][0]; 1843 _timeDiff = Math.abs(_backTime - _backTimeIdeal); 1844 if (backTime === null || _timeDiff < _timeDiffLast) { 1845 backTime = _backTime; 1846 backCoo = moveTrack[_i][1]; 1847 } else if (backTime === _backTimeIdeal || _timeDiff > _timeDiffLast) { 1848 break; 1849 } 1850 _timeDiffLast = _timeDiff; 1851 } 1852 1853 newPos = minMaxLimit(moveElPos, min, max); 1854 1855 var cooDiff = backCoo - coo, 1856 forwardFLAG = cooDiff >= 0, 1857 timeDiff = endTime - backTime, 1858 longTouchFLAG = timeDiff > TOUCH_TIMEOUT, 1859 swipeFLAG = !longTouchFLAG && moveElPos !== startElPos && newPos === moveElPos; 1860 1861 if (snap) { 1862 newPos = minMaxLimit(Math[swipeFLAG ? (forwardFLAG ? 'floor' : 'ceil') : 'round'](moveElPos / snap) * snap, min, max); 1863 min = max = newPos; 1864 } 1865 1866 if (swipeFLAG && (snap || newPos === moveElPos)) { 1867 speed = -(cooDiff / timeDiff); 1868 time *= minMaxLimit(Math.abs(speed), options.timeLow, options.timeHigh); 1869 virtualPos = Math.round(moveElPos + speed * time / friction); 1870 1871 if (!snap) { 1872 newPos = virtualPos; 1873 } 1874 1875 if (!forwardFLAG && virtualPos > max || forwardFLAG && virtualPos < min) { 1876 limitPos = forwardFLAG ? min : max; 1877 overPos = virtualPos - limitPos; 1878 if (!snap) { 1879 newPos = limitPos; 1880 } 1881 overPos = minMaxLimit(newPos + overPos * .03, limitPos - 50, limitPos + 50); 1882 time = Math.abs((moveElPos - overPos) / (speed / friction)); 1883 } 1884 } 1885 1886 time *= slowFLAG ? 10 : 1; 1887 1888 (options.onEnd || noop).call(el, $.extend(result, {moved: result.moved || longTouchFLAG && snap, pos: moveElPos, newPos: newPos, overPos: overPos, time: time})); 1889 } 1890 1891 tail = $.extend(touch(options.$wrap, $.extend({}, options, { 1892 onStart: onStart, 1893 onMove: onMove, 1894 onEnd: onEnd 1895 })), tail); 1896 1897 return tail; 1898} 1899function wheel ($el, options) { 1900 var el = $el[0], 1901 lockFLAG, 1902 lastDirection, 1903 lastNow, 1904 tail = { 1905 prevent: {} 1906 }; 1907 1908 addEvent(el, WHEEL, function (e) { 1909 var yDelta = e.wheelDeltaY || -1 * e.deltaY || 0, 1910 xDelta = e.wheelDeltaX || -1 * e.deltaX || 0, 1911 xWin = Math.abs(xDelta) && !Math.abs(yDelta), 1912 direction = getDirectionSign(xDelta < 0), 1913 sameDirection = lastDirection === direction, 1914 now = $.now(),
1915 tooFast = now - lastNow < TOUCH_TIMEOUT; 1916 1917 lastDirection = direction; 1918 lastNow = now; 1919 1920 if (!xWin || !tail.ok || tail.prevent[direction] && !lockFLAG) { 1921 return; 1922 } else { 1923 stopEvent(e, true); 1924 if (lockFLAG && sameDirection && tooFast) { 1925 return; 1926 } 1927 } 1928 1929 if (options.shift) { 1930 lockFLAG = true; 1931 clearTimeout(tail.t); 1932 tail.t = setTimeout(function () { 1933 lockFLAG = false; 1934 }, SCROLL_LOCK_TIMEOUT); 1935 } 1936 1937 (options.onEnd || noop)(e, options.shift ? direction : xDelta); 1938 1939 }); 1940 1941 return tail; 1942} 1943jQuery.Fotorama = function ($fotorama, opts) { 1944 $HTML = $('html'); 1945 $BODY = $('body'); 1946 1947 var that = this, 1948 stamp = $.now(), 1949 stampClass = _fotoramaClass + stamp, 1950 fotorama = $fotorama[0], 1951 data, 1952 dataFrameCount = 1, 1953 fotoramaData = $fotorama.data(), 1954 size, 1955 1956 $style = $('<style></style>'), 1957 1958 $anchor = $(div(hiddenClass)), 1959 $wrap = $(div(wrapClass)), 1960 $stage = $(div(stageClass)).appendTo($wrap), 1961 stage = $stage[0], 1962 1963 $stageShaft = $(div(stageShaftClass)).appendTo($stage), 1964 $stageFrame = $(), 1965 $arrPrev = $(div(arrClass + ' ' + arrPrevClass + buttonAttributes)), 1966 $arrNext = $(div(arrClass + ' ' + arrNextClass + buttonAttributes)), 1967 $arrs = $arrPrev.add($arrNext).appendTo($stage), 1968 $navWrap = $(div(navWrapClass)), 1969 $nav = $(div(navClass)).appendTo($navWrap), 1970 $navShaft = $(div(navShaftClass)).appendTo($nav), 1971 $navFrame, 1972 $navDotFrame = $(), 1973 $navThumbFrame = $(), 1974 1975 stageShaftData = $stageShaft.data(), 1976 navShaftData = $navShaft.data(), 1977 1978 $thumbBorder = $(div(thumbBorderClass)).appendTo($navShaft), 1979 1980 $fullscreenIcon = $(div(fullscreenIconClass + buttonAttributes)), 1981 fullscreenIcon = $fullscreenIcon[0], 1982 $videoPlay = $(div(videoPlayClass)), 1983 $videoClose = $(div(videoCloseClass)).appendTo($stage), 1984 videoClose = $videoClose[0], 1985 1986 spinner, 1987 $spinner = $(div(spinnerClass)), 1988 1989 $videoPlaying, 1990 1991 activeIndex = false, 1992 activeFrame, 1993 activeIndexes, 1994 repositionIndex, 1995 dirtyIndex, 1996 lastActiveIndex, 1997 prevIndex, 1998 nextIndex, 1999 nextAutoplayIndex, 2000 startIndex, 2001 2002 o_loop, 2003 o_nav, 2004 o_navThumbs, 2005 o_navTop, 2006 o_allowFullScreen, 2007 o_nativeFullScreen, 2008 o_fade, 2009 o_thumbSide, 2010 o_thumbSide2, 2011 o_transitionDuration, 2012 o_transition, 2013 o_shadows, 2014 o_rtl, 2015 o_keyboard, 2016 lastOptions = {}, 2017 2018 measures = {}, 2019 measuresSetFLAG, 2020 2021 stageShaftTouchTail = {}, 2022 stageWheelTail = {}, 2023 navShaftTouchTail = {}, 2024 navWheelTail = {}, 2025 2026 scrollTop, 2027 scrollLeft, 2028 2029 showedFLAG, 2030 pausedAutoplayFLAG, 2031 stoppedAutoplayFLAG, 2032 2033 toDeactivate = {}, 2034 toDetach = {}, 2035 2036 measuresStash, 2037 2038 touchedFLAG, 2039 2040 hoverFLAG, 2041 2042 navFrameKey, 2043 stageLeft = 0, 2044 2045 fadeStack = []; 2046 2047 $wrap[STAGE_FRAME_KEY] = $(div(stageFrameClass)); 2048 $wrap[NAV_THUMB_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameThumbClass + buttonAttributes, div(thumbClass))); 2049 $wrap[NAV_DOT_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameDotClass + buttonAttributes, div(dotClass))); 2050 2051 toDeactivate[STAGE_FRAME_KEY] = []; 2052 toDeactivate[NAV_THUMB_FRAME_KEY] = []; 2053 toDeactivate[NAV_DOT_FRAME_KEY] = []; 2054 toDetach[STAGE_FRAME_KEY] = {}; 2055 2056 $wrap 2057 .addClass(CSS3 ? wrapCss3Class : wrapCss2Class)
2058 .toggleClass(wrapNoControlsClass, !opts.controlsonstart); 2059 2060 fotoramaData.fotorama = this; 2061 2062 function checkForVideo () { 2063 $.each(data, function (i, dataFrame) { 2064 if (!dataFrame.i) { 2065 dataFrame.i = dataFrameCount++; 2066 var video = findVideoId(dataFrame.video, true); 2067 if (video) { 2068 var thumbs = {}; 2069 dataFrame.video = video; 2070 if (!dataFrame.img && !dataFrame.thumb) { 2071 thumbs = getVideoThumbs(dataFrame, data, that); 2072 } else { 2073 dataFrame.thumbsReady = true; 2074 } 2075 updateData(data, {img: thumbs.img, thumb: thumbs.thumb}, dataFrame.i, that); 2076 } 2077 } 2078 }); 2079 } 2080 2081 function allowKey (key) { 2082 return o_keyboard[key] || that.fullScreen; 2083 } 2084 2085 function bindGlobalEvents (FLAG) { 2086 var keydownCommon = 'keydown.' + _fotoramaClass, 2087 localStamp = _fotoramaClass + stamp, 2088 keydownLocal = 'keydown.' + localStamp, 2089 resizeLocal = 'resize.' + localStamp + ' ' + 'orientationchange.' + localStamp; 2090 2091 if (FLAG) { 2092 $DOCUMENT 2093 .on(keydownLocal, function (e) { 2094 var catched, 2095 index; 2096 2097 if ($videoPlaying && e.keyCode === 27) { 2098 catched = true; 2099 unloadVideo($videoPlaying, true, true); 2100 } else if (that.fullScreen || (opts.keyboard && !that.index)) { 2101 if (e.keyCode === 27) { 2102 catched = true; 2103 that.cancelFullScreen(); 2104 } else if ((e.shiftKey && e.keyCode === 32 && allowKey('space')) || (e.keyCode === 37 && allowKey('left')) || (e.keyCode === 38 && allowKey('up'))) { 2105 index = '<'; 2106 } else if ((e.keyCode === 32 && allowKey('space')) || (e.keyCode === 39 && allowKey('right')) || (e.keyCode === 40 && allowKey('down'))) { 2107 index = '>'; 2108 } else if (e.keyCode === 36 && allowKey('home')) { 2109 index = '<<'; 2110 } else if (e.keyCode === 35 && allowKey('end')) { 2111 index = '>>'; 2112 } 2113 } 2114 2115 (catched || index) && stopEvent(e); 2116 index && that.show({index: index, slow: e.altKey, user: true}); 2117 }); 2118 2119 if (!that.index) { 2120 $DOCUMENT 2121 .off(keydownCommon) 2122 .on(keydownCommon, 'textarea, input, select', function (e) { 2123 !$BODY.hasClass(_fullscreenClass) && e.stopPropagation(); 2124 }); 2125 } 2126 2127 $WINDOW.on(resizeLocal, that.resize); 2128 } else { 2129 $DOCUMENT.off(keydownLocal); 2130 $WINDOW.off(resizeLocal); 2131 } 2132 } 2133 2134 function appendElements (FLAG) { 2135 if (FLAG === appendElements.f) return; 2136 2137 if (FLAG) { 2138 $fotorama 2139 .html('') 2140 .addClass(_fotoramaClass + ' ' + stampClass) 2141 .append($wrap) 2142 .before($style) 2143 .before($anchor); 2144 2145 addInstance(that); 2146 } else { 2147 $wrap.detach(); 2148 $style.detach(); 2149 $anchor.detach(); 2150 $fotorama 2151 .html(fotoramaData.urtext) 2152 .removeClass(stampClass); 2153 2154 hideInstance(that); 2155 } 2156 2157 bindGlobalEvents(FLAG); 2158 appendElements.f = FLAG; 2159 } 2160 2161 function setData () { 2162 data = that.data = data || clone(opts.data) || getDataFromHtml($fotorama); 2163 size = that.size = data.length; 2164 2165 !ready.ok && opts.shuffle && shuffle(data); 2166 2167 checkForVideo(); 2168 2169 activeIndex = limitIndex(activeIndex); 2170 2171 size && appendElements(true); 2172 } 2173 2174 function stageNoMove () { 2175 var _noMove = (size < 2 && !opts.enableifsingleframe) || $videoPlaying; 2176 stageShaftTouchTail.noMove = _noMove || o_fade; 2177 stageShaftTouchTail.noSwipe = _noMove || !opts.swipe; 2178 2179 !o_transition && $stageShaft.toggleClass(grabClass, !opts.click && !stageShaftTouchTail.noMove && !stageShaftTouchTail.noSwipe); 2180 MS_POINTER && $wrap.toggleClass(wrapPanYClass, !stageShaftTouchTail.noSwipe); 2181 } 2182 2183 function setAutoplayInterval (interval) { 2184 if (interval === true) interval = ''; 2185 opts.autoplay = Math.max(+interval || AUTOPLAY_INTERVAL, o_transitionDuration * 1.5); 2186 } 2187 2188 /** 2189 * Options on the fly 2190 * */ 2191 function setOptions () { 2192 that.options = opts = optionsToLowerCase(opts); 2193 2194 o_fade = (opts.transition === 'crossfade' || opts.transition === 'dissolve'); 2195 2196 o_loop = opts.loop && (size > 2 || (o_fade && (!o_transition || o_transition !== 'slide'))); 2197 2198 o_transitionDuration = +opts.transitionduration || TRANSITION_DURATION; 2199 2200 o_rtl = opts.direction === 'rtl'; 2201 2202 o_keyboard = $.extend({}, opts.keyboard && KEYBOARD_OPTIONS, opts.keyboard); 2203 2204 var classes = {add: [], remove: []}; 2205 2206 function addOrRemoveClass (FLAG, value) { 2207 classes[FLAG ? 'add' : 'remove'].push(value); 2208 } 2209 2210 if (size > 1 || opts.enableifsingleframe) { 2211 o_nav = opts.nav; 2212 o_navTop = opts.navposition === 'top'; 2213 classes.remove.push(selectClass); 2214 2215 $arrs.toggle(!!opts.arrows); 2216 } else { 2217 o_nav = false;
2218 $arrs.hide(); 2219 } 2220 2221 spinnerStop(); 2222 spinner = new Spinner($.extend(spinnerDefaults, opts.spinner, spinnerOverride, {direction: o_rtl ? -1 : 1})); 2223 2224 arrsUpdate(); 2225 stageWheelUpdate(); 2226 2227 if (opts.autoplay) setAutoplayInterval(opts.autoplay); 2228 2229 o_thumbSide = numberFromMeasure(opts.thumbwidth) || THUMB_SIZE; 2230 o_thumbSide2 = numberFromMeasure(opts.thumbheight) || THUMB_SIZE; 2231 2232 stageWheelTail.ok = navWheelTail.ok = opts.trackpad && !SLOW; 2233 2234 stageNoMove(); 2235 2236 extendMeasures(opts, [measures]); 2237 2238 o_navThumbs = o_nav === 'thumbs'; 2239 2240 if (o_navThumbs) { 2241 frameDraw(size, 'navThumb'); 2242 2243 $navFrame = $navThumbFrame; 2244 navFrameKey = NAV_THUMB_FRAME_KEY; 2245 2246 setStyle($style, $.Fotorama.jst.style({w: o_thumbSide, h: o_thumbSide2, b: opts.thumbborderwidth, m: opts.thumbmargin, s: stamp, q: !COMPAT})); 2247 2248 $nav 2249 .addClass(navThumbsClass) 2250 .removeClass(navDotsClass); 2251 } else if (o_nav === 'dots') { 2252 frameDraw(size, 'navDot'); 2253 2254 $navFrame = $navDotFrame; 2255 navFrameKey = NAV_DOT_FRAME_KEY; 2256 2257 $nav 2258 .addClass(navDotsClass) 2259 .removeClass(navThumbsClass); 2260 } else { 2261 o_nav = false; 2262 $nav.removeClass(navThumbsClass + ' ' + navDotsClass); 2263 } 2264 2265 if (o_nav) { 2266 if (o_navTop) { 2267 $navWrap.insertBefore($stage); 2268 } else { 2269 $navWrap.insertAfter($stage); 2270 } 2271 frameAppend.nav = false; 2272 frameAppend($navFrame, $navShaft, 'nav'); 2273 } 2274 2275 o_allowFullScreen = opts.allowfullscreen; 2276 2277 if (o_allowFullScreen) { 2278 $fullscreenIcon.prependTo($stage); 2279 o_nativeFullScreen = FULLSCREEN && o_allowFullScreen === 'native'; 2280 } else { 2281 $fullscreenIcon.detach(); 2282 o_nativeFullScreen = false; 2283 } 2284 2285 addOrRemoveClass(o_fade, wrapFadeClass); 2286 addOrRemoveClass(!o_fade, wrapSlideClass); 2287 addOrRemoveClass(!opts.captions, wrapNoCaptionsClass); 2288 addOrRemoveClass(o_rtl, wrapRtlClass); 2289 addOrRemoveClass(opts.arrows !== 'always', wrapToggleArrowsClass); 2290 2291 o_shadows = opts.shadows && !SLOW; 2292 addOrRemoveClass(!o_shadows, wrapNoShadowsClass); 2293 2294 $wrap
2295 .addClass(classes.add.join(' ')) 2296 .removeClass(classes.remove.join(' ')); 2297 2298 lastOptions = $.extend({}, opts); 2299 } 2300 2301 function normalizeIndex (index) { 2302 return index < 0 ? (size + (index % size)) % size : index >= size ? index % size : index; 2303 } 2304 2305 function limitIndex (index) { 2306 return minMaxLimit(index, 0, size - 1); 2307 } 2308 2309 function edgeIndex (index) { 2310 return o_loop ? normalizeIndex(index) : limitIndex(index); 2311 } 2312 2313 function getPrevIndex (index) { 2314 return index > 0 || o_loop ? index - 1 : false; 2315 } 2316 2317 function getNextIndex (index) { 2318 return index < size - 1 || o_loop ? index + 1 : false; 2319 } 2320 2321 function setStageShaftMinmaxAndSnap () { 2322 stageShaftTouchTail.min = o_loop ? -Infinity : -getPosByIndex(size - 1, measures.w, opts.margin, repositionIndex); 2323 stageShaftTouchTail.max = o_loop ? Infinity : -getPosByIndex(0, measures.w, opts.margin, repositionIndex); 2324 stageShaftTouchTail.snap = measures.w + opts.margin; 2325 } 2326 2327 function setNavShaftMinMax () { 2328 ////////console.log('setNavShaftMinMax', measures.nw); 2329 navShaftTouchTail.min = Math.min(0, measures.nw - $navShaft.width()); 2330 navShaftTouchTail.max = 0; 2331 $navShaft.toggleClass(grabClass, !(navShaftTouchTail.noMove = navShaftTouchTail.min === navShaftTouchTail.max)); 2332 } 2333 2334 function eachIndex (indexes, type, fn) { 2335 if (typeof indexes === 'number') { 2336 indexes = new Array(indexes); 2337 var rangeFLAG = true; 2338 } 2339 return $.each(indexes, function (i, index) { 2340 if (rangeFLAG) index = i; 2341 if (typeof index === 'number') { 2342 var dataFrame = data[normalizeIndex(index)]; 2343 2344 if (dataFrame) { 2345 var key = '$' + type + 'Frame', 2346 $frame = dataFrame[key]; 2347 2348 fn.call(this, i, index, dataFrame, $frame, key, $frame && $frame.data()); 2349 } 2350 } 2351 }); 2352 } 2353 2354 function setMeasures (width, height, ratio, index) { 2355 if (!measuresSetFLAG || (measuresSetFLAG === '*' && index === startIndex)) { 2356 2357 //////console.log('setMeasures', index, opts.width, opts.height); 2358 2359 width = measureIsValid(opts.width) || measureIsValid(width) || WIDTH;
2360 height = measureIsValid(opts.height) || measureIsValid(height) || HEIGHT; 2361 that.resize({ 2362 width: width, 2363 ratio: opts.ratio || ratio || width / height 2364 }, 0, index !== startIndex && '*'); 2365 } 2366 } 2367 2368 function loadImg (indexes, type, specialMeasures, method, position, again) { 2369 eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) { 2370 2371 if (!$frame) return; 2372 2373 var fullFLAG = that.fullScreen && dataFrame.full && dataFrame.full !== dataFrame.img && !frameData.$full && type === 'stage'; 2374 2375 if (frameData.$img && !again && !fullFLAG) return; 2376 2377 var img = new Image(), 2378 $img = $(img), 2379 imgData = $img.data(); 2380 2381 frameData[fullFLAG ? '$full' : '$img'] = $img; 2382 2383 var srcKey = type === 'stage' ? (fullFLAG ? 'full' : 'img') : 'thumb', 2384 src = dataFrame[srcKey], 2385 dummy = fullFLAG ? null : dataFrame[type === 'stage' ? 'thumb' : 'img']; 2386 2387 if (type === 'navThumb') $frame = frameData.$wrap; 2388 2389 function triggerTriggerEvent (event) { 2390 var _index = normalizeIndex(index); 2391 triggerEvent(event, { 2392 index: _index, 2393 src: src, 2394 frame: data[_index] 2395 }); 2396 } 2397 2398 function error () { 2399 $img.remove(); 2400 2401 $.Fotorama.cache[src] = 'error'; 2402 2403 if ((!dataFrame.html || type !== 'stage') && dummy && dummy !== src) { 2404 dataFrame[srcKey] = src = dummy; 2405 loadImg([index], type, specialMeasures, method, position, true); 2406 } else { 2407 if (src && !dataFrame.html && !fullFLAG) { 2408 $frame 2409 .trigger('f:error') 2410 .removeClass(loadingClass) 2411 .addClass(errorClass); 2412 2413 triggerTriggerEvent('error'); 2414 } else if (type === 'stage') { 2415 $frame 2416 .trigger('f:load') 2417 .removeClass(loadingClass + ' ' + errorClass) 2418 .addClass(loadedClass); 2419 2420 triggerTriggerEvent('load'); 2421 setMeasures(); 2422 } 2423 2424 frameData.state = 'error'; 2425 2426 if (size > 1 && data[index] === dataFrame && !dataFrame.html && !dataFrame.deleted && !dataFrame.video && !fullFLAG) { 2427 dataFrame.deleted = true; 2428 that.splice(index, 1); 2429 } 2430 } 2431 } 2432 2433 function loaded () { 2434 //////console.log('loaded: ' + src); 2435 2436 ////console.log('$.Fotorama.measures[src]', $.Fotorama.measures[src]); 2437 2438 $.Fotorama.measures[src] = imgData.measures = $.Fotorama.measures[src] || { 2439 width: img.width, 2440 height: img.height, 2441 ratio: img.width / img.height 2442 }; 2443 2444 setMeasures(imgData.measures.width, imgData.measures.height, imgData.measures.ratio, index); 2445 2446 $img 2447 .off('load error') 2448 .addClass(imgClass + (fullFLAG ? ' ' + imgFullClass : '')) 2449 .prependTo($frame); 2450 2451 fit($img, ($.isFunction(specialMeasures) ? specialMeasures() : specialMeasures) || measures, method || dataFrame.fit || opts.fit, position || dataFrame.position || opts.position); 2452 2453 $.Fotorama.cache[src] = frameData.state = 'loaded'; 2454 2455 setTimeout(function () { 2456 $frame 2457 .trigger('f:load') 2458 .removeClass(loadingClass + ' ' + errorClass) 2459 .addClass(loadedClass + ' ' + (fullFLAG ? loadedFullClass : loadedImgClass)); 2460 2461 if (type === 'stage') { 2462 triggerTriggerEvent('load'); 2463 } else if (dataFrame.thumbratio === AUTO || !dataFrame.thumbratio && opts.thumbratio === AUTO) { 2464 // danger! reflow for all thumbnails 2465 dataFrame.thumbratio = imgData.measures.ratio; 2466 reset(); 2467 } 2468 }, 0); 2469 } 2470 2471 if (!src) { 2472 error(); 2473 return; 2474 } 2475 2476 function waitAndLoad () { 2477 var _i = 10; 2478 waitFor(function () { 2479 return !touchedFLAG || !_i-- && !SLOW; 2480 }, function () { 2481 loaded(); 2482 }); 2483 } 2484 2485 if (!$.Fotorama.cache[src]) { 2486 $.Fotorama.cache[src] = '*'; 2487 2488 $img 2489 .on('load', waitAndLoad) 2490 .on('error', error); 2491 } else { 2492 (function justWait () { 2493 if ($.Fotorama.cache[src] === 'error') { 2494 error(); 2495 } else if ($.Fotorama.cache[src] === 'loaded') { 2496 ////console.log('take from cache: ' + src);
2497 setTimeout(waitAndLoad, 0); 2498 } else { 2499 setTimeout(justWait, 100); 2500 } 2501 })(); 2502 } 2503 2504 frameData.state = ''; 2505 2506 if ( frameData.data.hasOwnProperty('alt') ) { img.alt = frameData.data.alt; } 2507 if ( frameData.data.hasOwnProperty('title') ) { img.title = frameData.data.title; } 2508 2509 img.src = src; 2510 }); 2511 } 2512 2513 function spinnerSpin ($el) { 2514 $spinner.append(spinner.spin().el).appendTo($el); 2515 } 2516 2517 function spinnerStop () { 2518 $spinner.detach(); 2519 spinner && spinner.stop(); 2520 } 2521 2522 function updateFotoramaState () { 2523 var $frame = activeFrame[STAGE_FRAME_KEY]; 2524 2525 if ($frame && !$frame.data().state) { 2526 spinnerSpin($frame); 2527 $frame.on('f:load f:error', function () { 2528 $frame.off('f:load f:error'); 2529 spinnerStop(); 2530 }); 2531 } 2532 } 2533 2534 function addNavFrameEvents (frame) { 2535 addEnterUp(frame, onNavFrameClick); 2536 addFocus(frame, function () { 2537 2538 setTimeout(function () { 2539 lockScroll($nav); 2540 }, 0); 2541 slideNavShaft({time: o_transitionDuration, guessIndex: $(this).data().eq, minMax: navShaftTouchTail}); 2542 }); 2543 } 2544 2545 function frameDraw (indexes, type) { 2546 eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) { 2547 if ($frame) return; 2548 2549 $frame = dataFrame[key] = $wrap[key].clone(); 2550 frameData = $frame.data(); 2551 frameData.data = dataFrame; 2552 var frame = $frame[0]; 2553 2554 if (type === 'stage') { 2555 2556 if (dataFrame.html) { 2557 $('<div class="' + htmlClass + '"></div>') 2558 .append( 2559 dataFrame._html ? $(dataFrame.html) 2560 .removeAttr('id') 2561 .html(dataFrame._html) // Because of IE 2562 : dataFrame.html 2563 ) 2564 .appendTo($frame); 2565 } 2566 2567 dataFrame.caption && $(div(captionClass, div(captionWrapClass, dataFrame.caption))).appendTo($frame); 2568 2569 dataFrame.video && $frame 2570 .addClass(stageFrameVideoClass) 2571 .append($videoPlay.clone()); 2572 2573 // This solves tabbing problems 2574 addFocus(frame, function () { 2575 setTimeout(function () { 2576 lockScroll($stage); 2577 }, 0); 2578 clickToShow({index: frameData.eq, user: true}); 2579 }); 2580 2581 $stageFrame = $stageFrame.add($frame); 2582 } else if (type === 'navDot') { 2583 addNavFrameEvents(frame); 2584 $navDotFrame = $navDotFrame.add($frame); 2585 } else if (type === 'navThumb') { 2586 addNavFrameEvents(frame); 2587 frameData.$wrap = $frame.children(':first'); 2588 $navThumbFrame = $navThumbFrame.add($frame); 2589 if (dataFrame.video) { 2590 frameData.$wrap.append($videoPlay.clone()); 2591 } 2592 } 2593 }); 2594 } 2595 2596 function callFit ($img, measuresToFit, method, position) { 2597 return $img && $img.length && fit($img, measuresToFit, method, position); 2598 } 2599 2600 function stageFramePosition (indexes) { 2601 eachIndex(indexes, 'stage', function (i, index, dataFrame, $frame, key, frameData) { 2602 if (!$frame) return; 2603 2604 var normalizedIndex = normalizeIndex(index), 2605 method = dataFrame.fit || opts.fit, 2606 position = dataFrame.position || opts.position; 2607 frameData.eq = normalizedIndex; 2608 2609 toDetach[STAGE_FRAME_KEY][normalizedIndex] = $frame.css($.extend({left: o_fade ? 0 : getPosByIndex(index, measures.w, opts.margin, repositionIndex)}, o_fade && getDuration(0))); 2610 2611 if (isDetached($frame[0])) { 2612 $frame.appendTo($stageShaft); 2613 unloadVideo(dataFrame.$video); 2614 } 2615 2616 callFit(frameData.$img, measures, method, position); 2617 callFit(frameData.$full, measures, method, position); 2618 }); 2619 } 2620 2621 function thumbsDraw (pos, loadFLAG) { 2622 if (o_nav !== 'thumbs' || isNaN(pos)) return; 2623 2624 var leftLimit = -pos, 2625 rightLimit = -pos + measures.nw; 2626 2627 $navThumbFrame.each(function () { 2628 var $this = $(this), 2629 thisData = $this.data(), 2630 eq = thisData.eq, 2631 getSpecialMeasures = function () { 2632 return { 2633 h: o_thumbSide2, 2634 w: thisData.w 2635 } 2636 }, 2637 specialMeasures = getSpecialMeasures(), 2638 dataFrame = data[eq] || {}, 2639 method = dataFrame.thumbfit || opts.thumbfit, 2640 position = dataFrame.thumbposition || opts.thumbposition; 2641 2642 specialMeasures.w = thisData.w; 2643 2644 if (thisData.l + thisData.w < leftLimit 2645 || thisData.l > rightLimit 2646 || callFit(thisData.$img, specialMeasures, method, position)) return; 2647 2648 loadFLAG && loadImg([eq], 'navThumb', getSpecialMeasures, method, position); 2649 }); 2650 } 2651 2652 function frameAppend ($frames, $shaft, type) {
2653 if (!frameAppend[type]) { 2654 2655 var thumbsFLAG = type === 'nav' && o_navThumbs, 2656 left = 0; 2657 2658 $shaft.append( 2659 $frames 2660 .filter(function () { 2661 var actual, 2662 $this = $(this), 2663 frameData = $this.data(); 2664 for (var _i = 0, _l = data.length; _i < _l; _i++) { 2665 if (frameData.data === data[_i]) { 2666 actual = true; 2667 frameData.eq = _i; 2668 break; 2669 } 2670 } 2671 return actual || $this.remove() && false; 2672 }) 2673 .sort(function (a, b) { 2674 return $(a).data().eq - $(b).data().eq; 2675 }) 2676 .each(function () { 2677 2678 if (!thumbsFLAG) return; 2679 2680 var $this = $(this), 2681 frameData = $this.data(), 2682 thumbwidth = Math.round(o_thumbSide2 * frameData.data.thumbratio) || o_thumbSide; 2683 2684 frameData.l = left; 2685 frameData.w = thumbwidth; 2686 2687 $this.css({width: thumbwidth}); 2688 2689 left += thumbwidth + opts.thumbmargin; 2690 }) 2691 ); 2692 2693 frameAppend[type] = true; 2694 } 2695 } 2696 2697 function getDirection (x) { 2698 return x - stageLeft > measures.w / 3; 2699 } 2700 2701 function disableDirrection (i) { 2702 return !o_loop && (!(activeIndex + i) || !(activeIndex - size + i)) && !$videoPlaying; 2703 } 2704 2705 function arrsUpdate () { 2706 var disablePrev = disableDirrection(0), 2707 disableNext = disableDirrection(1); 2708 $arrPrev 2709 .toggleClass(arrDisabledClass, disablePrev) 2710 .attr(disableAttr(disablePrev)); 2711 $arrNext 2712 .toggleClass(arrDisabledClass, disableNext) 2713 .attr(disableAttr(disableNext)); 2714 } 2715 2716 function stageWheelUpdate () { 2717 if (stageWheelTail.ok) { 2718 stageWheelTail.prevent = {'<': disableDirrection(0), '>': disableDirrection(1)}; 2719 } 2720 } 2721 2722 function getNavFrameBounds ($navFrame) { 2723 var navFrameData = $navFrame.data(), 2724 left, 2725 width; 2726 2727 if (o_navThumbs) { 2728 left = navFrameData.l; 2729 width = navFrameData.w; 2730 } else { 2731 left = $navFrame.position().left; 2732 width = $navFrame.width(); 2733 } 2734 2735 return { 2736 c: left + width / 2, 2737 min: -left + opts.thumbmargin * 10, 2738 max: -left + measures.w - width - opts.thumbmargin * 10 2739 }; 2740 } 2741 2742 function slideThumbBorder (time) { 2743 var navFrameData = activeFrame[navFrameKey].data(); 2744 slide($thumbBorder, { 2745 time: time * 1.2, 2746 pos: navFrameData.l, 2747 width: navFrameData.w - opts.thumbborderwidth * 2 2748 }); 2749 } 2750 2751 function slideNavShaft (options) { 2752 ////console.log('slideNavShaft', options.guessIndex, options.keep, slideNavShaft.l); 2753 var $guessNavFrame = data[options.guessIndex][navFrameKey]; 2754 if ($guessNavFrame) { 2755 var overflowFLAG = navShaftTouchTail.min !== navShaftTouchTail.max, 2756 minMax = options.minMax || overflowFLAG && getNavFrameBounds(activeFrame[navFrameKey]), 2757 l = overflowFLAG && (options.keep && slideNavShaft.l ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max)), 2758 pos = overflowFLAG && minMaxLimit(l, navShaftTouchTail.min, navShaftTouchTail.max), 2759 time = options.time * 1.1; 2760 2761 slide($navShaft, { 2762 time: time, 2763 pos: pos || 0, 2764 onEnd: function () { 2765 thumbsDraw(pos, true); 2766 } 2767 }); 2768 2769 //if (time) thumbsDraw(pos); 2770 2771 setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max)); 2772 slideNavShaft.l = l; 2773 } 2774 } 2775 2776 function navUpdate () { 2777 deactivateFrames(navFrameKey); 2778 toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass)); 2779 } 2780 2781 function deactivateFrames (key) { 2782 var _toDeactivate = toDeactivate[key]; 2783 2784 while (_toDeactivate.length) { 2785 _toDeactivate.shift().removeClass(activeClass); 2786 } 2787 } 2788 2789 function detachFrames (key) { 2790 var _toDetach = toDetach[key]; 2791 2792 //////console.log('_toDetach', _toDetach); 2793 //////console.log('activeIndexes', activeIndexes); 2794 2795 $.each(activeIndexes, function (i, index) { 2796 delete _toDetach[normalizeIndex(index)]; 2797 }); 2798 2799 $.each(_toDetach, function (index, $frame) { 2800 delete _toDetach[index]; 2801 //////console.log('Detach', index); 2802 $frame.detach(); 2803 }); 2804 } 2805 2806 function stageShaftReposition (skipOnEnd) { 2807 2808 repositionIndex = dirtyIndex = activeIndex; 2809 2810 var $frame = activeFrame[STAGE_FRAME_KEY]; 2811 2812 if ($frame) { 2813 deactivateFrames(STAGE_FRAME_KEY); 2814 toDeactivate[STAGE_FRAME_KEY].push($frame.addClass(activeClass)); 2815 2816 skipOnEnd || that.show.onEnd(true); 2817 stop($stageShaft, 0, true); 2818 2819 detachFrames(STAGE_FRAME_KEY); 2820 stageFramePosition(activeIndexes); 2821 setStageShaftMinmaxAndSnap(); 2822 setNavShaftMinMax(); 2823 } 2824 } 2825 2826 function extendMeasures (options, measuresArray) { 2827 if (!options) return; 2828 2829 $.each(measuresArray, function (i, measures) { 2830 if (!measures) return; 2831 2832 $.extend(measures, { 2833 width: options.width || measures.width, 2834 height: options.height, 2835 minwidth: options.minwidth, 2836 maxwidth: options.maxwidth, 2837 minheight: options.minheight, 2838 maxheight: options.maxheight, 2839 ratio: getRatio(options.ratio) 2840 }) 2841 }); 2842 } 2843 2844 function triggerEvent (event, extra) { 2845 $fotorama.trigger(_fotoramaClass + ':' + event, [that, extra]); 2846 } 2847 2848 function onTouchStart () { 2849 clearTimeout(onTouchEnd.t); 2850 touchedFLAG = 1; 2851
2852 if (opts.stopautoplayontouch) { 2853 that.stopAutoplay(); 2854 } else { 2855 pausedAutoplayFLAG = true; 2856 } 2857 } 2858 2859 function onTouchEnd () { 2860 if (!touchedFLAG) return; 2861 if (!opts.stopautoplayontouch) { 2862 releaseAutoplay(); 2863 changeAutoplay(); 2864 } 2865 2866 onTouchEnd.t = setTimeout(function () { 2867 touchedFLAG = 0; 2868 }, TRANSITION_DURATION + TOUCH_TIMEOUT); 2869 //////console.timeEnd('onTouchEnd'); 2870 } 2871 2872 function releaseAutoplay () { 2873 ////console.log('releaseAutoplay'); 2874 pausedAutoplayFLAG = !!($videoPlaying || stoppedAutoplayFLAG); 2875 } 2876 2877 function changeAutoplay () { 2878 ////console.log('changeAutoplay'); 2879 2880 clearTimeout(changeAutoplay.t); 2881 waitFor.stop(changeAutoplay.w); 2882 2883 if (!opts.autoplay || pausedAutoplayFLAG) { 2884 if (that.autoplay) { 2885 that.autoplay = false; 2886 triggerEvent('stopautoplay'); 2887 } 2888 2889 return; 2890 } 2891 2892 ////console.log('changeAutoplay continue'); 2893 2894 if (!that.autoplay) { 2895 that.autoplay = true; 2896 triggerEvent('startautoplay'); 2897 } 2898 2899 var _activeIndex = activeIndex; 2900 2901 2902 var frameData = activeFrame[STAGE_FRAME_KEY].data(); 2903 changeAutoplay.w = waitFor(function () { 2904 ////console.log('wait for the state of the current frame'); 2905 return frameData.state || _activeIndex !== activeIndex; 2906 }, function () { 2907 ////console.log('the current frame is ready'); 2908 changeAutoplay.t = setTimeout(function () { 2909 ////console.log('changeAutoplay.t setTimeout', pausedAutoplayFLAG, _activeIndex !== activeIndex); 2910 if (pausedAutoplayFLAG || _activeIndex !== activeIndex) return; 2911 2912 var _nextAutoplayIndex = nextAutoplayIndex, 2913 nextFrameData = data[_nextAutoplayIndex][STAGE_FRAME_KEY].data(); 2914 2915 changeAutoplay.w = waitFor(function () { 2916 ////console.log('wait for the state of the next frame'); 2917 return nextFrameData.state || _nextAutoplayIndex !== nextAutoplayIndex; 2918 }, function () { 2919 if (pausedAutoplayFLAG || _nextAutoplayIndex !== nextAutoplayIndex) return; 2920 that.show(o_loop ? getDirectionSign(!o_rtl) : nextAutoplayIndex); 2921 }); 2922 }, opts.autoplay); 2923 }); 2924 2925 } 2926 2927 that.startAutoplay = function (interval) { 2928 if (that.autoplay) return this; 2929 pausedAutoplayFLAG = stoppedAutoplayFLAG = false; 2930 setAutoplayInterval(interval || opts.autoplay); 2931 changeAutoplay(); 2932 2933 return this; 2934 }; 2935 2936 that.stopAutoplay = function () { 2937 if (that.autoplay) { 2938 pausedAutoplayFLAG = stoppedAutoplayFLAG = true; 2939 changeAutoplay(); 2940 } 2941 return this; 2942 }; 2943 2944 that.show = function (options) { 2945 ////console.log('that.show'); 2946 //////console.time('that.show prepare'); 2947 var index; 2948 2949 if (typeof options !== 'object') { 2950 index = options; 2951 options = {}; 2952 } else { 2953 index = options.index; 2954 } 2955 2956 index = index === '>' ? dirtyIndex + 1 : index === '<' ? dirtyIndex - 1 : index === '<<' ? 0 : index === '>>' ? size - 1 : index; 2957 index = isNaN(index) ? getIndexFromHash(index, data, true) : index; 2958 index = typeof index === 'undefined' ? activeIndex || 0 : index; 2959 2960 that.activeIndex = activeIndex = edgeIndex(index); 2961 prevIndex = getPrevIndex(activeIndex); 2962 nextIndex = getNextIndex(activeIndex); 2963 nextAutoplayIndex = normalizeIndex(activeIndex + (o_rtl ? -1 : 1)); 2964 activeIndexes = [activeIndex, prevIndex, nextIndex]; 2965 2966 dirtyIndex = o_loop ? index : activeIndex; 2967 2968 var diffIndex = Math.abs(lastActiveIndex - dirtyIndex), 2969 time = getNumber(options.time, function () { 2970 return Math.min(o_transitionDuration * (1 + (diffIndex - 1) / 12), o_transitionDuration * 2); 2971 }), 2972 overPos = options.overPos; 2973 2974 if (options.slow) time *= 10; 2975 2976 var _activeFrame = activeFrame; 2977 that.activeFrame = activeFrame = data[activeIndex]; 2978 //////console.timeEnd('that.show prepare'); 2979 2980 var silent = _activeFrame === activeFrame && !options.user; 2981 2982 //setTimeout(function () { 2983 //////console.time('unloadVideo'); 2984 unloadVideo($videoPlaying, activeFrame.i !== data[normalizeIndex(repositionIndex)].i); 2985 //////console.timeEnd('unloadVideo'); 2986 //////console.time('frameDraw'); 2987 frameDraw(activeIndexes, 'stage'); 2988 //////console.timeEnd('frameDraw'); 2989 //////console.time('stageFramePosition'); 2990 stageFramePosition(SLOW ? [dirtyIndex] : [dirtyIndex, getPrevIndex(dirtyIndex), getNextIndex(dirtyIndex)]); 2991 //////console.timeEnd('stageFramePosition'); 2992 //////console.time('updateTouchTails'); 2993 updateTouchTails('go', true); 2994 //////console.timeEnd('updateTouchTails'); 2995 //////console.time('triggerEvent'); 2996 2997 silent || triggerEvent('show', { 2998 user: options.user, 2999 time: time 3000 }); 3001 //////console.timeEnd('triggerEvent'); 3002 //}, 0); 3003 3004 //////console.time('bind onEnd'); 3005 3006 pausedAutoplayFLAG = true; 3007 3008 var onEnd = that.show.onEnd = function (skipReposition) { 3009 if (onEnd.ok) return; 3010 onEnd.ok = true; 3011 3012 skipReposition || stageShaftReposition(true); 3013 3014 if (!silent) {
3015 triggerEvent('showend', { 3016 user: options.user 3017 }); 3018 } 3019 3020 ////console.log('o_transition', o_transition); 3021 3022 if (!skipReposition && o_transition && o_transition !== opts.transition) { 3023 ////console.log('set transition back to: ' + o_transition); 3024 that.setOptions({transition: o_transition}); 3025 o_transition = false; 3026 return; 3027 } 3028 3029 updateFotoramaState(); 3030 loadImg(activeIndexes, 'stage'); 3031 3032 updateTouchTails('go', false); 3033 stageWheelUpdate(); 3034 3035 stageCursor(); 3036 releaseAutoplay(); 3037 changeAutoplay(); 3038 }; 3039 //////console.timeEnd('bind onEnd'); 3040 3041 if (!o_fade) { 3042 //////console.time('slide'); 3043 slide($stageShaft, { 3044 pos: -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex), 3045 overPos: overPos, 3046 time: time, 3047 onEnd: onEnd/*, 3048 _001: true*/ 3049 }); 3050 //////console.timeEnd('slide'); 3051 } else { 3052 var $activeFrame = activeFrame[STAGE_FRAME_KEY], 3053 $prevActiveFrame = activeIndex !== lastActiveIndex ? data[lastActiveIndex][STAGE_FRAME_KEY] : null; 3054 3055 fade($activeFrame, $prevActiveFrame, $stageFrame, { 3056 time: time, 3057 method: opts.transition, 3058 onEnd: onEnd 3059 }, fadeStack); 3060 } 3061 3062 //////console.time('arrsUpdate'); 3063 arrsUpdate(); 3064 //////console.timeEnd('arrsUpdate'); 3065 3066 if (o_nav) { 3067 //////console.time('navUpdate'); 3068 navUpdate(); 3069 //////console.timeEnd('navUpdate'); 3070 3071 //////console.time('slideNavShaft'); 3072 var guessIndex = limitIndex(activeIndex + minMaxLimit(dirtyIndex - lastActiveIndex, -1, 1)); 3073 slideNavShaft({time: time, coo: guessIndex !== activeIndex && options.coo, guessIndex: typeof options.coo !== 'undefined' ? guessIndex : activeIndex, keep: silent}); 3074 //////console.timeEnd('slideNavShaft'); 3075 3076 //////console.time('slideThumbBorder'); 3077 if (o_navThumbs) slideThumbBorder(time); 3078 //////console.timeEnd('slideThumbBorder'); 3079 } 3080 3081 //////console.time('that.show end'); 3082 showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex; 3083 lastActiveIndex = activeIndex; 3084 opts.hash && showedFLAG && !that.eq && setHash(activeFrame.id || activeIndex + 1); 3085 //////console.timeEnd('that.show end'); 3086 3087 //////console.timeEnd('that.show'); 3088 3089 return this; 3090 }; 3091 3092 that.requestFullScreen = function () { 3093 if (o_allowFullScreen && !that.fullScreen) { 3094 scrollTop = $WINDOW.scrollTop(); 3095 scrollLeft = $WINDOW.scrollLeft(); 3096 3097 lockScroll($WINDOW); 3098 3099 updateTouchTails('x', true); 3100 3101 measuresStash = $.extend({}, measures); 3102 3103 $fotorama 3104 .addClass(fullscreenClass) 3105 .appendTo($BODY.addClass(_fullscreenClass)); 3106 3107 $HTML.addClass(_fullscreenClass); 3108 3109 unloadVideo($videoPlaying, true, true); 3110 3111 that.fullScreen = true; 3112 3113 if (o_nativeFullScreen) { 3114 fullScreenApi.request(fotorama); 3115 } 3116 3117 that.resize(); 3118 loadImg(activeIndexes, 'stage'); 3119 updateFotoramaState(); 3120 3121 triggerEvent('fullscreenenter'); 3122 } 3123 3124 return this; 3125 }; 3126 3127 function cancelFullScreen () { 3128 if (that.fullScreen) { 3129 that.fullScreen = false; 3130 3131 if (FULLSCREEN) { 3132 fullScreenApi.cancel(fotorama); 3133 } 3134 3135 $BODY.removeClass(_fullscreenClass); 3136 $HTML.removeClass(_fullscreenClass); 3137 3138 $fotorama 3139 .removeClass(fullscreenClass) 3140 .insertAfter($anchor); 3141 3142 measures = $.extend({}, measuresStash); 3143 3144 unloadVideo($videoPlaying, true, true); 3145 3146 updateTouchTails('x', false); 3147 3148 that.resize(); 3149 loadImg(activeIndexes, 'stage'); 3150 3151 lockScroll($WINDOW, scrollLeft, scrollTop); 3152 3153 triggerEvent('fullscreenexit'); 3154 } 3155 } 3156 3157 that.cancelFullScreen = function () { 3158 if (o_nativeFullScreen && fullScreenApi.is()) { 3159 fullScreenApi.cancel(document); 3160 } else { 3161 cancelFullScreen(); 3162 } 3163 3164 return this; 3165 }; 3166 3167 that.toggleFullScreen = function () { 3168 return that[(that.fullScreen ? 'cancel' : 'request') + 'FullScreen'](); 3169 }; 3170 3171 addEvent(document, fullScreenApi.event, function () { 3172 if (data && !fullScreenApi.is() && !$videoPlaying) { 3173 cancelFullScreen(); 3174 } 3175 }); 3176 3177 that.resize = function (options) { 3178 if (!data) return this; 3179 3180 var time = arguments[1] || 0, 3181 setFLAG = arguments[2]; 3182 3183 extendMeasures(!that.fullScreen ? optionsToLowerCase(options) : {width: '100%', maxwidth: null, minwidth: null, height: '100%', maxheight: null, minheight: null}, [measures, setFLAG || that.fullScreen || opts]); 3184 3185 var width = measures.width, 3186 height = measures.height, 3187 ratio = measures.ratio,
3188 windowHeight = $WINDOW.height() - (o_nav ? $nav.height() : 0); 3189 3190 if (measureIsValid(width)) { 3191 $wrap 3192 .addClass(wrapOnlyActiveClass) 3193 .css({width: width, minWidth: measures.minwidth || 0, maxWidth: measures.maxwidth || MAX_WIDTH}); 3194 3195 width = measures.W = measures.w = $wrap.width(); 3196 measures.nw = o_nav && numberFromWhatever(opts.navwidth, width) || width; 3197 3198 if (opts.glimpse) { 3199 // Glimpse 3200 measures.w -= Math.round((numberFromWhatever(opts.glimpse, width) || 0) * 2); 3201 } 3202 3203 $stageShaft.css({width: measures.w, marginLeft: (measures.W - measures.w) / 2}); 3204 3205 //////console.log('measures.W', measures.W); 3206 //////console.log('measures.w', measures.w); 3207 3208 height = numberFromWhatever(height, windowHeight); 3209 3210 height = height || (ratio && width / ratio); 3211 3212 if (height) { 3213 width = Math.round(width); 3214 height = measures.h = Math.round(minMaxLimit(height, numberFromWhatever(measures.minheight, windowHeight), numberFromWhatever(measures.maxheight, windowHeight))); 3215 3216 $stage 3217 .stop() 3218 .animate({width: width, height: height}, time, function () { 3219 $wrap.removeClass(wrapOnlyActiveClass); 3220 }); 3221 3222 stageShaftReposition(); 3223 3224 if (o_nav) { 3225 $nav 3226 .stop() 3227 .animate({width: measures.nw}, time); 3228 3229 slideNavShaft({guessIndex: activeIndex, time: time, keep: true}); 3230 if (o_navThumbs && frameAppend.nav) slideThumbBorder(time); 3231 } 3232 3233 measuresSetFLAG = setFLAG || true; 3234 3235 ready(); 3236 } 3237 } 3238 3239 stageLeft = $stage.offset().left; 3240 3241 return this; 3242 }; 3243 3244 that.setOptions = function (options) { 3245 $.extend(opts, options); 3246 reset(); 3247 return this; 3248 }; 3249 3250 that.shuffle = function () { 3251 data && shuffle(data) && reset(); 3252 return this; 3253 }; 3254 3255 function setShadow ($el, edge) { 3256 //////console.time('setShadow'); 3257 if (o_shadows) { 3258 $el.removeClass(shadowsLeftClass + ' ' + shadowsRightClass); 3259 edge && !$videoPlaying && $el.addClass(edge.replace(/^|\s/g, ' ' + shadowsClass + '--')); 3260 } 3261 //////console.timeEnd('setShadow'); 3262 } 3263 3264 that.destroy = function () { 3265 that.cancelFullScreen(); 3266 that.stopAutoplay(); 3267 3268 data = that.data = null; 3269 3270 appendElements(); 3271 3272 activeIndexes = []; 3273 detachFrames(STAGE_FRAME_KEY); 3274 3275 reset.ok = false; 3276 3277 return this; 3278 }; 3279 3280 that.playVideo = function () { 3281 var dataFrame = activeFrame, 3282 video = dataFrame.video, 3283 _activeIndex = activeIndex; 3284 3285 if (typeof video === 'object' && dataFrame.videoReady) { 3286 o_nativeFullScreen && that.fullScreen && that.cancelFullScreen(); 3287 3288 waitFor(function () { 3289 return !fullScreenApi.is() || _activeIndex !== activeIndex; 3290 }, function () { 3291 if (_activeIndex === activeIndex) { 3292 dataFrame.$video = dataFrame.$video || $($.Fotorama.jst.video(video)); 3293 dataFrame.$video.appendTo(dataFrame[STAGE_FRAME_KEY]); 3294 3295 $wrap.addClass(wrapVideoClass); 3296 $videoPlaying = dataFrame.$video; 3297 3298 stageNoMove(); 3299 3300 $arrs.blur(); 3301 $fullscreenIcon.blur(); 3302 3303 triggerEvent('loadvideo'); 3304 } 3305 }); 3306 } 3307 3308 return this; 3309 }; 3310 3311 that.stopVideo = function () { 3312 unloadVideo($videoPlaying, true, true); 3313 return this; 3314 }; 3315 3316 function unloadVideo ($video, unloadActiveFLAG, releaseAutoplayFLAG) { 3317 if (unloadActiveFLAG) { 3318 $wrap.removeClass(wrapVideoClass); 3319 $videoPlaying = false; 3320 3321 stageNoMove(); 3322 } 3323 3324 if ($video && $video !== $videoPlaying) { 3325 $video.remove(); 3326 triggerEvent('unloadvideo'); 3327 } 3328 3329 if (releaseAutoplayFLAG) { 3330 releaseAutoplay(); 3331 changeAutoplay(); 3332 } 3333 } 3334 3335 function toggleControlsClass (FLAG) {
3336 $wrap.toggleClass(wrapNoControlsClass, FLAG); 3337 } 3338 3339 function stageCursor (e) { 3340 if (stageShaftTouchTail.flow) return; 3341 3342 var x = e ? e.pageX : stageCursor.x, 3343 pointerFLAG = x && !disableDirrection(getDirection(x)) && opts.click; 3344 3345 if (stageCursor.p !== pointerFLAG 3346 && $stage.toggleClass(pointerClass, pointerFLAG)) { 3347 stageCursor.p = pointerFLAG; 3348 stageCursor.x = x; 3349 } 3350 } 3351 3352 $stage.on('mousemove', stageCursor); 3353 3354 function clickToShow (showOptions) { 3355 clearTimeout(clickToShow.t); 3356 3357 if (opts.clicktransition && opts.clicktransition !== opts.transition) { 3358 ////console.log('change transition to: ' + opts.clicktransition); 3359 3360 // this timeout is for yield events flow 3361 setTimeout(function () { 3362 // save original transition for later 3363 var _o_transition = opts.transition; 3364 3365 that.setOptions({transition: opts.clicktransition}); 3366 3367 // now safe to pass base transition to o_transition, so that.show will restor it 3368 o_transition = _o_transition; 3369 // this timeout is here to prevent jerking in some browsers 3370 clickToShow.t = setTimeout(function () { 3371 that.show(showOptions); 3372 }, 10); 3373 }, 0); 3374 } else { 3375 that.show(showOptions); 3376 } 3377 } 3378 3379 function onStageTap (e, toggleControlsFLAG) { 3380 //////console.time('onStageTap'); 3381 var target = e.target, 3382 $target = $(target); 3383 3384 if ($target.hasClass(videoPlayClass)) { 3385 that.playVideo(); 3386 } else if (target === fullscreenIcon) { 3387 that.toggleFullScreen(); 3388 } else if ($videoPlaying) { 3389 target === videoClose && unloadVideo($videoPlaying, true, true); 3390 } else { 3391 if (toggleControlsFLAG) { 3392 toggleControlsClass(); 3393 } else if (opts.click) { 3394 3395 clickToShow({index: e.shiftKey || getDirectionSign(getDirection(e._x)), slow: e.altKey, user: true}); 3396 } 3397 } 3398 //////console.timeEnd('onStageTap'); 3399 } 3400 3401 function updateTouchTails (key, value) { 3402 stageShaftTouchTail[key] = navShaftTouchTail[key] = value; 3403 } 3404 3405 stageShaftTouchTail = moveOnTouch($stageShaft, { 3406 onStart: onTouchStart, 3407 onMove: function (e, result) { 3408 setShadow($stage, result.edge); 3409 }, 3410 onTouchEnd: onTouchEnd, 3411 onEnd: function (result) { 3412 //////console.time('stageShaftTouchTail.onEnd'); 3413 setShadow($stage); 3414 3415 //////console.log('result', result); 3416 3417 var toggleControlsFLAG = (MS_POINTER && !hoverFLAG || result.touch) && opts.arrows && opts.arrows !== 'always'; 3418 3419 if (result.moved || (toggleControlsFLAG && result.pos !== result.newPos && !result.control)) { 3420 var index = getIndexByPos(result.newPos, measures.w, opts.margin, repositionIndex); 3421 that.show({ 3422 index: index, 3423 time: o_fade ? o_transitionDuration : result.time, 3424 overPos: result.overPos, 3425 user: true 3426 }); 3427 } else if (!result.aborted && !result.control) { 3428 onStageTap(result.startEvent, toggleControlsFLAG); 3429 } 3430 //////console.timeEnd('stageShaftTouchTail.onEnd'); 3431 }, 3432// getPos: function () { 3433// return -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex); 3434// }, 3435 //_001: true, 3436 timeLow: 1, 3437 timeHigh: 1, 3438 friction: 2, 3439 select: '.' + selectClass + ', .' + selectClass + ' *', 3440 $wrap: $stage 3441 }); 3442 3443 navShaftTouchTail = moveOnTouch($navShaft, { 3444 onStart: onTouchStart, 3445 onMove: function (e, result) { 3446 setShadow($nav, result.edge); 3447 }, 3448 onTouchEnd: onTouchEnd, 3449 onEnd: function (result) { 3450 3451 function onEnd () { 3452 slideNavShaft.l = result.newPos; 3453 releaseAutoplay(); 3454 changeAutoplay(); 3455 thumbsDraw(result.newPos, true); 3456 } 3457 3458 if (!result.moved) { 3459 var target = result.$target.closest('.' + navFrameClass, $navShaft)[0]; 3460 target && onNavFrameClick.call(target, result.startEvent); 3461 } else if (result.pos !== result.newPos) { 3462 pausedAutoplayFLAG = true; 3463 slide($navShaft, { 3464 time: result.time, 3465 pos: result.newPos, 3466 overPos: result.overPos, 3467 onEnd: onEnd 3468 }); 3469 thumbsDraw(result.newPos); 3470 o_shadows && setShadow($nav, findShadowEdge(result.newPos, navShaftTouchTail.min, navShaftTouchTail.max)); 3471 } else { 3472 onEnd(); 3473 } 3474 }, 3475 timeLow: .5, 3476 timeHigh: 2, 3477 friction: 5, 3478 $wrap: $nav 3479 }); 3480 3481 stageWheelTail = wheel($stage, { 3482 shift: true, 3483 onEnd: function (e, direction) { 3484 //////console.log('wheel $stage onEnd', direction); 3485 onTouchStart(); 3486 onTouchEnd(); 3487 that.show({index: direction, slow: e.altKey}) 3488 } 3489 }); 3490 3491 navWheelTail = wheel($nav, { 3492 onEnd: function (e, direction) { 3493 //////console.log('wheel $nav onEnd', direction); 3494 onTouchStart(); 3495 onTouchEnd(); 3496 var newPos = stop($navShaft) + direction * .25; 3497 $navShaft.css(getTranslate(minMaxLimit(newPos, navShaftTouchTail.min, navShaftTouchTail.max))); 3498 o_shadows && setShadow($nav, findShadowEdge(newPos, navShaftTouchTail.min, navShaftTouchTail.max)); 3499 navWheelTail.prevent = {'<': newPos >= navShaftTouchTail.max, '>': newPos <= navShaftTouchTail.min}; 3500 clearTimeout(navWheelTail.t); 3501 navWheelTail.t = setTimeout(function () { 3502 slideNavShaft.l = newPos; 3503 thumbsDraw(newPos, true) 3504 }, TOUCH_TIMEOUT); 3505 thumbsDraw(newPos); 3506 } 3507 }); 3508 3509 $wrap.hover( 3510 function () { 3511 setTimeout(function () { 3512 if (touchedFLAG) return; 3513 toggleControlsClass(!(hoverFLAG = true)); 3514 }, 0); 3515 }, function () { 3516 if (!hoverFLAG) return; 3517 toggleControlsClass(!(hoverFLAG = false)); 3518 } 3519 ); 3520 3521 function onNavFrameClick (e) { 3522 var index = $(this).data().eq; 3523 clickToShow({index: index, slow: e.altKey, user: true, coo: e._x - $nav.offset().left}); 3524 } 3525 3526 function onArrClick (e) { 3527 clickToShow({index: $arrs.index(this) ? '>' : '<', slow: e.altKey, user: true}); 3528 } 3529 3530 smartClick($arrs, function (e) { 3531 stopEvent(e); 3532 onArrClick.call(this, e); 3533 }, { 3534 onStart: function () { 3535 onTouchStart(); 3536 stageShaftTouchTail.control = true; 3537 }, 3538 onTouchEnd: onTouchEnd 3539 }); 3540
3541 function addFocusOnControls (el) { 3542 addFocus(el, function () { 3543 setTimeout(function () { 3544 lockScroll($stage); 3545 }, 0); 3546 toggleControlsClass(false); 3547 }); 3548 } 3549 3550 $arrs.each(function () { 3551 addEnterUp(this, function (e) { 3552 onArrClick.call(this, e); 3553 }); 3554 addFocusOnControls(this); 3555 }); 3556 3557 addEnterUp(fullscreenIcon, that.toggleFullScreen); 3558 addFocusOnControls(fullscreenIcon); 3559 3560 function reset () { 3561 setData(); 3562 setOptions(); 3563 3564 if (!reset.i) { 3565 reset.i = true; 3566 // Only once 3567 var _startindex = opts.startindex; 3568 if (_startindex || opts.hash && location.hash) { 3569 startIndex = getIndexFromHash(_startindex || location.hash.replace(/^#/, ''), data, that.index === 0 || _startindex, _startindex); 3570 } 3571 activeIndex = repositionIndex = dirtyIndex = lastActiveIndex = startIndex = edgeIndex(startIndex) || 0;/*(o_rtl ? size - 1 : 0)*///; 3572 } 3573 3574 if (size) { 3575 if (changeToRtl()) return; 3576 3577 if ($videoPlaying) { 3578 unloadVideo($videoPlaying, true); 3579 } 3580 3581 activeIndexes = []; 3582 detachFrames(STAGE_FRAME_KEY); 3583 3584 reset.ok = true; 3585 3586 that.show({index: activeIndex, time: 0}); 3587 that.resize(); 3588 } else { 3589 that.destroy(); 3590 } 3591 } 3592 3593 function changeToRtl () { 3594 //////console.log('changeToRtl'); 3595 if (!changeToRtl.f === o_rtl) { 3596 changeToRtl.f = o_rtl; 3597 activeIndex = size - 1 - activeIndex; 3598 //////console.log('changeToRtl execute, activeIndex is', activeIndex); 3599 that.reverse(); 3600 3601 return true; 3602 } 3603 } 3604 3605 $.each('load push pop shift unshift reverse sort splice'.split(' '), function (i, method) { 3606 that[method] = function () { 3607 data = data || []; 3608 if (method !== 'load') { 3609 Array.prototype[method].apply(data, arguments); 3610 } else if (arguments[0] && typeof arguments[0] === 'object' && arguments[0].length) { 3611 data = clone(arguments[0]); 3612 } 3613 reset(); 3614 return that; 3615 } 3616 }); 3617 3618 function ready () { 3619 if (!ready.ok) { 3620 ready.ok = true; 3621 triggerEvent('ready'); 3622 } 3623 } 3624 3625 reset(); 3626}; 3627 3628 3629$.fn.fotorama = function (opts) { 3630 return this.each(function () { 3631 var that = this, 3632 $fotorama = $(this), 3633 fotoramaData = $fotorama.data(), 3634 fotorama = fotoramaData.fotorama; 3635 3636 if (!fotorama) { 3637 waitFor(function () { 3638 return !isHidden(that); 3639 }, function () { 3640 fotoramaData.urtext = $fotorama.html(); 3641 new $.Fotorama($fotorama, 3642 /* Priority for options: 3643 * 1. <div data-loop="true"></div> 3644 * 2. $('div').fotorama({loop: false}) 3645 * 3. Defaults */ 3646 $.extend( 3647 {}, 3648 OPTIONS, 3649 window.fotoramaDefaults, 3650 opts, 3651 fotoramaData 3652 ) 3653 ); 3654 }); 3655 } else { 3656 fotorama.setOptions(opts, true); 3657 } 3658 }); 3659}; 3660$.Fotorama.instances = []; 3661 3662function calculateIndexes () { 3663 $.each($.Fotorama.instances, function (index, instance) { 3664 instance.index = index; 3665 }); 3666} 3667 3668function addInstance (instance) { 3669 $.Fotorama.instances.push(instance); 3670 calculateIndexes(); 3671} 3672 3673function hideInstance (instance) { 3674 $.Fotorama.instances.splice(instance.index, 1); 3675 calculateIndexes(); 3676} 3677$.Fotorama.cache = {}; 3678$.Fotorama.measures = {}; 3679$ = $ || {}; 3680$.Fotorama = $.Fotorama || {}; 3681$.Fotorama.jst = $.Fotorama.jst || {}; 3682 3683$.Fotorama.jst.style = function(v) { 3684var __t, __p = '', __e = _.escape; 3685__p += '.fotorama' + 3686((__t = ( v.s )) == null ? '' : __t) + 3687' .fotorama__nav--thumbs .fotorama__nav__frame{\npadding:' + 3688((__t = ( v.m )) == null ? '' : __t) + 3689'px;\nheight:' + 3690((__t = ( v.h )) == null ? '' : __t) + 3691'px}\n.fotorama' + 3692((__t = ( v.s )) == null ? '' : __t) + 3693' .fotorama__thumb-border{\nheight:' + 3694((__t = ( v.h - v.b * (v.q ? 0 : 2) )) == null ? '' : __t) + 3695'px;\nborder-width:' + 3696((__t = ( v.b )) == null ? '' : __t) + 3697'px;\nmargin-top:' + 3698((__t = ( v.m )) == null ? '' : __t) + 3699'px}'; 3700return __p 3701}; 3702 3703$.Fotorama.jst.video = function(v) { 3704var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 3705function print() { __p += __j.call(arguments, '') } 3706__p += '<div class="fotorama__video"><iframe src="'; 3707 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 : '')) ; 3708__p += '" frameborder="0" allowfullscreen></iframe></div>\n'; 3709return __p 3710}; 3711$(function () { 3712 $('.' + _fotoramaClass + ':not([data-auto="false"])').fotorama(); 3713}); 3714})(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.