owlcarousel2-rails 2.1.0

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