Wednesday, April 18, 2012

PlastronJS By Example pt5

now we'll put in some more functionality which will include the count of todos the ability to check a todo as complete and also remove a todo.

first the list control we want to add in a count:

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 class='count'></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');

  this.getModel().modelChange(function() {
    goog.dom.setTextContent(this.getEls('.count')[0],
        this.getModel().getLength() + ' notes');
  }, this);
};

what I've done is add in a div at the end and then put in a listener on modelChange which will fire if any models are added or removed (or are changed so that they are sorted differently) and then just display the number of notes. Now on to the todo:

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>" +
    "<input type='checkbox' class='complete'/>" +
    "<div class='todoedit'></div>" +
    "<div class='delete'>X</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();
  }, "todoedit");

  this.click(function(e) {
    if(e.target.checked) {
      this.getEls(".todoedit")[0].style.textDecoration = 'line-through';
      this.getModel().set('complete', true);
    } else {
      this.getEls(".todoedit")[0].style.textDecoration = 'none';
      this.getModel().unset('complete');
    }
  }, "complete");

  this.click(function(e) {
    this.getModel().dispose();
    this.dispose();
  }, "delete")
};

Here I've added in a checkbox and a delete div and given them click functions. On clicking the checkbox it looks to see if the element is checked and changes the style of the text. It also sets 'complete' on the model or unsets it.

the delete will call dispose on the model which in turn will let the collection know it is disposed so the listener we put on to the collection will fire and update the count. We then dispose our control which will remove itself from the dom and clean up any event listeners it has setup.




1 comment: