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

标签 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() 不起作用,知道为什么吗?

最佳答案

accesskey 事件总是被触发

(除非您暂时禁用它)

大多数浏览器总是会触发绑定(bind)到 accesskey 属性的事件,即使其他绑定(bind)事件处理程序使用常见策略,例如 return falsestopPropagationstopImmediatePropagationpreventDefaultcancelBubble 等,这些在正常情况下可有效阻止事件冒泡和默认行为。

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

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

参见 this answer for a jQuery powered solution您可以使用它作为跳板来创建一个简单的 JS 解决方案来满足您的需求。

示例:

<script type="text/javascript">
  
  /* Function to cache accesskey attributes */
  function cacheAccessKeys() {
    
    /* Get all elements with accesskeys
    // This could be modified to select a smaller subset of elements */
    var akEls = document.querySelectorAll('[accesskey]');
    
    /* Iterate over each element in the set of matched elements */
    Array.prototype.forEach.call(akEls, function (el, i) {
      
      /* Set the value of data-accesskey to the value of accesskey */
      el.setAttribute('data-accesskey', el.getAttribute('accesskey'));
      
      /* Remove the accesskey attribute
      // to temporarily disable accesskey binding */
      el.removeAttribute('accesskey');
    });
  }

  /* Function to restore accesskey attributes */
  function restoreAccessKeys() {
    
    /* Get all elements with accesskeys
    // This could be modified to select a smaller subset of elements */
    var akEls = document.querySelectorAll('[data-accesskey]');
    
    /* Iterate over each element in the set of matched elements */
    Array.prototype.forEach.call(akEls, function (el, i) {
      
      /* Set the value of accesskey to the value of data-accesskey
      // to restore accesskey binding */
      el.setAttribute('accesskey', el.getAttribute('data-accesskey'));
      
      /* Clean-up (perhaps unnecessary) 
      // In case the accesskey attributes are set dynamically elsewhere,
      // this prevents mismatched caching. */
      el.removeAttribute('data-accesskey');
    });
  }

  function keyDown(e) {
    if (e.altKey && e.keyCode === 80) {
      console.log("I'm from key down!!!");
    }
  }

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

<div>
  
  
  <!-- On focus: Cache/remove accesskey attributes -->
  <!-- On keydown: Now the key combo in here won't trigger other handlers. -->
  <!-- On blur: Restore accesskey attributes -->
  <input type="text"
         onfocus="cacheAccessKeys();"
         onkeydown="keyDown(event);"
         onblur="restoreAccessKeys();"
         />
         
  <!-- On click: Activated by Alt + p access key combo
  //-- only when text field does NOT have focus. -->
  <input type="button"
         accesskey="p"
         value="Click me"
         onclick="clickMe();"
         />
</div>

关于Javascript event.stopPropagation() 不适用于 `accesskey` 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34006721/

相关文章:

javascript - 在 Javascript 中读取 json 但它总是给出 'undefined'

javascript - 如何在 Canvas 中拖动图像/对象?

html - 如何将Flexbox转化为具体的方式?

javascript - window.onbeforeunload 没有返回任何值的任何不良副作用?

caching - 当http post请求并且没有缓存时处理浏览器后退按钮

browser - Safari 找不到服务器。网站在所有其他浏览器上都正常

javascript - 放大六边形瓷砖javascript

javascript - 如何定位嵌套并包含在父 svg 中的 svg

html - 如何垂直对齐包含标题和图标图像的水平列表?

html - 垂直对齐 : middle for an object floated from left to the right