A rough prototype of what I like to call "JavaScript Model Objects" or JMO for short.While playing with ASP.NET AJAX I came across an idea of using AJAX, JSON, and JavaScript to bind data onto page elements. So today I decided to play around and try to create a "repeater" but on the client-side. This is the gist of the idea...
#1. Get the data which I want to bind using AJAX and JSON.
Example JSON data:
var myTestObj =
{
"rows":
[{"id":1, "title":"Test one", "imagesrc":"images/ajax.gif", "isTest":true},
{"id":2, "title":"Test two", "imagesrc":"images/playmini.gif", "isTest":true},
{"id":3, "title":"Test three", "imagesrc":"images/playmini.gif", "isTest":true}]
}
In this example the JSON data must have "rows" with an array of the row columns/values.
#2. Define the template that I want to bind to. This is defined directly on my HTML page.
Example:
<table>
<tr id="JMO1">
<td style="border: solid 1px black">!id!</td>
<td style="border: solid 1px black">!title!</td>
<td style="border: solid 1px black"><img src="!imagesrc!" /></td>
<td style="border: solid 1px black">!isTest!</td>
</tr>
</table>
As you can see I have a table with 4 columns. I want to bind to the TR object so I give my TR an id. The places where I want the data to appear are surrounded by exclamation points, like !<name>!. Also notice that I have given the TR tag an ID of "JMO1" which I will use to pass to my binding function. The TR tag is essentially my "Model Object."
#3. The functions to bind the data to my model object... Please note this is a very rough sketch of the functionality, and yes I am using jQuery:
function initJMO(modelObj, dataObj) {
var obj = $(modelObj);
var data = eval(dataObj);
var dataMembers = getDataMembers(obj)
if (dataMembers.length > 0) {
// Deep clone the model, save reference
//var clone = obj.clone(true);
var dataClone = obj[0].outerHTML;
for (x = data.rows.length-1; x >= 0; x--) {
var thisRow = dataClone;
for (i = 0; i < dataMembers.length; i++) {
var rg = new RegExp("!" + dataMembers[i] + "!"); rg.global = true;
if (dataMembers[i] == "length") {
ev = data.rows.length.toString();
} else {
ev = eval("data.rows[" + x + "]." + dataMembers[i]).toString();
}
thisRow = thisRow.replace(rg, ev);
}
obj.after(thisRow);
}
// Remove model
obj.remove();
}
}
function getDataMembers(obj) {
var str = obj[0].outerHTML;
if (str.length > 0) {
var rg = /!(\w+)!/g;
var match = str.match(rg);
var dMembers = [];
dMembers.push("length");
if (match != null) {
for(i = 0; i < match.length; i++) {
dMembers.push(match[i].replace(/!/g,""));
}
}
return dMembers;
} else {
return [];
}
}
$(function() {
initJMO("#JMO1", myTestObj);
} );
initJMO requires 2 params... 1 is the model object (our TR in this case). 2 is the data object (our un-eval'd JSON).
initJMO clones the model object, finds all the data members (column names) we want to bind to and then goes through and replaces each !<name>! with the corresponding JSON column's data. It then appends the source of our cloned/replaced element after the model object, thus repeating the data with each row of our data object. Finally initJMO removes the model object from the page.
So what you get is your model object repeated with every row of your data object.
The cool thing about this is you can define ANY element as the model object!Now yes this still needs a lot of work and there are a few issues with it but I'd like to get some feedback. Good idea? Has this been done before?
A sample page can be viewed here: http://www.dennydotnet.com/Test/Default2.aspx