UNPKG

uikit

Version:

UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.

343 lines (233 loc) • 9.71 kB
import Animations from './internal/lightbox-animations'; import Container from '../mixin/container'; import Modal from '../mixin/modal'; import Slideshow from '../mixin/slideshow'; import Togglable from '../mixin/togglable'; import {$, addClass, ajax, append, assign, attr, css, getImage, html, index, once, pointerDown, pointerMove, removeClass, Transition, trigger} from 'uikit-util'; export default { mixins: [Container, Modal, Togglable, Slideshow], functional: true, props: { delayControls: Number, preload: Number, videoAutoplay: Boolean, template: String }, data: () => ({ preload: 1, videoAutoplay: false, delayControls: 3000, items: [], cls: 'uk-open', clsPage: 'uk-lightbox-page', selList: '.uk-lightbox-items', attrItem: 'uk-lightbox-item', selClose: '.uk-close-large', selCaption: '.uk-lightbox-caption', pauseOnHover: false, velocity: 2, Animations, template: `<div class="uk-lightbox uk-overflow-hidden"> <ul class="uk-lightbox-items"></ul> <div class="uk-lightbox-toolbar uk-position-top uk-text-right uk-transition-slide-top uk-transition-opaque"> <button class="uk-lightbox-toolbar-icon uk-close-large" type="button" uk-close></button> </div> <a class="uk-lightbox-button uk-position-center-left uk-position-medium uk-transition-fade" href="#" uk-slidenav-previous uk-lightbox-item="previous"></a> <a class="uk-lightbox-button uk-position-center-right uk-position-medium uk-transition-fade" href="#" uk-slidenav-next uk-lightbox-item="next"></a> <div class="uk-lightbox-toolbar uk-lightbox-caption uk-position-bottom uk-text-center uk-transition-slide-bottom uk-transition-opaque"></div> </div>` }), created() { const $el = $(this.template); const list = $(this.selList, $el); this.items.forEach(() => append(list, '<li></li>')); this.$mount(append(this.container, $el)); }, computed: { caption({selCaption}, $el) { return $('.uk-lightbox-caption', $el); } }, events: [ { name: `${pointerMove} ${pointerDown} keydown`, handler: 'showControls' }, { name: 'click', self: true, delegate() { return this.selSlides; }, handler(e) { if (e.defaultPrevented) { return; } this.hide(); } }, { name: 'shown', self: true, handler() { this.showControls(); } }, { name: 'hide', self: true, handler() { this.hideControls(); removeClass(this.slides, this.clsActive); Transition.stop(this.slides); } }, { name: 'hidden', self: true, handler() { this.$destroy(true); } }, { name: 'keyup', el: document, handler(e) { if (!this.isToggled(this.$el)) { return; } switch (e.keyCode) { case 37: this.show('previous'); break; case 39: this.show('next'); break; } } }, { name: 'beforeitemshow', handler(e) { if (this.isToggled()) { return; } this.draggable = false; e.preventDefault(); this.toggleNow(this.$el, true); this.animation = Animations['scale']; removeClass(e.target, this.clsActive); this.stack.splice(1, 0, this.index); } }, { name: 'itemshow', handler({target}) { const i = index(target); const {caption} = this.getItem(i); css(this.caption, 'display', caption ? '' : 'none'); html(this.caption, caption); for (let j = 0; j <= this.preload; j++) { this.loadItem(this.getIndex(i + j)); this.loadItem(this.getIndex(i - j)); } } }, { name: 'itemshown', handler() { this.draggable = this.$props.draggable; } }, { name: 'itemload', handler(_, item) { const {source, type, alt} = item; this.setItem(item, '<span uk-spinner></span>'); if (!source) { return; } let matches; // Image if (type === 'image' || source.match(/\.(jp(e)?g|png|gif|svg|webp)($|\?)/i)) { getImage(source).then( img => this.setItem(item, `<img width="${img.width}" height="${img.height}" src="${source}" alt="${alt ? alt : ''}">`), () => this.setError(item) ); // Video } else if (type === 'video' || source.match(/\.(mp4|webm|ogv)($|\?)/i)) { const video = $(`<video controls playsinline${item.poster ? ` poster="${item.poster}"` : ''} uk-video="${this.videoAutoplay}"></video>`); attr(video, 'src', source); once(video, 'error loadedmetadata', type => { if (type === 'error') { this.setError(item); } else { attr(video, {width: video.videoWidth, height: video.videoHeight}); this.setItem(item, video); } }); // Iframe } else if (type === 'iframe' || source.match(/\.(html|php)($|\?)/i)) { this.setItem(item, `<iframe class="uk-lightbox-iframe" src="${source}" frameborder="0" allowfullscreen></iframe>`); // YouTube } else if ((matches = source.match(/\/\/.*?youtube(-nocookie)?\.[a-z]+\/watch\?v=([^&\s]+)/) || source.match(/()youtu\.be\/(.*)/))) { const [, , id] = matches; const setIframe = (width = 640, height = 450) => this.setItem(item, getIframe(`https://www.youtube${matches[1] || ''}.com/embed/${id}`, width, height, this.videoAutoplay)); getImage(`https://img.youtube.com/vi/${id}/maxresdefault.jpg`).then( ({width, height}) => { // YouTube default 404 thumb, fall back to low resolution if (width === 120 && height === 90) { getImage(`https://img.youtube.com/vi/${id}/0.jpg`).then( ({width, height}) => setIframe(width, height), setIframe ); } else { setIframe(width, height); } }, setIframe ); // Vimeo } else if ((matches = source.match(/(\/\/.*?)vimeo\.[a-z]+\/([0-9]+).*?/))) { ajax(`https://vimeo.com/api/oembed.json?maxwidth=1920&url=${encodeURI(source)}`, {responseType: 'json', withCredentials: false}) .then( ({response: {height, width}}) => this.setItem(item, getIframe(`https://player.vimeo.com/video/${matches[2]}`, width, height, this.videoAutoplay)), () => this.setError(item) ); } } } ], methods: { loadItem(index = this.index) { const item = this.getItem(index); if (item.content) { return; } trigger(this.$el, 'itemload', [item]); }, getItem(index = this.index) { return this.items[index] || {}; }, setItem(item, content) { assign(item, {content}); const el = html(this.slides[this.items.indexOf(item)], content); trigger(this.$el, 'itemloaded', [this, el]); this.$update(el); }, setError(item) { this.setItem(item, '<span uk-icon="icon: bolt; ratio: 2"></span>'); }, showControls() { clearTimeout(this.controlsTimer); this.controlsTimer = setTimeout(this.hideControls, this.delayControls); addClass(this.$el, 'uk-active', 'uk-transition-active'); }, hideControls() { removeClass(this.$el, 'uk-active', 'uk-transition-active'); } } }; function getIframe(src, width, height, autoplay) { return `<iframe src="${src}" width="${width}" height="${height}" style="max-width: 100%; box-sizing: border-box;" frameborder="0" allowfullscreen uk-video="autoplay: ${autoplay}" uk-responsive></iframe>`; }