33// @namespace http://axSgrease.nvaccess.org/
44// @description Improves the accessibility of Sched.
55// @author James Teh <jteh@mozilla.com>
6- // @copyright 2018 Mozilla Corporation
6+ // @copyright 2019 Mozilla Corporation, Derek Riemer
77// @license Mozilla Public License version 2.0
8- // @version 2018.1
9- // @grant GM_log
8+ // @version 2019.1
109// @include https://*.sched.com/*
1110// ==/UserScript==
1211
@@ -24,7 +23,9 @@ function makeRegion(el, label) {
2423
2524function makeButton ( el , label ) {
2625 el . setAttribute ( "role" , "button" ) ;
27- el . setAttribute ( "aria-label" , label ) ;
26+ if ( label ) {
27+ el . setAttribute ( "aria-label" , label ) ;
28+ }
2829}
2930
3031function makePresentational ( el ) {
@@ -43,6 +44,34 @@ function setExpanded(el, expanded) {
4344 el . setAttribute ( "aria-expanded" , expanded ? "true" : "false" ) ;
4445}
4546
47+ var idCounter = 0 ;
48+ // Get a node's id. If it doesn't have one, make and set one first.
49+ function setAriaIdIfNecessary ( elem ) {
50+ if ( ! elem . id ) {
51+ elem . setAttribute ( "id" , "axsg-" + idCounter ++ ) ;
52+ }
53+ return elem . id ;
54+ }
55+
56+ function makeElementOwn ( parentElement , listOfNodes ) {
57+ ids = [ ] ;
58+ for ( let node of listOfNodes ) {
59+ ids . push ( setAriaIdIfNecessary ( node ) ) ;
60+ }
61+ parentElement . setAttribute ( "aria-owns" , ids . join ( " " ) ) ;
62+ }
63+
64+ // Focus something even if it wasn't made focusable by the author.
65+ function forceFocus ( el ) {
66+ let focusable = el . hasAttribute ( "tabindex" ) ;
67+ if ( focusable ) {
68+ el . focus ( ) ;
69+ return ;
70+ }
71+ el . setAttribute ( "tabindex" , "-1" ) ;
72+ el . focus ( ) ;
73+ }
74+
4675/*** Code to apply the tweaks when appropriate. ***/
4776
4877function applyTweak ( el , tweak ) {
@@ -57,19 +86,22 @@ function applyTweak(el, tweak) {
5786function applyTweaks ( root , tweaks , checkRoot ) {
5887 for ( let tweak of tweaks ) {
5988 for ( let el of root . querySelectorAll ( tweak . selector ) ) {
60- applyTweak ( el , tweak ) ;
89+ try {
90+ applyTweak ( el , tweak ) ;
91+ } catch ( e ) {
92+ console . log ( "Exception while applying tweak for '" + tweak . selector + "': " + e ) ;
93+ }
6194 }
6295 if ( checkRoot && root . matches ( tweak . selector ) ) {
63- applyTweak ( root , tweak ) ;
96+ try {
97+ applyTweak ( root , tweak ) ;
98+ } catch ( e ) {
99+ console . log ( "Exception while applying tweak for '" + tweak . selector + "': " + e ) ;
100+ }
64101 }
65102 }
66103}
67104
68- function init ( ) {
69- applyTweaks ( document , LOAD_TWEAKS , false ) ;
70- applyTweaks ( document , DYNAMIC_TWEAKS , false ) ;
71- }
72-
73105let observer = new MutationObserver ( function ( mutations ) {
74106 for ( let mutation of mutations ) {
75107 try {
@@ -81,18 +113,25 @@ let observer = new MutationObserver(function(mutations) {
81113 applyTweaks ( node , DYNAMIC_TWEAKS , true ) ;
82114 }
83115 } else if ( mutation . type === "attributes" ) {
84- if ( mutation . attributeName == "class" ) {
85- applyTweaks ( mutation . target , DYNAMIC_TWEAKS , true ) ;
86- }
116+ applyTweaks ( mutation . target , DYNAMIC_TWEAKS , true ) ;
87117 }
88118 } catch ( e ) {
89119 // Catch exceptions for individual mutations so other mutations are still handled.
90- GM_log ( "Exception while handling mutation: " + e ) ;
120+ console . log ( "Exception while handling mutation: " + e ) ;
91121 }
92122 }
93123} ) ;
94- observer . observe ( document , { childList : true , attributes : true ,
95- subtree : true , attributeFilter : [ "class" ] } ) ;
124+
125+ function init ( ) {
126+ applyTweaks ( document , LOAD_TWEAKS , false ) ;
127+ applyTweaks ( document , DYNAMIC_TWEAKS , false ) ;
128+ options = { childList : true , subtree : true } ;
129+ if ( DYNAMIC_TWEAK_ATTRIBS . length > 0 ) {
130+ options . attributes = true ;
131+ options . attributeFilter = DYNAMIC_TWEAK_ATTRIBS ;
132+ }
133+ observer . observe ( document , options ) ;
134+ }
96135
97136/*** Define the actual tweaks. ***/
98137
@@ -120,6 +159,10 @@ const LOAD_TWEAKS = [
120159 } } ,
121160]
122161
162+ // Attributes that should be watched for changes and cause dynamic tweaks to be
163+ // applied.
164+ const DYNAMIC_TWEAK_ATTRIBS = [ "class" ] ;
165+
123166// Tweaks that must be applied whenever a node is added/changed.
124167const DYNAMIC_TWEAKS = [
125168 { selector : ':not(.sub)>.ev-save' ,
0 commit comments