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