Newer
Older
gnexus-ui-kit / src / js / components / drawer.js
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 drawer = document.createElement("div");
	drawer.className = "drawer";
	drawer.setAttribute("aria-hidden", "true");
	drawer.id = id;

	if(props.position === "left") {
		drawer.classList.add("drawer-left");
	}

	const backdrop = document.createElement("div");
	backdrop.className = "drawer-backdrop";

	const panel = document.createElement("aside");
	panel.className = "drawer-panel";
	panel.setAttribute("role", "dialog");
	panel.setAttribute("aria-modal", "true");
	panel.setAttribute("aria-labelledby", `${id}-title`);

	const header = document.createElement("header");
	header.className = "drawer-header";

	const drawerTitle = document.createElement("h4");
	drawerTitle.className = "drawer-title";
	drawerTitle.id = `${id}-title`;
	drawerTitle.textContent = title;

	const close = document.createElement("button");
	close.className = "btn-icon drawer-close";
	close.type = "button";
	close.setAttribute("aria-label", "Close");
	close.textContent = "✕";

	const body = document.createElement("div");
	body.className = "drawer-body";

	const drawerFooter = document.createElement("footer");
	drawerFooter.className = "drawer-footer";
	appendContent(drawerFooter, footer, props.footerMode ?? "html");

	header.append(drawerTitle, close);
	panel.append(header, body, drawerFooter);
	drawer.append(backdrop, panel);

	return drawer;
}

function init(drawer, onready) {
	drawer.show = function() {
		document.querySelector("body").append(drawer);

		setTimeout(() => {
			drawer.classList.add("a-show");
		}, 10);
	};

	drawer.close = function() {
		drawer.classList.add("a-hide");
		setTimeout(() => {
			drawer.remove();
		}, 300);
	};

	drawer.querySelector(".drawer-close").addEventListener("click", () => {
		drawer.close();
	});

	drawer.querySelector(".drawer-backdrop").addEventListener("click", () => {
		drawer.close();
	});

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

	return drawer;
}

function create(id, props) {
	props = props ?? {};
	const title = props.title || "";
	const footer = props.footer || "";

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

	const drawerBody = drawer.querySelector(".drawer-body");
	const drawerFooter = drawer.querySelector(".drawer-footer");

	if(typeof props.actions == "function") {
		const actionsResult = props.actions(drawer);

		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);
			}

			drawerFooter.append(actions);
		} else if(actionsResult instanceof Node) {
			drawerFooter.append(actionsResult);
		}
	}

	if(typeof props.body == "function") {
		const bodyResult = props.body(drawer);

		appendContent(drawerBody, bodyResult, props.bodyMode ?? "html");
	} else if(typeof props.bodyText != "undefined") {
		appendContent(drawerBody, props.bodyText, "text");
	} else if(typeof props.bodyHtml != "undefined") {
		appendContent(drawerBody, props.bodyHtml, "html");
	}

	return init(drawer, props?.onready);
}

export default {
	create
};