keydown 事件只触发一次
keydown event triggered only once
以下脚本针对 运行 在 facebook.com 的对话页面(用户可以在其中查看其所有对话的页面)。
该脚本的目的是使 "delete conversation" 过程自动化,该过程自然包括 4 次点击,当您有数百个对话时可能会很累并且浪费时间 --- 删除将通过点击 "D"键。
我运行 Greasemonkey 的脚本。
该脚本由 4 个主要部分组成:
- 监听所有 "D" 按键事件。
- 单击 link 打开带有 "Delete" 选项(小链轮)的模式。
- Clink 该模态中的 "Delete" link (它将打开第二个模态 "delete confirmation")。
- 单击该模式中的新 "Delete" link,以确认对话删除。
我的脚本
document.addEventListener('keydown', (k)=>{
if ( k.keyCode === 68 ) {
console.log('keydown: D');
return dC();
}
});
let dC = ()=>{
document.querySelector('._5blh._4-0h').click();
document.querySelector('.uiContextualLayer > [id^="js"] > div > ul > li:nth-child(4)').click();
setTimeout(()=>{ document.querySelector('._3quh._30yy._2t_._3ay_._5ixy').click(); }, 500);
};
作为初学者,我尝试将部分代码放入函数中,我尝试使用 for
而不是 forEach()
进行迭代,我尝试使用 return dC()
或 return false
dC()
电话。所有这些都产生了相同的结果,所以我绕着圈子走,不理解(或否认)我非常想念的更深层次的逻辑错误。
正在复制
作为 Greasemonkey 脚本安装,(匹配 https:www.facebook.com/*
只是为了测试),转到对话页面并点击 "D"。
我的问题
为什么事件只被监听一次?也就是说,为什么单击 D 一次可以使脚本运行,但再单击一次则不起作用?
我必须刷新页面才能重用脚本,这不是预期的行为。
注意:我更喜欢普通的解决方案。
将键值压入数组并在事件结束后取消设置这些数组。
// Create two empty arrays
var map = [];
var down = [];
$(document).on('keydown', 'body', function(e) {
// Check whether the map having any key values
if (!map[e.which]) {
// Set the keydown value to down array
down.push(e.which);
if (down[0] === 68) {
// Events to be done
}
}
map[e.which] = true;
// Once the key-down pressed and event done ,the keyup unset the array while key up
}).keyup(function(e) {
map[e.which] = false;
// unset(down,e.which);
down = [];
e.which = [];
});
正如所写,函数 dC(),它执行 4 个动作:
问题出在操作 #3:
看起来,每次点击 'settings' 菜单(action #2),都会创建一个新的 'settings-menu' 实例(新对象添加到 DOM), 因此这一行不起作用:
document.querySelector('.uiContextualLayer > [id^="js"] > div > ul > li:nth-child(4)').click();
一方面,querySelector returns first 回答给定模式的元素。
另一方面,每次单击设置按钮时,Facebook 都会创建一个 新的“.uiContextualLayer”(定位菜单链轮 link 并展开您的开发工具window注意添加的新元素)。
因此,我们所做的是检查 所有 个链轮元素,然后每次都使用最新的(最后一个)元素:
let menu = document.querySelectorAll('.uiContextualLayer._5v-0._53il');
menu = menu[menu.length-1];
这是最终代码。
(我添加了几个超时以确保绘制 UI 完成)
let dC = ()=>
{
// clicking the 'settings'
document.querySelector('._5blh._4-0h').click();
setTimeout(() => {
// taking the last instance of 'menu popup':
let menu = document.querySelectorAll('.uiContextualLayer._5v-0._53il');
menu = menu[menu.length-1];
// finding 'delete' button inside the menu popup
let lis = menu.querySelectorAll('ul > li');
let target = null;
for (let i=0;!target && i<lis.length;++i)
{
let span = lis[i].querySelector('a span span');
if (!span) continue;
if (span.innerHTML.contains('Delete'))
target = lis[i];
}
if (!target) {console.log('cannot find delete btn'); return;}
// clicking 'delete' button in menu
setTimeout(() => {
target.click();
setTimeout(()=>{
// clicking delete in modal
document.querySelector('._3quh._30yy._2t_._3ay_._5ixy').click();
}, 500);
}, 10);
},10);
};
以下脚本针对 运行 在 facebook.com 的对话页面(用户可以在其中查看其所有对话的页面)。
该脚本的目的是使 "delete conversation" 过程自动化,该过程自然包括 4 次点击,当您有数百个对话时可能会很累并且浪费时间 --- 删除将通过点击 "D"键。
我运行 Greasemonkey 的脚本。
该脚本由 4 个主要部分组成:
- 监听所有 "D" 按键事件。
- 单击 link 打开带有 "Delete" 选项(小链轮)的模式。
- Clink 该模态中的 "Delete" link (它将打开第二个模态 "delete confirmation")。
- 单击该模式中的新 "Delete" link,以确认对话删除。
我的脚本
document.addEventListener('keydown', (k)=>{
if ( k.keyCode === 68 ) {
console.log('keydown: D');
return dC();
}
});
let dC = ()=>{
document.querySelector('._5blh._4-0h').click();
document.querySelector('.uiContextualLayer > [id^="js"] > div > ul > li:nth-child(4)').click();
setTimeout(()=>{ document.querySelector('._3quh._30yy._2t_._3ay_._5ixy').click(); }, 500);
};
作为初学者,我尝试将部分代码放入函数中,我尝试使用 for
而不是 forEach()
进行迭代,我尝试使用 return dC()
或 return false
dC()
电话。所有这些都产生了相同的结果,所以我绕着圈子走,不理解(或否认)我非常想念的更深层次的逻辑错误。
正在复制
作为 Greasemonkey 脚本安装,(匹配 https:www.facebook.com/*
只是为了测试),转到对话页面并点击 "D"。
我的问题
为什么事件只被监听一次?也就是说,为什么单击 D 一次可以使脚本运行,但再单击一次则不起作用?
我必须刷新页面才能重用脚本,这不是预期的行为。
注意:我更喜欢普通的解决方案。
将键值压入数组并在事件结束后取消设置这些数组。
// Create two empty arrays
var map = [];
var down = [];
$(document).on('keydown', 'body', function(e) {
// Check whether the map having any key values
if (!map[e.which]) {
// Set the keydown value to down array
down.push(e.which);
if (down[0] === 68) {
// Events to be done
}
}
map[e.which] = true;
// Once the key-down pressed and event done ,the keyup unset the array while key up
}).keyup(function(e) {
map[e.which] = false;
// unset(down,e.which);
down = [];
e.which = [];
});
正如所写,函数 dC(),它执行 4 个动作:
问题出在操作 #3:
看起来,每次点击 'settings' 菜单(action #2),都会创建一个新的 'settings-menu' 实例(新对象添加到 DOM), 因此这一行不起作用:
document.querySelector('.uiContextualLayer > [id^="js"] > div > ul > li:nth-child(4)').click();
一方面,querySelector returns first 回答给定模式的元素。
另一方面,每次单击设置按钮时,Facebook 都会创建一个 新的“.uiContextualLayer”(定位菜单链轮 link 并展开您的开发工具window注意添加的新元素)。
因此,我们所做的是检查 所有 个链轮元素,然后每次都使用最新的(最后一个)元素:
let menu = document.querySelectorAll('.uiContextualLayer._5v-0._53il');
menu = menu[menu.length-1];
这是最终代码。
(我添加了几个超时以确保绘制 UI 完成)
let dC = ()=>
{
// clicking the 'settings'
document.querySelector('._5blh._4-0h').click();
setTimeout(() => {
// taking the last instance of 'menu popup':
let menu = document.querySelectorAll('.uiContextualLayer._5v-0._53il');
menu = menu[menu.length-1];
// finding 'delete' button inside the menu popup
let lis = menu.querySelectorAll('ul > li');
let target = null;
for (let i=0;!target && i<lis.length;++i)
{
let span = lis[i].querySelector('a span span');
if (!span) continue;
if (span.innerHTML.contains('Delete'))
target = lis[i];
}
if (!target) {console.log('cannot find delete btn'); return;}
// clicking 'delete' button in menu
setTimeout(() => {
target.click();
setTimeout(()=>{
// clicking delete in modal
document.querySelector('._3quh._30yy._2t_._3ay_._5ixy').click();
}, 500);
}, 10);
},10);
};