374 votes

JavaScript obtenir des données du presse-papiers sur événement paste (Croix navigateur)

Comment une application web de détecter une pâte événement et de récupérer les données pour être collé?

Je voudrais supprimer le contenu HTML avant le texte est collé dans un éditeur de texte riche.

Nettoyage du texte après avoir été collé par la suite fonctionne, mais le problème est que tous les précédents de mise en forme est perdue. Par exemple, je peux écrire une phrase dans l'éditeur et de le mettre en gras, mais quand je colle le nouveau texte, le formatage est perdu. Je veux nettoyer seulement le texte est collé, et de laisser une précédente mise en forme à lui seul.

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

Notez que MSIE a clipboardData.getData(), mais je ne pouvais pas trouver une fonctionnalité similaire pour les autres navigateurs.

381voto

Nico Burns Points 6012

Solution

Testé dans IE6+, FF 3.5+, récents-ish versions d'Opera, Chrome, Safari.

HTML

Créer un div balise comme suit:

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

JavsScript

Utilisez le code JavaScript suivant:

function handlepaste (elem, e) {
    var savedcontent = elem.innerHTML;
    if (e && e.clipboardData && e.clipboardData.getData) {// Webkit - get data from clipboard, put into editdiv, cleanup, then cancel event
        if (/text\/html/.test(e.clipboardData.types)) {
            elem.innerHTML = e.clipboardData.getData('text/html');
        }
        else if (/text\/plain/.test(e.clipboardData.types)) {
            elem.innerHTML = e.clipboardData.getData('text/plain');
        }
        else {
            elem.innerHTML = "";
        }
        waitforpastedata(elem, savedcontent);
        if (e.preventDefault) {
                e.stopPropagation();
                e.preventDefault();
        }
        return false;
    }
    else {// Everything else - empty editdiv and allow browser to paste content into it, then cleanup
        elem.innerHTML = "";
        waitforpastedata(elem, savedcontent);
        return true;
    }
}

function waitforpastedata (elem, savedcontent) {
    if (elem.childNodes && elem.childNodes.length > 0) {
        processpaste(elem, savedcontent);
    }
    else {
        that = {
            e: elem,
            s: savedcontent
        }
        that.callself = function () {
            waitforpastedata(that.e, that.s)
        }
        setTimeout(that.callself,20);
    }
}

function processpaste (elem, savedcontent) {
    pasteddata = elem.innerHTML;
    //^^Alternatively loop through dom (elem.childNodes or elem.getElementsByTagName) here

    elem.innerHTML = savedcontent;

    // Do whatever with gathered data;
    alert(pasteddata);
}

Explication

