PageSourceSearch

https://hotelsaol.pl/live/js-theme/tiny-slider/tiny-slider.js

js hotelsaol.pl collected 2026-10-06 12:54:34 UTC 102,001 bytes, 3,210 lines download raw bytes

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

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.