web-dev-qa-db-fra.com

JavaScript récupère les données du presse-papiers lors d'un événement de collage (navigateur croisé)

Comment une application Web peut-elle détecter un événement de collage et récupérer les données à coller?

Je souhaite supprimer le contenu HTML avant que le texte ne soit collé dans un éditeur de texte enrichi.

Nettoyer le texte après avoir été collé par la suite fonctionne, mais le problème est que tout le formatage précédent est perdu. Par exemple, je peux écrire une phrase dans l'éditeur et la mettre en gras, mais lorsque je colle un nouveau texte, toute la mise en forme est perdue. Je souhaite nettoyer uniquement le texte collé et ne pas toucher au formatage précédent.

Idéalement, la solution devrait fonctionner sur tous les navigateurs modernes (MSIE, Gecko, Chrome et Safari, par exemple).

Notez que MSIE a clipboardData.getData(), mais je n’ai pas trouvé de fonctionnalité similaire pour les autres navigateurs.

274
Alex

La situation a changé depuis l'écriture de cette réponse: maintenant que Firefox a ajouté la prise en charge de la version 22, tous les principaux navigateurs prennent désormais en charge l'accès aux données du Presse-papiers dans un événement de collage. Voir réponse de Nico Burns pour un exemple.

Dans le passé, cela n’était généralement pas possible de manière transversale. L'idéal serait de pouvoir obtenir le contenu collé via l'événement paste, ce qui est possible dans les navigateurs récents , mais pas dans certains navigateurs plus anciens (notamment Firefox <22).

Lorsque vous devez prendre en charge des navigateurs plus anciens, ce que vous pouvez faire est très complexe et nécessite un peu de bidouille qui fonctionnera dans les navigateurs Firefox 2+, IE 5.5+ et WebKit tels que Safari ou Chrome. Les versions récentes de TinyMCE et de CKEditor utilisent cette technique:

  1. Détecter un événement ctrl-v/shift-ins à l'aide d'un gestionnaire d'événements de frappe
  2. Dans ce gestionnaire, enregistrez la sélection actuelle de l'utilisateur, ajoutez un élément textarea hors écran (par exemple, à gauche, -1000 px), activez designMode et appelez focus() sur la zone de texte, déplaçant ainsi le curseur. et rediriger efficacement la pâte
  3. Définissez une minuterie très brève (disons 1 milliseconde) dans le gestionnaire d'événements pour appeler une autre fonction qui stocke la valeur textarea, supprime la zone textarea du document, active de nouveau la variable designMode, restaure la sélection de l'utilisateur et insère le texte.

Notez que cela ne fonctionnera que pour les événements de collage au clavier et non pour les pâtes du menu contextuel ou d'édition. Au moment du déclenchement de l'événement coller, il est trop tard pour rediriger le curseur dans la zone de texte (du moins dans certains navigateurs).

Dans le cas peu probable où vous auriez besoin de supporter Firefox 2, notez que vous devez placer la zone de texte dans le document parent plutôt que le document iframe de l'éditeur WYSIWYG dans ce navigateur.

141
Tim Down

Solution n ° 1 (texte brut uniquement et nécessite Firefox 22+)

Fonctionne pour IE6 +, FF 22+, Chrome, Safari, Edge (Testé uniquement dans IE9 +, mais devrait fonctionner pour les versions inférieures)

Si vous avez besoin d'assistance pour coller HTML ou Firefox <= 22, voir la solution n ° 2.

HTML

<div id='editableDiv' contenteditable='true'>Paste</div>

JavaScript

function handlePaste (e) {
    var clipboardData, pastedData;

    // Stop data actually being pasted into div
    e.stopPropagation();
    e.preventDefault();

    // Get pasted data via clipboard API
    clipboardData = e.clipboardData || window.clipboardData;
    pastedData = clipboardData.getData('Text');

    // Do whatever with pasteddata
    alert(pastedData);
}

document.getElementById('editableDiv').addEventListener('paste', handlePaste);

JSFiddle: https://jsfiddle.net/swL8ftLs/12/

Notez que cette solution utilise le paramètre 'Text' pour la fonction getData, qui est non standard. Cependant, cela fonctionne dans tous les navigateurs au moment de l'écriture.


Solution n ° 2 (HTML et fonctionne pour Firefox <= 22)

Testé dans IE6 +, FF 3.5+, Chrome, Safari, Edge

