JSFiddle - React, Tailwind, and code Playground

by Joshua McNeese

HTML

<script src="https://cdn.jsdelivr.net/jquery/2.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.6.1/lodash.min.js"></script>
<div id="todo"></div>

JavaScript

var Model = function(data) {
  this.data = data || {};
  _.bindAll(this, _.functionsIn(this));
};
Model.prototype.get = function(key) {
  return this.data[key];
};
Model.prototype.set = function(key, value) {
  if (_.isObject(key)) {
    _.assign(this.data, key);
  } else {
    this.data[key] = value;
  }
  $(this).trigger('updated', [this.data]);
};

var View = function(options) {
  _.assign(this, {
    tpl: undefined,
    el: undefined
  }, options);
  this.template = _.template(this.tpl, {
    interpolate: /{{([\s\S]+?)}}/g
  });
  _.bindAll(this, _.functionsIn(this));
};
View.prototype.render = function(data) {
  $(this.el).html(this.template(data));
};

var Controller = function(options) {
  _.assign(this, {
    model: undefined,
    view: undefined,
    events: {}
  }, options);
  _.bindAll(this, _.functionsIn(this));
};
Controller.prototype.init = function() {
  this.view.render(this.model.data);
  $(this.model).on('updated', _.rearg(this.view.render, [1, 0]));
  _.forEach(this.events, _.bind(function(method, path) {
    var parts = _.split(path, '.');
    $(this.view.el).on(parts[1], parts[0], this[method]);
  }, this));
};

var todoModel = new Model({
  title: 'Do homework',
  completed: false
});

todoModel.set('title', 'Do all homework');
todoModel.set({
  completed: true
});

console.log('todo completed', todoModel.get('completed')); // true
console.log('todo data', todoModel.data); // {title: 'Do all homework', completed: true}

var todoView = new View({
  el: '#todo',
  tpl: '<div>' +
    '<input id="todo_complete" type="checkbox"{{completed ? "checked" : ""}}>' +
    '<span style="{{completed ? "text-decoration:line-through" : ""}}">' +
    '{{completed ? "Done: " : ""}}{{title}}' +
    '</span>' +
    '</div>'
});

var todoController = new Controller({
  model: todoModel,
  view: todoView,
  events: {
    "input[type=checkbox].click": "toggleComplete"
  },

  toggleComplete: function() {
    this.model.set({
      completed:...