PageSourceSearch

https://amatix.es/modules/owlthemeconfigurator/views/js/frontend/owl.carousel.js

js amatix.es collected 2026-10-04 12:51:35 UTC 85,864 bytes, 3,252 lines download raw bytes

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