Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: static/js/main.js

Issue 29548567: Issue 4925 - Create accordion component for Help Center (Closed) Base URL: https://hg.adblockplus.org/help.eyeo.com
Left Patch Set: Rebase Created Sept. 19, 2017, 4:19 p.m.
Right Patch Set: Refactoring Created Sept. 28, 2017, 2:48 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « static/img/svg/arrow-icon-secondary.svg ('k') | static/scss/components/_accordion.scss » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
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 }());
LEFTRIGHT

Powered by Google App Engine
This is Rietveld