עץ הנגישות המלא בכלי הפיתוח ל-Chrome

Johan Bay
Johan Bay

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

מהו עץ הנגישות?

טכנולוגיה מסייעת כמו קוראי מסך משתמשת בממשק ה-API לנגישות של Chromium כדי לבצע אינטראקציה עם תוכן באינטרנט. המודל הבסיסי של ה-API הזה הוא עץ הנגישות: עץ של אובייקטי נגישות שהטכנולוגיה המסייעת יכולה לשלוח שאילתות על מאפיינים ומאפיינים ולבצע בהם פעולות. מפתחי אתרים מעצבים את עץ הנגישות ומשנים אותו בעיקר באמצעות מאפייני DOM, כמו מאפייני ARIA ל-HTML.

בכלי הפיתוח ל-Chrome אנחנו מספקים את חלונית הנגישות כדי לעזור למפתחים להבין איך התוכן שלהם חשוף לטכנולוגיה מסייעת. באופן קונקרטי, כאשר צומת נבחר במציג עץ ה-DOM, המאפיינים של צומת הנגישות התואם מוצגים בחלונית יחד עם תצוגה של אבות האב של הצומת והצאצאים המיידיים שלו.

חלונית הנגישות של כלי הפיתוח ל-Chrome.

איך נוצר העץ?

לפני שנעבור איך נראית תצוגת העץ המלאה הזו בכלי הפיתוח, נבחן בקצרה מהו עץ הנגישות במונחים מוחשיים יותר. עץ הנגישות הוא נגזרת של עץ ה-DOM. המבנה שלו די דומה, אבל פשוט יותר להסיר צמתים ללא תוכן סמנטי, כמו רכיב <div> שמשמש אך ורק לעיצוב. לכל צומת בעץ יש תפקיד כמו Button או Heading, ולעיתים קרובות שם יכול להיות על בסיס מאפייני ARIA או על תוכן שנגזר מתוכן הצומת. אם אנחנו מסתכלים על מסמך HTML:

<html>
<head>
  <title>How old are you?</title>
</head>
<body>
  <label for="age">Age</label>
  <input id="age" type="number" name="age" value="42">
  <div>
    <button>Back</button>
    <button>Next</button>
  </div>
</body>
</html>

כלי הרינדור ב-Chromium, שנקרא Blink, מפיק עץ נגישות פנימי באופן הבא, פחות או יותר.

role='rootWebArea' focusable name='How old are you?'
  role='genericContainer' ignored
    role='genericContainer' ignored
      role='labelText'
        role='staticText' name='Age'
      role='spinButton' editable focusable name='Age' value='42'
        role='genericContainer' editable
          role='staticText' editable name='42'
      role='genericContainer'
        role='button' focusable name='Back'
          role='staticText' name='Back'
        role='button' focusable name='Next'
          role='staticText' name='Next'

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

עץ נגישות מלא בכלי הפיתוח

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

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

<!DOCTYPE html>
<title>Test</title>
<h1>Heading for example page</h1>
<div>
  <button>Back</button>
  <button>Next</button>
</div>

בתצוגת העץ הקודמת אפשר לחקור רק צומת אחד ואת ישות האב שלו.

תצוגת העץ הקודמת בכלי הפיתוח.

עכשיו, כשמחליפים את המצב של העץ החדש, הוא מחליף את תצוגת עץ ה-DOM ומאפשר לראות את עץ הנגישות המלא של הדף:

תצוגת העץ החדשה בכלי הפיתוח.

בניית עצים עצלתיים

כדי שהעצים ישיגו ביצועים טובים גם באתרים גדולים יותר, העץ נבנה באופן מדורג בקצה הקדמי בזמן שחוקרים אותו. אחרי שמרחיבים צומת בעץ, הצאצאים של הצמתים מאוחזרים דרך פרוטוקול Chrome DevTools (CDP) והעץ נבנה מחדש.

עץ הנגישות החדש שמציג את התוצאה של דף גדול.

מצב לייב

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

סיפורם של עצים רבים

בתיאור מהו עץ הנגישות, למדתם איך מערכת Blink בונה עץ נגישות ל-DOM שהיא מעבדת, וכלי הפיתוח מאחזרים את העץ הזה דרך CDP. זה נכון, אבל השמטנו כמה סיבוכים בתיאור הזה. בפועל, יש הרבה דרכים שונות להתנסות בעץ הנגישות ב-Chromium. כשעיצבנו את תצוגת העץ החדשה של כלי הפיתוח, בחרנו כמה אפשרויות לגבי החלק הפנימי של תכונות הנגישות ב-Chromium שרצינו להציג.

פלטפורמות

לכל פלטפורמה יש ממשק API שונה לנגישות. למרות שצורת העץ זהה בכל הפלטפורמות, ה-API לאינטראקציה עם העץ שונה ושמות המאפיינים יכולים להיות שונים. בכלי הפיתוח מוצג העץ הפנימי של Chromium, שבו התפקידים והמאפיינים בדרך כלל תואמים לאלה שמוגדרים במפרט ARIA.

מסגרות מרובות ובידוד של אתר

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

צמתים שהמערכת מתעלמת מהם או לא מעניינת

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

תצוגת עץ חדשה עם כל הצמתים מוצגים.

האזהרה הזאת היא שלמעשה, המשמעות היא שאנחנו צריכים לבנות עץ נוסף מזה שזמין בקצה העורפי. לדוגמה, נניח שיש לנו את הצמתים A, B, C ו-X שבהם A הוא צאצא X ו-B, ול-X יש את צאצא ג'. אם X הוא צומת שמתעלמים ממנו, אנחנו מסירים את X מהעץ ובמקום זאת יוצרים עץ שבו C הוא צאצא של א'.

תרשים שמראה איך אנחנו מסורגים את העצים.

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

  • קל יותר לטפל בעדכונים של צמתים מהקצה העורפי, כי מבנה העץ זהה בשתי נקודות הקצה. לדוגמה, אם מסירים את הצומת B בדוגמה, נקבל עדכון לגבי צומת X (כי הצאצאים שלו השתנו), אבל אם קיצו את הצומת הזה יהיה לנו קשה להבין מה לעדכן.
  • הוא מבטיח שלכל צומתי ה-DOM יהיה צומת נגישות תואם. כשהעץ מופעל, אנחנו בוחרים את הצומת שתואם לצומת שנבחר כרגע בעץ ה-DOM. למשל, בדוגמה הקודמת, אם המשתמש עובר למצב של העץ בזמן שצומת ה-DOM שתואם ל-X נבחר, המערכת מחדירה את X בין הצמתים A ו-B ובוחרים ב-X בעץ. כך המשתמש יכול לבדוק את צומת הנגישות עבור כל צומתי ה-DOM ולהבין למה המערכת מתעלמת מהצומת.

רעיונות לעתיד

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

מסננים חלופיים

כפי שהוסבר למעלה, בשלב זה אנחנו מסננים צמתים שנחשבים לא מעניינים. אפשר להשבית את ההתנהגות הזו ולהציג את כל הצמתים, או לספק מסננים חלופיים כמו הצגת צמתים מסומנים או הצגת כותרות.

הדגשת בעיות A11y

נוכל לשלב ניתוח של 'שיטות מומלצות לנגישות' בעץ, ולהדגיש בעיות נגישות ישירות בצמתים הבעייתיים.

הצגת פעולות בנושא נגישות בכלי הפיתוח

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