Enyo Basics - Kinds, Components, Controls

In this document, we take a closer look at kinds, components, and controls--three foundational Enyo concepts that we touched upon in Enyo Basics - From the Bottom Up.

Kinds

In Enyo, nearly all code is located in object prototypes called kinds. A kind is an object constructor created using the enyo.kind factory method.

The kind in Enyo has a role analogous to that of the class in Java or C++. For example, kinds provide a standard mechanism for implementing inheritance, with subkinds inheriting properties and functions from their superkinds.

Here are examples of kinds that create objects representing points in two- and three-dimensional space. Note that the second kind (Point3D) inherits from the first (Point):

enyo.kind({
  name: "Point",
  x: 0,
  y: 0,
  constructor: function(x, y) {
      this.x = x;
      this.y = y;
  },
  translate: function(dx, dy) {
      this.x += dx;
      this.y += dy;
  },
  toString: function() {
      return this.x + ", " + this.y;
  }
});

enyo.kind({
  name: "Point3D",
  kind: "Point",
  z: 0,
  constructor: function(x, y, z) {
      this.inherited(arguments);
      this.z = z;
  },
  translate: function(dx, dy, dz) {
      this.inherited(arguments);
      this.z += dz;
  },
  toString: function() {
      return this.inherited(arguments) + ", " + this.z;
  }
});

p = new Point3D(1, 1, 1);

Components

Component objects are the basic building blocks of Enyo. Components share common features, which allow them to work together in a standard way. For example, all components have a name (string). A component may create other components, which it is said to own. Each component maintains a collection of the components it owns, and is responsible for the lifecycle of those components.

Here are the kind definitions of two components. At runtime, a SimulatedMessage object creates (and thus owns) a RandomizedTimer object, which it uses to simulate the sending of service messages at random intervals:

enyo.kind({
  name: "RandomizedTimer",
  kind: enyo.Component,
  baseInterval: 100,
  percentTrigger: 50,
  events: {
      onTriggered: ""
  },
  create: function() {
      this.inherited(arguments);
      this.job = window.setInterval(enyo.hitch(this, "timer"), this.baseInterval);
  },
  destroy: function() {
      window.clearInterval(this.job);
  },
  timer: function() {
      if (Math.random() < this.percentTrigger * 0.01) {
          this.doTriggered();
      }
  }
});

enyo.kind({
  name: "SimulatedMessage",
  kind: enyo.Component,
  components: [
      {name: "timer", kind: RandomizedTimer, percentTrigger: 10,
          onTriggered: "timerTriggered"}
  ],
  timerTriggered: function() {
      this.log("Simulated Service Message Occurred");
  }
});

Controls

A Control object is a component that controls a DOM node (i.e., an element in the user interface). Controls are generally visible and the user often interacts with them directly. Things like buttons and input boxes are obviously controls, but in Enyo a control may become as complex as an entire application.

In the following example, we define a Circle control and put it to use inside a TrafficLight control:

enyo.kind({
  name: "Circle",
  kind: "Control",
  published: {
      color: "magenta",
      bgColor: "black"
  },
  content: "Hi",
  style: "padding: 2px 6px; border: 3px solid; border-radius: 20px;
      cursor: pointer;",
  create: function() {
      this.inherited(arguments);
      this.colorChanged();
  },
  colorChanged: function() {
      this.applyStyle("border-color", this.color);
  },
  bgColorChanged: function() {
      this.applyStyle("background-color", this.bgColor);
  },
  mousedown: function() {
      this.applyStyle("background-color", "white");
  },
  mouseup: function() {
      this.applyStyle("background-color", "black");
  }
});

enyo.kind({
  name: "TrafficLight",
  kind: "Control",
  style: "position: absolute; padding: 4px; border: 1px solid black;
      background-color: silver;",
  components: [
      {kind: "Circle", color: "red", onclick: "circleClick"},
      {kind: "Circle", color: "yellow", onclick: "circleClick"},
      {kind: "Circle", color: "green", onclick: "circleClick"}
  ],
  circleClick: function(inSender) {
      var lights = {red: "tomato", yellow: "#FFFF80", green: "lightgreen"};
      if (this.lastCircle) {
          this.lastCircle.setBgColor("black");
      }
      this.lastCircle.setBgColor(lights[inSender.color]);
      this.lastCircle = inSender;
  }
});