/** * jquery plugin "swipe slider". * image slider that supports swiping function to change slides. */ (function ($) { $.fn.swipeslider = function (options) { var slidecontainer = this; var slider = this.find('.sw-slides'); // reference to slider var defaultsettings = { /** / how long one slide will change the other. */ transitionduration: 500, /** / enable autoplay */ autoplay: true, /** * how frequently slides will be changed. */ autoplaytimeout: 4000, /** * transition effect. */ timingfunction: 'ease-out', /** * show 'next' and 'previous' buttons. */ prevnextbuttons: true, /** * show slide switches. */ bullets: true, /** * enable swipe function. */ swipe: true, /** * overall height of the slider. set it to percent to make it responsive. * otherwise the slider will keep the height. */ sliderheight: '140px' }; var settings = $.extend(defaultsettings, options); // privates // /** sliding states: * 0 - sliding not started * 1 - sliding started * 2 - slide released */ var slidingstate = 0; var startclientx = 0; var startpixeloffset = 0; var pixeloffset = 0; var currentslide = 0; var slidecount = 0; // overall width of sliders. var slideswidth = 0; // flag for disbling swipe function while transition animation is playing. var allowswipe = true; var transitionduration = settings.transitionduration; var swipe = settings.swipe; var autoplaytimeout = settings.autoplaytimeout; // id of timeout function that waits for animation to end. var animationdelayid = undefined; var allowslideswitch = true; var autoplay = settings.autoplay; /** * set initial values. */ (function init() { $(slidecontainer).css('padding-top', settings.sliderheight); slideswidth = slider.width(); // change slide width when window changes. $(window).resize(resizeslider); if(settings.prevnextbuttons) { insertprevnextbuttons(); } // add last slide before first and first before last to seamless and engless transition slider.find('.sw-slide:last-child').clone().prependto(slider); slider.find('.sw-slide:nth-child(2)').clone().appendto(slider); slidecount = slider.find('.sw-slide').length; if(settings.bullets) { insertbullets(slidecount - 2); } settransitionduration(transitionduration); settimingfunction(settings.timingfunction); settransitionproperty('all'); if(swipe) { // add event handlers to react when user swipe. slider.on('mousedown touchstart', swipestart); $('html').on('mouseup touchend', swipeend); $('html').on('mousemove touchmove', swiping); } // jump to slide 1 (since another slide was added to the beginning of row); jumptoslide(1); enableautoplay(); })(); /** * changes slider size to response on window change. */ function resizeslider(){ // slide width is being changed automatically. tough slideswidth used to calculate a distance of transition effect. slideswidth = slider.width(); switchslide(); } /** * triggers when user starts swipe. * @param event browser event object */ function swipestart(event) { if(!allowswipe) { return; } disableautoplay(); // if it is mobile device redefine event to first touch point if (event.originalevent.touches) event = event.originalevent.touches[0]; // check if slide started on slider if (slidingstate == 0){ slidingstate = 1; // status 1 = slide started. startclientx = event.clientx; } } /** triggers when user continues swipe. * @param event browser event object */ function swiping(event) { var pointerdata; // get pointer data from event. if (event.originalevent.touches) { pointerdata = event.originalevent.touches[0]; } else { pointerdata = event; } // distance of slide from the first touch var deltaslide = pointerdata.clientx - startclientx; // if sliding started first time and there was a distance. if (slidingstate == 1 && deltaslide != 0) { slidingstate = 2; // set status to 'actually moving' startpixeloffset = currentslide * -slideswidth; // store current offset of slide } // when user move image if (slidingstate == 2) { event.preventdefault(); // disable default action to prevent unwanted selection. can't prevent touches. // means that user slide 1 pixel for every 1 pixel of mouse movement. var touchpixelratio = 1; // check for user doesn't slide out of boundaries if ((currentslide == 0 && pointerdata.clientx > startclientx) || (currentslide == slidecount - 1 && pointerdata.clientx < startclientx)) { // set ratio to 3 means image will be moving by 3 pixels each time user moves it's pointer by 1 pixel. (rubber-band effect) touchpixelratio = 3; } // how far to translate slide while dragging. pixeloffset = startpixeloffset + deltaslide / touchpixelratio; enabletransition(false); // apply moving and remove animation class translatex(pixeloffset); } } /** triggers when user finishes swipe. * @param event browser event object */ function swipeend(event) { if (slidingstate == 2) { // reset sliding state. slidingstate = 0; // calculate which slide need to be in view. currentslide = pixeloffset < startpixeloffset ? currentslide + 1 : currentslide -1; // make sure that unexisting slides weren't selected. currentslide = math.min(math.max(currentslide, 0), slidecount - 1); // since in this example slide is full viewport width offset can be calculated according to it. pixeloffset = currentslide * -slideswidth; disableswipe(); switchslide(); enableautoplay(); } slidingstate = 0; } /** * disables reaction on swipe while transition effect is playing. */ function disableswipe() { allowswipe = false; window.settimeout(enableswipe, transitionduration) } /** * enables reaction on swipe. */ function enableswipe() { allowswipe = true; } /** * disables autoplay function. * used while performing manual operations. */ function disableautoplay() { allowslideswitch = false; window.cleartimeout(animationdelayid); } /** * enables autoplay function. * used to prevent auto play when user performs manual switching. */ function enableautoplay() { if(autoplay) { allowslideswitch = true; startautoplay(); } } /** * launches autoplay function with delay. */ function startautoplay() { if(allowslideswitch) { animationdelayid = window.settimeout(performautoplay, autoplaytimeout); } } /** * switches between slides in autoplay mode. */ function performautoplay() { switchforward(); startautoplay(); } /** * switches slideshow one slide forward. */ function switchforward() { currentslide += 1; switchslide(); } /** * switches slideshow one slide backward. */ function switchbackward() { currentslide -= 1; switchslide(); } /** * switches slideshow to currentslide. */ function switchslide() { enabletransition(true); translatex(-currentslide * slideswidth); if(currentslide == 0) { window.settimeout(jumptoend, transitionduration); } else if (currentslide == slidecount - 1) { window.settimeout(jumptostart, transitionduration); } setactivebullet(currentslide); } /** * switches slideshow to the first slide. * remark: the first slide from html elements, not the slide that was added for smooth transition effect. */ function jumptostart() { jumptoslide(1); } /** * switches slideshow to the last slide. * remark: the last slide from html elements, not the slide that was added for smooth transition effect. */ function jumptoend() { jumptoslide(slidecount - 2); } /** * switches slideshow to exact slide number. * remark: respecting two slides that were added for smooth transaction effect. */ function jumptoslide(slidenumber) { enabletransition(false); currentslide = slidenumber; translatex(-slideswidth * currentslide); window.settimeout(returntransitionafterjump, 50); } /** * returns transition effect after jumptoslide function call. */ function returntransitionafterjump() { enabletransition(true); } /** * enables or disables transition * @param {bool} true to enable traintion. */ function enabletransition(enable) { if (enable) { settransitionproperty('all'); } else { settransitionproperty('none'); } } /** * translates slides on certain amount. * @param distance {number} distance of transition. if negative, transition from right to left. */ function translatex(distance) { slider // prefixes are being set automatically. // .css('-webkit-transform','translatex(' + distance + 'px)') // .css('-ms-transform','translatex(' + distance + 'px)') .css('transform','translatex(' + distance + 'px)'); } /** * sets duration of transition between slides. * @param duration {number} amount in milliseconds. */ function settransitionduration(duration) { slider // .css('-webkit-transition-duration', duration + 'ms') .css('transition-duration', duration + 'ms'); } /** * sets transition function. */ function settimingfunction(functiondescription) { slider // .css('-webkit-transition-timing-function', functiondescription) .css('transition-timing-function', functiondescription); } /** * sets property that will be used in transition effect. */ function settransitionproperty(property) { slider // .css('-webkit-transition-property', property) .css('transition-property', property); } /** * next slide and previous slide buttons. */ function insertprevnextbuttons() { slider.after(''); slidecontainer.find('.sw-prev').click(function(){ if(allowslideswitch){ disableautoplay(); switchbackward(); enableautoplay(); } }); slider.after(''); slidecontainer.find('.sw-next').click(function(){ if(allowslideswitch) { disableautoplay(); switchforward(); enableautoplay(); } }); } /** * add bullet indicator of current slide. */ function insertbullets(count) { slider.after(''); var bulletlist = slider.parent().find('.sw-bullet'); for (var i = 0; i < count; i++) { if (i == 0) { bulletlist.append('
  • '); } else { bulletlist.append('
  • '); } var item = slidecontainer.find('.sw-slide-' + i); // workaround a problem when iterator i will have max value due to closure nature. (function(lockedindex) { item.click(function() { // disable autoplay on time of transition. disableautoplay(); currentslide = lockedindex + 1; switchslide(); enableautoplay(); }); })(i); } } /** * sets active bullet mark of active slide. * @param number {number} active slide with respect of two added slides. */ function setactivebullet(number) { var activebullet = 0; if(number == 0) { activebullet = slidecount - 3; } else if (number == slidecount - 1) { activebullet = 0; } else { activebullet = number - 1; } slidecontainer.find('.sw-bullet').find('li').removeclass('active'); slidecontainer.find('.sw-slide-' + activebullet).addclass('active'); } return slidecontainer; } }(jquery));