JAVASCRIPT   36

owl.carousel.js

Guest on 6th August 2021 06:42:39 PM

  1. /**
  2.  * Owl carousel
  3.  * @version 2.0.0
  4.  * @author Bartosz Wojciechowski
  5.  * @license The MIT License (MIT)
  6.  * @todo Lazy Load Icon
  7.  * @todo prevent animationend bubling
  8.  * @todo itemsScaleUp
  9.  * @todo Test Zepto
  10.  * @todo stagePadding calculate wrong active classes
  11.  */
  12. ;(function($, window, document, undefined) {
  13.  
  14.         var drag, state, e;
  15.  
  16.         /**
  17.          * Template for status information about drag and touch events.
  18.          * @private
  19.          */
  20.         drag = {
  21.                 start: 0,
  22.                 startX: 0,
  23.                 startY: 0,
  24.                 current: 0,
  25.                 currentX: 0,
  26.                 currentY: 0,
  27.                 offsetX: 0,
  28.                 offsetY: 0,
  29.                 distance: null,
  30.                 startTime: 0,
  31.                 endTime: 0,
  32.                 updatedX: 0,
  33.                 targetEl: null
  34.         };
  35.  
  36.         /**
  37.          * Template for some status informations.
  38.          * @private
  39.          */
  40.         state = {
  41.                 isTouch: false,
  42.                 isScrolling: false,
  43.                 isSwiping: false,
  44.                 direction: false,
  45.                 inMotion: false
  46.         };
  47.  
  48.         /**
  49.          * Event functions references.
  50.          * @private
  51.          */
  52.         e = {
  53.                 _onDragStart: null,
  54.                 _onDragMove: null,
  55.                 _onDragEnd: null,
  56.                 _transitionEnd: null,
  57.                 _resizer: null,
  58.                 _responsiveCall: null,
  59.                 _goToLoop: null,
  60.                 _checkVisibile: null
  61.         };
  62.  
  63.         /**
  64.          * Creates a carousel.
  65.          * @class The Owl Carousel.
  66.          * @public
  67.          * @param {HTMLElement|jQuery} element - The element to create the carousel for.
  68.          * @param {Object} [options] - The options
  69.          */
  70.         function Owl(element, options) {
  71.  
  72.                 /**
  73.                  * Current settings for the carousel.
  74.                  * @public
  75.                  */
  76.                 this.settings = null;
  77.  
  78.                 /**
  79.                  * Current options set by the caller including defaults.
  80.                  * @public
  81.                  */
  82.                 this.options = $.extend({}, Owl.Defaults, options);
  83.  
  84.                 /**
  85.                  * Plugin element.
  86.                  * @public
  87.                  */
  88.                 this.$element = $(element);
  89.  
  90.                 /**
  91.                  * Caches informations about drag and touch events.
  92.                  */
  93.                 this.drag = $.extend({}, drag);
  94.  
  95.                 /**
  96.                  * Caches some status informations.
  97.                  * @protected
  98.                  */
  99.                 this.state = $.extend({}, state);
  100.  
  101.                 /**
  102.                  * @protected
  103.                  * @todo Must be documented
  104.                  */
  105.                 this.e = $.extend({}, e);
  106.  
  107.                 /**
  108.                  * References to the running plugins of this carousel.
  109.                  * @protected
  110.                  */
  111.                 this._plugins = {};
  112.  
  113.                 /**
  114.                  * Currently suppressed events to prevent them from beeing retriggered.
  115.                  * @protected
  116.                  */
  117.                 this._supress = {};
  118.  
  119.                 /**
  120.                  * Absolute current position.
  121.                  * @protected
  122.                  */
  123.                 this._current = null;
  124.  
  125.                 /**
  126.                  * Animation speed in milliseconds.
  127.                  * @protected
  128.                  */
  129.                 this._speed = null;
  130.  
  131.                 /**
  132.                  * Coordinates of all items in pixel.
  133.                  * @todo The name of this member is missleading.
  134.                  * @protected
  135.                  */
  136.                 this._coordinates = [];
  137.  
  138.                 /**
  139.                  * Current breakpoint.
  140.                  * @todo Real media queries would be nice.
  141.                  * @protected
  142.                  */
  143.                 this._breakpoint = null;
  144.  
  145.                 /**
  146.                  * Current width of the plugin element.
  147.                  */
  148.                 this._width = null;
  149.  
  150.                 /**
  151.                  * All real items.
  152.                  * @protected
  153.                  */
  154.                 this._items = [];
  155.  
  156.                 /**
  157.                  * All cloned items.
  158.                  * @protected
  159.                  */
  160.                 this._clones = [];
  161.  
  162.                 /**
  163.                  * Merge values of all items.
  164.                  * @todo Maybe this could be part of a plugin.
  165.                  * @protected
  166.                  */
  167.                 this._mergers = [];
  168.  
  169.                 /**
  170.                  * Invalidated parts within the update process.
  171.                  * @protected
  172.                  */
  173.                 this._invalidated = {};
  174.  
  175.                 /**
  176.                  * Ordered list of workers for the update process.
  177.                  * @protected
  178.                  */
  179.                 this._pipe = [];
  180.  
  181.                 $.each(Owl.Plugins, $.proxy(function(key, plugin) {
  182.                         this._plugins[key[0].toLowerCase() + key.slice(1)]
  183.                                 = new plugin(this);
  184.                 }, this));
  185.  
  186.                 $.each(Owl.Pipe, $.proxy(function(priority, worker) {
  187.                         this._pipe.push({
  188.                                 'filter': worker.filter,
  189.                                 'run': $.proxy(worker.run, this)
  190.                         });
  191.                 }, this));
  192.  
  193.                 this.setup();
  194.                 this.initialize();
  195.         }
  196.  
  197.         /**
  198.          * Default options for the carousel.
  199.          * @public
  200.          */
  201.         Owl.Defaults = {
  202.                 items: 3,
  203.                 loop: false,
  204.                 center: false,
  205.  
  206.                 mouseDrag: true,
  207.                 touchDrag: true,
  208.                 pullDrag: true,
  209.                 freeDrag: false,
  210.  
  211.                 margin: 0,
  212.                 stagePadding: 0,
  213.  
  214.                 merge: false,
  215.                 mergeFit: true,
  216.                 autoWidth: false,
  217.  
  218.                 startPosition: 0,
  219.                 rtl: false,
  220.  
  221.                 smartSpeed: 250,
  222.                 fluidSpeed: false,
  223.                 dragEndSpeed: false,
  224.  
  225.                 responsive: {},
  226.                 responsiveRefreshRate: 200,
  227.                 responsiveBaseElement: window,
  228.                 responsiveClass: false,
  229.  
  230.                 fallbackEasing: 'swing',
  231.  
  232.                 info: false,
  233.  
  234.                 nestedItemSelector: false,
  235.                 itemElement: 'div',
  236.                 stageElement: 'div',
  237.  
  238.                 // Classes and Names
  239.                 themeClass: 'owl-theme',
  240.                 baseClass: 'owl-carousel',
  241.                 itemClass: 'owl-item',
  242.                 centerClass: 'center',
  243.                 activeClass: 'active'
  244.         };
  245.  
  246.         /**
  247.          * Enumeration for width.
  248.          * @public
  249.          * @readonly
  250.          * @enum {String}
  251.          */
  252.         Owl.Width = {
  253.                 Default: 'default',
  254.                 Inner: 'inner',
  255.                 Outer: 'outer'
  256.         };
  257.  
  258.         /**
  259.          * Contains all registered plugins.
  260.          * @public
  261.          */
  262.         Owl.Plugins = {};
  263.  
  264.         /**
  265.          * Update pipe.
  266.          */
  267.         Owl.Pipe = [ {
  268.                 filter: [ 'width', 'items', 'settings' ],
  269.                 run: function(cache) {
  270.                         cache.current = this._items && this._items[this.relative(this._current)];
  271.                 }
  272.         }, {
  273.                 filter: [ 'items', 'settings' ],
  274.                 run: function() {
  275.                         var cached = this._clones,
  276.                                 clones = this.$stage.children('.cloned');
  277.  
  278.                         if (clones.length !== cached.length || (!this.settings.loop && cached.length > 0)) {
  279.                                 this.$stage.children('.cloned').remove();
  280.                                 this._clones = [];
  281.                         }
  282.                 }
  283.         }, {
  284.                 filter: [ 'items', 'settings' ],
  285.                 run: function() {
  286.                         var i, n,
  287.                                 clones = this._clones,
  288.                                 items = this._items,
  289.                                 delta = this.settings.loop ? clones.length - Math.max(this.settings.items * 2, 4) : 0;
  290.  
  291.                         for (i = 0, n = Math.abs(delta / 2); i < n; i++) {
  292.                                 if (delta > 0) {
  293.                                         this.$stage.children().eq(items.length + clones.length - 1).remove();
  294.                                         clones.pop();
  295.                                         this.$stage.children().eq(0).remove();
  296.                                         clones.pop();
  297.                                 } else {
  298.                                         clones.push(clones.length / 2);
  299.                                         this.$stage.append(items[clones[clones.length - 1]].clone().addClass('cloned'));
  300.                                         clones.push(items.length - 1 - (clones.length - 1) / 2);
  301.                                         this.$stage.prepend(items[clones[clones.length - 1]].clone().addClass('cloned'));
  302.                                 }
  303.                         }
  304.                 }
  305.         }, {
  306.                 filter: [ 'width', 'items', 'settings' ],
  307.                 run: function() {
  308.                         var rtl = (this.settings.rtl ? 1 : -1),
  309.                                 width = (this.width() / this.settings.items).toFixed(3),
  310.                                 coordinate = 0, merge, i, n;
  311.  
  312.                         this._coordinates = [];
  313.                         for (i = 0, n = this._clones.length + this._items.length; i < n; i++) {
  314.                                 merge = this._mergers[this.relative(i)];
  315.                                 merge = (this.settings.mergeFit && Math.min(merge, this.settings.items)) || merge;
  316.                                 coordinate += (this.settings.autoWidth ? this._items[this.relative(i)].width() + this.settings.margin : width * merge) * rtl;
  317.  
  318.                                 this._coordinates.push(coordinate);
  319.                         }
  320.                 }
  321.         }, {
  322.                 filter: [ 'width', 'items', 'settings' ],
  323.                 run: function() {
  324.                         var i, n, width = (this.width() / this.settings.items).toFixed(3), css = {
  325.                                 'width': Math.abs(this._coordinates[this._coordinates.length - 1]) + this.settings.stagePadding * 2,
  326.                                 'padding-left': this.settings.stagePadding || '',
  327.                                 'padding-right': this.settings.stagePadding || ''
  328.                         };
  329.  
  330.                         this.$stage.css(css);
  331.  
  332.                         css = { 'width': this.settings.autoWidth ? 'auto' : width - this.settings.margin };
  333.                         css[this.settings.rtl ? 'margin-left' : 'margin-right'] = this.settings.margin;
  334.  
  335.                         if (!this.settings.autoWidth && $.grep(this._mergers, function(v) { return v > 1 }).length > 0) {
  336.                                 for (i = 0, n = this._coordinates.length; i < n; i++) {
  337.                                         css.width = Math.abs(this._coordinates[i]) - Math.abs(this._coordinates[i - 1] || 0) - this.settings.margin;
  338.                                         this.$stage.children().eq(i).css(css);
  339.                                 }
  340.                         } else {
  341.                                 this.$stage.children().css(css);
  342.                         }
  343.                 }
  344.         }, {
  345.                 filter: [ 'width', 'items', 'settings' ],
  346.                 run: function(cache) {
  347.                         cache.current && this.reset(this.$stage.children().index(cache.current));
  348.                 }
  349.         }, {
  350.                 filter: [ 'position' ],
  351.                 run: function() {
  352.                         this.animate(this.coordinates(this._current));
  353.                 }
  354.         }, {
  355.                 filter: [ 'width', 'position', 'items', 'settings' ],
  356.                 run: function() {
  357.                         var rtl = this.settings.rtl ? 1 : -1,
  358.                                 padding = this.settings.stagePadding * 2,
  359.                                 begin = this.coordinates(this.current()) + padding,
  360.                                 end = begin + this.width() * rtl,
  361.                                 inner, outer, matches = [], i, n;
  362.  
  363.                         for (i = 0, n = this._coordinates.length; i < n; i++) {
  364.                                 inner = this._coordinates[i - 1] || 0;
  365.                                 outer = Math.abs(this._coordinates[i]) + padding * rtl;
  366.  
  367.                                 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
  368.                                         || (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
  369.                                         matches.push(i);
  370.                                 }
  371.                         }
  372.  
  373.                         this.$stage.children('.' + this.settings.activeClass).removeClass(this.settings.activeClass);
  374.                         this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass(this.settings.activeClass);
  375.  
  376.                         if (this.settings.center) {
  377.                                 this.$stage.children('.' + this.settings.centerClass).removeClass(this.settings.centerClass);
  378.                                 this.$stage.children().eq(this.current()).addClass(this.settings.centerClass);
  379.                         }
  380.                 }
  381.         } ];
  382.  
  383.         /**
  384.          * Initializes the carousel.
  385.          * @protected
  386.          */
  387.         Owl.prototype.initialize = function() {
  388.                 this.trigger('initialize');
  389.  
  390.                 this.$element
  391.                         .addClass(this.settings.baseClass)
  392.                         .addClass(this.settings.themeClass)
  393.                         .toggleClass('owl-rtl', this.settings.rtl);
  394.  
  395.                 // check support
  396.                 this.browserSupport();
  397.  
  398.                 if (this.settings.autoWidth && this.state.imagesLoaded !== true) {
  399.                         var imgs, nestedSelector, width;
  400.                         imgs = this.$element.find('img');
  401.                         nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
  402.                         width = this.$element.children(nestedSelector).width();
  403.  
  404.                         if (imgs.length && width <= 0) {
  405.                                 this.preloadAutoWidthImages(imgs);
  406.                                 return false;
  407.                         }
  408.                 }
  409.  
  410.                 this.$element.addClass('owl-loading');
  411.  
  412.                 // create stage
  413.                 this.$stage = $('<' + this.settings.stageElement + ' class="owl-stage"/>')
  414.                         .wrap('<div class="owl-stage-outer">');
  415.  
  416.                 // append stage
  417.                 this.$element.append(this.$stage.parent());
  418.  
  419.                 // append content
  420.                 this.replace(this.$element.children().not(this.$stage.parent()));
  421.  
  422.                 // set view width
  423.                 this._width = this.$element.width();
  424.  
  425.                 // update view
  426.                 this.refresh();
  427.  
  428.                 this.$element.removeClass('owl-loading').addClass('owl-loaded');
  429.  
  430.                 // attach generic events
  431.                 this.eventsCall();
  432.  
  433.                 // attach generic events
  434.                 this.internalEvents();
  435.  
  436.                 // attach custom control events
  437.                 this.addTriggerableEvents();
  438.  
  439.                 this.trigger('initialized');
  440.         };
  441.  
  442.         /**
  443.          * Setups the current settings.
  444.          * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
  445.          * @todo Support for media queries by using `matchMedia` would be nice.
  446.          * @public
  447.          */
  448.         Owl.prototype.setup = function() {
  449.                 var viewport = this.viewport(),
  450.                         overwrites = this.options.responsive,
  451.                         match = -1,
  452.                         settings = null;
  453.  
  454.                 if (!overwrites) {
  455.                         settings = $.extend({}, this.options);
  456.                 } else {
  457.                         $.each(overwrites, function(breakpoint) {
  458.                                 if (breakpoint <= viewport && breakpoint > match) {
  459.                                         match = Number(breakpoint);
  460.                                 }
  461.                         });
  462.  
  463.                         settings = $.extend({}, this.options, overwrites[match]);
  464.                         delete settings.responsive;
  465.  
  466.                         // responsive class
  467.                         if (settings.responsiveClass) {
  468.                                 this.$element.attr('class', function(i, c) {
  469.                                         return c.replace(/\b owl-responsive-\S+/g, '');
  470.                                 }).addClass('owl-responsive-' + match);
  471.                         }
  472.                 }
  473.  
  474.                 if (this.settings === null || this._breakpoint !== match) {
  475.                         this.trigger('change', { property: { name: 'settings', value: settings } });
  476.                         this._breakpoint = match;
  477.                         this.settings = settings;
  478.                         this.invalidate('settings');
  479.                         this.trigger('changed', { property: { name: 'settings', value: this.settings } });
  480.                 }
  481.         };
  482.  
  483.         /**
  484.          * Updates option logic if necessery.
  485.          * @protected
  486.          */
  487.         Owl.prototype.optionsLogic = function() {
  488.                 // Toggle Center class
  489.                 this.$element.toggleClass('owl-center', this.settings.center);
  490.  
  491.                 // if items number is less than in body
  492.                 if (this.settings.loop && this._items.length < this.settings.items) {
  493.                         this.settings.loop = false;
  494.                 }
  495.  
  496.                 if (this.settings.autoWidth) {
  497.                         this.settings.stagePadding = false;
  498.                         this.settings.merge = false;
  499.                 }
  500.         };
  501.  
  502.         /**
  503.          * Prepares an item before add.
  504.          * @todo Rename event parameter `content` to `item`.
  505.          * @protected
  506.          * @returns {jQuery|HTMLElement} - The item container.
  507.          */
  508.         Owl.prototype.prepare = function(item) {
  509.                 var event = this.trigger('prepare', { content: item });
  510.  
  511.                 if (!event.data) {
  512.                         event.data = $('<' + this.settings.itemElement + '/>')
  513.                                 .addClass(this.settings.itemClass).append(item)
  514.                 }
  515.  
  516.                 this.trigger('prepared', { content: event.data });
  517.  
  518.                 return event.data;
  519.         };
  520.  
  521.         /**
  522.          * Updates the view.
  523.          * @public
  524.          */
  525.         Owl.prototype.update = function() {
  526.                 var i = 0,
  527.                         n = this._pipe.length,
  528.                         filter = $.proxy(function(p) { return this[p] }, this._invalidated),
  529.                         cache = {};
  530.  
  531.                 while (i < n) {
  532.                         if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
  533.                                 this._pipe[i].run(cache);
  534.                         }
  535.                         i++;
  536.                 }
  537.  
  538.                 this._invalidated = {};
  539.         };
  540.  
  541.         /**
  542.          * Gets the width of the view.
  543.          * @public
  544.          * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
  545.          * @returns {Number} - The width of the view in pixel.
  546.          */
  547.         Owl.prototype.width = function(dimension) {
  548.                 dimension = dimension || Owl.Width.Default;
  549.                 switch (dimension) {
  550.                         case Owl.Width.Inner:
  551.                         case Owl.Width.Outer:
  552.                                 return this._width;
  553.                         default:
  554.                                 return this._width - this.settings.stagePadding * 2 + this.settings.margin;
  555.                 }
  556.         };
  557.  
  558.         /**
  559.          * Refreshes the carousel primarily for adaptive purposes.
  560.          * @public
  561.          */
  562.         Owl.prototype.refresh = function() {
  563.                 if (this._items.length === 0) {
  564.                         return false;
  565.                 }
  566.  
  567.                 var start = new Date().getTime();
  568.  
  569.                 this.trigger('refresh');
  570.  
  571.                 this.setup();
  572.  
  573.                 this.optionsLogic();
  574.  
  575.                 // hide and show methods helps here to set a proper widths,
  576.                 // this prevents scrollbar to be calculated in stage width
  577.                 this.$stage.addClass('owl-refresh');
  578.  
  579.                 this.update();
  580.  
  581.                 this.$stage.removeClass('owl-refresh');
  582.  
  583.                 this.state.orientation = window.orientation;
  584.  
  585.                 this.watchVisibility();
  586.  
  587.                 this.trigger('refreshed');
  588.         };
  589.  
  590.         /**
  591.          * Save internal event references and add event based functions.
  592.          * @protected
  593.          */
  594.         Owl.prototype.eventsCall = function() {
  595.                 // Save events references
  596.                 this.e._onDragStart = $.proxy(function(e) {
  597.                         this.onDragStart(e);
  598.                 }, this);
  599.                 this.e._onDragMove = $.proxy(function(e) {
  600.                         this.onDragMove(e);
  601.                 }, this);
  602.                 this.e._onDragEnd = $.proxy(function(e) {
  603.                         this.onDragEnd(e);
  604.                 }, this);
  605.                 this.e._onResize = $.proxy(function(e) {
  606.                         this.onResize(e);
  607.                 }, this);
  608.                 this.e._transitionEnd = $.proxy(function(e) {
  609.                         this.transitionEnd(e);
  610.                 }, this);
  611.                 this.e._preventClick = $.proxy(function(e) {
  612.                         this.preventClick(e);
  613.                 }, this);
  614.         };
  615.  
  616.         /**
  617.          * Checks window `resize` event.
  618.          * @protected
  619.          */
  620.         Owl.prototype.onThrottledResize = function() {
  621.                 window.clearTimeout(this.resizeTimer);
  622.                 this.resizeTimer = window.setTimeout(this.e._onResize, this.settings.responsiveRefreshRate);
  623.         };
  624.  
  625.         /**
  626.          * Checks window `resize` event.
  627.          * @protected
  628.          */
  629.         Owl.prototype.onResize = function() {
  630.                 if (!this._items.length) {
  631.                         return false;
  632.                 }
  633.  
  634.                 if (this._width === this.$element.width()) {
  635.                         return false;
  636.                 }
  637.  
  638.                 if (this.trigger('resize').isDefaultPrevented()) {
  639.                         return false;
  640.                 }
  641.  
  642.                 this._width = this.$element.width();
  643.  
  644.                 this.invalidate('width');
  645.  
  646.                 this.refresh();
  647.  
  648.                 this.trigger('resized');
  649.         };
  650.  
  651.         /**
  652.          * Checks for touch/mouse drag event type and add run event handlers.
  653.          * @protected
  654.          */
  655.         Owl.prototype.eventsRouter = function(event) {
  656.                 var type = event.type;
  657.  
  658.                 if (type === "mousedown" || type === "touchstart") {
  659.                         this.onDragStart(event);
  660.                 } else if (type === "mousemove" || type === "touchmove") {
  661.                         this.onDragMove(event);
  662.                 } else if (type === "mouseup" || type === "touchend") {
  663.                         this.onDragEnd(event);
  664.                 } else if (type === "touchcancel") {
  665.                         this.onDragEnd(event);
  666.                 }
  667.         };
  668.  
  669.         /**
  670.          * Checks for touch/mouse drag options and add necessery event handlers.
  671.          * @protected
  672.          */
  673.         Owl.prototype.internalEvents = function() {
  674.                 var isTouch = isTouchSupport(),
  675.                         isTouchIE = isTouchSupportIE();
  676.  
  677.                 if (this.settings.mouseDrag){
  678.                         this.$stage.on('mousedown', $.proxy(function(event) { this.eventsRouter(event) }, this));
  679.                         this.$stage.on('dragstart', function() { return false });
  680.                         this.$stage.get(0).onselectstart = function() { return false };
  681.                 } else {
  682.                         this.$element.addClass('owl-text-select-on');
  683.                 }
  684.  
  685.                 if (this.settings.touchDrag && !isTouchIE){
  686.                         this.$stage.on('touchstart touchcancel', $.proxy(function(event) { this.eventsRouter(event) }, this));
  687.                 }
  688.  
  689.                 // catch transitionEnd event
  690.                 if (this.transitionEndVendor) {
  691.                         this.on(this.$stage.get(0), this.transitionEndVendor, this.e._transitionEnd, false);
  692.                 }
  693.  
  694.                 // responsive
  695.                 if (this.settings.responsive !== false) {
  696.                         this.on(window, 'resize', $.proxy(this.onThrottledResize, this));
  697.                 }
  698.         };
  699.  
  700.         /**
  701.          * Handles touchstart/mousedown event.
  702.          * @protected
  703.          * @param {Event} event - The event arguments.
  704.          */
  705.         Owl.prototype.onDragStart = function(event) {
  706.                 var ev, isTouchEvent, pageX, pageY, animatedPos;
  707.  
  708.                 ev = event.originalEvent || event || window.event;
  709.  
  710.                 // prevent right click
  711.                 if (ev.which === 3 || this.state.isTouch) {
  712.                         return false;
  713.                 }
  714.  
  715.                 if (ev.type === 'mousedown') {
  716.                         this.$stage.addClass('owl-grab');
  717.                 }
  718.  
  719.                 this.trigger('drag');
  720.                 this.drag.startTime = new Date().getTime();
  721.                 this.speed(0);
  722.                 this.state.isTouch = true;
  723.                 this.state.isScrolling = false;
  724.                 this.state.isSwiping = false;
  725.                 this.drag.distance = 0;
  726.  
  727.                 pageX = getTouches(ev).x;
  728.                 pageY = getTouches(ev).y;
  729.  
  730.                 // get stage position left
  731.                 this.drag.offsetX = this.$stage.position().left;
  732.                 this.drag.offsetY = this.$stage.position().top;
  733.  
  734.                 if (this.settings.rtl) {
  735.                         this.drag.offsetX = this.$stage.position().left + this.$stage.width() - this.width()
  736.                                 + this.settings.margin;
  737.                 }
  738.  
  739.                 // catch position // ie to fix
  740.                 if (this.state.inMotion && this.support3d) {
  741.                         animatedPos = this.getTransformProperty();
  742.                         this.drag.offsetX = animatedPos;
  743.                         this.animate(animatedPos);
  744.                         this.state.inMotion = true;
  745.                 } else if (this.state.inMotion && !this.support3d) {
  746.                         this.state.inMotion = false;
  747.                         return false;
  748.                 }
  749.  
  750.                 this.drag.startX = pageX - this.drag.offsetX;
  751.                 this.drag.startY = pageY - this.drag.offsetY;
  752.  
  753.                 this.drag.start = pageX - this.drag.startX;
  754.                 this.drag.targetEl = ev.target || ev.srcElement;
  755.                 this.drag.updatedX = this.drag.start;
  756.  
  757.                 // to do/check
  758.                 // prevent links and images dragging;
  759.                 if (this.drag.targetEl.tagName === "IMG" || this.drag.targetEl.tagName === "A") {
  760.                         this.drag.targetEl.draggable = false;
  761.                 }
  762.  
  763.                 $(document).on('mousemove.owl.dragEvents mouseup.owl.dragEvents touchmove.owl.dragEvents touchend.owl.dragEvents', $.proxy(function(event) {this.eventsRouter(event)},this));
  764.         };
  765.  
  766.         /**
  767.          * Handles the touchmove/mousemove events.
  768.          * @todo Simplify
  769.          * @protected
  770.          * @param {Event} event - The event arguments.
  771.          */
  772.         Owl.prototype.onDragMove = function(event) {
  773.                 var ev, isTouchEvent, pageX, pageY, minValue, maxValue, pull;
  774.  
  775.                 if (!this.state.isTouch) {
  776.                         return;
  777.                 }
  778.  
  779.                 if (this.state.isScrolling) {
  780.                         return;
  781.                 }
  782.  
  783.                 ev = event.originalEvent || event || window.event;
  784.  
  785.                 pageX = getTouches(ev).x;
  786.                 pageY = getTouches(ev).y;
  787.  
  788.                 // Drag Direction
  789.                 this.drag.currentX = pageX - this.drag.startX;
  790.                 this.drag.currentY = pageY - this.drag.startY;
  791.                 this.drag.distance = this.drag.currentX - this.drag.offsetX;
  792.  
  793.                 // Check move direction
  794.                 if (this.drag.distance < 0) {
  795.                         this.state.direction = this.settings.rtl ? 'right' : 'left';
  796.                 } else if (this.drag.distance > 0) {
  797.                         this.state.direction = this.settings.rtl ? 'left' : 'right';
  798.                 }
  799.                 // Loop
  800.                 if (this.settings.loop) {
  801.                         if (this.op(this.drag.currentX, '>', this.coordinates(this.minimum())) && this.state.direction === 'right') {
  802.                                 this.drag.currentX -= (this.settings.center && this.coordinates(0)) - this.coordinates(this._items.length);
  803.                         } else if (this.op(this.drag.currentX, '<', this.coordinates(this.maximum())) && this.state.direction === 'left') {
  804.                                 this.drag.currentX += (this.settings.center && this.coordinates(0)) - this.coordinates(this._items.length);
  805.                         }
  806.                 } else {
  807.                         // pull
  808.                         minValue = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
  809.                         maxValue = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
  810.                         pull = this.settings.pullDrag ? this.drag.distance / 5 : 0;
  811.                         this.drag.currentX = Math.max(Math.min(this.drag.currentX, minValue + pull), maxValue + pull);
  812.                 }
  813.  
  814.                 // Lock browser if swiping horizontal
  815.  
  816.                 if ((this.drag.distance > 8 || this.drag.distance < -8)) {
  817.                         if (ev.preventDefault !== undefined) {
  818.                                 ev.preventDefault();
  819.                         } else {
  820.                                 ev.returnValue = false;
  821.                         }
  822.                         this.state.isSwiping = true;
  823.                 }
  824.  
  825.                 this.drag.updatedX = this.drag.currentX;
  826.  
  827.                 // Lock Owl if scrolling
  828.                 if ((this.drag.currentY > 16 || this.drag.currentY < -16) && this.state.isSwiping === false) {
  829.                         this.state.isScrolling = true;
  830.                         this.drag.updatedX = this.drag.start;
  831.                 }
  832.  
  833.                 this.animate(this.drag.updatedX);
  834.         };
  835.  
  836.         /**
  837.          * Handles the touchend/mouseup events.
  838.          * @protected
  839.          */
  840.         Owl.prototype.onDragEnd = function(event) {
  841.                 var compareTimes, distanceAbs, closest;
  842.  
  843.                 if (!this.state.isTouch) {
  844.                         return;
  845.                 }
  846.  
  847.                 if (event.type === 'mouseup') {
  848.                         this.$stage.removeClass('owl-grab');
  849.                 }
  850.  
  851.                 this.trigger('dragged');
  852.  
  853.                 // prevent links and images dragging;
  854.                 this.drag.targetEl.removeAttribute("draggable");
  855.  
  856.                 // remove drag event listeners
  857.  
  858.                 this.state.isTouch = false;
  859.                 this.state.isScrolling = false;
  860.                 this.state.isSwiping = false;
  861.  
  862.                 // to check
  863.                 if (this.drag.distance === 0 && this.state.inMotion !== true) {
  864.                         this.state.inMotion = false;
  865.                         return false;
  866.                 }
  867.  
  868.                 // prevent clicks while scrolling
  869.  
  870.                 this.drag.endTime = new Date().getTime();
  871.                 compareTimes = this.drag.endTime - this.drag.startTime;
  872.                 distanceAbs = Math.abs(this.drag.distance);
  873.  
  874.                 // to test
  875.                 if (distanceAbs > 3 || compareTimes > 300) {
  876.                         this.removeClick(this.drag.targetEl);
  877.                 }
  878.  
  879.                 closest = this.closest(this.drag.updatedX);
  880.  
  881.                 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
  882.                 this.current(closest);
  883.                 this.invalidate('position');
  884.                 this.update();
  885.  
  886.                 // if pullDrag is off then fire transitionEnd event manually when stick
  887.                 // to border
  888.                 if (!this.settings.pullDrag && this.drag.updatedX === this.coordinates(closest)) {
  889.                         this.transitionEnd();
  890.                 }
  891.  
  892.                 this.drag.distance = 0;
  893.  
  894.                 $(document).off('.owl.dragEvents');
  895.         };
  896.  
  897.         /**
  898.          * Attaches `preventClick` to disable link while swipping.
  899.          * @protected
  900.          * @param {HTMLElement} [target] - The target of the `click` event.
  901.          */
  902.         Owl.prototype.removeClick = function(target) {
  903.                 this.drag.targetEl = target;
  904.                 $(target).on('click.preventClick', this.e._preventClick);
  905.                 // to make sure click is removed:
  906.                 window.setTimeout(function() {
  907.                         $(target).off('click.preventClick');
  908.                 }, 300);
  909.         };
  910.  
  911.         /**
  912.          * Suppresses click event.
  913.          * @protected
  914.          * @param {Event} ev - The event arguments.
  915.          */
  916.         Owl.prototype.preventClick = function(ev) {
  917.                 if (ev.preventDefault) {
  918.                         ev.preventDefault();
  919.                 } else {
  920.                         ev.returnValue = false;
  921.                 }
  922.                 if (ev.stopPropagation) {
  923.                         ev.stopPropagation();
  924.                 }
  925.                 $(ev.target).off('click.preventClick');
  926.         };
  927.  
  928.         /**
  929.          * Catches stage position while animate (only CSS3).
  930.          * @protected
  931.          * @returns
  932.          */
  933.         Owl.prototype.getTransformProperty = function() {
  934.                 var transform, matrix3d;
  935.  
  936.                 transform = window.getComputedStyle(this.$stage.get(0), null).getPropertyValue(this.vendorName + 'transform');
  937.                 // var transform = this.$stage.css(this.vendorName + 'transform')
  938.                 transform = transform.replace(/matrix(3d)?\(|\)/g, '').split(',');
  939.                 matrix3d = transform.length === 16;
  940.  
  941.                 return matrix3d !== true ? transform[4] : transform[12];
  942.         };
  943.  
  944.         /**
  945.          * Gets absolute position of the closest item for a coordinate.
  946.          * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
  947.          * @protected
  948.          * @param {Number} coordinate - The coordinate in pixel.
  949.          * @return {Number} - The absolute position of the closest item.
  950.          */
  951.         Owl.prototype.closest = function(coordinate) {
  952.                 var position = -1, pull = 30, width = this.width(), coordinates = this.coordinates();
  953.  
  954.                 if (!this.settings.freeDrag) {
  955.                         // check closest item
  956.                         $.each(coordinates, $.proxy(function(index, value) {
  957.                                 if (coordinate > value - pull && coordinate < value + pull) {
  958.                                         position = index;
  959.                                 } else if (this.op(coordinate, '<', value)
  960.                                         && this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
  961.                                         position = this.state.direction === 'left' ? index + 1 : index;
  962.                                 }
  963.                                 return position === -1;
  964.                         }, this));
  965.                 }
  966.  
  967.                 if (!this.settings.loop) {
  968.                         // non loop boundries
  969.                         if (this.op(coordinate, '>', coordinates[this.minimum()])) {
  970.                                 position = coordinate = this.minimum();
  971.                         } else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
  972.                                 position = coordinate = this.maximum();
  973.                         }
  974.                 }
  975.  
  976.                 return position;
  977.         };
  978.  
  979.         /**
  980.          * Animates the stage.
  981.          * @public
  982.          * @param {Number} coordinate - The coordinate in pixels.
  983.          */
  984.         Owl.prototype.animate = function(coordinate) {
  985.                 this.trigger('translate');
  986.                 this.state.inMotion = this.speed() > 0;
  987.  
  988.                 if (this.support3d) {
  989.                         this.$stage.css({
  990.                                 transform: 'translate3d(' + coordinate + 'px' + ',0px, 0px)',
  991.                                 transition: (this.speed() / 1000) + 's'
  992.                         });
  993.                 } else if (this.state.isTouch) {
  994.                         this.$stage.css({
  995.                                 left: coordinate + 'px'
  996.                         });
  997.                 } else {
  998.                         this.$stage.animate({
  999.                                 left: coordinate
  1000.                         }, this.speed() / 1000, this.settings.fallbackEasing, $.proxy(function() {
  1001.                                 if (this.state.inMotion) {
  1002.                                         this.transitionEnd();
  1003.                                 }
  1004.                         }, this));
  1005.                 }
  1006.         };
  1007.  
  1008.         /**
  1009.          * Sets the absolute position of the current item.
  1010.          * @public
  1011.          * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
  1012.          * @returns {Number} - The absolute position of the current item.
  1013.          */
  1014.         Owl.prototype.current = function(position) {
  1015.                 if (position === undefined) {
  1016.                         return this._current;
  1017.                 }
  1018.  
  1019.                 if (this._items.length === 0) {
  1020.                         return undefined;
  1021.                 }
  1022.  
  1023.                 position = this.normalize(position);
  1024.  
  1025.                 if (this._current !== position) {
  1026.                         var event = this.trigger('change', { property: { name: 'position', value: position } });
  1027.  
  1028.                         if (event.data !== undefined) {
  1029.                                 position = this.normalize(event.data);
  1030.                         }
  1031.  
  1032.                         this._current = position;
  1033.  
  1034.                         this.invalidate('position');
  1035.  
  1036.                         this.trigger('changed', { property: { name: 'position', value: this._current } });
  1037.                 }
  1038.  
  1039.                 return this._current;
  1040.         };
  1041.  
  1042.         /**
  1043.          * Invalidates the given part of the update routine.
  1044.          * @param {String} part - The part to invalidate.
  1045.          */
  1046.         Owl.prototype.invalidate = function(part) {
  1047.                 this._invalidated[part] = true;
  1048.         }
  1049.  
  1050.         /**
  1051.          * Resets the absolute position of the current item.
  1052.          * @public
  1053.          * @param {Number} position - The absolute position of the new item.
  1054.          */
  1055.         Owl.prototype.reset = function(position) {
  1056.                 position = this.normalize(position);
  1057.  
  1058.                 if (position === undefined) {
  1059.                         return;
  1060.                 }
  1061.  
  1062.                 this._speed = 0;
  1063.                 this._current = position;
  1064.  
  1065.                 this.suppress([ 'translate', 'translated' ]);
  1066.  
  1067.                 this.animate(this.coordinates(position));
  1068.  
  1069.                 this.release([ 'translate', 'translated' ]);
  1070.         };
  1071.  
  1072.         /**
  1073.          * Normalizes an absolute or a relative position for an item.
  1074.          * @public
  1075.          * @param {Number} position - The absolute or relative position to normalize.
  1076.          * @param {Boolean} [relative=false] - Whether the given position is relative or not.
  1077.          * @returns {Number} - The normalized position.
  1078.          */
  1079.         Owl.prototype.normalize = function(position, relative) {
  1080.                 var n = (relative ? this._items.length : this._items.length + this._clones.length);
  1081.  
  1082.                 if (!$.isNumeric(position) || n < 1) {
  1083.                         return undefined;
  1084.                 }
  1085.  
  1086.                 if (this._clones.length) {
  1087.                         position = ((position % n) + n) % n;
  1088.                 } else {
  1089.                         position = Math.max(this.minimum(relative), Math.min(this.maximum(relative), position));
  1090.                 }
  1091.  
  1092.                 return position;
  1093.         };
  1094.  
  1095.         /**
  1096.          * Converts an absolute position for an item into a relative position.
  1097.          * @public
  1098.          * @param {Number} position - The absolute position to convert.
  1099.          * @returns {Number} - The converted position.
  1100.          */
  1101.         Owl.prototype.relative = function(position) {
  1102.                 position = this.normalize(position);
  1103.                 position = position - this._clones.length / 2;
  1104.                 return this.normalize(position, true);
  1105.         };
  1106.  
  1107.         /**
  1108.          * Gets the maximum position for an item.
  1109.          * @public
  1110.          * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
  1111.          * @returns {Number}
  1112.          */
  1113.         Owl.prototype.maximum = function(relative) {
  1114.                 var maximum, width, i = 0, coordinate,
  1115.                         settings = this.settings;
  1116.  
  1117.                 if (relative) {
  1118.                         return this._items.length - 1;
  1119.                 }
  1120.  
  1121.                 if (!settings.loop && settings.center) {
  1122.                         maximum = this._items.length - 1;
  1123.                 } else if (!settings.loop && !settings.center) {
  1124.                         maximum = this._items.length - settings.items;
  1125.                 } else if (settings.loop || settings.center) {
  1126.                         maximum = this._items.length + settings.items;
  1127.                 } else if (settings.autoWidth || settings.merge) {
  1128.                         revert = settings.rtl ? 1 : -1;
  1129.                         width = this.$stage.width() - this.$element.width();
  1130.                         while (coordinate = this.coordinates(i)) {
  1131.                                 if (coordinate * revert >= width) {
  1132.                                         break;
  1133.                                 }
  1134.                                 maximum = ++i;
  1135.                         }
  1136.                 } else {
  1137.                         throw 'Can not detect maximum absolute position.'
  1138.                 }
  1139.  
  1140.                 return maximum;
  1141.         };
  1142.  
  1143.         /**
  1144.          * Gets the minimum position for an item.
  1145.          * @public
  1146.          * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
  1147.          * @returns {Number}
  1148.          */
  1149.         Owl.prototype.minimum = function(relative) {
  1150.                 if (relative) {
  1151.                         return 0;
  1152.                 }
  1153.  
  1154.                 return this._clones.length / 2;
  1155.         };
  1156.  
  1157.         /**
  1158.          * Gets an item at the specified relative position.
  1159.          * @public
  1160.          * @param {Number} [position] - The relative position of the item.
  1161.          * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
  1162.          */
  1163.         Owl.prototype.items = function(position) {
  1164.                 if (position === undefined) {
  1165.                         return this._items.slice();
  1166.                 }
  1167.  
  1168.                 position = this.normalize(position, true);
  1169.                 return this._items[position];
  1170.         };
  1171.  
  1172.         /**
  1173.          * Gets an item at the specified relative position.
  1174.          * @public
  1175.          * @param {Number} [position] - The relative position of the item.
  1176.          * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
  1177.          */
  1178.         Owl.prototype.mergers = function(position) {
  1179.                 if (position === undefined) {
  1180.                         return this._mergers.slice();
  1181.                 }
  1182.  
  1183.                 position = this.normalize(position, true);
  1184.                 return this._mergers[position];
  1185.         };
  1186.  
  1187.         /**
  1188.          * Gets the absolute positions of clones for an item.
  1189.          * @public
  1190.          * @param {Number} [position] - The relative position of the item.
  1191.          * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
  1192.          */
  1193.         Owl.prototype.clones = function(position) {
  1194.                 var odd = this._clones.length / 2,
  1195.                         even = odd + this._items.length,
  1196.                         map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
  1197.  
  1198.                 if (position === undefined) {
  1199.                         return $.map(this._clones, function(v, i) { return map(i) });
  1200.                 }
  1201.  
  1202.                 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
  1203.         };
  1204.  
  1205.         /**
  1206.          * Sets the current animation speed.
  1207.          * @public
  1208.          * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
  1209.          * @returns {Number} - The current animation speed in milliseconds.
  1210.          */
  1211.         Owl.prototype.speed = function(speed) {
  1212.                 if (speed !== undefined) {
  1213.                         this._speed = speed;
  1214.                 }
  1215.  
  1216.                 return this._speed;
  1217.         };
  1218.  
  1219.         /**
  1220.          * Gets the coordinate of an item.
  1221.          * @todo The name of this method is missleanding.
  1222.          * @public
  1223.          * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
  1224.          * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
  1225.          */
  1226.         Owl.prototype.coordinates = function(position) {
  1227.                 var coordinate = null;
  1228.  
  1229.                 if (position === undefined) {
  1230.                         return $.map(this._coordinates, $.proxy(function(coordinate, index) {
  1231.                                 return this.coordinates(index);
  1232.                         }, this));
  1233.                 }
  1234.  
  1235.                 if (this.settings.center) {
  1236.                         coordinate = this._coordinates[position];
  1237.                         coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
  1238.                 } else {
  1239.                         coordinate = this._coordinates[position - 1] || 0;
  1240.                 }
  1241.  
  1242.                 return coordinate;
  1243.         };
  1244.  
  1245.         /**
  1246.          * Calculates the speed for a translation.
  1247.          * @protected
  1248.          * @param {Number} from - The absolute position of the start item.
  1249.          * @param {Number} to - The absolute position of the target item.
  1250.          * @param {Number} [factor=undefined] - The time factor in milliseconds.
  1251.          * @returns {Number} - The time in milliseconds for the translation.
  1252.          */
  1253.         Owl.prototype.duration = function(from, to, factor) {
  1254.                 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
  1255.         };
  1256.  
  1257.         /**
  1258.          * Slides to the specified item.
  1259.          * @public
  1260.          * @param {Number} position - The position of the item.
  1261.          * @param {Number} [speed] - The time in milliseconds for the transition.
  1262.          */
  1263.         Owl.prototype.to = function(position, speed) {
  1264.                 if (this.settings.loop) {
  1265.                         var distance = position - this.relative(this.current()),
  1266.                                 revert = this.current(),
  1267.                                 before = this.current(),
  1268.                                 after = this.current() + distance,
  1269.                                 direction = before - after < 0 ? true : false,
  1270.                                 items = this._clones.length + this._items.length;
  1271.  
  1272.                         if (after < this.settings.items && direction === false) {
  1273.                                 revert = before + this._items.length;
  1274.                                 this.reset(revert);
  1275.                         } else if (after >= items - this.settings.items && direction === true) {
  1276.                                 revert = before - this._items.length;
  1277.                                 this.reset(revert);
  1278.                         }
  1279.                         window.clearTimeout(this.e._goToLoop);
  1280.                         this.e._goToLoop = window.setTimeout($.proxy(function() {
  1281.                                 this.speed(this.duration(this.current(), revert + distance, speed));
  1282.                                 this.current(revert + distance);
  1283.                                 this.update();
  1284.                         }, this), 30);
  1285.                 } else {
  1286.                         this.speed(this.duration(this.current(), position, speed));
  1287.                         this.current(position);
  1288.                         this.update();
  1289.                 }
  1290.         };
  1291.  
  1292.         /**
  1293.          * Slides to the next item.
  1294.          * @public
  1295.          * @param {Number} [speed] - The time in milliseconds for the transition.
  1296.          */
  1297.         Owl.prototype.next = function(speed) {
  1298.                 speed = speed || false;
  1299.                 this.to(this.relative(this.current()) + 1, speed);
  1300.         };
  1301.  
  1302.         /**
  1303.          * Slides to the previous item.
  1304.          * @public
  1305.          * @param {Number} [speed] - The time in milliseconds for the transition.
  1306.          */
  1307.         Owl.prototype.prev = function(speed) {
  1308.                 speed = speed || false;
  1309.                 this.to(this.relative(this.current()) - 1, speed);
  1310.         };
  1311.  
  1312.         /**
  1313.          * Handles the end of an animation.
  1314.          * @protected
  1315.          * @param {Event} event - The event arguments.
  1316.          */
  1317.         Owl.prototype.transitionEnd = function(event) {
  1318.  
  1319.                 // if css2 animation then event object is undefined
  1320.                 if (event !== undefined) {
  1321.                         event.stopPropagation();
  1322.  
  1323.                         // Catch only owl-stage transitionEnd event
  1324.                         if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
  1325.                                 return false;
  1326.                         }
  1327.                 }
  1328.  
  1329.                 this.state.inMotion = false;
  1330.                 this.trigger('translated');
  1331.         };
  1332.  
  1333.         /**
  1334.          * Gets viewport width.
  1335.          * @protected
  1336.          * @return {Number} - The width in pixel.
  1337.          */
  1338.         Owl.prototype.viewport = function() {
  1339.                 var width;
  1340.                 if (this.options.responsiveBaseElement !== window) {
  1341.                         width = $(this.options.responsiveBaseElement).width();
  1342.                 } else if (window.innerWidth) {
  1343.                         width = window.innerWidth;
  1344.                 } else if (document.documentElement && document.documentElement.clientWidth) {
  1345.                         width = document.documentElement.clientWidth;
  1346.                 } else {
  1347.                         throw 'Can not detect viewport width.';
  1348.                 }
  1349.                 return width;
  1350.         };
  1351.  
  1352.         /**
  1353.          * Replaces the current content.
  1354.          * @public
  1355.          * @param {HTMLElement|jQuery|String} content - The new content.
  1356.          */
  1357.         Owl.prototype.replace = function(content) {
  1358.                 this.$stage.empty();
  1359.                 this._items = [];
  1360.  
  1361.                 if (content) {
  1362.                         content = (content instanceof jQuery) ? content : $(content);
  1363.                 }
  1364.  
  1365.                 if (this.settings.nestedItemSelector) {
  1366.                         content = content.find('.' + this.settings.nestedItemSelector);
  1367.                 }
  1368.  
  1369.                 content.filter(function() {
  1370.                         return this.nodeType === 1;
  1371.                 }).each($.proxy(function(index, item) {
  1372.                         item = this.prepare(item);
  1373.                         this.$stage.append(item);
  1374.                         this._items.push(item);
  1375.                         this._mergers.push(item.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
  1376.                 }, this));
  1377.  
  1378.                 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
  1379.  
  1380.                 this.invalidate('items');
  1381.         };
  1382.  
  1383.         /**
  1384.          * Adds an item.
  1385.          * @todo Use `item` instead of `content` for the event arguments.
  1386.          * @public
  1387.          * @param {HTMLElement|jQuery|String} content - The item content to add.
  1388.          * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
  1389.          */
  1390.         Owl.prototype.add = function(content, position) {
  1391.                 position = position === undefined ? this._items.length : this.normalize(position, true);
  1392.  
  1393.                 this.trigger('add', { content: content, position: position });
  1394.  
  1395.                 if (this._items.length === 0 || position === this._items.length) {
  1396.                         this.$stage.append(content);
  1397.                         this._items.push(content);
  1398.                         this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
  1399.                 } else {
  1400.                         this._items[position].before(content);
  1401.                         this._items.splice(position, 0, content);
  1402.                         this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
  1403.                 }
  1404.  
  1405.                 this.invalidate('items');
  1406.  
  1407.                 this.trigger('added', { content: content, position: position });
  1408.         };
  1409.  
  1410.         /**
  1411.          * Removes an item by its position.
  1412.          * @todo Use `item` instead of `content` for the event arguments.
  1413.          * @public
  1414.          * @param {Number} position - The relative position of the item to remove.
  1415.          */
  1416.         Owl.prototype.remove = function(position) {
  1417.                 position = this.normalize(position, true);
  1418.  
  1419.                 if (position === undefined) {
  1420.                         return;
  1421.                 }
  1422.  
  1423.                 this.trigger('remove', { content: this._items[position], position: position });
  1424.  
  1425.                 this._items[position].remove();
  1426.                 this._items.splice(position, 1);
  1427.                 this._mergers.splice(position, 1);
  1428.  
  1429.                 this.invalidate('items');
  1430.  
  1431.                 this.trigger('removed', { content: null, position: position });
  1432.         };
  1433.  
  1434.         /**
  1435.          * Adds triggerable events.
  1436.          * @protected
  1437.          */
  1438.         Owl.prototype.addTriggerableEvents = function() {
  1439.                 var handler = $.proxy(function(callback, event) {
  1440.                         return $.proxy(function(e) {
  1441.                                 if (e.relatedTarget !== this) {
  1442.                                         this.suppress([ event ]);
  1443.                                         callback.apply(this, [].slice.call(arguments, 1));
  1444.                                         this.release([ event ]);
  1445.                                 }
  1446.                         }, this);
  1447.                 }, this);
  1448.  
  1449.                 $.each({
  1450.                         'next': this.next,
  1451.                         'prev': this.prev,
  1452.                         'to': this.to,
  1453.                         'destroy': this.destroy,
  1454.                         'refresh': this.refresh,
  1455.                         'replace': this.replace,
  1456.                         'add': this.add,
  1457.                         'remove': this.remove
  1458.                 }, $.proxy(function(event, callback) {
  1459.                         this.$element.on(event + '.owl.carousel', handler(callback, event + '.owl.carousel'));
  1460.                 }, this));
  1461.  
  1462.         };
  1463.  
  1464.         /**
  1465.          * Watches the visibility of the carousel element.
  1466.          * @protected
  1467.          */
  1468.         Owl.prototype.watchVisibility = function() {
  1469.  
  1470.                 // test on zepto
  1471.                 if (!isElVisible(this.$element.get(0))) {
  1472.                         this.$element.addClass('owl-hidden');
  1473.                         window.clearInterval(this.e._checkVisibile);
  1474.                         this.e._checkVisibile = window.setInterval($.proxy(checkVisible, this), 500);
  1475.                 }
  1476.  
  1477.                 function isElVisible(el) {
  1478.                         return el.offsetWidth > 0 && el.offsetHeight > 0;
  1479.                 }
  1480.  
  1481.                 function checkVisible() {
  1482.                         if (isElVisible(this.$element.get(0))) {
  1483.                                 this.$element.removeClass('owl-hidden');
  1484.                                 this.refresh();
  1485.                                 window.clearInterval(this.e._checkVisibile);
  1486.                         }
  1487.                 }
  1488.         };
  1489.  
  1490.         /**
  1491.          * Preloads images with auto width.
  1492.          * @protected
  1493.          * @todo Still to test
  1494.          */
  1495.         Owl.prototype.preloadAutoWidthImages = function(imgs) {
  1496.                 var loaded, that, $el, img;
  1497.  
  1498.                 loaded = 0;
  1499.                 that = this;
  1500.                 imgs.each(function(i, el) {
  1501.                         $el = $(el);
  1502.                         img = new Image();
  1503.  
  1504.                         img.onload = function() {
  1505.                                 loaded++;
  1506.                                 $el.attr('src', img.src);
  1507.                                 $el.css('opacity', 1);
  1508.                                 if (loaded >= imgs.length) {
  1509.                                         that.state.imagesLoaded = true;
  1510.                                         that.initialize();
  1511.                                 }
  1512.                         };
  1513.  
  1514.                         img.src = $el.attr('src') || $el.attr('data-src') || $el.attr('data-src-retina');
  1515.                 });
  1516.         };
  1517.  
  1518.         /**
  1519.          * Destroys the carousel.
  1520.          * @public
  1521.          */
  1522.         Owl.prototype.destroy = function() {
  1523.  
  1524.                 if (this.$element.hasClass(this.settings.themeClass)) {
  1525.                         this.$element.removeClass(this.settings.themeClass);
  1526.                 }
  1527.  
  1528.                 if (this.settings.responsive !== false) {
  1529.                         $(window).off('resize.owl.carousel');
  1530.                 }
  1531.  
  1532.                 if (this.transitionEndVendor) {
  1533.                         this.off(this.$stage.get(0), this.transitionEndVendor, this.e._transitionEnd);
  1534.                 }
  1535.  
  1536.                 for ( var i in this._plugins) {
  1537.                         this._plugins[i].destroy();
  1538.                 }
  1539.  
  1540.                 if (this.settings.mouseDrag || this.settings.touchDrag) {
  1541.                         this.$stage.off('mousedown touchstart touchcancel');
  1542.                         $(document).off('.owl.dragEvents');
  1543.                         this.$stage.get(0).onselectstart = function() {};
  1544.                         this.$stage.off('dragstart', function() { return false });
  1545.                 }
  1546.  
  1547.                 // remove event handlers in the ".owl.carousel" namespace
  1548.                 this.$element.off('.owl');
  1549.  
  1550.                 this.$stage.children('.cloned').remove();
  1551.                 this.e = null;
  1552.                 this.$element.removeData('owlCarousel');
  1553.  
  1554.                 this.$stage.children().contents().unwrap();
  1555.                 this.$stage.children().unwrap();
  1556.                 this.$stage.unwrap();
  1557.         };
  1558.  
  1559.         /**
  1560.          * Operators to calculate right-to-left and left-to-right.
  1561.          * @protected
  1562.          * @param {Number} [a] - The left side operand.
  1563.          * @param {String} [o] - The operator.
  1564.          * @param {Number} [b] - The right side operand.
  1565.          */
  1566.         Owl.prototype.op = function(a, o, b) {
  1567.                 var rtl = this.settings.rtl;
  1568.                 switch (o) {
  1569.                         case '<':
  1570.                                 return rtl ? a > b : a < b;
  1571.                         case '>':
  1572.                                 return rtl ? a < b : a > b;
  1573.                         case '>=':
  1574.                                 return rtl ? a <= b : a >= b;
  1575.                         case '<=':
  1576.                                 return rtl ? a >= b : a <= b;
  1577.                         default:
  1578.                                 break;
  1579.                 }
  1580.         };
  1581.  
  1582.         /**
  1583.          * Attaches to an internal event.
  1584.          * @protected
  1585.          * @param {HTMLElement} element - The event source.
  1586.          * @param {String} event - The event name.
  1587.          * @param {Function} listener - The event handler to attach.
  1588.          * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
  1589.          */
  1590.         Owl.prototype.on = function(element, event, listener, capture) {
  1591.                 if (element.addEventListener) {
  1592.                         element.addEventListener(event, listener, capture);
  1593.                 } else if (element.attachEvent) {
  1594.                         element.attachEvent('on' + event, listener);
  1595.                 }
  1596.         };
  1597.  
  1598.         /**
  1599.          * Detaches from an internal event.
  1600.          * @protected
  1601.          * @param {HTMLElement} element - The event source.
  1602.          * @param {String} event - The event name.
  1603.          * @param {Function} listener - The attached event handler to detach.
  1604.          * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
  1605.          */
  1606.         Owl.prototype.off = function(element, event, listener, capture) {
  1607.                 if (element.removeEventListener) {
  1608.                         element.removeEventListener(event, listener, capture);
  1609.                 } else if (element.detachEvent) {
  1610.                         element.detachEvent('on' + event, listener);
  1611.                 }
  1612.         };
  1613.  
  1614.         /**
  1615.          * Triggers an public event.
  1616.          * @protected
  1617.          * @param {String} name - The event name.
  1618.          * @param {*} [data=null] - The event data.
  1619.          * @param {String} [namespace=.owl.carousel] - The event namespace.
  1620.          * @returns {Event} - The event arguments.
  1621.          */
  1622.         Owl.prototype.trigger = function(name, data, namespace) {
  1623.                 var status = {
  1624.                         item: { count: this._items.length, index: this.current() }
  1625.                 }, handler = $.camelCase(
  1626.                         $.grep([ 'on', name, namespace ], function(v) { return v })
  1627.                                 .join('-').toLowerCase()
  1628.                 ), event = $.Event(
  1629.                         [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
  1630.                         $.extend({ relatedTarget: this }, status, data)
  1631.                 );
  1632.  
  1633.                 if (!this._supress[name]) {
  1634.                         $.each(this._plugins, function(name, plugin) {
  1635.                                 if (plugin.onTrigger) {
  1636.                                         plugin.onTrigger(event);
  1637.                                 }
  1638.                         });
  1639.  
  1640.                         this.$element.trigger(event);
  1641.  
  1642.                         if (this.settings && typeof this.settings[handler] === 'function') {
  1643.                                 this.settings[handler].apply(this, event);
  1644.                         }
  1645.                 }
  1646.  
  1647.                 return event;
  1648.         };
  1649.  
  1650.         /**
  1651.          * Suppresses events.
  1652.          * @protected
  1653.          * @param {Array.<String>} events - The events to suppress.
  1654.          */
  1655.         Owl.prototype.suppress = function(events) {
  1656.                 $.each(events, $.proxy(function(index, event) {
  1657.                         this._supress[event] = true;
  1658.                 }, this));
  1659.         }
  1660.  
  1661.         /**
  1662.          * Releases suppressed events.
  1663.          * @protected
  1664.          * @param {Array.<String>} events - The events to release.
  1665.          */
  1666.         Owl.prototype.release = function(events) {
  1667.                 $.each(events, $.proxy(function(index, event) {
  1668.                         delete this._supress[event];
  1669.                 }, this));
  1670.         }
  1671.  
  1672.         /**
  1673.          * Checks the availability of some browser features.
  1674.          * @protected
  1675.          */
  1676.         Owl.prototype.browserSupport = function() {
  1677.                 this.support3d = isPerspective();
  1678.  
  1679.                 if (this.support3d) {
  1680.                         this.transformVendor = isTransform();
  1681.  
  1682.                         // take transitionend event name by detecting transition
  1683.                         var endVendors = [ 'transitionend', 'webkitTransitionEnd', 'transitionend', 'oTransitionEnd' ];
  1684.                         this.transitionEndVendor = endVendors[isTransition()];
  1685.  
  1686.                         // take vendor name from transform name
  1687.                         this.vendorName = this.transformVendor.replace(/Transform/i, '');
  1688.                         this.vendorName = this.vendorName !== '' ? '-' + this.vendorName.toLowerCase() + '-' : '';
  1689.                 }
  1690.  
  1691.                 this.state.orientation = window.orientation;
  1692.         };
  1693.  
  1694.         /**
  1695.          * Get touch/drag coordinats.
  1696.          * @private
  1697.          * @param {event} - mousedown/touchstart event
  1698.          * @returns {object} - Contains X and Y of current mouse/touch position
  1699.          */
  1700.  
  1701.         function getTouches(event) {
  1702.                 if (event.touches !== undefined) {
  1703.                         return {
  1704.                                 x: event.touches[0].pageX,
  1705.                                 y: event.touches[0].pageY
  1706.                         };
  1707.                 }
  1708.  
  1709.                 if (event.touches === undefined) {
  1710.                         if (event.pageX !== undefined) {
  1711.                                 return {
  1712.                                         x: event.pageX,
  1713.                                         y: event.pageY
  1714.                                 };
  1715.                         }
  1716.  
  1717.                 if (event.pageX === undefined) {
  1718.                         return {
  1719.                                         x: event.clientX,
  1720.                                         y: event.clientY
  1721.                                 };
  1722.                         }
  1723.                 }
  1724.         }
  1725.  
  1726.         /**
  1727.          * Checks for CSS support.
  1728.          * @private
  1729.          * @param {Array} array - The CSS properties to check for.
  1730.          * @returns {Array} - Contains the supported CSS property name and its index or `false`.
  1731.          */
  1732.         function isStyleSupported(array) {
  1733.                 var p, s, fake = document.createElement('div'), list = array;
  1734.                 for (p in list) {
  1735.                         s = list[p];
  1736.                         if (typeof fake.style[s] !== 'undefined') {
  1737.                                 fake = null;
  1738.                                 return [ s, p ];
  1739.                         }
  1740.                 }
  1741.                 return [ false ];
  1742.         }
  1743.  
  1744.         /**
  1745.          * Checks for CSS transition support.
  1746.          * @private
  1747.          * @todo Realy bad design
  1748.          * @returns {Number}
  1749.          */
  1750.         function isTransition() {
  1751.                 return isStyleSupported([ 'transition', 'WebkitTransition', 'MozTransition', 'OTransition' ])[1];
  1752.         }
  1753.  
  1754.         /**
  1755.          * Checks for CSS transform support.
  1756.          * @private
  1757.          * @returns {String} The supported property name or false.
  1758.          */
  1759.         function isTransform() {
  1760.                 return isStyleSupported([ 'transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ])[0];
  1761.         }
  1762.  
  1763.         /**
  1764.          * Checks for CSS perspective support.
  1765.          * @private
  1766.          * @returns {String} The supported property name or false.
  1767.          */
  1768.         function isPerspective() {
  1769.                 return isStyleSupported([ 'perspective', 'webkitPerspective', 'MozPerspective', 'OPerspective', 'MsPerspective' ])[0];
  1770.         }
  1771.  
  1772.         /**
  1773.          * Checks wether touch is supported or not.
  1774.          * @private
  1775.          * @returns {Boolean}
  1776.          */
  1777.         function isTouchSupport() {
  1778.                 return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);
  1779.         }
  1780.  
  1781.         /**
  1782.          * Checks wether touch is supported or not for IE.
  1783.          * @private
  1784.          * @returns {Boolean}
  1785.          */
  1786.         function isTouchSupportIE() {
  1787.                 return window.navigator.msPointerEnabled;
  1788.         }
  1789.  
  1790.         /**
  1791.          * The jQuery Plugin for the Owl Carousel
  1792.          * @public
  1793.          */
  1794.         $.fn.owlCarousel = function(options) {
  1795.                 return this.each(function() {
  1796.                         if (!$(this).data('owlCarousel')) {
  1797.                                 $(this).data('owlCarousel', new Owl(this, options));
  1798.                         }
  1799.                 });
  1800.         };
  1801.  
  1802.         /**
  1803.          * The constructor for the jQuery Plugin
  1804.          * @public
  1805.          */
  1806.         $.fn.owlCarousel.Constructor = Owl;
  1807.  
  1808. })(window.Zepto || window.jQuery, window, document);
  1809.  
  1810. /**
  1811.  * Lazy Plugin
  1812.  * @version 2.0.0
  1813.  * @author Bartosz Wojciechowski
  1814.  * @license The MIT License (MIT)
  1815.  */
  1816. ;(function($, window, document, undefined) {
  1817.  
  1818.         /**
  1819.          * Creates the lazy plugin.
  1820.          * @class The Lazy Plugin
  1821.          * @param {Owl} carousel - The Owl Carousel
  1822.          */
  1823.         var Lazy = function(carousel) {
  1824.  
  1825.                 /**
  1826.                  * Reference to the core.
  1827.                  * @protected
  1828.                  * @type {Owl}
  1829.                  */
  1830.                 this._core = carousel;
  1831.  
  1832.                 /**
  1833.                  * Already loaded items.
  1834.                  * @protected
  1835.                  * @type {Array.<jQuery>}
  1836.                  */
  1837.                 this._loaded = [];
  1838.  
  1839.                 /**
  1840.                  * Event handlers.
  1841.                  * @protected
  1842.                  * @type {Object}
  1843.                  */
  1844.                 this._handlers = {
  1845.                         'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
  1846.                                 if (!e.namespace) {
  1847.                                         return;
  1848.                                 }
  1849.  
  1850.                                 if (!this._core.settings || !this._core.settings.lazyLoad) {
  1851.                                         return;
  1852.                                 }
  1853.  
  1854.                                 if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
  1855.                                         var settings = this._core.settings,
  1856.                                                 n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
  1857.                                                 i = ((settings.center && n * -1) || 0),
  1858.                                                 position = ((e.property && e.property.value) || this._core.current()) + i,
  1859.                                                 clones = this._core.clones().length,
  1860.                                                 load = $.proxy(function(i, v) { this.load(v) }, this);
  1861.  
  1862.                                         while (i++ < n) {
  1863.                                                 this.load(clones / 2 + this._core.relative(position));
  1864.                                                 clones && $.each(this._core.clones(this._core.relative(position++)), load);
  1865.                                         }
  1866.                                 }
  1867.                         }, this)
  1868.                 };
  1869.  
  1870.                 // set the default options
  1871.                 this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
  1872.  
  1873.                 // register event handler
  1874.                 this._core.$element.on(this._handlers);
  1875.         }
  1876.  
  1877.         /**
  1878.          * Default options.
  1879.          * @public
  1880.          */
  1881.         Lazy.Defaults = {
  1882.                 lazyLoad: false
  1883.         }
  1884.  
  1885.         /**
  1886.          * Loads all resources of an item at the specified position.
  1887.          * @param {Number} position - The absolute position of the item.
  1888.          * @protected
  1889.          */
  1890.         Lazy.prototype.load = function(position) {
  1891.                 var $item = this._core.$stage.children().eq(position),
  1892.                         $elements = $item && $item.find('.owl-lazy');
  1893.  
  1894.                 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
  1895.                         return;
  1896.                 }
  1897.  
  1898.                 $elements.each($.proxy(function(index, element) {
  1899.                         var $element = $(element), image,
  1900.                                 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
  1901.  
  1902.                         this._core.trigger('load', { element: $element, url: url }, 'lazy');
  1903.  
  1904.                         if ($element.is('img')) {
  1905.                                 $element.one('load.owl.lazy', $.proxy(function() {
  1906.                                         $element.css('opacity', 1);
  1907.                                         this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
  1908.                                 }, this)).attr('src', url);
  1909.                         } else {
  1910.                                 image = new Image();
  1911.                                 image.onload = $.proxy(function() {
  1912.                                         $element.css({
  1913.                                                 'background-image': 'url(' + url + ')',
  1914.                                                 'opacity': '1'
  1915.                                         });
  1916.                                         this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
  1917.                                 }, this);
  1918.                                 image.src = url;
  1919.                         }
  1920.                 }, this));
  1921.  
  1922.                 this._loaded.push($item.get(0));
  1923.         }
  1924.  
  1925.         /**
  1926.          * Destroys the plugin.
  1927.          * @public
  1928.          */
  1929.         Lazy.prototype.destroy = function() {
  1930.                 var handler, property;
  1931.  
  1932.                 for (handler in this.handlers) {
  1933.                         this._core.$element.off(handler, this.handlers[handler]);
  1934.                 }
  1935.                 for (property in Object.getOwnPropertyNames(this)) {
  1936.                         typeof this[property] != 'function' && (this[property] = null);
  1937.                 }
  1938.         }
  1939.  
  1940.         $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
  1941.  
  1942. })(window.Zepto || window.jQuery, window, document);
  1943.  
  1944. /**
  1945.  * AutoHeight Plugin
  1946.  * @version 2.0.0
  1947.  * @author Bartosz Wojciechowski
  1948.  * @license The MIT License (MIT)
  1949.  */
  1950. ;(function($, window, document, undefined) {
  1951.  
  1952.         /**
  1953.          * Creates the auto height plugin.
  1954.          * @class The Auto Height Plugin
  1955.          * @param {Owl} carousel - The Owl Carousel
  1956.          */
  1957.         var AutoHeight = function(carousel) {
  1958.                 /**
  1959.                  * Reference to the core.
  1960.                  * @protected
  1961.                  * @type {Owl}
  1962.                  */
  1963.                 this._core = carousel;
  1964.  
  1965.                 /**
  1966.                  * All event handlers.
  1967.                  * @protected
  1968.                  * @type {Object}
  1969.                  */
  1970.                 this._handlers = {
  1971.                         'initialized.owl.carousel': $.proxy(function() {
  1972.                                 if (this._core.settings.autoHeight) {
  1973.                                         this.update();
  1974.                                 }
  1975.                         }, this),
  1976.                         'changed.owl.carousel': $.proxy(function(e) {
  1977.                                 if (this._core.settings.autoHeight && e.property.name == 'position'){
  1978.                                         this.update();
  1979.                                 }
  1980.                         }, this),
  1981.                         'loaded.owl.lazy': $.proxy(function(e) {
  1982.                                 if (this._core.settings.autoHeight && e.element.closest('.' + this._core.settings.itemClass)
  1983.                                         === this._core.$stage.children().eq(this._core.current())) {
  1984.                                         this.update();
  1985.                                 }
  1986.                         }, this)
  1987.                 };
  1988.  
  1989.                 // set default options
  1990.                 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
  1991.  
  1992.                 // register event handlers
  1993.                 this._core.$element.on(this._handlers);
  1994.         };
  1995.  
  1996.         /**
  1997.          * Default options.
  1998.          * @public
  1999.          */
  2000.         AutoHeight.Defaults = {
  2001.                 autoHeight: false,
  2002.                 autoHeightClass: 'owl-height'
  2003.         };
  2004.  
  2005.         /**
  2006.          * Updates the view.
  2007.          */
  2008.         AutoHeight.prototype.update = function() {
  2009.                 this._core.$stage.parent()
  2010.                         .height(this._core.$stage.children().eq(this._core.current()).height())
  2011.                         .addClass(this._core.settings.autoHeightClass);
  2012.         };
  2013.  
  2014.         AutoHeight.prototype.destroy = function() {
  2015.                 var handler, property;
  2016.  
  2017.                 for (handler in this._handlers) {
  2018.                         this._core.$element.off(handler, this._handlers[handler]);
  2019.                 }
  2020.                 for (property in Object.getOwnPropertyNames(this)) {
  2021.                         typeof this[property] != 'function' && (this[property] = null);
  2022.                 }
  2023.         };
  2024.  
  2025.         $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
  2026.  
  2027. })(window.Zepto || window.jQuery, window, document);
  2028.  
  2029. /**
  2030.  * Video Plugin
  2031.  * @version 2.0.0
  2032.  * @author Bartosz Wojciechowski
  2033.  * @license The MIT License (MIT)
  2034.  */
  2035. ;(function($, window, document, undefined) {
  2036.  
  2037.         /**
  2038.          * Creates the video plugin.
  2039.          * @class The Video Plugin
  2040.          * @param {Owl} carousel - The Owl Carousel
  2041.          */
  2042.         var Video = function(carousel) {
  2043.                 /**
  2044.                  * Reference to the core.
  2045.                  * @protected
  2046.                  * @type {Owl}
  2047.                  */
  2048.                 this._core = carousel;
  2049.  
  2050.                 /**
  2051.                  * Cache all video URLs.
  2052.                  * @protected
  2053.                  * @type {Object}
  2054.                  */
  2055.                 this._videos = {};
  2056.  
  2057.                 /**
  2058.                  * Current playing item.
  2059.                  * @protected
  2060.                  * @type {jQuery}
  2061.                  */
  2062.                 this._playing = null;
  2063.  
  2064.                 /**
  2065.                  * Whether this is in fullscreen or not.
  2066.                  * @protected
  2067.                  * @type {Boolean}
  2068.                  */
  2069.                 this._fullscreen = false;
  2070.  
  2071.                 /**
  2072.                  * All event handlers.
  2073.                  * @protected
  2074.                  * @type {Object}
  2075.                  */
  2076.                 this._handlers = {
  2077.                         'resize.owl.carousel': $.proxy(function(e) {
  2078.                                 if (this._core.settings.video && !this.isInFullScreen()) {
  2079.                                         e.preventDefault();
  2080.                                 }
  2081.                         }, this),
  2082.                         'refresh.owl.carousel changed.owl.carousel': $.proxy(function(e) {
  2083.                                 if (this._playing) {
  2084.                                         this.stop();
  2085.                                 }
  2086.                         }, this),
  2087.                         'prepared.owl.carousel': $.proxy(function(e) {
  2088.                                 var $element = $(e.content).find('.owl-video');
  2089.                                 if ($element.length) {
  2090.                                         $element.css('display', 'none');
  2091.                                         this.fetch($element, $(e.content));
  2092.                                 }
  2093.                         }, this)
  2094.                 };
  2095.  
  2096.                 // set default options
  2097.                 this._core.options = $.extend({}, Video.Defaults, this._core.options);
  2098.  
  2099.                 // register event handlers
  2100.                 this._core.$element.on(this._handlers);
  2101.  
  2102.                 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
  2103.                         this.play(e);
  2104.                 }, this));
  2105.         };
  2106.  
  2107.         /**
  2108.          * Default options.
  2109.          * @public
  2110.          */
  2111.         Video.Defaults = {
  2112.                 video: false,
  2113.                 videoHeight: false,
  2114.                 videoWidth: false
  2115.         };
  2116.  
  2117.         /**
  2118.          * Gets the video ID and the type (YouTube/Vimeo only).
  2119.          * @protected
  2120.          * @param {jQuery} target - The target containing the video data.
  2121.          * @param {jQuery} item - The item containing the video.
  2122.          */
  2123.         Video.prototype.fetch = function(target, item) {
  2124.  
  2125.                 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
  2126.                         id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
  2127.                         width = target.attr('data-width') || this._core.settings.videoWidth,
  2128.                         height = target.attr('data-height') || this._core.settings.videoHeight,
  2129.                         url = target.attr('href');
  2130.  
  2131.                 if (url) {
  2132.                         id = url.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
  2133.  
  2134.                         if (id[3].indexOf('youtu') > -1) {
  2135.                                 type = 'youtube';
  2136.                         } else if (id[3].indexOf('vimeo') > -1) {
  2137.                                 type = 'vimeo';
  2138.                         } else {
  2139.                                 throw new Error('Video URL not supported.');
  2140.                         }
  2141.                         id = id[6];
  2142.                 } else {
  2143.                         throw new Error('Missing video URL.');
  2144.                 }
  2145.  
  2146.                 this._videos[url] = {
  2147.                         type: type,
  2148.                         id: id,
  2149.                         width: width,
  2150.                         height: height
  2151.                 };
  2152.  
  2153.                 item.attr('data-video', url);
  2154.  
  2155.                 this.thumbnail(target, this._videos[url]);
  2156.         };
  2157.  
  2158.         /**
  2159.          * Creates video thumbnail.
  2160.          * @protected
  2161.          * @param {jQuery} target - The target containing the video data.
  2162.          * @param {Object} info - The video info object.
  2163.          * @see `fetch`
  2164.          */
  2165.         Video.prototype.thumbnail = function(target, video) {
  2166.  
  2167.                 var tnLink,
  2168.                         icon,
  2169.                         path,
  2170.                         dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
  2171.                         customTn = target.find('img'),
  2172.                         srcType = 'src',
  2173.                         lazyClass = '',
  2174.                         settings = this._core.settings,
  2175.                         create = function(path) {
  2176.                                 icon = '<div class="owl-video-play-icon"></div>';
  2177.  
  2178.                                 if (settings.lazyLoad) {
  2179.                                         tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
  2180.                                 } else {
  2181.                                         tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
  2182.                                 }
  2183.                                 target.after(tnLink);
  2184.                                 target.after(icon);
  2185.                         };
  2186.  
  2187.                 // wrap video content into owl-video-wrapper div
  2188.                 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
  2189.  
  2190.                 if (this._core.settings.lazyLoad) {
  2191.                         srcType = 'data-src';
  2192.                         lazyClass = 'owl-lazy';
  2193.                 }
  2194.  
  2195.                 // custom thumbnail
  2196.                 if (customTn.length) {
  2197.                         create(customTn.attr(srcType));
  2198.                         customTn.remove();
  2199.                         return false;
  2200.                 }
  2201.  
  2202.                 if (video.type === 'youtube') {
  2203.                         path = "http://img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
  2204.                         create(path);
  2205.                 } else if (video.type === 'vimeo') {
  2206.                         $.ajax({
  2207.                                 type: 'GET',
  2208.                                 url: 'http://vimeo.com/api/v2/video/' + video.id + '.json',
  2209.                                 jsonp: 'callback',
  2210.                                 dataType: 'jsonp',
  2211.                                 success: function(data) {
  2212.                                         path = data[0].thumbnail_large;
  2213.                                         create(path);
  2214.                                 }
  2215.                         });
  2216.                 }
  2217.         };
  2218.  
  2219.         /**
  2220.          * Stops the current video.
  2221.          * @public
  2222.          */
  2223.         Video.prototype.stop = function() {
  2224.                 this._core.trigger('stop', null, 'video');
  2225.                 this._playing.find('.owl-video-frame').remove();
  2226.                 this._playing.removeClass('owl-video-playing');
  2227.                 this._playing = null;
  2228.         };
  2229.  
  2230.         /**
  2231.          * Starts the current video.
  2232.          * @public
  2233.          * @param {Event} ev - The event arguments.
  2234.          */
  2235.         Video.prototype.play = function(ev) {
  2236.                 this._core.trigger('play', null, 'video');
  2237.  
  2238.                 if (this._playing) {
  2239.                         this.stop();
  2240.                 }
  2241.  
  2242.                 var target = $(ev.target || ev.srcElement),
  2243.                         item = target.closest('.' + this._core.settings.itemClass),
  2244.                         video = this._videos[item.attr('data-video')],
  2245.                         width = video.width || '100%',
  2246.                         height = video.height || this._core.$stage.height(),
  2247.                         html, wrap;
  2248.  
  2249.                 if (video.type === 'youtube') {
  2250.                         html = '<iframe width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/'
  2251.                                 + video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
  2252.                 } else if (video.type === 'vimeo') {
  2253.                         html = '<iframe src="http://player.vimeo.com/video/' + video.id + '?autoplay=1" width="' + width
  2254.                                 + '" height="' + height
  2255.                                 + '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
  2256.                 }
  2257.  
  2258.                 item.addClass('owl-video-playing');
  2259.                 this._playing = item;
  2260.  
  2261.                 wrap = $('<div style="height:' + height + 'px; width:' + width + 'px" class="owl-video-frame">'
  2262.                         + html + '</div>');
  2263.                 target.after(wrap);
  2264.         };
  2265.  
  2266.         /**
  2267.          * Checks whether an video is currently in full screen mode or not.
  2268.          * @todo Bad style because looks like a readonly method but changes members.
  2269.          * @protected
  2270.          * @returns {Boolean}
  2271.          */
  2272.         Video.prototype.isInFullScreen = function() {
  2273.  
  2274.                 // if Vimeo Fullscreen mode
  2275.                 var element = document.fullscreenElement || document.mozFullScreenElement
  2276.                         || document.webkitFullscreenElement;
  2277.  
  2278.                 if (element && $(element).parent().hasClass('owl-video-frame')) {
  2279.                         this._core.speed(0);
  2280.                         this._fullscreen = true;
  2281.                 }
  2282.  
  2283.                 if (element && this._fullscreen && this._playing) {
  2284.                         return false;
  2285.                 }
  2286.  
  2287.                 // comming back from fullscreen
  2288.                 if (this._fullscreen) {
  2289.                         this._fullscreen = false;
  2290.                         return false;
  2291.                 }
  2292.  
  2293.                 // check full screen mode and window orientation
  2294.                 if (this._playing) {
  2295.                         if (this._core.state.orientation !== window.orientation) {
  2296.                                 this._core.state.orientation = window.orientation;
  2297.                                 return false;
  2298.                         }
  2299.                 }
  2300.  
  2301.                 return true;
  2302.         };
  2303.  
  2304.         /**
  2305.          * Destroys the plugin.
  2306.          */
  2307.         Video.prototype.destroy = function() {
  2308.                 var handler, property;
  2309.  
  2310.                 this._core.$element.off('click.owl.video');
  2311.  
  2312.                 for (handler in this._handlers) {
  2313.                         this._core.$element.off(handler, this._handlers[handler]);
  2314.                 }
  2315.                 for (property in Object.getOwnPropertyNames(this)) {
  2316.                         typeof this[property] != 'function' && (this[property] = null);
  2317.                 }
  2318.         };
  2319.  
  2320.         $.fn.owlCarousel.Constructor.Plugins.Video = Video;
  2321.  
  2322. })(window.Zepto || window.jQuery, window, document);
  2323.  
  2324. /**
  2325.  * Animate Plugin
  2326.  * @version 2.0.0
  2327.  * @author Bartosz Wojciechowski
  2328.  * @license The MIT License (MIT)
  2329.  */
  2330. ;(function($, window, document, undefined) {
  2331.  
  2332.         /**
  2333.          * Creates the animate plugin.
  2334.          * @class The Navigation Plugin
  2335.          * @param {Owl} scope - The Owl Carousel
  2336.          */
  2337.         var Animate = function(scope) {
  2338.                 this.core = scope;
  2339.                 this.core.options = $.extend({}, Animate.Defaults, this.core.options);
  2340.                 this.swapping = true;
  2341.                 this.previous = undefined;
  2342.                 this.next = undefined;
  2343.  
  2344.                 this.handlers = {
  2345.                         'change.owl.carousel': $.proxy(function(e) {
  2346.                                 if (e.property.name == 'position') {
  2347.                                         this.previous = this.core.current();
  2348.                                         this.next = e.property.value;
  2349.                                 }
  2350.                         }, this),
  2351.                         'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
  2352.                                 this.swapping = e.type == 'translated';
  2353.                         }, this),
  2354.                         'translate.owl.carousel': $.proxy(function(e) {
  2355.                                 if (this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
  2356.                                         this.swap();
  2357.                                 }
  2358.                         }, this)
  2359.                 };
  2360.  
  2361.                 this.core.$element.on(this.handlers);
  2362.         };
  2363.  
  2364.         /**
  2365.          * Default options.
  2366.          * @public
  2367.          */
  2368.         Animate.Defaults = {
  2369.                 animateOut: false,
  2370.                 animateIn: false
  2371.         };
  2372.  
  2373.         /**
  2374.          * Toggles the animation classes whenever an translations starts.
  2375.          * @protected
  2376.          * @returns {Boolean|undefined}
  2377.          */
  2378.         Animate.prototype.swap = function() {
  2379.  
  2380.                 if (this.core.settings.items !== 1 || !this.core.support3d) {
  2381.                         return;
  2382.                 }
  2383.  
  2384.                 this.core.speed(0);
  2385.  
  2386.                 var left,
  2387.                         clear = $.proxy(this.clear, this),
  2388.                         previous = this.core.$stage.children().eq(this.previous),
  2389.                         next = this.core.$stage.children().eq(this.next),
  2390.                         incoming = this.core.settings.animateIn,
  2391.                         outgoing = this.core.settings.animateOut;
  2392.  
  2393.                 if (this.core.current() === this.previous) {
  2394.                         return;
  2395.                 }
  2396.  
  2397.                 if (outgoing) {
  2398.                         left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
  2399.                         previous.css( { 'left': left + 'px' } )
  2400.                                 .addClass('animated owl-animated-out')
  2401.                                 .addClass(outgoing)
  2402.                                 .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', clear);
  2403.                 }
  2404.  
  2405.                 if (incoming) {
  2406.                         next.addClass('animated owl-animated-in')
  2407.                                 .addClass(incoming)
  2408.                                 .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', clear);
  2409.                 }
  2410.         };
  2411.  
  2412.         Animate.prototype.clear = function(e) {
  2413.                 $(e.target).css( { 'left': '' } )
  2414.                         .removeClass('animated owl-animated-out owl-animated-in')
  2415.                         .removeClass(this.core.settings.animateIn)
  2416.                         .removeClass(this.core.settings.animateOut);
  2417.                 this.core.transitionEnd();
  2418.         }
  2419.  
  2420.         /**
  2421.          * Destroys the plugin.
  2422.          * @public
  2423.          */
  2424.         Animate.prototype.destroy = function() {
  2425.                 var handler, property;
  2426.  
  2427.                 for (handler in this.handlers) {
  2428.                         this.core.$element.off(handler, this.handlers[handler]);
  2429.                 }
  2430.                 for (property in Object.getOwnPropertyNames(this)) {
  2431.                         typeof this[property] != 'function' && (this[property] = null);
  2432.                 }
  2433.         };
  2434.  
  2435.         $.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
  2436.  
  2437. })(window.Zepto || window.jQuery, window, document);
  2438.  
  2439. /**
  2440.  * Autoplay Plugin
  2441.  * @version 2.0.0
  2442.  * @author Bartosz Wojciechowski
  2443.  * @license The MIT License (MIT)
  2444.  */
  2445. ;(function($, window, document, undefined) {
  2446.  
  2447.         /**
  2448.          * Creates the autoplay plugin.
  2449.          * @class The Autoplay Plugin
  2450.          * @param {Owl} scope - The Owl Carousel
  2451.          */
  2452.         var Autoplay = function(scope) {
  2453.                 this.core = scope;
  2454.                 this.core.options = $.extend({}, Autoplay.Defaults, this.core.options);
  2455.  
  2456.                 this.handlers = {
  2457.                         'translated.owl.carousel refreshed.owl.carousel': $.proxy(function() {
  2458.                                 this.autoplay();
  2459.                         }, this),
  2460.                         'play.owl.autoplay': $.proxy(function(e, t, s) {
  2461.                                 this.play(t, s);
  2462.                         }, this),
  2463.                         'stop.owl.autoplay': $.proxy(function() {
  2464.                                 this.stop();
  2465.                         }, this),
  2466.                         'mouseover.owl.autoplay': $.proxy(function() {
  2467.                                 if (this.core.settings.autoplayHoverPause) {
  2468.                                         this.pause();
  2469.                                 }
  2470.                         }, this),
  2471.                         'mouseleave.owl.autoplay': $.proxy(function() {
  2472.                                 if (this.core.settings.autoplayHoverPause) {
  2473.                                         this.autoplay();
  2474.                                 }
  2475.                         }, this)
  2476.                 };
  2477.  
  2478.                 this.core.$element.on(this.handlers);
  2479.         };
  2480.  
  2481.         /**
  2482.          * Default options.
  2483.          * @public
  2484.          */
  2485.         Autoplay.Defaults = {
  2486.                 autoplay: false,
  2487.                 autoplayTimeout: 5000,
  2488.                 autoplayHoverPause: false,
  2489.                 autoplaySpeed: false
  2490.         };
  2491.  
  2492.         /**
  2493.          * @protected
  2494.          * @todo Must be documented.
  2495.          */
  2496.         Autoplay.prototype.autoplay = function() {
  2497.                 if (this.core.settings.autoplay && !this.core.state.videoPlay) {
  2498.                         window.clearInterval(this.interval);
  2499.  
  2500.                         this.interval = window.setInterval($.proxy(function() {
  2501.                                 this.play();
  2502.                         }, this), this.core.settings.autoplayTimeout);
  2503.                 } else {
  2504.                         window.clearInterval(this.interval);
  2505.                 }
  2506.         };
  2507.  
  2508.         /**
  2509.          * Starts the autoplay.
  2510.          * @public
  2511.          * @param {Number} [timeout] - ...
  2512.          * @param {Number} [speed] - ...
  2513.          * @returns {Boolean|undefined} - ...
  2514.          * @todo Must be documented.
  2515.          */
  2516.         Autoplay.prototype.play = function(timeout, speed) {
  2517.                 // if tab is inactive - doesnt work in <IE10
  2518.                 if (document.hidden === true) {
  2519.                         return;
  2520.                 }
  2521.  
  2522.                 if (this.core.state.isTouch || this.core.state.isScrolling
  2523.                         || this.core.state.isSwiping || this.core.state.inMotion) {
  2524.                         return;
  2525.                 }
  2526.  
  2527.                 if (this.core.settings.autoplay === false) {
  2528.                         window.clearInterval(this.interval);
  2529.                         return;
  2530.                 }
  2531.  
  2532.                 this.core.next(this.core.settings.autoplaySpeed);
  2533.         };
  2534.  
  2535.         /**
  2536.          * Stops the autoplay.
  2537.          * @public
  2538.          */
  2539.         Autoplay.prototype.stop = function() {
  2540.                 window.clearInterval(this.interval);
  2541.         };
  2542.  
  2543.         /**
  2544.          * Pauses the autoplay.
  2545.          * @public
  2546.          */
  2547.         Autoplay.prototype.pause = function() {
  2548.                 window.clearInterval(this.interval);
  2549.         };
  2550.  
  2551.         /**
  2552.          * Destroys the plugin.
  2553.          */
  2554.         Autoplay.prototype.destroy = function() {
  2555.                 var handler, property;
  2556.  
  2557.                 window.clearInterval(this.interval);
  2558.  
  2559.                 for (handler in this.handlers) {
  2560.                         this.core.$element.off(handler, this.handlers[handler]);
  2561.                 }
  2562.                 for (property in Object.getOwnPropertyNames(this)) {
  2563.                         typeof this[property] != 'function' && (this[property] = null);
  2564.                 }
  2565.         };
  2566.  
  2567.         $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
  2568.  
  2569. })(window.Zepto || window.jQuery, window, document);
  2570.  
  2571. /**
  2572.  * Navigation Plugin
  2573.  * @version 2.0.0
  2574.  * @author Artus Kolanowski
  2575.  * @license The MIT License (MIT)
  2576.  */
  2577. ;(function($, window, document, undefined) {
  2578.         'use strict';
  2579.  
  2580.         /**
  2581.          * Creates the navigation plugin.
  2582.          * @class The Navigation Plugin
  2583.          * @param {Owl} carousel - The Owl Carousel.
  2584.          */
  2585.         var Navigation = function(carousel) {
  2586.                 /**
  2587.                  * Reference to the core.
  2588.                  * @protected
  2589.                  * @type {Owl}
  2590.                  */
  2591.                 this._core = carousel;
  2592.  
  2593.                 /**
  2594.                  * Indicates whether the plugin is initialized or not.
  2595.                  * @protected
  2596.                  * @type {Boolean}
  2597.                  */
  2598.                 this._initialized = false;
  2599.  
  2600.                 /**
  2601.                  * The current paging indexes.
  2602.                  * @protected
  2603.                  * @type {Array}
  2604.                  */
  2605.                 this._pages = [];
  2606.  
  2607.                 /**
  2608.                  * All DOM elements of the user interface.
  2609.                  * @protected
  2610.                  * @type {Object}
  2611.                  */
  2612.                 this._controls = {};
  2613.  
  2614.                 /**
  2615.                  * Markup for an indicator.
  2616.                  * @protected
  2617.                  * @type {Array.<String>}
  2618.                  */
  2619.                 this._templates = [];
  2620.  
  2621.                 /**
  2622.                  * The carousel element.
  2623.                  * @type {jQuery}
  2624.                  */
  2625.                 this.$element = this._core.$element;
  2626.  
  2627.                 /**
  2628.                  * Overridden methods of the carousel.
  2629.                  * @protected
  2630.                  * @type {Object}
  2631.                  */
  2632.                 this._overrides = {
  2633.                         next: this._core.next,
  2634.                         prev: this._core.prev,
  2635.                         to: this._core.to
  2636.                 };
  2637.  
  2638.                 /**
  2639.                  * All event handlers.
  2640.                  * @protected
  2641.                  * @type {Object}
  2642.                  */
  2643.                 this._handlers = {
  2644.                         'prepared.owl.carousel': $.proxy(function(e) {
  2645.                                 if (this._core.settings.dotsData) {
  2646.                                         this._templates.push($(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot'));
  2647.                                 }
  2648.                         }, this),
  2649.                         'add.owl.carousel': $.proxy(function(e) {
  2650.                                 if (this._core.settings.dotsData) {
  2651.                                         this._templates.splice(e.position, 0, $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot'));
  2652.                                 }
  2653.                         }, this),
  2654.                         'remove.owl.carousel prepared.owl.carousel': $.proxy(function(e) {
  2655.                                 if (this._core.settings.dotsData) {
  2656.                                         this._templates.splice(e.position, 1);
  2657.                                 }
  2658.                         }, this),
  2659.                         'change.owl.carousel': $.proxy(function(e) {
  2660.                                 if (e.property.name == 'position') {
  2661.                                         if (!this._core.state.revert && !this._core.settings.loop && this._core.settings.navRewind) {
  2662.                                                 var current = this._core.current(),
  2663.                                                         maximum = this._core.maximum(),
  2664.                                                         minimum = this._core.minimum();
  2665.                                                 e.data = e.property.value > maximum
  2666.                                                         ? current >= maximum ? minimum : maximum
  2667.                                                         : e.property.value < minimum ? maximum : e.property.value;
  2668.                                         }
  2669.                                 }
  2670.                         }, this),
  2671.                         'changed.owl.carousel': $.proxy(function(e) {
  2672.                                 if (e.property.name == 'position') {
  2673.                                         this.draw();
  2674.                                 }
  2675.                         }, this),
  2676.                         'refreshed.owl.carousel': $.proxy(function() {
  2677.                                 if (!this._initialized) {
  2678.                                         this.initialize();
  2679.                                         this._initialized = true;
  2680.                                 }
  2681.                                 this._core.trigger('refresh', null, 'navigation');
  2682.                                 this.update();
  2683.                                 this.draw();
  2684.                                 this._core.trigger('refreshed', null, 'navigation');
  2685.                         }, this)
  2686.                 };
  2687.  
  2688.                 // set default options
  2689.                 this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
  2690.  
  2691.                 // register event handlers
  2692.                 this.$element.on(this._handlers);
  2693.         }
  2694.  
  2695.         /**
  2696.          * Default options.
  2697.          * @public
  2698.          * @todo Rename `slideBy` to `navBy`
  2699.          */
  2700.         Navigation.Defaults = {
  2701.                 nav: false,
  2702.                 navRewind: true,
  2703.                 navText: [ 'prev', 'next' ],
  2704.                 navSpeed: false,
  2705.                 navElement: 'div',
  2706.                 navContainer: false,
  2707.                 navContainerClass: 'owl-nav',
  2708.                 navClass: [ 'owl-prev', 'owl-next' ],
  2709.                 slideBy: 1,
  2710.                 dotClass: 'owl-dot',
  2711.                 dotsClass: 'owl-dots',
  2712.                 dots: true,
  2713.                 dotsEach: false,
  2714.                 dotData: false,
  2715.                 dotsSpeed: false,
  2716.                 dotsContainer: false,
  2717.                 controlsClass: 'owl-controls'
  2718.         }
  2719.  
  2720.         /**
  2721.          * Initializes the layout of the plugin and extends the carousel.
  2722.          * @protected
  2723.          */
  2724.         Navigation.prototype.initialize = function() {
  2725.                 var $container, override,
  2726.                         options = this._core.settings;
  2727.  
  2728.                 // create the indicator template
  2729.                 if (!options.dotsData) {
  2730.                         this._templates = [ $('<div>')
  2731.                                 .addClass(options.dotClass)
  2732.                                 .append($('<span>'))
  2733.                                 .prop('outerHTML') ];
  2734.                 }
  2735.  
  2736.                 // create controls container if needed
  2737.                 if (!options.navContainer || !options.dotsContainer) {
  2738.                         this._controls.$container = $('<div>')
  2739.                                 .addClass(options.controlsClass)
  2740.                                 .appendTo(this.$element);
  2741.                 }
  2742.  
  2743.                 // create DOM structure for absolute navigation
  2744.                 this._controls.$indicators = options.dotsContainer ? $(options.dotsContainer)
  2745.                         : $('<div>').hide().addClass(options.dotsClass).appendTo(this._controls.$container);
  2746.  
  2747.                 this._controls.$indicators.on('click', 'div', $.proxy(function(e) {
  2748.                         var index = $(e.target).parent().is(this._controls.$indicators)
  2749.                                 ? $(e.target).index() : $(e.target).parent().index();
  2750.  
  2751.                         e.preventDefault();
  2752.  
  2753.                         this.to(index, options.dotsSpeed);
  2754.                 }, this));
  2755.  
  2756.                 // create DOM structure for relative navigation
  2757.                 $container = options.navContainer ? $(options.navContainer)
  2758.                         : $('<div>').addClass(options.navContainerClass).prependTo(this._controls.$container);
  2759.  
  2760.                 this._controls.$next = $('<' + options.navElement + '>');
  2761.                 this._controls.$previous = this._controls.$next.clone();
  2762.  
  2763.                 this._controls.$previous
  2764.                         .addClass(options.navClass[0])
  2765.                         .html(options.navText[0])
  2766.                         .hide()
  2767.                         .prependTo($container)
  2768.                         .on('click', $.proxy(function(e) {
  2769.                                 this.prev(options.navSpeed);
  2770.                         }, this));
  2771.                 this._controls.$next
  2772.                         .addClass(options.navClass[1])
  2773.                         .html(options.navText[1])
  2774.                         .hide()
  2775.                         .appendTo($container)
  2776.                         .on('click', $.proxy(function(e) {
  2777.                                 this.next(options.navSpeed);
  2778.                         }, this));
  2779.  
  2780.                 // override public methods of the carousel
  2781.                 for (override in this._overrides) {
  2782.                         this._core[override] = $.proxy(this[override], this);
  2783.                 }
  2784.         }
  2785.  
  2786.         /**
  2787.          * Destroys the plugin.
  2788.          * @protected
  2789.          */
  2790.         Navigation.prototype.destroy = function() {
  2791.                 var handler, control, property, override;
  2792.  
  2793.                 for (handler in this._handlers) {
  2794.                         this.$element.off(handler, this._handlers[handler]);
  2795.                 }
  2796.                 for (control in this._controls) {
  2797.                         this._controls[control].remove();
  2798.                 }
  2799.                 for (override in this.overides) {
  2800.                         this._core[override] = this._overrides[override];
  2801.                 }
  2802.                 for (property in Object.getOwnPropertyNames(this)) {
  2803.                         typeof this[property] != 'function' && (this[property] = null);
  2804.                 }
  2805.         }
  2806.  
  2807.         /**
  2808.          * Updates the internal state.
  2809.          * @protected
  2810.          */
  2811.         Navigation.prototype.update = function() {
  2812.                 var i, j, k,
  2813.                         options = this._core.settings,
  2814.                         lower = this._core.clones().length / 2,
  2815.                         upper = lower + this._core.items().length,
  2816.                         size = options.center || options.autoWidth || options.dotData
  2817.                                 ? 1 : options.dotsEach || options.items;
  2818.  
  2819.                 if (options.slideBy !== 'page') {
  2820.                         options.slideBy = Math.min(options.slideBy, options.items);
  2821.                 }
  2822.  
  2823.                 if (options.dots || options.slideBy == 'page') {
  2824.                         this._pages = [];
  2825.  
  2826.                         for (i = lower, j = 0, k = 0; i < upper; i++) {
  2827.                                 if (j >= size || j === 0) {
  2828.                                         this._pages.push({
  2829.                                                 start: i - lower,
  2830.                                                 end: i - lower + size - 1
  2831.                                         });
  2832.                                         j = 0, ++k;
  2833.                                 }
  2834.                                 j += this._core.mergers(this._core.relative(i));
  2835.                         }
  2836.                 }
  2837.         }
  2838.  
  2839.         /**
  2840.          * Draws the user interface.
  2841.          * @todo The option `dotData` wont work.
  2842.          * @protected
  2843.          */
  2844.         Navigation.prototype.draw = function() {
  2845.                 var difference, i, html = '',
  2846.                         options = this._core.settings,
  2847.                         $items = this._core.$stage.children(),
  2848.                         index = this._core.relative(this._core.current());
  2849.  
  2850.                 if (options.nav && !options.loop && !options.navRewind) {
  2851.                         this._controls.$previous.toggleClass('disabled', index <= 0);
  2852.                         this._controls.$next.toggleClass('disabled', index >= this._core.maximum());
  2853.                 }
  2854.  
  2855.                 this._controls.$previous.toggle(options.nav);
  2856.                 this._controls.$next.toggle(options.nav);
  2857.  
  2858.                 if (options.dots) {
  2859.                         difference = this._pages.length - this._controls.$indicators.children().length;
  2860.  
  2861.                         if (options.dotData && difference !== 0) {
  2862.                                 for (i = 0; i < this._controls.$indicators.children().length; i++) {
  2863.                                         html += this._templates[this._core.relative(i)];
  2864.                                 }
  2865.                                 this._controls.$indicators.html(html);
  2866.                         } else if (difference > 0) {
  2867.                                 html = new Array(difference + 1).join(this._templates[0]);
  2868.                                 this._controls.$indicators.append(html);
  2869.                         } else if (difference < 0) {
  2870.                                 this._controls.$indicators.children().slice(difference).remove();
  2871.                         }
  2872.  
  2873.                         this._controls.$indicators.find('.active').removeClass('active');
  2874.                         this._controls.$indicators.children().eq($.inArray(this.current(), this._pages)).addClass('active');
  2875.                 }
  2876.  
  2877.                 this._controls.$indicators.toggle(options.dots);
  2878.         }
  2879.  
  2880.         /**
  2881.          * Extends event data.
  2882.          * @protected
  2883.          * @param {Event} event - The event object which gets thrown.
  2884.          */
  2885.         Navigation.prototype.onTrigger = function(event) {
  2886.                 var settings = this._core.settings;
  2887.  
  2888.                 event.page = {
  2889.                         index: $.inArray(this.current(), this._pages),
  2890.                         count: this._pages.length,
  2891.                         size: settings && (settings.center || settings.autoWidth || settings.dotData
  2892.                                 ? 1 : settings.dotsEach || settings.items)
  2893.                 };
  2894.         }
  2895.  
  2896.         /**
  2897.          * Gets the current page position of the carousel.
  2898.          * @protected
  2899.          * @returns {Number}
  2900.          */
  2901.         Navigation.prototype.current = function() {
  2902.                 var index = this._core.relative(this._core.current());
  2903.                 return $.grep(this._pages, function(o) {
  2904.                         return o.start <= index && o.end >= index;
  2905.                 }).pop();
  2906.         }
  2907.  
  2908.         /**
  2909.          * Gets the current succesor/predecessor position.
  2910.          * @protected
  2911.          * @returns {Number}
  2912.          */
  2913.         Navigation.prototype.getPosition = function(successor) {
  2914.                 var position, length,
  2915.                         options = this._core.settings;
  2916.  
  2917.                 if (options.slideBy == 'page') {
  2918.                         position = $.inArray(this.current(), this._pages);
  2919.                         length = this._pages.length;
  2920.                         successor ? ++position : --position;
  2921.                         position = this._pages[((position % length) + length) % length].start;
  2922.                 } else {
  2923.                         position = this._core.relative(this._core.current());
  2924.                         length = this._core.items().length;
  2925.                         successor ? position += options.slideBy : position -= options.slideBy;
  2926.                 }
  2927.                 return position;
  2928.         }
  2929.  
  2930.         /**
  2931.          * Slides to the next item or page.
  2932.          * @public
  2933.          * @param {Number} [speed=false] - The time in milliseconds for the transition.
  2934.          */
  2935.         Navigation.prototype.next = function(speed) {
  2936.                 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
  2937.         }
  2938.  
  2939.         /**
  2940.          * Slides to the previous item or page.
  2941.          * @public
  2942.          * @param {Number} [speed=false] - The time in milliseconds for the transition.
  2943.          */
  2944.         Navigation.prototype.prev = function(speed) {
  2945.                 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
  2946.         }
  2947.  
  2948.         /**
  2949.          * Slides to the specified item or page.
  2950.          * @public
  2951.          * @param {Number} position - The position of the item or page.
  2952.          * @param {Number} [speed] - The time in milliseconds for the transition.
  2953.          * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
  2954.          */
  2955.         Navigation.prototype.to = function(position, speed, standard) {
  2956.                 var length;
  2957.  
  2958.                 if (!standard) {
  2959.                         length = this._pages.length;
  2960.                         $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
  2961.                 } else {
  2962.                         $.proxy(this._overrides.to, this._core)(position, speed);
  2963.                 }
  2964.         }
  2965.  
  2966.         $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
  2967.  
  2968. })(window.Zepto || window.jQuery, window, document);
  2969.  
  2970. /**
  2971.  * Hash Plugin
  2972.  * @version 2.0.0
  2973.  * @author Artus Kolanowski
  2974.  * @license The MIT License (MIT)
  2975.  */
  2976. ;(function($, window, document, undefined) {
  2977.         'use strict';
  2978.  
  2979.         /**
  2980.          * Creates the hash plugin.
  2981.          * @class The Hash Plugin
  2982.          * @param {Owl} carousel - The Owl Carousel
  2983.          */
  2984.         var Hash = function(carousel) {
  2985.                 /**
  2986.                  * Reference to the core.
  2987.                  * @protected
  2988.                  * @type {Owl}
  2989.                  */
  2990.                 this._core = carousel;
  2991.  
  2992.                 /**
  2993.                  * Hash table for the hashes.
  2994.                  * @protected
  2995.                  * @type {Object}
  2996.                  */
  2997.                 this._hashes = {};
  2998.  
  2999.                 /**
  3000.                  * The carousel element.
  3001.                  * @type {jQuery}
  3002.                  */
  3003.                 this.$element = this._core.$element;
  3004.  
  3005.                 /**
  3006.                  * All event handlers.
  3007.                  * @protected
  3008.                  * @type {Object}
  3009.                  */
  3010.                 this._handlers = {
  3011.                         'initialized.owl.carousel': $.proxy(function() {
  3012.                                 if (this._core.settings.startPosition == 'URLHash') {
  3013.                                         $(window).trigger('hashchange.owl.navigation');
  3014.                                 }
  3015.                         }, this),
  3016.                         'prepared.owl.carousel': $.proxy(function(e) {
  3017.                                 var hash = $(e.content).find('[data-hash]').andSelf('[data-hash]').attr('data-hash');
  3018.                                 this._hashes[hash] = e.content;
  3019.                         }, this)
  3020.                 };
  3021.  
  3022.                 // set default options
  3023.                 this._core.options = $.extend({}, Hash.Defaults, this._core.options);
  3024.  
  3025.                 // register the event handlers
  3026.                 this.$element.on(this._handlers);
  3027.  
  3028.                 // register event listener for hash navigation
  3029.                 $(window).on('hashchange.owl.navigation', $.proxy(function() {
  3030.                         var hash = window.location.hash.substring(1),
  3031.                                 items = this._core.$stage.children(),
  3032.                                 position = this._hashes[hash] && items.index(this._hashes[hash]) || 0;
  3033.  
  3034.                         if (!hash) {
  3035.                                 return false;
  3036.                         }
  3037.  
  3038.                         this._core.to(position, false, true);
  3039.                 }, this));
  3040.         }
  3041.  
  3042.         /**
  3043.          * Default options.
  3044.          * @public
  3045.          */
  3046.         Hash.Defaults = {
  3047.                 URLhashListener: false
  3048.         }
  3049.  
  3050.         /**
  3051.          * Destroys the plugin.
  3052.          * @public
  3053.          */
  3054.         Hash.prototype.destroy = function() {
  3055.                 var handler, property;
  3056.  
  3057.                 $(window).off('hashchange.owl.navigation');
  3058.  
  3059.                 for (handler in this._handlers) {
  3060.                         this._core.$element.off(handler, this._handlers[handler]);
  3061.                 }
  3062.                 for (property in Object.getOwnPropertyNames(this)) {
  3063.                         typeof this[property] != 'function' && (this[property] = null);
  3064.                 }
  3065.         }
  3066.  
  3067.         $.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
  3068.  
  3069. })(window.Zepto || window.jQuery, window, document);

Raw Paste


Login or Register to edit or fork this paste. It's free.