在图片中,Facebook评论框没有提交按钮,当你写东西并按下Enter按钮时,评论就会发布。
我想通过在控制台中运行的JavaScript提交评论。但我试图触发Enter事件,提交DOM的事件。无法使其发挥作用。
答案 0 :(得分:15)
当前评论框不是<textarea>
内的传统<form>
。他们在div上使用contenteditable属性。要在此方案中提交,您需要收听其中一个键盘事件(keydown
,keypress
,keyup
)并查找Enter
密钥是密码13。
在这种情况下,FB看起来像是在听keydown
evt,所以当我运行这段代码时,我能够假装提交评论:
function fireEvent(type, element) {
var evt;
if(document.createEvent) {
evt = document.createEvent("HTMLEvents");
evt.initEvent(type, true, true);
} else {
evt = document.createEventObject();
evt.eventType = type;
}
evt.eventName = type;
evt.keyCode = 13;
evt.which = 13;
if(document.createEvent) {
element.dispatchEvent(evt);
} else {
element.fireEvent("on" + evt.eventType, evt);
}
}
fireEvent('keydown', document.querySelector('[role="combobox"]._54-z span span'));
关于这一点需要注意几点。课程._54-z
是他们刚刚在我的页面上使用的课程。你的旅费可能会改变。使用开发工具确保你抓住正确的元素(它应该具有咏叹调角色&#34; combobox&#34;)。此外,如果您希望支持旧浏览器,则必须调整上面的fireEvent
功能代码。我只测试了最新Chrome中的上述示例。
最后,为了使问题复杂化,Facebook正在使用React创建当前页面的虚拟DOM表示。如果您手动将字符键入组合框然后运行上面的代码,它将按预期工作。但是,您无法将组合框的最内层<span>
内部HTML设置为您要查找的内容,然后触发keydown
。您可能需要在组合框上触发change
事件,以确保您的消息持续存在于虚拟DOM中。
那应该让你开始吧!希望有所帮助!
答案 1 :(得分:4)
几年后,该帖子仍然有用,实际上是我发现的唯一与此相关的帖子,而当时我正试图通过JS代码发布到FB组(类似于原始问题)。
我终于破解了它-经过测试并可以工作:
setTimeout(() => {
document.querySelector('[placeholder^="Write something"]').click();
setTimeout(() => {
let postText = "I'm a Facebook post from Javascript!";
let dataDiv = document.querySelector('[contenteditable] [data-offset-key]');
let dataKey = dataDiv.attributes["data-offset-key"].value;
//Better to construct the span structure exactly in the form FB does it
let spanHTML = `<span data-offset-key="${dataKey}"><span data-text="true">${postText}</span></span>`;
dataDiv.innerHTML = spanHTML;
let eventType = "input";
//This can probably be optimized, no need to fire events for so many elements
let div = document.querySelectorAll('div[role=presentation]')[1].parentElement.parentElement;
let collection = div.getElementsByTagName("*");
[...collection].forEach(elem => {
let evt = document.createEvent("HTMLEvents");
evt.initEvent(eventType, true, true); //second "true" is for bubbling - might be important
elem.dispatchEvent(evt);
});
//Clicking the post button
setTimeout(()=>{
document.querySelector('.rfloat button[type=submit][value="1"]').click();
},2000);
}, 4000);
}, 7000);
这就是故事,正如我从这篇文章中的先前评论以及对FB代码的挖掘中学到的。 FB使用React,因此由于React使用虚拟DOM,因此对DOM的更改不会“流行”。如果从JS更改DOM后单击“发布”,则不会发布文本。因此,您必须按照此处的建议手动触发事件。
但是-为正确的元素触发正确的事件是一件棘手的事情,几乎使我无法成功。长时间的工作后,我发现这段代码行得通,可能是因为它针对多个元素,从群组发布的父元素开始,然后向下钻取到所有子元素并为每个子元素触发事件(这是{{ 1}}位)。按照编写的方法,显然可以优化此方法以找到需要触发事件的一个正确元素。
关于触发的哪个事件,如此处所讨论的,我尝试了几个,发现[...collection].forEach(elem => {
是其中的一个。另外,在我将"input"
的第二个参数更改为initEvent
-即true
之后,代码开始工作。不知道这是否有所作为,但是我已经花了很多时间来摆弄这个东西,如果它起作用的话,对我来说足够了。当然,evt.initEvent(eventType, true, true)
可以一起玩。
关于我尝试走的一条不同路径的另一条注释,最终却徒劳无功:使用React Dev Tools Chrome扩展程序,您可以访问组件本身及其所有setTimeout
和props
使用state
。令人惊讶的是,它在控制台的外部内也有效,因此使用TamperMonkey之类的东西来运行JS代码也可以。我实际上发现FB将帖子文本保持在该状态的位置。作为参考,它位于名为$r
的组件中,该组件负责帖子的编辑器部分,下面是访问该代码的代码。
ComposerStatusAttachmentMentionsInputContainer
实际上可以访问很多React内容,例如$r
。从理论上讲,我相信我可以使用它来设置React中发布文本的状态(如果您知道React,您将同意setState
是触发更改的正确方法)。
但是,经过很长时间,我发现这很难做到,因为FB在React之上使用了一个名为Draft.js的框架,该框架可以处理所有帖子。该框架具有自己的方法,类,数据结构,而没有,并且很难在没有源代码的情况下从“外部”进行操作。
我还尝试手动触发附加到组件的setState
函数,由于我没有正确的参数(像onchange
和{{ 1}}来自Draft.Js,需要使用我无法访问的editorContent
之类的方法精心构造(我怎么也无法从缠绕在其中的库中访问静态方法,我该如何访问)源代码?我没办法。
无论如何,只要您具有React开发工具并且突出显示selectionContent
,就可以访问用于存储文本的状态变量的代码:
Modifier
但是,正如我写的那样,这几乎没有用:-)
答案 2 :(得分:2)
由于我无法通过“正常” facebook页面发表评论,所以我记得他们也有移动版本,该版本位于m.facebook。 com,那里仍然有“提交”按钮,因此根据您的需求,这可能是个不错的选择
因此,您可以转到移动Facebook帖子(例如https://m.facebook.com/${author}/posts/${postId})并这样做
loop {
...
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
答案 3 :(得分:0)
经过3周的实验(使用@Benjamin Solum的fireEvent
函数),这是一个有效的解决方案:
querySelector
方法)此版本只能在您的个人墙上使用(除非您更改查询选择器)
function fireEvent(type, element, keyCode) {
var evt;
if(document.createEvent) {
evt = document.createEvent("HTMLEvents");
evt.initEvent(type, true, true);
} else {
evt = document.createEventObject();
evt.eventType = type;
}
evt.eventName = type;
if (keyCode !== undefined){
evt.keyCode = keyCode;
evt.which = keyCode;
}
if(document.createEvent) {
element.dispatchEvent(evt);
} else {
element.fireEvent("on" + evt.eventType, evt);
}
}
// clicking the comment link - it reveals the combobox
document.querySelector(".fbTimelineSection .comment_link").click();
setTimeout(function(){
var combobox = document.querySelector(".fbTimelineSection [role='combobox']");
var spanWrapper = document.querySelector(".fbTimelineSection [role='combobox'] span");
// add text to the combobox
spanWrapper.innerHTML = "<span data-text='true'>Thank you!</span>";
var spanElement = document.querySelector(".fbTimelineSection [role='combobox'] span span");
fireEvent("blur", combobox);
fireEvent("focus", combobox);
fireEvent("input", combobox);
fireEvent("keydown", spanElement, 13); // pushing enter
},2000);
答案 4 :(得分:0)
function fireEvent(type, element) {
var evt;
if(document.createEvent) {
evt = document.createEvent("HTMLEvents");
evt.initEvent(type, true, true);
} else {
evt = document.createEventObject();
evt.eventType = type;
}
evt.eventName = type;
evt.keyCode = 13;
evt.which = 13;
if(document.createEvent) {
element.dispatchEvent(evt);
} else {
element.fireEvent("on" + evt.eventType, evt);
}
}
fireEvent('keydown', document.
答案 5 :(得分:0)
为了解决您的问题,您可能会看到此链接,有一个示例如何“使用 JavaScript 对 facebook 帖子自动评论”
“以下是步骤:
使用 m.facebook.com 转到 facebook 页面 登录并打开任何帖子。 按 Ctrl+Shift+I 在 Chrome 中打开开发人员模式 导航到控制台。 现在,运行以下脚本。”
var count = 100;
var message = "Hi";
var loop = setInterval(function(){
var input = document.getElementsByName("comment_text")[0];
var submit = document.querySelector('button[type="submit"]');
submit.disabled = false;
input.value = message;
submit.click();
count -= 1;
if(count == 0)
{
clearInterval(loop);
}
}, 10000);
亲切的问候
参考:source page