PageSourceSearch

https://ruscondicioner.ru/modules/mod_sj_vm_deals/assets/js/owl.carousel.js

js ruscondicioner.ru collected 2026-10-04 14:05:38 UTC 96,721 bytes, 3,113 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.