Skip to content

Instantly share code, notes, and snippets.

@hidao80
Last active September 2, 2024 12:17
Show Gist options
  • Save hidao80/c67f058701cccd18ea9d22cd040dff04 to your computer and use it in GitHub Desktop.
Save hidao80/c67f058701cccd18ea9d22cd040dff04 to your computer and use it in GitHub Desktop.
Script that will open an image preview dialog by loading and specifying a class for the target tag.
/**
* Usage: Add the class name "hd simple-preview-modal" to the image tag.
* If you want to load a different image from the src attribute, add the data-preview-src attribute.
* <img src="..." class="hd simple-preview-modal" data-preview-src="...">
*
* Copyright (c) 2023 hidao80
* Released under the MIT license
* https://opensource.org/licenses/mit-license.php
*/
(() => {
const SIGNATURE = 'hd';
const SCRIPT_ITEM_PREFIX = 'simple-preview-modal';
window.addEventListener("load", () => {
// If the script is already loaded, do nothing.
if (document.getElementById(SCRIPT_ITEM_PREFIX)) {
return;
}
// Add a style sheet to the page.
const styles = [
`#${SCRIPT_ITEM_PREFIX}-close {
position: absolute;
top: 0.2em;
right: 0.2em;
padding: 0.3em;
line-height: 0.6;
background-color: transparent;
border: 0;
font-size: 2em;
}`,
`#${SCRIPT_ITEM_PREFIX}-close:focus {
outline: 0;
}`,
`#${SCRIPT_ITEM_PREFIX}-img {
margin-top: 1.3em;
}`,
];
let usableSheet = [...document.styleSheets].slice(-1)[0];
if (!usableSheet) {
const styles = document.createElement("style");
document.body.appendChild(styles);
usableSheet = [...document.styleSheets].slice(-1)[0];
}
for (let style of styles) {
usableSheet.insertRule(style, usableSheet.cssRules.length);
}
/**
* Create a DOM element.
* @param {string} tag - Tag name of the element.
* @param {object} attrs - Attributes of the element.
* @returns {HTMLElement} Created element.
*/
const create = (tag, attrs) => {
const elem = document.createElement(tag);
for (const key in attrs) {
elem.setAttribute(key, attrs[key]);
}
return elem;
};
/**
* Close the preview dialog.
* @param {string} message - Message to be passed to the close event.
*/
const close = (message) => {
previewImg.setAttribute('src', '');
dialog.close(message);
};
// Add a single DOM in the preview dialog.
const dialog = create('dialog', { id: SCRIPT_ITEM_PREFIX });
const div = create('div', { id: `${SCRIPT_ITEM_PREFIX}-body` });
const previewImg = create('img', { id: `${SCRIPT_ITEM_PREFIX}-img` });
const closeBtn = create('button', { id: `${SCRIPT_ITEM_PREFIX}-close`, type: 'button' });
closeBtn.innerHTML = '&times;';
div.appendChild(previewImg);
dialog.appendChild(div);
dialog.appendChild(closeBtn);
document.body.appendChild(dialog);
// Copy the attribute values of the clicked image to the img element for preview.
// If there is a data-preview-src attribute, load the image from its URL.
document.querySelectorAll(`img.${SIGNATURE}.${SCRIPT_ITEM_PREFIX}`).forEach(elem => {
elem.addEventListener("click", () => {
["src", "alt", "title"].forEach(attr => {
previewImg.setAttribute(attr, elem.getAttribute(attr));
});
if (elem.dataset?.previewSrc) {
previewImg.setAttribute("src", elem.dataset?.previewSrc);
}
dialog.showModal();
});
});
// Define event listeners and processing.
// Multiple targets are grouped together in an array because they are processed the same way.
[dialog, closeBtn].forEach(elem => {
elem.addEventListener('click', event => {
if (event.target === elem) {
close('cancelled');
}
});
});
});
})();
(()=>{const e="simple-preview-modal";window.addEventListener("load",(()=>{if(document.getElementById(e))return;const t=["#simple-preview-modal-close{position:absolute;top:0.2em;right:0.2em;padding:0.3em;line-height:0.6;background-color:transparent;border:0;font-size:2em;}","#simple-preview-modal-close:focus{outline:0;}","#simple-preview-modal-img{margin-top:1.3em;}"];let i=[...document.styleSheets].slice(-1)[0];if(!i){const e=document.createElement("style");document.body.appendChild(e),i=[...document.styleSheets].slice(-1)[0]}for(let e of t)i.insertRule(e,i.cssRules.length);const n=(e,t)=>{const i=document.createElement(e);for(const e in t)i.setAttribute(e,t[e]);return i},o=n("dialog",{id:e}),l=n("div",{id:"simple-preview-modal-body"}),d=n("img",{id:"simple-preview-modal-img"}),r=n("button",{id:"simple-preview-modal-close",type:"button"});r.innerHTML="&times;",l.appendChild(d),o.appendChild(l),o.appendChild(r),document.body.appendChild(o),document.querySelectorAll("img.hd.simple-preview-modal").forEach((e=>{e.addEventListener("click",(()=>{["src","alt","title"].forEach((t=>{d.setAttribute(t,e.getAttribute(t))})),e.dataset?.previewSrc&&d.setAttribute("src",e.dataset?.previewSrc),o.showModal()}))})),[o,r].forEach((e=>{e.addEventListener("click",(t=>{var i;t.target===e&&(i="cancelled",d.setAttribute("src",""),o.close(i))}))}))}))})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment