Captura de entrada de pegado


210

Estoy buscando una manera de desinfectar la entrada que pego en el navegador, ¿es esto posible con jQuery?

Me las he arreglado para llegar a esto hasta ahora:

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

Lamentablemente, mi desarrollo se ha detenido debido a este problema "menor". Realmente me haría una caravana feliz si alguien pudiera señalarme en la dirección correcta.


66
Marque stackoverflow.com/a/1503425/749232 como la respuesta para el uso de otras personas que experimentan el mismo problema. Eso lo resolvió para mí.
saji89

2
.live () está en desuso a partir de jquery 1.9, recomiendan .on () en su lugar
Sameer Alibhai

Respuestas:


337

OK, me encontré con el mismo problema ... Di la vuelta

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

Solo un pequeño tiempo de espera hasta que se pueda completar la función .val ().

MI.


20
¿Qué sucede si ya hay texto en el área de texto y lo pega y solo desea el texto pegado?
barfoon

39
Funciona perfectamente, gracias. Un tiempo de espera de 0 funciona igual de bien. La función solo necesita diferirse para el siguiente ciclo.
Daniel Lewis

44
Acabo de estar en una situación similar. El tiempo de espera está ahí porque el evento de pegado no es inmediato, pero toma unos milisegundos para que se pegue el contenido del portapapeles.
James

8
@ user563811: Solo tenga en cuenta que el tiempo de espera mínimo oficial es de 4 ms en HTML5.
pimvdb

44
Como dice Sharif, 0ms todavía coloca el evento en la parte inferior de la pila.
BobRodes

67

De hecho, puede tomar el valor directamente del evento . Sin embargo, es un poco obtuso cómo llegar.

Devuelve falso si no quieres que pase.

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

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

});

2
Este es el camino a seguir
DdW

1
es decir, 11: window.clipboardData.getData ('texto')
Wallstrider

44
Sin embargo, tenga en cuenta que la necesidad de la propiedad "originalEvent" solo es necesaria si está manejando el evento con jQuery. Puedes hacerlo simplemente e.clipboardData.getData('text')en JavaScript.
Asier Paz

¡La mejor respuesta aquí! Pero, me pareció extraño que la versión abreviada de la vinculación no funcione con esto, es decir, error si intento esto: $ (this) .paste (function (e) {...}) ;, even aunque eso funciona para la entrega corta .on ('clic'), etc.
HoldOffHunger

niggle: al código le falta un par de cierre. Aparentemente, el cambio es demasiado pequeño para permitirme arreglarlo como una edición.
Joachim Lous

42

Para la compatibilidad multiplataforma, debe manejar eventos de entrada y cambio de propiedad:

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

2
Hermosa solución que funciona como captura de eventos de pegado y keyup. Nota: Esto hace que la función de evento se active dos veces por alguna razón si resalta los contenidos de entrada y luego escribe algo al menos en IE8 (no importante en muchos casos, pero posiblemente muy importante en otros).
baacke

Agradable ! ¡No sabía sobre esto, y se adapta perfectamente a mis necesidades!
Marc Brillault

18

Lo solucioné utilizando el siguiente código:

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

Ahora solo necesito almacenar la ubicación del cursor y agregarme a esa posición, entonces estoy listo ... creo :)


1
¿Cómo almacenaste la ubicación de caret?
Petah

@Petah Puede verificar con qué elemento se enfoca .find(':focus'), y sabiendo que ese elemento determina la ubicación del cursor. Mira esto .
Jacob

Recuerde que "live" está en desuso a favor de "on"
NBPalomino

inputmarca la diferencia :) Normalmente tengo estos en mis eventos de cuadro de texto, keyup keydown paste inputpero obviamente depende de cuáles sean sus motivos
Pierre

10

Hmm ... creo que puedes usar e.clipboardDatapara atrapar los datos que se están pegando. Si no funciona, eche un vistazo aquí .

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

2
Cuando ejecuto esto en Safari me sale 'indefinido' :(
Christoffer Winterkvist

1
clipboardData es un recinto de seguridad en la mayoría de los navegadores (agujero de seguridad obvia.)
podperson

2
¡Internet Explorer solamente!
Lodewijk

9

Escuche el evento de pegar y configure un escucha de evento de keyup. En keyup, captura el valor y elimina el detector de eventos keyup.

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

66
Esto es muy bueno, pero no funciona para pegar con el botón derecho.
Joseph Ravenwolfe el

tampoco funciona para pegar con el botón central (X11) solo funciona si usaron el teclado para pegar.
Jasen

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

Funcionará bien


6

Esto se está acercando a lo que podrías desear.

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() ) );
   }
 });
});

Tenga en cuenta que cuando no se encuentra el objeto clipboardData (en navegadores que no sean IE) actualmente está obteniendo el valor completo del elemento + el valor del portapapeles.

