Newer
Older
gnexus-ui-kit / src / js / components / modals.js
@root root 7 hours ago 3 KB Tech
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, props = {}) {
	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 panel = document.createElement("div");
	panel.className = "modal-panel";
	panel.setAttribute("role", "dialog");
	panel.setAttribute("aria-modal", "true");
	panel.setAttribute("aria-labelledby", `${id}-title`);

	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, props.footerMode ?? "html");

	header.append(modalTitle, close);
	panel.append(header, body, modalFooter);
	modal.append(backdrop, panel);

	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", e => {
		modal.close();
	});

	if(typeof onready == "function") {
		onready(modal);
	}

	return modal;
}

	/**
	 * Create new modal window;
	 * @param  {string} id    Uniq id (selector)
	 * @param  {string} title Display title
	 * @param  {object} props { body: modal => {}, actions => modal => {} }
	 * @return {object}       DOM object
	 */
function create(id, props) {
	props = props ?? {};
	const title = props.title || "";
	const footer = props.footer || "";

	const modal = template(id, title, footer, props);

	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(let 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
}