วิธีเพิ่มข้อมูลเพิ่มเติมในข้อความเว็บที่คัดลอก


103

ขณะนี้บางเว็บไซต์ใช้บริการ JavaScript จากTyntที่ต่อท้ายข้อความเข้ากับเนื้อหาที่คัดลอก

หากคุณคัดลอกข้อความจากไซต์โดยใช้สิ่งนี้แล้ววางคุณจะได้รับลิงก์ไปยังเนื้อหาต้นฉบับที่ด้านล่างของข้อความ

Tynt ยังติดตามสิ่งนี้เมื่อเกิดขึ้น เป็นเคล็ดลับที่ทำได้ดี

สคริปต์ของพวกเขาในการทำสิ่งนี้น่าประทับใจ - แทนที่จะพยายามจัดการคลิปบอร์ด (ซึ่ง IE เวอร์ชันเก่าเท่านั้นที่อนุญาตให้ทำตามค่าเริ่มต้นและควรปิดอยู่เสมอ) พวกเขาจะจัดการกับการเลือกจริง

ดังนั้นเมื่อคุณเลือกกลุ่มข้อความเนื้อหาพิเศษจะถูกเพิ่มเป็นส่วนที่ซ่อน<div>อยู่ในการเลือกของคุณ เมื่อคุณวางสไตล์พิเศษจะถูกละเว้นและลิงก์พิเศษจะปรากฏขึ้น

จริงๆแล้วนี่เป็นเรื่องง่ายที่จะทำกับบล็อกข้อความธรรมดา ๆ แต่จะเป็นฝันร้ายเมื่อคุณพิจารณาการเลือกทั้งหมดที่เป็นไปได้ใน HTML ที่ซับซ้อนในเบราว์เซอร์ต่างๆ

ฉันกำลังพัฒนาเว็บแอปพลิเคชัน - ฉันไม่ต้องการให้ใครสามารถติดตามเนื้อหาที่คัดลอกมาและฉันต้องการให้ข้อมูลเพิ่มเติมมีบางอย่างตามบริบทแทนที่จะเป็นเพียงลิงก์ บริการของ Tynt ไม่เหมาะสมจริงๆในกรณีนี้

มีใครรู้จักไลบรารี JavaScript แบบโอเพนซอร์ส (อาจเป็นปลั๊กอิน jQuery หรือคล้ายกัน) ที่มีฟังก์ชันการทำงานที่คล้ายกัน แต่ไม่เปิดเผยข้อมูลแอปพลิเคชันภายใน


1
มีลักษณะที่คำตอบของฉันที่stackoverflow.com/questions/6344588/... มันทำคล้ายกันมากตามที่คุณเสนอ
Niklas


48
กรุณาอย่าทำเช่นนี้ ได้โปรดโปรดอย่า
couchand

5
@couchand ทำไมไม่? ฉันเข้าใจว่าสิ่งนี้น่ารำคาญแค่ไหนในเว็บไซต์สแปม แต่นี่เป็นแอปพลิเคชันที่สามารถใช้สำหรับการอ้างอิงและข้อมูลภายในมีความละเอียดอ่อน นั่นเป็นเหตุผลที่ฉันไม่ต้องการใช้ Tynt
Keith

4
แน่ใจไหมว่าต้องการทำสิ่งนี้ ในฐานะผู้ใช้ฉันเกลียดมันและฉันจะถ่ายทอดความโกรธนี้ลงในผลิตภัณฑ์ของคุณ: อย่าแตะต้องคลิปบอร์ดของฉัน!
aloisdg ย้ายไปที่ codidact.com

คำตอบ:


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]

มีสองวิธีหลักในการเพิ่มข้อมูลพิเศษให้กับข้อความเว็บที่คัดลอก

1. การจัดการการเลือก

แนวคิดคือการเฝ้าดูcopy eventจากนั้นต่อท้ายคอนเทนเนอร์ที่ซ่อนอยู่พร้อมข้อมูลเพิ่มเติมของเราไปที่domและขยายการเลือกไป
วิธีนี้เป็นวิธีที่ดัดแปลงมาจากบทความนี้โดยc.bavota ตรวจสอบเวอร์ชันของjitbitด้วยสำหรับกรณีที่ซับซ้อนมากขึ้น

  • ความเข้ากันได้ของเบราว์เซอร์ : เบราว์เซอร์หลักทั้งหมด IE> 8
  • การสาธิต : jsFiddle demoสาธิต
  • รหัส 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 แต่นั่นไม่ใช่การเริ่มต้นที่ไม่ดี
Keith

2
ควรมีวิธีแก้ปัญหาสำหรับแท็ก "<pre>" สคริปต์นี้เวอร์ชันที่ราบรื่นกว่านี้อยู่ที่นี่
Alex

15
โปรดทราบว่า "การจัดการคลิปบอร์ด" ทำงาน prefectly ใน Firefox, Chrome และ Safari ถ้าคุณเปลี่ยนไปwindow.clipboardData event.clipboardDataIE (v11 ด้วย) ไม่รองรับevent.clipboardData jsfiddle.net/m56af0je/8

3
หากคุณกำลังใช้ Google Analytics เป็นต้นคุณยังสามารถปิดเหตุการณ์เพื่อบันทึกสิ่งที่ผู้ใช้กำลังคัดลอกจากไซต์ของคุณ น่าสนใจ
geedubb

2
ตัวเลือกแรกละเว้นอักขระบรรทัดใหม่ของข้อความที่คัดลอก
58

7

นี่เป็นวิธีการแก้ปัญหา vanilla 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 จากโครงการ readme "สคริปต์นี้แก้ไขเนื้อหาของการเลือกก่อนที่จะเรียกเหตุการณ์การคัดลอกส่งผลให้เกิดการคัดลอก แตกต่างจากสิ่งที่ผู้ใช้เลือก

สิ่งนี้ช่วยให้คุณสามารถต่อท้าย / ต่อท้ายเนื้อหาในการเลือกได้เช่นข้อมูลลิขสิทธิ์หรือเนื้อหาอื่น ๆ

เผยแพร่ภายใต้ใบอนุญาต MIT "


1
นั่นดูมีอนาคตมาก ใช้รูปแบบอินไลน์ซึ่งเราไม่อนุญาตกับ CSP ของเรา แต่อาจปรับเปลี่ยนได้ ไชโย!
Keith

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

การกู้คืนการเลือกข้อความเป็นความคิดที่ดีมิฉะนั้นจะทำลายพฤติกรรมเริ่มต้นของเบราว์เซอร์
Sergey

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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.