HTML

<div id='div' contenteditable='true'>Paste</div>

JavaScript

var editableDiv = document.getElementById('editableDiv');

function handlepaste (e) {
    var types, pastedData, savedContent;

    // Browsers that support the 'text/html' type in the Clipboard API (Chrome, Firefox 22+)
    if (e && e.clipboardData && e.clipboardData.types && e.clipboardData.getData) {

        // Check for 'text/html' in types list. See abligh's answer below for deatils on
        // why the DOMStringList bit is needed. We cannot fall back to 'text/plain' as
        // Safari/Edge don't advertise HTML data even if it is available
        types = e.clipboardData.types;
        if (((types instanceof DOMStringList) && types.contains("text/html")) || (types.indexOf && types.indexOf('text/html') !== -1)) {

            // Extract data and pass it to callback
            pastedData = e.clipboardData.getData('text/html');
            processPaste(editableDiv, pastedData);

            // Stop the data from actually being pasted
            e.stopPropagation();
            e.preventDefault();
            return false;
        }
    }

    // Everything else: Move existing element contents to a DocumentFragment for safekeeping
    savedContent = document.createDocumentFragment();
    while(editableDiv.childNodes.length > 0) {
        savedContent.appendChild(editableDiv.childNodes[0]);
    }

    // Then wait for browser to paste content into it and cleanup
    waitForPastedData(editableDiv, savedContent);
    return true;
}

function waitForPastedData (elem, savedContent) {

    // If data has been processes by browser, process it
    if (elem.childNodes && elem.childNodes.length > 0) {

        // Retrieve pasted content via innerHTML
        // (Alternatively loop through elem.childNodes or elem.getElementsByTagName here)
        var pastedData = elem.innerHTML;

        // Restore saved content
        elem.innerHTML = "";
        elem.appendChild(savedContent);

        // Call callback
        processPaste(elem, pastedData);
    }

    // Else wait 20ms and try again
    else {
        setTimeout(function () {
            waitForPastedData(elem, savedContent)
        }, 20);
    }
}

function processPaste (elem, pastedData) {
    // Do whatever with gathered data;
    alert(pastedData);
    elem.focus();
}

// Modern browsers. Note: 3rd argument is required for Firefox <= 6
if (editableDiv.addEventListener) {
    editableDiv.addEventListener('paste', handlepaste, false);
}
// IE <= 8
else {
    editableDiv.attachEvent('onpaste', handlepaste);
}

JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/

Explication

L'événement onpaste de div est associé à la fonction handlePaste et passe un argument unique: l'objet event de l'événement de collage. La propriété clipboardData de cet événement nous intéresse particulièrement, car elle permet l’accès au Presse-papiers dans les navigateurs autres que les navigateurs. Dans IE, l'équivalent est window.clipboardData, bien que son API soit légèrement différente.

Voir la section ressources ci-dessous.


La fonction handlepaste:

Cette fonction a deux branches.

La première vérifie l'existence de event.clipboardData et vérifie si sa propriété types contient 'text/html' (types peut être une DOMStringList qui est vérifiée à l'aide de la commande contains ou une chaîne vérifiée à l'aide de la méthode indexOf. Si toutes ces conditions sont remplies, nous procédons comme dans la solution n ° 1, à l'exception de 'text/html' au lieu de 'text/plain'. Cela fonctionne actuellement dans Chrome et Firefox 22+.

Si cette méthode n'est pas supportée (tous les autres navigateurs), alors nous

  1. Enregistrer le contenu de l'élément dans un fichier DocumentFragment
  2. Vider l'élément
  3. Appelez la fonction waitForPastedData

La fonction waitforpastedata:

Cette fonction interroge d'abord les données collées (une fois par 20 ms), ce qui est nécessaire car elles n'apparaissent pas immédiatement. Lorsque les données sont apparues, il:

  1. Enregistre le innerHTML de la div éditable (qui est maintenant les données collées) dans une variable
  2. Restaure le contenu enregistré dans DocumentFragment
  3. Appelle la fonction 'processPaste' avec les données récupérées

La fonction processpaste:

Fait des choses arbitraires avec les données collées. Dans ce cas, nous alertons simplement les données, vous pouvez faire ce que vous voulez. Vous voudrez probablement exécuter les données collées via un processus de désinfection des données.


Sauvegarde et restauration de la position du curseur

