Edit on Github

Basics

The basics of using Toolkitchen are simple:

  1. Load platform.js to polyfill missing platform features, such as Shadow DOM and HTML Imports.
  2. Load components with <link rel="import" href="/path/to/component-file.html">
  3. Use the custom element in your page.

Here’s a bare bones example:

<!DOCTYPE html>
<html>
  <head>
    <!-- 1. Shim missing platform features -->
    <script src="toolkit/platform/platform.js"></script>
    <!-- 2. Load a component -->
    <link rel="import" href="toolkit-ui/elements/g-menu-item.html">
  </head>
  <body>
    <!-- 3. Instantiate the component with its tag. -->
    <g-menu-item src="images/email.svg">Email Link</g-menu-item>
  </body>
</html>

Note: You must always run your app from a web server. This is for the HTML Imports polyfill will work properly. This requirement will go away when the API is available natively in browsers.

Components

Custom Elements are the core building blocks of Toolkit-based applications. You create applications by assembling custom elements together, either ones provided by the Toolkit or that you create yourself.

Creating a basic component

The platform polyfills provided by Toolkitchen let you load and display custom elements. Just by loading platform.js you get support for these new technologies.

<element name="my-element">
  <section>
    I'm a my-element!
  </section>
  <footer>nothing to see here</footer>
  <script>
    // When <element> is in document, might run in wrong context.
    // Only do work when this == <element>.
    if (this !== window) {
      var section = this.querySelector('section');
      this.register({
        prototype: {
          readyCallback: function() {
            this.innerHTML = section.innerHTML;
          }
        }
     });
    }
  </script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/platform/platform.js"></script>
    <!-- Load custom element -->
    <link rel="import" href="my-element.html">
  </head>
  <body>
    <!-- Instantiate custom element -->
    <my-element></my-element>
  </body>
</html>
Result

Creating a Toolkit component

Toolkit provides extra goodies for creating custom elements. We call these souped-up custom elements “Toolkit components”. To create Toolkit component, follow these steps:

  1. Load the Toolkit kernel (toolkit/toolkit.js or toolkit/toolkit.min.js).

Note: toolkit.js loads platform.js under the hood. You only need to include toolkit.js when writing a Toolkit component.

  • In your custom element, add a <script> element that calls the Toolkit.register() initializer. This endows the custom element with Toolkit features, such as data binding and event mapping.

In the following sample we convert our basic custom element into a Toolkit component named tk-element.

<element name="tk-element">
  <template>
    <span>I'm <b>tk-element</b>. This is my Shadow DOM.</span>
  </template>
  <script>
    Toolkit.register(this);
  </script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/toolkit.js"></script>
    <link rel="import" href="tk-element.html">
  </head>
  <body>
    <tk-element></tk-element>
  </body>
</html>
Result

Toolkit.register() takes the element it needs to register as its first argument. In the context of <element>, this refers to the element.

Declarative data binding

You can bind properties in your component to Toolkit supports declarative data binding using the “double-mustache” syntax ({{}}) from Model Driven Views. The {{}} is replaced by the value of the property referenced between the brackets.

<element name="tk-element-databinding">
  <template>
    This is <strong>{{owner}}</strong>'s tk-element.
  </template>
  <script>
    Toolkit.register(this, {
      owner: 'Daniel'
    });
  </script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/toolkit.js"></script>
    <link rel="import" href="tk-element-databinding.html">
  </head>
  <body>
    <tk-element-databinding></tk-element-databinding>
  </body>
</html>
Result

Binding to markup

You can use binding expressions in most HTML markup, except for tag names themselves. In the following example, we create a new property on our component named color whose value is bound to the value of the color style applied to the custom element.

<element name="tk-element-databinding-color">
  <template>
    This is a <strong>{{owner}}</strong>'s tk-element. 
    {{owner}} likes the color 
    <span style="color: {{color}}">{{color}}</span>.
  </template>
  <script>
    Toolkit.register(this, {
      owner: "Daniel",
      color: "red"
    });
  </script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/toolkit.js"></script>
    <link rel="import" href="tk-element-databinding-color.html">
  </head>
  <body>
    <tk-element-databinding-color></tk-element-databinding-color>
  </body>
