PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.2.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.2.0
2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 All 65 releases
subscription / assets / js / admin-components / modal.js

modal.js in Subscriptions for WooCommerce with Stripe Recurring Payments 2.2.0, at assets/js/admin-components/modal.js

102 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * WPSubsModal — reusable centered dialog over a dimmed backdrop.
3 *
4 * Behaviour only; the visual comes from the .wpsubs-modal CSS. A modal is a
5 * `.wpsubs-modal[hidden]` element with an id. Any control opens it via
6 * `data-wpsubs-modal-open="<modal-id>"`; any control inside closes it via
7 * `data-wpsubs-modal-close` (the backdrop and the header/footer buttons use it).
8 * Escape also closes. No per-page wiring needed.
9 *
10 * A modal with `data-wpsubs-modal-autoopen` opens automatically on load (e.g. the
11 * Pro-upgrade preview modals). Opening locks body scroll; it's restored when the
12 * last open modal closes.
13 *
14 * Usage:
15 * PHP: wpsubs_render_modal( $args ) — renders the markup
16 * JS: auto-inits; WPSubsModal.open(id) / .close(id) available programmatically
17 *
18 * Events fired on the modal element (bubbles):
19 * wpsubs:modal:open / wpsubs:modal:close
20 */
21 (function () {
22 "use strict";
23
24 /**
25 * @param {string|HTMLElement} target Modal id or element.
26 * @return {HTMLElement|null}
27 */
28 function resolve(target) {
29 if (target instanceof HTMLElement) return target;
30 return document.getElementById(String(target));
31 }
32
33 function open(target) {
34 var modal = resolve(target);
35 if (!modal) return;
36 modal.hidden = false;
37 document.body.style.overflow = "hidden";
38 modal.dispatchEvent(new CustomEvent("wpsubs:modal:open", { bubbles: true }));
39 var focusable = modal.querySelector("input, textarea, select, button:not([data-wpsubs-modal-close])");
40 if (focusable) focusable.focus();
41 }
42
43 function close(target) {
44 var modal = resolve(target);
45 if (!modal) return;
46 modal.hidden = true;
47 // Restore body scroll only when no modal remains open.
48 if (!document.querySelector(".wpsubs-modal:not([hidden])")) {
49 document.body.style.overflow = "";
50 }
51 modal.dispatchEvent(new CustomEvent("wpsubs:modal:close", { bubbles: true }));
52 }
53
54 function closeAll() {
55 document.querySelectorAll(".wpsubs-modal:not([hidden])").forEach(function (m) {
56 close(m);
57 });
58 }
59
60 // Delegated open/close — works for markup added after load too.
61 document.addEventListener("click", function (e) {
62 var opener = e.target.closest("[data-wpsubs-modal-open]");
63 if (opener) {
64 e.preventDefault();
65 open(opener.getAttribute("data-wpsubs-modal-open"));
66 return;
67 }
68 var closer = e.target.closest("[data-wpsubs-modal-close]");
69 if (closer) {
70 e.preventDefault();
71 var modal = closer.closest(".wpsubs-modal");
72 if (modal) close(modal);
73 }
74 });
75
76 document.addEventListener("keydown", function (e) {
77 if (e.key === "Escape") closeAll();
78 });
79
80 /**
81 * Open any modal flagged to auto-open on load.
82 *
83 * @param {Document|HTMLElement} [root]
84 */
85 function init(root) {
86 (root || document).querySelectorAll(".wpsubs-modal[data-wpsubs-modal-autoopen]").forEach(function (modal) {
87 open(modal);
88 });
89 }
90
91 if (document.readyState === "loading") {
92 document.addEventListener("DOMContentLoaded", function () {
93 init();
94 });
95 } else {
96 init();
97 }
98
99 // Public API
100 window.WPSubsModal = { open: open, close: close, init: init };
101 })();
102