4
\$\begingroup\$

I am having a huge brain fart with efficiency right now.

The idea here is if I have a static table (unfortunately formatted this way with the data I've received), how would I appropriately append a select option dropdown with every value from the table categorized easily?

I currently have it working, but it seems as if I could make it more efficient than my current statement. I have the feeling with all the DOM manipulation I have going on, if I tried to use this on a table with thousands of items it would lag the browser. Let's get to the code.

JS Fiddle: http://jsfiddle.net/z2V2p/1/

HTML:

<table id='data'>
    <tr>
      <td>Item 1</td>
      <td>Value 1</td>
      <td>Prop 1</td>
    </tr>
    <tr >
      <td>Item 2</td>
      <td>Value 2</td>
      <td>Prop 2</td>
    </tr>
    <tr >
      <td>Item 3</td>
      <td>Value 3</td>
      <td>Prop 3</td>
    </tr>
</table>

<select id="item"></select>
<select id="value"></select>
<select id="prop"></select>

Javascript/jQuery:

$('tr td').each(function() {
    var $this = $(this);
    var text = $this.text();
    var select = '<option value="'+text+'">'+text+'</option>';
    switch($this.index()){
        case 0:
          $('#item').append(select);
          break;
        case 1:
          $('#value').append(select);
          break;
        case 2:
          $('#prop').append(select);
          break;
        default:
          alert('Unexpected Error.');
     }
});

So, I suppose the questions are:

  • Is there any easy way to make this more efficient?
  • Perhaps utilizing an array to cache the values, and append them from that?
  • Or is there an easier method of using index of the items instead of my switch case that would render quicker and be more expandable for further tds if they were implemented?

I appreciate all of the help.

I've considered just ultimately converting the darn table to a json object, but I figured I'd reach out here first. (this will deploy thousands of times per week, and I don't want anything hard coded.)

Looking for a way to add every TD in its index of its TR to be appended to an existing select option based on the index value.

Basically re-categorize columns of td elements.

\$\endgroup\$
3
\$\begingroup\$

First little thing: var names are important. So

var option = '<option value="'+text+'">'+text+'</option>';

Second and main. When we are making webapps with JS, the main perfomance rule is:

Reduce access to DOM

I tried you code with 15000 tr's in Firefox and Chrome. I wrapped you code with

console.time('DOM');
...
console.timeEnd('DOM');

Results was:

  • Chrome - about 5000ms
  • Firefox - about 20000ms

Then i replaced $.append() with just strings concatenation

console.time('String');
var itemOptions = '', valueOptions = '', propOptions = '';
$('tr td').each(function() {
    var $this = $(this);
    var text = $this.text();
    var option = '<option value="'+text+'">'+text+'</option>';
    switch($this.index()){
        case 0:
            itemOptions += option;
          break;
        case 1:
            valueOptions += option;
          break;
        case 2:
            propOptions += option;
          break;
        default:
          alert('Unexpected Error.');
     }
});
$('#item').append(itemOptions);
$('#value').append(valueOptions);
$('#prop').append(propOptions);
console.timeEnd('String');

Results:

  • Chrome - about 1100ms (bravo, Chrome :))
  • Firefox - about 4000ms

If you will change your data source to a JSON or something, next optimisation will not need, but you can set first argument of .each() method (index of all td elements) to avoid using .index(). I noticed about 300-500ms of speed increase. So the last version is

console.time('String');
var itemOptions = '', valueOptions = '', propOptions = '';
$('tr td').each(function(index) {
    var $this = $(this);
    var text = $this.text();
    var option = '<option value="'+text+'">'+text+'</option>';
    var modulo = index % 3;
    switch(modulo){
        case 0 :
            itemOptions += option;
          break;
        case 1:
            valueOptions += option;
          break;
        case 2:
            propOptions += option;
          break;
        default:
          alert('Unexpected Error.');
     }
});
$('#item').append(itemOptions);
$('#value').append(valueOptions);
$('#prop').append(propOptions);
console.timeEnd('String');

Results:

  • Chrome - about 850ms
  • Firefox - about 3500ms
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

We can do some thing like this http://jsfiddle.net/z2V2p/11/

<script>
    var dataArray = [];

    dataArray[0] = ['item','Item 1','Item2','Item3','Item4'];
    dataArray[1] = ['value','Value 1','Value 2','Value 3','Value 6','Value 5'];
    dataArray[2] = ['prop','Prop 1','Prop 2','Prop 3','Prop 6','Prop 5','Prop 6'];
</script>

by this way we will remove the table and now the dom will be happy :)
if you noticed the id of the select had been added to the array now we can remove the switch too by this code:

for(i=0; i < dataArray.length; i++){
    $select = $('#'+dataArray[i][0]);
    for(i2=1; i2 < dataArray[i].length; i2++){
        var option = '<option value="'+dataArray[i][i2]+'">'+dataArray[i][i2]+'</option>';
        $select.append(option);
    }
}

but now we have a problem with loop inside loop.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Well, the idea is to capture every item inside of a 500 3 td (3 items) table. I don't want to hard code 500 values inside my code... \$\endgroup\$ – Nicholas Hazel Feb 6 '14 at 5:15
  • \$\begingroup\$ My point being, if I use a function to convert this table into different arrays, isn't that harder to accomplish than my code for the client? I mean, find DOM objects into array, then parse array into DOM seems like duplicate effort. \$\endgroup\$ – Nicholas Hazel Feb 6 '14 at 5:21
  • \$\begingroup\$ We might as well just $domObject = $domObject(converted) right...? \$\endgroup\$ – Nicholas Hazel Feb 6 '14 at 5:33
  • \$\begingroup\$ So what i understand now that we have: formatted data as table > 3 tr > multiple td and we cannot change this format, are me right ? \$\endgroup\$ – Saad Shahd Feb 6 '14 at 5:49
  • \$\begingroup\$ Well, I'm happy to use this as it works in .42s when live with 40k items. I just like to expand. So, how can we make it .10 seconds by removing a step of DOM manipulation? Answering your Q, pretend its 10,000 tr and all have 3 td items. Its just an efficiency question, as I feel I could expand the switch case more manageable and expandable. \$\endgroup\$ – Nicholas Hazel Feb 6 '14 at 5:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.