制作chrome插件,解决简书复制的小尾巴——我最终失败了

我们在简书(或者其他的一些网站)看到了一些代码就会想复制下来,但是复制下来之后会出现一个问题,就是小尾巴。


image.png

很长的一个小尾巴。
如果一不小心就会运行这段代码。
但是不知道为什么,我的内容没有小尾巴,我以为是每个文章都会有的来着的。
先来说说最简单的办法(其实也是足够的了,但是为了学习到更多东西还是用麻烦的办法吧)把它的copy事件直接取消掉。


直接取消掉copy事件

或者还有一种办法
var content = document.getElementsByClassName('show-content')[0];
content.removeEventListener('copy',getEventListeners(content).copy[0].listener);

但是,问题是,他们都无法用在JS代码中,只有在控制台产生效果而已。
所以,通过制作一个chrome的插件来解决这个问题,当然啦,如果是用在其他浏览器上面也是可以的啊,因为大家都借鉴了chrome的做法。
说说通过这篇文章可以学到的内容吧(如果你不会的话)

1.制作chrome插件。

2.了解copy事件。

3.了解Selection和Range。


第一部分,说说简书是怎么实现小尾巴的好啦。
有一个事件叫做copy,在复制的时候会触发它,所以说,像这样子。

window.addEventListener('copy',function(e){
            console.log(e);
            console.log(e.clipboardData);
 })

结果


只要按下了ctrl+c就会产生这样的结果了

但是要直接过去到底复制了什么是做不到的(以前用IE是可以的),要不然就会产生安全问题了。

所以说,clipboardData 这个东西只有 setData() 才是有反应的,getData() 返回的一直是一个空行。
所以,要实现小尾巴,有三个步骤要走的。

1.获取用户选中的内容

2.在原有内容的基础上添加小尾巴

3.把修改好的内容用 clipboardData.setData() 添加进黏贴板。

第二和第三步都很容易可以实现。所以重点在第一步了。


第二部分,说说如何实现第一步。
先说两个东西

var selection  = getSelection();
var range = select.getRangeAt(0);
//因为在chrome上range数量永远都是一个,所以一直用0就好了
//注意啦,如果事先没有选中过任何对象的话,第二行会报错的。

这两个东西(selection和range)在MDN说的很明白了就不多说了。中文教程也是有的。
但是,为了让不了解的人快点懂,还是说说好了。
#####################################

一首来自首页的诗歌

对比一下下面的效果。


toString和copyCotents

如果,是下面用户复制到的内容是下面的那种肯定会不高兴了。
但是,上面的那种呢。有html节点诶,怎么办。
很好处理的。就是把这一段东西插入一个用户看不见的地方去并且在最后加入小尾巴,然后,利用 下面四个API进行全部选取就好了。
这样子加了小尾巴的内容就到了用户的剪贴板里面了。

        Range.setEnd()
        Range.setStart()
        document.createRange()
        Selection.addRange()

第三部分了,说说怎么放在一个看不见的地方,然后还让它被选取。

为了方便说明还是让大家可以看见它好了,相信会看见这篇文章的人实现这个东西应该是没有问题的。
跳过了若干你应该知道的步骤以后来到了这里。


image.png

image.png

然后是这样的。

var selection  = getSelection();
var range = document.createRange()
selection.removeAllRanges();
range.setStart(experimental.firstChild,0);
range.setEndAfter(experimental.lastChild);
select.addRange(range)
得到的效果

可以自由进行既然已经选中了,那么可以触发Copy了。
关于如何触发copy当然是这个咯

document.execCommand('Copy');

目前为止,完整的代码如下。

        let blankSpace=document.createElement('div');
        let article=document.getElementsByClassName('article')[0];
        article.insertBefore(blankSpace,article.firstChild);
        window.addEventListener('copy',function(e){
            let data=e['clipboardData'];
            let selection=getSelection();
            let oldRange=selection.getRangeAt(0);
            //把原来的range保存下来,得会还要放回去的。
            let content=oldRange.cloneContents();
            blankSpace.appendChild(content);
            let newRange=document.createRange();
            selection.removeAllRanges();
            newRange.setStart(blankSpace.firstChild,0);
            newRange.setEndAfter(blankSpace.lastChild);
            selection.addRange(newRange);
            document.execCommand('Copy');
            selection.removeAllRanges();
            selection.addRange(oldRange);
        })
//!!!但是,这段代码真的是正确的么,它可以实现我们的目的么。不可以的。

说说吧,为什么不可以。很简单的原因,会产生递归调用。document.execCommand('Copy'); 一样会产生一个copy事件,而且这个事件会让所有的Listener收到,相当于是广播的效果。
怎么处理呢。当执前的时候remove掉,之后再加上。
同时,document.execCommand是一个广播,也就是说,简书的copy会再来一次,我们本来是像复制没有小尾巴的结果,结果在复制的时候又被加上了小尾巴。


第三部分,如何解决上面的问题。
先说结果,我还是没想到怎么办才好。但是还是说说我都是怎么考虑的吧。我们都知道,先注册的事件先执行,后注册的后执行。
我们加进去的事件肯定是后执行的。
我用一下代码验证了我的想法

var hanshu=getEventListeners(document.getElementsByClassName('show-content')[0]).copy[0].listener
        
        var  aacfun = function(e){
            console.log('aaa');
            hanshu(e)
        }
        document.getElementsByClassName('show-content')[0].removeEventListener('copy',hanshu)
        document.getElementsByClassName('show-content')[0].addEventListener('copy',aacfun)

把原来的函数提取出来,然后再注册一次(注意,getEventListeners是Chrome的API代码里面是用不了的,只可以在console里面。)
结果,告诉我aaa被先输出,然后才执行了我的回调函数。

我还干了另外的事情。关于 document.execcommand的返回值,如果是true代表执行了,false代表不可以执行,document.execcommand('copy')出于安全考虑只有在用户触发的事件才可以触发(模拟的就不可以了),并且回调函数中不可以用 setTimeout之类的操作。

我的返回值始终是 true 而且,我在它后面被处理。我搞不明白为什么我的结果里面仍然有小尾巴。
好了,这篇文章暂时就到这里了,继续下去只是浪费时间罢了。
很对不起看了文章的人们了,不过,我认为我写的文章更加是为了去“划重点”,告诉大家有什么东西要去学,要去用的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容