</html>
Result

Binding between components and native elements

The following example demonstrates binding component properties to attributes of native input elements.

<element name="tk-binding-to-elements">
  <template>
    <p>This is <strong>{{owner}}</strong>'s tk-element but 
    <strong>{{name}}</strong> lets me borrow it. 
    He likes the color <span style="color: {{color}}">{{color}}</span>. 
    I am <strong>{{age}}</strong> years old.</p>
    <label for="ageInput">Age:</label>
    <input id="ageInput" type="range" value="{{age}}">
    <label for="nameInput">Name:</label>
    <input id="nameInput" value="{{name}}" placeholder="Your name here...">
  </template>
  <script>
    Toolkit.register(this, {
      age: "25",
      name: "Daniel",
      color: "red",
      owner: "Eric",
      nameChanged: function() {
        if (this.name) {
          // ensure capitalization
          this.name = this.name[0].toUpperCase() +  this.name.slice(1);
        }
      }
    });
</script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/toolkit.js"></script>
    <link rel="import" href="tk-binding-to-elements.html">
  </head>
  <body>
    <tk-element></tk-element>
  </body>
</html>
Result

Adding a ready() lifecyle method

When a component has finished initializing itself, it calls its ready method, if it exists.

<element name="tk-element-ready">
  <template>
    This is a <b>tk-element</b> with a ready() method.
    <span id="readyEl">Not ready...</span>
  </template>
  <script>
    Toolkit.register(this, {
      owner: "Daniel",
      ready: function() {
        this.$.readyEl.innerText = this.owner + " is ready!";
      }
    });
  </script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/toolkit.js"></script>
    <link rel="import" href="tk-element-ready.html">
  </head>
  <body>
    <tk-element-ready></tk-element-ready>
  </body>
</html>
Result

Publishing properties

By default, properties you declare are not accessible via attribute. You can publish a property by listing it in the attributes attribute on the <element> tag. Published properties can be initialized using attributes on the node, and can be data-bound using attributes on the node.

A property declared in the attributes attribute is initially set to null. You can provide a more appropriate default value by also including the property directly in your prototype, as usual.

Using the “attributes” attribute

The following example defines an attributes attribute on the custom element whose value is the string "owner color".

<element name="tk-element-property-public"
         attributes="owner color">
  <template>
    This is a <strong>{{owner}}</strong>'s tk-element. 
    He likes the color <b style="color: {{color}}">{{color}}</b>.
  </template>
  <script>
    Toolkit.register(this, {
      // These default property values are overridden
      // by initial attribute values.
      color: "red",
      owner: "Daniel"
    });
  </script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/toolkit.js"></script>
    <link rel="import" href="tk-element-property-public.html">
  </head>
  <body>
    <div class="well">
      <!-- Component specifies values its public properties. -->
      <tk-element-property-public owner="Scott" color="blue">
      </tk-element-property-public>
    </div>
  </body>
</html>
Result

Automatic node finding

Shadow DOM is a self-contained document-like subtree; id’s in that subtree do not interact with id’s in other trees. Each Toolkit element generates a map of id’s to node references in the element’s template. This map is accessible as $ on the element.

<element name="tk-node-finding">
  <template>
    <p>
    This is a <strong>{{owner}}</strong>'s tk-element.
    He likes the color <b style="color: {{color}}">{{color}}</b>.
    </p>
    <button on-click="setFocus">Set focus to text input</button>
    <input id="nameInput" value="{{owner}}" on-keyup="setName"
           placeholder="Your name here...">
  </template>
  <script>
    Toolkit.register(this, {
      color: "red",
      owner: "Daniel",
      setFocus: function() {
        this.$.nameInput.focus();
      }
    });
  </script>
</element>
<!DOCTYPE html>
<html>
  <head>
    <script src="toolkit/toolkit.js"></script>
    <!-- Load custom element -->
    <link rel="import" href="tk-node-finding.html">
  </head>
  <body>
    <!-- Instantiate custom element -->
    <tk-node-finding></tk-node-finding>
  </body>
</html>
Result