Using Script Tags As Data Contains In AJAX-Powered jQuery

Posted June 8, 2009 at 10:19 AM

Tags: Javascript / DHTML

Last week, I blogged about how cool it was that the jQuery metadata plugin used Script tags to store application meta-data. I liked this for a number of reasons including the mime-typed nature of the script tags and their contextual embedding. After demonstrating the script tag meta-data use in a static way, I thought it would be good to demonstrate it in an AJAX-powered way. In this example, I am going to be pulling down HTML table rows with embedded meta-data script tags:

 
 
 
 
 
 
 
 
 
 

As you can see in the data, I start off with an HTML table that only has its THEAD defined. When the DOM is ready to be interacted with, I then use jQuery to pull down the table's TBODY. This TBODY contains not only the row data, it also contains Script tags that contain row meta-data. Because each Script tag contains data for a given row, I am returning a Script tag for each TR:

 Launch code in new window » Download code as text file »

  • <!--- Bulid the query to be used in the demo. --->
  • <cfset qGirl = QueryNew( "" ) />
  •  
  • <!--- Add the ID column. --->
  • <cfset QueryAddColumn(
  • qGirl,
  • "id",
  • "cf_sql_integer",
  • ListToArray( "1,2,3,4,5" )
  • ) />
  •  
  • <!--- Add the name column. --->
  • <cfset QueryAddColumn(
  • qGirl,
  • "name",
  • "cf_sql_varchar",
  • ListToArray( "Libby,Molly,Sarah,Kim,Kit" )
  • ) />
  •  
  •  
  • <!--- Return the rendered HTML. --->
  • <cfoutput>
  •  
  • <tbody>
  • <cfloop query="qGirl">
  •  
  • <!---
  • We need to create a unique ID for the row so that
  • the JSON meta data can be associated with it.
  • --->
  • <cfset strRowID = "row-#CreateUUID()#" />
  •  
  • <!--- Send meta data. --->
  • <script
  • type="text/x-json"
  • rel="#strRowID#"
  • class="metadata">
  • {
  • id: #qGirl.id#,
  • name: "#HtmlEditFormat( qGirl.name )#"
  • }
  • </script>
  •  
  • <tr id="#strRowID#">
  • <td>
  • #qGirl.id#
  • </td>
  • <td>
  • #qGirl.name#
  • </td>
  • <td>
  • <a class="delete">Delete</a>
  • </td>
  • </tr>
  •  
  • </cfloop>
  • </tbody>
  •  
  • </cfoutput>

While the Script tags are created contextually to the TR to which they refer, I have to give the TR a unique ID and pass that via the REL attribute of the Script tag. This is because the Script tags are moved around by the browser when the html is appended to the table. As you can see from the video, after our append() method, the Script tags are all added to the table itself and are no longer accessible in the context of the associated TR. The REL attribute allows us to gather the script tags from their new location and still associate their data with the original row.

The association of this meta-data is done by the jQuery code that handles the AJAX response:

 Launch code in new window » Download code as text file »

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>jQuery And Script Tags With AJAX-Table Data</title>
  • <script type="text/javascript" src="jquery-1.3.2.js"></script>
  • <script type="text/javascript">
  •  
  • // When the DOM has loaded, gather the table data.
  • $(
  • function(){
  • $.ajax(
  • {
  • method: "get",
  • url: "./scripts_data.cfm",
  • dataType: "html",
  • success: populateTable
  • }
  • );
  • }
  • );
  •  
  •  
  • // I take the AJAX response and populate the table with
  • // initailized records.
  • function populateTable( strHTML ){
  • var jTable = $( "#table" );
  •  
  • // Append raw HTML to the table. We can initialize the
  • // html data after we append it.
  • //
  • // NOTE: After we append the HTML, the Script tags
  • // will have been stripped out and placed at the
  • // bottom of the table!
  • jTable.append( strHTML );
  •  
  • // Log table HTML for demo.
  • console.log( jTable.html() );
  •  
  • // Bind the meta data (remember, script tags became
  • // children of the table itself).
  • jTable.find( "> script.metadata" ).each(
  • function( intI, objScript ){
  • var jThis = $( this );
  • var jRow = $( "#" + jThis.attr( "rel" ) );
  •  
  • // Bind the meta data to the row.
  • jRow.data(
  • "metadata",
  • eval( "(" + jThis.html() + ")" )
  • );
  • }
  • );
  •  
  • // Gather records.
  • var jRows = jTable.find( "tbody > tr" );
  •  
  • // Now that the meta data is bound to the record,
  • // let's hook up the row action links.
  • jRows.find( "a.delete" )
  • .attr( "href", "javascript:void( 0 )" )
  • .click(
  • function( objEvent ){
  • var jRow = $( this ).parents( "tr:first" );
  •  
  • // This doesn't really do anything - just
  • // for demonstration purposes. Showing
  • // how we can grab meta data from the row.
  • confirm(
  • "Are you sure you want to delete " +
  • jRow.data( "metadata" ).name +
  • " from the table?"
  • );
  •  
  • // Prevent default event.
  • return( false );
  • }
  • )
  • ;
  • }
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery And Script Tags With AJAX-Table Data
  • </h1>
  •  
  • <table id="table" cellspacing="1" border="1" cellpadding="5">
  • <thead>
  • <tr>
  • <th>
  • ID
  • </th>
  • <th>
  • Name
  • </th>
  • <th>
  • Actions
  • </th>
  • </tr>
  • </thead>
  •  
  • <!--- Table data will loaded via AJAX. --->
  • </table>
  •  
  • </body>
  • </html>

