PageSourceSearch

https://blackfacts.com/lib/tiny-slider/dist/tiny-slider.js

js blackfacts.com collected 2026-09-24 21:12:06 UTC 105,890 bytes, 3,671 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.