accessibility-widgets 1.0.6 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +370 -365
- package/package.json +1 -1
- package/widget.js +1244 -436
package/widget.js
CHANGED
|
@@ -1,10 +1,396 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/*
|
|
2
2
|
===========================================
|
|
3
3
|
ACCESSIBILITY WIDGET
|
|
4
|
-
A comprehensive web accessibility tool
|
|
5
4
|
===========================================
|
|
6
5
|
*/
|
|
7
6
|
|
|
7
|
+
// ===========================================
|
|
8
|
+
// TRANSLATIONS
|
|
9
|
+
// ===========================================
|
|
10
|
+
|
|
11
|
+
const TRANSLATIONS = {
|
|
12
|
+
en: {
|
|
13
|
+
accessibilityMenu: 'Accessibility Menu',
|
|
14
|
+
closeAccessibilityMenu: 'Close Accessibility Menu',
|
|
15
|
+
accessibilityTools: 'Accessibility Tools',
|
|
16
|
+
resetAllSettings: 'Reset All Settings',
|
|
17
|
+
screenReader: 'Screen Reader',
|
|
18
|
+
voiceCommand: 'Voice Command',
|
|
19
|
+
textSpacing: 'Text Spacing',
|
|
20
|
+
pauseAnimations: 'Pause Animations',
|
|
21
|
+
hideImages: 'Hide Images',
|
|
22
|
+
dyslexiaFriendly: 'Dyslexia Friendly',
|
|
23
|
+
biggerCursor: 'Bigger Cursor',
|
|
24
|
+
lineHeight: 'Line Height',
|
|
25
|
+
fontSelection: 'Font Selection',
|
|
26
|
+
colorFilter: 'Color Filter',
|
|
27
|
+
textAlign: 'Text Align',
|
|
28
|
+
textSize: 'Text Size',
|
|
29
|
+
highContrast: 'High Contrast',
|
|
30
|
+
defaultFont: 'Default Font',
|
|
31
|
+
noFilter: 'No Filter',
|
|
32
|
+
default: 'Default',
|
|
33
|
+
screenReaderOn: 'Screen reader on',
|
|
34
|
+
screenReaderOff: 'Screen reader off',
|
|
35
|
+
voiceControlActivated: 'Voice control activated',
|
|
36
|
+
notSupportedBrowser: 'is not supported in this browser',
|
|
37
|
+
close: 'Close',
|
|
38
|
+
reset: 'Reset',
|
|
39
|
+
saturation: 'Saturation',
|
|
40
|
+
selectLanguage: 'Select Language'
|
|
41
|
+
},
|
|
42
|
+
de: {
|
|
43
|
+
accessibilityMenu: 'Barrierefreiheitsmenü',
|
|
44
|
+
closeAccessibilityMenu: 'Barrierefreiheitsmenü schließen',
|
|
45
|
+
accessibilityTools: 'Barrierefreiheitswerkzeuge',
|
|
46
|
+
resetAllSettings: 'Alle Einstellungen zurücksetzen',
|
|
47
|
+
screenReader: 'Screenreader',
|
|
48
|
+
voiceCommand: 'Sprachbefehl',
|
|
49
|
+
textSpacing: 'Textabstand',
|
|
50
|
+
pauseAnimations: 'Animationen pausieren',
|
|
51
|
+
hideImages: 'Bilder ausblenden',
|
|
52
|
+
dyslexiaFriendly: 'Legasthenie-freundlich',
|
|
53
|
+
biggerCursor: 'Größerer Cursor',
|
|
54
|
+
lineHeight: 'Zeilenhöhe',
|
|
55
|
+
fontSelection: 'Schriftauswahl',
|
|
56
|
+
colorFilter: 'Farbfilter',
|
|
57
|
+
textAlign: 'Textausrichtung',
|
|
58
|
+
textSize: 'Textgröße',
|
|
59
|
+
highContrast: 'Hoher Kontrast',
|
|
60
|
+
defaultFont: 'Standardschrift',
|
|
61
|
+
noFilter: 'Kein Filter',
|
|
62
|
+
default: 'Standard',
|
|
63
|
+
screenReaderOn: 'Screenreader ein',
|
|
64
|
+
screenReaderOff: 'Screenreader aus',
|
|
65
|
+
voiceControlActivated: 'Sprachsteuerung aktiviert',
|
|
66
|
+
notSupportedBrowser: 'wird in diesem Browser nicht unterstützt',
|
|
67
|
+
close: 'Schließen',
|
|
68
|
+
reset: 'Zurücksetzen',
|
|
69
|
+
saturation: 'Sättigung',
|
|
70
|
+
selectLanguage: 'Sprache wählen'
|
|
71
|
+
},
|
|
72
|
+
es: {
|
|
73
|
+
accessibilityMenu: 'Menú de Accesibilidad',
|
|
74
|
+
closeAccessibilityMenu: 'Cerrar Menú de Accesibilidad',
|
|
75
|
+
accessibilityTools: 'Herramientas de Accesibilidad',
|
|
76
|
+
resetAllSettings: 'Restablecer Todas las Configuraciones',
|
|
77
|
+
screenReader: 'Lector de Pantalla',
|
|
78
|
+
voiceCommand: 'Comando de Voz',
|
|
79
|
+
textSpacing: 'Espaciado de Texto',
|
|
80
|
+
pauseAnimations: 'Pausar Animaciones',
|
|
81
|
+
hideImages: 'Ocultar Imágenes',
|
|
82
|
+
dyslexiaFriendly: 'Amigable para Dislexia',
|
|
83
|
+
biggerCursor: 'Cursor Más Grande',
|
|
84
|
+
lineHeight: 'Altura de Línea',
|
|
85
|
+
fontSelection: 'Selección de Fuente',
|
|
86
|
+
colorFilter: 'Filtro de Color',
|
|
87
|
+
textAlign: 'Alineación de Texto',
|
|
88
|
+
textSize: 'Tamaño de Texto',
|
|
89
|
+
highContrast: 'Alto Contraste',
|
|
90
|
+
defaultFont: 'Fuente Predeterminada',
|
|
91
|
+
noFilter: 'Sin Filtro',
|
|
92
|
+
default: 'Predeterminado',
|
|
93
|
+
screenReaderOn: 'Lector de pantalla activado',
|
|
94
|
+
screenReaderOff: 'Lector de pantalla desactivado',
|
|
95
|
+
voiceControlActivated: 'Control de voz activado',
|
|
96
|
+
notSupportedBrowser: 'no es compatible con este navegador',
|
|
97
|
+
close: 'Cerrar',
|
|
98
|
+
reset: 'Restablecer',
|
|
99
|
+
saturation: 'Saturación',
|
|
100
|
+
selectLanguage: 'Seleccionar Idioma'
|
|
101
|
+
},
|
|
102
|
+
it: {
|
|
103
|
+
accessibilityMenu: 'Menu Accessibilità',
|
|
104
|
+
closeAccessibilityMenu: 'Chiudi Menu Accessibilità',
|
|
105
|
+
accessibilityTools: 'Strumenti di Accessibilità',
|
|
106
|
+
resetAllSettings: 'Ripristina Tutte le Impostazioni',
|
|
107
|
+
screenReader: 'Lettore Schermo',
|
|
108
|
+
voiceCommand: 'Comando Vocale',
|
|
109
|
+
textSpacing: 'Spaziatura Testo',
|
|
110
|
+
pauseAnimations: 'Pausa Animazioni',
|
|
111
|
+
hideImages: 'Nascondi Immagini',
|
|
112
|
+
dyslexiaFriendly: 'Adatto alla Dislessia',
|
|
113
|
+
biggerCursor: 'Cursore Più Grande',
|
|
114
|
+
lineHeight: 'Altezza Linea',
|
|
115
|
+
fontSelection: 'Selezione Font',
|
|
116
|
+
colorFilter: 'Filtro Colore',
|
|
117
|
+
textAlign: 'Allineamento Testo',
|
|
118
|
+
textSize: 'Dimensione Testo',
|
|
119
|
+
highContrast: 'Alto Contrasto',
|
|
120
|
+
defaultFont: 'Font Predefinito',
|
|
121
|
+
noFilter: 'Nessun Filtro',
|
|
122
|
+
default: 'Predefinito',
|
|
123
|
+
screenReaderOn: 'Lettore schermo attivo',
|
|
124
|
+
screenReaderOff: 'Lettore schermo disattivo',
|
|
125
|
+
voiceControlActivated: 'Controllo vocale attivato',
|
|
126
|
+
notSupportedBrowser: 'non è supportato in questo browser',
|
|
127
|
+
close: 'Chiudi',
|
|
128
|
+
reset: 'Ripristina',
|
|
129
|
+
saturation: 'Saturazione',
|
|
130
|
+
selectLanguage: 'Seleziona Lingua'
|
|
131
|
+
},
|
|
132
|
+
fr: {
|
|
133
|
+
accessibilityMenu: 'Menu Accessibilité',
|
|
134
|
+
closeAccessibilityMenu: 'Fermer le Menu Accessibilité',
|
|
135
|
+
accessibilityTools: 'Outils d\'Accessibilité',
|
|
136
|
+
resetAllSettings: 'Réinitialiser Tous les Paramètres',
|
|
137
|
+
screenReader: 'Lecteur d\'Écran',
|
|
138
|
+
voiceCommand: 'Commande Vocale',
|
|
139
|
+
textSpacing: 'Espacement du Texte',
|
|
140
|
+
pauseAnimations: 'Mettre en Pause les Animations',
|
|
141
|
+
hideImages: 'Masquer les Images',
|
|
142
|
+
dyslexiaFriendly: 'Convivial pour la Dyslexie',
|
|
143
|
+
biggerCursor: 'Curseur Plus Grand',
|
|
144
|
+
lineHeight: 'Hauteur de Ligne',
|
|
145
|
+
fontSelection: 'Sélection de Police',
|
|
146
|
+
colorFilter: 'Filtre de Couleur',
|
|
147
|
+
textAlign: 'Alignement du Texte',
|
|
148
|
+
textSize: 'Taille du Texte',
|
|
149
|
+
highContrast: 'Contraste Élevé',
|
|
150
|
+
defaultFont: 'Police par Défaut',
|
|
151
|
+
noFilter: 'Aucun Filtre',
|
|
152
|
+
default: 'Par Défaut',
|
|
153
|
+
screenReaderOn: 'Lecteur d\'écran activé',
|
|
154
|
+
screenReaderOff: 'Lecteur d\'écran désactivé',
|
|
155
|
+
voiceControlActivated: 'Contrôle vocal activé',
|
|
156
|
+
notSupportedBrowser: 'n\'est pas pris en charge dans ce navigateur',
|
|
157
|
+
close: 'Fermer',
|
|
158
|
+
reset: 'Réinitialiser',
|
|
159
|
+
saturation: 'Saturation',
|
|
160
|
+
selectLanguage: 'Sélectionner la Langue'
|
|
161
|
+
},
|
|
162
|
+
ru: {
|
|
163
|
+
accessibilityMenu: 'Меню Доступности',
|
|
164
|
+
closeAccessibilityMenu: 'Закрыть Меню Доступности',
|
|
165
|
+
accessibilityTools: 'Инструменты Доступности',
|
|
166
|
+
resetAllSettings: 'Сбросить Все Настройки',
|
|
167
|
+
screenReader: 'Программа Чтения с Экрана',
|
|
168
|
+
voiceCommand: 'Голосовая Команда',
|
|
169
|
+
textSpacing: 'Межбуквенный Интервал',
|
|
170
|
+
pauseAnimations: 'Приостановить Анимацию',
|
|
171
|
+
hideImages: 'Скрыть Изображения',
|
|
172
|
+
dyslexiaFriendly: 'Для Дислексии',
|
|
173
|
+
biggerCursor: 'Увеличенный Курсор',
|
|
174
|
+
lineHeight: 'Высота Строки',
|
|
175
|
+
fontSelection: 'Выбор Шрифта',
|
|
176
|
+
colorFilter: 'Цветовой Фильтр',
|
|
177
|
+
textAlign: 'Выравнивание Текста',
|
|
178
|
+
textSize: 'Размер Текста',
|
|
179
|
+
highContrast: 'Высокая Контрастность',
|
|
180
|
+
defaultFont: 'Шрифт по Умолчанию',
|
|
181
|
+
noFilter: 'Без Фильтра',
|
|
182
|
+
default: 'По Умолчанию',
|
|
183
|
+
screenReaderOn: 'Программа чтения включена',
|
|
184
|
+
screenReaderOff: 'Программа чтения выключена',
|
|
185
|
+
voiceControlActivated: 'Голосовое управление активировано',
|
|
186
|
+
notSupportedBrowser: 'не поддерживается в этом браузере',
|
|
187
|
+
close: 'Закрыть',
|
|
188
|
+
reset: 'Сбросить',
|
|
189
|
+
saturation: 'Насыщенность',
|
|
190
|
+
selectLanguage: 'Выберите Язык'
|
|
191
|
+
},
|
|
192
|
+
tr: {
|
|
193
|
+
accessibilityMenu: 'Erişilebilirlik Menüsü',
|
|
194
|
+
closeAccessibilityMenu: 'Erişilebilirlik Menüsünü Kapat',
|
|
195
|
+
accessibilityTools: 'Erişilebilirlik Araçları',
|
|
196
|
+
resetAllSettings: 'Tüm Ayarları Sıfırla',
|
|
197
|
+
screenReader: 'Ekran Okuyucu',
|
|
198
|
+
voiceCommand: 'Sesli Komut',
|
|
199
|
+
textSpacing: 'Metin Aralığı',
|
|
200
|
+
pauseAnimations: 'Animasyonları Duraklat',
|
|
201
|
+
hideImages: 'Resimleri Gizle',
|
|
202
|
+
dyslexiaFriendly: 'Disleksi Dostu',
|
|
203
|
+
biggerCursor: 'Daha Büyük İmleç',
|
|
204
|
+
lineHeight: 'Satır Yüksekliği',
|
|
205
|
+
fontSelection: 'Yazı Tipi Seçimi',
|
|
206
|
+
colorFilter: 'Renk Filtresi',
|
|
207
|
+
textAlign: 'Metin Hizalama',
|
|
208
|
+
textSize: 'Metin Boyutu',
|
|
209
|
+
highContrast: 'Yüksek Kontrast',
|
|
210
|
+
defaultFont: 'Varsayılan Yazı Tipi',
|
|
211
|
+
noFilter: 'Filtre Yok',
|
|
212
|
+
default: 'Varsayılan',
|
|
213
|
+
screenReaderOn: 'Ekran okuyucu açık',
|
|
214
|
+
screenReaderOff: 'Ekran okuyucu kapalı',
|
|
215
|
+
voiceControlActivated: 'Sesli kontrol etkinleştirildi',
|
|
216
|
+
notSupportedBrowser: 'bu tarayıcıda desteklenmiyor',
|
|
217
|
+
close: 'Kapat',
|
|
218
|
+
reset: 'Sıfırla',
|
|
219
|
+
saturation: 'Doygunluk',
|
|
220
|
+
selectLanguage: 'Dil Seçin'
|
|
221
|
+
},
|
|
222
|
+
ar: {
|
|
223
|
+
accessibilityMenu: 'قائمة إمكانية الوصول',
|
|
224
|
+
closeAccessibilityMenu: 'إغلاق قائمة إمكانية الوصول',
|
|
225
|
+
accessibilityTools: 'أدوات إمكانية الوصول',
|
|
226
|
+
resetAllSettings: 'إعادة تعيين جميع الإعدادات',
|
|
227
|
+
screenReader: 'قارئ الشاشة',
|
|
228
|
+
voiceCommand: 'الأمر الصوتي',
|
|
229
|
+
textSpacing: 'تباعد النص',
|
|
230
|
+
pauseAnimations: 'إيقاف الرسوم المتحركة مؤقتًا',
|
|
231
|
+
hideImages: 'إخفاء الصور',
|
|
232
|
+
dyslexiaFriendly: 'صديق لعسر القراءة',
|
|
233
|
+
biggerCursor: 'مؤشر أكبر',
|
|
234
|
+
lineHeight: 'ارتفاع الخط',
|
|
235
|
+
fontSelection: 'اختيار الخط',
|
|
236
|
+
colorFilter: 'مرشح الألوان',
|
|
237
|
+
textAlign: 'محاذاة النص',
|
|
238
|
+
textSize: 'حجم النص',
|
|
239
|
+
highContrast: 'تباين عالي',
|
|
240
|
+
defaultFont: 'الخط الافتراضي',
|
|
241
|
+
noFilter: 'بدون مرشح',
|
|
242
|
+
default: 'افتراضي',
|
|
243
|
+
screenReaderOn: 'قارئ الشاشة مفعّل',
|
|
244
|
+
screenReaderOff: 'قارئ الشاشة معطل',
|
|
245
|
+
voiceControlActivated: 'تم تفعيل التحكم الصوتي',
|
|
246
|
+
notSupportedBrowser: 'غير مدعوم في هذا المتصفح',
|
|
247
|
+
close: 'إغلاق',
|
|
248
|
+
reset: 'إعادة تعيين',
|
|
249
|
+
saturation: 'التشبع',
|
|
250
|
+
selectLanguage: 'اختر اللغة'
|
|
251
|
+
},
|
|
252
|
+
hi: {
|
|
253
|
+
accessibilityMenu: 'पहुँच मेनू',
|
|
254
|
+
closeAccessibilityMenu: 'पहुँच मेनू बंद करें',
|
|
255
|
+
accessibilityTools: 'पहुँच उपकरण',
|
|
256
|
+
resetAllSettings: 'सभी सेटिंग्स रीसेट करें',
|
|
257
|
+
screenReader: 'स्क्रीन रीडर',
|
|
258
|
+
voiceCommand: 'वॉयस कमांड',
|
|
259
|
+
textSpacing: 'टेक्स्ट स्पेसिंग',
|
|
260
|
+
pauseAnimations: 'एनिमेशन रोकें',
|
|
261
|
+
hideImages: 'चित्र छिपाएँ',
|
|
262
|
+
dyslexiaFriendly: 'डिस्लेक्सिया के अनुकूल',
|
|
263
|
+
biggerCursor: 'बड़ा कर्सर',
|
|
264
|
+
lineHeight: 'लाइन की ऊँचाई',
|
|
265
|
+
fontSelection: 'फ़ॉन्ट चयन',
|
|
266
|
+
colorFilter: 'रंग फ़िल्टर',
|
|
267
|
+
textAlign: 'टेक्स्ट संरेखण',
|
|
268
|
+
textSize: 'टेक्स्ट का आकार',
|
|
269
|
+
highContrast: 'उच्च कंट्रास्ट',
|
|
270
|
+
defaultFont: 'डिफ़ॉल्ट फ़ॉन्ट',
|
|
271
|
+
noFilter: 'कोई फ़िल्टर नहीं',
|
|
272
|
+
default: 'डिफ़ॉल्ट',
|
|
273
|
+
screenReaderOn: 'स्क्रीन रीडर चालू',
|
|
274
|
+
screenReaderOff: 'स्क्रीन रीडर बंद',
|
|
275
|
+
voiceControlActivated: 'वॉयस नियंत्रण सक्रिय',
|
|
276
|
+
notSupportedBrowser: 'इस ब्राउज़र में समर्थित नहीं है',
|
|
277
|
+
close: 'बंद करें',
|
|
278
|
+
reset: 'रीसेट करें',
|
|
279
|
+
saturation: 'संतृप्ति',
|
|
280
|
+
selectLanguage: 'भाषा चुनें'
|
|
281
|
+
},
|
|
282
|
+
'zh-cn': {
|
|
283
|
+
accessibilityMenu: '辅助功能菜单',
|
|
284
|
+
closeAccessibilityMenu: '关闭辅助功能菜单',
|
|
285
|
+
accessibilityTools: '辅助功能工具',
|
|
286
|
+
resetAllSettings: '重置所有设置',
|
|
287
|
+
screenReader: '屏幕阅读器',
|
|
288
|
+
voiceCommand: '语音命令',
|
|
289
|
+
textSpacing: '文本间距',
|
|
290
|
+
pauseAnimations: '暂停动画',
|
|
291
|
+
hideImages: '隐藏图片',
|
|
292
|
+
dyslexiaFriendly: '阅读障碍友好',
|
|
293
|
+
biggerCursor: '更大的光标',
|
|
294
|
+
lineHeight: '行高',
|
|
295
|
+
fontSelection: '字体选择',
|
|
296
|
+
colorFilter: '颜色滤镜',
|
|
297
|
+
textAlign: '文本对齐',
|
|
298
|
+
textSize: '文本大小',
|
|
299
|
+
highContrast: '高对比度',
|
|
300
|
+
defaultFont: '默认字体',
|
|
301
|
+
noFilter: '无滤镜',
|
|
302
|
+
default: '默认',
|
|
303
|
+
screenReaderOn: '屏幕阅读器已开启',
|
|
304
|
+
screenReaderOff: '屏幕阅读器已关闭',
|
|
305
|
+
voiceControlActivated: '语音控制已激活',
|
|
306
|
+
notSupportedBrowser: '此浏览器不支持',
|
|
307
|
+
close: '关闭',
|
|
308
|
+
reset: '重置',
|
|
309
|
+
saturation: '饱和度',
|
|
310
|
+
selectLanguage: '选择语言'
|
|
311
|
+
},
|
|
312
|
+
jp: {
|
|
313
|
+
accessibilityMenu: 'アクセシビリティメニュー',
|
|
314
|
+
closeAccessibilityMenu: 'アクセシビリティメニューを閉じる',
|
|
315
|
+
accessibilityTools: 'アクセシビリティツール',
|
|
316
|
+
resetAllSettings: 'すべての設定をリセット',
|
|
317
|
+
screenReader: 'スクリーンリーダー',
|
|
318
|
+
voiceCommand: '音声コマンド',
|
|
319
|
+
textSpacing: 'テキスト間隔',
|
|
320
|
+
pauseAnimations: 'アニメーション一時停止',
|
|
321
|
+
hideImages: '画像を非表示',
|
|
322
|
+
dyslexiaFriendly: 'ディスレクシア対応',
|
|
323
|
+
biggerCursor: '大きいカーソル',
|
|
324
|
+
lineHeight: '行の高さ',
|
|
325
|
+
fontSelection: 'フォント選択',
|
|
326
|
+
colorFilter: 'カラーフィルター',
|
|
327
|
+
textAlign: 'テキスト配置',
|
|
328
|
+
textSize: 'テキストサイズ',
|
|
329
|
+
highContrast: 'ハイコントラスト',
|
|
330
|
+
defaultFont: 'デフォルトフォント',
|
|
331
|
+
noFilter: 'フィルターなし',
|
|
332
|
+
default: 'デフォルト',
|
|
333
|
+
screenReaderOn: 'スクリーンリーダーがオン',
|
|
334
|
+
screenReaderOff: 'スクリーンリーダーがオフ',
|
|
335
|
+
voiceControlActivated: '音声制御が有効',
|
|
336
|
+
notSupportedBrowser: 'このブラウザではサポートされていません',
|
|
337
|
+
close: '閉じる',
|
|
338
|
+
reset: 'リセット',
|
|
339
|
+
saturation: '彩度',
|
|
340
|
+
selectLanguage: '言語を選択'
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
// Language detection and management
|
|
345
|
+
let currentLanguage = 'en';
|
|
346
|
+
|
|
347
|
+
function detectBrowserLanguage() {
|
|
348
|
+
const browserLang = (navigator.language || navigator.userLanguage).toLowerCase();
|
|
349
|
+
|
|
350
|
+
// Direct match
|
|
351
|
+
if (TRANSLATIONS[browserLang]) {
|
|
352
|
+
return browserLang;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Try language code only (e.g., 'en' from 'en-US')
|
|
356
|
+
const langCode = browserLang.split('-')[0];
|
|
357
|
+
if (TRANSLATIONS[langCode]) {
|
|
358
|
+
return langCode;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Special case for Chinese
|
|
362
|
+
if (browserLang.includes('zh')) {
|
|
363
|
+
if (browserLang.includes('cn') || browserLang.includes('hans')) {
|
|
364
|
+
return 'zh-cn';
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Default to English
|
|
369
|
+
return 'en';
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function setLanguage(lang) {
|
|
373
|
+
if (TRANSLATIONS[lang]) {
|
|
374
|
+
currentLanguage = lang;
|
|
375
|
+
localStorage.setItem('accessibilityWidgetLanguage', lang);
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function getTranslation(key) {
|
|
382
|
+
return TRANSLATIONS[currentLanguage][key] || TRANSLATIONS['en'][key] || key;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Initialize language from localStorage or detect from browser
|
|
386
|
+
const savedLanguage = localStorage.getItem('accessibilityWidgetLanguage');
|
|
387
|
+
if (savedLanguage && TRANSLATIONS[savedLanguage]) {
|
|
388
|
+
currentLanguage = savedLanguage;
|
|
389
|
+
} else {
|
|
390
|
+
currentLanguage = detectBrowserLanguage();
|
|
391
|
+
localStorage.setItem('accessibilityWidgetLanguage', currentLanguage);
|
|
392
|
+
}
|
|
393
|
+
|
|
8
394
|
// ===========================================
|
|
9
395
|
// CONFIGURATION VARIABLES
|
|
10
396
|
// ===========================================
|
|
@@ -14,21 +400,20 @@ const DEFAULT_WIDGET_CONFIG = {
|
|
|
14
400
|
// Core Features
|
|
15
401
|
enableHighContrast: true,
|
|
16
402
|
enableBiggerText: true,
|
|
17
|
-
enableTextSpacing: true,
|
|
18
|
-
enablePauseAnimations: true,
|
|
403
|
+
enableTextSpacing: true, // Now has 3 levels
|
|
404
|
+
enablePauseAnimations: true, // Enhanced to include reduced motion features
|
|
19
405
|
enableHideImages: true,
|
|
20
406
|
enableDyslexiaFont: true,
|
|
21
407
|
enableBiggerCursor: true,
|
|
22
|
-
enableLineHeight: true,
|
|
408
|
+
enableLineHeight: true, // Now has 3 levels (2em, 3em, 4em)
|
|
23
409
|
enableTextAlign: true,
|
|
24
|
-
|
|
410
|
+
|
|
25
411
|
// Advanced Features
|
|
26
412
|
enableScreenReader: true,
|
|
27
413
|
enableVoiceControl: true,
|
|
28
|
-
enableReducedMotion: true,
|
|
29
414
|
enableFontSelection: true,
|
|
30
415
|
enableColorFilter: true,
|
|
31
|
-
|
|
416
|
+
|
|
32
417
|
// Widget Styling
|
|
33
418
|
widgetWidth: '440px',
|
|
34
419
|
widgetPosition: {
|
|
@@ -37,21 +422,16 @@ const DEFAULT_WIDGET_CONFIG = {
|
|
|
37
422
|
left: '20px',
|
|
38
423
|
bottom: '20px'
|
|
39
424
|
},
|
|
40
|
-
|
|
425
|
+
|
|
41
426
|
// Colors
|
|
42
427
|
colors: {
|
|
43
|
-
primary: '#
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
border: '#e6e6e6',
|
|
49
|
-
borderHover: '#d4d4d4',
|
|
50
|
-
shadow: 'rgba(0, 0, 0, 0.2)',
|
|
51
|
-
focus: '#ff6b35',
|
|
52
|
-
focusGlow: 'rgba(255, 107, 53, 0.3)'
|
|
428
|
+
primary: '#1663d7', // Header bg, main button bg, active border, close hover bg
|
|
429
|
+
secondary: '#ffffff', // Main button icon color
|
|
430
|
+
optionBg: '#ffffff', // Option button background
|
|
431
|
+
optionText: '#333333', // Option button text color
|
|
432
|
+
optionIcon: '#000000' // Option button icon color
|
|
53
433
|
},
|
|
54
|
-
|
|
434
|
+
|
|
55
435
|
// Button styling
|
|
56
436
|
button: {
|
|
57
437
|
size: '55px',
|
|
@@ -59,34 +439,34 @@ const DEFAULT_WIDGET_CONFIG = {
|
|
|
59
439
|
iconSize: '40px',
|
|
60
440
|
shadow: '0 4px 8px rgba(0, 0, 0, 0.2)'
|
|
61
441
|
},
|
|
62
|
-
|
|
442
|
+
|
|
63
443
|
// Menu styling
|
|
64
444
|
menu: {
|
|
65
|
-
headerHeight: '
|
|
445
|
+
headerHeight: '70px',
|
|
66
446
|
padding: '0 10px 10px 10px',
|
|
67
447
|
optionPadding: '20px 10px',
|
|
68
448
|
optionMargin: '10px',
|
|
69
449
|
borderRadius: '8px',
|
|
70
450
|
fontSize: '16px',
|
|
71
|
-
titleFontSize: '
|
|
451
|
+
titleFontSize: '16px',
|
|
72
452
|
closeButtonSize: '44px'
|
|
73
453
|
},
|
|
74
|
-
|
|
454
|
+
|
|
75
455
|
// Typography
|
|
76
456
|
typography: {
|
|
77
457
|
fontFamily: 'Arial, sans-serif',
|
|
78
|
-
fontSize: '
|
|
458
|
+
fontSize: '17px',
|
|
79
459
|
titleFontSize: '22px',
|
|
80
|
-
titleFontWeight: '
|
|
460
|
+
titleFontWeight: '700',
|
|
81
461
|
lineHeight: '1'
|
|
82
462
|
},
|
|
83
|
-
|
|
463
|
+
|
|
84
464
|
// Animation
|
|
85
465
|
animation: {
|
|
86
466
|
transition: '0.2s',
|
|
87
467
|
hoverScale: '1.05'
|
|
88
468
|
},
|
|
89
|
-
|
|
469
|
+
|
|
90
470
|
// Language/Text Configuration
|
|
91
471
|
lang: {
|
|
92
472
|
accessibilityMenu: 'Accessibility Menu',
|
|
@@ -101,7 +481,6 @@ const DEFAULT_WIDGET_CONFIG = {
|
|
|
101
481
|
dyslexiaFriendly: 'Dyslexia Friendly',
|
|
102
482
|
biggerCursor: 'Bigger Cursor',
|
|
103
483
|
lineHeight: 'Line Height',
|
|
104
|
-
reducedMotion: 'Reduced Motion',
|
|
105
484
|
fontSelection: 'Font Selection',
|
|
106
485
|
colorFilter: 'Color Filter',
|
|
107
486
|
textAlign: 'Text Align',
|
|
@@ -114,7 +493,8 @@ const DEFAULT_WIDGET_CONFIG = {
|
|
|
114
493
|
screenReaderOff: 'Screen reader off',
|
|
115
494
|
voiceControlActivated: 'Voice control activated',
|
|
116
495
|
notSupportedBrowser: 'is not supported in this browser',
|
|
117
|
-
close: 'Close'
|
|
496
|
+
close: 'Close',
|
|
497
|
+
reset: 'Reset'
|
|
118
498
|
},
|
|
119
499
|
|
|
120
500
|
// Voice Command Configuration - Developers can customize commands for different languages
|
|
@@ -136,7 +516,7 @@ const DEFAULT_WIDGET_CONFIG = {
|
|
|
136
516
|
|
|
137
517
|
// Grid Layout Configuration
|
|
138
518
|
gridLayout: {
|
|
139
|
-
columns: '1fr 1fr', // Default 2-column layout
|
|
519
|
+
columns: '1fr 1fr', // Default 2-column layout
|
|
140
520
|
gap: '10px' // Gap between grid items
|
|
141
521
|
}
|
|
142
522
|
};
|
|
@@ -144,9 +524,9 @@ const DEFAULT_WIDGET_CONFIG = {
|
|
|
144
524
|
// Function to deep merge user configuration with defaults
|
|
145
525
|
function mergeConfigs(defaultConfig, userConfig) {
|
|
146
526
|
const result = { ...defaultConfig };
|
|
147
|
-
|
|
527
|
+
|
|
148
528
|
if (!userConfig) return result;
|
|
149
|
-
|
|
529
|
+
|
|
150
530
|
for (const key in userConfig) {
|
|
151
531
|
if (userConfig.hasOwnProperty(key)) {
|
|
152
532
|
if (typeof userConfig[key] === 'object' && userConfig[key] !== null && !Array.isArray(userConfig[key])) {
|
|
@@ -156,26 +536,38 @@ function mergeConfigs(defaultConfig, userConfig) {
|
|
|
156
536
|
}
|
|
157
537
|
}
|
|
158
538
|
}
|
|
159
|
-
|
|
539
|
+
|
|
160
540
|
return result;
|
|
161
541
|
}
|
|
162
542
|
|
|
163
543
|
// Merge user configuration with defaults
|
|
164
|
-
// Users can define window.ACCESSIBILITY_WIDGET_CONFIG before loading this script
|
|
165
544
|
const WIDGET_CONFIG = mergeConfigs(DEFAULT_WIDGET_CONFIG, window.ACCESSIBILITY_WIDGET_CONFIG || {});
|
|
166
545
|
|
|
167
546
|
// ===========================================
|
|
168
547
|
// STYLES & VISUAL ASSETS
|
|
169
548
|
// ===========================================
|
|
170
549
|
|
|
171
|
-
//
|
|
172
|
-
const
|
|
550
|
+
// Widget styles (will go inside Shadow DOM - NOT affected by page styles or accessibility features)
|
|
551
|
+
const widgetStyles = `
|
|
552
|
+
:host {
|
|
553
|
+
all: initial;
|
|
554
|
+
font-family: ${WIDGET_CONFIG.typography.fontFamily};
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
* {
|
|
558
|
+
box-sizing: border-box;
|
|
559
|
+
}
|
|
560
|
+
|
|
173
561
|
#snn-accessibility-fixed-button {
|
|
174
562
|
position: fixed !important;
|
|
175
563
|
${WIDGET_CONFIG.widgetPosition.side}: ${WIDGET_CONFIG.widgetPosition[WIDGET_CONFIG.widgetPosition.side]} !important;
|
|
176
564
|
bottom: ${WIDGET_CONFIG.widgetPosition.bottom} !important;
|
|
177
565
|
z-index: 9999;
|
|
566
|
+
background:${WIDGET_CONFIG.colors.primary};
|
|
567
|
+
padding:5px;
|
|
568
|
+
border-radius:100%;
|
|
178
569
|
}
|
|
570
|
+
|
|
179
571
|
#snn-accessibility-button {
|
|
180
572
|
background: ${WIDGET_CONFIG.colors.primary};
|
|
181
573
|
border: none;
|
|
@@ -188,78 +580,130 @@ const styles = `
|
|
|
188
580
|
display: flex;
|
|
189
581
|
justify-content: center;
|
|
190
582
|
align-items: center;
|
|
583
|
+
border:solid 4px white;
|
|
191
584
|
}
|
|
585
|
+
|
|
192
586
|
#snn-accessibility-button:hover {
|
|
193
587
|
transform: scale(${WIDGET_CONFIG.animation.hoverScale});
|
|
194
588
|
}
|
|
589
|
+
|
|
195
590
|
#snn-accessibility-button:focus {
|
|
196
|
-
outline: 2px solid ${WIDGET_CONFIG.colors.
|
|
591
|
+
outline: 2px solid ${WIDGET_CONFIG.colors.secondary};
|
|
197
592
|
outline-offset: 2px;
|
|
198
593
|
}
|
|
594
|
+
|
|
199
595
|
#snn-accessibility-button svg {
|
|
200
596
|
width: ${WIDGET_CONFIG.button.iconSize};
|
|
201
597
|
height: ${WIDGET_CONFIG.button.iconSize};
|
|
202
|
-
fill: ${WIDGET_CONFIG.colors.
|
|
598
|
+
fill: ${WIDGET_CONFIG.colors.secondary};
|
|
203
599
|
pointer-events: none;
|
|
204
600
|
}
|
|
601
|
+
|
|
205
602
|
#snn-accessibility-menu {
|
|
206
603
|
position: fixed;
|
|
207
604
|
top: 0;
|
|
208
605
|
${WIDGET_CONFIG.widgetPosition.side}: 0;
|
|
209
|
-
width: ${WIDGET_CONFIG.widgetWidth};
|
|
606
|
+
max-width: ${WIDGET_CONFIG.widgetWidth};
|
|
607
|
+
width:100%;
|
|
210
608
|
height: 100vh;
|
|
211
609
|
overflow-y: auto;
|
|
212
|
-
background-color:
|
|
610
|
+
background-color: #e2e2e2;
|
|
213
611
|
padding: 0;
|
|
214
612
|
display: none;
|
|
215
613
|
font-family: ${WIDGET_CONFIG.typography.fontFamily};
|
|
216
614
|
z-index: 999999;
|
|
217
615
|
scrollbar-width: thin;
|
|
616
|
+
line-height:1 !important;
|
|
218
617
|
}
|
|
618
|
+
|
|
219
619
|
.snn-accessibility-option {
|
|
220
620
|
font-size: ${WIDGET_CONFIG.menu.fontSize};
|
|
221
621
|
display: flex;
|
|
622
|
+
flex-direction: column;
|
|
222
623
|
align-items: center;
|
|
223
|
-
|
|
624
|
+
justify-content: space-around;
|
|
625
|
+
padding: 5px;
|
|
224
626
|
width: 100%;
|
|
225
|
-
background-color: ${WIDGET_CONFIG.colors.
|
|
226
|
-
color: ${WIDGET_CONFIG.colors.
|
|
227
|
-
border:
|
|
627
|
+
background-color: ${WIDGET_CONFIG.colors.optionBg};
|
|
628
|
+
color: ${WIDGET_CONFIG.colors.optionText};
|
|
629
|
+
border: 3px solid ${WIDGET_CONFIG.colors.optionBg};
|
|
228
630
|
cursor: pointer;
|
|
229
631
|
border-radius: ${WIDGET_CONFIG.menu.borderRadius};
|
|
230
|
-
transition: background-color ${WIDGET_CONFIG.animation.transition};
|
|
632
|
+
transition: background-color ${WIDGET_CONFIG.animation.transition}, border-color ${WIDGET_CONFIG.animation.transition};
|
|
231
633
|
line-height: ${WIDGET_CONFIG.typography.lineHeight} !important;
|
|
634
|
+
gap: 5px;
|
|
635
|
+
min-height: 105px;
|
|
232
636
|
}
|
|
637
|
+
|
|
233
638
|
.snn-accessibility-option:hover {
|
|
234
|
-
|
|
639
|
+
border-color: ${WIDGET_CONFIG.colors.primary};
|
|
235
640
|
}
|
|
641
|
+
|
|
236
642
|
.snn-accessibility-option.active {
|
|
237
|
-
|
|
238
|
-
|
|
643
|
+
border-color: ${WIDGET_CONFIG.colors.primary};
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
.snn-accessibility-option:disabled {
|
|
647
|
+
opacity: 0.5;
|
|
648
|
+
cursor: not-allowed;
|
|
239
649
|
}
|
|
650
|
+
|
|
240
651
|
.snn-icon {
|
|
241
|
-
margin-right: 12px;
|
|
242
652
|
width: ${WIDGET_CONFIG.button.iconSize};
|
|
243
653
|
height: ${WIDGET_CONFIG.button.iconSize};
|
|
654
|
+
fill: ${WIDGET_CONFIG.colors.optionIcon};
|
|
655
|
+
flex-shrink: 0;
|
|
244
656
|
}
|
|
657
|
+
|
|
245
658
|
.snn-icon svg {
|
|
246
659
|
width: 100%;
|
|
247
660
|
height: 100%;
|
|
248
661
|
fill: currentColor;
|
|
249
662
|
}
|
|
250
|
-
|
|
663
|
+
|
|
664
|
+
.snn-button-text {
|
|
665
|
+
text-align: center;
|
|
666
|
+
line-height: 1.2;
|
|
667
|
+
font-size:16px;
|
|
668
|
+
font-weight: 600;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
.snn-option-steps {
|
|
672
|
+
display: flex;
|
|
673
|
+
gap: 5px;
|
|
674
|
+
align-items: center;
|
|
675
|
+
justify-content: center;
|
|
676
|
+
margin-top: 5px;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
.snn-option-step {
|
|
680
|
+
width: 30px;
|
|
681
|
+
height: 6px;
|
|
682
|
+
border-radius: 3px;
|
|
683
|
+
background-color: #d0d0d0;
|
|
684
|
+
transition: background-color ${WIDGET_CONFIG.animation.transition};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
.snn-option-step.active {
|
|
688
|
+
background-color: ${WIDGET_CONFIG.colors.primary};
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
.snn-close, .snn-reset-button {
|
|
251
692
|
background: none;
|
|
252
693
|
border: none;
|
|
253
694
|
font-size: ${WIDGET_CONFIG.menu.closeButtonSize};
|
|
254
|
-
color: ${WIDGET_CONFIG.colors.
|
|
695
|
+
color: ${WIDGET_CONFIG.colors.secondary};
|
|
255
696
|
cursor: pointer;
|
|
256
|
-
margin-left: auto;
|
|
257
697
|
line-height: ${WIDGET_CONFIG.typography.lineHeight};
|
|
258
698
|
border-radius: ${WIDGET_CONFIG.button.borderRadius};
|
|
259
699
|
width: ${WIDGET_CONFIG.menu.closeButtonSize};
|
|
260
700
|
height: ${WIDGET_CONFIG.menu.closeButtonSize};
|
|
261
701
|
position: relative;
|
|
702
|
+
display: flex;
|
|
703
|
+
align-items: center;
|
|
704
|
+
justify-content: center;
|
|
262
705
|
}
|
|
706
|
+
|
|
263
707
|
.snn-close::before {
|
|
264
708
|
content: '×';
|
|
265
709
|
position: absolute;
|
|
@@ -269,50 +713,94 @@ const styles = `
|
|
|
269
713
|
font-size: ${WIDGET_CONFIG.menu.closeButtonSize};
|
|
270
714
|
line-height: 1;
|
|
271
715
|
}
|
|
272
|
-
|
|
273
|
-
|
|
716
|
+
|
|
717
|
+
.snn-reset-button svg {
|
|
718
|
+
width: 22px;
|
|
719
|
+
height: 22px;
|
|
720
|
+
fill: ${WIDGET_CONFIG.colors.secondary};
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
.snn-close:focus, .snn-reset-button:focus {
|
|
724
|
+
outline: solid 2px ${WIDGET_CONFIG.colors.secondary};
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
.snn-close:hover, .snn-reset-button:hover {
|
|
728
|
+
color: ${WIDGET_CONFIG.colors.secondary};
|
|
729
|
+
background: rgba(255, 255, 255, 0.2);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/* Tooltip styles */
|
|
733
|
+
.snn-tooltip {
|
|
734
|
+
position: absolute;
|
|
735
|
+
bottom: -35px;
|
|
736
|
+
left: 50%;
|
|
737
|
+
transform: translateX(-50%);
|
|
738
|
+
background-color: rgba(0, 0, 0, 0.8);
|
|
739
|
+
color: white;
|
|
740
|
+
padding: 6px 10px;
|
|
741
|
+
border-radius: 4px;
|
|
742
|
+
font-size: 12px;
|
|
743
|
+
white-space: nowrap;
|
|
744
|
+
pointer-events: none;
|
|
745
|
+
opacity: 0;
|
|
746
|
+
transition: opacity 0.2s;
|
|
747
|
+
z-index: 1000;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
.snn-tooltip::before {
|
|
751
|
+
content: '';
|
|
752
|
+
position: absolute;
|
|
753
|
+
top: -4px;
|
|
754
|
+
left: 50%;
|
|
755
|
+
transform: translateX(-50%);
|
|
756
|
+
width: 0;
|
|
757
|
+
height: 0;
|
|
758
|
+
border-left: 5px solid transparent;
|
|
759
|
+
border-right: 5px solid transparent;
|
|
760
|
+
border-bottom: 5px solid rgba(0, 0, 0, 0.8);
|
|
274
761
|
}
|
|
275
|
-
|
|
276
|
-
|
|
762
|
+
|
|
763
|
+
.snn-close:hover .snn-tooltip,
|
|
764
|
+
.snn-close:focus .snn-tooltip,
|
|
765
|
+
.snn-reset-button:hover .snn-tooltip,
|
|
766
|
+
.snn-reset-button:focus .snn-tooltip {
|
|
767
|
+
opacity: 1;
|
|
277
768
|
}
|
|
769
|
+
|
|
278
770
|
.snn-header {
|
|
279
771
|
display: flex;
|
|
280
772
|
align-items: center;
|
|
281
|
-
margin-bottom: 20px;
|
|
282
773
|
padding: 10px;
|
|
283
|
-
background:
|
|
774
|
+
background: ${WIDGET_CONFIG.colors.primary};
|
|
284
775
|
height: ${WIDGET_CONFIG.menu.headerHeight};
|
|
285
776
|
position: sticky;
|
|
286
777
|
top: 0;
|
|
287
778
|
z-index: 10;
|
|
288
779
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
780
|
+
gap: 8px;
|
|
289
781
|
}
|
|
290
782
|
|
|
291
783
|
.snn-content {
|
|
292
|
-
padding:
|
|
784
|
+
padding: 20px 20px 0px 20px;
|
|
293
785
|
}
|
|
294
786
|
|
|
295
|
-
.snn-
|
|
296
|
-
font-size: ${WIDGET_CONFIG.menu.fontSize};
|
|
297
|
-
display: flex;
|
|
298
|
-
align-items: center;
|
|
299
|
-
justify-content: center;
|
|
300
|
-
margin-bottom: 10px;
|
|
301
|
-
padding: ${WIDGET_CONFIG.menu.optionPadding};
|
|
787
|
+
.snn-language-selector {
|
|
302
788
|
width: 100%;
|
|
303
|
-
background
|
|
304
|
-
color:
|
|
789
|
+
background: white;
|
|
790
|
+
color: black;
|
|
305
791
|
border: none;
|
|
792
|
+
padding: 14px;
|
|
793
|
+
font-size: 16px;
|
|
794
|
+
font-family: ${WIDGET_CONFIG.typography.fontFamily};
|
|
795
|
+
border-radius: 5px;
|
|
796
|
+
margin-bottom: 20px;
|
|
306
797
|
cursor: pointer;
|
|
307
|
-
|
|
308
|
-
transition: background-color ${WIDGET_CONFIG.animation.transition};
|
|
309
|
-
line-height: ${WIDGET_CONFIG.typography.lineHeight} !important;
|
|
310
|
-
font-weight: 500;
|
|
311
|
-
gap: 8px;
|
|
798
|
+
outline: none;
|
|
312
799
|
}
|
|
313
800
|
|
|
314
|
-
.snn-
|
|
315
|
-
|
|
801
|
+
.snn-language-selector:focus {
|
|
802
|
+
outline: 2px solid ${WIDGET_CONFIG.colors.primary};
|
|
803
|
+
outline-offset: 2px;
|
|
316
804
|
}
|
|
317
805
|
|
|
318
806
|
.snn-options-grid {
|
|
@@ -322,53 +810,53 @@ const styles = `
|
|
|
322
810
|
margin-bottom: 20px;
|
|
323
811
|
}
|
|
324
812
|
|
|
325
|
-
|
|
326
813
|
.snn-title {
|
|
327
814
|
margin: 0;
|
|
328
815
|
font-size: ${WIDGET_CONFIG.menu.titleFontSize};
|
|
329
|
-
color: ${WIDGET_CONFIG.colors.
|
|
816
|
+
color: ${WIDGET_CONFIG.colors.secondary};
|
|
330
817
|
line-height: ${WIDGET_CONFIG.typography.lineHeight} !important;
|
|
331
818
|
margin-left: 5px;
|
|
332
819
|
font-weight: ${WIDGET_CONFIG.typography.titleFontWeight};
|
|
820
|
+
flex: 1;
|
|
821
|
+
letter-spacing: 1px !important;
|
|
822
|
+
word-spacing: 2px !important;
|
|
823
|
+
text-align: left;
|
|
333
824
|
}
|
|
334
|
-
|
|
825
|
+
`;
|
|
826
|
+
|
|
827
|
+
// Page accessibility styles (will go in main document - these affect the page, NOT the widget)
|
|
828
|
+
const pageStyles = `
|
|
829
|
+
/* High Contrast Modes */
|
|
335
830
|
.snn-high-contrast-medium {
|
|
336
|
-
filter:
|
|
831
|
+
filter: none !important;
|
|
337
832
|
}
|
|
338
|
-
.snn-high-contrast-medium *{
|
|
833
|
+
.snn-high-contrast-medium *:not(#snn-accessibility-widget-container):not(#snn-accessibility-widget-container *) {
|
|
339
834
|
filter: contrast(1.3) !important;
|
|
340
835
|
}
|
|
341
|
-
.snn-high-contrast-medium #snn-accessibility-menu{
|
|
342
|
-
filter: contrast(0.8) !important;
|
|
343
|
-
}
|
|
344
836
|
|
|
345
837
|
.snn-high-contrast-high {
|
|
346
838
|
background-color: #000 !important;
|
|
347
839
|
color: #fff !important;
|
|
348
|
-
filter:
|
|
840
|
+
filter: none !important;
|
|
349
841
|
}
|
|
350
|
-
.snn-high-contrast-high *{
|
|
842
|
+
.snn-high-contrast-high *:not(#snn-accessibility-widget-container):not(#snn-accessibility-widget-container *) {
|
|
351
843
|
background-color: #000 !important;
|
|
352
844
|
color: #fff !important;
|
|
353
845
|
filter: contrast(1.5) !important;
|
|
354
846
|
}
|
|
355
|
-
.snn-high-contrast-high #snn-accessibility-menu{
|
|
356
|
-
filter: contrast(0.7) !important;
|
|
357
|
-
}
|
|
358
847
|
|
|
359
848
|
.snn-high-contrast-ultra {
|
|
360
849
|
background-color: #000 !important;
|
|
361
850
|
color: #ffff00 !important;
|
|
362
|
-
filter:
|
|
851
|
+
filter: none !important;
|
|
363
852
|
}
|
|
364
|
-
.snn-high-contrast-ultra *{
|
|
853
|
+
.snn-high-contrast-ultra *:not(#snn-accessibility-widget-container):not(#snn-accessibility-widget-container *) {
|
|
365
854
|
background-color: #000 !important;
|
|
366
855
|
color: #ffff00 !important;
|
|
367
856
|
filter: contrast(2.0) !important;
|
|
368
857
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
858
|
+
|
|
859
|
+
/* Text Size */
|
|
372
860
|
.snn-bigger-text-medium * {
|
|
373
861
|
font-size: 20px !important;
|
|
374
862
|
}
|
|
@@ -378,32 +866,66 @@ const styles = `
|
|
|
378
866
|
.snn-bigger-text-xlarge * {
|
|
379
867
|
font-size: 28px !important;
|
|
380
868
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
869
|
+
|
|
870
|
+
/* Text Spacing - 3 Options */
|
|
871
|
+
.snn-text-spacing-light * {
|
|
872
|
+
letter-spacing: 0.1em !important;
|
|
873
|
+
word-spacing: 0.5em !important;
|
|
874
|
+
}
|
|
875
|
+
.snn-text-spacing-medium * {
|
|
876
|
+
letter-spacing: 0.15em !important;
|
|
877
|
+
word-spacing: 1em !important;
|
|
878
|
+
}
|
|
879
|
+
.snn-text-spacing-heavy * {
|
|
880
|
+
letter-spacing: 0.25em !important;
|
|
881
|
+
word-spacing: 2em !important;
|
|
384
882
|
}
|
|
883
|
+
|
|
884
|
+
/* Pause Animations (Enhanced to include Reduced Motion features) */
|
|
385
885
|
.snn-pause-animations * {
|
|
386
886
|
animation: none !important;
|
|
387
887
|
transition: none !important;
|
|
388
888
|
}
|
|
889
|
+
.snn-pause-animations *::before {
|
|
890
|
+
animation: none !important;
|
|
891
|
+
transition: none !important;
|
|
892
|
+
}
|
|
893
|
+
.snn-pause-animations *::after {
|
|
894
|
+
animation: none !important;
|
|
895
|
+
transition: none !important;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/* Dyslexia Font */
|
|
389
899
|
.snn-dyslexia-font {
|
|
390
|
-
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Bradley Hand', Brush Script MT, fantasy !important;
|
|
900
|
+
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Bradley Hand', 'Brush Script MT', fantasy !important;
|
|
391
901
|
}
|
|
392
902
|
.snn-dyslexia-font * {
|
|
393
|
-
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Bradley Hand', Brush Script MT, fantasy !important;
|
|
903
|
+
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Bradley Hand', 'Brush Script MT', fantasy !important;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/* Line Height - 3 Options */
|
|
907
|
+
.snn-line-height-2em * {
|
|
908
|
+
line-height: 2 !important;
|
|
394
909
|
}
|
|
395
|
-
.snn-line-height
|
|
396
|
-
line-height:
|
|
910
|
+
.snn-line-height-3em * {
|
|
911
|
+
line-height: 3 !important;
|
|
397
912
|
}
|
|
398
|
-
.snn-
|
|
913
|
+
.snn-line-height-4em * {
|
|
914
|
+
line-height: 4 !important;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/* Text Alignment */
|
|
918
|
+
.snn-text-align-left * {
|
|
399
919
|
text-align: left !important;
|
|
400
920
|
}
|
|
401
|
-
.snn-text-align-center
|
|
921
|
+
.snn-text-align-center * {
|
|
402
922
|
text-align: center !important;
|
|
403
923
|
}
|
|
404
|
-
.snn-text-align-right
|
|
924
|
+
.snn-text-align-right * {
|
|
405
925
|
text-align: right !important;
|
|
406
926
|
}
|
|
927
|
+
|
|
928
|
+
/* Bigger Cursor */
|
|
407
929
|
.snn-bigger-cursor {
|
|
408
930
|
cursor: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNzIiIHZpZXdCb3g9IjAgMCA0OCA3MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNCAyVjcwTDIwIDU0SDM2TDQgMloiIGZpbGw9IiMwMDAiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSI0Ii8+PC9zdmc+'), auto !important;
|
|
409
931
|
}
|
|
@@ -433,27 +955,56 @@ const styles = `
|
|
|
433
955
|
|
|
434
956
|
/* Color Filters */
|
|
435
957
|
.snn-filter-protanopia {
|
|
958
|
+
filter: none !important;
|
|
959
|
+
}
|
|
960
|
+
.snn-filter-protanopia body > *:not(#snn-accessibility-widget-container) {
|
|
436
961
|
filter: url('#protanopia-filter') !important;
|
|
437
962
|
}
|
|
438
963
|
.snn-filter-deuteranopia {
|
|
964
|
+
filter: none !important;
|
|
965
|
+
}
|
|
966
|
+
.snn-filter-deuteranopia body > *:not(#snn-accessibility-widget-container) {
|
|
439
967
|
filter: url('#deuteranopia-filter') !important;
|
|
440
968
|
}
|
|
441
969
|
.snn-filter-tritanopia {
|
|
970
|
+
filter: none !important;
|
|
971
|
+
}
|
|
972
|
+
.snn-filter-tritanopia body > *:not(#snn-accessibility-widget-container) {
|
|
442
973
|
filter: url('#tritanopia-filter') !important;
|
|
443
974
|
}
|
|
444
975
|
.snn-filter-grayscale {
|
|
976
|
+
filter: none !important;
|
|
977
|
+
}
|
|
978
|
+
.snn-filter-grayscale body > *:not(#snn-accessibility-widget-container) {
|
|
445
979
|
filter: grayscale(100%) !important;
|
|
446
980
|
}
|
|
447
981
|
|
|
448
|
-
/*
|
|
449
|
-
.snn-
|
|
450
|
-
|
|
451
|
-
transition: none !important;
|
|
982
|
+
/* Saturation Filters */
|
|
983
|
+
.snn-saturation-low {
|
|
984
|
+
filter: none !important;
|
|
452
985
|
}
|
|
453
|
-
.snn-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
986
|
+
.snn-saturation-low body > *:not(#snn-accessibility-widget-container) {
|
|
987
|
+
filter: saturate(0.5) !important;
|
|
988
|
+
}
|
|
989
|
+
.snn-saturation-high {
|
|
990
|
+
filter: none !important;
|
|
991
|
+
}
|
|
992
|
+
.snn-saturation-high body > *:not(#snn-accessibility-widget-container) {
|
|
993
|
+
filter: saturate(10) !important;
|
|
994
|
+
}
|
|
995
|
+
.snn-saturation-none {
|
|
996
|
+
filter: none !important;
|
|
997
|
+
}
|
|
998
|
+
.snn-saturation-none body > *:not(#snn-accessibility-widget-container) {
|
|
999
|
+
filter: grayscale(100%) saturate(0) !important;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/* Protect widget container from page styles */
|
|
1003
|
+
#snn-accessibility-widget-container,
|
|
1004
|
+
#snn-accessibility-widget-container * {
|
|
1005
|
+
filter: none !important;
|
|
1006
|
+
background-color: initial !important;
|
|
1007
|
+
color: initial !important;
|
|
457
1008
|
}
|
|
458
1009
|
`;
|
|
459
1010
|
|
|
@@ -461,40 +1012,44 @@ const styles = `
|
|
|
461
1012
|
// SVG ICONS
|
|
462
1013
|
// ===========================================
|
|
463
1014
|
|
|
464
|
-
// SVG icons
|
|
465
1015
|
const icons = {
|
|
466
|
-
buttonsvg: `<svg
|
|
467
|
-
highContrast: `<svg
|
|
468
|
-
biggerText: `<svg
|
|
469
|
-
textSpacing: `<svg
|
|
470
|
-
pauseAnimations: `<svg
|
|
1016
|
+
buttonsvg: `<svg xmlns="http://www.w3.org/2000/svg" style="fill:white;" viewBox="0 0 24 24" width="30px" height="30px"><path d="M0 0h24v24H0V0z" fill="none"></path><path d="M20.5 6c-2.61.7-5.67 1-8.5 1s-5.89-.3-8.5-1L3 8c1.86.5 4 .83 6 1v13h2v-6h2v6h2V9c2-.17 4.14-.5 6-1l-.5-2zM12 6c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"></path></svg>`,
|
|
1017
|
+
highContrast: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" version="1.2" viewBox="0 0 35 35"><path fill="currentColor" fill-rule="evenodd" d="M1.89998 15.6285c0-7.58203 6.14649-13.72852 13.72852-13.72852 7.5821 0 13.7286 6.14649 13.7286 13.72852 0 .6081-.0395 1.2069-.1161 1.794.5933.2913 1.1478.6497 1.6534 1.0654.1725-.9268.2627-1.8825.2627-2.8594 0-8.57615-6.9524-15.5285244-15.5286-15.5285244C7.05235.0999756.0999756 7.05235.0999756 15.6285c0 8.5762 6.9523744 15.5286 15.5285244 15.5286 1.2241 0 2.415-.1416 3.5574-.4093-.4388-.4866-.8222-1.0242-1.1402-1.6028-.7847.1394-1.5924.2121-2.4172.2121-7.58203 0-13.72852-6.1465-13.72852-13.7286Z" clip-rule="evenodd"/><path fill="currentColor" fill-rule="evenodd" d="M2.35 15.6286C2.35 8.29502 8.29502 2.35 15.6286 2.35c7.3335 0 13.2785 5.94502 13.2785 13.2786 0 .5408-.0323 1.0741-.0951 1.5979.444.1881.8687.4128 1.2703.6703.1151-.7392.1748-1.4967.1748-2.2682C30.2571 7.54943 23.7077 1 15.6286 1 7.54943 1 15.6286 1 7.54943 1 15.6286c0 8.0791 6.54943 14.6285 14.6286 14.6285 1.0033 0 1.9831-.101 2.9297-.2934-.276-.3898-.52-.8038-.7282-1.2382-.716.1195-1.4515.1816-2.2015.1816-7.33358 0-13.2786-5.945-13.2786-13.2785Z" clip-rule="evenodd"/><path fill="currentColor" fill-rule="evenodd" d="M15.6286 1C7.54943 1 1 7.54943 1 15.6286c0 8.0791 6.54943 14.6285 14.6286 14.6285" clip-rule="evenodd"/><path stroke="currentColor" stroke-width="1.8" d="M15.6286 1C7.54943 1 1 7.54943 1 15.6286c0 8.0791 6.54943 14.6285 14.6286 14.6285"/><path fill="currentColor" fill-rule="evenodd" d="M22.8729 25.114c0-1.3811 1.0901-2.5007 2.4359-2.5007 1.3459 0 2.436 1.1196 2.436 2.5007 0 1.38-1.0901 2.4997-2.436 2.4997-1.3458 0-2.4359-1.1197-2.4359-2.4997Zm7.2258-2.0373c-.0899-.2248-.071-.4785.0512-.6875l.912-1.5598c.0898-.1532.0668-.3504-.0574-.4779l-1.0556-1.0832c-.1232-.1264-.3153-.1511-.4657-.0589l-1.5225.9374c-.201.1237-.4495.1427-.667.051-.2181-.092-.3797-.2819-.4358-.5118l-.4329-1.7763c-.0428-.1735-.1953-.2957-.3696-.2957h-1.4931c-.1744 0-.3268.1222-.3696.2957l-.433 1.7763c-.056.2299-.2177.4198-.4357.5118-.2176.0917-.466.0727-.6671-.051l-1.5225-.9374c-.1503-.0922-.3424-.0675-.4656.0589l-1.0556 1.0832c-.1243.1275-.1473.3247-.0575.4779l.9121 1.5598c.1222.209.1411.4627.0511.6875-.0895.2239-.2806.3916-.5142.4514l-1.7165.4395c-.1692.0439-.2882.2003-.2882.3803v1.5311c0 .18.119.3364.2882.3804l1.7165.4394c.2336.0599.4247.2276.5142.4515.09.2247.0711.4785-.0511.6874l-.9121 1.5599c-.0898.1532-.0668.3503.0575.4778l1.0556 1.0833c.1232.1264.3153.151.4656.0589l1.5225-.9374c.2011-.1238.4495-.1428.6671-.051.218.092.3797.2818.4357.5118l.433 1.7762c.0428.1736.1952.2968.3696.2968h1.4931c.1743 0 .3268-.1232.3696-.2968l.4329-1.7762c.0561-.23.2177-.4198.4358-.5118.2175-.0918.466-.0728.667.051l1.5225.9374c.1504.0921.3425.0675.4657-.0589l1.0556-1.0833c.1242-.1275.1472-.3246.0574-.4778l-.912-1.5599c-.1222-.2089-.1411-.4627-.0512-.6874.0896-.2239.2806-.3916.5142-.4515l1.7166-.4394c.1691-.044.2881-.2004.2881-.3804v-1.5311c0-.18-.119-.3364-.2881-.3803l-1.7166-.4395c-.2336-.0598-.4246-.2275-.5142-.4514Z" clip-rule="evenodd"/></svg>`,
|
|
1018
|
+
biggerText: `<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 36 23"><g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="round" stroke-width="2"><path stroke-linejoin="round" d="M26.58 21.3225806V1m-7.92 4.06451613V1H34.5v4.06451613"/><path d="M22.62 21.3225806h7.92"/><path stroke-linejoin="round" d="M6.78 18.6129032V5.06451613M1.5 7.77419355V5.06451613h10.56v2.70967742"/><path d="M4.14 18.6129032h5.28"/></g></svg>`,
|
|
1019
|
+
textSpacing: `<svg xmlns="http://www.w3.org/2000/svg" width="800px" height="800px" viewBox="0 0 15 15" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.55293 0.999969C4.75295 0.999969 4.93372 1.11917 5.0125 1.30301L8.01106 8.29982C8.11984 8.55363 8.00226 8.84757 7.74844 8.95635C7.49463 9.06512 7.20069 8.94754 7.09191 8.69373L6.11613 6.41685H2.98973L2.01395 8.69373C1.90517 8.94754 1.61123 9.06512 1.35742 8.95635C1.1036 8.84757 0.986023 8.55363 1.0948 8.29982L4.09336 1.30301C4.17214 1.11917 4.35291 0.999969 4.55293 0.999969ZM4.55293 2.76929L5.75186 5.56685H3.354L4.55293 2.76929ZM11.0562 9.00214C11.2617 9.00214 11.4463 8.87633 11.5215 8.68502L14.2733 1.68299C14.3743 1.42598 14.2478 1.13575 13.9908 1.03475C13.7338 0.933747 13.4436 1.06021 13.3426 1.31722L11.0562 7.13514L8.76973 1.31722C8.66873 1.06021 8.3785 0.933747 8.1215 1.03475C7.86449 1.13575 7.73802 1.42598 7.83902 1.68299L10.5908 8.68502C10.666 8.87633 10.8506 9.00214 11.0562 9.00214ZM14.9537 12.4999C14.9537 12.606 14.9115 12.7077 14.8365 12.7828L12.8365 14.7828C12.6803 14.939 12.4271 14.939 12.2708 14.7828C12.1146 14.6265 12.1146 14.3733 12.2708 14.2171L13.588 12.8999H1.51937L2.83653 14.2171C2.99274 14.3733 2.99274 14.6265 2.83653 14.7828C2.68032 14.939 2.42705 14.939 2.27084 14.7828L0.270843 12.7828C0.195828 12.7077 0.153687 12.606 0.153687 12.4999C0.153687 12.3938 0.195828 12.2921 0.270843 12.2171L2.27084 10.2171C2.42705 10.0609 2.68032 10.0609 2.83653 10.2171C2.99274 10.3733 2.99274 10.6265 2.83653 10.7828L1.51937 12.0999L13.588 12.0999L12.2708 10.7828C12.1146 10.6265 12.1146 10.3733 12.2708 10.2171C12.4271 10.0609 12.6803 10.0609 12.8365 10.2171L14.8365 12.2171C14.9115 12.2921 14.9537 12.3938 14.9537 12.4999Z" fill="#000000"/></svg>`,
|
|
1020
|
+
pauseAnimations: `<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 37 36"><g fill="none" fill-rule="evenodd"><path fill="currentColor" d="M15.8087111 23.6666667h-1.2702778c-.4429444 0-.8018333-.3598334-.8018333-.8027778v-9.7277778c0-.4429444.3588889-.8027778.8018333-.8027778h1.2702778c.4429445 0 .8027778.3598334.8027778.8027778v9.7277778c0 .4429444-.3598333.8027778-.8027778.8027778m6.6525722 0h-1.2702777c-.442 0-.8018334-.3598334-.8018334-.8027778v-9.7277778c0-.4429444.3598334-.8027778.8018334-.8027778h1.2702777c.4438889 0 .8027778.3598334.8027778.8027778v9.7277778c0 .4429444-.3588889.8027778-.8027778.8027778"/><path stroke="currentColor" stroke-linecap="round" stroke-width="1.88888889" d="M18.5 4.77777778V1m0 34v-3.7777778M31.7222222 18H35.5m-34 0h3.77777778m3.87278889-9.34943333L6.47873333 5.97967778M30.5204167 30.0204167l-2.6708889-2.6708889m-.0000945-18.69896113 2.6708889-2.67088889M6.47911111 30.0204167l2.67183333-2.6708889M23.5542889 5.78219444l1.4440555-3.49066666M12.0013722 33.7087556l1.4440556-3.4906667m17.2723778-7.1638 3.4906666 1.4440555M2.79124444 11.5013722l3.49066667 1.4440556m7.15274999-7.15860558L11.9877722 2.2971m13.0246445 31.4061778-1.4468889-3.4897222m7.14765-17.2788945L34.2029 11.4877722M2.79672222 24.5124167l3.48972222-1.4468889"/></g></svg>`,
|
|
471
1021
|
hideImages: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M32 12C16 12 4 32 4 32s12 20 28 20 28-20 28-20S48 12 32 12zm0 32a12 12 0 1112-12 12 12 0 01-12 12z"/><circle cx="32" cy="32" r="8"/></svg>`,
|
|
472
|
-
dyslexiaFont: `<svg
|
|
473
|
-
biggerCursor: `<svg
|
|
474
|
-
lineHeight: `<svg
|
|
1022
|
+
dyslexiaFont: `<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 31 22"><path fill="currentColor" fill-rule="evenodd" d="M.5 22V1.0083333h7.2421899c6.8051611 0 11.6124768 4.3388889 11.6124768 10.4805556C19.3546667 17.6305556 14.547351 22 7.7421899 22H.5Zm2.4348742-4.31h4.8073157c5.3692097 0 9.1463863-2.8616703 9.1463863-7.27 0-4.3807776-3.7771766-7.2422222-9.1463863-7.2422222H2.9348742V17.69ZM26.2735913 4.0333333l.0114609 2.1694445h4.0126191V8.25h-4.001719L26.77 22h-3.535416L23.78 8.25h-2.4238344V6.2027778h2.55923l.0751088-2.1694445C24.0706908 1.6805556 25.6007488 0 27.697782 0 28.6896221 0 29.677687.3666667 30.5 1.0083333l-.9627285 1.6805556c-.3479788-.3666667-.9515992-.6416667-1.627768-.6416667-.8819593 0-1.6420082.825-1.6359122 1.9861111Z"/></svg>`,
|
|
1023
|
+
biggerCursor: `<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 27 27"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m15.9983464 11.5517813 9.5269972 9.52699721-4.4465655 4.44656549-9.5269972-9.52699717-4.05145413 9.06403815L1 1.0000004l24.0623846 6.5003268z"/></svg>`,
|
|
1024
|
+
lineHeight: `<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 47 25"><g fill="none" fill-rule="evenodd"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M3.99999962 2.71042226V22.7104223"/><path fill="currentColor" d="m.16814235 20.5270412 3.44487862 4.2104072c.17486379.2137224.48987514.2452235.70359754.0703597a.4999988.4999988 0 0 0 .07035976-.0703597l3.44487862-4.2104072c.17486378-.2137225.14336265-.5287338-.07035976-.7035976-.08933106-.073089-.20119771-.1130213-.31661889-.1130213H.555121c-.27614238 0-.5.2238576-.5.5 0 .1154211.0399323.2272878.11302135.3166189Zm0-161332381L3.61302097.18339592c.17486379-.21372241.48987514-.24522355.70359754-.07035976a.49999975.49999975 0 0 1 .07035976.07035976l3.44487862 4.2104072c.17486378.2137224.14336265.52873375-.07035976.70359754-.08933106.07308905-.20119771.11302135-.31661889.11302135H.555121c-.27614237 0-.5-.22385762-.5-.5 0-.11542118.0399323-.22728783.11302135-.3166189Z"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.4999996 1.71042226h30m-30 7h30m-30 7.00000004h30m-30 7h24"/></g></svg>`,
|
|
475
1025
|
textAlign: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M10 16h44v4H10zm0 12h44v4H10zm0 12h44v4H10zm0 12h44v4H10z"/></svg>`,
|
|
476
1026
|
screenReader: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M16 24 L24 24 L32 16 L32 48 L24 40 L16 40 Z" fill="#333" stroke="#555" stroke-width="2"/><path d="M36 20 C42 24, 42 40, 36 44" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round"/><path d="M36 12 C48 24, 48 40, 36 52" fill="none" stroke="#555" stroke-width="2" stroke-linecap="round"/><rect x="28" y="48" width="8" height="8" fill="#ccc"/></svg>`,
|
|
477
|
-
resetAll: `<svg
|
|
1027
|
+
resetAll: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 17" width="100%" height="100%"><g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="round" stroke-width="1.84"><path d="M16.20106 8c0 .9667-.189683 1.8872-.5324673 2.7251-.3427843.8372-.8386698 1.5911-1.4517524 2.2246-.6130825.6335-1.3426846 1.1459-2.152902 1.5001-.8108948.3542-1.70172746.5502-2.6372711.5502-.93554365 0-1.8263763-.196-2.63727112-.5502-.81021738-.3542-1.53981948-.8666-2.15290203-1.5001M2.6522744 8c0-.9667.189683-1.8872.53246728-2.7251.34278427-.8372.83866982-1.5911 1.45175237-2.2246.61308255-.6335 1.34268465-1.1459 2.15290203-1.5001C7.6002909 1.196 8.49112355 1 9.4266672 1c.93554364 0 1.8263763.196 2.6372711.5502.8102174.3542 1.5398195.8666 2.152902 1.5001"></path><path stroke-linejoin="round" d="m4.92576062 6.96092-2.48958935 1.484L1 5.87242m13.0125924 2.93832 2.3886509-1.652L18 9.62694"></path></g></svg>`,
|
|
478
1028
|
voiceControl: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M32 44a12 12 0 0012-12V20a12 12 0 10-24 0v12a12 12 0 0012 12z" fill="#333"/><path d="M20 32h24v4H20z" fill="#555"/><path d="M32 48v8" stroke="#555" stroke-width="4" stroke-linecap="round"/></svg>`,
|
|
479
1029
|
fontSelection: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><text x="32" y="40" font-family="serif" font-size="24" text-anchor="middle" fill="#333">Aa</text><path d="M8 48h48v2H8z"/></svg>`,
|
|
480
1030
|
colorFilter: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><circle cx="32" cy="32" r="24" fill="none" stroke="#333" stroke-width="2"/><path d="M32 8a24 24 0 000 48V8z" fill="#f00" opacity="0.3"/><path d="M32 8a24 24 0 000 48" fill="none" stroke="#333" stroke-width="2" stroke-dasharray="4,2"/></svg>`,
|
|
1031
|
+
saturation: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><circle cx="20" cy="32" r="12" fill="#ff0000" opacity="0.7"/><circle cx="32" cy="32" r="12" fill="#00ff00" opacity="0.7"/><circle cx="44" cy="32" r="12" fill="#0000ff" opacity="0.7"/></svg>`,
|
|
481
1032
|
reducedMotion: `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect x="16" y="24" width="8" height="16" fill="#333"/><rect x="28" y="24" width="8" height="16" fill="#333"/><rect x="40" y="24" width="8" height="16" fill="#333"/></svg>`,
|
|
482
1033
|
};
|
|
483
1034
|
|
|
484
1035
|
// ===========================================
|
|
485
|
-
//
|
|
1036
|
+
// SHADOW DOM SETUP
|
|
486
1037
|
// ===========================================
|
|
487
1038
|
|
|
488
|
-
|
|
489
|
-
|
|
1039
|
+
let shadowRoot = null;
|
|
1040
|
+
|
|
1041
|
+
// Inject styles into the page (NOT the widget)
|
|
1042
|
+
function injectPageStyles() {
|
|
490
1043
|
const styleSheet = document.createElement('style');
|
|
491
|
-
styleSheet.innerText =
|
|
1044
|
+
styleSheet.innerText = pageStyles;
|
|
1045
|
+
styleSheet.id = 'snn-accessibility-page-styles';
|
|
492
1046
|
document.head.appendChild(styleSheet);
|
|
493
|
-
|
|
494
|
-
// Add SVG color blindness filters
|
|
1047
|
+
|
|
1048
|
+
// Add SVG color blindness filters to main document
|
|
495
1049
|
const svgFilters = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
496
1050
|
svgFilters.style.position = 'absolute';
|
|
497
1051
|
svgFilters.style.width = '0';
|
|
1052
|
+
svgFilters.setAttribute('class', 'snn-accessibility-filters');
|
|
498
1053
|
svgFilters.style.height = '0';
|
|
499
1054
|
svgFilters.innerHTML = `
|
|
500
1055
|
<defs>
|
|
@@ -512,8 +1067,25 @@ function injectStyles() {
|
|
|
512
1067
|
document.body.appendChild(svgFilters);
|
|
513
1068
|
}
|
|
514
1069
|
|
|
1070
|
+
// Create shadow DOM container
|
|
1071
|
+
function createShadowContainer() {
|
|
1072
|
+
const container = document.createElement('div');
|
|
1073
|
+
container.id = 'snn-accessibility-widget-container';
|
|
1074
|
+
document.body.appendChild(container);
|
|
1075
|
+
|
|
1076
|
+
// Create shadow root
|
|
1077
|
+
shadowRoot = container.attachShadow({ mode: 'open' });
|
|
1078
|
+
|
|
1079
|
+
// Add widget styles to shadow DOM
|
|
1080
|
+
const styleElement = document.createElement('style');
|
|
1081
|
+
styleElement.textContent = widgetStyles;
|
|
1082
|
+
shadowRoot.appendChild(styleElement);
|
|
1083
|
+
|
|
1084
|
+
return shadowRoot;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
515
1087
|
// ===========================================
|
|
516
|
-
//
|
|
1088
|
+
// CORE UTILITY FUNCTIONS
|
|
517
1089
|
// ===========================================
|
|
518
1090
|
|
|
519
1091
|
// Cache for DOM elements to improve performance
|
|
@@ -522,7 +1094,7 @@ const domCache = {
|
|
|
522
1094
|
documentElement: document.documentElement,
|
|
523
1095
|
images: null,
|
|
524
1096
|
lastImageUpdate: 0,
|
|
525
|
-
getImages: function() {
|
|
1097
|
+
getImages: function () {
|
|
526
1098
|
const now = Date.now();
|
|
527
1099
|
if (!this.images || now - this.lastImageUpdate > 5000) {
|
|
528
1100
|
this.images = document.querySelectorAll('img');
|
|
@@ -537,13 +1109,10 @@ function applySettings() {
|
|
|
537
1109
|
const settings = [
|
|
538
1110
|
{ key: 'biggerCursor', className: 'snn-bigger-cursor' },
|
|
539
1111
|
{ key: 'biggerText', className: 'snn-bigger-text' },
|
|
540
|
-
{ key: 'highContrast', className: 'snn-high-contrast'
|
|
1112
|
+
{ key: 'highContrast', className: 'snn-high-contrast' },
|
|
541
1113
|
{ key: 'dyslexiaFont', className: 'snn-dyslexia-font' },
|
|
542
|
-
{ key: 'lineHeight', className: 'snn-line-height' },
|
|
543
1114
|
{ key: 'textAlign', className: 'snn-text-align' },
|
|
544
1115
|
{ key: 'pauseAnimations', className: 'snn-pause-animations' },
|
|
545
|
-
{ key: 'textSpacing', className: 'snn-text-spacing' },
|
|
546
|
-
{ key: 'reducedMotion', className: 'snn-reduced-motion' },
|
|
547
1116
|
];
|
|
548
1117
|
|
|
549
1118
|
// Batch DOM operations for better performance
|
|
@@ -601,6 +1170,14 @@ function applySettings() {
|
|
|
601
1170
|
domCache.documentElement.classList.add(`snn-filter-${selectedFilter}`);
|
|
602
1171
|
}
|
|
603
1172
|
|
|
1173
|
+
// Handle saturation filters
|
|
1174
|
+
const saturationClasses = ['snn-saturation-low', 'snn-saturation-high', 'snn-saturation-none'];
|
|
1175
|
+
domCache.documentElement.classList.remove(...saturationClasses);
|
|
1176
|
+
const selectedSaturation = localStorage.getItem('saturation');
|
|
1177
|
+
if (selectedSaturation) {
|
|
1178
|
+
domCache.documentElement.classList.add(`snn-saturation-${selectedSaturation}`);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
604
1181
|
// Handle text alignment
|
|
605
1182
|
const alignClasses = ['snn-text-align-left', 'snn-text-align-center', 'snn-text-align-right'];
|
|
606
1183
|
domCache.body.classList.remove(...alignClasses);
|
|
@@ -619,10 +1196,26 @@ function applySettings() {
|
|
|
619
1196
|
|
|
620
1197
|
// Handle high contrast
|
|
621
1198
|
const contrastClasses = ['snn-high-contrast-medium', 'snn-high-contrast-high', 'snn-high-contrast-ultra'];
|
|
622
|
-
domCache.
|
|
1199
|
+
domCache.body.classList.remove(...contrastClasses);
|
|
623
1200
|
const selectedContrast = localStorage.getItem('highContrast');
|
|
624
1201
|
if (selectedContrast) {
|
|
625
|
-
domCache.
|
|
1202
|
+
domCache.body.classList.add(`snn-high-contrast-${selectedContrast}`);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// Handle Text Spacing (3 Levels)
|
|
1206
|
+
const spacingClasses = ['snn-text-spacing-light', 'snn-text-spacing-medium', 'snn-text-spacing-heavy'];
|
|
1207
|
+
domCache.body.classList.remove(...spacingClasses);
|
|
1208
|
+
const selectedSpacing = localStorage.getItem('textSpacing');
|
|
1209
|
+
if (selectedSpacing) {
|
|
1210
|
+
domCache.body.classList.add(`snn-text-spacing-${selectedSpacing}`);
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// Handle Line Height (3 Levels)
|
|
1214
|
+
const lineHeightClasses = ['snn-line-height-2em', 'snn-line-height-3em', 'snn-line-height-4em'];
|
|
1215
|
+
domCache.body.classList.remove(...lineHeightClasses);
|
|
1216
|
+
const selectedLineHeight = localStorage.getItem('lineHeight');
|
|
1217
|
+
if (selectedLineHeight) {
|
|
1218
|
+
domCache.body.classList.add(`snn-line-height-${selectedLineHeight}`);
|
|
626
1219
|
}
|
|
627
1220
|
|
|
628
1221
|
// Handle images with cached query
|
|
@@ -653,12 +1246,12 @@ function createAccessibilityButton() {
|
|
|
653
1246
|
const button = document.createElement('button');
|
|
654
1247
|
button.id = 'snn-accessibility-button';
|
|
655
1248
|
button.innerHTML = icons.buttonsvg;
|
|
656
|
-
button.setAttribute('aria-label',
|
|
1249
|
+
button.setAttribute('aria-label', getTranslation('accessibilityMenu'));
|
|
657
1250
|
|
|
658
1251
|
button.addEventListener('click', function () {
|
|
659
1252
|
toggleMenu();
|
|
660
1253
|
});
|
|
661
|
-
|
|
1254
|
+
|
|
662
1255
|
button.addEventListener('keydown', function (e) {
|
|
663
1256
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
664
1257
|
e.preventDefault();
|
|
@@ -667,7 +1260,7 @@ function createAccessibilityButton() {
|
|
|
667
1260
|
});
|
|
668
1261
|
|
|
669
1262
|
buttonContainer.appendChild(button);
|
|
670
|
-
|
|
1263
|
+
shadowRoot.appendChild(buttonContainer);
|
|
671
1264
|
}
|
|
672
1265
|
|
|
673
1266
|
// Reset all accessibility settings
|
|
@@ -684,9 +1277,9 @@ function resetAccessibilitySettings() {
|
|
|
684
1277
|
'textSpacing',
|
|
685
1278
|
'highContrast',
|
|
686
1279
|
'voiceControl',
|
|
687
|
-
'reducedMotion',
|
|
688
1280
|
'fontSelection',
|
|
689
1281
|
'colorFilter',
|
|
1282
|
+
'saturation',
|
|
690
1283
|
];
|
|
691
1284
|
keys.forEach((key) => localStorage.removeItem(key));
|
|
692
1285
|
|
|
@@ -696,25 +1289,45 @@ function resetAccessibilitySettings() {
|
|
|
696
1289
|
'snn-bigger-text',
|
|
697
1290
|
'snn-dyslexia-font',
|
|
698
1291
|
'snn-pause-animations',
|
|
699
|
-
'snn-text-spacing',
|
|
700
|
-
'snn-line-height',
|
|
701
1292
|
'snn-text-align',
|
|
702
|
-
'snn-reduced-motion',
|
|
703
1293
|
'snn-font-arial',
|
|
704
1294
|
'snn-font-times',
|
|
705
1295
|
'snn-font-verdana'
|
|
706
1296
|
];
|
|
707
1297
|
cssClasses.forEach(cls => document.body.classList.remove(cls));
|
|
708
1298
|
|
|
1299
|
+
const bodyClasses2 = [
|
|
1300
|
+
'snn-high-contrast-medium',
|
|
1301
|
+
'snn-high-contrast-high',
|
|
1302
|
+
'snn-high-contrast-ultra'
|
|
1303
|
+
];
|
|
1304
|
+
bodyClasses2.forEach(cls => document.body.classList.remove(cls));
|
|
1305
|
+
|
|
709
1306
|
const documentClasses = [
|
|
710
|
-
'snn-high-contrast',
|
|
711
1307
|
'snn-filter-protanopia',
|
|
712
1308
|
'snn-filter-deuteranopia',
|
|
713
1309
|
'snn-filter-tritanopia',
|
|
714
|
-
'snn-filter-grayscale'
|
|
1310
|
+
'snn-filter-grayscale',
|
|
1311
|
+
'snn-saturation-low',
|
|
1312
|
+
'snn-saturation-high',
|
|
1313
|
+
'snn-saturation-none'
|
|
715
1314
|
];
|
|
716
1315
|
documentClasses.forEach(cls => document.documentElement.classList.remove(cls));
|
|
717
1316
|
|
|
1317
|
+
const textSizeClasses = [
|
|
1318
|
+
'snn-bigger-text-medium',
|
|
1319
|
+
'snn-bigger-text-large',
|
|
1320
|
+
'snn-bigger-text-xlarge'
|
|
1321
|
+
];
|
|
1322
|
+
textSizeClasses.forEach(cls => document.body.classList.remove(cls));
|
|
1323
|
+
|
|
1324
|
+
// Clear Multi-level classes
|
|
1325
|
+
const spacingClasses = ['snn-text-spacing-light', 'snn-text-spacing-medium', 'snn-text-spacing-heavy'];
|
|
1326
|
+
spacingClasses.forEach(cls => document.body.classList.remove(cls));
|
|
1327
|
+
|
|
1328
|
+
const lineHeightClasses = ['snn-line-height-2em', 'snn-line-height-3em', 'snn-line-height-4em'];
|
|
1329
|
+
lineHeightClasses.forEach(cls => document.body.classList.remove(cls));
|
|
1330
|
+
|
|
718
1331
|
domCache.getImages().forEach((img) => (img.style.display = ''));
|
|
719
1332
|
|
|
720
1333
|
if (screenReader.active) {
|
|
@@ -727,10 +1340,14 @@ function resetAccessibilitySettings() {
|
|
|
727
1340
|
|
|
728
1341
|
applySettings();
|
|
729
1342
|
|
|
730
|
-
const buttons =
|
|
1343
|
+
const buttons = shadowRoot.querySelectorAll('#snn-accessibility-menu .snn-accessibility-option');
|
|
731
1344
|
buttons.forEach((button) => {
|
|
732
1345
|
button.classList.remove('active');
|
|
733
1346
|
button.setAttribute('aria-pressed', 'false');
|
|
1347
|
+
|
|
1348
|
+
// Reset step indicators
|
|
1349
|
+
const steps = button.querySelectorAll('.snn-option-step');
|
|
1350
|
+
steps.forEach(step => step.classList.remove('active'));
|
|
734
1351
|
});
|
|
735
1352
|
}
|
|
736
1353
|
|
|
@@ -742,18 +1359,25 @@ function createToggleButton(
|
|
|
742
1359
|
targetElement = document.body,
|
|
743
1360
|
customToggleFunction = null,
|
|
744
1361
|
iconSVG = '',
|
|
745
|
-
requiresFeature = null
|
|
1362
|
+
requiresFeature = null,
|
|
1363
|
+
optionId = null
|
|
746
1364
|
) {
|
|
747
1365
|
const button = document.createElement('button');
|
|
748
|
-
button.innerHTML =
|
|
1366
|
+
button.innerHTML = `
|
|
1367
|
+
<span class="snn-icon">${iconSVG}</span>
|
|
1368
|
+
<span class="snn-button-text">${buttonText}</span>
|
|
1369
|
+
`;
|
|
749
1370
|
button.setAttribute('data-key', localStorageKey);
|
|
750
1371
|
button.setAttribute('aria-label', buttonText);
|
|
751
1372
|
button.classList.add('snn-accessibility-option');
|
|
1373
|
+
if (optionId) {
|
|
1374
|
+
button.setAttribute('data-accessibility-option-id', optionId);
|
|
1375
|
+
}
|
|
752
1376
|
|
|
753
1377
|
// Check if feature is supported
|
|
754
1378
|
if (requiresFeature && !requiresFeature.isSupported) {
|
|
755
1379
|
button.disabled = true;
|
|
756
|
-
button.setAttribute('title', `${buttonText} ${
|
|
1380
|
+
button.setAttribute('title', `${buttonText} ${getTranslation('notSupportedBrowser')}`);
|
|
757
1381
|
button.style.opacity = '0.5';
|
|
758
1382
|
return button;
|
|
759
1383
|
}
|
|
@@ -768,17 +1392,17 @@ function createToggleButton(
|
|
|
768
1392
|
button.addEventListener('click', function () {
|
|
769
1393
|
handleToggle();
|
|
770
1394
|
});
|
|
771
|
-
|
|
1395
|
+
|
|
772
1396
|
button.addEventListener('keydown', function (e) {
|
|
773
1397
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
774
1398
|
e.preventDefault();
|
|
775
1399
|
handleToggle();
|
|
776
1400
|
}
|
|
777
1401
|
});
|
|
778
|
-
|
|
1402
|
+
|
|
779
1403
|
function handleToggle() {
|
|
780
1404
|
const newIsActive = localStorage.getItem(localStorageKey) !== 'true';
|
|
781
|
-
|
|
1405
|
+
|
|
782
1406
|
// If there's a custom toggle function, call it and check if it succeeded
|
|
783
1407
|
if (customToggleFunction) {
|
|
784
1408
|
const success = customToggleFunction(newIsActive);
|
|
@@ -787,7 +1411,7 @@ function createToggleButton(
|
|
|
787
1411
|
return;
|
|
788
1412
|
}
|
|
789
1413
|
}
|
|
790
|
-
|
|
1414
|
+
|
|
791
1415
|
localStorage.setItem(localStorageKey, newIsActive);
|
|
792
1416
|
button.setAttribute('aria-pressed', newIsActive);
|
|
793
1417
|
|
|
@@ -808,56 +1432,111 @@ function createToggleButton(
|
|
|
808
1432
|
}
|
|
809
1433
|
|
|
810
1434
|
// Create special action buttons (for cycling through options)
|
|
811
|
-
function createActionButton(buttonText, actionFunction, iconSVG) {
|
|
1435
|
+
function createActionButton(buttonText, actionFunction, iconSVG, optionsConfig = null, optionId = null) {
|
|
812
1436
|
const button = document.createElement('button');
|
|
813
|
-
|
|
1437
|
+
|
|
1438
|
+
let buttonHTML = `
|
|
1439
|
+
<span class="snn-icon">${iconSVG}</span>
|
|
1440
|
+
<span class="snn-button-text">${buttonText}</span>
|
|
1441
|
+
`;
|
|
1442
|
+
|
|
1443
|
+
// Add option steps if configured
|
|
1444
|
+
if (optionsConfig) {
|
|
1445
|
+
buttonHTML += '<div class="snn-option-steps">';
|
|
1446
|
+
for (let i = 0; i < optionsConfig.count; i++) {
|
|
1447
|
+
buttonHTML += '<div class="snn-option-step"></div>';
|
|
1448
|
+
}
|
|
1449
|
+
buttonHTML += '</div>';
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
button.innerHTML = buttonHTML;
|
|
814
1453
|
button.setAttribute('aria-label', buttonText);
|
|
815
1454
|
button.classList.add('snn-accessibility-option');
|
|
816
|
-
|
|
1455
|
+
button.setAttribute('data-options-config', optionsConfig ? JSON.stringify(optionsConfig) : '');
|
|
1456
|
+
if (optionId) {
|
|
1457
|
+
button.setAttribute('data-accessibility-option-id', optionId);
|
|
1458
|
+
}
|
|
1459
|
+
|
|
817
1460
|
// Update initial status
|
|
818
|
-
updateActionButtonStatus(button,
|
|
819
|
-
|
|
1461
|
+
updateActionButtonStatus(button, optionId, optionsConfig);
|
|
1462
|
+
|
|
820
1463
|
button.addEventListener('click', function () {
|
|
821
1464
|
const result = actionFunction();
|
|
822
1465
|
if (result) {
|
|
823
|
-
|
|
824
|
-
statusSpan.textContent = result;
|
|
1466
|
+
updateActionButtonStatus(button, optionId, optionsConfig);
|
|
825
1467
|
}
|
|
826
1468
|
});
|
|
827
|
-
|
|
1469
|
+
|
|
828
1470
|
button.addEventListener('keydown', function (e) {
|
|
829
1471
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
830
1472
|
e.preventDefault();
|
|
831
1473
|
const result = actionFunction();
|
|
832
1474
|
if (result) {
|
|
833
|
-
|
|
834
|
-
statusSpan.textContent = result;
|
|
1475
|
+
updateActionButtonStatus(button, optionId, optionsConfig);
|
|
835
1476
|
}
|
|
836
1477
|
}
|
|
837
1478
|
});
|
|
838
|
-
|
|
1479
|
+
|
|
839
1480
|
return button;
|
|
840
1481
|
}
|
|
841
1482
|
|
|
842
1483
|
// Update action button status on page load
|
|
843
|
-
function updateActionButtonStatus(button,
|
|
844
|
-
|
|
1484
|
+
function updateActionButtonStatus(button, optionId, optionsConfig) {
|
|
1485
|
+
if (!optionsConfig) return;
|
|
1486
|
+
|
|
1487
|
+
const steps = button.querySelectorAll('.snn-option-step');
|
|
1488
|
+
let currentIndex = -1;
|
|
845
1489
|
|
|
846
|
-
if (
|
|
1490
|
+
if (optionId === 'fontSelection') {
|
|
847
1491
|
const currentFont = localStorage.getItem('fontSelection');
|
|
848
|
-
|
|
849
|
-
|
|
1492
|
+
const fonts = ['arial', 'times', 'verdana'];
|
|
1493
|
+
currentIndex = currentFont ? fonts.indexOf(currentFont) : -1;
|
|
1494
|
+
} else if (optionId === 'colorFilter') {
|
|
850
1495
|
const currentFilter = localStorage.getItem('colorFilter');
|
|
851
|
-
|
|
852
|
-
|
|
1496
|
+
const filters = ['protanopia', 'deuteranopia', 'tritanopia', 'grayscale'];
|
|
1497
|
+
currentIndex = currentFilter ? filters.indexOf(currentFilter) : -1;
|
|
1498
|
+
} else if (optionId === 'textAlign') {
|
|
853
1499
|
const currentAlign = localStorage.getItem('textAlign');
|
|
854
|
-
|
|
855
|
-
|
|
1500
|
+
const alignments = ['left', 'center', 'right'];
|
|
1501
|
+
currentIndex = currentAlign ? alignments.indexOf(currentAlign) : -1;
|
|
1502
|
+
} else if (optionId === 'biggerText') {
|
|
856
1503
|
const currentSize = localStorage.getItem('biggerText');
|
|
857
|
-
|
|
858
|
-
|
|
1504
|
+
const sizes = ['medium', 'large', 'xlarge'];
|
|
1505
|
+
currentIndex = currentSize ? sizes.indexOf(currentSize) : -1;
|
|
1506
|
+
} else if (optionId === 'highContrast') {
|
|
859
1507
|
const currentContrast = localStorage.getItem('highContrast');
|
|
860
|
-
|
|
1508
|
+
const contrasts = ['medium', 'high', 'ultra'];
|
|
1509
|
+
currentIndex = currentContrast ? contrasts.indexOf(currentContrast) : -1;
|
|
1510
|
+
} else if (optionId === 'textSpacing') {
|
|
1511
|
+
const currentSpacing = localStorage.getItem('textSpacing');
|
|
1512
|
+
const spacings = ['light', 'medium', 'heavy'];
|
|
1513
|
+
currentIndex = currentSpacing ? spacings.indexOf(currentSpacing) : -1;
|
|
1514
|
+
} else if (optionId === 'lineHeight') {
|
|
1515
|
+
const currentLineHeight = localStorage.getItem('lineHeight');
|
|
1516
|
+
const heights = ['2em', '3em', '4em'];
|
|
1517
|
+
currentIndex = currentLineHeight ? heights.indexOf(currentLineHeight) : -1;
|
|
1518
|
+
} else if (optionId === 'saturation') {
|
|
1519
|
+
const currentSaturation = localStorage.getItem('saturation');
|
|
1520
|
+
const saturations = ['low', 'high', 'none'];
|
|
1521
|
+
currentIndex = currentSaturation ? saturations.indexOf(currentSaturation) : -1;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
// Update step indicators - show all previous steps as active
|
|
1525
|
+
steps.forEach((step, index) => {
|
|
1526
|
+
if (index <= currentIndex) {
|
|
1527
|
+
step.classList.add('active');
|
|
1528
|
+
} else {
|
|
1529
|
+
step.classList.remove('active');
|
|
1530
|
+
}
|
|
1531
|
+
});
|
|
1532
|
+
|
|
1533
|
+
// Toggle active class on button itself if any option is selected
|
|
1534
|
+
if (currentIndex !== -1) {
|
|
1535
|
+
button.classList.add('active');
|
|
1536
|
+
button.setAttribute('aria-pressed', 'true');
|
|
1537
|
+
} else {
|
|
1538
|
+
button.classList.remove('active');
|
|
1539
|
+
button.setAttribute('aria-pressed', 'false');
|
|
861
1540
|
}
|
|
862
1541
|
}
|
|
863
1542
|
|
|
@@ -879,15 +1558,15 @@ function handleFontSelection() {
|
|
|
879
1558
|
const currentFont = localStorage.getItem('fontSelection') || 'default';
|
|
880
1559
|
const currentIndex = fonts.indexOf(currentFont);
|
|
881
1560
|
const nextIndex = (currentIndex + 1) % (fonts.length + 1); // +1 for default
|
|
882
|
-
|
|
1561
|
+
|
|
883
1562
|
// Remove all font classes in one operation
|
|
884
1563
|
const fontClasses = ['snn-font-arial', 'snn-font-times', 'snn-font-verdana'];
|
|
885
1564
|
domCache.body.classList.remove(...fontClasses);
|
|
886
|
-
|
|
1565
|
+
|
|
887
1566
|
if (nextIndex === fonts.length) {
|
|
888
1567
|
// Default font
|
|
889
1568
|
localStorage.removeItem('fontSelection');
|
|
890
|
-
return
|
|
1569
|
+
return getTranslation('defaultFont');
|
|
891
1570
|
} else {
|
|
892
1571
|
const selectedFont = fonts[nextIndex];
|
|
893
1572
|
localStorage.setItem('fontSelection', selectedFont);
|
|
@@ -896,21 +1575,47 @@ function handleFontSelection() {
|
|
|
896
1575
|
}
|
|
897
1576
|
}
|
|
898
1577
|
|
|
1578
|
+
// Saturation handler with 3 states (low, high, none/grayscale)
|
|
1579
|
+
function handleSaturation() {
|
|
1580
|
+
const saturations = ['low', 'high', 'none'];
|
|
1581
|
+
const currentSaturation = localStorage.getItem('saturation') || 'default';
|
|
1582
|
+
const currentIndex = saturations.indexOf(currentSaturation);
|
|
1583
|
+
const nextIndex = (currentIndex + 1) % (saturations.length + 1); // +1 for default
|
|
1584
|
+
|
|
1585
|
+
// Remove all saturation classes in one operation
|
|
1586
|
+
const saturationClasses = ['snn-saturation-low', 'snn-saturation-high', 'snn-saturation-none'];
|
|
1587
|
+
domCache.documentElement.classList.remove(...saturationClasses);
|
|
1588
|
+
|
|
1589
|
+
if (nextIndex === saturations.length) {
|
|
1590
|
+
// Default saturation
|
|
1591
|
+
localStorage.removeItem('saturation');
|
|
1592
|
+
return 'Default';
|
|
1593
|
+
} else {
|
|
1594
|
+
const selectedSaturation = saturations[nextIndex];
|
|
1595
|
+
localStorage.setItem('saturation', selectedSaturation);
|
|
1596
|
+
domCache.documentElement.classList.add(`snn-saturation-${selectedSaturation}`);
|
|
1597
|
+
if (selectedSaturation === 'none') {
|
|
1598
|
+
return 'No Saturation';
|
|
1599
|
+
}
|
|
1600
|
+
return selectedSaturation.charAt(0).toUpperCase() + selectedSaturation.slice(1) + ' Saturation';
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
|
|
899
1604
|
// Color filter handler (optimized)
|
|
900
1605
|
function handleColorFilter() {
|
|
901
1606
|
const filters = ['protanopia', 'deuteranopia', 'tritanopia', 'grayscale'];
|
|
902
1607
|
const currentFilter = localStorage.getItem('colorFilter') || 'none';
|
|
903
1608
|
const currentIndex = filters.indexOf(currentFilter);
|
|
904
1609
|
const nextIndex = (currentIndex + 1) % (filters.length + 1); // +1 for none
|
|
905
|
-
|
|
1610
|
+
|
|
906
1611
|
// Remove all filter classes in one operation
|
|
907
1612
|
const filterClasses = ['snn-filter-protanopia', 'snn-filter-deuteranopia', 'snn-filter-tritanopia', 'snn-filter-grayscale'];
|
|
908
1613
|
domCache.documentElement.classList.remove(...filterClasses);
|
|
909
|
-
|
|
1614
|
+
|
|
910
1615
|
if (nextIndex === filters.length) {
|
|
911
1616
|
// No filter
|
|
912
1617
|
localStorage.removeItem('colorFilter');
|
|
913
|
-
return
|
|
1618
|
+
return getTranslation('noFilter');
|
|
914
1619
|
} else {
|
|
915
1620
|
const selectedFilter = filters[nextIndex];
|
|
916
1621
|
localStorage.setItem('colorFilter', selectedFilter);
|
|
@@ -925,15 +1630,15 @@ function handleTextAlign() {
|
|
|
925
1630
|
const currentAlign = localStorage.getItem('textAlign') || 'none';
|
|
926
1631
|
const currentIndex = alignments.indexOf(currentAlign);
|
|
927
1632
|
const nextIndex = (currentIndex + 1) % (alignments.length + 1); // +1 for none
|
|
928
|
-
|
|
1633
|
+
|
|
929
1634
|
// Remove all alignment classes
|
|
930
1635
|
const alignClasses = ['snn-text-align-left', 'snn-text-align-center', 'snn-text-align-right'];
|
|
931
1636
|
domCache.body.classList.remove(...alignClasses);
|
|
932
|
-
|
|
1637
|
+
|
|
933
1638
|
if (nextIndex === alignments.length) {
|
|
934
1639
|
// Default alignment
|
|
935
1640
|
localStorage.removeItem('textAlign');
|
|
936
|
-
return
|
|
1641
|
+
return getTranslation('default');
|
|
937
1642
|
} else {
|
|
938
1643
|
const selectedAlign = alignments[nextIndex];
|
|
939
1644
|
localStorage.setItem('textAlign', selectedAlign);
|
|
@@ -948,15 +1653,15 @@ function handleBiggerText() {
|
|
|
948
1653
|
const currentSize = localStorage.getItem('biggerText') || 'none';
|
|
949
1654
|
const currentIndex = textSizes.indexOf(currentSize);
|
|
950
1655
|
const nextIndex = (currentIndex + 1) % (textSizes.length + 1); // +1 for none
|
|
951
|
-
|
|
1656
|
+
|
|
952
1657
|
// Remove all text size classes
|
|
953
1658
|
const textClasses = ['snn-bigger-text-medium', 'snn-bigger-text-large', 'snn-bigger-text-xlarge'];
|
|
954
1659
|
domCache.body.classList.remove(...textClasses);
|
|
955
|
-
|
|
1660
|
+
|
|
956
1661
|
if (nextIndex === textSizes.length) {
|
|
957
1662
|
// Default text size
|
|
958
1663
|
localStorage.removeItem('biggerText');
|
|
959
|
-
return
|
|
1664
|
+
return getTranslation('default');
|
|
960
1665
|
} else {
|
|
961
1666
|
const selectedSize = textSizes[nextIndex];
|
|
962
1667
|
localStorage.setItem('biggerText', selectedSize);
|
|
@@ -971,23 +1676,69 @@ function handleHighContrast() {
|
|
|
971
1676
|
const currentContrast = localStorage.getItem('highContrast') || 'none';
|
|
972
1677
|
const currentIndex = contrastLevels.indexOf(currentContrast);
|
|
973
1678
|
const nextIndex = (currentIndex + 1) % (contrastLevels.length + 1); // +1 for none
|
|
974
|
-
|
|
1679
|
+
|
|
975
1680
|
// Remove all contrast classes
|
|
976
1681
|
const contrastClasses = ['snn-high-contrast-medium', 'snn-high-contrast-high', 'snn-high-contrast-ultra'];
|
|
977
|
-
domCache.
|
|
978
|
-
|
|
1682
|
+
domCache.body.classList.remove(...contrastClasses);
|
|
1683
|
+
|
|
979
1684
|
if (nextIndex === contrastLevels.length) {
|
|
980
1685
|
// Default contrast
|
|
981
1686
|
localStorage.removeItem('highContrast');
|
|
982
|
-
return
|
|
1687
|
+
return getTranslation('default');
|
|
983
1688
|
} else {
|
|
984
1689
|
const selectedContrast = contrastLevels[nextIndex];
|
|
985
1690
|
localStorage.setItem('highContrast', selectedContrast);
|
|
986
|
-
domCache.
|
|
1691
|
+
domCache.body.classList.add(`snn-high-contrast-${selectedContrast}`);
|
|
987
1692
|
return selectedContrast.charAt(0).toUpperCase() + selectedContrast.slice(1);
|
|
988
1693
|
}
|
|
989
1694
|
}
|
|
990
1695
|
|
|
1696
|
+
// Text Spacing Handler with 3 states (1em, 2em, 4em equivalents)
|
|
1697
|
+
function handleTextSpacing() {
|
|
1698
|
+
const spacings = ['light', 'medium', 'heavy']; // Maps to 1, 2, 4 approx
|
|
1699
|
+
const currentSpacing = localStorage.getItem('textSpacing') || 'none';
|
|
1700
|
+
const currentIndex = spacings.indexOf(currentSpacing);
|
|
1701
|
+
const nextIndex = (currentIndex + 1) % (spacings.length + 1); // +1 for none
|
|
1702
|
+
|
|
1703
|
+
// Remove all spacing classes
|
|
1704
|
+
const spacingClasses = ['snn-text-spacing-light', 'snn-text-spacing-medium', 'snn-text-spacing-heavy'];
|
|
1705
|
+
domCache.body.classList.remove(...spacingClasses);
|
|
1706
|
+
|
|
1707
|
+
if (nextIndex === spacings.length) {
|
|
1708
|
+
// Default
|
|
1709
|
+
localStorage.removeItem('textSpacing');
|
|
1710
|
+
return getTranslation('default');
|
|
1711
|
+
} else {
|
|
1712
|
+
const selectedSpacing = spacings[nextIndex];
|
|
1713
|
+
localStorage.setItem('textSpacing', selectedSpacing);
|
|
1714
|
+
domCache.body.classList.add(`snn-text-spacing-${selectedSpacing}`);
|
|
1715
|
+
return selectedSpacing.charAt(0).toUpperCase() + selectedSpacing.slice(1);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
// Line Height Handler with 3 states (2em, 3em, 4em)
|
|
1720
|
+
function handleLineHeight() {
|
|
1721
|
+
const heights = ['2em', '3em', '4em'];
|
|
1722
|
+
const currentHeight = localStorage.getItem('lineHeight') || 'none';
|
|
1723
|
+
const currentIndex = heights.indexOf(currentHeight);
|
|
1724
|
+
const nextIndex = (currentIndex + 1) % (heights.length + 1); // +1 for none
|
|
1725
|
+
|
|
1726
|
+
// Remove all line height classes
|
|
1727
|
+
const heightClasses = ['snn-line-height-2em', 'snn-line-height-3em', 'snn-line-height-4em'];
|
|
1728
|
+
domCache.body.classList.remove(...heightClasses);
|
|
1729
|
+
|
|
1730
|
+
if (nextIndex === heights.length) {
|
|
1731
|
+
// Default
|
|
1732
|
+
localStorage.removeItem('lineHeight');
|
|
1733
|
+
return getTranslation('default');
|
|
1734
|
+
} else{
|
|
1735
|
+
const selectedHeight = heights[nextIndex];
|
|
1736
|
+
localStorage.setItem('lineHeight', selectedHeight);
|
|
1737
|
+
domCache.body.classList.add(`snn-line-height-${selectedHeight}`);
|
|
1738
|
+
return selectedHeight;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
|
|
991
1742
|
// ===========================================
|
|
992
1743
|
// ACCESSIBILITY FEATURES
|
|
993
1744
|
// ===========================================
|
|
@@ -1004,7 +1755,7 @@ const screenReader = {
|
|
|
1004
1755
|
window.speechSynthesis.cancel();
|
|
1005
1756
|
const speech = new SpeechSynthesisUtterance(content);
|
|
1006
1757
|
speech.lang = 'en-US';
|
|
1007
|
-
speech.onerror = function(event) {
|
|
1758
|
+
speech.onerror = function (event) {
|
|
1008
1759
|
console.warn('Speech synthesis error:', event.error);
|
|
1009
1760
|
};
|
|
1010
1761
|
window.speechSynthesis.speak(speech);
|
|
@@ -1016,28 +1767,28 @@ const screenReader = {
|
|
|
1016
1767
|
},
|
|
1017
1768
|
toggle: function (isActive) {
|
|
1018
1769
|
if (!screenReader.isSupported) {
|
|
1019
|
-
console.warn(`Speech synthesis ${
|
|
1770
|
+
console.warn(`Speech synthesis ${getTranslation('notSupportedBrowser')}`);
|
|
1020
1771
|
return false;
|
|
1021
1772
|
}
|
|
1022
|
-
|
|
1773
|
+
|
|
1023
1774
|
screenReader.active = isActive;
|
|
1024
1775
|
localStorage.setItem('screenReader', isActive);
|
|
1025
|
-
|
|
1776
|
+
|
|
1026
1777
|
try {
|
|
1027
1778
|
if (isActive) {
|
|
1028
1779
|
document.addEventListener('focusin', screenReader.handleFocus);
|
|
1029
|
-
const feedbackSpeech = new SpeechSynthesisUtterance(
|
|
1780
|
+
const feedbackSpeech = new SpeechSynthesisUtterance(getTranslation('screenReaderOn'));
|
|
1030
1781
|
feedbackSpeech.lang = 'en-US';
|
|
1031
|
-
feedbackSpeech.onerror = function(event) {
|
|
1782
|
+
feedbackSpeech.onerror = function (event) {
|
|
1032
1783
|
console.warn('Speech synthesis feedback error:', event.error);
|
|
1033
1784
|
};
|
|
1034
1785
|
window.speechSynthesis.speak(feedbackSpeech);
|
|
1035
1786
|
} else {
|
|
1036
1787
|
document.removeEventListener('focusin', screenReader.handleFocus);
|
|
1037
1788
|
window.speechSynthesis.cancel();
|
|
1038
|
-
const feedbackSpeech = new SpeechSynthesisUtterance(
|
|
1789
|
+
const feedbackSpeech = new SpeechSynthesisUtterance(getTranslation('screenReaderOff'));
|
|
1039
1790
|
feedbackSpeech.lang = 'en-US';
|
|
1040
|
-
feedbackSpeech.onerror = function(event) {
|
|
1791
|
+
feedbackSpeech.onerror = function (event) {
|
|
1041
1792
|
console.warn('Speech synthesis feedback error:', event.error);
|
|
1042
1793
|
};
|
|
1043
1794
|
window.speechSynthesis.speak(feedbackSpeech);
|
|
@@ -1046,7 +1797,7 @@ const screenReader = {
|
|
|
1046
1797
|
console.warn('Screen reader toggle error:', error);
|
|
1047
1798
|
return false;
|
|
1048
1799
|
}
|
|
1049
|
-
|
|
1800
|
+
|
|
1050
1801
|
return true;
|
|
1051
1802
|
},
|
|
1052
1803
|
};
|
|
@@ -1060,13 +1811,13 @@ const voiceControl = {
|
|
|
1060
1811
|
maxRetries: 3,
|
|
1061
1812
|
toggle: function (isActive) {
|
|
1062
1813
|
if (!voiceControl.isSupported) {
|
|
1063
|
-
console.warn(`Speech Recognition API ${
|
|
1814
|
+
console.warn(`Speech Recognition API ${getTranslation('notSupportedBrowser')}`);
|
|
1064
1815
|
return false;
|
|
1065
1816
|
}
|
|
1066
|
-
|
|
1817
|
+
|
|
1067
1818
|
voiceControl.isActive = isActive;
|
|
1068
1819
|
localStorage.setItem('voiceControl', isActive);
|
|
1069
|
-
|
|
1820
|
+
|
|
1070
1821
|
try {
|
|
1071
1822
|
if (isActive) {
|
|
1072
1823
|
voiceControl.startListening();
|
|
@@ -1081,14 +1832,14 @@ const voiceControl = {
|
|
|
1081
1832
|
console.warn('Voice control toggle error:', error);
|
|
1082
1833
|
return false;
|
|
1083
1834
|
}
|
|
1084
|
-
|
|
1835
|
+
|
|
1085
1836
|
return true;
|
|
1086
1837
|
},
|
|
1087
1838
|
startListening: function () {
|
|
1088
1839
|
if (!voiceControl.isSupported) {
|
|
1089
1840
|
return;
|
|
1090
1841
|
}
|
|
1091
|
-
|
|
1842
|
+
|
|
1092
1843
|
try {
|
|
1093
1844
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
1094
1845
|
voiceControl.recognition = new SpeechRecognition();
|
|
@@ -1097,7 +1848,7 @@ const voiceControl = {
|
|
|
1097
1848
|
voiceControl.recognition.continuous = false;
|
|
1098
1849
|
|
|
1099
1850
|
voiceControl.recognition.onstart = function () {
|
|
1100
|
-
console.log(
|
|
1851
|
+
console.log(getTranslation('voiceControlActivated'));
|
|
1101
1852
|
voiceControl.retryCount = 0;
|
|
1102
1853
|
};
|
|
1103
1854
|
|
|
@@ -1139,10 +1890,10 @@ const voiceControl = {
|
|
|
1139
1890
|
},
|
|
1140
1891
|
handleVoiceCommand: function (command) {
|
|
1141
1892
|
console.log(`Received command: ${command}`);
|
|
1142
|
-
|
|
1893
|
+
|
|
1143
1894
|
try {
|
|
1144
1895
|
// Check for show menu commands
|
|
1145
|
-
if (WIDGET_CONFIG.voiceCommands.showMenu.includes(
|
|
1896
|
+
if (WIDGET_CONFIG.voiceCommands.showMenu.some(cmd => command.includes(cmd))) {
|
|
1146
1897
|
if (!menuCache.button) menuCache.init();
|
|
1147
1898
|
if (menuCache.button) {
|
|
1148
1899
|
menuCache.button.click();
|
|
@@ -1151,36 +1902,36 @@ const voiceControl = {
|
|
|
1151
1902
|
}
|
|
1152
1903
|
|
|
1153
1904
|
// Check for reset all commands
|
|
1154
|
-
if (WIDGET_CONFIG.voiceCommands.resetAll.includes(
|
|
1905
|
+
if (WIDGET_CONFIG.voiceCommands.resetAll.some(cmd => command.includes(cmd))) {
|
|
1155
1906
|
resetAccessibilitySettings();
|
|
1156
1907
|
return;
|
|
1157
1908
|
}
|
|
1158
1909
|
|
|
1159
1910
|
// Build dynamic command map based on configuration
|
|
1160
1911
|
let localStorageKey = null;
|
|
1161
|
-
|
|
1912
|
+
|
|
1162
1913
|
// Check each command group
|
|
1163
|
-
if (WIDGET_CONFIG.voiceCommands.highContrast.includes(
|
|
1914
|
+
if (WIDGET_CONFIG.voiceCommands.highContrast.some(cmd => command.includes(cmd))) {
|
|
1164
1915
|
localStorageKey = 'highContrast';
|
|
1165
|
-
} else if (WIDGET_CONFIG.voiceCommands.biggerText.includes(
|
|
1916
|
+
} else if (WIDGET_CONFIG.voiceCommands.biggerText.some(cmd => command.includes(cmd))) {
|
|
1166
1917
|
localStorageKey = 'biggerText';
|
|
1167
|
-
} else if (WIDGET_CONFIG.voiceCommands.textSpacing.includes(
|
|
1918
|
+
} else if (WIDGET_CONFIG.voiceCommands.textSpacing.some(cmd => command.includes(cmd))) {
|
|
1168
1919
|
localStorageKey = 'textSpacing';
|
|
1169
|
-
} else if (WIDGET_CONFIG.voiceCommands.pauseAnimations.includes(
|
|
1920
|
+
} else if (WIDGET_CONFIG.voiceCommands.pauseAnimations.some(cmd => command.includes(cmd))) {
|
|
1170
1921
|
localStorageKey = 'pauseAnimations';
|
|
1171
|
-
} else if (WIDGET_CONFIG.voiceCommands.hideImages.includes(
|
|
1922
|
+
} else if (WIDGET_CONFIG.voiceCommands.hideImages.some(cmd => command.includes(cmd))) {
|
|
1172
1923
|
localStorageKey = 'hideImages';
|
|
1173
|
-
} else if (WIDGET_CONFIG.voiceCommands.dyslexiaFont.includes(
|
|
1924
|
+
} else if (WIDGET_CONFIG.voiceCommands.dyslexiaFont.some(cmd => command.includes(cmd))) {
|
|
1174
1925
|
localStorageKey = 'dyslexiaFont';
|
|
1175
|
-
} else if (WIDGET_CONFIG.voiceCommands.biggerCursor.includes(
|
|
1926
|
+
} else if (WIDGET_CONFIG.voiceCommands.biggerCursor.some(cmd => command.includes(cmd))) {
|
|
1176
1927
|
localStorageKey = 'biggerCursor';
|
|
1177
|
-
} else if (WIDGET_CONFIG.voiceCommands.lineHeight.includes(
|
|
1928
|
+
} else if (WIDGET_CONFIG.voiceCommands.lineHeight.some(cmd => command.includes(cmd))) {
|
|
1178
1929
|
localStorageKey = 'lineHeight';
|
|
1179
|
-
} else if (WIDGET_CONFIG.voiceCommands.textAlign.includes(
|
|
1930
|
+
} else if (WIDGET_CONFIG.voiceCommands.textAlign.some(cmd => command.includes(cmd))) {
|
|
1180
1931
|
localStorageKey = 'textAlign';
|
|
1181
|
-
} else if (WIDGET_CONFIG.voiceCommands.screenReader.includes(
|
|
1932
|
+
} else if (WIDGET_CONFIG.voiceCommands.screenReader.some(cmd => command.includes(cmd))) {
|
|
1182
1933
|
localStorageKey = 'screenReader';
|
|
1183
|
-
} else if (WIDGET_CONFIG.voiceCommands.voiceControl.includes(
|
|
1934
|
+
} else if (WIDGET_CONFIG.voiceCommands.voiceControl.some(cmd => command.includes(cmd))) {
|
|
1184
1935
|
localStorageKey = 'voiceControl';
|
|
1185
1936
|
}
|
|
1186
1937
|
|
|
@@ -1216,20 +1967,28 @@ function createAccessibilityMenu() {
|
|
|
1216
1967
|
const header = document.createElement('div');
|
|
1217
1968
|
header.classList.add('snn-header');
|
|
1218
1969
|
|
|
1219
|
-
const title = document.createElement('
|
|
1970
|
+
const title = document.createElement('div');
|
|
1220
1971
|
title.classList.add('snn-title');
|
|
1221
1972
|
title.id = 'snn-accessibility-title';
|
|
1222
|
-
title.textContent =
|
|
1973
|
+
title.textContent = getTranslation('accessibilityTools');
|
|
1223
1974
|
|
|
1975
|
+
// Create reset button
|
|
1976
|
+
const resetButton = document.createElement('button');
|
|
1977
|
+
resetButton.classList.add('snn-reset-button');
|
|
1978
|
+
resetButton.innerHTML = `${icons.resetAll}<span class="snn-tooltip">${getTranslation('reset')}</span>`;
|
|
1979
|
+
resetButton.setAttribute('aria-label', getTranslation('resetAllSettings'));
|
|
1980
|
+
resetButton.addEventListener('click', resetAccessibilitySettings);
|
|
1981
|
+
|
|
1982
|
+
// Create close button
|
|
1224
1983
|
const closeButton = document.createElement('button');
|
|
1225
1984
|
closeButton.className = 'snn-close';
|
|
1226
|
-
closeButton.innerHTML = ''
|
|
1227
|
-
closeButton.setAttribute('
|
|
1985
|
+
closeButton.innerHTML = `<span class="snn-tooltip">${getTranslation('close')}</span>`;
|
|
1986
|
+
closeButton.setAttribute('aria-label', getTranslation('closeAccessibilityMenu'));
|
|
1228
1987
|
|
|
1229
1988
|
closeButton.addEventListener('click', function () {
|
|
1230
1989
|
closeMenu();
|
|
1231
1990
|
});
|
|
1232
|
-
|
|
1991
|
+
|
|
1233
1992
|
closeButton.addEventListener('keydown', function (e) {
|
|
1234
1993
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
1235
1994
|
e.preventDefault();
|
|
@@ -1238,6 +1997,7 @@ function createAccessibilityMenu() {
|
|
|
1238
1997
|
});
|
|
1239
1998
|
|
|
1240
1999
|
header.appendChild(title);
|
|
2000
|
+
header.appendChild(resetButton);
|
|
1241
2001
|
header.appendChild(closeButton);
|
|
1242
2002
|
menu.appendChild(header);
|
|
1243
2003
|
|
|
@@ -1245,136 +2005,271 @@ function createAccessibilityMenu() {
|
|
|
1245
2005
|
const content = document.createElement('div');
|
|
1246
2006
|
content.classList.add('snn-content');
|
|
1247
2007
|
|
|
1248
|
-
// Create
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
2008
|
+
// Create language selector dropdown
|
|
2009
|
+
const languageSelector = document.createElement('select');
|
|
2010
|
+
languageSelector.classList.add('snn-language-selector');
|
|
2011
|
+
languageSelector.setAttribute('aria-label', getTranslation('selectLanguage'));
|
|
2012
|
+
|
|
2013
|
+
const languages = [
|
|
2014
|
+
{ code: 'en', name: 'English' },
|
|
2015
|
+
{ code: 'de', name: 'Deutsch' },
|
|
2016
|
+
{ code: 'es', name: 'Español' },
|
|
2017
|
+
{ code: 'it', name: 'Italiano' },
|
|
2018
|
+
{ code: 'fr', name: 'Français' },
|
|
2019
|
+
{ code: 'ru', name: 'Русский' },
|
|
2020
|
+
{ code: 'tr', name: 'Türkçe' },
|
|
2021
|
+
{ code: 'ar', name: 'العربية' },
|
|
2022
|
+
{ code: 'hi', name: 'हिन्दी' },
|
|
2023
|
+
{ code: 'zh-cn', name: '简体中文' },
|
|
2024
|
+
{ code: 'jp', name: '日本語' }
|
|
2025
|
+
];
|
|
2026
|
+
|
|
2027
|
+
languages.forEach(lang => {
|
|
2028
|
+
const option = document.createElement('option');
|
|
2029
|
+
option.value = lang.code;
|
|
2030
|
+
option.textContent = lang.name;
|
|
2031
|
+
if (lang.code === currentLanguage) {
|
|
2032
|
+
option.selected = true;
|
|
2033
|
+
}
|
|
2034
|
+
languageSelector.appendChild(option);
|
|
2035
|
+
});
|
|
2036
|
+
|
|
2037
|
+
languageSelector.addEventListener('change', function(e) {
|
|
2038
|
+
const newLang = e.target.value;
|
|
2039
|
+
if (setLanguage(newLang)) {
|
|
2040
|
+
// Recreate the menu with new language
|
|
2041
|
+
updateMenuLanguage();
|
|
2042
|
+
}
|
|
2043
|
+
});
|
|
2044
|
+
|
|
2045
|
+
content.appendChild(languageSelector);
|
|
1255
2046
|
|
|
1256
2047
|
// Create grid wrapper for accessibility options
|
|
1257
2048
|
const optionsGrid = document.createElement('div');
|
|
1258
2049
|
optionsGrid.classList.add('snn-options-grid');
|
|
1259
2050
|
|
|
1260
|
-
//
|
|
1261
|
-
|
|
2051
|
+
// ===================================================================
|
|
2052
|
+
// UNIFIED BUTTON CONFIGURATION WITH EXPLICIT ORDERING
|
|
2053
|
+
// Add/remove/reorder buttons by changing the 'order' property
|
|
2054
|
+
// Lower order numbers appear first, higher numbers appear last
|
|
2055
|
+
// ===================================================================
|
|
2056
|
+
const allButtonConfigs = [
|
|
2057
|
+
// Order 1-4: Primary accessibility features
|
|
1262
2058
|
{
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
enabled: WIDGET_CONFIG.
|
|
2059
|
+
order: 1,
|
|
2060
|
+
type: 'action',
|
|
2061
|
+
text: getTranslation('textSize'),
|
|
2062
|
+
actionFunction: handleBiggerText,
|
|
2063
|
+
icon: icons.biggerText,
|
|
2064
|
+
enabled: WIDGET_CONFIG.enableBiggerText,
|
|
2065
|
+
optionsConfig: { count: 3 },
|
|
2066
|
+
optionId: 'biggerText'
|
|
1269
2067
|
},
|
|
1270
2068
|
{
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
enabled: WIDGET_CONFIG.
|
|
2069
|
+
order: 2,
|
|
2070
|
+
type: 'action',
|
|
2071
|
+
text: getTranslation('highContrast'),
|
|
2072
|
+
actionFunction: handleHighContrast,
|
|
2073
|
+
icon: icons.highContrast,
|
|
2074
|
+
enabled: WIDGET_CONFIG.enableHighContrast,
|
|
2075
|
+
optionsConfig: { count: 3 },
|
|
2076
|
+
optionId: 'highContrast'
|
|
1277
2077
|
},
|
|
1278
2078
|
{
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
2079
|
+
order: 3,
|
|
2080
|
+
type: 'action',
|
|
2081
|
+
text: getTranslation('textAlign'),
|
|
2082
|
+
actionFunction: handleTextAlign,
|
|
2083
|
+
icon: icons.textAlign,
|
|
2084
|
+
enabled: WIDGET_CONFIG.enableTextAlign,
|
|
2085
|
+
optionsConfig: { count: 3 },
|
|
2086
|
+
optionId: 'textAlign'
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
order: 4,
|
|
2090
|
+
type: 'action',
|
|
2091
|
+
text: getTranslation('colorFilter'),
|
|
2092
|
+
actionFunction: handleColorFilter,
|
|
2093
|
+
icon: icons.colorFilter,
|
|
2094
|
+
enabled: WIDGET_CONFIG.enableColorFilter,
|
|
2095
|
+
optionsConfig: { count: 4 },
|
|
2096
|
+
optionId: 'colorFilter'
|
|
2097
|
+
},
|
|
2098
|
+
|
|
2099
|
+
// Order 5-11: Other visual/text features
|
|
2100
|
+
{
|
|
2101
|
+
order: 5,
|
|
2102
|
+
type: 'action', // Changed from toggle to action
|
|
2103
|
+
text: getTranslation('textSpacing'),
|
|
2104
|
+
actionFunction: handleTextSpacing,
|
|
1282
2105
|
icon: icons.textSpacing,
|
|
1283
2106
|
enabled: WIDGET_CONFIG.enableTextSpacing,
|
|
2107
|
+
optionsConfig: { count: 3 },
|
|
2108
|
+
optionId: 'textSpacing'
|
|
1284
2109
|
},
|
|
1285
2110
|
{
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
2111
|
+
order: 6,
|
|
2112
|
+
type: 'action', // Changed from toggle to action
|
|
2113
|
+
text: getTranslation('lineHeight'),
|
|
2114
|
+
actionFunction: handleLineHeight,
|
|
2115
|
+
icon: icons.lineHeight,
|
|
2116
|
+
enabled: WIDGET_CONFIG.enableLineHeight,
|
|
2117
|
+
optionsConfig: { count: 3 },
|
|
2118
|
+
optionId: 'lineHeight'
|
|
1291
2119
|
},
|
|
1292
2120
|
{
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
2121
|
+
order: 7,
|
|
2122
|
+
type: 'action',
|
|
2123
|
+
text: getTranslation('fontSelection'),
|
|
2124
|
+
actionFunction: handleFontSelection,
|
|
2125
|
+
icon: icons.fontSelection,
|
|
2126
|
+
enabled: WIDGET_CONFIG.enableFontSelection,
|
|
2127
|
+
optionsConfig: { count: 3 },
|
|
2128
|
+
optionId: 'fontSelection'
|
|
2129
|
+
},
|
|
2130
|
+
{
|
|
2131
|
+
order: 7.5,
|
|
2132
|
+
type: 'action',
|
|
2133
|
+
text: getTranslation('saturation'),
|
|
2134
|
+
actionFunction: handleSaturation,
|
|
2135
|
+
icon: icons.saturation,
|
|
2136
|
+
enabled: true,
|
|
2137
|
+
optionsConfig: { count: 3 },
|
|
2138
|
+
optionId: 'saturation'
|
|
1298
2139
|
},
|
|
1299
2140
|
{
|
|
1300
|
-
|
|
2141
|
+
order: 8,
|
|
2142
|
+
type: 'toggle',
|
|
2143
|
+
text: getTranslation('dyslexiaFriendly'),
|
|
1301
2144
|
key: 'dyslexiaFont',
|
|
1302
2145
|
className: 'snn-dyslexia-font',
|
|
1303
2146
|
icon: icons.dyslexiaFont,
|
|
1304
2147
|
enabled: WIDGET_CONFIG.enableDyslexiaFont,
|
|
2148
|
+
optionId: 'dyslexiaFont'
|
|
1305
2149
|
},
|
|
1306
2150
|
{
|
|
1307
|
-
|
|
2151
|
+
order: 9,
|
|
2152
|
+
type: 'toggle',
|
|
2153
|
+
text: getTranslation('biggerCursor'),
|
|
1308
2154
|
key: 'biggerCursor',
|
|
1309
2155
|
className: 'snn-bigger-cursor',
|
|
1310
2156
|
icon: icons.biggerCursor,
|
|
1311
2157
|
enabled: WIDGET_CONFIG.enableBiggerCursor,
|
|
2158
|
+
optionId: 'biggerCursor'
|
|
1312
2159
|
},
|
|
1313
2160
|
{
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
2161
|
+
order: 10,
|
|
2162
|
+
type: 'toggle',
|
|
2163
|
+
text: getTranslation('hideImages'),
|
|
2164
|
+
key: 'hideImages',
|
|
2165
|
+
icon: icons.hideImages,
|
|
2166
|
+
customToggleFunction: toggleHideImages,
|
|
2167
|
+
enabled: WIDGET_CONFIG.enableHideImages,
|
|
2168
|
+
optionId: 'hideImages'
|
|
2169
|
+
},
|
|
2170
|
+
|
|
2171
|
+
// Order 11: Animation controls (Reduced Motion merged here)
|
|
2172
|
+
{
|
|
2173
|
+
order: 11,
|
|
2174
|
+
type: 'toggle',
|
|
2175
|
+
text: getTranslation('pauseAnimations'),
|
|
2176
|
+
key: 'pauseAnimations',
|
|
2177
|
+
className: 'snn-pause-animations',
|
|
2178
|
+
icon: icons.pauseAnimations,
|
|
2179
|
+
enabled: WIDGET_CONFIG.enablePauseAnimations,
|
|
2180
|
+
optionId: 'pauseAnimations'
|
|
2181
|
+
},
|
|
2182
|
+
|
|
2183
|
+
// Order 98-99: Screen Reader and Voice Control (always last)
|
|
2184
|
+
{
|
|
2185
|
+
order: 98,
|
|
2186
|
+
type: 'toggle',
|
|
2187
|
+
text: getTranslation('screenReader'),
|
|
2188
|
+
key: 'screenReader',
|
|
2189
|
+
customToggleFunction: screenReader.toggle,
|
|
2190
|
+
icon: icons.screenReader,
|
|
2191
|
+
requiresFeature: screenReader,
|
|
2192
|
+
enabled: WIDGET_CONFIG.enableScreenReader,
|
|
2193
|
+
optionId: 'screenReader'
|
|
1319
2194
|
},
|
|
1320
2195
|
{
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
2196
|
+
order: 99,
|
|
2197
|
+
type: 'toggle',
|
|
2198
|
+
text: getTranslation('voiceCommand'),
|
|
2199
|
+
key: 'voiceControl',
|
|
2200
|
+
customToggleFunction: voiceControl.toggle,
|
|
2201
|
+
icon: icons.voiceControl,
|
|
2202
|
+
requiresFeature: voiceControl,
|
|
2203
|
+
enabled: WIDGET_CONFIG.enableVoiceControl,
|
|
2204
|
+
optionId: 'voiceControl'
|
|
1326
2205
|
},
|
|
1327
2206
|
];
|
|
2207
|
+
|
|
2208
|
+
// Sort buttons by order and add only enabled ones to the grid
|
|
2209
|
+
allButtonConfigs
|
|
2210
|
+
.filter(config => config.enabled)
|
|
2211
|
+
.sort((a, b) => a.order - b.order)
|
|
2212
|
+
.forEach((config) => {
|
|
2213
|
+
let button;
|
|
2214
|
+
|
|
2215
|
+
if (config.type === 'action') {
|
|
2216
|
+
button = createActionButton(config.text, config.actionFunction, config.icon, config.optionsConfig, config.optionId);
|
|
2217
|
+
} else if (config.type === 'toggle') {
|
|
2218
|
+
button = createToggleButton(
|
|
2219
|
+
config.text,
|
|
2220
|
+
config.key,
|
|
2221
|
+
config.className,
|
|
2222
|
+
config.target || document.body,
|
|
2223
|
+
config.customToggleFunction,
|
|
2224
|
+
config.icon,
|
|
2225
|
+
config.requiresFeature,
|
|
2226
|
+
config.optionId
|
|
2227
|
+
);
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
if (button) {
|
|
2231
|
+
optionsGrid.appendChild(button);
|
|
2232
|
+
}
|
|
2233
|
+
});
|
|
2234
|
+
|
|
2235
|
+
// Add grid to content
|
|
2236
|
+
content.appendChild(optionsGrid);
|
|
2237
|
+
|
|
2238
|
+
// Add content to menu
|
|
2239
|
+
menu.appendChild(content);
|
|
2240
|
+
|
|
2241
|
+
shadowRoot.appendChild(menu);
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
// Update menu language without recreating everything
|
|
2245
|
+
function updateMenuLanguage() {
|
|
2246
|
+
const menu = shadowRoot.getElementById('snn-accessibility-menu');
|
|
2247
|
+
if (!menu) return;
|
|
1328
2248
|
|
|
1329
|
-
|
|
1330
|
-
options.forEach((option) => {
|
|
1331
|
-
if (option.enabled) {
|
|
1332
|
-
const button = createToggleButton(
|
|
1333
|
-
option.text,
|
|
1334
|
-
option.key,
|
|
1335
|
-
option.className,
|
|
1336
|
-
option.target,
|
|
1337
|
-
option.customToggleFunction,
|
|
1338
|
-
option.icon,
|
|
1339
|
-
option.requiresFeature
|
|
1340
|
-
);
|
|
1341
|
-
optionsGrid.appendChild(button);
|
|
1342
|
-
}
|
|
1343
|
-
});
|
|
2249
|
+
const wasOpen = menu.style.display === 'block';
|
|
1344
2250
|
|
|
1345
|
-
//
|
|
1346
|
-
|
|
1347
|
-
const fontButton = createActionButton(WIDGET_CONFIG.lang.fontSelection, handleFontSelection, icons.fontSelection);
|
|
1348
|
-
optionsGrid.appendChild(fontButton);
|
|
1349
|
-
}
|
|
2251
|
+
// Remove old menu
|
|
2252
|
+
menu.remove();
|
|
1350
2253
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
2254
|
+
// Clear cache
|
|
2255
|
+
menuCache.menu = null;
|
|
2256
|
+
menuCache.closeButton = null;
|
|
2257
|
+
keyboardCache.focusableElements = null;
|
|
1355
2258
|
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
optionsGrid.appendChild(textAlignButton);
|
|
1359
|
-
}
|
|
2259
|
+
// Recreate menu
|
|
2260
|
+
createAccessibilityMenu();
|
|
1360
2261
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
2262
|
+
// Update button aria-label
|
|
2263
|
+
const mainButton = shadowRoot.getElementById('snn-accessibility-button');
|
|
2264
|
+
if (mainButton) {
|
|
2265
|
+
mainButton.setAttribute('aria-label', getTranslation('accessibilityMenu'));
|
|
1364
2266
|
}
|
|
1365
2267
|
|
|
1366
|
-
if
|
|
1367
|
-
|
|
1368
|
-
|
|
2268
|
+
// Reopen if it was open
|
|
2269
|
+
if (wasOpen) {
|
|
2270
|
+
menuCache.init();
|
|
2271
|
+
openMenu();
|
|
1369
2272
|
}
|
|
1370
|
-
|
|
1371
|
-
// Add grid to content
|
|
1372
|
-
content.appendChild(optionsGrid);
|
|
1373
|
-
|
|
1374
|
-
// Add content to menu
|
|
1375
|
-
menu.appendChild(content);
|
|
1376
|
-
|
|
1377
|
-
document.body.appendChild(menu);
|
|
1378
2273
|
}
|
|
1379
2274
|
|
|
1380
2275
|
// ===========================================
|
|
@@ -1386,9 +2281,9 @@ const menuCache = {
|
|
|
1386
2281
|
menu: null,
|
|
1387
2282
|
button: null,
|
|
1388
2283
|
closeButton: null,
|
|
1389
|
-
init: function() {
|
|
1390
|
-
this.menu =
|
|
1391
|
-
this.button =
|
|
2284
|
+
init: function () {
|
|
2285
|
+
this.menu = shadowRoot.getElementById('snn-accessibility-menu');
|
|
2286
|
+
this.button = shadowRoot.getElementById('snn-accessibility-button');
|
|
1392
2287
|
this.closeButton = this.menu?.querySelector('.snn-close');
|
|
1393
2288
|
}
|
|
1394
2289
|
};
|
|
@@ -1397,7 +2292,7 @@ const menuCache = {
|
|
|
1397
2292
|
function toggleMenu() {
|
|
1398
2293
|
if (!menuCache.menu) menuCache.init();
|
|
1399
2294
|
const isOpen = menuCache.menu.style.display === 'block';
|
|
1400
|
-
|
|
2295
|
+
|
|
1401
2296
|
if (isOpen) {
|
|
1402
2297
|
closeMenu();
|
|
1403
2298
|
} else {
|
|
@@ -1409,11 +2304,15 @@ function openMenu() {
|
|
|
1409
2304
|
if (!menuCache.menu) menuCache.init();
|
|
1410
2305
|
menuCache.menu.style.display = 'block';
|
|
1411
2306
|
menuCache.menu.setAttribute('aria-hidden', 'false');
|
|
1412
|
-
|
|
1413
|
-
|
|
2307
|
+
|
|
2308
|
+
// UPDATED: Now focuses on the first tool button instead of the Close button
|
|
2309
|
+
const firstOption = menuCache.menu.querySelector('.snn-accessibility-option');
|
|
2310
|
+
if (firstOption) {
|
|
2311
|
+
firstOption.focus();
|
|
2312
|
+
} else if (menuCache.closeButton) {
|
|
1414
2313
|
menuCache.closeButton.focus();
|
|
1415
2314
|
}
|
|
1416
|
-
|
|
2315
|
+
|
|
1417
2316
|
// Add keyboard navigation
|
|
1418
2317
|
document.addEventListener('keydown', handleMenuKeyboard);
|
|
1419
2318
|
}
|
|
@@ -1422,11 +2321,11 @@ function closeMenu() {
|
|
|
1422
2321
|
if (!menuCache.menu) menuCache.init();
|
|
1423
2322
|
menuCache.menu.style.display = 'none';
|
|
1424
2323
|
menuCache.menu.setAttribute('aria-hidden', 'true');
|
|
1425
|
-
|
|
2324
|
+
|
|
1426
2325
|
if (menuCache.button) {
|
|
1427
2326
|
menuCache.button.focus();
|
|
1428
2327
|
}
|
|
1429
|
-
|
|
2328
|
+
|
|
1430
2329
|
// Remove keyboard navigation
|
|
1431
2330
|
document.removeEventListener('keydown', handleMenuKeyboard);
|
|
1432
2331
|
}
|
|
@@ -1435,13 +2334,13 @@ function closeMenu() {
|
|
|
1435
2334
|
let keyboardCache = {
|
|
1436
2335
|
focusableElements: null,
|
|
1437
2336
|
lastUpdate: 0,
|
|
1438
|
-
getFocusableElements: function() {
|
|
2337
|
+
getFocusableElements: function () {
|
|
1439
2338
|
const now = Date.now();
|
|
1440
2339
|
if (!this.focusableElements || now - this.lastUpdate > 1000) {
|
|
1441
2340
|
if (menuCache.menu) {
|
|
1442
2341
|
this.focusableElements = {
|
|
1443
2342
|
all: menuCache.menu.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),
|
|
1444
|
-
options: Array.from(menuCache.menu.querySelectorAll('.snn-accessibility-option, .snn-close'))
|
|
2343
|
+
options: Array.from(menuCache.menu.querySelectorAll('.snn-accessibility-option, .snn-close, .snn-reset-button'))
|
|
1445
2344
|
};
|
|
1446
2345
|
this.lastUpdate = now;
|
|
1447
2346
|
}
|
|
@@ -1452,20 +2351,20 @@ let keyboardCache = {
|
|
|
1452
2351
|
|
|
1453
2352
|
function handleMenuKeyboard(e) {
|
|
1454
2353
|
if (!menuCache.menu || menuCache.menu.style.display !== 'block') return;
|
|
1455
|
-
|
|
2354
|
+
|
|
1456
2355
|
if (e.key === 'Escape') {
|
|
1457
2356
|
e.preventDefault();
|
|
1458
2357
|
closeMenu();
|
|
1459
2358
|
return;
|
|
1460
2359
|
}
|
|
1461
|
-
|
|
2360
|
+
|
|
1462
2361
|
const elements = keyboardCache.getFocusableElements();
|
|
1463
2362
|
if (!elements) return;
|
|
1464
|
-
|
|
2363
|
+
|
|
1465
2364
|
if (e.key === 'Tab') {
|
|
1466
2365
|
const firstElement = elements.all[0];
|
|
1467
2366
|
const lastElement = elements.all[elements.all.length - 1];
|
|
1468
|
-
|
|
2367
|
+
|
|
1469
2368
|
if (e.shiftKey) {
|
|
1470
2369
|
if (document.activeElement === firstElement) {
|
|
1471
2370
|
e.preventDefault();
|
|
@@ -1478,18 +2377,18 @@ function handleMenuKeyboard(e) {
|
|
|
1478
2377
|
}
|
|
1479
2378
|
}
|
|
1480
2379
|
}
|
|
1481
|
-
|
|
2380
|
+
|
|
1482
2381
|
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
1483
2382
|
e.preventDefault();
|
|
1484
|
-
const currentIndex = elements.options.indexOf(
|
|
2383
|
+
const currentIndex = elements.options.indexOf(shadowRoot.activeElement);
|
|
1485
2384
|
let nextIndex;
|
|
1486
|
-
|
|
2385
|
+
|
|
1487
2386
|
if (e.key === 'ArrowDown') {
|
|
1488
2387
|
nextIndex = currentIndex === elements.options.length - 1 ? 0 : currentIndex + 1;
|
|
1489
2388
|
} else {
|
|
1490
2389
|
nextIndex = currentIndex === 0 ? elements.options.length - 1 : currentIndex - 1;
|
|
1491
2390
|
}
|
|
1492
|
-
|
|
2391
|
+
|
|
1493
2392
|
elements.options[nextIndex].focus();
|
|
1494
2393
|
}
|
|
1495
2394
|
}
|
|
@@ -1500,8 +2399,16 @@ function handleMenuKeyboard(e) {
|
|
|
1500
2399
|
|
|
1501
2400
|
// Initialize the widget
|
|
1502
2401
|
function initAccessibilityWidget() {
|
|
1503
|
-
|
|
2402
|
+
// Create shadow DOM first
|
|
2403
|
+
createShadowContainer();
|
|
2404
|
+
|
|
2405
|
+
// Inject page styles (for accessibility features)
|
|
2406
|
+
injectPageStyles();
|
|
2407
|
+
|
|
2408
|
+
// Apply saved settings
|
|
1504
2409
|
applySettings();
|
|
2410
|
+
|
|
2411
|
+
// Create widget UI inside shadow DOM
|
|
1505
2412
|
createAccessibilityButton();
|
|
1506
2413
|
createAccessibilityMenu();
|
|
1507
2414
|
}
|
|
@@ -1515,103 +2422,4 @@ if (document.readyState === 'loading') {
|
|
|
1515
2422
|
document.addEventListener('DOMContentLoaded', initAccessibilityWidget);
|
|
1516
2423
|
} else {
|
|
1517
2424
|
initAccessibilityWidget();
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
/*
|
|
1521
|
-
===========================================
|
|
1522
|
-
WIDGET FEATURES SUMMARY:
|
|
1523
|
-
|
|
1524
|
-
Core Features:
|
|
1525
|
-
- High contrast mode
|
|
1526
|
-
- Text size adjustment
|
|
1527
|
-
- Text spacing modification
|
|
1528
|
-
- Animation pausing
|
|
1529
|
-
- Image hiding
|
|
1530
|
-
- Dyslexia-friendly font
|
|
1531
|
-
- Cursor size adjustment
|
|
1532
|
-
- Line height adjustment
|
|
1533
|
-
- Text alignment
|
|
1534
|
-
|
|
1535
|
-
Advanced Features:
|
|
1536
|
-
- Screen reader with speech synthesis
|
|
1537
|
-
- Voice control with speech recognition
|
|
1538
|
-
- Reading mode
|
|
1539
|
-
- Enhanced focus indicators
|
|
1540
|
-
- Reduced motion mode
|
|
1541
|
-
- Font selection (Arial, Times, Verdana)
|
|
1542
|
-
- Color blindness filters (Protanopia, Deuteranopia, Tritanopia, Grayscale)
|
|
1543
|
-
|
|
1544
|
-
Technical Features:
|
|
1545
|
-
- Persistent settings via localStorage
|
|
1546
|
-
- Full keyboard navigation
|
|
1547
|
-
- ARIA compliance
|
|
1548
|
-
- Error handling for browser compatibility
|
|
1549
|
-
- Performance optimization with DOM caching
|
|
1550
|
-
- Single file deployment
|
|
1551
|
-
|
|
1552
|
-
Configuration Options:
|
|
1553
|
-
- Customizable language/text strings
|
|
1554
|
-
- Customizable voice command strings
|
|
1555
|
-
- Configurable grid layout (columns and gap)
|
|
1556
|
-
- All widget styling and positioning options
|
|
1557
|
-
- Feature enable/disable toggles
|
|
1558
|
-
|
|
1559
|
-
===========================================
|
|
1560
|
-
|
|
1561
|
-
CONFIGURATION EXAMPLE:
|
|
1562
|
-
|
|
1563
|
-
To customize the widget, define window.ACCESSIBILITY_WIDGET_CONFIG
|
|
1564
|
-
before loading the widget script:
|
|
1565
|
-
|
|
1566
|
-
<script>
|
|
1567
|
-
window.ACCESSIBILITY_WIDGET_CONFIG = {
|
|
1568
|
-
// Customize language/text strings
|
|
1569
|
-
lang: {
|
|
1570
|
-
accessibilityMenu: 'Menu de Accesibilidad',
|
|
1571
|
-
screenReader: 'Lector de Pantalla',
|
|
1572
|
-
biggerText: 'Texto Más Grande',
|
|
1573
|
-
highContrast: 'Alto Contraste',
|
|
1574
|
-
// ... customize any text string
|
|
1575
|
-
},
|
|
1576
|
-
|
|
1577
|
-
// Customize voice commands for different languages
|
|
1578
|
-
voiceCommands: {
|
|
1579
|
-
showMenu: ['mostrar menú', 'abrir menú', 'menú de accesibilidad'],
|
|
1580
|
-
highContrast: ['alto contraste'],
|
|
1581
|
-
biggerText: ['texto más grande', 'texto grande'],
|
|
1582
|
-
textSpacing: ['espaciado de texto'],
|
|
1583
|
-
pauseAnimations: ['pausar animaciones', 'detener animaciones'],
|
|
1584
|
-
hideImages: ['ocultar imágenes'],
|
|
1585
|
-
dyslexiaFont: ['fuente para dislexia', 'fuente dislexia'],
|
|
1586
|
-
biggerCursor: ['cursor más grande', 'cursor grande'],
|
|
1587
|
-
lineHeight: ['altura de línea'],
|
|
1588
|
-
textAlign: ['alinear texto', 'alineación de texto'],
|
|
1589
|
-
screenReader: ['lector de pantalla'],
|
|
1590
|
-
voiceControl: ['comando de voz', 'control de voz'],
|
|
1591
|
-
resetAll: ['reiniciar todo', 'resetear todo']
|
|
1592
|
-
},
|
|
1593
|
-
|
|
1594
|
-
// Customize grid layout
|
|
1595
|
-
gridLayout: {
|
|
1596
|
-
columns: '1fr 1fr 1fr', // 3-column layout
|
|
1597
|
-
gap: '15px' // Custom gap between buttons
|
|
1598
|
-
},
|
|
1599
|
-
|
|
1600
|
-
// Other customizable options
|
|
1601
|
-
widgetWidth: '500px',
|
|
1602
|
-
widgetPosition: {
|
|
1603
|
-
side: 'left',
|
|
1604
|
-
left: '30px',
|
|
1605
|
-
bottom: '30px'
|
|
1606
|
-
},
|
|
1607
|
-
colors: {
|
|
1608
|
-
primary: '#2196F3',
|
|
1609
|
-
primaryHover: '#1976D2',
|
|
1610
|
-
// ... customize any color
|
|
1611
|
-
}
|
|
1612
|
-
};
|
|
1613
|
-
</script>
|
|
1614
|
-
<script src="widget.js"></script>
|
|
1615
|
-
|
|
1616
|
-
===========================================
|
|
1617
|
-
*/
|
|
2425
|
+
}
|