Javascript event.stopPropagation()不适用于`accesskey`属性

时间:2015-11-30 19:47:25

标签: javascript html browser

一个简单的html页面只包含两个控件,一个文本框和一个按钮。页面加载后,如果用户在文本框中单击并按“alt”+ p(按钮访问键),则该消息应显示为“我是从按键下来!!!”但如果用户单击文本框内的任何位置,则该消息应该显示为“只有在焦点位于文本框之外时才应该调用!!!”。完整代码如下所示:

<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script type="text/javascript">
    function keyDown() {
        if (event.altKey && event.keyCode == 80) {
            event.returnValue = false;
            event.cancelBubble = true;
            event.keyCode = 0;
            alert("I'm from key down!!!");
        }
    }

    function clickMe() {
        alert("I should be called only when the focus is outside the textbox!!!");
    }
 </script>
</head>
<body>

<div>
    <input type="text" onkeydown ="keyDown();" />
    <input type="button" value="Click me" accesskey="p" onclick="clickMe();" />
</div>

</body>
</html>

在IE10及以下版本中可以正常使用。但它在IE11和Chrome中不起作用,相反它会一个接一个地显示两条警告信息,例如“我来自关键!!!”和“只有当焦点在文本框之外时才应该调用!!!”这是不可取的。因此,keyDown()事件处理程序已更改为支持IE10 +和Chrome

function keyDown() {
     if (event.altKey && event.keyCode == 80) {
        event.preventDefault ? event.preventDefault() : (event.returnValue = false);
        event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
        event.keyCode = 0;
        alert("I'm from key down!!!");
     }
}

但是在这种情况下event.stopPropagation()不起作用,任何想法为什么?

5 个答案:

答案 0 :(得分:2)

始终触发accesskey事件

(除非您暂时禁用它)

大多数浏览器将始终触发绑定到accesskey属性的事件,即使其他绑定事件处理程序使用常见策略,例如return falsestopPropagationstopImmediatePropagation,{{1 }},preventDefault等,在正常情况下可以有效地阻止事件冒泡和默认行为。

但是在你的情况下,你有一个处理程序检查你通过cancelBubble绑定到另一个元素的相同组合键。因此,每当在文本字段具有焦点时输入关键组合时,两个处理程序都会被触发:首先在accesskey处理程序中,然后无论是否尝试阻止该事件冒泡,keyDown处理程序都是触发因为clickMe激活了它。

一种解决方案是在您不想收听时暂时删除accesskey属性(例如当您的文字输入有焦点时),然后在您不想要时恢复它们再忽略它们(例如当你的文字输入失去焦点时)。

请参阅this answer for a jQuery powered solution,您可以将其用作跳板,以创建符合您需求的简单JS解决方案。

示例:

&#13;
&#13;
accesskey
&#13;
&#13;
&#13;

答案 1 :(得分:1)

accesskey属性似乎是个问题。 Chrome和IE使用 ALT + accesskey 来激活按键。 https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey。删除它,问题就消失了。

<强> jsFiddle example

答案 2 :(得分:1)

这是另一种解决方法,只需禁用已启用的accesskey元素,然后重新启用它。

    function keyDown() {
        if (event.altKey && event.keyCode == 80) {
          var accecskeyObj = $("input[accesskey=" + event.key + "][disabled != disabled]");
         accecskeyObj.prop('disabled',true);
         alert("I'm from key down!!!");
         accecskeyObj.prop('disabled',false);
        }
    }

http://jsfiddle.net/2efgbde1/1/

答案 3 :(得分:0)

您没有通过事件对象。

<input type="text" onkeydown="keyDown();" />
<input type="button" value="Click me" onclick="clickMe();" />

function keyDown() {
    if (event.altKey && event.keyCode == 80) {
        event.returnValue = false;
        event.cancelBubble = true;
        event.keyCode = 0;
        alert("I'm from key down!!!");
    }
}

function clickMe() {
    alert("I should be called only when the focus is outside the textbox!!!");
}

但是,既然它已经定义为全球性的,它不应该成为问题。我检查并添加了任何类型的accesskey,chrome背靠背绕过两个警报框。

为了解决这个问题,我不认为您有任何其他选择,而不是删除访问密钥。删除后,它会在chrome和IE上显示相同的结果。

b = np.asarray(x)
for i in range(len(x.flat)):
    b.flat[i] = operation(x.flat[i])

答案 4 :(得分:0)

这只是一种解决方法,不能成为一个合适的解决方案 - accesskey属性是问题,所以要暂时删除此属性并再次添加它,如@gfullam所述。这可以通过使用jquery有效地完成,但不知道为什么stopPropagation()不起作用。

<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
    function keyDown(evt) {
        var e = evt || window.event;
        if (e.altKey && e.keyCode == 80) {
           //event.returnValue = false;
           //event.cancelBubble = true;
           //event.keyCode = 0;
            var allAccessKeys = $('[accesskey]').each(function () {
                $(this).data('allAccessKeys', $(this).attr 
                ('accesskey')).removeAttr('accesskey');
            });

            alert("I'm from key down!!!");

            setTimeout(function () {
                allAccessKeys.each(function () {
                    $(this).attr('accesskey', $(this).data 
                    ('allAccessKeys'));
                });
            }, 0);
        }
    }

    function clickMe() {
        alert("I should be called only when the focus is outside the textbox!!!");
    }
</script>
</head>
<body>

<div>
    <input type="text" onkeydown="keyDown(event);" />
    <input type="button" value="Click me" accesskey="p" onclick="clickMe();" />
</div>

</body>
</html>