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.