shibori 1.0.0.beta1

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