views:

216

answers:

4

Hey,

I have a table which have a thead section and a tbody section. Im using jQuery each to find and count all THs in a table. This works fine. But at the same time i want to check if the TDs of the THs in the tbody is containing any input elements.

Here is what i have so far:

jQuery('#' + _target).each(function () {

        var $table = jQuery(this);
        var i = 0;
        jQuery('th', $table).each(function (column) {
            if (jQuery(this).find("input")) {
                dataTypes[i] = { "sSortDataType": "input" }
            }
            else {
                dataTypes[i] = { "sSortDataType": "html" }
            }

            i++;
        });
    });

I hope this is enough information for you to help me out?

A: 

Like this:

if (jQuery(this).is(":has(input)")) {

You can simplify your code using .map:

    dataTypes = jQuery('th', $table).map(function () {
        if (jQuery(this).is(":has(input)"))
            return { "sSortDataType": "input" };
        else
            return { "sSortDataType": "html" };
    }).get();
SLaks
`.is()` returns a boolean value, so length is unnecessary.
Tatu Ulmanen
@Tatu: I already fixed that.
SLaks
Why `.is(":has(input)")` instead of just `.has('input')` ?
patrick dw
@patrick: `.has()` filters the jQuery object; it doesn't return a boolean.
SLaks
I think he wants to find out if the column headed by the TH has any input elements, not whether the header itself contains an input element. This would be important in knowing whether the sorting needs to account for HTML or can use the data directly.
tvanfosson
I see now the `length` is removed. I suppose it would be more efficient to avoid the filtering.
patrick dw
@tvanfosson: I hadn't seen that part. I would have edited in the correct selector, but you beat me to it.
SLaks
A: 

If you're just looking for the counts could you not just use something like the following?

var thMatches = $('#' + _target + ' th');
var thCount = thMatches.length;
var thCountWithInputs = thMatches.find('input').length;

I've not got my IDE in front of me so the above may not be correct however I think it's pretty close to what you are looking for.

Brian Scott
A: 

Each will give you the index of the element in the list. Assuming that all of your TH elements belong to a column and you have no THs elsewhere in the table, you can use this to find the nth-child TD (column) elements of each row and see if any of those contain an input.

jQuery('#' + _target).each(function () {
    var $table = jQuery(this);
    var i = 0;
    jQuery('th', $table).each(function (column) {
        if ($('tbody > tr').find('td:nth-child(' + (column+1) + ')')
                           .has('input')
                           .length) {
            dataTypes[i] = { "sSortDataType": "input" }
        }
        else {
            dataTypes[i] = { "sSortDataType": "html" }
        }

        i++;
    });
});

EDIT: nth-child is one-based, whereas each is zero-based, so I've added one to the column variable to account for this.

tvanfosson
`.has()` does not return a boolean.
SLaks
@SLaks - Correct - I neglected the length property. I've fixed this.
tvanfosson
+2  A: 
dataTypes = $('#' + _target + ' th').map(function(i, th) {
  var $table = $(th).closest('table');
  var pos = $table.index(th) + 1;
  return { "sSortDataType": $table.find('td:nth-child('+pos+')').is(':has(input)') ? 'input' : 'html' };
});

Edit: if you are running this on a single table (in which case the each call in the original example does not make much sense), it gets simpler:

dataTypes = $('#' + _target + ' th').map(function(pos, th) {
  return { "sSortDataType": $(th).closest('table').find('td:nth-child('+(pos+1)+')').is(':has(input)') ? 'input' : 'html' };
});
Tgr
this only returns an array containing "html" strings?
Poku
I had the arguments of the map callback in the wrong order. Fixed now.
Tgr
Now it works. Thank you!
Poku