');
slider.viewport.prepend(slider.loader);
// set el to a massive width, to hold any needed slides
// also strip any margin and padding from el
el.css({
width: slider.settings.mode === 'horizontal' ? (slider.children.length * 1000 + 215) + '%' : 'auto',
position: 'relative'
});
// if using CSS, add the easing property
if (slider.usingCSS && slider.settings.easing) {
el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing);
// if not using CSS and no easing value was supplied, use the default JS animation easing (swing)
} else if (!slider.settings.easing) {
slider.settings.easing = 'swing';
}
// make modifications to the viewport (.bx-viewport)
slider.viewport.css({
width: '100%',
overflow: 'hidden',
position: 'relative'
});
slider.viewport.parent().css({
maxWidth: getViewportMaxWidth()
});
// apply css to all slider children
slider.children.css({
// the float attribute is a reserved word in compressors like YUI compressor and need to be quoted #48
'float': slider.settings.mode === 'horizontal' ? 'left' : 'none',
listStyle: 'none',
position: 'relative'
});
// apply the calculated width after the float is applied to prevent scrollbar interference
slider.children.css('width', getSlideWidth());
// if slideMargin is supplied, add the css
if (slider.settings.mode === 'horizontal' && slider.settings.slideMargin > 0) { slider.children.css('marginRight', slider.settings.slideMargin); }
if (slider.settings.mode === 'vertical' && slider.settings.slideMargin > 0) { slider.children.css('marginBottom', slider.settings.slideMargin); }
// if "fade" mode, add positioning and z-index CSS
if (slider.settings.mode === 'fade') {
slider.children.css({
position: 'absolute',
zIndex: 0,
display: 'none'
});
// prepare the z-index on the showing element
slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'});
}
// create an element to contain all slider controls (pager, start / stop, etc)
slider.controls.el = $('
');
// if captions are requested, add them
if (slider.settings.captions) { appendCaptions(); }
// check if startSlide is last slide
slider.active.last = slider.settings.startSlide === getPagerQty() - 1;
// if video is true, set up the fitVids plugin
if (slider.settings.video) { el.fitVids(); }
//preloadImages
if (slider.settings.preloadImages === 'none') {
preloadSelector = null;
}
else if (slider.settings.preloadImages === 'all' || slider.settings.ticker) {
preloadSelector = slider.children;
}
// only check for control addition if not in "ticker" mode
if (!slider.settings.ticker) {
// if controls are requested, add them
if (slider.settings.controls) { appendControls(); }
// if auto is true, and auto controls are requested, add them
if (slider.settings.auto && slider.settings.autoControls) { appendControlsAuto(); }
// if pager is requested, add it
if (slider.settings.pager) { appendPager(); }
// if any control option is requested, add the controls wrapper
if (slider.settings.controls || slider.settings.autoControls || slider.settings.pager) { slider.viewport.after(slider.controls.el); }
// if ticker mode, do not allow a pager
} else {
slider.settings.pager = false;
}
if (preloadSelector === null) {
start();
} else {
loadElements(preloadSelector, start);
}
};
var loadElements = function(selector, callback) {
var total = selector.find('img:not([src=""]), iframe').length,
count = 0;
if (total === 0) {
callback();
return;
}
selector.find('img:not([src=""]), iframe').each(function() {
$(this).one('load error', function() {
if (++count === total) { callback(); }
}).each(function() {
if (this.complete || this.src == '') { $(this).trigger('load'); }
});
});
};
/**
* Start the slider
*/
var start = function() {
// if infinite loop, prepare additional slides
if (slider.settings.infiniteLoop && slider.settings.mode !== 'fade' && !slider.settings.ticker) {
var slice = slider.settings.mode === 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides,
sliceAppend = slider.children.slice(0, slice).clone(true).addClass('bx-clone'),
slicePrepend = slider.children.slice(-slice).clone(true).addClass('bx-clone');
if (slider.settings.ariaHidden) {
sliceAppend.attr('aria-hidden', true);
slicePrepend.attr('aria-hidden', true);
}
el.append(sliceAppend).prepend(slicePrepend);
}
// remove the loading DOM element
slider.loader.remove();
// set the left / top position of "el"
setSlidePosition();
// if "vertical" mode, always use adaptiveHeight to prevent odd behavior
if (slider.settings.mode === 'vertical') { slider.settings.adaptiveHeight = true; }
// set the viewport height
slider.viewport.height(getViewportHeight());
// make sure everything is positioned just right (same as a window resize)
el.redrawSlider();
// onSliderLoad callback
slider.settings.onSliderLoad.call(el, slider.active.index);
// slider has been fully initialized
slider.initialized = true;
// add the resize call to the window
if (slider.settings.responsive) { $(window).on('resize', resizeWindow); }
// if auto is true and has more than 1 page, start the show
if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) { initAuto(); }
// if ticker is true, start the ticker
if (slider.settings.ticker) { initTicker(); }
// if pager is requested, make the appropriate pager link active
if (slider.settings.pager) { updatePagerActive(slider.settings.startSlide); }
// check for any updates to the controls (like hideControlOnEnd updates)
if (slider.settings.controls) { updateDirectionControls(); }
// if touchEnabled is true, setup the touch events
if (slider.settings.touchEnabled && !slider.settings.ticker) { initTouch(); }
// if keyboardEnabled is true, setup the keyboard events
if (slider.settings.keyboardEnabled && !slider.settings.ticker) {
$(document).keydown(keyPress);
}
};
/**
* Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value
*/
var getViewportHeight = function() {
var height = 0;
// first determine which children (slides) should be used in our height calculation
var children = $();
// if mode is not "vertical" and adaptiveHeight is false, include all children
if (slider.settings.mode !== 'vertical' && !slider.settings.adaptiveHeight) {
children = slider.children;
} else {
// if not carousel, return the single active child
if (!slider.carousel) {
children = slider.children.eq(slider.active.index);
// if carousel, return a slice of children
} else {
// get the individual slide index
var currentIndex = slider.settings.moveSlides === 1 ? slider.active.index : slider.active.index * getMoveBy();
// add the current slide to the children
children = slider.children.eq(currentIndex);
// cycle through the remaining "showing" slides
for (i = 1; i <= slider.settings.maxSlides - 1; i++) {
// if looped back to the start
if (currentIndex + i >= slider.children.length) {
children = children.add(slider.children.eq(i - 1));
} else {
children = children.add(slider.children.eq(currentIndex + i));
}
}
}
}
// if "vertical" mode, calculate the sum of the heights of the children
if (slider.settings.mode === 'vertical') {
children.each(function(index) {
height += $(this).outerHeight();
});
// add user-supplied margins
if (slider.settings.slideMargin > 0) {
height += slider.settings.slideMargin * (slider.settings.minSlides - 1);
}
// if not "vertical" mode, calculate the max height of the children
} else {
height = Math.max.apply(Math, children.map(function() {
return $(this).outerHeight(false);
}).get());
}
if (slider.viewport.css('box-sizing') === 'border-box') {
height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) +
parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width'));
} else if (slider.viewport.css('box-sizing') === 'padding-box') {
height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom'));
}
return height;
};
/**
* Returns the calculated width to be used for the outer wrapper / viewport
*/
var getViewportMaxWidth = function() {
var width = '100%';
if (slider.settings.slideWidth > 0) {
if (slider.settings.mode === 'horizontal') {
width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
} else {
width = slider.settings.slideWidth;
}
}
return width;
};
/**
* Returns the calculated width to be applied to each slide
*/
var getSlideWidth = function() {
var newElWidth = slider.settings.slideWidth, // start with any user-supplied slide width
wrapWidth = slider.viewport.width(); // get the current viewport width
// if slide width was not supplied, or is larger than the viewport use the viewport width
if (slider.settings.slideWidth === 0 ||
(slider.settings.slideWidth > wrapWidth && !slider.carousel) ||
slider.settings.mode === 'vertical') {
newElWidth = wrapWidth;
// if carousel, use the thresholds to determine the width
} else if (slider.settings.maxSlides > 1 && slider.settings.mode === 'horizontal') {
if (wrapWidth > slider.maxThreshold) {
return newElWidth;
} else if (wrapWidth < slider.minThreshold) {
newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides;
} else if (slider.settings.shrinkItems) {
newElWidth = Math.floor((wrapWidth + slider.settings.slideMargin) / (Math.ceil((wrapWidth + slider.settings.slideMargin) / (newElWidth + slider.settings.slideMargin))) - slider.settings.slideMargin);
}
}
return newElWidth;
};
/**
* Returns the number of slides currently visible in the viewport (includes partially visible slides)
*/
var getNumberSlidesShowing = function() {
var slidesShowing = 1,
childWidth = null;
if (slider.settings.mode === 'horizontal' && slider.settings.slideWidth > 0) {
// if viewport is smaller than minThreshold, return minSlides
if (slider.viewport.width() < slider.minThreshold) {
slidesShowing = slider.settings.minSlides;
// if viewport is larger than maxThreshold, return maxSlides
} else if (slider.viewport.width() > slider.maxThreshold) {
slidesShowing = slider.settings.maxSlides;
// if viewport is between min / max thresholds, divide viewport width by first child width
} else {
childWidth = slider.children.first().width() + slider.settings.slideMargin;
slidesShowing = Math.floor((slider.viewport.width() +
slider.settings.slideMargin) / childWidth) || 1;
}
// if "vertical" mode, slides showing will always be minSlides
} else if (slider.settings.mode === 'vertical') {
slidesShowing = slider.settings.minSlides;
}
return slidesShowing;
};
/**
* Returns the number of pages (one full viewport of slides is one "page")
*/
var getPagerQty = function() {
var pagerQty = 0,
breakPoint = 0,
counter = 0;
// if moveSlides is specified by the user
if (slider.settings.moveSlides > 0) {
if (slider.settings.infiniteLoop) {
pagerQty = Math.ceil(slider.children.length / getMoveBy());
} else {
// when breakpoint goes above children length, counter is the number of pages
while (breakPoint < slider.children.length) {
++pagerQty;
breakPoint = counter + getNumberSlidesShowing();
counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing();
}
return counter;
}
// if moveSlides is 0 (auto) divide children length by sides showing, then round up
} else {
pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing());
}
return pagerQty;
};
/**
* Returns the number of individual slides by which to shift the slider
*/
var getMoveBy = function() {
// if moveSlides was set by the user and moveSlides is less than number of slides showing
if (slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()) {
return slider.settings.moveSlides;
}
// if moveSlides is 0 (auto)
return getNumberSlidesShowing();
};
/**
* Sets the slider's (el) left or top position
*/
var setSlidePosition = function() {
var position, lastChild, lastShowingIndex;
// if last slide, not infinite loop, and number of children is larger than specified maxSlides
if (slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop) {
if (slider.settings.mode === 'horizontal') {
// get the last child's position
lastChild = slider.children.last();
position = lastChild.position();
// set the left position
setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0);
} else if (slider.settings.mode === 'vertical') {
// get the last showing index's position
lastShowingIndex = slider.children.length - slider.settings.minSlides;
position = slider.children.eq(lastShowingIndex).position();
// set the top position
setPositionProperty(-position.top, 'reset', 0);
}
// if not last slide
} else {
// get the position of the first showing slide
position = slider.children.eq(slider.active.index * getMoveBy()).position();
// check for last slide
if (slider.active.index === getPagerQty() - 1) { slider.active.last = true; }
// set the respective position
if (position !== undefined) {
if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); }
else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); }
}
}
};
/**
* Sets the el's animating property position (which in turn will sometimes animate el).
* If using CSS, sets the transform property. If not using CSS, sets the top / left property.
*
* @param value (int)
* - the animating property's value
*
* @param type (string) 'slide', 'reset', 'ticker'
* - the type of instance for which the function is being
*
* @param duration (int)
* - the amount of time (in ms) the transition should occupy
*
* @param params (array) optional
* - an optional parameter containing any variables that need to be passed in
*/
var setPositionProperty = function(value, type, duration, params) {
var animateObj, propValue;
// use CSS transform
if (slider.usingCSS) {
// determine the translate3d value
propValue = slider.settings.mode === 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)';
// add the CSS transition-duration
el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');
if (type === 'slide') {
// set the property value
el.css(slider.animProp, propValue);
if (duration !== 0) {
// add a callback method - executes when CSS transition completes
el.on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) {
//make sure it's the correct one
if (!$(e.target).is(el)) { return; }
// remove the callback
el.off('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
updateAfterSlideTransition();
});
} else { //duration = 0
updateAfterSlideTransition();
}
} else if (type === 'reset') {
el.css(slider.animProp, propValue);
} else if (type === 'ticker') {
// make the transition use 'linear'
el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear');
el.css(slider.animProp, propValue);
if (duration !== 0) {
el.on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) {
//make sure it's the correct one
if (!$(e.target).is(el)) { return; }
// remove the callback
el.off('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
// reset the position
setPositionProperty(params.resetValue, 'reset', 0);
// start the loop again
tickerLoop();
});
} else { //duration = 0
setPositionProperty(params.resetValue, 'reset', 0);
tickerLoop();
}
}
// use JS animate
} else {
animateObj = {};
animateObj[slider.animProp] = value;
if (type === 'slide') {
el.animate(animateObj, duration, slider.settings.easing, function() {
updateAfterSlideTransition();
});
} else if (type === 'reset') {
el.css(slider.animProp, value);
} else if (type === 'ticker') {
el.animate(animateObj, duration, 'linear', function() {
setPositionProperty(params.resetValue, 'reset', 0);
// run the recursive loop after animation
tickerLoop();
});
}
}
};
/**
* Populates the pager with proper amount of pages
*/
var populatePager = function() {
var pagerHtml = '',
linkContent = '',
pagerQty = getPagerQty();
// loop through each pager item
for (var i = 0; i < pagerQty; i++) {
linkContent = '';
// if a buildPager function is supplied, use it to get pager link value, else use index + 1
if (slider.settings.buildPager && $.isFunction(slider.settings.buildPager) || slider.settings.pagerCustom) {
linkContent = slider.settings.buildPager(i);
slider.pagerEl.addClass('bx-custom-pager');
} else {
linkContent = i + 1;
slider.pagerEl.addClass('bx-default-pager');
}
// var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1;
// add the markup to the string
pagerHtml += '';
}
// populate the pager element with pager links
slider.pagerEl.html(pagerHtml);
};
/**
* Appends the pager to the controls element
*/
var appendPager = function() {
if (!slider.settings.pagerCustom) {
// create the pager DOM element
slider.pagerEl = $('