Dans une situation réelle, vous souhaiterez probablement enregistrer la sélection avant, puis la restaurer ( Définir la position du curseur sur contentEditable <div> ). Vous pouvez ensuite insérer les données collées à la position du curseur lorsque l'utilisateur a initié l'action de collage.

Ressources:

Merci à Tim Down d’avoir suggéré l’utilisation d’un DocumentFragment et d’avoir détecté une erreur dans Firefox due à l’utilisation de DOMStringList au lieu d’une chaîne pour clipboardData.types

289
Nico Burns

Version simple:

document.querySelector('[contenteditable]').addEventListener('paste', (e) => {
    e.preventDefault();
    const text = (e.originalEvent || e).clipboardData.getData('text/plain');
    window.document.execCommand('insertText', false, text);
});

Utilisation de clipboardData

Démo: http://jsbin.com/nozifexasu/edit?js,output

Edge, Firefox, Chrome, Safari, Opera testé.


Remarque: N'oubliez pas de vérifier les entrées/sorties sur côté serveur également ( comme PHP strip-tags )

120
l2aelba

démonstration en direct

Testé sur Chrome/FF/IE11

Il existe un inconvénient pour Chrome/IE: ces navigateurs ajoutent un élément <div> à chaque nouvelle ligne. Il y a un article à ce sujet ici et il peut être corrigé en définissant l'élément contenteditable sur display:inline-block

Sélectionnez du code HTML en surbrillance et collez-le ici:

function onPaste(e){
  var content;
  e.preventDefault();

  if( e.clipboardData ){
    content = e.clipboardData.getData('text/plain');
    document.execCommand('insertText', false, content);
    return false;
  }
  else if( window.clipboardData ){
    content = window.clipboardData.getData('Text');
    if (window.getSelection)
      window.getSelection().getRangeAt(0).insertNode( document.createTextNode(content) );
  }
}


/////// EVENT BINDING /////////
document.querySelector('[contenteditable]').addEventListener('paste', onPaste);
[contenteditable]{ 
  /* chroem bug: https://stackoverflow.com/a/24689420/104380 */
  display:inline-block;
  width: calc(100% - 40px);
  min-height:120px; 
  margin:10px;
  padding:10px;
  border:1px dashed green;
}

/* 
 mark HTML inside the "contenteditable"  
 (Shouldn't be any OFC!)'
*/
[contenteditable] *{
  background-color:red;
}
<div contenteditable></div>
25
vsync

J'ai rédigé une petite preuve de concept pour la proposition de Tim Downs ici avec textarea hors écran. Et voici le code:

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
<script language="JavaScript">
 $(document).ready(function()
{

var ctrlDown = false;
var ctrlKey = 17, vKey = 86, cKey = 67;

$(document).keydown(function(e)
{
    if (e.keyCode == ctrlKey) ctrlDown = true;
}).keyup(function(e)
{
    if (e.keyCode == ctrlKey) ctrlDown = false;
});

$(".capture-paste").keydown(function(e)
{
    if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)){
        $("#area").css("display","block");
        $("#area").focus();         
    }
});

$(".capture-paste").keyup(function(e)
{
    if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)){                      
        $("#area").blur();
        //do your sanitation check or whatever stuff here
        $("#paste-output").text($("#area").val());
        $("#area").val("");
        $("#area").css("display","none");
    }
});

});
</script>

</head>
<body class="capture-paste">

<div id="paste-output"></div>


    <div>
    <textarea id="area" style="display: none; position: absolute; left: -99em;"></textarea>
    </div>

</body>
</html>

Il suffit de copier et coller le code entier dans un fichier html et d’essayer de coller (en utilisant ctrl-v) du texte du presse-papiers n’importe où sur le document.

Je l'ai testé dans IE9 et dans les nouvelles versions de Firefox, Chrome et Opera. Fonctionne assez bien. En outre, il est bon que vous puissiez utiliser la combinaison de touches de votre choix pour activer cette fonctionnalité. Bien sûr, n'oubliez pas d'inclure les sources jQuery.

N'hésitez pas à utiliser ce code et si vous avez des améliorations ou des problèmes, merci de les poster. Notez également que je ne suis pas un développeur Javascript, donc j'ai peut-être oublié quelque chose (=> faites votre propre test).

15
JanM

