vendor: 2,672 bytes, lines 1-111
1/* This is a custom fork of Tiny Slider v2.9.1 2* https://github.com/ganlanyuan/tiny-slider 3* 4* Our customization needs exceed what can be achieved via the native API. 5* 6* FORMAT CHANGELOG: 7* - set `cloneCount` to 0 when the slider is in gallery mode 8*/ 9 10 11var tns = (function (){ 12 var win = window; 13 14 var raf = win.requestAnimationFrame 15 || win.webkitRequestAnimationFrame 16 || win.mozRequestAnimationFrame 17 || win.msRequestAnimationFrame 18 || function(cb) { return setTimeout(cb, 16); }; 19 20 var win$1 = window; 21 22 var caf = win$1.cancelAnimationFrame 23 || win$1.mozCancelAnimationFrame 24 || function(id){ clearTimeout(id); }; 25 26 function extend() { 27 var obj, name, copy, 28 target = arguments[0] || {}, 29 i = 1, 30 length = arguments.length; 31 32 for (; i < length; i++) { 33 if ((obj = arguments[i]) !== null) { 34 for (name in obj) { 35 copy = obj[name]; 36 37 if (target === copy) { 38 continue; 39 } else if (copy !== undefined) { 40 target[name] = copy; 41 } 42 } 43 } 44 } 45 return target; 46 } 47 48 function checkStorageValue (value) { 49 return ['true', 'false'].indexOf(value) >= 0 ? JSON.parse(value) : value; 50 } 51 52 function setLocalStorage(storage, key, value, access) { 53 if (access) { 54 try { storage.setItem(key, value); } catch (e) {} 55 } 56 return value; 57 } 58 59 function getSlideId() { 60 var id = window.tnsId; 61 window.tnsId = !id ? 1 : id + 1; 62 63 return 'tns' + window.tnsId; 64 } 65 66 function getBody () { 67 var doc = document, 68 body = doc.body; 69 70 if (!body) { 71 body = doc.createElement('body'); 72 body.fake = true; 73 } 74 75 return body; 76 } 77 78 var docElement = document.documentElement; 79 80 function setFakeBody (body) { 81 var docOverflow = ''; 82 if (body.fake) { 83 docOverflow = docElement.style.overflow; 84 //avoid crashing IE8, if background image is used 85 body.style.background = ''; 86 //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible 87 body.style.overflow = docElement.style.overflow = 'hidden'; 88 docElement.appendChild(body); 89 } 90 91 return docOverflow; 92 } 93 94 function resetFakeBody (body, docOverflow) { 95 if (body.fake) { 96 body.remove(); 97 docElement.style.overflow = docOverflow; 98 // Trigger layout so kinetic scrolling isn't disabled in iOS6+ 99 // eslint-disable-next-line 100 docElement.offsetHeight; 101 } 102 } 103 104 // get css-calc 105 106 function calc() { 107 var doc = document, 108 body = getBody(), 109 docOverflow = setFakeBody(body), 110 div = doc.createElement('div'), 111 result = false;
112 113 body.appendChild(div); 114 try { 115 var str = '(10px * 10)', 116 vals = ['calc' + str, '-moz-calc' + str, '-webkit-calc' + str], 117 val; 118 for (var i = 0; i < 3; i++) { 119 val = vals[i]; 120 div.style.width = val; 121 if (div.offsetWidth === 100) { 122 result = val.replace(str, ''); 123 break; 124 } 125 } 126 } catch (e) {} 127 128 body.fake ? resetFakeBody(body, docOverflow) : div.remove(); 129 130 return result; 131 } 132 133 // get subpixel support value 134 135 function percentageLayout() { 136 // check subpixel layout supporting 137 var doc = document, 138 body = getBody(), 139 docOverflow = setFakeBody(body), 140 wrapper = doc.createElement('div'), 141 outer = doc.createElement('div'), 142 str = '', 143 count = 70, 144 perPage = 3, 145 supported = false; 146 147 wrapper.className = "tns-t-subp2"; 148 outer.className = "tns-t-ct"; 149 150 for (var i = 0; i < count; i++) { 151 str += '<div></div>'; 152 } 153 154 outer.innerHTML = str; 155 wrapper.appendChild(outer); 156 body.appendChild(wrapper); 157 158 supported = Math.abs(wrapper.getBoundingClientRect().left - outer.children[count - perPage].getBoundingClientRect().left) < 2; 159 160 body.fake ? resetFakeBody(body, docOverflow) : wrapper.remove(); 161 162 return supported; 163 } 164 165 function mediaquerySupport () { 166 var doc = document, 167 body = getBody(), 168 docOverflow = setFakeBody(body), 169 div = doc.createElement('div'), 170 style = doc.createElement('style'), 171 rule = '@media all and (min-width:1px){.tns-mq-test{position:absolute}}', 172 position; 173 174 style.type = 'text/css'; 175 div.className = 'tns-mq-test'; 176 177 body.appendChild(style); 178 body.appendChild(div); 179 180 if (style.styleSheet) { 181 style.styleSheet.cssText = rule; 182 } else { 183 style.appendChild(doc.createTextNode(rule)); 184 } 185 186 position = window.getComputedStyle ? window.getComputedStyle(div).position : div.currentStyle['position']; 187 188 body.fake ? resetFakeBody(body, docOverflow) : div.remove(); 189 190 return position === "absolute"; 191 } 192 193 // create and append style sheet 194 function createStyleSheet (media) { 195 // Create the <style> tag 196 var style = document.createElement("style"); 197 // style.setAttribute("type", "text/css"); 198 199 // Add a media (and/or media query) here if you'd like! 200 // style.setAttribute("media", "screen") 201 // style.setAttribute("media", "only screen and (max-width : 1024px)") 202 if (media) { style.setAttribute("media", media); } 203 204 // WebKit hack :( 205 // style.appendChild(document.createTextNode("")); 206 207 // Add the <style> element to the page 208 document.querySelector('head').appendChild(style); 209 210 return style.sheet ? style.sheet : style.styleSheet; 211 } 212 213 // cross browsers addRule method 214 function addCSSRule(sheet, selector, rules, index) { 215 // return raf(function() { 216 'insertRule' in sheet ? 217 sheet.insertRule(selector + '{' + rules + '}', index) : 218 sheet.addRule(selector, rules, index); 219 // }); 220 } 221 222 // cross browsers addRule method 223 function removeCSSRule(sheet, index) { 224 // return raf(function() { 225 'deleteRule' in sheet ? 226 sheet.deleteRule(index) : 227 sheet.removeRule(index); 228 // }); 229 } 230 231 function getCssRulesLength(sheet) { 232 var rule = ('insertRule' in sheet) ? sheet.cssRules : sheet.rules; 233 return rule.length; 234 } 235 236 function toDegree (y, x) { 237 return Math.atan2(y, x) * (180 / Math.PI); 238 } 239 240 function getTouchDirection(angle, range) { 241 var direction = false, 242 gap = Math.abs(90 - Math.abs(angle)); 243 244 if (gap >= 90 - range) { 245 direction = 'horizontal'; 246 } else if (gap <= range) { 247 direction = 'vertical'; 248 } 249 250 return direction; 251 } 252 253 // https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/ 254 function forEach (arr, callback, scope) { 255 for (var i = 0, l = arr.length; i < l; i++) { 256 callback.call(scope, arr[i], i); 257 } 258 } 259 260 var classListSupport = 'classList' in document.createElement('_'); 261 262 var hasClass = classListSupport ? 263 function (el, str) { return el.classList.contains(str); } : 264 function (el, str) { return el.className.indexOf(str) >= 0; }; 265 266 var addClass = classListSupport ? 267 function (el, str) { 268 if (!hasClass(el, str)) { el.classList.add(str); } 269 } : 270 function (el, str) { 271 if (!hasClass(el, str)) { el.className += ' ' + str; } 272 }; 273 274 var removeClass = classListSupport ? 275 function (el, str) { 276 if (hasClass(el, str)) { el.classList.remove(str); } 277 } : 278 function (el, str) { 279 if (hasClass(el, str)) { el.className = el.className.replace(str, ''); } 280 }; 281 282 function hasAttr(el, attr) { 283 return el.hasAttribute(attr); 284 } 285 286 function getAttr(el, attr) { 287 return el.getAttribute(attr); 288 } 289 290 function isNodeList(el) { 291 // Only NodeList has the "item()" function 292 return typeof el.item !== "undefined"; 293 } 294 295 function setAttrs(els, attrs) { 296 els = (isNodeList(els) || els instanceof Array) ? els : [els]; 297 if (Object.prototype.toString.call(attrs) !== '[object Object]') { return; } 298 299 for (var i = els.length; i--;) { 300 for(var key in attrs) { 301 els[i].setAttribute(key, attrs[key]); 302 } 303 } 304 } 305 306 function removeAttrs(els, attrs) { 307 els = (isNodeList(els) || els instanceof Array) ? els : [els]; 308 attrs = (attrs instanceof Array) ? attrs : [attrs]; 309 310 var attrLength = attrs.length; 311 for (var i = els.length; i--;) { 312 for (var j = attrLength; j--;) { 313 els[i].removeAttribute(attrs[j]); 314 } 315 } 316 } 317 318 function arrayFromNodeList (nl) { 319 var arr = []; 320 for (var i = 0, l = nl.length; i < l; i++) { 321 arr.push(nl[i]); 322 } 323 return arr; 324 } 325 326 function hideElement(el, forceHide) { 327 if (el.style.display !== 'none') { el.style.display = 'none'; } 328 } 329 330 function showElement(el, forceHide) { 331 if (el.style.display === 'none') { el.style.display = ''; } 332 } 333 334 function isVisible(el) { 335 return window.getComputedStyle(el).display !== 'none'; 336 } 337 338 function whichProperty(props){ 339 if (typeof props === 'string') { 340 var arr = [props], 341 Props = props.charAt(0).toUpperCase() + props.substr(1), 342 prefixes = ['Webkit', 'Moz', 'ms', 'O']; 343
vendor: 10,019 bytes, lines 344-636
344 prefixes.forEach(function(prefix) { 345 if (prefix !== 'ms' || props === 'transform') { 346 arr.push(prefix + Props); 347 } 348 }); 349 350 props = arr; 351 } 352 353 var el = document.createElement('fakeelement'), 354 len = props.length; 355 for(var i = 0; i < props.length; i++){ 356 var prop = props[i]; 357 if( el.style[prop] !== undefined ){ return prop; } 358 } 359 360 return false; // explicit for ie9- 361 } 362 363 function has3DTransforms(tf){ 364 if (!tf) { return false; } 365 if (!window.getComputedStyle) { return false; } 366 367 var doc = document, 368 body = getBody(), 369 docOverflow = setFakeBody(body), 370 el = doc.createElement('p'), 371 has3d, 372 cssTF = tf.length > 9 ? '-' + tf.slice(0, -9).toLowerCase() + '-' : ''; 373 374 cssTF += 'transform'; 375 376 // Add it to the body to get the computed style 377 body.insertBefore(el, null); 378 379 el.style[tf] = 'translate3d(1px,1px,1px)'; 380 has3d = window.getComputedStyle(el).getPropertyValue(cssTF); 381 382 body.fake ? resetFakeBody(body, docOverflow) : el.remove(); 383 384 return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); 385 } 386 387 // get transitionend, animationend based on transitionDuration 388 // @propin: string 389 // @propOut: string, first-letter uppercase 390 // Usage: getEndProperty('WebkitTransitionDuration', 'Transition') => webkitTransitionEnd 391 function getEndProperty(propIn, propOut) { 392 var endProp = false; 393 if (/^Webkit/.test(propIn)) { 394 endProp = 'webkit' + propOut + 'End'; 395 } else if (/^O/.test(propIn)) { 396 endProp = 'o' + propOut + 'End'; 397 } else if (propIn) { 398 endProp = propOut.toLowerCase() + 'end'; 399 } 400 return endProp; 401 } 402 403 // Test via a getter in the options object to see if the passive property is accessed 404 var supportsPassive = false; 405 try { 406 var opts = Object.defineProperty({}, 'passive', { 407 get: function() { 408 supportsPassive = true; 409 } 410 }); 411 window.addEventListener("test", null, opts); 412 } catch (e) {} 413 var passiveOption = supportsPassive ? { passive: true } : false; 414 415 function addEvents(el, obj, preventScrolling) { 416 for (var prop in obj) { 417 var option = ['touchstart', 'touchmove'].indexOf(prop) >= 0 && !preventScrolling ? passiveOption : false; 418 el.addEventListener(prop, obj[prop], option); 419 } 420 } 421 422 function removeEvents(el, obj) { 423 for (var prop in obj) { 424 var option = ['touchstart', 'touchmove'].indexOf(prop) >= 0 ? passiveOption : false; 425 el.removeEventListener(prop, obj[prop], option); 426 } 427 } 428 429 function Events() { 430 return { 431 topics: {}, 432 on: function (eventName, fn) { 433 this.topics[eventName] = this.topics[eventName] || []; 434 this.topics[eventName].push(fn); 435 }, 436 off: function(eventName, fn) { 437 if (this.topics[eventName]) { 438 for (var i = 0; i < this.topics[eventName].length; i++) { 439 if (this.topics[eventName][i] === fn) { 440 this.topics[eventName].splice(i, 1); 441 break; 442 } 443 } 444 } 445 }, 446 emit: function (eventName, data) { 447 data.type = eventName; 448 if (this.topics[eventName]) { 449 this.topics[eventName].forEach(function(fn) { 450 fn(data, eventName); 451 }); 452 } 453 } 454 }; 455 } 456 457 function jsTransform(element, attr, prefix, postfix, to, duration, callback) { 458 var tick = Math.min(duration, 10), 459 unit = (to.indexOf('%') >= 0) ? '%' : 'px', 460 to = to.replace(unit, ''), 461 from = Number(element.style[attr].replace(prefix, '').replace(postfix, '').replace(unit, '')), 462 positionTick = (to - from) / duration * tick, 463 running; 464 465 setTimeout(moveElement, tick); 466 function moveElement() { 467 duration -= tick; 468 from += positionTick; 469 element.style[attr] = prefix + from + unit + postfix; 470 if (duration > 0) { 471 setTimeout(moveElement, tick); 472 } else { 473 callback(); 474 } 475 } 476 } 477 478 // Object.keys 479 if (!Object.keys) { 480 Object.keys = function(object) { 481 var keys = []; 482 for (var name in object) { 483 if (Object.prototype.hasOwnProperty.call(object, name)) { 484 keys.push(name); 485 } 486 } 487 return keys; 488 }; 489 } 490 491 // ChildNode.remove 492 if(!("remove" in Element.prototype)){ 493 Element.prototype.remove = function(){ 494 if(this.parentNode) { 495 this.parentNode.removeChild(this); 496 } 497 }; 498 } 499 500 var tns = function(options) { 501 options = extend({ 502 container: '.slider', 503 mode: 'carousel', 504 axis: 'horizontal', 505 items: 1, 506 gutter: 0, 507 edgePadding: 0, 508 fixedWidth: false, 509 autoWidth: false, 510 viewportMax: false, 511 slideBy: 1, 512 center: false, 513 controls: true, 514 controlsPosition: 'top', 515 controlsText: ['prev', 'next'], 516 controlsContainer: false, 517 prevButton: false, 518 nextButton: false, 519 nav: true, 520 navPosition: 'top', 521 navContainer: false, 522 navAsThumbnails: false, 523 arrowKeys: false, 524 speed: 300, 525 autoplay: false, 526 autoplayPosition: 'top', 527 autoplayTimeout: 5000, 528 autoplayDirection: 'forward', 529 autoplayText: ['start', 'stop'], 530 autoplayHoverPause: false, 531 autoplayButton: false, 532 autoplayButtonOutput: true, 533 autoplayResetOnVisibility: true, 534 animateIn: 'tns-fadeIn', 535 animateOut: 'tns-fadeOut', 536 animateNormal: 'tns-normal', 537 animateDelay: false, 538 loop: true, 539 rewind: false, 540 autoHeight: false, 541 responsive: false, 542 lazyload: false, 543 lazyloadSelector: '.tns-lazy-img', 544 touch: true, 545 mouseDrag: false, 546 swipeAngle: 15, 547 nested: false, 548 preventActionWhenRunning: false, 549 preventScrollOnTouch: false, 550 freezable: true, 551 onInit: false, 552 useLocalStorage: true 553 }, options || {}); 554 555 var doc = document, 556 win = window, 557 KEYS = { 558 ENTER: 13, 559 SPACE: 32, 560 LEFT: 37, 561 RIGHT: 39 562 }, 563 tnsStorage = {}, 564 localStorageAccess = options.useLocalStorage; 565 566 if (localStorageAccess) { 567 // check browser version and local storage access 568 var browserInfo = navigator.userAgent; 569 var uid = new Date; 570 571 try { 572 tnsStorage = win.localStorage; 573 if (tnsStorage) { 574 tnsStorage.setItem(uid, uid); 575 localStorageAccess = tnsStorage.getItem(uid) == uid; 576 tnsStorage.removeItem(uid); 577 } else { 578 localStorageAccess = false; 579 } 580 if (!localStorageAccess) { tnsStorage = {}; } 581 } catch(e) { 582 localStorageAccess = false; 583 } 584 585 if (localStorageAccess) { 586 // remove storage when browser version changes 587 if (tnsStorage['tnsApp'] && tnsStorage['tnsApp'] !== browserInfo) { 588 ['tC', 'tPL', 'tMQ', 'tTf', 't3D', 'tTDu', 'tTDe', 'tADu', 'tADe', 'tTE', 'tAE'].forEach(function(item) { tnsStorage.removeItem(item); }); 589 } 590 // update browserInfo 591 localStorage['tnsApp'] = browserInfo; 592 } 593 } 594 595 var CALC = tnsStorage['tC'] ? checkStorageValue(tnsStorage['tC']) : setLocalStorage(tnsStorage, 'tC', calc(), localStorageAccess), 596 PERCENTAGELAYOUT = tnsStorage['tPL'] ? checkStorageValue(tnsStorage['tPL']) : setLocalStorage(tnsStorage, 'tPL', percentageLayout(), localStorageAccess), 597 CSSMQ = tnsStorage['tMQ'] ? checkStorageValue(tnsStorage['tMQ']) : setLocalStorage(tnsStorage, 'tMQ', mediaquerySupport(), localStorageAccess), 598 TRANSFORM = tnsStorage['tTf'] ? checkStorageValue(tnsStorage['tTf']) : setLocalStorage(tnsStorage, 'tTf', whichProperty('transform'), localStorageAccess), 599 HAS3DTRANSFORMS = tnsStorage['t3D'] ? checkStorageValue(tnsStorage['t3D']) : setLocalStorage(tnsStorage, 't3D', has3DTransforms(TRANSFORM), localStorageAccess), 600 TRANSITIONDURATION = tnsStorage['tTDu'] ? checkStorageValue(tnsStorage['tTDu']) : setLocalStorage(tnsStorage, 'tTDu', whichProperty('transitionDuration'), localStorageAccess), 601 TRANSITIONDELAY = tnsStorage['tTDe'] ? checkStorageValue(tnsStorage['tTDe']) : setLocalStorage(tnsStorage, 'tTDe', whichProperty('transitionDelay'), localStorageAccess), 602 ANIMATIONDURATION = tnsStorage['tADu'] ? checkStorageValue(tnsStorage['tADu']) : setLocalStorage(tnsStorage, 'tADu', whichProperty('animationDuration'), localStorageAccess), 603 ANIMATIONDELAY = tnsStorage['tADe'] ? checkStorageValue(tnsStorage['tADe']) : setLocalStorage(tnsStorage, 'tADe', whichProperty('animationDelay'), localStorageAccess), 604 TRANSITIONEND = tnsStorage['tTE'] ? checkStorageValue(tnsStorage['tTE']) : setLocalStorage(tnsStorage, 'tTE', getEndProperty(TRANSITIONDURATION, 'Transition'), localStorageAccess), 605 ANIMATIONEND = tnsStorage['tAE'] ? checkStorageValue(tnsStorage['tAE']) : setLocalStorage(tnsStorage, 'tAE', getEndProperty(ANIMATIONDURATION, 'Animation'), localStorageAccess); 606 607 // get element nodes from selectors 608 var supportConsoleWarn = win.console && typeof win.console.warn === "function", 609 tnsList = ['container', 'controlsContainer', 'prevButton', 'nextButton', 'navContainer', 'autoplayButton'], 610 optionsElements = {}; 611 612 tnsList.forEach(function(item) { 613 if (typeof options[item] === 'string') { 614 var str = options[item], 615 el = doc.querySelector(str); 616 optionsElements[item] = str; 617 618 if (el && el.nodeName) { 619 options[item] = el; 620 } else { 621 if (supportConsoleWarn) { console.warn('Can\'t find', options[item]); } 622 return; 623 } 624 } 625 }); 626 627 // make sure at least 1 slide 628 if (options.container.children.length < 1) { 629 if (supportConsoleWarn) { console.warn('No slides found in', options.container); } 630 return; 631 } 632 633 // update options 634 var responsive = options.responsive, 635 nested = options.nested, 636 carousel = options.mode === 'carousel' ? true : false;
637 638 if (responsive) { 639 // apply responsive[0] to options and remove it 640 if (0 in responsive) { 641 options = extend(options, responsive[0]); 642 delete responsive[0]; 643 } 644 645 var responsiveTem = {}; 646 for (var key in responsive) { 647 var val = responsive[key]; 648 // update responsive 649 // from: 300: 2 650 // to: 651 // 300: { 652 // items: 2 653 // } 654 val = typeof val === 'number' ? {items: val} : val; 655 responsiveTem[key] = val; 656 } 657 responsive = responsiveTem; 658 responsiveTem = null; 659 } 660 661 // update options 662 function updateOptions (obj) { 663 for (var key in obj) { 664 if (!carousel) { 665 if (key === 'slideBy') { obj[key] = 'page'; } 666 if (key === 'edgePadding') { obj[key] = false; } 667 if (key === 'autoHeight') { obj[key] = false; } 668 } 669 670 // update responsive options 671 if (key === 'responsive') { updateOptions(obj[key]); } 672 } 673 } 674 if (!carousel) { updateOptions(options); } 675 676 677 // === define and set variables === 678 if (!carousel) { 679 options.axis = 'horizontal'; 680 options.slideBy = 'page'; 681 options.edgePadding = false; 682 683 var animateIn = options.animateIn, 684 animateOut = options.animateOut, 685 animateDelay = options.animateDelay, 686 animateNormal = options.animateNormal; 687 } 688 689 var horizontal = options.axis === 'horizontal' ? true : false, 690 outerWrapper = doc.createElement('div'), 691 innerWrapper = doc.createElement('div'), 692 middleWrapper, 693 container = options.container, 694 containerParent = container.parentNode, 695 containerHTML = container.outerHTML, 696 slideItems = container.children, 697 slideCount = slideItems.length, 698 breakpointZone, 699 windowWidth = getWindowWidth(), 700 isOn = false; 701 if (responsive) { setBreakpointZone(); } 702 if (carousel) { container.className += ' tns-vpfix'; } 703 704 // fixedWidth: viewport > rightBoundary > indexMax 705 var autoWidth = options.autoWidth, 706 fixedWidth = getOption('fixedWidth'), 707 edgePadding = getOption('edgePadding'), 708 gutter = getOption('gutter'), 709 viewport = getViewportWidth(), 710 center = getOption('center'), 711 items = !autoWidth ? Math.floor(getOption('items')) : 1, 712 slideBy = getOption('slideBy'), 713 viewportMax = options.viewportMax || options.fixedWidthViewportWidth, 714 arrowKeys = getOption('arrowKeys'), 715 speed = getOption('speed'), 716 rewind = options.rewind, 717 loop = rewind ? false : options.loop, 718 autoHeight = getOption('autoHeight'), 719 controls = getOption('controls'), 720 controlsText = getOption('controlsText'), 721 nav = getOption('nav'), 722 touch = getOption('touch'), 723 mouseDrag = getOption('mouseDrag'), 724 autoplay = getOption('autoplay'), 725 autoplayTimeout = getOption('autoplayTimeout'), 726 autoplayText = getOption('autoplayText'), 727 autoplayHoverPause = getOption('autoplayHoverPause'), 728 autoplayResetOnVisibility = getOption('autoplayResetOnVisibility'), 729 sheet = createStyleSheet(), 730 lazyload = options.lazyload, 731 lazyloadSelector = options.lazyloadSelector, 732 slidePositions, // collection of slide positions 733 slideItemsOut = [], 734 cloneCount = loop && carousel ? getCloneCountForLoop() : 0, 735 slideCountNew = !carousel ? slideCount + cloneCount : slideCount + cloneCount * 2, 736 hasRightDeadZone = (fixedWidth || autoWidth) && !loop ? true : false, 737 rightBoundary = fixedWidth ? getRightBoundary() : null, 738 updateIndexBeforeTransform = (!carousel || !loop) ? true : false, 739 // transform 740 transformAttr = horizontal ? 'left' : 'top', 741 transformPrefix = '', 742 transformPostfix = '', 743 // index 744 getIndexMax = (function () { 745 if (fixedWidth) { 746 return function() { return center && !loop ? slideCount - 1 : Math.ceil(- rightBoundary / (fixedWidth + gutter)); }; 747 } else if (autoWidth) { 748 return function() { 749 for (var i = slideCountNew; i--;) { 750 if (slidePositions[i] >= - rightBoundary) { return i; } 751 } 752 }; 753 } else { 754 return function() { 755 if (center && carousel && !loop) { 756 return slideCount - 1; 757 } else { 758 return loop || carousel ? Math.max(0, slideCountNew - Math.ceil(items)) : slideCountNew - 1; 759 } 760 }; 761 } 762 })(), 763 index = getStartIndex(getOption('startIndex')), 764 indexCached = index, 765 displayIndex = getCurrentSlide(), 766 indexMin = 0, 767 indexMax = !autoWidth ? getIndexMax() : null, 768 // resize 769 resizeTimer, 770 preventActionWhenRunning = options.preventActionWhenRunning, 771 swipeAngle = options.swipeAngle, 772 moveDirectionExpected = swipeAngle ? '?' : true, 773 running = false, 774 onInit = options.onInit, 775 events = new Events(), 776 // id, class
vendor: 21,861 bytes, lines 777-1412
777 newContainerClasses = ' tns-slider tns-' + options.mode, 778 slideId = container.id || getSlideId(), 779 disable = getOption('disable'), 780 disabled = false, 781 freezable = options.freezable, 782 freeze = freezable && !autoWidth ? getFreeze() : false, 783 frozen = false, 784 controlsEvents = { 785 'click': onControlsClick, 786 'keydown': onControlsKeydown 787 }, 788 navEvents = { 789 'click': onNavClick, 790 'keydown': onNavKeydown 791 }, 792 hoverEvents = { 793 'mouseover': mouseoverPause, 794 'mouseout': mouseoutRestart 795 }, 796 visibilityEvent = {'visibilitychange': onVisibilityChange}, 797 docmentKeydownEvent = {'keydown': onDocumentKeydown}, 798 touchEvents = { 799 'touchstart': onPanStart, 800 'touchmove': onPanMove, 801 'touchend': onPanEnd, 802 'touchcancel': onPanEnd 803 }, dragEvents = { 804 'mousedown': onPanStart, 805 'mousemove': onPanMove, 806 'mouseup': onPanEnd, 807 'mouseleave': onPanEnd 808 }, 809 hasControls = hasOption('controls'), 810 hasNav = hasOption('nav'), 811 navAsThumbnails = autoWidth ? true : options.navAsThumbnails, 812 hasAutoplay = hasOption('autoplay'), 813 hasTouch = hasOption('touch'), 814 hasMouseDrag = hasOption('mouseDrag'), 815 slideActiveClass = 'tns-slide-active', 816 imgCompleteClass = 'tns-complete', 817 imgEvents = { 818 'load': onImgLoaded, 819 'error': onImgFailed 820 }, 821 imgsComplete, 822 liveregionCurrent, 823 preventScroll = options.preventScrollOnTouch === 'force' ? true : false; 824 825 // controls 826 if (hasControls) { 827 var controlsContainer = options.controlsContainer, 828 controlsContainerHTML = options.controlsContainer ? options.controlsContainer.outerHTML : '', 829 prevButton = options.prevButton, 830 nextButton = options.nextButton, 831 prevButtonHTML = options.prevButton ? options.prevButton.outerHTML : '', 832 nextButtonHTML = options.nextButton ? options.nextButton.outerHTML : '', 833 prevIsButton, 834 nextIsButton; 835 } 836 837 // nav 838 if (hasNav) { 839 var navContainer = options.navContainer, 840 navContainerHTML = options.navContainer ? options.navContainer.outerHTML : '', 841 navItems, 842 pages = autoWidth ? slideCount : getPages(), 843 pagesCached = 0, 844 navClicked = -1, 845 navCurrentIndex = getCurrentNavIndex(), 846 navCurrentIndexCached = navCurrentIndex, 847 navActiveClass = 'tns-nav-active', 848 navStr = 'Carousel Page ', 849 navStrCurrent = ' (Current Slide)'; 850 } 851 852 // autoplay 853 if (hasAutoplay) { 854 var autoplayDirection = options.autoplayDirection === 'forward' ? 1 : -1, 855 autoplayButton = options.autoplayButton, 856 autoplayButtonHTML = options.autoplayButton ? options.autoplayButton.outerHTML : '', 857 autoplayHtmlStrings = ['<span class=\'tns-visually-hidden\'>', ' animation</span>'], 858 autoplayTimer, 859 animating, 860 autoplayHoverPaused, 861 autoplayUserPaused, 862 autoplayVisibilityPaused; 863 } 864 865 if (hasTouch || hasMouseDrag) { 866 var initPosition = {}, 867 lastPosition = {}, 868 translateInit, 869 disX, 870 disY, 871 panStart = false, 872 rafIndex, 873 getDist = horizontal ? 874 function(a, b) { return a.x - b.x; } : 875 function(a, b) { return a.y - b.y; }; 876 } 877 878 // disable slider when slidecount <= items 879 if (!autoWidth) { resetVariblesWhenDisable(disable || freeze); } 880 881 if (TRANSFORM) { 882 transformAttr = TRANSFORM; 883 transformPrefix = 'translate'; 884 885 if (HAS3DTRANSFORMS) { 886 transformPrefix += horizontal ? '3d(' : '3d(0px, '; 887 transformPostfix = horizontal ? ', 0px, 0px)' : ', 0px)'; 888 } else { 889 transformPrefix += horizontal ? 'X(' : 'Y('; 890 transformPostfix = ')'; 891 } 892 893 } 894 895 if (carousel) { container.className = container.className.replace('tns-vpfix', ''); } 896 initStructure(); 897 initSheet(); 898 initSliderTransform(); 899 900 // === COMMON FUNCTIONS === // 901 function resetVariblesWhenDisable (condition) { 902 if (condition) { 903 controls = nav = touch = mouseDrag = arrowKeys = autoplay = autoplayHoverPause = autoplayResetOnVisibility = false; 904 } 905 } 906 907 function getCurrentSlide () { 908 var tem = carousel ? index - cloneCount : index; 909 while (tem < 0) { tem += slideCount; } 910 return tem%slideCount + 1; 911 } 912 913 function getStartIndex (ind) { 914 ind = ind ? Math.max(0, Math.min(loop ? slideCount - 1 : slideCount - items, ind)) : 0; 915 return carousel ? ind + cloneCount : ind; 916 } 917 918 function getAbsIndex (i) { 919 if (i == null) { i = index; } 920 921 if (carousel) { i -= cloneCount; } 922 while (i < 0) { i += slideCount; } 923 924 return Math.floor(i%slideCount); 925 } 926 927 function getCurrentNavIndex () { 928 var absIndex = getAbsIndex(), 929 result; 930 931 result = navAsThumbnails ? absIndex : 932 fixedWidth || autoWidth ? Math.ceil((absIndex + 1) * pages / slideCount - 1) : 933 Math.floor(absIndex / items); 934 935 // set active nav to the last one when reaches the right edge 936 if (!loop && carousel && index === indexMax) { result = pages - 1; } 937 938 return result; 939 } 940 941 function getItemsMax () { 942 // fixedWidth or autoWidth while viewportMax is not available 943 if (autoWidth || (fixedWidth && !viewportMax)) { 944 return slideCount - 1; 945 // most cases 946 } else { 947 var str = fixedWidth ? 'fixedWidth' : 'items', 948 arr = []; 949 950 if (fixedWidth || options[str] < slideCount) { arr.push(options[str]); } 951 952 if (responsive) { 953 for (var bp in responsive) { 954 var tem = responsive[bp][str]; 955 if (tem && (fixedWidth || tem < slideCount)) { arr.push(tem); } 956 } 957 } 958 959 if (!arr.length) { arr.push(0); } 960 961 return Math.ceil(fixedWidth ? viewportMax / Math.min.apply(null, arr) : Math.max.apply(null, arr)); 962 } 963 } 964 965 function getCloneCountForLoop () { 966 var itemsMax = getItemsMax(), 967 result = carousel ? Math.ceil((itemsMax * 5 - slideCount)/2) : (itemsMax * 4 - slideCount); 968 result = Math.max(itemsMax, result); 969 970 return hasOption('edgePadding') ? result + 1 : result; 971 } 972 973 function getWindowWidth () { 974 return win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth; 975 } 976 977 function getInsertPosition (pos) { 978 return pos === 'top' ? 'afterbegin' : 'beforeend'; 979 } 980 981 function getClientWidth (el) { 982 if (el == null) { return; } 983 var div = doc.createElement('div'), rect, width; 984 el.appendChild(div); 985 rect = div.getBoundingClientRect(); 986 width = rect.right - rect.left; 987 div.remove(); 988 return width || getClientWidth(el.parentNode); 989 } 990 991 function getViewportWidth () { 992 var gap = edgePadding ? edgePadding * 2 - gutter : 0; 993 return getClientWidth(containerParent) - gap; 994 } 995 996 function hasOption (item) { 997 if (options[item]) { 998 return true; 999 } else { 1000 if (responsive) { 1001 for (var bp in responsive) { 1002 if (responsive[bp][item]) { return true; } 1003 } 1004 } 1005 return false; 1006 } 1007 } 1008 1009 // get option: 1010 // fixed width: viewport, fixedWidth, gutter => items 1011 // others: window width => all variables 1012 // all: items => slideBy 1013 function getOption (item, ww) { 1014 if (ww == null) { ww = windowWidth; } 1015 1016 if (item === 'items' && fixedWidth) { 1017 return Math.floor((viewport + gutter) / (fixedWidth + gutter)) || 1; 1018 1019 } else { 1020 var result = options[item]; 1021 1022 if (responsive) { 1023 for (var bp in responsive) { 1024 // bp: convert string to number 1025 if (ww >= parseInt(bp)) { 1026 if (item in responsive[bp]) { result = responsive[bp][item]; } 1027 } 1028 } 1029 } 1030 1031 if (item === 'slideBy' && result === 'page') { result = getOption('items'); } 1032 if (!carousel && (item === 'slideBy' || item === 'items')) { result = Math.floor(result); } 1033 1034 return result; 1035 } 1036 } 1037 1038 function getSlideMarginLeft (i) { 1039 return CALC ? 1040 CALC + '(' + i * 100 + '% / ' + slideCountNew + ')' : 1041 i * 100 / slideCountNew + '%'; 1042 } 1043 1044 function getInnerWrapperStyles (edgePaddingTem, gutterTem, fixedWidthTem, speedTem, autoHeightBP) { 1045 var str = ''; 1046 1047 if (edgePaddingTem !== undefined) { 1048 var gap = edgePaddingTem; 1049 if (gutterTem) { gap -= gutterTem; } 1050 str = horizontal ? 1051 'margin: 0 ' + gap + 'px 0 ' + edgePaddingTem + 'px;' : 1052 'margin: ' + edgePaddingTem + 'px 0 ' + gap + 'px 0;'; 1053 } else if (gutterTem && !fixedWidthTem) { 1054 var gutterTemUnit = '-' + gutterTem + 'px', 1055 dir = horizontal ? gutterTemUnit + ' 0 0' : '0 ' + gutterTemUnit + ' 0'; 1056 str = 'margin: 0 ' + dir + ';'; 1057 } 1058 1059 if (!carousel && autoHeightBP && TRANSITIONDURATION && speedTem) { str += getTransitionDurationStyle(speedTem); } 1060 return str; 1061 } 1062 1063 function getContainerWidth (fixedWidthTem, gutterTem, itemsTem) { 1064 if (fixedWidthTem) { 1065 return (fixedWidthTem + gutterTem) * slideCountNew + 'px'; 1066 } else { 1067 return CALC ? 1068 CALC + '(' + slideCountNew * 100 + '% / ' + itemsTem + ')' : 1069 slideCountNew * 100 / itemsTem + '%'; 1070 } 1071 } 1072 1073 function getSlideWidthStyle (fixedWidthTem, gutterTem, itemsTem) { 1074 var width; 1075 1076 if (fixedWidthTem) { 1077 width = (fixedWidthTem + gutterTem) + 'px'; 1078 } else { 1079 if (!carousel) { itemsTem = Math.floor(itemsTem); } 1080 var dividend = carousel ? slideCountNew : itemsTem; 1081 width = CALC ? 1082 CALC + '(100% / ' + dividend + ')' : 1083 100 / dividend + '%'; 1084 } 1085 1086 width = 'width:' + width; 1087 1088 // inner slider: overwrite outer slider styles 1089 return nested !== 'inner' ? width + ';' : width + ' !important;'; 1090 } 1091 1092 function getSlideGutterStyle (gutterTem) { 1093 var str = ''; 1094 1095 // gutter maybe interger || 0 1096 // so can't use 'if (gutter)' 1097 if (gutterTem !== false) { 1098 var prop = horizontal ? 'padding-' : 'margin-', 1099 dir = horizontal ? 'right' : 'bottom'; 1100 str = prop + dir + ': ' + gutterTem + 'px;'; 1101 } 1102 1103 return str; 1104 } 1105 1106 function getCSSPrefix (name, num) { 1107 var prefix = name.substring(0, name.length - num).toLowerCase(); 1108 if (prefix) { prefix = '-' + prefix + '-'; } 1109 1110 return prefix; 1111 } 1112 1113 function getTransitionDurationStyle (speed) { 1114 return getCSSPrefix(TRANSITIONDURATION, 18) + 'transition-duration:' + speed / 1000 + 's;'; 1115 } 1116 1117 function getAnimationDurationStyle (speed) { 1118 return getCSSPrefix(ANIMATIONDURATION, 17) + 'animation-duration:' + speed / 1000 + 's;'; 1119 } 1120 1121 function initStructure () { 1122 var classOuter = 'tns-outer', 1123 classInner = 'tns-inner', 1124 hasGutter = hasOption('gutter'); 1125 1126 outerWrapper.className = classOuter; 1127 innerWrapper.className = classInner; 1128 outerWrapper.id = slideId + '-ow'; 1129 innerWrapper.id = slideId + '-iw'; 1130 1131 // set container properties 1132 if (container.id === '') { container.id = slideId; } 1133 newContainerClasses += PERCENTAGELAYOUT || autoWidth ? ' tns-subpixel' : ' tns-no-subpixel'; 1134 newContainerClasses += CALC ? ' tns-calc' : ' tns-no-calc'; 1135 if (autoWidth) { newContainerClasses += ' tns-autowidth'; } 1136 newContainerClasses += ' tns-' + options.axis; 1137 container.className += newContainerClasses; 1138 1139 // add constrain layer for carousel 1140 if (carousel) { 1141 middleWrapper = doc.createElement('div'); 1142 middleWrapper.id = slideId + '-mw'; 1143 middleWrapper.className = 'tns-ovh'; 1144 1145 outerWrapper.appendChild(middleWrapper); 1146 middleWrapper.appendChild(innerWrapper); 1147 } else { 1148 outerWrapper.appendChild(innerWrapper); 1149 } 1150 1151 if (autoHeight) { 1152 var wp = middleWrapper ? middleWrapper : innerWrapper; 1153 wp.className += ' tns-ah'; 1154 } 1155 1156 containerParent.insertBefore(outerWrapper, container); 1157 innerWrapper.appendChild(container); 1158 1159 // add id, class, aria attributes 1160 // before clone slides 1161 forEach(slideItems, function(item, i) { 1162 addClass(item, 'tns-item'); 1163 if (!item.id) { item.id = slideId + '-item' + i; } 1164 if (!carousel && animateNormal) { addClass(item, animateNormal); } 1165 setAttrs(item, { 1166 'aria-hidden': 'true', 1167 'tabindex': '-1' 1168 }); 1169 }); 1170 1171 // ## clone slides 1172 // carousel: n + slides + n 1173 // gallery: slides + n 1174 if (cloneCount) { 1175 var fragmentBefore = doc.createDocumentFragment(), 1176 fragmentAfter = doc.createDocumentFragment(); 1177 1178 for (var j = cloneCount; j--;) { 1179 var num = j%slideCount, 1180 cloneFirst = slideItems[num].cloneNode(true); 1181 removeAttrs(cloneFirst, 'id'); 1182 fragmentAfter.insertBefore(cloneFirst, fragmentAfter.firstChild); 1183 1184 if (carousel) { 1185 var cloneLast = slideItems[slideCount - 1 - num].cloneNode(true); 1186 removeAttrs(cloneLast, 'id'); 1187 fragmentBefore.appendChild(cloneLast); 1188 } 1189 } 1190 1191 container.insertBefore(fragmentBefore, container.firstChild); 1192 container.appendChild(fragmentAfter); 1193 slideItems = container.children; 1194 } 1195 1196 } 1197 1198 function initSliderTransform () { 1199 // ## images loaded/failed 1200 if (hasOption('autoHeight') || autoWidth || !horizontal) { 1201 var imgs = container.querySelectorAll('img'); 1202 1203 // add img load event listener 1204 forEach(imgs, function(img) { 1205 var src = img.src; 1206 1207 if (!lazyload) { 1208 // not data img 1209 if (src && src.indexOf('data:image') < 0) { 1210 img.src = ''; 1211 addEvents(img, imgEvents); 1212 addClass(img, 'loading'); 1213 1214 img.src = src; 1215 // data img 1216 } else { 1217 imgLoaded(img); 1218 } 1219 } 1220 }); 1221 1222 // set imgsComplete 1223 raf(function(){ imgsLoadedCheck(arrayFromNodeList(imgs), function() { imgsComplete = true; }); }); 1224 1225 // reset imgs for auto height: check visible imgs only 1226 if (hasOption('autoHeight')) { imgs = getImageArray(index, Math.min(index + items - 1, slideCountNew - 1)); } 1227 1228 lazyload ? initSliderTransformStyleCheck() : raf(function(){ imgsLoadedCheck(arrayFromNodeList(imgs), initSliderTransformStyleCheck); }); 1229 1230 } else { 1231 // set container transform property 1232 if (carousel) { doContainerTransformSilent(); } 1233 1234 // update slider tools and events 1235 initTools(); 1236 initEvents(); 1237 } 1238 } 1239 1240 function initSliderTransformStyleCheck () { 1241 if (autoWidth) { 1242 // check styles application 1243 var num = loop ? index : slideCount - 1; 1244 1245 (function stylesApplicationCheck() { 1246 slideItems[num - 1].getBoundingClientRect().right.toFixed(2) === slideItems[num].getBoundingClientRect().left.toFixed(2) ? 1247 initSliderTransformCore() : 1248 setTimeout(function(){ stylesApplicationCheck(); }, 16); 1249 })(); 1250 1251 } else { 1252 initSliderTransformCore(); 1253 } 1254 } 1255 1256 1257 function initSliderTransformCore () { 1258 // run Fn()s which are rely on image loading 1259 if (!horizontal || autoWidth) { 1260 setSlidePositions(); 1261 1262 if (autoWidth) { 1263 rightBoundary = getRightBoundary(); 1264 if (freezable) { freeze = getFreeze(); } 1265 indexMax = getIndexMax(); // <= slidePositions, rightBoundary <= 1266 resetVariblesWhenDisable(disable || freeze); 1267 } else { 1268 updateContentWrapperHeight(); 1269 } 1270 } 1271 1272 // set container transform property 1273 if (carousel) { doContainerTransformSilent(); } 1274 1275 // update slider tools and events 1276 initTools(); 1277 initEvents(); 1278 } 1279 1280 function initSheet () { 1281 // gallery: 1282 // set animation classes and left value for gallery slider 1283 if (!carousel) { 1284 for (var i = index, l = index + Math.min(slideCount, items); i < l; i++) { 1285 var item = slideItems[i]; 1286 item.style.left = (i - index) * 100 / items + '%'; 1287 addClass(item, animateIn); 1288 removeClass(item, animateNormal); 1289 } 1290 } 1291 1292 // #### LAYOUT 1293 1294 // ## INLINE-BLOCK VS FLOAT 1295 1296 // ## PercentageLayout: 1297 // slides: inline-block 1298 // remove blank space between slides by set font-size: 0 1299 1300 // ## Non PercentageLayout: 1301 // slides: float 1302 // margin-right: -100% 1303 // margin-left: ~ 1304 1305 // Resource: https://docs.google.com/spreadsheets/d/147up245wwTXeQYve3BRSAD4oVcvQmuGsFteJOeA5xNQ/edit?usp=sharing 1306 if (horizontal) { 1307 if (PERCENTAGELAYOUT || autoWidth) { 1308 addCSSRule(sheet, '#' + slideId + ' > .tns-item', 'font-size:' + win.getComputedStyle(slideItems[0]).fontSize + ';', getCssRulesLength(sheet)); 1309 addCSSRule(sheet, '#' + slideId, 'font-size:0;', getCssRulesLength(sheet)); 1310 } else if (carousel) { 1311 forEach(slideItems, function (slide, i) { 1312 slide.style.marginLeft = getSlideMarginLeft(i); 1313 }); 1314 } 1315 } 1316 1317 1318 // ## BASIC STYLES 1319 if (CSSMQ) { 1320 // middle wrapper style 1321 if (TRANSITIONDURATION) { 1322 var str = middleWrapper && options.autoHeight ? getTransitionDurationStyle(options.speed) : ''; 1323 addCSSRule(sheet, '#' + slideId + '-mw', str, getCssRulesLength(sheet)); 1324 } 1325 1326 // inner wrapper styles 1327 str = getInnerWrapperStyles(options.edgePadding, options.gutter, options.fixedWidth, options.speed, options.autoHeight); 1328 addCSSRule(sheet, '#' + slideId + '-iw', str, getCssRulesLength(sheet)); 1329 1330 // container styles 1331 if (carousel) { 1332 str = horizontal && !autoWidth ? 'width:' + getContainerWidth(options.fixedWidth, options.gutter, options.items) + ';' : ''; 1333 if (TRANSITIONDURATION) { str += getTransitionDurationStyle(speed); } 1334 addCSSRule(sheet, '#' + slideId, str, getCssRulesLength(sheet)); 1335 } 1336 1337 // slide styles 1338 str = horizontal && !autoWidth ? getSlideWidthStyle(options.fixedWidth, options.gutter, options.items) : ''; 1339 if (options.gutter) { str += getSlideGutterStyle(options.gutter); } 1340 // set gallery items transition-duration 1341 if (!carousel) { 1342 if (TRANSITIONDURATION) { str += getTransitionDurationStyle(speed); } 1343 if (ANIMATIONDURATION) { str += getAnimationDurationStyle(speed); } 1344 } 1345 if (str) { addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet)); } 1346 1347 // non CSS mediaqueries: IE8 1348 // ## update inner wrapper, container, slides if needed 1349 // set inline styles for inner wrapper & container 1350 // insert stylesheet (one line) for slides only (since slides are many) 1351 } else { 1352 // middle wrapper styles 1353 update_carousel_transition_duration(); 1354 1355 // inner wrapper styles 1356 innerWrapper.style.cssText = getInnerWrapperStyles(edgePadding, gutter, fixedWidth, autoHeight); 1357 1358 // container styles 1359 if (carousel && horizontal && !autoWidth) { 1360 container.style.width = getContainerWidth(fixedWidth, gutter, items); 1361 } 1362 1363 // slide styles 1364 var str = horizontal && !autoWidth ? getSlideWidthStyle(fixedWidth, gutter, items) : ''; 1365 if (gutter) { str += getSlideGutterStyle(gutter); } 1366 1367 // append to the last line 1368 if (str) { addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet)); } 1369 } 1370 1371 // ## MEDIAQUERIES 1372 if (responsive && CSSMQ) { 1373 for (var bp in responsive) { 1374 // bp: convert string to number 1375 bp = parseInt(bp); 1376 1377 var opts = responsive[bp], 1378 str = '', 1379 middleWrapperStr = '', 1380 innerWrapperStr = '', 1381 containerStr = '', 1382 slideStr = '', 1383 itemsBP = !autoWidth ? getOption('items', bp) : null, 1384 fixedWidthBP = getOption('fixedWidth', bp), 1385 speedBP = getOption('speed', bp), 1386 edgePaddingBP = getOption('edgePadding', bp), 1387 autoHeightBP = getOption('autoHeight', bp), 1388 gutterBP = getOption('gutter', bp); 1389 1390 // middle wrapper string 1391 if (TRANSITIONDURATION && middleWrapper && getOption('autoHeight', bp) && 'speed' in opts) { 1392 middleWrapperStr = '#' + slideId + '-mw{' + getTransitionDurationStyle(speedBP) + '}'; 1393 } 1394 1395 // inner wrapper string 1396 if ('edgePadding' in opts || 'gutter' in opts) { 1397 innerWrapperStr = '#' + slideId + '-iw{' + getInnerWrapperStyles(edgePaddingBP, gutterBP, fixedWidthBP, speedBP, autoHeightBP) + '}'; 1398 } 1399 1400 // container string 1401 if (carousel && horizontal && !autoWidth && ('fixedWidth' in opts || 'items' in opts || (fixedWidth && 'gutter' in opts))) { 1402 containerStr = 'width:' + getContainerWidth(fixedWidthBP, gutterBP, itemsBP) + ';'; 1403 } 1404 if (TRANSITIONDURATION && 'speed' in opts) { 1405 containerStr += getTransitionDurationStyle(speedBP); 1406 } 1407 if (containerStr) { 1408 containerStr = '#' + slideId + '{' + containerStr + '}'; 1409 } 1410 1411 // slide string 1412 if ('fixedWidth' in opts || (fixedWidth && 'gutter' in opts) || !carousel && 'items' in o
1412pts) { 1413 slideStr += getSlideWidthStyle(fixedWidthBP, gutterBP, itemsBP); 1414 } 1415 if ('gutter' in opts) { 1416 slideStr += getSlideGutterStyle(gutterBP); 1417 } 1418 // set gallery items transition-duration 1419 if (!carousel && 'speed' in opts) { 1420 if (TRANSITIONDURATION) { slideStr += getTransitionDurationStyle(speedBP); } 1421 if (ANIMATIONDURATION) { slideStr += getAnimationDurationStyle(speedBP); } 1422 } 1423 if (slideStr) { slideStr = '#' + slideId + ' > .tns-item{' + slideStr + '}'; } 1424 1425 // add up 1426 str = middleWrapperStr + innerWrapperStr + containerStr + slideStr; 1427 1428 if (str) { 1429 sheet.insertRule('@media (min-width: ' + bp / 16 + 'em) {' + str + '}', sheet.cssRules.length); 1430 } 1431 } 1432 } 1433 } 1434 1435 function initTools () { 1436 // == slides == 1437 updateSlideStatus(); 1438 1439 // == live region == 1440 outerWrapper.insertAdjacentHTML('afterbegin', '<div class="tns-liveregion tns-visually-hidden" aria-live="polite" aria-atomic="true">slide <span class="current">' + getLiveRegionStr() + '</span> of ' + slideCount + '</div>'); 1441 liveregionCurrent = outerWrapper.querySelector('.tns-liveregion .current'); 1442 1443 // == autoplayInit == 1444 if (hasAutoplay) { 1445 var txt = autoplay ? 'stop' : 'start'; 1446 if (autoplayButton) { 1447 setAttrs(autoplayButton, {'data-action': txt}); 1448 } else if (options.autoplayButtonOutput) { 1449 outerWrapper.insertAdjacentHTML(getInsertPosition(options.autoplayPosition), '<button type="button" data-action="' + txt + '">' + autoplayHtmlStrings[0] + txt + autoplayHtmlStrings[1] + autoplayText[0] + '</button>'); 1450 autoplayButton = outerWrapper.querySelector('[data-action]'); 1451 } 1452 1453 // add event 1454 if (autoplayButton) { 1455 addEvents(autoplayButton, {'click': toggleAutoplay}); 1456 } 1457 1458 if (autoplay) { 1459 startAutoplay(); 1460 if (autoplayHoverPause) { addEvents(container, hoverEvents); } 1461 if (autoplayResetOnVisibility) { addEvents(container, visibilityEvent); } 1462 } 1463 } 1464 1465 // == navInit == 1466 if (hasNav) { 1467 var initIndex = !carousel ? 0 : cloneCount; 1468 // customized nav 1469 // will not hide the navs in case they're thumbnails 1470 if (navContainer) { 1471 setAttrs(navContainer, {'aria-label': 'Carousel Pagination'}); 1472 navItems = navContainer.children; 1473 forEach(navItems, function(item, i) { 1474 setAttrs(item, { 1475 'data-nav': i, 1476 'tabindex': '-1', 1477 'aria-label': navStr + (i + 1), 1478 'aria-controls': slideId, 1479 }); 1480 }); 1481 1482 // generated nav 1483 } else { 1484 var navHtml = '', 1485 hiddenStr = navAsThumbnails ? '' : 'style="display:none"'; 1486 for (var i = 0; i < slideCount; i++) { 1487 // hide nav items by default 1488 navHtml += '<button type="button" data-nav="' + i +'" tabindex="-1" aria-controls="' + slideId + '" ' + hiddenStr + ' aria-label="' + navStr + (i + 1) +'"></button>'; 1489 } 1490 navHtml = '<div class="tns-nav" aria-label="Carousel Pagination">' + navHtml + '</div>'; 1491 outerWrapper.insertAdjacentHTML(getInsertPosition(options.navPosition), navHtml); 1492 1493 navContainer = outerWrapper.querySelector('.tns-nav'); 1494 navItems = navContainer.children; 1495 } 1496 1497 updateNavVisibility(); 1498 1499 // add transition 1500 if (TRANSITIONDURATION) { 1501 var prefix = TRANSITIONDURATION.substring(0, TRANSITIONDURATION.length - 18).toLowerCase(), 1502 str = 'transition: all ' + speed / 1000 + 's'; 1503 1504 if (prefix) { 1505 str = '-' + prefix + '-' + str; 1506 } 1507 1508 addCSSRule(sheet, '[aria-controls^=' + slideId + '-item]', str, getCssRulesLength(sheet)); 1509 } 1510 1511 setAttrs(navItems[navCurrentIndex], {'aria-label': navStr + (navCurrentIndex + 1) + navStrCurrent}); 1512 removeAttrs(navItems[navCurrentIndex], 'tabindex'); 1513 addClass(navItems[navCurrentIndex], navActiveClass); 1514 1515 // add events 1516 addEvents(navContainer, navEvents); 1517 } 1518 1519 1520 1521 // == controlsInit == 1522 if (hasControls) { 1523 if (!controlsContainer && (!prevButton || !nextButton)) { 1524 outerWrapper.insertAdjacentHTML(getInsertPosition(options.controlsPosition), '<div class="tns-controls" aria-label="Carousel Navigation" tabindex="0"><button type="button" data-controls="prev" tabindex="-1" aria-controls="' + slideId +'">' + controlsText[0] + '</button><button type="button" data-controls="next" tabindex="-1" aria-controls="' + slideId +'">' + controlsText[1] + '</button></div>'); 1525 1526 controlsContainer = outerWrapper.querySelector('.tns-controls'); 1527 } 1528 1529 if (!prevButton || !nextButton) { 1530 prevButton = controlsContainer.children[0]; 1531 nextButton = controlsContainer.children[1]; 1532 } 1533 1534 if (options.controlsContainer) { 1535 setAttrs(controlsContainer, { 1536 'aria-label': 'Carousel Navigation', 1537 'tabindex': '0' 1538 }); 1539 } 1540 1541 if (options.controlsContainer || (options.prevButton && options.nextButton)) { 1542 setAttrs([prevButton, nextButton], { 1543 'aria-controls': slideId, 1544 'tabindex': '-1', 1545 }); 1546 } 1547 1548 if (options.controlsContainer || (options.prevButton && options.nextButton)) { 1549 setAttrs(prevButton, {'data-controls' : 'prev'}); 1550 setAttrs(nextButton, {'data-controls' : 'next'}); 1551 } 1552 1553 prevIsButton = isButton(prevButton); 1554 nextIsButton = isButton(nextButton); 1555 1556 updateControlsStatus(); 1557 1558 // add events
vendor: 53,780 bytes, lines 1559-3196
1559 if (controlsContainer) { 1560 addEvents(controlsContainer, controlsEvents); 1561 } else { 1562 addEvents(prevButton, controlsEvents); 1563 addEvents(nextButton, controlsEvents); 1564 } 1565 } 1566 1567 // hide tools if needed 1568 disableUI(); 1569 } 1570 1571 function initEvents () { 1572 // add events 1573 if (carousel && TRANSITIONEND) { 1574 var eve = {}; 1575 eve[TRANSITIONEND] = onTransitionEnd; 1576 addEvents(container, eve); 1577 } 1578 1579 if (touch) { addEvents(container, touchEvents, options.preventScrollOnTouch); } 1580 if (mouseDrag) { addEvents(container, dragEvents); } 1581 if (arrowKeys) { addEvents(doc, docmentKeydownEvent); } 1582 1583 if (nested === 'inner') { 1584 events.on('outerResized', function () { 1585 resizeTasks(); 1586 events.emit('innerLoaded', info()); 1587 }); 1588 } else if (responsive || fixedWidth || autoWidth || autoHeight || !horizontal) { 1589 addEvents(win, {'resize': onResize}); 1590 } 1591 1592 if (autoHeight) { 1593 if (nested === 'outer') { 1594 events.on('innerLoaded', doAutoHeight); 1595 } else if (!disable) { doAutoHeight(); } 1596 } 1597 1598 doLazyLoad(); 1599 if (disable) { disableSlider(); } else if (freeze) { freezeSlider(); } 1600 1601 events.on('indexChanged', additionalUpdates); 1602 if (nested === 'inner') { events.emit('innerLoaded', info()); } 1603 if (typeof onInit === 'function') { onInit(info()); } 1604 isOn = true; 1605 } 1606 1607 function destroy () { 1608 // sheet 1609 sheet.disabled = true; 1610 if (sheet.ownerNode) { sheet.ownerNode.remove(); } 1611 1612 // remove win event listeners 1613 removeEvents(win, {'resize': onResize}); 1614 1615 // arrowKeys, controls, nav 1616 if (arrowKeys) { removeEvents(doc, docmentKeydownEvent); } 1617 if (controlsContainer) { removeEvents(controlsContainer, controlsEvents); } 1618 if (navContainer) { removeEvents(navContainer, navEvents); } 1619 1620 // autoplay 1621 removeEvents(container, hoverEvents); 1622 removeEvents(container, visibilityEvent); 1623 if (autoplayButton) { removeEvents(autoplayButton, {'click': toggleAutoplay}); } 1624 if (autoplay) { clearInterval(autoplayTimer); } 1625 1626 // container 1627 if (carousel && TRANSITIONEND) { 1628 var eve = {}; 1629 eve[TRANSITIONEND] = onTransitionEnd; 1630 removeEvents(container, eve); 1631 } 1632 if (touch) { removeEvents(container, touchEvents); } 1633 if (mouseDrag) { removeEvents(container, dragEvents); } 1634 1635 // cache Object values in options && reset HTML 1636 var htmlList = [containerHTML, controlsContainerHTML, prevButtonHTML, nextButtonHTML, navContainerHTML, autoplayButtonHTML]; 1637 1638 tnsList.forEach(function(item, i) { 1639 var el = item === 'container' ? outerWrapper : options[item]; 1640 1641 if (typeof el === 'object' && el) { 1642 var prevEl = el.previousElementSibling ? el.previousElementSibling : false, 1643 parentEl = el.parentNode; 1644 el.outerHTML = htmlList[i]; 1645 options[item] = prevEl ? prevEl.nextElementSibling : parentEl.firstElementChild; 1646 } 1647 }); 1648 1649 1650 // reset variables 1651 tnsList = animateIn = animateOut = animateDelay = animateNormal = horizontal = outerWrapper = innerWrapper = container = containerParent = containerHTML = slideItems = slideCount = breakpointZone = windowWidth = autoWidth = fixedWidth = edgePadding = gutter = viewport = items = slideBy = viewportMax = arrowKeys = speed = rewind = loop = autoHeight = sheet = lazyload = slidePositions = slideItemsOut = cloneCount = slideCountNew = hasRightDeadZone = rightBoundary = updateIndexBeforeTransform = transformAttr = transformPrefix = transformPostfix = getIndexMax = index = indexCached = indexMin = indexMax = resizeTimer = swipeAngle = moveDirectionExpected = running = onInit = events = newContainerClasses = slideId = disable = disabled = freezable = freeze = frozen = controlsEvents = navEvents = hoverEvents = visibilityEvent = docmentKeydownEvent = touchEvents = dragEvents = hasControls = hasNav = navAsThumbnails = hasAutoplay = hasTouch = hasMouseDrag = slideActiveClass = imgCompleteClass = imgEvents = imgsComplete = controls = controlsText = controlsContainer = controlsContainerHTML = prevButton = nextButton = prevIsButton = nextIsButton = nav = navContainer = navContainerHTML = navItems = pages = pagesCached = navClicked = navCurrentIndex = navCurrentIndexCached = navActiveClass = navStr = navStrCurrent = autoplay = autoplayTimeout = autoplayDirection = autoplayText = autoplayHoverPause = autoplayButton = autoplayButtonHTML = autoplayResetOnVisibility = autoplayHtmlStrings = autoplayTimer = animating = autoplayHoverPaused = autoplayUserPaused = autoplayVisibilityPaused = initPosition = lastPosition = translateInit = disX = disY = panStart = rafIndex = getDist = touch = mouseDrag = null; 1652 // check variables 1653 // [animateIn, animateOut, animateDelay, animateNormal, horizontal, outerWrapper, innerWrapper, container, containerParent, containerHTML, slideItems, slideCount, breakpointZone, windowWidth, autoWidth, fixedWidth, edgePadding, gutter, viewport, items, slideBy, viewportMax, arrowKeys, speed, rewind, loop, autoHeight, sheet, lazyload, slidePositions, slideItemsOut, cloneCount, slideCountNew, hasRightDeadZone, rightBoundary, updateIndexBeforeTransform, transformAttr, transformPrefix, transformPostfix, getIndexMax, index, indexCached, indexMin, indexMax, resizeTimer, swipeAngle, moveDirectionExpected, running, onInit, events, newContainerClasses, slideId, disable, disabled, freezable, freeze, frozen, controlsEvents, navEvents, hoverEvents, visibilityEvent, docmentKeydownEvent, touchEvents, dragEvents, hasControls, hasNav, navAsThumbnails, hasAutoplay, hasTouch, hasMouseDrag, slideActiveClass, imgCompleteClass, imgEvents, imgsComplete, controls, controlsText, controlsContainer, controlsContainerHTML, prevButton, nextButton, prevIsButton, nextIsButton, nav, navContainer, navContainerHTML, navItems, pages, pagesCached, navClicked, navCurrentIndex, navCurrentIndexCached, navActiveClass, navStr, navStrCurrent, autoplay, autoplayTimeout, autoplayDirection, autoplayText, autoplayHoverPause, autoplayButton, autoplayButtonHTML, autoplayResetOnVisibility, autoplayHtmlStrings, autoplayTimer, animating, autoplayHoverPaused, autoplayUserPaused, autoplayVisibilityPaused, initPosition, lastPosition, translateInit, disX, disY, panStart, rafIndex, getDist, touch, mouseDrag ].forEach(function(item) { if (item !== null) { console.log(item); } }); 1654 1655 for (var a in this) { 1656 if (a !== 'rebuild') { this[a] = null; } 1657 } 1658 isOn = false; 1659 } 1660 1661 // === ON RESIZE === 1662 // responsive || fixedWidth || autoWidth || !horizontal 1663 function onResize (e) { 1664 raf(function(){ resizeTasks(getEvent(e)); }); 1665 } 1666 1667 function resizeTasks (e) { 1668 if (!isOn) { return; } 1669 if (nested === 'outer') { events.emit('outerResized', info(e)); } 1670 windowWidth = getWindowWidth(); 1671 var bpChanged, 1672 breakpointZoneTem = breakpointZone, 1673 needContainerTransform = false; 1674 1675 if (responsive) { 1676 setBreakpointZone(); 1677 bpChanged = breakpointZoneTem !== breakpointZone; 1678 // if (hasRightDeadZone) { needContainerTransform = true; } // *? 1679 if (bpChanged) { events.emit('newBreakpointStart', info(e)); } 1680 } 1681 1682 var indChanged, 1683 itemsChanged, 1684 itemsTem = items, 1685 disableTem = disable, 1686 freezeTem = freeze, 1687 arrowKeysTem = arrowKeys, 1688 controlsTem = controls, 1689 navTem = nav, 1690 touchTem = touch, 1691 mouseDragTem = mouseDrag, 1692 autoplayTem = autoplay, 1693 autoplayHoverPauseTem = autoplayHoverPause, 1694 autoplayResetOnVisibilityTem = autoplayResetOnVisibility, 1695 indexTem = index; 1696 1697 if (bpChanged) { 1698 var fixedWidthTem = fixedWidth, 1699 autoHeightTem = autoHeight, 1700 controlsTextTem = controlsText, 1701 centerTem = center, 1702 autoplayTextTem = autoplayText; 1703 1704 if (!CSSMQ) { 1705 var gutterTem = gutter, 1706 edgePaddingTem = edgePadding; 1707 } 1708 } 1709 1710 // get option: 1711 // fixed width: viewport, fixedWidth, gutter => items 1712 // others: window width => all variables 1713 // all: items => slideBy 1714 arrowKeys = getOption('arrowKeys'); 1715 controls = getOption('controls'); 1716 nav = getOption('nav'); 1717 touch = getOption('touch'); 1718 center = getOption('center'); 1719 mouseDrag = getOption('mouseDrag'); 1720 autoplay = getOption('autoplay'); 1721 autoplayHoverPause = getOption('autoplayHoverPause'); 1722 autoplayResetOnVisibility = getOption('autoplayResetOnVisibility'); 1723 1724 if (bpChanged) { 1725 disable = getOption('disable'); 1726 fixedWidth = getOption('fixedWidth'); 1727 speed = getOption('speed'); 1728 autoHeight = getOption('autoHeight'); 1729 controlsText = getOption('controlsText'); 1730 autoplayText = getOption('autoplayText'); 1731 autoplayTimeout = getOption('autoplayTimeout'); 1732 1733 if (!CSSMQ) { 1734 edgePadding = getOption('edgePadding'); 1735 gutter = getOption('gutter'); 1736 } 1737 } 1738 // update options 1739 resetVariblesWhenDisable(disable); 1740 1741 viewport = getViewportWidth(); // <= edgePadding, gutter 1742 if ((!horizontal || autoWidth) && !disable) { 1743 setSlidePositions(); 1744 if (!horizontal) { 1745 updateContentWrapperHeight(); // <= setSlidePositions 1746 needContainerTransform = true; 1747 } 1748 } 1749 if (fixedWidth || autoWidth) { 1750 rightBoundary = getRightBoundary(); // autoWidth: <= viewport, slidePositions, gutter 1751 // fixedWidth: <= viewport, fixedWidth, gutter 1752 indexMax = getIndexMax(); // autoWidth: <= rightBoundary, slidePositions 1753 // fixedWidth: <= rightBoundary, fixedWidth, gutter 1754 } 1755 1756 if (bpChanged || fixedWidth) { 1757 items = getOption('items'); 1758 slideBy = getOption('slideBy'); 1759 itemsChanged = items !== itemsTem; 1760 1761 if (itemsChanged) { 1762 if (!fixedWidth && !autoWidth) { indexMax = getIndexMax(); } // <= items 1763 // check index before transform in case 1764 // slider reach the right edge then items become bigger 1765 updateIndex(); 1766 } 1767 } 1768 1769 if (bpChanged) { 1770 if (disable !== disableTem) { 1771 if (disable) { 1772 disableSlider(); 1773 } else { 1774 enableSlider(); // <= slidePositions, rightBoundary, indexMax 1775 } 1776 } 1777 } 1778 1779 if (freezable && (bpChanged || fixedWidth || autoWidth)) { 1780 freeze = getFreeze(); // <= autoWidth: slidePositions, gutter, viewport, rightBoundary 1781 // <= fixedWidth: fixedWidth, gutter, rightBoundary 1782 // <= others: items 1783 1784 if (freeze !== freezeTem) { 1785 if (freeze) { 1786 doContainerTransform(getContainerTransformValue(getStartIndex(0))); 1787 freezeSlider(); 1788 } else { 1789 unfreezeSlider(); 1790 needContainerTransform = true; 1791 } 1792 } 1793 } 1794 1795 resetVariblesWhenDisable(disable || freeze); // controls, nav, touch, mouseDrag, arrowKeys, autoplay, autoplayHoverPause, autoplayResetOnVisibility 1796 if (!autoplay) { autoplayHoverPause = autoplayResetOnVisibility = false; } 1797 1798 if (arrowKeys !== arrowKeysTem) { 1799 arrowKeys ? 1800 addEvents(doc, docmentKeydownEvent) : 1801 removeEvents(doc, docmentKeydownEvent); 1802 } 1803 if (controls !== controlsTem) { 1804 if (controls) { 1805 if (controlsContainer) { 1806 showElement(controlsContainer); 1807 } else { 1808 if (prevButton) { showElement(prevButton); } 1809 if (nextButton) { showElement(nextButton); } 1810 } 1811 } else { 1812 if (controlsContainer) { 1813 hideElement(controlsContainer); 1814 } else { 1815 if (prevButton) { hideElement(prevButton); } 1816 if (nextButton) { hideElement(nextButton); } 1817 } 1818 } 1819 } 1820 if (nav !== navTem) { 1821 nav ? 1822 showElement(navContainer) : 1823 hideElement(navContainer); 1824 } 1825 if (touch !== touchTem) { 1826 touch ? 1827 addEvents(container, touchEvents, options.preventScrollOnTouch) : 1828 removeEvents(container, touchEvents); 1829 } 1830 if (mouseDrag !== mouseDragTem) { 1831 mouseDrag ? 1832 addEvents(container, dragEvents) : 1833 removeEvents(container, dragEvents); 1834 } 1835 if (autoplay !== autoplayTem) { 1836 if (autoplay) { 1837 if (autoplayButton) { showElement(autoplayButton); } 1838 if (!animating && !autoplayUserPaused) { startAutoplay(); } 1839 } else { 1840 if (autoplayButton) { hideElement(autoplayButton); } 1841 if (animating) { stopAutoplay(); } 1842 } 1843 } 1844 if (autoplayHoverPause !== autoplayHoverPauseTem) { 1845 autoplayHoverPause ? 1846 addEvents(container, hoverEvents) : 1847 removeEvents(container, hoverEvents); 1848 } 1849 if (autoplayResetOnVisibility !== autoplayResetOnVisibilityTem) { 1850 autoplayResetOnVisibility ? 1851 addEvents(doc, visibilityEvent) : 1852 removeEvents(doc, visibilityEvent); 1853 } 1854 1855 if (bpChanged) { 1856 if (fixedWidth !== fixedWidthTem || center !== centerTem) { needContainerTransform = true; } 1857 1858 if (autoHeight !== autoHeightTem) { 1859 if (!autoHeight) { innerWrapper.style.height = ''; } 1860 } 1861 1862 if (controls && controlsText !== controlsTextTem) { 1863 prevButton.innerHTML = controlsText[0]; 1864 nextButton.innerHTML = controlsText[1]; 1865 } 1866 1867 if (autoplayButton && autoplayText !== autoplayTextTem) { 1868 var i = autoplay ? 1 : 0, 1869 html = autoplayButton.innerHTML, 1870 len = html.length - autoplayTextTem[i].length; 1871 if (html.substring(len) === autoplayTextTem[i]) { 1872 autoplayButton.innerHTML = html.substring(0, len) + autoplayText[i]; 1873 } 1874 } 1875 } else { 1876 if (center && (fixedWidth || autoWidth)) { needContainerTransform = true; } 1877 } 1878 1879 if (itemsChanged || fixedWidth && !autoWidth) { 1880 pages = getPages(); 1881 updateNavVisibility(); 1882 } 1883 1884 indChanged = index !== indexTem; 1885 if (indChanged) { 1886 events.emit('indexChanged', info()); 1887 needContainerTransform = true; 1888 } else if (itemsChanged) { 1889 if (!indChanged) { additionalUpdates(); } 1890 } else if (fixedWidth || autoWidth) { 1891 doLazyLoad(); 1892 updateSlideStatus(); 1893 updateLiveRegion(); 1894 } 1895 1896 if (itemsChanged && !carousel) { updateGallerySlidePositions(); } 1897 1898 if (!disable && !freeze) { 1899 // non-mediaqueries: IE8 1900 if (bpChanged && !CSSMQ) { 1901 // middle wrapper styles 1902 1903 // inner wrapper styles 1904 if (edgePadding !== edgePaddingTem || gutter !== gutterTem) { 1905 innerWrapper.style.cssText = getInnerWrapperStyles(edgePadding, gutter, fixedWidth, speed, autoHeight); 1906 } 1907 1908 if (horizontal) { 1909 // container styles 1910 if (carousel) { 1911 container.style.width = getContainerWidth(fixedWidth, gutter, items); 1912 } 1913 1914 // slide styles 1915 var str = getSlideWidthStyle(fixedWidth, gutter, items) + 1916 getSlideGutterStyle(gutter); 1917 1918 // remove the last line and 1919 // add new styles 1920 removeCSSRule(sheet, getCssRulesLength(sheet) - 1); 1921 addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet)); 1922 } 1923 } 1924 1925 // auto height 1926 if (autoHeight) { doAutoHeight(); } 1927 1928 if (needContainerTransform) { 1929 doContainerTransformSilent(); 1930 indexCached = index; 1931 } 1932 } 1933 1934 if (bpChanged) { events.emit('newBreakpointEnd', info(e)); } 1935 } 1936 1937 1938 1939 1940 1941 // === INITIALIZATION FUNCTIONS === // 1942 function getFreeze () { 1943 if (!fixedWidth && !autoWidth) { 1944 var a = center ? items - (items - 1) / 2 : items; 1945 return slideCount <= a; 1946 } 1947 1948 var width = fixedWidth ? (fixedWidth + gutter) * slideCount : slidePositions[slideCount], 1949 vp = edgePadding ? viewport + edgePadding * 2 : viewport + gutter; 1950 1951 if (center) { 1952 vp -= fixedWidth ? (viewport - fixedWidth) / 2 : (viewport - (slidePositions[index + 1] - slidePositions[index] - gutter)) / 2; 1953 } 1954 1955 return width <= vp; 1956 } 1957 1958 function setBreakpointZone () { 1959 breakpointZone = 0; 1960 for (var bp in responsive) { 1961 bp = parseInt(bp); // convert string to number 1962 if (windowWidth >= bp) { breakpointZone = bp; } 1963 } 1964 } 1965 1966 // (slideBy, indexMin, indexMax) => index 1967 var updateIndex = (function () { 1968 return loop ? 1969 carousel ? 1970 // loop + carousel 1971 function () { 1972 var leftEdge = indexMin, 1973 rightEdge = indexMax; 1974 1975 leftEdge += slideBy; 1976 rightEdge -= slideBy; 1977 1978 // adjust edges when has edge paddings 1979 // or fixed-width slider with extra space on the right side 1980 if (edgePadding) { 1981 leftEdge += 1; 1982 rightEdge -= 1; 1983 } else if (fixedWidth) { 1984 if ((viewport + gutter)%(fixedWidth + gutter)) { rightEdge -= 1; } 1985 } 1986 1987 if (cloneCount) { 1988 if (index > rightEdge) { 1989 index -= slideCount; 1990 } else if (index < leftEdge) { 1991 index += slideCount; 1992 } 1993 } 1994 } : 1995 // loop + gallery 1996 function() { 1997 if (index > indexMax) { 1998 while (index >= indexMin + slideCount) { index -= slideCount; } 1999 } else if (index < indexMin) { 2000 while (index <= indexMax - slideCount) { index += slideCount; } 2001 } 2002 } : 2003 // non-loop 2004 function() { 2005 index = Math.max(indexMin, Math.min(indexMax, index)); 2006 }; 2007 })(); 2008 2009 function disableUI () { 2010 if (!autoplay && autoplayButton) { hideElement(autoplayButton); } 2011 if (!nav && navContainer) { hideElement(navContainer); } 2012 if (!controls) { 2013 if (controlsContainer) { 2014 hideElement(controlsContainer); 2015 } else { 2016 if (prevButton) { hideElement(prevButton); } 2017 if (nextButton) { hideElement(nextButton); } 2018 } 2019 } 2020 } 2021 2022 function enableUI () { 2023 if (autoplay && autoplayButton) { showElement(autoplayButton); } 2024 if (nav && navContainer) { showElement(navContainer); } 2025 if (controls) { 2026 if (controlsContainer) { 2027 showElement(controlsContainer); 2028 } else { 2029 if (prevButton) { showElement(prevButton); } 2030 if (nextButton) { showElement(nextButton); } 2031 } 2032 } 2033 } 2034 2035 function freezeSlider () { 2036 if (frozen) { return; } 2037 2038 // remove edge padding from inner wrapper 2039 if (edgePadding) { innerWrapper.style.margin = '0px'; } 2040 2041 // add class tns-transparent to cloned slides 2042 if (cloneCount) { 2043 var str = 'tns-transparent'; 2044 for (var i = cloneCount; i--;) { 2045 if (carousel) { addClass(slideItems[i], str); } 2046 addClass(slideItems[slideCountNew - i - 1], str); 2047 } 2048 } 2049 2050 // update tools 2051 disableUI(); 2052 2053 frozen = true; 2054 } 2055 2056 function unfreezeSlider () { 2057 if (!frozen) { return; } 2058 2059 // restore edge padding for inner wrapper 2060 // for mordern browsers 2061 if (edgePadding && CSSMQ) { innerWrapper.style.margin = ''; } 2062 2063 // remove class tns-transparent to cloned slides 2064 if (cloneCount) { 2065 var str = 'tns-transparent'; 2066 for (var i = cloneCount; i--;) { 2067 if (carousel) { removeClass(slideItems[i], str); } 2068 removeClass(slideItems[slideCountNew - i - 1], str); 2069 } 2070 } 2071 2072 // update tools 2073 enableUI(); 2074 2075 frozen = false; 2076 } 2077 2078 function disableSlider () { 2079 if (disabled) { return; } 2080 2081 sheet.disabled = true; 2082 container.className = container.className.replace(newContainerClasses.substring(1), ''); 2083 removeAttrs(container, ['style']); 2084 if (loop) { 2085 for (var j = cloneCount; j--;) { 2086 if (carousel) { hideElement(slideItems[j]); } 2087 hideElement(slideItems[slideCountNew - j - 1]); 2088 } 2089 } 2090 2091 // vertical slider 2092 if (!horizontal || !carousel) { removeAttrs(innerWrapper, ['style']); } 2093 2094 // gallery 2095 if (!carousel) { 2096 for (var i = index, l = index + slideCount; i < l; i++) { 2097 var item = slideItems[i]; 2098 removeAttrs(item, ['style']); 2099 removeClass(item, animateIn); 2100 removeClass(item, animateNormal); 2101 } 2102 } 2103 2104 // update tools 2105 disableUI(); 2106 2107 disabled = true; 2108 } 2109 2110 function enableSlider () { 2111 if (!disabled) { return; } 2112 2113 sheet.disabled = false; 2114 container.className += newContainerClasses; 2115 doContainerTransformSilent(); 2116 2117 if (loop) { 2118 for (var j = cloneCount; j--;) { 2119 if (carousel) { showElement(slideItems[j]); } 2120 showElement(slideItems[slideCountNew - j - 1]); 2121 } 2122 } 2123 2124 // gallery 2125 if (!carousel) { 2126 for (var i = index, l = index + slideCount; i < l; i++) { 2127 var item = slideItems[i], 2128 classN = i < index + items ? animateIn : animateNormal; 2129 item.style.left = (i - index) * 100 / items + '%'; 2130 addClass(item, classN); 2131 } 2132 } 2133 2134 // update tools 2135 enableUI(); 2136 2137 disabled = false; 2138 } 2139 2140 function updateLiveRegion () { 2141 var str = getLiveRegionStr(); 2142 if (liveregionCurrent.innerHTML !== str) { liveregionCurrent.innerHTML = str; } 2143 } 2144 2145 function getLiveRegionStr () { 2146 var arr = getVisibleSlideRange(), 2147 start = arr[0] + 1, 2148 end = arr[1] + 1; 2149 return start === end ? start + '' : start + ' to ' + end; 2150 } 2151 2152 function getVisibleSlideRange (val) { 2153 if (val == null) { val = getContainerTransformValue(); } 2154 var start = index, end, rangestart, rangeend; 2155 2156 // get range start, range end for autoWidth and fixedWidth 2157 if (center || edgePadding) { 2158 if (autoWidth || fixedWidth) { 2159 rangestart = - (parseFloat(val) + edgePadding); 2160 rangeend = rangestart + viewport + edgePadding * 2; 2161 } 2162 } else { 2163 if (autoWidth) { 2164 rangestart = slidePositions[index]; 2165 rangeend = rangestart + viewport; 2166 } 2167 } 2168 2169 // get start, end 2170 // - check auto width 2171 if (autoWidth) { 2172 slidePositions.forEach(function(point, i) { 2173 if (i < slideCountNew) { 2174 if ((center || edgePadding) && point <= rangestart + 0.5) { start = i; } 2175 if (rangeend - point >= 0.5) { end = i; } 2176 } 2177 }); 2178 2179 // - check percentage width, fixed width 2180 } else { 2181 2182 if (fixedWidth) { 2183 var cell = fixedWidth + gutter; 2184 if (center || edgePadding) { 2185 start = Math.floor(rangestart/cell); 2186 end = Math.ceil(rangeend/cell - 1); 2187 } else { 2188 end = start + Math.ceil(viewport/cell) - 1; 2189 } 2190 2191 } else { 2192 if (center || edgePadding) { 2193 var a = items - 1; 2194 if (center) { 2195 start -= a / 2; 2196 end = index + a / 2; 2197 } else { 2198 end = index + a; 2199 } 2200 2201 if (edgePadding) { 2202 var b = edgePadding * items / viewport; 2203 start -= b; 2204 end += b; 2205 } 2206 2207 start = Math.floor(start); 2208 end = Math.ceil(end); 2209 } else { 2210 end = start + items - 1; 2211 } 2212 } 2213 2214 start = Math.max(start, 0); 2215 end = Math.min(end, slideCountNew - 1); 2216 } 2217 2218 return [start, end]; 2219 } 2220 2221 function doLazyLoad () { 2222 if (lazyload && !disable) { 2223 getImageArray.apply(null, getVisibleSlideRange()).forEach(function (img) { 2224 if (!hasClass(img, imgCompleteClass)) { 2225 // stop propagation transitionend event to container 2226 var eve = {}; 2227 eve[TRANSITIONEND] = function (e) { e.stopPropagation(); }; 2228 addEvents(img, eve); 2229 2230 addEvents(img, imgEvents); 2231 2232 // update src 2233 img.src = getAttr(img, 'data-src'); 2234 2235 // update srcset 2236 var srcset = getAttr(img, 'data-srcset'); 2237 if (srcset) { img.srcset = srcset; } 2238 2239 addClass(img, 'loading'); 2240 } 2241 }); 2242 } 2243 } 2244 2245 function onImgLoaded (e) { 2246 imgLoaded(getTarget(e)); 2247 } 2248 2249 function onImgFailed (e) { 2250 imgFailed(getTarget(e)); 2251 } 2252 2253 function imgLoaded (img) { 2254 addClass(img, 'loaded'); 2255 imgCompleted(img); 2256 } 2257 2258 function imgFailed (img) { 2259 addClass(img, 'failed'); 2260 imgCompleted(img); 2261 } 2262 2263 function imgCompleted (img) { 2264 addClass(img, imgCompleteClass); 2265 removeClass(img, 'loading'); 2266 removeEvents(img, imgEvents); 2267 } 2268 2269 function getImageArray (start, end) { 2270 var imgs = []; 2271 while (start <= end) { 2272 forEach(slideItems[start].querySelectorAll('img'), function (img) { imgs.push(img); }); 2273 start++; 2274 } 2275 2276 return imgs; 2277 } 2278 2279 // check if all visible images are loaded 2280 // and update container height if it's done 2281 function doAutoHeight () { 2282 var imgs = getImageArray.apply(null, getVisibleSlideRange()); 2283 raf(function(){ imgsLoadedCheck(imgs, updateInnerWrapperHeight); }); 2284 } 2285 2286 function imgsLoadedCheck (imgs, cb) { 2287 // execute callback function if all images are complete 2288 if (imgsComplete) { return cb(); } 2289 2290 // check image classes 2291 imgs.forEach(function (img, index) { 2292 if (!lazyload && img.complete) { imgCompleted(img); } // Check image.complete 2293 if (hasClass(img, imgCompleteClass)) { imgs.splice(index, 1); } 2294 }); 2295 2296 // execute callback function if selected images are all complete 2297 if (!imgs.length) { return cb(); } 2298 2299 // otherwise execute this functiona again 2300 raf(function(){ imgsLoadedCheck(imgs, cb); }); 2301 } 2302 2303 function additionalUpdates () { 2304 doLazyLoad(); 2305 updateSlideStatus(); 2306 updateLiveRegion(); 2307 updateControlsStatus(); 2308 updateNavStatus(); 2309 } 2310 2311 2312 function update_carousel_transition_duration () { 2313 if (carousel && autoHeight) { 2314 middleWrapper.style[TRANSITIONDURATION] = speed / 1000 + 's'; 2315 } 2316 } 2317 2318 function getMaxSlideHeight (slideStart, slideRange) { 2319 var heights = []; 2320 for (var i = slideStart, l = Math.min(slideStart + slideRange, slideCountNew); i < l; i++) { 2321 heights.push(slideItems[i].offsetHeight); 2322 } 2323 2324 return Math.max.apply(null, heights); 2325 } 2326 2327 // update inner wrapper height 2328 // 1. get the max-height of the visible slides 2329 // 2. set transitionDuration to speed 2330 // 3. update inner wrapper height to max-height 2331 // 4. set transitionDuration to 0s after transition done 2332 function updateInnerWrapperHeight () { 2333 var maxHeight = autoHeight ? getMaxSlideHeight(index, items) : getMaxSlideHeight(cloneCount, slideCount), 2334 wp = middleWrapper ? middleWrapper : innerWrapper; 2335 2336 if (wp.style.height !== maxHeight) { wp.style.height = maxHeight + 'px'; } 2337 } 2338 2339 // get the distance from the top edge of the first slide to each slide 2340 // (init) => slidePositions 2341 function setSlidePositions () { 2342 slidePositions = [0]; 2343 var attr = horizontal ? 'left' : 'top', 2344 attr2 = horizontal ? 'right' : 'bottom', 2345 base = slideItems[0].getBoundingClientRect()[attr]; 2346 2347 forEach(slideItems, function(item, i) { 2348 // skip the first slide 2349 if (i) { slidePositions.push(item.getBoundingClientRect()[attr] - base); } 2350 // add the end edge 2351 if (i === slideCountNew - 1) { slidePositions.push(item.getBoundingClientRect()[attr2] - base); } 2352 }); 2353 } 2354 2355 // update slide 2356 function updateSlideStatus () { 2357 var range = getVisibleSlideRange(), 2358 start = range[0], 2359 end = range[1]; 2360 2361 forEach(slideItems, function(item, i) { 2362 // show slides 2363 if (i >= start && i <= end) { 2364 if (hasAttr(item, 'aria-hidden')) { 2365 removeAttrs(item, ['aria-hidden', 'tabindex']); 2366 addClass(item, slideActiveClass); 2367 } 2368 // hide slides 2369 } else { 2370 if (!hasAttr(item, 'aria-hidden')) { 2371 setAttrs(item, { 2372 'aria-hidden': 'true', 2373 'tabindex': '-1' 2374 }); 2375 removeClass(item, slideActiveClass); 2376 } 2377 } 2378 }); 2379 } 2380 2381 // gallery: update slide position 2382 function updateGallerySlidePositions () { 2383 var l = index + Math.min(slideCount, items); 2384 for (var i = slideCountNew; i--;) { 2385 var item = slideItems[i]; 2386 2387 if (i >= index && i < l) { 2388 // add transitions to visible slides when adjusting their positions 2389 addClass(item, 'tns-moving'); 2390 2391 item.style.left = (i - index) * 100 / items + '%'; 2392 addClass(item, animateIn); 2393 removeClass(item, animateNormal); 2394 } else if (item.style.left) { 2395 item.style.left = ''; 2396 addClass(item, animateNormal); 2397 removeClass(item, animateIn); 2398 } 2399 2400 // remove outlet animation 2401 removeClass(item, animateOut); 2402 } 2403 2404 // removing '.tns-moving' 2405 setTimeout(function() { 2406 forEach(slideItems, function(el) { 2407 removeClass(el, 'tns-moving'); 2408 }); 2409 }, 300); 2410 } 2411 2412 // set tabindex on Nav 2413 function updateNavStatus () { 2414 // get current nav 2415 if (nav) { 2416 navCurrentIndex = navClicked >= 0 ? navClicked : getCurrentNavIndex(); 2417 navClicked = -1; 2418 2419 if (navCurrentIndex !== navCurrentIndexCached) { 2420 var navPrev = navItems[navCurrentIndexCached], 2421 navCurrent = navItems[navCurrentIndex]; 2422 2423 setAttrs(navPrev, { 2424 'tabindex': '-1', 2425 'aria-label': navStr + (navCurrentIndexCached + 1) 2426 }); 2427 removeClass(navPrev, navActiveClass); 2428 2429 setAttrs(navCurrent, {'aria-label': navStr + (navCurrentIndex + 1) + navStrCurrent}); 2430 removeAttrs(navCurrent, 'tabindex'); 2431 addClass(navCurrent, navActiveClass); 2432 2433 navCurrentIndexCached = navCurrentIndex; 2434 } 2435 } 2436 } 2437 2438 function getLowerCaseNodeName (el) { 2439 return el.nodeName.toLowerCase(); 2440 } 2441 2442 function isButton (el) { 2443 return getLowerCaseNodeName(el) === 'button'; 2444 } 2445 2446 function isAriaDisabled (el) { 2447 return el.getAttribute('aria-disabled') === 'true'; 2448 } 2449 2450 function disEnableElement (isButton, el, val) { 2451 if (isButton) { 2452 el.disabled = val; 2453 } else { 2454 el.setAttribute('aria-disabled', val.toString()); 2455 } 2456 } 2457 2458 // set 'disabled' to true on controls when reach the edges 2459 function updateControlsStatus () { 2460 if (!controls || rewind || loop) { return; } 2461 2462 var prevDisabled = (prevIsButton) ? prevButton.disabled : isAriaDisabled(prevButton), 2463 nextDisabled = (nextIsButton) ? nextButton.disabled : isAriaDisabled(nextButton), 2464 disablePrev = (index <= indexMin) ? true : false, 2465 disableNext = (!rewind && index >= indexMax) ? true : false; 2466 2467 if (disablePrev && !prevDisabled) { 2468 disEnableElement(prevIsButton, prevButton, true); 2469 } 2470 if (!disablePrev && prevDisabled) { 2471 disEnableElement(prevIsButton, prevButton, false); 2472 } 2473 if (disableNext && !nextDisabled) { 2474 disEnableElement(nextIsButton, nextButton, true); 2475 } 2476 if (!disableNext && nextDisabled) { 2477 disEnableElement(nextIsButton, nextButton, false); 2478 } 2479 } 2480 2481 // set duration 2482 function resetDuration (el, str) { 2483 if (TRANSITIONDURATION) { el.style[TRANSITIONDURATION] = str; } 2484 } 2485 2486 function getSliderWidth () { 2487 return fixedWidth ? (fixedWidth + gutter) * slideCountNew : slidePositions[slideCountNew]; 2488 } 2489 2490 function getCenterGap (num) { 2491 if (num == null) { num = index; } 2492 2493 var gap = edgePadding ? gutter : 0; 2494 return autoWidth ? ((viewport - gap) - (slidePositions[num + 1] - slidePositions[num] - gutter))/2 : 2495 fixedWidth ? (viewport - fixedWidth) / 2 : 2496 (items - 1) / 2; 2497 } 2498 2499 function getRightBoundary () { 2500 var gap = edgePadding ? gutter : 0, 2501 result = (viewport + gap) - getSliderWidth(); 2502 2503 if (center && !loop) { 2504 result = fixedWidth ? - (fixedWidth + gutter) * (slideCountNew - 1) - getCenterGap() : 2505 getCenterGap(slideCountNew - 1) - slidePositions[slideCountNew - 1]; 2506 } 2507 if (result > 0) { result = 0; } 2508 2509 return result; 2510 } 2511 2512 function getContainerTransformValue (num) { 2513 if (num == null) { num = index; } 2514 2515 var val; 2516 if (horizontal && !autoWidth) { 2517 if (fixedWidth) { 2518 val = - (fixedWidth + gutter) * num; 2519 if (center) { val += getCenterGap(); } 2520 } else { 2521 var denominator = TRANSFORM ? slideCountNew : items; 2522 if (center) { num -= getCenterGap(); } 2523 val = - num * 100 / denominator; 2524 } 2525 } else { 2526 val = - slidePositions[num]; 2527 if (center && autoWidth) { 2528 val += getCenterGap(); 2529 } 2530 } 2531 2532 if (hasRightDeadZone) { val = Math.max(val, rightBoundary); } 2533 2534 val += (horizontal && !autoWidth && !fixedWidth) ? '%' : 'px'; 2535 2536 return val; 2537 } 2538 2539 function doContainerTransformSilent (val) { 2540 resetDuration(container, '0s'); 2541 doContainerTransform(val); 2542 } 2543 2544 function doContainerTransform (val) { 2545 if (val == null) { val = getContainerTransformValue(); } 2546 container.style[transformAttr] = transformPrefix + val + transformPostfix; 2547 } 2548 2549 function animateSlide (number, classOut, classIn, isOut) { 2550 var l = number + items; 2551 if (!loop) { l = Math.min(l, slideCountNew); } 2552 2553 for (var i = number; i < l; i++) { 2554 var item = slideItems[i]; 2555 2556 // set item positions 2557 if (!isOut) { item.style.left = (i - index) * 100 / items + '%'; } 2558 2559 if (animateDelay && TRANSITIONDELAY) { 2560 item.style[TRANSITIONDELAY] = item.style[ANIMATIONDELAY] = animateDelay * (i - number) / 1000 + 's'; 2561 } 2562 removeClass(item, classOut); 2563 addClass(item, classIn); 2564 2565 if (isOut) { slideItemsOut.push(item); } 2566 } 2567 } 2568 2569 // make transfer after click/drag: 2570 // 1. change 'transform' property for mordern browsers 2571 // 2. change 'left' property for legacy browsers 2572 var transformCore = (function () { 2573 return carousel ? 2574 function () { 2575 resetDuration(container, ''); 2576 if (TRANSITIONDURATION || !speed) { 2577 // for morden browsers with non-zero duration or 2578 // zero duration for all browsers 2579 doContainerTransform(); 2580 // run fallback function manually 2581 // when duration is 0 / container is hidden 2582 if (!speed || !isVisible(container)) { onTransitionEnd(); } 2583 2584 } else { 2585 // for old browser with non-zero duration 2586 jsTransform(container, transformAttr, transformPrefix, transformPostfix, getContainerTransformValue(), speed, onTransitionEnd); 2587 } 2588 2589 if (!horizontal) { updateContentWrapperHeight(); } 2590 } : 2591 function () { 2592 slideItemsOut = []; 2593 2594 var eve = {}; 2595 eve[TRANSITIONEND] = eve[ANIMATIONEND] = onTransitionEnd; 2596 removeEvents(slideItems[indexCached], eve); 2597 addEvents(slideItems[index], eve); 2598 2599 animateSlide(indexCached, animateIn, animateOut, true); 2600 animateSlide(index, animateNormal, animateIn); 2601 2602 // run fallback function manually 2603 // when transition or animation not supported / duration is 0 2604 if (!TRANSITIONEND || !ANIMATIONEND || !speed || !isVisible(container)) { onTransitionEnd(); } 2605 }; 2606 })(); 2607 2608 function render (e, sliderMoved) { 2609 if (updateIndexBeforeTransform) { updateIndex(); } 2610 2611 // render when slider was moved (touch or drag) even though index may not change 2612 if (index !== indexCached || sliderMoved) { 2613 // events 2614 events.emit('indexChanged', info()); 2615 events.emit('transitionStart', info()); 2616 if (autoHeight) { doAutoHeight(); } 2617 2618 // pause autoplay when click or keydown from user 2619 if (animating && e && ['click', 'keydown'].indexOf(e.type) >= 0) { stopAutoplay(); } 2620 2621 running = true; 2622 transformCore(); 2623 } 2624 } 2625 2626 /* 2627 * Transfer prefixed properties to the same format 2628 * CSS: -Webkit-Transform => webkittransform 2629 * JS: WebkitTransform => webkittransform 2630 * @param {string} str - property 2631 * 2632 */ 2633 function strTrans (str) { 2634 return str.toLowerCase().replace(/-/g, ''); 2635 } 2636 2637 // AFTER TRANSFORM 2638 // Things need to be done after a transfer: 2639 // 1. check index 2640 // 2. add classes to visible slide 2641 // 3. disable controls buttons when reach the first/last slide in non-loop slider 2642 // 4. update nav status 2643 // 5. lazyload images 2644 // 6. update container height 2645 function onTransitionEnd (event) { 2646 // check running on gallery mode 2647 // make sure trantionend/animationend events run only once 2648 if (carousel || running) { 2649 events.emit('transitionEnd', info(event)); 2650 2651 if (!carousel && slideItemsOut.length > 0) { 2652 for (var i = 0; i < slideItemsOut.length; i++) { 2653 var item = slideItemsOut[i]; 2654 // set item positions 2655 item.style.left = ''; 2656 2657 if (ANIMATIONDELAY && TRANSITIONDELAY) { 2658 item.style[ANIMATIONDELAY] = ''; 2659 item.style[TRANSITIONDELAY] = ''; 2660 } 2661 removeClass(item, animateOut); 2662 addClass(item, animateNormal); 2663 } 2664 } 2665 2666 /* update slides, nav, controls after checking ... 2667 * => legacy browsers who don't support 'event' 2668 * have to check event first, otherwise event.target will cause an error 2669 * => or 'gallery' mode: 2670 * + event target is slide item 2671 * => or 'carousel' mode: 2672 * + event target is container, 2673 * + event.property is the same with transform attribute 2674 */ 2675 if (!event || 2676 !carousel && event.target.parentNode === container || 2677 event.target === container && strTrans(event.propertyName) === strTrans(transformAttr)) { 2678 2679 if (!updateIndexBeforeTransform) { 2680 var indexTem = index; 2681 updateIndex(); 2682 if (index !== indexTem) { 2683 events.emit('indexChanged', info()); 2684 2685 doContainerTransformSilent(); 2686 } 2687 } 2688 2689 if (nested === 'inner') { events.emit('innerLoaded', info()); } 2690 running = false; 2691 indexCached = index; 2692 } 2693 } 2694 2695 } 2696 2697 // # ACTIONS 2698 function goTo (targetIndex, e) { 2699 if (freeze) { return; } 2700 2701 // prev slideBy 2702 if (targetIndex === 'prev') { 2703 onControlsClick(e, -1); 2704 2705 // next slideBy 2706 } else if (targetIndex === 'next') { 2707 onControlsClick(e, 1); 2708 2709 // go to exact slide 2710 } else { 2711 if (running) { 2712 if (preventActionWhenRunning) { return; } else { onTransitionEnd(); } 2713 } 2714 2715 var absIndex = getAbsIndex(), 2716 indexGap = 0; 2717 2718 if (targetIndex === 'first') { 2719 indexGap = - absIndex; 2720 } else if (targetIndex === 'last') { 2721 indexGap = carousel ? slideCount - items - absIndex : slideCount - 1 - absIndex; 2722 } else { 2723 if (typeof targetIndex !== 'number') { targetIndex = parseInt(targetIndex); } 2724 2725 if (!isNaN(targetIndex)) { 2726 // from directly called goTo function 2727 if (!e) { targetIndex = Math.max(0, Math.min(slideCount - 1, targetIndex)); } 2728 2729 indexGap = targetIndex - absIndex; 2730 } 2731 } 2732 2733 // gallery: make sure new page won't overlap with current page 2734 if (!carousel && indexGap && Math.abs(indexGap) < items) { 2735 var factor = indexGap > 0 ? 1 : -1; 2736 indexGap += (index + indexGap - slideCount) >= indexMin ? slideCount * factor : slideCount * 2 * factor * -1; 2737 } 2738 2739 index += indexGap; 2740 2741 // make sure index is in range 2742 if (carousel && loop) { 2743 if (index < indexMin) { index += slideCount; } 2744 if (index > indexMax) { index -= slideCount; } 2745 } 2746 2747 // if index is changed, start rendering 2748 if (getAbsIndex(index) !== getAbsIndex(indexCached)) { 2749 render(e); 2750 } 2751 2752 } 2753 } 2754 2755 // on controls click 2756 function onControlsClick (e, dir) { 2757 if (running) { 2758 if (preventActionWhenRunning) { return; } else { onTransitionEnd(); } 2759 } 2760 var passEventObject; 2761 2762 if (!dir) { 2763 e = getEvent(e); 2764 var target = getTarget(e); 2765 2766 while (target !== controlsContainer && [prevButton, nextButton].indexOf(target) < 0) { target = target.parentNode; } 2767 2768 var targetIn = [prevButton, nextButton].indexOf(target); 2769 if (targetIn >= 0) { 2770 passEventObject = true; 2771 dir = targetIn === 0 ? -1 : 1; 2772 } 2773 } 2774 2775 if (rewind) { 2776 if (index === indexMin && dir === -1) { 2777 goTo('last', e); 2778 return; 2779 } else if (index === indexMax && dir === 1) { 2780 goTo('first', e); 2781 return; 2782 } 2783 } 2784 2785 if (dir) { 2786 index += slideBy * dir; 2787 if (autoWidth) { index = Math.floor(index); } 2788 // pass e when click control buttons or keydown 2789 render((passEventObject || (e && e.type === 'keydown')) ? e : null); 2790 } 2791 } 2792 2793 // on nav click 2794 function onNavClick (e) { 2795 if (running) { 2796 if (preventActionWhenRunning) { return; } else { onTransitionEnd(); } 2797 } 2798 2799 e = getEvent(e); 2800 var target = getTarget(e), navIndex; 2801 2802 // find the clicked nav item 2803 while (target !== navContainer && !hasAttr(target, 'data-nav')) { target = target.parentNode; } 2804 if (hasAttr(target, 'data-nav')) { 2805 var navIndex = navClicked = Number(getAttr(target, 'data-nav')), 2806 targetIndexBase = fixedWidth || autoWidth ? navIndex * slideCount / pages : navIndex * items, 2807 targetIndex = navAsThumbnails ? navIndex : Math.min(Math.ceil(targetIndexBase), slideCount - 1); 2808 goTo(targetIndex, e); 2809 2810 if (navCurrentIndex === navIndex) { 2811 if (animating) { stopAutoplay(); } 2812 navClicked = -1; // reset navClicked 2813 } 2814 } 2815 } 2816 2817 // autoplay functions 2818 function setAutoplayTimer () { 2819 autoplayTimer = setInterval(function () { 2820 onControlsClick(null, autoplayDirection); 2821 }, autoplayTimeout); 2822 2823 animating = true; 2824 } 2825 2826 function stopAutoplayTimer () { 2827 clearInterval(autoplayTimer); 2828 animating = false; 2829 } 2830 2831 function updateAutoplayButton (action, txt) { 2832 setAttrs(autoplayButton, {'data-action': action}); 2833 autoplayButton.innerHTML = autoplayHtmlStrings[0] + action + autoplayHtmlStrings[1] + txt; 2834 } 2835 2836 function startAutoplay () { 2837 setAutoplayTimer(); 2838 if (autoplayButton) { updateAutoplayButton('stop', autoplayText[1]); } 2839 } 2840 2841 function stopAutoplay () { 2842 stopAutoplayTimer(); 2843 if (autoplayButton) { updateAutoplayButton('start', autoplayText[0]); } 2844 } 2845 2846 // programaitcally play/pause the slider 2847 function play () { 2848 if (autoplay && !animating) { 2849 startAutoplay(); 2850 autoplayUserPaused = false; 2851 } 2852 } 2853 function pause () { 2854 if (animating) { 2855 stopAutoplay(); 2856 autoplayUserPaused = true; 2857 } 2858 } 2859 2860 function toggleAutoplay () { 2861 if (animating) { 2862 stopAutoplay(); 2863 autoplayUserPaused = true; 2864 } else { 2865 startAutoplay(); 2866 autoplayUserPaused = false; 2867 } 2868 } 2869 2870 function onVisibilityChange () { 2871 if (doc.hidden) { 2872 if (animating) { 2873 stopAutoplayTimer(); 2874 autoplayVisibilityPaused = true; 2875 } 2876 } else if (autoplayVisibilityPaused) { 2877 setAutoplayTimer(); 2878 autoplayVisibilityPaused = false; 2879 } 2880 } 2881 2882 function mouseoverPause () { 2883 if (animating) { 2884 stopAutoplayTimer(); 2885 autoplayHoverPaused = true; 2886 } 2887 } 2888 2889 function mouseoutRestart () { 2890 if (autoplayHoverPaused) { 2891 setAutoplayTimer(); 2892 autoplayHoverPaused = false; 2893 } 2894 } 2895 2896 // keydown events on document 2897 function onDocumentKeydown (e) { 2898 e = getEvent(e); 2899 var keyIndex = [KEYS.LEFT, KEYS.RIGHT].indexOf(e.keyCode); 2900 2901 if (keyIndex >= 0) { 2902 onControlsClick(e, keyIndex === 0 ? -1 : 1); 2903 } 2904 } 2905 2906 // on key control 2907 function onControlsKeydown (e) { 2908 e = getEvent(e); 2909 var keyIndex = [KEYS.LEFT, KEYS.RIGHT].indexOf(e.keyCode); 2910 2911 if (keyIndex >= 0) { 2912 if (keyIndex === 0) { 2913 if (!prevButton.disabled) { onControlsClick(e, -1); } 2914 } else if (!nextButton.disabled) { 2915 onControlsClick(e, 1); 2916 } 2917 } 2918 } 2919 2920 // set focus 2921 function setFocus (el) { 2922 el.focus(); 2923 } 2924 2925 // on key nav 2926 function onNavKeydown (e) { 2927 e = getEvent(e); 2928 var curElement = doc.activeElement; 2929 if (!hasAttr(curElement, 'data-nav')) { return; } 2930 2931 // var code = e.keyCode, 2932 var keyIndex = [KEYS.LEFT, KEYS.RIGHT, KEYS.ENTER, KEYS.SPACE].indexOf(e.keyCode), 2933 navIndex = Number(getAttr(curElement, 'data-nav')); 2934 2935 if (keyIndex >= 0) { 2936 if (keyIndex === 0) { 2937 if (navIndex > 0) { setFocus(navItems[navIndex - 1]); } 2938 } else if (keyIndex === 1) { 2939 if (navIndex < pages - 1) { setFocus(navItems[navIndex + 1]); } 2940 } else { 2941 navClicked = navIndex; 2942 goTo(navIndex, e); 2943 } 2944 } 2945 } 2946 2947 function getEvent (e) { 2948 e = e || win.event; 2949 return isTouchEvent(e) ? e.changedTouches[0] : e; 2950 } 2951 function getTarget (e) { 2952 return e.target || win.event.srcElement; 2953 } 2954 2955 function isTouchEvent (e) { 2956 return e.type.indexOf('touch') >= 0; 2957 } 2958 2959 function preventDefaultBehavior (e) { 2960 e.preventDefault ? e.preventDefault() : e.returnValue = false; 2961 } 2962 2963 function getMoveDirectionExpected () { 2964 return getTouchDirection(toDegree(lastPosition.y - initPosition.y, lastPosition.x - initPosition.x), swipeAngle) === options.axis; 2965 } 2966 2967 function onPanStart (e) { 2968 if (running) { 2969 if (preventActionWhenRunning) { return; } else { onTransitionEnd(); } 2970 } 2971 2972 if (autoplay && animating) { stopAutoplayTimer(); } 2973 2974 panStart = true; 2975 if (rafIndex) { 2976 caf(rafIndex); 2977 rafIndex = null; 2978 } 2979 2980 var $ = getEvent(e); 2981 events.emit(isTouchEvent(e) ? 'touchStart' : 'dragStart', info(e)); 2982 2983 if (!isTouchEvent(e) && ['img', 'a'].indexOf(getLowerCaseNodeName(getTarget(e))) >= 0) { 2984 preventDefaultBehavior(e); 2985 } 2986 2987 lastPosition.x = initPosition.x = $.clientX; 2988 lastPosition.y = initPosition.y = $.clientY; 2989 if (carousel) { 2990 translateInit = parseFloat(container.style[transformAttr].replace(transformPrefix, '')); 2991 resetDuration(container, '0s'); 2992 } 2993 } 2994 2995 function onPanMove (e) { 2996 if (panStart) { 2997 var $ = getEvent(e); 2998 lastPosition.x = $.clientX; 2999 lastPosition.y = $.clientY; 3000 3001 if (carousel) { 3002 if (!rafIndex) { rafIndex = raf(function(){ panUpdate(e); }); } 3003 } else { 3004 if (moveDirectionExpected === '?') { moveDirectionExpected = getMoveDirectionExpected(); } 3005 if (moveDirectionExpected) { preventScroll = true; } 3006 } 3007 3008 if ((typeof e.cancelable !== 'boolean' || e.cancelable) && preventScroll) { 3009 e.preventDefault(); 3010 } 3011 } 3012 } 3013 3014 function panUpdate (e) { 3015 if (!moveDirectionExpected) { 3016 panStart = false; 3017 return; 3018 } 3019 caf(rafIndex); 3020 if (panStart) { rafIndex = raf(function(){ panUpdate(e); }); } 3021 3022 if (moveDirectionExpected === '?') { moveDirectionExpected = getMoveDirectionExpected(); } 3023 if (moveDirectionExpected) { 3024 if (!preventScroll && isTouchEvent(e)) { preventScroll = true; } 3025 3026 try { 3027 if (e.type) { events.emit(isTouchEvent(e) ? 'touchMove' : 'dragMove', info(e)); } 3028 } catch(err) {} 3029 3030 var x = translateInit, 3031 dist = getDist(lastPosition, initPosition); 3032 if (!horizontal || fixedWidth || autoWidth) { 3033 x += dist; 3034 x += 'px'; 3035 } else { 3036 var percentageX = TRANSFORM ? dist * items * 100 / ((viewport + gutter) * slideCountNew): dist * 100 / (viewport + gutter); 3037 x += percentageX; 3038 x += '%'; 3039 } 3040 3041 container.style[transformAttr] = transformPrefix + x + transformPostfix; 3042 } 3043 } 3044 3045 function onPanEnd (e) { 3046 if (panStart) { 3047 if (rafIndex) { 3048 caf(rafIndex); 3049 rafIndex = null; 3050 } 3051 if (carousel) { resetDuration(container, ''); } 3052 panStart = false; 3053 3054 var $ = getEvent(e); 3055 lastPosition.x = $.clientX; 3056 lastPosition.y = $.clientY; 3057 var dist = getDist(lastPosition, initPosition); 3058 3059 if (Math.abs(dist)) { 3060 // drag vs click 3061 if (!isTouchEvent(e)) { 3062 // prevent "click" 3063 var target = getTarget(e); 3064 addEvents(target, {'click': function preventClick (e) { 3065 preventDefaultBehavior(e); 3066 removeEvents(target, {'click': preventClick}); 3067 }}); 3068 } 3069 3070 if (carousel) { 3071 rafIndex = raf(function() { 3072 if (horizontal && !autoWidth) { 3073 var indexMoved = - dist * items / (viewport + gutter); 3074 indexMoved = dist > 0 ? Math.floor(indexMoved) : Math.ceil(indexMoved); 3075 index += indexMoved; 3076 } else { 3077 var moved = - (translateInit + dist); 3078 if (moved <= 0) { 3079 index = indexMin; 3080 } else if (moved >= slidePositions[slideCountNew - 1]) { 3081 index = indexMax; 3082 } else { 3083 var i = 0; 3084 while (i < slideCountNew && moved >= slidePositions[i]) { 3085 index = i; 3086 if (moved > slidePositions[i] && dist < 0) { index += 1; } 3087 i++; 3088 } 3089 } 3090 } 3091 3092 render(e, dist); 3093 events.emit(isTouchEvent(e) ? 'touchEnd' : 'dragEnd', info(e)); 3094 }); 3095 } else { 3096 if (moveDirectionExpected) { 3097 onControlsClick(e, dist > 0 ? -1 : 1); 3098 } 3099 } 3100 } 3101 } 3102 3103 // reset 3104 if (options.preventScrollOnTouch === 'auto') { preventScroll = false; } 3105 if (swipeAngle) { moveDirectionExpected = '?'; } 3106 if (autoplay && !animating) { setAutoplayTimer(); } 3107 } 3108 3109 // === RESIZE FUNCTIONS === // 3110 // (slidePositions, index, items) => vertical_conentWrapper.height 3111 function updateContentWrapperHeight () { 3112 var wp = middleWrapper ? middleWrapper : innerWrapper; 3113 wp.style.height = slidePositions[index + items] - slidePositions[index] + 'px'; 3114 } 3115 3116 function getPages () { 3117 var rough = fixedWidth ? (fixedWidth + gutter) * slideCount / viewport : slideCount / items; 3118 return Math.min(Math.ceil(rough), slideCount); 3119 } 3120 3121 /* 3122 * 1. update visible nav items list 3123 * 2. add "hidden" attributes to previous visible nav items 3124 * 3. remove "hidden" attrubutes to new visible nav items 3125 */ 3126 function updateNavVisibility () { 3127 if (!nav || navAsThumbnails) { return; } 3128 3129 if (pages !== pagesCached) { 3130 var min = pagesCached, 3131 max = pages, 3132 fn = showElement; 3133 3134 if (pagesCached > pages) { 3135 min = pages; 3136 max = pagesCached; 3137 fn = hideElement; 3138 } 3139 3140 while (min < max) { 3141 fn(navItems[min]); 3142 min++; 3143 } 3144 3145 // cache pages 3146 pagesCached = pages; 3147 } 3148 } 3149 3150 function info (e) { 3151 return { 3152 container: container, 3153 slideItems: slideItems, 3154 navContainer: navContainer, 3155 navItems: navItems, 3156 controlsContainer: controlsContainer, 3157 hasControls: hasControls, 3158 prevButton: prevButton, 3159 nextButton: nextButton, 3160 items: items, 3161 slideBy: slideBy, 3162 cloneCount: cloneCount, 3163 slideCount: slideCount, 3164 slideCountNew: slideCountNew, 3165 index: index, 3166 indexCached: indexCached, 3167 displayIndex: getCurrentSlide(), 3168 navCurrentIndex: navCurrentIndex, 3169 navCurrentIndexCached: navCurrentIndexCached, 3170 pages: pages, 3171 pagesCached: pagesCached, 3172 sheet: sheet, 3173 isOn: isOn, 3174 event: e || {}, 3175 }; 3176 } 3177 3178 return { 3179 version: '2.9.2', 3180 getInfo: info, 3181 events: events, 3182 goTo: goTo, 3183 play: play, 3184 pause: pause, 3185 isOn: isOn, 3186 updateSliderHeight: updateInnerWrapperHeight, 3187 refresh: initSliderTransform, 3188 destroy: destroy, 3189 rebuild: function() { 3190 return tns(extend(options, optionsElements)); 3191 } 3192 }; 3193 }; 3194 3195 return tns; 3196 })();
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.