a simple jQuery data binder. Originally forked from petersirka/jquery.bindings

Just write some stuff in this super ghetto-oldschool-retro form i got her and see it be bound!


The Form:

GITHUB BAM!

Check out my sweetness that is bindings!

This is a

I just wanna eat

What's my gender? !

You will pay me $ million dollars!

The Model JSON:


			  

I will try and keep this as simple as possible...

1.) Who is Terry?

Terry doesn't give no... snacks. He keeps it simple, and if its not simple, he flips the flubber out!

So it is for Terry that this... thing was put together. 'At a boy Terry!

2.) What does this thing do?

Well, this allows you to simply bind data from a javascript object to html elements, and get the data back again.

YA YA! I KNOW! Another one of these right? Why not use angular? Why not knockout or backbone or react? Terry wants simple! So thats what Terry gets! Sometime when you've had bout' 30 too many, you want something quick and dirty to get the job done.

Why get dressed when you can go out in your underpants?

Terry
  • The binder connects a JSON with HTML elements according to a data-model attribute
  • The data-model contains the property name from the object thats being binded
  • <input>, <select>, <div contenteditable="true"> and <textarea> work with two-way data-bindings
  • The data-model is updated when data changes either through and input or by modifying the model manually. I'll get to that.

First thing - Include the jQuery (>1.1) and then this script.

Then define bindings via html attributes

  1. Start by defining the name of the model with a data-model-name attribute in what we'll call the parent element
    • Like this: <div id="somediv" data-model-name="muppetBabies">...<div> where you're being a werido and have data about muppet babies... weird.
  2. Next you add some html entities (inputs, selects, textareas, divs, whatever!) inside of the parent element and bind them to a model property using the data-model attribute
  3. If you want to have Terry bind the model when the page loads, just add data-bind-on-load as an attribute somewhere in the page, say in the body?
  4. So you'll end up with something like this:
    <div id="container" data-model-name="muppetBabies">
    							   <input type="text" data-model="coolness_level" />
    							   <div data-model="muppet_name"></div>
    						</div>
  5. If you DON'T want to have Terry bind the model when the page loads, don't include data-bind-on-load and instead use:
    • $.fn.binder('create'); to bind all elements with models defined through data-mode-name
    • $.fn.binder('create','nameOfModel'); to bind a particular model in a page that is defined through the data-mode-name attribute
    • $('#somediv').binder('create'); to bind all models within a particular element with a model defined through data-mode-name
    • $('#somediv').binder('create','nameOfModel'); to bind a particular model in particular element that is defined through the data-mode-name attribute
    • I hope you're getting the picture...




