On contemporary websites and web applications, it is extremely common task to display a list of items on page. In any reasonable framework and/or templating engine, this can be accomplished rather trivially. Here’s how it could look like in Jinja or Django templates:
While it isn’t a hindrance by itself (there are many great tools to help, including Mustache or – sadly discontinued – jQuery Templates), it raises an issue of code duplication. Ideally, we would still want some initial data to be displayed just when the page itself is loaded. And at first, this seems as to require both server-side and client-side rendering functions… I hope I do not really have to explain why it would be a mighty bad idea to create, use and (try to) maintain them.
That’s why we would opt for rendering exclusively in the browser. Fortunately, it is not only possible, but also quite easy if we already have the logic for handling AJAX calls. Using it, we can prepare initial items in JSON format and put them directly inside some
|json filter represents the before mentioned logic, while
renderItems draws the objects-turned items as children of given element. What it does inside can vary from manipulating HTML strings directly (eww!), creating DOM objects (slightly better) or invoking some JS templating engine (best).
A simple solution, outlined above, looks sufficient for many practical applications. It is far from ideal, though. For one, it suffers from an acute disconnection, since the actual place where the data is displayed (
$('#items')) can be arbitrarily far from the
<script> tag. But more importantly, it scales poorly and lacks modularity: should we need to use our list on more than one site, we may need to carefully tailor several moving parts – such as the
Incidentally, both of those issues can be resolved at once. Let’s create a self-replacing
<script>: quite similar to the one above, but with some interesting twists. Rather than referencing some DOM element via hard-coded selector, it shall render the items “where they stand”: exactly where the very
<script> is located. And just as a final touch, the script will even remove itself from the DOM tree when it’s no longer needed.
Sounds like a pretty clever trick, but it’s not exactly complicated at all. In its entirety, it can look somewhat like this:
What makes it work is the fact that
var $script = ...; line lies outside of the
$document.ready function. Thanks to that, it is executed as soon as the
<script> block is parsed – before the rest of document is processed, and way before the
$(document).ready callback is invoked.
At that early time, this script is therefore the last
<script> element in the DOM tree. In other words, it’s exactly what
$('script').last() will return! What we are doing in the first line is therefore nothing else, but obtaining a reference to the enclosing
How’s that useful, though?… Well, if we have indeed dropped this
<script> right where we wanted our dynamic list to display, its
parent() would be the element to render our items in. And because we don’t mind cleaning up after ourselves when done, we finish this by
remove()-ing the script. Nice and tidy.
What makes it a pretty powerful technique is easy and flexible integration with modern templating engines. We can almost effortlessly made this snippet into a reusable template part, such as Jinja macro:
The final usage would be then extremely clean and simple:
Adding comments is disabled.Comments are disabled.