jquerydomcode-maintainability

JQuery:Inserting big amounts of html through DOM manipulation - maintainability?


I've found good posts on good practices inserting dom elements using jquery like this, this and this

It's ok when you just need to insert a few elements, but it seems to me that these option are very bad from the point of view of maintainability (Code is repeated twice, thus if any change is needed it needs to happen twice then it becomes very prone to error ),

This is (just a small part) what I've got

<script type="text/javascript">
var phnFragment = "<tr><td align=\"right\">Telephone:</td><td colspan=\"2\"><select name=\"select\" size=\"1\"style=\"width: 100px;\"><option>-- Choose --</option><option>Home</option><option>Mobile</option><option>Work</option></select><input type=\"text\" size=\"20px\" /></td></tr>";
    $(document).ready(function() {
    $('#addmorephones').click(function() {
                $("#phones").append(phnFragment);
            });
    });
</script>
....
....
<tr id="phones">
        <td align="right">Telephone:</td>
        <td colspan="2"><select name="select" size="1"
            style="width: 100px;">
            <option>-- Choose --</option>
            <option>Home</option>
            <option>Mobile</option>
            <option>Work</option>
        </select><input type="text" size="20px" /> <a href="javascript:void(0);" id="addmorephones">[+]</a>
        </td>
    </tr>

Is there a better way to accomplish this? Is there a way to tell jquery to copy part of the dom tree and use it as fragment to insert?

Would love to learn alternatives


Solution

  • Is there a way to tell jquery to copy part of the dom tree and use it as fragment to insert?

    Yes: clone. (You don't even really need jQuery for it; cloneNode is part of the DOM API.) If you have any id values in what you clone, you'll need to iterate over the result changing them, of course, since ids have to be unique. But it's perfect for things like table rows and the like.

    On page load, you can grab one of the real ones, clone it (without attaching it to the document), cleanse it of anything you don't need, and then just keep cloning that model. Helps keep your JavaScript somewhat decoupled from your markup.

    Example:

    HTML:

    <table>
      <tbody>
        <tr><td>I'm a row in the table</td></tr>
      </tbody>
    </table>
    

    JavaScript:

    jQuery(function($) {
      var counter = 10,
          rowModel;
    
      // Get the row model, clone it, remove the
      // content we'll replace anyway.
      rowModel = $("tr:first").clone();
      rowModel.find("td:first").empty();
    
      // Do our first tick
      tick();
    
      // Use the model to append to the table
      function tick() {
        var clone = rowModel.clone();
    
        clone.find("td:first").html("Added at " + new Date());
        $("tbody:first").append(clone);
    
        // Again?
        if (--counter > 0) {
          setTimeout(tick, 500);
        }
      }
    
    });
    

    Live copy

    Obviously that's a quick-and-dirty, but you get the idea. If you use data-xyz attributes (allowed in HTML5), names, classes, etc., you can avoid tying your code too closely to your structure.