דיאלוגים מודאליים בדפדפן

18/08/2023

לפעמים יש לי אמונות והרגלים כל כך עתיקים שאפילו כשיש מסביב רמזים לשינוי אני לא טורח לבדוק אותם. דיאלוגים מודאליים ב HTML? אין דבר כזה. צריך ליצור אלמנט ולהשתמש ב CSS כדי לתת "הרגשה של מודאלי". ככה זה היה תמיד.

כן טוב, מה שהיה הוא לא מה שיהיה. כרום 37, אדג' 79, פיירפוקס 98, אופרה 24, ספארי 15.4 ואפילו דפדפני המובייל - כולם תומכים היום תמיכה מובנית וטבעית באלמנט dialog ויודעים להציג דיאלוג מודאלי בלי שום ספריה ובצורה נגישה.

בואו נראה איך זה עובד.

1. דוגמה 1 - דיאלוג עם כפתור סגירה

בשביל ליצור דיאלוג מודאלי אני רק צריך אלמנט מסוג dialog ב HTML:

<p>
  Hello World
  <button id="show">show dialog</button>
</p>
<dialog id="modal">
  <p>Dialog Content</p>
  <button>Close</button>
</dialog>

בשביל להציג או לסגור את הדיאלוג אני משתמש ב JavaScript. הפונקציה showModal מציגה את הדיאלוג בצורה מודאלית, והפונקציה close סוגרת את הדיאלוג:

document.querySelector('#show').addEventListener('click', () => {
  const dialog = document.getElementById("modal");
  dialog.showModal();
})

document.querySelector('#modal button').addEventListener('click', () => {
  const dialog = document.getElementById("modal");
  dialog.close();
});

כשהדיאלוג פתוח אי אפשר ללחוץ על הכפתורים הרגילים שנמצאים על העמוד ובשינוי פוקוס עם טאב אנחנו נשארים בתוך הדיאלוג - ולחיצה על Escape סוגרת אוטומטית את הדיאלוג. קסום.

2. דוגמה 2 - דיאלוג לא מודאלי

אם אתם רוצים שהעמוד ימשיך לתפקד תוך כדי שהדיאלוג מוצג אז הדיאלוג שלכם נקרא "דיאלוג לא מודאלי", ותוכלו להשתמש בפונקציה show בשביל להציג את הדיאלוג בצורה כזאת:

document.querySelector('#show').addEventListener('click', () => {
  const dialog = document.getElementById("modal");
  const counter = dialog.querySelector('.counter');
  counter.textContent = Number(counter.textContent) + 1;
  dialog.show();
})

document.querySelector('#modal button').addEventListener('click', () => {
  const dialog = document.getElementById("modal");
  dialog.close();
});

והנה גם הוא באייפריים בשביל משחקים:

3. דוגמא 3 - דיאלוגים מחזירים ערך

ואם הסיפור עד כאן לא היה מספיק משוגע, תשמחו לשמוע שדיאלוגים יכולים גם להציג טפסים ולהחזיר ערך שייצג את הערכים שהמשתמש בחר דרך הטופס. אם בתוך דיאלוג יש טופס, ולטופס הזה יש מאפיין method עם הערך dialog, אז בלחיצה על כפתור של הטופס הדיאלוג אוטומטית ייסגר, ומאפיין returnValue של הדיאלוג יכיל את ה value של הכפתור שנלחץ.

בדוגמה הבאה שמתבססת על דוגמה מהתיעוד הדיאלוג כולל טופס עם תיבת בחירה:

<!-- A modal dialog containing a form -->
<dialog id="favDialog">
  <form method="dialog">
    <p>
      <label>
        Favorite animal:
        <select>
          <option value="default">Choose…</option>
          <option>Brine shrimp</option>
          <option>Red panda</option>
          <option>Spider monkey</option>
        </select>
      </label>
    </p>
    <div>
      <button value="cancel">Cancel</button>
      <button id="confirmBtn" value="default">Confirm</button>
    </div>
  </form>
</dialog>
<p>
  <button id="showDialog">Show the dialog</button>
</p>
<output></output>

בעזרת JavaScript אנחנו מציגים את הדיאלוג בעת לחיצה על הכפתור אבל הפעם אין צורך לסגור אותו. הטופס ייסגר לבד וישלח אירוע close, שקוד הטיפול בו לוקח את ה value של הכפתור שנלחץ ומעתיק אותו למסך מחוץ לדיאלוג:

const showButton = document.getElementById("showDialog");
const favDialog = document.getElementById("favDialog");
const outputBox = document.querySelector("output");
const selectEl = favDialog.querySelector("select");
const confirmBtn = favDialog.querySelector("#confirmBtn");

// "Show the dialog" button opens the <dialog> modally
showButton.addEventListener("click", () => {
  favDialog.showModal();
});

// "Favorite animal" input sets the value of the submit button
selectEl.addEventListener("change", (e) => {
  confirmBtn.value = selectEl.value;
});

// "Cancel" button closes the dialog without submitting because of [formmethod="dialog"], triggering a close event.
favDialog.addEventListener("close", (e) => {
  outputBox.value =
    favDialog.returnValue === "default"
      ? "No return value."
      : `ReturnValue: ${favDialog.returnValue}.`; // Have to check for "default" rather than empty string
});

וזה בקודפן למשחקים: