Javascript Closures for Data Binding

Example of how to use javascript closures to perform data binding. Uses jQuery to make things clear. author(s): Michael Anderson

HTML

<script src="http://http://therobotsbrain.blogspot.com/"></script>
<h1>Test for binding data into dynamic forms using javascript closures</h1>
This creates multiple divs (with each click on the add button) and binds the contained control to
an element of the <code>data</code> array.

<br/><a id="add_button" href="#">Click me to add a new datum</a><br/>
<div id="target_div"></div>

<div id="data"></div>

JavaScript

$(document).ready( function() {
    $('#add_button').click( add_pane_with_data_binding );
    } );

var data = [];

var DatumClass = function(v) { this._v = v; this._watchers=[]; }
DatumClass.prototype = new Object;
DatumClass.prototype.get_value = function() { return this._v; }
DatumClass.prototype.set_value = function(v,token)
{
  this._v = v;
  //Notify the watchers
  var len=this._watchers.length
  for( var i=0; i<len; ++i )
  {
    console.log(this._watchers[i]);
    this._watchers[i].value_changed(this, this._v, token);
  }
}

var ViewClass = function(input,datum) { this._input = input; this._datum = datum; }
ViewClass.prototype = new Object;
ViewClass.prototype.value_changed = function( datum, value, token )
{
  if( token!=this._input && this._input.val()!=value ) this._input.val(value);
}

function create_bound_input( datum )
{
  var this_input = $('<input type="text"></input>');
  this_input.val( datum.get_value() );

  //Now bind the change via a closure
  this_input.bind('change', function(e) { datum.set_value( this_input.val(), this_input ); } );

  //Now add them as watchers so that if someone else changes the value they get notified
  var observer = new ViewClass( this_input, datum );
  datum._watchers.push(observer);
  return this_input;
}

  //Lets keep our data display uptodate automatically as a watcher too..
var json_watcher={};
json_watcher.value_changed = function( datum, value, token)
{
	$('#data').empty();
	var len = data.length;
	for( var i=0; i<len; ++i )
	{
		var vv = $( '<span>'+data[i].get_value()+'</span>' );
		vv.css({"font-family":"sans-serif", "border":"1px solid #cc0"});
		$('#data').append($('<div><b>'+i+'</b></div>').append(vv));
	}
}

function add_pane_with_data_binding()
{
  //Add the data
  var this_data = new DatumClass("Hello World");
  data.push( this_data );

  //Add view to the target div
  var this_div = $('<div></div>');
  $('#target_div').append( this_div );

  var this_input = create_bound_input(this_data);
 ...