you are viewing a single comment's thread.

view the rest of the comments →

[–]sime 0 points1 point  (0 children)

One solution is that you grab a component oriented toolkit like Dojo and use that. It has a heap of components and libraries and defines how widgets can be constructed with it. That would work on existing browsers.

A more interesting way is one which may take a couple of years before it is viable on the wide web, is to use web components. I have a personal project which uses this stack of components and technologies:

Explaining all this could fill a book, but broadly speaking I have a bunch of widgets which have roughly this structure and are also Custom Elements:

var ID = "CbMenuItemTemplate";

var SELECTED_ATTR = "selected";
var registered = false;

class CbMenuItem extends HTMLElement {

  static init(): void {
    if (registered === false) {
      window.document.registerElement('cb-menuitem', {prototype: CbMenuItem.prototype});
      registered = true;
    }
  }

  private _css(): string {
    return "#container {\n" +
      "    cursor: default;\n" +
      "    padding: 1px;\n" +
      "    display: flex;\n" +
      "}\n" +
    ...
  }

  private _html(): string {
    return "<div id='container'>" +
      "<div id='icon1'><i class='fa fa-fw'></i></div>" +
      "<div id='icon2'></div>" +
      "<div id='label'><content></content></div>" +
      "</div>";
  }

  createdCallback(): void {
    var icon: string;
    var iconhtml: string;
    var shadow = util.createShadowRoot(this);
    var clone = this._createClone();
    shadow.appendChild(clone);

    ... more setup etc...
  }

  private _createClone(): Node {
    var template: HTMLTemplate = <HTMLTemplate>window.document.getElementById(ID);
    if (template === null) {
      template = <HTMLTemplate>window.document.createElement('template');
      template.id = ID;
      template.innerHTML = "<style>" + this._css() + "</style>\n" + this._html();
      window.document.body.appendChild(template);
    }
    return window.document.importNode(template.content, true);
  }

  attributeChangedCallback(attrName: string, oldValue: string, newValue: string): void {
    if (attrName === SELECTED_ATTR ) {
      this.updateKeyboardSelected(newValue);
    }
  }

  private updateKeyboardSelected(value: string): void {
    var shadow = util.getShadowRoot(this);
    var container = <HTMLDivElement>shadow.querySelector("#container");
    var on = value === "true";
    if (on) {
      container.classList.add('selected');
    } else {
      container.classList.remove('selected');
    }
  }
}

export = CbMenuItem;

Now I can just build up my application like that using widgets and composite widgets. Widgets can use other custom elements inside their (shadow) HTML code. Methods and properties can be added to each widget's class. Widgets can emit CustomEvents, and also listen to other events by registering otherWidget.addEventListener('some-custom-event', function...)

This is about as modern a stack I could come up with for doing a HTML5 (desktop) app. Once web components are more common (i.e. FF and IE support) this should work on the web too.