为掘金编写了一款简易版一键三连的油猴脚本(一)+https://developer.aliyun.com/article/1394364
3.2、尝试让div获取焦点
在这一步的时候,率先尝试的是下面的这个方法,因为这位作者尝试用Vue去实现掘金发送沸点的那个选择表情的功能,这篇文章也让我避免了一些坑~
Vue实现可编辑div获取焦点🎉 感谢作者~
这篇文章用了
以上三种方式来尝试实现,第一个 tabindex=0
,好像是不行的,我就直接跳过了。
我又接着去找寻第二种方式:
发现下面这篇文章:
在可编辑div中定位光标和设置光标,还给了代码和实例
作者的源代码,大家可以点链接过去看一下,我就不增加篇幅了。
参考完上面作者的代码,我改成了下面这样:
// 定义最后光标对象 var lastEditRange; // 编辑框点击事件 document.getElementsByClassName("rich-input")[0].onclick = function () { // 获取选定对象 var selection = getSelection(); // 设置最后光标对象 lastEditRange = selection.getRangeAt(0); }; // 编辑框按键弹起事件 document.getElementsByClassName("rich-input")[0].onkeyup = function () { // 获取选定对象 var selection = getSelection(); // 设置最后光标对象 lastEditRange = selection.getRangeAt(0); }; // 发送表情 function editContent() { // 获取可编辑框 var editor = document.getElementsByClassName("rich-input")[0]; // 获取输入框 var comment = [ "针不戳呀,写的针不戳!", "学习了!b( ̄▽ ̄)d", "本文不错( ̄ˇ ̄),值得学习!(= ̄ω ̄=)", "感谢博主的分享!(^ ^)/▽▽\(^ ^)", "感谢博主,你的文章让我得到一些收获!( ̄ˇ ̄)", ]; var STARTNUMBER = -1; var ENDNUMBER = 5; var temp_count = Math.floor(Math.random() * (STARTNUMBER - ENDNUMBER + 1)) + ENDNUMBER; //取STARTNUMBER-ENDNUMBER之间的随机数 [STARTNUMBER,ENDNUMBER] var editComment = comment[temp_count]; // 编辑框获得焦点 editor.focus(); // 获取选定对象 var selection = getSelection(); // 如果保存的有上次的光标对象 if (lastEditRange) { // 清除所有选区 selection.removeAllRanges(); // 添加最后光标还原之前的状态 selection.addRange(lastEditRange); } // 如果选定对象范围是编辑框范围 // 创建表情文本节点进行插入 var emojiText = document.createTextNode(editComment); // 如果文本框的子元素大于0,则表示有其他元素,则按照位置插入表情节点 if (editor.childNodes.length > 0) { for (var i = 0; i < editor.childNodes.length; i++) { if (i == selection.anchorOffset) { editor.insertBefore(emojiText, editor.childNodes[i]); } } } else { // 否则直接插入一个表情元素 editor.appendChild(emojiText); } // 创建新的光标对象 var range = document.createRange(); // 将光标对象的范围界定为新建的表情节点 range.selectNodeContents(emojiText); // 定位光标位置在表情节点的最大长度位置 range.setStart(emojiText, emojiText.length); // 将选区折叠为一个光标 range.collapse(true); // 清除所有光标对象A selection.removeAllRanges(); // 添加新的光标对象 selection.addRange(range); // 记录最后光标对象 lastEditRange = selection.getRangeAt(0); } editContent();
执行效果如下:
(图片说明:focus 方法确实成功,点亮文本框了,但是内容的改变,仍然无法被监听)
包括光标的位置此时也改变了,但它仍然只算我修改了视图内容,因为评论的按钮仍然是暗的。
这个时候,我突然想到,我手动给它赋值不行,我可以操纵复制粘贴方法啊。
然后这个时候又开始踩坑了!!!
3.3、尝试使用copy、paste 方法
我只是隐约知道浏览器可以操作 copy、paste 方法,并没有尝试过。
又继续开始疯狂的搜索~
这次尝试之前,我先了试,确定在获取到div内容框的焦点后,cv是可以的之后,我就想在粘贴板上做点文章
我的思路是,先把评论内容制造好,然后用Js复制到粘贴版上,之后再调用 paste 方法将内容粘贴到 div 的那个内容框中去。
想法还是挺美好的。
参考着下面的内容进行着尝试
尝试了下面的内容
Document.execCommand()
方法- 异步的 Clipboard API
copy
事件和paste
事件
3.3.1、Document.execCommand()
最先尝试的 Document.execCommand()
事件,Chrome、Firefox 不支持
document.execCommand('paste')
导致这一步直接GG 了~
3.3.2、Clipboard API
然后 Clipboard API
是偏向于操作剪贴板,就是可以写入,读出,但是并不是触发 paste方法,
我也找了一个小案例:
<body> <p>hello world</p> <button id="btn-copy">copy text</button> <button id="btn-paste">copy text</button> <script> const copyBtn = document.querySelector('#btn-copy'); copyBtn.addEventListener( 'click', async function () { try { // 将 p 标签内的文本编辑后写入剪切板 await navigator.clipboard.writeText( `${document.querySelector('p').textContent}!` ); } catch (e) { console.error('Failed to copy: ', e); } }, false ); const pasteBtn = document.querySelector('#btn-paste'); pasteBtn.addEventListener( 'click', async function () { try { // 读取剪切板中的文本 const text = await navigator.clipboard.readText(); console.log(text); } catch (e) { console.error('Failed to read clipboard content: ', e); } }, false ); </script> </body>
这个坑也让我躺了,又去尝试下一个方法:
另外还参考了 MDN 文档:Element: paste event
3.3.3、clipboard.js
我也尝试了这个方法,但是我发现,它只能监听用户的 paste 事件,当时粘贴事件发生时,才能处理事件~
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <script type="text/javascript" src="https://cdn.bootcss.com/clipboard.js/2.0.1/clipboard.js" ></script> </head> <body> <!-- Target --> <input id="input" value="你好,我是宁在春" /> <!-- Trigger --> <button class="copy">Copy to clipboard</button> <button id="paste">paste</button> <textarea id="output"> </textarea> <script> var clipboard = new ClipboardJS(".copy", { text: function (trigger) { return doCopy(); }, }); var pastBtn = document.getElementById("output"); pastBtn.addEventListener("paste", function (event) { console.log(pastBtn); if (event.clipboardData || event.originalEvent) { var clipboardData = event.clipboardData || window.clipboardData; var val = clipboardData.getData("text"); if (val) { doPast(val); } else { throw new Error("剪切板内容为空或者非文本类型"); } event.preventDefault(); } }); //获取要复制到剪切板的内容 function doCopy() { return document.getElementById("input").value; } //处理剪切板内容 function doPast(value) { alert(value); } </script> </body> </html>
补充
:在这一步的时候,我原本还想继续去尝试用JavaScript 模拟键盘按键去尝试触发复制粘贴事件的,但是没有去尝试啦。
主要在网上搜到的知识,不敢说千篇一律,但是点开大都数文章略微有点让人失望~,还有一点就是转载来转载去(个人吐槽,轻喷),一篇文章能看见好几次,哈哈
后来想起第一篇看到的文章,聊到的掘金的表情,然后就有了下面的灵光一现~
3.4、灵光一现
这个时候,我想着,手动改你内容不行,直接点击表情,然后放到div中,这样总可以吧
因为只要打开emjoe 面板,点一下表情,就会自动的添加到那个内容框中去,这一次尝试竟然是ok的~
// 获取评论区焦点 function getFocus() { document.getElementsByClassName("rich-input")[0].focus(); } //打开emoje 表情选择框 function getEmojeClick() { document.getElementsByClassName("emoji-box")[0].click(); } //选择emoje表情 function getChoseEmoje() { var emojipicker = document.getElementsByClassName("emojipicker")[0]; var emojeImage = emojipicker.getElementsByClassName("list")[1]; var item = emojeImage.getElementsByClassName("item")[0]; var spanImage = item.getElementsByClassName("byte-tooltip__wrapper")[0]; var img = spanImage.querySelector("img"); img.click(); } getFocus(); getEmojeClick(); getChoseEmoje();
大家可以直接把这一步放到掘金的文章页面,F12后,将代码复制运行,是可行的~
在这一步可行之后,我又想在这个基础上增强,既然选择掘金的表情是可以的,那我先加一个表情,然后再加上我自己的评论内容,不就行了吗~,说做就做
代码不贴了,直接说结果,失败了~,还是和之前一模一样,发起请求的时候,根本没有携带这个数据内容
后记
最后实现效果大家也看到了,因为暂时没有找到更好的一个方法去实现,我最后用表情妥协了,表情选用了几个比较正向的表情,然后在评论的时候进行随机选择
代码比较偏向于基础,使用到的全部都是 JavaScript 中的基础知识,写出来也是我的一个尝试,大家喜欢与否,我并不能知晓。
关于这篇文章,如果是对于从来没有接触过油猴脚本的小伙伴来说,拿来看一看这么简单,也算是一个接触。
除了这一点外,我也不敢说此文,对读者而言,能有多少收获了。
如果感兴趣可以多做尝试,在这其中,多少会有一些收获。
对了,不要被陌生的事物吓住了,只要迈出第一步,那么就是成功的😀
我明白我对于前端领域,就是一位小白,文中不可避免可能会出现错误或遗漏,请大家一定要进行指出!
当然如果让你有所收获的话,也希望可以留下你的赞~,哈哈
大伙可以直接将代码放进油猴,来试一试这个脚本的效果,可以在这篇文章中,让我看到你们的实操吗~
也可以把第一个中 function 中的所有代码直接放到网页中执行,也是可以的~