|
1 | 1 | <template>
|
2 |
| - <div class="agile" :class="{'agile--fade': fade_}"> |
| 2 | + <div class="agile" :class="{'agile--fade': settings.fade}"> |
3 | 3 | <div class="agile__list">
|
4 | 4 | <div class="agile__track"
|
5 |
| - :style="{width: width.track + 'px', transform: 'translate(-' + transform + 'px)', transition: 'transform ' + timing_ + ' ' + transitionDelay + 'ms'}"> |
| 5 | + :style="{width: width.track + 'px', transform: 'translate(-' + transform + 'px)', transition: 'transform ' + settings.timing + ' ' + transitionDelay + 'ms'}"> |
6 | 6 | <slot></slot>
|
7 | 7 | </div>
|
8 | 8 |
|
9 |
| - <ul v-if="dots_" class="agile__dots"> |
| 9 | + <ul v-if="settings.dots" class="agile__dots"> |
10 | 10 | <li v-for="n in slidesCount" class="agile__dot"
|
11 | 11 | :class="{'agile__dot--current': n - 1 === currentSlide}">
|
12 | 12 | <button @click="setSlide(n - 1)">{{n}}</button>
|
13 | 13 | </li>
|
14 | 14 | </ul>
|
15 | 15 |
|
16 |
| - <button v-if="arrows_" class="agile__arrow agile__arrow--prev" |
17 |
| - :disabled="currentSlide === 0 && !infinite_" @click="prevSlide" v-html="arrow_"> |
| 16 | + <button v-if="settings.arrows" class="agile__arrow agile__arrow--prev" |
| 17 | + :disabled="currentSlide === 0 && !settings.infinite" @click="prevSlide" v-html="settings.arrow"> |
18 | 18 | </button>
|
19 |
| - <button v-if="arrows_" class="agile__arrow agile__arrow--next" |
20 |
| - :disabled="currentSlide === slidesCount - 1 && !infinite_" @click="nextSlide" v-html="arrow_"> |
| 19 | + <button v-if="settings.arrows" class="agile__arrow agile__arrow--next" |
| 20 | + :disabled="currentSlide === slidesCount - 1 && !settings.infinite" @click="nextSlide" |
| 21 | + v-html="settings.arrow"> |
21 | 22 | </button>
|
22 | 23 | </div>
|
23 | 24 | </div>
|
|
63 | 64 | default: true
|
64 | 65 | },
|
65 | 66 |
|
| 67 | + mobileFirst: { |
| 68 | + type: Boolean, |
| 69 | + default: true |
| 70 | + }, |
| 71 | +
|
66 | 72 | options: {
|
67 | 73 | type: Object,
|
68 | 74 | default: function () {
|
|
80 | 86 | default: true
|
81 | 87 | },
|
82 | 88 |
|
| 89 | + responsive: { |
| 90 | + type: Object, |
| 91 | + default: function () { |
| 92 | + return null |
| 93 | + } |
| 94 | + }, |
| 95 | +
|
83 | 96 | speed: {
|
84 | 97 | type: Number,
|
85 | 98 | default: 300
|
|
117 | 130 | track: 0
|
118 | 131 | },
|
119 | 132 | slidesToShow: 1,
|
120 |
| - arrow_: this.arrow, |
121 |
| - arrows_: this.arrows, |
122 |
| - autoplay_: this.autoplay, |
123 |
| - autoplaySpeed_: this.autoplaySpeed, |
124 |
| - dots_: this.dots, |
125 |
| - fade_: this.fade, |
126 |
| - infinite_: this.infinite, |
127 |
| - pauseOnDotsHover_: this.pauseOnDotsHover, |
128 |
| - pauseOnHover_: this.pauseOnHover, |
129 |
| - speed_: this.speed, |
130 |
| - timing_: this.timing |
| 133 | + defaultSettings: { |
| 134 | + arrow: this.arrow, |
| 135 | + arrows: this.arrows, |
| 136 | + autoplay: this.autoplay, |
| 137 | + autoplaySpeed: this.autoplaySpeed, |
| 138 | + dots: this.dots, |
| 139 | + fade: this.fade, |
| 140 | + infinite: this.infinite, |
| 141 | + mobileFirst: this.mobileFirst, |
| 142 | + pauseOnDotsHover: this.pauseOnDotsHover, |
| 143 | + pauseOnHover: this.pauseOnHover, |
| 144 | + responsive: this.responsive, |
| 145 | + speed: this.speed, |
| 146 | + timing: this.timing |
| 147 | + }, |
| 148 | + settings: {} |
131 | 149 | }
|
132 | 150 | },
|
133 | 151 |
|
134 |
| - mounted () { |
| 152 | + beforeMount () { |
135 | 153 | // Read settings from options object
|
136 | 154 | if (this.options) {
|
137 | 155 | for (let key in this.options) {
|
138 |
| - this[key + '_'] = this.options[key] |
| 156 | + this.defaultSettings[key] = this.options[key] |
139 | 157 | }
|
140 | 158 | }
|
141 | 159 |
|
| 160 | + // Sort breakpoints |
| 161 | + if (this.defaultSettings.responsive) { |
| 162 | + this.defaultSettings.responsive.sort(this.compare) |
| 163 | + } |
| 164 | +
|
| 165 | + // Set first load settings |
| 166 | + Object.assign(this.settings, this.defaultSettings) |
| 167 | +
|
142 | 168 | // Protection against contradictory settings
|
143 |
| - if (this.autoplay_) { |
144 |
| - this.infinite_ = true |
| 169 | + if (this.settings.autoplay) { |
| 170 | + this.settings.infinite = true |
145 | 171 | }
|
146 | 172 |
|
147 |
| - if (this.pauseOnDotsHover_) { |
148 |
| - this.dots_ = true |
| 173 | + if (this.settings.pauseOnDotsHover) { |
| 174 | + this.settings.dots = true |
149 | 175 | }
|
| 176 | + }, |
150 | 177 |
|
| 178 | + mounted () { |
151 | 179 | // Prepare list
|
152 | 180 | this.el.list = this.$el.getElementsByClassName('agile__list')[0]
|
153 | 181 |
|
154 | 182 | // Prepare dots
|
155 |
| - if (this.dots_) { |
| 183 | + if (this.settings.dots) { |
156 | 184 | this.el.dots = this.$el.getElementsByClassName('agile__dots')[0].children
|
157 | 185 | }
|
158 | 186 |
|
159 | 187 | // Prepare slides
|
160 | 188 | this.el.slides = this.$el.getElementsByClassName('agile__track')[0].children
|
161 | 189 | this.slidesCount = this.el.slides.length
|
162 | 190 |
|
163 |
| - if (this.infinite_ && !this.fade_) { |
| 191 | + if (this.settings.infinite && !this.settings.fade) { |
164 | 192 | this.allSlidesCount = this.slidesCount + 2
|
165 | 193 | } else {
|
166 | 194 | this.allSlidesCount = this.slidesCount
|
|
170 | 198 | this.el.slides[i].classList.add('agile__slide')
|
171 | 199 |
|
172 | 200 | // Prepare slides for fade mode
|
173 |
| - if (this.fade_) { |
| 201 | + if (this.settings.fade) { |
174 | 202 | this.el.slides[i].style.transition = 'opacity ' + this.timing + ' ' + this.speed + 'ms'
|
175 | 203 | }
|
176 | 204 | }
|
|
179 | 207 | this.el.track = this.$el.getElementsByClassName('agile__track')[0]
|
180 | 208 |
|
181 | 209 | // Prepare infinity mode
|
182 |
| - if (this.infinite_ && !this.fade_) { |
| 210 | + if (this.settings.infinite && !this.settings.fade) { |
183 | 211 | let firstSlide = this.el.track.firstChild.cloneNode(true)
|
184 | 212 | let lastSlide = this.el.track.lastChild.cloneNode(true)
|
185 | 213 |
|
|
191 | 219 | }
|
192 | 220 |
|
193 | 221 | // Prepare autoplay
|
194 |
| - if (this.autoplay_) { |
| 222 | + if (this.settings.autoplay) { |
195 | 223 | this.startAutoplay()
|
196 | 224 | }
|
197 | 225 |
|
|
213 | 241 | }
|
214 | 242 |
|
215 | 243 | // Autoplay
|
216 |
| - if (this.autoplay_) { |
217 |
| - if (this.pauseOnHover_) { |
| 244 | + if (this.settings.autoplay) { |
| 245 | + if (this.settings.pauseOnHover) { |
218 | 246 | this.el.track.addEventListener('mouseover', this.stopAutoplay)
|
219 | 247 | this.el.track.addEventListener('mouseout', this.startAutoplay)
|
220 | 248 | }
|
221 | 249 |
|
222 |
| - if (this.pauseOnDotsHover_) { |
| 250 | + if (this.settings.pauseOnDotsHover) { |
223 | 251 | for (let i = 0; i < this.slidesCount; ++i) {
|
224 | 252 | this.el.dots[i].addEventListener('mouseover', this.stopAutoplay)
|
225 | 253 | this.el.dots[i].addEventListener('mouseout', this.startAutoplay)
|
|
241 | 269 | this.el.track.removeEventListener('mousemove', this.handleMouseMove)
|
242 | 270 | }
|
243 | 271 |
|
244 |
| - if (this.autoplay_) { |
245 |
| - if (this.pauseOnHover_) { |
| 272 | + if (this.settings.autoplay) { |
| 273 | + if (this.settings.pauseOnHover) { |
246 | 274 | this.el.track.removeEventListener('mouseover', this.stopAutoplay)
|
247 | 275 | this.el.track.removeEventListener('mouseout', this.startAutoplay)
|
248 | 276 | }
|
249 | 277 |
|
250 |
| - if (this.pauseOnDotsHover_) { |
| 278 | + if (this.settings.pauseOnDotsHover) { |
251 | 279 | for (let i = 0; i < this.slidesCount; ++i) {
|
252 | 280 | this.el.dots[i].removeEventListener('mouseover', this.stopAutoplay)
|
253 | 281 | this.el.dots[i].removeEventListener('mouseout', this.startAutoplay)
|
|
265 | 293 | }
|
266 | 294 | },
|
267 | 295 |
|
| 296 | + compare (a, b) { |
| 297 | + if (a.breakpoint < b.breakpoint) { |
| 298 | + return this.defaultSettings.mobileFirst ? -1 : 1 |
| 299 | + } else if (a.breakpoint > b.breakpoint) { |
| 300 | + return this.defaultSettings.mobileFirst ? 1 : -1 |
| 301 | + } else { |
| 302 | + return 0 |
| 303 | + } |
| 304 | + }, |
| 305 | +
|
268 | 306 | handleMouseDown (e) {
|
269 | 307 | if (!e.touches) {
|
270 | 308 | e.preventDefault()
|
|
321 | 359 |
|
322 | 360 | setSlide (n, transition = true, autoplayTimeout = true) {
|
323 | 361 | // Reset autoplay timeout and set new
|
324 |
| - if (this.autoplay_ && autoplayTimeout) { |
| 362 | + if (this.settings.autoplay && autoplayTimeout) { |
325 | 363 | this.stopAutoplay()
|
326 | 364 | this.startAutoplay()
|
327 | 365 | }
|
328 | 366 |
|
329 |
| - if (this.fade_) { |
| 367 | + if (this.settings.fade) { |
330 | 368 | // Disable transition for initial slide
|
331 | 369 | if (transition === false) {
|
332 | 370 | this.el.slides[n].style.transition = '0ms'
|
|
340 | 378 | this.el.slides[i].classList.remove('agile__slide--expiring')
|
341 | 379 | }
|
342 | 380 |
|
343 |
| - if (this.infinite_ && n < 0) { |
| 381 | + if (this.settings.infinite && n < 0) { |
344 | 382 | n = this.slidesCount - 1
|
345 | 383 | } else if (n >= this.slidesCount) {
|
346 | 384 | n = 0
|
|
352 | 390 |
|
353 | 391 | setTimeout(() => {
|
354 | 392 | this.el.slides[e].classList.remove('agile__slide--expiring')
|
355 |
| - }, this.speed_) |
| 393 | + }, this.settings.speed) |
356 | 394 |
|
357 | 395 | this.transform = 0
|
358 | 396 | } else {
|
|
363 | 401 | this.el.slides[i].classList.remove('agile__slide--active')
|
364 | 402 | }
|
365 | 403 |
|
366 |
| - if (this.infinite_ && !this.fade_) { |
| 404 | + if (this.settings.infinite && !this.settings.fade) { |
367 | 405 | this.transform += this.width.slide
|
368 | 406 | this.addActiveClass(n + 1)
|
369 | 407 | } else {
|
|
376 | 414 | this.transitionDelay = this.speed
|
377 | 415 | }
|
378 | 416 |
|
379 |
| - if (this.infinite_ && n < 0) { |
| 417 | + if (this.settings.infinite && n < 0) { |
380 | 418 | this.currentSlide = this.slidesCount - 1
|
381 | 419 |
|
382 | 420 | setTimeout(() => {
|
383 | 421 | this.setSlide(this.slidesCount - 1, false)
|
384 | 422 | }, this.speed)
|
385 |
| - } else if (this.infinite_ && n >= this.slidesCount) { |
| 423 | + } else if (this.settings.infinite && n >= this.slidesCount) { |
386 | 424 | this.currentSlide = 0
|
387 | 425 |
|
388 | 426 | setTimeout(() => {
|
389 | 427 | this.setSlide(0, false)
|
390 |
| - }, this.speed_) |
| 428 | + }, this.settings.speed) |
391 | 429 | } else {
|
392 | 430 | this.currentSlide = n
|
393 | 431 | }
|
|
404 | 442 |
|
405 | 443 | watch: {
|
406 | 444 | width () {
|
| 445 | + // Responsive |
| 446 | + if (this.defaultSettings.responsive) { |
| 447 | + let responsiveSettings = {} |
| 448 | + Object.assign(responsiveSettings, this.defaultSettings) |
| 449 | +
|
| 450 | + responsiveSettings.responsive.forEach((responsive) => { |
| 451 | + if (this.defaultSettings.mobileFirst) { |
| 452 | + if (responsive.breakpoint < this.width.document) { |
| 453 | + for (let key in responsive.settings) { |
| 454 | + responsiveSettings[key] = responsive.settings[key] |
| 455 | + } |
| 456 | + } |
| 457 | + } else { |
| 458 | + if (responsive.breakpoint > this.width.document) { |
| 459 | + for (let key in responsive.settings) { |
| 460 | + responsiveSettings[key] = responsive.settings[key] |
| 461 | + } |
| 462 | + } |
| 463 | + } |
| 464 | + }) |
| 465 | +
|
| 466 | + Object.assign(this.settings, responsiveSettings) |
| 467 | + } |
| 468 | +
|
407 | 469 | // Actions on document resize
|
408 | 470 | for (let i = 0; i < this.allSlidesCount; ++i) {
|
409 | 471 | this.el.slides[i].style.width = this.width.container + 'px'
|
410 | 472 |
|
411 | 473 | // Prepare slides for fade mode
|
412 |
| - if (this.fade_) { |
| 474 | + if (this.settings.fade) { |
413 | 475 | this.el.slides[i].style.transform = 'translate(-' + i * this.width.slide + 'px)'
|
414 | 476 | }
|
415 | 477 | }
|
|
425 | 487 | }
|
426 | 488 |
|
427 | 489 | if (this.dragDistance > this.swipeDistance) {
|
428 |
| - if (!this.infinite_ && this.currentSlide === 0) { |
| 490 | + if (!this.settings.infinite && this.currentSlide === 0) { |
429 | 491 | return
|
430 | 492 | }
|
431 | 493 |
|
|
434 | 496 | }
|
435 | 497 |
|
436 | 498 | if (this.dragDistance < -1 * this.swipeDistance) {
|
437 |
| - if (!this.infinite_ && this.currentSlide === this.slidesCount - 1) { |
| 499 | + if (!this.settings.infinite && this.currentSlide === this.slidesCount - 1) { |
438 | 500 | return
|
439 | 501 | }
|
440 | 502 |
|
|
0 commit comments