keydown事件仅触发一次 [英] keydown event triggered only once

查看:684
本文介绍了keydown事件仅触发一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下脚本旨在在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:

  1. 收听所有"D"键击中事件.
  2. 点击带有删除"选项(小链轮)的模态链接.
  3. 在该模式中链接删除"链接(它将打开第二个模式删除确认").
  4. 在该模式下单击新的删除"链接,以确认删除对话.

我的脚本

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