L' onpaste événement a l' handlepaste fonction attaché à elle, et passa deux arguments: this (c'est à dire une référence à l'élément que l'événement est attaché) et event qui est l'objet de l'événement.


L' handlepaste fonction de:

La première ligne enregistre simplement le contenu de l'modifiable div à une variable de sorte qu'il peut être restauré à nouveau à la fin.

L' if vérifie si le navigateur est un navigateur webkit (chrome ou safari), et si c'est elle fixe le contenu de l'modifiable div pour les données collées. Ensuite, il annule l'événement pour prévenir webkit-coller quelque chose deux fois. C'est parce que webkit est maladroit, et de ne pas coller quoi que ce soit si vous suffit de décocher la div.

Si ce n'est pas un navigateur webkit puis il efface simplement le modifiable div.

Il appelle ensuite l' waitforpastedata fonction


L' waitforpastedata fonction de:

Cela est nécessaire parce que les données collées n'apparaît pas tout de suite, donc si vous avez juste appelé processpaste tout de suite alors qu'il n'aurait pas toutes les données à traiter.

Ce qu'il fait est de vérifier si le modifiable div a un contenu, si elle ne l'appelle alors processpaste, sinon il définit une minuterie d'appel lui-même et vérifier de nouveau en 20 millisecondes.


L' processpaste fonction de:

Cette fonction enregistré le innerHTML de l'modifiable div (qui est maintenant les données collées) à une variable, restaure le innerHTML de l'modifiable div revenir à sa valeur initiale, et l'alerte les données collées. Évidemment, dans un véritable scénario d'utilisation, vous auriez probablement eu envie d'autre chose que simplement les données d'alerte, vous pouvez faire ce que vous voulez à partir d'ici.

Vous voudrez probablement pour exécuter les données collées à travers un certain type de données, processus de désinfection. Cela peut être fait soit pendant qu'il est encore dans le modifiable div, ou sur l'extrait de la chaîne.


Dans une vraie situation vous auriez probablement souhaitez enregistrer la sélection avant, et de le restaurer par la suite (Définir la position du curseur sur contentEditable <div>). Vous pouvez ensuite insérer les données collées à la position du curseur lors de l'utilisateur a lancé l'action de collage.

P. S. La combinaison de ce code, IE <= 8 et jsfiddle ne semble pas fonctionner, mais il ne fonctionne pas sous ie <= 8 dans un non-jsfiddle de l'environnement.

163voto

Tim Down Points 124501

La situation a changé depuis la rédaction de cette réponse: maintenant que Firefox a ajouté la prise en charge dans la version 22, tous les principaux navigateurs prennent désormais en charge l'accès aux données du presse-papiers dans une pâte à l'événement. Voir Nico Brûlures de la réponse pour un exemple.

Dans le passé, cela n'a généralement pas été possible dans un cross-browser. L'idéal serait d'être en mesure d'obtenir le contenu collé via l' paste cas, ce qui est possible dans les navigateurs récents , mais pas dans certains navigateurs plus anciens (en particulier, Firefox < 22).

Lorsque vous avez besoin de soutenir les anciens navigateurs, ce que vous pouvez faire est très impliquée et un peu un hack qui fonctionne dans Firefox 2+, IE 5.5+ WebKit et les navigateurs comme Safari ou Chrome. Les versions récentes de deux TinyMCE et CKEditor utiliser cette technique:

  1. Détecter un ctrl-v / maj-ins d'événement à l'aide d'un gestionnaire d'événements keypress
  2. Dans ce gestionnaire, enregistrer la sélection de l'utilisateur, ajouter un élément textarea hors de l'écran (disons à gauche-1000px) du document, activez designMode off et appelez - focus() sur le textarea, donc le déplacement de l'accent circonflexe et efficace de rediriger la pâte
  3. Un très bref de la minuterie (disons 1 milliseconde) dans le gestionnaire d'événements pour appeler une autre fonction qui stocke le textarea de la valeur, supprime la zone de texte du document, tours, designMode de retour sur, restaure la sélection de l'utilisateur et colle le texte en.

Notez que cela ne fonctionne que pour le clavier coller les événements et non les pâtes à partir du contexte ou de modifier les menus. Par le temps que la pâte événement se déclenche, il est trop tard pour rediriger le curseur dans le textarea (dans certains navigateurs, au moins).

Dans le cas peu probable que vous avez besoin à l'appui de Firefox 2, notez que vous aurez besoin de placer la zone de texte dans le document parent plutôt que l'éditeur WYSIWYG de l'iframe document dans le navigateur.

154voto

l2aelba Points 3156

Version simple : (jQuery)

ou

À l’aide deavec secours quand le navigateur ne supporte pas.

Demo : http://jsbin.com/usERiZES/1/Edit?js, sortie

Firefox, Chrome, Safari testés.

17voto

JanM Points 166

J'ai écrit un peu preuve de concept pour Tim Downs proposition ici hors écran textarea. 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 de coller tout le code dans un fichier html et essayer de coller (à l'aide de ctrl-v) du texte à partir du presse-papiers n'importe où sur le document.

Je l'ai testé dans IE9 et les nouvelles versions de Firefox, Chrome et Opera. Fonctionne très bien. Aussi il est bon que l'on peut utiliser quelle que soit la combinaison de touches, il préfère triger cette fonctionnalité. Bien sûr, n'oubliez pas d'inclure jQuery sources.

N'hésitez pas à utiliser ce code et si vous venez avec certaines améliorations ou des problèmes, veuillez les envoyer. Notez également que je ne suis pas développeur Javascript donc j'ai peut-être raté quelque chose (=>faire votre propre testign).

10voto

xuser Points 160

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X