Entrada de captura de pasta


210

Estou procurando uma maneira de higienizar as entradas que colo no navegador, isso é possível com o jQuery?

Eu consegui chegar a isso até agora:

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

Infelizmente, meu desenvolvimento chegou a um ponto insuportável por causa desse problema "menor". Eu realmente me faria um campista feliz se alguém pudesse me indicar a direção certa.


6
Marque stackoverflow.com/a/1503425/749232 como a resposta para o uso de outras pessoas com o mesmo problema. Isso resolveu para mim.
saji89

2
.Live () é obsoleto a partir do jQuery 1.9, eles recomendam .no () em vez
Sameer Alibhai

Respostas:


337

OK, acabei de esbarrar no mesmo problema. Percorri o longo caminho

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

Apenas um pequeno tempo limite até que a função .val () possa ser preenchida.

E.


20
E se já houver texto na área de texto e você colar, e você quiser apenas o texto colado?
barfoon

39
Funciona perfeitamente, obrigado. Um tempo limite de 0 também funciona. A função só precisa ser adiada para o próximo loop.
Daniel Lewis

4
Apenas estive em uma situação semelhante. O tempo limite está aí porque o evento de colagem não é imediato, mas leva alguns milissegundos para que o conteúdo da área de transferência seja colado.
James

8
@ user563811: Observe que o tempo limite mínimo oficial é de 4 ms no HTML5.
Pimvdb

4
Como sharif diz, 0ms ainda coloca o evento na parte inferior da pilha.
BobRodes 10/09/12

67

Você pode realmente pegar o valor diretamente do evento . É um pouco obtuso como chegar até lá.

Retorne false se você não quiser que ele continue.

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

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

});

2
Este é o caminho a percorrer
DDW

1
ou seja, 11: window.clipboardData.getData ('text')
Wallstrider

4
No entanto, observe que a necessidade da propriedade "originalEvent" será necessária apenas se você estiver manipulando o evento com jQuery. Você pode fazer apenas e.clipboardData.getData('text')em JavaScript simples.
Asier Paz

Melhor resposta aqui! Mas - achei estranho que a versão abreviada de binding não funcione com isso, ou seja, erro se eu tentar o seguinte: $ (this) .paste (function (e) {...}); embora isso funcione para
mãos

niggle: o código está faltando um ponto final. Aparentemente, a mudança é muito pequena para permitir que eu a corrija como uma edição.
Joachim Lous

42

Para compatibilidade entre plataformas, ele deve manipular os eventos oninput e onpropertychange:

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

2
Solução bonita que funciona como captura de eventos de colar e de keyup. Nota: Isso faz com que a função de evento seja acionada duas vezes por algum motivo, se você destacar o conteúdo da entrada e digitar algo em pelo menos no IE8 (não importante em muitos casos, mas possivelmente muito importante em outros).
Baacke

Agradável ! Eu não sabia sobre este, e ele se encaixa perfeitamente às minhas necessidades!
Marc Brillault 03/02

18

Eu meio que corrigi usando o seguinte 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);
    }
});

Agora eu só preciso armazenar a localização do sinal de intercalação e anexar a essa posição, então estou pronto ... eu acho :)


1
Como você armazenou o local do cursor?
Petah

@Petah Você pode verificar com qual elemento o foco está .find(':focus')e sabendo que esse elemento determina a localização do cursor. Veja isso .
Jacob

Lembre-se que "ao vivo" é depreciado em favor do "on"
NBPalomino

inputfaz a diferença :) Eu normalmente têm estes em meus eventos de caixa de texto keyup keydown paste input, mas, obviamente, depende do que seus motivos são
Pierre

10

Hmm ... acho que você pode usar e.clipboardDatapara pegar os dados que estão sendo colados. Se não der certo, dê uma olhada aqui .

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

2
Quando executo isso no Safari, fico 'indefinido' :(
Christoffer Winterkvist 26/03/2009

1
clipboardData está no modo seguro na maioria dos navegadores (falha de segurança óbvia.)
podperson

2
Apenas Internet Explorer!
Lodewijk

9

Ouça o evento de colar e defina um ouvinte de evento de keyup. No keyup, capture o valor e remova o ouvinte de evento do keyup.

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

6
Isso é muito bom, mas não funciona para colar com o botão direito.
Joseph Ravenwolfe

nem funciona para colar com o botão do meio (X11), só funciona se eles usaram o teclado para colar.
Jasen

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

Vai funcionar bem.


6

Isso está se aproximando do que você pode querer.

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

Observe que, quando o objeto clipboardData não é encontrado (em navegadores que não sejam o IE), você está atualmente obtendo o valor total do elemento + o valor da área de transferência.

Provavelmente, você pode executar algumas etapas extras para diferenciar os dois valores, antes de uma entrada e após a entrada, se realmente estiver somente após os dados que foram realmente colados no elemento.


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

Isso funcionará para o evento de colagem do mouse.


2
Este é o melhor uso de todos.
Sinan Eldem

5

Que tal comparar o valor original do campo e o valor alterado do campo e deduzir a diferença como valor colado? Isso captura o texto colado corretamente, mesmo se houver texto existente no 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 está funcionando para mim, cole com o botão direito ou cole cópia direta

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

Quando colar Section 1: Labour Cost, torna-se1 na caixa de texto.

Para permitir apenas o valor flutuante, eu uso esse 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();

        ...
    }
});

