company_banner

Три способа поддержать вставку картинок в поле ввода от разработчиков Яндекс.Почты

    Три способа вставки картинок в тело письма в Яндекс.Почте

    Не так давно мы подробно рассказывали про новые аттачи в Яндекс.Почте. В декабре в у нас появился новый просмоторщик картинок. Работать с изображениями в Почте благодаря этим нововведениям стало действительно проще и удобнее.

    Тем не менее, оставалась ещё одна сложность: в связи с браузерными ограничениями изображения нельзя было вставлять прямо в тело письма. Картинку нужно было сохранить на своём компьютере и уже оттуда прикрепить к письму, как любой другой файл.

    Мы долго думали над этой проблемой. Можно было использовать java-апплет или flash, но у этих решений были существенные ограничения. Например, при использовании java-апплета нужно будет обязательно разрешать выполнение апплета в браузере. В итоге мы решили использовать новые возможности современных браузеров, такие как Clipboard API, File API и Drag n Drop.

    Читайте в нашем посте о том, как вставлять в письмо картинки из буфера обмена или по публичному URL и как добавлять их в тело письма простым перетягиванием с рабочего стола.


    Вставка картинок из буфера обмена


    До недавнего времени полноценная работа с буфером обмена в веб-приложениях казалась невозможной. Но затем появился новый API, специально предназначенный именно для этого (Clipboard API). Он представляет собой интерфейс для работы с данными из буфера обмена при копировании, вырезании и вставке. Интерфейс достаточно универсальный и работает не только с текстовыми данными, но и с файлами в разных форматах. Но, как это обычно бывает, поддерживается он не всеми браузерами и в разном объёме.

    Наиболее полная поддержка на сегодняшний день реализована только в WebKit-браузерах (Safari, Chrome, Яндекс.Браузер). В этих браузерах для событий copy, cut и paste в объекте события есть доступ к объекту clipboardData. У clipboardData есть свойства items (элементы в буфере обмена) и types (типы информации в буфере обмена). Получать или менять информацию из буфера можно при помощи методов getData и setData.

    В Chrome (c 18 версии) и Яндекс.Браузере есть доступ к картинкам в буфере обмена при вставке. Делается это примерно так:

        // Элемент с contentEditable
        var el = document.getElementById('editor');
    
        el.addEventListener('paste', function(e) {
            var clipboard = e.clipboardData;
    
            if (clipboard && clipboard.items) {
                // В буфере обмена может быть только один элемент
                var item = clipboard.items[0];
    
                if (item && item.type.indexOf('image/') > -1) {
                    // Получаем картинку в виде блоба
                    var blob = item.getAsFile();
    
                    if (blob) {
                        // Читаем файл и вставляем его в data:uri
                        var reader = new FileReader();
                        reader.readAsDataURL(blob);
    
                        reader.onload = function(event) {
                            var img = new Image();
                            img.src = event.target.result;
    
                            el.appendChild(img);
                        }
                    }
                }
            }
        });
    

    Кроме браузеров на движке WebKit, вставка картинкок из буфера обмена также работает в Firefox: там картинки в designMode сразу вставляются в data:uri.

    Вставка картинок по публичному URL


    Одно из самых простых и привычных действий — скопировать картинку со страницы в интернете и вставить её в письмо — не поддерживается браузерами по умолчанию. В Safari 5+ в объекте clipboardData нет свойства items, но есть массив types, содержащий типы копируемой иформации. И если копируемая картинка уже есть в интернете по публичному урлу, то её тоже получится вставить. При обычной вставке картинок в designMode Safari создает элемент img с фейковым значением аттрибута src (webkit-fake-url://416873AC...). К этому ресурсу никак нельзя получить доступ из JS, поэтому, чтобы фейковая картинка не вставлялась нужно делать preventDefault у объекта события.

        // Элемент с contentEditable
        var el = document.getElementById('editor');
    
        el.addEventListener('paste', function(e) {
            var clipboard = e.clipboardData;
    
            if (clipboard && clipboard.types) {
                var types = clipboard.types;
    
                if (types.indexOf('public.url') > -1) {
                    // Останавливаем действие по умолчанию, чтобы не вставлялась картинка с фейковым урлом (webkit-fake-url://416873AC...)
                    e.preventDefault();
    
                    // Вставляем картинку
                    var img = new Image();
                    img.src = clipboard.getData('public.url');
    
                    el.appendChild(img);
                }
            }
        });
    

    Вставка по публичному урлу по умолчанию работает в IE9 и выше.

    Вставка перетягиванием


    Помимо прямого копирования картинок из буфера обмена или по публичному урлу, в некоторых браузерах есть возможность вставлять картинки драг-н-дропом. Это очень удобно, потому что можно добавить к письму несколько картинок сразу.

        // Элемент с contentEditable
        var el = document.getElementById('editor');
    
        el.addEventListener('drop', function(e) {
            var dataTransfer = e.dataTransfer;
    
            if (dataTransfer && dataTransfer.files) {
                var files = dataTransfer.files;
                var len = files.length;
    
                if (len) {
                    for (var i = 0; i < len; i++) {
                        var file = files[i];
    
                        // Вставляем только картинки
                        if (file.type.indexOf('image/') < 0) continue;
    
                        var reader = new FileReader();
                        reader.readAsDataURL(file);
    
                        reader.onload = function(event) {
                            var img = new Image();
                            img.src = event.target.result;
    
                            el.appendChild(img);
                        };
                    }
    
                    e.preventDefault();
                }
            }
        });
    

    Это работает в Firefox, Safari 5.1+, Chrome и Яндекс.Браузере.

    В Яндекс.Почте для написания писем с оформлением используется WYSIWYG-редактор TinyMCE. Мы написали для него плагин, объединяющий все решения из этой статьи. Он доступен по адресу github.com/Panya/tinymce_pasteimage.
    Яндекс
    Как мы делаем Яндекс

    Комментарии 25

      –6
      Word это умеет с рождения, а Google Docs это умеет делать уже больше чем полгода. По моему, эта функция очень удобна и жаль, что так медленно добирается до всех проектов интернета. Мамам, бабушкам и папам — жить станет несравненно легче. И самое главное, реализация занимает один вечер.
        0
        Какие полгода, я уже года 2 как минимум в gmail вставляю изображения из буфера обмена по Ctrl+V
        +7
        Вот это я понимаю, поддержка современных стандартов.

        >> Наиболее полная поддержка на сегодняшний день реализована только в WebKit-браузерах (Safari, Chrome, Яндекс.Браузер)

        А как же Нихром и Интернет (от мейл ру)?
          0
          И в них тоже :)
            +11
            Зачем упомянать эти говносборки?
            +16
            В Яндекс.Почте для написания писем с оформлением используется WYSIWYG-редактор TinyMCE. Мы написали для него плагин, объединяющий все решения из этой статьи. Он доступен по адресу github.com/Panya/tinymce_pasteimage.

            Последний абзац очень порадовал. Понимаю, что в масштабах Яндекса это мелочь, но всё же спасибо за то что делитесь наработками.
              +3
              Почему в качестве визивига используете именно TinyMCE? Вопрос больше из любопытства (так как альтернатив полно), хотя иметь визивиг на Хабре лично мне очень бы хотелось )
                –2
                Хабр, это тихий островок в бушующем мире bold, itallic и подобного. Лучше без WYSIWYG.
                  0
                  Ну, можно же иметь «переключатель» и совмещать оба варианта :) Кому-то удобно визивигить, а кому-то — иметь почти полный контроль над текстом.
                    0
                    Тут нет противопоставления, ибо wysiwyg как раз и обеспечивает полный контроль над текстом.

                    Наверное, надо было сказать так: «кому-то хочется иметь полный контроль над текстом (т. е. wysiwyg), а кому-то в этом нет необходимости»…
                  0
                  А вы знаете другой редактор, который создает одинаковый html-код в разных браузерах?
                    +1
                    С удовольствием бы принял во внимание таковой ;) А пока мне нравится этот редактор, у которого с кроссбраузерностью вполне неплохо (по крайней мере для аудитории Хабра).
                      0
                      Он же платный…
                        +2
                        Это да, но если продукт качественный, то не грех и заплатить за него :)
                        0
                        оффтоп конечно, но я очень удивился, когда узнал, что дизайнер этого продукта — Артем Росновский (радиоведущий, подкастер...)
                      +3
                      На момент выбора визивига было только два достойных кандидата — FCKEditor (сейчас CKEditor) и TinyMCE. TinyMCE выбрали тогда из-за большей кроссбраузерности (результат форматирования в разных браузерах не должен различаться) и хорошей плагинной системы. Сейчас, возможно, ситуация поменялась, но я пока не смотрел на альтернативы.
                      0
                      Вот я давно жду реализации подписи в Яндекс.Почта с возможностью использования изображений. Об этом что-нибудь можете сказать?
                        +2
                        Это уже в разработке. Скоро.
                        0
                        Извините, может, я чего-то не понял. Попробовал подключить ваш плагин к TinyMCE.

                        — Вставка картинки из буфера (предварительно скопирована в буфер через Copy Image в том же Хроме 24-й версии). В FF как работала — так и работает. В Хроме как не работала, так и не работает.
                        — Пробую копировать картинку в Опере, а вставлять в Хроме. Не работает ни с вашим плагином, ни без (в mspaint вставляется нормально).
                        — Перетягивание картинки из локальной папки в зону редактора перезагружает страницу — просто открывается эта картинка (Хром последней версии).

                        Я точно чего-то не понял. Помогите понять, что именно.

                        Может, это из-за того, что редактор запускается на localhost? Но ведь через веб-сервер же.
                          0
                          Прощу прощения, про первый пункт обманул. Если копировать в Хроме и вставлять в Хроме же — всё работает (и работало до Вашего плагина).
                          А вот картинка, которую скопировал из Оперы или граф. редактора — не вставляется в Хроме даже с плагином. А в FF вставляется (даже без плагина).
                            0
                            Хм, вы точно правильно подключили плагин? Первый пункт никак не может работать без плагина (можете проверить на www.tinymce.com/tryit/full.php). Второй и особенно третий должны работать (даже на локалхосте).
                          +1
                          Здорово, но я раньше вставлял картинку скопировав url картинки, потом нажимал кнопку обзор и внизу в поле вставлял скопированный адрес. Картинка таким образом загружалась, а я не тратил времени на то чтобы её куда-то сохранять. Уже и привык…
                            0
                            Удобная штука, но… картинка кодируется в data:uri, объем сообщения может стать просто огромным, если запостить скажем 3Мб фотку. Неплохо было бы иметь ограничение.
                              +2
                              Ограничение размера настраивается в плагине. Также, никто не мешает грузить изображение куда-нибудь через FormData а не сразу вставлять.
                              0
                              Перечисляя WebKit-браузеры, упомянули только Safari, Chrome — и Яндекс.Браузер. А полный список-то немаленький: те же Comodo Dragon, RockMelt, SRWare Iron, CoolNovo, Sleipnir 3 for Windows, Torch browser, Arora, Dooble, Web, Midori, Origyn Web Browser, Shiira, SlimBoat, Uzbl, iCab 4+, OmniWeb, Maxthon, ну и Chromium, в конце концов!

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое