javascript - 如何使用 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”、“l”、“o”}。基本上,当我粘贴此代码并在控制台中按 Enter 时,我希望 JavaScript 在击键之间有几毫秒的延迟按“Hello”。这样我就可以完成打字测试了。如何让 JavaScript 进入按键?
解决方案
你被否决了很多,因为一般来说,人们不喜欢关于如何破解的问题......但我检查了是否可以回答你的问题,发现如果问题集中在技术方面并且包括合理的努力,那就是好吧。
我不得不承认我正在寻找一个完全证明的理由来结束你的问题(!)......但是因为无论如何你都非常接近找到解决方案,这里是如何做到这一点以及如何防止它(对于网站所有者) .
因此,正如评论中提到的,您需要将事件分派到用户应该键入的正确元素......所以,而不是document.body
.
但是关于调度哪些事件,这很简单。在输入输入时,触发的事件是(按顺序):keydown
、keypress
和。见下文:input
keyup
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
设置属性 tro 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">
推荐阅读
- python - dask:并行模型中的共享内存
- typescript - 为什么 Typescript 不以正确的方式支持函数重载?
- javascript - 如何使用 javascript/jquery 用标签包装元素的兄弟文本?
- math - 在第一象限中查找圆和两条直线的切点
- sql - 根据日期逻辑在表中插入行 - sql/hive
- php - 使用 PHP 脚本在命令行中运行 PHP 文件
- java - Spring Boot - 自定义查询上的空指针
- java - Elasticsearch计数嵌套对象列表的数量(java)
- filesystems - 我在 Ubuntu16.04 中尝试 cd 代码,但屏幕显示输入/输出错误'
- opengl - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, ...) 和 GL_TEXTURE_SWIZZLE_RGBA