owlcarousel2 2.2.0.pre.4.pre.g22132e0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +53 -0
  7. data/Rakefile +13 -0
  8. data/lib/owlcarousel2.rb +9 -0
  9. data/lib/owlcarousel2/engine.rb +5 -0
  10. data/lib/owlcarousel2/version.rb +3 -0
  11. data/owlcarousel2.gemspec +25 -0
  12. data/vendor/assets/images/owlcarousel2/ajax-loader.gif +0 -0
  13. data/vendor/assets/images/owlcarousel2/owl.video.play.png +0 -0
  14. data/vendor/assets/javascripts/owlcarousel2/owl.animate.js +121 -0
  15. data/vendor/assets/javascripts/owlcarousel2/owl.autoheight.js +97 -0
  16. data/vendor/assets/javascripts/owlcarousel2/owl.autoplay.js +199 -0
  17. data/vendor/assets/javascripts/owlcarousel2/owl.autorefresh.js +111 -0
  18. data/vendor/assets/javascripts/owlcarousel2/owl.carousel.js +1692 -0
  19. data/vendor/assets/javascripts/owlcarousel2/owl.hash.js +122 -0
  20. data/vendor/assets/javascripts/owlcarousel2/owl.lazyload.js +135 -0
  21. data/vendor/assets/javascripts/owlcarousel2/owl.navigation.js +382 -0
  22. data/vendor/assets/javascripts/owlcarousel2/owl.support.js +83 -0
  23. data/vendor/assets/javascripts/owlcarousel2/owl.support.modernizr.js +66 -0
  24. data/vendor/assets/javascripts/owlcarousel2/owl.video.js +319 -0
  25. data/vendor/assets/stylesheets/owlcarousel2/_animate.scss +28 -0
  26. data/vendor/assets/stylesheets/owlcarousel2/_autoheight.scss +7 -0
  27. data/vendor/assets/stylesheets/owlcarousel2/_core.scss +114 -0
  28. data/vendor/assets/stylesheets/owlcarousel2/_lazyload.scss +17 -0
  29. data/vendor/assets/stylesheets/owlcarousel2/_theme.default.scss +30 -0
  30. data/vendor/assets/stylesheets/owlcarousel2/_theme.green.scss +30 -0
  31. data/vendor/assets/stylesheets/owlcarousel2/_theme.scss +64 -0
  32. data/vendor/assets/stylesheets/owlcarousel2/_video.scss +51 -0
  33. data/vendor/assets/stylesheets/owlcarousel2/owl.carousel.scss +5 -0
  34. data/vendor/assets/stylesheets/owlcarousel2/owl.theme.default.scss +1 -0
  35. data/vendor/assets/stylesheets/owlcarousel2/owl.theme.green.scss +1 -0
  36. metadata +93 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * AutoRefresh Plugin
