addNavButton(containerName) {
    const navButtons = document.getElementById('nav-button-container');
    const contents = document.getElementById('contents');
    const button = document.getElementById('nav-button-' + containerName);

    // TODO: Switch to using MDL tabs.

    // Determine if the element is selected.
    const params = this.getParams_();
    let selected =
        params.get('panel') == encodeURI(button.getAttribute('tab-identifier'));
    if (selected) {
      // Re-apply any saved data from hash.
      const hashValues = params.get('panelData');
      if (hashValues) {
        button.setAttribute('tab-hash', hashValues);
      }
    } else if (!params.has('panel')) {
      // Check if it's selected by default.
      selected = button.getAttribute('defaultselected') != null;
    }

    // Create the div for this nav button's container within the contents.
    const container = document.createElement('div');
    this.hideElement_(container);
    contents.appendChild(container);

    // Add a click listener to display this container, and hide the others.
    const switchPage = () => {
      // This element should be the selected one.
      for (const child of navButtons.childNodes) {
        if (child.nodeType == Node.ELEMENT_NODE) {
          goog.asserts.assert(child instanceof Element, 'Wrong node type!');
          child.classList.remove('mdl-button--accent');
        }
      }
      for (const child of contents.childNodes) {
        if (child.nodeType == Node.ELEMENT_NODE) {
          goog.asserts.assert(child instanceof Element, 'Wrong node type!');
          this.hideElement_(child);
        }
      }
      button.classList.add('mdl-button--accent');
      this.showElement_(container);
      this.remakeHash();

      // Dispatch an event so that a page can load any deferred content.
      this.dispatchEventWithName_('shaka-main-page-changed');

      // Scroll so that the top of the tab is in view.
      container.scrollIntoView({behavior: 'smooth', block: 'start'});
    };

    button.addEventListener('click', switchPage);
    if (selected) {
      // Defer this call to switchPage until the container is fully set up.
      Promise.resolve().then(switchPage);
    }

    return {
      container: /** @type {!HTMLDivElement} */ (container),
      button: /** @type {!HTMLButtonElement} */ (button),
    };
  }
Sets up a nav button, and an associated tab.
This method is meant to be called by the various tabs, as part of their
setup process.
@param {string} containerName Used to determine the id of the button this
  is looking for.  Also used as the className of the container, for CSS.
@return {{
  container: !HTMLDivElement,
  button: !HTMLButtonElement,
}} The container for the tab, and the button element that activates it.