【问题标题】:Not able to capture click event on Netflix seek bar无法在 Netflix 搜索栏上捕获点击事件
【发布时间】:2021-11-08 04:36:42
【问题描述】:

我有一个 chrome 扩展程序,它依赖于检测 Netflix 搜索栏上的点击事件。一旦用户将鼠标悬停在视频播放器上,div ([data-uia=timeline-bar]) 会动态添加到 dom,因此我尝试使用事件冒泡来监听事件。

    //after injecting jquery on page 
    $('body').on('click','[data-uia=timeline-bar]',function(e){
        console.log('click detected');
    })

没有成功,所以我尝试在捕获阶段添加侦听器。正在检测所有点击事件,但搜索栏点击。

document.addEventListener('click',
(e) => {console.log('click detected during capture phase')}
,true);

有没有办法监听 ([data-uia=timeline-bar]) 上的点击事件?

【问题讨论】:

  • 我不确定我是否遇到了您的问题。你不能添加监听器,因为它是动态删除和添加的吗?
  • 我无法控制 netflix dom,但是我可以在页面中注入一些代码。我尝试将侦听器附加到它,但它不起作用。

标签: javascript google-chrome-extension onclicklistener reverse-engineering netflix


【解决方案1】:

MutationObserver 添加到 [data-uia=timeline-bar] 元素的父元素中,以观察其子元素何时发生变化,例如添加时间线栏?并在添加了时间线栏元素后在回调中附加一个侦听器?

// The timeline-bar's parent's data-uia is "timeline" in the Netflix player DOM.

let parent = document.querySelector("[data-uia=timeline]"),
    options = {
      childList: true
    },
    observer = new MutationObserver(mCallback);

observer.observe(parent, options);

function mCallback (mutations) {
  for (let mutation of mutations) {
    if (mutation.type === 'childList') { 
      for(let node of mutation.addedNodes){
        if(node.getAttribute("data-uia") === "timeline-bar"){
           node.addEventListener('click', () => {
             alert("clicked");
            // Do click stuff...
           });
        }
      }
    }
  }
}

// To test the observer
btnAttr.addEventListener('click', function () {
  let el = document.createElement("div");
  el.setAttribute("data-uia", "timeline-bar");
  el.innerText = "A TIMELINE-BAR";
  parent.appendChild(el);
}, false);

在这里编写代码:https://codepen.io/freedruk/pen/powaKBy

【讨论】:

  • 我最初试图避免突变观察者路线,但现在什么都有效。这适用于Netflix吗?我在控制台中进行了测试,但它不适用于 Netflix 播放器。我相信 data-uia=timeline 本身是动态添加的。让我尝试改变课程。仅供参考,您不需要单独的测试。真正的测试将是它是否适用于 Netflix 播放器。
  • 我已编辑您的代码以定位正确的 dom 元素。附加观察者的父级不应该是动态的。 click 事件有时会触发,而其他时候会错过。看看你能不能想出别的办法codepen.io/t3rminal/pen/RwgMzQd
【解决方案2】:

确实,您的目标需要努力工作,因为 dom 元素会被永久创建和删除。我可以提出的唯一方法当然可以被认为是肮脏的,但你至少可以尝试一下;)

$("[data-uia='player']").on("DOMSubtreeModified", function(){
    const ref = "div[data-uia='timeline-knob']";

    if($(ref)){
        $(ref).off("mouseover").on("mouseover", function(event){
            const that = $(this);
            const previousSibling = event.target.previousSibling;

            if(previousSibling.style.left){
                console.log("Click presumed");
            }
            else {
                console.log("released");
            }
        });
    };
});

诀窍是观察时间轴旋钮对象,并分析前一个兄弟div的情况,因为当鼠标在时间轴上时会发生一些重绘。

这只是一种解决方法,我希望这可以帮助你:)祝你有美好的一天!

[编辑 1]

更优雅的方式:

const ref = "div[data-uia='timeline'].active";
const onclick = (e) => {
    console.log("clicked on", e);
};
const prepare = (obj, e) => {
    $(e.target).css("pointer-events","auto").css("border", "0.1px solid rgba(255,255,255,0)");
    $(obj).off("click.test").on("click.test", (clickevent) => {onclick(clickevent.target);});
};

$("[data-uia='player']").on("DOMSubtreeModified", function(modevent){
    $(ref).each(() => {
        prepare(ref,modevent);
    });
});

我不得不面对几个困难:

  1. 甚至“时间轴”节点也会重新生成,因此我们在每次“播放器”修改时都将“点击”事件附加到它
  2. 基本上,我们经常需要点击空的 div(例如正好在时间轴上),然后不会触发“点击”事件,因此我们对其应用几乎不可见的布局来强制浏览器将其视为可点击节点。
  3. 并非最不重要的一个:Netflix 使用“pointer-events”css 属性来阻止“click”事件,因此我们必须将其修复为“auto”

我多次测试了这段代码,它似乎工作正常;)

【讨论】:

  • 哇!这很有趣。该代码在用户单击搜索栏时有效,但如果您单击搜索栏略高于或低于搜索栏,则会错过点击。让我试试是否可以修改代码以达到结果。 imgur.com/vEPNEG9
  • 让我看看能不能打补丁;)
  • 太好了。你是谁菲利普。想和你联系。你是怎么弄清楚这些事情的?随着元素不断进出dom,这个过程更加困难。您是否设法以某种方式冻结它然后进行调试?什么是“click.test”?让我稍微玩一下代码。
  • 赏金来了 :) 如果您不介意连接,请在 piyush.neo@gmail.com 上打个“嗨”。
  • 非常感谢这个丰厚的奖励!在寻找可接受的解决方案时,我学到了很多东西,感谢这次挑战。如果您不介意我用英语的“法式风格”,我会尽快与您联系:D
猜你喜欢
  • 1970-01-01
  • 2020-04-11
  • 2018-11-02
  • 1970-01-01
  • 2014-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多