"Doing" Development Journal - JavaScript Model

The basic layout is done, now we can focus on implementing some behavior with JavaScript. Initially I would like to be able to create an Activity and then immediately have it show up as being done with some random duration. I will save dealing with the state where the timer is running until later.

Activity Model

Doing revolves around stating the Activity you are about to do and then doing that. Based on the mockup, it is apparent that an Activity must have a name, a duration, and notes.

Activity Attributes

Since we are using Ivy for this project, we will just create a normal JavaScript constructor with three Ivy attributes:

function Activity(name, notes, duration){
  this.name     = Ivy.attr(name     || '');
  this.notes    = Ivy.attr(notes    || '');
  this.duration = Ivy.attr(duration || 0 );
}

We can now use this object as such:

var activity = new Activity("Start Doing!");
activity.name.get() //=> "Start Doing!"
activity.name.set("Finish Doing");

Doing View Model

The View Model is a JavaScript object that will represent our UI. There are two logical parts, the "Current Activity", and the "Done Activities". The current activity is just a single item, so we will model it with an Ivy.attr. When that activity is replaced with a new one, Ivy will automatically update everything bound to it. The done activities will be an Ivy.array since they represent a list of activities.

function DoingView(currentActivity){
  this.currentActivity = Ivy.attr(currentActivity);
  this.doneActivities  = Ivy.array();
}

I can update my HTML with Ivy's bindings:

<div id='doing-panel' data-bind='with: currentActivity'>
    <!-- ... -->
    <input data-bind='value: name'/>
    <!-- ... -->
    <textarea data-bind='value: notes'></textarea>
    <!-- ... -->
</div>

<div id='done-panel'>
  <!-- ... -->
    <tbody data-bind='each: doneActivities'>
      <tr> 
        <td data-bind='text: name'>Item One</td> <td data-bind='text: duration'>15m</td> 
      </tr>
    </tbody>
  <!-- ... -->
</div>

We will kick this off with an onload handler. There are more clever ways of doing this, but we do not need to worry about that just yet.

window.onload = function(){
  var activity = new Activity("Start Doing!", "Take notes here.");
  Ivy.bindDom(document.body, new DoingView(activity));
};

Responding to Events

I've already decided that I don't need to implement the active state where the timer is running, but I would like to hook up some events and test out the "Done Activities" list. First I will write the start method for the DoingView:

DoingView.prototype.start = function(activity){
  var current = this.currentActivity.get();

  // set a random duration for now between 0s and 5h
  var seconds = Math.random() * 5 * 60 * 60 * 1000;
  current.duration.set(seconds);

  this.doneActivities.push(current);
  this.currentActivity.set(new Activity());
};

This will get the current activity, give it a random duration, and then push it onto the done list. We bind it by adding data-bind='on: submit ../start' to the form. This tells the form to call start on its parent, which is the DoingView. Now we can start activities and then see them show up in the list of done activities.

Events are wired up

Next time we can spend a few minutes formatting those durations.

blog comments powered by Disqus
Monkey Small Crow Small