JMT Alimentation Animal
Project version : 1.0.3

Carousel

<div class="carousel container" tabindex="-1">
    <div class="home-carousel">
        <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
        <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
        <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
        <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
        <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
        <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
    </div>

    <a href="#facebookLike" class="carousel__facebook">
      <i class="icon icon--facebook"></i>
      <span>17890 personnes nous suivent sur Facebook. Et vous ?</span>
   </a>
</div>

<script>
    document.addEventListener('DOMContentLoaded', () => {
        var slider = tns({
            container: '.home-carousel',
            items: 1,
            nav: true,
            navPosition: 'bottom',
            mouseDrag: true,
            controls: false,
            autoplay: true,
            autoplayButtonOutput: false
        });
    })
</script>
<div class="carousel container" tabindex="-1">
   <div class="home-carousel">
      <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
      <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
      <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
      <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
      <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
      <a href="" tabindex="-1"><img src="https://source.unsplash.com/DTSDD968Mpw"></a>
   </div>

   <a href="#facebookLike" class="carousel__facebook">
      <i class="icon icon--facebook"></i>
      <span>17890 personnes nous suivent sur Facebook. Et vous ?</span>
   </a>
</div>

<script>
   document.addEventListener('DOMContentLoaded', () => {
      var slider = tns({
         container: '.home-carousel',
         items: 1,
         nav: true,
         navPosition: 'bottom',
         mouseDrag: true,
         controls: false,
         autoplay: true,
         autoplayButtonOutput: false
      });
   })
