如何向复制的网络文本添加额外信息


103

现在,某些网站使用Tynt的JavaScript服务,该服务将文本追加到复制的内容中。

如果使用此方法从站点复制文本,然后粘贴,则在文本底部将获得指向原始内容的链接。

Tynt也会在发生这种情况时对其进行跟踪。做得好,这是一个巧妙的技巧。

他们执行此操作的脚本令人印象深刻-而不是尝试操纵剪贴板(只有IE的较早版本才允许他们执行默认操作,并且应该始终将其关闭),而是操纵实际的选择。

因此,当您选择文本块时,多余的内容将作为隐藏内容添加<div>到您的选择中。粘贴时,多余的样式将被忽略,并显示多余的链接。

实际上,使用简单的文本块很容易做到这一点,但是当您考虑到在不同浏览器中跨复杂HTML进行所有选择时,这将是一场噩梦。

我正在开发一个Web应用程序-我不希望任何人都能跟踪复制的内容,我希望这些额外的信息包含上下文相关的内容,而不仅仅是链接。在这种情况下,Tynt的服务并不适合。

有谁知道开源的JavaScript库(可能是jQuery插件或类似的库)提供相似的功能,但不公开内部应用程序数据?


1
stackoverflow.com/questions/6344588/…上查看我的答案。它的执行方式与您建议的非常相似
Niklas


48
请不要这样做。请请不要。
沙发和

5
@couchand为什么不呢?我知道在垃圾邮件站点上这很烦人,但这是针对可用于引用且内部数据敏感的应用程序。这就是为什么我不想使用Tynt。
基思

4
你确定你要这么做吗?作为用户,我讨厌它,我会将这种愤怒传达给您的产品:请勿触摸我的剪贴板!
aloisdg移至codidact.com

Answers:


138

2020更新

适用于所有最新浏览器的解决方案。

document.addEventListener('copy', (event) => {
  const pagelink = `\n\nRead more at: ${document.location.href}`;
  event.clipboardData.setData('text', document.getSelection() + pagelink);
  event.preventDefault();
});
Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br/>
<textarea name="textarea" rows="7" cols="50" placeholder="paste your copied text here"></textarea>


[旧帖子-2020年更新之前]

向复制的Web文本添加额外信息的主要方法有两种。

1.操纵选择

这个想法是要注意copy event,然后将带有我们额外信息的隐藏容器附加到dom,然后将选择范围扩展到该容器。
这种方法适合从本文c.bavota。还要检查jitbit的版本以了解更复杂的情况。

  • 浏览器兼容性:所有主要浏览器,IE> 8。
  • 演示jsFiddle演示
  • JavaScript代码

    function addLink() {
        //Get the selected text and append the extra info
        var selection = window.getSelection(),
            pagelink = '<br /><br /> Read more at: ' + document.location.href,
            copytext = selection + pagelink,
            newdiv = document.createElement('div');

        //hide the newly created container
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';

        //insert the container, fill it with the extended text, and define the new selection
        document.body.appendChild(newdiv);
        newdiv.innerHTML = copytext;
        selection.selectAllChildren(newdiv);

        window.setTimeout(function () {
            document.body.removeChild(newdiv);
        }, 100);
    }

    document.addEventListener('copy', addLink);

2.操作剪贴板

这个想法是观看copy event并直接修改剪贴板数据。使用该clipboardData属性是可能的。请注意,此属性可在中的所有主要浏览器中使用read-only。该setData方法仅在IE上可用。

  • 浏览器兼容性:IE> 4。
  • 演示jsFiddle演示
  • JavaScript代码

    function addLink(event) {
        event.preventDefault();

        var pagelink = '\n\n Read more at: ' + document.location.href,
            copytext =  window.getSelection() + pagelink;

        if (window.clipboardData) {
            window.clipboardData.setData('Text', copytext);
        }
    }

    document.addEventListener('copy', addLink);

1
干杯! 不幸的是,我们需要它在IE中运行,但这并不是一个不好的开始。
基思

2
应该有一个“ <pre>”标签的解决方法,此脚本的更平滑版本在这里
Alex

15
请注意,如果更改window.clipboardData为,则“操作剪贴板”在FireFox,Chrome和Safari中完全有效event.clipboardData。IE(v11也是)不支持event.clipboardData jsfiddle.net/m56af0je/8
mems

3
如果您使用的是Google Analytics(分析)等,甚至可以触发一个事件来记录用户正在从您的网站复制的内容。有趣
geedubb 2015年

2
第一个选项将忽略复制文本的换行符。
瑟汉姆

7

这是经过修改的解决方案的原始javascript解决方案,但支持更多浏览器(跨浏览器方法)

function addLink(e) {
    e.preventDefault();
    var pagelink = '\nRead more: ' + document.location.href,
    copytext =  window.getSelection() + pagelink;
    clipdata = e.clipboardData || window.clipboardData;
    if (clipdata) {
        clipdata.setData('Text', copytext);
    }
}
document.addEventListener('copy', addLink);

3

我测试并正在运行的jQuery的最短版本是:

