简体   繁体   中英

jQuery handing both focus and click on an element

I'm trying to determine workflow to fine-tune a data entry web application. Picture several address forms on a single web page:

  1. Name___________
     Street_________
     Phone__________

  2. Name___________
     Street_________
     Phone__________

  [...many more...]

Now I'd like to know if the user is using the tab key to get to the second "Name" field (or anywhere within that record), or if they're using the mouse to click on it. (Or shift-tab to move in reverse.)

I've set a handler on both focus and click for the input fields:

$('input').click(function() { TabulateClick(this) });
$('input').focus(function() { TabulateFocus(this) });

And in the handler, I determine which address the user is working on and whether we've "switched" Address records. (If the focus was in "Phone" for the first address, and you click on the "Name" field in the same address , that's not actually switching records, so I don't tabulate that.)

    function TabulateClick(field)
    {
         var currentAddressRecord = FindAddress(field);
         if ( lastAddressRecord != currentAddressRecord )
             switchedAddressesWithClick++;
         lastAddressRecord = currentAddress;
    }
    function TabulateFocus(field)
    {
         var currentAddress = FindAddress(field);
         if ( lastAddressRecord != currentAddressRecord )
             switchedAddressesWithTab++;
         lastAddressRecord = currentAddress;
    }

My problem is that when I mouse-click into the field the focus event fires first tabulating a false switchedAddressesWithTab and changing the currentAddress (that's bad ). When the click handler runs, the lastAddressRecord is spoiled.

Is there a way inside of the focus handler to know that there is a pending click event on the same object? Or in the click handler to know that it was previously just handled by focus ?

Here's something that I think works based on the fact that the mousedown happens before the focus. See demo .

var lastClick = null;
$('input').mousedown(function(e) {
  lastClick = e.target;
}).focus(function(e){
    if (e.target == lastClick) {
      console.log('click');
    } else {
      console.log('tab');    
    }
    lastClick = null;

});

To fix the bug discovered by Josiah, I changed my code to the below. See demo .

var lastFocusedElement = null;
var isClick = false;
$('input').mousedown(function(e) {     
     isClick= true;
}).focus(function(e){

    // To prevent focus firing when element already had focus
    if (lastFocusedElement != e.target) {
        if (isClick) {
          console.log('click ----');
        } else {
          console.log('tab -----');    
        }
        lastFocusedElement = e.target;
        isClick = false;
    }
});

$(document.body).focus(function(){
  lastFocusedElement = document.body;
});

The one problem is that you don't get 'click' or tab when you switch away from the window and switch back. You get a focus event on the input that had focus, but you can't determine if it's a tab or a click, because it's neither.

I think this is the closest you'll get, I would try this on your page and see if the behavior is good enough.

You could use the .on() method in jQuery. Here is another way to bind both events on the same element.

var hasClicked = false;
$('.myinputfield').on('mousedown : click',function(e){
     if (e.type == 'mousedown') {
        // execute code
        hasClicked = true;
     }
     if(e.type == 'focus' && !hasClicked) {
        //execute code
        console.log(e.type)
     }
     hasClicked = false;
});

Just bind the focus and then check the event to see if e.which == 9 // tab .

My original idea did not work (thanks @Juan). Using the combination of events should get you where you want to be. If the user clicks into the text box the last key press will not be a tab. All inputs are watching and storing the last key code to pass to the focus event. here is the fiddle

var lastKeyCode = 0;
$('input').focus(function(e) {
    if(lastKeyCode == 9)
         // tabbed into field
    else
         // clicked into field
}).keydown(function(e){
    if(e.which == 9) // added timeout to clear lastkeypress
        setTimeout(function(){lastKeyPress = 0}, 50);
    lastKeyPress = e.which; // store last key code
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM