Using jQuery Clone to Add Dynamic Data

As a User Interface Expert first and Programmer second, I put a lot of consideration into how I code. With every step, I do my best to ensure that designers with less programming experience will be able to accomplish what they’d like. This distinction in programming methods is most clear in how I place dynamic data onto the page.

Whereas many scripts embed the html markup into their javascript, I much prefer to leave it on the page. More specifically, I prefer to leave a model of the html on the page, and to inject the dynamic data using that model. As my example, I’ll continue yesterday’s post on a rolling delicious feed.

If you’d like to skip ahead, you can view the demo here, or scroll down to view the whole block of code.

But I prefer to break things down first. Let’s look at my so-called model:

<div id="deliciousList">
    <div id="deliciousModel" class="model item">
        <p><a class="url"><span class="title"></span></a></p>
        <p>Posted by: <span class="author"></span></p>
		<p>Tags: <span class="tags"></span></p>
    </div>
</div>

Notice that it creates the delicious list, and that inside it is an “item”. We’ll be identifying this model, and duplicating it as many times as we need to. When it’s duplicated, we’ll simply find the spans with the appropriate classes, and insert content. It’s easy and processor efficient, see for yourself:

// Clone duplicates the model (with bindings), strips model class/id, gives a unique id, and then adds it before the model
 $("#deliciousModel").clone(true).removeAttr("id") .removeClass("model").attr("id", "del" + i).insertBefore("#deliciousModel")

 // The finds get each class from within the model and replace it with values from the feed.
 .find(".url").attr("href", entry.u).end()
 .find(".author").html(entry.a).end()
 .find(".tags").html(processedTags).end()
 .find(".title").html(entry.d);

The first line does the cloning, removes the identifying attributes (and class model causes a display:hide;), and inserts the new block.

The subsequent lines insert the appropriate data. Each “find” and “end” here is really important. By chaining the javascript, we’re preventing the code from constantly searching the entire document, and we’re containing the modifications to the model itself.

For the entire block of code, view below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Delicious Feed</title>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>
<script type="application/javascript">
    $(document).ready(function(){
// DELICIOUS JSON -- http://feeds.delicious.com/v2/json/tag/hyperstudio
$.getJSON('delicious-json.php', function(data){
$.each(data, function(i, entry) {

tags = entry.t;
tagLength = tags.length;
processedTags = '';

jQuery.each(tags, function(i, val) {
processedTags += ' ' + val;
if (i < tagLength - 1) processedTags += ',';
});

// Clone duplicates the model (with bindings), strips model class/id, gives a unique id, and then adds it before the model
$("#deliciousModel").clone(true).removeAttr("id") .removeClass("model").attr("id", "del" + i).insertBefore("#deliciousModel")

// The finds get each class from within the model and replace it with values from the feed.
.find(".url").attr("href", entry.u).end()
.find(".author").html(entry.a).end()
.find(".tags").html(processedTags).end()
.find(".title").html(entry.d);

if ( i == 10 )  return false; // Limit to 10 entries

});
});
    });
</script>
<style type="text/css">
html { font-size:10px; font-family:Arial, Helvetica, sans-serif;}
a {color:#066; font-size:12px;}
p {margin:0; padding:0;}
a:hover {color:#099;}
#deliciousList {border:1px solid #333; width:400px; margin:0 auto; padding:0 10px;}
.item {margin:10px 0;}
.clear {clear:both;}
.model {display:none;}
</style>
</head>
<body>
<div id="deliciousList">
    <div id="deliciousModel" class="model item">
        <p><a class="url"><span class="title"></span></a></p>
        <p>Posted by: <span class="author"></span></p>
<p>Tags: <span class="tags"></span></p>
    </div>
</div>
</body>
</html>

Calling Remote JSON Files via Javascript / jQuery

Not too long ago, I was asked to create a rolling delicious feed using their JSON data. It took me quite a while to realize what was going wrong – but the solution was obvious as soon as the problem became clear. If you’re going down the same path, maybe this bit of advice will help.

Firstly, you have to create a local reference of the JSON data. As I understand it, this has to do with the JSON server settings and security. In any event, it’s easy enough to do. Create a file, such as my delicious-json.php. All you need to put in it is this:


<?php
echo file_get_contents("http://feeds.delicious.com/v2/json/tag/hyperstudio");
?>

Easy peasy. Now you can reference it via jQuery, like so:

<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>
$(document).ready(function(){
// DELICIOUS JSON -- http://feeds.delicious.com/v2/json/tag/hyperstudio
  $.getJSON('delicious-json.php', function(data){
    $.each(data, function(i, entry) {
      // Process your data here
    });
  });
});

How you use the JSON is up to you. In tomorrow’s post, I’ll describe my preferred method – cloning a model. Doing so has a lot of speed benefits, but more importantly, it separates the html from the javascript. As a consequence, any web designer can easily step in and modify the aesthetics without touching code. This facilitates the very important separation of concerns.