Basé sur l2aelba réponse. Cela a été testé sur FF, Safari, Chrome, IE (8,9,10 et 11)

    $("#editText").on("paste", function (e) {
        e.preventDefault();

        var text;
        var clp = (e.originalEvent || e).clipboardData;
        if (clp === undefined || clp === null) {
            text = window.clipboardData.getData("text") || "";
            if (text !== "") {
                if (window.getSelection) {
                    var newNode = document.createElement("span");
                    newNode.innerHTML = text;
                    window.getSelection().getRangeAt(0).insertNode(newNode);
                } else {
                    document.selection.createRange().pasteHTML(text);
                }
            }
        } else {
            text = clp.getData('text/plain') || "";
            if (text !== "") {
                document.execCommand('insertText', false, text);
            }
        }
    });
10
tmorell

Celui-ci n'utilise aucun setTimeout ().

J'ai utilisé this excellent article pour obtenir une prise en charge multi-navigateurs.

$(document).on("focus", "input[type=text],textarea", function (e) {
    var t = e.target;
    if (!$(t).data("EventListenerSet")) {
        //get length of field before paste
        var keyup = function () {
            $(this).data("lastLength", $(this).val().length);
        };
        $(t).data("lastLength", $(t).val().length);
        //catch paste event
        var paste = function () {
            $(this).data("paste", 1);//Opera 11.11+
        };
        //process modified data, if paste occured
        var func = function () {
            if ($(this).data("paste")) {
                alert(this.value.substr($(this).data("lastLength")));
                $(this).data("paste", 0);
                this.value = this.value.substr(0, $(this).data("lastLength"));
                $(t).data("lastLength", $(t).val().length);
            }
        };
        if (window.addEventListener) {
            t.addEventListener('keyup', keyup, false);
            t.addEventListener('paste', paste, false);
            t.addEventListener('input', func, false);
        }
        else {//IE
            t.attachEvent('onkeyup', function () {
                keyup.call(t);
            });
            t.attachEvent('onpaste', function () {
                paste.call(t);
            });
            t.attachEvent('onpropertychange', function () {
                func.call(t);
            });
        }
        $(t).data("EventListenerSet", 1);
    }
}); 

Ce code est étendu avec une poignée de sélection avant coller: démo

9
user669677

Cela devrait fonctionner sur tous les navigateurs prenant en charge l'événement onpaste et l'observateur de mutation.

Cette solution va au-delà du texte uniquement. Elle vous permet en réalité de modifier le contenu collé avant qu'il ne soit collé dans un élément.

Il fonctionne en utilisant des observateurs de mutation (pris en charge par Chrome, Firefox et IE11 +) contenteditable, onpaste (pris en charge par tous les principaux navigateurs) et en mutation.

étape 1

Créer un élément HTML avec contenteditable

<div contenteditable="true" id="target_paste_element"></div>

étape 2

Dans votre code Javascript, ajoutez l'événement suivant

document.getElementById("target_paste_element").addEventListener("paste", pasteEventVerifierEditor.bind(window, pasteCallBack), false);

Nous devons lier pasteCallBack, car l'observateur de mutation sera appelé de manière asynchrone.

étape 3

Ajoutez la fonction suivante à votre code

function pasteEventVerifierEditor(callback, e)
{
   //is fired on a paste event. 
    //pastes content into another contenteditable div, mutation observer observes this, content get pasted, dom tree is copied and can be referenced through call back.
    //create temp div
    //save the caret position.
    savedCaret = saveSelection(document.getElementById("target_paste_element"));

    var tempDiv = document.createElement("div");
    tempDiv.id = "id_tempDiv_paste_editor";
    //tempDiv.style.display = "none";
    document.body.appendChild(tempDiv);
    tempDiv.contentEditable = "true";

    tempDiv.focus();

    //we have to wait for the change to occur.
    //attach a mutation observer
    if (window['MutationObserver'])
    {
        //this is new functionality
        //observer is present in firefox/chrome and IE11
        // select the target node
        // create an observer instance
        tempDiv.observer = new MutationObserver(pasteMutationObserver.bind(window, callback));
        // configuration of the observer:
        var config = { attributes: false, childList: true, characterData: true, subtree: true };

        // pass in the target node, as well as the observer options
        tempDiv.observer.observe(tempDiv, config);

    }   

}



