Hm.js

where model and view should live in

Model

In Hm.js, the models are public accessible data and functions. They are saved in a singleton object called repository. Repository is a JSON object and it is tree-like structure. Rather than accessing the model directly, we use a node object to access them. The main reason for that is model event. When node method is called to change the model, model events can be triggered. Without model event, it is impossible to implement publisher subscriber pattern.

With a model node, We can create, read, update, delete data and invoke method in the repository. In the following, I will use JS Bin to live demo all sample codes, which are fully executable. You can click on the link to the top right to see the code in action. More than that, you can modify the code and see the change instantly. The following is some sample on how to use node.

//create a node pointing to root of repository
var root = hm();
root.set("customer", {
 firstName: "John",
 lastName: "Doe",
 fullName: function () {
  return this.get("firstName") + "," + this.get("lastName");
 },
 phones: [
  { type: "home", number: "444-4444" },
  { type: "office", number: "888-8888"}
 ]
});

//get a subnode value
hm.log(root.get("customer.firstName"));

//traverse to subnode, and get its value
hm.log(root.cd("customer.lastName").get());

//get model property
hm.log(root.cd("customer").get("fullName"));

//create a new node at "customer.firstName"
var firstName = root.cd("customer.firstName");
  //update node value
firstName.update("May");
hm.log(firstName.get());

//update child node, from the context node
root.update("customer.lastName", "Wu");
hm.log(root.get("customer.lastName"));
hm.log(root.get("customer.fullName"));

 //create a node at "customer.phones"
var phones = hm("customer.phones");
phones.push({type: "mobile", number: "111-1111"});

Model events

Model events can be propagated vertically from bottom to top in repository, this is called event propagation or event bubbling. For example when firstName change, event can propagated up to person. They can also be cascaded horizontally in repository, this is called event cascading. For example, when firstName change, event can cascade to fullName. The following example shows how what event will be triggered when firstName node is changed, and the sequence in which they are triggered.


function dump(e) {
  var color = e.originalPublisher.path != e.publisher.path ?
              "red" :
              "green";
  hm.log(e.originalPublisher.path + "-->  " +
         e.publisher.path, color);
  hm.log("event type: " + e.type);
  hm.log("");
}

var person = hm("person", {
  firstName: "John",
  lastName: "Doe",
  fullName: function () {
    return this.get("firstName") + "," + this.get("lastName");
  }
});

hm.handle("person", "after*", dump);
hm.handle("person.fullName", "afterUpdate", dump);
hm.handle("person.firstName", "afterUpdate", dump);
person.set("firstName", "May");