code: function hashchange_(e) {
      if (counterLastMatch > 1) {
        counterLastMatch = 0;
        throw new Error(`Cannot go back to last matched hash ${e.oldURL}`);
      }
      // Look for all router3 elements in order
      Promise.all(slice
        .call(document.querySelectorAll(selClass))
        .map(element => {
          /**
           * link router3 with fragment
           * (This process should be decoupled...)
           */
          return new Promise(resolve => {
            let fragments = slice.call(element.querySelectorAll('.mdl-fragment'));
            if (element.classList.contains('mdl-fragment')) {
              resolve_(element, resolve);
            } else {
              // if there's at least one child fragment, then load all fragments
              // and resolve their promises
              Promise.all(fragments.map(fragment => {
                return new Promise(resolve => resolve_(fragment, resolve));
              })).then(resolve);
            }
          });
        })
      ).then(() => {
        // when everything was loaded...
        let match = slice
          .call(document.querySelectorAll(selClass))
          .map(element => route_(element,
              e && e.newURL ? e.newURL : window.location.href, lastMatch))
          .find(result => result);
        if (match) {
          stateRevert = false;
          lastMatch = match;
          counterLastMatch = 0;
        } else {
          let newHash = window.location.hash || '';
          if (newHash !== '') {
            stateRevert = true;
            counterLastMatch++;
            window.location.hash = e && e.oldURL ? e.oldURL.split('#')[1] : '';
            setTimeout(() => {
              throw new Error(`Cannot navigate to ${newHash.slice(1)}`);
            });
          }
        }
      });
    }
docs: Hash Change handler that also is executed when
  load event has been dispatched
  
  @private