JQuery:Inserting big amounts of html through DOM manipulation - maintainability?
-
29-10-2019 - |
Question
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 id
s 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);
}
}
});
Obviously that's a quick-and-dirty, but you get the idea. If you use data-xyz
attributes (allowed in HTML5), name
s, class
es, etc., you can avoid tying your code too closely to your structure.
OTHER TIPS
In this case, you could grab the contents of #phones
during the ready event:
$(document).ready(function() {
var phnFragment = $("#phones").html();
$('#addmorephones').click(function() {
$("#phones").append(phnFragment);
});
});
If you need to copy more complex information (like events), you can use the .clone() method:
$(document).ready(function() {
var $phnFragment = $("#phones").children().clone();
$('#addmorephones').click(function() {
$("#phones").append($phnFragment.clone());
});
});
T.J. has a great answer if you've got existing markup you want to reuse. You can also use the text/html script type to put your content in markup as a template, as demonstrated here: