Editor WYSIWYG - Colando uma imagem da área de trabalho no Chrome

21/06/2016

Quem trabalha com desenvolvimento web provavelmente já precisou implementar um "editorzinho" de textos básico com formatação (negrito e etc, alteração de fonte e etc), o famoso editor no estilo WYSIWYG, quase um Word. :)

Existem diversas soluções no mercado que podem ser integradas a projetos de terceiros e eu creio que uma das mais completas seja o CKeditor, no meu caso optei por algo mais enxuto, mas com o mínimo necessário além de um API que me atendesse, o SCEditor.

Apesar de N tipos de editores, alguns muito simples, outros bem completos, todos os que vi funcionam com a mesma lógica de disponibilização da área que será editada, a definição da propriedade "ContentEditable=true" na tag HTML que então será a área do editor.

...então caímos no assunto da publicação, nem todos os browsers aceitam colar uma imagem no editor!

Quando o usuário faz uma captura de tela pela tecla Print Screen ou com uma ferramenta (SnagIt por exemplo), a imagem fica na área de transferência, então ao colar no editor a mesma é codificada para o padrão texto Base64 e embutida em uma tag IMG no HTML , recurso idêntico ao GMail quando incorpora imagens como anexo, bem, esse é o comportamento correto, mas...no Chrome nada acontece.

Testei no Internet Explorer 11 e no Firefox 35 e funciona certinho, mas no Chrome 40 nada acontece, quando a gente tenta colar uma imagem nem mesmo aparece algum indicador que foi tentado, já com texto ou HTML na área de transferência o mesmo é colado sem problemas.

Tentei encontrar alguma chave de configuração no Chrome que permitisse colar imagem mas não encontrei nada, algo tipo "Enable Image Paste".


Então resolvi apelar testando códigos de interceptação do "paste" da imagem pelo usuário, e 

não é que funcionou!



A SOLUÇÃO

A idéia básica é interceptar o "paste" dado pelo usuário, interpretar o conteúdo da área de trabalho como imagem, gerar a cadeia base64 da image e então injetar no HTML do editor a tag IMG com a string.

Não há uma solução genérica, uma que funcione em qualquer browser, a que funcionou está na referência 2 abaixo, e ainda precisei fazer algumas alterações.

Como o problema é apenas no Chrome descartei o código para os outros browsers.

Ao invés de incorporar a imagem como base64 eu poderia salvá-la em disco e então adicionar uma tag IMG com o link da imagem no servidor, isso não seria um problema, o mais difícil foi achar uma rotina que interceptasse o "paste" no Chrome.

 

[Atualização em 25/fev/15]

Após colocar o comentário sobre o problema num fórum do site do SCEditor que eu utilizo, o autor mandou uma solução mais enxuta da mesma idéia, e que pelo o que testei funciona de forma genérica (são algumas poucas alterações do código original que montei):

var IMAGE_MIME_REGEX = /^image\/(p?jpeg|gif|png)$/i;

var loadImage = function (file) {
    var reader = new FileReader();
    reader.onload = function(e){
        var img = document.createElement('img');
        img.src = e.target.result;
        
        var range = window.getSelection().getRangeAt(0);
        range.deleteContents();
        range.insertNode(img);
    };
    reader.readAsDataURL(file);
};

document.onpaste = function(e){
    var items = e.clipboardData.items;

    for (var i = 0; i < items.length; i++) {
        if (IMAGE_MIME_REGEX.test(items[i].type)) {
            loadImage(items[i].getAsFile());
            return;
        }
    }
    
    // Normal paste handling here
}

Referências:

  1. http://pt.wikipedia.org/wiki/WYSIWYG
  2. https://gist.github.com/Buildstarted/4577472/
  3. http://www.w3schools.com/jsref/event_onpaste.asp
  4. http://pt.wikipedia.org/wiki/Base64
  5. http://stackoverflow.com/questions/237254/how-do-you-handle-oncut-oncopy-and-onpaste-in-jquery
  6. http://www.sceditor.com/posts/how-to-upload-and-insert-an-image/
  7. http://ckeditor.com/
  8. http://jsfiddle.net/6yocdszm/ (atualização de 25/fev/15)