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.

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

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

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

Christoffer Winterkvist
fonte
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]
});
zombar
fonte
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');
}
Eric
fonte
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.

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

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

Isso funcionará para o evento de colagem do mouse.

Abhiram
fonte
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);
    });
});
Alo Sarv
fonte
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();
      }
    });
RN Kushwaha
fonte
4
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/html') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/html'));
        e.preventDefault();

        ...
    }
});

Mais distante:

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


fonte
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");
    }
}
Alex, o cozinheiro
fonte
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;
}
lordcheeto
fonte