views:

506

answers:

4

I have this sample code:

$myTrigger
    .click(function(e){
         alert('click');
    })
    .focus(function(e){
         alert('focus');
         $(this).click()
    })

The intent is that I want something to happen when you click on $myTrigger. If, on the other hand, you tab onto it via the keyboard (ie, focus) I want the exact same thing to happen, so I ask it to click.

The catch is if I click on it, it also focuses. So both alerts are going off.

Is there a way to prevent the focus event from going off when clicking?

UPDATE:

Ajm's comment got me thinking that I'm maybe asking the wrong thing.

Question: Does a click event always also trigger focus in javascript (and/or in jQuery?). Can I assume whenever I want to handle both clicking with the mouse and tabbing-in with the keyboard, the focus() event will handle both?

Or is it dependent on the particular element that I'm attaching the events to? (In this case $myObject happens to be an anchor tag (link).

A: 

I ran into a similar problem a while back. I solved it by responding to the first event, and ignoring events for the next 20ms.

Try something like this:

$(document).ready(OnReady);

var okToClick = true;

function OnReady() {
    //Attach to both click and focus events
    $("#item").click(PerformAction).focus(PerformAction);
}

function PerformAction() {
    if (okToClick) {
        okToClick = false;

        // Do something interesting here...

        setTimeout(function() { okToClick = true; }, 20);
    }
}
Matt Brunell
I wouldn't say that is so much a solution as it is an ugly hack around the issue.
Keith Rousseau
Yep. It's a hack. Can't argue there. But in my case, it was the *only* solution.
Matt Brunell
A: 

You can use only the focus() method and read this article about events (e) types on JavaScript: http://www.quirksmode.org/js/events_properties.html

To detect what event you got with you mouse or keyboard (to test it), u can use:

if (!e) var e = window.event;
alert(e.type);
TiuTalk
I suppose my question is really "does focus ALWAYS get called on CLICK?"
DA
@DA - Yeah, because when you click on the element you're activating it's focus too since your focused in that element. :)
TiuTalk
@TiuTalk, well, I did a test and that does not appear to be the case. You can't give a DIV a focus event, for instance, and then click on it and have that event fired. It appears that this is only true for 'focusable' elements.
DA
A: 

To prevent focus from being called twice set a variable to tell if the element has focus.

var hasFocus = false;
$('#myTrigger').focusIn(
   function(){
      hasFocus = true;
      //do stuff
   }
);

$('#myTrigger').focusOut(
   function(){
      hasFocus = false;
   }
);

Put all functionality on focus and tell jQuery to set the foucus on the element when it is clicked if you run into a browser which doesn't do that.

$(#myTrigger).click( function(){ if(!hasFocus){$(#myTrigger).focus()}});
Adam
that won't work as focus would then get called twice.
DA
Good point. You'll have to set a variable to see if it's gotten focus yet.
Adam
+1  A: 

jQuery has a built-in functon for this that's not used all that often called .one()

$mytrigger.one('click focus', function() { alert("event"); });

This will only trigger once, or you can re-bind if you want afterwards.

Nick Craver
Does that call 'one of these two events once' or does it call 'each of these events once'? The documentation doesn't say. (Obviously, I can try it out an will as soon as I can...)
DA
@DA - Once in total is probably the clearest description
Nick Craver
Yup. It works! THANKS!
DA