TO BIND USE -> $.fn.binder('ACTION,'MODEL_NAME',DATA)

So lets break this down

$.fn.binder('ACTION','MODEL_NAME',DATA);
  • You can either not reference an element (ie leave it as shown above)
  • or reference an element that has the data-model-name-attribute ie $('#someelement').binder......
  • The first way would either look for instances of [data-model-name] within the page and start model binding for all of them, or relay on the 'MODEL_NAME' to find it.
$.fn.binder('ACTION','MODEL_NAME','DATA');

This is the action that you want the Terry Binder to perform. This is a STRING and available actions inclue:

  • create - This action is used to creating the binding between model and html elements
  • model - This action tells the binder to return the model data for use in Javascript. This is the DEFAULT value.
  • refresh - If the model has been modified externally, this action will refresh the data in the HTML
  • update - This action allows you to pass data to the binder to update the model manually
  • destroy - This action destroys the data binding for a particular model
$.fn.binder('ACTION','MODEL_NAME','DATA');

This is an OPTIONAL STRING that tell the binders what to name the model, and what data-model-name attribute to use.

$.fn.binder('ACTION','MODEL_NAME','DATA');

This is a data OBJECT to fill the model. This is OPTIONAL. See the Model Binding section below to learn more.

To start, you need to define your model. Models are JSON objects and can have nested properties. At this point Terry has had a few too many so keep the data structure simple. We can get more complex once he sobers up.

So lets say we have this object:

var obj = { 
					  'property1' : 123,
					  'property2' : 'Terry is da bomb',
					  'property300' : 'oh yeah boom'
					}

And we want to bind it to this form:

<form data-model-name="someModel" id="someform">
					   <input type="text" data-model="property1">
					   <input type="number" data-model="property2">
					   <input type="text" data-model="property3">
					</form>

To bind, we have a couple options! First would be a binder create on the jQuery form element like this:

$.fn.binder('create','someModel',obj);

Through the data-model-name, binder will know the object to be used to build the model.

Binder will return the model to you when you call:

$('#someform').binder('model');
						 //eg. var somevariable = $('#someform').binder('model');

						 //or you can use
						$.fn.binder('model','someModel');
					  

Both of the above will return the exact same thing.

If your object has the same name as the data-model-attribute and is in scope of binder, then binder will detect the model automatically when initiated. You can also define the binder model manually:

$.binder.model.someModel = {
						  attribute1 : "I am a value",
						  attribute2 : "Yet another value",
						  attribute3 : 123321
						}

						$.fn.binder('create');
					  


Coming Soon...

Model Create

This event occurs as soon as a model is bound by the binder

$('#form').on('model-create', function(e, model) { 
							  // Is triggered after $.fn.binder('create')
						});

Model Update

This fires on all manual model updates

						$('#form').on('model-update', function(e, model, path) {
							 // Is triggered after is the model updated - eg $.fn.binder('update')
						});
						

Model Change

This event firest every time a model is changed through an html element

						$('#form').on('model-change', function(e, path, value, model, name, element) {
							 // DO SOMETHING!!!!
						});
						

Autosave

Make a change to this form:

Input 1 + Input 2 =

Below is the example used in this page. Autosave had two events: autosave-delay and autosave. The autosave delay event is used to let you know that a save is pending. If three seconds passes with no changes to the model the autosave event fires.

						/*autosave-delay event: this event passes the name of the model (string)*/
						 $('[data-model-name="something"]').on('autosave-delay',function(e, modelname){
						   $('#autosave-notify').html('<div class="alert alert-info">Preparing to save...</div>');
						 });
 
						/*autosave event : this event passes the model data that was changed (JSON), the name of the model (string), and the entire model (JSON)*/
 						$('[data-model-name="something"]').on('autosave',function(e,updateddata,modelname,model){
						   $('#autosave-notify').html('<div class="alert alert-success">Saved:'+JSON.stringify(updateddata)+' </div>');
						 });

						

Model Destroy

After the bindings have been removed, this model fires.

						$('#form').on('model-destroy', function(e) {
							 // Is triggered when is destroyed binding
						});
						

Model Default

Fires when resetting a model back to its default state.

						$('#form').on('model-default', function(e, model) {
							 // set to the default model
						});
						

Model Validation

This will fire when a model that is set to validate fails


						$('#form').on('model-validate', function(e, errorlist) {
							 errorlist[0].path;
							 errorlist[0].value;
							 errorlist[0].element;
						});

						// OR

						$('#form').on('validate', function(e, errorlist) {
							 errorlist[0].path;
							 errorlist[0].value;
							 errorlist[0].element;
						});
						

In Progress. More coming soon

Custom Templating
$.binder.custom.tabemplatename = function(name, value, custom, model, schema)

This allows you to use data from the model and display it in the html in any way you see fit! consider the following example:

						//The model:
						 var someTable = table: {
						  headers: {cell1:"Cell 1", cell2: "Cell 2", cell3:"Cell 3"},
						  body: [
						   {cell1: "these",cell2: "cells",cell3: "are"},
						   {cell1: "stored",cell2: "in",cell3: "an"},
						   {cell1: "object",cell2: "wee!",cell3: "binder"},
						   {cell1: "template",cell2: "displays",cell3: "them!"}
						  ]
						 }

						//The HTML:
						<div id="someTable" data-model-name="someTable" >
						 <table data-model="table" data-custom="table" class="table table-hover">


						 </table>
						</div>

						//And the template:
						 $.binder.custom.table = function(name, value, custom, model, schema){						
						  var tableContent = "<thead><tr>";
						  $.each(value.headers, function(key,val){
						   tableContent += "<th>" + val + "</th>";
						  });
						  tableContent += "</tr></thead><tbody>";
						  $.each(value.body,function(index,val){
						   tableContent += "<tr>";
						   $.each(value.headers, function(i,v){
						    tableContent += "<td>" + val[i] + "</td>";
						   });		
						  	tableContent += "</tr>";

						  });
						 tableContent += "</tbody>";
						 return tableContent;
						};

					
So the above code results in:
Validation

This is used in the calculation example above. Look at the first input in that example to test

					
/* This is a simple validation rule on the 'something' model */
$.binder.validation.something = function(path, value, model, name) {
 	switch (path) {
          case 'first_input':
                 return value > 0 && value < 20;			      
  	}
 	    return true;
};

/* This is a simple watch statement that adds some bootstrap classes and a validation message */
$.binder.watch = function (isValid, path, value, model, schema) { 
 	var el = this;
 	var parent = $(el).parent();
 	if(isValid == false){
  	   parent.addClass('has-error');		
  		if(parent.find('p.text-danger').length == 0){
   			parent.append('<p class="text-danger">Validation Error</p>');
  		}
 	}
 	else{
  		parent.removeClass('has-error');
  		parent.children('p.text-danger').remove();
 	}
};