/*
* jquery flexslider v1.8
* http://flex.madebymufffin.com
*
* copyright 2011, tyler smith
* free to use under the mit license.
* http://www.opensource.org/licenses/mit-license.php
*
* contrib: darin richardson
*/
;(function ($) {
//flexslider: object instance
$.flexslider = function(el, options) {
var slider = el;
slider.init = function() {
slider.vars = $.extend({}, $.flexslider.defaults, options);
slider.data('flexslider', true);
slider.container = $('.slides', slider);
slider.slides = $('.slides > li', slider);
slider.count = slider.slides.length;
slider.animating = false;
slider.currentslide = slider.vars.slidetostart;
slider.animatingto = slider.currentslide;
slider.atend = (slider.currentslide == 0) ? true : false;
slider.eventtype = ('ontouchstart' in document.documentelement) ? 'touchstart' : 'click';
slider.clonecount = 0;
slider.cloneoffset = 0;
slider.manualpause = false;
slider.vertical = (slider.vars.slidedirection == "vertical");
slider.prop = (slider.vertical) ? "top" : "marginleft";
slider.args = {};
//test for webbkit css3 animations
slider.transitions = "webkittransition" in document.body.style;
if (slider.transitions) slider.prop = "-webkit-transform";
//test for controlscontainer
if (slider.vars.controlscontainer != "") {
slider.controlscontainer = $(slider.vars.controlscontainer).eq($('.slides').index(slider.container));
slider.containerexists = slider.controlscontainer.length > 0;
}
//test for manualcontrols
if (slider.vars.manualcontrols != "") {
slider.manualcontrols = $(slider.vars.manualcontrols, ((slider.containerexists) ? slider.controlscontainer : slider));
slider.manualexists = slider.manualcontrols.length > 0;
}
///////////////////////////////////////////////////////////////////
// flexslider: randomize slides
if (slider.vars.randomize) {
slider.slides.sort(function() { return (math.round(math.random())-0.5); });
slider.container.empty().append(slider.slides);
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// flexslider: slider animation initialize
if (slider.vars.animation.tolowercase() == "slide") {
if (slider.transitions) {
slider.settransition(0);
}
slider.css({"overflow": "hidden"});
if (slider.vars.animationloop) {
slider.clonecount = 2;
slider.cloneoffset = 1;
slider.container.append(slider.slides.filter(':first').clone().addclass('clone')).prepend(slider.slides.filter(':last').clone().addclass('clone'));
}
//create newslides to capture possible clones
slider.newslides = $('.slides > li', slider);
var slideroffset = (-1 * (slider.currentslide + slider.cloneoffset));
if (slider.vertical) {
slider.newslides.css({"display": "block", "width": "100%", "float": "left"});
slider.container.height((slider.count + slider.clonecount) * 200 + "%").css("position", "absolute").width("100%");
//timeout function to give browser enough time to get proper height initially
settimeout(function() {
slider.css({"position": "relative"}).height(slider.slides.filter(':first').height());
slider.args[slider.prop] = (slider.transitions) ? "translate3d(0," + slideroffset * slider.height() + "px,0)" : slideroffset * slider.height() + "px";
slider.container.css(slider.args);
}, 100);
} else {
slider.args[slider.prop] = (slider.transitions) ? "translate3d(" + slideroffset * slider.width() + "px,0,0)" : slideroffset * slider.width() + "px";
slider.container.width((slider.count + slider.clonecount) * 200 + "%").css(slider.args);
//timeout function to give browser enough time to get proper width initially
settimeout(function() {
slider.newslides.width(slider.width()).css({"float": "left", "display": "block"});
}, 100);
}
} else { //default to fade
//not supporting fade css3 transitions right now
slider.transitions = false;
slider.slides.css({"width": "100%", "float": "left", "marginright": "-100%"}).eq(slider.currentslide).fadein(slider.vars.animationduration);
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// flexslider: control nav
if (slider.vars.controlnav) {
if (slider.manualexists) {
slider.controlnav = slider.manualcontrols;
} else {
var controlnavscaffold = $('
');
var j = 1;
for (var i = 0; i < slider.count; i++) {
controlnavscaffold.append('' + j + '');
j++;
}
if (slider.containerexists) {
$(slider.controlscontainer).append(controlnavscaffold);
slider.controlnav = $('.flex-control-nav li a', slider.controlscontainer);
} else {
slider.append(controlnavscaffold);
slider.controlnav = $('.flex-control-nav li a', slider);
}
}
slider.controlnav.eq(slider.currentslide).addclass('active');
slider.controlnav.bind(slider.eventtype, function(event) {
event.preventdefault();
if (!$(this).hasclass('active')) {
(slider.controlnav.index($(this)) > slider.currentslide) ? slider.direction = "next" : slider.direction = "prev";
slider.flexanimate(slider.controlnav.index($(this)), slider.vars.pauseonaction);
}
});
}
///////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//flexslider: direction nav
if (slider.vars.directionnav) {
var directionnavscaffold = $('');
if (slider.containerexists) {
$(slider.controlscontainer).append(directionnavscaffold);
slider.directionnav = $('.flex-direction-nav li a', slider.controlscontainer);
} else {
slider.append(directionnavscaffold);
slider.directionnav = $('.flex-direction-nav li a', slider);
}
//set initial disable styles if necessary
if (!slider.vars.animationloop) {
if (slider.currentslide == 0) {
slider.directionnav.filter('.prev').addclass('disabled');
} else if (slider.currentslide == slider.count - 1) {
slider.directionnav.filter('.next').addclass('disabled');
}
}
slider.directionnav.bind(slider.eventtype, function(event) {
event.preventdefault();
var target = ($(this).hasclass('next')) ? slider.gettarget('next') : slider.gettarget('prev');
if (slider.canadvance(target)) {
slider.flexanimate(target, slider.vars.pauseonaction);
}
});
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//flexslider: keyboard nav
if (slider.vars.keyboardnav && $('ul.slides').length == 1) {
function keyboardmove(event) {
if (slider.animating) {
return;
} else if (event.keycode != 39 && event.keycode != 37){
return;
} else {
if (event.keycode == 39) {
var target = slider.gettarget('next');
} else if (event.keycode == 37){
var target = slider.gettarget('prev');
}
if (slider.canadvance(target)) {
slider.flexanimate(target, slider.vars.pauseonaction);
}
}
}
$(document).bind('keyup', keyboardmove);
}
//////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// flexslider: mousewheel interaction
if (slider.vars.mousewheel) {
slider.mousewheelevent = (/firefox/i.test(navigator.useragent)) ? "dommousescroll" : "mousewheel";
slider.bind(slider.mousewheelevent, function(e) {
e.preventdefault();
e = e ? e : window.event;
var wheeldata = e.detail ? e.detail * -1 : e.wheeldelta / 40,
target = (wheeldata < 0) ? slider.gettarget('next') : slider.gettarget('prev');
if (slider.canadvance(target)) {
slider.flexanimate(target, slider.vars.pauseonaction);
}
});
}
///////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//flexslider: slideshow setup
if (slider.vars.slideshow) {
//pauseonhover
if (slider.vars.pauseonhover && slider.vars.slideshow) {
slider.hover(function() {
slider.pause();
}, function() {
if (!slider.manualpause) {
slider.resume();
}
});
}
//initialize animation
slider.animatedslides = setinterval(slider.animateslides, slider.vars.slideshowspeed);
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//flexslider: pause/play
if (slider.vars.pauseplay) {
var pauseplayscaffold = $('
');
if (slider.containerexists) {
slider.controlscontainer.append(pauseplayscaffold);
slider.pauseplay = $('.flex-pauseplay span', slider.controlscontainer);
} else {
slider.append(pauseplayscaffold);
slider.pauseplay = $('.flex-pauseplay span', slider);
}
var pauseplaystate = (slider.vars.slideshow) ? 'pause' : 'play';
slider.pauseplay.addclass(pauseplaystate).text((pauseplaystate == 'pause') ? slider.vars.pausetext : slider.vars.playtext);
slider.pauseplay.bind(slider.eventtype, function(event) {
event.preventdefault();
if ($(this).hasclass('pause')) {
slider.pause();
slider.manualpause = true;
} else {
slider.resume();
slider.manualpause = false;
}
});
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//flexslider:touch swip gestures
//some brilliant concepts adapted from the following sources
//source: touchswipe - http://www.netcu.de/jquery-touchwipe-iphone-ipad-library
//source: swipejs - http://swipejs.com
if ('ontouchstart' in document.documentelement) {
//for brevity, variables are named for x-axis scrolling
//the variables are then swapped if vertical sliding is applied
//this reduces redundant code...i think :)
//if debugging, recognize variables are named for horizontal scrolling
var startx,
starty,
offset,
cwidth,
dx,
startt,
scrolling = false;
slider.each(function() {
if ('ontouchstart' in document.documentelement) {
this.addeventlistener('touchstart', ontouchstart, false);
}
});
function ontouchstart(e) {
if (slider.animating) {
e.preventdefault();
} else if (e.touches.length == 1) {
slider.pause();
cwidth = (slider.vertical) ? slider.height() : slider.width();
startt = number(new date());
offset = (slider.vertical) ? (slider.currentslide + slider.cloneoffset) * slider.height() : (slider.currentslide + slider.cloneoffset) * slider.width();
startx = (slider.vertical) ? e.touches[0].pagey : e.touches[0].pagex;
starty = (slider.vertical) ? e.touches[0].pagex : e.touches[0].pagey;
slider.settransition(0);
this.addeventlistener('touchmove', ontouchmove, false);
this.addeventlistener('touchend', ontouchend, false);
}
}
function ontouchmove(e) {
dx = (slider.vertical) ? startx - e.touches[0].pagey : startx - e.touches[0].pagex;
scrolling = (slider.vertical) ? (math.abs(dx) < math.abs(e.touches[0].pagex - starty)) : (math.abs(dx) < math.abs(e.touches[0].pagey - starty));
if (!scrolling) {
e.preventdefault();
if (slider.vars.animation == "slide" && slider.transitions) {
if (!slider.vars.animationloop) {
dx = dx/((slider.currentslide == 0 && dx < 0 || slider.currentslide == slider.count - 1 && dx > 0) ? (math.abs(dx)/cwidth+2) : 1);
}
slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + (-offset - dx) + "px,0)": "translate3d(" + (-offset - dx) + "px,0,0)";
slider.container.css(slider.args);
}
}
}
function ontouchend(e) {
slider.animating = false;
if (slider.animatingto == slider.currentslide && !scrolling && !(dx == null)) {
var target = (dx > 0) ? slider.gettarget('next') : slider.gettarget('prev');
if (slider.canadvance(target) && number(new date()) - startt < 550 && math.abs(dx) > 20 || math.abs(dx) > cwidth/2) {
slider.flexanimate(target, slider.vars.pauseonaction);
} else {
slider.flexanimate(slider.currentslide, slider.vars.pauseonaction);
}
}
//finish the touch by undoing the touch session
this.removeeventlistener('touchmove', ontouchmove, false);
this.removeeventlistener('touchend', ontouchend, false);
startx = null;
starty = null;
dx = null;
offset = null;
}
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//flexslider: resize functions (if necessary)
if (slider.vars.animation.tolowercase() == "slide") {
$(window).resize(function(){
if (!slider.animating) {
if (slider.vertical) {
slider.height(slider.slides.filter(':first').height());
slider.args[slider.prop] = (-1 * (slider.currentslide + slider.cloneoffset))* slider.slides.filter(':first').height() + "px";
if (slider.transitions) {
slider.settransition(0);
slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
}
slider.container.css(slider.args);
} else {
slider.newslides.width(slider.width());
slider.args[slider.prop] = (-1 * (slider.currentslide + slider.cloneoffset))* slider.width() + "px";
if (slider.transitions) {
slider.settransition(0);
slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
}
slider.container.css(slider.args);
}
}
});
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//flexslider: destroy the slider entity
//destory is not included in the minified version right now, but this is a working function for anyone who wants to include it.
//simply bind the actions you need from this function into a function in the start() callback to the event of your chosing
/*
slider.destroy = function() {
slider.pause();
if (slider.controlnav && slider.vars.manualcontrols == "") slider.controlnav.closest('.flex-control-nav').remove();
if (slider.directionnav) slider.directionnav.closest('.flex-direction-nav').remove();
if (slider.vars.pauseplay) slider.pauseplay.closest('.flex-pauseplay').remove();
if (slider.vars.keyboardnav && $('ul.slides').length == 1) $(document).unbind('keyup', keyboardmove);
if (slider.vars.mousewheel) slider.unbind(slider.mousewheelevent);
if (slider.transitions) slider.each(function(){this.removeeventlistener('touchstart', ontouchstart, false);});
if (slider.vars.animation == "slide" && slider.vars.animationloop) slider.newslides.filter('.clone').remove();
if (slider.vertical) slider.height("auto");
slider.slides.hide();
slider.removedata('flexslider');
}
*/
//////////////////////////////////////////////////////////////////
//flexslider: start() callback
slider.vars.start(slider);
}
//flexslider: animation actions
slider.flexanimate = function(target, pause) {
if (!slider.animating) {
//animating flag
slider.animating = true;
//flexslider: before() animation callback
slider.animatingto = target;
slider.vars.before(slider);
//optional paramter to pause slider when making an anmiation call
if (pause) {
slider.pause();
}
//update controlnav
if (slider.vars.controlnav) {
slider.controlnav.removeclass('active').eq(target).addclass('active');
}
//is the slider at either end
slider.atend = (target == 0 || target == slider.count - 1) ? true : false;
if (!slider.vars.animationloop && slider.vars.directionnav) {
if (target == 0) {
slider.directionnav.removeclass('disabled').filter('.prev').addclass('disabled');
} else if (target == slider.count - 1) {
slider.directionnav.removeclass('disabled').filter('.next').addclass('disabled');
} else {
slider.directionnav.removeclass('disabled');
}
}
if (!slider.vars.animationloop && target == slider.count - 1) {
slider.pause();
//flexslider: end() of cycle callback
slider.vars.end(slider);
}
if (slider.vars.animation.tolowercase() == "slide") {
var dimension = (slider.vertical) ? slider.slides.filter(':first').height() : slider.slides.filter(':first').width();
if (slider.currentslide == 0 && target == slider.count - 1 && slider.vars.animationloop && slider.direction != "next") {
slider.slidestring = "0px";
} else if (slider.currentslide == slider.count - 1 && target == 0 && slider.vars.animationloop && slider.direction != "prev") {
slider.slidestring = (-1 * (slider.count + 1)) * dimension + "px";
} else {
slider.slidestring = (-1 * (target + slider.cloneoffset)) * dimension + "px";
}
slider.args[slider.prop] = slider.slidestring;
if (slider.transitions) {
slider.settransition(slider.vars.animationduration);
slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.slidestring + ",0)" : "translate3d(" + slider.slidestring + ",0,0)";
slider.container.css(slider.args).one("webkittransitionend transitionend", function(){
slider.wrapup(dimension);
});
} else {
slider.container.animate(slider.args, slider.vars.animationduration, function(){
slider.wrapup(dimension);
});
}
} else { //default to fade
slider.slides.eq(slider.currentslide).fadeout(slider.vars.animationduration);
slider.slides.eq(target).fadein(slider.vars.animationduration, function() {
slider.wrapup();
});
}
}
}
//flexslider: function to minify redundant animation actions
slider.wrapup = function(dimension) {
if (slider.vars.animation == "slide") {
//jump the slider if necessary
if (slider.currentslide == 0 && slider.animatingto == slider.count - 1 && slider.vars.animationloop) {
slider.args[slider.prop] = (-1 * slider.count) * dimension + "px";
if (slider.transitions) {
slider.settransition(0);
slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
}
slider.container.css(slider.args);
} else if (slider.currentslide == slider.count - 1 && slider.animatingto == 0 && slider.vars.animationloop) {
slider.args[slider.prop] = -1 * dimension + "px";
if (slider.transitions) {
slider.settransition(0);
slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
}
slider.container.css(slider.args);
}
}
slider.animating = false;
slider.currentslide = slider.animatingto;
//flexslider: after() animation callback
slider.vars.after(slider);
}
//flexslider: automatic slideshow
slider.animateslides = function() {
if (!slider.animating) {
slider.flexanimate(slider.gettarget("next"));
}
}
//flexslider: automatic slideshow pause
slider.pause = function() {
clearinterval(slider.animatedslides);
if (slider.vars.pauseplay) {
slider.pauseplay.removeclass('pause').addclass('play').text(slider.vars.playtext);
}
}
//flexslider: automatic slideshow start/resume
slider.resume = function() {
slider.animatedslides = setinterval(slider.animateslides, slider.vars.slideshowspeed);
if (slider.vars.pauseplay) {
slider.pauseplay.removeclass('play').addclass('pause').text(slider.vars.pausetext);
}
}
//flexslider: helper function for non-looping sliders
slider.canadvance = function(target) {
if (!slider.vars.animationloop && slider.atend) {
if (slider.currentslide == 0 && target == slider.count - 1 && slider.direction != "next") {
return false;
} else if (slider.currentslide == slider.count - 1 && target == 0 && slider.direction == "next") {
return false;
} else {
return true;
}
} else {
return true;
}
}
//flexslider: helper function to determine animation target
slider.gettarget = function(dir) {
slider.direction = dir;
if (dir == "next") {
return (slider.currentslide == slider.count - 1) ? 0 : slider.currentslide + 1;
} else {
return (slider.currentslide == 0) ? slider.count - 1 : slider.currentslide - 1;
}
}
//flexslider: helper function to set css3 transitions
slider.settransition = function(dur) {
slider.container.css({'-webkit-transition-duration': (dur/1000) + "s"});
}
//flexslider: initialize
slider.init();
}
//flexslider: default settings
$.flexslider.defaults = {
animation: "fade", //string: select your animation type, "fade" or "slide"
slidedirection: "horizontal", //string: select the sliding direction, "horizontal" or "vertical"
slideshow: true, //boolean: animate slider automatically
slideshowspeed: 12000, //integer: set the speed of the slideshow cycling, in milliseconds
animationduration: 1500, //integer: set the speed of animations, in milliseconds
directionnav: true, //boolean: create navigation for previous/next navigation? (true/false)
controlnav: true, //boolean: create navigation for paging control of each clide? note: leave true for manualcontrols usage
keyboardnav: true, //boolean: allow slider navigating via keyboard left/right keys
mousewheel: false, //boolean: allow slider navigating via mousewheel
prevtext: "previous", //string: set the text for the "previous" directionnav item
nexttext: "next", //string: set the text for the "next" directionnav item
pauseplay: false, //boolean: create pause/play dynamic element
pausetext: 'pause', //string: set the text for the "pause" pauseplay item
playtext: 'play', //string: set the text for the "play" pauseplay item
randomize: false, //boolean: randomize slide order
slidetostart: 0, //integer: the slide that the slider should start on. array notation (0 = first slide)
animationloop: true, //boolean: should the animation loop? if false, directionnav will received "disable" classes at either end
pauseonaction: true, //boolean: pause the slideshow when interacting with control elements, highly recommended.
pauseonhover: false, //boolean: pause the slideshow when hovering over slider, then resume when no longer hovering
controlscontainer: "", //selector: declare which container the navigation elements should be appended too. default container is the flexslider element. example use would be ".flexslider-container", "#container", etc. if the given element is not found, the default action will be taken.
manualcontrols: "", //selector: declare custom control navigation. example would be ".flex-control-nav li" or "#tabs-nav li img", etc. the number of elements in your controlnav should match the number of slides/tabs.
start: function(){}, //callback: function(slider) - fires when the slider loads the first slide
before: function(){}, //callback: function(slider) - fires asynchronously with each slider animation
after: function(){}, //callback: function(slider) - fires after each slider animation completes
end: function(){} //callback: function(slider) - fires when the slider reaches the last slide (asynchronous)
}
//flexslider: plugin function
$.fn.flexslider = function(options) {
return this.each(function() {
if ($(this).find('.slides li').length == 1) {
$(this).find('.slides li').fadein(400);
}
else if ($(this).data('flexslider') != true) {
new $.flexslider($(this), options);
}
});
}
})(jquery);