function pasteMutationObserver(callback)
{

    document.getElementById("id_tempDiv_paste_editor").observer.disconnect();
    delete document.getElementById("id_tempDiv_paste_editor").observer;

    if (callback)
    {
        //return the copied dom tree to the supplied callback.
        //copy to avoid closures.
        callback.apply(document.getElementById("id_tempDiv_paste_editor").cloneNode(true));
    }
    document.body.removeChild(document.getElementById("id_tempDiv_paste_editor"));

}

function pasteCallBack()
{
    //paste the content into the element.
    restoreSelection(document.getElementById("target_paste_element"), savedCaret);
    delete savedCaret;

    pasteHtmlAtCaret(this.innerHTML, false, true);
}   


saveSelection = function(containerEl) {
if (containerEl == document.activeElement)
{
    var range = window.getSelection().getRangeAt(0);
    var preSelectionRange = range.cloneRange();
    preSelectionRange.selectNodeContents(containerEl);
    preSelectionRange.setEnd(range.startContainer, range.startOffset);
    var start = preSelectionRange.toString().length;

    return {
        start: start,
        end: start + range.toString().length
    };
}
};

restoreSelection = function(containerEl, savedSel) {
    containerEl.focus();
    var charIndex = 0, range = document.createRange();
    range.setStart(containerEl, 0);
    range.collapse(true);
    var nodeStack = [containerEl], node, foundStart = false, stop = false;

    while (!stop && (node = nodeStack.pop())) {
        if (node.nodeType == 3) {
            var nextCharIndex = charIndex + node.length;
            if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
                range.setStart(node, savedSel.start - charIndex);
                foundStart = true;
            }
            if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
                range.setEnd(node, savedSel.end - charIndex);
                stop = true;
            }
            charIndex = nextCharIndex;
        } else {
            var i = node.childNodes.length;
            while (i--) {
                nodeStack.Push(node.childNodes[i]);
            }
        }
    }

    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
}

function pasteHtmlAtCaret(html, returnInNode, selectPastedContent) {
//function written by Tim Down

var sel, range;
if (window.getSelection) {
    // IE9 and non-IE
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
        range = sel.getRangeAt(0);
        range.deleteContents();

        // Range.createContextualFragment() would be useful here but is
        // only relatively recently standardized and is not supported in
        // some browsers (IE9, for one)
        var el = document.createElement("div");
        el.innerHTML = html;
        var frag = document.createDocumentFragment(), node, lastNode;
        while ( (node = el.firstChild) ) {
            lastNode = frag.appendChild(node);
        }
        var firstNode = frag.firstChild;
        range.insertNode(frag);

        // Preserve the selection
        if (lastNode) {
            range = range.cloneRange();
            if (returnInNode)
            {
                range.setStart(lastNode, 0); //this part is edited, set caret inside pasted node.
            }
            else
            {
                range.setStartAfter(lastNode); 
            }
            if (selectPastedContent) {
                range.setStartBefore(firstNode);
            } else {
                range.collapse(true);
            }
            sel.removeAllRanges();
            sel.addRange(range);
        }
    }
} else if ( (sel = document.selection) && sel.type != "Control") {
    // IE < 9
    var originalRange = sel.createRange();
    originalRange.collapse(true);
    sel.createRange().pasteHTML(html);
    if (selectPastedContent) {
        range = sel.createRange();
        range.setEndPoint("StartToStart", originalRange);
        range.select();
    }
}

}

Que fait le code:

  1. Quelqu'un déclenche l'événement coller en utilisant ctrl-v, contextmenu ou d'autres moyens
  2. Dans l'événement de collage, un nouvel élément avec contenteditable est créé (un élément avec contenteditable a des privilèges élevés).
  3. La position de caret de l'élément cible est enregistrée.
  4. L'accent est mis sur le nouvel élément
  5. Le contenu est collé dans le nouvel élément et rendu dans le DOM.
  6. L'observateur de la mutation détecte ce problème (il enregistre toutes les modifications apportées à l'arborescence et au contenu du dom). Puis déclenche l'événement de mutation.
  7. Le domaine du contenu collé est cloné dans une variable et renvoyé au rappel. L'élément temporaire est détruit.
  8. Le rappel reçoit le DOM cloné. Le caret est restauré. Vous pouvez l'éditer avant de l'ajouter à votre cible. élément. Dans cet exemple, j'utilise les fonctions Tim Downs pour enregistrer/restaurer le curseur et coller le code HTML dans l'élément.

