Search code examples
jquerycontainsjquery-chaining

Jquery Contains and Not Contains Chaining


Image i have table like this :

<table>
    <tr>
        <td>Adresse IP</td>
        <td class='tdSoap'>10.2.3.4</td>
    </tr>
    <tr>
        <td>Zobi</td>
        <td class='tdSoap'>blabla</td>
    </tr>
    <tr>
        <td>Adresse</td>
        <td class='tdSoap'>NYC</td>
    </tr>
</table>

I want get the "NYC" value, by selecting the TR what has a TD with "Adresse", but NOT with "Adresse IP".

I already do what I want with this code :

$("table tr:has(td:contains('Adresse'))").not(":contains(Adresse\u00a0IP)").find("td.tdSoap").text();

But, I tried a lot with this kind of code, and never succeed :

$("table tr:has(td:contains('Adresse'):not(':contains(Adresse\u00a0IP)')) td.tdSoap").text();

PS : "\u00a" is becaused of that http://bugs.jquery.com/ticket/3450


Solution

  • perhaps this:

    $("table tr td:contains('Adresse')").not(':contains(Adresse\u00a0IP)').next('.tdSoap').text();
    

    why does this not work:(what you have)

    $("table tr:has(td:contains('Adresse'):not(':contains(Adresse\u00a0IP)')) td.tdSoap").text();
    

    jQuery uses a right to left in a selector, so think this:

    1. find all td.tdSoap
    2. now find those that have not any 'Adresse\u00a0IP' - well none do inside the td.tdSoap
    3. now find those that do have 'Adresse' - well none do inside the td.tdSoap
    4. now has, combine those - still none INSIDE that td.tdSoap so nothing is selected.

    Now, this also works taking out the "has" and added a next:

    $("table tr td:contains('Adresse'):not(':contains(Adresse\u00a0IP)')").next("td.tdSoap").addClass('myfirst');
    

    However, run some performance metrics and see which of these is faster:

    $('table').find('tr').find('td:contains("Adresse")').not(':contains("Adresse\u00a0IP")').next('.tdSoap').text();
    $('table').find('.tdSoap').prev(':contains(Adresse)').not(':contains(Adresse\u00a0IP)').next().text();
    $("table tr td:contains('Adresse'):not(':contains(Adresse\u00a0IP)')").next('td.tdSoap').text();
    $("table tr:has(td:contains('Adresse'))").not(":contains(Adresse\u00a0IP)").find("td.tdSoap").text();
    $("table tr td:contains('Adresse')").not(':contains(Adresse\u00a0IP)').next('.tdSoap').text();
    

    NOTE: those get the text of all of them if you have more "groups" of these, not sure you want all of them, but that is what you have.

    EDIT: this works with or without the &nbsp

    $('table').find('tr').find('td:contains("Adresse")').not(':contains("Adresse\u00a0IP")').not(':contains("Adresse IP")').next('.tdSoap').text();