Mais distante:


text / html não é válido, apenas URL e texto.
Mike

@ Mike Copiei o trecho diretamente da documentação referenciada.
Davidcondrey,

Eu tentei isso por cerca de um dia. text / html nunca funcionaria. Acabei adicionando um tempo limite de 0 de atraso e consegui pegar o html da div em que estavam colando. Se alguém tivesse um violino em funcionamento, isso ajudaria. Talvez eu estou apenas fazendo errado ...
Mike

3

Veja este exemplo: http://www.p2e.dk/diverse/detectPaste.htm

Ele rastreia essencialmente todas as alterações com o evento oninput e verifica se é uma comparação colar por string. Ah, e no IE há um evento de pasta. Assim:

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

Portanto, é impossível apenas obter o texto da colagem quando o evento ocorre?
Christoffer Winterkvist 26/03/09

Bem, acho que você terá que lidar com isso sozinho, tipo, comparar o antes e o depois. Tem que ser bastante fácil. Mas por que você não revalida toda a entrada? Lento?
Ilya Birman

Eu apenas pensei que isso seria possível, mas acho que não. No momento, estou tentando outro método colando-o em uma área de texto e transferindo-o para seu destino final. Espero que funcione.
Christoffer Winterkvist 26/03/09

Você só precisa encontrar o fragmento de correspondência máxima no início de duas strings (antes e depois). Tudo a partir daí e até a diferença de comprimentos é o texto colado.
Ilya Birman

@IlyaBirman não, não é: por exemplo, o texto colado pode estar substituindo parte (ou a totalidade) do original
Jasen

1

Este método usa jqueries contents (). Desembrulhar ().

  1. Primeiro, detecte o evento de colagem
  2. Adicione uma classe exclusiva às tags que já estão no elemento no qual estamos colando.
  3. Após um determinado tempo limite, verifique todo o conteúdo, desembrulhando as tags que não possuem a classe que você definiu anteriormente. Nota: Este método não remove as tags de fechamento automático como
    Veja um exemplo abaixo.

    //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, a melhor, mais curta e auto-falante resposta já vista !!! Muito obrigado, você fez o meu dia;)
webprogrammer

0

Isso provou ser bastante ilusório. O valor da entrada não é atualizado antes da execução do código dentro da função de evento colar. Tentei chamar outros eventos da função de evento colar, mas o valor de entrada ainda não é atualizado com o texto colado na função de qualquer evento. Isso é todos os eventos além do keyup. Se você chamar keyup de dentro da função de evento de colagem, poderá limpar o texto colado de dentro da função de evento de keyup. igual a...

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

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

Há uma ressalva aqui. No Firefox, se você redefinir o texto de entrada em cada keyup, se o texto for maior que a área visível da largura de entrada permitida, a redefinição do valor em cada keyup interromperá a funcionalidade do navegador que rola automaticamente o texto para a posição de cursor na posição fim do texto. Em vez disso, o texto volta ao início, deixando o cursor fora de vista.


onpaste é chamado antes que o conteúdo seja colado. Você precisa de um atraso de pelo menos 4ms para criar sua própria função de pós-pasta e lavar os resultados da pasta.
DragonLord 18/10/12

-1

Script para remover caracteres especiais de todos os campos com a 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
Você poderia adicionar uma descrição da higienização relevante e por que ela pode ajudar a resolver o problema do pôster? O simples fornecimento de um bloco de código não ajuda realmente o OP (ou futuros pesquisadores) a entender como resolver o problema - apenas incentiva a copiar / colar código incompreendido.
Troy Alford

-2

Há uma ressalva aqui. No Firefox, se você redefinir o texto de entrada em cada keyup, se o texto for maior que a área visível da largura de entrada permitida, a redefinição do valor em cada keyup interromperá a funcionalidade do navegador que rola automaticamente o texto para a posição de cursor na posição fim do texto. Em vez disso, o texto volta ao início, deixando o cursor fora de vista.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.