Last active
December 28, 2015 18:38
-
-
Save azz/7544093 to your computer and use it in GitHub Desktop.
Modified "Basic jQuery Slider" to add an active class to the current `li` tag.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Basic jQuery Slider plug-in v.1.3 | |
* | |
* http://www.basic-slider.com | |
* | |
* Authored by John Cobb | |
* http://www.johncobb.name | |
* @john0514 | |
* | |
* Copyright 2011, John Cobb | |
* License: GNU General Public License, version 3 (GPL-3.0) | |
* http://www.opensource.org/licenses/gpl-3.0.html | |
* | |
* Modified by Der Flatulator 19 November 2013 | |
* | |
*/ | |
;(function($) { | |
"use strict"; | |
$.fn.bjqs = function(o) { | |
// slider default settings | |
var defaults = { | |
// w + h to enforce consistency | |
width : 700, | |
height : 300, | |
// transition valuess | |
animtype : 'fade', | |
animduration : 450, // length of transition | |
animspeed : 4000, // delay between transitions | |
automatic : true, // enable/disable automatic slide rotation | |
// control and marker configuration | |
showcontrols : true, // enable/disable next + previous UI elements | |
centercontrols : true, // vertically center controls | |
nexttext : 'Next', // text/html inside next UI element | |
prevtext : 'Prev', // text/html inside previous UI element | |
showmarkers : true, // enable/disable individual slide UI markers | |
centermarkers : true, // horizontally center markers | |
// interaction values | |
keyboardnav : true, // enable/disable keyboard navigation | |
hoverpause : true, // enable/disable pause slides on hover | |
// presentational options | |
usecaptions : true, // enable/disable captions using img title attribute | |
randomstart : false, // start from a random slide | |
responsive : false // enable responsive behaviour | |
}; | |
// create settings from defauls and user options | |
var settings = $.extend({}, defaults, o); | |
// slider elements | |
var $wrapper = this, | |
$slider = $wrapper.find('ul.bjqs'), | |
$slides = $slider.children('li'), | |
// control elements | |
$c_wrapper = null, | |
$c_fwd = null, | |
$c_prev = null, | |
// marker elements | |
$m_wrapper = null, | |
$m_markers = null, | |
// elements for slide animation | |
$canvas = null, | |
$clone_first = null, | |
$clone_last = null; | |
// state management object | |
var state = { | |
slidecount : $slides.length, // total number of slides | |
animating : false, // bool: is transition is progress | |
paused : false, // bool: is the slider paused | |
currentslide : 1, // current slide being viewed (not 0 based) | |
nextslide : 0, // slide to view next (not 0 based) | |
currentindex : 0, // current slide being viewed (0 based) | |
nextindex : 0, // slide to view next (0 based) | |
interval : null // interval for automatic rotation | |
}; | |
var responsive = { | |
width : null, | |
height : null, | |
ratio : null | |
}; | |
// helpful variables | |
var vars = { | |
fwd : 'forward', | |
prev : 'previous' | |
}; | |
// run through options and initialise settings | |
var init = function() { | |
// differentiate slider li from content li | |
$slides.addClass('bjqs-slide'); | |
// conf dimensions, responsive or static | |
if( settings.responsive ){ | |
conf_responsive(); | |
} | |
else{ | |
conf_static(); | |
} | |
// configurations only avaliable if more than 1 slide | |
if( state.slidecount > 1 ){ | |
// enable random start | |
if (settings.randomstart){ | |
conf_random(); | |
} | |
// create and show controls | |
if( settings.showcontrols ){ | |
conf_controls(); | |
} | |
// create and show markers | |
if( settings.showmarkers ){ | |
conf_markers(); | |
} | |
// enable slidenumboard navigation | |
if( settings.keyboardnav ){ | |
conf_keynav(); | |
} | |
// enable pause on hover | |
if (settings.hoverpause && settings.automatic){ | |
conf_hoverpause(); | |
} | |
// conf slide animation | |
if (settings.animtype === 'slide'){ | |
conf_slide(); | |
} | |
} else { | |
// Stop automatic animation, because we only have one slide! | |
settings.automatic = false; | |
} | |
if(settings.usecaptions){ | |
conf_captions(); | |
} | |
// TODO: need to accomodate random start for slide transition setting | |
if(settings.animtype === 'slide' && !settings.randomstart){ | |
state.currentindex = 1; | |
state.currentslide = 2; | |
} | |
// slide components are hidden by default, show them now | |
$slider.show(); | |
$slides.eq(state.currentindex).show(); | |
// Finally, if automatic is set to true, kick off the interval | |
if(settings.automatic){ | |
state.interval = setInterval(function () { | |
go(vars.fwd, false); | |
}, settings.animspeed); | |
} | |
}; | |
var conf_responsive = function() { | |
responsive.width = $wrapper.outerWidth(); | |
responsive.ratio = responsive.width/settings.width, | |
responsive.height = settings.height * responsive.ratio; | |
if(settings.animtype === 'fade'){ | |
// initial setup | |
$slides.css({ | |
'height' : settings.height, | |
'width' : '100%' | |
}); | |
$slides.children('img').css({ | |
'height' : settings.height, | |
'width' : '100%' | |
}); | |
$slider.css({ | |
'height' : settings.height, | |
'width' : '100%' | |
}); | |
$wrapper.css({ | |
'height' : settings.height, | |
'max-width' : settings.width, | |
'position' : 'relative' | |
}); | |
if(responsive.width < settings.width){ | |
$slides.css({ | |
'height' : responsive.height | |
}); | |
$slides.children('img').css({ | |
'height' : responsive.height | |
}); | |
$slider.css({ | |
'height' : responsive.height | |
}); | |
$wrapper.css({ | |
'height' : responsive.height | |
}); | |
} | |
$(window).resize(function() { | |
// calculate and update dimensions | |
responsive.width = $wrapper.outerWidth(); | |
responsive.ratio = responsive.width/settings.width, | |
responsive.height = settings.height * responsive.ratio; | |
$slides.css({ | |
'height' : responsive.height | |
}); | |
$slides.children('img').css({ | |
'height' : responsive.height | |
}); | |
$slider.css({ | |
'height' : responsive.height | |
}); | |
$wrapper.css({ | |
'height' : responsive.height | |
}); | |
}); | |
} | |
if(settings.animtype === 'slide'){ | |
// initial setup | |
$slides.css({ | |
'height' : settings.height, | |
'width' : settings.width | |
}); | |
$slides.children('img').css({ | |
'height' : settings.height, | |
'width' : settings.width | |
}); | |
$slider.css({ | |
'height' : settings.height, | |
'width' : settings.width * settings.slidecount | |
}); | |
$wrapper.css({ | |
'height' : settings.height, | |
'max-width' : settings.width, | |
'position' : 'relative' | |
}); | |
if(responsive.width < settings.width){ | |
$slides.css({ | |
'height' : responsive.height | |
}); | |
$slides.children('img').css({ | |
'height' : responsive.height | |
}); | |
$slider.css({ | |
'height' : responsive.height | |
}); | |
$wrapper.css({ | |
'height' : responsive.height | |
}); | |
} | |
$(window).resize(function() { | |
// calculate and update dimensions | |
responsive.width = $wrapper.outerWidth(), | |
responsive.ratio = responsive.width/settings.width, | |
responsive.height = settings.height * responsive.ratio; | |
$slides.css({ | |
'height' : responsive.height, | |
'width' : responsive.width | |
}); | |
$slides.children('img').css({ | |
'height' : responsive.height, | |
'width' : responsive.width | |
}); | |
$slider.css({ | |
'height' : responsive.height, | |
'width' : responsive.width * settings.slidecount | |
}); | |
$wrapper.css({ | |
'height' : responsive.height | |
}); | |
$canvas.css({ | |
'height' : responsive.height, | |
'width' : responsive.width | |
}); | |
resize_complete(function(){ | |
go(false,state.currentslide); | |
}, 200, "some unique string"); | |
}); | |
} | |
}; | |
var resize_complete = (function () { | |
var timers = {}; | |
return function (callback, ms, uniqueId) { | |
if (!uniqueId) { | |
uniqueId = "Don't call this twice without a uniqueId"; | |
} | |
if (timers[uniqueId]) { | |
clearTimeout (timers[uniqueId]); | |
} | |
timers[uniqueId] = setTimeout(callback, ms); | |
}; | |
})(); | |
// enforce fixed sizing on slides, slider and wrapper | |
var conf_static = function() { | |
$slides.css({ | |
'height' : settings.height, | |
'width' : settings.width | |
}); | |
$slider.css({ | |
'height' : settings.height, | |
'width' : settings.width | |
}); | |
$wrapper.css({ | |
'height' : settings.height, | |
'width' : settings.width, | |
'position' : 'relative' | |
}); | |
}; | |
var conf_slide = function() { | |
// create two extra elements which are clones of the first and last slides | |
$clone_first = $slides.eq(0).clone(); | |
$clone_last = $slides.eq(state.slidecount-1).clone(); | |
// add them to the DOM where we need them | |
$clone_first.attr({'data-clone' : 'last', 'data-slide' : 0}).appendTo($slider).show(); | |
$clone_last.attr({'data-clone' : 'first', 'data-slide' : 0}).prependTo($slider).show(); | |
// update the elements object | |
$slides = $slider.children('li'); | |
state.slidecount = $slides.length; | |
// add the first active class | |
if (settings.showmarkers) | |
$slides.eq(state.currentslide - 1).addClass('active'); | |
// create a 'canvas' element which is neccessary for the slide animation to work | |
$canvas = $('<div class="bjqs-wrapper"></div>'); | |
// if the slider is responsive && the calculated width is less than the max width | |
if(settings.responsive && (responsive.width < settings.width)){ | |
$canvas.css({ | |
'width' : responsive.width, | |
'height' : responsive.height, | |
'overflow' : 'hidden', | |
'position' : 'relative' | |
}); | |
// update the dimensions to the slider to accomodate all the slides side by side | |
$slider.css({ | |
'width' : responsive.width * (state.slidecount + 2), | |
'left' : -responsive.width * state.currentslide | |
}); | |
} | |
else { | |
$canvas.css({ | |
'width' : settings.width, | |
'height' : settings.height, | |
'overflow' : 'hidden', | |
'position' : 'relative' | |
}); | |
// update the dimensions to the slider to accomodate all the slides side by side | |
$slider.css({ | |
'width' : settings.width * (state.slidecount + 2), | |
'left' : -settings.width * state.currentslide | |
}); | |
} | |
// add some inline styles which will align our slides for left-right sliding | |
$slides.css({ | |
'float' : 'left', | |
'position' : 'relative', | |
'display' : 'list-item' | |
}); | |
// 'everything.. in it's right place' | |
$canvas.prependTo($wrapper); | |
$slider.appendTo($canvas); | |
}; | |
var conf_controls = function() { | |
// create the elements for the controls | |
$c_wrapper = $('<ul class="bjqs-controls"></ul>'); | |
$c_fwd = $('<li class="bjqs-next"><a href="#" data-direction="'+ vars.fwd +'">' + settings.nexttext + '</a></li>'); | |
$c_prev = $('<li class="bjqs-prev"><a href="#" data-direction="'+ vars.prev +'">' + settings.prevtext + '</a></li>'); | |
// bind click events | |
$c_wrapper.on('click','a',function(e){ | |
e.preventDefault(); | |
var direction = $(this).attr('data-direction'); | |
if(!state.animating){ | |
if(direction === vars.fwd){ | |
go(vars.fwd,false); | |
} | |
if(direction === vars.prev){ | |
go(vars.prev,false); | |
} | |
} | |
}); | |
// put 'em all together | |
$c_prev.appendTo($c_wrapper); | |
$c_fwd.appendTo($c_wrapper); | |
$c_wrapper.appendTo($wrapper); | |
// vertically center the controls | |
if (settings.centercontrols) { | |
$c_wrapper.addClass('v-centered'); | |
// calculate offset % for vertical positioning | |
var offset_px = ($wrapper.height() - $c_fwd.children('a').outerHeight()) / 2, | |
ratio = (offset_px / settings.height) * 100, | |
offset = ratio + '%'; | |
$c_fwd.find('a').css('top', offset); | |
$c_prev.find('a').css('top', offset); | |
} | |
}; | |
var conf_markers = function() { | |
// create a wrapper for our markers | |
$m_wrapper = $('<ol class="bjqs-markers"></ol>'); | |
// for every slide, create a marker | |
$.each($slides, function(key, slide){ | |
var slidenum = key + 1, | |
gotoslide = key + 1; | |
if(settings.animtype === 'slide'){ | |
// + 2 to account for clones | |
gotoslide = key + 2; | |
} | |
var marker = $('<li><a href="#">'+ slidenum +'</a></li>'); | |
// set the first marker to be active | |
if(slidenum === state.currentslide){ marker.addClass('active-marker'); } | |
// bind the click event | |
marker.on('click','a',function(e){ | |
e.preventDefault(); | |
if(!state.animating && state.currentslide !== gotoslide){ | |
go(false,gotoslide); | |
} | |
}); | |
// add the marker to the wrapper | |
marker.appendTo($m_wrapper); | |
}); | |
$m_wrapper.appendTo($wrapper); | |
$m_markers = $m_wrapper.find('li'); | |
// center the markers | |
if (settings.centermarkers) { | |
$m_wrapper.addClass('h-centered'); | |
var offset = (settings.width - $m_wrapper.width()) / 2; | |
$m_wrapper.css('left', offset); | |
} | |
}; | |
var conf_keynav = function() { | |
$(document).keyup(function (event) { | |
if (!state.paused) { | |
clearInterval(state.interval); | |
state.paused = true; | |
} | |
if (!state.animating) { | |
if (event.keyCode === 39) { | |
event.preventDefault(); | |
go(vars.fwd, false); | |
} else if (event.keyCode === 37) { | |
event.preventDefault(); | |
go(vars.prev, false); | |
} | |
} | |
if (state.paused && settings.automatic) { | |
state.interval = setInterval(function () { | |
go(vars.fwd); | |
}, settings.animspeed); | |
state.paused = false; | |
} | |
}); | |
}; | |
var conf_hoverpause = function() { | |
$wrapper.hover(function () { | |
if (!state.paused) { | |
clearInterval(state.interval); | |
state.paused = true; | |
} | |
}, function () { | |
if (state.paused) { | |
state.interval = setInterval(function () { | |
go(vars.fwd, false); | |
}, settings.animspeed); | |
state.paused = false; | |
} | |
}); | |
}; | |
var conf_captions = function() { | |
$.each($slides, function (key, slide) { | |
var caption = $(slide).children('img:first-child').attr('title'); | |
// Account for images wrapped in links | |
if(!caption){ | |
caption = $(slide).children('a').find('img:first-child').attr('title'); | |
} | |
if (caption) { | |
caption = $('<p class="bjqs-caption">' + caption + '</p>'); | |
caption.appendTo($(slide)); | |
} | |
}); | |
}; | |
var conf_random = function() { | |
var rand = Math.floor(Math.random() * state.slidecount) + 1; | |
state.currentslide = rand; | |
state.currentindex = rand-1; | |
}; | |
var set_next = function(direction) { | |
if(direction === vars.fwd){ | |
if($slides.eq(state.currentindex).next().length){ | |
state.nextindex = state.currentindex + 1; | |
state.nextslide = state.currentslide + 1; | |
} | |
else{ | |
state.nextindex = 0; | |
state.nextslide = 1; | |
} | |
} | |
else{ | |
if($slides.eq(state.currentindex).prev().length){ | |
state.nextindex = state.currentindex - 1; | |
state.nextslide = state.currentslide - 1; | |
} | |
else{ | |
state.nextindex = state.slidecount - 1; | |
state.nextslide = state.slidecount; | |
} | |
} | |
}; | |
var go = function(direction, position) { | |
// only if we're not already doing things | |
if(!state.animating){ | |
// doing things | |
state.animating = true; | |
if(position){ | |
state.nextslide = position; | |
state.nextindex = position-1; | |
} | |
else{ | |
set_next(direction); | |
} | |
// fade animation | |
if(settings.animtype === 'fade'){ | |
if(settings.showmarkers){ | |
$m_markers.removeClass('active-marker'); | |
$m_markers.eq(state.nextindex).addClass('active-marker'); | |
$slides.removeClass('active'); | |
$slides.eq(state.nextindex).addClass('active'); | |
} | |
// fade out current | |
$slides.eq(state.currentindex).fadeOut(settings.animduration); | |
// fade in next | |
$slides.eq(state.nextindex).fadeIn(settings.animduration, function(){ | |
// update state variables | |
state.animating = false; | |
state.currentslide = state.nextslide; | |
state.currentindex = state.nextindex; | |
}); | |
} | |
// slide animation | |
if(settings.animtype === 'slide'){ | |
if(settings.showmarkers){ | |
var markerindex = state.nextindex-1; | |
if(markerindex === state.slidecount-2){ | |
markerindex = 0; | |
} | |
else if(markerindex === -1){ | |
markerindex = state.slidecount-3; | |
} | |
$m_markers.removeClass('active-marker'); | |
$m_markers.eq(markerindex).addClass('active-marker'); | |
$slides.removeClass('active'); | |
$slides.eq(markerindex).addClass('active'); | |
} | |
// if the slider is responsive && the calculated width is less than the max width | |
if(settings.responsive && ( responsive.width < settings.width ) ){ | |
state.slidewidth = responsive.width; | |
} | |
else{ | |
state.slidewidth = settings.width; | |
} | |
$slider.animate({'left': -state.nextindex * state.slidewidth }, settings.animduration, function(){ | |
state.currentslide = state.nextslide; | |
state.currentindex = state.nextindex; | |
// is the current slide a clone? | |
if($slides.eq(state.currentindex).attr('data-clone') === 'last'){ | |
// affirmative, at the last slide (clone of first) | |
$slider.css({'left': -state.slidewidth }); | |
state.currentslide = 2; | |
state.currentindex = 1; | |
} | |
else if($slides.eq(state.currentindex).attr('data-clone') === 'first'){ | |
// affirmative, at the fist slide (clone of last) | |
$slider.css({'left': -state.slidewidth *(state.slidecount - 2)}); | |
state.currentslide = state.slidecount - 1; | |
state.currentindex = state.slidecount - 2; | |
} | |
state.animating = false; | |
}); | |
} | |
} | |
}; | |
// lets get the party started :) | |
init(); | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment