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