Hm.js

where model and view should live in

Unified Subscription

There are two ways to handle events, event subscription and event binding. Their differences are subtle but important.

  1. A event subscription has two objects, publisher and subscriber, while event binding has only publisher and no subscriber.
  2. When target event happens, the handler of event binding tends to control arbitrary things which may or may not be in conflict with each others, because there is not subscriber. When target event happens, in the handler of event subscriptions, the subscriber tends to do very specific things which only affect himself, so there will be no conflict and so there is no need to to "synchronize".
  3. The publisher of a subscription does not need to keep track of event handler, while publisher of event binding holds a list of event handlers.

Hm.js use event subscription to implement the publish-subscribe pattern. A typical subscriptions include the following steps.

  1. A subscriber use Hm.js to register a subscription for a event of a publisher with a handler workflow. As a result of the registration, Hm.js keep a record like the following:
    var x = {
     publisher: publisher,
     subscriber: subscriber,
     event: event,
     handler: workflow
    };
    
  2. Publisher trigger the event.
  3. Hm.js find all that record x is a match. It execute the workflow like the following:
    executeWorkflow(x.workflow, x.publisher, x.subscriber, x.event);
    

The third step is interesting, which is result of the differences mentioned above.

Firstly, because publisher does not keep record of subscription, it can not notify the subscriber. The notification is handled by Hm. If publisher is a model, this means that a model is more light-weight, because it does not have the burden to keep track of its subscriptions.

Secondly, the workflow object is not executing itself, instead it s executed by Hm.js workflow executor. The workflow does not know either publisher or subscriber, the workflow executor introduce them to workflow when it is executed. This make the workflow stateless, and very reusable.

The reason it is called Unified Subscription is that, both publisher and subscriber can be model (model node) or view (jQuery object or DOM element), and the event can be either model event or view event (DOM event or jQuery event).

Programmatic Subscription

The third step is taken care by Hm.js, we are mostly responsible for step 1 (subscription registration), and sometimes step 2 (event triggering). The follow examples show to how to do subscription registration. The first example shows programmatic subscriptions.


var customer = hm("customer", {
 firstName: "",
 lastName: "",
 fullName: function () { /* implementation */ }
});

//model firstName subscribe view "#txtFirstName"'s event
customer.cd("firstName").sub("$#txtFirstNmae", "change", function (e) {
 this.set(e.publisher.val());
});

//model lastName subscribe view "#txtLastName"'s event
customer.cd("lastName").sub("$#txtLastName", "change", function (e) {
  this.set(e.publisher.val());
});

//view lblFullName subscribe mode "customer.fullName"'s event
$("#lblFullName").sub(customer.cd("fullName"), "afterUpdate",
  function (e) {
   this.text(e.publisher.get());
});

Declarative Subscription

The follow is the declarative registration of subscriptions of the previous example. Declarative subscription is really doing the same thing of programmatic subscription, but just differently.


<div data-sub="ns:customer">
<div>First Name: <input data-sub="val:firstName" type="text" /></div>
<div>Last Name: <input data-sub="val:lastName" type="text" /></div>
<div>Full Name: <span data-sub="text:fullName"></span></div>
</div>