如何在打字测试中作弊使用JavaScript输入字母



我正在尝试想出一个解决方案,以虚拟按键进行打字测试。我想要的是获取文本并将单个字母存储在数组中,然后按下所有键,每次按下之间有一些延迟。

这是文本布局的HTML。想象它有hello这个词

<div class="digit-container">
<div>
<span>h</span>
</div>
</div>
<div class="digit-container">
<div>
<span>e</span>
</div>
</div>
<div class="digit-container">
<div>
<span>l</span>
</div>
</div>
<div class="digit-container">
<div>
<span>l</span>
</div>
</div>
<div class="digit-container">
<div>
<span>o</span>
</div>
</div>

这是我想出的JavaScript代码。我已经设法将这些字母存储在一个数组中。

const elements = document.querySelectorAll(".digit-container > div > span");
const chars = Array.from(elements).map((item) => item.textContent);
const delay = 1000;
let i = 0;
const pressKey = () => {
setTimeout(() => {
const char = chars[i];
const event = new KeyboardEvent("keyup", {
key: char
});
document.body.dispatchEvent(event);
if (i !== chars.length - 1) {
i++;
pressKey();
}
}, delay);
};
pressKey();
document.body.addEventListener("keyup", (e) => {
console.log(e.key);
});

然而,这只显示控制台中hello字。现在我想让JavaScript为这个字母数组发送按键{"h", "e", "l", "}。基本上,当我粘贴这些代码并在控制台中按enter键时,我希望JavaScript按"Hello"按键之间有一毫秒的延迟。这样我就可以完成打字测试了。我怎么能得到JavaScript进入按键?

你得到了很多否定,因为一般来说,人们不喜欢关于如何破解的问题…但是我检查了一下是否可以回答你的问题,发现如果问题集中在技术方面,并且包括合理的努力,那就可以了。

我必须承认,我一直在寻找一个充分证明的理由来结束你的问题(!)…但是既然你非常接近找到解决方案,这里是如何做到这一点,以及如何防止它(对于网站所有者)。


因此,正如在注释中提到的,您需要将事件分派到用户应该键入…的正确元素。所以,不给document.body

但是关于分派哪些事件,这很简单。在输入时,触发的事件(按顺序)是:keydownkeypressinputkeyup。见下文:

let targetInput = document.querySelector("#test");
let targetEvents = ["blur", "focus", "input", "keydown", "keyup", "keypress", "select"];
targetEvents.forEach(function (evt) {
targetInput.addEventListener(evt, (event) => {
console.log(`${event.type}`)
setTimeout(()=>console.clear(),1600)
});
})
<input type="txt" id="test">

所以如果你想几乎完美地模拟用户键盘动作,我的建议是模拟这四个…您还必须将键值附加到输入的值。

如何防止这种黑客方法

说……我也是不喜欢鼓励黑客行为的人之一。所以我也提供了一种方法来知道键盘动作是否通过JS模拟。真实键盘动作istrusted属性设置为true。浏览器提供了这些信息,并且不能通过JS重写。因此,如果你是一个网站的所有者,需要测试真实用户动作,你需要检查事件的isTrusted属性。

let targetInput = document.querySelector("#test");
let targetEvents = ["keydown", "keypress", "input", "keyup"];
targetEvents.forEach(function (evt) {
targetInput.addEventListener(evt, (event) => {
console.log(`${(event.isTrusted)?"Real user ":"JavaScript"} - ${event.type}: ${event.key}`)
if(event.isTrusted){
setTimeout(()=>console.clear(),3000)
}
});
})
let chars = ["H", "e", "l", "l", "o"];
let i = 0;
const pressKey = () => {
setTimeout(() => {
const char = chars[i];
// Dispatch all the events
targetEvents.forEach(function (evt) {
let event = new KeyboardEvent(evt, {
key: char,
isTrusted: true  // Useless attempt overriding the isTrusted property
});
targetInput.dispatchEvent(event);

});

// Add the letter to the input value
targetInput.value += char;
if (i !== chars.length - 1) {
i++;
pressKey();
}
}, 150);
};
pressKey();
<input type="txt" id="test">

最新更新