web-dev-qa-db-fra.com

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

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

Si vous copiez du texte à partir d'un site à l'aide de cela, puis collez-le, vous obtenez un lien vers le contenu d'origine au bas du texte.

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

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

Ainsi, lorsque vous sélectionnez un bloc de texte, le contenu supplémentaire est ajouté en tant que <div> caché 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 un cauchemar lorsque vous considérez toutes les sélections possibles avec du HTML complexe dans différents navigateurs.

Je développe une application Web - je ne veux pas que quiconque soit capable de 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.

Est-ce que quelqu'un connaît une bibliothèque JavaScript open source (peut-être un plug-in jQuery ou similaire) offrant des fonctionnalités similaires mais n'exposant pas les données d'application internes?

85
Keith

Il existe deux manières principales d'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 à la dom et d'étendre la sélection à celui-ci.
Cette méthode est adaptée de cet article by c.bavota. Vérifiez également la version de jitbit pour les cas plus complexes.

  • Compatibilité navigateur: tous les principaux navigateurs, IE> 8.
  • Demo: jsFiddle demo .
  • 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 le copy event et de modifier directement les données du presse-papier. Ceci est possible en utilisant la propriété clipboardData. Notez que cette propriété est disponible dans tous les principaux navigateurs dans read-only; la méthode setData est uniquement disponible sur IE.

  • Compatibilité du navigateur: IE> 4.
  • Demo: jsFiddle demo .
  • 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);
114
CronosS

Ceci est une solution javascript Vanilla d'une solution modifiée ci-dessus mais prend en charge plusieurs navigateurs (méthode multi-navigateurs) 

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
GiorgosK

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

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

En améliorant 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);
2
digitalPBK

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
tronic

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

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
almo