'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var win = window;
var caf = win.cancelAnimationFrame || win.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() {
if (window.matchMedia || window.msMatchMedia) {
return true;
}
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, nonce) {
// 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);
} // Add nonce attribute for Content Security Policy
if (nonce) {
style.setAttribute("nonce", nonce);
} // 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');
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;
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,
nonce: false
}, 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(null, getOption('nonce')),
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 = 0; 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;
getCurrentSlide();
var indexMin = 0,
indexMax = !autoWidth ? getIndexMax() : null,
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',
slideClonedClass = 'tns-slide-cloned',
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,
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';
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);
addClass(cloneFirst, slideClonedClass);
removeAttrs(cloneFirst, 'id');
fragmentAfter.insertBefore(cloneFirst, fragmentAfter.firstChild);
if (carousel) {
var cloneLast = slideItems[slideCount - 1 - num].cloneNode(true);
addClass(cloneLast, slideClonedClass);
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 && slideCount > 1) {
// 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) {
// will not hide the navs in case they're thumbnails
if (navContainer) {
setAttrs(navContainer, {
'aria-label': 'Carousel Pagination'
});
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
});
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 = swipeAngle = moveDirectionExpected = running = onInit = events = newContainerClasses = slideId = disable = disabled = freezable = freeze = frozen = controlsEvents = navEvents = hoverEvents = visibilityEvent = docmentKeydownEvent = touchEvents = dragEvents = hasControls = hasNav = navAsThumbnails = hasAutoplay = hasTouch = hasMouseDrag = slideActiveClass = imgCompleteClass = imgEvents = imgsComplete = controls = controlsText = controlsContainer = controlsContainerHTML = prevButton = nextButton = prevIsButton = nextIsButton = nav = navContainer = navContainerHTML = navItems = pages = pagesCached = navClicked = navCurrentIndex = navCurrentIndexCached = navActiveClass = navStr = navStrCurrent = autoplay = autoplayTimeout = autoplayDirection = autoplayText = autoplayHoverPause = autoplayButton = autoplayButtonHTML = autoplayResetOnVisibility = autoplayHtmlStrings = autoplayTimer = animating = autoplayHoverPaused = autoplayUserPaused = autoplayVisibilityPaused = initPosition = lastPosition = translateInit = panStart = rafIndex = getDist = touch = mouseDrag = null; // check variables
// [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) {
if (nav) {
showElement(navContainer);
updateNavVisibility();
} else {
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.4',
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));
}
};
};
exports.tns = tns;