Ingresso incolla cattura


210

Sto cercando un modo per disinfettare l'input che ho incollato nel browser, è possibile farlo con jQuery?

Sono riuscito a trovare questo finora:

$(this).live(pasteEventName, function(e) {
 // this is where i would like to sanitize my input
 return false;
}

Sfortunatamente il mio sviluppo è arrivato a una stretta stridente a causa di questo problema "minore". Mi farebbe davvero un campeggiatore felice se qualcuno potesse indicarmi la giusta direzione.


6
Contrassegna stackoverflow.com/a/1503425/749232 come risposta per l'utilizzo di altre persone che riscontrano lo stesso problema. Questo mi ha risolto.
saji89,

2
.live () è deprecato a partire da jquery 1.9, raccomandano invece
.on

Risposte:


337

OK, mi sono appena imbattuto nello stesso problema ... Ho fatto il lungo cammino

$('input').on('paste', function () {
  var element = this;
  setTimeout(function () {
    var text = $(element).val();
    // do something with text
  }, 100);
});

Solo un piccolo timeout fino a quando .val () func può essere popolato.

E.


20
E se ci fosse già del testo nell'area di testo e lo incollassi e volessi semplicemente il testo incollato?
barfoon

39
Funziona perfettamente, grazie. Un timeout di 0 funziona altrettanto bene. La funzione deve solo essere rinviata al ciclo successivo.
Daniel Lewis,

4
Sono appena stato in una situazione simile. Il timeout è lì perché l'evento incolla non è immediato, ma richiede alcuni millisecondi per incollare il contenuto degli appunti.
James

8
@ user563811: nota solo che il timeout minimo ufficiale è di 4ms in HTML5.
pimvdb,

4
Come dice sharif, 0ms mette comunque l'evento in fondo alla pila.
BobRodes

67

Puoi effettivamente prendere il valore direttamente dall'evento . È un po 'ottuso come arrivarci però.

Restituisci false se non vuoi che passi.

$(this).on('paste', function(e) {

  var pasteData = e.originalEvent.clipboardData.getData('text')

});

2
Questa è la strada da percorrere
DdW,

1
cioè 11: window.clipboardData.getData ('text')
Wallstrider

4
Tuttavia, si noti che la necessità della proprietà "originalEvent" è necessaria solo se si gestisce l'evento con jQuery. Puoi farlo semplicemente e.clipboardData.getData('text')in JavaScript.
Asier Paz,

La migliore risposta qui! Ma - ho trovato strano che la versione abbreviata di binding non funzioni con questo, cioè errore se provo questo: $ (this) .paste (function (e) {...}) ;, even però che lavori per breve consegna .on ( 'click'), ecc ..
HoldOffHunger

niggle: nel codice manca una parentesi chiusa. Apparentemente la modifica è troppo piccola per permettermi di ripararla come modifica.
Gioacchino Lous,

42

Per la compatibilità multipiattaforma, dovrebbe gestire gli eventi oninput e onpropertychange:

$ (something).bind ("input propertychange", function (e) {
    // check for paste as in example above and
    // do something
})

2
Bellissima soluzione che funziona sia come catching sia come keyup catching. Nota: questo provoca l'attivazione della funzione evento due volte per qualche motivo se si evidenziano i contenuti di input e quindi si digita qualcosa in almeno IE8 (non importante in molti casi, ma forse molto importante in altri).
Baacke,

Bello ! Non sapevo di questo, e si adatta perfettamente alle mie esigenze!
Marc Brillault,

18

Ho risolto il problema usando il seguente codice:

$("#editor").live('input paste',function(e){
    if(e.target.id == 'editor') {
        $('<textarea></textarea>').attr('id', 'paste').appendTo('#editMode');
        $("#paste").focus();
        setTimeout($(this).paste, 250);
    }
});

Ora ho solo bisogno di memorizzare la posizione del punto di inserimento e aggiungerla a quella posizione, quindi sono pronto ... Penso :)


1
Come hai memorizzato la posizione del cursore?
Petah,

@Petah Potresti verificare con quale elemento ha lo stato attivo .find(':focus')e conoscere quell'elemento determina la posizione del cursore per esso. Vedere questo .
Jacob,

Ricorda che "live" è deprecato a favore di "on"
NBPalomino,

inputfa la differenza :) Normalmente ho questi eventi nella mia casella di testo, keyup keydown paste inputma ovviamente dipende dalle tue motivazioni
Pierre,

10

Hmm ... Penso che puoi usare e.clipboardDataper catturare i dati incollati. Se non esce, dai un'occhiata qui .

$(this).live("paste", function(e) {
    alert(e.clipboardData); // [object Clipboard]
});

