owl carousel v2.3.4 copyright 2013-2018 david deutsch licensed under see license in httpsgithub.comowlcarousel2owlcarousel2blobmasterlicense owl carousel @version 2.3.4 @author bartosz wojciechowski @author david deutsch @license the mit license (mit) @todo lazy load icon @todo prevent animationend bubling @todo itemsscaleup @todo test zepto @todo stagepadding calculate wrong active classes ;(function($, window, document, undefined) { creates a carousel. @class the owl carousel. @public @param {htmlelementjquery} element - the element to create the carousel for. @param {object} [options] - the options function owl(element, options) { current settings for the carousel. @public this.settings = null; current options set by the caller including defaults. @public this.options = $.extend({}, owl.defaults, options); plugin element. @public this.$element = $(element); proxied event handlers. @protected this._handlers = {}; references to the running plugins of this carousel. @protected this._plugins = {}; currently suppressed events to prevent them from being retriggered. @protected this._supress = {}; absolute current position. @protected this._current = null; animation speed in milliseconds. @protected this._speed = null; coordinates of all items in pixel. @todo the name of this member is missleading. @protected this._coordinates = []; current breakpoint. @todo real media queries would be nice. @protected this._breakpoint = null; current width of the plugin element. this._width = null; all real items. @protected this._items = []; all cloned items. @protected this._clones = []; merge values of all items. @todo maybe this could be part of a plugin. @protected this._mergers = []; widths of all items. this._widths = []; invalidated parts within the update process. @protected this._invalidated = {}; ordered list of workers for the update process. @protected this._pipe = []; current state information for the drag operation. @todo #261 @protected this._drag = { time null, target null, pointer null, stage { start null, current null }, direction null }; current state information and their tags. @type {object} @protected this._states = { current {}, tags { 'initializing' [ 'busy' ], 'animating' [ 'busy' ], 'dragging' [ 'interacting' ] } }; $.each([ 'onresize', 'onthrottledresize' ], $.proxy(function(i, handler) { this._handlers[handler] = $.proxy(this[handler], this); }, this)); $.each(owl.plugins, $.proxy(function(key, plugin) { this._plugins[key.charat(0).tolowercase() + key.slice(1)] = new plugin(this); }, this)); $.each(owl.workers, $.proxy(function(priority, worker) { this._pipe.push({ 'filter' worker.filter, 'run' $.proxy(worker.run, this) }); }, this)); this.setup(); this.initialize(); } default options for the carousel. @public owl.defaults = { items 3, loop false, center false, rewind false, checkvisibility true, mousedrag true, touchdrag true, pulldrag true, freedrag false, margin 0, stagepadding 0, merge false, mergefit true, autowidth false, startposition 0, rtl false, smartspeed 250, fluidspeed false, dragendspeed false, responsive {}, responsiverefreshrate 200, responsivebaseelement window, fallbackeasing 'swing', slidetransition '', info false, nesteditemselector false, itemelement 'div', stageelement 'div', refreshclass 'owl-refresh', loadedclass 'owl-loaded', loadingclass 'owl-loading', rtlclass 'owl-rtl', responsiveclass 'owl-responsive', dragclass 'owl-drag', itemclass 'owl-item', stageclass 'owl-stage', stageouterclass 'owl-stage-outer', grabclass 'owl-grab' }; enumeration for width. @public @readonly @enum {string} owl.width = { default 'default', inner 'inner', outer 'outer' }; enumeration for types. @public @readonly @enum {string} owl.type = { event 'event', state 'state' }; contains all registered plugins. @public owl.plugins = {}; list of workers involved in the update process. owl.workers = [ { filter [ 'width', 'settings' ], run function() { this._width = this.$element.width(); } }, { filter [ 'width', 'items', 'settings' ], run function(cache) { cache.current = this._items && this._items[this.relative(this._current)]; } }, { filter [ 'items', 'settings' ], run function() { this.$stage.children('.cloned').remove(); } }, { filter [ 'width', 'items', 'settings' ], run function(cache) { var margin = this.settings.margin '', grid = !this.settings.autowidth, rtl = this.settings.rtl, css = { 'width' 'auto', 'margin-left' rtl margin '', 'margin-right' rtl '' margin }; !grid && this.$stage.children().css(css); cache.css = css; } }, { filter [ 'width', 'items', 'settings' ], run function(cache) { var width = (this.width() this.settings.items).tofixed(3) - this.settings.margin, merge = null, iterator = this._items.length, grid = !this.settings.autowidth, widths = []; cache.items = { merge false, width width }; while (iterator--) { merge = this._mergers[iterator]; merge = this.settings.mergefit && math.min(merge, this.settings.items) merge; cache.items.merge = merge 1 cache.items.merge; widths[iterator] = !grid this._items[iterator].width() width merge; } this._widths = widths; } }, { filter [ 'items', 'settings' ], run function() { var clones = [], items = this._items, settings = this.settings, todo should be computed from number of min width items in stage view = math.max(settings.items 2, 4), size = math.ceil(items.length 2) 2, repeat = settings.loop && items.length settings.rewind view math.max(view, size) 0, append = '', prepend = ''; repeat = 2; while (repeat 0) { switch to only using appended clones clones.push(this.normalize(clones.length 2, true)); append = append + items[clones[clones.length - 1]][0].outerhtml; clones.push(this.normalize(items.length - 1 - (clones.length - 1) 2, true)); prepend = items[clones[clones.length - 1]][0].outerhtml + prepend; repeat -= 1; } this._clones = clones; $(append).addclass('cloned').appendto(this.$stage); $(prepend).addclass('cloned').prependto(this.$stage); } }, { filter [ 'width', 'items', 'settings' ], run function() { var rtl = this.settings.rtl 1 -1, size = this._clones.length + this._items.length, iterator = -1, previous = 0, current = 0, coordinates = []; while (++iterator size) { previous = coordinates[iterator - 1] 0; current = this._widths[this.relative(iterator)] + this.settings.margin; coordinates.push(previous + current rtl); } this._coordinates = coordinates; } }, { filter [ 'width', 'items', 'settings' ], run function() { var padding = this.settings.stagepadding, coordinates = this._coordinates, css = { 'width' math.ceil(math.abs(coordinates[coordinates.length - 1])) + padding 2, 'padding-left' padding '', 'padding-right' padding '' }; this.$stage.css(css); } }, { filter [ 'width', 'items', 'settings' ], run function(cache) { var iterator = this._coordinates.length, grid = !this.settings.autowidth, items = this.$stage.children(); if (grid && cache.items.merge) { while (iterator--) { cache.css.width = this._widths[this.relative(iterator)]; items.eq(iterator).css(cache.css); } } else if (grid) { cache.css.width = cache.items.width; items.css(cache.css); } } }, { filter [ 'items' ], run function() { this._coordinates.length 1 && this.$stage.removeattr('style'); } }, { filter [ 'width', 'items', 'settings' ], run function(cache) { cache.current = cache.current this.$stage.children().index(cache.current) 0; cache.current = math.max(this.minimum(), math.min(this.maximum(), cache.current)); this.reset(cache.current); } }, { filter [ 'position' ], run function() { this.animate(this.coordinates(this._current)); } }, { filter [ 'width', 'position', 'items', 'settings' ], run function() { var rtl = this.settings.rtl 1 -1, padding = this.settings.stagepadding 2, begin = this.coordinates(this.current()) + padding, end = begin + this.width() rtl, inner, outer, matches = [], i, n; for (i = 0, n = this._coordinates.length; i n; i++) { inner = this._coordinates[i - 1] 0; outer = math.abs(this._coordinates[i]) + padding rtl; if ((this.op(inner, '=', begin) && (this.op(inner, '', end))) (this.op(outer, '', begin) && this.op(outer, '', end))) { matches.push(i); } } this.$stage.children('.active').removeclass('active'); this.$stage.children('eq(' + matches.join('), eq(') + ')').addclass('active'); this.$stage.children('.center').removeclass('center'); if (this.settings.center) { this.$stage.children().eq(this.current()).addclass('center'); } } } ]; create the stage dom element owl.prototype.initializestage = function() { this.$stage = this.$element.find('.' + this.settings.stageclass); if the stage is already in the dom, grab it and skip stage initialization if (this.$stage.length) { return; } this.$element.addclass(this.options.loadingclass); create stage this.$stage = $('' + this.settings.stageelement + '', { class this.settings.stageclass }).wrap( $( 'div', { class this.settings.stageouterclass })); append stage this.$element.append(this.$stage.parent()); }; create item dom elements owl.prototype.initializeitems = function() { var $items = this.$element.find('.owl-item'); if the items are already in the dom, grab them and skip item initialization if ($items.length) { this._items = $items.get().map(function(item) { return $(item); }); this._mergers = this._items.map(function() { return 1; }); this.refresh(); return; } append content this.replace(this.$element.children().not(this.$stage.parent())); check visibility if (this.isvisible()) { update view this.refresh(); } else { invalidate width this.invalidate('width'); } this.$element .removeclass(this.options.loadingclass) .addclass(this.options.loadedclass); }; initializes the carousel. @protected owl.prototype.initialize = function() { this.enter('initializing'); this.trigger('initialize'); this.$element.toggleclass(this.settings.rtlclass, this.settings.rtl); if (this.settings.autowidth && !this.is('pre-loading')) { var imgs, nestedselector, width; imgs = this.$element.find('img'); nestedselector = this.settings.nesteditemselector '.' + this.settings.nesteditemselector undefined; width = this.$element.children(nestedselector).width(); if (imgs.length && width = 0) { this.preloadautowidthimages(imgs); } } this.initializestage(); this.initializeitems(); register event handlers this.registereventhandlers(); this.leave('initializing'); this.trigger('initialized'); }; @returns {boolean} visibility of $element if you know the carousel will always be visible you can set `checkvisibility` to `false` to prevent the expensive browser layout forced reflow the $element.is('visible') does owl.prototype.isvisible = function() { return this.settings.checkvisibility this.$element.is('visible') true; }; setups the current settings. @todo remove responsive classes. why should adaptive designs be brought into ie8 @todo support for media queries by using `matchmedia` would be nice. @public owl.prototype.setup = function() { var viewport = this.viewport(), overwrites = this.options.responsive, match = -1, settings = null; if (!overwrites) { settings = $.extend({}, this.options); } else { $.each(overwrites, function(breakpoint) { if (breakpoint = viewport && breakpoint match) { match = number(breakpoint); } }); settings = $.extend({}, this.options, overwrites[match]); if (typeof settings.stagepadding === 'function') { settings.stagepadding = settings.stagepadding(); } delete settings.responsive; responsive class if (settings.responsiveclass) { this.$element.attr('class', this.$element.attr('class').replace(new regexp('(' + this.options.responsiveclass + '-)s+s', 'g'), '$1' + match) ); } } this.trigger('change', { property { name 'settings', value settings } }); this._breakpoint = match; this.settings = settings; this.invalidate('settings'); this.trigger('changed', { property { name 'settings', value this.settings } }); }; updates option logic if necessery. @protected owl.prototype.optionslogic = function() { if (this.settings.autowidth) { this.settings.stagepadding = false; this.settings.merge = false; } }; prepares an item before add. @todo rename event parameter `content` to `item`. @protected @returns {jqueryhtmlelement} - the item container. owl.prototype.prepare = function(item) { var event = this.trigger('prepare', { content item }); if (!event.data) { event.data = $('' + this.settings.itemelement + '') .addclass(this.options.itemclass).append(item) } this.trigger('prepared', { content event.data }); return event.data; }; updates the view. @public owl.prototype.update = function() { var i = 0, n = this._pipe.length, filter = $.proxy(function(p) { return this[p] }, this._invalidated), cache = {}; while (i n) { if (this._invalidated.all $.grep(this._pipe[i].filter, filter).length 0) { this._pipe[i].run(cache); } i++; } this._invalidated = {}; !this.is('valid') && this.enter('valid'); }; gets the width of the view. @public @param {owl.width} [dimension=owl.width.default] - the dimension to return. @returns {number} - the width of the view in pixel. owl.prototype.width = function(dimension) { dimension = dimension owl.width.default; switch (dimension) { case owl.width.inner case owl.width.outer return this._width; default return this._width - this.settings.stagepadding 2 + this.settings.margin; } }; refreshes the carousel primarily for adaptive purposes. @public owl.prototype.refresh = function() { this.enter('refreshing'); this.trigger('refresh'); this.setup(); this.optionslogic(); this.$element.addclass(this.options.refreshclass); this.update(); this.$element.removeclass(this.options.refreshclass); this.leave('refreshing'); this.trigger('refreshed'); }; checks window `resize` event. @protected owl.prototype.onthrottledresize = function() { window.cleartimeout(this.resizetimer); this.resizetimer = window.settimeout(this._handlers.onresize, this.settings.responsiverefreshrate); }; checks window `resize` event. @protected owl.prototype.onresize = function() { if (!this._items.length) { return false; } if (this._width === this.$element.width()) { return false; } if (!this.isvisible()) { return false; } this.enter('resizing'); if (this.trigger('resize').isdefaultprevented()) { this.leave('resizing'); return false; } this.invalidate('width'); this.refresh(); this.leave('resizing'); this.trigger('resized'); }; registers event handlers. @todo check `mspointerenabled` @todo #261 @protected owl.prototype.registereventhandlers = function() { if ($.support.transition) { this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.ontransitionend, this)); } if (this.settings.responsive !== false) { this.on(window, 'resize', this._handlers.onthrottledresize); } if (this.settings.mousedrag) { this.$element.addclass(this.options.dragclass); this.$stage.on('mousedown.owl.core', $.proxy(this.ondragstart, this)); this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); } if (this.settings.touchdrag){ this.$stage.on('touchstart.owl.core', $.proxy(this.ondragstart, this)); this.$stage.on('touchcancel.owl.core', $.proxy(this.ondragend, this)); } }; handles `touchstart` and `mousedown` events. @todo horizontal swipe threshold as option @todo #261 @protected @param {event} event - the event arguments. owl.prototype.ondragstart = function(event) { var stage = null; if (event.which === 3) { return; } if ($.support.transform) { stage = this.$stage.css('transform').replace(.() g, '').split(','); stage = { x stage[stage.length === 16 12 4], y stage[stage.length === 16 13 5] }; } else { stage = this.$stage.position(); stage = { x this.settings.rtl stage.left + this.$stage.width() - this.width() + this.settings.margin stage.left, y stage.top }; } if (this.is('animating')) { $.support.transform this.animate(stage.x) this.$stage.stop() this.invalidate('position'); } this.$element.toggleclass(this.options.grabclass, event.type === 'mousedown'); this.speed(0); this._drag.time = new date().gettime(); this._drag.target = $(event.target); this._drag.stage.start = stage; this._drag.stage.current = stage; this._drag.pointer = this.pointer(event); $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.ondragend, this)); $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { var delta = this.difference(this._drag.pointer, this.pointer(event)); $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.ondragmove, this)); if (math.abs(delta.x) math.abs(delta.y) && this.is('valid')) { return; } event.preventdefault(); this.enter('dragging'); this.trigger('drag'); }, this)); }; handles the `touchmove` and `mousemove` events. @todo #261 @protected @param {event} event - the event arguments. owl.prototype.ondragmove = function(event) { var minimum = null, maximum = null, pull = null, delta = this.difference(this._drag.pointer, this.pointer(event)), stage = this.difference(this._drag.stage.start, delta); if (!this.is('dragging')) { return; } event.preventdefault(); if (this.settings.loop) { minimum = this.coordinates(this.minimum()); maximum = this.coordinates(this.maximum() + 1) - minimum; stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; } else { minimum = this.settings.rtl this.coordinates(this.maximum()) this.coordinates(this.minimum()); maximum = this.settings.rtl this.coordinates(this.minimum()) this.coordinates(this.maximum()); pull = this.settings.pulldrag -1 delta.x 5 0; stage.x = math.max(math.min(stage.x, minimum + pull), maximum + pull); } this._drag.stage.current = stage; this.animate(stage.x); }; handles the `touchend` and `mouseup` events. @todo #261 @todo threshold for click event @protected @param {event} event - the event arguments. owl.prototype.ondragend = function(event) { var delta = this.difference(this._drag.pointer, this.pointer(event)), stage = this._drag.stage.current, direction = delta.x 0 ^ this.settings.rtl 'left' 'right'; $(document).off('.owl.core'); this.$element.removeclass(this.options.grabclass); if (delta.x !== 0 && this.is('dragging') !this.is('valid')) { this.speed(this.settings.dragendspeed this.settings.smartspeed); this.current(this.closest(stage.x, delta.x !== 0 direction this._drag.direction)); this.invalidate('position'); this.update(); this._drag.direction = direction; if (math.abs(delta.x) 3 new date().gettime() - this._drag.time 300) { this._drag.target.one('click.owl.core', function() { return false; }); } } if (!this.is('dragging')) { return; } this.leave('dragging'); this.trigger('dragged'); }; gets absolute position of the closest item for a coordinate. @todo setting `freedrag` makes `closest` not reusable. see #165. @protected @param {number} coordinate - the coordinate in pixel. @param {string} direction - the direction to check for the closest item. ether `left` or `right`. @return {number} - the absolute position of the closest item. owl.prototype.closest = function(coordinate, direction) { var position = -1, pull = 30, width = this.width(), coordinates = this.coordinates(); if (!this.settings.freedrag) { check closest item $.each(coordinates, $.proxy(function(index, value) { on a left pull, check on current index if (direction === 'left' && coordinate value - pull && coordinate value + pull) { position = index; on a right pull, check on previous index to do so, subtract width from value and set position = index + 1 } else if (direction === 'right' && coordinate value - width - pull && coordinate value - width + pull) { position = index + 1; } else if (this.op(coordinate, '', value) && this.op(coordinate, '', coordinates[index + 1] !== undefined coordinates[index + 1] value - width)) { position = direction === 'left' index + 1 index; } return position === -1; }, this)); } if (!this.settings.loop) { non loop boundries if (this.op(coordinate, '', coordinates[this.minimum()])) { position = coordinate = this.minimum(); } else if (this.op(coordinate, '', coordinates[this.maximum()])) { position = coordinate = this.maximum(); } } return position; }; animates the stage. @todo #270 @public @param {number} coordinate - the coordinate in pixels. owl.prototype.animate = function(coordinate) { var animate = this.speed() 0; this.is('animating') && this.ontransitionend(); if (animate) { this.enter('animating'); this.trigger('translate'); } if ($.support.transform3d && $.support.transition) { this.$stage.css({ transform 'translate3d(' + coordinate + 'px,0px,0px)', transition (this.speed() 1000) + 's' + ( this.settings.slidetransition ' ' + this.settings.slidetransition '' ) }); } else if (animate) { this.$stage.animate({ left coordinate + 'px' }, this.speed(), this.settings.fallbackeasing, $.proxy(this.ontransitionend, this)); } else { this.$stage.css({ left coordinate + 'px' }); } }; checks whether the carousel is in a specific state or not. @param {string} state - the state to check. @returns {boolean} - the flag which indicates if the carousel is busy. owl.prototype.is = function(state) { return this._states.current[state] && this._states.current[state] 0; }; sets the absolute position of the current item. @public @param {number} [position] - the new absolute position or nothing to leave it unchanged. @returns {number} - the absolute position of the current item. owl.prototype.current = function(position) { if (position === undefined) { return this._current; } if (this._items.length === 0) { return undefined; } position = this.normalize(position); if (this._current !== position) { var event = this.trigger('change', { property { name 'position', value position } }); if (event.data !== undefined) { position = this.normalize(event.data); } this._current = position; this.invalidate('position'); this.trigger('changed', { property { name 'position', value this._current } }); } return this._current; }; invalidates the given part of the update routine. @param {string} [part] - the part to invalidate. @returns {array.string} - the invalidated parts. owl.prototype.invalidate = function(part) { if ($.type(part) === 'string') { this._invalidated[part] = true; this.is('valid') && this.leave('valid'); } return $.map(this._invalidated, function(v, i) { return i }); }; resets the absolute position of the current item. @public @param {number} position - the absolute position of the new item. owl.prototype.reset = function(position) { position = this.normalize(position); if (position === undefined) { return; } this._speed = 0; this._current = position; this.suppress([ 'translate', 'translated' ]); this.animate(this.coordinates(position)); this.release([ 'translate', 'translated' ]); }; normalizes an absolute or a relative position of an item. @public @param {number} position - the absolute or relative position to normalize. @param {boolean} [relative=false] - whether the given position is relative or not. @returns {number} - the normalized position. owl.prototype.normalize = function(position, relative) { var n = this._items.length, m = relative 0 this._clones.length; if (!this.isnumeric(position) n 1) { position = undefined; } else if (position 0 position = n + m) { position = ((position - m 2) % n + n) % n + m 2; } return position; }; converts an absolute position of an item into a relative one. @public @param {number} position - the absolute position to convert. @returns {number} - the converted position. owl.prototype.relative = function(position) { position -= this._clones.length 2; return this.normalize(position, true); }; gets the maximum position for the current item. @public @param {boolean} [relative=false] - whether to return an absolute position or a relative position. @returns {number} owl.prototype.maximum = function(relative) { var settings = this.settings, maximum = this._coordinates.length, iterator, reciprocalitemswidth, elementwidth; if (settings.loop) { maximum = this._clones.length 2 + this._items.length - 1; } else if (settings.autowidth settings.merge) { iterator = this._items.length; if (iterator) { reciprocalitemswidth = this._items[--iterator].width(); elementwidth = this.$element.width(); while (iterator--) { reciprocalitemswidth += this._items[iterator].width() + this.settings.margin; if (reciprocalitemswidth elementwidth) { break; } } } maximum = iterator + 1; } else if (settings.center) { maximum = this._items.length - 1; } else { maximum = this._items.length - settings.items; } if (relative) { maximum -= this._clones.length 2; } return math.max(maximum, 0); }; gets the minimum position for the current item. @public @param {boolean} [relative=false] - whether to return an absolute position or a relative position. @returns {number} owl.prototype.minimum = function(relative) { return relative 0 this._clones.length 2; }; gets an item at the specified relative position. @public @param {number} [position] - the relative position of the item. @return {jqueryarray.jquery} - the item at the given position or all items if no position was given. owl.prototype.items = function(position) { if (position === undefined) { return this._items.slice(); } position = this.normalize(position, true); return this._items[position]; }; gets an item at the specified relative position. @public @param {number} [position] - the relative position of the item. @return {jqueryarray.jquery} - the item at the given position or all items if no position was given. owl.prototype.mergers = function(position) { if (position === undefined) { return this._mergers.slice(); } position = this.normalize(position, true); return this._mergers[position]; }; gets the absolute positions of clones for an item. @public @param {number} [position] - the relative position of the item. @returns {array.number} - the absolute positions of clones for the item or all if no position was given. owl.prototype.clones = function(position) { var odd = this._clones.length 2, even = odd + this._items.length, map = function(index) { return index % 2 === 0 even + index 2 odd - (index + 1) 2 }; if (position === undefined) { return $.map(this._clones, function(v, i) { return map(i) }); } return $.map(this._clones, function(v, i) { return v === position map(i) null }); }; sets the current animation speed. @public @param {number} [speed] - the animation speed in milliseconds or nothing to leave it unchanged. @returns {number} - the current animation speed in milliseconds. owl.prototype.speed = function(speed) { if (speed !== undefined) { this._speed = speed; } return this._speed; }; gets the coordinate of an item. @todo the name of this method is missleanding. @public @param {number} position - the absolute position of the item within `minimum()` and `maximum()`. @returns {numberarray.number} - the coordinate of the item in pixel or all coordinates. owl.prototype.coordinates = function(position) { var multiplier = 1, newposition = position - 1, coordinate; if (position === undefined) { return $.map(this._coordinates, $.proxy(function(coordinate, index) { return this.coordinates(index); }, this)); } if (this.settings.center) { if (this.settings.rtl) { multiplier = -1; newposition = position + 1; } coordinate = this._coordinates[position]; coordinate += (this.width() - coordinate + (this._coordinates[newposition] 0)) 2 multiplier; } else { coordinate = this._coordinates[newposition] 0; } coordinate = math.ceil(coordinate); return coordinate; }; calculates the speed for a translation. @protected @param {number} from - the absolute position of the start item. @param {number} to - the absolute position of the target item. @param {number} [factor=undefined] - the time factor in milliseconds. @returns {number} - the time in milliseconds for the translation. owl.prototype.duration = function(from, to, factor) { if (factor === 0) { return 0; } return math.min(math.max(math.abs(to - from), 1), 6) math.abs((factor this.settings.smartspeed)); }; slides to the specified item. @public @param {number} position - the position of the item. @param {number} [speed] - the time in milliseconds for the transition. owl.prototype.to = function(position, speed) { var current = this.current(), revert = null, distance = position - this.relative(current), direction = (distance 0) - (distance 0), items = this._items.length, minimum = this.minimum(), maximum = this.maximum(); if (this.settings.loop) { if (!this.settings.rewind && math.abs(distance) items 2) { distance += direction -1 items; } position = current + distance; revert = ((position - minimum) % items + items) % items + minimum; if (revert !== position && revert - distance = maximum && revert - distance 0) { current = revert - distance; position = revert; this.reset(current); } } else if (this.settings.rewind) { maximum += 1; position = (position % maximum + maximum) % maximum; } else { position = math.max(minimum, math.min(maximum, position)); } this.speed(this.duration(current, position, speed)); this.current(position); if (this.isvisible()) { this.update(); } }; slides to the next item. @public @param {number} [speed] - the time in milliseconds for the transition. owl.prototype.next = function(speed) { speed = speed false; this.to(this.relative(this.current()) + 1, speed); }; slides to the previous item. @public @param {number} [speed] - the time in milliseconds for the transition. owl.prototype.prev = function(speed) { speed = speed false; this.to(this.relative(this.current()) - 1, speed); }; handles the end of an animation. @protected @param {event} event - the event arguments. owl.prototype.ontransitionend = function(event) { if css2 animation then event object is undefined if (event !== undefined) { event.stoppropagation(); catch only owl-stage transitionend event if ((event.target event.srcelement event.originaltarget) !== this.$stage.get(0)) { return false; } } this.leave('animating'); this.trigger('translated'); }; gets viewport width. @protected @return {number} - the width in pixel. owl.prototype.viewport = function() { var width; if (this.options.responsivebaseelement !== window) { width = $(this.options.responsivebaseelement).width(); } else if (window.innerwidth) { width = window.innerwidth; } else if (document.documentelement && document.documentelement.clientwidth) { width = document.documentelement.clientwidth; } else { console.warn('can not detect viewport width.'); } return width; }; replaces the current content. @public @param {htmlelementjquerystring} content - the new content. owl.prototype.replace = function(content) { this.$stage.empty(); this._items = []; if (content) { content = (content instanceof jquery) content $(content); } if (this.settings.nesteditemselector) { content = content.find('.' + this.settings.nesteditemselector); } content.filter(function() { return this.nodetype === 1; }).each($.proxy(function(index, item) { item = this.prepare(item); this.$stage.append(item); this._items.push(item); this._mergers.push(item.find('[data-merge]').addback('[data-merge]').attr('data-merge') 1 1); }, this)); this.reset(this.isnumeric(this.settings.startposition) this.settings.startposition 0); this.invalidate('items'); }; adds an item. @todo use `item` instead of `content` for the event arguments. @public @param {htmlelementjquerystring} content - the item content to add. @param {number} [position] - the relative position at which to insert the item otherwise the item will be added to the end. owl.prototype.add = function(content, position) { var current = this.relative(this._current); position = position === undefined this._items.length this.normalize(position, true); content = content instanceof jquery content $(content); this.trigger('add', { content content, position position }); content = this.prepare(content); if (this._items.length === 0 position === this._items.length) { this._items.length === 0 && this.$stage.append(content); this._items.length !== 0 && this._items[position - 1].after(content); this._items.push(content); this._mergers.push(content.find('[data-merge]').addback('[data-merge]').attr('data-merge') 1 1); } else { this._items[position].before(content); this._items.splice(position, 0, content); this._mergers.splice(position, 0, content.find('[data-merge]').addback('[data-merge]').attr('data-merge') 1 1); } this._items[current] && this.reset(this._items[current].index()); this.invalidate('items'); this.trigger('added', { content content, position position }); }; removes an item by its position. @todo use `item` instead of `content` for the event arguments. @public @param {number} position - the relative position of the item to remove. owl.prototype.remove = function(position) { position = this.normalize(position, true); if (position === undefined) { return; } this.trigger('remove', { content this._items[position], position position }); this._items[position].remove(); this._items.splice(position, 1); this._mergers.splice(position, 1); this.invalidate('items'); this.trigger('removed', { content null, position position }); }; preloads images with auto width. @todo replace by a more generic approach @protected owl.prototype.preloadautowidthimages = function(images) { images.each($.proxy(function(i, element) { this.enter('pre-loading'); element = $(element); $(new image()).one('load', $.proxy(function(e) { element.attr('src', e.target.src); element.css('opacity', 1); this.leave('pre-loading'); !this.is('pre-loading') && !this.is('initializing') && this.refresh(); }, this)).attr('src', element.attr('src') element.attr('data-src') element.attr('data-src-retina')); }, this)); }; destroys the carousel. @public owl.prototype.destroy = function() { this.$element.off('.owl.core'); this.$stage.off('.owl.core'); $(document).off('.owl.core'); if (this.settings.responsive !== false) { window.cleartimeout(this.resizetimer); this.off(window, 'resize', this._handlers.onthrottledresize); } for (var i in this._plugins) { this._plugins[i].destroy(); } this.$stage.children('.cloned').remove(); this.$stage.unwrap(); this.$stage.children().contents().unwrap(); this.$stage.children().unwrap(); this.$stage.remove(); this.$element .removeclass(this.options.refreshclass) .removeclass(this.options.loadingclass) .removeclass(this.options.loadedclass) .removeclass(this.options.rtlclass) .removeclass(this.options.dragclass) .removeclass(this.options.grabclass) .attr('class', this.$element.attr('class').replace(new regexp(this.options.responsiveclass + '-s+s', 'g'), '')) .removedata('owl.carousel'); }; operators to calculate right-to-left and left-to-right. @protected @param {number} [a] - the left side operand. @param {string} [o] - the operator. @param {number} [b] - the right side operand. owl.prototype.op = function(a, o, b) { var rtl = this.settings.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; } }; attaches to an internal event. @protected @param {htmlelement} element - the event source. @param {string} event - the event name. @param {function} listener - the event handler to attach. @param {boolean} capture - wether the event should be handled at the capturing phase or not. 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); } }; detaches from an internal event. @protected @param {htmlelement} element - the event source. @param {string} event - the event name. @param {function} listener - the attached event handler to detach. @param {boolean} capture - wether the attached event handler was registered as a capturing listener or not. 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); } }; triggers a public event. @todo remove `status`, `relatedtarget` should be used instead. @protected @param {string} name - the event name. @param {} [data=null] - the event data. @param {string} [namespace=carousel] - the event namespace. @param {string} [state] - the state which is associated with the event. @param {boolean} [enter=false] - indicates if the call enters the specified state or not. @returns {event} - the event arguments. owl.prototype.trigger = function(name, data, namespace, state, enter) { var status = { item { count this._items.length, index this.current() } }, handler = $.camelcase( $.grep([ 'on', name, namespace ], function(v) { return v }) .join('-').tolowercase() ), event = $.event( [ name, 'owl', namespace 'carousel' ].join('.').tolowercase(), $.extend({ relatedtarget this }, status, data) ); if (!this._supress[name]) { $.each(this._plugins, function(name, plugin) { if (plugin.ontrigger) { plugin.ontrigger(event); } }); this.register({ type owl.type.event, name name }); this.$element.trigger(event); if (this.settings && typeof this.settings[handler] === 'function') { this.settings[handler].call(this, event); } } return event; }; enters a state. @param name - the state name. owl.prototype.enter = function(name) { $.each([ name ].concat(this._states.tags[name] []), $.proxy(function(i, name) { if (this._states.current[name] === undefined) { this._states.current[name] = 0; } this._states.current[name]++; }, this)); }; leaves a state. @param name - the state name. owl.prototype.leave = function(name) { $.each([ name ].concat(this._states.tags[name] []), $.proxy(function(i, name) { this._states.current[name]--; }, this)); }; registers an event or state. @public @param {object} object - the event or state to register. owl.prototype.register = function(object) { if (object.type === owl.type.event) { if (!$.event.special[object.name]) { $.event.special[object.name] = {}; } if (!$.event.special[object.name].owl) { var _default = $.event.special[object.name]._default; $.event.special[object.name]._default = function(e) { if (_default && _default.apply && (!e.namespace e.namespace.indexof('owl') === -1)) { return _default.apply(this, arguments); } return e.namespace && e.namespace.indexof('owl') -1; }; $.event.special[object.name].owl = true; } } else if (object.type === owl.type.state) { if (!this._states.tags[object.name]) { this._states.tags[object.name] = object.tags; } else { this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); } this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { return $.inarray(tag, this._states.tags[object.name]) === i; }, this)); } }; suppresses events. @protected @param {array.string} events - the events to suppress. owl.prototype.suppress = function(events) { $.each(events, $.proxy(function(index, event) { this._supress[event] = true; }, this)); }; releases suppressed events. @protected @param {array.string} events - the events to release. owl.prototype.release = function(events) { $.each(events, $.proxy(function(index, event) { delete this._supress[event]; }, this)); }; gets unified pointer coordinates from event. @todo #261 @protected @param {event} - the `mousedown` or `touchstart` event. @returns {object} - contains `x` and `y` coordinates of current pointer position. owl.prototype.pointer = function(event) { var result = { x null, y null }; event = event.originalevent event window.event; event = event.touches && event.touches.length event.touches[0] event.changedtouches && event.changedtouches.length event.changedtouches[0] event; if (event.pagex) { result.x = event.pagex; result.y = event.pagey; } else { result.x = event.clientx; result.y = event.clienty; } return result; }; determines if the input is a number or something that can be coerced to a number @protected @param {numberstringobjectarraybooleanregexpfunctionsymbol} - the input to be tested @returns {boolean} - an indication if the input is a number or can be coerced to a number owl.prototype.isnumeric = function(number) { return !isnan(parsefloat(number)); }; gets the difference of two vectors. @todo #261 @protected @param {object} - the first vector. @param {object} - the second vector. @returns {object} - the difference. owl.prototype.difference = function(first, second) { return { x first.x - second.x, y first.y - second.y }; }; the jquery plugin for the owl carousel @todo navigation plugin `next` and `prev` @public $.fn.owlcarousel = function(option) { var args = array.prototype.slice.call(arguments, 1); return this.each(function() { var $this = $(this), data = $this.data('owl.carousel'); if (!data) { data = new owl(this, typeof option == 'object' && option); $this.data('owl.carousel', data); $.each([ 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' ], function(i, event) { data.register({ type owl.type.event, name event }); data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { if (e.namespace && e.relatedtarget !== this) { this.suppress([ event ]); data[event].apply(this, [].slice.call(arguments, 1)); this.release([ event ]); } }, data)); }); } if (typeof option == 'string' && option.charat(0) !== '_') { data[option].apply(data, args); } }); }; the constructor for the jquery plugin @public $.fn.owlcarousel.constructor = owl; })(window.zepto window.jquery, window, document); autorefresh plugin @version 2.3.4 @author artus kolanowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { creates the auto refresh plugin. @class the auto refresh plugin @param {owl} carousel - the owl carousel var autorefresh = function(carousel) { reference to the core. @protected @type {owl} this._core = carousel; refresh interval. @protected @type {number} this._interval = null; whether the element is currently visible or not. @protected @type {boolean} this._visible = null; all event handlers. @protected @type {object} this._handlers = { 'initialized.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.autorefresh) { this.watch(); } }, this) }; set default options this._core.options = $.extend({}, autorefresh.defaults, this._core.options); register event handlers this._core.$element.on(this._handlers); }; default options. @public autorefresh.defaults = { autorefresh true, autorefreshinterval 500 }; watches the element. autorefresh.prototype.watch = function() { if (this._interval) { return; } this._visible = this._core.isvisible(); this._interval = window.setinterval($.proxy(this.refresh, this), this._core.settings.autorefreshinterval); }; refreshes the element. autorefresh.prototype.refresh = function() { if (this._core.isvisible() === this._visible) { return; } this._visible = !this._visible; this._core.$element.toggleclass('owl-hidden', !this._visible); this._visible && (this._core.invalidate('width') && this._core.refresh()); }; destroys the plugin. autorefresh.prototype.destroy = function() { var handler, property; window.clearinterval(this._interval); for (handler in this._handlers) { this._core.$element.off(handler, this._handlers[handler]); } for (property in object.getownpropertynames(this)) { typeof this[property] != 'function' && (this[property] = null); } }; $.fn.owlcarousel.constructor.plugins.autorefresh = autorefresh; })(window.zepto window.jquery, window, document); lazy plugin @version 2.3.4 @author bartosz wojciechowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { creates the lazy plugin. @class the lazy plugin @param {owl} carousel - the owl carousel var lazy = function(carousel) { reference to the core. @protected @type {owl} this._core = carousel; already loaded items. @protected @type {array.jquery} this._loaded = []; event handlers. @protected @type {object} this._handlers = { 'initialized.owl.carousel change.owl.carousel resized.owl.carousel' $.proxy(function(e) { if (!e.namespace) { return; } if (!this._core.settings !this._core.settings.lazyload) { return; } if ((e.property && e.property.name == 'position') e.type == 'initialized') { var settings = this._core.settings, n = (settings.center && math.ceil(settings.items 2) settings.items), i = ((settings.center && n -1) 0), position = (e.property && e.property.value !== undefined e.property.value this._core.current()) + i, clones = this._core.clones().length, load = $.proxy(function(i, v) { this.load(v) }, this); todo need documentation for this new option if (settings.lazyloadeager 0) { n += settings.lazyloadeager; if the carousel is looping also preload images that are to the left if (settings.loop) { position -= settings.lazyloadeager; n++; } } while (i++ n) { this.load(clones 2 + this._core.relative(position)); clones && $.each(this._core.clones(this._core.relative(position)), load); position++; } } }, this) }; set the default options this._core.options = $.extend({}, lazy.defaults, this._core.options); register event handler this._core.$element.on(this._handlers); }; default options. @public lazy.defaults = { lazyload false, lazyloadeager 0 }; loads all resources of an item at the specified position. @param {number} position - the absolute position of the item. @protected lazy.prototype.load = function(position) { var $item = this._core.$stage.children().eq(position), $elements = $item && $item.find('.owl-lazy'); if (!$elements $.inarray($item.get(0), this._loaded) -1) { return; } $elements.each($.proxy(function(index, element) { var $element = $(element), image, url = (window.devicepixelratio 1 && $element.attr('data-src-retina')) $element.attr('data-src') $element.attr('data-srcset'); this._core.trigger('load', { element $element, url url }, 'lazy'); if ($element.is('img')) { $element.one('load.owl.lazy', $.proxy(function() { $element.css('opacity', 1); this._core.trigger('loaded', { element $element, url url }, 'lazy'); }, this)).attr('src', url); } else if ($element.is('source')) { $element.one('load.owl.lazy', $.proxy(function() { this._core.trigger('loaded', { element $element, url url }, 'lazy'); }, this)).attr('srcset', url); } else { image = new image(); image.onload = $.proxy(function() { $element.css({ 'background-image' 'url(' + url + ')', 'opacity' '1' }); this._core.trigger('loaded', { element $element, url url }, 'lazy'); }, this); image.src = url; } }, this)); this._loaded.push($item.get(0)); }; destroys the plugin. @public lazy.prototype.destroy = function() { var handler, property; for (handler in this.handlers) { this._core.$element.off(handler, this.handlers[handler]); } for (property in object.getownpropertynames(this)) { typeof this[property] != 'function' && (this[property] = null); } }; $.fn.owlcarousel.constructor.plugins.lazy = lazy; })(window.zepto window.jquery, window, document); autoheight plugin @version 2.3.4 @author bartosz wojciechowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { creates the auto height plugin. @class the auto height plugin @param {owl} carousel - the owl carousel var autoheight = function(carousel) { reference to the core. @protected @type {owl} this._core = carousel; this._previousheight = null; all event handlers. @protected @type {object} this._handlers = { 'initialized.owl.carousel refreshed.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.autoheight) { this.update(); } }, this), 'changed.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.autoheight && e.property.name === 'position'){ this.update(); } }, this), 'loaded.owl.lazy' $.proxy(function(e) { if (e.namespace && this._core.settings.autoheight && e.element.closest('.' + this._core.settings.itemclass).index() === this._core.current()) { this.update(); } }, this) }; set default options this._core.options = $.extend({}, autoheight.defaults, this._core.options); register event handlers this._core.$element.on(this._handlers); this._intervalid = null; var refthis = this; these changes have been taken from a pr by gavrochelegnou proposed in #1575 and have been made compatible with the latest jquery version $(window).on('load', function() { if (refthis._core.settings.autoheight) { refthis.update(); } }); autoresize the height of the carousel when window is resized when carousel has images, the height is dependent on the width and should also change on resize $(window).resize(function() { if (refthis._core.settings.autoheight) { if (refthis._intervalid != null) { cleartimeout(refthis._intervalid); } refthis._intervalid = settimeout(function() { refthis.update(); }, 250); } }); }; default options. @public autoheight.defaults = { autoheight false, autoheightclass 'owl-height' }; updates the view. autoheight.prototype.update = function() { var start = this._core._current, end = start + this._core.settings.items, lazyloadenabled = this._core.settings.lazyload, visible = this._core.$stage.children().toarray().slice(start, end), heights = [], maxheight = 0; $.each(visible, function(index, item) { heights.push($(item).height()); }); maxheight = math.max.apply(null, heights); if (maxheight = 1 && lazyloadenabled && this._previousheight) { maxheight = this._previousheight; } this._previousheight = maxheight; this._core.$stage.parent() .height(maxheight) .addclass(this._core.settings.autoheightclass); }; autoheight.prototype.destroy = function() { var handler, property; for (handler in this._handlers) { this._core.$element.off(handler, this._handlers[handler]); } for (property in object.getownpropertynames(this)) { typeof this[property] !== 'function' && (this[property] = null); } }; $.fn.owlcarousel.constructor.plugins.autoheight = autoheight; })(window.zepto window.jquery, window, document); video plugin @version 2.3.4 @author bartosz wojciechowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { creates the video plugin. @class the video plugin @param {owl} carousel - the owl carousel var video = function(carousel) { reference to the core. @protected @type {owl} this._core = carousel; cache all video urls. @protected @type {object} this._videos = {}; current playing item. @protected @type {jquery} this._playing = null; all event handlers. @todo the cloned content removale is too late @protected @type {object} this._handlers = { 'initialized.owl.carousel' $.proxy(function(e) { if (e.namespace) { this._core.register({ type 'state', name 'playing', tags [ 'interacting' ] }); } }, this), 'resize.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.video && this.isinfullscreen()) { e.preventdefault(); } }, this), 'refreshed.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.is('resizing')) { this._core.$stage.find('.cloned .owl-video-frame').remove(); } }, this), 'changed.owl.carousel' $.proxy(function(e) { if (e.namespace && e.property.name === 'position' && this._playing) { this.stop(); } }, this), 'prepared.owl.carousel' $.proxy(function(e) { if (!e.namespace) { return; } var $element = $(e.content).find('.owl-video'); if ($element.length) { $element.css('display', 'none'); this.fetch($element, $(e.content)); } }, this) }; set default options this._core.options = $.extend({}, video.defaults, this._core.options); register event handlers this._core.$element.on(this._handlers); this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { this.play(e); }, this)); }; default options. @public video.defaults = { video false, videoheight false, videowidth false }; gets the video id and the type (youtubevimeovzaar only). @protected @param {jquery} target - the target containing the video data. @param {jquery} item - the item containing the video. video.prototype.fetch = function(target, item) { var type = (function() { if (target.attr('data-vimeo-id')) { return 'vimeo'; } else if (target.attr('data-vzaar-id')) { return 'vzaar' } else { return 'youtube'; } })(), id = target.attr('data-vimeo-id') target.attr('data-youtube-id') target.attr('data-vzaar-id'), width = target.attr('data-width') this._core.settings.videowidth, height = target.attr('data-height') this._core.settings.videoheight, url = target.attr('href'); if (url) { parses the id's out of the following urls (and probably more) httpswww.youtube.comwatchv=id httpsyoutu.beid httpsvimeo.comid httpsvimeo.comchannelschannelid httpsvimeo.comgroupsgroupvideosid httpsapp.vzaar.comvideosid visual example httpsregexper.com#(http%3a%7chttps%3a%7c)%5c%2f%5c%2f(player.%7cwww.%7capp.)%3f(vimeo%5c.com%7cyoutu(be%5c.com%7c%5c.be%7cbe%5c.googleapis%5c.com)%7cvzaar%5c.com)%5c%2f(video%5c%2f%7cvideos%5c%2f%7cembed%5c%2f%7cchannels%5c%2f.%2b%5c%2f%7cgroups%5c%2f.%2b%5c%2f%7cwatch%5c%3fv%3d%7cv%5c%2f)%3f(%5ba-za-z0-9._%25-%5d)(%5c%26%5cs%2b)%3f id = url.match((httphttps)(player.www.app.)(vimeo.comyoutu(be.com.bebe.googleapis.combe-nocookie.com)vzaar.com)(videovideosembedchannels.+groups.+watchv=v)([a-za-z0-9._%-])(&s+)); if (id[3].indexof('youtu') -1) { type = 'youtube'; } else if (id[3].indexof('vimeo') -1) { type = 'vimeo'; } else if (id[3].indexof('vzaar') -1) { type = 'vzaar'; } else { throw new error('video url not supported.'); } id = id[6]; } else { throw new error('missing video url.'); } this._videos[url] = { type type, id id, width width, height height }; item.attr('data-video', url); this.thumbnail(target, this._videos[url]); }; creates video thumbnail. @protected @param {jquery} target - the target containing the video data. @param {object} info - the video info object. @see `fetch` video.prototype.thumbnail = function(target, video) { var tnlink, icon, path, dimensions = video.width && video.height 'width' + video.width + 'px;height' + video.height + 'px;' '', customtn = target.find('img'), srctype = 'src', lazyclass = '', settings = this._core.settings, create = function(path) { icon = 'div class=owl-video-play-icondiv'; if (settings.lazyload) { tnlink = $('div',{ class 'owl-video-tn ' + lazyclass, srctype path }); } else { tnlink = $( 'div', { class owl-video-tn, style 'opacity1;background-imageurl(' + path + ')' }); } target.after(tnlink); target.after(icon); }; wrap video content into owl-video-wrapper div target.wrap( $( 'div', { class owl-video-wrapper, style dimensions })); if (this._core.settings.lazyload) { srctype = 'data-src'; lazyclass = 'owl-lazy'; } custom thumbnail if (customtn.length) { create(customtn.attr(srctype)); customtn.remove(); return false; } if (video.type === 'youtube') { path = img.youtube.comvi + video.id + hqdefault.jpg; create(path); } else if (video.type === 'vimeo') { $.ajax({ type 'get', url 'vimeo.comapiv2video' + video.id + '.json', jsonp 'callback', datatype 'jsonp', success function(data) { path = data[0].thumbnail_large; create(path); } }); } else if (video.type === 'vzaar') { $.ajax({ type 'get', url 'vzaar.comapivideos' + video.id + '.json', jsonp 'callback', datatype 'jsonp', success function(data) { path = data.framegrab_url; create(path); } }); } }; stops the current video. @public video.prototype.stop = function() { this._core.trigger('stop', null, 'video'); this._playing.find('.owl-video-frame').remove(); this._playing.removeclass('owl-video-playing'); this._playing = null; this._core.leave('playing'); this._core.trigger('stopped', null, 'video'); }; starts the current video. @public @param {event} event - the event arguments. video.prototype.play = function(event) { var target = $(event.target), item = target.closest('.' + this._core.settings.itemclass), video = this._videos[item.attr('data-video')], width = video.width '100%', height = video.height this._core.$stage.height(), html, iframe; if (this._playing) { return; } this._core.enter('playing'); this._core.trigger('play', null, 'video'); item = this._core.items(this._core.relative(item.index())); this._core.reset(item.index()); html = $( 'iframe frameborder=0 allowfullscreen mozallowfullscreen webkitallowfullscreen iframe' ); html.attr( 'height', height ); html.attr( 'width', width ); if (video.type === 'youtube') { html.attr( 'src', 'www.youtube.comembed' + video.id + 'autoplay=1&rel=0&v=' + video.id ); } else if (video.type === 'vimeo') { html.attr( 'src', 'player.vimeo.comvideo' + video.id + 'autoplay=1' ); } else if (video.type === 'vzaar') { html.attr( 'src', 'view.vzaar.com' + video.id + 'playerautoplay=true' ); } iframe = $(html).wrap( 'div class=owl-video-frame ' ).insertafter(item.find('.owl-video')); this._playing = item.addclass('owl-video-playing'); }; checks whether an video is currently in full screen mode or not. @todo bad style because looks like a readonly method but changes members. @protected @returns {boolean} video.prototype.isinfullscreen = function() { var element = document.fullscreenelement document.mozfullscreenelement document.webkitfullscreenelement; return element && $(element).parent().hasclass('owl-video-frame'); }; destroys the plugin. video.prototype.destroy = function() { var handler, property; this._core.$element.off('click.owl.video'); for (handler in this._handlers) { this._core.$element.off(handler, this._handlers[handler]); } for (property in object.getownpropertynames(this)) { typeof this[property] != 'function' && (this[property] = null); } }; $.fn.owlcarousel.constructor.plugins.video = video; })(window.zepto window.jquery, window, document); animate plugin @version 2.3.4 @author bartosz wojciechowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { creates the animate plugin. @class the navigation plugin @param {owl} scope - the owl carousel var animate = function(scope) { this.core = scope; this.core.options = $.extend({}, animate.defaults, this.core.options); this.swapping = true; this.previous = undefined; this.next = undefined; this.handlers = { 'change.owl.carousel' $.proxy(function(e) { if (e.namespace && e.property.name == 'position') { this.previous = this.core.current(); this.next = e.property.value; } }, this), 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel' $.proxy(function(e) { if (e.namespace) { this.swapping = e.type == 'translated'; } }, this), 'translate.owl.carousel' $.proxy(function(e) { if (e.namespace && this.swapping && (this.core.options.animateout this.core.options.animatein)) { this.swap(); } }, this) }; this.core.$element.on(this.handlers); }; default options. @public animate.defaults = { animateout false, animatein false }; toggles the animation classes whenever an translations starts. @protected @returns {booleanundefined} animate.prototype.swap = function() { if (this.core.settings.items !== 1) { return; } if (!$.support.animation !$.support.transition) { return; } this.core.speed(0); var left, clear = $.proxy(this.clear, this), previous = this.core.$stage.children().eq(this.previous), next = this.core.$stage.children().eq(this.next), incoming = this.core.settings.animatein, outgoing = this.core.settings.animateout; if (this.core.current() === this.previous) { return; } if (outgoing) { left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); previous.one($.support.animation.end, clear) .css( { 'left' left + 'px' } ) .addclass('animated owl-animated-out') .addclass(outgoing); } if (incoming) { next.one($.support.animation.end, clear) .addclass('animated owl-animated-in') .addclass(incoming); } }; animate.prototype.clear = function(e) { $(e.target).css( { 'left' '' } ) .removeclass('animated owl-animated-out owl-animated-in') .removeclass(this.core.settings.animatein) .removeclass(this.core.settings.animateout); this.core.ontransitionend(); }; destroys the plugin. @public animate.prototype.destroy = function() { var handler, property; for (handler in this.handlers) { this.core.$element.off(handler, this.handlers[handler]); } for (property in object.getownpropertynames(this)) { typeof this[property] != 'function' && (this[property] = null); } }; $.fn.owlcarousel.constructor.plugins.animate = animate; })(window.zepto window.jquery, window, document); autoplay plugin @version 2.3.4 @author bartosz wojciechowski @author artus kolanowski @author david deutsch @author tom de caluwãƒâ© @license the mit license (mit) ;(function($, window, document, undefined) { creates the autoplay plugin. @class the autoplay plugin @param {owl} scope - the owl carousel var autoplay = function(carousel) { reference to the core. @protected @type {owl} this._core = carousel; the autoplay timeout id. @type {number} this._call = null; depending on the state of the plugin, this variable contains either the start time of the timer or the current timer value if it's paused. since we start in a paused state we initialize the timer value. @type {number} this._time = 0; stores the timeout currently used. @type {number} this._timeout = 0; indicates whenever the autoplay is paused. @type {boolean} this._paused = true; all event handlers. @protected @type {object} this._handlers = { 'changed.owl.carousel' $.proxy(function(e) { if (e.namespace && e.property.name === 'settings') { if (this._core.settings.autoplay) { this.play(); } else { this.stop(); } } else if (e.namespace && e.property.name === 'position' && this._paused) { reset the timer. this code is triggered when the position of the carousel was changed through user interaction. this._time = 0; } }, this), 'initialized.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.autoplay) { this.play(); } }, this), 'play.owl.autoplay' $.proxy(function(e, t, s) { if (e.namespace) { this.play(t, s); } }, this), 'stop.owl.autoplay' $.proxy(function(e) { if (e.namespace) { this.stop(); } }, this), 'mouseover.owl.autoplay' $.proxy(function() { if (this._core.settings.autoplayhoverpause && this._core.is('rotating')) { this.pause(); } }, this), 'mouseleave.owl.autoplay' $.proxy(function() { if (this._core.settings.autoplayhoverpause && this._core.is('rotating')) { this.play(); } }, this), 'touchstart.owl.core' $.proxy(function() { if (this._core.settings.autoplayhoverpause && this._core.is('rotating')) { this.pause(); } }, this), 'touchend.owl.core' $.proxy(function() { if (this._core.settings.autoplayhoverpause) { this.play(); } }, this) }; register event handlers this._core.$element.on(this._handlers); set default options this._core.options = $.extend({}, autoplay.defaults, this._core.options); }; default options. @public autoplay.defaults = { autoplay false, autoplaytimeout 5000, autoplayhoverpause false, autoplayspeed false }; transition to the next slide and set a timeout for the next transition. @private @param {number} [speed] - the animation speed for the animations. autoplay.prototype._next = function(speed) { this._call = window.settimeout( $.proxy(this._next, this, speed), this._timeout (math.round(this.read() this._timeout) + 1) - this.read() ); if (this._core.is('interacting') document.hidden) { return; } this._core.next(speed this._core.settings.autoplayspeed); } reads the current timer value when the timer is playing. @public autoplay.prototype.read = function() { return new date().gettime() - this._time; }; starts the autoplay. @public @param {number} [timeout] - the interval before the next animation starts. @param {number} [speed] - the animation speed for the animations. autoplay.prototype.play = function(timeout, speed) { var elapsed; if (!this._core.is('rotating')) { this._core.enter('rotating'); } timeout = timeout this._core.settings.autoplaytimeout; calculate the elapsed time since the last transition. if the carousel wasn't playing this calculation will yield zero. elapsed = math.min(this._time % (this._timeout timeout), timeout); if (this._paused) { start the clock. this._time = this.read(); this._paused = false; } else { clear the active timeout to allow replacement. window.cleartimeout(this._call); } adjust the origin of the timer to match the new timeout value. this._time += this.read() % timeout - elapsed; this._timeout = timeout; this._call = window.settimeout($.proxy(this._next, this, speed), timeout - elapsed); }; stops the autoplay. @public autoplay.prototype.stop = function() { if (this._core.is('rotating')) { reset the clock. this._time = 0; this._paused = true; window.cleartimeout(this._call); this._core.leave('rotating'); } }; pauses the autoplay. @public autoplay.prototype.pause = function() { if (this._core.is('rotating') && !this._paused) { pause the clock. this._time = this.read(); this._paused = true; window.cleartimeout(this._call); } }; destroys the plugin. autoplay.prototype.destroy = function() { var handler, property; this.stop(); for (handler in this._handlers) { this._core.$element.off(handler, this._handlers[handler]); } for (property in object.getownpropertynames(this)) { typeof this[property] != 'function' && (this[property] = null); } }; $.fn.owlcarousel.constructor.plugins.autoplay = autoplay; })(window.zepto window.jquery, window, document); navigation plugin @version 2.3.4 @author artus kolanowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { 'use strict'; creates the navigation plugin. @class the navigation plugin @param {owl} carousel - the owl carousel. var navigation = function(carousel) { reference to the core. @protected @type {owl} this._core = carousel; indicates whether the plugin is initialized or not. @protected @type {boolean} this._initialized = false; the current paging indexes. @protected @type {array} this._pages = []; all dom elements of the user interface. @protected @type {object} this._controls = {}; markup for an indicator. @protected @type {array.string} this._templates = []; the carousel element. @type {jquery} this.$element = this._core.$element; overridden methods of the carousel. @protected @type {object} this._overrides = { next this._core.next, prev this._core.prev, to this._core.to }; all event handlers. @protected @type {object} this._handlers = { 'prepared.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.dotsdata) { this._templates.push('div class=' + this._core.settings.dotclass + '' + $(e.content).find('[data-dot]').addback('[data-dot]').attr('data-dot') + 'div'); } }, this), 'added.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.dotsdata) { this._templates.splice(e.position, 0, this._templates.pop()); } }, this), 'remove.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.dotsdata) { this._templates.splice(e.position, 1); } }, this), 'changed.owl.carousel' $.proxy(function(e) { if (e.namespace && e.property.name == 'position') { this.draw(); } }, this), 'initialized.owl.carousel' $.proxy(function(e) { if (e.namespace && !this._initialized) { this._core.trigger('initialize', null, 'navigation'); this.initialize(); this.update(); this.draw(); this._initialized = true; this._core.trigger('initialized', null, 'navigation'); } }, this), 'refreshed.owl.carousel' $.proxy(function(e) { if (e.namespace && this._initialized) { this._core.trigger('refresh', null, 'navigation'); this.update(); this.draw(); this._core.trigger('refreshed', null, 'navigation'); } }, this) }; set default options this._core.options = $.extend({}, navigation.defaults, this._core.options); register event handlers this.$element.on(this._handlers); }; default options. @public @todo rename `slideby` to `navby` navigation.defaults = { nav false, navtext [ 'span aria-label=' + 'previous' + '‹span', 'span aria-label=' + 'next' + '›span' ], navspeed false, navelement 'button type=button role=presentation', navcontainer false, navcontainerclass 'owl-nav', navclass [ 'owl-prev', 'owl-next' ], slideby 1, dotclass 'owl-dot', dotsclass 'owl-dots', dots true, dotseach false, dotsdata false, dotsspeed false, dotscontainer false }; initializes the layout of the plugin and extends the carousel. @protected navigation.prototype.initialize = function() { var override, settings = this._core.settings; create dom structure for relative navigation this._controls.$relative = (settings.navcontainer $(settings.navcontainer) $('div').addclass(settings.navcontainerclass).appendto(this.$element)).addclass('disabled'); this._controls.$previous = $('' + settings.navelement + '') .addclass(settings.navclass[0]) .html(settings.navtext[0]) .prependto(this._controls.$relative) .on('click', $.proxy(function(e) { this.prev(settings.navspeed); }, this)); this._controls.$next = $('' + settings.navelement + '') .addclass(settings.navclass[1]) .html(settings.navtext[1]) .appendto(this._controls.$relative) .on('click', $.proxy(function(e) { this.next(settings.navspeed); }, this)); create dom structure for absolute navigation if (!settings.dotsdata) { this._templates = [ $('button role=button') .addclass(settings.dotclass) .append($('span')) .prop('outerhtml') ]; } this._controls.$absolute = (settings.dotscontainer $(settings.dotscontainer) $('div').addclass(settings.dotsclass).appendto(this.$element)).addclass('disabled'); this._controls.$absolute.on('click', 'button', $.proxy(function(e) { var index = $(e.target).parent().is(this._controls.$absolute) $(e.target).index() $(e.target).parent().index(); e.preventdefault(); this.to(index, settings.dotsspeed); }, this)); $el.on('focusin', function() { $(document).off(.carousel); $(document).on('keydown.carousel', function(e) { if(e.keycode == 37) { $el.trigger('prev.owl') } if(e.keycode == 39) { $el.trigger('next.owl') } }); }); override public methods of the carousel for (override in this._overrides) { this._core[override] = $.proxy(this[override], this); } }; destroys the plugin. @protected navigation.prototype.destroy = function() { var handler, control, property, override, settings; settings = this._core.settings; for (handler in this._handlers) { this.$element.off(handler, this._handlers[handler]); } for (control in this._controls) { if (control === '$relative' && settings.navcontainer) { this._controls[control].html(''); } else { this._controls[control].remove(); } } for (override in this.overides) { this._core[override] = this._overrides[override]; } for (property in object.getownpropertynames(this)) { typeof this[property] != 'function' && (this[property] = null); } }; updates the internal state. @protected navigation.prototype.update = function() { var i, j, k, lower = this._core.clones().length 2, upper = lower + this._core.items().length, maximum = this._core.maximum(true), settings = this._core.settings, size = settings.center settings.autowidth settings.dotsdata 1 settings.dotseach settings.items; if (settings.slideby !== 'page') { settings.slideby = math.min(settings.slideby, settings.items); } if (settings.dots settings.slideby == 'page') { this._pages = []; for (i = lower, j = 0, k = 0; i upper; i++) { if (j = size j === 0) { this._pages.push({ start math.min(maximum, i - lower), end i - lower + size - 1 }); if (math.min(maximum, i - lower) === maximum) { break; } j = 0, ++k; } j += this._core.mergers(this._core.relative(i)); } } }; draws the user interface. @todo the option `dotsdata` wont work. @protected navigation.prototype.draw = function() { var difference, settings = this._core.settings, disabled = this._core.items().length = settings.items, index = this._core.relative(this._core.current()), loop = settings.loop settings.rewind; this._controls.$relative.toggleclass('disabled', !settings.nav disabled); if (settings.nav) { this._controls.$previous.toggleclass('disabled', !loop && index = this._core.minimum(true)); this._controls.$next.toggleclass('disabled', !loop && index = this._core.maximum(true)); } this._controls.$absolute.toggleclass('disabled', !settings.dots disabled); if (settings.dots) { difference = this._pages.length - this._controls.$absolute.children().length; if (settings.dotsdata && difference !== 0) { this._controls.$absolute.html(this._templates.join('')); } else if (difference 0) { this._controls.$absolute.append(new array(difference + 1).join(this._templates[0])); } else if (difference 0) { this._controls.$absolute.children().slice(difference).remove(); } this._controls.$absolute.find('.active').removeclass('active'); this._controls.$absolute.children().eq($.inarray(this.current(), this._pages)).addclass('active'); } }; extends event data. @protected @param {event} event - the event object which gets thrown. navigation.prototype.ontrigger = function(event) { var settings = this._core.settings; event.page = { index $.inarray(this.current(), this._pages), count this._pages.length, size settings && (settings.center settings.autowidth settings.dotsdata 1 settings.dotseach settings.items) }; }; gets the current page position of the carousel. @protected @returns {number} navigation.prototype.current = function() { var current = this._core.relative(this._core.current()); return $.grep(this._pages, $.proxy(function(page, index) { return page.start = current && page.end = current; }, this)).pop(); }; gets the current succesorpredecessor position. @protected @returns {number} navigation.prototype.getposition = function(successor) { var position, length, settings = this._core.settings; if (settings.slideby == 'page') { position = $.inarray(this.current(), this._pages); length = this._pages.length; successor ++position --position; position = this._pages[((position % length) + length) % length].start; } else { position = this._core.relative(this._core.current()); length = this._core.items().length; successor position += settings.slideby position -= settings.slideby; } return position; }; slides to the next item or page. @public @param {number} [speed=false] - the time in milliseconds for the transition. navigation.prototype.next = function(speed) { $.proxy(this._overrides.to, this._core)(this.getposition(true), speed); }; slides to the previous item or page. @public @param {number} [speed=false] - the time in milliseconds for the transition. navigation.prototype.prev = function(speed) { $.proxy(this._overrides.to, this._core)(this.getposition(false), speed); }; slides to the specified item or page. @public @param {number} position - the position of the item or page. @param {number} [speed] - the time in milliseconds for the transition. @param {boolean} [standard=false] - whether to use the standard behaviour or not. navigation.prototype.to = function(position, speed, standard) { var length; if (!standard && this._pages.length) { length = this._pages.length; $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); } else { $.proxy(this._overrides.to, this._core)(position, speed); } }; $.fn.owlcarousel.constructor.plugins.navigation = navigation; })(window.zepto window.jquery, window, document); hash plugin @version 2.3.4 @author artus kolanowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { 'use strict'; creates the hash plugin. @class the hash plugin @param {owl} carousel - the owl carousel var hash = function(carousel) { reference to the core. @protected @type {owl} this._core = carousel; hash index for the items. @protected @type {object} this._hashes = {}; the carousel element. @type {jquery} this.$element = this._core.$element; all event handlers. @protected @type {object} this._handlers = { 'initialized.owl.carousel' $.proxy(function(e) { if (e.namespace && this._core.settings.startposition === 'urlhash') { $(window).trigger('hashchange.owl.navigation'); } }, this), 'prepared.owl.carousel' $.proxy(function(e) { if (e.namespace) { var hash = $(e.content).find('[data-hash]').addback('[data-hash]').attr('data-hash'); if (!hash) { return; } this._hashes[hash] = e.content; } }, this), 'changed.owl.carousel' $.proxy(function(e) { if (e.namespace && e.property.name === 'position') { var current = this._core.items(this._core.relative(this._core.current())), hash = $.map(this._hashes, function(item, hash) { return item === current hash null; }).join(); if (!hash window.location.hash.slice(1) === hash) { return; } window.location.hash = hash; } }, this) }; set default options this._core.options = $.extend({}, hash.defaults, this._core.options); register the event handlers this.$element.on(this._handlers); register event listener for hash navigation $(window).on('hashchange.owl.navigation', $.proxy(function(e) { var hash = window.location.hash.substring(1), items = this._core.$stage.children(), position = this._hashes[hash] && items.index(this._hashes[hash]); if (position === undefined position === this._core.current()) { return; } this._core.to(this._core.relative(position), false, true); }, this)); }; default options. @public hash.defaults = { urlhashlistener false }; destroys the plugin. @public hash.prototype.destroy = function() { var handler, property; $(window).off('hashchange.owl.navigation'); for (handler in this._handlers) { this._core.$element.off(handler, this._handlers[handler]); } for (property in object.getownpropertynames(this)) { typeof this[property] != 'function' && (this[property] = null); } }; $.fn.owlcarousel.constructor.plugins.hash = hash; })(window.zepto window.jquery, window, document); support plugin @version 2.3.4 @author vivid planet software gmbh @author artus kolanowski @author david deutsch @license the mit license (mit) ;(function($, window, document, undefined) { var style = $('support').get(0).style, prefixes = 'webkit moz o ms'.split(' '), events = { transition { end { webkittransition 'webkittransitionend', moztransition 'transitionend', otransition 'otransitionend', transition 'transitionend' } }, animation { end { webkitanimation 'webkitanimationend', mozanimation 'animationend', oanimation 'oanimationend', animation 'animationend' } } }, tests = { csstransforms function() { return !!test('transform'); }, csstransforms3d function() { return !!test('perspective'); }, csstransitions function() { return !!test('transition'); }, cssanimations function() { return !!test('animation'); } }; function test(property, prefixed) { var result = false, upper = property.charat(0).touppercase() + property.slice(1); $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { if (style[property] !== undefined) { result = prefixed property true; return false; } }); return result; } function prefixed(property) { return test(property, true); } if (tests.csstransitions()) { jshint -w053 $.support.transition = new string(prefixed('transition')) $.support.transition.end = events.transition.end[ $.support.transition ]; } if (tests.cssanimations()) { jshint -w053 $.support.animation = new string(prefixed('animation')) $.support.animation.end = events.animation.end[ $.support.animation ]; } if (tests.csstransforms()) { jshint -w053 $.support.transform = new string(prefixed('transform')); $.support.transform3d = tests.csstransforms3d(); } })(window.zepto window.jquery, window, document);