<main></main>
.btn-reset {
  display:block;
  margin:10px 0;  
}
var CountedTextView = Backbone.View.extend({
  tagName: 'div',
  
  templateText: Handlebars.compile('<textarea>{{text}}</textarea><button class="btn-reset">Reset</button>'),
  
  templateCount: Handlebars.compile('<p>You typed {{count}} characters in the box</p>'),
  
  initialize: function() {
    this.listenTo(this.model, 'change', this.render);
  },
  
  events: {
    'input textarea': 'textChanged',
    'click .btn-reset': 'resetText'
  },
  
  resetText: function(ev) {
    this.model.revert();
  },
  
  textChanged: function(ev) {
    this.model.set({text: ev.target.value });
  },
  
  initDOM: function(state) {
    this.$el.html(this.templateText(state) + this.templateCount(state));
  },
  
  
  render: function() {
    
    var state = {
      text: this.model.toJSON().text,
      count: this.model.toJSON().text.length
    };
    
    if ( ! this.$el.html() ) {
      this.initDOM(state);
    }

    var $ta = $('textarea', this.$el);
    var $count = $('p', this.$el);
    
    $ta.val(state.text);
    $count.html(this.templateCount(state));

    return this;
  }
  
});

var initialText = "type something";
var CountedTextModel = Backbone.Model.extend({
  defaults: {
    text: initialText
  },
  revert: function() {
    this.set({text: initialText});
  }
});

var myModel = new CountedTextModel();
var myView = new CountedTextView({model: myModel});
$('main').append(myView.$el);
myView.render();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js
  2. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js
  3. //cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js
  4. https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.3/handlebars.min.js