以下代码旨在将元素(myInput
)的innerHTML更改为另一个元素(// ==UserScript==
// @name Duolingo
// @include *://duolingo.com/*
// @include *://www.duolingo.com/*
// ==/UserScript==
setTimeout(()=>{
let myInput = document.querySelector('._7q434._1qCW5._2fPEB._3_NyK._1Juqt._3WbPm');
let myNote = document.createElement('div');
document.body.appendChild(myNote);
myNote.setAttribute("style", "position: fixed; bottom: 0; right: 0; display: block; width: 400px; height: 400px; background: orange; color: #000");
myInput.addEventListener('keydown', (k)=>{
if ( k.keyCode === 13 ) {
myNote.innerHTML += myInput.value + '<br>';
}
});
}, 2000);
)的值,每次 <按> em>返回 键:
innerHTML
我在duolingo.com(一个学习像法语这样的mind2mind语言的网站)的Greasemonkey中运行代码,在文本问题会话中,例如“翻译这句话”。
代码的目的是创建一个小的橙色背景框,其中包含我在Duolingo问题中尝试过的输入,因为Duolingo没有保存这些。
使用脚本,我可以保存它们,如果我重新输入一个语言问题,以后再使用它们,因为它可以节省一些时间重新输入大部分句子。
代码失败,因为innerHTML
只更改了一次。如果值再次发生变化并且我压制 返回 ,则不会发生任何事情。
使用duolingo.com上的Greasemonkey(或类似程序)中的代码重现。
为什么addEventListener
只会被更改一次?鉴于return
一直在倾听,为什么它只能工作一次?
使用return false
进行更改或添加setTimeout(()=>{
window.myCss =`.note {position: fixed; bottom: 0; right: 0; width: 400px; height: 400px; background: orange}`;
style = document.createElement("style");
style.type = "text/css";
style.styleSheet ? style.styleSheet.cssText = myCss : style.appendChild(document.createTextNode(myCss) );
head = document.head || document.getElementsByTagName("head")[0];
head.appendChild(style);
let note = document.createElement('div');
note.classList.add('note');
document.querySelector('body').appendChild(note);
let savedValue;
document.addEventListener('keydown', (e)=>{
let target = e.target;
if (target.nodeName === 'textarea') {
savedValue = e.target.value;
}
});
if (k.keyCode === 13) {
setTimeout(()=>{
document.querySelector('textarea').value = savedValue;
}, 100);
}
}, 2500);
无效。
可能需要另外一种方法来添加一个包含每次按下值的新元素。
html
我在控制台中没有任何错误。
我尝试阅读文章,我理解在原始示例中我喋喋不休而不是捕获(我应该通过每次从textarea
元素转到BServico.write(new byte[] { 28, 46 }); //Cancels Chinese character mode
//TEST
for (int i = 0; i < 20; i++) {
String text = String.format("%d - %s - çüáéíóúñåæø\n", i, Integer.toHexString(i));
BServico.write(new byte[] { 0x1B, 0x74, (byte)i });
try {
BServico.write(text.getBytes("ISO-8859-1"));
} catch (Exception ex) {
//
}
}
元素来捕获任何处理程序重新捕捉它的处理程序,但我看不出如何从中改进代码。也许我现在读的不好,因为我心情不好......
答案 0 :(得分:3)
duolingo中的测验是根据我的判断编写的,因此很可能你添加事件监听器的元素不再存在。有几种方法可以解决这个问题,但最好的方法是使用事件冒泡(可能在捕获阶段)来监听不会被替换的内容,例如tools: context = "activity name"
元素,并等待来自元素的事件符合您的需求。
您的代码将如下所示:
body
答案 1 :(得分:1)
代码失败(删除拼写错误后),因为它将事件监听器添加到网页覆盖每个新问题的文本区域。当textarea被覆盖时,它会破坏您添加的上一个事件侦听器。它还会使该代码中myInput
的值孤立。
在持久性容器或整个主体上使用更智能的事件侦听器。并根据需要刷新myInput
。
还有其他问题:
._7q434._1qCW5._2fPEB._3_NyK._1Juqt._3WbPm
是一个非常脆弱的选择器,并会在下次网站代码更改时中断。它在我看到的某些页面上也不起作用。
textarea[data-test]
可能会奏效。或者甚至textarea
也可以满足代码的其余部分。
setTimeout
是一种等待元素的脆弱方式,而且是already causing you grief。请改用waitForKeyElements
或MutationObserver
或类似名称。但在您的情况下,由于您正在等待用户交互,您可能不需要任何其他延迟机制。
将所有内容放在一起,您的用户脚本将类似于:
// ==UserScript==
// @name Duolingo, answer text recycler
// @match *://*.duolingo.com/*
// @run-at document-idle
// ==/UserScript==
let myNote = document.createElement ('div');
document.body.appendChild (myNote);
myNote.setAttribute (
"style",
"position: fixed; bottom: 0; right: 0; width: 400px; height: 400px; background: orange; overflow: auto;"
);
document.addEventListener ('keydown', (zEvent) => {
if (zEvent.keyCode === 13) {
if (zEvent.target.nodeName === 'TEXTAREA') {
let myInput = document.querySelector ('textarea[data-test]');
if (myInput) {
myNote.innerHTML += myInput.value + '<br>';
}
}
}
} );
答案 2 :(得分:0)
// ==UserScript==
// @name Duolingo
// @namespace nms
// @include *://duolingo.com/*
// @include *://www.duolingo.com/*
// @version 1
// @grant none
// ==/UserScript==
setTimeout(()=>{
// Style:
/*let myCss =`
.note {position: fixed; bottom: 0; right: 0; width: 400px; height: 400px; background: orange}
`;*/
let myCss =`
.note {position: fixed; top: 100px; left:100px; bottom: 100px; right: 100px; width: 200px; height: 200px; background: orange}
`;
style = document.createElement("style");
style.type = "text/css";
style.styleSheet ? style.styleSheet.cssText = myCss : style.appendChild(document.createTextNode(myCss) );
head = document.head || document.getElementsByTagName("head")[0];
head.appendChild(style);
// Behavior:
let myNote = document.createElement('div');
myNote.classList.add('note');
document.querySelector('body').appendChild(myNote);
let myInputField = document.querySelector('textarea');
myInputField.addEventListener('keydown', (k)=>{
if ( k.keyCode === 13 ) {
myNote.innerHTML = myInputField.value;
}
});
}, 2000);
&#13;
<textarea></textarea>
<br>
<div id="myNote">
</div>
&#13;
如果您在StackOverflow的完整页面视图中运行原始代码,则代码运行正常。我改变了橙色矩形的css,以便在非完整页面视图中更好地查看结果,它也可以工作。注意:我使用的是Google Chrome版本49.0.2623.112米。