2
Quando
eseguo

1
clipboardData è sandbox su molti browser (ovvio buco di sicurezza.)
podperson

2
Solo per Internet Explorer!
Lodewijk,

9

Ascolta l'evento incolla e imposta un listener di eventi keyup. Al keyup, acquisire il valore e rimuovere il listener di eventi keyup.

$('.inputTextArea').bind('paste', function (e){
    $(e.target).keyup(getInput);
});
function getInput(e){
    var inputText = $(e.target).val();
    $(e.target).unbind('keyup');
}

6
Questo è molto buono, ma non funziona per incollare il tasto destro.
Joseph Ravenwolfe,

né funziona per incollare con il clic centrale (X11) funziona solo se hanno usato la tastiera per incollare.
Jasen,

7
$("#textboxid").on('input propertychange', function () {
    //perform operation
        });

Funzionerà benissimo.


6

Questo si sta avvicinando a ciò che potresti desiderare.

function sanitize(s) {
  return s.replace(/\bfoo\b/g, "~"); 
};

$(function() {
 $(":text, textarea").bind("input paste", function(e) {
   try {
     clipboardData.setData("text",
       sanitize(clipboardData.getData("text"))
     );
   } catch (e) {
     $(this).val( sanitize( $(this).val() ) );
   }
 });
});

Si noti che quando l'oggetto ClipboardData non viene trovato (su browser diversi da IE) si sta attualmente ottenendo il valore completo dell'elemento + il valore con gli appunti.

Probabilmente puoi fare qualche passo in più per difendere i due valori, prima di un input e dopo l'input, se in realtà stai solo dopo quali dati sono stati realmente incollati nell'elemento.


6
 $('').bind('input propertychange', function() {....});                      

Questo funzionerà per l'evento incolla del mouse.


2
Questo è il miglior utilizzo di tutti.
Sinan Eldem,

5

Che ne dici di confrontare il valore originale del campo e il valore modificato del campo e dedurre la differenza come valore incollato? In questo modo il testo incollato viene catturato correttamente anche se nel campo è presente del testo.

http://jsfiddle.net/6b7sK/

function text_diff(first, second) {
    var start = 0;
    while (start < first.length && first[start] == second[start]) {
        ++start;
    }
    var end = 0;
    while (first.length - end > start && first[first.length - end - 1] == second[second.length - end - 1]) {
        ++end;
    }
    end = second.length - end;
    return second.substr(start, end - start);
}
$('textarea').bind('paste', function () {
    var self = $(this);
    var orig = self.val();
    setTimeout(function () {
        var pasted = text_diff(orig, $(self).val());
        console.log(pasted);
    });
});

5

Questo codice funziona per me o incolla dal clic destro o copia diretta incolla

   $('.textbox').on('paste input propertychange', function (e) {
        $(this).val( $(this).val().replace(/[^0-9.]/g, '') );
    })

Quando lo incollo Section 1: Labour Costdiventa 1nella casella di testo.

Per consentire solo il valore float, utilizzo questo codice

 //only decimal
    $('.textbox').keypress(function(e) {
        if(e.which == 46 && $(this).val().indexOf('.') != -1) {
            e.preventDefault();
        } 
       if (e.which == 8 || e.which == 46) {
            return true;
       } else if ( e.which < 48 || e.which > 57) {
            e.preventDefault();
      }
    });

4
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/html') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/html'));
        e.preventDefault();

        ...
    }
});

Ulteriore:


text / html non è valido, solo url e text.
Mike,

@ Mike Ho copiato lo snippet direttamente dalla documentazione di riferimento.
davidcondrey,

L'ho provato per circa un giorno. text / html non funzionerebbe mai. Ho finito per aggiungere un timeout di 0 ritardo e sono stato in grado di catturare l'html dal div in cui si stavano incollando. Se qualcuno avesse un violino funzionante, questo sarebbe d'aiuto. Forse sto solo sbagliando ...
Mike,

3

Vedi questo esempio: http://www.p2e.dk/diverse/detectPaste.htm

Tiene traccia essenzialmente di ogni modifica con l'evento oninput e quindi controlla se si tratta di un incolla per confronto di stringhe. Oh, e in IE c'è un evento onpaste. Così:

$ (something).bind ("input paste", function (e) {
    // check for paste as in example above and
    // do something
})

Quindi è impossibile solo ottenere il testo incollato quando si verifica l'evento?
Christoffer Winterkvist,

Beh, immagino che dovrai affrontarlo da solo, come, confrontare il prima e il dopo. Deve essere piuttosto semplice. Ma perché non riconvalidi l'intero input? Lento?
Ilya Birman,