</script>
/* No context defined for this component. */
  • Content:
    // Version: 2.9.2
    
    .tns-outer {
       padding: 0 !important; // remove padding: clientWidth = width + padding (0) = width
       [hidden] { display: none !important; }
       [aria-controls], [data-action] { cursor: pointer; }
    }
    .tns-slider {
       -webkit-transition: all 0s;
       -moz-transition: all 0s;
       transition: all 0s;
       > .tns-item {
          font-size: 0;
         -webkit-box-sizing: border-box;
         -moz-box-sizing: border-box;
         box-sizing: border-box;
    
          img {
             width: 100%;
             height: auto;
          }
       }
    }
     
     .tns-horizontal {
       &.tns-subpixel {
         white-space: nowrap;
         > .tns-item {
           display: inline-block;
           vertical-align: top;
           white-space: normal;
         }
       }
       &.tns-no-subpixel {
         &:after {
           content: '';
           display: table;
           clear: both;
         }
         > .tns-item {
           float: left;
         }
       }
       &.tns-carousel {
         &.tns-no-subpixel {
           > .tns-item {
             margin-right: -100%;
           }
         }
       }
     }
     .tns-no-calc {
       position: relative;
       left: 0;
     }
     .tns-gallery {
       position: relative;
       left: 0;
       min-height: 1px; // make sure slider container is visible
       // overflow: hidden;
       > .tns-item {
         position: absolute;
         left: -100%;
         -webkit-transition: transform 0s, opacity 0s;
         -moz-transition: transform 0s, opacity 0s;
         transition: transform 0s, opacity 0s;
       }
       > .tns-slide-active {
         position: relative;
         left: auto !important;
       }
       > .tns-moving {
         -webkit-transition: all 0.25s;
         -moz-transition: all 0.25s;
         transition: all 0.25s;
       }
     }
     .tns-autowidth { display: inline-block; }
     .tns-lazy-img {
       -webkit-transition: opacity 0.6s;
       -moz-transition: opacity 0.6s;
       transition: opacity 0.6s;
       opacity: 0.6;
       &.tns-complete { opacity: 1; }
     }
     .tns-ah {
       -webkit-transition: height 0s;
       -moz-transition: height 0s;
       transition: height 0s;
     }
     .tns-ovh {overflow: hidden; }
     .tns-visually-hidden { position: absolute; left: -10000em; }
     .tns-transparent { opacity: 0; visibility: hidden; }
     
     .tns-fadeIn {
       opacity: 1;
       filter: alpha(opacity=100);
       z-index: 0;
     }
     .tns-normal, .tns-fadeOut {
       opacity: 0;
       filter: alpha(opacity=0);
       z-index: -1;
     }
    
     .tns-controls { outline: none }
    
    
    // *** Add style to slider
    // Layout
    
    
    .carousel.container {
      padding: 0;
      margin-bottom: 4rem;
    }
    
    .tns-ovh {
       //border: 14px solid $c-white;
       border-bottom: 14px solid $c-white;
    
       @include mediaWQuery($media-query-m) {
          border: 24px solid $c-white;
       }
    }
    // Nav
    .tns-nav {
       background: $c-white;
       display: inline-block;
      position: absolute;
      top: 100%;
    	left: 50%;
       padding: .6875rem 0;
       transform: translateX(-50%) translateY(-14px);
       font-size: 0;
    
       @include mediaWQuery($media-query-m) {
          transform: translateX(-50%) translateY(-24px);
       }
    
       &::before, &::after {
          content: '';
          position: absolute;
          left: -45px;
          bottom: 0;
          width: 45px;
          height: calc(100% - 14px);
          background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='56' height='38' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath id='a' d='M0 0h60v38H0z'/%3E%3C/defs%3E%3Cg transform='translate(-4)' fill='none' fill-rule='evenodd'%3E%3Cmask id='b' fill='%23fff'%3E%3Cuse xlink:href='%23a'/%3E%3C/mask%3E%3Cuse fill-opacity='0' fill='%23D8D8D8' xlink:href='%23a'/%3E%3Cpath d='M-385-497H785V0H395c-7 0-13.6 3-18.2 8.4l-18.1 21.2a24 24 0 0 1-18.3 8.4h-282a24 24 0 0 1-18.6-8.8L23.2 8.8A24 24 0 0 0 4.6 0H-385v-497z' fill='%23FFF' mask='url(%23b)'/%3E%3C/g%3E%3C/svg%3E");
          background-position: center;
    
          @include mediaWQuery($media-query-m) {
             height: calc(100% - 24px);
          }
       }
    
       &::after {
          left: initial;
          right: -45px;
          transform: scaleX(-1); /* Standard */
       }
    
       button {
          position: relative;
          width: 15px;
          height: 15px;
          background: #9CDAFE;
          border: 0;
          border-radius: 100%;
          transition: .2s ease;   
    
          & + button { margin-left: .5rem }
    
          &::after {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: $c-yellow;
            
            border-radius: 100%;
            z-index: -2;
            transform: translateY(0);
            opacity: 0;
            transition: opacity .2s ease, transform .2s ease;
    
            @include mediaWQuery($media-query-s) {
              background-size: 14px 15px;
              background-position: center;
              background-repeat: no-repeat;
              background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='14' height='15' xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='%234C4636' stroke-width='2' fill='none' fill-rule='evenodd' stroke-linecap='round'%3E%3Cpath stroke-linejoin='round' d='M1 7l6-6 6 6'/%3E%3Cpath d='M7 2.5v11'/%3E%3C/g%3E%3C/svg%3E");
            }
          }
    
          @include mediaWQuery($media-query-s) {
             width: 25px;
             height: 25px;
             & + button { margin-left: 1rem }
          }
    
          @include mediaWQuery($media-query-l) {
             width: 35px;
             height: 35px;
          }
    
          // * Active state
          &.tns-nav-active {
            position: relative;
            background: $c-yellow-dark;
            z-index: 10;
    
            &:hover, &:focus { background: $c-yellow-dark }
    
            &::after {
              content: '';
              opacity: 1;
              transform: translateY(-4px);
            }
          }
    
          &:hover, &:focus {
             background: $c-yellow;
          }
       }
    }
     
     
     // *** Fix a viewport issue in initialization
     .tns-vpfix {
       white-space: nowrap;
       > div, > li {
         display: inline-block;
       }
     }
     
     // *** Detecting browser capability ***
     $width: 310px;
     $height: 10px;
     $count: 70;
     $perpage: 3;
     
     .tns-t {
       &-subp2 {
         margin: 0 auto;
         width: $width;
         position: relative;
         height: $height;
         overflow: hidden;
       }
       &-ct {
         width: (100% * $count / $perpage);
         width: -webkit-calc(100% * #{$count} / #{$perpage});
         width: -moz-calc(100% * #{$count} / #{$perpage});
         width: calc(100% * #{$count} / #{$perpage});
         position: absolute;
         right: 0;
         &:after {
           content: '';
           display: table;
           clear: both;
         }
         > div {
           width: (100% / $count);
           width: -webkit-calc(100% / #{$count});
           width: -moz-calc(100% / #{$count});
           width: calc(100% / #{$count});
           height: $height;
           float: left;
         }
       }
     }
    
    .carousel {
      position: relative;
      &__facebook {
        display: none;
    
        @include mediaWQuery($media-query-xl) {
          display: flex;
          align-items: center;
          position: absolute;
          left: 0;
          top: 100%;
          max-width: 340px;
          padding: .5rem 1rem;
          background: #2D6BBF;
          border-radius: 0 50px 50px;
          line-height: 1;
          font-size: rem(16);
          color: $c-white;
          text-decoration: none;
    
          > i { margin-right: .5rem }
    
          &:hover, &:focus {
            background: darken(#2D6BBF, 10%);
            color: $c-white;
          }
        }
      }
    }
  • URL: /components/raw/carousel/carousel.scss
  • Filesystem Path: components/05-objects/05-carousels/01-carousel/carousel.scss
  • Size: 7.1 KB
  • Content:
    var tns = (function (){
       var win = window;
       
       var raf = win.requestAnimationFrame
         || win.webkitRequestAnimationFrame
         || win.mozRequestAnimationFrame
         || win.msRequestAnimationFrame
         || function(cb) { return setTimeout(cb, 16); };
       
       var win$1 = window;
       
       var caf = win$1.cancelAnimationFrame
         || win$1.mozCancelAnimationFrame
         || function(id){ clearTimeout(id); };
       
       function extend() {
         var obj, name, copy,
             target = arguments[0] || {},
             i = 1,
             length = arguments.length;
       
         for (; i < length; i++) {
           if ((obj = arguments[i]) !== null) {
             for (name in obj) {
               copy = obj[name];
       
               if (target === copy) {
                 continue;
               } else if (copy !== undefined) {
                 target[name] = copy;
               }
             }
           }
         }
         return target;
       }
       
       function checkStorageValue (value) {
         return ['true', 'false'].indexOf(value) >= 0 ? JSON.parse(value) : value;
       }
       
       function setLocalStorage(storage, key, value, access) {
         if (access) {
           try { storage.setItem(key, value); } catch (e) {}
         }
         return value;
       }
       
       function getSlideId() {
         var id = window.tnsId;
         window.tnsId = !id ? 1 : id + 1;
         
         return 'tns' + window.tnsId;
       }
       
       function getBody () {
         var doc = document,
             body = doc.body;
       
         if (!body) {
           body = doc.createElement('body');
           body.fake = true;
         }
       
         return body;
       }
       
       var docElement = document.documentElement;
       
       function setFakeBody (body) {
         var docOverflow = '';
         if (body.fake) {
           docOverflow = docElement.style.overflow;
           //avoid crashing IE8, if background image is used
           body.style.background = '';
           //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
           body.style.overflow = docElement.style.overflow = 'hidden';
           docElement.appendChild(body);
         }
       
         return docOverflow;
       }
       
       function resetFakeBody (body, docOverflow) {
         if (body.fake) {
           body.remove();
           docElement.style.overflow = docOverflow;
           // Trigger layout so kinetic scrolling isn't disabled in iOS6+
           // eslint-disable-next-line
           docElement.offsetHeight;
         }
       }
       
       // get css-calc 
       
       function calc() {
         var doc = document, 
             body = getBody(),
             docOverflow = setFakeBody(body),
             div = doc.createElement('div'), 
             result = false;
       
         body.appendChild(div);
         try {
           var str = '(10px * 10)',
               vals = ['calc' + str, '-moz-calc' + str, '-webkit-calc' + str],
               val;
           for (var i = 0; i < 3; i++) {
             val = vals[i];
             div.style.width = val;
             if (div.offsetWidth === 100) { 
               result = val.replace(str, ''); 
               break;
             }
           }
         } catch (e) {}
         
         body.fake ? resetFakeBody(body, docOverflow) : div.remove();
       
         return result;
       }
       
       // get subpixel support value
       
       function percentageLayout() {
         // check subpixel layout supporting
         var doc = document,
             body = getBody(),
             docOverflow = setFakeBody(body),
             wrapper = doc.createElement('div'),
             outer = doc.createElement('div'),
             str = '',
             count = 70,
             perPage = 3,
             supported = false;
       
         wrapper.className = "tns-t-subp2";
         outer.className = "tns-t-ct";
       
         for (var i = 0; i < count; i++) {
           str += '<div></div>';
         }
       
         outer.innerHTML = str;
         wrapper.appendChild(outer);
         body.appendChild(wrapper);
       
         supported = Math.abs(wrapper.getBoundingClientRect().left - outer.children[count - perPage].getBoundingClientRect().left) < 2;
       
         body.fake ? resetFakeBody(body, docOverflow) : wrapper.remove();
       
         return supported;
       }
       
       function mediaquerySupport () {
         var doc = document,
             body = getBody(),
             docOverflow = setFakeBody(body),
             div = doc.createElement('div'),
             style = doc.createElement('style'),
             rule = '@media all and (min-width:1px){.tns-mq-test{position:absolute}}',
             position;
       
         style.type = 'text/css';
         div.className = 'tns-mq-test';
       
         body.appendChild(style);
         body.appendChild(div);
       
         if (style.styleSheet) {
           style.styleSheet.cssText = rule;
         } else {
           style.appendChild(doc.createTextNode(rule));
         }
       
         position = window.getComputedStyle ? window.getComputedStyle(div).position : div.currentStyle['position'];
       
         body.fake ? resetFakeBody(body, docOverflow) : div.remove();
       
         return position === "absolute";
       }
       
       // create and append style sheet
       function createStyleSheet (media) {
         // Create the <style> tag
         var style = document.createElement("style");
         // style.setAttribute("type", "text/css");
       
         // Add a media (and/or media query) here if you'd like!
         // style.setAttribute("media", "screen")
         // style.setAttribute("media", "only screen and (max-width : 1024px)")
         if (media) { style.setAttribute("media", media); }
       
         // WebKit hack :(
         // style.appendChild(document.createTextNode(""));
       
         // Add the <style> element to the page
         document.querySelector('head').appendChild(style);
       
         return style.sheet ? style.sheet : style.styleSheet;
       }
       
       // cross browsers addRule method
       function addCSSRule(sheet, selector, rules, index) {
         // return raf(function() {
           'insertRule' in sheet ?
             sheet.insertRule(selector + '{' + rules + '}', index) :
             sheet.addRule(selector, rules, index);
         // });
       }
       
       // cross browsers addRule method
       function removeCSSRule(sheet, index) {
         // return raf(function() {
           'deleteRule' in sheet ?
             sheet.deleteRule(index) :
             sheet.removeRule(index);
         // });
       }
       
       function getCssRulesLength(sheet) {
         var rule = ('insertRule' in sheet) ? sheet.cssRules : sheet.rules;
         return rule.length;
       }
       
       function toDegree (y, x) {
         return Math.atan2(y, x) * (180 / Math.PI);
       }
       
       function getTouchDirection(angle, range) {
         var direction = false,
             gap = Math.abs(90 - Math.abs(angle));
             
         if (gap >= 90 - range) {
           direction = 'horizontal';
         } else if (gap <= range) {
           direction = 'vertical';
         }
       
         return direction;
       }
       
       // https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/
       function forEach (arr, callback, scope) {
         for (var i = 0, l = arr.length; i < l; i++) {
           callback.call(scope, arr[i], i);
         }
       }
       
       var classListSupport = 'classList' in document.createElement('_');
       
       var hasClass = classListSupport ?
           function (el, str) { return el.classList.contains(str); } :
           function (el, str) { return el.className.indexOf(str) >= 0; };
       
       var addClass = classListSupport ?
           function (el, str) {
             if (!hasClass(el,  str)) { el.classList.add(str); }
           } :
           function (el, str) {
             if (!hasClass(el,  str)) { el.className += ' ' + str; }
           };
       
       var removeClass = classListSupport ?
           function (el, str) {
             if (hasClass(el,  str)) { el.classList.remove(str); }
           } :
           function (el, str) {
             if (hasClass(el, str)) { el.className = el.className.replace(str, ''); }
           };
       
       function hasAttr(el, attr) {
         return el.hasAttribute(attr);
       }
       
       function getAttr(el, attr) {
         return el.getAttribute(attr);
       }
       
       function isNodeList(el) {
         // Only NodeList has the "item()" function
         return typeof el.item !== "undefined"; 
       }
       
       function setAttrs(els, attrs) {
         els = (isNodeList(els) || els instanceof Array) ? els : [els];
         if (Object.prototype.toString.call(attrs) !== '[object Object]') { return; }
       
         for (var i = els.length; i--;) {
           for(var key in attrs) {
             els[i].setAttribute(key, attrs[key]);
           }
         }
       }
       
       function removeAttrs(els, attrs) {
         els = (isNodeList(els) || els instanceof Array) ? els : [els];
         attrs = (attrs instanceof Array) ? attrs : [attrs];
       
         var attrLength = attrs.length;
         for (var i = els.length; i--;) {
           for (var j = attrLength; j--;) {
             els[i].removeAttribute(attrs[j]);
           }
         }
       }
       
       function arrayFromNodeList (nl) {
         var arr = [];
         for (var i = 0, l = nl.length; i < l; i++) {
           arr.push(nl[i]);
         }
         return arr;
       }
       
       function hideElement(el, forceHide) {
         if (el.style.display !== 'none') { el.style.display = 'none'; }
       }
       
       function showElement(el, forceHide) {
         if (el.style.display === 'none') { el.style.display = ''; }
       }
       
       function isVisible(el) {
         return window.getComputedStyle(el).display !== 'none';
       }
       
       function whichProperty(props){
         if (typeof props === 'string') {
           var arr = [props],
               Props = props.charAt(0).toUpperCase() + props.substr(1),
               prefixes = ['Webkit', 'Moz', 'ms', 'O'];
               
           prefixes.forEach(function(prefix) {
             if (prefix !== 'ms' || props === 'transform') {
               arr.push(prefix + Props);
             }
           });
       
           props = arr;
         }
       
         var el = document.createElement('fakeelement'),
             len = props.length;
         for(var i = 0; i < props.length; i++){
           var prop = props[i];
           if( el.style[prop] !== undefined ){ return prop; }
         }
       
         return false; // explicit for ie9-
       }
       
       function has3DTransforms(tf){
         if (!tf) { return false; }
         if (!window.getComputedStyle) { return false; }
         
         var doc = document,
             body = getBody(),
             docOverflow = setFakeBody(body),
             el = doc.createElement('p'),
             has3d,
             cssTF = tf.length > 9 ? '-' + tf.slice(0, -9).toLowerCase() + '-' : '';
       
         cssTF += 'transform';
       
         // Add it to the body to get the computed style
         body.insertBefore(el, null);
       
         el.style[tf] = 'translate3d(1px,1px,1px)';
         has3d = window.getComputedStyle(el).getPropertyValue(cssTF);
       
         body.fake ? resetFakeBody(body, docOverflow) : el.remove();
       
         return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
       }
       
       // get transitionend, animationend based on transitionDuration
       // @propin: string
       // @propOut: string, first-letter uppercase
       // Usage: getEndProperty('WebkitTransitionDuration', 'Transition') => webkitTransitionEnd
       function getEndProperty(propIn, propOut) {
         var endProp = false;
         if (/^Webkit/.test(propIn)) {
           endProp = 'webkit' + propOut + 'End';
         } else if (/^O/.test(propIn)) {
           endProp = 'o' + propOut + 'End';
         } else if (propIn) {
           endProp = propOut.toLowerCase() + 'end';
         }
         return endProp;
       }
       
       // Test via a getter in the options object to see if the passive property is accessed
       var supportsPassive = false;
       try {
         var opts = Object.defineProperty({}, 'passive', {
           get: function() {
             supportsPassive = true;
           }
         });
         window.addEventListener("test", null, opts);
       } catch (e) {}
       var passiveOption = supportsPassive ? { passive: true } : false;
       
       function addEvents(el, obj, preventScrolling) {
         for (var prop in obj) {
           var option = ['touchstart', 'touchmove'].indexOf(prop) >= 0 && !preventScrolling ? passiveOption : false;
           el.addEventListener(prop, obj[prop], option);
         }
       }
       
       function removeEvents(el, obj) {
         for (var prop in obj) {
           var option = ['touchstart', 'touchmove'].indexOf(prop) >= 0 ? passiveOption : false;
           el.removeEventListener(prop, obj[prop], option);
         }
       }
       
       function Events() {
         return {
           topics: {},
           on: function (eventName, fn) {
             this.topics[eventName] = this.topics[eventName] || [];
             this.topics[eventName].push(fn);
           },
           off: function(eventName, fn) {
             if (this.topics[eventName]) {
               for (var i = 0; i < this.topics[eventName].length; i++) {
                 if (this.topics[eventName][i] === fn) {
                   this.topics[eventName].splice(i, 1);
                   break;
                 }
               }
             }
           },
           emit: function (eventName, data) {
             data.type = eventName;
             if (this.topics[eventName]) {
               this.topics[eventName].forEach(function(fn) {
                 fn(data, eventName);
               });
             }
           }
         };
       }
       
       function jsTransform(element, attr, prefix, postfix, to, duration, callback) {
         var tick = Math.min(duration, 10),
             unit = (to.indexOf('%') >= 0) ? '%' : 'px',
             to = to.replace(unit, ''),
             from = Number(element.style[attr].replace(prefix, '').replace(postfix, '').replace(unit, '')),
             positionTick = (to - from) / duration * tick,
             running;
       
         setTimeout(moveElement, tick);
         function moveElement() {
           duration -= tick;
           from += positionTick;
           element.style[attr] = prefix + from + unit + postfix;
           if (duration > 0) { 
             setTimeout(moveElement, tick); 
           } else {
             callback();
           }
         }
       }
       
       // Object.keys
       if (!Object.keys) {
         Object.keys = function(object) {
           var keys = [];
           for (var name in object) {
             if (Object.prototype.hasOwnProperty.call(object, name)) {
               keys.push(name);
             }
           }
           return keys;
         };
       }
       
       // ChildNode.remove
       if(!("remove" in Element.prototype)){
         Element.prototype.remove = function(){
           if(this.parentNode) {
             this.parentNode.removeChild(this);
           }
         };
       }
       
       var tns = function(options) {
         options = extend({
           container: '.slider',
           mode: 'carousel',
           axis: 'horizontal',
           items: 1,
           gutter: 0,
           edgePadding: 0,
           fixedWidth: false,
           autoWidth: false,
           viewportMax: false,
           slideBy: 1,
           center: false,
           controls: true,
           controlsPosition: 'top',
           controlsText: ['prev', 'next'],
           controlsContainer: false,
           prevButton: false,
           nextButton: false,
           nav: true,
           navPosition: 'top',
           navContainer: false,
           navAsThumbnails: false,
           arrowKeys: false,
           speed: 300,
           autoplay: false,
           autoplayPosition: 'top',
           autoplayTimeout: 5000,
           autoplayDirection: 'forward',
           autoplayText: ['start', 'stop'],
           autoplayHoverPause: false,
           autoplayButton: false,
           autoplayButtonOutput: true,
           autoplayResetOnVisibility: true,
           animateIn: 'tns-fadeIn',
           animateOut: 'tns-fadeOut',
           animateNormal: 'tns-normal',
           animateDelay: false,
           loop: true,
           rewind: false,
           autoHeight: false,
           responsive: false,
           lazyload: false,
           lazyloadSelector: '.tns-lazy-img',
           touch: true,
           mouseDrag: false,
           swipeAngle: 15,
           nested: false,
           preventActionWhenRunning: false,
           preventScrollOnTouch: false,
           freezable: true,
           onInit: false,
           useLocalStorage: true
         }, options || {});
       
         var doc = document,
             win = window,
             KEYS = {
               ENTER: 13,
               SPACE: 32,
               LEFT: 37,
               RIGHT: 39
             },
             tnsStorage = {},
             localStorageAccess = options.useLocalStorage;
       
         if (localStorageAccess) {
           // check browser version and local storage access
           var browserInfo = navigator.userAgent;
           var uid = new Date;
       
           try {
             tnsStorage = win.localStorage;
             if (tnsStorage) {
               tnsStorage.setItem(uid, uid);
               localStorageAccess = tnsStorage.getItem(uid) == uid;
               tnsStorage.removeItem(uid);
             } else {
               localStorageAccess = false;
             }
             if (!localStorageAccess) { tnsStorage = {}; }
           } catch(e) {
             localStorageAccess = false;
           }
       
           if (localStorageAccess) {
             // remove storage when browser version changes
             if (tnsStorage['tnsApp'] && tnsStorage['tnsApp'] !== browserInfo) {
               ['tC', 'tPL', 'tMQ', 'tTf', 't3D', 'tTDu', 'tTDe', 'tADu', 'tADe', 'tTE', 'tAE'].forEach(function(item) { tnsStorage.removeItem(item); });
             }
             // update browserInfo
             localStorage['tnsApp'] = browserInfo;
           }
         }
       
         var CALC = tnsStorage['tC'] ? checkStorageValue(tnsStorage['tC']) : setLocalStorage(tnsStorage, 'tC', calc(), localStorageAccess),
             PERCENTAGELAYOUT = tnsStorage['tPL'] ? checkStorageValue(tnsStorage['tPL']) : setLocalStorage(tnsStorage, 'tPL', percentageLayout(), localStorageAccess),
             CSSMQ = tnsStorage['tMQ'] ? checkStorageValue(tnsStorage['tMQ']) : setLocalStorage(tnsStorage, 'tMQ', mediaquerySupport(), localStorageAccess),
             TRANSFORM = tnsStorage['tTf'] ? checkStorageValue(tnsStorage['tTf']) : setLocalStorage(tnsStorage, 'tTf', whichProperty('transform'), localStorageAccess),
             HAS3DTRANSFORMS = tnsStorage['t3D'] ? checkStorageValue(tnsStorage['t3D']) : setLocalStorage(tnsStorage, 't3D', has3DTransforms(TRANSFORM), localStorageAccess),
             TRANSITIONDURATION = tnsStorage['tTDu'] ? checkStorageValue(tnsStorage['tTDu']) : setLocalStorage(tnsStorage, 'tTDu', whichProperty('transitionDuration'), localStorageAccess),
             TRANSITIONDELAY = tnsStorage['tTDe'] ? checkStorageValue(tnsStorage['tTDe']) : setLocalStorage(tnsStorage, 'tTDe', whichProperty('transitionDelay'), localStorageAccess),
             ANIMATIONDURATION = tnsStorage['tADu'] ? checkStorageValue(tnsStorage['tADu']) : setLocalStorage(tnsStorage, 'tADu', whichProperty('animationDuration'), localStorageAccess),
             ANIMATIONDELAY = tnsStorage['tADe'] ? checkStorageValue(tnsStorage['tADe']) : setLocalStorage(tnsStorage, 'tADe', whichProperty('animationDelay'), localStorageAccess),
             TRANSITIONEND = tnsStorage['tTE'] ? checkStorageValue(tnsStorage['tTE']) : setLocalStorage(tnsStorage, 'tTE', getEndProperty(TRANSITIONDURATION, 'Transition'), localStorageAccess),
             ANIMATIONEND = tnsStorage['tAE'] ? checkStorageValue(tnsStorage['tAE']) : setLocalStorage(tnsStorage, 'tAE', getEndProperty(ANIMATIONDURATION, 'Animation'), localStorageAccess);
       
         // get element nodes from selectors
         var supportConsoleWarn = win.console && typeof win.console.warn === "function",
             tnsList = ['container', 'controlsContainer', 'prevButton', 'nextButton', 'navContainer', 'autoplayButton'],
             optionsElements = {};
       
         tnsList.forEach(function(item) {
           if (typeof options[item] === 'string') {
             var str = options[item],
                 el = doc.querySelector(str);
             optionsElements[item] = str;
       
             if (el && el.nodeName) {
               options[item] = el;
             } else {
               if (supportConsoleWarn) { console.warn('Can\'t find', options[item]); }
               return;
             }
           }
         });
       
         // make sure at least 1 slide
         if (options.container.children.length < 1) {
           if (supportConsoleWarn) { console.warn('No slides found in', options.container); }
           return;
          }
       
         // update options
         var responsive = options.responsive,
             nested = options.nested,
             carousel = options.mode === 'carousel' ? true : false;
       
         if (responsive) {
           // apply responsive[0] to options and remove it
           if (0 in responsive) {
             options = extend(options, responsive[0]);
             delete responsive[0];
           }
       
           var responsiveTem = {};
           for (var key in responsive) {
             var val = responsive[key];
             // update responsive
             // from: 300: 2
             // to:
             //   300: {
             //     items: 2
             //   }
             val = typeof val === 'number' ? {items: val} : val;
             responsiveTem[key] = val;
           }
           responsive = responsiveTem;
           responsiveTem = null;
         }
       
         // update options
         function updateOptions (obj) {
           for (var key in obj) {
             if (!carousel) {
               if (key === 'slideBy') { obj[key] = 'page'; }
               if (key === 'edgePadding') { obj[key] = false; }
               if (key === 'autoHeight') { obj[key] = false; }
             }
       
             // update responsive options
             if (key === 'responsive') { updateOptions(obj[key]); }
           }
         }
         if (!carousel) { updateOptions(options); }
       
       
         // === define and set variables ===
         if (!carousel) {
           options.axis = 'horizontal';
           options.slideBy = 'page';
           options.edgePadding = false;
       
           var animateIn = options.animateIn,
               animateOut = options.animateOut,
               animateDelay = options.animateDelay,
               animateNormal = options.animateNormal;
         }
       
         var horizontal = options.axis === 'horizontal' ? true : false,
             outerWrapper = doc.createElement('div'),
             innerWrapper = doc.createElement('div'),
             middleWrapper,
             container = options.container,
             containerParent = container.parentNode,
             containerHTML = container.outerHTML,
             slideItems = container.children,
             slideCount = slideItems.length,
             breakpointZone,
             windowWidth = getWindowWidth(),
             isOn = false;
         if (responsive) { setBreakpointZone(); }
         if (carousel) { container.className += ' tns-vpfix'; }
       
         // fixedWidth: viewport > rightBoundary > indexMax
         var autoWidth = options.autoWidth,
             fixedWidth = getOption('fixedWidth'),
             edgePadding = getOption('edgePadding'),
             gutter = getOption('gutter'),
             viewport = getViewportWidth(),
             center = getOption('center'),
             items = !autoWidth ? Math.floor(getOption('items')) : 1,
             slideBy = getOption('slideBy'),
             viewportMax = options.viewportMax || options.fixedWidthViewportWidth,
             arrowKeys = getOption('arrowKeys'),
             speed = getOption('speed'),
             rewind = options.rewind,
             loop = rewind ? false : options.loop,
             autoHeight = getOption('autoHeight'),
             controls = getOption('controls'),
             controlsText = getOption('controlsText'),
             nav = getOption('nav'),
             touch = getOption('touch'),
             mouseDrag = getOption('mouseDrag'),
             autoplay = getOption('autoplay'),
             autoplayTimeout = getOption('autoplayTimeout'),
             autoplayText = getOption('autoplayText'),
             autoplayHoverPause = getOption('autoplayHoverPause'),
             autoplayResetOnVisibility = getOption('autoplayResetOnVisibility'),
             sheet = createStyleSheet(),
             lazyload = options.lazyload,
             lazyloadSelector = options.lazyloadSelector,
             slidePositions, // collection of slide positions
             slideItemsOut = [],
             cloneCount = loop ? getCloneCountForLoop() : 0,
             slideCountNew = !carousel ? slideCount + cloneCount : slideCount + cloneCount * 2,
             hasRightDeadZone = (fixedWidth || autoWidth) && !loop ? true : false,
             rightBoundary = fixedWidth ? getRightBoundary() : null,
             updateIndexBeforeTransform = (!carousel || !loop) ? true : false,
             // transform
             transformAttr = horizontal ? 'left' : 'top',
             transformPrefix = '',
             transformPostfix = '',
             // index
             getIndexMax = (function () {
               if (fixedWidth) {
                 return function() { return center && !loop ? slideCount - 1 : Math.ceil(- rightBoundary / (fixedWidth + gutter)); };
               } else if (autoWidth) {
                 return function() {
                   for (var i = slideCountNew; i--;) {
                     if (slidePositions[i] >= - rightBoundary) { return i; }
                   }
                 };
               } else {
                 return function() {
                   if (center && carousel && !loop) {
                     return slideCount - 1;
                   } else {
                     return loop || carousel ? Math.max(0, slideCountNew - Math.ceil(items)) : slideCountNew - 1;
                   }
                 };
               }
             })(),
             index = getStartIndex(getOption('startIndex')),
             indexCached = index,
             displayIndex = getCurrentSlide(),
             indexMin = 0,
             indexMax = !autoWidth ? getIndexMax() : null,
             // resize
             resizeTimer,
             preventActionWhenRunning = options.preventActionWhenRunning,
             swipeAngle = options.swipeAngle,
             moveDirectionExpected = swipeAngle ? '?' : true,
             running = false,
             onInit = options.onInit,
             events = new Events(),
             // id, class
             newContainerClasses = ' tns-slider tns-' + options.mode,
             slideId = container.id || getSlideId(),
             disable = getOption('disable'),
             disabled = false,
             freezable = options.freezable,
             freeze = freezable && !autoWidth ? getFreeze() : false,
             frozen = false,
             controlsEvents = {
               'click': onControlsClick,
               'keydown': onControlsKeydown
             },
             navEvents = {
               'click': onNavClick,
               'keydown': onNavKeydown
             },
             hoverEvents = {
               'mouseover': mouseoverPause,
               'mouseout': mouseoutRestart
             },
             visibilityEvent = {'visibilitychange': onVisibilityChange},
             docmentKeydownEvent = {'keydown': onDocumentKeydown},
             touchEvents = {
               'touchstart': onPanStart,
               'touchmove': onPanMove,
               'touchend': onPanEnd,
               'touchcancel': onPanEnd
             }, dragEvents = {
               'mousedown': onPanStart,
               'mousemove': onPanMove,
               'mouseup': onPanEnd,
               'mouseleave': onPanEnd
             },
             hasControls = hasOption('controls'),
             hasNav = hasOption('nav'),
             navAsThumbnails = autoWidth ? true : options.navAsThumbnails,
             hasAutoplay = hasOption('autoplay'),
             hasTouch = hasOption('touch'),
             hasMouseDrag = hasOption('mouseDrag'),
             slideActiveClass = 'tns-slide-active',
             imgCompleteClass = 'tns-complete',
             imgEvents = {
               'load': onImgLoaded,
               'error': onImgFailed
             },
             imgsComplete,
             liveregionCurrent,
             preventScroll = options.preventScrollOnTouch === 'force' ? true : false;
       
         // controls
         if (hasControls) {
           var controlsContainer = options.controlsContainer,
               controlsContainerHTML = options.controlsContainer ? options.controlsContainer.outerHTML : '',
               prevButton = options.prevButton,
               nextButton = options.nextButton,
               prevButtonHTML = options.prevButton ? options.prevButton.outerHTML : '',
               nextButtonHTML = options.nextButton ? options.nextButton.outerHTML : '',
               prevIsButton,
               nextIsButton;
         }
       
         // nav
         if (hasNav) {
           var navContainer = options.navContainer,
               navContainerHTML = options.navContainer ? options.navContainer.outerHTML : '',
               navItems,
               pages = autoWidth ? slideCount : getPages(),
               pagesCached = 0,
               navClicked = -1,
               navCurrentIndex = getCurrentNavIndex(),
               navCurrentIndexCached = navCurrentIndex,
               navActiveClass = 'tns-nav-active',
               navStr = 'Carousel Page ',
               navStrCurrent = ' (Current Slide)';
         }
       
         // autoplay
         if (hasAutoplay) {
           var autoplayDirection = options.autoplayDirection === 'forward' ? 1 : -1,
               autoplayButton = options.autoplayButton,
               autoplayButtonHTML = options.autoplayButton ? options.autoplayButton.outerHTML : '',
               autoplayHtmlStrings = ['<span class=\'tns-visually-hidden\'>', ' animation</span>'],
               autoplayTimer,
               animating,
               autoplayHoverPaused,
               autoplayUserPaused,
               autoplayVisibilityPaused;
         }
       
         if (hasTouch || hasMouseDrag) {
           var initPosition = {},
               lastPosition = {},
               translateInit,
               disX,
               disY,
               panStart = false,
               rafIndex,
               getDist = horizontal ?
                 function(a, b) { return a.x - b.x; } :
                 function(a, b) { return a.y - b.y; };
         }
       
         // disable slider when slidecount <= items
         if (!autoWidth) { resetVariblesWhenDisable(disable || freeze); }
       
         if (TRANSFORM) {
           transformAttr = TRANSFORM;
           transformPrefix = 'translate';
       
           if (HAS3DTRANSFORMS) {
             transformPrefix += horizontal ? '3d(' : '3d(0px, ';
             transformPostfix = horizontal ? ', 0px, 0px)' : ', 0px)';
           } else {
             transformPrefix += horizontal ? 'X(' : 'Y(';
             transformPostfix = ')';
           }
       
         }
       
         if (carousel) { container.className = container.className.replace('tns-vpfix', ''); }
         initStructure();
         initSheet();
         initSliderTransform();
       
         // === COMMON FUNCTIONS === //
         function resetVariblesWhenDisable (condition) {
           if (condition) {
             controls = nav = touch = mouseDrag = arrowKeys = autoplay = autoplayHoverPause = autoplayResetOnVisibility = false;
           }
         }
       
         function getCurrentSlide () {
           var tem = carousel ? index - cloneCount : index;
           while (tem < 0) { tem += slideCount; }
           return tem%slideCount + 1;
         }
       
         function getStartIndex (ind) {
           ind = ind ? Math.max(0, Math.min(loop ? slideCount - 1 : slideCount - items, ind)) : 0;
           return carousel ? ind + cloneCount : ind;
         }
       
         function getAbsIndex (i) {
           if (i == null) { i = index; }
       
           if (carousel) { i -= cloneCount; }
           while (i < 0) { i += slideCount; }
       
           return Math.floor(i%slideCount);
         }
       
         function getCurrentNavIndex () {
           var absIndex = getAbsIndex(),
               result;
       
           result = navAsThumbnails ? absIndex :
             fixedWidth || autoWidth ? Math.ceil((absIndex + 1) * pages / slideCount - 1) :
                 Math.floor(absIndex / items);
       
           // set active nav to the last one when reaches the right edge
           if (!loop && carousel && index === indexMax) { result = pages - 1; }
       
           return result;
         }
       
         function getItemsMax () {
           // fixedWidth or autoWidth while viewportMax is not available
           if (autoWidth || (fixedWidth && !viewportMax)) {
             return slideCount - 1;
           // most cases
           } else {
             var str = fixedWidth ? 'fixedWidth' : 'items',
                 arr = [];
       
             if (fixedWidth || options[str] < slideCount) { arr.push(options[str]); }
       
             if (responsive) {
               for (var bp in responsive) {
                 var tem = responsive[bp][str];
                 if (tem && (fixedWidth || tem < slideCount)) { arr.push(tem); }
               }
             }
       
             if (!arr.length) { arr.push(0); }
       
             return Math.ceil(fixedWidth ? viewportMax / Math.min.apply(null, arr) : Math.max.apply(null, arr));
           }
         }
       
         function getCloneCountForLoop () {
           var itemsMax = getItemsMax(),
               result = carousel ? Math.ceil((itemsMax * 5 - slideCount)/2) : (itemsMax * 4 - slideCount);
           result = Math.max(itemsMax, result);
       
           return hasOption('edgePadding') ? result + 1 : result;
         }
       
         function getWindowWidth () {
           return win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth;
         }
       
         function getInsertPosition (pos) {
           return pos === 'top' ? 'afterbegin' : 'beforeend';
         }
       
         function getClientWidth (el) {
           if (el == null) { return; }
           var div = doc.createElement('div'), rect, width;
           el.appendChild(div);
           rect = div.getBoundingClientRect();
           width = rect.right - rect.left;
           div.remove();
           return width || getClientWidth(el.parentNode);
         }
       
         function getViewportWidth () {
           var gap = edgePadding ? edgePadding * 2 - gutter : 0;
           return getClientWidth(containerParent) - gap;
         }
       
         function hasOption (item) {
           if (options[item]) {
             return true;
           } else {
             if (responsive) {
               for (var bp in responsive) {
                 if (responsive[bp][item]) { return true; }
               }
             }
             return false;
           }
         }
       
         // get option:
         // fixed width: viewport, fixedWidth, gutter => items
         // others: window width => all variables
         // all: items => slideBy
         function getOption (item, ww) {
           if (ww == null) { ww = windowWidth; }
       
           if (item === 'items' && fixedWidth) {
             return Math.floor((viewport + gutter) / (fixedWidth + gutter)) || 1;
       
           } else {
             var result = options[item];
       
             if (responsive) {
               for (var bp in responsive) {
                 // bp: convert string to number
                 if (ww >= parseInt(bp)) {
                   if (item in responsive[bp]) { result = responsive[bp][item]; }
                 }
               }
             }
       
             if (item === 'slideBy' && result === 'page') { result = getOption('items'); }
             if (!carousel && (item === 'slideBy' || item === 'items')) { result = Math.floor(result); }
       
             return result;
           }
         }
       
         function getSlideMarginLeft (i) {
           return CALC ?
             CALC + '(' + i * 100 + '% / ' + slideCountNew + ')' :
             i * 100 / slideCountNew + '%';
         }
       
         function getInnerWrapperStyles (edgePaddingTem, gutterTem, fixedWidthTem, speedTem, autoHeightBP) {
           var str = '';
       
           if (edgePaddingTem !== undefined) {
             var gap = edgePaddingTem;
             if (gutterTem) { gap -= gutterTem; }
             str = horizontal ?
               'margin: 0 ' + gap + 'px 0 ' + edgePaddingTem + 'px;' :
               'margin: ' + edgePaddingTem + 'px 0 ' + gap + 'px 0;';
           } else if (gutterTem && !fixedWidthTem) {
             var gutterTemUnit = '-' + gutterTem + 'px',
                 dir = horizontal ? gutterTemUnit + ' 0 0' : '0 ' + gutterTemUnit + ' 0';
             str = 'margin: 0 ' + dir + ';';
           }
       
           if (!carousel && autoHeightBP && TRANSITIONDURATION && speedTem) { str += getTransitionDurationStyle(speedTem); }
           return str;
         }
       
         function getContainerWidth (fixedWidthTem, gutterTem, itemsTem) {
           if (fixedWidthTem) {
             return (fixedWidthTem + gutterTem) * slideCountNew + 'px';
           } else {
             return CALC ?
               CALC + '(' + slideCountNew * 100 + '% / ' + itemsTem + ')' :
               slideCountNew * 100 / itemsTem + '%';
           }
         }
       
         function getSlideWidthStyle (fixedWidthTem, gutterTem, itemsTem) {
           var width;
       
           if (fixedWidthTem) {
             width = (fixedWidthTem + gutterTem) + 'px';
           } else {
             if (!carousel) { itemsTem = Math.floor(itemsTem); }
             var dividend = carousel ? slideCountNew : itemsTem;
             width = CALC ?
               CALC + '(100% / ' + dividend + ')' :
               100 / dividend + '%';
           }
       
           width = 'width:' + width;
       
           // inner slider: overwrite outer slider styles
           return nested !== 'inner' ? width + ';' : width + ' !important;';
         }
       
         function getSlideGutterStyle (gutterTem) {
           var str = '';
       
           // gutter maybe interger || 0
           // so can't use 'if (gutter)'
           if (gutterTem !== false) {
             var prop = horizontal ? 'padding-' : 'margin-',
                 dir = horizontal ? 'right' : 'bottom';
             str = prop +  dir + ': ' + gutterTem + 'px;';
           }
       
           return str;
         }
       
         function getCSSPrefix (name, num) {
           var prefix = name.substring(0, name.length - num).toLowerCase();
           if (prefix) { prefix = '-' + prefix + '-'; }
       
           return prefix;
         }
       
         function getTransitionDurationStyle (speed) {
           return getCSSPrefix(TRANSITIONDURATION, 18) + 'transition-duration:' + speed / 1000 + 's;';
         }
       
         function getAnimationDurationStyle (speed) {
           return getCSSPrefix(ANIMATIONDURATION, 17) + 'animation-duration:' + speed / 1000 + 's;';
         }
       
         function initStructure () {
           var classOuter = 'tns-outer',
               classInner = 'tns-inner',
               hasGutter = hasOption('gutter');
       
           outerWrapper.className = classOuter;
           innerWrapper.className = classInner;
           outerWrapper.id = slideId + '-ow';
           innerWrapper.id = slideId + '-iw';
       
           // set container properties
           if (container.id === '') { container.id = slideId; }
           newContainerClasses += PERCENTAGELAYOUT || autoWidth ? ' tns-subpixel' : ' tns-no-subpixel';
           newContainerClasses += CALC ? ' tns-calc' : ' tns-no-calc';
           if (autoWidth) { newContainerClasses += ' tns-autowidth'; }
           newContainerClasses += ' tns-' + options.axis;
           container.className += newContainerClasses;
       
           // add constrain layer for carousel
           if (carousel) {
             middleWrapper = doc.createElement('div');
             middleWrapper.id = slideId + '-mw';
             middleWrapper.className = 'tns-ovh';
       
             outerWrapper.appendChild(middleWrapper);
             middleWrapper.appendChild(innerWrapper);
           } else {
             outerWrapper.appendChild(innerWrapper);
           }
       
           if (autoHeight) {
             var wp = middleWrapper ? middleWrapper : innerWrapper;
             wp.className += ' tns-ah';
           }
       
           containerParent.insertBefore(outerWrapper, container);
           innerWrapper.appendChild(container);
       
           // add id, class, aria attributes
           // before clone slides
           forEach(slideItems, function(item, i) {
             addClass(item, 'tns-item');
             if (!item.id) { item.id = slideId + '-item' + i; }
             if (!carousel && animateNormal) { addClass(item, animateNormal); }
             setAttrs(item, {
               'aria-hidden': 'true',
               'tabindex': '-1'
             });
           });
       
           // ## clone slides
           // carousel: n + slides + n
           // gallery:      slides + n
           if (cloneCount) {
             var fragmentBefore = doc.createDocumentFragment(),
                 fragmentAfter = doc.createDocumentFragment();
       
             for (var j = cloneCount; j--;) {
               var num = j%slideCount,
                   cloneFirst = slideItems[num].cloneNode(true);
               removeAttrs(cloneFirst, 'id');
               fragmentAfter.insertBefore(cloneFirst, fragmentAfter.firstChild);
       
               if (carousel) {
                 var cloneLast = slideItems[slideCount - 1 - num].cloneNode(true);
                 removeAttrs(cloneLast, 'id');
                 fragmentBefore.appendChild(cloneLast);
               }
             }
       
             container.insertBefore(fragmentBefore, container.firstChild);
             container.appendChild(fragmentAfter);
             slideItems = container.children;
           }
       
         }
       
         function initSliderTransform () {
           // ## images loaded/failed
           if (hasOption('autoHeight') || autoWidth || !horizontal) {
             var imgs = container.querySelectorAll('img');
       
             // add img load event listener
             forEach(imgs, function(img) {
               var src = img.src;
       
               if (!lazyload) {
                 // not data img
                 if (src && src.indexOf('data:image') < 0) {
                   img.src = '';
                   addEvents(img, imgEvents);
                   addClass(img, 'loading');
       
                   img.src = src;
                 // data img
                 } else {
                   imgLoaded(img);
                 }
               }
             });
       
             // set imgsComplete
             raf(function(){ imgsLoadedCheck(arrayFromNodeList(imgs), function() { imgsComplete = true; }); });
       
             // reset imgs for auto height: check visible imgs only
             if (hasOption('autoHeight')) { imgs = getImageArray(index, Math.min(index + items - 1, slideCountNew - 1)); }
       
             lazyload ? initSliderTransformStyleCheck() : raf(function(){ imgsLoadedCheck(arrayFromNodeList(imgs), initSliderTransformStyleCheck); });
       
           } else {
             // set container transform property
             if (carousel) { doContainerTransformSilent(); }
       
             // update slider tools and events
             initTools();
             initEvents();
           }
         }
       
         function initSliderTransformStyleCheck () {
           if (autoWidth) {
             // check styles application
             var num = loop ? index : slideCount - 1;
       
             (function stylesApplicationCheck() {
               var left = slideItems[num].getBoundingClientRect().left;
               var right = slideItems[num - 1].getBoundingClientRect().right;
       
               (Math.abs(left - right) <= 1) ?
                 initSliderTransformCore() :
                 setTimeout(function(){ stylesApplicationCheck(); }, 16);
             })();
       
           } else {
             initSliderTransformCore();
           }
         }
       
       
         function initSliderTransformCore () {
           // run Fn()s which are rely on image loading
           if (!horizontal || autoWidth) {
             setSlidePositions();
       
             if (autoWidth) {
               rightBoundary = getRightBoundary();
               if (freezable) { freeze = getFreeze(); }
               indexMax = getIndexMax(); // <= slidePositions, rightBoundary <=
               resetVariblesWhenDisable(disable || freeze);
             } else {
               updateContentWrapperHeight();
             }
           }
       
           // set container transform property
           if (carousel) { doContainerTransformSilent(); }
       
           // update slider tools and events
           initTools();
           initEvents();
         }
       
         function initSheet () {
           // gallery:
           // set animation classes and left value for gallery slider
           if (!carousel) {
             for (var i = index, l = index + Math.min(slideCount, items); i < l; i++) {
               var item = slideItems[i];
               item.style.left = (i - index) * 100 / items + '%';
               addClass(item, animateIn);
               removeClass(item, animateNormal);
             }
           }
       
           // #### LAYOUT
       
           // ## INLINE-BLOCK VS FLOAT
       
           // ## PercentageLayout:
           // slides: inline-block
           // remove blank space between slides by set font-size: 0
       
           // ## Non PercentageLayout:
           // slides: float
           //         margin-right: -100%
           //         margin-left: ~
       
           // Resource: https://docs.google.com/spreadsheets/d/147up245wwTXeQYve3BRSAD4oVcvQmuGsFteJOeA5xNQ/edit?usp=sharing
           if (horizontal) {
             if (PERCENTAGELAYOUT || autoWidth) {
               addCSSRule(sheet, '#' + slideId + ' > .tns-item', 'font-size:' + win.getComputedStyle(slideItems[0]).fontSize + ';', getCssRulesLength(sheet));
               addCSSRule(sheet, '#' + slideId, 'font-size:0;', getCssRulesLength(sheet));
             } else if (carousel) {
               forEach(slideItems, function (slide, i) {
                 slide.style.marginLeft = getSlideMarginLeft(i);
               });
             }
           }
       
       
           // ## BASIC STYLES
           if (CSSMQ) {
             // middle wrapper style
             if (TRANSITIONDURATION) {
               var str = middleWrapper && options.autoHeight ? getTransitionDurationStyle(options.speed) : '';
               addCSSRule(sheet, '#' + slideId + '-mw', str, getCssRulesLength(sheet));
             }
       
             // inner wrapper styles
             str = getInnerWrapperStyles(options.edgePadding, options.gutter, options.fixedWidth, options.speed, options.autoHeight);
             addCSSRule(sheet, '#' + slideId + '-iw', str, getCssRulesLength(sheet));
       
             // container styles
             if (carousel) {
               str = horizontal && !autoWidth ? 'width:' + getContainerWidth(options.fixedWidth, options.gutter, options.items) + ';' : '';
               if (TRANSITIONDURATION) { str += getTransitionDurationStyle(speed); }
               addCSSRule(sheet, '#' + slideId, str, getCssRulesLength(sheet));
             }
       
             // slide styles
             str = horizontal && !autoWidth ? getSlideWidthStyle(options.fixedWidth, options.gutter, options.items) : '';
             if (options.gutter) { str += getSlideGutterStyle(options.gutter); }
             // set gallery items transition-duration
             if (!carousel) {
               if (TRANSITIONDURATION) { str += getTransitionDurationStyle(speed); }
               if (ANIMATIONDURATION) { str += getAnimationDurationStyle(speed); }
             }
             if (str) { addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet)); }
       
           // non CSS mediaqueries: IE8
           // ## update inner wrapper, container, slides if needed
           // set inline styles for inner wrapper & container
           // insert stylesheet (one line) for slides only (since slides are many)
           } else {
             // middle wrapper styles
             update_carousel_transition_duration();
       
             // inner wrapper styles
             innerWrapper.style.cssText = getInnerWrapperStyles(edgePadding, gutter, fixedWidth, autoHeight);
       
             // container styles
             if (carousel && horizontal && !autoWidth) {
               container.style.width = getContainerWidth(fixedWidth, gutter, items);
             }
       
             // slide styles
             var str = horizontal && !autoWidth ? getSlideWidthStyle(fixedWidth, gutter, items) : '';
             if (gutter) { str += getSlideGutterStyle(gutter); }
       
             // append to the last line
             if (str) { addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet)); }
           }
       
           // ## MEDIAQUERIES
           if (responsive && CSSMQ) {
             for (var bp in responsive) {
               // bp: convert string to number
               bp = parseInt(bp);
       
               var opts = responsive[bp],
                   str = '',
                   middleWrapperStr = '',
                   innerWrapperStr = '',
                   containerStr = '',
                   slideStr = '',
                   itemsBP = !autoWidth ? getOption('items', bp) : null,
                   fixedWidthBP = getOption('fixedWidth', bp),
                   speedBP = getOption('speed', bp),
                   edgePaddingBP = getOption('edgePadding', bp),
                   autoHeightBP = getOption('autoHeight', bp),
                   gutterBP = getOption('gutter', bp);
       
               // middle wrapper string
               if (TRANSITIONDURATION && middleWrapper && getOption('autoHeight', bp) && 'speed' in opts) {
                 middleWrapperStr = '#' + slideId + '-mw{' + getTransitionDurationStyle(speedBP) + '}';
               }
       
               // inner wrapper string
               if ('edgePadding' in opts || 'gutter' in opts) {
                 innerWrapperStr = '#' + slideId + '-iw{' + getInnerWrapperStyles(edgePaddingBP, gutterBP, fixedWidthBP, speedBP, autoHeightBP) + '}';
               }
       
               // container string
               if (carousel && horizontal && !autoWidth && ('fixedWidth' in opts || 'items' in opts || (fixedWidth && 'gutter' in opts))) {
                 containerStr = 'width:' + getContainerWidth(fixedWidthBP, gutterBP, itemsBP) + ';';
               }
               if (TRANSITIONDURATION && 'speed' in opts) {
                 containerStr += getTransitionDurationStyle(speedBP);
               }
               if (containerStr) {
                 containerStr = '#' + slideId + '{' + containerStr + '}';
               }
       
               // slide string
               if ('fixedWidth' in opts || (fixedWidth && 'gutter' in opts) || !carousel && 'items' in opts) {
                 slideStr += getSlideWidthStyle(fixedWidthBP, gutterBP, itemsBP);
               }
               if ('gutter' in opts) {
                 slideStr += getSlideGutterStyle(gutterBP);
               }
               // set gallery items transition-duration
               if (!carousel && 'speed' in opts) {
                 if (TRANSITIONDURATION) { slideStr += getTransitionDurationStyle(speedBP); }
                 if (ANIMATIONDURATION) { slideStr += getAnimationDurationStyle(speedBP); }
               }
               if (slideStr) { slideStr = '#' + slideId + ' > .tns-item{' + slideStr + '}'; }
       
               // add up
               str = middleWrapperStr + innerWrapperStr + containerStr + slideStr;
       
               if (str) {
                 sheet.insertRule('@media (min-width: ' + bp / 16 + 'em) {' + str + '}', sheet.cssRules.length);
               }
             }
           }
         }
       
         function initTools () {
           // == slides ==
           updateSlideStatus();
       
           // == live region ==
           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>');
           liveregionCurrent = outerWrapper.querySelector('.tns-liveregion .current');
       
           // == autoplayInit ==
           if (hasAutoplay) {
             var txt = autoplay ? 'stop' : 'start';
             if (autoplayButton) {
               setAttrs(autoplayButton, {'data-action': txt});
             } else if (options.autoplayButtonOutput) {
               outerWrapper.insertAdjacentHTML(getInsertPosition(options.autoplayPosition), '<button type="button" data-action="' + txt + '">' + autoplayHtmlStrings[0] + txt + autoplayHtmlStrings[1] + autoplayText[0] + '</button>');
               autoplayButton = outerWrapper.querySelector('[data-action]');
             }
       
             // add event
             if (autoplayButton) {
               addEvents(autoplayButton, {'click': toggleAutoplay});
             }
       
             if (autoplay) {
               startAutoplay();
               if (autoplayHoverPause) { addEvents(container, hoverEvents); }
               if (autoplayResetOnVisibility) { addEvents(container, visibilityEvent); }
             }
           }
       
           // == navInit ==
           if (hasNav) {
             var initIndex = !carousel ? 0 : cloneCount;
             // customized nav
             // will not hide the navs in case they're thumbnails
             if (navContainer) {
                setAttrs(navContainer,
                {
                  'aria-label': 'Carousel Pagination',
                  'tabindex' : '-1'
                });
               navItems = navContainer.children;
               forEach(navItems, function(item, i) {
                 setAttrs(item, {
                   'data-nav': i,
                   'tabindex': '-1',
                   'aria-label': navStr + (i + 1),
                   'aria-controls': slideId,
                 });
               });
       
             // generated nav
             } else {
               var navHtml = '',
                   hiddenStr = navAsThumbnails ? '' : 'style="display:none"';
               for (var i = 0; i < slideCount; i++) {
                 // hide nav items by default
                 navHtml += '<button type="button" data-nav="' + i +'" tabindex="-1" aria-controls="' + slideId + '" ' + hiddenStr + ' aria-label="' + navStr + (i + 1) +'"></button>';
               }
               navHtml = '<div class="tns-nav" aria-label="Carousel Pagination">' + navHtml + '</div>';
               outerWrapper.insertAdjacentHTML(getInsertPosition(options.navPosition), navHtml);
       
               navContainer = outerWrapper.querySelector('.tns-nav');
               navItems = navContainer.children;
             }
       
             updateNavVisibility();
       
             // add transition
             if (TRANSITIONDURATION) {
               var prefix = TRANSITIONDURATION.substring(0, TRANSITIONDURATION.length - 18).toLowerCase(),
                   str = 'transition: all ' + speed / 1000 + 's';
       
               if (prefix) {
                 str = '-' + prefix + '-' + str;
               }
       
               addCSSRule(sheet, '[aria-controls^=' + slideId + '-item]', str, getCssRulesLength(sheet));
             }
       
             setAttrs(navItems[navCurrentIndex], {'aria-label': navStr + (navCurrentIndex + 1) + navStrCurrent}, 'tabindex', '-1');
             removeAttrs(navItems[navCurrentIndex], 'tabindex');
             addClass(navItems[navCurrentIndex], navActiveClass);
       
             // add events
             addEvents(navContainer, navEvents);
           }
       
       
       
           // == controlsInit ==
           if (hasControls) {
             if (!controlsContainer && (!prevButton || !nextButton)) {
               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>');
       
               controlsContainer = outerWrapper.querySelector('.tns-controls');
             }
       
             if (!prevButton || !nextButton) {
               prevButton = controlsContainer.children[0];
               nextButton = controlsContainer.children[1];
             }
       
             if (options.controlsContainer) {
               setAttrs(controlsContainer, {
                 'aria-label': 'Carousel Navigation',
                 'tabindex': '0'
               });
             }
       
             if (options.controlsContainer || (options.prevButton && options.nextButton)) {
               setAttrs([prevButton, nextButton], {
                 'aria-controls': slideId,
                 'tabindex': '-1',
               });
             }
       
             if (options.controlsContainer || (options.prevButton && options.nextButton)) {
               setAttrs(prevButton, {'data-controls' : 'prev'});
               setAttrs(nextButton, {'data-controls' : 'next'});
             }
       
             prevIsButton = isButton(prevButton);
             nextIsButton = isButton(nextButton);
       
             updateControlsStatus();
       
             // add events
             if (controlsContainer) {
               addEvents(controlsContainer, controlsEvents);
             } else {
               addEvents(prevButton, controlsEvents);
               addEvents(nextButton, controlsEvents);
             }
           }
       
           // hide tools if needed
           disableUI();
         }
       
         function initEvents () {
           // add events
           if (carousel && TRANSITIONEND) {
             var eve = {};
             eve[TRANSITIONEND] = onTransitionEnd;
             addEvents(container, eve);
           }
       
           if (touch) { addEvents(container, touchEvents, options.preventScrollOnTouch); }
           if (mouseDrag) { addEvents(container, dragEvents); }
           if (arrowKeys) { addEvents(doc, docmentKeydownEvent); }
       
           if (nested === 'inner') {
             events.on('outerResized', function () {
               resizeTasks();
               events.emit('innerLoaded', info());
             });
           } else if (responsive || fixedWidth || autoWidth || autoHeight || !horizontal) {
             addEvents(win, {'resize': onResize});
           }
       
           if (autoHeight) {
             if (nested === 'outer') {
               events.on('innerLoaded', doAutoHeight);
             } else if (!disable) { doAutoHeight(); }
           }
       
           doLazyLoad();
           if (disable) { disableSlider(); } else if (freeze) { freezeSlider(); }
       
           events.on('indexChanged', additionalUpdates);
           if (nested === 'inner') { events.emit('innerLoaded', info()); }
           if (typeof onInit === 'function') { onInit(info()); }
           isOn = true;
         }
       
         function destroy () {
           // sheet
           sheet.disabled = true;
           if (sheet.ownerNode) { sheet.ownerNode.remove(); }
       
           // remove win event listeners
           removeEvents(win, {'resize': onResize});
       
           // arrowKeys, controls, nav
           if (arrowKeys) { removeEvents(doc, docmentKeydownEvent); }
           if (controlsContainer) { removeEvents(controlsContainer, controlsEvents); }
           if (navContainer) { removeEvents(navContainer, navEvents); }
       
           // autoplay
           removeEvents(container, hoverEvents);
           removeEvents(container, visibilityEvent);
           if (autoplayButton) { removeEvents(autoplayButton, {'click': toggleAutoplay}); }
           if (autoplay) { clearInterval(autoplayTimer); }
       
           // container
           if (carousel && TRANSITIONEND) {
             var eve = {};
             eve[TRANSITIONEND] = onTransitionEnd;
             removeEvents(container, eve);
           }
           if (touch) { removeEvents(container, touchEvents); }
           if (mouseDrag) { removeEvents(container, dragEvents); }
       
           // cache Object values in options && reset HTML
           var htmlList = [containerHTML, controlsContainerHTML, prevButtonHTML, nextButtonHTML, navContainerHTML, autoplayButtonHTML];
       
           tnsList.forEach(function(item, i) {
             var el = item === 'container' ? outerWrapper : options[item];
       
             if (typeof el === 'object' && el) {
               var prevEl = el.previousElementSibling ? el.previousElementSibling : false,
                   parentEl = el.parentNode;
               el.outerHTML = htmlList[i];
               options[item] = prevEl ? prevEl.nextElementSibling : parentEl.firstElementChild;
             }
           });
       
       
           // reset variables
           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;
           // check variables
           // [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); } });
       
           for (var a in this) {
             if (a !== 'rebuild') { this[a] = null; }
           }
           isOn = false;
         }
       
       // === ON RESIZE ===
         // responsive || fixedWidth || autoWidth || !horizontal
         function onResize (e) {
           raf(function(){ resizeTasks(getEvent(e)); });
         }
       
         function resizeTasks (e) {
           if (!isOn) { return; }
           if (nested === 'outer') { events.emit('outerResized', info(e)); }
           windowWidth = getWindowWidth();
           var bpChanged,
               breakpointZoneTem = breakpointZone,
               needContainerTransform = false;
       
           if (responsive) {
             setBreakpointZone();
             bpChanged = breakpointZoneTem !== breakpointZone;
             // if (hasRightDeadZone) { needContainerTransform = true; } // *?
             if (bpChanged) { events.emit('newBreakpointStart', info(e)); }
           }
       
           var indChanged,
               itemsChanged,
               itemsTem = items,
               disableTem = disable,
               freezeTem = freeze,
               arrowKeysTem = arrowKeys,
               controlsTem = controls,
               navTem = nav,
               touchTem = touch,
               mouseDragTem = mouseDrag,
               autoplayTem = autoplay,
               autoplayHoverPauseTem = autoplayHoverPause,
               autoplayResetOnVisibilityTem = autoplayResetOnVisibility,
               indexTem = index;
       
           if (bpChanged) {
             var fixedWidthTem = fixedWidth,
                 autoHeightTem = autoHeight,
                 controlsTextTem = controlsText,
                 centerTem = center,
                 autoplayTextTem = autoplayText;
       
             if (!CSSMQ) {
               var gutterTem = gutter,
                   edgePaddingTem = edgePadding;
             }
           }
       
           // get option:
           // fixed width: viewport, fixedWidth, gutter => items
           // others: window width => all variables
           // all: items => slideBy
           arrowKeys = getOption('arrowKeys');
           controls = getOption('controls');
           nav = getOption('nav');
           touch = getOption('touch');
           center = getOption('center');
           mouseDrag = getOption('mouseDrag');
           autoplay = getOption('autoplay');
           autoplayHoverPause = getOption('autoplayHoverPause');
           autoplayResetOnVisibility = getOption('autoplayResetOnVisibility');
       
           if (bpChanged) {
             disable = getOption('disable');
             fixedWidth = getOption('fixedWidth');
             speed = getOption('speed');
             autoHeight = getOption('autoHeight');
             controlsText = getOption('controlsText');
             autoplayText = getOption('autoplayText');
             autoplayTimeout = getOption('autoplayTimeout');
       
             if (!CSSMQ) {
               edgePadding = getOption('edgePadding');
               gutter = getOption('gutter');
             }
           }
           // update options
           resetVariblesWhenDisable(disable);
       
           viewport = getViewportWidth(); // <= edgePadding, gutter
           if ((!horizontal || autoWidth) && !disable) {
             setSlidePositions();
             if (!horizontal) {
               updateContentWrapperHeight(); // <= setSlidePositions
               needContainerTransform = true;
             }
           }
           if (fixedWidth || autoWidth) {
             rightBoundary = getRightBoundary(); // autoWidth: <= viewport, slidePositions, gutter
                                                 // fixedWidth: <= viewport, fixedWidth, gutter
             indexMax = getIndexMax(); // autoWidth: <= rightBoundary, slidePositions
                                       // fixedWidth: <= rightBoundary, fixedWidth, gutter
           }
       
           if (bpChanged || fixedWidth) {
             items = getOption('items');
             slideBy = getOption('slideBy');
             itemsChanged = items !== itemsTem;
       
             if (itemsChanged) {
               if (!fixedWidth && !autoWidth) { indexMax = getIndexMax(); } // <= items
               // check index before transform in case
               // slider reach the right edge then items become bigger
               updateIndex();
             }
           }
       
           if (bpChanged) {
             if (disable !== disableTem) {
               if (disable) {
                 disableSlider();
               } else {
                 enableSlider(); // <= slidePositions, rightBoundary, indexMax
               }
             }
           }
       
           if (freezable && (bpChanged || fixedWidth || autoWidth)) {
             freeze = getFreeze(); // <= autoWidth: slidePositions, gutter, viewport, rightBoundary
                                   // <= fixedWidth: fixedWidth, gutter, rightBoundary
                                   // <= others: items
       
             if (freeze !== freezeTem) {
               if (freeze) {
                 doContainerTransform(getContainerTransformValue(getStartIndex(0)));
                 freezeSlider();
               } else {
                 unfreezeSlider();
                 needContainerTransform = true;
               }
             }
           }
       
           resetVariblesWhenDisable(disable || freeze); // controls, nav, touch, mouseDrag, arrowKeys, autoplay, autoplayHoverPause, autoplayResetOnVisibility
           if (!autoplay) { autoplayHoverPause = autoplayResetOnVisibility = false; }
       
           if (arrowKeys !== arrowKeysTem) {
             arrowKeys ?
               addEvents(doc, docmentKeydownEvent) :
               removeEvents(doc, docmentKeydownEvent);
           }
           if (controls !== controlsTem) {
             if (controls) {
               if (controlsContainer) {
                 showElement(controlsContainer);
               } else {
                 if (prevButton) { showElement(prevButton); }
                 if (nextButton) { showElement(nextButton); }
               }
             } else {
               if (controlsContainer) {
                 hideElement(controlsContainer);
               } else {
                 if (prevButton) { hideElement(prevButton); }
                 if (nextButton) { hideElement(nextButton); }
               }
             }
           }
           if (nav !== navTem) {
             nav ?
               showElement(navContainer) :
               hideElement(navContainer);
           }
           if (touch !== touchTem) {
             touch ?
               addEvents(container, touchEvents, options.preventScrollOnTouch) :
               removeEvents(container, touchEvents);
           }
           if (mouseDrag !== mouseDragTem) {
             mouseDrag ?
               addEvents(container, dragEvents) :
               removeEvents(container, dragEvents);
           }
           if (autoplay !== autoplayTem) {
             if (autoplay) {
               if (autoplayButton) { showElement(autoplayButton); }
               if (!animating && !autoplayUserPaused) { startAutoplay(); }
             } else {
               if (autoplayButton) { hideElement(autoplayButton); }
               if (animating) { stopAutoplay(); }
             }
           }
           if (autoplayHoverPause !== autoplayHoverPauseTem) {
             autoplayHoverPause ?
               addEvents(container, hoverEvents) :
               removeEvents(container, hoverEvents);
           }
           if (autoplayResetOnVisibility !== autoplayResetOnVisibilityTem) {
             autoplayResetOnVisibility ?
               addEvents(doc, visibilityEvent) :
               removeEvents(doc, visibilityEvent);
           }
       
           if (bpChanged) {
             if (fixedWidth !== fixedWidthTem || center !== centerTem) { needContainerTransform = true; }
       
             if (autoHeight !== autoHeightTem) {
               if (!autoHeight) { innerWrapper.style.height = ''; }
             }
       
             if (controls && controlsText !== controlsTextTem) {
               prevButton.innerHTML = controlsText[0];
               nextButton.innerHTML = controlsText[1];
             }
       
             if (autoplayButton && autoplayText !== autoplayTextTem) {
               var i = autoplay ? 1 : 0,
                   html = autoplayButton.innerHTML,
                   len = html.length - autoplayTextTem[i].length;
               if (html.substring(len) === autoplayTextTem[i]) {
                 autoplayButton.innerHTML = html.substring(0, len) + autoplayText[i];
               }
             }
           } else {
             if (center && (fixedWidth || autoWidth)) { needContainerTransform = true; }
           }
       
           if (itemsChanged || fixedWidth && !autoWidth) {
             pages = getPages();
             updateNavVisibility();
           }
       
           indChanged = index !== indexTem;
           if (indChanged) {
             events.emit('indexChanged', info());
             needContainerTransform = true;
           } else if (itemsChanged) {
             if (!indChanged) { additionalUpdates(); }
           } else if (fixedWidth || autoWidth) {
             doLazyLoad();
             updateSlideStatus();
             updateLiveRegion();
           }
       
           if (itemsChanged && !carousel) { updateGallerySlidePositions(); }
       
           if (!disable && !freeze) {
             // non-mediaqueries: IE8
             if (bpChanged && !CSSMQ) {
               // middle wrapper styles
       
               // inner wrapper styles
               if (edgePadding !== edgePaddingTem || gutter !== gutterTem) {
                 innerWrapper.style.cssText = getInnerWrapperStyles(edgePadding, gutter, fixedWidth, speed, autoHeight);
               }
       
               if (horizontal) {
                 // container styles
                 if (carousel) {
                   container.style.width = getContainerWidth(fixedWidth, gutter, items);
                 }
       
                 // slide styles
                 var str = getSlideWidthStyle(fixedWidth, gutter, items) +
                           getSlideGutterStyle(gutter);
       
                 // remove the last line and
                 // add new styles
                 removeCSSRule(sheet, getCssRulesLength(sheet) - 1);
                 addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet));
               }
             }
       
             // auto height
             if (autoHeight) { doAutoHeight(); }
       
             if (needContainerTransform) {
               doContainerTransformSilent();
               indexCached = index;
             }
           }
       
           if (bpChanged) { events.emit('newBreakpointEnd', info(e)); }
         }
       
       
       
       
       
         // === INITIALIZATION FUNCTIONS === //
         function getFreeze () {
           if (!fixedWidth && !autoWidth) {
             var a = center ? items - (items - 1) / 2 : items;
             return  slideCount <= a;
           }
       
           var width = fixedWidth ? (fixedWidth + gutter) * slideCount : slidePositions[slideCount],
               vp = edgePadding ? viewport + edgePadding * 2 : viewport + gutter;
       
           if (center) {
             vp -= fixedWidth ? (viewport - fixedWidth) / 2 : (viewport - (slidePositions[index + 1] - slidePositions[index] - gutter)) / 2;
           }
       
           return width <= vp;
         }
       
         function setBreakpointZone () {
           breakpointZone = 0;
           for (var bp in responsive) {
             bp = parseInt(bp); // convert string to number
             if (windowWidth >= bp) { breakpointZone = bp; }
           }
         }
       
         // (slideBy, indexMin, indexMax) => index
         var updateIndex = (function () {
           return loop ?
             carousel ?
               // loop + carousel
               function () {
                 var leftEdge = indexMin,
                     rightEdge = indexMax;
       
                 leftEdge += slideBy;
                 rightEdge -= slideBy;
       
                 // adjust edges when has edge paddings
                 // or fixed-width slider with extra space on the right side
                 if (edgePadding) {
                   leftEdge += 1;
                   rightEdge -= 1;
                 } else if (fixedWidth) {
                   if ((viewport + gutter)%(fixedWidth + gutter)) { rightEdge -= 1; }
                 }
       
                 if (cloneCount) {
                   if (index > rightEdge) {
                     index -= slideCount;
                   } else if (index < leftEdge) {
                     index += slideCount;
                   }
                 }
               } :
               // loop + gallery
               function() {
                 if (index > indexMax) {
                   while (index >= indexMin + slideCount) { index -= slideCount; }
                 } else if (index < indexMin) {
                   while (index <= indexMax - slideCount) { index += slideCount; }
                 }
               } :
             // non-loop
             function() {
               index = Math.max(indexMin, Math.min(indexMax, index));
             };
         })();
       
         function disableUI () {
           if (!autoplay && autoplayButton) { hideElement(autoplayButton); }
           if (!nav && navContainer) { hideElement(navContainer); }
           if (!controls) {
             if (controlsContainer) {
               hideElement(controlsContainer);
             } else {
               if (prevButton) { hideElement(prevButton); }
               if (nextButton) { hideElement(nextButton); }
             }
           }
         }
       
         function enableUI () {
           if (autoplay && autoplayButton) { showElement(autoplayButton); }
           if (nav && navContainer) { showElement(navContainer); }
           if (controls) {
             if (controlsContainer) {
               showElement(controlsContainer);
             } else {
               if (prevButton) { showElement(prevButton); }
               if (nextButton) { showElement(nextButton); }
             }
           }
         }
       
         function freezeSlider () {
           if (frozen) { return; }
       
           // remove edge padding from inner wrapper
           if (edgePadding) { innerWrapper.style.margin = '0px'; }
       
           // add class tns-transparent to cloned slides
           if (cloneCount) {
             var str = 'tns-transparent';
             for (var i = cloneCount; i--;) {
               if (carousel) { addClass(slideItems[i], str); }
               addClass(slideItems[slideCountNew - i - 1], str);
             }
           }
       
           // update tools
           disableUI();
       
           frozen = true;
         }
       
         function unfreezeSlider () {
           if (!frozen) { return; }
       
           // restore edge padding for inner wrapper
           // for mordern browsers
           if (edgePadding && CSSMQ) { innerWrapper.style.margin = ''; }
       
           // remove class tns-transparent to cloned slides
           if (cloneCount) {
             var str = 'tns-transparent';
             for (var i = cloneCount; i--;) {
               if (carousel) { removeClass(slideItems[i], str); }
               removeClass(slideItems[slideCountNew - i - 1], str);
             }
           }
       
           // update tools
           enableUI();
       
           frozen = false;
         }
       
         function disableSlider () {
           if (disabled) { return; }
       
           sheet.disabled = true;
           container.className = container.className.replace(newContainerClasses.substring(1), '');
           removeAttrs(container, ['style']);
           if (loop) {
             for (var j = cloneCount; j--;) {
               if (carousel) { hideElement(slideItems[j]); }
               hideElement(slideItems[slideCountNew - j - 1]);
             }
           }
       
           // vertical slider
           if (!horizontal || !carousel) { removeAttrs(innerWrapper, ['style']); }
       
           // gallery
           if (!carousel) {
             for (var i = index, l = index + slideCount; i < l; i++) {
               var item = slideItems[i];
               removeAttrs(item, ['style']);
               removeClass(item, animateIn);
               removeClass(item, animateNormal);
             }
           }
       
           // update tools
           disableUI();
       
           disabled = true;
         }
       
         function enableSlider () {
           if (!disabled) { return; }
       
           sheet.disabled = false;
           container.className += newContainerClasses;
           doContainerTransformSilent();
       
           if (loop) {
             for (var j = cloneCount; j--;) {
               if (carousel) { showElement(slideItems[j]); }
               showElement(slideItems[slideCountNew - j - 1]);
             }
           }
       
           // gallery
           if (!carousel) {
             for (var i = index, l = index + slideCount; i < l; i++) {
               var item = slideItems[i],
                   classN = i < index + items ? animateIn : animateNormal;
               item.style.left = (i - index) * 100 / items + '%';
               addClass(item, classN);
             }
           }
       
           // update tools
           enableUI();
       
           disabled = false;
         }
       
         function updateLiveRegion () {
           var str = getLiveRegionStr();
           if (liveregionCurrent.innerHTML !== str) { liveregionCurrent.innerHTML = str; }
         }
       
         function getLiveRegionStr () {
           var arr = getVisibleSlideRange(),
               start = arr[0] + 1,
               end = arr[1] + 1;
           return start === end ? start + '' : start + ' to ' + end;
         }
       
         function getVisibleSlideRange (val) {
           if (val == null) { val = getContainerTransformValue(); }
           var start = index, end, rangestart, rangeend;
       
           // get range start, range end for autoWidth and fixedWidth
           if (center || edgePadding) {
             if (autoWidth || fixedWidth) {
               rangestart = - (parseFloat(val) + edgePadding);
               rangeend = rangestart + viewport + edgePadding * 2;
             }
           } else {
             if (autoWidth) {
               rangestart = slidePositions[index];
               rangeend = rangestart + viewport;
             }
           }
       
           // get start, end
           // - check auto width
           if (autoWidth) {
             slidePositions.forEach(function(point, i) {
               if (i < slideCountNew) {
                 if ((center || edgePadding) && point <= rangestart + 0.5) { start = i; }
                 if (rangeend - point >= 0.5) { end = i; }
               }
             });
       
           // - check percentage width, fixed width
           } else {
       
             if (fixedWidth) {
               var cell = fixedWidth + gutter;
               if (center || edgePadding) {
                 start = Math.floor(rangestart/cell);
                 end = Math.ceil(rangeend/cell - 1);
               } else {
                 end = start + Math.ceil(viewport/cell) - 1;
               }
       
             } else {
               if (center || edgePadding) {
                 var a = items - 1;
                 if (center) {
                   start -= a / 2;
                   end = index + a / 2;
                 } else {
                   end = index + a;
                 }
       
                 if (edgePadding) {
                   var b = edgePadding * items / viewport;
                   start -= b;
                   end += b;
                 }
       
                 start = Math.floor(start);
                 end = Math.ceil(end);
               } else {
                 end = start + items - 1;
               }
             }
       
             start = Math.max(start, 0);
             end = Math.min(end, slideCountNew - 1);
           }
       
           return [start, end];
         }
       
         function doLazyLoad () {
           if (lazyload && !disable) {
             var arg = getVisibleSlideRange();
             arg.push(lazyloadSelector);
       
             getImageArray.apply(null, arg).forEach(function (img) {
               if (!hasClass(img, imgCompleteClass)) {
                 // stop propagation transitionend event to container
                 var eve = {};
                 eve[TRANSITIONEND] = function (e) { e.stopPropagation(); };
                 addEvents(img, eve);
       
                 addEvents(img, imgEvents);
       
                 // update src
                 img.src = getAttr(img, 'data-src');
       
                 // update srcset
                 var srcset = getAttr(img, 'data-srcset');
                 if (srcset) { img.srcset = srcset; }
       
                 addClass(img, 'loading');
               }
             });
           }
         }
       
         function onImgLoaded (e) {
           imgLoaded(getTarget(e));
         }
       
         function onImgFailed (e) {
           imgFailed(getTarget(e));
         }
       
         function imgLoaded (img) {
           addClass(img, 'loaded');
           imgCompleted(img);
         }
       
         function imgFailed (img) {
           addClass(img, 'failed');
           imgCompleted(img);
         }
       
         function imgCompleted (img) {
           addClass(img, imgCompleteClass);
           removeClass(img, 'loading');
           removeEvents(img, imgEvents);
         }
       
         function getImageArray (start, end, imgSelector) {
           var imgs = [];
           if (!imgSelector) { imgSelector = 'img'; }
       
           while (start <= end) {
             forEach(slideItems[start].querySelectorAll(imgSelector), function (img) { imgs.push(img); });
             start++;
           }
       
           return imgs;
         }
       
         // check if all visible images are loaded
         // and update container height if it's done
         function doAutoHeight () {
           var imgs = getImageArray.apply(null, getVisibleSlideRange());
           raf(function(){ imgsLoadedCheck(imgs, updateInnerWrapperHeight); });
         }
       
         function imgsLoadedCheck (imgs, cb) {
           // execute callback function if all images are complete
           if (imgsComplete) { return cb(); }
       
           // check image classes
           imgs.forEach(function (img, index) {
             if (!lazyload && img.complete) { imgCompleted(img); } // Check image.complete
             if (hasClass(img, imgCompleteClass)) { imgs.splice(index, 1); }
           });
       
           // execute callback function if selected images are all complete
           if (!imgs.length) { return cb(); }
       
           // otherwise execute this functiona again
           raf(function(){ imgsLoadedCheck(imgs, cb); });
         }
       
         function additionalUpdates () {
           doLazyLoad();
           updateSlideStatus();
           updateLiveRegion();
           updateControlsStatus();
           updateNavStatus();
         }
       
       
         function update_carousel_transition_duration () {
           if (carousel && autoHeight) {
             middleWrapper.style[TRANSITIONDURATION] = speed / 1000 + 's';
           }
         }
       
         function getMaxSlideHeight (slideStart, slideRange) {
           var heights = [];
           for (var i = slideStart, l = Math.min(slideStart + slideRange, slideCountNew); i < l; i++) {
             heights.push(slideItems[i].offsetHeight);
           }
       
           return Math.max.apply(null, heights);
         }
       
         // update inner wrapper height
         // 1. get the max-height of the visible slides
         // 2. set transitionDuration to speed
         // 3. update inner wrapper height to max-height
         // 4. set transitionDuration to 0s after transition done
         function updateInnerWrapperHeight () {
           var maxHeight = autoHeight ? getMaxSlideHeight(index, items) : getMaxSlideHeight(cloneCount, slideCount),
               wp = middleWrapper ? middleWrapper : innerWrapper;
       
           if (wp.style.height !== maxHeight) { wp.style.height = maxHeight + 'px'; }
         }
       
         // get the distance from the top edge of the first slide to each slide
         // (init) => slidePositions
         function setSlidePositions () {
           slidePositions = [0];
           var attr = horizontal ? 'left' : 'top',
               attr2 = horizontal ? 'right' : 'bottom',
               base = slideItems[0].getBoundingClientRect()[attr];
       
           forEach(slideItems, function(item, i) {
             // skip the first slide
             if (i) { slidePositions.push(item.getBoundingClientRect()[attr] - base); }
             // add the end edge
             if (i === slideCountNew - 1) { slidePositions.push(item.getBoundingClientRect()[attr2] - base); }
           });
         }
       
         // update slide
         function updateSlideStatus () {
           var range = getVisibleSlideRange(),
               start = range[0],
               end = range[1];
       
           forEach(slideItems, function(item, i) {
             // show slides
             if (i >= start && i <= end) {
               if (hasAttr(item, 'aria-hidden')) {
                 removeAttrs(item, ['aria-hidden', 'tabindex']);
                 addClass(item, slideActiveClass);
               }
             // hide slides
             } else {
               if (!hasAttr(item, 'aria-hidden')) {
                 setAttrs(item, {
                   'aria-hidden': 'true',
                   'tabindex': '-1'
                 });
                 removeClass(item, slideActiveClass);
               }
             }
           });
         }
       
         // gallery: update slide position
         function updateGallerySlidePositions () {
           var l = index + Math.min(slideCount, items);
           for (var i = slideCountNew; i--;) {
             var item = slideItems[i];
       
             if (i >= index && i < l) {
               // add transitions to visible slides when adjusting their positions
               addClass(item, 'tns-moving');
       
               item.style.left = (i - index) * 100 / items + '%';
               addClass(item, animateIn);
               removeClass(item, animateNormal);
             } else if (item.style.left) {
               item.style.left = '';
               addClass(item, animateNormal);
               removeClass(item, animateIn);
             }
       
             // remove outlet animation
             removeClass(item, animateOut);
           }
       
           // removing '.tns-moving'
           setTimeout(function() {
             forEach(slideItems, function(el) {
               removeClass(el, 'tns-moving');
             });
           }, 300);
         }
       
         // set tabindex on Nav
         function updateNavStatus () {
           // get current nav
           if (nav) {
             navCurrentIndex = navClicked >= 0 ? navClicked : getCurrentNavIndex();
             navClicked = -1;
       
             if (navCurrentIndex !== navCurrentIndexCached) {
               var navPrev = navItems[navCurrentIndexCached],
                   navCurrent = navItems[navCurrentIndex];
       
               setAttrs(navPrev, {
                 'tabindex': '-1',
                 'aria-label': navStr + (navCurrentIndexCached + 1)
               });
               removeClass(navPrev, navActiveClass);
       
               setAttrs(navCurrent, {'aria-label': navStr + (navCurrentIndex + 1) + navStrCurrent});
               //removeAttrs(navCurrent, 'tabindex');
               addClass(navCurrent, navActiveClass);
       
               navCurrentIndexCached = navCurrentIndex;
             }
           }
         }
       
         function getLowerCaseNodeName (el) {
           return el.nodeName.toLowerCase();
         }
       
         function isButton (el) {
           return getLowerCaseNodeName(el) === 'button';
         }
       
         function isAriaDisabled (el) {
           return el.getAttribute('aria-disabled') === 'true';
         }
       
         function disEnableElement (isButton, el, val) {
           if (isButton) {
             el.disabled = val;
           } else {
             el.setAttribute('aria-disabled', val.toString());
           }
         }
       
         // set 'disabled' to true on controls when reach the edges
         function updateControlsStatus () {
           if (!controls || rewind || loop) { return; }
       
           var prevDisabled = (prevIsButton) ? prevButton.disabled : isAriaDisabled(prevButton),
               nextDisabled = (nextIsButton) ? nextButton.disabled : isAriaDisabled(nextButton),
               disablePrev = (index <= indexMin) ? true : false,
               disableNext = (!rewind && index >= indexMax) ? true : false;
       
           if (disablePrev && !prevDisabled) {
             disEnableElement(prevIsButton, prevButton, true);
           }
           if (!disablePrev && prevDisabled) {
             disEnableElement(prevIsButton, prevButton, false);
           }
           if (disableNext && !nextDisabled) {
             disEnableElement(nextIsButton, nextButton, true);
           }
           if (!disableNext && nextDisabled) {
             disEnableElement(nextIsButton, nextButton, false);
           }
         }
       
         // set duration
         function resetDuration (el, str) {
           if (TRANSITIONDURATION) { el.style[TRANSITIONDURATION] = str; }
         }
       
         function getSliderWidth () {
           return fixedWidth ? (fixedWidth + gutter) * slideCountNew : slidePositions[slideCountNew];
         }
       
         function getCenterGap (num) {
           if (num == null) { num = index; }
       
           var gap = edgePadding ? gutter : 0;
           return autoWidth ? ((viewport - gap) - (slidePositions[num + 1] - slidePositions[num] - gutter))/2 :
             fixedWidth ? (viewport - fixedWidth) / 2 :
               (items - 1) / 2;
         }
       
         function getRightBoundary () {
           var gap = edgePadding ? gutter : 0,
               result = (viewport + gap) - getSliderWidth();
       
           if (center && !loop) {
             result = fixedWidth ? - (fixedWidth + gutter) * (slideCountNew - 1) - getCenterGap() :
               getCenterGap(slideCountNew - 1) - slidePositions[slideCountNew - 1];
           }
           if (result > 0) { result = 0; }
       
           return result;
         }
       
         function getContainerTransformValue (num) {
           if (num == null) { num = index; }
       
           var val;
           if (horizontal && !autoWidth) {
             if (fixedWidth) {
               val = - (fixedWidth + gutter) * num;
               if (center) { val += getCenterGap(); }
             } else {
               var denominator = TRANSFORM ? slideCountNew : items;
               if (center) { num -= getCenterGap(); }
               val = - num * 100 / denominator;
             }
           } else {
             val = - slidePositions[num];
             if (center && autoWidth) {
               val += getCenterGap();
             }
           }
       
           if (hasRightDeadZone) { val = Math.max(val, rightBoundary); }
       
           val += (horizontal && !autoWidth && !fixedWidth) ? '%' : 'px';
       
           return val;
         }
       
         function doContainerTransformSilent (val) {
           resetDuration(container, '0s');
           doContainerTransform(val);
         }
       
         function doContainerTransform (val) {
           if (val == null) { val = getContainerTransformValue(); }
           container.style[transformAttr] = transformPrefix + val + transformPostfix;
         }
       
         function animateSlide (number, classOut, classIn, isOut) {
           var l = number + items;
           if (!loop) { l = Math.min(l, slideCountNew); }
       
           for (var i = number; i < l; i++) {
               var item = slideItems[i];
       
             // set item positions
             if (!isOut) { item.style.left = (i - index) * 100 / items + '%'; }
       
             if (animateDelay && TRANSITIONDELAY) {
               item.style[TRANSITIONDELAY] = item.style[ANIMATIONDELAY] = animateDelay * (i - number) / 1000 + 's';
             }
             removeClass(item, classOut);
             addClass(item, classIn);
       
             if (isOut) { slideItemsOut.push(item); }
           }
         }
       
         // make transfer after click/drag:
         // 1. change 'transform' property for mordern browsers
         // 2. change 'left' property for legacy browsers
         var transformCore = (function () {
           return carousel ?
             function () {
               resetDuration(container, '');
               if (TRANSITIONDURATION || !speed) {
                 // for morden browsers with non-zero duration or
                 // zero duration for all browsers
                 doContainerTransform();
                 // run fallback function manually
                 // when duration is 0 / container is hidden
                 if (!speed || !isVisible(container)) { onTransitionEnd(); }
       
               } else {
                 // for old browser with non-zero duration
                 jsTransform(container, transformAttr, transformPrefix, transformPostfix, getContainerTransformValue(), speed, onTransitionEnd);
               }
       
               if (!horizontal) { updateContentWrapperHeight(); }
             } :
             function () {
               slideItemsOut = [];
       
               var eve = {};
               eve[TRANSITIONEND] = eve[ANIMATIONEND] = onTransitionEnd;
               removeEvents(slideItems[indexCached], eve);
               addEvents(slideItems[index], eve);
       
               animateSlide(indexCached, animateIn, animateOut, true);
               animateSlide(index, animateNormal, animateIn);
       
               // run fallback function manually
               // when transition or animation not supported / duration is 0
               if (!TRANSITIONEND || !ANIMATIONEND || !speed || !isVisible(container)) { onTransitionEnd(); }
             };
         })();
       
         function render (e, sliderMoved) {
           if (updateIndexBeforeTransform) { updateIndex(); }
       
           // render when slider was moved (touch or drag) even though index may not change
           if (index !== indexCached || sliderMoved) {
             // events
             events.emit('indexChanged', info());
             events.emit('transitionStart', info());
             if (autoHeight) { doAutoHeight(); }
       
             // pause autoplay when click or keydown from user
             if (animating && e && ['click', 'keydown'].indexOf(e.type) >= 0) { stopAutoplay(); }
       
             running = true;
             transformCore();
           }
         }
       
         /*
          * Transfer prefixed properties to the same format
          * CSS: -Webkit-Transform => webkittransform
          * JS: WebkitTransform => webkittransform
          * @param {string} str - property
          *
          */
         function strTrans (str) {
           return str.toLowerCase().replace(/-/g, '');
         }
       
         // AFTER TRANSFORM
         // Things need to be done after a transfer:
         // 1. check index
         // 2. add classes to visible slide
         // 3. disable controls buttons when reach the first/last slide in non-loop slider
         // 4. update nav status
         // 5. lazyload images
         // 6. update container height
         function onTransitionEnd (event) {
           // check running on gallery mode
           // make sure trantionend/animationend events run only once
           if (carousel || running) {
             events.emit('transitionEnd', info(event));
       
             if (!carousel && slideItemsOut.length > 0) {
               for (var i = 0; i < slideItemsOut.length; i++) {
                 var item = slideItemsOut[i];
                 // set item positions
                 item.style.left = '';
       
                 if (ANIMATIONDELAY && TRANSITIONDELAY) {
                   item.style[ANIMATIONDELAY] = '';
                   item.style[TRANSITIONDELAY] = '';
                 }
                 removeClass(item, animateOut);
                 addClass(item, animateNormal);
               }
             }
       
             /* update slides, nav, controls after checking ...
              * => legacy browsers who don't support 'event'
              *    have to check event first, otherwise event.target will cause an error
              * => or 'gallery' mode:
              *   + event target is slide item
              * => or 'carousel' mode:
              *   + event target is container,
              *   + event.property is the same with transform attribute
              */
             if (!event ||
                 !carousel && event.target.parentNode === container ||
                 event.target === container && strTrans(event.propertyName) === strTrans(transformAttr)) {
       
               if (!updateIndexBeforeTransform) {
                 var indexTem = index;
                 updateIndex();
                 if (index !== indexTem) {
                   events.emit('indexChanged', info());
       
                   doContainerTransformSilent();
                 }
               }
       
               if (nested === 'inner') { events.emit('innerLoaded', info()); }
               running = false;
               indexCached = index;
             }
           }
       
         }
       
         // # ACTIONS
         function goTo (targetIndex, e) {
           if (freeze) { return; }
       
           // prev slideBy
           if (targetIndex === 'prev') {
             onControlsClick(e, -1);
       
           // next slideBy
           } else if (targetIndex === 'next') {
             onControlsClick(e, 1);
       
           // go to exact slide
           } else {
             if (running) {
               if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
             }
       
             var absIndex = getAbsIndex(),
                 indexGap = 0;
       
             if (targetIndex === 'first') {
               indexGap = - absIndex;
             } else if (targetIndex === 'last') {
               indexGap = carousel ? slideCount - items - absIndex : slideCount - 1 - absIndex;
             } else {
               if (typeof targetIndex !== 'number') { targetIndex = parseInt(targetIndex); }
       
               if (!isNaN(targetIndex)) {
                 // from directly called goTo function
                 if (!e) { targetIndex = Math.max(0, Math.min(slideCount - 1, targetIndex)); }
       
                 indexGap = targetIndex - absIndex;
               }
             }
       
             // gallery: make sure new page won't overlap with current page
             if (!carousel && indexGap && Math.abs(indexGap) < items) {
               var factor = indexGap > 0 ? 1 : -1;
               indexGap += (index + indexGap - slideCount) >= indexMin ? slideCount * factor : slideCount * 2 * factor * -1;
             }
       
             index += indexGap;
       
             // make sure index is in range
             if (carousel && loop) {
               if (index < indexMin) { index += slideCount; }
               if (index > indexMax) { index -= slideCount; }
             }
       
             // if index is changed, start rendering
             if (getAbsIndex(index) !== getAbsIndex(indexCached)) {
               render(e);
             }
       
           }
         }
       
         // on controls click
         function onControlsClick (e, dir) {
           if (running) {
             if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
           }
           var passEventObject;
       
           if (!dir) {
             e = getEvent(e);
             var target = getTarget(e);
       
             while (target !== controlsContainer && [prevButton, nextButton].indexOf(target) < 0) { target = target.parentNode; }
       
             var targetIn = [prevButton, nextButton].indexOf(target);
             if (targetIn >= 0) {
               passEventObject = true;
               dir = targetIn === 0 ? -1 : 1;
             }
           }
       
           if (rewind) {
             if (index === indexMin && dir === -1) {
               goTo('last', e);
               return;
             } else if (index === indexMax && dir === 1) {
               goTo('first', e);
               return;
             }
           }
       
           if (dir) {
             index += slideBy * dir;
             if (autoWidth) { index = Math.floor(index); }
             // pass e when click control buttons or keydown
             render((passEventObject || (e && e.type === 'keydown')) ? e : null);
           }
         }
       
         // on nav click
         function onNavClick (e) {
           if (running) {
             if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
           }
       
           e = getEvent(e);
           var target = getTarget(e), navIndex;
       
           // find the clicked nav item
           while (target !== navContainer && !hasAttr(target, 'data-nav')) { target = target.parentNode; }
           if (hasAttr(target, 'data-nav')) {
             var navIndex = navClicked = Number(getAttr(target, 'data-nav')),
                 targetIndexBase = fixedWidth || autoWidth ? navIndex * slideCount / pages : navIndex * items,
                 targetIndex = navAsThumbnails ? navIndex : Math.min(Math.ceil(targetIndexBase), slideCount - 1);
             goTo(targetIndex, e);
       
             if (navCurrentIndex === navIndex) {
               if (animating) { stopAutoplay(); }
               navClicked = -1; // reset navClicked
             }
           }
         }
       
         // autoplay functions
         function setAutoplayTimer () {
           autoplayTimer = setInterval(function () {
             onControlsClick(null, autoplayDirection);
           }, autoplayTimeout);
       
           animating = true;
         }
       
         function stopAutoplayTimer () {
           clearInterval(autoplayTimer);
           animating = false;
         }
       
         function updateAutoplayButton (action, txt) {
           setAttrs(autoplayButton, {'data-action': action});
           autoplayButton.innerHTML = autoplayHtmlStrings[0] + action + autoplayHtmlStrings[1] + txt;
         }
       
         function startAutoplay () {
           setAutoplayTimer();
           if (autoplayButton) { updateAutoplayButton('stop', autoplayText[1]); }
         }
       
         function stopAutoplay () {
           stopAutoplayTimer();
           if (autoplayButton) { updateAutoplayButton('start', autoplayText[0]); }
         }
       
         // programaitcally play/pause the slider
         function play () {
           if (autoplay && !animating) {
             startAutoplay();
             autoplayUserPaused = false;
           }
         }
         function pause () {
           if (animating) {
             stopAutoplay();
             autoplayUserPaused = true;
           }
         }
       
         function toggleAutoplay () {
           if (animating) {
             stopAutoplay();
             autoplayUserPaused = true;
           } else {
             startAutoplay();
             autoplayUserPaused = false;
           }
         }
       
         function onVisibilityChange () {
           if (doc.hidden) {
             if (animating) {
               stopAutoplayTimer();
               autoplayVisibilityPaused = true;
             }
           } else if (autoplayVisibilityPaused) {
             setAutoplayTimer();
             autoplayVisibilityPaused = false;
           }
         }
       
         function mouseoverPause () {
           if (animating) {
             stopAutoplayTimer();
             autoplayHoverPaused = true;
           }
         }
       
         function mouseoutRestart () {
           if (autoplayHoverPaused) {
             setAutoplayTimer();
             autoplayHoverPaused = false;
           }
         }
       
         // keydown events on document
         function onDocumentKeydown (e) {
           e = getEvent(e);
           var keyIndex = [KEYS.LEFT, KEYS.RIGHT].indexOf(e.keyCode);
       
           if (keyIndex >= 0) {
             onControlsClick(e, keyIndex === 0 ? -1 : 1);
           }
         }
       
         // on key control
         function onControlsKeydown (e) {
           e = getEvent(e);
           var keyIndex = [KEYS.LEFT, KEYS.RIGHT].indexOf(e.keyCode);
       
           if (keyIndex >= 0) {
             if (keyIndex === 0) {
               if (!prevButton.disabled) { onControlsClick(e, -1); }
             } else if (!nextButton.disabled) {
               onControlsClick(e, 1);
             }
           }
         }
       
         // set focus
         function setFocus (el) {
           el.focus();
         }
       
         // on key nav
         function onNavKeydown (e) {
           e = getEvent(e);
           var curElement = doc.activeElement;
           if (!hasAttr(curElement, 'data-nav')) { return; }
       
           // var code = e.keyCode,
           var keyIndex = [KEYS.LEFT, KEYS.RIGHT, KEYS.ENTER, KEYS.SPACE].indexOf(e.keyCode),
               navIndex = Number(getAttr(curElement, 'data-nav'));
       
           if (keyIndex >= 0) {
             if (keyIndex === 0) {
               if (navIndex > 0) { setFocus(navItems[navIndex - 1]); }
             } else if (keyIndex === 1) {
               if (navIndex < pages - 1) { setFocus(navItems[navIndex + 1]); }
             } else {
               navClicked = navIndex;
               goTo(navIndex, e);
             }
           }
         }
       
         function getEvent (e) {
           e = e || win.event;
           return isTouchEvent(e) ? e.changedTouches[0] : e;
         }
         function getTarget (e) {
           return e.target || win.event.srcElement;
         }
       
         function isTouchEvent (e) {
           return e.type.indexOf('touch') >= 0;
         }
       
         function preventDefaultBehavior (e) {
           e.preventDefault ? e.preventDefault() : e.returnValue = false;
         }
       
         function getMoveDirectionExpected () {
           return getTouchDirection(toDegree(lastPosition.y - initPosition.y, lastPosition.x - initPosition.x), swipeAngle) === options.axis;
         }
       
         function onPanStart (e) {
           if (running) {
             if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
           }
       
           if (autoplay && animating) { stopAutoplayTimer(); }
       
           panStart = true;
           if (rafIndex) {
             caf(rafIndex);
             rafIndex = null;
           }
       
           var $ = getEvent(e);
           events.emit(isTouchEvent(e) ? 'touchStart' : 'dragStart', info(e));
       
           if (!isTouchEvent(e) && ['img', 'a'].indexOf(getLowerCaseNodeName(getTarget(e))) >= 0) {
             preventDefaultBehavior(e);
           }
       
           lastPosition.x = initPosition.x = $.clientX;
           lastPosition.y = initPosition.y = $.clientY;
           if (carousel) {
             translateInit = parseFloat(container.style[transformAttr].replace(transformPrefix, ''));
             resetDuration(container, '0s');
           }
         }
       
         function onPanMove (e) {
           if (panStart) {
             var $ = getEvent(e);
             lastPosition.x = $.clientX;
             lastPosition.y = $.clientY;
       
             if (carousel) {
               if (!rafIndex) { rafIndex = raf(function(){ panUpdate(e); }); }
             } else {
               if (moveDirectionExpected === '?') { moveDirectionExpected = getMoveDirectionExpected(); }
               if (moveDirectionExpected) { preventScroll = true; }
             }
       
             if ((typeof e.cancelable !== 'boolean' || e.cancelable) && preventScroll) {
               e.preventDefault();
             }
           }
         }
       
         function panUpdate (e) {
           if (!moveDirectionExpected) {
             panStart = false;
             return;
           }
           caf(rafIndex);
           if (panStart) { rafIndex = raf(function(){ panUpdate(e); }); }
       
           if (moveDirectionExpected === '?') { moveDirectionExpected = getMoveDirectionExpected(); }
           if (moveDirectionExpected) {
             if (!preventScroll && isTouchEvent(e)) { preventScroll = true; }
       
             try {
               if (e.type) { events.emit(isTouchEvent(e) ? 'touchMove' : 'dragMove', info(e)); }
             } catch(err) {}
       
             var x = translateInit,
                 dist = getDist(lastPosition, initPosition);
             if (!horizontal || fixedWidth || autoWidth) {
               x += dist;
               x += 'px';
             } else {
               var percentageX = TRANSFORM ? dist * items * 100 / ((viewport + gutter) * slideCountNew): dist * 100 / (viewport + gutter);
               x += percentageX;
               x += '%';
             }
       
             container.style[transformAttr] = transformPrefix + x + transformPostfix;
           }
         }
       
         function onPanEnd (e) {
           if (panStart) {
             if (rafIndex) {
               caf(rafIndex);
               rafIndex = null;
             }
             if (carousel) { resetDuration(container, ''); }
             panStart = false;
       
             var $ = getEvent(e);
             lastPosition.x = $.clientX;
             lastPosition.y = $.clientY;
             var dist = getDist(lastPosition, initPosition);
       
             if (Math.abs(dist)) {
               // drag vs click
               if (!isTouchEvent(e)) {
                 // prevent "click"
                 var target = getTarget(e);
                 addEvents(target, {'click': function preventClick (e) {
                   preventDefaultBehavior(e);
                   removeEvents(target, {'click': preventClick});
                 }});
               }
       
               if (carousel) {
                 rafIndex = raf(function() {
                   if (horizontal && !autoWidth) {
                     var indexMoved = - dist * items / (viewport + gutter);
                     indexMoved = dist > 0 ? Math.floor(indexMoved) : Math.ceil(indexMoved);
                     index += indexMoved;
                   } else {
                     var moved = - (translateInit + dist);
                     if (moved <= 0) {
                       index = indexMin;
                     } else if (moved >= slidePositions[slideCountNew - 1]) {
                       index = indexMax;
                     } else {
                       var i = 0;
                       while (i < slideCountNew && moved >= slidePositions[i]) {
                         index = i;
                         if (moved > slidePositions[i] && dist < 0) { index += 1; }
                         i++;
                       }
                     }
                   }
       
                   render(e, dist);
                   events.emit(isTouchEvent(e) ? 'touchEnd' : 'dragEnd', info(e));
                 });
               } else {
                 if (moveDirectionExpected) {
                   onControlsClick(e, dist > 0 ? -1 : 1);
                 }
               }
             }
           }
       
           // reset
           if (options.preventScrollOnTouch === 'auto') { preventScroll = false; }
           if (swipeAngle) { moveDirectionExpected = '?'; }
           if (autoplay && !animating) { setAutoplayTimer(); }
         }
       
         // === RESIZE FUNCTIONS === //
         // (slidePositions, index, items) => vertical_conentWrapper.height
         function updateContentWrapperHeight () {
           var wp = middleWrapper ? middleWrapper : innerWrapper;
           wp.style.height = slidePositions[index + items] - slidePositions[index] + 'px';
         }
       
         function getPages () {
           var rough = fixedWidth ? (fixedWidth + gutter) * slideCount / viewport : slideCount / items;
           return Math.min(Math.ceil(rough), slideCount);
         }
       
         /*
          * 1. update visible nav items list
          * 2. add "hidden" attributes to previous visible nav items
          * 3. remove "hidden" attrubutes to new visible nav items
          */
         function updateNavVisibility () {
           if (!nav || navAsThumbnails) { return; }
       
           if (pages !== pagesCached) {
             var min = pagesCached,
                 max = pages,
                 fn = showElement;
       
             if (pagesCached > pages) {
               min = pages;
               max = pagesCached;
               fn = hideElement;
             }
       
             while (min < max) {
               fn(navItems[min]);
               min++;
             }
       
             // cache pages
             pagesCached = pages;
           }
         }
       
         function info (e) {
           return {
             container: container,
             slideItems: slideItems,
             navContainer: navContainer,
             navItems: navItems,
             controlsContainer: controlsContainer,
             hasControls: hasControls,
             prevButton: prevButton,
             nextButton: nextButton,
             items: items,
             slideBy: slideBy,
             cloneCount: cloneCount,
             slideCount: slideCount,
             slideCountNew: slideCountNew,
             index: index,
             indexCached: indexCached,
             displayIndex: getCurrentSlide(),
             navCurrentIndex: navCurrentIndex,
             navCurrentIndexCached: navCurrentIndexCached,
             pages: pages,
             pagesCached: pagesCached,
             sheet: sheet,
             isOn: isOn,
             event: e || {},
           };
         }
       
         return {
           version: '2.9.2',
           getInfo: info,
           events: events,
           goTo: goTo,
           play: play,
           pause: pause,
           isOn: isOn,
           updateSliderHeight: updateInnerWrapperHeight,
           refresh: initSliderTransform,
           destroy: destroy,
           rebuild: function() {
             return tns(extend(options, optionsElements));
           }
         };
       };
       
       return tns;
       })();
  • URL: /components/raw/carousel/carousel.js
  • Filesystem Path: components/05-objects/05-carousels/01-carousel/carousel.js
  • Size: 109.8 KB

There are no notes for this item.