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: Add support for navigating between headings with arrow keys Created Sept. 19, 2017, 9:14 a.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 {
11 var navbarCollapseEls = this.parentElement.getElementsByClassName("navbar- collapse"); 11 var navbarCollapseEls = this.parentElement.getElementsByClassName("navbar- collapse");
12 for (var i = 0; i < navbarCollapseEls.length; i++) 12 for (var i = 0; i < navbarCollapseEls.length; i++)
13 { 13 {
14 navbarCollapseEls[i] 14 navbarCollapseEls[i]
15 .classList.toggle("open") 15 .classList.toggle("open")
16 } 16 }
17 } 17 }
18 18
19 var toggleNavbarCollapseEls = document.getElementsByClassName("toggle-navbar -collapse"); 19 var toggleNavbarCollapseEls = document.getElementsByClassName("toggle-navbar -collapse");
20 for (var i = 0; i < toggleNavbarCollapseEls.length; i++) 20 for (var i = 0; i < toggleNavbarCollapseEls.length; i++)
21 { 21 {
22 toggleNavbarCollapseEls[i] 22 toggleNavbarCollapseEls[i]
23 .addEventListener("click", toggleNavbarCollapse, false); 23 .addEventListener("click", toggleNavbarCollapse, false);
24 } 24 }
25 25
26 // Custom Select
27 function onClickCustomSelect()
28 {
29 var options = this.nextElementSibling;
30 if (options.getAttribute("aria-hidden") == "true")
31 {
32 options.removeAttribute("aria-hidden");
33 this.setAttribute("aria-expanded", "true");
34 }
35 else
36 {
37 options.setAttribute("aria-hidden", "true");
38 this.setAttribute("aria-expanded", "false");
39 }
40 }
41
42 var customSelectEls = document.getElementsByClassName('custom-select-selecte d');
43 for (var i = 0; i < customSelectEls.length; i++)
44 {
45 customSelectEls[i]
46 .addEventListener("click", onClickCustomSelect, false);
47 customSelectEls[i]
48 .nextElementSibling
49 .setAttribute("aria-hidden", "true");
50 }
51
26 // Accordion menu 52 // Accordion menu
27 53
28 function setupAccordionMenu(accordionEl) 54 function Accordion(accordion)
29 { 55 {
30 var accordionButtons = accordionEl.getElementsByClassName('accordion-toggl e-button'); 56 this.accordion = accordion;
31 57
32 for ( var i = 0; i < accordionButtons.length; i++ ) 58 var accordionButtons = this.accordion.getElementsByClassName('accordion-to ggle-button');
59 for (var i = 0; i < accordionButtons.length; i++)
33 { 60 {
34 accordionButtons[i] 61 // Close all sections except the first
35 .addEventListener("click", toggleAccordionSection, false); 62 if (i !== 0)
36 accordionButtons[i]
37 .addEventListener("keydown", navigateAccordionHeadings, false);
38
39 // Close all sections besides the first
40 if ( i !== 0 )
41 { 63 {
42 accordionButtons[i].setAttribute("aria-expanded", "false"); 64 accordionButtons[i].setAttribute("aria-expanded", "false");
43 accordionButtons[i].setAttribute("aria-disabled", "false");
44 document 65 document
45 .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
46 .setAttribute("hidden", "true"); 67 .setAttribute("hidden", "true");
47 } 68 }
48 } 69 }
70
71 this.accordion
72 .addEventListener("click", this._onClick.bind(this), false);
73 this.accordion
74 .addEventListener("keydown", this._onKeyDown.bind(this), false);
49 } 75 }
50 76
51 function toggleAccordionSection() 77 Accordion.prototype.toggleSection = function(clickedButton)
52 { 78 {
53 // Hide currently expanded section 79 // Hide currently expanded section
54 var accordion = this.parentElement.parentElement; 80 var expandedButton = this.accordion.querySelector("button[aria-expanded='t rue']");
55 var expandedButton = accordion.querySelector("button[aria-expanded='true'] "); 81 if (expandedButton)
56 if ( expandedButton )
57 { 82 {
58 expandedButton.setAttribute("aria-expanded", "false"); 83 expandedButton.setAttribute("aria-expanded", "false");
59 expandedButton.setAttribute("aria-disabled", "false");
60 document 84 document
61 .getElementById( expandedButton.getAttribute("aria-controls") ) 85 .getElementById( expandedButton.getAttribute("aria-controls") )
62 .setAttribute("hidden", "true"); 86 .setAttribute("hidden", "true");
63 } 87 }
64 88
65 if ( expandedButton === this ) return; 89 // If currently expanded section is clicked
90 if (expandedButton === clickedButton) return;
66 91
67 // Expand new section 92 // Expand new section
68 this.setAttribute("aria-expanded", "true"); 93 clickedButton.setAttribute("aria-expanded", "true");
69 this.setAttribute("aria-disabled", "true");
70 document 94 document
71 .getElementById( this.getAttribute("aria-controls") ) 95 .getElementById( clickedButton.getAttribute("aria-controls") )
72 .removeAttribute("hidden"); 96 .removeAttribute("hidden");
73 } 97 }
74 98
75 function navigateAccordionHeadings(e) 99 Accordion.prototype.focusNextSection = function()
76 { 100 {
77 if ( e.keyCode !== 38 && e.keyCode !== 40 ) return; 101 var currentFocus = document.activeElement;
102 var nextheading = currentFocus.parentElement.nextElementSibling.nextElemen tSibling;
78 103
79 var accordion = this.parentElement.parentElement; 104 if (nextheading)
80
81 // Direction == up
82 if ( e.keyCode == 38 )
83 { 105 {
84 var prevEl = this.parentElement.previousElementSibling; 106 nextheading // .accordion-heading
85 if ( prevEl ) 107 .firstElementChild // .accordion-toggle-button
86 { 108 .focus();
87 prevEl // .accordion-body
88 .previousElementSibling // .accordion-heading
89 .firstElementChild // .accordion-toggle-button
90 .focus();
91 }
92 else
93 {
94 accordion
95 .lastElementChild // .accordion-body
96 .previousElementSibling // .accordion-heading
97 .firstElementChild // .accordion-toggle-button
98 .focus();
99 }
100 } 109 }
101 110 else
102 // Direction == down
103 else if ( e.keyCode == 40 )
104 { 111 {
105 var nextheading = this.parentElement.nextElementSibling.nextElementSibli ng; 112 this.accordion
106 if ( nextheading ) 113 .firstElementChild // .accordion-heading
107 { 114 .firstElementChild // .accordion-toggle-button
108 nextheading // .accordion-heading 115 .focus();
109 .firstElementChild // .accordion-toggle-button
110 .focus();
111 }
112 else
113 {
114 accordion
115 .firstElementChild // .accordion-heading
116 .firstElementChild // .accordion-toggle-button
117 .focus();
118 }
119 } 116 }
120 } 117 }
121 118
122 var accordionMenus = document.getElementsByClassName('accordion'); 119 Accordion.prototype.focusPrevSection = function()
123 for (var i = 0; i < accordionMenus.length; i++)
124 { 120 {
125 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]);
126 } 166 }
127 167
128 }, false); 168 }, false);
129 }()); 169 }());
LEFTRIGHT

Powered by Google App Engine
This is Rietveld