Bagaimana menambahkan info tambahan ke teks web yang disalin

103

Beberapa situs web sekarang menggunakan layanan JavaScript dari Tynt yang menambahkan teks ke konten yang disalin.

Jika Anda menyalin teks dari situs menggunakan ini dan kemudian menempelkannya, Anda mendapatkan tautan ke konten asli di bagian bawah teks.

Tynt juga melacak ini saat terjadi. Ini trik rapi yang dilakukan dengan baik.

Skrip mereka untuk melakukan ini sangat mengesankan - daripada mencoba memanipulasi clipboard (yang hanya versi IE yang lebih lama memungkinkan mereka melakukannya secara default dan yang harus selalu dimatikan) mereka memanipulasi pilihan yang sebenarnya.

Jadi, ketika Anda memilih blok teks, konten tambahan ditambahkan sebagai tersembunyi yang <div>disertakan dalam pilihan Anda. Saat Anda menempelkan gaya ekstra diabaikan dan tautan tambahan muncul.

Ini sebenarnya cukup mudah dilakukan dengan blok teks sederhana, tetapi mimpi buruk ketika Anda mempertimbangkan semua pilihan yang mungkin di HTML kompleks di browser yang berbeda.

Saya sedang mengembangkan aplikasi web - Saya tidak ingin siapa pun dapat melacak konten yang disalin dan saya ingin info tambahan berisi sesuatu yang kontekstual, bukan hanya tautan. Layanan Tynt tidak benar-benar sesuai dalam kasus ini.

Adakah yang tahu tentang pustaka JavaScript open source (mungkin jQuery plug in atau serupa) yang menyediakan fungsionalitas serupa tetapi tidak mengekspos data aplikasi internal?

Keith
sumber
1
Lihat jawaban saya di stackoverflow.com/questions/6344588/… . Ini dilakukan sangat mirip seperti yang Anda usulkan
Niklas
48
Tolong jangan lakukan ini. TOLONG TOLONG jangan.
sofa dan
5
@couchdan mengapa tidak? Saya mengerti betapa menyebalkannya ini di situs spam, tetapi ini untuk aplikasi yang dapat digunakan untuk kutipan dan di mana data internalnya sensitif. Itulah mengapa saya tidak ingin menggunakan Tynt.
Keith
4
Anda yakin ingin melakukan ini? Sebagai pengguna, saya membencinya dan saya akan memasukkan kemarahan ini ke dalam produk Anda: Jangan sentuh papan klip saya!
aloisdg pindah ke codidact.com

Jawaban:

138

Pembaruan 2020

Solusi yang berfungsi di semua browser terbaru .

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>


[Pos lama - sebelum pembaruan tahun 2020]

Ada dua cara utama untuk menambahkan info tambahan ke teks web yang disalin.

1. Memanipulasi seleksi

Idenya adalah untuk memperhatikan copy event, kemudian menambahkan wadah tersembunyi dengan info ekstra kami ke dom, dan memperluas pilihan ke sana.
Metode ini diadaptasi dari artikel ini oleh c.bavota . Periksa juga versi jitbit untuk kasus yang lebih kompleks.

  • Kompatibilitas browser : Semua browser utama, IE> 8.
  • Demo : demo jsFiddle .
  • Kode 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. Memanipulasi clipboard

Idenya adalah untuk menonton copy eventdan langsung memodifikasi data clipboard. Ini dimungkinkan dengan menggunakan clipboardDataproperti. Perhatikan bahwa properti ini tersedia di semua browser utama di read-only; yang setDatametode ini hanya tersedia pada IE.

  • Kompatibilitas browser : IE> 4.
  • Demo : demo jsFiddle .
  • Kode 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);
CronosS
sumber
1
Bersulang! Sayangnya kami membutuhkannya bekerja di IE, tetapi itu bukan awal yang buruk.
Keith
2
Harus ada solusi untuk tag "<pre>", versi yang lebih halus dari skrip ini ada di sini
Alex
15
Perhatikan bahwa "Memanipulasi clipboard" bekerja prefectly di FireFox, Chrome dan Safari jika Anda mengubah window.clipboardDatake event.clipboardData. IE (v11 juga) tidak mendukung event.clipboardData jsfiddle.net/m56af0je/8
mems
3
Jika Anda menggunakan Google Analytics dll, Anda bahkan dapat mengaktifkan peristiwa untuk mencatat apa yang disalin pengguna dari situs Anda. Menarik
geedubb
2
Opsi pertama mengabaikan karakter baris baru dari teks yang disalin.
soham
7

Ini adalah solusi javascript vanilla dari solusi yang dimodifikasi di atas tetapi mendukung lebih banyak browser (metode lintas browser)

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);
GiorgosK
sumber
3

Versi terpendek untuk jQuery yang saya uji dan berfungsi adalah:

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);
});
pengguna2276146
sumber
di mana kode yang sebenarnya menyalin hasil ke clipboard?
vsync
@vsync Saya yakin ini hanya menambah fungsionalitas sebelum penyalinan dilakukan (yang dilakukan oleh sistem saat pengguna memulainya).
TerranRich
@vsync - seperti yang dikatakan TerraRich, saya mencoba menjawab pertanyaan, yaitu tentang menambahkan info tambahan ke teks yang disalin, jadi solusi hanya mencakup bagian ini.
pengguna2276146
3

Berikut adalah plugin di jquery untuk melakukannya https://github.com/niklasvh/jquery.plugin.clipboard Dari proyek readme "Skrip ini memodifikasi konten pilihan sebelum event copy dipanggil, menghasilkan pilihan yang disalin berbeda dari yang dipilih pengguna.

Ini memungkinkan Anda untuk menambahkan / menambahkan konten ke pilihan, seperti informasi hak cipta atau konten lainnya.

Dirilis di bawah Lisensi MIT "

sktguha.dll
sumber
1
Itu terlihat sangat menjanjikan. Ini menggunakan gaya sebaris yang tidak kami izinkan dengan CSP kami, tetapi ini berpotensi dapat diadaptasi. Bersulang!
Keith
3

Memperbaiki jawaban, mengembalikan pilihan setelah perubahan untuk mencegah pilihan acak setelah salinan.

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);
digitalPBK
sumber
@TsukimotoMitsumasa Harus adavar range = selection.getRangeAt(0);
Vokiel
Mengembalikan pilihan teks adalah ide yang bagus, jika tidak, itu merusak perilaku browser default.
Sergey
2

Perbaikan untuk 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();
});
tronic
sumber
1
Saat Anda menyalin-menempel, Anda kehilangan format ( <a> , <img> , <b> dan tag lainnya). Lebih baik mendapatkan kode HTML dari teks yang dipilih. Gunakan fungsi getSelectionHtml () dari jawaban ini: [ stackoverflow.com/a/4177234/4177020] Dan sekarang Anda dapat mengganti string var selection = window.getSelection();ini dengan yang ini:var selection = getSelectionHtml();
Dmitry Kulahin
0

Juga solusi yang sedikit lebih pendek:

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;
} );
almo
sumber
0

Ini adalah kompilasi dari 2 jawaban di atas + kompatibilitas dengan Microsoft Edge.

Saya juga telah menambahkan pemulihan dari pilihan asli di bagian akhir, seperti yang diharapkan secara default di browser apa pun.

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