/** * @name owl carousel - code name phenix * @author bartosz wojciechowski * @release 2014 * licensed under mit * * @version 2.0.0-beta.1.8 * @versionnotes not compatibile with owl carousel <2.0.0 */ /* {0,0} )_) "" to do: * lazy load icon * prevent animationend bubling * itemsscaleup * test zepto callback events list: oninitbefore oninitafter onresponsivebefore onresponsiveafter ontransitionstart ontransitionend ontouchstart ontouchend onchangestate onlazyloaded onvideoplay onvideostop custom events list: next.owl prev.owl goto.owl jumpto.owl additem.owl removeitem.owl refresh.owl play.owl stop.owl stopvideo.owl */ ;(function ( $, window, document, undefined ) { var defaults = { items: 3, loop: false, center: false, mousedrag: true, touchdrag: true, pulldrag: true, freedrag: false, margin: 0, stagepadding: 0, merge: false, mergefit: true, autowidth: false, autoheight: false, startposition: 0, urlhashlistener: false, nav: false, navrewind: true, navtext: ['prev','next'], slideby: 1, dots: true, dotseach: false, dotdata: false, lazyload: false, lazycontent: false, autoplay: false, autoplaytimeout: 5000, autoplayhoverpause: false, smartspeed: 250, fluidspeed: false, autoplayspeed: false, navspeed: false, dotsspeed: false, dragendspeed: false, responsive: {}, responsiverefreshrate : 200, responsivebaseelement: window, responsiveclass: false, video: false, videoheight: false, videowidth: false, animateout: false, animatein: false, fallbackeasing: 'swing', callbacks: false, info: false, nesteditemselector: false, itemelement: 'div', stageelement: 'div', //classes and names themeclass: 'owl-theme', baseclass: 'owl-carousel', itemclass: 'owl-item', centerclass: 'center', activeclass: 'active', navcontainerclass: 'owl-nav', navclass: ['owl-prev','owl-next'], controlsclass: 'owl-controls', dotclass: 'owl-dot', dotsclass: 'owl-dots', autoheightclass: 'owl-height' }; // reference to dom elements // those with $ sign are jquery objects var dom = { el: null, // main element $el: null, // jquery main element stage: null, // stage $stage: null, // jquery stage ostage: null, // outer stage $ostage: null, // $ outer stage $items: null, // all items, clones and originals included $oitems: null, // original items $citems: null, // cloned items only $cc: null, $navprev: null, $navnext: null, $page: null, $nav: null, $content: null }; /** * variables * @since 2.0.0 */ // only for development process // widths var width = { el: 0, stage: 0, item: 0, prevwindow: 0, clonelast: 0 }; // numbers var num = { items: 0, oitems: 0, citems: 0, active: 0, merged: [], nav: [], allpages: 0 }; // positions var pos = { start: 0, max: 0, maxvalue: 0, prev: 0, current: 0, currentabs: 0, currentpage:0, stage: 0, items: [], lscurrent: 0 }; // drag/touches var drag = { start: 0, startx: 0, starty: 0, current: 0, currentx: 0, currenty: 0, offsetx: 0, offsety: 0, distance: null, starttime: 0, endtime: 0, updatedx: 0, targetel: null }; // speeds var speed = { ondragend: 300, nav: 300, css2speed: 0 }; // states var state = { istouch: false, isscrolling: false, isswiping: false, direction: false, inmotion: false, autoplay: false, lazycontent: false }; // event functions references var e = { _ondragstart: null, _ondragmove: null, _ondragend: null, _transitionend: null, _resizer: null, _responsivecall:null, _gotoloop: null, _checkvisibile: null, _autoplay: null, _pause: null, _play: null, _stop: null }; function owl( element, options ) { // add basic owl information to dom element element.owlcarousel = { 'name': 'owl carousel', 'author': 'bartosz wojciechowski', 'version': '2.0.0-beta.1.8', 'released': '03.05.2014' }; // attach variables to object // only for development process this.options = $.extend( {}, defaults, options); this._options = $.extend( {}, defaults, options); this.dom = $.extend( {}, dom); this.width = $.extend( {}, width); this.num = $.extend( {}, num); this.pos = $.extend( {}, pos); this.drag = $.extend( {}, drag); this.speed = $.extend( {}, speed); this.state = $.extend( {}, state); this.e = $.extend( {}, e); this.dom.el = element; this.dom.$el = $(element); this.init(); } /** * init * @since 2.0.0 */ owl.prototype.init = function(){ this.firecallback('oninitbefore'); //add base class if(!this.dom.$el.hasclass(this.options.baseclass)){ this.dom.$el.addclass(this.options.baseclass); } //add theme class if(!this.dom.$el.hasclass(this.options.themeclass)){ this.dom.$el.addclass(this.options.themeclass); } //add theme class if(this.options.rtl){ this.dom.$el.addclass('owl-rtl'); } // check support this.browsersupport(); // sort responsive items in array this.sortoptions(); // update options.items on given size this.setresponsiveoptions(); if(this.options.autowidth && this.state.imagesloaded !== true){ var imgs = this.dom.$el.find('img'); if(imgs.length){ this.preloadautowidthimages(imgs); return false; } } // get and store window width // ios safari likes to trigger unnecessary resize event this.width.prevwindow = this.windowwidth(); // create stage object this.createstage(); // append local content this.fetchcontent(); // attach generic events this.eventscall(); // attach custom control events this.addcustomevents(); // attach generic events this.internalevents(); this.dom.$el.addclass('owl-loading'); this.refresh(true); this.dom.$el.removeclass('owl-loading').addclass('owl-loaded'); this.firecallback('oninitafter'); }; /** * sortoptions * @desc sort responsive sizes * @since 2.0.0 */ owl.prototype.sortoptions = function(){ var resopt = this.options.responsive; this.responsivesorted = {}; var keys = [], i, j, k; for (i in resopt){ keys.push(i); } keys = keys.sort(function (a, b) {return a - b;}); for (j = 0; j < keys.length; j++){ k = keys[j]; this.responsivesorted[k] = resopt[k]; } }; /** * setresponsiveoptions * @since 2.0.0 */ owl.prototype.setresponsiveoptions = function(){ if(this.options.responsive === false){return false;} var width = this.windowwidth(); var resopt = this.options.responsive; var i,j,k, minwidth; // overwrite non resposnive options for(k in this._options){ if(k !== 'responsive'){ this.options[k] = this._options[k]; } } // find responsive width for (i in this.responsivesorted){ if(i<= width){ minwidth = i; // set responsive options for(j in this.responsivesorted[minwidth]){ this.options[j] = this.responsivesorted[minwidth][j]; } } } this.num.breakpoint = minwidth; // responsive class if(this.options.responsiveclass){ this.dom.$el.attr('class', function(i, c){ return c.replace(/\b owl-responsive-\s+/g, ''); }).addclass('owl-responsive-'+minwidth); } }; /** * optionslogic * @desc update option logic if necessery * @since 2.0.0 */ owl.prototype.optionslogic = function(){ // toggle center class this.dom.$el.toggleclass('owl-center',this.options.center); // scroll per - 'page' option will scroll per visible items number // you can set this to any other number below visible items. if(this.options.slideby && this.options.slideby === 'page'){ this.options.slideby = this.options.items; } else if(this.options.slideby > this.options.items){ this.options.slideby = this.options.items; } // if items number is less than in body if(this.options.loop && this.num.oitems < this.options.items){ this.options.loop = false; } if(this.num.oitems <= this.options.items){ this.options.navrewind = false; } if(this.options.autowidth){ this.options.stagepadding = false; this.options.dotseach = 1; this.options.merge = false; } if(this.state.lazycontent){ this.options.loop = false; this.options.merge = false; this.options.dots = false; this.options.freedrag = false; this.options.lazycontent = true; } if((this.options.animatein || this.options.animateout) && this.options.items === 1 && this.support3d){ this.state.animate = true; } else {this.state.animate = false;} }; /** * createstage * @desc create stage and outer-stage elements * @since 2.0.0 */ owl.prototype.createstage = function(){ var ostage = document.createelement('div'); var stage = document.createelement(this.options.stageelement); ostage.classname = 'owl-stage-outer'; stage.classname = 'owl-stage'; ostage.appendchild(stage); this.dom.el.appendchild(ostage); this.dom.ostage = ostage; this.dom.$ostage = $(ostage); this.dom.stage = stage; this.dom.$stage = $(stage); ostage = null; stage = null; }; /** * createitem * @desc create item container * @since 2.0.0 */ owl.prototype.createitem = function(){ var item = document.createelement(this.options.itemelement); item.classname = this.options.itemclass; return item; }; /** * fetchcontent * @since 2.0.0 */ owl.prototype.fetchcontent = function(extcontent){ if(extcontent){ this.dom.$content = (extcontent instanceof jquery) ? extcontent : $(extcontent); } else if(this.options.nesteditemselector){ this.dom.$content= this.dom.$el.find('.'+this.options.nesteditemselector).not('.owl-stage-outer'); } else { this.dom.$content= this.dom.$el.children().not('.owl-stage-outer'); } // content length this.num.oitems = this.dom.$content.length; // init structure if(this.num.oitems !== 0){ this.initstructure(); } }; /** * initstructure * @param [refresh] - if refresh and not lazycontent then dont create normal structure * @since 2.0.0 */ owl.prototype.initstructure = function(){ // lazycontent needs at least 3*items if(this.options.lazycontent && this.num.oitems >= this.options.items*3){ this.state.lazycontent = true; } else { this.state.lazycontent = false; } if(this.state.lazycontent){ // start position this.pos.currentabs = this.options.items; //remove lazy content from dom this.dom.$content.remove(); } else { // create normal structure this.createnormalstructure(); } }; /** * createnormalstructure * @desc create normal structure for small/mid weight content * @since 2.0.0 */ owl.prototype.createnormalstructure = function(){ for(var i = 0; i < this.num.oitems; i++){ // fill 'owl-item' with content var item = this.fillitem(this.dom.$content,i); // append into stage this.dom.$stage.append(item); } this.dom.$content = null; }; /** * createcustomstructure * @since 2.0.0 */ owl.prototype.createcustomstructure = function(howmanyitems){ for(var i = 0; i < howmanyitems; i++){ var emptyitem = this.createitem(); var item = $(emptyitem); this.setdata(item,false); this.dom.$stage.append(item); } }; /** * createlazycontentstructure * @desc create lazycontent structure for large content and better mobile experience * @since 2.0.0 */ owl.prototype.createlazycontentstructure = function(refresh){ if(!this.state.lazycontent){return false;} // prevent recreate - to do if(refresh && this.dom.$stage.children().length === this.options.items*3){ return false; } // remove items from stage this.dom.$stage.empty(); // create custom structure this.createcustomstructure(3*this.options.items); }; /** * fillitem * @desc fill empty item container with provided content * @since 2.0.0 * @param [content] - string/$dom - passed owl-item * @param [i] - index in jquery object * return $ new object */ owl.prototype.fillitem = function(content,i){ var emptyitem = this.createitem(); var c = content[i] || content; // set item data var traversed = this.traverscontent(c); this.setdata(emptyitem,false,traversed); return $(emptyitem).append(c); }; /** * traverscontent * @since 2.0.0 * @param [c] - content * return object */ owl.prototype.traverscontent = function(c){ var $c = $(c), dotvalue, hashvalue; if(this.options.dotdata){ dotvalue = $c.find('[data-dot]').andself().data('dot'); } // update url hash if(this.options.urlhashlistener){ hashvalue = $c.find('[data-hash]').andself().data('hash'); } return { dot : dotvalue || false, hash : hashvalue || false }; }; /** * setdata * @desc set item jquery data * @since 2.0.0 * @param [item] - dom - passed owl-item * @param [cloneobj] - $dom - passed clone item */ owl.prototype.setdata = function(item,cloneobj,traversed){ var dot,hash; if(traversed){ dot = traversed.dot; hash = traversed.hash; } var itemdata = { index: false, indexabs: false, posleft: false, clone: false, active: false, loaded: false, lazyload: false, current: false, width: false, center: false, page: false, hasvideo: false, playvideo: false, dot: dot, hash: hash }; // copy itemdata to cloned item if(cloneobj){ itemdata = $.extend({}, itemdata, cloneobj.data('owl-item')); } $(item).data('owl-item', itemdata); }; /** * updatelocalcontent * @since 2.0.0 */ owl.prototype.updatelocalcontent = function(){ this.dom.$oitems = this.dom.$stage.find('.'+this.options.itemclass).filter(function(){ return $(this).data('owl-item').clone === false; }); this.num.oitems = this.dom.$oitems.length; //update index on original items for(var k = 0; k -1) { type = 'youtube'; } else if (id[3].indexof('vimeo') > -1) { type = 'vimeo'; } id = id[6]; } else { throw new error('missing video link.'); } item.data('owl-item').videotype = type; item.data('owl-item').videoid = id; item.data('owl-item').videowidth = width; item.data('owl-item').videoheight = height; info = { type: type, id: id }; // check dimensions var dimensions = width && height ? 'style="width:'+width+'px;height:'+height+'px;"' : ''; // wrap video content into owl-video-wrapper div videoel.wrap('
'); this.createvideotn(videoel,info); }; /** * createvideotn * @desc create video thumbnail * @since 2.0.0 */ owl.prototype.createvideotn = function(videoel,info){ var tnlink,icon,height; var customtn = videoel.find('img'); var srctype = 'src'; var lazyclass = ''; var that = this; if(this.options.lazyload){ srctype = 'data-src'; lazyclass = 'owl-lazy'; } // custom thumbnail if(customtn.length){ addthumbnail(customtn.attr(srctype)); customtn.remove(); return false; } function addthumbnail(tnpath){ icon = '
'; if(that.options.lazyload){ tnlink = '
'; } else{ tnlink = '
'; } videoel.after(tnlink); videoel.after(icon); } if(info.type === 'youtube'){ var path = "http://img.youtube.com/vi/"+ info.id +"/hqdefault.jpg"; addthumbnail(path); } else if(info.type === 'vimeo'){ $.ajax({ type:'get', url: 'http://vimeo.com/api/v2/video/' + info.id + '.json', jsonp: 'callback', datatype: 'jsonp', success: function(data){ var path = data[0].thumbnail_large; addthumbnail(path); if(that.options.loop){ that.updateitemstate(); } } }); } }; /** * stopvideo * @since 2.0.0 */ owl.prototype.stopvideo = function(){ this.firecallback('onvideostop'); var item = this.dom.$items.eq(this.state.videoplayindex); item.find('.owl-video-frame').remove(); item.removeclass('owl-video-playing'); this.state.videoplay = false; }; /** * playvideo * @since 2.0.0 */ owl.prototype.playvideo = function(ev){ this.firecallback('onvideoplay'); if(this.state.videoplay){ this.stopvideo(); } var videolink,videowrap, target = $(ev.target || ev.srcelement), item = target.closest('.'+this.options.itemclass); var videotype = item.data('owl-item').videotype, id = item.data('owl-item').videoid, width = item.data('owl-item').videowidth || math.floor(item.data('owl-item').width - this.options.margin), height = item.data('owl-item').videoheight || this.dom.$stage.height(); if(videotype === 'youtube'){ videolink = ""; } else if(videotype === 'vimeo'){ videolink = ''; } item.addclass('owl-video-playing'); this.state.videoplay = true; this.state.videoplayindex = item.data('owl-item').indexabs; videowrap = $('
' + videolink + '
'); target.after(videowrap); }; /** * loopclone * @desc make a clones for infinity loop * @since 2.0.0 */ owl.prototype.loopclone = function(){ if(!this.options.loop || this.state.lazycontent || this.num.oitems < this.options.items){return false;} var firstclone, lastclone, i, num = this.options.items, lastnum = this.num.oitems-1; // if neighbour margin then add one more duplicat if(this.options.stagepadding && this.options.items === 1){ num+=1; } this.num.citems = num * 2; for(i = 0; i < num; i++){ // clone item var first = this.dom.$oitems.eq(i).clone(true,true); var last = this.dom.$oitems.eq(lastnum-i).clone(true,true); firstclone = $(first[0]).addclass('cloned'); lastclone = $(last[0]).addclass('cloned'); // set clone data // somehow data has reference to same data id in cash this.setdata(firstclone[0],first); this.setdata(lastclone[0],last); firstclone.data('owl-item').clone = true; lastclone.data('owl-item').clone = true; this.dom.$stage.append(firstclone); this.dom.$stage.prepend(lastclone); firstclone = lastclone = null; } this.dom.$citems = this.dom.$stage.find('.'+this.options.itemclass).filter(function(){ return $(this).data('owl-item').clone === true; }); }; /** * reclone * @desc update cloned elements * @since 2.0.0 */ owl.prototype.reclone = function(){ // remove cloned items if(this.dom.$citems !== null){ // && (this.num.oitems !== 0 && this.num.oitems <= this.options.items)){ this.dom.$citems.remove(); this.dom.$citems = null; this.num.citems = 0; } if(!this.options.loop){ return; } // generete new elements this.loopclone(); }; /** * calculate * @desc update item index data * @since 2.0.0 */ owl.prototype.calculate = function(){ var i,j,k,dist,posleft=0,fullwidth=0; // element width minus neighbour this.width.el = this.dom.$el.width() - (this.options.stagepadding*2); //to check this.width.view = this.dom.$el.width(); // calculate width minus addition margins var elminusmargin = this.width.el - (this.options.margin * (this.options.items === 1 ? 0 : this.options.items -1)); // calculate element width and item width this.width.el = this.width.el + this.options.margin; this.width.item = ((elminusmargin / this.options.items) + this.options.margin).tofixed(3); this.dom.$items = this.dom.$stage.find('.owl-item'); this.num.items = this.dom.$items.length; //change to autowidths if(this.options.autowidth){ this.dom.$items.css('width',''); } // set grid array this.pos.items = []; this.num.merged = []; this.num.nav = []; // item distances if(this.options.rtl){ dist = this.options.center ? -((this.width.el)/2) : 0; } else { dist = this.options.center ? (this.width.el)/2 : 0; } this.width.mergestage = 0; // calculate items positions for(i = 0; i this.options.items){ mergenumber = this.options.items; } this.num.merged.push(parseint(mergenumber)); this.width.mergestage += this.width.item * this.num.merged[i]; } else { this.num.merged.push(1); } // array based on merged items used by dots and navigation if(this.options.loop){ if(i>=this.num.citems/2 && i this.width.stage){ if(this.options.rtl){ window.settimeout(function(){ this.dom.stage.style.width = this.width.stage + 'px'; }.bind(this),0); } else{ this.dom.stage.style.width = this.width.stage + 'px'; } for(var i=0; i',stagex + view))) || (this.op(outsideview,'<',stagex) && this.op(outsideview,'>',stagex + view)) ){ this.num.active++; if(this.options.freedrag && !foundcurrent){ foundcurrent = true; this.pos.current = item.data('owl-item').index; this.pos.currentabs = item.data('owl-item').indexabs; } item.data('owl-item').active = true; item.data('owl-item').current = true; item.addclass(this.options.activeclass); if(!this.options.lazyload){ item.data('owl-item').loaded = true; } if(this.options.loop && (this.options.lazyload || this.options.center)){ this.updatecloneditemsstate(item.data('owl-item').index); } } } }; /** * updatecloneditemsstate * @desc set current state on sibilings items for lazyload and center * @since 2.0.0 */ owl.prototype.updatecloneditemsstate = function(activeindex){ //find cloned center var center, $el,i; if(this.options.center){ center = this.dom.$items.eq(this.pos.currentabs).data('owl-item').index; } for(i = 0; i this.pos.currentabs ){ this.pos.lccurrent -= this.options.items - this.pos.currentabs; this.state.lcdirection = 'left'; } this.pos.lccurrent = jumpto !== 0 ? jumpto : this.pos.lccurrent; if(this.pos.lccurrent >= this.dom.$content.length){ this.pos.lccurrent = this.pos.lccurrent-this.dom.$content.length; } else if(this.pos.lccurrent < -this.dom.$content.length+1){ this.pos.lccurrent = this.pos.lccurrent+this.dom.$content.length; } if(this.options.startposition>0){ this.pos.lccurrent = this.options.startposition; this._options.startposition = this.options.startposition = 0; } this.pos.lccurrentabs = this.pos.lccurrent < 0 ? this.pos.lccurrent+this.dom.$content.length : this.pos.lccurrent; }; /** * updatelazycontent * @param [update] - boolean - update call by content manipulations * @since 2.0.0 */ owl.prototype.updatelazycontent = function(update){ if(this.pos.lccurrent === undefined){ this.pos.lccurrent = 0; this.pos.current = this.pos.currentabs = this.options.items; } if(!update){ this.updatelazyposition(); } var i,j,item,contentpos,content,freshitem,freshdata; if(this.state.lcdirection !== false){ for(i = 0; i= this.dom.$content.length){ contentpos = contentpos - this.dom.$content.length; } if(contentpos < -this.dom.$content.length){ contentpos = contentpos + this.dom.$content.length; } content = this.dom.$content.eq(contentpos); freshitem = this.dom.$items.eq(j); freshdata = freshitem.data('owl-item'); if(freshdata.active === false || this.pos.gotolazycontent !== 0 || update === true){ freshitem.empty(); freshitem.append(content.clone(true,true)); freshdata.active = true; freshdata.current = true; if(!this.options.lazyload){ freshdata.loaded = true; } else { freshdata.loaded = false; } } } this.pos.gotolazycontent = 0; this.pos.current = this.pos.currentabs = this.options.items; this.setspeed(0); this.animstage(this.pos.items[this.options.items]); }; /** * eventscall * @desc save internal event references and add event based functions like transitionend,responsive etc. * @since 2.0.0 */ owl.prototype.eventscall = function(){ // save events references this.e._ondragstart = function(e){this.ondragstart(e); }.bind(this); this.e._ondragmove = function(e){this.ondragmove(e); }.bind(this); this.e._ondragend = function(e){this.ondragend(e); }.bind(this); this.e._transitionend = function(e){this.transitionend(e); }.bind(this); this.e._resizer = function(){this.responsivetimer(); }.bind(this); this.e._responsivecall =function(){this.responsive(); }.bind(this); this.e._preventclick = function(e){this.preventclick(e); }.bind(this); this.e._gotohash = function(){this.gotohash(); }.bind(this); this.e._gotopage = function(e){this.gotopage(e); }.bind(this); this.e._ap = function(){this.autoplay(); }.bind(this); this.e._play = function(){this.play(); }.bind(this); this.e._pause = function(){this.pause(); }.bind(this); this.e._playvideo = function(e){this.playvideo(e); }.bind(this); this.e._navnext = function(e){ if($(e.target).hasclass('disabled')){return false;} e.preventdefault(); this.next(); }.bind(this); this.e._navprev = function(e){ if($(e.target).hasclass('disabled')){return false;} e.preventdefault(); this.prev(); }.bind(this); }; /** * responsivetimer * @desc check window resize event with 200ms delay / this.options.responsiverefreshrate * @since 2.0.0 */ owl.prototype.responsivetimer = function(){ if(this.windowwidth() === this.width.prevwindow){ return false; } window.clearinterval(this.e._autoplay); window.cleartimeout(this.resizetimer); this.resizetimer = window.settimeout(this.e._responsivecall, this.options.responsiverefreshrate); this.width.prevwindow = this.windowwidth(); }; /** * internalevents * @desc checks for touch/mouse drag options and add necessery event handlers. * @since 2.0.0 */ owl.prototype.internalevents = function(){ var istouch = istouchsupport(); var istouchie = istouchsupportie(); if(istouch && !istouchie){ this.dragtype = ['touchstart','touchmove','touchend','touchcancel']; } else if(istouch && istouchie){ this.dragtype = ['mspointerdown','mspointermove','mspointerup','mspointercancel']; } else { this.dragtype = ['mousedown','mousemove','mouseup']; } if( (istouch || istouchie) && this.options.touchdrag){ //touch cancel event this.on(document, this.dragtype[3], this.e._ondragend); } else { // firefox startdrag fix - addeventlistener doesnt work here :/ this.dom.$stage.on('dragstart', function() {return false;}); if(this.options.mousedrag){ //disable text select this.dom.stage.onselectstart = function(){return false;}; } else { // enable text select this.dom.$el.addclass('owl-text-select-on'); } } // video play button event delegation this.dom.$stage.on(this.dragtype[2], '.owl-video-play-icon', this.e._playvideo); if(this.options.urlhashlistener){ this.on(window, 'hashchange', this.e._gotohash, false); } if(this.options.autoplayhoverpause){ var that = this; this.dom.$stage.on('mouseover', this.e._pause ); this.dom.$stage.on('mouseleave', this.e._ap ); } // catch transitionend event if(this.transitionendvendor){ this.on(this.dom.stage, this.transitionendvendor, this.e._transitionend, false); } // responsive if(this.options.responsive !== false){ this.on(window, 'resize', this.e._resizer, false); } this.updateevents(); }; /** * updateevents * @since 2.0.0 */ owl.prototype.updateevents = function(){ if(this.options.touchdrag && (this.dragtype[0] === 'touchstart' || this.dragtype[0] === 'mspointerdown')){ this.on(this.dom.stage, this.dragtype[0], this.e._ondragstart,false); } else if(this.options.mousedrag && this.dragtype[0] === 'mousedown'){ this.on(this.dom.stage, this.dragtype[0], this.e._ondragstart,false); } else { this.off(this.dom.stage, this.dragtype[0], this.e._ondragstart); } }; /** * ondragstart * @desc touchstart/mousedown event * @since 2.0.0 */ owl.prototype.ondragstart = function(event){ var ev = event.originalevent || event || window.event; // prevent right click if (ev.which === 3) { return false; } if(this.dragtype[0] === 'mousedown'){ this.dom.$stage.addclass('owl-grab'); } this.firecallback('ontouchstart'); this.drag.starttime = new date().gettime(); this.setspeed(0); this.state.istouch = true; this.state.isscrolling = false; this.state.isswiping = false; this.drag.distance = 0; // if is 'touchstart' var istouchevent = ev.type === 'touchstart'; var pagex = istouchevent ? event.targettouches[0].pagex : (ev.pagex || ev.clientx); var pagey = istouchevent ? event.targettouches[0].pagey : (ev.pagey || ev.clienty); //get stage position left this.drag.offsetx = this.dom.$stage.position().left - this.options.stagepadding; this.drag.offsety = this.dom.$stage.position().top; if(this.options.rtl){ this.drag.offsetx = this.dom.$stage.position().left + this.width.stage - this.width.el + this.options.margin; } //catch position // ie to fix if(this.state.inmotion && this.support3d){ var animatedpos = this.gettransformproperty(); this.drag.offsetx = animatedpos; this.animstage(animatedpos); } else if(this.state.inmotion && !this.support3d ){ this.state.inmotion = false; return false; } this.drag.startx = pagex - this.drag.offsetx; this.drag.starty = pagey - this.drag.offsety; this.drag.start = pagex - this.drag.startx; this.drag.targetel = ev.target || ev.srcelement; this.drag.updatedx = this.drag.start; // to do/check //prevent links and images dragging; //this.drag.targetel.draggable = false; this.on(document, this.dragtype[1], this.e._ondragmove, false); this.on(document, this.dragtype[2], this.e._ondragend, false); }; /** * ondragmove * @desc touchmove/mousemove event * @since 2.0.0 */ owl.prototype.ondragmove = function(event){ if (!this.state.istouch){ return; } if (this.state.isscrolling){ return; } var neighbouritemwidth=0; var ev = event.originalevent || event || window.event; // if is 'touchstart' var istouchevent = ev.type == 'touchmove'; var pagex = istouchevent ? ev.targettouches[0].pagex : (ev.pagex || ev.clientx); var pagey = istouchevent ? ev.targettouches[0].pagey : (ev.pagey || ev.clienty); // drag direction this.drag.currentx = pagex - this.drag.startx; this.drag.currenty = pagey - this.drag.starty; this.drag.distance = this.drag.currentx - this.drag.offsetx; // check move direction if (this.drag.distance < 0) { this.state.direction = this.options.rtl ? 'right' : 'left'; } else if(this.drag.distance > 0){ this.state.direction = this.options.rtl ? 'left' : 'right'; } // loop if(this.options.loop){ if(this.op(this.drag.currentx, '>', this.pos.minvalue) && this.state.direction === 'right' ){ this.drag.currentx -= this.pos.loop; }else if(this.op(this.drag.currentx, '<', this.pos.maxvalue) && this.state.direction === 'left' ){ this.drag.currentx += this.pos.loop; } } else { // pull var minvalue = this.options.rtl ? this.pos.maxvalue : this.pos.minvalue; var maxvalue = this.options.rtl ? this.pos.minvalue : this.pos.maxvalue; var pull = this.options.pulldrag ? this.drag.distance / 5 : 0; this.drag.currentx = math.max(math.min(this.drag.currentx, minvalue + pull), maxvalue + pull); } // lock browser if swiping horizontal if ((this.drag.distance > 8 || this.drag.distance < -8)) { if (ev.preventdefault !== undefined) { ev.preventdefault(); } else { ev.returnvalue = false; } this.state.isswiping = true; } this.drag.updatedx = this.drag.currentx; // lock owl if scrolling if ((this.drag.currenty > 16 || this.drag.currenty < -16) && this.state.isswiping === false) { this.state.isscrolling = true; this.drag.updatedx = this.drag.start; } this.animstage(this.drag.updatedx); }; /** * ondragend * @desc touchend/mouseup event * @since 2.0.0 */ owl.prototype.ondragend = function(event){ if (!this.state.istouch){ return; } if(this.dragtype[0] === 'mousedown'){ this.dom.$stage.removeclass('owl-grab'); } this.firecallback('ontouchend'); //prevent links and images dragging; //this.drag.targetel.draggable = true; //remove drag event listeners this.state.istouch = false; this.state.isscrolling = false; this.state.isswiping = false; //to check if(this.drag.distance === 0 && this.state.inmotion !== true){ this.state.inmotion = false; return false; } // prevent clicks while scrolling this.drag.endtime = new date().gettime(); var comparetimes = this.drag.endtime - this.drag.starttime; var distanceabs = math.abs(this.drag.distance); //to test if(distanceabs > 3 || comparetimes > 300){ this.removeclick(this.drag.targetel); } var closest = this.closest(this.drag.updatedx); this.setspeed(this.options.dragendspeed, false, true); this.animstage(this.pos.items[closest]); //if pulldrag is off then fire transitionend event manually when stick to border if(!this.options.pulldrag && this.drag.updatedx === this.pos.items[closest]){ this.transitionend(); } this.drag.distance = 0; this.off(document, this.dragtype[1], this.e._ondragmove); this.off(document, this.dragtype[2], this.e._ondragend); }; /** * removeclick * @desc attach preventclick function to disable link while swipping * @since 2.0.0 * @param [target] - clicked dom element */ owl.prototype.removeclick = function(target){ this.drag.targetel = target; this.on(target,'click', this.e._preventclick, false); }; /** * preventclick * @desc add preventdefault for any link and then remove removeclick event hanlder * @since 2.0.0 */ owl.prototype.preventclick = function(ev){ if(ev.preventdefault) { ev.preventdefault(); }else { ev.returnvalue = false; } if(ev.stoppropagation){ ev.stoppropagation(); } this.off(this.drag.targetel,'click',this.e._preventclick,false); }; /** * gettransformproperty * @desc catch stage position while animate (only css3) * @since 2.0.0 */ owl.prototype.gettransformproperty = function(){ var transform = window.getcomputedstyle(this.dom.stage, null).getpropertyvalue(this.vendorname + 'transform'); //var transform = this.dom.$stage.css(this.vendorname + 'transform') transform = transform.replace(/matrix(3d)?\(|\)/g, '').split(','); var matrix3d = transform.length === 16; return matrix3d !== true ? transform[4] : transform[12]; }; /** * closest * @desc get closest item after touchend/mouseup * @since 2.0.0 * @param [x] - curent position in pixels * return position in pixels */ owl.prototype.closest = function(x){ var newx = 0, pull = 30; if(!this.options.freedrag){ // check closest item for(var i = 0; i< this.num.items; i++){ if(x > this.pos.items[i]-pull && x < this.pos.items[i]+pull){ newx = i; }else if(this.op(x,'<',this.pos.items[i]) && this.op(x,'>',this.pos.items[i+1 || this.pos.items[i] - this.width.el]) ){ newx = this.state.direction === 'left' ? i+1 : i; } } } //non loop boundries if(!this.options.loop){ if(this.op(x,'>',this.pos.minvalue)){ newx = x = this.pos.min; } else if(this.op(x,'<',this.pos.maxvalue)){ newx = x = this.pos.max; } } if(!this.options.freedrag){ // set positions this.pos.currentabs = newx; this.pos.current = this.dom.$items.eq(newx).data('owl-item').index; } else { this.updateitemstate(); return x; } return newx; }; /** * animstage * @desc animate stage position (both css3/css2) and perform onchange functions/events * @since 2.0.0 * @param [x] - curent position in pixels */ owl.prototype.animstage = function(pos){ // if speed is 0 the set inmotion to false if(this.speed.current !== 0 && this.pos.currentabs !== this.pos.min){ this.firecallback('ontransitionstart'); this.state.inmotion = true; } var posx = this.pos.stage = pos, style = this.dom.stage.style; if(this.support3d){ translate = 'translate3d(' + posx + 'px'+',0px, 0px)'; style[this.transformvendor] = translate; } else if(this.state.istouch){ style.left = posx+'px'; } else { this.dom.$stage.animate({left: posx},this.speed.css2speed, this.options.fallbackeasing, function(){ if(this.state.inmotion){ this.transitionend(); } }.bind(this)); } this.onchange(); }; /** * updateposition * @desc update current positions * @since 2.0.0 * @param [pos] - number - new position */ owl.prototype.updateposition = function(pos){ // if no items then stop if(this.num.oitems === 0){return false;} // to do //if(pos > this.num.items){pos = 0;} if(pos === undefined){return false;} //pos - new current position var nextpos = pos; this.pos.prev = this.pos.currentabs; if(this.state.revert){ this.pos.current = this.dom.$items.eq(nextpos).data('owl-item').index; this.pos.currentabs = nextpos; return; } if(!this.options.loop){ if(this.options.navrewind){ nextpos = nextpos > this.pos.max ? this.pos.min : (nextpos < 0 ? this.pos.max : nextpos); } else { nextpos = nextpos > this.pos.max ? this.pos.max : (nextpos <= 0 ? 0 : nextpos); } } else { nextpos = nextpos >= this.num.oitems ? this.num.oitems-1 : nextpos; } this.pos.current = this.dom.$oitems.eq(nextpos).data('owl-item').index; this.pos.currentabs = this.dom.$oitems.eq(nextpos).data('owl-item').indexabs; }; /** * setspeed * @since 2.0.0 * @param [speed] - number * @param [pos] - number - next position - use this param to calculate smartspeed * @param [drag] - boolean - if drag is true then smart speed is disabled * return speed */ owl.prototype.setspeed = function(speed,pos,drag) { var s = speed, nextpos = pos; if((s === false && s !== 0 && drag !== true) || s === undefined){ //double check this // var nextpx = this.pos.items[nextpos]; // var currpx = this.pos.stage // var diff = math.abs(nextpx-currpx); // var s = diff/1 // if(s>1000){ // s = 1000; // } var diff = math.abs(nextpos - this.pos.prev); diff = diff === 0 ? 1 : diff; if(diff>6){diff = 6;} s = diff * this.options.smartspeed; } if(s === false && drag === true){ s = this.options.smartspeed; } if(s === 0){s=0;} if(this.support3d){ var style = this.dom.stage.style; style.webkittransitionduration = style.mstransitionduration = style.mstransitionduration = style.moztransitionduration = style.otransitionduration = style.transitionduration = (s / 1000) + 's'; } else{ this.speed.css2speed = s; } this.speed.current = s; return s; }; /** * jumpto * @since 2.0.0 * @param [pos] - number - next position - use this param to calculate smartspeed * @param [update] - boolean - if drag is true then smart speed is disabled */ owl.prototype.jumpto = function(pos,update){ if(this.state.lazycontent){ this.pos.gotolazycontent = pos; } this.updateposition(pos); this.setspeed(0); this.animstage(this.pos.items[this.pos.currentabs]); if(update !== true){ this.updateitemstate(); } }; /** * goto * @since 2.0.0 * @param [pos] - number * @param [speed] - speed in ms * @param [speed] - speed in ms */ owl.prototype.goto = function(pos,speed){ if(this.state.lazycontent && this.state.inmotion){ return false; } this.updateposition(pos); if(this.state.animate){speed = 0;} this.setspeed(speed,this.pos.currentabs); if(this.state.animate){this.animate();} this.animstage(this.pos.items[this.pos.currentabs]); }; /** * next * @since 2.0.0 */ owl.prototype.next = function(optionalspeed){ var s = optionalspeed || this.options.navspeed; if(this.options.loop && !this.state.lazycontent){ this.gotoloop(this.options.slideby, s); }else{ this.goto(this.pos.current + this.options.slideby, s); } }; /** * prev * @since 2.0.0 */ owl.prototype.prev = function(optionalspeed){ var s = optionalspeed || this.options.navspeed; if(this.options.loop && !this.state.lazycontent){ this.gotoloop(-this.options.slideby, s); }else{ this.goto(this.pos.current-this.options.slideby, s); } }; /** * gotoloop * @desc go to given position if loop is enabled - used only internal * @since 2.0.0 * @param [distance] - number -how far to go * @param [speed] - number - speed in ms */ owl.prototype.gotoloop = function(distance,speed){ var revert = this.pos.currentabs, prevposition = this.pos.currentabs, newposition = this.pos.currentabs + distance, direction = prevposition - newposition < 0 ? true : false; this.state.revert = true; if(newposition < 1 && direction === false){ this.state.bypass = true; revert = this.num.items - (this.options.items-prevposition) - this.options.items; this.jumpto(revert,true); } else if(newposition >= this.num.items - this.options.items && direction === true ){ this.state.bypass = true; revert = prevposition - this.num.oitems; this.jumpto(revert,true); } window.cleartimeout(this.e._gotoloop); this.e._gotoloop = window.settimeout(function(){ this.state.bypass = false; this.goto(revert + distance, speed); this.state.revert = false; }.bind(this), 30); }; /** * initposition * @since 2.0.0 */ owl.prototype.initposition = function(init){ if( !this.dom.$oitems || !init || this.state.lazycontent ){return false;} var pos = this.options.startposition; if(this.options.startposition === 'urlhash'){ pos = this.options.startposition = this.hashposition(); } else if(typeof this.options.startposition !== number && !this.options.center){ this.options.startposition = 0; } this.dom.ostage.scrollleft = 0; this.jumpto(pos,true); }; /** * gotohash * @since 2.0.0 */ owl.prototype.gotohash = function(){ var pos = this.hashposition(); if(pos === false){ pos = 0; } this.dom.ostage.scrollleft = 0; this.goto(pos,this.options.navspeed); }; /** * hashposition * @desc find hash in url then look into items to find contained id * @since 2.0.0 * return hashpos - number of item */ owl.prototype.hashposition = function(){ var hash = window.location.hash.substring(1), hashpos; if(hash === ""){return false;} for(var i=0;i= this.pos.max){ window.clearinterval(this.e._autoplay); this.goto(0); } else { this.next(this.options.autoplayspeed); } this.state.autoplay=true; }; /** * stop * @since 2.0.0 */ owl.prototype.stop = function(){ this._options.autoplay = this.options.autoplay = false; this.state.autoplay = false; window.clearinterval(this.e._autoplay); }; owl.prototype.pause = function(){ window.clearinterval(this.e._autoplay); }; /** * transitionend * @desc event used by css3 animation end and $.animate callback like transitionend,responsive etc. * @since 2.0.0 */ owl.prototype.transitionend = function(event){ // if css2 animation then event object is undefined if(event !== undefined){ event.stoppropagation(); // catch only owl-stage transitionend event var eventtarget = event.target || event.srcelement || event.originaltarget; if(eventtarget !== this.dom.stage){ return false; } } this.state.inmotion = false; this.updateitemstate(); this.autoplay(); this.firecallback('ontransitionend'); }; /** * iselwidthchanged * @desc check if element width has changed * @since 2.0.0 */ owl.prototype.iselwidthchanged = function(){ var newelwidth = this.dom.$el.width() - this.options.stagepadding,//to check prevelwidth = this.width.el + this.options.margin; return newelwidth !== prevelwidth; }; /** * windowwidth * @desc get window/responsivebaseelement width * @since 2.0.0 */ owl.prototype.windowwidth = function() { if(this.options.responsivebaseelement !== window){ this.width.window = $(this.options.responsivebaseelement).width(); } else if (window.innerwidth){ this.width.window = window.innerwidth; } else if (document.documentelement && document.documentelement.clientwidth){ this.width.window = document.documentelement.clientwidth; } return this.width.window; }; /** * controls * @desc calls controls container, navigation and dots creator * @since 2.0.0 */ owl.prototype.controls = function(){ var cc = document.createelement('div'); cc.classname = this.options.controlsclass; this.dom.$el.append(cc); this.dom.$cc = $(cc); }; /** * updatecontrols * @since 2.0.0 */ owl.prototype.updatecontrols = function(){ if(this.dom.$cc === null && (this.options.nav || this.options.dots)){ this.controls(); } if(this.dom.$nav === null && this.options.nav){ this.createnavigation(this.dom.$cc[0]); } if(this.dom.$page === null && this.options.dots){ this.createdots(this.dom.$cc[0]); } if(this.dom.$nav !== null){ if(this.options.nav){ this.dom.$nav.show(); this.updatenavigation(); } else { this.dom.$nav.hide(); } } if(this.dom.$page !== null){ if(this.options.dots){ this.dom.$page.show(); this.updatedots(); } else { this.dom.$page.hide(); } } }; /** * createnavigation * @since 2.0.0 * @param [cc] - dom element - controls container */ owl.prototype.createnavigation = function(cc){ // create nav container var nav = document.createelement('div'); nav.classname = this.options.navcontainerclass; cc.appendchild(nav); // create left and right buttons var navprev = document.createelement('div'), navnext = document.createelement('div'); navprev.classname = this.options.navclass[0]; navnext.classname = this.options.navclass[1]; nav.appendchild(navprev); nav.appendchild(navnext); this.dom.$nav = $(nav); this.dom.$navprev = $(navprev).html(this.options.navtext[0]); this.dom.$navnext = $(navnext).html(this.options.navtext[1]); // add events to do //this.on(navprev, this.dragtype[2], this.e._navprev, false); //this.on(navnext, this.dragtype[2], this.e._navnext, false); //ff fix? this.dom.$nav.on(this.dragtype[2], '.'+this.options.navclass[0], this.e._navprev); this.dom.$nav.on(this.dragtype[2], '.'+this.options.navclass[1], this.e._navnext); }; /** * createnavigation * @since 2.0.0 * @param [cc] - dom element - controls container */ owl.prototype.createdots = function(cc){ // create dots container var page = document.createelement('div'); page.classname = this.options.dotsclass; cc.appendchild(page); // save reference this.dom.$page = $(page); // add events //this.on(page, this.dragtype[2], this.e._gotopage, false); // ff fix? to test! var that = this; this.dom.$page.on(this.dragtype[2], '.'+this.options.dotclass, gotopage); function gotopage(e){ e.preventdefault(); var page = $(this).data('page'); that.goto(page,that.options.dotsspeed); } // build dots this.rebuilddots(); }; /** * gotopage * @desc event used by dots * @since 2.0.0 */ // owl.prototype.gotopage = function(e){ // console.log(e.taget); // var page = $(e.currenttarget).data('page') // this.goto(page,this.options.dotsspeed); // return false; // }; /** * rebuilddots * @since 2.0.0 */ owl.prototype.rebuilddots = function(){ if(this.dom.$page === null){return false;} var each, dot, span, counter = 0, last = 0, i, page=0, roundpages = 0; each = this.options.dotseach || this.options.items; // display full dots if center if(this.options.center || this.options.dotdata){ each = 1; } // clear dots this.dom.$page.html(''); for(i = 0; i < this.num.nav.length; i++){ if(counter >= each || counter === 0){ dot = document.createelement('div'); dot.classname = this.options.dotclass; span = document.createelement('span'); dot.appendchild(span); var $dot = $(dot); if(this.options.dotdata){ $dot.html(this.dom.$oitems.eq(i).data('owl-item').dot); } $dot.data('page',page); $dot.data('gotopage',roundpages); this.dom.$page.append(dot); counter = 0; roundpages++; } this.dom.$oitems.eq(i).data('owl-item').page = roundpages-1; //add merged items counter += this.num.nav[i]; page++; } // find rest of dots if(!this.options.loop && !this.options.center){ for(var j = this.num.nav.length-1; j >= 0; j--){ last += this.num.nav[j]; this.dom.$oitems.eq(j).data('owl-item').page = roundpages-1; if(last >= each){ break; } } } this.num.allpages = roundpages-1; }; /** * updatedots * @since 2.0.0 */ owl.prototype.updatedots = function(){ var dots = this.dom.$page.children(); var itemindex = this.dom.$oitems.eq(this.pos.current).data('owl-item').page; for(var i = 0; i < dots.length; i++){ var dotpage = dots.eq(i).data('gotopage'); if(dotpage===itemindex){ this.pos.currentpage = i; dots.eq(i).addclass('active'); }else{ dots.eq(i).removeclass('active'); } } }; /** * updatenavigation * @since 2.0.0 */ owl.prototype.updatenavigation = function(){ var isnav = this.options.nav; this.dom.$navnext.toggleclass('disabled',!isnav); this.dom.$navprev.toggleclass('disabled',!isnav); if(!this.options.loop && isnav && !this.options.navrewind){ if(this.pos.current <= 0){ this.dom.$navprev.addclass('disabled'); } if(this.pos.current >= this.pos.max){ this.dom.$navnext.addclass('disabled'); } } }; owl.prototype.insertcontent = function(content){ this.dom.$stage.empty(); this.fetchcontent(content); this.refresh(); }; /** * additem - add an item * @since 2.0.0 * @param [content] - dom element / string '
content
' * @param [pos] - number - position */ owl.prototype.additem = function(content,pos){ pos = pos || 0; if(this.state.lazycontent){ this.dom.$content = this.dom.$content.add($(content)); this.updateitemstate(true); } else { // wrap content var item = this.fillitem(content); // if carousel is empty then append item if(this.dom.$oitems.length === 0){ this.dom.$stage.append(item); } else { // append item var it = this.dom.$oitems.eq(pos); if(pos !== -1){it.before(item);} else {it.after(item);} } // update and calculate carousel this.refresh(); } }; /** * removeitem - remove an item * @since 2.0.0 * @param [pos] - number - position */ owl.prototype.removeitem = function(pos){ if(this.state.lazycontent){ this.dom.$content.splice(pos,1); this.updateitemstate(true); } else { this.dom.$oitems.eq(pos).remove(); this.refresh(); } }; /** * addcustomevents * @desc add custom events by jquery .on method * @since 2.0.0 */ owl.prototype.addcustomevents = function(){ this.e.next = function(e,s){this.next(s); }.bind(this); this.e.prev = function(e,s){this.prev(s); }.bind(this); this.e.goto = function(e,p,s){this.goto(p,s); }.bind(this); this.e.jumpto = function(e,p){this.jumpto(p); }.bind(this); this.e.additem = function(e,c,p){this.additem(c,p); }.bind(this); this.e.removeitem = function(e,p){this.removeitem(p);}.bind(this); this.e.refresh = function(e){this.refresh(); }.bind(this); this.e.destroy = function(e){this.destroy(); }.bind(this); this.e.autoheight = function(e){this.autoheight(true);}.bind(this); this.e.stop = function(){this.stop(); }.bind(this); this.e.play = function(e,t,s){this.play(t,s); }.bind(this); this.e.insertcontent = function(e,d){this.insertcontent(d); }.bind(this); this.dom.$el.on('next.owl',this.e.next); this.dom.$el.on('prev.owl',this.e.prev); this.dom.$el.on('goto.owl',this.e.goto); this.dom.$el.on('jumpto.owl',this.e.jumpto); this.dom.$el.on('additem.owl',this.e.additem); this.dom.$el.on('removeitem.owl',this.e.removeitem); this.dom.$el.on('destroy.owl',this.e.destroy); this.dom.$el.on('refresh.owl',this.e.refresh); this.dom.$el.on('autoheight.owl',this.e.autoheight); this.dom.$el.on('play.owl',this.e.play); this.dom.$el.on('stop.owl',this.e.stop); this.dom.$el.on('stopvideo.owl',this.e.stop); this.dom.$el.on('insertcontent.owl',this.e.insertcontent); }; /** * on * @desc on method for adding internal events * @since 2.0.0 */ owl.prototype.on = function (element, event, listener, capture) { if (element.addeventlistener) { element.addeventlistener(event, listener, capture); } else if (element.attachevent) { element.attachevent('on' + event, listener); } }; /** * off * @desc off method for removing internal events * @since 2.0.0 */ owl.prototype.off = function (element, event, listener, capture) { if (element.removeeventlistener) { element.removeeventlistener(event, listener, capture); } else if (element.detachevent) { element.detachevent('on' + event, listener); } }; /** * firecallback * @since 2.0.0 * @param event - string - event name * @param data - object - additional options - to do */ owl.prototype.firecallback = function(event, data){ if(!this.options.callbacks){return;} if(this.dom.el.dispatchevent){ // dispatch event var evt = document.createevent('customevent'); //evt.initevent(event, false, true ); evt.initcustomevent(event, true, true, data); return this.dom.el.dispatchevent(evt); } else if (!this.dom.el.dispatchevent){ // there is no clean solution for custom events name in <=ie8 // but if you know better way, please let me know :) return this.dom.$el.trigger(event); } }; /** * watchvisibility * @desc check if el is visible - handy if owl is inside hidden content (tabs etc.) * @since 2.0.0 */ owl.prototype.watchvisibility = function(){ // test on zepto if(!iselvisible(this.dom.el)) { this.dom.$el.addclass('owl-hidden'); window.clearinterval(this.e._checkvisibile); this.e._checkvisibile = window.setinterval(checkvisible.bind(this),500); } function iselvisible(el) { return el.offsetwidth > 0 && el.offsetheight > 0; } function checkvisible(){ if (iselvisible(this.dom.el)) { this.dom.$el.removeclass('owl-hidden'); this.refresh(); window.clearinterval(this.e._checkvisibile); } } }; /** * onchange * @since 2.0.0 */ owl.prototype.onchange = function(){ if(!this.state.istouch && !this.state.bypass && !this.state.responsive ){ if (this.options.nav || this.options.dots) { this.updatecontrols(); } this.autoheight(); this.firecallback('onchangestate'); } if(!this.state.istouch && !this.state.bypass){ // set status to do this.storeinfo(); // stopvideo if(this.state.videoplay){ this.stopvideo(); } } }; /** * storeinfo * store basic information about current states * @since 2.0.0 */ owl.prototype.storeinfo = function(){ var currentposition = this.state.lazycontent ? this.pos.lccurrentabs || 0 : this.pos.current; var allitems = this.state.lazycontent ? this.dom.$content.length-1 : this.num.oitems; this.info = { items: this.options.items, allitems: allitems, currentposition:currentposition, currentpage: this.pos.currentpage, allpages: this.num.allpages, autoplay: this.state.autoplay, windowwidth: this.width.window, elwidth: this.width.el, breakpoint: this.num.breakpoint }; if (typeof this.options.info === 'function') { this.options.info.apply(this,[this.info,this.dom.el]); } }; /** * autoheight * @since 2.0.0 */ owl.prototype.autoheight = function(callback){ if(this.options.autoheight !== true && callback !== true){ return false; } if(!this.dom.$ostage.hasclass(this.options.autoheightclass)){ this.dom.$ostage.addclass(this.options.autoheightclass); } var loaded = this.dom.$items.eq(this.pos.currentabs); var stage = this.dom.$ostage; var iterations = 0; var isloaded = window.setinterval(function() { iterations += 1; if(loaded.data('owl-item').loaded){ stage.height(loaded.height() + 'px'); clearinterval(isloaded); } else if(iterations === 500){ clearinterval(isloaded); } }, 100); }; /** * preloadautowidthimages * @desc still to test * @since 2.0.0 */ owl.prototype.preloadautowidthimages = function(imgs){ var loaded = 0; var that = this; imgs.each(function(i,el){ var $el = $(el); var img = new image(); img.onload = function(){ loaded++; $el.attr('src',img.src); $el.css('opacity',1); if(loaded >= imgs.length){ that.state.imagesloaded = true; that.init(); } } img.src = $el.attr('src') || $el.attr('data-src') || $el.attr('data-src-retina');; }) }; /** * lazyload * @desc lazyload images * @since 2.0.0 */ owl.prototype.lazyload = function(){ var attr = isretina() ? 'data-src-retina' : 'data-src'; var src, img,i; for(i = 0; i < this.num.items; i++){ var $item = this.dom.$items.eq(i); if( $item.data('owl-item').current === true && $item.data('owl-item').loaded === false){ img = $item.find('.owl-lazy'); src = img.attr(attr); src = src || img.attr('data-src'); if(src){ img.css('opacity','0'); this.preload(img,$item); } } } }; /** * preload * @since 2.0.0 */ owl.prototype.preload = function(images,$item){ var that = this; // fix this later images.each(function(i,el){ var $el = $(el); var img = new image(); img.onload = function(){ $item.data('owl-item').loaded = true; if($el.is('img')){ $el.attr('src',img.src); }else{ $el.css('background-image','url(' + img.src + ')'); } $el.css('opacity',1); that.firecallback('onlazyloaded'); }; img.src = $el.attr('data-src') || $el.attr('data-src-retina'); }); }; /** * animate * @since 2.0.0 */ owl.prototype.animate = function(){ var previtem = this.dom.$items.eq(this.pos.prev), prevpos = math.abs(previtem.data('owl-item').width) * this.pos.prev, currentitem = this.dom.$items.eq(this.pos.currentabs), currentpos = math.abs(currentitem.data('owl-item').width) * this.pos.currentabs; if(this.pos.currentabs === this.pos.prev){ return false; } var pos = currentpos - prevpos; var tin = this.options.animatein; var tout = this.options.animateout; var that = this; removestyles = function(){ $(this).css({ "left" : "" }) .removeclass('animated owl-animated-out owl-animated-in') .removeclass(tin) .removeclass(tout); that.transitionend(); }; if(tout){ previtem .css({ "left" : pos + "px" }) .addclass('animated owl-animated-out '+tout) .one('webkitanimationend mozanimationend msanimationend oanimationend animationend', removestyles); } if(tin){ currentitem .addclass('animated owl-animated-in '+tin) .one('webkitanimationend mozanimationend msanimationend oanimationend animationend', removestyles); } }; /** * destroy * @desc remove owl structure and events :( * @since 2.0.0 */ owl.prototype.destroy = function(){ window.clearinterval(this.e._autoplay); if(this.dom.$el.hasclass(this.options.themeclass)){ this.dom.$el.removeclass(this.options.themeclass); } if(this.options.responsive !== false){ this.off(window, 'resize', this.e._resizer); } if(this.transitionendvendor){ this.off(this.dom.stage, this.transitionendvendor, this.e._transitionend); } if(this.options.mousedrag || this.options.touchdrag){ this.off(this.dom.stage, this.dragtype[0], this.e._ondragstart); if(this.options.mousedrag){ this.off(document, this.dragtype[3], this.e._ondragstart); } if(this.options.mousedrag){ this.dom.$stage.off('dragstart', function() {return false;}); this.dom.stage.onselectstart = function(){}; } } if(this.options.urlhashlistener){ this.off(window, 'hashchange', this.e._gotohash); } this.dom.$el.off('next.owl',this.e.next); this.dom.$el.off('prev.owl',this.e.prev); this.dom.$el.off('goto.owl',this.e.goto); this.dom.$el.off('jumpto.owl',this.e.jumpto); this.dom.$el.off('additem.owl',this.e.additem); this.dom.$el.off('removeitem.owl',this.e.removeitem); this.dom.$el.off('refresh.owl',this.e.refresh); this.dom.$el.off('autoheight.owl',this.e.autoheight); this.dom.$el.off('play.owl',this.e.play); this.dom.$el.off('stop.owl',this.e.stop); this.dom.$el.off('stopvideo.owl',this.e.stop); this.dom.$stage.off('click',this.e._playvideo); if(this.dom.$cc !== null){ this.dom.$cc.remove(); } if(this.dom.$citems !== null){ this.dom.$citems.remove(); } this.e = null; this.dom.$el.data('owlcarousel',null); delete this.dom.el.owlcarousel; this.dom.$stage.unwrap(); this.dom.$items.unwrap(); this.dom.$items.contents().unwrap(); this.dom = null; }; /** * opertators * @desc used to calculate rtl * @param [a] - number - left side * @param [o] - string - operator * @param [b] - number - right side * @since 2.0.0 */ owl.prototype.op = function(a,o,b){ var rtl = this.options.rtl; switch(o) { case '<': return rtl ? a > b : a < b; case '>': return rtl ? a < b : a > b; case '>=': return rtl ? a <= b : a >= b; case '<=': return rtl ? a >= b : a <= b; default: break; } }; /** * opertators * @desc used to calculate rtl * @since 2.0.0 */ owl.prototype.browsersupport = function(){ this.support3d = isperspective(); if(this.support3d){ this.transformvendor = istransform(); // take transitionend event name by detecting transition var endvendors = ['transitionend','webkittransitionend','transitionend','otransitionend']; this.transitionendvendor = endvendors[istransition()]; // take vendor name from transform name this.vendorname = this.transformvendor.replace(/transform/i,''); this.vendorname = this.vendorname !== '' ? '-'+this.vendorname.tolowercase()+'-' : ''; } this.state.orientation = window.orientation; }; // pivate methods // css detection; function isstylesupported(array){ var p,s,fake = document.createelement('div'),list = array; for(p in list){ s = list[p]; if(typeof fake.style[s] !== 'undefined'){ fake = null; return [s,p]; } } return [false]; } function istransition(){ return isstylesupported(['transition','webkittransition','moztransition','otransition'])[1]; } function istransform() { return isstylesupported(['transform','webkittransform','moztransform','otransform','mstransform'])[0]; } function isperspective(){ return isstylesupported(['perspective','webkitperspective','mozperspective','operspective','msperspective'])[0]; } function istouchsupport(){ return 'ontouchstart' in window || !!(navigator.msmaxtouchpoints); } function istouchsupportie(){ return window.navigator.mspointerenabled; } function isretina(){ return window.devicepixelratio > 1; } $.fn.owlcarousel = function ( options ) { return this.each(function () { if (!$(this).data('owlcarousel')) { $(this).data( 'owlcarousel', new owl( this, options )); } }); }; })( window.zepto || window.jquery, window, document ); //https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/function/bind //the bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. if (!function.prototype.bind) { function.prototype.bind = function (othis) { if (typeof this !== 'function') { // closest thing possible to the ecmascript 5 internal iscallable function throw new typeerror('function.prototype.bind - what is trying to be bound is not callable'); } var aargs = array.prototype.slice.call(arguments, 1), ftobind = this, fnop = function () {}, fbound = function () { return ftobind.apply(this instanceof fnop && othis ? this : othis, aargs.concat(array.prototype.slice.call(arguments))); }; fnop.prototype = this.prototype; fbound.prototype = new fnop(); return fbound; }; }