jQuery(document).on('copy', function(e)
{
  var sel = window.getSelection();
  var copyFooter = 
        "<br /><br /> Source: <a href='" + document.location.href + "'>" + document.location.href + "</a><br />© YourSite";
  var copyHolder = $('<div>', {html: sel+copyFooter, style: {position: 'absolute', left: '-99999px'}});
  $('body').append(copyHolder);
  sel.selectAllChildren( copyHolder[0] );
  window.setTimeout(function() {
      copyHolder.remove();
  },0);
});

实际将结果复制到剪贴板的代码在哪里?
vsync

@vsync我相信这只是在复制发生之前添加了功能(由用户启动时由系统完成)。
TerranRich

@vsync-正如TerraRich所说,我试图回答这个问题,它是关于在复制的文本中添加额外的信息,因此解决方案仅涵盖了这一部分。
user2276146

3

这是jquery中的一个插件,用于执行此操作 https://github.com/niklasvh/jquery.plugin.clipboard 来自项目自述文件“此脚本在调用复制事件之前修改选择的内容,从而导致复制的选择与用户选择的内容不同。

这使您可以将内容添加/添加到所选内容之前,例如版权信息或其他内容。

根据MIT许可发布”


1
这看起来很有希望。它使用了我们的CSP不允许的内联样式,但是有可能被改编。干杯!
基思2015年

3

改善答案,更改后恢复选择,以防止复制后出现随机选择。

function addLink() {
    //Get the selected text and append the extra info
    var selection = window.getSelection(),
        pagelink = '<br /><br /> Read more at: ' + document.location.href,
        copytext = selection + pagelink,
        newdiv = document.createElement('div');
    var range = selection.getRangeAt(0); // edited according to @Vokiel's comment

    //hide the newly created container
    newdiv.style.position = 'absolute';
    newdiv.style.left = '-99999px';

    //insert the container, fill it with the extended text, and define the new selection
    document.body.appendChild(newdiv);
    newdiv.innerHTML = copytext;
    selection.selectAllChildren(newdiv);

    window.setTimeout(function () {
        document.body.removeChild(newdiv);
        selection.removeAllRanges();
        selection.addRange(range);
    }, 100);
}

document.addEventListener('copy', addLink);

@TsukimotoMitsumasa应该有var range = selection.getRangeAt(0);
Vokiel

恢复文本选择是一个好主意,否则,它将破坏默认的浏览器行为。
谢尔盖

2

2018年的改进

document.addEventListener('copy', function (e) {
    var selection = window.getSelection();
    e.clipboardData.setData('text/plain', $('<div/>').html(selection + "").text() + "\n\n" + 'Source: ' + document.location.href);
    e.clipboardData.setData('text/html', selection + '<br /><br />Source: <a href="' + document.location.href + '">' + document.title + '</a>');
    e.preventDefault();
});

1
复制粘贴时,格式会丢失(<a><img><b>和其他标签)。最好获取选定文本的HTML代码。使用此答案中的getSelectionHtml()函数:[ stackoverflow.com/a/4177234/4177020]现在,您可以使用以下命令替换此字符串var selection = window.getSelection();var selection = getSelectionHtml();
Dmitry Kulahin

0

还有一个更短的解决方案:

jQuery( document ).ready( function( $ )
    {
    function addLink()
    {
    var sel = window.getSelection();
    var pagelink = "<br /><br /> Source: <a href='" + document.location.href + "'>" + document.location.href + "</a><br />© text is here";
    var div = $( '<div>', {style: {position: 'absolute', left: '-99999px'}, html: sel + pagelink} );
    $( 'body' ).append( div );
    sel.selectAllChildren( div[0] );
    div.remove();
    }



document.oncopy = addLink;
} );

0

它是以上2个答案的汇总以及与Microsoft Edge的兼容性。

我还在末尾添加了原始选择的还原,因为在任何浏览器中都可以默认使用它。

function addCopyrightInfo() {
    //Get the selected text and append the extra info
    var selection, selectedNode, html;
    if (window.getSelection) {
        var selection = window.getSelection();
        if (selection.rangeCount) {
            selectedNode = selection.getRangeAt(0).startContainer.parentNode;
            var container = document.createElement("div");
            container.appendChild(selection.getRangeAt(0).cloneContents());
            html = container.innerHTML;
        }
    }
    else {
        console.debug("The text [selection] not found.")
        return;
    }

    // Save current selection to resore it back later.
    var range = selection.getRangeAt(0);

    if (!html)
        html = '' + selection;

    html += "<br/><br/><small><span>Source: </span><a target='_blank' title='" + document.title + "' href='" + document.location.href + "'>" + document.title + "</a></small><br/>";
    var newdiv = document.createElement('div');

    //hide the newly created container
    newdiv.style.position = 'absolute';
    newdiv.style.left = '-99999px';

    // Insert the container, fill it with the extended text, and define the new selection.
    selectedNode.appendChild(newdiv); // *For the Microsoft Edge browser so that the page wouldn't scroll to the bottom.

    newdiv.innerHTML = html;
    selection.selectAllChildren(newdiv);

    window.setTimeout(function () {
        selectedNode.removeChild(newdiv);
        selection.removeAllRanges();
        selection.addRange(range); // Restore original selection.
    }, 5); // Timeout is reduced to 10 msc for Microsoft Edge's sake so that it does not blink very noticeably.  
}

document.addEventListener('copy', addCopyrightInfo);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.