meta-lightbox/src/js/window.js

464 lines
11 KiB
JavaScript
Raw Normal View History

2021-01-25 12:15:33 +01:00
/*
* Lightbox window
*/
2021-02-24 10:40:59 +01:00
2021-08-18 21:11:59 +02:00
import Events from "./_events";
2021-01-30 22:00:13 +01:00
2021-02-24 10:43:39 +01:00
const W = window;
2021-08-18 21:11:59 +02:00
const axios = require("axios");
2021-01-25 12:15:33 +01:00
2021-08-04 00:55:06 +02:00
class MetaWindow {
2021-08-18 21:11:59 +02:00
state = {
content: "",
type: ["empty"],
shown: false,
loading: false,
error: false,
embed: false,
collections: [],
current: null,
target: null,
};
init() {
const ui = this;
console.log(`MetaWindow: [links] init`);
// collect new collections
document
.querySelectorAll('[data-toggle="lightbox"],[data-gallery="${gallery}"]')
.forEach((el) => {
const gallery = el.getAttribute("data-gallery");
2021-08-11 18:57:45 +02:00
if (gallery) {
ui.state.collections[gallery] = [];
document
.querySelectorAll(
2021-08-18 21:11:59 +02:00
`[data-toggle="lightbox"][data-gallery="${gallery}"]`
2021-08-11 18:57:45 +02:00
)
.forEach((el) => {
ui.state.collections[gallery].push(el);
});
}
// click handler
2021-08-18 21:11:59 +02:00
el.addEventListener("click", (e) => {
2021-08-11 18:57:45 +02:00
e.preventDefault();
console.log(`MetaWindow: [link] click`);
2021-08-04 00:57:03 +02:00
2021-08-11 18:57:45 +02:00
const el = e.currentTarget;
2021-08-18 21:11:59 +02:00
const link = el.getAttribute("href") || el.getAttribute("data-href");
const embed = el.getAttribute("data-embed");
2021-08-11 18:57:45 +02:00
ui.state.current = el;
if (embed) {
ui.embed(link);
} else {
ui.load(link);
}
2021-08-18 21:11:59 +02:00
const title = el.getAttribute("data-title");
2021-08-11 18:57:45 +02:00
if (title) {
ui.setCaption(title);
}
2021-08-04 00:55:06 +02:00
});
2021-08-11 18:57:45 +02:00
});
2021-08-18 21:11:59 +02:00
}
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
constructor(
state = {
2021-08-11 18:57:45 +02:00
shown: false,
2021-08-18 21:11:59 +02:00
},
action
) {
const ui = this;
ui.name = ui.constructor.name;
console.log(`${ui.name}: init`);
ui.axios = axios;
ui.setState(state);
switch (action) {
case "show":
ui.hide();
break;
case "hide":
ui.hide();
break;
2021-02-24 10:38:08 +01:00
}
2021-08-18 21:11:59 +02:00
W.dispatchEvent(new Event(`{ui.name}.init`));
}
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
show = () => {
const ui = this;
console.log(`${ui.name}: show`);
2021-08-04 00:55:06 +02:00
2021-08-18 21:11:59 +02:00
ui.setState({
shown: true,
});
W.dispatchEvent(new Event(`{ui.name}.show`));
};
2021-08-04 00:55:06 +02:00
2021-08-18 21:11:59 +02:00
hide = () => {
const ui = this;
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
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;
}
2021-02-24 10:40:59 +01:00
2021-08-18 21:11:59 +02:00
ui.state.collections[gallery][i].click();
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
console.log(`${ui.name}: next`);
W.dispatchEvent(new Event(`{ui.name}.next`));
};
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
prev = () => {
const ui = this;
const el = ui.state.current;
const gallery = el.getAttribute("data-gallery");
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
let i = ui._currIndex();
if (i > 0) {
i--;
} else {
i = ui.state.collections[gallery].length - 1;
}
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
ui.state.collections[gallery][i].click();
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
console.log(`${ui.name}: prev`);
W.dispatchEvent(new Event(`{ui.name}.prev`));
};
reset = () => {
const ui = this;
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
ui.setState({
content: "",
type: ["empty"],
shown: false,
loading: false,
error: false,
embed: false,
//collections: [],
//current: null,
//target: null,
});
};
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"]}`
);
const 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(
`<img src="data:${
resp.headers["content-type"]
};base64,${ui._imageEncode(resp.data)}" />`,
`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 "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), [
`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.";
2021-08-11 18:57:45 +02:00
break;
2021-08-18 21:11:59 +02:00
case 500:
msg = "Server issue, please try again latter.";
2021-08-11 18:57:45 +02:00
break;
default:
2021-08-18 21:11:59 +02:00
msg = "Something went wrong.";
2021-08-11 18:57:45 +02:00
break;
}
2021-08-18 21:11:59 +02:00
} else if (error.request) {
msg = "No response received";
} else {
console.warn("Error", error.message);
}
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
ui.setState({
error: msg,
});
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
W.dispatchEvent(new Event(`{ui.name}.error`));
})
.then(() => {
ui.setState({
loading: false,
});
2021-08-11 18:57:45 +02:00
});
2021-08-18 21:11:59 +02:00
};
2021-08-10 01:46:42 +02:00
2021-08-18 21:11:59 +02:00
_currIndex = () => {
const ui = this;
const el = ui.state.current;
const gallery = el.getAttribute("data-gallery");
2021-08-04 00:55:06 +02:00
2021-08-18 21:11:59 +02:00
return ui.state.collections[gallery].indexOf(el);
};
2021-08-04 00:55:06 +02:00
2021-08-18 21:11:59 +02:00
embed = (link) => {
const ui = this;
console.log(`${ui.name}: embed`);
2021-08-04 00:55:06 +02:00
2021-08-18 21:11:59 +02:00
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;
};
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
: [`meta-${ui.name}--html`, `meta-${ui.name}--text`];
if (!Array.isArray(typeArr)) {
typeArr = type.split(" ");
2021-08-04 00:55:06 +02:00
}
2021-08-18 21:11:59 +02:00
ui.setState({
content: html,
type: typeArr,
});
};
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
getHtml = () => {
const ui = this;
2021-08-10 02:08:01 +02:00
2021-08-18 21:11:59 +02:00
if (ui.state.embed) {
const youtubeEmbed = require("youtube-embed");
const embedLink = youtubeEmbed(ui.state.embed);
ui.state.content = `<iframe width="600" height="380" src="${embedLink}" frameborder="0"></iframe>`;
}
2021-08-10 02:08:01 +02:00
2021-08-18 21:11:59 +02:00
return ui.state.content;
};
2021-02-24 10:38:08 +01:00
2021-08-18 21:11:59 +02:00
setState(state) {
const ui = this;
ui.state = Object.assign({}, ui.state, state);
ui.render();
}
2021-04-02 11:20:48 +02:00
2021-08-18 21:11:59 +02:00
render() {
const ui = this;
const name = ui.name;
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
const navs = null;
const el = ui.state.current;
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
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);
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
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 =
'<i class="icon fa fas fa-times"></i>' +
' <span class="visually-hidden">Close</span>';
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 =
'<i class="icon fa fas fa-chevron-left"></i>' +
' <span class="visually-hidden">Previous</span>';
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 =
'<i class="icon fa fas fa-chevron-right"></i>' +
' <span class="visually-hidden">Next</span>';
nextBtn.addEventListener("click", (e) => {
e.preventDefault();
ui.next();
});
navs.append(nextBtn);
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
metaContent.append(navs);
2021-08-11 18:57:45 +02:00
}
2021-08-18 21:11:59 +02:00
}
2021-08-11 18:57:45 +02:00
2021-08-18 21:11:59 +02:00
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);
2021-02-24 10:38:08 +01:00
}
2021-08-18 21:11:59 +02:00
return ui;
}
2021-01-25 12:15:33 +01:00
}
export default MetaWindow;