tags:

views:

27

answers:

3

I have loaded a table of data into an HTML page so that it looks like this:

<div id="objList" style="display:none">
    <div class="objRecord">
        <div class="objID">6846</div>
        <div class="objColor">blue</div>
        <div class="objSize">500</div>
        <div class="objType">Q</div>
    </div>
    ...
    <div class="objRecord">
        <div class="objID">6877</div>
        <div class="objColor">green</div>
        <div class="objSize">600</div>
        <div class="objType">T</div>
    </div>
</div>

The reason that I've done it this way is because it's a relatively small amount of data and I don't want the page to be "chatty" and go back to the server (ajax) for new data on each event.

I will be querying that table of data based on user events on the page.

My questions:
1. Is there anything wrong with that structure for retrieving records using jQuery? How would you do it? I was thinking that I could also use a table + tr + td structure for the data but can't see the advantage to that - yet...
2. How would I, for example, get the sizes for all the blue objects from the table with jQuery?

I can get all the blue records in the table using:

var myobjects = $('.objRecord .objColor:contains("blue")').parent();

But I am now struggling to get the size value out of that array...

for (var i = 0; i < myobjects.length; i++) {
    var x = myobjects[i]; // somehow get the size out of this?
}
+1  A: 

You can iterate over your .objColor elements with $.each, and look for the .objSize element within its siblings:

$('#objList .objColor:contains("blue")').each(function () {
  var size = $(this).siblings('.objSize').text(); // 500
});
CMS
+1  A: 

You could do a single iteration over the table when the page first loads, and move the data into an array of JavaScript object literals:

$(document).ready(function(){
   var data = [];
   $('#objList .objRecord').each(function(){
     var  $this = $(this),
         record = {
           ref: $this,
           objID:    Number($this.find('.objID').text()),
           objColor: $this.find('.objColor').text(),
           objSize:  Number($this.find('.objSize').text()),
           objType:  $this.find('.objType').text()
         };

     data.push(record);
     $this.data('record', record);
   });
});

This happens once; now subsequent queries will be executed against a much faster JavaScript array, than against the DOM tree.

To get an array of all the sizes:

var sizes = $.map(data, function(d){ return d.objSize });

The nice thing is, you stored a double reference. So you can access it from the DOM node in the case where you might get it from a click event:

$('.objSize').click(function(){
  // Find the parent `.objRecord` then call its data function
  var record =  $(this).closest('.objRecord').data('record');

  alert(record.objType);
})

And it can be retreived from the JavaScript object:

var record = data[0]; // first record
record.ref.hide(); // Hides the `.objRecord` associated with this record.
Doug Neiner
+1  A: 
  1. I'd suggest always using table/tr/td for tabular data as it provides tabular semantics in your markup, which can be used in your scripting by tag name instead of by class name (perhaps a bit faster and more convenient). To name the cols per row I'd use jQuery to $('tr').each(function(){/*assign class name to TDs here*/});
  2. (Assuming table/tr/td, ..) try $('td.objColor:contains(blue)').siblings('.objSize').text();
stimpy77