/* * Lightbox window */ import Events from './_events'; const W = window; const axios = require('axios'); class MetaWindow { state = { content: '', type: [], shown: false, loading: false, error: false, embed: false, collections: [], current: null, target: null, }; init(target) { const ui = this; console.log(`MetaWindow: [links] init`); ui.state.target = target; // reset collections ui.state.collections = {}; // collect new collections document.querySelectorAll('[data-toggle="lightbox"],[data-gallery="${gallery}"]').forEach((el) => { const gallery = el.getAttribute('data-gallery'); if (gallery) { ui.state.collections[gallery] = []; document .querySelectorAll( `[data-toggle="lightbox"][data-gallery="${gallery}"]`, ) .forEach((el) => { ui.state.collections[gallery].push(el); }); } // click handler el.addEventListener('click', (e) => { e.preventDefault(); console.log(`MetaWindow: [link] click`); const el = e.currentTarget; const link = el.getAttribute('href') || el.getAttribute('data-href'); const embed = el.getAttribute('data-embed'); ui.state.current = el; if (embed) { ui.embed(link); } else { ui.load(link); } const title = el.getAttribute('data-title'); if (title) { ui.setCaption(title); } }); }); } constructor(props) { const ui = this; ui.name = ui.constructor.name; console.log(`${ui.name}: init`); ui.axios = axios; 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: [], shown: false, loading: false, error: false, embed: false, }); }; load = (link) => { const ui = this; const axios = ui.axios; ui.reset(); ui.setState({ loading: true, }); ui.show(); axios .get(link, { responseType: 'arraybuffer', }) .then((resp) => { // handle success console.log( `${ui.name}: response content-type: ${resp.headers['content-type']}`, ); let json = false; switch (resp.headers['content-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)); ui.setContent( ``, 'image', ); break; case 'application/json': case 'application/ld+json': // irregular types: case 'application/json; charset=UTF-8': ui.setContent(`${json['Content']}`, 'text html json'); 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( ui._abToString(resp.data), 'text html 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, }); }); }; _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: ['embed', 'video'], }); ui.show(); }; setCaption = (title) => { const ui = this; console.log(`${ui.name}: setCaption`); ui.state.caption = title; }; getCaption = () => { const ui = this; return ui.state.caption; } _abToString = (arrayBuffer) => { return String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)); }; _imageEncode = (arrayBuffer) => { const u8 = new Uint8Array(arrayBuffer); const b64encoded = btoa( [].reduce.call( new Uint8Array(arrayBuffer), (p, c) => { return p + String.fromCharCode(c); }, '', ), ); return b64encoded; }; setContent = (html, type) => { const ui = this; console.log(`${ui.name}: setContent`); let typeArr = type ? type : ['html', 'text']; if (!Array.isArray(typeArr)) { typeArr = type.split(' '); } ui.setState({ content: html, type: typeArr, }); }; getHtml = () => { const ui = this; return ui.state.content; }; setState(newState) { const ui = this; ui.state = Object.assign({}, ui.state, newState); 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-${name}__${ui.state.type.join(` meta-${name}__`)}`); 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__prev', 'a'); nextBtn.innerHTML = '' + ' Next'; nextBtn.addEventListener('click', (e) => { e.preventDefault(); ui.next(); }); navs.append(nextBtn); metaContent.append(navs); } } let content = ''; if (ui.state.embed) { content = '
' + ' ... Loading ... ' + '
'; } else { const content = document.createElement('section'); content.classList.add('meta-wrap', 'typography'); 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); } return ui; } } export default MetaWindow;