我有一个使用TradingView小部件的页面,您可以在其中键入键盘上的任意键以触发符号搜索。我使用Chrome的调试器来断点,并确切地知道执行此操作的代码行。我希望将按键事件起泡到通用DOM,由我自己的自定义函数处理。
该怎么做?任何示例代码将不胜感激。这是TradingView的代码片段(“ t”是关键事件):
a || (o.handle = a = function(t) {
return s === Te || t && Te.event.triggered === t.type ? s : Te.event.dispatch.apply(a.elem, arguments)
}
因此,我希望将键事件发送到我自己的函数中,而不是return语句。完整的TradingView代码,其中代码为:https://static.bitmex.com/assets/tradingView/static/tv-chart.min-6ce28e05fd34b9cf06a4e63b29980a72.js
而不是更改页面代码(这是可能的,但可能很乏味),请考虑更改您自己的侦听器以在capturing阶段而不是冒泡阶段中运行。例如,代替
document.body.addEventListener('keypress', fn);
做
document.body.addEventListener('keypress', fn, true);
它将在事件冒泡到内部元素之前运行。
如果运行fn
之前需要完成内部元素上页面的侦听器,则可以在小的fn
之后调用setTimeout
:
document.body.addEventListener('keypress', () => setTimeout(fn), true);
[如果您还想阻止小部件的代码运行,请确保在捕获侦听器中调用stopPropagation
,以使事件不会捕获到小部件中:
const fn = (event) => {
event.stopPropagation();
// rest of code
};
如果要发送关键事件的容器在iframe内,由于安全问题,父窗口将根本看不到该事件。
在most页上,您可以使用postMessage
将事件传达给上级,例如:
// ==UserScript==
// @name 0 New Userscript
// @include https://www.bitmex.com/app/trade/XBTUSD
// @include https://static.bitmex.com/chartEmbed*
// @grant GM_getValue
// @run-at document-start
// ==/UserScript==
if (window.location.host === 'www.bitmex.com') {
const mainFn = () => {
console.log('b');
};
// We're on the top level
const keydown = (e) => {
e.stopPropagation();
if (!e.altKey && e.key === 'b') {
mainFn();
}
};
window.addEventListener('keydown', keydown, true);
window.addEventListener('message', (e) => {
if (e.origin === 'https://static.bitmex.com' && e.data === 'keydown inside iframe') {
mainFn();
}
});
} else {
// We're in the iframe
// When a keypress is detected, message the parent window
const keydown = (e) => {
console.log('iframe kd');
e.stopPropagation();
if (!e.altKey && e.key === 'b') {
window.top.postMessage('keydown inside iframe', '*');
}
};
window.addEventListener('click', keydown, true);
}
@run-at document-start
是必需的,因为iframe具有正在运行forbids userscripts without it的CSP。
但是不幸的是,还有另一个问题:在这种特殊情况下,iframe窗口also在用户脚本有机会运行之前,会在页面加载时覆盖EventTarget.prototype.addEventListener
。尽管您可以[[通常]]使用// @run-at document-start
来确保在页面脚本覆盖变量之前保存对变量的引用,但这在iframe中是不可能的。 iframe中的Chrome用户脚本无法在页面加载开始时就运行。[没有引用EventTarget.addEventListener
(或EventTarget.prototype.onclick
或EventTarget.prototype.onkeydown
设置器等),无法访问注册用户操作的浏览器级API。
我认为您要找的东西在Tampermonkey中是不可能的。