/**
* Modals browser helper.
*
* Mirrors gnexus-ui-kit Modals public surface:
* create(id, props)
*/
function appendContent(container, content, mode = "html") {
if(content instanceof Node) {
container.append(content);
return;
}
if(typeof content !== "undefined" && content !== null) {
if(mode === "text") {
container.textContent = content;
} else {
container.innerHTML = content;
}
}
}
function template(id, title, footer) {
const modal = document.createElement("div");
modal.className = "modal";
modal.setAttribute("aria-hidden", "true");
modal.id = id;
const backdrop = document.createElement("div");
backdrop.className = "modal-backdrop";
const dialog = document.createElement("div");
dialog.className = "modal-dialog";
dialog.setAttribute("role", "dialog");
dialog.setAttribute("aria-modal", "true");
dialog.setAttribute("aria-labelledby", `${id}-title`);
const panel = document.createElement("div");
panel.className = "modal-panel";
const header = document.createElement("header");
header.className = "modal-header";
const modalTitle = document.createElement("h4");
modalTitle.className = "modal-title";
modalTitle.id = `${id}-title`;
modalTitle.textContent = title;
const close = document.createElement("button");
close.className = "btn-icon modal-close";
close.type = "button";
close.setAttribute("aria-label", "Close");
close.textContent = "✕";
const body = document.createElement("div");
body.className = "modal-body";
const modalFooter = document.createElement("footer");
modalFooter.className = "modal-footer";
appendContent(modalFooter, footer);
header.append(modalTitle, close);
panel.append(body, modalFooter);
dialog.append(header, panel);
modal.append(backdrop, dialog);
return modal;
}
function init(modal, onready) {
modal.show = function() {
document.querySelector("body").append(modal);
setTimeout(() => {
modal.classList.add("a-show");
}, 10);
};
modal.close = function() {
modal.classList.add("a-hide");
setTimeout(() => {
modal.remove();
}, 300);
};
modal.querySelector(".modal-close").addEventListener("click", () => {
modal.close();
});
modal.querySelector(".modal-backdrop")?.addEventListener("click", () => {
modal.close();
});
if(typeof onready === "function") {
onready(modal);
}
return modal;
}
/**
* Create a new modal window.
* @param {string} id - Unique id
* @param {object} props - { title, footer, body, bodyText, bodyHtml, actions, onready }
* @returns {HTMLElement} Modal DOM element with show()/close()
*/
function create(id, props = {}) {
const title = props.title || "";
const footer = props.footer || "";
const modal = template(id, title, footer);
const modalBody = modal.querySelector(".modal-body");
const modalFooter = modal.querySelector(".modal-footer");
if(typeof props.actions === "function") {
const actionsResult = props.actions(modal);
if(Array.isArray(actionsResult) && actionsResult[0] instanceof Node) {
const actions = document.createElement("div");
actions.classList.add("actions");
for(const actionElement of actionsResult) {
actions.append(actionElement);
}
modalFooter.append(actions);
} else if(actionsResult instanceof Node) {
modalFooter.append(actionsResult);
}
}
if(typeof props.body === "function") {
const bodyResult = props.body(modal);
appendContent(modalBody, bodyResult, props.bodyMode ?? "html");
} else if(typeof props.bodyText !== "undefined") {
appendContent(modalBody, props.bodyText, "text");
} else if(typeof props.bodyHtml !== "undefined") {
appendContent(modalBody, props.bodyHtml, "html");
}
return init(modal, props?.onready);
}
export default {
create
};