Probablemente pueda hacer algunos pasos adicionales para diferenciar los dos valores, antes de una entrada y después de la entrada, si realmente solo busca los datos que realmente se pegaron en el elemento.


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

Esto funcionará para el evento de pegado del mouse.


2
Este es el mejor uso de todos.
Sinan Eldem

5

¿Qué tal comparar el valor original del campo y el valor cambiado del campo y deducir la diferencia como el valor pegado? Esto captura el texto pegado correctamente incluso si hay texto existente en el campo.

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

Este código me funciona, ya sea pegar con el botón derecho o copiar directamente

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

Cuando pego Section 1: Labour Costse convierte 1en cuadro de texto.

Para permitir solo el valor flotante, uso este código

 //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();

        ...
    }
});

Más lejos:


text / html no es válido, solo url y text.
Mike

@ Mike Copié el fragmento directamente de la documentación referenciada.
davidcondrey

Probé esto durante aproximadamente un día. text / html nunca funcionaría. Terminé agregando un tiempo de espera de 0 de retraso y pude tomar el html del div donde estaban pegando. Si alguien tuviera un violín que funcionara, eso ayudaría. Tal vez lo estoy haciendo mal ...
Mike

3

Vea este ejemplo: http://www.p2e.dk/diverse/detectPaste.htm

Esencialmente rastrea cada cambio con el evento oninput y luego verifica si es una comparación pegar por cadena. Ah, y en IE hay un evento onpaste. Entonces:

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

Entonces, ¿es imposible obtener el texto pegado cuando ocurre el evento?
Christoffer Winterkvist

Bueno, supongo que tendrás que lidiar con eso tú mismo, como comparar el antes y el después. Tiene que ser bastante fácil. Pero, ¿por qué no revalidas toda la entrada? ¿Lento?
Ilya Birman el

Solo pensé que sería posible hacerlo, pero supongo que no, ahora estoy probando otro método pegándolo en un área de texto y luego transfiriéndolo a su destino final. Espero que eso funcione.
Christoffer Winterkvist

Solo tiene que encontrar el fragmento de coincidencia máxima al comienzo de dos cadenas (antes y después). Todo desde allí y hasta la diferencia de longitudes es el texto pegado.
Ilya Birman el

@IlyaBirman no, no lo es: por ejemplo, el texto pegado puede estar reemplazando parte (o todo) del original
Jasen

1

Este método utiliza jqueries contenidos (). Unwrap ().

  1. Primero, detecta el evento pegar
  2. Agregue una clase única a las etiquetas que ya están en el elemento en el que estamos pegando.
  3. Después de un tiempo de espera determinado, escanee todos los contenidos que desempaquetan las etiquetas que no tienen la clase que configuró anteriormente. Nota: Este método no elimina las etiquetas de cierre automático como
    Ver un ejemplo a continuación.

    //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);

¡Definitivamente la mejor, la respuesta más breve y auto hablante jamás vista! Muchas gracias, me
alegraste el

0

Esto resultó ser bastante ilusorio. El valor de la entrada no se actualiza antes de la ejecución del código dentro de la función de evento pegar. Intenté llamar a otros eventos desde la función de pegar eventos, pero el valor de entrada todavía no se actualiza con el texto pegado dentro de la función de cualquier evento. Eso es todos los eventos aparte de keyup. Si llama a keyup desde la función de evento de pegado, puede desinfectar el texto pegado desde dentro de la función de evento de keyup. al igual que...

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

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

Hay una advertencia aquí. En Firefox, si restablece el texto de entrada en cada tecla, si el texto es más largo que el área visible permitida por el ancho de entrada, al restablecer el valor en cada tecla se rompe la funcionalidad del navegador que desplaza automáticamente el texto a la posición de intercalación en el Fin del texto. En cambio, el texto se desplaza hacia atrás hasta el principio, dejando el cursor fuera de la vista.


Se llama a onpaste antes de pegar el contenido. Necesita un retraso programado de al menos 4 ms para crear su propia función de post-pasta, para lavar los resultados de la pasta.
DragonLord

-1

Script para eliminar caracteres especiales de todos los campos con la clase 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
¿Podría agregar una descripción de la desinfección relevante y por qué puede ayudar a resolver el problema del afiche? Simplemente proporcionar un bloque de código realmente no ayuda al OP (o futuros buscadores) a comprender cómo resolver el problema, solo alienta a copiar / pegar código incomprendido.
Troy Alford

-2

Hay una advertencia aquí. En Firefox, si restablece el texto de entrada en cada tecla, si el texto es más largo que el área visible permitida por el ancho de entrada, al restablecer el valor en cada tecla se rompe la funcionalidad del navegador que desplaza automáticamente el texto a la posición de intercalación en el Fin del texto. En cambio, el texto se desplaza hacia atrás hasta el principio, dejando el cursor fuera de la vista.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.