Note that there are some explanatory texts on larger screens.

plurals
  1. POjavascript loop slows per iteration
    text
    copied!<p>I have a javascript FOR loop that adds a row to a table, as part of a web form, for each iteration of the loop. The loop gets progressively slower as it goes. </p> <p>Here are times for a table in which 15 rows were added:</p> <pre><code> sample 1 start: 1355250090.832 end: 1355250090.873 difference: 0.041 sample 2 start: 1355250090.873 end: 1355250090.952 difference: 0.079 sample 3 start: 1355250090.953 end: 1355250091.393 difference: 0.440 sample 4 start: 1355250091.393 end: 1355250091.659 difference: 0.266 sample 5 start: 1355250091.659 end: 1355250092.284 difference: 0.625 sample 6 start: 1355250092.284 end: 1355250093.159 difference: 0.875 sample 7 start: 1355250093.159 end: 1355250093.863 difference: 0.704 sample 8 start: 1355250093.863 end: 1355250094.924 difference: 1.061 sample 9 start: 1355250094.924 end: 1355250095.924 difference: 1.000 sample 10 start: 1355250095.924 end: 1355250097.175 difference: 1.251 sample 11 start: 1355250097.175 end: 1355250098.362 difference: 1.187 sample 12 start: 1355250098.362 end: 1355250099.690 difference: 1.328 sample 13 start: 1355250099.690 end: 1355250101.378 difference: 1.688 sample 14 start: 1355250101.378 end: 1355250103.003 difference: 1.625 sample 15 start: 1355250103.003 end: 1355250104.878 difference: 1.875 </code></pre> <p>Here is the javascript for the function that adds the table row:</p> <pre><code> function addSample(){ fTrain+="addSample();&lt;br&gt;"; var sample=""; var temp=""; var tempString=""; var endCode=""; var helper1=""; var helper2=""; var dcf=""; var dct=""; var useDate=false; var dateToUse=""; var slDays=""; var tsid=""; var tabNDX=0; //alert(sampleCount.toString()); //$("#statUpdate").html("adding sample: "+sampleCount.toString()); if(sampleCount&gt;=20){ var tdt="WARNING\n"; tdt+="You have exceeded 20 samples. To avoid data loss, you should not put more "; tdt+="than 20 samples per submission."; alert(tdt); } // copy existing values into array if(sampleCount&gt;=1){ var tArray=""; tArray=copyValues(); var ticArray=""; ticArray=copyTics(); } if(ie){ endCode="&lt;/TABLE&gt;&lt;BR&gt;&amp;nbsp;"; // for some reason this has to be upper case in IE }else{ endCode="&lt;/table&gt;&lt;br&gt;&amp;nbsp;"; } sampleCount=sampleCount+1; tabNDX=1000+(sampleCount*20); // needs a buffer to seperate from other tab indecies in virtual windows if (bColor=="#ffffff"){ bColor=ltOrange; }else{ bColor="#ffffff"; } // add header on first addition only if(sampleCount==1){ sample+="&lt;table border='1' id='sampleTable' style='border-collapse:collapse;border:1pt solid black'&gt;"; sample+="&lt;tr&gt;"; sample+="&lt;th class='tsmall'&gt;copy cell &lt;input onChange='needSave=1;' checked type='checkbox' name='CST' id='CST'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&amp;nbsp;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CGL' id='CGL'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CPT' id='CPT'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CCM' id='CCM'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CDP' id='CDP'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CED' id='CED'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CDVT' id='CDVT'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CTSPD' id='CTSPD'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CVSPD' id='CVSPD'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CMNM' id='CMNM'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CE' id='CE'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' style='visibility:hidden' type='checkbox' name='CDVM' id='CDVM'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&lt;input onChange='needSave=1;' checked type='checkbox' name='CTECH' id='CTECH'&gt;&lt;/th&gt;"; sample+="&lt;th class='tsmall'&gt;&amp;nbsp;&lt;/th&gt;"; sample+="&lt;/tr&gt;"; sample+="&lt;tr&gt;"; sample+="&lt;th class='ysmall' style='background:#ffffff' colspan='7'&gt;&amp;nbsp;&lt;/th&gt;"; sample+="&lt;th class='ysmall' colspan='4'&gt;Stud Targets&lt;/th&gt;"; sample+="&lt;th class='ysmall' style='background:#ffffff' colspan='6'&gt;&amp;nbsp;&lt;/th&gt;"; sample+="&lt;/tr&gt;"; sample+="&lt;tr&gt;"; sample+="&lt;th class='small'&gt;Sample type&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Sample ID&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Genetics&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Pkg. type&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Conc.&lt;br&gt;method&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Date&lt;br&gt;processed&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Expiration&lt;br&gt;date&lt;/th&gt;"; sample+="&lt;th class='small'&gt;DVT&lt;/th&gt;"; sample+="&lt;th class='small'&gt;TSD&lt;/th&gt;"; sample+="&lt;th class='small'&gt;VSD&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Min&lt;br&gt;normal&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Extender&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Dose vol.&lt;/th&gt;"; sample+="&lt;th class='small'&gt;Proc. tech&lt;/th&gt;"; sample+="&lt;th class='small'&gt;del&lt;/th&gt;"; sample+="&lt;/tr&gt;"; // decide if to copy date from above dcf=document.getElementById('dateCollectedFrom').value; dct=document.getElementById('dateCollectedTo').value; // same date if(dcf==dct){ useDate=true; dateToUse=dcf; } if(useDate===false){ // one date only has value if( dcf!=="" &amp;&amp; dct==="" ){ useDate=true; dateToUse=dcf; } // one date only has value if( dct!=="" &amp;&amp; dcf==="" ){ useDate=true; dateToUse=dct; } } // end date decision block } // end if sample counter == 1 // sample guts var sc=sampleCount.toString(); sample+="&lt;tr id='tr_"+sc+"' &gt;"; var inputSize="4"; // default text box input size // sample type sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;select onChange='needSave=1;' tabindex='"+(tabNDX).toString()+"' style='background:"+bColor+";font-size:8pt;' name='sampleType_"+sc+"' id='sampleType_"+sc+"' "; sample+="onClick=\"if(this.value.indexOf('other')&gt;-1){document.getElementById('otherSample_"+sc+"').style.visibility='visible'}else{document.getElementById('otherSample_"+sc+"').style.visibility='hidden'};\" " ; sample+="onBlur=\"if(this.value.indexOf('other')&gt;-1){document.getElementById('otherSample_"+sc+"').style.visibility='visible'}else{document.getElementById('otherSample_"+sc+"').style.visibility='hidden'};\" &gt;"; sample+="&gt;"+sampleTypes()+"&lt;/select&gt;&lt;br&gt;"; sample+="&lt;input size='10' style='background:"+bColor+";font-size:8pt;visibility:hidden' type='text' name='otherSample_"+sc+"' id='otherSample_"+sc+"'&gt;&lt;/td&gt;" ; // sample ID tsid=""; sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;input onkeypress='return checkKey2(this,event);' onchange='needSave=1;updateAnaArray(this.value,"+sc+");' tabindex='"+(tabNDX+1).toString()+"' size='8' style='background:"+bColor+";font-size:8pt;' "+tsid+" type='text' name='sampleID_"+sc+"' id='sampleID_"+sc+"'&gt;&lt;br&gt;"; sample+="&lt;button style='font-size:8pt' onmouseout='hoverAnalysis(\"clear\");' onmouseover='hoverAnalysis("+sc+");' onClick='if(uniqueSample("+sc+")){analyze("+sc+")}'&gt;Analysis&lt;/button&gt;"; sample+="&lt;span style='display:none;' id='osid_"+sc+"'&gt;&lt;/span&gt;"; sample+="&lt;/td&gt;" // genetic line-breed sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;input onChange='needSave=1;' tabindex='"+(tabNDX+2).toString()+"' size='"+inputSize+"' style='background:"+bColor+";font-size:8pt;' type='text' name='glb_"+sc+"' id='glb_"+sc+"'&gt;&lt;/td&gt;"; // packaging type sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;" sample+="&lt;span onClick='displayPT("+sc+")' onMouseOver='this.style.cursor=\"pointer\"' style='font-size:8pt' id='pthDisplay_"+sc+"'&gt;[+]&lt;/span&gt;&lt;br&gt;"; sample+="&lt;div id='ptHolder_"+sc+"' style='display:none'&gt;"; sample+="&lt;select style='background:"+bColor+";font-size:8pt;' name='packageType_"+sc+"' id='packageType_"+sc+"' "; sample+="onChange='needSave=1;packageLogic("+sc+")' "; sample+="onBlur='packageLogic("+sc+")' "; sample+="&gt;"+packagingTypes()+"&lt;/select&gt;"; sample+="&lt;span id='pkt_"+sc+"'&gt;&lt;/span&gt;&lt;input size='10' style='background:"+bColor+";font-size:8pt;display:inline' type='text' name='otherPackage_"+sc+"' id='otherPackage_"+sc+"'&gt;"; sample+="&lt;div id='packDiv_"+sc+"'&gt;&lt;/div&gt;"; sample+="&lt;/div&gt;"; sample+="&lt;/td&gt;" // concentration method sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;select onChange='needSave=1;' style='background:"+bColor+";font-size:8pt;' name='cm_"+sc+"' id='cm_"+sc+"' "; sample+="onClick='checkCM("+sc+")' "; sample+="onBlur='checkCM("+sc+")' "; sample+="&gt;"+cMethod()+"&lt;/select&gt;&lt;br&gt;"; sample+="&lt;span name='cmSpan_"+sc+"' id='cmSpan_"+sc+"' &gt;"; sample+="&lt;input size='8' onChange='needSave=1;' style='background:"+bColor+";font-size:8pt;visibility:visible' type='text' name='otherCM_"+sc+"' id='otherCM_"+sc+"'&gt;"; sample+="&lt;/span&gt;&lt;br&gt;"; sample+="&lt;span name='oOtherCM_"+sc+"' id='oOtherCM_"+sc+"' &gt;"; sample+="&lt;/span&gt;&lt;/td&gt;"; // date processed helper2="storageLife_"+sc; if(sampleCount==1){ // put in default date if logic fulfilled sample+="&lt;td valign='top' align='right' style='background:"+bColor+";'&gt;&lt;input onChange='needSave=1;' tabindex='"+(tabNDX+7).toString()+"' value='"+dateToUse+"' size='8' onBlur='if(this.value!=\"\"){if(isDate(this.value,1)==false){this.focus()}else{"; }else{ sample+="&lt;td valign='top' align='right' style='background:"+bColor+";'&gt;&lt;input onChange='needSave=1;' tabindex='"+(tabNDX+7).toString()+"' size='8' onBlur='if(this.value!=\"\"){if(isDate(this.value,1)==false){this.focus()}else{"; } sample+="figureLife(document.getElementById(\""+helper2+"\").value,"+sc+",\"dp\");}}' style='background:"+bColor+";font-size:8pt;' type='text' name='dateProc_"+sc+"' id='dateProc_"+sc+"'&gt; "; helper1="dateProc_"+sc; sample+="&lt;button id='labDO1_"+sc+"' onClick='displayDatePicker(\""+helper1+"\")' style='width:10px;height:10px'&gt;&lt;/button&gt;&lt;br&gt;"; sample+="&lt;span id='labSLD_"+sc+"' style='font-size:8pt;background:#ffffc0;'&gt;storage life:&lt;/span&gt;&lt;br&gt;"; if(sc==1){ slDays=" value='5' "; }else{ slDays=""; } sample+="&lt;/td&gt;"; // expiration date helper1="expirationDate_"+sc; sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;input tabindex='"+(tabNDX+8).toString()+"' size='8' onChange='needSave=1' onBlur='figureLife(document.getElementById(\""+helper2+"\").value,"+sc+",\"ed\");' style='background:"+bColor+";font-size:8pt;' type='text' name='expirationDate_"+sc+"' id='expirationDate_"+sc+"'&gt; "; sample+="&lt;button id='labDO2_"+sc+"' onClick='displayDatePicker(\""+helper1+"\");' style='width:10px;height:10px'&gt;&lt;/button&gt;&lt;br&gt;"; // storage life sample+="&lt;input style='background:#ffffc0' "+slDays+" size='"+inputSize+"' onBlur='figureLife(this.value,"+sc+",\"sl\")' onChange='needSave=1;figureLife(this.value,"+sc+",\"sl\")' style='background:"+bColor+";font-size:8pt;' type='text' name='storageLife_"+sc+"' id='storageLife_"+sc+"'&gt;&lt;/td&gt;"; // dose volume target (dvt) sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;input tabindex='"+(tabNDX+9).toString()+"' onChange='needSave=1;checkField(this.value,\"dv\",this.id)' size='"+inputSize+"' style='background:"+bColor+";font-size:8pt;' type='text' name='dvt_"+sc+"' id='dvt_"+sc+"'&gt;&lt;/td&gt;"; // total sperm per dose (tsd) sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;input tabindex='"+(tabNDX+10).toString()+"' onChange='needSave=1;checkField(this.value,\"vs\",this.id)' size='"+inputSize+"' style='background:"+bColor+";font-size:8pt;' type='text' name='tspd_"+sc+"' id='tspd_"+sc+"'&gt;&lt;/td&gt;"; // viable sperm per dose VSD sample+="&lt;td valign='top' align='right' style='background:"+bColor+";'&gt;&lt;input tabindex='"+(tabNDX+11).toString()+"' size='6' onChange='needSave=1;checkField(this.value,\"vs\",this.id)' style='background:"+bColor+";font-size:8pt;' type='text' name='vspd_"+sc+"' id='vspd_"+sc+"'&gt;&lt;br&gt;"; sample+="&lt;span style='font-size:8pt;background:#ffffc0' id='labMOT_"+sc+"' &gt;motil&lt;input onChange='needSave=1;' tabindex='"+(tabNDX+12).toString()+"' type='checkbox' id='vspdMot_"+sc+"' name='vspdMot_"+sc+"'&gt;&lt;/span&gt;"; sample+="&lt;/td&gt;"; // minimum normal morphology sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;input tabindex='"+(tabNDX+13).toString()+"' onChange='needSave=1;checkField(this.value,\"mn\",this.id)' size='6' style='background:"+bColor+";font-size:8pt;' type='text' name='mnm_"+sc+"' id='mnm_"+sc+"'&gt;&lt;br&gt;"; sample+="&lt;span style='font-size:8pt;background:#ffffc0' id='labMOR_"+sc+"' &gt;morph&lt;input onChange='needSave=1;' tabindex='"+(tabNDX+14).toString()+"' type='checkbox' id='vspdMor_"+sc+"' name='vspdMor_"+sc+"'&gt;&lt;/span&gt;&lt;/td&gt;"; // extender sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;select onChange='needSave=1;' tabindex='"+(tabNDX+15).toString()+"' style='background:"+bColor+";font-size:8pt;' name='extender_"+sc+"' id='extender_"+sc+"' "; sample+="onClick=\"if(this.value.indexOf('other')&gt;-1){document.getElementById('otherExtender_"+sc+"').style.visibility='visible'}else{document.getElementById('otherExtender_"+sc+"').style.visibility='hidden'};\" " ; sample+="onBlur=\"if(this.value.indexOf('other')&gt;-1){document.getElementById('otherExtender_"+sc+"').style.visibility='visible'}else{document.getElementById('otherExtender_"+sc+"').style.visibility='hidden'};\" &gt;"; sample+="&gt;"+extenderTypes()+"&lt;/select&gt;&lt;br&gt;"; sample+="&lt;input size='10' onChange='needSave=1;' style='background:"+bColor+";font-size:8pt;visibility:visible' type='text' name='otherExtender_"+sc+"' id='otherExtender_"+sc+"'&gt;"; // pooled-ss // they decided not to use this field so I'm just hiding it under extender // instead of changing all of the management functions and CGI sample+="&lt;span style='display:none'&gt;"; sample+="&lt;br&gt;&lt;span sid='labP_"+sc+"' &gt;Pooled:&lt;/span&gt;&lt;input onChange='needSave=1;' type='radio' name='pss_"+sc+"' id='Ppss_"+sc+"'&gt;&lt;br&gt;" ; sample+="&lt;span id='labSS_"+sc+"' &gt;SS:&lt;/span&gt; &lt;input onChange='needSave=1;' type='radio' name='pss_"+sc+"' id='Spss_"+sc+"'&gt;" ; sample+="&lt;/span&gt;"; sample+="&lt;/td&gt;" ; // dose volume measured sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;input tabindex='"+(tabNDX+17).toString()+"' onChange='needSave=1;checkField(this.value,\"dv\",this.id)' size='"+inputSize+"' style='background:"+bColor+";font-size:8pt;' type='text' name='dvm_"+sc+"' id='dvm_"+sc+"'&gt;&lt;br&gt;"; sample+="&lt;span style='font-size:8pt'&gt;Client tech:&lt;/span&gt;&lt;br&gt;"; sample+="&lt;input onChange='needSave=1;' size='8' tabindex='"+(tabNDX+18).toString()+"' style='background:"+bColor+";font-size:8pt;' type='text' id='cTech_"+sc+"' name='cTech_"+sc+"'&gt;&lt;/td&gt;"; // proc tech sample+="&lt;td valign='top' style='background:"+bColor+";'&gt;&lt;span style='font-size:8pt'&gt;KRC tech:&lt;/span&gt;&lt;br&gt;&lt;select onChange='needSave=1;' tabindex='"+(tabNDX+19).toString()+"' style='background:"+bColor+";font-size:8pt;' name='KRCtech_"+sc+"' id='KRCtech_"+sc+"'&gt;"+techList+"&lt;/select&gt;"; sample+="&lt;/td&gt;"; // remove sample sample+="&lt;td align='center' valign='center' style='background:"+bColor+";'&gt;&lt;br&gt;&lt;button id='labDB_"+sc+"' class='bClass' style='width:25px' onClick='needSave=1;removeSample("+sc+");'&gt;&lt;img src='"+httpsBase+"/images/rem.gif'&gt;&lt;/button&gt;&lt;/td&gt;"; // end row sample+="&lt;/tr&gt;"; var sh=document.getElementById('sampleHolder'); if(sampleCount==1){ sample+=endCode; sh.innerHTML=sample; }else{ // adjust ending html // firefox is stripping out extender values here?? // save extender values // also mot/morph values var theEx=new Array(); var theMot=new Array(); var theMor=new Array(); for(var i=1;i&lt;=(sampleCount-1);i++){ theEx[i]=$("#extender_"+i.toString()).val(); theMot[i]=$("#vspdMot_"+i.toString()).attr('checked'); theMor[i]=$("#vspdMor_"+i.toString()).attr('checked'); } temp=sh.innerHTML; tempString=replace(temp,endCode,""); sh.innerHTML=tempString+sample+endCode; } var ef=getEdit(); if(ef != -1){ // only paste values when entering a new sample if(sampleCount!=1){ // must value tics before pasting values!! pasteTics(ticArray); pasteValues(tArray); } } ticArray=[]; tArray=[]; // replace extender values if(sampleCount&gt;1){ for(i=1;i&lt;=(sampleCount-1);i++){ $("#extender_"+i.toString()).val(theEx[i]); $("#vspdMot_"+i.toString()).prop("checked",theMot[i]); $("#vspdMor_"+i.toString()).prop("checked",theMor[i]); } // make the new sample "other" $("#extender_"+sampleCount.toString()).val("other"); // if copy down extender is checked then apply to new sample if( $('#CE').is(':checked')){ var lastCE=$("#extender_"+(sampleCount-1).toString()).val(); $("#extender_"+sampleCount.toString()).val(lastCE); } if( $('#CVSPD').is(':checked')){ var lastMot=$("#vspdMot_"+(sampleCount-1).toString()).attr('checked'); $("#vspdMot_"+(sampleCount).toString()).prop("checked",lastMot); } if( $('#CMNM').is(':checked')){ var lastMor=$("#vspdMor_"+(sampleCount-1).toString()).attr('checked'); $("#vspdMor_"+(sampleCount).toString()).prop("checked",lastMor); } } for(i=1;i&lt;=maxIterations;i++){ //for(i=1;i&lt;=sampleCount;i++){ if(document.getElementById("sampleID_"+i.toString())){ loadIconAnalysis( $("#sampleID_"+i.toString()).val() ); } } } // end add sample </code></pre> <p>this is how the addSample() function is called and my times were taken:</p> <pre><code> for(i =1;i&lt;=editSampleCount;++i){ sseconds = new Date().getTime() / 1000; tempTime+="sample "+i.toString()+" start: "+sseconds.toFixed(3)+" "; $(document).ready(function() { addSample(); }); eseconds = new Date().getTime() / 1000; tempTime+="end: "+eseconds.toFixed(3)+" difference: "+(eseconds-sseconds).toFixed(3)+"&lt;br&gt;"; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload