views:

124

answers:

8

For a page, I've been given a link wrapped inside a label, like this:

<label for='checkbox_elem'>
    Links to <a href='somepage.php' target='anotherwindow'>another page.</a>
</label>

When the user clicks on the link in all browser, the page is spawned in a new tab as envisioned, but in Firefox the checkbox linked to the label is also selected. This is a non-desired behavior.

I want to run some jQuery to allow the link to pop, but to kill the event thereafter. I have the following, which works, but isn't very elegant:

$(document).ready(function(){
    $('label a').click(function(e){
        open($(this).attr('href'), $(this).attr('target'));
        return false;
    });
});

Can any of you think of a more elegant way to do this than to replicate the element's behavior manually and kill the event?


As an aside, I've been trying w/ stopPropagation, but haven't had much success.

Also, please note that the above solution does work, but I am looking for something more elegant for generically stopping events from propagating past their first call. (The first native call. If I add a callback, I still want the native element behavior to fire, but not that of its parent) .

Thanks, Joe

A: 

You could use $(elem).one(fn) -- http://api.jquery.com/one/

peol
I want my handler to continue to be called on every click, but I need it to override the bubble-up *after* the normal <a> element event is fired. It looks like one() will not change my problem.
Joseph Mastey
A: 

Maybe you should change your html to:

<label for='checkbox_elem'>Links to </label>
<a href='somepage.php' target='anotherwindow'>another page.</a>

and use no javascript at all?

Coffee Bite
Thanks for the suggestion. Not my HTML, it's coming out of a CMS controlled by non-technical users. :)
Joseph Mastey
A: 

Well, if you are allowed to change the html on client-side, you can always move the links outside the label like this,

$(document).ready(function(){ 
    $('label').find('a').each(function(){
        var $anchor = $(this);        
        $(this).closest('label').after($anchor);
    });
});​

demo

Reigel
I actually like this approach (there are a few more complications, but generally workable), but I'm not sure it's *more* elegant to rewrite HTML to get around such issues.
Joseph Mastey
honestly, I can't think of any other approach... Cause as you said, you have no control on the source of the html...
Reigel
+1  A: 

Try stopping the event from propagating at the label.

$(document).ready(function(){
    $('label').click(function(e){
        e.stopPropagation();
    });
});
Marnix van Valen
Tried this one. The label needs to retain its normal click behavior, except when the event is coming from an <a> element. This disables the label behavior.
Joseph Mastey
I'd say FireFox is not doing what it's supposed to. I tried stopping propagation on every combination of mouse events and elements I could think of and nothing seems to prevent firefox from toggling the checkbox. I did notice however that the change event reports it's ultimate event source is a click event on the text node within the link. Not sure how to catch that event though...
Marnix van Valen
A: 

This one:

<label> test <a href="#">Test</a> <input type="checkbox" name="check[]" /></label>

Or even:

<label for="test1"> test <a href="#">Test</a> <input type="checkbox" name="test1" id="test1" class="checkbox" /></label>

And js:

$('a').click(function(e){
    var t=$(this);
    window.open(t.attr('href'), t.attr('target'));
    return false;
});

Works for me. Maybe there is smth that interfere with your script?

Ionut Staicu
I can use window.open, but that is a pretty specific override, and pretty kludgy. The purpose of my question is to see if there is an elegant solution to the problem, rather than the hack I already have.
Joseph Mastey
Oups, i didn't get the part with 'a more elegant way' :D However, you cant' Maybe if you play with `position:absolute` with the link, but I consider that is more ugly than this.
Ionut Staicu
A: 

Try:

$(document).ready(function(){
    $('label a').one(function(e){
        open($(this).attr('href'), $(this).attr('target'));
        return false;
    });
});
Sarfraz
This is identical to the code that I posted, but only prevents the label click on the first time that the user does it. The one() function is unfortunately not suitable for this purpose.
Joseph Mastey
A: 

The problem occurs because when you click a label which has a for attribute a click event is dispatched for the associated input. It seems that in Firefox stopping propagation of the click event for the label does not stop this happening (which may be a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=528926).

So, what you could do is prevent the default action of that event instead, something like this:

$('label').click(function(e) {
    if (e.target !== this) {
        //e.stopPropagation();
        $('input#' + $(this).attr('for')).one('click', function(e) {
            e.preventDefault();
            this.blur();
        });
    }
});
Richard M
A: 

KISS

$(document).ready(function(){
    $('label a').click(function(e){
        open($(this).attr('href'), $(this).attr('target'));
        $(this).parent().click(); //Click the label again to reverse the effects of the first click.
        return false;
    });
});
Kristoffer S Hansen