Monday, April 16, 2012

PlastronJS by example pt4

today we're going to display the todo and allow some editing.

First I'll create the control for a todo item:

goog.provide('todomvc.todocontrol');

goog.require('mvc.Control');

todomvc.todocontrol = function(model) {
  goog.base(this, model);
  this.editable = false;
};
goog.inherits(todomvc.todocontrol, mvc.Control);



todomvc.todocontrol.prototype.createDom = function() {
  this.el = goog.dom.htmlToDocumentFragment("<div>" +
    "<div class='todoedit'></div>" +
    "</div>");
 console.log(this.el);
 this.setElementInternal(this.el);
};

todomvc.todocontrol.prototype.makeEditable = function() {
  this.getEls('.todoedit')[0].innerHTML =
      "<input type='text' value='" + this.getModel().get('text') + "'/>";
  this.editable = true;
};

todomvc.todocontrol.prototype.makeUneditable = function() {
  this.getEls('.todoedit')[0].innerHTML = this.getModel().get('text');
  this.editable = false;
};

todomvc.todocontrol.prototype.enterDocument = function() {
  this.makeUneditable();

  this.on('keyup', function(e) {
    this.getModel().set('text', this.getEls('input')[1].value);
  });

  this.on('focusout', function() {
    this.makeUneditable();
  });

  this.click(function() {
    if(!this.editable)
      this.makeEditable();
  });
};

It should look fairly similar to our list control. It has a createDom method where I'm putting in the div and an enterDocument where I setup all the listeners. I've also created makeEditable and makeUneditable functions which will put in an input which will listen to key up events to change the models text.

I've also put in a focusout event (notice it's not blur because blur events don't bubble so won't reach the control's listener) to go back to uneditable mode. Now we need to add this to our list control:

goog.provide('todomvc.listcontrol');

goog.require('mvc.Control');
goog.require('todomvc.todocontrol');

todomvc.listcontrol = function(model) {
  goog.base(this, model);
};
goog.inherits(todomvc.listcontrol, mvc.Control);



todomvc.listcontrol.prototype.createDom = function() {
  this.el = goog.dom.htmlToDocumentFragment("<div>" +
    "<div>Todo</div>" +
    "<div><input type='text' class='todoform'/></div>" +
    "<div class='todolist'></div></div>");
 console.log(this.el);
 this.setElementInternal(this.el);
};

todomvc.listcontrol.prototype.enterDocument = function() {
  goog.base(this, 'enterDocument');

  this.on('keyup', function(e) {
    // on return
    if (e.keyCode != 13) return;

    // create new model
    var text = (this.getEls('input')[0]).value;
    var newModel = this.getModel().newModel({'text': text});

    //create new model control
    var newModelControl = new todomvc.todocontrol(newModel);
    this.addChild(newModelControl);
    newModelControl.render(this.getEls('.todolist')[0]);
  }, 'todoform');
};

first thing I did was add in the goog.require at the top. Since this is a new file we'll have to add it to out deps.js with the command we used in the first post:

lib/closure-library/closure/bin/calcdeps.py --dep lib/closure-library --input js/main.js --path lib/plastronjs --path lib/plastronjs/sync --path js/ --output_mode deps > deps.js

I also added in the goog.base() for enterDocument. This is because I'm adding the controls as a child and goog.ui.Component does some things with it's enterDocument to setup relationships between itself and child components.

I also changed the form to just listen to a keyup as this is what is being done on todomvc's website (and debugging forms can be a pain as the browser will submit the form even if you break in the javascript).

and then the part at the bottom I setup the control, pass it the new model (mvc.Collection#newModel returns the model that was created and added) added it as a child of the control and then rendered it in to a div that I put in to hold the children.

save those changes and run then. You should be able to see that you can create new notes, click them and edit them. The only thing we use to display the test is a call to get('text') so we can see that the changes are being saved to the model.



2 comments:

  1. thanks for your tutorial, i have seen a little problem in todocontrol line 36 :
    this.getModel().set('text', this.getEls('input')[1].value);

    should be :

    this.getModel().set('text', this.getEls('input')[0].value);

    ReplyDelete