Como um aplicativo Web detecta um evento de colagem e recupera os dados a serem colados?
Gostaria de remover o conteúdo HTML antes que o texto seja colado em um editor de rich text.
Limpar o texto depois de ser colado depois funciona, mas o problema é que toda a formatação anterior é perdida. Por exemplo, posso escrever uma frase no editor e torná-la em negrito, mas quando colo um novo texto, toda a formatação é perdida. Quero limpar apenas o texto colado e deixar intacta a formatação anterior.
Idealmente, a solução deve funcionar em todos os navegadores modernos (por exemplo, MSIE, Gecko, Chrome e Safari).
Observe que o MSIE possui clipboardData.getData()
, mas não foi possível encontrar funcionalidades semelhantes para outros navegadores.
event.clipboardData.getData('Text')
trabalhou para mim.document.addEventListener('paste'...
funcionou para mim, mas causou conflitos se um usuário quisesse colar em outro lugar da página. Então eu tenteimyCanvasElement.addEventListener('paste'...
, mas isso não funcionou. Eventualmente, eu descobri quemyCanvasElement.parentElement.addEventListener('paste'...
funcionava.Respostas:
A situação mudou desde que escrevemos esta resposta: agora que o Firefox adicionou suporte na versão 22, todos os principais navegadores agora suportam o acesso aos dados da área de transferência em um evento de colagem. Veja a resposta de Nico Burns para um exemplo.
No passado, isso geralmente não era possível de uma maneira entre navegadores. O ideal seria conseguir o conteúdo colado por meio do
paste
evento, o que é possível em navegadores recentes, mas não em navegadores antigos (em particular, Firefox <22).Quando você precisa oferecer suporte a navegadores antigos, o que você pode fazer é bastante complicado e funciona um pouco, que funcionará nos navegadores Firefox 2+, IE 5.5+ e WebKit, como Safari ou Chrome. Versões recentes do TinyMCE e do CKEditor usam esta técnica:
designMode
e chamefocus()
a área de texto, movendo o cursor e redirecionando a pastadesignMode
da área de texto , remova a área de texto do documento, ligue novamente, restaure a seleção do usuário e cole o texto.Observe que isso funcionará apenas para eventos de colagem do teclado e não para pastas do menu de contexto ou edição. Quando o evento de colagem é disparado, é tarde demais para redirecionar o cursor para a área de texto (em alguns navegadores, pelo menos).
No caso improvável de suporte ao Firefox 2, observe que você precisará colocar a área de texto no documento pai em vez do documento do iframe do editor WYSIWYG nesse navegador.
fonte
designMode
é uma propriedade booleanadocument
e torna a página inteira editável quandotrue
. Os editores WYSIWYG geralmente usam um iframe comdesignMode
on como o painel editável. O salvamento e a restauração da seleção do usuário são feitos de uma maneira no IE e de outros navegadores, assim como a colagem do conteúdo no editor. Você precisa obter umTextRange
no IE e umRange
em outros navegadores.paste
evento, mas geralmente é tarde demais para redirecionar a pasta para outro elemento, para que esse hack não funcione. O fallback na maioria dos editores é mostrar uma caixa de diálogo para o usuário colar.paste
evento, no entanto, permitirá limpar o conteúdo do elemento (e salvá-lo em uma variável para que você possa restaurá-lo mais tarde). Se esse contêiner for umdiv
(provavelmente também funciona para umiframe
), você poderá percorrer o conteúdo colado usando métodos dom normais ou obtê-lo como uma string usandoinnerHTML
. Você pode restaurar o conteúdo anterior dodiv
e inserir o conteúdo que desejar. Ah, e você tem que usar o mesmo hack do temporizador acima. Eu estou surpreso que TinyMCE não faça isso ...Solução nº 1 (somente texto sem formatação e requer o Firefox 22+)
Funciona para IE6 +, FF 22+, Chrome, Safari, Edge (testado apenas no IE9 +, mas deve funcionar para versões inferiores)
Se você precisar de suporte para colar HTML ou Firefox <= 22, consulte a Solução 2.
HTML
Javascript
JSFiddle: https://jsfiddle.net/swL8ftLs/12/
Observe que esta solução usa o parâmetro 'Texto' para a
getData
função, que não é padrão. No entanto, ele funciona em todos os navegadores no momento da escrita.Solução 2 (HTML e funciona no Firefox <= 22)
Testado no IE6 +, FF 3.5+, Chrome, Safari, Edge
HTML
Javascript
JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/
Explicação
O
onpaste
evento dodiv
possui ahandlePaste
função anexada e transmitiu um único argumento: oevent
objeto para o evento de colagem. De particular interesse para nós, é aclipboardData
propriedade deste evento que permite o acesso à área de transferência em navegadores que não sejam. No IE, o equivalente éwindow.clipboardData
, embora isso tenha uma API ligeiramente diferente.Veja a seção de recursos abaixo.
A
handlepaste
função:Esta função tem dois ramos.
A primeira verifica a existência de
event.clipboardData
e verifica se suatypes
propriedade contém 'text / html' (types
pode ser umDOMStringList
que é verificado usando ocontains
método ou uma string que é verificada usando oindexOf
método). Se todas essas condições forem atendidas, procederemos como na solução 1, exceto com 'text / html' em vez de 'text / plain'. Atualmente, ele funciona no Chrome e Firefox 22+.Se esse método não for suportado (todos os outros navegadores), então nós
DocumentFragment
waitForPastedData
funçãoA
waitforpastedata
função:Essa função pesquisa primeiro os dados colados (uma vez a cada 20ms), o que é necessário porque não aparece imediatamente. Quando os dados aparecerem:
A
processpaste
função:Faz coisas arbitrárias com os dados colados. Nesse caso, apenas alertamos os dados, você pode fazer o que quiser. Você provavelmente desejará executar os dados colados através de algum tipo de processo de limpeza de dados.
Salvando e restaurando a posição do cursor
Em uma situação real, você provavelmente desejaria salvar a seleção antes e restaurá-la depois ( Defina a posição do cursor em contentEditable <div> ). Você pode inserir os dados colados na posição em que o cursor estava quando o usuário iniciou a ação de colar.
Recursos:
Agradecemos a Tim Down por sugerir o uso de um DocumentFragment, e também por detectar um erro no Firefox devido ao uso de DOMStringList em vez de uma string para clipboardData.types
fonte
DocumentFragment
lugar em vez de usá-loinnerHTML
por vários motivos: primeiro, você mantém os manipuladores de eventos existentes; segundo, salvar e restaurarinnerHTML
não é garantido para criar uma cópia idêntica do DOM anterior; terceiro, você pode salvar a seleção como umaRange
alternativa, em vez de precisar adicionar elementos de marcador ou calcular deslocamentos de texto (que é o que você faria se usasseinnerHTML
).DocumentFragment
uma dor no IE? É o mesmo que em outros navegadores, a menos que você use um intervalo e oextractContents()
faça, o que não é mais conciso do que a alternativa em qualquer caso. Implementei um exemplo de sua técnica, usando o Rangy para manter as coisas agradáveis e uniformes nos navegadores: jsfiddle.net/bQeWC/4 .waitforpastedata
funçãotext/html
usando a API da área de transferência do W3C. No passado, essa tentativa lançaria uma exceção. Portanto, não é mais necessário esta solução alternativa / hack para o Edge.Versão simples:
Usando
clipboardData
Demonstração: http://jsbin.com/nozifexasu/edit?js,output
Teste de Edge, Firefox, Chrome, Safari, Opera.
⚠ Document.execCommand () está obsoleto agora.
Nota: Lembre-se de verificar a entrada / saída no lado do servidor também (como tags de faixa PHP )
fonte
window.clipboardData.getData('Text');
e.preventDefault(); if (e.clipboardData) { content = (e.originalEvent || e).clipboardData.getData('text/plain'); document.execCommand('insertText', false, content); } else if (window.clipboardData) { content = window.clipboardData.getData('Text'); document.selection.createRange().pasteHTML(content); }
Demonstração ao vivo
Testado no Chrome / FF / IE11
Há um incômodo no Chrome / IE, que é o fato de esses navegadores adicionarem
<div>
elemento para cada nova linha. Há um post sobre isso aqui e ele pode ser corrigido definindo o elemento contenteditable comodisplay:inline-block
Selecione algum HTML destacado e cole-o aqui:
fonte
Eu escrevi uma pequena prova de conceito para a proposta de Tim Downs aqui com área de texto fora da tela. E aqui vai o código:
Apenas copie e cole o código inteiro em um arquivo html e tente colar (usando ctrl-v) o texto da área de transferência em qualquer lugar do documento.
Eu testei no IE9 e em novas versões do Firefox, Chrome e Opera. Funciona muito bem. Também é bom que se possa usar qualquer combinação de teclas que ele preferir para aprimorar essa funcionalidade. Claro que não se esqueça de incluir fontes jQuery.
Sinta-se à vontade para usar esse código e, se vier com algumas melhorias ou problemas, poste-os de volta. Observe também que eu não sou desenvolvedor de Javascript, por isso posso ter perdido alguma coisa (=> faça seu próprio testign).
fonte
Baseado no l2aelba anwser. Isso foi testado em FF, Safari, Chrome, IE (8,9,10 e 11)
fonte
Este não usa nenhum setTimeout ().
Eu usei este ótimo artigo para obter suporte entre navegadores.
Este código é estendido com o identificador de seleção antes de colar: demo
fonte
Para limpar o texto colado e substituir o texto atualmente selecionado pelo texto colado, o assunto é bastante trivial:
JS:
fonte
Isso deve funcionar em todos os navegadores que suportam o evento onpaste e o observador de mutações.
Essa solução vai além da obtenção apenas do texto, na verdade permite editar o conteúdo colado antes de ser colado em um elemento.
Ele funciona usando evento onpaste, contenteditable (suportado por todos os principais navegadores) e observadores de mutação (suportados pelo Chrome, Firefox e IE11 +)
passo 1
Crie um elemento HTML com contenteditable
passo 2
No seu código Javascript, adicione o seguinte evento
Precisamos vincular pasteCallBack, já que o observador da mutação será chamado de forma assíncrona.
etapa 3
Adicione a seguinte função ao seu código
O que o código faz:
Exemplo
Mostrar snippet de código
Muito obrigado a Tim Down. Veja este post pela resposta:
Obter o conteúdo colado no documento ao colar
fonte
A solução que funciona para mim é adicionar um ouvinte de evento para colar um evento, se você estiver colando em uma entrada de texto. Como o evento paste acontece antes que o texto nas alterações de entrada, dentro do meu manipulador on paste, crio uma função adiada dentro da qual checo por alterações na minha caixa de entrada que ocorreram na pasta:
fonte
Isso foi muito longo para um comentário sobre a resposta de Nico, que eu acho que não funciona mais no Firefox (pelos comentários), e não funcionou para mim no Safari como está.
Primeiro, agora você parece ser capaz de ler diretamente da área de transferência. Em vez de codificar como:
usar:
porque o Firefox tem um
types
campoDOMStringList
que não é implementadotest
.O próximo Firefox não permitirá colar, a menos que o foco esteja em um
contenteditable=true
campo.Por fim, o Firefox não permitirá colar de maneira confiável , a menos que o foco esteja em uma
textarea
(ou talvez entrada) que não é apenascontenteditable=true
mas também:display:none
visibility:hidden
Eu estava tentando ocultar o campo de texto para que a colar funcionasse em um emulador JS VNC (ou seja, estava indo para um cliente remoto e não havia realmente
textarea
etc para colar). Descobri que tentar ocultar o campo de texto no exemplo acima apresentava sintomas onde, às vezes, funcionava, mas geralmente falhava na segunda pasta (ou quando o campo era limpo para evitar colar os mesmos dados duas vezes), pois o campo perdia o foco e não recuperava adequadamente apesar dissofocus()
. A solução que eu encontrei foi colocá-lo emz-order: -1000
, torná-lodisplay:none
, 1px por 1px e definir todas as cores para transparentes. Que nojo.No Safari, você aplica a segunda parte do acima, ou seja, você precisa de um
textarea
que não édisplay:none
.fonte
O primeiro que vem à mente é o manipulador de pastas da lib de fechamento do Google, http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html
fonte
Solução simples:
fonte
Isso funcionou para mim:
fonte
fonte
Você pode fazer isso desta maneira:
use este plugin jQuery para eventos de pré e pós-colar:
Agora você pode usar este plugin ;:
Explicação
Primeiro, defina um uid para todos os elementos existentes como atributo de dados.
Em seguida, compare todos os nós POST PASTE event. Portanto, comparando, você pode identificar o recém-inserido porque eles terão um uid e, em seguida, basta remover o atributo style / class / id dos elementos recém-criados, para que você possa manter sua formatação mais antiga.
fonte
fonte
Apenas deixe o navegador colar, como de costume, em sua div editável de conteúdo e, depois da pasta, troque os elementos de extensão usados para estilos de texto personalizados pelo próprio texto. Isso parece funcionar bem no Internet Explorer e nos outros navegadores que tentei ...
Esta solução pressupõe que você esteja executando o jQuery e que não deseja formatação de texto em nenhum dos seus divs editáveis de conteúdo .
O lado positivo é que é super simples.
fonte
span
marcar? Eu imaginaria que a pergunta era sobre todas as tags.Esta solução é substituir a tag html, é simples e em vários navegadores; verifique este jsfiddle: http://jsfiddle.net/tomwan/cbp1u2cx/1/ , código principal:
aviso: você deve fazer algum trabalho sobre o filtro xss na parte de trás, porque esta solução não pode filtrar cadeias de caracteres como '<< >>'
fonte
Este é um código existente publicado acima, mas eu o atualizei para o IE, o erro ocorreu quando o texto existente é selecionado e colado não exclui o conteúdo selecionado. Isso foi corrigido pelo código abaixo
Veja o código completo abaixo
fonte