Hidden divs for "lazy javascript" loading? Possible security/other issues?

Posted by xyld on Stack Overflow See other posts from Stack Overflow or by xyld
Published on 2010-05-04T16:11:31Z Indexed on 2010/05/04 16:28 UTC
Read the original article Hit count: 231

I'm curious about people's opinion's and thoughts about this situation. The reason I'd like to lazy load javascript is because of performance. Loading javascript at the end of the body reduces the browser blocking and ends up with much faster page loads.

But there is some automation I'm using to generate the html (django specifically). This automation has the convenience of allowing forms to be built with "Widgets" that output content it needs to render the entire widget (extra javascript, css, ...). The problem is that the widget wants to output javascript immediately into the middle of the document, but I want to ensure all javascript loads at the end of the body.

When the following widget is added to a form, you can see it renders some <script>...</script> tags:

class AutoCompleteTagInput(forms.TextInput):
    class Media:                                                    
        css = {
            'all': ('css/jquery.autocomplete.css', )
        }                                             
        js = (
            'js/jquery.bgiframe.js',
            'js/jquery.ajaxQueue.js',                               
            'js/jquery.autocomplete.js',
        )       

    def render(self, name, value, attrs=None):        
        output = super(AutoCompleteTagInput, self).render(name, value, attrs)
        page_tags = Tag.objects.usage_for_model(DataSet)
        tag_list = simplejson.dumps([tag.name for tag in page_tags],
                                    ensure_ascii=False)
        return mark_safe(u'''<script type="text/javascript">                  
            jQuery("#id_%s").autocomplete(%s, {
                width: 150,                                         
                max: 10,
                highlight: false,
                scroll: true,
                scrollHeight: 100,
                matchContains: true,
                autoFill: true              
        });                               
        </script>''' % (name, tag_list,)) + output

What I'm proposing is that if someone uses a <div class=".lazy-js">...</div> with some css (.lazy-js { display: none; }) and some javascript (jQuery('.lazy-js').each(function(index) { eval(jQuery(this).text()); }), you can effectively force all javascript to load at the end of page load:

class AutoCompleteTagInput(forms.TextInput):
    class Media:                                                    
        css = {
            'all': ('css/jquery.autocomplete.css', )
        }                                             
        js = (
            'js/jquery.bgiframe.js',
            'js/jquery.ajaxQueue.js',                               
            'js/jquery.autocomplete.js',
        )       

    def render(self, name, value, attrs=None):        
        output = super(AutoCompleteTagInput, self).render(name, value, attrs)
        page_tags = Tag.objects.usage_for_model(DataSet)
        tag_list = simplejson.dumps([tag.name for tag in page_tags],
                                    ensure_ascii=False)
        return mark_safe(u'''<div class="lazy-js">                  
            jQuery("#id_%s").autocomplete(%s, {
                width: 150,                                         
                max: 10,
                highlight: false,
                scroll: true,
                scrollHeight: 100,
                matchContains: true,
                autoFill: true              
        });                               
        </div>''' % (name, tag_list,)) + output

Nevermind all the details of my specific implementation (the specific media involved), I'm looking for a consensus on whether the method of using lazy-loaded javascript through hidden a hidden tags can pose issues whether security or other related?

One of the most convenient parts about this is that it follows the DRY principle rather well IMO because you don't need to hack up a specific lazy-load for each instance in the page. It just "works".

UPDATE: I'm not sure if django has the ability to queue things (via fancy template inheritance or something?) to be output just before the end of the </body>?

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about lazy-evaluation