3
+ * @version 2.1.0
4
+ * @author Artus Kolanowski
5
+ * @author David Deutsch
6
+ * @license The MIT License (MIT)
7
+ */
8
+ ;(function($, window, document, undefined) {
9
+
10
+ /**
11
+ * Creates the auto refresh plugin.
12
+ * @class The Auto Refresh Plugin
13
+ * @param {Owl} carousel - The Owl Carousel
14
+ */
15
+ var AutoRefresh = function(carousel) {
16
+ /**
17
+ * Reference to the core.
18
+ * @protected
19
+ * @type {Owl}
20
+ */
21
+ this._core = carousel;
22
+
23
+ /**
24
+ * Refresh interval.
25
+ * @protected
26
+ * @type {number}
27
+ */
28
+ this._interval = null;
29
+
30
+ /**
31
+ * Whether the element is currently visible or not.
32
+ * @protected
33
+ * @type {Boolean}
34
+ */
35
+ this._visible = null;
36
+
37
+ /**
38
+ * All event handlers.
39
+ * @protected
40
+ * @type {Object}
41
+ */
42
+ this._handlers = {
43
+ 'initialized.owl.carousel': $.proxy(function(e) {
44
+ if (e.namespace && this._core.settings.autoRefresh) {
45
+ this.watch();
46
+ }
47
+ }, this)
48
+ };
49
+
50
+ // set default options
51
+ this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
52
+
53
+ // register event handlers
54
+ this._core.$element.on(this._handlers);
55
+ };
56
+
57
+ /**
58
+ * Default options.
59
+ * @public
60
+ */
61
+ AutoRefresh.Defaults = {
62
+ autoRefresh: true,
63
+ autoRefreshInterval: 500
64
+ };
65
+
66
+ /**
67
+ * Watches the element.
68
+ */
69
+ AutoRefresh.prototype.watch = function() {
70
+ if (this._interval) {
71
+ return;
72
+ }
73
+
74
+ this._visible = this._core.$element.is(':visible');
75
+ this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
76
+ };
77
+
78
+ /**
79
+ * Refreshes the element.
80
+ */
81
+ AutoRefresh.prototype.refresh = function() {
82
+ if (this._core.$element.is(':visible') === this._visible) {
83
+ return;
84
+ }
85
+
86
+ this._visible = !this._visible;
87
+
88
+ this._core.$element.toggleClass('owl-hidden', !this._visible);
89
+
90
+ this._visible && (this._core.invalidate('width') && this._core.refresh());
91
+ };
92
+
93
+ /**
94
+ * Destroys the plugin.
95
+ */
96
+ AutoRefresh.prototype.destroy = function() {
97
+ var handler, property;
98
+
99
+ window.clearInterval(this._interval);
100
+
101
+ for (handler in this._handlers) {
102
+ this._core.$element.off(handler, this._handlers[handler]);
103
+ }
104
+ for (property in Object.getOwnPropertyNames(this)) {
105
+ typeof this[property] != 'function' && (this[property] = null);
106
+ }
107
+ };
108
+
109
+ $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
110
+
111
+ })(window.Zepto || window.jQuery, window, document);
@@ -0,0 +1,1692 @@
1
+ /**
2
+ * Owl carousel
3
+ * @version 2.1.6
4
+ * @author Bartosz Wojciechowski
5
+ * @author David Deutsch
6
+ * @license The MIT License (MIT)
7
+ * @todo Lazy Load Icon
8
+ * @todo prevent animationend bubling
9
+ * @todo itemsScaleUp
10
+ * @todo Test Zepto
11
+ * @todo stagePadding calculate wrong active classes
12
+ */
13
+ ;(function($, window, document, undefined) {
14
+
15
+ /**
16
+ * Creates a carousel.
17
+ * @class The Owl Carousel.
18
+ * @public
19
+ * @param {HTMLElement|jQuery} element - The element to create the carousel for.
20
+ * @param {Object} [options] - The options
21
+ */
22
+ function Owl(element, options) {
23
+
24
+ /**
25
+ * Current settings for the carousel.
26
+ * @public
27
+ */
28
+ this.settings = null;
29
+
30
+ /**
31
+ * Current options set by the caller including defaults.
32
+ * @public
33
+ */
34
+ this.options = $.extend({}, Owl.Defaults, options);
35
+
36
+ /**
37
+ * Plugin element.
38
+ * @public
39
+ */
40
+ this.$element = $(element);
41
+
42
+ /**
43
+ * Proxied event handlers.
44
+ * @protected
45
+ */
46
+ this._handlers = {};
47
+
48
+ /**
49
+ * References to the running plugins of this carousel.
50
+ * @protected
51
+ */
52
+ this._plugins = {};
53
+
54
+ /**
55
+ * Currently suppressed events to prevent them from beeing retriggered.
56
+ * @protected
57
+ */
58
+ this._supress = {};
59
+
60
+ /**
61
+ * Absolute current position.
62
+ * @protected
63
+ */
64
+ this._current = null;
65
+
66
+ /**
67
+ * Animation speed in milliseconds.
68
+ * @protected
69
+ */
70
+ this._speed = null;
71
+
72
+ /**
73
+ * Coordinates of all items in pixel.
74
+ * @todo The name of this member is missleading.
75
+ * @protected
76
+ */
77
+ this._coordinates = [];
78
+
79
+ /**
80
+ * Current breakpoint.
81
+ * @todo Real media queries would be nice.
82
+ * @protected
83
+ */
84
+ this._breakpoint = null;
85
+
86
+ /**
87
+ * Current width of the plugin element.
88
+ */
89
+ this._width = null;
90
+
91
+ /**
92
+ * All real items.
93
+ * @protected
94
+ */
95
+ this._items = [];
96
+
97
+ /**
98
+ * All cloned items.
99
+ * @protected
100
+ */
101
+ this._clones = [];
102
+
103
+ /**
104
+ * Merge values of all items.
105
+ * @todo Maybe this could be part of a plugin.
106
+ * @protected
107
+ */
108
+ this._mergers = [];
109
+
110
+ /**
111
+ * Widths of all items.
112
+ */
113
+ this._widths = [];
114
+
115
+ /**
116
+ * Invalidated parts within the update process.
117
+ * @protected
118
+ */
119
+ this._invalidated = {};
120
+
121
+ /**
122
+ * Ordered list of workers for the update process.
123
+ * @protected
124
+ */
125
+ this._pipe = [];
126
+
127
+ /**
128
+ * Current state information for the drag operation.
129
+ * @todo #261
130
+ * @protected
131
+ */
132
+ this._drag = {
133
+ time: null,
134
+ target: null,
135
+ pointer: null,
136
+ stage: {
137
+ start: null,
138
+ current: null
139
+ },
140
+ direction: null
141
+ };
142
+
143
+ /**
144
+ * Current state information and their tags.
145
+ * @type {Object}
146
+ * @protected
147
+ */
148
+ this._states = {
149
+ current: {},
150
+ tags: {
151
+ 'initializing': [ 'busy' ],
152
+ 'animating': [ 'busy' ],
153
+ 'dragging': [ 'interacting' ]
154
+ }
155
+ };
156
+
157
+ $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
158
+ this._handlers[handler] = $.proxy(this[handler], this);
159
+ }, this));
160
+
161
+ $.each(Owl.Plugins, $.proxy(function(key, plugin) {
162
+ this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
163
+ = new plugin(this);
164
+ }, this));
165
+
166
+ $.each(Owl.Workers, $.proxy(function(priority, worker) {
167
+ this._pipe.push({
168
+ 'filter': worker.filter,
169
+ 'run': $.proxy(worker.run, this)
170
+ });
171
+ }, this));
172
+
173
+ this.setup();
174
+ this.initialize();
175
+ }
176
+
177
+ /**
178
+ * Default options for the carousel.
179
+ * @public
180
+ */
181
+ Owl.Defaults = {
182
+ items: 3,
183
+ loop: false,
184
+ center: false,
185
+ rewind: false,
186
+
187
+ mouseDrag: true,
188
+ touchDrag: true,
189
+ pullDrag: true,
190
+ freeDrag: false,
191
+
192
+ margin: 0,
193
+ stagePadding: 0,
194
+
195
+ merge: false,
196
+ mergeFit: true,
197
+ autoWidth: false,
198
+
199
+ startPosition: 0,
200
+ rtl: false,
201
+
202
+ smartSpeed: 250,
203
+ fluidSpeed: false,
204
+ dragEndSpeed: false,
205
+
206
+ responsive: {},
207
+ responsiveRefreshRate: 200,
208
+ responsiveBaseElement: window,
209
+
210
+ fallbackEasing: 'swing',
211
+
212
+ info: false,
213
+
214
+ nestedItemSelector: false,
215
+ itemElement: 'div',
216
+ stageElement: 'div',
217
+
218
+ refreshClass: 'owl-refresh',
219
+ loadedClass: 'owl-loaded',
220
+ loadingClass: 'owl-loading',
221
+ rtlClass: 'owl-rtl',
222
+ responsiveClass: 'owl-responsive',
223
+ dragClass: 'owl-drag',
224
+ itemClass: 'owl-item',
225
+ stageClass: 'owl-stage',
226
+ stageOuterClass: 'owl-stage-outer',
227
+ grabClass: 'owl-grab'
228
+ };
229
+
230
+ /**
231
+ * Enumeration for width.
232
+ * @public
233
+ * @readonly
234
+ * @enum {String}
235
+ */
236
+ Owl.Width = {
237
+ Default: 'default',
238
+ Inner: 'inner',
239
+ Outer: 'outer'
240
+ };
241
+
242
+ /**
243
+ * Enumeration for types.
244
+ * @public
245
+ * @readonly
246
+ * @enum {String}
247
+ */
248
+ Owl.Type = {
249
+ Event: 'event',
250
+ State: 'state'
251
+ };
252
+
253
+ /**
254
+ * Contains all registered plugins.
255
+ * @public
256
+ */
257
+ Owl.Plugins = {};
258
+
259
+ /**
260
+ * List of workers involved in the update process.
261
+ */
262
+ Owl.Workers = [ {
263
+ filter: [ 'width', 'settings' ],
264
+ run: function() {
265
+ this._width = this.$element.width();
266
+ }
267
+ }, {
268
+ filter: [ 'width', 'items', 'settings' ],
269
+ run: function(cache) {
270
+ cache.current = this._items && this._items[this.relative(this._current)];
271
+ }
272
+ }, {
273
+ filter: [ 'items', 'settings' ],
274
+ run: function() {
275
+ this.$stage.children('.cloned').remove();
276
+ }
277
+ }, {
278
+ filter: [ 'width', 'items', 'settings' ],
279
+ run: function(cache) {
280
+ var margin = this.settings.margin || '',
281
+ grid = !this.settings.autoWidth,
282
+ rtl = this.settings.rtl,
283
+ css = {
284
+ 'width': 'auto',
285
+ 'margin-left': rtl ? margin : '',
286
+ 'margin-right': rtl ? '' : margin
287
+ };
288
+
289
+ !grid && this.$stage.children().css(css);
290
+
291
+ cache.css = css;
292
+ }
293
+ }, {
294
+ filter: [ 'width', 'items', 'settings' ],
295
+ run: function(cache) {
296
+ var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
297
+ merge = null,
298
+ iterator = this._items.length,
299
+ grid = !this.settings.autoWidth,
300
+ widths = [];
301
+
302
+ cache.items = {
303
+ merge: false,
304
+ width: width
305
+ };
306
+
307
+ while (iterator--) {
308
+ merge = this._mergers[iterator];
309
+ merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
310
+
311
+ cache.items.merge = merge > 1 || cache.items.merge;
312
+
313
+ widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
314
+ }
315
+
316
+ this._widths = widths;
317
+ }
318
+ }, {
319
+ filter: [ 'items', 'settings' ],
320
+ run: function() {
321
+ var clones = [],
322
+ items = this._items,
323
+ settings = this.settings,
324
+ // TODO: Should be computed from number of min width items in stage
325
+ view = Math.max(settings.items * 2, 4),
326
+ size = Math.ceil(items.length / 2) * 2,
327
+ repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
328
+ append = '',
329
+ prepend = '';
330
+
331
+ repeat /= 2;
332
+
333
+ while (repeat--) {
334
+ // Switch to only using appended clones
335
+ clones.push(this.normalize(clones.length / 2, true));
336
+ append = append + items[clones[clones.length - 1]][0].outerHTML;
337
+ clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
338
+ prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
339
+ }
340
+
341
+ this._clones = clones;
342
+
343
+ $(append).addClass('cloned').appendTo(this.$stage);
344
+ $(prepend).addClass('cloned').prependTo(this.$stage);
345
+ }
346
+ }, {
347
+ filter: [ 'width', 'items', 'settings' ],
348
+ run: function() {
349
+ var rtl = this.settings.rtl ? 1 : -1,
350
+ size = this._clones.length + this._items.length,
351
+ iterator = -1,
352
+ previous = 0,
353
+ current = 0,
354
+ coordinates = [];
355
+
356
+ while (++iterator < size) {
357
+ previous = coordinates[iterator - 1] || 0;
358
+ current = this._widths[this.relative(iterator)] + this.settings.margin;
359
+ coordinates.push(previous + current * rtl);
360
+ }
361
+
362
+ this._coordinates = coordinates;
363
+ }
364
+ }, {
365
+ filter: [ 'width', 'items', 'settings' ],
366
+ run: function() {
367
+ var padding = this.settings.stagePadding,
368
+ coordinates = this._coordinates,
369
+ css = {
370
+ 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
371
+ 'padding-left': padding || '',
372
+ 'padding-right': padding || ''
373
+ };
374
+
375
+ this.$stage.css(css);
376
+ }
377
+ }, {
378
+ filter: [ 'width', 'items', 'settings' ],
379
+ run: function(cache) {
380
+ var iterator = this._coordinates.length,
381
+ grid = !this.settings.autoWidth,
382
+ items = this.$stage.children();
383
+
384
+ if (grid && cache.items.merge) {
385
+ while (iterator--) {
386
+ cache.css.width = this._widths[this.relative(iterator)];
387
+ items.eq(iterator).css(cache.css);
388
+ }
389
+ } else if (grid) {
390
+ cache.css.width = cache.items.width;
391
+ items.css(cache.css);
392
+ }
393
+ }
394
+ }, {
395
+ filter: [ 'items' ],
396
+ run: function() {
397
+ this._coordinates.length < 1 && this.$stage.removeAttr('style');
398
+ }
399
+ }, {
400
+ filter: [ 'width', 'items', 'settings' ],
401
+ run: function(cache) {
402
+ cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
403
+ cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
404
+ this.reset(cache.current);
405
+ }
406
+ }, {
407
+ filter: [ 'position' ],
408
+ run: function() {
409
+ this.animate(this.coordinates(this._current));
410
+ }
411
+ }, {
412
+ filter: [ 'width', 'position', 'items', 'settings' ],
413
+ run: function() {
414
+ var rtl = this.settings.rtl ? 1 : -1,
415
+ padding = this.settings.stagePadding * 2,
416
+ begin = this.coordinates(this.current()) + padding,
417
+ end = begin + this.width() * rtl,
418
+ inner, outer, matches = [], i, n;
419
+
420
+ for (i = 0, n = this._coordinates.length; i < n; i++) {
421
+ inner = this._coordinates[i - 1] || 0;
422
+ outer = Math.abs(this._coordinates[i]) + padding * rtl;
423
+
424
+ if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
425
+ || (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
426
+ matches.push(i);
427
+ }
428
+ }
429
+
430
+ this.$stage.children('.active').removeClass('active');
431
+ this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
432
+
433
+ if (this.settings.center) {
434
+ this.$stage.children('.center').removeClass('center');
435
+ this.$stage.children().eq(this.current()).addClass('center');
436
+ }
437
+ }
438
+ } ];
439
+
440
+ /**
441
+ * Initializes the carousel.
442
+ * @protected
443
+ */
444
+ Owl.prototype.initialize = function() {
445
+ this.enter('initializing');
446
+ this.trigger('initialize');
447
+
448
+ this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
449
+
450
+ if (this.settings.autoWidth && !this.is('pre-loading')) {
451
+ var imgs, nestedSelector, width;
452
+ imgs = this.$element.find('img');
453
+ nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
454
+ width = this.$element.children(nestedSelector).width();
455
+
456
+ if (imgs.length && width <= 0) {
457
+ this.preloadAutoWidthImages(imgs);
458
+ }
459
+ }
460
+
461
+ this.$element.addClass(this.options.loadingClass);
462
+
463
+ // create stage
464
+ this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
465
+ .wrap('<div class="' + this.settings.stageOuterClass + '"/>');
466
+
467
+ // append stage
468
+ this.$element.append(this.$stage.parent());
469
+
470
+ // append content
471
+ this.replace(this.$element.children().not(this.$stage.parent()));
472
+
473
+ // check visibility
474
+ if (this.$element.is(':visible')) {
475
+ // update view
476
+ this.refresh();
477
+ } else {
478
+ // invalidate width
479
+ this.invalidate('width');
480
+ }
481
+
482
+ this.$element
483
+ .removeClass(this.options.loadingClass)
484
+ .addClass(this.options.loadedClass);
485
+
486
+ // register event handlers
487
+ this.registerEventHandlers();
488
+
489
+ this.leave('initializing');
490
+ this.trigger('initialized');
491
+ };
492
+
493
+ /**
494
+ * Setups the current settings.
495
+ * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
496
+ * @todo Support for media queries by using `matchMedia` would be nice.
497
+ * @public
498
+ */
499
+ Owl.prototype.setup = function() {
500
+ var viewport = this.viewport(),
501
+ overwrites = this.options.responsive,
502
+ match = -1,
503
+ settings = null;
504
+
505
+ if (!overwrites) {
506
+ settings = $.extend({}, this.options);
507
+ } else {
508
+ $.each(overwrites, function(breakpoint) {
509
+ if (breakpoint <= viewport && breakpoint > match) {
510
+ match = Number(breakpoint);
511
+ }
512
+ });
513
+
514
+ settings = $.extend({}, this.options, overwrites[match]);
515
+ if (typeof settings.stagePadding === 'function') {
516
+ settings.stagePadding = settings.stagePadding();
517
+ }
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
+ this.trigger('change', { property: { name: 'settings', value: settings } });
529
+ this._breakpoint = match;
530
+ this.settings = settings;
531
+ this.invalidate('settings');
532
+ this.trigger('changed', { property: { name: 'settings', value: this.settings } });
533
+ };
534
+
535
+ /**
536
+ * Updates option logic if necessery.
537
+ * @protected
538
+ */
539
+ Owl.prototype.optionsLogic = function() {
540
+ if (this.settings.autoWidth) {
541
+ this.settings.stagePadding = false;
542
+ this.settings.merge = false;
543
+ }
544
+ };
545
+
546
+ /**
547
+ * Prepares an item before add.
548
+ * @todo Rename event parameter `content` to `item`.
549
+ * @protected
550
+ * @returns {jQuery|HTMLElement} - The item container.
551
+ */
552
+ Owl.prototype.prepare = function(item) {
553
+ var event = this.trigger('prepare', { content: item });
554
+
555
+ if (!event.data) {
556
+ event.data = $('<' + this.settings.itemElement + '/>')
557
+ .addClass(this.options.itemClass).append(item)
558
+ }
559
+
560
+ this.trigger('prepared', { content: event.data });
561
+
562
+ return event.data;
563
+ };
564
+
565
+ /**
566
+ * Updates the view.
567
+ * @public
568
+ */
569
+ Owl.prototype.update = function() {
570
+ var i = 0,
571
+ n = this._pipe.length,
572
+ filter = $.proxy(function(p) { return this[p] }, this._invalidated),
573
+ cache = {};
574
+
575
+ while (i < n) {
576
+ if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
577
+ this._pipe[i].run(cache);
578
+ }
579
+ i++;
580
+ }
581
+
582
+ this._invalidated = {};
583
+
584
+ !this.is('valid') && this.enter('valid');
585
+ };
586
+
587
+ /**
588
+ * Gets the width of the view.
589
+ * @public
590
+ * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
591
+ * @returns {Number} - The width of the view in pixel.
592
+ */
593
+ Owl.prototype.width = function(dimension) {
594
+ dimension = dimension || Owl.Width.Default;
595
+ switch (dimension) {
596
+ case Owl.Width.Inner:
597
+ case Owl.Width.Outer:
598
+ return this._width;
599
+ default:
600
+ return this._width - this.settings.stagePadding * 2 + this.settings.margin;
601
+ }
602
+ };
603
+
604
+ /**
605
+ * Refreshes the carousel primarily for adaptive purposes.
606
+ * @public
607
+ */
608
+ Owl.prototype.refresh = function() {
609
+ this.enter('refreshing');
610
+ this.trigger('refresh');
611
+
612
+ this.setup();
613
+
614
+ this.optionsLogic();
615
+
616
+ this.$element.addClass(this.options.refreshClass);
617
+
618
+ this.update();
619
+
620
+ this.$element.removeClass(this.options.refreshClass);
621
+
622
+ this.leave('refreshing');
623
+ this.trigger('refreshed');
624
+ };
625
+
626
+ /**
627
+ * Checks window `resize` event.
628
+ * @protected
629
+ */
630
+ Owl.prototype.onThrottledResize = function() {
631
+ window.clearTimeout(this.resizeTimer);
632
+ this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
633
+ };
634
+
635
+ /**
636
+ * Checks window `resize` event.
637
+ * @protected
638
+ */
639
+ Owl.prototype.onResize = function() {
640
+ if (!this._items.length) {
641
+ return false;
642
+ }
643
+
644
+ if (this._width === this.$element.width()) {
645
+ return false;
646
+ }
647
+
648
+ if (!this.$element.is(':visible')) {
649
+ return false;
650
+ }
651
+
652
+ this.enter('resizing');
653
+
654
+ if (this.trigger('resize').isDefaultPrevented()) {
655
+ this.leave('resizing');
656
+ return false;
657
+ }
658
+
659
+ this.invalidate('width');
660
+
661
+ this.refresh();
662
+
663
+ this.leave('resizing');
664
+ this.trigger('resized');
665
+ };
666
+
667
+ /**
668
+ * Registers event handlers.
669
+ * @todo Check `msPointerEnabled`
670
+ * @todo #261
671
+ * @protected
672
+ */
673
+ Owl.prototype.registerEventHandlers = function() {
674
+ if ($.support.transition) {
675
+ this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
676
+ }
677
+
678
+ if (this.settings.responsive !== false) {
679
+ this.on(window, 'resize', this._handlers.onThrottledResize);
680
+ }
681
+
682
+ if (this.settings.mouseDrag) {
683
+ this.$element.addClass(this.options.dragClass);
684
+ this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
685
+ this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
686
+ }
687
+
688
+ if (this.settings.touchDrag){
689
+ this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
690
+ this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
691
+ }
692
+ };
693
+
694
+ /**
695
+ * Handles `touchstart` and `mousedown` events.
696
+ * @todo Horizontal swipe threshold as option
697
+ * @todo #261
698
+ * @protected
699
+ * @param {Event} event - The event arguments.
700
+ */
701
+ Owl.prototype.onDragStart = function(event) {
702
+ var stage = null;
703
+
704
+ if (event.which === 3) {
705
+ return;
706
+ }
707
+
708
+ if ($.support.transform) {
709
+ stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
710
+ stage = {
711
+ x: stage[stage.length === 16 ? 12 : 4],
712
+ y: stage[stage.length === 16 ? 13 : 5]
713
+ };
714
+ } else {
715
+ stage = this.$stage.position();
716
+ stage = {
717
+ x: this.settings.rtl ?
718
+ stage.left + this.$stage.width() - this.width() + this.settings.margin :
719
+ stage.left,
720
+ y: stage.top
721
+ };
722
+ }
723
+
724
+ if (this.is('animating')) {
725
+ $.support.transform ? this.animate(stage.x) : this.$stage.stop()
726
+ this.invalidate('position');
727
+ }
728
+
729
+ this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
730
+
731
+ this.speed(0);
732
+
733
+ this._drag.time = new Date().getTime();
734
+ this._drag.target = $(event.target);
735
+ this._drag.stage.start = stage;
736
+ this._drag.stage.current = stage;
737
+ this._drag.pointer = this.pointer(event);
738
+
739
+ $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
740
+
741
+ $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
742
+ var delta = this.difference(this._drag.pointer, this.pointer(event));
743
+
744
+ $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
745
+
746
+ if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
747
+ return;
748
+ }
749
+
750
+ event.preventDefault();
751
+
752
+ this.enter('dragging');
753
+ this.trigger('drag');
754
+ }, this));
755
+ };
756
+
757
+ /**
758
+ * Handles the `touchmove` and `mousemove` events.
759
+ * @todo #261
760
+ * @protected
761
+ * @param {Event} event - The event arguments.
762
+ */
763
+ Owl.prototype.onDragMove = function(event) {
764
+ var minimum = null,
765
+ maximum = null,
766
+ pull = null,
767
+ delta = this.difference(this._drag.pointer, this.pointer(event)),
768
+ stage = this.difference(this._drag.stage.start, delta);
769
+
770
+ if (!this.is('dragging')) {
771
+ return;
772
+ }
773
+
774
+ event.preventDefault();
775
+
776
+ if (this.settings.loop) {
777
+ minimum = this.coordinates(this.minimum());
778
+ maximum = this.coordinates(this.maximum() + 1) - minimum;
779
+ stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
780
+ } else {
781
+ minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
782
+ maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
783
+ pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
784
+ stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
785
+ }
786
+
787
+ this._drag.stage.current = stage;
788
+
789
+ this.animate(stage.x);
790
+ };
791
+
792
+ /**
793
+ * Handles the `touchend` and `mouseup` events.
794
+ * @todo #261
795
+ * @todo Threshold for click event
796
+ * @protected
797
+ * @param {Event} event - The event arguments.
798
+ */
799
+ Owl.prototype.onDragEnd = function(event) {
800
+ var delta = this.difference(this._drag.pointer, this.pointer(event)),
801
+ stage = this._drag.stage.current,
802
+ direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
803
+
804
+ $(document).off('.owl.core');
805
+
806
+ this.$element.removeClass(this.options.grabClass);
807
+
808
+ if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
809
+ this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
810
+ this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
811
+ this.invalidate('position');
812
+ this.update();
813
+
814
+ this._drag.direction = direction;
815
+
816
+ if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
817
+ this._drag.target.one('click.owl.core', function() { return false; });
818
+ }
819
+ }
820
+
821
+ if (!this.is('dragging')) {
822
+ return;
823
+ }
824
+
825
+ this.leave('dragging');
826
+ this.trigger('dragged');
827
+ };
828
+
829
+ /**
830
+ * Gets absolute position of the closest item for a coordinate.
831
+ * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
832
+ * @protected
833
+ * @param {Number} coordinate - The coordinate in pixel.
834
+ * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
835
+ * @return {Number} - The absolute position of the closest item.
836
+ */
837
+ Owl.prototype.closest = function(coordinate, direction) {
838
+ var position = -1,
839
+ pull = 30,
840
+ width = this.width(),
841
+ coordinates = this.coordinates();
842
+
843
+ if (!this.settings.freeDrag) {
844
+ // check closest item
845
+ $.each(coordinates, $.proxy(function(index, value) {
846
+ // on a left pull, check on current index
847
+ if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) {
848
+ position = index;
849
+ // on a right pull, check on previous index
850
+ // to do so, subtract width from value and set position = index + 1
851
+ } else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) {
852
+ position = index + 1;
853
+ } else if (this.op(coordinate, '<', value)
854
+ && this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
855
+ position = direction === 'left' ? index + 1 : index;
856
+ }
857
+ return position === -1;
858
+ }, this));
859
+ }
860
+
861
+ if (!this.settings.loop) {
862
+ // non loop boundries
863
+ if (this.op(coordinate, '>', coordinates[this.minimum()])) {
864
+ position = coordinate = this.minimum();
865
+ } else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
866
+ position = coordinate = this.maximum();
867
+ }
868
+ }
869
+
870
+ return position;
871
+ };
872
+
873
+ /**
874
+ * Animates the stage.
875
+ * @todo #270
876
+ * @public
877
+ * @param {Number} coordinate - The coordinate in pixels.
878
+ */
879
+ Owl.prototype.animate = function(coordinate) {
880
+ var animate = this.speed() > 0;
881
+
882
+ this.is('animating') && this.onTransitionEnd();
883
+
884
+ if (animate) {
885
+ this.enter('animating');
886
+ this.trigger('translate');
887
+ }
888
+
889
+ if ($.support.transform3d && $.support.transition) {
890
+ this.$stage.css({
891
+ transform: 'translate3d(' + coordinate + 'px,0px,0px)',
892
+ transition: (this.speed() / 1000) + 's'
893
+ });
894
+ } else if (animate) {
895
+ this.$stage.animate({
896
+ left: coordinate + 'px'
897
+ }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
898
+ } else {
899
+ this.$stage.css({
900
+ left: coordinate + 'px'
901
+ });
902
+ }
903
+ };
904
+
905
+ /**
906
+ * Checks whether the carousel is in a specific state or not.
907
+ * @param {String} state - The state to check.
908
+ * @returns {Boolean} - The flag which indicates if the carousel is busy.
909
+ */
910
+ Owl.prototype.is = function(state) {
911
+ return this._states.current[state] && this._states.current[state] > 0;
912
+ };
913
+
914
+ /**
915
+ * Sets the absolute position of the current item.
916
+ * @public
917
+ * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
918
+ * @returns {Number} - The absolute position of the current item.
919
+ */
920
+ Owl.prototype.current = function(position) {
921
+ if (position === undefined) {
922
+ return this._current;
923
+ }
924
+
925
+ if (this._items.length === 0) {
926
+ return undefined;
927
+ }
928
+
929
+ position = this.normalize(position);
930
+
931
+ if (this._current !== position) {
932
+ var event = this.trigger('change', { property: { name: 'position', value: position } });
933
+
934
+ if (event.data !== undefined) {
935
+ position = this.normalize(event.data);
936
+ }
937
+
938
+ this._current = position;
939
+
940
+ this.invalidate('position');
941
+
942
+ this.trigger('changed', { property: { name: 'position', value: this._current } });
943
+ }
944
+
945
+ return this._current;
946
+ };
947
+
948
+ /**
949
+ * Invalidates the given part of the update routine.
950
+ * @param {String} [part] - The part to invalidate.
951
+ * @returns {Array.<String>} - The invalidated parts.
952
+ */
953
+ Owl.prototype.invalidate = function(part) {
954
+ if ($.type(part) === 'string') {
955
+ this._invalidated[part] = true;
956
+ this.is('valid') && this.leave('valid');
957
+ }
958
+ return $.map(this._invalidated, function(v, i) { return i });
959
+ };
960
+
961
+ /**
962
+ * Resets the absolute position of the current item.
963
+ * @public
964
+ * @param {Number} position - The absolute position of the new item.
965
+ */
966
+ Owl.prototype.reset = function(position) {
967
+ position = this.normalize(position);
968
+
969
+ if (position === undefined) {
970
+ return;
971
+ }
972
+
973
+ this._speed = 0;
974
+ this._current = position;
975
+
976
+ this.suppress([ 'translate', 'translated' ]);
977
+
978
+ this.animate(this.coordinates(position));
979
+
980
+ this.release([ 'translate', 'translated' ]);
981
+ };
982
+
983
+ /**
984
+ * Normalizes an absolute or a relative position of an item.
985
+ * @public
986
+ * @param {Number} position - The absolute or relative position to normalize.
987
+ * @param {Boolean} [relative=false] - Whether the given position is relative or not.
988
+ * @returns {Number} - The normalized position.
989
+ */
990
+ Owl.prototype.normalize = function(position, relative) {
991
+ var n = this._items.length,
992
+ m = relative ? 0 : this._clones.length;
993
+
994
+ if (!this.isNumeric(position) || n < 1) {
995
+ position = undefined;
996
+ } else if (position < 0 || position >= n + m) {
997
+ position = ((position - m / 2) % n + n) % n + m / 2;
998
+ }
999
+
1000
+ return position;
1001
+ };
1002
+
1003
+ /**
1004
+ * Converts an absolute position of an item into a relative one.
1005
+ * @public
1006
+ * @param {Number} position - The absolute position to convert.
1007
+ * @returns {Number} - The converted position.
1008
+ */
1009
+ Owl.prototype.relative = function(position) {
1010
+ position -= this._clones.length / 2;
1011
+ return this.normalize(position, true);
1012
+ };
1013
+
1014
+ /**
1015
+ * Gets the maximum position for the current item.
1016
+ * @public
1017
+ * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
1018
+ * @returns {Number}
1019
+ */
1020
+ Owl.prototype.maximum = function(relative) {
1021
+ var settings = this.settings,
1022
+ maximum = this._coordinates.length,
1023
+ iterator,
1024
+ reciprocalItemsWidth,
1025
+ elementWidth;
1026
+
1027
+ if (settings.loop) {
1028
+ maximum = this._clones.length / 2 + this._items.length - 1;
1029
+ } else if (settings.autoWidth || settings.merge) {
1030
+ iterator = this._items.length;
1031
+ reciprocalItemsWidth = this._items[--iterator].width();
1032
+ elementWidth = this.$element.width();
1033
+ while (iterator--) {
1034
+ reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin;
1035
+ if (reciprocalItemsWidth > elementWidth) {
1036
+ break;
1037
+ }
1038
+ }
1039
+ maximum = iterator + 1;
1040
+ } else if (settings.center) {
1041
+ maximum = this._items.length - 1;
1042
+ } else {
1043
+ maximum = this._items.length - settings.items;
1044
+ }
1045
+
1046
+ if (relative) {
1047
+ maximum -= this._clones.length / 2;
1048
+ }
1049
+
1050
+ return Math.max(maximum, 0);
1051
+ };
1052
+
1053
+ /**
1054
+ * Gets the minimum position for the current item.
1055
+ * @public
1056
+ * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
1057
+ * @returns {Number}
1058
+ */
1059
+ Owl.prototype.minimum = function(relative) {
1060
+ return relative ? 0 : this._clones.length / 2;
1061
+ };
1062
+
1063
+ /**
1064
+ * Gets an item at the specified relative position.
1065
+ * @public
1066
+ * @param {Number} [position] - The relative position of the item.
1067
+ * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
1068
+ */
1069
+ Owl.prototype.items = function(position) {
1070
+ if (position === undefined) {
1071
+ return this._items.slice();
1072
+ }
1073
+
1074
+ position = this.normalize(position, true);
1075
+ return this._items[position];
1076
+ };
1077
+
1078
+ /**
1079
+ * Gets an item at the specified relative position.
1080
+ * @public
1081
+ * @param {Number} [position] - The relative position of the item.
1082
+ * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
1083
+ */
1084
+ Owl.prototype.mergers = function(position) {
1085
+ if (position === undefined) {
1086
+ return this._mergers.slice();
1087
+ }
1088
+
1089
+ position = this.normalize(position, true);
1090
+ return this._mergers[position];
1091
+ };
1092
+
1093
+ /**
1094
+ * Gets the absolute positions of clones for an item.
1095
+ * @public
1096
+ * @param {Number} [position] - The relative position of the item.
1097
+ * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
1098
+ */
1099
+ Owl.prototype.clones = function(position) {
1100
+ var odd = this._clones.length / 2,
1101
+ even = odd + this._items.length,
1102
+ map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
1103
+
1104
+ if (position === undefined) {
1105
+ return $.map(this._clones, function(v, i) { return map(i) });
1106
+ }
1107
+
1108
+ return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
1109
+ };
1110
+
1111
+ /**
1112
+ * Sets the current animation speed.
1113
+ * @public
1114
+ * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
1115
+ * @returns {Number} - The current animation speed in milliseconds.
1116
+ */
1117
+ Owl.prototype.speed = function(speed) {
1118
+ if (speed !== undefined) {
1119
+ this._speed = speed;
1120
+ }
1121
+
1122
+ return this._speed;
1123
+ };
1124
+
1125
+ /**
1126
+ * Gets the coordinate of an item.
1127
+ * @todo The name of this method is missleanding.
1128
+ * @public
1129
+ * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
1130
+ * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
1131
+ */
1132
+ Owl.prototype.coordinates = function(position) {
1133
+ var multiplier = 1,
1134
+ newPosition = position - 1,
1135
+ coordinate;
1136
+
1137
+ if (position === undefined) {
1138
+ return $.map(this._coordinates, $.proxy(function(coordinate, index) {
1139
+ return this.coordinates(index);
1140
+ }, this));
1141
+ }
1142
+
1143
+ if (this.settings.center) {
1144
+ if (this.settings.rtl) {
1145
+ multiplier = -1;
1146
+ newPosition = position + 1;
1147
+ }
1148
+
1149
+ coordinate = this._coordinates[position];
1150
+ coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;
1151
+ } else {
1152
+ coordinate = this._coordinates[newPosition] || 0;
1153
+ }
1154
+
1155
+ coordinate = Math.ceil(coordinate);
1156
+
1157
+ return coordinate;
1158
+ };
1159
+
1160
+ /**
1161
+ * Calculates the speed for a translation.
1162
+ * @protected
1163
+ * @param {Number} from - The absolute position of the start item.
1164
+ * @param {Number} to - The absolute position of the target item.
1165
+ * @param {Number} [factor=undefined] - The time factor in milliseconds.
1166
+ * @returns {Number} - The time in milliseconds for the translation.
1167
+ */
1168
+ Owl.prototype.duration = function(from, to, factor) {
1169
+ if (factor === 0) {
1170
+ return 0;
1171
+ }
1172
+
1173
+ return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
1174
+ };
1175
+
1176
+ /**
1177
+ * Slides to the specified item.
1178
+ * @public
1179
+ * @param {Number} position - The position of the item.
1180
+ * @param {Number} [speed] - The time in milliseconds for the transition.
1181
+ */
1182
+ Owl.prototype.to = function(position, speed) {
1183
+ var current = this.current(),
1184
+ revert = null,
1185
+ distance = position - this.relative(current),
1186
+ direction = (distance > 0) - (distance < 0),
1187
+ items = this._items.length,
1188
+ minimum = this.minimum(),
1189
+ maximum = this.maximum();
1190
+
1191
+ if (this.settings.loop) {
1192
+ if (!this.settings.rewind && Math.abs(distance) > items / 2) {
1193
+ distance += direction * -1 * items;
1194
+ }
1195
+
1196
+ position = current + distance;
1197
+ revert = ((position - minimum) % items + items) % items + minimum;
1198
+
1199
+ if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
1200
+ current = revert - distance;
1201
+ position = revert;
1202
+ this.reset(current);
1203
+ }
1204
+ } else if (this.settings.rewind) {
1205
+ maximum += 1;
1206
+ position = (position % maximum + maximum) % maximum;
1207
+ } else {
1208
+ position = Math.max(minimum, Math.min(maximum, position));
1209
+ }
1210
+
1211
+ this.speed(this.duration(current, position, speed));
1212
+ this.current(position);
1213
+
1214
+ if (this.$element.is(':visible')) {
1215
+ this.update();
1216
+ }
1217
+ };
1218
+
1219
+ /**
1220
+ * Slides to the next item.
1221
+ * @public
1222
+ * @param {Number} [speed] - The time in milliseconds for the transition.
1223
+ */
1224
+ Owl.prototype.next = function(speed) {
1225
+ speed = speed || false;
1226
+ this.to(this.relative(this.current()) + 1, speed);
1227
+ };
1228
+
1229
+ /**
1230
+ * Slides to the previous item.
1231
+ * @public
1232
+ * @param {Number} [speed] - The time in milliseconds for the transition.
1233
+ */
1234
+ Owl.prototype.prev = function(speed) {
1235
+ speed = speed || false;
1236
+ this.to(this.relative(this.current()) - 1, speed);
1237
+ };
1238
+
1239
+ /**
1240
+ * Handles the end of an animation.
1241
+ * @protected
1242
+ * @param {Event} event - The event arguments.
1243
+ */
1244
+ Owl.prototype.onTransitionEnd = function(event) {
1245
+
1246
+ // if css2 animation then event object is undefined
1247
+ if (event !== undefined) {
1248
+ event.stopPropagation();
1249
+
1250
+ // Catch only owl-stage transitionEnd event
1251
+ if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
1252
+ return false;
1253
+ }
1254
+ }
1255
+
1256
+ this.leave('animating');
1257
+ this.trigger('translated');
1258
+ };
1259
+
1260
+ /**
1261
+ * Gets viewport width.
1262
+ * @protected
1263
+ * @return {Number} - The width in pixel.
1264
+ */
1265
+ Owl.prototype.viewport = function() {
1266
+ var width;
1267
+ if (this.options.responsiveBaseElement !== window) {
1268
+ width = $(this.options.responsiveBaseElement).width();
1269
+ } else if (window.innerWidth) {
1270
+ width = window.innerWidth;
1271
+ } else if (document.documentElement && document.documentElement.clientWidth) {
1272
+ width = document.documentElement.clientWidth;
1273
+ } else {
1274
+ throw 'Can not detect viewport width.';
1275
+ }
1276
+ return width;
1277
+ };
1278
+
1279
+ /**
1280
+ * Replaces the current content.
1281
+ * @public
1282
+ * @param {HTMLElement|jQuery|String} content - The new content.
1283
+ */
1284
+ Owl.prototype.replace = function(content) {
1285
+ this.$stage.empty();
1286
+ this._items = [];
1287
+
1288
+ if (content) {
1289
+ content = (content instanceof jQuery) ? content : $(content);
1290
+ }
1291
+
1292
+ if (this.settings.nestedItemSelector) {
1293
+ content = content.find('.' + this.settings.nestedItemSelector);
1294
+ }
1295
+
1296
+ content.filter(function() {
1297
+ return this.nodeType === 1;
1298
+ }).each($.proxy(function(index, item) {
1299
+ item = this.prepare(item);
1300
+ this.$stage.append(item);
1301
+ this._items.push(item);
1302
+ this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
1303
+ }, this));
1304
+
1305
+ this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
1306
+
1307
+ this.invalidate('items');
1308
+ };
1309
+
1310
+ /**
1311
+ * Adds an item.
1312
+ * @todo Use `item` instead of `content` for the event arguments.
1313
+ * @public
1314
+ * @param {HTMLElement|jQuery|String} content - The item content to add.
1315
+ * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
1316
+ */
1317
+ Owl.prototype.add = function(content, position) {
1318
+ var current = this.relative(this._current);
1319
+
1320
+ position = position === undefined ? this._items.length : this.normalize(position, true);
1321
+ content = content instanceof jQuery ? content : $(content);
1322
+
1323
+ this.trigger('add', { content: content, position: position });
1324
+
1325
+ content = this.prepare(content);
1326
+
1327
+ if (this._items.length === 0 || position === this._items.length) {
1328
+ this._items.length === 0 && this.$stage.append(content);
1329
+ this._items.length !== 0 && this._items[position - 1].after(content);
1330
+ this._items.push(content);
1331
+ this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
1332
+ } else {
1333
+ this._items[position].before(content);
1334
+ this._items.splice(position, 0, content);
1335
+ this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
1336
+ }
1337
+
1338
+ this._items[current] && this.reset(this._items[current].index());
1339
+
1340
+ this.invalidate('items');
1341
+
1342
+ this.trigger('added', { content: content, position: position });
1343
+ };
1344
+
1345
+ /**
1346
+ * Removes an item by its position.
1347
+ * @todo Use `item` instead of `content` for the event arguments.
1348
+ * @public
1349
+ * @param {Number} position - The relative position of the item to remove.
1350
+ */
1351
+ Owl.prototype.remove = function(position) {
1352
+ position = this.normalize(position, true);
1353
+
1354
+ if (position === undefined) {
1355
+ return;
1356
+ }
1357
+
1358
+ this.trigger('remove', { content: this._items[position], position: position });
1359
+
1360
+ this._items[position].remove();
1361
+ this._items.splice(position, 1);
1362
+ this._mergers.splice(position, 1);
1363
+
1364
+ this.invalidate('items');
1365
+
1366
+ this.trigger('removed', { content: null, position: position });
1367
+ };
1368
+
1369
+ /**
1370
+ * Preloads images with auto width.
1371
+ * @todo Replace by a more generic approach
1372
+ * @protected
1373
+ */
1374
+ Owl.prototype.preloadAutoWidthImages = function(images) {
1375
+ images.each($.proxy(function(i, element) {
1376
+ this.enter('pre-loading');
1377
+ element = $(element);
1378
+ $(new Image()).one('load', $.proxy(function(e) {
1379
+ element.attr('src', e.target.src);
1380
+ element.css('opacity', 1);
1381
+ this.leave('pre-loading');
1382
+ !this.is('pre-loading') && !this.is('initializing') && this.refresh();
1383
+ }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
1384
+ }, this));
1385
+ };
1386
+
1387
+ /**
1388
+ * Destroys the carousel.
1389
+ * @public
1390
+ */
1391
+ Owl.prototype.destroy = function() {
1392
+
1393
+ this.$element.off('.owl.core');
1394
+ this.$stage.off('.owl.core');
1395
+ $(document).off('.owl.core');
1396
+
1397
+ if (this.settings.responsive !== false) {
1398
+ window.clearTimeout(this.resizeTimer);
1399
+ this.off(window, 'resize', this._handlers.onThrottledResize);
1400
+ }
1401
+
1402
+ for (var i in this._plugins) {
1403
+ this._plugins[i].destroy();
1404
+ }
1405
+
1406
+ this.$stage.children('.cloned').remove();
1407
+
1408
+ this.$stage.unwrap();
1409
+ this.$stage.children().contents().unwrap();
1410
+ this.$stage.children().unwrap();
1411
+
1412
+ this.$element
1413
+ .removeClass(this.options.refreshClass)
1414
+ .removeClass(this.options.loadingClass)
1415
+ .removeClass(this.options.loadedClass)
1416
+ .removeClass(this.options.rtlClass)
1417
+ .removeClass(this.options.dragClass)
1418
+ .removeClass(this.options.grabClass)
1419
+ .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
1420
+ .removeData('owl.carousel');
1421
+ };
1422
+
1423
+ /**
1424
+ * Operators to calculate right-to-left and left-to-right.
1425
+ * @protected
1426
+ * @param {Number} [a] - The left side operand.
1427
+ * @param {String} [o] - The operator.
1428
+ * @param {Number} [b] - The right side operand.
1429
+ */
1430
+ Owl.prototype.op = function(a, o, b) {
1431
+ var rtl = this.settings.rtl;
1432
+ switch (o) {
1433
+ case '<':
1434
+ return rtl ? a > b : a < b;
1435
+ case '>':
1436
+ return rtl ? a < b : a > b;
1437
+ case '>=':
1438
+ return rtl ? a <= b : a >= b;
1439
+ case '<=':
1440
+ return rtl ? a >= b : a <= b;
1441
+ default:
1442
+ break;
1443
+ }
1444
+ };
1445
+
1446
+ /**
1447
+ * Attaches to an internal event.
1448
+ * @protected
1449
+ * @param {HTMLElement} element - The event source.
1450
+ * @param {String} event - The event name.
1451
+ * @param {Function} listener - The event handler to attach.
1452
+ * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
1453
+ */
1454
+ Owl.prototype.on = function(element, event, listener, capture) {
1455
+ if (element.addEventListener) {
1456
+ element.addEventListener(event, listener, capture);
1457
+ } else if (element.attachEvent) {
1458
+ element.attachEvent('on' + event, listener);
1459
+ }
1460
+ };
1461
+
1462
+ /**
1463
+ * Detaches from an internal event.
1464
+ * @protected
1465
+ * @param {HTMLElement} element - The event source.
1466
+ * @param {String} event - The event name.
1467
+ * @param {Function} listener - The attached event handler to detach.
1468
+ * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
1469
+ */
1470
+ Owl.prototype.off = function(element, event, listener, capture) {
1471
+ if (element.removeEventListener) {
1472
+ element.removeEventListener(event, listener, capture);
1473
+ } else if (element.detachEvent) {
1474
+ element.detachEvent('on' + event, listener);
1475
+ }
1476
+ };
1477
+
1478
+ /**
1479
+ * Triggers a public event.
1480
+ * @todo Remove `status`, `relatedTarget` should be used instead.
1481
+ * @protected
1482
+ * @param {String} name - The event name.
1483
+ * @param {*} [data=null] - The event data.
1484
+ * @param {String} [namespace=carousel] - The event namespace.
1485
+ * @param {String} [state] - The state which is associated with the event.
1486
+ * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
1487
+ * @returns {Event} - The event arguments.
1488
+ */
1489
+ Owl.prototype.trigger = function(name, data, namespace, state, enter) {
1490
+ var status = {
1491
+ item: { count: this._items.length, index: this.current() }
1492
+ }, handler = $.camelCase(
1493
+ $.grep([ 'on', name, namespace ], function(v) { return v })
1494
+ .join('-').toLowerCase()
1495
+ ), event = $.Event(
1496
+ [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
1497
+ $.extend({ relatedTarget: this }, status, data)
1498
+ );
1499
+
1500
+ if (!this._supress[name]) {
1501
+ $.each(this._plugins, function(name, plugin) {
1502
+ if (plugin.onTrigger) {
1503
+ plugin.onTrigger(event);
1504
+ }
1505
+ });
1506
+
1507
+ this.register({ type: Owl.Type.Event, name: name });
1508
+ this.$element.trigger(event);
1509
+
1510
+ if (this.settings && typeof this.settings[handler] === 'function') {
1511
+ this.settings[handler].call(this, event);
1512
+ }
1513
+ }
1514
+
1515
+ return event;
1516
+ };
1517
+
1518
+ /**
1519
+ * Enters a state.
1520
+ * @param name - The state name.
1521
+ */
1522
+ Owl.prototype.enter = function(name) {
1523
+ $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
1524
+ if (this._states.current[name] === undefined) {
1525
+ this._states.current[name] = 0;
1526
+ }
1527
+
1528
+ this._states.current[name]++;
1529
+ }, this));
1530
+ };
1531
+
1532
+ /**
1533
+ * Leaves a state.
1534
+ * @param name - The state name.
1535
+ */
1536
+ Owl.prototype.leave = function(name) {
1537
+ $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
1538
+ this._states.current[name]--;
1539
+ }, this));
1540
+ };
1541
+
1542
+ /**
1543
+ * Registers an event or state.
1544
+ * @public
1545
+ * @param {Object} object - The event or state to register.
1546
+ */
1547
+ Owl.prototype.register = function(object) {
1548
+ if (object.type === Owl.Type.Event) {
1549
+ if (!$.event.special[object.name]) {
1550
+ $.event.special[object.name] = {};
1551
+ }
1552
+
1553
+ if (!$.event.special[object.name].owl) {
1554
+ var _default = $.event.special[object.name]._default;
1555
+ $.event.special[object.name]._default = function(e) {
1556
+ if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
1557
+ return _default.apply(this, arguments);
1558
+ }
1559
+ return e.namespace && e.namespace.indexOf('owl') > -1;
1560
+ };
1561
+ $.event.special[object.name].owl = true;
1562
+ }
1563
+ } else if (object.type === Owl.Type.State) {
1564
+ if (!this._states.tags[object.name]) {
1565
+ this._states.tags[object.name] = object.tags;
1566
+ } else {
1567
+ this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
1568
+ }
1569
+
1570
+ this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
1571
+ return $.inArray(tag, this._states.tags[object.name]) === i;
1572
+ }, this));
1573
+ }
1574
+ };
1575
+
1576
+ /**
1577
+ * Suppresses events.
1578
+ * @protected
1579
+ * @param {Array.<String>} events - The events to suppress.
1580
+ */
1581
+ Owl.prototype.suppress = function(events) {
1582
+ $.each(events, $.proxy(function(index, event) {
1583
+ this._supress[event] = true;
1584
+ }, this));
1585
+ };
1586
+
1587
+ /**
1588
+ * Releases suppressed events.
1589
+ * @protected
1590
+ * @param {Array.<String>} events - The events to release.
1591
+ */
1592
+ Owl.prototype.release = function(events) {
1593
+ $.each(events, $.proxy(function(index, event) {
1594
+ delete this._supress[event];
1595
+ }, this));
1596
+ };
1597
+
1598
+ /**
1599
+ * Gets unified pointer coordinates from event.
1600
+ * @todo #261
1601
+ * @protected
1602
+ * @param {Event} - The `mousedown` or `touchstart` event.
1603
+ * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
1604
+ */
1605
+ Owl.prototype.pointer = function(event) {
1606
+ var result = { x: null, y: null };
1607
+
1608
+ event = event.originalEvent || event || window.event;
1609
+
1610
+ event = event.touches && event.touches.length ?
1611
+ event.touches[0] : event.changedTouches && event.changedTouches.length ?
1612
+ event.changedTouches[0] : event;
1613
+
1614
+ if (event.pageX) {
1615
+ result.x = event.pageX;
1616
+ result.y = event.pageY;
1617
+ } else {
1618
+ result.x = event.clientX;
1619
+ result.y = event.clientY;
1620
+ }
1621
+
1622
+ return result;
1623
+ };
1624
+
1625
+ /**
1626
+ * Determines if the input is a Number or something that can be coerced to a Number
1627
+ * @protected
1628
+ * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested
1629
+ * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number
1630
+ */
1631
+ Owl.prototype.isNumeric = function(number) {
1632
+ return !isNaN(parseFloat(number));
1633
+ };
1634
+
1635
+ /**
1636
+ * Gets the difference of two vectors.
1637
+ * @todo #261
1638
+ * @protected
1639
+ * @param {Object} - The first vector.
1640
+ * @param {Object} - The second vector.
1641
+ * @returns {Object} - The difference.
1642
+ */
1643
+ Owl.prototype.difference = function(first, second) {
1644
+ return {
1645
+ x: first.x - second.x,
1646
+ y: first.y - second.y
1647
+ };
1648
+ };
1649
+
1650
+ /**
1651
+ * The jQuery Plugin for the Owl Carousel
1652
+ * @todo Navigation plugin `next` and `prev`
1653
+ * @public
1654
+ */
1655
+ $.fn.owlCarousel = function(option) {
1656
+ var args = Array.prototype.slice.call(arguments, 1);
1657
+
1658
+ return this.each(function() {
1659
+ var $this = $(this),
1660
+ data = $this.data('owl.carousel');
1661
+
1662
+ if (!data) {
1663
+ data = new Owl(this, typeof option == 'object' && option);
1664
+ $this.data('owl.carousel', data);
1665
+
1666
+ $.each([
1667
+ 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
1668
+ ], function(i, event) {
1669
+ data.register({ type: Owl.Type.Event, name: event });
1670
+ data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
1671
+ if (e.namespace && e.relatedTarget !== this) {
1672
+ this.suppress([ event ]);
1673
+ data[event].apply(this, [].slice.call(arguments, 1));
1674
+ this.release([ event ]);
1675
+ }
1676
+ }, data));
1677
+ });
1678
+ }
1679
+
1680
+ if (typeof option == 'string' && option.charAt(0) !== '_') {
1681
+ data[option].apply(data, args);
1682
+ }
1683
+ });
1684
+ };
1685
+
1686
+ /**
1687
+ * The constructor for the jQuery Plugin
1688
+ * @public
1689
+ */
1690
+ $.fn.owlCarousel.Constructor = Owl;
1691
+
1692
+ })(window.Zepto || window.jQuery, window, document);