/* * Lightbox window */ import Events from './_events'; const W = window; class MetaWindow { state = { content: '', type: ['empty'], shown: false, loading: false, error: false, embed: false, collections: [], current: null, target: null, extraClass: null, }; cleanLinks() { document.querySelectorAll(`[data-toggle="lightbox"]`) .forEach((el) => { el.classList.remove('loading'); }); } collectGaleries(gallery) { const ui = this; if (!gallery) { return; } ui.state.collections[gallery] = []; document .querySelectorAll( `[data-toggle="lightbox"][data-gallery="${gallery}"]` ) .forEach((el) => { ui.state.collections[gallery].push(el); }); } toggle(el) { const ui = this; ui.cleanLinks(); const link = el.getAttribute('href') || el.getAttribute('data-href'); const embed = el.getAttribute('data-embed'); el.classList.add('loading'); ui.state.current = el; const title = el.getAttribute('data-title'); if (title) { ui.setCaption(title); } if (embed) { ui.embed(link); } else { ui.load(link); } ui.addExtraClass(el.getAttribute('data-lightbox-class')); } init() { const ui = this; console.log(`MetaWindow: [links] init`); document .querySelectorAll(`[data-toggle="lightbox"],[data-gallery]`) .forEach((el) => { const gallery = el.getAttribute('data-gallery'); ui.collectGaleries(gallery); // click handler el.addEventListener('click', (e) => { e.preventDefault(); console.log(`MetaWindow: [link] click`); const el = e.currentTarget; ui.toggle(el); }); }); } constructor( state = { shown: false, }, action ) { const ui = this; ui.name = ui.constructor.name; console.log(`${ui.name}: init`); ui.setState(state); switch (action) { case 'show': ui.hide(); break; case 'hide': ui.hide(); break; } W.dispatchEvent(new Event(`{ui.name}.init`)); } show = () => { const ui = this; console.log(`${ui.name}: show`); ui.setState({ shown: true, }); W.dispatchEvent(new Event(`{ui.name}.show`)); }; hide = () => { const ui = this; console.log(`${ui.name}: hide`); ui.setState({ shown: false, }); W.dispatchEvent(new Event(`{ui.name}.hide`)); }; next = () => { const ui = this; const el = ui.state.current; const gallery = el.getAttribute('data-gallery'); let i = ui._currIndex(); if (i < ui.state.collections[gallery].length - 1) { i++; } else { i = 0; } ui.state.collections[gallery][i].click(); console.log(`${ui.name}: next`); W.dispatchEvent(new Event(`{ui.name}.next`)); }; prev = () => { const ui = this; const el = ui.state.current; const gallery = el.getAttribute('data-gallery'); let i = ui._currIndex(); if (i > 0) { i--; } else { i = ui.state.collections[gallery].length - 1; } ui.state.collections[gallery][i].click(); console.log(`${ui.name}: prev`); W.dispatchEvent(new Event(`{ui.name}.prev`)); }; reset = () => { const ui = this; ui.setState({ content: '', type: ['empty'], shown: false, loading: false, error: false, embed: false, //collections: [], //current: null, //target: null, }); }; load = (link) => { const ui = this; ui.reset(); ui.setState({ loading: true, }); ui.show(); fetch(link).then((resp) => { // handle success const type = resp.headers.get("content-type"); console.log(resp); console.log( `${ui.name}: response content-type: ${type}` ); const json = false; switch (type) { case 'image/jpeg': case 'image/png': case 'image/svg+xml': case 'image/bmp': case 'image/gif': case 'image/tiff': case 'image/webp': // irregular types: case 'image/jpg': case 'image/svg': //json = JSON.parse(ui._abToString(resp.data)); resp.arrayBuffer().then((buffer) => { ui.setContent( ``, `meta-${ui.name}--image` ); }); break; case 'application/json': case 'application/ld+json': // irregular types: case 'application/json; charset=UTF-8': ui.setContent(`${json['Content']}`, [ `meta-${ui.name}--text`, `meta-${ui.name}--html`, `meta-${ui.name}--json`, ]); break; case 'video/mp4': ui.setContent(``, [ `meta-${ui.name}--image`, `meta-${ui.name}--video`, ]); break; case 'text/html': case 'application/xhtml+xml': case 'text/plain': // irregular types: case 'text/html; charset=UTF-8': case 'application/xhtml+xml; charset=UTF-8': case 'text/plain; charset=UTF-8': ui.setContent(resp.data, [ `meta-${ui.name}--text`, `meta-${ui.name}--html`, `meta-${ui.name}--pajax`, ]); break; default: console.warn(`${ui.name}: Unknown response content-type!`); break; } W.dispatchEvent(new Event(`{ui.name}.loaded`)); }) .catch((error) => { console.error(error); let msg = ''; if (error.response) { switch (error.response.status) { case 404: msg = 'Not Found.'; break; case 500: msg = 'Server issue, please try again latter.'; break; default: msg = 'Something went wrong.'; break; } } else if (error.request) { msg = 'No response received'; } else { console.warn('Error', error.message); } ui.setState({ error: msg, }); W.dispatchEvent(new Event(`{ui.name}.error`)); }) .then(() => { ui.setState({ loading: false, }); setTimeout(() => { ui.state.current.classList.remove('loading'); }, 1000); }); }; _currIndex = () => { const ui = this; const el = ui.state.current; const gallery = el.getAttribute('data-gallery'); return ui.state.collections[gallery].indexOf(el); }; embed = (link) => { const ui = this; console.log(`${ui.name}: embed`); ui.reset(); ui.setState({ embed: link, loading: false, type: [`meta-${ui.name}--embed`, `meta-${ui.name}--video`], }); ui.show(); }; setCaption = (title) => { const ui = this; console.log(`${ui.name}: setCaption`); ui.state.caption = title; }; addExtraClass = (cls) => { const ui = this; if (!cls || !cls.length) { return; } console.log(`${ui.name}: addExtraClass(${cls})`); ui.state.extraClass = cls; }; getCaption = () => { const ui = this; return ui.state.caption; }; /*_abToString = (arrayBuffer) => { return String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)); };*/ _imageEncode = (buffer) => { let binary = ''; const bytes = [].slice.call(new Uint8Array(buffer)); bytes.forEach((b) => binary += String.fromCharCode(b)); return window.btoa(binary); }; setContent = (html, type) => { const ui = this; console.log(`${ui.name}: setContent`); let typeArr = type ? type : [`meta-${ui.name}--html`, `meta-${ui.name}--text`]; if (!Array.isArray(typeArr)) { typeArr = type.split(' '); } ui.setState({ content: html, type: typeArr, }); }; getHtml = () => { const ui = this; if (ui.state.embed) { const youtubeEmbed = require('youtube-embed'); const embedLink = youtubeEmbed(ui.state.embed); ui.state.content = ``; } return ui.state.content; }; setState(state) { const ui = this; ui.state = Object.assign({}, ui.state, state); ui.render(); } render() { const ui = this; const name = ui.name; const navs = null; const el = ui.state.current; ui.state.target.innerHTML = ''; const meta = document.createElement('div'); meta.classList.add(`meta-${name}`); meta.classList.add(...ui.state.type); ui.state.target.append(meta); const metaOverlay = document.createElement('div'); metaOverlay.classList.add(`meta-${name}-overlay`); if (ui.state.shown) { metaOverlay.classList.add(`meta-${name}-overlay--open`); } if (ui.state.loading) { metaOverlay.classList.add(`meta-${name}-overlay--loading`); } if (ui.state.error) { metaOverlay.classList.add(`meta-${name}-overlay--error`); } meta.append(metaOverlay); const metaContent = document.createElement('div'); metaContent.classList.add('meta-content'); metaOverlay.append(metaContent); const btnClose = document.createElement('button'); btnClose.classList.add('meta-nav', 'meta-close', 'a'); btnClose.innerHTML = '' + ' Close'; btnClose.addEventListener('click', (e) => { e.preventDefault(); ui.hide(); }); metaContent.append(btnClose); if (el) { const gallery = el.getAttribute('data-gallery'); if (gallery && ui.state.collections[gallery].length > 1) { const navs = document.createElement('nav'); navs.classList.add('meta-navs'); const prevBtn = document.createElement('button'); prevBtn.classList.add( 'meta-nav', 'meta-nav-arrow', 'meta-nav-arrow__prev', 'a' ); prevBtn.innerHTML = '' + ' Previous'; prevBtn.addEventListener('click', (e) => { e.preventDefault(); ui.prev(); }); navs.append(prevBtn); const nextBtn = document.createElement('button'); nextBtn.classList.add( 'meta-nav', 'meta-nav-arrow', 'meta-nav-arrow__next', 'a' ); nextBtn.innerHTML = '' + ' Next'; nextBtn.addEventListener('click', (e) => { e.preventDefault(); ui.next(); }); navs.append(nextBtn); metaContent.append(navs); } } const content = document.createElement('section'); content.classList.add('meta-wrap', 'typography'); if (ui.state.extraClass) { content.classList.add(ui.state.extraClass); } content.innerHTML = ui.getHtml(); metaContent.append(content); if (ui.state.error) { const error = document.createElement('div'); error.classList.add('meta-error'); error.innerHTML = ui.state.error; metaContent.append(error); } else if (ui.state.caption) { const caption = document.createElement('div'); caption.classList.add('meta-caption'); caption.innerHTML = ui.getCaption(); metaContent.append(caption); } // update fontawesome dome if (typeof window.FontAwesome !== 'undefined') { window.FontAwesome.dom.i2svg(); } return ui; } } export default MetaWindow;