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

Johan Bay
Johan Bay

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

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

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

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

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

איך נוצר העץ?

לפני שנראה איך נראית תצוגת העץ המלאה החדשה ב-DevTools, ננסה להסביר בקצרה מהו עץ הנגישות במונחים מוחשי יותר. עץ הנגישות הוא נגזרת של עץ ה-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>

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

תצוגת העץ הקודמת ב-DevTools.

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

תצוגת העץ החדשה ב-DevTools.

יצירת עץ ביעילות

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

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

בשידור חי

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

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

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

פלטפורמות

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

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

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

צמתים שלא נלקחו בחשבון וצמתים לא מעניינים

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

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

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

תרשים שמראה איך אנחנו גוזמים את העץ.

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

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

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

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

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

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

הדגשת בעיות נגישות

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

הצגת פעולות נגישות ב-DevTools

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