Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 (function(){ | 1 (function(){ |
2 document.addEventListener("DOMContentLoaded", function() | 2 document.addEventListener("DOMContentLoaded", function() |
3 { | 3 { |
4 | 4 |
5 // Change html class name from "no-js" to "js" | 5 // Change html class name from "no-js" to "js" |
6 document.documentElement.className = "js"; | 6 document.documentElement.className = "js"; |
7 | 7 |
8 // Toggle Navbar Collapse | 8 // Toggle Navbar Collapse |
9 function toggleNavbarCollapse() | 9 function toggleNavbarCollapse() |
10 { | 10 { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 var customSelectEls = document.getElementsByClassName('custom-select-selecte d'); | 42 var customSelectEls = document.getElementsByClassName('custom-select-selecte d'); |
43 for (var i = 0; i < customSelectEls.length; i++) | 43 for (var i = 0; i < customSelectEls.length; i++) |
44 { | 44 { |
45 customSelectEls[i] | 45 customSelectEls[i] |
46 .addEventListener("click", onClickCustomSelect, false); | 46 .addEventListener("click", onClickCustomSelect, false); |
47 customSelectEls[i] | 47 customSelectEls[i] |
48 .nextElementSibling | 48 .nextElementSibling |
49 .setAttribute("aria-hidden", "true"); | 49 .setAttribute("aria-hidden", "true"); |
50 } | 50 } |
51 | 51 |
52 | |
53 // Accordion menu | 52 // Accordion menu |
juliandoucette
2017/09/20 14:19:38
NIT: I prefer an OO approach (an Accordion Functio
ire
2017/09/25 11:25:18
Done.
| |
54 | 53 |
55 function setupAccordionMenu(accordionEl) | 54 function Accordion(accordion) |
juliandoucette
2017/09/20 14:19:37
Suggest: "accordion"
"No hungarian notation, no s
ire
2017/09/25 11:25:18
Done. Does this apply to the "accordionButtons"? S
juliandoucette
2017/09/26 18:57:05
I don't think so. But it's hard to explain why :D
ire
2017/09/28 14:48:52
Haha okay. I don't think it applies either, but I
| |
56 { | 55 { |
57 var accordionButtons = accordionEl.getElementsByClassName('accordion-toggl e-button'); | 56 this.accordion = accordion; |
58 | 57 |
59 for ( var i = 0; i < accordionButtons.length; i++ ) | 58 var accordionButtons = this.accordion.getElementsByClassName('accordion-to ggle-button'); |
juliandoucette
2017/09/20 14:19:38
NIT: I think that we don't put spaces inside these
ire
2017/09/25 11:25:17
Done.
| |
59 for (var i = 0; i < accordionButtons.length; i++) | |
60 { | 60 { |
61 accordionButtons[i] | 61 // Close all sections except the first |
juliandoucette
2017/09/20 14:19:38
Suggest: Initialize state before adding event list
ire
2017/09/25 11:25:17
I don't have an opinion either way. Done.
juliandoucette
2017/09/26 18:57:06
You didn't do this?
ire
2017/09/28 14:48:52
Oops, missed this. Done now (I hope :p)
| |
62 .addEventListener("click", toggleAccordionSection, false); | 62 if (i !== 0) |
63 accordionButtons[i] | |
64 .addEventListener("keydown", navigateAccordionHeadings, false); | |
65 | |
66 // Close all sections besides the first | |
juliandoucette
2017/09/20 14:19:37
Suggest: "except" instead of "besides" :D
"beside
ire
2017/09/25 11:25:18
I've been using "besides" wrong all my life :O hah
| |
67 if ( i !== 0 ) | |
68 { | 63 { |
69 accordionButtons[i].setAttribute("aria-expanded", "false"); | 64 accordionButtons[i].setAttribute("aria-expanded", "false"); |
70 accordionButtons[i].setAttribute("aria-disabled", "false"); | |
juliandoucette
2017/09/20 14:19:38
I think that aria-disabled is only appropriate whe
ire
2017/09/25 11:25:17
Yup, see my comment above.
| |
71 document | 65 document |
72 .getElementById( accordionButtons[i].getAttribute("aria-controls") ) | 66 .getElementById( accordionButtons[i].getAttribute("aria-controls") ) |
juliandoucette
2017/10/09 21:18:16
NIT: Extra whitespace inside brackets
(The same a
| |
73 .setAttribute("hidden", "true"); | 67 .setAttribute("hidden", "true"); |
74 } | 68 } |
75 } | 69 } |
70 | |
71 this.accordion | |
72 .addEventListener("click", this._onClick.bind(this), false); | |
73 this.accordion | |
74 .addEventListener("keydown", this._onKeyDown.bind(this), false); | |
76 } | 75 } |
77 | 76 |
78 function toggleAccordionSection() | 77 Accordion.prototype.toggleSection = function(clickedButton) |
juliandoucette
2017/09/20 14:19:38
NIT: This function name sounds functional, but it'
ire
2017/09/25 11:25:17
I generally prefer explanatory names, particularly
juliandoucette
2017/09/26 18:57:05
I agree. But I think that the context is misleadin
ire
2017/09/28 14:48:52
Yes, I created the issue #5652 to refactor this an
| |
79 { | 78 { |
80 // Hide currently expanded section | 79 // Hide currently expanded section |
81 var accordion = this.parentElement.parentElement; | 80 var expandedButton = this.accordion.querySelector("button[aria-expanded='t rue']"); |
82 var expandedButton = accordion.querySelector("button[aria-expanded='true'] "); | 81 if (expandedButton) |
83 if ( expandedButton ) | |
juliandoucette
2017/09/20 14:19:38
NIT/Suggest: Make it clearer that you are checking
ire
2017/09/25 11:25:18
Doesn't the name "expandedButton" do that?
juliandoucette
2017/09/26 18:57:05
Yes? :/ (I have no idea what I was thinking :D)
| |
84 { | 82 { |
85 expandedButton.setAttribute("aria-expanded", "false"); | 83 expandedButton.setAttribute("aria-expanded", "false"); |
86 expandedButton.setAttribute("aria-disabled", "false"); | |
87 document | 84 document |
88 .getElementById( expandedButton.getAttribute("aria-controls") ) | 85 .getElementById( expandedButton.getAttribute("aria-controls") ) |
89 .setAttribute("hidden", "true"); | 86 .setAttribute("hidden", "true"); |
90 } | 87 } |
91 | 88 |
92 if ( expandedButton === this ) return; | 89 // If currently expanded section is clicked |
juliandoucette
2017/09/20 14:19:37
NIT/Suggest: Make it clearer that you are handling
ire
2017/09/25 11:25:18
Done.
| |
90 if (expandedButton === clickedButton) return; | |
93 | 91 |
94 // Expand new section | 92 // Expand new section |
95 this.setAttribute("aria-expanded", "true"); | 93 clickedButton.setAttribute("aria-expanded", "true"); |
96 this.setAttribute("aria-disabled", "true"); | |
97 document | 94 document |
98 .getElementById( this.getAttribute("aria-controls") ) | 95 .getElementById( clickedButton.getAttribute("aria-controls") ) |
99 .removeAttribute("hidden"); | 96 .removeAttribute("hidden"); |
juliandoucette
2017/09/20 14:19:38
NIT/Suggest: .focus() too? So that you could click
ire
2017/09/25 11:25:17
Why focus an element that isn't typically focusabl
juliandoucette
2017/09/26 18:57:05
I think that I was confused. What I was really sug
ire
2017/09/28 14:48:52
Now I think I'm confused :/
But currently, you ca
| |
100 } | 97 } |
101 | 98 |
102 function navigateAccordionHeadings(e) | 99 Accordion.prototype.focusNextSection = function() |
juliandoucette
2017/09/20 14:19:37
NIT/Suggest: "event"
Julian Doucette: Does our co
ire
2017/09/25 11:25:17
Done.
| |
103 { | 100 { |
104 if ( e.keyCode !== 38 && e.keyCode !== 40 ) return; | 101 var currentFocus = document.activeElement; |
juliandoucette
2017/09/20 14:19:38
NIT/Suggest: Prefer event.key and fall back to eve
ire
2017/09/25 11:25:17
Done.
| |
102 var nextheading = currentFocus.parentElement.nextElementSibling.nextElemen tSibling; | |
105 | 103 |
106 var accordion = this.parentElement.parentElement; | 104 if (nextheading) |
107 | |
108 // Direction == up | |
109 if ( e.keyCode == 38 ) | |
juliandoucette
2017/09/20 14:19:38
NIT/Suggest: Name keycodes e.g. var KEY_UP = 38.
ire
2017/09/25 11:25:18
Done.
| |
110 { | 105 { |
111 var prevEl = this.parentElement.previousElementSibling; | 106 nextheading // .accordion-heading |
112 if ( prevEl ) | 107 .firstElementChild // .accordion-toggle-button |
juliandoucette
2017/09/20 14:19:38
NIT/Suggest: Make it clearer that you are checking
ire
2017/09/25 11:25:18
This would mean I cannot use the same variable nam
juliandoucette
2017/09/26 18:57:05
Acknowledged.
| |
113 { | 108 .focus(); |
114 prevEl // .accordion-body | |
115 .previousElementSibling // .accordion-heading | |
116 .firstElementChild // .accordion-toggle-button | |
117 .focus(); | |
118 } | |
119 else | |
120 { | |
121 accordion | |
122 .lastElementChild // .accordion-body | |
123 .previousElementSibling // .accordion-heading | |
124 .firstElementChild // .accordion-toggle-button | |
125 .focus(); | |
126 } | |
127 } | 109 } |
128 | 110 else |
129 // Direction == down | |
130 else if ( e.keyCode == 40 ) | |
131 { | 111 { |
132 var nextheading = this.parentElement.nextElementSibling.nextElementSibli ng; | 112 this.accordion |
133 if ( nextheading ) | 113 .firstElementChild // .accordion-heading |
134 { | 114 .firstElementChild // .accordion-toggle-button |
135 nextheading // .accordion-heading | 115 .focus(); |
136 .firstElementChild // .accordion-toggle-button | |
137 .focus(); | |
138 } | |
139 else | |
140 { | |
141 accordion | |
142 .firstElementChild // .accordion-heading | |
143 .firstElementChild // .accordion-toggle-button | |
144 .focus(); | |
145 } | |
146 } | 116 } |
147 } | 117 } |
148 | 118 |
149 var accordionMenus = document.getElementsByClassName('accordion'); | 119 Accordion.prototype.focusPrevSection = function() |
150 for (var i = 0; i < accordionMenus.length; i++) | |
151 { | 120 { |
152 setupAccordionMenu( accordionMenus[i] ); | 121 var currentFocus = document.activeElement; |
122 var prevAccordionBody = currentFocus.parentElement.previousElementSibling; | |
123 | |
124 if (prevAccordionBody) | |
125 { | |
126 prevAccordionBody // .accordion-body | |
127 .previousElementSibling // .accordion-heading | |
128 .firstElementChild // .accordion-toggle-button | |
129 .focus(); | |
130 } | |
131 else | |
132 { | |
133 this.accordion | |
134 .lastElementChild // .accordion-body | |
135 .previousElementSibling // .accordion-heading | |
136 .firstElementChild // .accordion-toggle-button | |
137 .focus(); | |
138 } | |
139 } | |
140 | |
141 Accordion.prototype._onKeyDown = function(event) | |
142 { | |
143 if (!event.target.classList.contains("accordion-toggle-button")) return; | |
144 | |
145 if (event.key == "ArrowUp" || event.keyCode == 38) | |
146 { | |
147 this.focusPrevSection(); | |
148 } | |
149 else if (event.key == "ArrowDown" || event.keyCode == 40) | |
150 { | |
151 this.focusNextSection(); | |
152 } | |
153 } | |
154 | |
155 Accordion.prototype._onClick = function(event) | |
156 { | |
157 if (!event.target.classList.contains("accordion-toggle-button")) return; | |
158 | |
159 this.toggleSection(event.target); | |
160 } | |
161 | |
162 var accordions = document.getElementsByClassName('accordion'); | |
163 for (var i = 0; i < accordions.length; i++) | |
164 { | |
165 new Accordion(accordions[i]); | |
153 } | 166 } |
154 | 167 |
155 }, false); | 168 }, false); |
156 }()); | 169 }()); |
LEFT | RIGHT |