/* ════════════════════════════════════════════════════ ERP 공용 확인/경고 창 — window.confirm()/alert() 대체 ──────────────────────────────────────────────────── 브라우저 기본 창은 제목에 도메인("dbx.no1king.freeddns.org 내용:")이 찍히고 위치·정렬·아이콘을 바꿀 수 없다. 그래서 같은 역할의 창을 직접 그린다. 쓰는 법 (기본 창과 달리 **비동기**다 — Promise 를 돌려준다): erpConfirm("지울까요?").then(function (ok) { if (ok) ... }); erpAlert("실패했습니다.").then(...) HTML 만으로 쓰려면 form 에 data-erp-confirm 을 달면 된다. 제출을 가로채 확인을 받은 뒤 통과시킨다(가로챈 제출은 form.submit() 으로 다시 보내므로 이 스크립트의 submit 리스너를 다시 타지 않는다).
════════════════════════════════════════════════════ */ (function () { "use strict"; var TITLE = "No.1 King ERP 프로그램"; // 경고 삼각형. 외부 아이콘 라이브러리를 쓰지 않는다(자체 호스팅 원칙). var ICON = '"; function build(message, options) { var backdrop = document.createElement("div"); backdrop.className = "erp-dialog-backdrop"; var box = document.createElement("div"); box.className = "erp-dialog" + (options.ask ? " erp-dialog-ask" : ""); box.setAttribute("role", "alertdialog"); box.setAttribute("aria-modal", "true"); box.setAttribute("aria-label", TITLE); var title = document.createElement("h2"); title.className = "erp-dialog-title"; title.textContent = TITLE; var body = document.createElement("div"); body.className = "erp-dialog-body"; var icon = document.createElement("span"); icon.className = "erp-dialog-icon"; icon.innerHTML = ICON; var text = document.createElement("p"); text.className = "erp-dialog-message"; // 메시지는 반드시 textContent 로 넣는다 — 서버/사용자 문자열이 들어와도 // HTML 로 해석되지 않게. text.textContent = String(message == null ? "" : message); var actions = document.createElement("div"); actions.className = "erp-dialog-actions"; var cancel = null; if (options.ask) { cancel = document.createElement("button"); cancel.type = "button"; cancel.className = "erp-btn erp-btn-outline"; cancel.textContent = options.cancelText || "취소"; actions.appendChild(cancel); } var ok = document.createElement("button"); ok.type = "button"; ok.className = "erp-btn erp-btn-primary"; ok.textContent = options.okText || "확인"; actions.appendChild(ok); body.appendChild(icon); body.appendChild(text); box.appendChild(title); box.appendChild(body); box.appendChild(actions); backdrop.appendChild(box); return { backdrop: backdrop, box: box, ok: ok, cancel: cancel }; } function open(message, options) { return new Promise(function (resolve) { var el = build(message, options); var previous = document.activeElement; var closed = false; function close(result) { if (closed) return; closed = true; document.removeEventListener("keydown", onKey, true); el.backdrop.remove(); if (previous && typeof previous.focus === "function") previous.focus(); resolve(result); } function onKey(e) { if (e.key === "Escape") { e.preventDefault(); close(false); // 확인창의 Esc = 취소, 알림창의 Esc = 닫기 } else if (e.key === "Enter") { e.preventDefault(); close(true); } else if (e.key === "Tab") { // 포커스가 창 밖으로 나가지 않게 두 버튼 사이에서만 돈다. var focusable = el.cancel ? [el.cancel, el.ok] : [el.ok]; var index = focusable.indexOf(document.activeElement); e.preventDefault(); var next = e.shiftKey ? index - 1 : index + 1; if (next < 0) next = focusable.length - 1; if (next >= focusable.length) next = 0; focusable[next].focus(); } } el.ok.addEventListener("click", function () { close(true); }); if (el.cancel) el.cancel.addEventListener("click", function () { close(false); }); // 바깥을 누르면 취소(= 안전한 쪽). 창 안쪽 클릭은 그대로 둔다. el.backdrop.addEventListener("mousedown", function (e) { if (e.target === el.backdrop) close(false); }); document.addEventListener("keydown", onKey, true); document.body.appendChild(el.backdrop); el.ok.focus(); }); } window.erpConfirm = function (message, options) { var opts = options || {}; opts.ask = true; return open(message, opts); }; window.erpAlert = function (message, options) { var opts = options || {}; opts.ask = false; return open(message, opts).then(function () { return undefined; }); }; // data-erp-confirm 이 달린 폼은 제출 전에 확인을 받는다. document.addEventListener("submit", function (e) { var form = e.target; if (!form || !form.dataset || !form.dataset.erpConfirm) return; if (form.dataset.erpConfirmed === "1") return; // 확인을 마치고 다시 보낸 것 e.preventDefault(); window.erpConfirm(form.dataset.erpConfirm).then(function (ok) { if (!ok) return; form.dataset.erpConfirmed = "1"; form.submit(); // submit 이벤트를 다시 타지 않는다 }); }); })();