开发者

Defer to default behavior when handling certain keys in a keydown event

I'm usi开发者_JAVA技巧ng jQuery to handle a keydown event on an html tree. As you can see from the code, I'm handling the tab key so that it walks the tree. But if it gets to the end of the tree, I'd like it to tab out of the tree and into the next available field. I've tried returning true in this case, but that doesn't work.

This is preventing other keys from functioning as well. For example, I'd also like to have CTRL+R working, but it does nothing when I'm focused on the tree.

I am returning before e.stopPropagation() and e.preventDefault() are called, so I'd expect my event to get picked up by the default browser handlers, but they don't. I've read in other posts that there's no way to force the default behavior, so I'd think my best bet is just to stop handling the event and pass it on, but it's not being passed. Does anyone know why?

$(treeItem).keydown(function(e) {
  return onKeyDown(obj, e);
});

var onKeyDown = function(obj, e) {
  if (!obj.isRoot) {
    switch (e.keyCode) {
      case keyCode.LEFT: collapseNode(obj); break;
      case keyCode.RIGHT: expandNode(obj); break;
      case keyCode.UP: stepUpTree(obj); break;
      case keyCode.DOWN: stepDownTree(obj); break;
      case keyCode.TAB: if (e.shiftKey) stepUpTree(obj); else stepDownTree(obj); break;
      case keyCode.ENTER: me.activateNode(obj); break;
      default: return true;
    }
  }

  e.stopPropagation();
  e.preventDefault();
}

EDIT

I've updated the code to more accurately reflect what's happening. Now it's more clear what the problem is. The event is attached to a list item element, so when I return true, it keeps firing on all the ancestors until it gets to the root. At that point, the default behavior is stopped. The solution is to only prevent the default behavior when I know I need to, instead of making it the default behavior.


You don't have to return true to tell the browser to keep processing the event; that's what it will do absent your doing preventDefault or return false. Simply return in your default clause. (I'd expect return true; to be harmless, but hey, you never know.)

There are a couple of bugs in your quoted code. I assume you used copy-and-paste (why would you retype it?) and so I wonder if the problems you're having are just that errors are being thrown or the logic isn't quite doing what you expect.

In particular

  • You're missing the comma between obj and e in the arguments part of your onKeyDown function definition, so that's a syntax error.
  • You're switching off of e.keycode. It should be e.keyCode (note the capital C). If the missing comma above isn't actually in your code, but this is, e.keycode will always be undefined and not match any of your cases, so everything will go to default.


For anyone else encountering a similar problem...

You might want to explicitly state which cases should prevent default behavior, instead of making that the default case.

In my case, the event was bound to a list item element, which means that if propagation is allowed, it will fire all the way up the tree. Keycodes that were not listed in my switch statement would just return true and propagate up the tree, until it got to the root. Then it would skip the switch statement and preventDefault() would be called.

In other words...

     var onTreeItemKeyDown = function (obj, event) {
         if (obj.id() !== me.treeDataManager.getRootItemId()) {
             switch (event.keyCode) {
                 case keyCode.LEFT: collapseNode(obj, event); break;
                 case keyCode.RIGHT: expandNode(obj, event); break;
                 case keyCode.UP: getPreviousItem(obj); haltEvent(event); break;
                 case keyCode.DOWN: getNextItem(obj); haltEvent(event); break;
                 case keyCode.ENTER: if (options.activateContent) { options.activateContent(obj); haltEvent(event); } break;
                 default: return true;
             }
         }

         return true;
     }

     var haltEvent = function (event) {
         event.stopPropagation();
         event.preventDefault();
     }

     var expandNode = function (obj, event) {
         obj.isExpanded(true);
         options.selectNode(obj);
         haltEvent(event);
     }

     var collapseNode = function (obj, event) {
         obj.isExpanded(false);
         options.selectNode(obj);
         haltEvent(event);
     }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