30 votes

Nettoyer le texte collé dans Microsoft Word en utilisant JavaScript

J'utilise un "contenteditable". <div/> et en activant PASTE.

Il est étonnant de constater la quantité de code de balisage qui est collé à partir d'une copie du presse-papiers de Microsoft Word. Je me bats contre ce problème, et j'ai fait la moitié du chemin en utilisant Prototypes'. stripTags() fonction ( ce qui ne semble malheureusement pas me permettre de conserver certains tags ).

Cependant, même après cela, je me retrouve avec une quantité hallucinante de code de balisage inutile.

Ma question est donc la suivante : existe-t-il une fonction (utilisant JavaScript) ou une approche que je peux utiliser pour nettoyer la majorité de ces balises inutiles ?

24voto

OneNerd Points 2972

Voici la fonction que j'ai fini par écrire et qui fait le travail assez bien (pour autant que je puisse dire).

Je suis tout à fait ouvert aux suggestions d'amélioration si quelqu'un en a. Merci.

function cleanWordPaste( in_word_text ) {
 var tmp = document.createElement("DIV");
 tmp.innerHTML = in_word_text;
 var newString = tmp.textContent||tmp.innerText;
 // this next piece converts line breaks into break tags
 // and removes the seemingly endless crap code
 newString  = newString.replace(/\n\n/g, "<br />").replace(/.*<!--.*-->/g,"");
 // this next piece removes any break tags (up to 10) at beginning
 for ( i=0; i<10; i++ ) {
  if ( newString.substr(0,6)=="<br />" ) { 
   newString = newString.replace("<br />", ""); 
  }
 }
 return newString;
}

J'espère que cela sera utile à certains d'entre vous.

3voto

Todd Main Points 24036

Vous pouvez soit utiliser la version complète CKEditor qui nettoie sur la pâte, ou regardez la source .

3voto

Daniel Sellers Points 627

J'utilise ceci :

$(body_doc).find('body').bind('paste',function(e){
                var rte = $(this);
                _activeRTEData = $(rte).html();
                beginLen = $.trim($(rte).html()).length; 

                setTimeout(function(){
                    var text = $(rte).html();
                    var newLen = $.trim(text).length;

                    //identify the first char that changed to determine caret location
                    caret = 0;

                    for(i=0;i < newLen; i++){
                        if(_activeRTEData[i] != text[i]){
                            caret = i-1;
                            break;  
                        }
                    }

                    var origText = text.slice(0,caret);
                    var newText = text.slice(caret, newLen - beginLen + caret + 4);
                    var tailText = text.slice(newLen - beginLen + caret + 4, newLen);

                    var newText = newText.replace(/(.*(?:endif-->))|([ ]?<[^>]*>[ ]?)|(&nbsp;)|([^}]*})/g,'');

                    newText = newText.replace(/[·]/g,'');

                    $(rte).html(origText + newText + tailText);
                    $(rte).contents().last().focus();
                },100);
            });

body_doc est la iframe éditable, si vous utilisez un div éditable, vous pouvez laisser tomber la partie .find('body'). En gros, il détecte un événement de collage, vérifie l'emplacement, nettoie le nouveau texte, puis replace le texte nettoyé à l'endroit où il a été collé. (Cela peut sembler déroutant... mais ce n'est pas si grave que cela.

Le setTimeout est nécessaire car vous ne pouvez pas saisir le texte avant qu'il ne soit effectivement collé dans l'élément, les événements de collage se déclenchent dès que le collage commence.

2voto

Josh Points 7132

Que diriez-vous d'avoir un bouton "coller en texte brut" qui affiche un <textarea> en permettant à l'utilisateur de coller le texte à cet endroit ? de cette façon, toutes les balises seront supprimées pour vous. C'est ce que je fais avec mon CMS ; j'ai renoncé à essayer de nettoyer le désordre de Word.

0voto

rob Points 3743

J'ai fait quelque chose comme ça il y a longtemps, où j'ai totalement nettoyé les choses dans un éditeur de texte riche et converti les balises de police en styles, les brs en p's, etc, pour que ce soit cohérent entre les navigateurs et empêcher certaines choses laides d'entrer via le collage. J'ai pris ma fonction récursive et j'en ai retiré la majeure partie, à l'exception de la logique de base, ce qui pourrait être un bon point de départ ("result" est un objet qui accumule le résultat, qui nécessite probablement un deuxième passage pour être converti en chaîne), si c'est ce dont vous avez besoin :

var cleanDom = function(result, n) {
var nn = n.nodeName;
if(nn=="#text") {
    var text = n.nodeValue;

    }
else {
    if(nn=="A" && n.href)
        ...;
    else if(nn=="IMG" & n.src) {
        ....
        }
    else if(nn=="DIV") {
        if(n.className=="indent")
            ...
        }
    else if(nn=="FONT") {
        }       
    else if(nn=="BR") {
        }

    if(!UNSUPPORTED_ELEMENTS[nn]) {
        if(n.childNodes.length > 0)
            for(var i=0; i<n.childNodes.length; i++) 
                cleanDom(result, n.childNodes[i]);
        }
    }
}

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