Merci beaucoup à Tim Down Voir ce post pour la réponse:

Récupère le contenu collé sur le document lors de l’événement coller

5
Mouser

Pour nettoyer le texte collé et remplacer le texte actuellement sélectionné par le texte collé, le sujet est plutôt trivial:

<div id='div' contenteditable='true' onpaste='handlepaste(this, event)'>Paste</div>

JS:

function handlepaste(el, e) {
  document.execCommand('insertText', false, e.clipboardData.getData('text/plain'));
  e.preventDefault();
}
5

C'était trop long pour un commentaire sur la réponse de Nico, qui, à mon avis, ne fonctionne plus sous Firefox (d'après les commentaires), et ne fonctionne pas pour moi sous Safari en l'état.

Premièrement, vous semblez maintenant pouvoir lire directement à partir du presse-papiers. Plutôt que de coder comme:

if (/text\/plain/.test(e.clipboardData.types)) {
    // shouldn't this be writing to elem.value for text/plain anyway?
    elem.innerHTML = e.clipboardData.getData('text/plain');
}

utilisation:

types = e.clipboardData.types;
if (((types instanceof DOMStringList) && types.contains("text/plain")) ||
    (/text\/plain/.test(types))) {
    // shouldn't this be writing to elem.value for text/plain anyway?
    elem.innerHTML = e.clipboardData.getData('text/plain');
}

parce que Firefox a un champ types qui est un DOMStringList qui n'implémente pas test.

Next Firefox n'autorisera pas le collage sauf si le champ _ est utilisé dans le champ contenteditable=true.

Enfin, Firefox n'autorisera pas le collage de manière fiable à moins que le focus soit dans un textarea (ou peut-être une entrée) qui n'est pas seulement contenteditable=true mais aussi:

  • pas display:none
  • pas visibility:hidden
  • pas de taille zéro

J'essayais de masquer le champ de texte pour pouvoir utiliser la fonction de collage sur un émulateur JS VNC (c'est-à-dire qu'il était dirigé vers un client distant et qu'il n'y avait pas réellement textarea etc dans lequel coller). J'ai trouvé que tenter de masquer le champ de texte ci-dessus donnait des symptômes là où cela fonctionnait parfois, mais échouait généralement lors du second collage (ou lorsque le champ était effacé pour éviter de coller deux fois les mêmes données) car le champ avait perdu le focus et ne récupérait pas correctement. malgré focus(). La solution que j’ai proposée consistait à le placer dans z-order: -1000, à le transformer en display:none, à le définir sous la forme 1px sur 1px et à définir toutes les couleurs en transparent. Beurk.

Sur Safari, la deuxième partie de ce qui précède s’applique, c’est-à-dire que vous devez avoir un textarea qui n’est pas display:none.

4
abligh

La solution qui fonctionne pour moi consiste à ajouter un écouteur d’événement pour coller un événement si vous le collez dans une entrée de texte. Etant donné que l'événement paste survient avant que le texte en entrée ne change, dans mon gestionnaire on paste, je crée une fonction différée dans laquelle je vérifie les modifications apportées à ma zone de saisie lors de l'insertion:

onPaste: function() {
    var oThis = this;
    setTimeout(function() { // Defer until onPaste() is done
        console.log('paste', oThis.input.value);
        // Manipulate pasted input
    }, 1);
}
4
Lex

La première chose qui me vient à l’esprit est le gestionnaire de collage de la bibliothèque de fermeture de Google http://closure-library.googlecode.com/svn/trunk/closure/goosure/demos/pastehandler.html

3
tDo

Solution simple:

document.onpaste = function(e) {
    var pasted = e.clipboardData.getData('Text');
    console.log(pasted)
}
2
lama12345

Cette solution est de remplacer la balise html, c'est simple et multi-navigateur; vérifier ce jsfiddle: http://jsfiddle.net/tomwan/cbp1u2cx/1/ , code de base:

var $plainText = $("#plainText");
var $linkOnly = $("#linkOnly");
var $html = $("#html");

$plainText.on('paste', function (e) {
    window.setTimeout(function () {
        $plainText.html(removeAllTags(replaceStyleAttr($plainText.html())));
    }, 0);
});

$linkOnly.on('paste', function (e) {
    window.setTimeout(function () {
        $linkOnly.html(removeTagsExcludeA(replaceStyleAttr($linkOnly.html())));
    }, 0);
});

