PageSourceSearch

https://connectfcsed.com/wp-content/themes/efor/js/owl-carousel/owl.carousel.min.js

js connectfcsed.com collected 2026-10-09 22:25:25 UTC 94,392 bytes, 3,461 lines download raw bytes

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