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.

Christoffer Winterkvist
fuente
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.

Evgeni Dimov
fuente
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')

});
Charles Haro
fuente
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
})
Xue Liangliang
fuente
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 :)

Christoffer Winterkvist
fuente
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]
});
moff
fuente
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');
}
Eric
fuente
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

Rajat Jain
fuente
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.

Señor suerte
fuente
6
 $('').bind('input propertychange', function() {....});                      

Esto funcionará para el evento de pegado del mouse.

Abhiram
fuente
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);
    });
});
Alo Sarv
fuente
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();
      }
    });
RN Kushwaha
fuente
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:

davidcondrey
fuente
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
})
Ilya Birman
fuente
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);
Shadrack B. Orina
fuente
¡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.


fuente
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");
    }
}
Alex el cocinero
fuente
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;
}
lordcheeto
fuente