如何在文档级别捕获keybd事件,但让可编辑字段有它们的事件

How to capture keybd events at document level, but let editable fields have their events?

本文关键字:事件 编辑 字段 文档级别 keybd      更新时间:2023-09-26

编辑:由于没有人回应,我将尝试更简洁地重述我的问题。在处理浏览器页面上的击键时(如左/右/空格),如何判断击键是否将由浏览器页面上具有焦点的元素处理,或者

以下是非浏览器设置中的一个典型示例。想象一下,你有一个Windows对话框,里面有一堆典型的对话框控件、几个按钮和一个丰富的编辑控件。如果你在一个典型的对话框控制中,键盘上的Enter键将激活对话框上的OK按钮,并接受对话框的更改。如果您在富编辑控件中,则按Enter键将输入新行。对话框能够以某种方式判断对话框中的当前控件是否要处理回车键,或者是否应该全局处理它。

在我的特定浏览器案例中,我使用YUI2事件处理来捕捉文档级别的击键,这样我就可以允许用户使用键盘上的左/右箭头在页面上的幻灯片中移动,而不必明确地将焦点设置为页面上的任何特定元素(这是我的用户喜欢的功能)。但是,如果页面包含任何可编辑字段,我希望这些左/右箭头由页面上的该字段处理,而不是由我的幻灯片处理。我正在寻找一种优雅的方式来做到这一点。

我意识到我可以查看原始事件目标,并"尝试"弄清楚该目标是否能够处理左/右箭头(输入、文本区域、内容可编辑等),但我希望有一个更简单的方法。只有当网页上的对象没有处理键击时,才有办法在文档级别处理键击吗。现在,在我的YUI键盘处理程序中,我得到了所有的键盘事件,甚至是那些将由目标对象实际处理的事件。

以下是我的代码现在的样子,我正在寻找一种更优雅的方法来实现这一点,它不需要ObjectWantsKeys函数,因为它有点脆弱:

JF.Slideshow.prototype._HookupKeyNav = function () {
    var k = YAHOO.util.KeyListener;
    var key = k.KEY;
    // see if keyboard handling is enabled or not
    if (((this._config.keyboardNav == "auto") && (JF.SlideshowCnt <= 1)) || (this._config.keyboardNav == "on")) {
        this._keyListener = new YAHOO.util.KeyListener(
        document, {
            ctrl: false,
            shift: false,
            alt: false,
            keys: [key.LEFT, key.RIGHT, key.SPACE]
        }, {
            fn: this._HandleKeys,
            scope: this,
            correctScope: true
        });
        this._keyListener.enable();
    }
}
JF.Slideshow.prototype._HandleKeys = function (type, args, obj) {
    var keyCode = args[0];
    var event = args[1];
    var target = event.srcElement || event.target;
    if (JFL.ObjectWantsKeys(target)) return; // if the current focus object wants keystrokes, then we shouldn't process them
    var key = YAHOO.util.KeyListener.KEY;
    switch (keyCode) {
    case key.LEFT:
        this.Back();
        break;
    case key.RIGHT:
        this.Forward();
        break;
    case key.SPACE:
        this.StartStopToggle();
        break;
    default:
        break;
    }
}
JFL.ObjectWantsKeys = function (o) {
    // list of HTML object types that want the keystroke if they have focus
    var list = {
        "input": true,
        "textarea": true
    };
    try {
        // unfortunately o.contentEditable set to an empty string means it is editable so we need this more complicated comparision
        if ((typeof o.contentEditable !== "undefined") && (o.contentEditable === "true" || o.contentEditable === true || o.contentEditable === "")) {
            return (true); // focus object is editable
        }
        if (o.tagName && list[o.tagName.toLowerCase()]) {
            return (list[o.tagName.toLowerCase()]); // focus object can take keys
        }
    } catch (e) {}
    return (false);
}

我通过检查具有焦点的元素的类型来解决这个问题:

var tag = document.activeElement.tagName;
if (tag == "INPUT" || tag == "TEXTAREA")
  return;

这并不完美,因为我也不希望KeyListener在显示YAHOO.widget.Dialog时处理击键(这会给出一个标记名"BODY")。我不得不用YAHOO.widget.OverlayManager把一些东西拼凑在一起,然后检查活动对话框。如果它为空,我将处理击键。

这并不优雅,我希望有更好的解决方案。我在YUI论坛上发布了一条消息:

http://yuilibrary.com/forum/viewtopic.php?p=26413

如果我在那里得到答案,它也可能对你有所帮助。