3

I have a table where I pull data and add it to an array of arrays. The problems is if one of the table cells is empty it appears in the array as "undefined". I tried using an if the last element is undefined if so using .pop() the element should be removed. I still get undefined elements. Here's my code and live demo

HTML :

<table id="contactlisttable">
    <tr>
        <th>Name</th>
        <th>Title</th>
        <th>Phone</th>
    </tr>
    <tr>
        <td class="contactlist contactlistlastfirst">Joey</td>
        <td class="contactlist contactlisttitle">webdesigner</td>
        <td class="contactlist contactlistphone"></td>
    </tr>
    <tr>
        <td class="contactlist contactlistlastfirst">Anthony</td>
        <td class="contactlist contactlisttitle">webdesigner</td>
        <td class="contactlist contactlistphone">5555555</td>
    </tr>
</table> 


JavaScript :

//IE9+ compatable solution
$(function(){
    var results = [], row; 
    $('#contactlisttable').find('th, td').each(function(){
        if(!this.previousElementSibling){ //New Row?
            row = []; 
            results.push(row); 
            if($(this) === 'undefined'){//Remove undefined elements
                row.pop();
            }
        }
        row.push(this.textContent || this.innerText); //Add the values (textContent is standard while innerText is not)       
    }); 
    console.log(results); 
}); 

2
  • What would you like to go in the array is the field is undefined? Commented Dec 23, 2013 at 15:44
  • This would also remove the "sparse" aspect of the array. Why not just use an object at that point? Commented Dec 23, 2013 at 15:46

5 Answers 5

2

jsFiddle Demo

Instead of doing the conditional statements, just take advantage of your html structure. First select by the table rows, and then iterate the child td or th elements. You can also take advantage of jQuery's text instead of doing the feature detection. jQuery's text will be more reliable.

var results = [];
$('#contactlisttable tr').each(function(){
 var row = [];
 $(this).find('td,th').each(function(){
     row.push($(this).text());
 });
 results.push(row);
});
console.log(results);
Sign up to request clarification or add additional context in comments.

1 Comment

+1 An inner loop makes far more sense. Could use .map() to create the Arrays too, though you'd need to work around jQuery's auto-flattening for the inner .map().
1

Instead of pushing and popping if it doesn't match, don't push in the first place.

Updated from your jsfiddle:

//IE9+ compatable solution
$(function(){
    var results = [], row; 
    $('#contactlisttable').find('th, td').each(function(){
        if(!this.previousElementSibling && typeof(this) != 'undefined'){ //New Row?
            row = []; 
            results.push(row); 
        }
        row.push(this.textContent || this.innerText); //Add the values (textContent is standard while innerText is not)       
    }); 
    console.log(results); 
}); 

Comments

1

You can also avoid adding undefined (or actually empty) elements this way:

$('#contactlisttable').find('th, td').each(function(){
    if(!this.previousElementSibling){ //New Row?
        row = [];
        results.push(row);
    }
    if(!(this.textContent == '')){
        row.push(this.textContent || this.innerText);            
    }
}); 

1 Comment

Travis J's answers is far more appropriate for this case.
0

To know if something is undefined dont just compare to "undefined", use typeof().

So you want to do :

if (typeof(this) === "undefined")

5 Comments

That will never be true because you are constructing a jQuery object. The object will never return undefined as its type. I didn't downvote though, just pointing it out.
Indeed, just whent too fast. Corrected.
typeof isn't a function. You don't neeed the parens.
It avoid bleeding eyes.
@EoiFirst do you do the same thing with return, i.e.: return(true)? Making non-function keywords look like function calls makes my eyes bleed. ;)
0

You could add a compact method like in underscore and lodash...

Array.prototype.compact = function() {
    return this.filter(function(x){
        return x !== undefined;
    });
}

console.log([1,2, '', undefined, 'e', undefined].compact()); // [ 1, 2, '', 'e' ]

You should probably add a check for a native implementation of compact as well, since you are overriding a native prototype with this.

Or, just

2 Comments

Why put compact() on Function.prototype if it's only meant to work with Arrays?
My bad, early morning :P... Updated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.