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) { // AMD
11
        define('uikit-lightbox', ['uikit'], function(){
12
            return component || addon(UIkit2);
13
        });
14
    }
15

    
16
})(function(UI){
17

    
18
    "use strict";
19

    
20
    var modal, cache = {};
21

    
22
    UI.component('lightbox', {
23

    
24
        defaults: {
25
            allowfullscreen : true,
26
            duration        : 400,
27
            group           : false,
28
            keyboard        : true
29
        },
30

    
31
        index : 0,
32
        items : false,
33

    
34
        boot: function() {
35

    
36
            UI.$html.on('click', '[data-uk-lightbox]', function(e){
37

    
38
                e.preventDefault();
39

    
40
                var link = UI.$(this);
41

    
42
                if (!link.data('lightbox')) {
43

    
44
                    UI.lightbox(link, UI.Utils.options(link.attr('data-uk-lightbox')));
45
                }
46

    
47
                link.data('lightbox').show(link);
48
            });
49

    
50
            // keyboard navigation
51
            UI.$doc.on('keyup', function(e) {
52

    
53
                if (modal && modal.is(':visible') && modal.lightbox.options.keyboard) {
54

    
55
                    e.preventDefault();
56

    
57
                    switch(e.keyCode) {
58
                        case 37:
59
                            modal.lightbox.previous();
60
                            break;
61
                        case 39:
62
                            modal.lightbox.next();
63
                            break;
64
                    }
65
                }
66
            });
67
        },
68

    
69
        init: function() {
70

    
71
            var siblings = [];
72

    
73
            this.index    = 0;
74
            this.siblings = [];
75

    
76
            if (this.element && this.element.length) {
77

    
78
                var domSiblings  = this.options.group ? UI.$('[data-uk-lightbox*="'+this.options.group+'"]') : this.element;
79

    
80
                domSiblings.each(function() {
81

    
82
                    var ele = UI.$(this);
83

    
84
                    siblings.push({
85
                        source : ele.attr('href'),
86
                        title  : ele.attr('data-title') || ele.attr('title'),
87
                        type   : ele.attr("data-lightbox-type") || 'auto',
88
                        link   : ele
89
                    });
90
                });
91

    
92
                this.index    = domSiblings.index(this.element);
93
                this.siblings = siblings;
94

    
95
            } else if (this.options.group && this.options.group.length) {
96
                this.siblings = this.options.group;
97
            }
98

    
99
            this.trigger('lightbox-init', [this]);
100
        },
101

    
102
        show: function(index) {
103

    
104
            this.modal = getModal(this);
105

    
106
            // stop previous animation
107
            this.modal.dialog.stop();
108
            this.modal.content.stop();
109

    
110
            var $this = this, promise = UI.$.Deferred(), data, item;
111

    
112
            index = index || 0;
113

    
114
            // index is a jQuery object or DOM element
115
            if (typeof(index) == 'object') {
116

    
117
                this.siblings.forEach(function(s, idx){
118

    
119
                    if (index[0] === s.link[0]) {
120
                        index = idx;
121
                    }
122
                });
123
            }
124

    
125
            // fix index if needed
126
            if ( index < 0 ) {
127
                index = this.siblings.length - index;
128
            } else if (!this.siblings[index]) {
129
                index = 0;
130
            }
131

    
132
            item   = this.siblings[index];
133

    
134
            data = {
135
                lightbox : $this,
136
                source   : item.source,
137
                type     : item.type,
138
                index    : index,
139
                promise  : promise,
140
                title    : item.title,
141
                item     : item,
142
                meta     : {
143
                    content : '',
144
                    width   : null,
145
                    height  : null
146
                }
147
            };
148

    
149
            this.index = index;
150

    
151
            this.modal.content.empty();
152

    
153
            if (!this.modal.is(':visible')) {
154
                this.modal.content.css({width:'', height:''}).empty();
155
                this.modal.modal.show();
156
            }
157

    
158
            this.modal.loader.removeClass('uk-hidden');
159

    
160
            promise.promise().done(function() {
161

    
162
                $this.data = data;
163
                $this.fitSize(data);
164

    
165
            }).fail(function(){
166

    
167
                data.meta.content = '<div class="uk-position-cover uk-flex uk-flex-middle uk-flex-center"><strong>Loading resource failed!</strong></div>';
168
                data.meta.width   = 400;
169
                data.meta.height  = 300;
170

    
171
                $this.data = data;
172
                $this.fitSize(data);
173
            });
174

    
175
            $this.trigger('showitem.uk.lightbox', [data]);
176
        },
177

    
178
        fitSize: function() {
179

    
180
            var $this    = this,
181
                data     = this.data,
182
                pad      = this.modal.dialog.outerWidth() - this.modal.dialog.width(),
183
                dpadTop  = parseInt(this.modal.dialog.css('margin-top'), 10),
184
                dpadBot  = parseInt(this.modal.dialog.css('margin-bottom'), 10),
185
                dpad     = dpadTop + dpadBot,
186
                content  = data.meta.content,
187
                duration = $this.options.duration;
188

    
189
            if (this.siblings.length > 1) {
190

    
191
                content = [
192
                    content,
193
                    '<a href="#" class="uk-slidenav uk-slidenav-contrast uk-slidenav-previous uk-hidden-touch" data-lightbox-previous></a>',
194
                    '<a href="#" class="uk-slidenav uk-slidenav-contrast uk-slidenav-next uk-hidden-touch" data-lightbox-next></a>'
195
                ].join('');
196
            }
197

    
198
            // calculate width
199
            var tmp = UI.$('<div>&nbsp;</div>').css({
200
                opacity   : 0,
201
                position  : 'absolute',
202
                top       : 0,
203
                left      : 0,
204
                width     : '100%',
205
                maxWidth  : $this.modal.dialog.css('max-width'),
206
                padding   : $this.modal.dialog.css('padding'),
207
                margin    : $this.modal.dialog.css('margin')
208
            }), maxwidth, maxheight, w = data.meta.width, h = data.meta.height;
209

    
210
            tmp.appendTo('body').width();
211

    
212
            maxwidth  = tmp.width();
213
            maxheight = window.innerHeight - dpad;
214

    
215
            tmp.remove();
216

    
217
            this.modal.dialog.find('.uk-modal-caption').remove();
218

    
219
            if (data.title) {
220
                this.modal.dialog.append('<div class="uk-modal-caption">'+data.title+'</div>');
221
                maxheight -= this.modal.dialog.find('.uk-modal-caption').outerHeight();
222
            }
223

    
224
            if (maxwidth < data.meta.width) {
225

    
226
                h = Math.floor( h * (maxwidth / w) );
227
                w = maxwidth;
228
            }
229

    
230
            if (maxheight < h) {
231

    
232
                h = Math.floor(maxheight);
233
                w = Math.ceil(data.meta.width * (maxheight/data.meta.height));
234
            }
235

    
236
            this.modal.content.css('opacity', 0).width(w).html(content);
237

    
238
            if (data.type == 'iframe') {
239
                this.modal.content.find('iframe:first').height(h);
240
            }
241

    
242
            var dh   = h + pad,
243
                t    = Math.floor(window.innerHeight/2 - dh/2) - dpad;
244

    
245
            if (t < 0) { t = 0; }
246

    
247
            this.modal.closer.addClass('uk-hidden');
248

    
249
            if ($this.modal.data('mwidth') == w &&  $this.modal.data('mheight') == h) {
250
                duration = 0;
251
            }
252

    
253
            this.modal.dialog.animate({width: w + pad, height: h + pad, top: t }, duration, 'swing', function() {
254
                $this.modal.loader.addClass('uk-hidden');
255
                $this.modal.content.css({width:''}).animate({opacity: 1}, function() {
256
                    $this.modal.closer.removeClass('uk-hidden');
257
                });
258

    
259
                $this.modal.data({mwidth: w, mheight: h});
260
            });
261
        },
262

    
263
        next: function() {
264
            this.show(this.siblings[(this.index+1)] ? (this.index+1) : 0);
265
        },
266

    
267
        previous: function() {
268
            this.show(this.siblings[(this.index-1)] ? (this.index-1) : this.siblings.length-1);
269
        }
270
    });
271

    
272

    
273
    // Plugins
274

    
275
    UI.plugin('lightbox', 'image', {
276

    
277
        init: function(lightbox) {
278

    
279
            lightbox.on('showitem.uk.lightbox', function(e, data){
280

    
281
                if (data.type == 'image' || data.source && data.source.match(/\.(jpg|jpeg|png|gif|svg)$/i)) {
282

    
283
                    var resolve = function(source, width, height) {
284

    
285
                        data.meta = {
286
                            content : '<img class="uk-responsive-width" width="'+width+'" height="'+height+'" src ="'+source+'">',
287
                            width   : width,
288
                            height  : height
289
                        };
290

    
291
                        data.type = 'image';
292

    
293
                        data.promise.resolve();
294
                    };
295

    
296
                    if (!cache[data.source]) {
297

    
298
                        var img = new Image();
299

    
300
                        img.onerror = function(){
301
                            data.promise.reject('Loading image failed');
302
                        };
303

    
304
                        img.onload = function(){
305
                            cache[data.source] = {width: img.width, height: img.height};
306
                            resolve(data.source, cache[data.source].width, cache[data.source].height);
307
                        };
308

    
309
                        img.src = data.source;
310

    
311
                    } else {
312
                        resolve(data.source, cache[data.source].width, cache[data.source].height);
313
                    }
314
                }
315
            });
316
        }
317
    });
318

    
319
    UI.plugin('lightbox', 'youtube', {
320

    
321
        init: function(lightbox) {
322

    
323
            var youtubeRegExp = /(\/\/.*?youtube\.[a-z]+)\/watch\?v=([^&]+)&?(.*)/,
324
                youtubeRegExpShort = /youtu\.be\/(.*)/;
325

    
326

    
327
            lightbox.on('showitem.uk.lightbox', function(e, data){
328

    
329
                var id, matches, resolve = function(id, width, height) {
330

    
331
                    data.meta = {
332
                        content: '<iframe src="//www.youtube.com/embed/'+id+'" width="'+width+'" height="'+height+'" style="max-width:100%;"'+(modal.lightbox.options.allowfullscreen?' allowfullscreen':'')+'></iframe>',
333
                        width: width,
334
                        height: height
335
                    };
336

    
337
                    data.type = 'iframe';
338

    
339
                    data.promise.resolve();
340
                };
341

    
342
                if (matches = data.source.match(youtubeRegExp)) {
343
                    id = matches[2];
344
                }
345

    
346
                if (matches = data.source.match(youtubeRegExpShort)) {
347
                    id = matches[1];
348
                }
349

    
350
                if (id) {
351

    
352
                    if(!cache[id]) {
353

    
354
                        var img = new Image(), lowres = false;
355

    
356
                        img.onerror = function(){
357
                            cache[id] = {width:640, height:320};
358
                            resolve(id, cache[id].width, cache[id].height);
359
                        };
360

    
361
                        img.onload = function(){
362
                            //youtube default 404 thumb, fall back to lowres
363
                            if (img.width == 120 && img.height == 90) {
364
                                if (!lowres) {
365
                                    lowres = true;
366
                                    img.src = '//img.youtube.com/vi/' + id + '/0.jpg';
367
                                } else {
368
                                    cache[id] = {width: 640, height: 320};
369
                                    resolve(id, cache[id].width, cache[id].height);
370
                                }
371
                            } else {
372
                                cache[id] = {width: img.width, height: img.height};
373
                                resolve(id, img.width, img.height);
374
                            }
375
                        };
376

    
377
                        img.src = '//img.youtube.com/vi/'+id+'/maxresdefault.jpg';
378

    
379
                    } else {
380
                        resolve(id, cache[id].width, cache[id].height);
381
                    }
382

    
383
                    e.stopImmediatePropagation();
384
                }
385
            });
386
        }
387
    });
388

    
389

    
390
    UI.plugin('lightbox', 'vimeo', {
391

    
392
        init: function(lightbox) {
393

    
394
            var regex = /(\/\/.*?)vimeo\.[a-z]+\/([0-9]+).*?/, matches;
395

    
396

    
397
            lightbox.on('showitem.uk.lightbox', function(e, data){
398

    
399
                var id, resolve = function(id, width, height) {
400

    
401
                    data.meta = {
402
                        content: '<iframe src="//player.vimeo.com/video/'+id+'" width="'+width+'" height="'+height+'" style="width:100%;box-sizing:border-box;"'+(modal.lightbox.options.allowfullscreen?' allowfullscreen':'')+'></iframe>',
403
                        width: width,
404
                        height: height
405
                    };
406

    
407
                    data.type = 'iframe';
408

    
409
                    data.promise.resolve();
410
                };
411

    
412
                if (matches = data.source.match(regex)) {
413

    
414
                    id = matches[2];
415

    
416
                    if(!cache[id]) {
417

    
418
                        UI.$.ajax({
419
                            type     : 'GET',
420
                            url      : '//vimeo.com/api/oembed.json?url=' + encodeURI(data.source),
421
                            jsonp    : 'callback',
422
                            dataType : 'jsonp',
423
                            success  : function(data) {
424
                                cache[id] = {width:data.width, height:data.height};
425
                                resolve(id, cache[id].width, cache[id].height);
426
                            }
427
                        });
428

    
429
                    } else {
430
                        resolve(id, cache[id].width, cache[id].height);
431
                    }
432

    
433
                    e.stopImmediatePropagation();
434
                }
435
            });
436
        }
437
    });
438

    
439
    UI.plugin('lightbox', 'video', {
440

    
441
        init: function(lightbox) {
442

    
443
            lightbox.on('showitem.uk.lightbox', function(e, data){
444

    
445

    
446
                var resolve = function(source, width, height) {
447

    
448
                    data.meta = {
449
                        content: '<video class="uk-responsive-width" src="'+source+'" width="'+width+'" height="'+height+'" controls></video>',
450
                        width: width,
451
                        height: height
452
                    };
453

    
454
                    data.type = 'video';
455

    
456
                    data.promise.resolve();
457
                };
458

    
459
                if (data.type == 'video' || data.source.match(/\.(mp4|webm|ogv)$/i)) {
460

    
461
                    if (!cache[data.source]) {
462

    
463
                        var vid = UI.$('<video style="position:fixed;visibility:hidden;top:-10000px;"></video>').attr('src', data.source).appendTo('body');
464

    
465
                        var idle = setInterval(function() {
466

    
467
                            if (vid[0].videoWidth) {
468
                                clearInterval(idle);
469
                                cache[data.source] = {width: vid[0].videoWidth, height: vid[0].videoHeight};
470
                                resolve(data.source, cache[data.source].width, cache[data.source].height);
471
                                vid.remove();
472
                            }
473

    
474
                        }, 20);
475

    
476
                    } else {
477
                        resolve(data.source, cache[data.source].width, cache[data.source].height);
478
                    }
479
                }
480
            });
481
        }
482
    });
483

    
484

    
485
    UI.plugin('lightbox', 'iframe', {
486

    
487
        init: function (lightbox) {
488

    
489
            lightbox.on('showitem.uk.lightbox', function (e, data) {
490

    
491
                var resolve = function (source, width, height) {
492

    
493
                    data.meta = {
494
                        content: '<iframe class="uk-responsive-width" src="' + source + '" width="' + width + '" height="' + height + '"'+(modal.lightbox.options.allowfullscreen?' allowfullscreen':'')+'></iframe>',
495
                        width: width,
496
                        height: height
497
                    };
498

    
499
                    data.type = 'iframe';
500

    
501
                    data.promise.resolve();
502
                };
503

    
504
                if (data.type === 'iframe' || data.source.match(/\.(html|php)$/)) {
505
                    resolve(data.source, (lightbox.options.width || 800), (lightbox.options.height || 600));
506
                }
507
            });
508

    
509
        }
510
    });
511

    
512
    function getModal(lightbox) {
513

    
514
        if (modal) {
515
            modal.lightbox = lightbox;
516
            return modal;
517
        }
518

    
519
        // init lightbox container
520
        modal = UI.$([
521
            '<div class="uk-modal">',
522
                '<div class="uk-modal-dialog uk-modal-dialog-lightbox uk-slidenav-position" style="margin-left:auto;margin-right:auto;width:200px;height:200px;top:'+Math.abs(window.innerHeight/2 - 200)+'px;">',
523
                    '<a href="#" class="uk-modal-close uk-close uk-close-alt"></a>',
524
                    '<div class="uk-lightbox-content"></div>',
525
                    '<div class="uk-modal-spinner uk-hidden"></div>',
526
                '</div>',
527
            '</div>'
528
        ].join('')).appendTo('body');
529

    
530
        modal.dialog  = modal.find('.uk-modal-dialog:first');
531
        modal.content = modal.find('.uk-lightbox-content:first');
532
        modal.loader  = modal.find('.uk-modal-spinner:first');
533
        modal.closer  = modal.find('.uk-close.uk-close-alt');
534
        modal.modal   = UI.modal(modal, {modal:false});
535

    
536
        // next / previous
537
        modal.on('swipeRight swipeLeft', function(e) {
538
            modal.lightbox[e.type=='swipeLeft' ? 'next':'previous']();
539
        }).on('click', '[data-lightbox-previous], [data-lightbox-next]', function(e){
540
            e.preventDefault();
541
            modal.lightbox[UI.$(this).is('[data-lightbox-next]') ? 'next':'previous']();
542
        });
543

    
544
        // destroy content on modal hide
545
        modal.on('hide.uk.modal', function(e) {
546
            modal.content.html('');
547
        });
548

    
549
        var resizeCache = {w: window.innerWidth, h:window.innerHeight};
550

    
551
        UI.$win.on('load resize orientationchange', UI.Utils.debounce(function(e){
552

    
553
            if (resizeCache.w !== window.innerWidth && modal.is(':visible') && !UI.Utils.isFullscreen()) {
554
                modal.lightbox.fitSize();
555
            }
556

    
557
            resizeCache = {w: window.innerWidth, h:window.innerHeight};
558

    
559
        }, 100));
560

    
561
        modal.lightbox = lightbox;
562

    
563
        return modal;
564
    }
565

    
566
    UI.lightbox.create = function(items, options) {
567

    
568
        if (!items) return;
569

    
570
        var group = [], o;
571

    
572
        items.forEach(function(item) {
573

    
574
            group.push(UI.$.extend({
575
                source : '',
576
                title  : '',
577
                type   : 'auto',
578
                link   : false
579
            }, (typeof(item) == 'string' ? {'source': item} : item)));
580
        });
581

    
582
        o = UI.lightbox(UI.$.extend({}, options, {'group':group}));
583

    
584
        return o;
585
    };
586

    
587
    return UI.lightbox;
588
});
(17-17/46)