JSFiddle - React, Tailwind, and code Playground

by Daniel Lizik

HTML

<a href="#input">input</a>
<a href="#preview">preview</a>
<a href="#send">send</a>

<div data-route="input">
input
</div>

<div data-route="preview">
preview
</div>

<div data-route="send">
send
</div>

JavaScript

(function(name, global, factory) {

  //amd
  if (typeof global.define === 'function' && global.define.amd)
    global.define([], function() { return factory; });

  //common js
  else if (typeof global.module === 'object' && global.module.exports) {
    global.module.exports = factory;
  
  //browser
  else if (global.window)
    global[name] = factory;
    
})('hashRouter', this, (function(utils) {

  var util = utils(),
      $ = util.$,
      ui = util.ui;
    
  /**
   * @factory
   *
   * config params
   * @param policy - synchronous function must return true for route to render
   * @param resolve - promise to run before route is rendered
   * @param after - function to run after route has been rendered
   * @param name - name of the route, must be specified in html with configurable attribute
   */
   
  return function(config) {
    var self = {
      routes: {},
      config: config,
      hash: hash,
      here: ''
    };
    watch(self);
    otherwise(self);
    return self;
  }
  
  function hash(config) {
    var self = this;
    var instance = routeFactory.call(self, config);
    if (!this.routes.hasOwnProperty(instance.hash))
      self.routes[instance.hash] = instance;
    return self;
  }
  
  function routeFactory(config) {
    return {
      hash: '#' + config.name,
      name: config.name,
      after: config.after || function() {},
      policy: config.policy || function() { return true; },
      resolve: config.resolve || function() { return Promise.resolve(); }
    }
  }
  
  function watch(self) {
    var urls = {}, route, i;
    window.addEventListener('hashchange', function(e) {
      loc = location.hash;
      //update main factory instance
      self.here = loc;
      if (self.routes.hasOwnProperty(loc)) {
        route = self.routes[loc];
        view.call(self, route)
        route.after.call(self, route)
      }
    });
  }
  
  function otherwise(self) {
    if (!self.here || self.here === '')
      location.hash =...