-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
194 lines (159 loc) · 4.8 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// add utilities
const util = {
generateID: function ( base ) {
return base + Math.floor(Math.random() * 999);
}
};
(function ( w, doc, undefined ) {
/**
* A11Y ARIA Switch
*
* Author: Scott O'Hara
* Version: 2.0.1
* License: https://github.com/scottaohara/aria-switch-control/blob/main/LICENSE
*/
let ARIAswitchOptions = {
baseID: 'aria_switch',
defaultStateSelector: 'data-switch',
showLabels: 'data-switch-labels',
dataKeepDisabled: 'data-keep-disabled'
};
const ARIAswitch = function ( inst, options ) {
const _options = Object.assign(ARIAswitchOptions, options);
const el = inst;
let elID;
let keepDisabledState;
let initState;
let isCheckbox;
/**
* Initialize the switch instance.
* Create unique IDs and generate
* a markup pattern if necessary.
*/
const init = function () {
elID = el.id || util.generateID(_options.baseID);
keepDisabledState = el.hasAttribute(_options.dataKeepDisabled);
initState = el.getAttribute(_options.defaultStateSelector);
setupBaseWidget()
setupCheckedState();
generateToggleUI();
addEvents();
};
/**
* Setup the baseline semantics of the widget,
* ensuring that switches become/stay enabled/disabled,
* and that only elements that need it get an appropriate
* tabindex attribute.
*/
const setupBaseWidget = function () {
el.setAttribute('role', 'switch');
// did this start off as a link?
if ( el.href ) el.removeAttribute('href');
if ( !keepDisabledState ) {
el.hidden = false;
el.disabled = false;
el.removeAttribute('aria-disabled');
}
if ( el.hasAttribute('aria-disabled') ) {
el.tabIndex = -1;
}
else {
// if not a BUTTON or INPUT since those are focusable
// by default
if ( el.tagName !== 'BUTTON' && el.tagName !== 'INPUT' ) {
el.tabIndex = 0;
}
}
};
/**
* Setup state depending on the type of starter element.
*/
const setupCheckedState = function () {
if ( initState && (el || {}).type !== 'checkbox' ) {
el.setAttribute('aria-checked', 'true');
}
else if ( !initState && (el || {}).type !== 'checkbox' ) {
el.setAttribute('aria-checked', 'false');
}
if ( initState && (el || {}).type === 'checkbox' ) {
el.checked = true;
}
};
/**
* Add click and keypress events to elements
*/
const addEvents = function () {
el.addEventListener('click', toggleState, false);
if ( el.tagName !== 'BUTTON' ) {
el.addEventListener('keypress', keyToggle, false);
}
};
/**
* Generate the element to serve as the toggle
* slider, or whatever version of the UI people
* want to visually create.
*/
const generateToggleUI = function () {
const ui = doc.createElement('span');
const hasLabels = el.hasAttribute(_options.showLabels);
ui.setAttribute('aria-hidden', 'true');
if ( hasLabels ) ui.classList.add('show-labels');
// if a checkbox, append the UI as a sibling.
// otherwise, as a child of the element.
if ( (el || {}).type === 'checkbox' ) {
el.parentNode.appendChild(ui);
}
else {
el.appendChild(ui);
}
};
/**
* Toggle between the on and off state of the switch.
* Ignore switches that are baseline checkboxes. Checkboxes
* can update their checked state natively and do not need
* aria-checked.
*/
const toggleState = function ( e ) {
if ( !el.hasAttribute('aria-disabled') ) {
if ( (el || {}).type !== 'checkbox' ) {
e.preventDefault();
el.setAttribute('aria-checked', el.getAttribute('aria-checked') === 'true' ? 'false' : 'true');
}
}
};
/**
* Handle keyboard events for the switch.
*/
const keyToggle = function ( e ) {
const keyCode = e.keyCode || e.which;
switch ( keyCode ) {
case 32:
case 13:
e.preventDefault();
toggleState(e);
break;
default:
break;
}
/**
* Checkboxes don't allow for Enter key to activate
* by default. However, "switches" do have this
* expectation, especially since they can be announced
* as toggle buttons with some screen reader / browser pairings.
*/
if ( (el || {}).type === 'checkbox' ) {
switch ( keyCode ) {
case 13:
e.preventDefault();
this.checked = this.checked == true ? false : true;
break;
default:
break;
}
}
}
init.call( this );
return this;
}; // ARIAswitch()
w.ARIAswitch = ARIAswitch;
})( window, document );