如何创建仅在第一次按下时起作用的“ keydown”事件?

时间:2018-10-15 15:18:28

标签: javascript html

下面是所有HTML和javascript的相关部分。 javascript代码段是从顶部开始的所有内容,然后我只显示了两个“ keydown”事件,否则将有很多内容需要阅读。这两个事件分别标记为“ SECTION 1”和“ SECTION 2”。

我有几个不同的“ keydown”事件,它们添加了各种不同的HTML内容。此网页几乎完全是用javascript设计的,只是作为演示。

每次用户按下相关键时,我都希望将内容添加到HTML文档中。当前,只需重复按同一键,就可以无限次添加同一内容。这不是我想要的。

我如何做到使活动只能进行一次?

/* ////////// INTIAL TITLE ////////// */

var initialTitle = document.createElement("h1");
var intialTitleContent = document.createTextNode("Please press the \"1\" key on your keyboard.");
initialTitle.appendChild(intialTitleContent);
document.body.appendChild(initialTitle);

/* ////////// KEYPRESS FUNCTIONS ////////// */

window.addEventListener("keydown", checkKeyPress, false);
function checkKeyPress(key) {
    
// SECTION 1 - Paragraph explaining what this page is about and what to do.
    if (key.keyCode == "49") // "1"
    {
        var pElement = document.createElement("p");
        var content = document.createTextNode("Welcome! This page is made entirely out of javascript. It is completely impractical to create a webpage in this manner. This page is simply a demonstration of how javascript can be used to create and add HTML element and CSS to a HTML document. Meaning within the HTML document the <body> element only contains a link to the javascript code and what the javascript code has added. You can add content by pressing the \"1\" through to \"9\" keys. Each piece of content can then be styled by pressing the \"s\" key.");
        pElement.appendChild(content);
        document.body.appendChild(pElement);
    }
    
// SECTION 2 - TABLE
    else if (key.keyCode == "50") // "2"
    {
        var tableDiv = document.createElement("div");
        var tableElement = document.createElement("table");

        tableDiv.classList.add("div_1");
        
        for (var z = 1; z <= 4; z++) { //Creating "tr" elements.
            var trElement = document.createElement("tr");
            
            tableElement.appendChild(trElement);
            
            for (var i = 1; i <= 4; i++) { //Creating "td" elements within the "tr" elements.
                var tdElement = document.createElement("td");

                tdElement.classList.add("tableCell");
                trElement.appendChild(tdElement);
            }
        }
        
        tableDiv.appendChild(tableElement);
        document.body.appendChild(tableDiv); 
        
        /* Table styling below this point */
        
        var tableCellStyling = document.getElementsByClassName("tableCell");
        
        for (var y = 0; y < tableCellStyling.length; y++) {
            tableCellStyling[y].style.width = "80px";
            tableCellStyling[y].style.height = "80px";
            tableCellStyling[y].style.border = "2px solid #303030";
        }
    }
<!doctype html>
<html lang="en-gb">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, intial-scale= 1.0"/>
    <title>Javascript Only Site</title>
</head>
<body>

    <script src="js/JOS.js"></script>
</body>
</html>

6 个答案:

答案 0 :(得分:3)

如果您希望事件仅触发一次,则可以在事件的回调内removeEventListener。您将需要一个包含对处理程序的引用的变量来执行此操作,因此它看起来像:

var eventHandler = function(event){
  //do things
  document.removeEventListener('keypress', eventHandler);
}

document.addEventListener('keypress', eventHandler);

但是,请查看您的代码段,如果您只希望触发一次每个键控代码行为,则可以创建一个映射,以跟踪先前按下过哪些键,然后短暂返回。

var pressedKeys = {};

/* ////////// INTIAL TITLE ////////// */

var initialTitle = document.createElement("h1");
var intialTitleContent = document.createTextNode("Please press the \"1\" key on your keyboard.");
initialTitle.appendChild(intialTitleContent);
document.body.appendChild(initialTitle);

/* ////////// KEYPRESS FUNCTIONS ////////// */

window.addEventListener("keydown", checkKeyPress, false);
function checkKeyPress(key) {



    /** ADDED CODE **/
    if(pressedKeys[key.keyCode] !== undefined){//return if we've seen this key before
      return;
    }
    pressedKeys[key.keyCode] = 1;//just assign a value
    /** END ADDED CODE **/
    
    
    
    
// SECTION 1 - Paragraph explaining what this page is about and what to do.
    if (key.keyCode == "49") // "1"
    {
        var pElement = document.createElement("p");
        var content = document.createTextNode("Welcome! This page is made entirely out of javascript. It is completely impractical to create a webpage in this manner. This page is simply a demonstration of how javascript can be used to create and add HTML element and CSS to a HTML document. Meaning within the HTML document the <body> element only contains a link to the javascript code and what the javascript code has added. You can add content by pressing the \"1\" through to \"9\" keys. Each piece of content can then be styled by pressing the \"s\" key.");
        pElement.appendChild(content);
        document.body.appendChild(pElement);
    }
    
// SECTION 2 - TABLE
    else if (key.keyCode == "50") // "2"
    {
        var tableDiv = document.createElement("div");
        var tableElement = document.createElement("table");

        tableDiv.classList.add("div_1");
        
        for (var z = 1; z <= 4; z++) { //Creating "tr" elements.
            var trElement = document.createElement("tr");
            
            tableElement.appendChild(trElement);
            
            for (var i = 1; i <= 4; i++) { //Creating "td" elements within the "tr" elements.
                var tdElement = document.createElement("td");

                tdElement.classList.add("tableCell");
                trElement.appendChild(tdElement);
            }
        }
        
        tableDiv.appendChild(tableElement);
        document.body.appendChild(tableDiv); 
        
        /* Table styling below this point */
        
        var tableCellStyling = document.getElementsByClassName("tableCell");
        
        for (var y = 0; y < tableCellStyling.length; y++) {
            tableCellStyling[y].style.width = "80px";
            tableCellStyling[y].style.height = "80px";
            tableCellStyling[y].style.border = "2px solid #303030";
        }
    }

答案 1 :(得分:2)

第一次触发事件后,您将删除事件侦听器。

document.querySelector('input').onkeydown = () => {
  alert('key down')
  document.querySelector('input').onkeydown = '';
}
<input type="text">

答案 2 :(得分:1)

在脚本顶部声明一个布尔值:

let keyDownAllowed = true;

然后在您的按键事件中:

if(keyDownAllowed){
   //Set keyDownAllowed to false;
   keyDownAllowed = false;
   //Add to your HTML
}else{
   //Just return or do anything else which you want to do on every key down
   return;
}

答案 3 :(得分:1)

window.removeEventListener("keydown", checkKeyPress, false);

您可以随时使用removeEventListener删除监听器。函数引用和useCapture标志应该相同。

window.addEventListener("keydown", checkKeyPress, false);

function checkKeyPress(e) {
  alert(e.key + ' pressed');
  window.removeEventListener("keydown", checkKeyPress, false);
}

window.focus();

答案 4 :(得分:0)

即使问题不是 ,我怀疑很多绊脚石的人都在寻找一种方法来仅捕获多个keydown事件中的第一个按住某个键时,浏览器/操作系统会快速连续触发这些事件。

这是我的解决方案,仅当在目标上第一个按下键(例如window或某个input字段)时,该函数才运行您传递的函数。如果用户要再次触发键,则必须释放并再次按下。


香草JS

const onKeyPress = (func, target = window) => {
  // persistent "store" to track what keys are being pressed
  let pressed = {};

  // whenever a keydown event is fired ontarget element
  const onKeyDown = (event) => {
    // if key isn't already pressed, run func
    if (!pressed[event.which])
      func(event);

    // add key to store
    pressed = { ...pressed, [event.which]: true };
  };

  // whenever a keyup event is fired on the window element
  const onKeyUp = (event) => {
    const { [event.which]: id, ...rest } = pressed;
    // remove key from store
    pressed = rest;
  };

  // add listeners
  target.addEventListener('keydown', onKeyDown);
  window.addEventListener('keyup', onKeyUp);

  // return a function that can be called to remove listeners
  return () => {
    target.removeEventListener('keydown', onKeyDown);
    window.removeEventListener('keyup', onKeyUp);
  };
};

然后使用它:

const removeListener = onKeyPress((event) => console.log(event.which + ' key pressed'))

removeListener(); // when you want to remove listeners later

反应和反应挂钩

import { useState } from 'react';
import { useEffect } from 'react';
import { useCallback } from 'react';

export const useKeyPress = (func, target = window) => {
  // persistent "store" to track what keys are being pressed
  const [pressed, setPressed] = useState({});

  // whenever a keydown event is fired ontarget element
  const onKeyDown = useCallback(
    (event) => {
      // if key isn't already pressed, run func
      if (!pressed[event.which])
        func(event);

      // add key to store
      setPressed({ ...pressed, [event.which]: true });
    },
    [func, pressed]
  );

  // whenever a keyup event is fired on the window element
  const onKeyUp = useCallback((event) => {
    // remove key from store
    const { [event.which]: id, ...rest } = pressed;
    setPressed(rest);
  }, [pressed]);

  useEffect(() => {
    // add listeners when component mounts/changes
    target.addEventListener('keydown', onKeyDown);
    window.addEventListener('keyup', onKeyUp);

    // cleanup/remove listeners when component unmounts/changes
    return () => {
      target.removeEventListener('keydown', onKeyDown);
      window.removeEventListener('keyup', onKeyUp);
    };
  }, [target, onKeyDown, onKeyUp]);
};

然后使用它:

import { useKeyPress } from 'wherever';

useKeyPress((event) => console.log(event.which + ' key pressed'))

答案 5 :(得分:0)

另一种方法。如果要跟踪同时按住的几个键并在按特定组合时执行操作,请尝试此操作。检查控制台以获取结果。需要jQuery。

var key_statuses = {};

$(function () {
    $('body').keydown(function (e) {
        var code = e.keyCode || e.which;
        if (key_statuses[code] == "down") {
            return;
        }
        key_statuses[code] = "down";

        // Your actions here

        console.clear();
        console.log(key_statuses);
    });

    $('body').keyup(function (e) {
        var code = e.keyCode || e.which;
        delete key_statuses[code];

        console.clear();
        console.log(key_statuses);
    });
});