keydown事件仅触发一次 [英] keydown event triggered only once
问题描述
以下脚本旨在在facebook.com的对话页面(用户可以在其中查看其所有对话的页面)上运行.
The following script is aimed to run on facebook.com's conversations page (the page in which a user can see all its conversations).
该脚本的目的是使删除对话"过程自动化,该过程自然包括4次单击,当您进行数百次对话时可能会很累人并且浪费时间---可以通过敲击"D"键从键盘上进行删除.
The script's purpose is to automize the "delete conversation" process which naturally includes 4 clicks and can be tiresome and time wasting when you have hundreds of conversations --- deletion will be done from keyboard by hitting the "D" key.
我用Greasemonkey运行脚本.
I run the script with Greasemonkey.
该脚本包含4个主要部分:
The script is comprised of 4 main segments:
- 收听所有"D"键击中事件.
- 点击带有删除"选项(小链轮)的模态链接.
- 在该模式中链接删除"链接(它将打开第二个模式删除确认").
- 在该模式下单击新的删除"链接,以确认删除对话.
我的脚本
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()
进行迭代,并尝试在dC()
调用下使用return dC()
或return false
.所有这些都产生了相同的结果,所以我走了个圈,不了解(或否认)我非常想念的更深层次的逻辑错误.
As a beginner, I tried put parts of the code in functions, I tried iterating with for
instead forEach()
, I tried using return dC()
or return false
under the dC()
call. All of these yielded the same results so I walked in circles not understanding (or denying) a deeper logical error which I sorely miss.
安装为Greasemonkey脚本,(与https:www.facebook.com/*
匹配以进行测试),转到对话"页面,然后单击"D".
Install as Greasemonkey script, (match as https:www.facebook.com/*
just for the test), go to conversations page and hit "D".
为什么事件仅被监听一次?也就是说,为什么单击一次D将使脚本正常工作,但再单击一次却无济于事?
Why the event is listened only once? That is, why clicking D once will case the script to work but any further clicks will do nothing?
我将不得不刷新页面以重新使用脚本,这不是预期的行为.
I will have to refresh the page for that to reuse the script and that's not the intended behavior.
注意:我希望使用香草溶液.
Note: I would prefer a vanilla solution.
推荐答案
函数dC()编写了4个动作:
As written, function dC(), it does 4 actions:
问题出在动作3 :
貌似,每次单击设置"菜单(操作2 ),都会创建一个新的设置菜单"实例(将新对象添加到DOM),因此此行不会工作:
Seemingly, every click on 'settings' menu (action #2), a new 'settings-menu' instance is created (new object added to the DOM), thus this line won't work:
document.querySelector (' .uiContextualLayer > [id ^ ="js"]> div> ul> li:nth-child(4)'). ();
document.querySelector('.uiContextualLayer > [id^="js"] > div > ul > li:nth-child(4)').click();
一方面, querySelector 返回用于回答给定模式的 first 元素.
On the one hand, querySelector returns the first element that answers the given pattern.
另一方面,每次单击设置按钮时,Facebook都会创建一个新的'.uiContextualLayer'(定位菜单链轮链接并扩展您的devtool窗口以注意添加的新元素).
On the other hand, Facebook creates a new '.uiContextualLayer' each time the settings button is clicked (target the menu chainwheel link and stretch up your devtool window to note the new element added).
因此,我们要做的是在之后检查所有链轮元素,然后每次都使用最新(最后)元素:
Hence, what we do is to check all chainwheel elements after and then work with the newest (last) element each time:
let menu = document.querySelectorAll (' .uiContextualLayer ._ 5v-0._53il');
menu = menu [menu.length-1];
let menu = document.querySelectorAll('.uiContextualLayer._5v-0._53il');
menu = menu[menu.length-1];
这是最终代码.
(我添加了一些超时,以确保完成UI绘制)
Here is the final code.
(I added few more timeouts to make sure drawing the UI is finished)
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);
};
这篇关于keydown事件仅触发一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!