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.
Test here (credits to @Omar)
Here is what one can do to speed up dom insertion + enhancement, assuming one only uses jquery mobile for css formatting.
-- 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With