PageSourceSearch

https://asoyroj.com/owl.carousel2.js

js asoyroj.com collected 2026-10-02 13:43:25 UTC 78,941 bytes, 3,059 lines download raw bytes

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