function replaceStyleAttr (str) {
    return str.replace(/(<[\w\W]*?)(style)([\w\W]*?>)/g, function (a, b, c, d) {
        return b + 'style_replace' + d;
    });
}

function removeTagsExcludeA (str) {
    return str.replace(/<\/?((?!a)(\w+))\s*[\w\W]*?>/g, '');
}

function removeAllTags (str) {
    return str.replace(/<\/?(\w+)\s*[\w\W]*?>/g, '');
}

remarque: vous devriez travailler sur le filtre xss au verso car cette solution ne peut pas filtrer les chaînes telles que '<< >>'

2
TomWan

Cela a fonctionné pour moi:

function onPasteMe(currentData, maxLen) {
    // validate max length of pasted text
    var totalCharacterCount = window.clipboardData.getData('Text').length;
}

<input type="text" onPaste="return onPasteMe(this, 50);" />
2
Timmy Duncan
function myFunct( e ){
    e.preventDefault();

    var pastedText = undefined;
    if( window.clipboardData && window.clipboardData.getData ){
    pastedText = window.clipboardData.getData('Text');
} 
else if( e.clipboardData && e.clipboardData.getData ){
    pastedText = e.clipboardData.getData('text/plain');
}

//work with text

}
document.onpaste = myFunct;
1
Ivan

Vous pouvez le faire de cette façon:

utilisez ce plugin jQuery pour les événements pré et post-collage:

$.fn.pasteEvents = function( delay ) {
    if (delay == undefined) delay = 20;
    return $(this).each(function() {
        var $el = $(this);
        $el.on("paste", function() {
            $el.trigger("prepaste");
            setTimeout(function() { $el.trigger("postpaste"); }, delay);
        });
    });
};

Maintenant vous pouvez utiliser ce plugin ;:

$('#txt').on("prepaste", function() { 

    $(this).find("*").each(function(){

        var tmp=new Date.getTime();
        $(this).data("uid",tmp);
    });


}).pasteEvents();

$('#txt').on("postpaste", function() { 


  $(this).find("*").each(function(){

     if(!$(this).data("uid")){
        $(this).removeClass();
          $(this).removeAttr("style id");
      }
    });
}).pasteEvents();

Explication

Définissez d'abord un uid pour tous les éléments existants en tant qu'attribut de données.

Comparez ensuite tous les nœuds POST événement PASTE. Donc, en comparant, vous pouvez identifier le nouvel élément inséré, car ils auront un ID utilisateur, puis supprimez simplement l'attribut style/class/id des éléments nouvellement créés, afin que vous puissiez conserver votre ancienne mise en forme.

1
Peeyush
$('#dom').on('paste',function (e){
    setTimeout(function(){
        console.log(e.currentTarget.value);
    },0);
});
1
Roman Yudin

Il suffit de laisser le navigateur coller comme d'habitude dans son contenu éditable, puis, après le collage, permutez les éléments span utilisés pour les styles de texte personnalisés avec le texte lui-même. Cela semble fonctionner correctement dans Internet Explorer et les autres navigateurs que j'ai essayés ...

$('[contenteditable]').on('paste', function (e) {
    setTimeout(function () {
        $(e.target).children('span').each(function () {
            $(this).replaceWith($(this).text());
        });
    }, 0);
});

Cette solution suppose que vous exécutez jQuery et que vous ne voulez pas formater le texte dans vos divs éditables avec le conten.

Le côté positif est que c'est super simple.

1
DaveAlger

Ceci est un code existant posté ci-dessus mais je l'ai mis à jour pour IE, le bogue qui se passait lorsque le texte existant est sélectionné et que le texte collé ne supprime pas le contenu sélectionné. Ceci a été corrigé par le code ci-dessous

selRange.deleteContents(); 

Voir le code complet ci-dessous

$('[contenteditable]').on('paste', function (e) {
    e.preventDefault();

    if (window.clipboardData) {
        content = window.clipboardData.getData('Text');        
        if (window.getSelection) {
            var selObj = window.getSelection();
            var selRange = selObj.getRangeAt(0);
            selRange.deleteContents();                
            selRange.insertNode(document.createTextNode(content));
        }
    } else if (e.originalEvent.clipboardData) {
        content = (e.originalEvent || e).clipboardData.getData('text/plain');
        document.execCommand('insertText', false, content);
    }        
});
0
Ravi Selvaraj