Project

General

Profile

1
function plugin(UIkit) {
2

    
3
    if (plugin.installed) {
4
        return;
5
    }
6

    
7
    var {$, doc, extend, Dimensions, getIndex, Transition} = UIkit.util;
8
    var active;
9

    
10
    doc.on({
11
        keydown: e => {
12
            if (active) {
13
                switch (e.keyCode) {
14
                    case 37:
15
                        active.show('previous');
16
                        break;
17
                    case 39:
18
                        active.show('next');
19
                        break;
20
                }
21
            }
22
        }
23
    });
24

    
25
    UIkit.component('lightbox', {
26

    
27
        name: 'lightbox',
28

    
29
        props: {
30
            toggle: String,
31
            duration: Number,
32
            inverse: Boolean
33
        },
34

    
35
        defaults: {
36
            toggle: 'a',
37
            duration: 400,
38
            dark: false,
39
            attrItem: 'uk-lightbox-item',
40
            items: [],
41
            index: 0
42
        },
43

    
44
        computed: {
45

    
46
            toggles() {
47
                return $(this.toggle, this.$el).each((_, el) => this.items.push({
48
                    source: el.getAttribute('href'),
49
                    title: el.getAttribute('title'),
50
                    type: el.getAttribute('type')
51
                }));
52
            }
53

    
54
        },
55

    
56
        events: [
57

    
58
            {
59

    
60
                name: 'click',
61

    
62
                delegate() {
63
                    return `${this.toggle}:not(.uk-disabled)`;
64
                },
65

    
66
                handler(e) {
67
                    e.preventDefault();
68
                    this.show(this.toggles.index(e.currentTarget));
69
                }
70

    
71
            },
72

    
73
            {
74

    
75
                name: 'showitem',
76

    
77
                handler(e) {
78

    
79
                    var item = this.getItem();
80

    
81
                    if (item.content) {
82
                        this.$update();
83
                        e.stopImmediatePropagation();
84
                    }
85
                }
86

    
87
            }
88

    
89
        ],
90

    
91
        update: {
92

    
93
            write() {
94

    
95
                var item = this.getItem();
96

    
97
                if (!this.modal || !item.content) {
98
                    return;
99
                }
100

    
101
                var panel = this.modal.panel,
102
                    dim = {width: panel.width(), height: panel.height()},
103
                    max = {
104
                        width: window.innerWidth - (panel.outerWidth(true) - dim.width),
105
                        height: window.innerHeight - (panel.outerHeight(true) - dim.height)
106
                    },
107
                    newDim = Dimensions.fit({width: item.width, height: item.height}, max);
108

    
109
                Transition.stop(panel);
110
                Transition.stop(this.modal.content);
111

    
112
                if (this.modal.content) {
113
                    this.modal.content.remove();
114
                }
115

    
116
                this.modal.content = $(item.content).css('opacity', 0).appendTo(panel);
117
                panel.css(dim);
118

    
119
                Transition.start(panel, newDim, this.duration).then(() => {
120
                    Transition.start(this.modal.content, {opacity: 1}, 400).then(() => {
121
                        panel.find('[uk-transition-hide]').show();
122
                        panel.find('[uk-transition-show]').hide();
123
                    });
124
                });
125

    
126
            },
127

    
128
            events: ['resize']
129

    
130
        },
131

    
132
        methods: {
133

    
134
            show(index) {
135

    
136
                this.index = getIndex(index, this.items, this.index);
137

    
138
                if (!this.modal) {
139
                    this.modal = UIkit.modal.dialog(`
140
                        <button class="uk-modal-close-outside" uk-transition-hide type="button" uk-close></button>
141
                        <span class="uk-position-center" uk-transition-show uk-spinner></span>
142
                    `, {center: true});
143
                    this.modal.$el.css('overflow', 'hidden').addClass('uk-modal-lightbox');
144
                    this.modal.panel.css({width: 200, height: 200});
145
                    this.modal.caption = $('<div class="uk-modal-caption" uk-transition-hide></div>').appendTo(this.modal.panel);
146

    
147
                    if (this.items.length > 1) {
148
                        $(`<div class="${this.dark ? 'uk-dark' : 'uk-light'}" uk-transition-hide>
149
                                <a href="#" class="uk-position-center-left" uk-slidenav-previous uk-lightbox-item="previous"></a>
150
                                <a href="#" class="uk-position-center-right" uk-slidenav-next uk-lightbox-item="next"></a>
151
                            </div>
152
                        `).appendTo(this.modal.panel.addClass('uk-slidenav-position'));
153
                    }
154

    
155
                    this.modal.$el
156
                        .on('hidden', this.hide)
157
                        .on('click', `[${this.attrItem}]`, e => {
158
                            e.preventDefault();
159
                            this.show($(e.currentTarget).attr(this.attrItem));
160
                        }).on('swipeRight swipeLeft', e => {
161
                        e.preventDefault();
162
                        if (!window.getSelection().toString()) {
163
                            this.show(e.type === 'swipeLeft' ? 'next' : 'previous');
164
                        }
165
                    });
166
                }
167

    
168
                active = this;
169

    
170
                this.modal.panel.find('[uk-transition-hide]').hide();
171
                this.modal.panel.find('[uk-transition-show]').show();
172

    
173
                this.modal.content && this.modal.content.remove();
174
                this.modal.caption.text(this.getItem().title);
175

    
176
                var event = $.Event('showitem');
177
                this.$el.trigger(event);
178
                if (!event.isImmediatePropagationStopped()) {
179
                    this.setError(this.getItem());
180
                }
181
            },
182

    
183
            hide() {
184

    
185
                active = active && active !== this && active;
186

    
187
                this.modal.hide().then(() => {
188
                    this.modal.$destroy(true);
189
                    this.modal = null;
190
                });
191
            },
192

    
193
            getItem() {
194
                return this.items[this.index] || {source: '', title: '', type: ''};
195
            },
196

    
197
            setItem(item, content, width = 200, height = 200) {
198
                extend(item, {content, width, height});
199
                this.$update();
200
            },
201

    
202
            setError(item) {
203
                this.setItem(item, '<div class="uk-position-cover uk-flex uk-flex-middle uk-flex-center"><strong>Loading resource failed!</strong></div>', 400, 300);
204
            }
205

    
206
        }
207

    
208
    });
209

    
210
    UIkit.mixin({
211

    
212
        events: {
213

    
214
            showitem(e) {
215

    
216
                let item = this.getItem();
217

    
218
                if (item.type !== 'image' && item.source && !item.source.match(/\.(jp(e)?g|png|gif|svg)$/i)) {
219
                    return;
220
                }
221

    
222
                var img = new Image();
223

    
224
                img.onerror = () => this.setError(item);
225
                img.onload = () => this.setItem(item, `<img class="uk-responsive-width" width="${img.width}" height="${img.height}" src ="${item.source}">`, img.width, img.height);
226

    
227
                img.src = item.source;
228

    
229
                e.stopImmediatePropagation();
230
            }
231

    
232
        }
233

    
234
    }, 'lightbox');
235

    
236
    UIkit.mixin({
237

    
238
        events: {
239

    
240
            showitem(e) {
241

    
242
                let item = this.getItem();
243

    
244
                if (item.type !== 'video' && item.source && !item.source.match(/\.(mp4|webm|ogv)$/i)) {
245
                    return;
246
                }
247

    
248
                var video = $('<video class="uk-responsive-width" controls></video>')
249
                    .on('loadedmetadata', () => this.setItem(item, video.attr({width: video[0].videoWidth, height: video[0].videoHeight}), video[0].videoWidth, video[0].videoHeight))
250
                    .attr('src', item.source);
251

    
252
                e.stopImmediatePropagation();
253
            }
254

    
255
        }
256

    
257
    }, 'lightbox');
258

    
259
    UIkit.mixin({
260

    
261
        events: {
262

    
263
            showitem(e) {
264

    
265
                let item = this.getItem(), matches;
266

    
267
                if (!(matches = item.source.match(/\/\/.*?youtube\.[a-z]+\/watch\?v=([^&]+)&?(.*)/)) && !(item.source.match(/youtu\.be\/(.*)/))) {
268
                    return;
269
                }
270

    
271
                let id = matches[1],
272
                    img = new Image(),
273
                    lowres = false,
274
                    setIframe = (width, height) => this.setItem(item, `<iframe src="//www.youtube.com/embed/${id}" width="${width}" height="${height}" style="max-width:100%;box-sizing:border-box;"></iframe>`, width, height);
275

    
276
                img.onerror = () => setIframe(640, 320);
277
                img.onload = () => {
278
                    //youtube default 404 thumb, fall back to lowres
279
                    if (img.width === 120 && img.height === 90) {
280
                        if (!lowres) {
281
                            lowres = true;
282
                            img.src = `//img.youtube.com/vi/${id}/0.jpg`;
283
                        } else {
284
                            setIframe(640, 320);
285
                        }
286
                    } else {
287
                        setIframe(img.width, img.height);
288
                    }
289
                };
290

    
291
                img.src = `//img.youtube.com/vi/${id}/maxresdefault.jpg`;
292

    
293
                e.stopImmediatePropagation();
294
            }
295

    
296
        }
297

    
298
    }, 'lightbox');
299

    
300
    UIkit.mixin({
301

    
302
        events: {
303

    
304
            showitem(e) {
305

    
306
                let item = this.getItem(), matches;
307

    
308
                if (!(matches = item.source.match(/(\/\/.*?)vimeo\.[a-z]+\/([0-9]+).*?/))) {
309
                    return;
310
                }
311

    
312
                let id = matches[2],
313
                    setIframe = (width, height) => this.setItem(item, `<iframe src="//player.vimeo.com/video/${id}" width="${width}" height="${height}" style="max-width:100%;box-sizing:border-box;"></iframe>`, width, height);
314

    
315
                $.ajax({type: 'GET', url: `http://vimeo.com/api/oembed.json?url=${encodeURI(item.source)}`, jsonp: 'callback', dataType: 'jsonp'}).then((res) => setIframe(res.width, res.height));
316

    
317
                e.stopImmediatePropagation();
318
            }
319

    
320
        }
321

    
322
    }, 'lightbox');
323

    
324
}
325

    
326
if (!BUNDLED && typeof window !== 'undefined' && window.UIkit) {
327
    window.UIkit.use(plugin);
328
}
329

    
330
export default plugin;
(1-1/5)