As you can see, after the AJAX response HTML is appended to the table, we loop over the Script tags and associate the JSON meta-data with the target TR using jQuery's data() method. Once this is done, we can easily gather the action links in each row and perform actions based on the associated meta-data.

I was a bit irritated and disappointed that the Script tags were stripped out of the HTML when it was appended to the table. I feel that this hurts the usefulness of script-based data storage. I will keep doing some experimentation to see if I can find a way to stop that from happening. But, until then, this code was a nice demonstration of how I was thinking about using the Script tags as data containers in AJAX-powered applications.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page




Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Matt Osbun
Jun 9, 2009 at 8:19 AM // reply »
26 Comments

Interesting.

I've been playing with the idea of metadata Javascript objects to make DOM manipulation easier. I think I like this approach better than what I was doing, though.


Jun 9, 2009 at 8:29 AM // reply »
6,371 Comments

@Matt,

I'm still playing around with it. I'm not thrilled with the way that the script tags get moved around. I find it somewhat shady :)


Matt Osbun
Jun 9, 2009 at 8:52 AM // reply »
26 Comments

@Ben

It seems to me that if you're using the rel attribute and maybe storing a hashmap in the metadata, the position in the page souldnt matter as much.

Something I'm curious to play with.


Jun 9, 2009 at 8:56 AM // reply »
6,371 Comments

@Matt,

Yeah, that seems to be the way to solve this. From my experimentation, it seems that the script tags are always stripped out and added after the top-most element in the AJAX data.


Jun 11, 2009 at 3:15 PM // reply »
3 Comments

Hey Ben,

You can post Javascript along with your HTML if you're willing to do a little extra work on the server side. Something like this:

---- PAGE.CFM ---
<HTML>
<head>
<script src="script.cfm"></script>
<script>
function callback(content)
{
// do stuff with my content here...
// or call foo() from my included script
}
</script>
</head>
<body>
<cf_whatever>
</cf_whatever>
</body>
</HTML>

---- SCRIPT.CFM ---
<cfoutput>
// This file includes a regular javascript, and a bunch of HTML embedded in a callback function.
function foo(bar) {return bar++;}
callback("#JsStringFormat(myHtmlContentHere)#");
</cfoutput>


Jun 11, 2009 at 5:23 PM // reply »
6,371 Comments

@Ben,

Yeah, you can definitely pass HTML and Javascript along. And, what's nice is that in jQuery, the DOM ready method:

$( function(){} );

... will fire immediately if inside that Javascript.


Post Comment  |  Ask Ben

Recent Blog Comments
Jill
Nov 7, 2009 at 11:40 AM
How To Unformat Your Code (Like A Pro)
Derek, I think you might be right - sweet! Thanks for the link :) ... read »
Nov 7, 2009 at 11:25 AM
How To Unformat Your Code (Like A Pro)
I think it would be way easier to just use this http://www.logichammer.com/html-formatter/ He just released v3 and it rocks. ... read »
Jill
Nov 7, 2009 at 7:58 AM
How To Unformat Your Code (Like A Pro)
LMAO - this was pretty funny! I have to admit - I also love to reformat code so I can read it. My boss used to tell me to leave my OCD at home. Now I don't feel so bad after reading everyone else' ... read »
Nov 6, 2009 at 10:10 PM
How To Unformat Your Code (Like A Pro)
The timing of this post is just uncanny. I spent the last 15-20 minutes manually un-formatting my "Ben Nadel" style code within a CFC of mine. I was really digging the readability a few weeks ago, bu ... read »
Roe
Nov 6, 2009 at 5:11 PM
Passing Arrays By Reference In ColdFusion - SWEEET!
ArraySort also reorders the results of these java obj's ... read »
Nov 6, 2009 at 4:53 PM
How To Unformat Your Code (Like A Pro)
I tried to go *back* the other way. Adding formatting is actually a much more complicated problem than removing formatting. Anyway, here is what I could put together with a minimal amount of time: ... read »
Asaf
Nov 6, 2009 at 2:35 PM
ColdFusion GetPageContext() Massive Exploration
Hi, I actually found this post useful. I recently acquired a SSL certificate for my website and when I switched over to HTTPS Internet Explorer would throw an error when trying to download a dynamic ... read »
Nov 6, 2009 at 2:19 PM
How To Unformat Your Code (Like A Pro)
@Chuck, @Nathan, Well, now I feel like it's a challenge.... I accept. ... read »