complex jquery selector : challenge

878 Views Asked by At

I've searched among jquery selectors for some time now, but can't find any solution to my problem.

I've got an html table filed by a foreach. On each line, several links that pop up tooltips. My problem : can't find the right selector.

<table>
    <?php foreach($article) :?>
    <tr>
        <td>
            <div class="none" style="display:none;">
                <div class="tooltip_1">
                    "The content of my tooltip_1"
                </div>
                <div class="tooltip_2">
                    "The content of my tooltip_2"
                </div>
            </div>
            <div class="cell">
                <a href="#" class="link_to_tooltip_1">a link</a>
                <a href="#" class="link_to_tooltip_2">a link</a>
            </div>
        </td>
    <tr>
    <?php endforeach; ?>
</table>

To show my tooltip, I use qTip, and it works like this :

$('a[class="link_to_tooltip_1"]').qtip({
    content: $('jquery selector'),
    (... other options)
});

So basicaly, I would need something like

content: $('self.parentNode.parentNode > div[class="none"] > div[class="tooltip_1"]'),

in other words :

  • start from link "link_to_tooltip_1"
  • go back to parent div "cell"
  • go back to parent td
  • then go to child div "none"
  • and finally select child div "tooltip_1"

Thanks a lot.

5

There are 5 best solutions below

4
On BEST ANSWER
// this is "complex" version;
// assumes .cell and .none are nested inside same container, whether <td> or <li> or anything
$(".link_to_tooltip_1").each(function () {
    console.log($(this).closest(".cell").siblings(".none").find(".tooltip_1"));
    // $(this).qtip({ content: /* use above selector */ });
});

// this is the "not-so-complex" version;
// assumes both items are nested arbitrary level deep inside same <td>
$(".link_to_tooltip_1").each(function () {
    console.log($(this).closest("td").find(".tooltip_1"));
    // $(this).qtip({ content: /* use above selector */ });
});

jsFiddle Link

2
On
$('a.link_to_tooltip1').closest('tr').find('.tooltip_1');

is probably what you're seeking for ?

1
On

Here is the selector you are looking for:

"td:has(.cell .link_to_tooltip_1) .none .tooltip_1"

Explanations:

You can't go backwards (match an element, and then its parent). However you can select an element and verify that it contains elements that match an other selector:

"td:has(.cell .link_to_tooltip_1)"

This selects the parent <td> of .link_to_tooltip_1. So this does exactly the .link_to_tooltip_1.parentNode.parentNode you described.

Then you just have to select .none .tooltip_1 in the selected <td>:

"td:has(.cell .link_to_tooltip_1) .none .tooltip_1"

So your example code becomes:

$('a[class="link_to_tooltip_1"]').qtip({
    content: $("td:has(.cell .link_to_tooltip_1) .none .tooltip_1"),
    (... other options)
});

And as you were asking for, this is done with just a jquery selector :-)

1
On

why not place your tooltip like this ? :

<table>
    <?php foreach($article) :?>
    <tr>
        <td>
            <div class="cell">
                <span class="tooltip_1" style="display:none;" >"The content of my tooltip_1"</span><a href="#" class="link_to_tooltip_1">a link</a>
                <span class="tooltip_2" style="display:none;" >"The content of my tooltip_2"</span><a href="#" class="link_to_tooltip_2">a link</a>
            </div>
        </td>
    <tr>
    <?php endforeach; ?>
</table>

and

$('a[class="link_to_tooltip_1"]').qtip({
    content: $(this).children("span"),
    (... other options)
});

Edit I didn't know you can't use $(this). So in this context, you can do :

$('a[class="link_to_tooltip_1"]').each(function(){
    var content = $(this).prev("span");
    $(this).qtip({
    content: content,
    (... other options)
});
2
On

I'd try something like this:

add a class to the elements with tooltips and rel attribute with the target class of element holding data

<a href="#" class="iHaveATooltip" rel="tooltip1">link with tooltip yar!</a>

then in JS

$('a.iHaveATooltip').bind('mouseenter', function(){ 
    $(this).addClass('showingTooltip'); 
}).bind('mouseleave', function(){ 
    $(this).removeClass('showingTooltip'); 
}).qtip({
    content: function(){ return $('.' + $('.showingTooltip').attr('rel')).html() },
    (... other options)
});

it's the only idea I can come with to cheat the lack of support for generic data referencing based on DOM structure. Though can't promise it will work as I don't know the plugin and don't know if passing function as an argument won't collide with how it's implemented - you might have to change the plugin to allow it to accept function as content parameter.

good bye and good luck,

Tom