Project

General

Profile

1
/*! UIkit 2.27.5 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */
2
(function(addon) {
3

    
4
    var component;
5

    
6
    if (window.UIkit2) {
7
        component = addon(UIkit2);
8
    }
9

    
10
    if (typeof define == 'function' && define.amd) {
11
        define('uikit-slider', ['uikit'], function(){
12
            return component || addon(UIkit2);
13
        });
14
    }
15

    
16
})(function(UI){
17

    
18
    "use strict";
19

    
20
    var dragging, delayIdle, anchor, dragged, store = {};
21

    
22
    UI.component('slider', {
23

    
24
        defaults: {
25
            center           : false,
26
            threshold        : 10,
27
            infinite         : true,
28
            autoplay         : false,
29
            autoplayInterval : 7000,
30
            pauseOnHover     : true,
31
            activecls        : 'uk-active'
32
        },
33

    
34
        boot:  function() {
35

    
36
            // init code
37
            UI.ready(function(context) {
38

    
39
                setTimeout(function(){
40

    
41
                    UI.$('[data-uk-slider]', context).each(function(){
42

    
43
                        var ele = UI.$(this);
44

    
45
                        if (!ele.data('slider')) {
46
                            UI.slider(ele, UI.Utils.options(ele.attr('data-uk-slider')));
47
                        }
48
                    });
49

    
50
                }, 0);
51
            });
52
        },
53

    
54
        init: function() {
55

    
56
            var $this = this;
57

    
58
            this.container = this.element.find('.uk-slider');
59
            this.focus     = 0;
60

    
61
            UI.$win.on('resize load', UI.Utils.debounce(function() {
62
                $this.update(true);
63
            }, 100));
64

    
65
            this.on('click.uk.slider', '[data-uk-slider-item]', function(e) {
66

    
67
                e.preventDefault();
68

    
69
                var item = UI.$(this).attr('data-uk-slider-item');
70

    
71
                if ($this.focus == item) return;
72

    
73
                // stop autoplay
74
                $this.stop();
75

    
76
                switch(item) {
77
                    case 'next':
78
                    case 'previous':
79
                        $this[item=='next' ? 'next':'previous']();
80
                        break;
81
                    default:
82
                        $this.updateFocus(parseInt(item, 10));
83
                }
84
            });
85

    
86
            this.container.on({
87

    
88
                'touchstart mousedown': function(evt) {
89

    
90
                    if (evt.originalEvent && evt.originalEvent.touches) {
91
                        evt = evt.originalEvent.touches[0];
92
                    }
93

    
94
                    // ignore right click button
95
                    if (evt.button && evt.button==2 || !$this.active) {
96
                        return;
97
                    }
98

    
99
                    // stop autoplay
100
                    $this.stop();
101

    
102
                    anchor  = UI.$(evt.target).is('a') ? UI.$(evt.target) : UI.$(evt.target).parents('a:first');
103
                    dragged = false;
104

    
105
                    if (anchor.length) {
106

    
107
                        anchor.one('click', function(e){
108
                            if (dragged) e.preventDefault();
109
                        });
110
                    }
111

    
112
                    delayIdle = function(e) {
113

    
114
                        dragged  = true;
115
                        dragging = $this;
116
                        store    = {
117
                            touchx : parseInt(e.pageX, 10),
118
                            dir    : 1,
119
                            focus  : $this.focus,
120
                            base   : $this.options.center ? 'center':'area'
121
                        };
122

    
123
                        if (e.originalEvent && e.originalEvent.touches) {
124
                            e = e.originalEvent.touches[0];
125
                        }
126

    
127
                        dragging.element.data({
128
                            'pointer-start': {x: parseInt(e.pageX, 10), y: parseInt(e.pageY, 10)},
129
                            'pointer-pos-start': $this.pos
130
                        });
131

    
132
                        $this.container.addClass('uk-drag');
133

    
134
                        delayIdle = false;
135
                    };
136

    
137
                    delayIdle.x         = parseInt(evt.pageX, 10);
138
                    delayIdle.threshold = $this.options.threshold;
139

    
140
                },
141

    
142
                mouseenter: function() { if ($this.options.pauseOnHover) $this.hovering = true;  },
143
                mouseleave: function() { $this.hovering = false; }
144
            });
145

    
146
            this.update(true);
147

    
148
            this.on('display.uk.check', function(){
149
                if ($this.element.is(":visible")) {
150
                    $this.update(true);
151
                }
152
            });
153

    
154
            // prevent dragging links + images
155
            this.element.find('a,img').attr('draggable', 'false');
156

    
157
            // Set autoplay
158
            if (this.options.autoplay) {
159
                this.start();
160
            }
161

    
162
            UI.domObserve(this.element, function(e) {
163
                if ($this.element.children(':not([data-slider-slide])').length) {
164
                    $this.update(true);
165
                }
166
            });
167

    
168
        },
169

    
170
        update: function(focus) {
171

    
172
            var $this = this, pos = 0, maxheight = 0, item, width, cwidth, size;
173

    
174
            this.items = this.container.children().filter(':visible');
175
            this.vp    = this.element[0].getBoundingClientRect().width;
176

    
177
            this.container.css({'min-width': '', 'min-height': ''});
178

    
179
            this.items.each(function(idx){
180

    
181
                item      = UI.$(this).attr('data-slider-slide', idx);
182
                size      = item.css({'left': '', 'width':''})[0].getBoundingClientRect();
183
                width     = size.width;
184
                cwidth    = item.width();
185
                maxheight = Math.max(maxheight, size.height);
186

    
187
                item.css({'left': pos, 'width':width}).data({'idx':idx, 'left': pos, 'width': width, 'cwidth':cwidth, 'area': (pos+width), 'center':(pos - ($this.vp/2 - cwidth/2))});
188

    
189
                pos += width;
190
            });
191

    
192
            this.container.css({'min-width': pos, 'min-height': maxheight});
193

    
194
            if (this.options.infinite && (pos <= (2*this.vp) || this.items.length < 5) && !this.itemsResized) {
195

    
196
                // fill with cloned items
197
                this.container.children().each(function(idx){
198
                   $this.container.append($this.items.eq(idx).clone(true).attr('id', ''));
199
                }).each(function(idx){
200
                   $this.container.append($this.items.eq(idx).clone(true).attr('id', ''));
201
                });
202

    
203
                this.itemsResized = true;
204

    
205
                return this.update();
206
            }
207

    
208
            this.cw     = pos;
209
            this.pos    = 0;
210
            this.active = pos >= this.vp;
211

    
212
            this.container.css({
213
                '-ms-transform': '',
214
                '-webkit-transform': '',
215
                'transform': ''
216
            });
217

    
218
            if (focus) this.updateFocus(this.focus);
219
        },
220

    
221
        updatePos: function(pos) {
222
            this.pos = pos;
223
            this.container.css({
224
                '-ms-transform': 'translateX('+pos+'px)',
225
                '-webkit-transform': 'translateX('+pos+'px)',
226
                'transform': 'translateX('+pos+'px)'
227
            });
228
        },
229

    
230
        updateFocus: function(idx, dir) {
231

    
232
            if (!this.active) {
233
                return;
234
            }
235

    
236
            dir = dir || (idx > this.focus ? 1:-1);
237

    
238
            var item = this.items.eq(idx), area, i;
239

    
240
            if (this.options.infinite) {
241
                this.infinite(idx, dir);
242
            }
243

    
244
            if (this.options.center) {
245

    
246
                this.updatePos(item.data('center')*-1);
247

    
248
                this.items.filter('.'+this.options.activecls).removeClass(this.options.activecls);
249
                item.addClass(this.options.activecls);
250

    
251
            } else {
252

    
253
                if (this.options.infinite) {
254

    
255
                    this.updatePos(item.data('left')*-1);
256

    
257
                } else {
258

    
259
                    area = 0;
260

    
261
                    for (i=idx;i<this.items.length;i++) {
262
                        area += this.items.eq(i).data('width');
263
                    }
264

    
265

    
266
                    if (area > this.vp) {
267

    
268
                        this.updatePos(item.data('left')*-1);
269

    
270
                    } else {
271

    
272
                        if (dir == 1) {
273

    
274
                            area = 0;
275

    
276
                            for (i=this.items.length-1;i>=0;i--) {
277

    
278
                                area += this.items.eq(i).data('width');
279

    
280
                                if (area == this.vp) {
281
                                    idx = i;
282
                                    break;
283
                                }
284

    
285
                                if (area > this.vp) {
286
                                    idx = (i < this.items.length-1) ? i+1 : i;
287
                                    break;
288
                                }
289
                            }
290

    
291
                            if (area > this.vp) {
292
                                this.updatePos((this.container.width() - this.vp) * -1);
293
                            } else {
294
                                this.updatePos(this.items.eq(idx).data('left')*-1);
295
                            }
296
                        }
297
                    }
298
                }
299
            }
300

    
301
            // mark elements
302
            var left = this.items.eq(idx).data('left');
303

    
304
            this.items.removeClass('uk-slide-before uk-slide-after').each(function(i){
305
                if (i!==idx) {
306
                    UI.$(this).addClass(UI.$(this).data('left') < left ? 'uk-slide-before':'uk-slide-after');
307
                }
308
            });
309

    
310
            this.focus = idx;
311

    
312
            this.trigger('focusitem.uk.slider', [idx,this.items.eq(idx),this]);
313
        },
314

    
315
        next: function() {
316

    
317
            var focus = this.items[this.focus + 1] ? (this.focus + 1) : (this.options.infinite ? 0:this.focus);
318

    
319
            this.updateFocus(focus, 1);
320
        },
321

    
322
        previous: function() {
323

    
324
            var focus = this.items[this.focus - 1] ? (this.focus - 1) : (this.options.infinite ? (this.items[this.focus - 1] ? this.items-1:this.items.length-1):this.focus);
325

    
326
            this.updateFocus(focus, -1);
327
        },
328

    
329
        start: function() {
330

    
331
            this.stop();
332

    
333
            var $this = this;
334

    
335
            this.interval = setInterval(function() {
336
                if (!$this.hovering) $this.next();
337
            }, this.options.autoplayInterval);
338

    
339
        },
340

    
341
        stop: function() {
342
            if (this.interval) clearInterval(this.interval);
343
        },
344

    
345
        infinite: function(baseidx, direction) {
346

    
347
            var $this = this, item = this.items.eq(baseidx), i, z = baseidx, move = [], area = 0;
348

    
349
            if (direction == 1) {
350

    
351

    
352
                for (i=0;i<this.items.length;i++) {
353

    
354
                    if (z != baseidx) {
355
                        area += this.items.eq(z).data('width');
356
                        move.push(this.items.eq(z));
357
                    }
358

    
359
                    if (area > this.vp) {
360
                        break;
361
                    }
362

    
363
                    z = z+1 == this.items.length ? 0:z+1;
364
                }
365

    
366
                if (move.length) {
367

    
368
                    move.forEach(function(itm){
369

    
370
                        var left = item.data('area');
371

    
372
                        itm.css({'left': left}).data({
373
                            left  : left,
374
                            area  : (left+itm.data('width')),
375
                            center: (left - ($this.vp/2 - itm.data('cwidth')/2))
376
                        });
377

    
378
                        item = itm;
379
                    });
380
                }
381

    
382

    
383
            } else {
384

    
385
                for (i=this.items.length-1;i >-1 ;i--) {
386

    
387
                    area += this.items.eq(z).data('width');
388

    
389
                    if (z != baseidx) {
390
                        move.push(this.items.eq(z));
391
                    }
392

    
393
                    if (area > this.vp) {
394
                        break;
395
                    }
396

    
397
                    z = z-1 == -1 ? this.items.length-1:z-1;
398
                }
399

    
400
                if (move.length) {
401

    
402
                    move.forEach(function(itm){
403

    
404
                        var left = item.data('left') - itm.data('width');
405

    
406
                        itm.css({'left': left}).data({
407
                            left  : left,
408
                            area  : (left+itm.data('width')),
409
                            center: (left - ($this.vp/2 - itm.data('cwidth')/2))
410
                        });
411

    
412
                        item = itm;
413
                    });
414
                }
415
            }
416
        }
417
    });
418

    
419
    // handle dragging
420
    UI.$doc.on('mousemove.uk.slider touchmove.uk.slider', function(e) {
421

    
422
        if (e.originalEvent && e.originalEvent.touches) {
423
            e = e.originalEvent.touches[0];
424
        }
425

    
426
        if (delayIdle && Math.abs(e.pageX - delayIdle.x) > delayIdle.threshold) {
427

    
428
            if (!window.getSelection().toString()) {
429
                delayIdle(e);
430
            } else {
431
                dragging = delayIdle = false;
432
            }
433
        }
434

    
435
        if (!dragging) {
436
            return;
437
        }
438

    
439
        var x, xDiff, pos, dir, focus, item, next, diff, i, z, itm;
440

    
441
        if (e.clientX || e.clientY) {
442
            x = e.clientX;
443
        } else if (e.pageX || e.pageY) {
444
            x = e.pageX - document.body.scrollLeft - document.documentElement.scrollLeft;
445
        }
446

    
447
        focus = store.focus;
448
        xDiff = x - dragging.element.data('pointer-start').x;
449
        pos   = dragging.element.data('pointer-pos-start') + xDiff;
450
        dir   = x > dragging.element.data('pointer-start').x ? -1:1;
451
        item  = dragging.items.eq(store.focus);
452

    
453
        if (dir == 1) {
454

    
455
            diff = item.data('left') + Math.abs(xDiff);
456

    
457
            for (i=0,z=store.focus;i<dragging.items.length;i++) {
458

    
459
                itm = dragging.items.eq(z);
460

    
461
                if (z != store.focus && itm.data('left') < diff && itm.data('area') > diff) {
462
                    focus = z;
463
                    break;
464
                }
465

    
466
                z = z+1 == dragging.items.length ? 0:z+1;
467
            }
468

    
469
        } else {
470

    
471
            diff = item.data('left') - Math.abs(xDiff);
472

    
473
            for (i=0,z=store.focus;i<dragging.items.length;i++) {
474

    
475
                itm = dragging.items.eq(z);
476

    
477
                if (z != store.focus && itm.data('area') <= item.data('left') && itm.data('center') < diff) {
478
                    focus = z;
479
                    break;
480
                }
481

    
482
                z = z-1 == -1 ? dragging.items.length-1:z-1;
483
            }
484
        }
485

    
486
        if (dragging.options.infinite && focus!=store._focus) {
487
            dragging.infinite(focus, dir);
488
        }
489

    
490
        dragging.updatePos(pos);
491

    
492
        store.dir     = dir;
493
        store._focus  = focus;
494
        store.touchx  = parseInt(e.pageX, 10);
495
        store.diff    = diff;
496
    });
497

    
498
    UI.$doc.on('mouseup.uk.slider touchend.uk.slider', function(e) {
499

    
500
        if (dragging) {
501

    
502
            dragging.container.removeClass('uk-drag');
503

    
504
            // TODO is this needed?
505
            dragging.items.eq(store.focus);
506

    
507
            var itm, focus = false, i, z;
508

    
509
            if (store.dir == 1) {
510

    
511
                for (i=0,z=store.focus;i<dragging.items.length;i++) {
512

    
513
                    itm = dragging.items.eq(z);
514

    
515
                    if (z != store.focus && itm.data('left') > store.diff) {
516
                        focus = z;
517
                        break;
518
                    }
519

    
520
                    z = z+1 == dragging.items.length ? 0:z+1;
521
                }
522
                if (!dragging.options.infinite && !focus) {
523
                    focus = dragging.items.length;
524
                }
525

    
526
            } else {
527

    
528
                for (i=0,z=store.focus;i<dragging.items.length;i++) {
529

    
530
                    itm = dragging.items.eq(z);
531

    
532
                    if (z != store.focus && itm.data('left') < store.diff) {
533
                        focus = z;
534
                        break;
535
                    }
536

    
537
                    z = z-1 == -1 ? dragging.items.length-1:z-1;
538
                }
539
                if (!dragging.options.infinite && !focus) {
540
                    focus = 0
541
                }
542
            }
543

    
544
            dragging.updateFocus(focus!==false ? focus:store._focus);
545

    
546
        }
547

    
548
        dragging = delayIdle = false;
549
    });
550

    
551
    return UI.slider;
552
});
(29-29/46)