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