Comment ajouter des informations supplémentaires au texte Web copié


103

Certains sites Web utilisent désormais un service JavaScript de Tynt qui ajoute du texte au contenu copié.

Si vous copiez du texte à partir d'un site en utilisant ceci, puis collez, vous obtenez un lien vers le contenu d'origine au bas du texte.

Tynt suit également cela au fur et à mesure. C'est une belle astuce bien faite.

Leur script pour faire cela est impressionnant - plutôt que d'essayer de manipuler le presse-papiers (ce que seules les anciennes versions d'IE leur permettent de faire par défaut et qui devrait toujours être désactivé), ils manipulent la sélection réelle.

Ainsi, lorsque vous sélectionnez un bloc de texte, le contenu supplémentaire est ajouté en tant que caché <div>inclus dans votre sélection. Lorsque vous collez le style supplémentaire est ignoré et le lien supplémentaire apparaît.

C'est en fait assez facile à faire avec de simples blocs de texte, mais c'est un cauchemar quand on considère toutes les sélections possibles dans un HTML complexe dans différents navigateurs.

Je développe une application Web - je ne veux pas que quiconque puisse suivre le contenu copié et j'aimerais que les informations supplémentaires contiennent quelque chose de contextuel, plutôt qu'un simple lien. Le service de Tynt n'est pas vraiment approprié dans ce cas.

Quelqu'un connaît-il une bibliothèque JavaScript open source (peut-être un plug-in jQuery ou similaire) qui fournit des fonctionnalités similaires mais qui n'expose pas les données d'application internes?


1
Jetez un œil à ma réponse sur stackoverflow.com/questions/6344588/… . Il est fait de façon très similaire que vous proposiez
Niklas


48
Veuillez ne pas faire ça. S'IL VOUS PLAÎT S'IL VOUS PLAÎT SVP ne faites pas.
couchand

5
@couchand pourquoi pas? Je comprends à quel point c'est ennuyeux sur les sites de spam, mais c'est pour une application qui peut être utilisée pour des citations et où les données internes sont sensibles. C'est pourquoi je ne voulais pas utiliser Tynt.
Keith

4
Es-tu sûr de vouloir faire ça? En tant qu'utilisateur, je déteste ça et je porterai cette colère dans votre produit: ne touchez pas à mon presse-papiers!
aloisdg passe à codidact.com le

Réponses:


138

Mise à jour 2020

Solution qui fonctionne sur tous les navigateurs récents .

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>


[Article plus ancien - avant la mise à jour 2020]

Il existe deux méthodes principales pour ajouter des informations supplémentaires au texte Web copié.

1. Manipulation de la sélection

L'idée est de surveiller le copy event, puis d'ajouter un conteneur caché avec nos informations supplémentaires au dom, et d'y étendre la sélection.
Cette méthode est adaptée de cet article par c.bavota . Vérifiez également la version de jitbit pour des cas plus complexes.

  • Compatibilité du navigateur : Tous les principaux navigateurs, IE> 8.
  • Démo : démo jsFiddle .
  • Code 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. Manipulation du presse-papiers

L'idée est de regarder copy eventet de modifier directement les données du presse-papiers. Ceci est possible en utilisant la clipboardDatapropriété. Notez que cette propriété est disponible dans tous les principaux navigateurs de read-only; la setDataméthode n'est disponible que sur IE.

  • Compatibilité du navigateur : IE> 4.
  • Démo : démo jsFiddle .
  • Code 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
À votre santé! Malheureusement, nous avons besoin que cela fonctionne dans IE, mais ce n'est pas un mauvais début.
Keith

2
Il devrait y avoir une solution de contournement pour les balises "<pre>", une version plus fluide de ce script est ici
Alex

15
Notez que "Manipuler le presse-papiers" fonctionne parfaitement dans FireFox, Chrome et Safari si vous passez window.clipboardDataà event.clipboardData. IE (v11 aussi) ne prend pas en charge event.clipboardData jsfiddle.net/m56af0je/8
mems

3
Si vous utilisez Google Analytics, etc., vous pouvez même déclencher un événement pour enregistrer ce que les utilisateurs copient à partir de votre site. Intéressant
geedubb

2
La première option ignore les caractères de nouvelle ligne du texte copié.
soham

7

Ceci est une solution javascript vanille d'une solution modifiée ci-dessus mais prend en charge plus de navigateurs (méthode de navigateur croisé)

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

La version la plus courte de jQuery que j'ai testée et qui fonctionne est:

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

où est le code qui copie réellement le résultat dans le presse-papiers?
vsync

@vsync Je crois que cela ajoute simplement des fonctionnalités juste avant la copie (ce qui est fait par le système lorsque l'utilisateur l'initie).
TerranRich

@vsync - comme l'a dit TerraRich, j'ai essayé de répondre à la question, qui concernait l'ajout d'informations supplémentaires dans le texte copié, donc la solution ne couvre que cette partie.
user2276146

3

Voici un plugin dans jquery pour faire ça https://github.com/niklasvh/jquery.plugin.clipboard Depuis le fichier readme du projet "Ce script modifie le contenu d'une sélection avant qu'un événement de copie ne soit appelé, résultant en la sélection copiée étant différent de ce que l'utilisateur a sélectionné.

Cela vous permet d'ajouter / ajouter du contenu à la sélection, comme des informations sur les droits d'auteur ou tout autre contenu.

Publié sous licence MIT "


1
Cela semble très prometteur. Il utilise des styles en ligne que nous n'autorisons pas avec notre CSP, mais il pourrait potentiellement être adapté. À votre santé!
Keith

3

Amélioration de la réponse, restaurez la sélection après les modifications pour éviter les sélections aléatoires après la copie.

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 Il devrait y avoirvar range = selection.getRangeAt(0);
Vokiel

La restauration de la sélection de texte est une bonne idée, sinon elle rompt le comportement par défaut du navigateur.
Sergey

2

Amélioration pour 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
Lorsque vous copiez-collez vous perdez la mise en forme ( <a> , <img> , <b> et autres balises). Il est préférable d'obtenir le code HTML du texte sélectionné. Utilisez la fonction getSelectionHtml () de cette réponse: [ stackoverflow.com/a/4177234/4177020] Et maintenant vous pouvez remplacer cette chaîne var selection = window.getSelection();par celle-ci:var selection = getSelectionHtml();
Dmitry Kulahin

0

Aussi une solution un peu plus courte:

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

C'est une compilation de 2 réponses ci-dessus + compatibilité avec Microsoft Edge.

J'ai également ajouté une restauration de la sélection d'origine à la fin, comme prévu par défaut dans n'importe quel navigateur.

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);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.