Ho solo pensato che sarebbe stato possibile farlo, ma credo di no, in questo momento sto provando un altro metodo incollandolo in una textarea e trasferendolo poi alla sua destinazione finale. Spero che funzionerà.
Christoffer Winterkvist,

Devi solo trovare il frammento di corrispondenza massimo all'inizio di due stringhe (prima e dopo). Tutto da lì e fino alla differenza di lunghezze è il testo incollato.
Ilya Birman,

@IlyaBirman no non lo è: ad es. Il testo incollato potrebbe sostituire una parte (o tutto) dell'originale
Jasen,

1

Questo metodo utilizza jqueries contents (). Unwrap ().

  1. Innanzitutto, rileva l'evento incolla
  2. Aggiungi una classe unica ai tag che sono già nell'elemento in cui stiamo incollando.
  3. Dopo un determinato timeout, scansiona tutti i tag di scartamento del contenuto che non hanno la classe impostata in precedenza. Nota: questo metodo non rimuove i tag a chiusura automatica come
    Vedi un esempio di seguito.

    //find all children .find('*') and add the class .within .addClass("within") to all tags
    $('#answer_text').find('*').each(function () {
    $(this).addClass("within");
    });
    setTimeout(function() {
    $('#answer_text').find('*').each(function () {
        //if the current child does not have the specified class unwrap its contents
        $(this).not(".within").contents().unwrap();
    });
    }, 0);

Sicuramente la risposta migliore, più breve e autodidatta mai vista !!! Grazie mille, hai reso la mia giornata;)
web il

0

Ciò si è rivelato piuttosto illusorio. Il valore dell'input non viene aggiornato prima dell'esecuzione del codice all'interno della funzione evento incolla. Ho provato a chiamare altri eventi all'interno della funzione evento incolla ma il valore di input non è ancora aggiornato con il testo incollato all'interno della funzione di eventuali eventi. Questo è tutti gli eventi oltre a keyup. Se si chiama keyup dalla funzione evento incolla è possibile disinfettare il testo incollato dalla funzione evento keyup. così...

$(':input').live
(
    'input paste',
    function(e)
    {
        $(this).keyup();
    }
);

$(':input').live
(
    'keyup',
    function(e)
    {
        // sanitize pasted text here
    }
);

C'è un avvertimento qui. In Firefox, se si reimposta il testo di input su ogni keyup, se il testo è più lungo dell'area visualizzabile consentita dalla larghezza di input, quindi il ripristino del valore su ogni keyup interrompe la funzionalità del browser che fa scorrere automaticamente il testo nella posizione di inserimento fine del testo. Invece il testo scorre di nuovo all'inizio, lasciando il cursore fuori dalla vista.


viene chiamato onpaste prima di incollare il contenuto. È necessario un ritardo temporizzato di almeno 4 ms per creare la propria funzione di retropasto, per lavare i risultati della pasta.
DragonLord,

-1

Script per rimuovere caratteri speciali da tutti i campi con classe portlet-form-input-field:

// Remove special chars from input field on paste
jQuery('.portlet-form-input-field').bind('paste', function(e) {
    var textInput = jQuery(this);
    setTimeout(function() {
        textInput.val(replaceSingleEndOfLineCharactersInString(textInput.val()));
    }, 200);
});

function replaceSingleEndOfLineCharactersInString(value) {
    <%
        // deal with end-of-line characters (\n or \r\n) that will affect string length calculation,
        // also remove all non-printable control characters that can cause XML validation errors
    %>
    if (value != "") {
        value = value.replace(/(\x00|\x01|\x02|\x03|\x04|\x05|\x06|\x07|\x08|\x0B|\x0C|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F|\x7F)/gm,'');
        return value = value.replace(/(\r\n|\n|\r)/gm,'##').replace(/(\#\#)/gm,"\r\n");
    }
}

2
Potresti aggiungere una descrizione della sanificazione pertinente e perché potrebbe aiutare a risolvere il problema del poster? Fornire semplicemente un blocco di codice non aiuta davvero l'OP (o i futuri ricercatori) a capire come risolvere il problema, incoraggia semplicemente a copiare / incollare il codice incompreso.
Troy Alford,

-2

C'è un avvertimento qui. In Firefox, se si reimposta il testo di input su ogni keyup, se il testo è più lungo dell'area visualizzabile consentita dalla larghezza di input, quindi il ripristino del valore su ogni keyup interrompe la funzionalità del browser che fa scorrere automaticamente il testo nella posizione di inserimento fine del testo. Invece il testo scorre di nuovo all'inizio, lasciando il cursore fuori dalla vista.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.