keydown事件只触发一次

时间:2017-09-04 02:47:53

标签: javascript loops events keyboard-shortcuts

以下脚本旨在在facebook.com的对话页面(用户可以查看其所有对话的页面)上运行。

该脚本的目的是自动化“删除对话”过程,该过程自然包括4次点击,当您有数百个对话时可能会很烦人并浪费时间 - 通过点击“D”键从键盘进行删除。

我用Greasemonkey运行脚本。

该脚本由4个主要部分组成:

  1. 收听所有“D”键击中事件。
  2. 单击使用“删除”选项(小链轮)打开模态的链接。
  3. 在该模式中隐藏“删除”链接(它将打开第二个模式“删除确认”)。
  4. 点击该模式中的新“删除”链接,确认删除会话。
  5. 我的脚本

    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() {1}}致电。所有这些都产生了相同的结果,所以我走了一圈,不理解(或否认)一个我非常想念的更严重的逻辑错误。

    再生

    安装为Greasemonkey脚本(仅为测试匹配https:www.facebook.com/*),转到对话页面并点击“D”。

    我的问题

    为什么只听一次事件?也就是说,为什么单击D会使脚本生效,但任何进一步的点击都无效?

    我将不得不刷新页面以重用脚本,而这不是预期的行为。

    注意:我更喜欢香草解决方案。

2 个答案:

答案 0 :(得分:1)

如上所述,函数dC(),它执行4个操作:

问题出在行动#3

似乎每次点击“设置”都会显示出来。菜单(动作#2 ),一个新的设置菜单'实例已创建(添加到DOM的新对象),因此该行无法工作:

  

document.querySelector (' .uiContextualLayer > [id ^ =" js"]> div> ul>李:第n个孩子(4)')点击();

一方面, querySelector 会返回应答给定模式的第一个元素。

另一方面,每次点击设置按钮时,Facebook都会创建新的.uiContextualLayer' (定位菜单链轮链接并拉伸你的devtool窗口以注意到新元素补充)。

因此,我们所做的是检查所有链轮元素,然后每次使用最新(最后)元素:

  

let menu = document.querySelectorAll (' .uiContextualLayer ._ 5v-0._53il');
menu = menu [menu 。长度-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);
};

答案 1 :(得分:0)

将键值推入数组并在事件结束后取消设置这些数组。

// 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 = [];
    });