(function ($) {
var focused = true;
//flexslider: object instance
$.flexslider = function(el, options) {
var slider = $(el);
// making variables public
slider.vars = $.extend({}, $.flexslider.defaults, options);
var namespace = slider.vars.namespace,
msgesture = window.navigator && window.navigator.mspointerenabled && window.msgesture,
touch = (( "ontouchstart" in window ) || msgesture || window.documenttouch && document instanceof documenttouch) && slider.vars.touch,
// depricating this idea, as devices are being released with both of these events
eventtype = "click touchend mspointerup keyup",
watchedevent = "",
watchedeventcleartimer,
vertical = slider.vars.direction === "vertical",
reverse = slider.vars.reverse,
carousel = (slider.vars.itemwidth > 0),
fade = slider.vars.animation === "fade",
asnav = slider.vars.asnavfor !== "",
methods = {};
// store a reference to the slider object
$.data(el, "flexslider", slider);
// private slider methods
methods = {
init: function() {
slider.animating = false;
// get current slide and make sure it is a number
slider.currentslide = parseint( ( slider.vars.startat ? slider.vars.startat : 0), 10 );
if ( isnan( slider.currentslide ) ) { slider.currentslide = 0; }
slider.animatingto = slider.currentslide;
slider.atend = (slider.currentslide === 0 || slider.currentslide === slider.last);
slider.containerselector = slider.vars.selector.substr(0,slider.vars.selector.search(' '));
slider.slides = $(slider.vars.selector, slider);
slider.container = $(slider.containerselector, slider);
slider.count = slider.slides.length;
// sync:
slider.syncexists = $(slider.vars.sync).length > 0;
// slide:
if (slider.vars.animation === "slide") { slider.vars.animation = "swing"; }
slider.prop = (vertical) ? "top" : "marginleft";
slider.args = {};
// slideshow:
slider.manualpause = false;
slider.stopped = false;
//pause when invisible
slider.started = false;
slider.starttimeout = null;
// touch/usecss:
slider.transitions = !slider.vars.video && !fade && slider.vars.usecss && (function() {
var obj = document.createelement('div'),
props = ['perspectiveproperty', 'webkitperspective', 'mozperspective', 'operspective', 'msperspective'];
for (var i in props) {
if ( obj.style[ props[i] ] !== undefined ) {
slider.pfx = props[i].replace('perspective','').tolowercase();
slider.prop = "-" + slider.pfx + "-transform";
return true;
}
}
return false;
}());
slider.ensureanimationend = '';
// controlscontainer:
if (slider.vars.controlscontainer !== "") slider.controlscontainer = $(slider.vars.controlscontainer).length > 0 && $(slider.vars.controlscontainer);
// manual:
if (slider.vars.manualcontrols !== "") slider.manualcontrols = $(slider.vars.manualcontrols).length > 0 && $(slider.vars.manualcontrols);
// custom direction nav:
if (slider.vars.customdirectionnav !== "") slider.customdirectionnav = $(slider.vars.customdirectionnav).length === 2 && $(slider.vars.customdirectionnav);
// randomize:
if (slider.vars.randomize) {
slider.slides.sort(function() { return (math.round(math.random())-0.5); });
slider.container.empty().append(slider.slides);
}
slider.domath();
// init
slider.setup("init");
// controlnav:
if (slider.vars.controlnav) { methods.controlnav.setup(); }
// directionnav:
if (slider.vars.directionnav) { methods.directionnav.setup(); }
// keyboard:
if (slider.vars.keyboard && ($(slider.containerselector).length === 1 || slider.vars.multiplekeyboard)) {
$(document).bind('keyup', function(event) {
var keycode = event.keycode;
if (!slider.animating && (keycode === 39 || keycode === 37)) {
var target = (keycode === 39) ? slider.gettarget('next') :
(keycode === 37) ? slider.gettarget('prev') : false;
slider.flexanimate(target, slider.vars.pauseonaction);
}
});
}
// mousewheel:
if (slider.vars.mousewheel) {
slider.bind('mousewheel', function(event, delta, deltax, deltay) {
event.preventdefault();
var target = (delta < 0) ? slider.gettarget('next') : slider.gettarget('prev');
slider.flexanimate(target, slider.vars.pauseonaction);
});
}
// pauseplay
if (slider.vars.pauseplay) { methods.pauseplay.setup(); }
//pause when invisible
if (slider.vars.slideshow && slider.vars.pauseinvisible) { methods.pauseinvisible.init(); }
// slidseshow
if (slider.vars.slideshow) {
if (slider.vars.pauseonhover) {
slider.hover(function() {
if (!slider.manualplay && !slider.manualpause) { slider.pause(); }
}, function() {
if (!slider.manualpause && !slider.manualplay && !slider.stopped) { slider.play(); }
});
}
// initialize animation
//if we're visible, or we don't use pagevisibility api
if(!slider.vars.pauseinvisible || !methods.pauseinvisible.ishidden()) {
(slider.vars.initdelay > 0) ? slider.starttimeout = settimeout(slider.play, slider.vars.initdelay) : slider.play();
}
}
// asnav:
if (asnav) { methods.asnav.setup(); }
// touch
if (touch && slider.vars.touch) { methods.touch(); }
// fade&&smoothheight || slide:
if (!fade || (fade && slider.vars.smoothheight)) { $(window).bind("resize orientationchange focus", methods.resize); }
slider.find("img").attr("draggable", "false");
// api: start() callback
settimeout(function(){
slider.vars.start(slider);
}, 200);
},
asnav: {
setup: function() {
slider.asnav = true;
slider.animatingto = math.floor(slider.currentslide/slider.move);
slider.currentitem = slider.currentslide;
slider.slides.removeclass(namespace + "active-slide").eq(slider.currentitem).addclass(namespace + "active-slide");
if(!msgesture){
slider.slides.on(eventtype, function(e){
e.preventdefault();
var $slide = $(this),
target = $slide.index();
var posfromleft = $slide.offset().left - $(slider).scrollleft(); // find position of slide relative to left of slider container
if( posfromleft <= 0 && $slide.hasclass( namespace + 'active-slide' ) ) {
slider.flexanimate(slider.gettarget("prev"), true);
} else if (!$(slider.vars.asnavfor).data('flexslider').animating && !$slide.hasclass(namespace + "active-slide")) {
slider.direction = (slider.currentitem < target) ? "next" : "prev";
slider.flexanimate(target, slider.vars.pauseonaction, false, true, true);
}
});
}else{
el._slider = slider;
slider.slides.each(function (){
var that = this;
that._gesture = new msgesture();
that._gesture.target = that;
that.addeventlistener("mspointerdown", function (e){
e.preventdefault();
if(e.currenttarget._gesture) {
e.currenttarget._gesture.addpointer(e.pointerid);
}
}, false);
that.addeventlistener("msgesturetap", function (e){
e.preventdefault();
var $slide = $(this),
target = $slide.index();
if (!$(slider.vars.asnavfor).data('flexslider').animating && !$slide.hasclass('active')) {
slider.direction = (slider.currentitem < target) ? "next" : "prev";
slider.flexanimate(target, slider.vars.pauseonaction, false, true, true);
}
});
});
}
}
},
controlnav: {
setup: function() {
if (!slider.manualcontrols) {
methods.controlnav.setuppaging();
} else { // manualcontrols:
methods.controlnav.setupmanual();
}
},
setuppaging: function() {
var type = (slider.vars.controlnav === "thumbnails") ? 'control-thumbs' : 'control-paging',
j = 1,
item,
slide;
slider.controlnavscaffold = $('
');
if (slider.pagingcount > 1) {
for (var i = 0; i < slider.pagingcount; i++) {
slide = slider.slides.eq(i);
if ( undefined === slide.attr( 'data-thumb-alt' ) ) { slide.attr( 'data-thumb-alt', '' ); }
alttext = ( '' !== slide.attr( 'data-thumb-alt' ) ) ? alttext = ' alt="' + slide.attr( 'data-thumb-alt' ) + '"' : '';
item = (slider.vars.controlnav === "thumbnails") ? '' : '' + j + '';
if ( 'thumbnails' === slider.vars.controlnav && true === slider.vars.thumbcaptions ) {
var captn = slide.attr( 'data-thumbcaption' );
if ( '' !== captn && undefined !== captn ) { item += '' + captn + ''; }
}
slider.controlnavscaffold.append('' + item + '');
j++;
}
}
// controlscontainer:
(slider.controlscontainer) ? $(slider.controlscontainer).append(slider.controlnavscaffold) : slider.append(slider.controlnavscaffold);
methods.controlnav.set();
methods.controlnav.active();
slider.controlnavscaffold.delegate('a, img', eventtype, function(event) {
event.preventdefault();
if (watchedevent === "" || watchedevent === event.type) {
var $this = $(this),
target = slider.controlnav.index($this);
if (!$this.hasclass(namespace + 'active')) {
slider.direction = (target > slider.currentslide) ? "next" : "prev";
slider.flexanimate(target, slider.vars.pauseonaction);
}
}
// setup flags to prevent event duplication
if (watchedevent === "") {
watchedevent = event.type;
}
methods.settoclearwatchedevent();
});
},
setupmanual: function() {
slider.controlnav = slider.manualcontrols;
methods.controlnav.active();
slider.controlnav.bind(eventtype, function(event) {
event.preventdefault();
if (watchedevent === "" || watchedevent === event.type) {
var $this = $(this),
target = slider.controlnav.index($this);
if (!$this.hasclass(namespace + 'active')) {
(target > slider.currentslide) ? slider.direction = "next" : slider.direction = "prev";
slider.flexanimate(target, slider.vars.pauseonaction);
}
}
// setup flags to prevent event duplication
if (watchedevent === "") {
watchedevent = event.type;
}
methods.settoclearwatchedevent();
});
},
set: function() {
var selector = (slider.vars.controlnav === "thumbnails") ? 'img' : 'a';
slider.controlnav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlscontainer) ? slider.controlscontainer : slider);
},
active: function() {
slider.controlnav.removeclass(namespace + "active").eq(slider.animatingto).addclass(namespace + "active");
},
update: function(action, pos) {
if (slider.pagingcount > 1 && action === "add") {
slider.controlnavscaffold.append($('' + slider.count + ''));
} else if (slider.pagingcount === 1) {
slider.controlnavscaffold.find('li').remove();
} else {
slider.controlnav.eq(pos).closest('li').remove();
}
methods.controlnav.set();
(slider.pagingcount > 1 && slider.pagingcount !== slider.controlnav.length) ? slider.update(pos, action) : methods.controlnav.active();
}
},
directionnav: {
setup: function() {
var directionnavscaffold = $('');
// custom direction nav:
if (slider.customdirectionnav) {
slider.directionnav = slider.customdirectionnav;
// controlscontainer:
} else if (slider.controlscontainer) {
$(slider.controlscontainer).append(directionnavscaffold);
slider.directionnav = $('.' + namespace + 'direction-nav li a', slider.controlscontainer);
} else {
slider.append(directionnavscaffold);
slider.directionnav = $('.' + namespace + 'direction-nav li a', slider);
}
methods.directionnav.update();
slider.directionnav.bind(eventtype, function(event) {
event.preventdefault();
var target;
if (watchedevent === "" || watchedevent === event.type) {
target = ($(this).hasclass(namespace + 'next')) ? slider.gettarget('next') : slider.gettarget('prev');
slider.flexanimate(target, slider.vars.pauseonaction);
}
// setup flags to prevent event duplication
if (watchedevent === "") {
watchedevent = event.type;
}
methods.settoclearwatchedevent();
});
},
update: function() {
var disabledclass = namespace + 'disabled';
if (slider.pagingcount === 1) {
slider.directionnav.addclass(disabledclass).attr('tabindex', '-1');
} else if (!slider.vars.animationloop) {
if (slider.animatingto === 0) {
slider.directionnav.removeclass(disabledclass).filter('.' + namespace + "prev").addclass(disabledclass).attr('tabindex', '-1');
} else if (slider.animatingto === slider.last) {
slider.directionnav.removeclass(disabledclass).filter('.' + namespace + "next").addclass(disabledclass).attr('tabindex', '-1');
} else {
slider.directionnav.removeclass(disabledclass).removeattr('tabindex');
}
} else {
slider.directionnav.removeclass(disabledclass).removeattr('tabindex');
}
}
},
pauseplay: {
setup: function() {
var pauseplayscaffold = $('');
// controlscontainer:
if (slider.controlscontainer) {
slider.controlscontainer.append(pauseplayscaffold);
slider.pauseplay = $('.' + namespace + 'pauseplay a', slider.controlscontainer);
} else {
slider.append(pauseplayscaffold);
slider.pauseplay = $('.' + namespace + 'pauseplay a', slider);
}
methods.pauseplay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');
slider.pauseplay.bind(eventtype, function(event) {
event.preventdefault();
if (watchedevent === "" || watchedevent === event.type) {
if ($(this).hasclass(namespace + 'pause')) {
slider.manualpause = true;
slider.manualplay = false;
slider.pause();
} else {
slider.manualpause = false;
slider.manualplay = true;
slider.play();
}
}
// setup flags to prevent event duplication
if (watchedevent === "") {
watchedevent = event.type;
}
methods.settoclearwatchedevent();
});
},
update: function(state) {
(state === "play") ? slider.pauseplay.removeclass(namespace + 'pause').addclass(namespace + 'play').html(slider.vars.playtext) : slider.pauseplay.removeclass(namespace + 'play').addclass(namespace + 'pause').html(slider.vars.pausetext);
}
},
touch: function() {
var startx,
starty,
offset,
cwidth,
dx,
startt,
ontouchstart,
ontouchmove,
ontouchend,
scrolling = false,
localx = 0,
localy = 0,
accdx = 0;
if(!msgesture){
ontouchstart = function(e) {
if (slider.animating) {
e.preventdefault();
} else if ( ( window.navigator.mspointerenabled ) || e.touches.length === 1 ) {
slider.pause();
// carousel:
cwidth = (vertical) ? slider.h : slider. w;
startt = number(new date());
// carousel:
// local vars for x and y points.
localx = e.touches[0].pagex;
localy = e.touches[0].pagey;
offset = (carousel && reverse && slider.animatingto === slider.last) ? 0 :
(carousel && reverse) ? slider.limit - (((slider.itemw + slider.vars.itemmargin) * slider.move) * slider.animatingto) :
(carousel && slider.currentslide === slider.last) ? slider.limit :
(carousel) ? ((slider.itemw + slider.vars.itemmargin) * slider.move) * slider.currentslide :
(reverse) ? (slider.last - slider.currentslide + slider.cloneoffset) * cwidth : (slider.currentslide + slider.cloneoffset) * cwidth;
startx = (vertical) ? localy : localx;
starty = (vertical) ? localx : localy;
el.addeventlistener('touchmove', ontouchmove, false);
el.addeventlistener('touchend', ontouchend, false);
}
};
ontouchmove = function(e) {
// local vars for x and y points.
localx = e.touches[0].pagex;
localy = e.touches[0].pagey;
dx = (vertical) ? startx - localy : startx - localx;
scrolling = (vertical) ? (math.abs(dx) < math.abs(localx - starty)) : (math.abs(dx) < math.abs(localy - starty));
var fxms = 500;
if ( ! scrolling || number( new date() ) - startt > fxms ) {
e.preventdefault();
if (!fade && slider.transitions) {
if (!slider.vars.animationloop) {
dx = dx/((slider.currentslide === 0 && dx < 0 || slider.currentslide === slider.last && dx > 0) ? (math.abs(dx)/cwidth+2) : 1);
}
slider.setprops(offset + dx, "settouch");
}
}
};
ontouchend = function(e) {
// finish the touch by undoing the touch session
el.removeeventlistener('touchmove', ontouchmove, false);
if (slider.animatingto === slider.currentslide && !scrolling && !(dx === null)) {
var updatedx = (reverse) ? -dx : dx,
target = (updatedx > 0) ? slider.gettarget('next') : slider.gettarget('prev');
if (slider.canadvance(target) && (number(new date()) - startt < 550 && math.abs(updatedx) > 50 || math.abs(updatedx) > cwidth/2)) {
slider.flexanimate(target, slider.vars.pauseonaction);
} else {
if (!fade) { slider.flexanimate(slider.currentslide, slider.vars.pauseonaction, true); }
}
}
el.removeeventlistener('touchend', ontouchend, false);
startx = null;
starty = null;
dx = null;
offset = null;
};
el.addeventlistener('touchstart', ontouchstart, false);
}else{
el.style.mstouchaction = "none";
el._gesture = new msgesture();
el._gesture.target = el;
el.addeventlistener("mspointerdown", onmspointerdown, false);
el._slider = slider;
el.addeventlistener("msgesturechange", onmsgesturechange, false);
el.addeventlistener("msgestureend", onmsgestureend, false);
function onmspointerdown(e){
e.stoppropagation();
if (slider.animating) {
e.preventdefault();
}else{
slider.pause();
el._gesture.addpointer(e.pointerid);
accdx = 0;
cwidth = (vertical) ? slider.h : slider. w;
startt = number(new date());
// carousel:
offset = (carousel && reverse && slider.animatingto === slider.last) ? 0 :
(carousel && reverse) ? slider.limit - (((slider.itemw + slider.vars.itemmargin) * slider.move) * slider.animatingto) :
(carousel && slider.currentslide === slider.last) ? slider.limit :
(carousel) ? ((slider.itemw + slider.vars.itemmargin) * slider.move) * slider.currentslide :
(reverse) ? (slider.last - slider.currentslide + slider.cloneoffset) * cwidth : (slider.currentslide + slider.cloneoffset) * cwidth;
}
}
function onmsgesturechange(e) {
e.stoppropagation();
var slider = e.target._slider;
if(!slider){
return;
}
var transx = -e.translationx,
transy = -e.translationy;
//accumulate translations.
accdx = accdx + ((vertical) ? transy : transx);
dx = accdx;
scrolling = (vertical) ? (math.abs(accdx) < math.abs(-transx)) : (math.abs(accdx) < math.abs(-transy));
if(e.detail === e.msgesture_flag_inertia){
setimmediate(function (){
el._gesture.stop();
});
return;
}
if (!scrolling || number(new date()) - startt > 500) {
e.preventdefault();
if (!fade && slider.transitions) {
if (!slider.vars.animationloop) {
dx = accdx / ((slider.currentslide === 0 && accdx < 0 || slider.currentslide === slider.last && accdx > 0) ? (math.abs(accdx) / cwidth + 2) : 1);
}
slider.setprops(offset + dx, "settouch");
}
}
}
function onmsgestureend(e) {
e.stoppropagation();
var slider = e.target._slider;
if(!slider){
return;
}
if (slider.animatingto === slider.currentslide && !scrolling && !(dx === null)) {
var updatedx = (reverse) ? -dx : dx,
target = (updatedx > 0) ? slider.gettarget('next') : slider.gettarget('prev');
if (slider.canadvance(target) && (number(new date()) - startt < 550 && math.abs(updatedx) > 50 || math.abs(updatedx) > cwidth/2)) {
slider.flexanimate(target, slider.vars.pauseonaction);
} else {
if (!fade) { slider.flexanimate(slider.currentslide, slider.vars.pauseonaction, true); }
}
}
startx = null;
starty = null;
dx = null;
offset = null;
accdx = 0;
}
}
},
resize: function() {
if (!slider.animating && slider.is(':visible')) {
if (!carousel) { slider.domath(); }
if (fade) {
// smooth height:
methods.smoothheight();
} else if (carousel) { //carousel:
slider.slides.width(slider.computedw);
slider.update(slider.pagingcount);
slider.setprops();
}
else if (vertical) { //vertical:
slider.viewport.height(slider.h);
slider.setprops(slider.h, "settotal");
} else {
// smooth height:
if (slider.vars.smoothheight) { methods.smoothheight(); }
slider.newslides.width(slider.computedw);
slider.setprops(slider.computedw, "settotal");
}
}
},
smoothheight: function(dur) {
if (!vertical || fade) {
var $obj = (fade) ? slider : slider.viewport;
(dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingto).height()}, dur) : $obj.height(slider.slides.eq(slider.animatingto).height());
}
},
sync: function(action) {
var $obj = $(slider.vars.sync).data("flexslider"),
target = slider.animatingto;
switch (action) {
case "animate": $obj.flexanimate(target, slider.vars.pauseonaction, false, true); break;
case "play": if (!$obj.playing && !$obj.asnav) { $obj.play(); } break;
case "pause": $obj.pause(); break;
}
},
uniqueid: function($clone) {
// append _clone to current level and children elements with id attributes
$clone.filter( '[id]' ).add($clone.find( '[id]' )).each(function() {
var $this = $(this);
$this.attr( 'id', $this.attr( 'id' ) + '_clone' );
});
return $clone;
},
pauseinvisible: {
visprop: null,
init: function() {
var visprop = methods.pauseinvisible.gethiddenprop();
if (visprop) {
var evtname = visprop.replace(/[h|h]idden/,'') + 'visibilitychange';
document.addeventlistener(evtname, function() {
if (methods.pauseinvisible.ishidden()) {
if(slider.starttimeout) {
cleartimeout(slider.starttimeout); //if clock is ticking, stop timer and prevent from starting while invisible
} else {
slider.pause(); //or just pause
}
}
else {
if(slider.started) {
slider.play(); //initiated before, just play
} else {
if (slider.vars.initdelay > 0) {
settimeout(slider.play, slider.vars.initdelay);
} else {
slider.play(); //didn't init before: simply init or wait for it
}
}
}
});
}
},
ishidden: function() {
var prop = methods.pauseinvisible.gethiddenprop();
if (!prop) {
return false;
}
return document[prop];
},
gethiddenprop: function() {
var prefixes = ['webkit','moz','ms','o'];
// if 'hidden' is natively supported just return it
if ('hidden' in document) {
return 'hidden';
}
// otherwise loop over all the known prefixes until we find one
for ( var i = 0; i < prefixes.length; i++ ) {
if ((prefixes[i] + 'hidden') in document) {
return prefixes[i] + 'hidden';
}
}
// otherwise it's not supported
return null;
}
},
settoclearwatchedevent: function() {
cleartimeout(watchedeventcleartimer);
watchedeventcleartimer = settimeout(function() {
watchedevent = "";
}, 3000);
}
};
})(jquery);