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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2026335/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:27:52  来源:igfitidea点击:

How to add extra info to copied web text

javascriptclipboard

提问by Keith

Some websites now use a JavaScript service from Tyntthat appends text to copied content.

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

If you copy text from a site using this and then paste you get a link to the original content at the bottom of the text.

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

Tynt also tracks this as it happens. It's a neat trick well done.

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

Their script for doing this is impressive - rather than try to manipulate the clipboard (which only older versions of IE lets them do by default and which should always be turned off) they manipulate the actual selection.

他们执行此操作的脚本令人印象深刻 - 而不是尝试操纵剪贴板(默认情况下只有旧版本的 IE 允许他们这样做并且应该始终关闭)他们操纵实际选择。

So when you select a block of text the extra content is added as a hidden <div>included in your selection. When you paste the extra style is ignored and the extra link appears.

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

This is actually fairly easy to do with simple blocks of text, but a nightmare when you consider all the selections possible across complex HTML in different browsers.

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

I'm developing a web application - I don't want anyone to be able to track the content copied and I would like the extra info to contain something contextual, rather than just a link. Tynt's service isn't really appropriate in this case.

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

Does anyone know of an open source JavaScript library (maybe a jQuery plug in or similar) that provides similar functionality but that doesn't expose internal application data?

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

回答by CronosS

2020 Update

2020 更新

Solution that works on all recentbrowsers.

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

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>



[Older post - before the 2020 update]

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

There are two main ways to add extra info to copied web text.

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

1. Manipulating the selection

1. 操作选择

The idea is to watch for the copy event, then append a hidden container with our extra info to the dom, and extend the selection to it.
This method is adapted from this articleby c.bavota. Check also jitbit's versionfor more complex case.

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

  • Browser compatibility: All major browsers, IE > 8.
  • Demo: jsFiddle demo.
  • Javascript code:
  • 浏览器兼容性:所有主流浏览器,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. Manipulating the clipboard

2. 操作剪贴板

The idea is to watch the copy eventand directly modify the clipboard data. This is possible using the clipboardDataproperty. Note that this property is available in all major browsers in read-only; the setDatamethod is only available on IE.

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

  • Browser compatibility: IE > 4.
  • Demo: jsFiddle demo.
  • Javascript code:
  • 浏览器兼容性: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);

回答by GiorgosK

This is a vanilla javascript solution from a modified solution above but supports more browsers (cross browser method)

这是上述修改后的解决方案中的香草 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);

回答by user2276146

The shortest version for jQuery that I tested and is working is:

我测试过并正在工作的 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);
});

回答by Saikat Guha

Here is a plugin in jquery to do that https://github.com/niklasvh/jquery.plugin.clipboardFrom the project readme "This script modifies the contents of a selection prior to a copy event being called, resulting in the copied selection being different from what the user selected.

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

This allows you to append/prepend content to the selection, such as copyright information or other content.

这允许您将内容附加/预先添加到选择中,例如版权信息或其他内容。

Released under MIT License"

在 MIT 许可下发布”

回答by digitalPBK

Improving on the answer, restore selection after the alterations to prevent random selections after copy.

改进答案,在更改后恢复选择以防止复制后的随机选择。

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);

回答by tronic

Improvement for 2018

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();
});

回答by Sergey

It's a compilation of 2 answers above + compatibility with Microsoft Edge.

这是上面 2 个答案的汇编 + 与 Microsoft Edge 的兼容性。

I've also added a restore of the original selection at the end, as it is expected by default in any browser.

我还在最后添加了原始选择的恢复,因为它在任何浏览器中都是默认的。

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 almo

Also a little shorter solution:

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

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;
} );