content/static: update accordion controller init

Updates accordion controller to select active panel
on init. Opens doc panel on init for pages without
readme.

Change-Id: I4c0d190217bc109f322b6f5a09fff930bc7ac3a3
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/259801
Trust: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/content/static/html/helpers/_unit_outline.tmpl b/content/static/html/helpers/_unit_outline.tmpl
index 00f53ec..419b1b3 100644
--- a/content/static/html/helpers/_unit_outline.tmpl
+++ b/content/static/html/helpers/_unit_outline.tmpl
@@ -13,19 +13,19 @@
     </div>
     {{if .Readme.String}}
       <a href="?readme=expanded#readme-top" class="UnitOutline-accordion js-accordionTrigger js-readmeExpand"
-          aria-expanded="true" aria-controls="readme-panel" id="readme-accordion">
+          role="button" aria-expanded="false" aria-controls="readme-panel" id="readme-accordion">
         README
       </a>
       <div class="UnitOutline-panel js-accordionPanel"
-          id="readme-panel" role="region" aria-labelledby="readme-accordion" aria-hidden="false"></div>
+          id="readme-panel" role="region" aria-labelledby="readme-accordion" aria-hidden="true"></div>
     {{end}}
     {{if (or .DocOutline.String .Unit.IsPackage)}}
       <a class="UnitOutline-accordion  js-accordionTrigger" href="#doc-top"
-          aria-expanded="false" aria-controls="outline-panel" id="outline-accordion">
+          role="button" aria-expanded="false" aria-controls="outline-panel" id="outline-accordion">
         Documentation
       </a>
       <div class="UnitOutline-panel js-accordionPanel"
-          id="outline-panel" role="region" aria-labelledby="ouline-accordion" aria-hidden="true">
+          id="outline-panel" role="region" aria-labelledby="outline-accordion" aria-hidden="true">
         <div class="Documentation">
           {{.DocOutline}}
         </div>
@@ -33,7 +33,7 @@
     {{end}}
     {{if .SourceFiles}}
       <a class="UnitOutline-accordion js-accordionTrigger" href="#files-top"
-          aria-expanded="false" aria-controls="files-panel" id="files-accordion">
+          role="button" aria-expanded="false" aria-controls="files-panel" id="files-accordion">
         Source Files
       </a>
       <div class="UnitOutline-panel js-accordionPanel"
@@ -41,7 +41,7 @@
     {{end}}
     {{if (or .Subdirectories .NestedModules)}}
       <a class="UnitOutline-accordion js-accordionTrigger" href="#directories-top"
-          aria-expanded="false" aria-controls="directories-panel" id="directories-accordion">
+          role="button" aria-expanded="false" aria-controls="directories-panel" id="directories-accordion">
         Directories
       </a>
       <div class="UnitOutline-panel js-accordionPanel"
diff --git a/content/static/js/accordion.js b/content/static/js/accordion.js
index 62b640c..4cdb6c0 100644
--- a/content/static/js/accordion.js
+++ b/content/static/js/accordion.js
@@ -5,6 +5,29 @@
  * license that can be found in the LICENSE file.
  */
 
+/**
+ * Controller for an accordion element. This class will add event
+ * listeners to close and open the panels of an accordion. When
+ * initialized it will select the active panel based on the URL
+ * hash for the requested page.
+ *
+ * Accordions must have the following structure:
+ *
+ *  <div class="js-accordion">
+ *    <a role="button" class="js-accordionTrigger" href="#panel-1" aria-expanded="false" aria-controls="first-panel" id="first-accordion">
+ *      Title
+ *    </a>
+ *    <div class="js-accordionPanel" id="first-panel" role="region" aria-labelledby="first-accordion" aria-hidden="true">
+ *      Panel Content
+ *    </div>
+ *    <a role="button" class="js-accordionTrigger" href="#panel-2" aria-expanded="false" aria-controls="second-panel" id="second-accordion">
+ *      Title
+ *    </a>
+ *    <div class="js-accordionPanel" id="second-panel" role="region" aria-labelledby="second-accordion" aria-hidden="true">
+ *      Panel Content
+ *    </div>
+ *  </div>
+ */
 export class AccordionController {
   constructor(accordion) {
     this.accordion = accordion;
@@ -25,21 +48,29 @@
         this.handleKeyPress(e);
       }
     });
+
+    const activeHash = document.querySelector(`a[href=${JSON.stringify(window.location.hash)}]`);
+    const initialTrigger =
+      this.triggers.find(
+        trigger => this.getPanel(trigger).contains(activeHash) || trigger.contains(activeHash)
+      ) || this.activeTrigger;
+
+    this.select(initialTrigger);
+  }
+
+  getPanel(trigger) {
+    return document.getElementById(trigger.getAttribute('aria-controls'));
   }
 
   select(target) {
     const isExpanded = target.getAttribute('aria-expanded') === 'true';
     if (!isExpanded) {
       target.setAttribute('aria-expanded', 'true');
-      document
-        .getElementById(target.getAttribute('aria-controls'))
-        .setAttribute('aria-hidden', 'false');
+      this.getPanel(target).setAttribute('aria-hidden', 'false');
     }
     if (this.activeTrigger !== target) {
       this.activeTrigger.setAttribute('aria-expanded', 'false');
-      document
-        .getElementById(this.activeTrigger.getAttribute('aria-controls'))
-        .setAttribute('aria-hidden', 'true');
+      this.getPanel(this.activeTrigger).setAttribute('aria-hidden', 'true');
     }
     this.activeTrigger = target;
   }
@@ -47,6 +78,7 @@
   handleKeyPress(e) {
     const target = e.target;
     const key = e.which;
+    const SPACE = 32;
     const PAGE_UP = 33;
     const PAGE_DOWN = 34;
     const END = 35;
@@ -73,6 +105,8 @@
         this.triggers[0].focus();
         e.preventDefault();
         break;
+      case SPACE:
+        this.select(target);
 
       default:
         break;
diff --git a/content/static/js/unit.js b/content/static/js/unit.js
index 9ef592a..ee068ae 100644
--- a/content/static/js/unit.js
+++ b/content/static/js/unit.js
@@ -8,18 +8,11 @@
 import { AccordionController } from './accordion.js';
 
 /**
- * Instantiates accordian controller for the left sidebar and sets
- * the panel for the current location hash as active.
+ * Instantiates accordion controller for the left sidebar.
  */
 const accordion = document.querySelector('.js-accordion');
 if (accordion) {
-  const accordionCtlr = new AccordionController(accordion);
-  const activePanel =
-    window.location.hash &&
-    document.querySelector(`a[href=${JSON.stringify(window.location.hash)}]`);
-  if (activePanel) {
-    accordionCtlr.select(activePanel);
-  }
+  new AccordionController(accordion);
 }
 
 /**