PageSourceSearch

https://wifaqulmadaris.org/Loads/plugins/owl-carousel/owl.carousel.js

js wifaqulmadaris.org collected 2026-10-02 13:53:45 UTC 109,811 bytes, 3,423 lines download raw bytes

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