更改页面 javascript 代码 (TamperMonkey) 以将键盘敲击发送到父级 DOM
Change page javascript code (TamperMonkey) to send keyboard strokes to the parent DOM
我有一个使用 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
与其更改页面代码(这是可能的,但可能很乏味),不如考虑在 捕获 阶段将您自己的侦听器更改为 运行,而不是冒泡阶段。例如,而不是
document.body.addEventListener('keypress', fn);
做
document.body.addEventListener('keypress', fn, true);
它会 运行 在事件冒泡到内部元素之前。
如果页面在内部元素上的侦听器需要在您的 fn
运行 之前完成,您可以在小 setTimeout
之后调用 fn
:
document.body.addEventListener('keypress', () => setTimeout(fn), true);
如果您还想阻止 运行ning 小部件的代码,请确保在您的捕获侦听器中调用 stopPropagation
,这样事件就不会捕获到小部件:
const fn = (event) => {
event.stopPropagation();
// rest of code
};
如果您要向其发送按键事件的容器位于 iframe 中,由于安全问题,父级 window 根本看不到该事件。
在 大多数 页面上,您可以使用 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 来自 运行ning 的 CSP。
但不幸的是,还有另一个问题:在这种特殊情况下,iframe window also 在用户脚本有机会之前在页面加载时覆盖 EventTarget.prototype.addEventListener
到 运行。虽然您可以 通常 使用 // @run-at document-start
来确保在页面脚本覆盖变量之前保存对变量的引用,但这在 iframe 中是不可能的; Chrome iframe 中的用户脚本不能 运行 在页面加载的最开始。
如果不引用 EventTarget.addEventListener
(或 EventTarget.prototype.onclick
或 EventTarget.prototype.onkeydown
设置器等),则无法访问注册用户的浏览器级别 API动作。
我认为在 Tampermonkey 中找不到您要找的东西。
我有一个使用 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
与其更改页面代码(这是可能的,但可能很乏味),不如考虑在 捕获 阶段将您自己的侦听器更改为 运行,而不是冒泡阶段。例如,而不是
document.body.addEventListener('keypress', fn);
做
document.body.addEventListener('keypress', fn, true);
它会 运行 在事件冒泡到内部元素之前。
如果页面在内部元素上的侦听器需要在您的 fn
运行 之前完成,您可以在小 setTimeout
之后调用 fn
:
document.body.addEventListener('keypress', () => setTimeout(fn), true);
如果您还想阻止 运行ning 小部件的代码,请确保在您的捕获侦听器中调用 stopPropagation
,这样事件就不会捕获到小部件:
const fn = (event) => {
event.stopPropagation();
// rest of code
};
如果您要向其发送按键事件的容器位于 iframe 中,由于安全问题,父级 window 根本看不到该事件。
在 大多数 页面上,您可以使用 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 来自 运行ning 的 CSP。
但不幸的是,还有另一个问题:在这种特殊情况下,iframe window also 在用户脚本有机会之前在页面加载时覆盖 EventTarget.prototype.addEventListener
到 运行。虽然您可以 通常 使用 // @run-at document-start
来确保在页面脚本覆盖变量之前保存对变量的引用,但这在 iframe 中是不可能的; Chrome iframe 中的用户脚本不能 运行 在页面加载的最开始。
如果不引用 EventTarget.addEventListener
(或 EventTarget.prototype.onclick
或 EventTarget.prototype.onkeydown
设置器等),则无法访问注册用户的浏览器级别 API动作。
我认为在 Tampermonkey 中找不到您要找的东西。