Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing three ways of inserting dom elements + enhancing them with jQuery mobile

I have perfomance issues when inserting data into the dom.

Insertions + jQuery mobile enhancement done on pagecontainerbeforeshow() event, jQuery mobile version 1.4.2.

I have tried to see which would be the fastest approach by comparing three simplified versions of what I want to do:

jQuery approach :

for(var i=0;i<2000;++i){
    $('<div>').attr({'data-role':'collapsible','id':'asdf'+i+''}).html('<h2>asdf</h2>').appendTo("#manage_content");
    $('<ul>').attr({'data-role':'listview'}).html('<li>bit</li>').appendTo('#asdf'+i+'');
    }
$('#manage').trigger('create');

Pure js, creating all nodes :

var d=document.createDocumentFragment();
var title,listitem,list;
var coll=new Array();
for(var i=0;i<2000;++i){
coll[i]=document.createElement('div');
coll[i].setAttribute("data-role", "collapsible");
title = document.createElement('h2');
title.innerHTML='asdf';
coll[i].appendChild(title);
list=document.createElement('ul');
list.setAttribute("data-role","listview");
listitem = document.createElement('li');
listitem.innerHTML='bit';
list.appendChild(listitem);
coll[i].appendChild(list);
d.appendChild(coll[i]);
}
document.getElementById("manage_content").appendChild(d);
$('#manage').trigger('create');

jQuery with big string :

var html='';
for(var i=0;i<2000;++i){
    html+='<div data-role="collapsible"><h2>asdf<h2><ul data-role="listview"><li>bit</li></ul></div>';
}
$('#manage_content').append(html);
$('#manage').trigger('create');

To my surprise, the three ways of doing this give same result (around 7seconds execution time...)

Am I doing any of the ways wrong? Is there a better way?

I have seen lots of questions related to this topic but mostly outdated or stating that the pure javascript should be faster, which is not the case for me.

Without jQuery enhancement :

  • jQuery standard : ~400ms
  • Pure JS : ~40ms
  • jQuery big string : ~80ms
    So pure javascript with document fragments is the best even though it is horrible to read/write x_x

    With jQuery enhancement :

    Test here (credits to @Omar)

  • like image 521
    IazertyuiopI Avatar asked Nov 10 '22 06:11

    IazertyuiopI


    1 Answers

    Here is what one can do to speed up dom insertion + enhancement, assuming one only uses jquery mobile for css formatting.

  • For the insertion part : as many comments suggest, method 3 seems to be the best option, because the small perfomance gain of method 2 is not enough to make up for its lack of readability, which would turn the enhancement part into hell...

  • For the enhancement part :

  • -- Add all the jquery mobile classes manually to html elements
    -- Do not add any data-% attribute.
    -- Do not call $('your_page').trigger('create') or $('.ui-content').enhanceWithin()
    -- Add desired widget events manually instead.

    Performance gain :

    With regular jquery mobile enhancement, the page creation took 2s in my worst case of use.
    With this method, it is around 50ms... so 40* perf increase...

    The code below is for a sample case (mine obviously) of two nested collapsiblesets and a listview as last child. If someone is interested I could add jsperf for x times this element insertion + enhancement.

    fiddle : http://jsfiddle.net/3pyRX/1/

    HTML:

    <div data-role='content'>
    
    <div class="ui-collapsible ui-collapsible-themed-content">
                            <h2 class="ui-collapsible-heading">
                            <a href="#" class="ui-collapsible-heading-toggle ui-btn ui-icon-plus ui-btn-icon-left ui-btn-b">Employee collapsible</a>
                            </h2>
                            <div class="ui-collapsible-content ui-body-inherit" style="display:none;">
                                <div class="ui-collapsible ui-collapsible-themed-content">
                                    <h2 class="ui-collapsible-heading">
                                    <a class="ui-collapsible-heading-toggle ui-btn ui-icon-plus ui-btn-icon-left ui-btn-b">
                                        <p class="inline">Child collapsible</p>
                                        <p class="inline coll_head_butt timecard ui-link ui-btn ui-btn-b ui-icon-check ui-btn-icon-notext ui-shadow ui-corner-all"></p>
                                    </a>
                                    </h2>
                                    <div class="ui-collapsible-content ui-body-inherit" style="display:none;">
                                        <ul class="ui-listview">
                                        <li class="projectxtask ui-li-has-count"><a class="ui-btn">li 1<span class="ui-li-count ui-body-inherit">42</span></a></li>
                                        <li><a class="ui-btn">li 2</a></li><li><a class="ui-btn">li 3</a></li>
                                        </ul>
                                    </div>
                                </div>
                            </div>
                        </div>
    </div>
    


    CSS:

    .projectxtask a{
    
        background-color:#33ccff !important;
        padding-right:2.6em !important;
        border-top:1px solid black !important;
        border-bottom:1px solid black !important;
    }
    .inline{display:inline !important;}
    
    
    .coll_head_butt{
        margin-left : 20px !important;
        border-style:none !important;
        box-shadow:none !important;
    }
    


    JS:

    $('.ui-collapsible-heading').on('click',function(event,ui){
    
        var coll_content = $(this).siblings();
        if(coll_content.is(":visible"))
            {$('a',this).removeClass( "ui-icon-minus" ).addClass( "ui-icon-plus" );
            coll_content.hide();}
        else
            {$('a',this).removeClass( "ui-icon-plus" ).addClass( "ui-icon-minus" );
            coll_content.show();}   
    });
    

    The code is a bit annoying to write but if you have similar performance issues as mine jquery mobile it is well worth it.

    I added the icon inside the collapsible header in this sample because with jquery mobile, you would use <.a data-icon=check data-iconpos=notext data-role=button> to get an icon button, which is not possible to do without jquery mobile enhancement because nested <.a> tags are not allowed in html and will be corrected by the browser.
    When manually adding classes, replacing the <.a> with a <.p> like I did here seemingly works.

    like image 158
    IazertyuiopI Avatar answered Nov 14 '22 23:11

    IazertyuiopI