15 апреля, 2009

Копировать в буфер

Не самая критичная фича, но весьма специфическая в реализации.

Что это и зачем

Обычно эту кнопку помещают возле всяких «кодов для вставки» видео, или картинок. Чтобы людям было проще копировать. Как-то так:

копирование на bit.lyКопирование ссылки на одном из укоротителей ссылок

копирование на дни.руКопирование кода на dni.ru

Как это делают

Скопировать в буфер в IE можно обычным джаваскриптом:

  1. window.clipboardData.setData(’Text’,'Текст который будет в буфере’);

У всех остальных браузеров настройки безопасности по дефолту не позволят это сделать. Потому обычно этот вопрос решали с помощью Flash. Динамически создавался флэш ролик, и в его параметры добавляли текст, который нужно было поместить в буфер. А сам флэш уже имеет доступ к буферу в любой системе-браузере, примерно так:

  1. flash = '<embed src="copy.swf" FlashVars="clipboard='+encodeURIComponent(t)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
  2. element.innerHTML = flash;

Ролик запрограммирован так, что при создании сразу копирует свой параметр clipboard пользователю в буфер.
Так это всегда и работало. Но.

Проблема

Однако, осенью 2008 в флэше нашелся эксплойт, благодаря которому злоумышленники могли как угодно использовать буфер обмена пользователя без его ведома (собственно, метод описанный выше и был эксплойтом). Поэтому в Flash 10 было введено ограничение

With Flash Player 10, the System.setClipboard() method may be successfully called only through ActionScript that originates from user interaction.

Потому, на самом деле, вся та куча плагинов для jquery, например, которые вы нагуглите по запросу «jquery copy to clipboard» попросту не работает в 10м Flash плеере.
При этом, они отлично работают в 8 и 9 версиях (что внесло кучу путаницы в разбирательство с ситуацией). Но учитывая что 10й имеет долю больше 50% нет никакого смысла его игнорировать. Копирование в буфер старым способом больше нельзя считать надежным.

Решение

Так как мне в одном из проектов совершенно обязательно надо было реализовать эту фичу. Пришлось использовать единственный на данный момент вариант. Его я сделал реиспользуемым в своих же интересах.
Способ прост: если нельзя скопировать без клика на флэше, значит будем кликать на флэш.
Genn помог с самой простой и гибкой реализацией этой идеи.
Мы создали флэш-кнопку в качестве параметров которой передаются:

  • clipboard — текст который нужно скопировать в буфер
  • normal — картинка для для дефолтового состояния кнопки
  • hover — картинка для mouseover состояния кнопки
  • pressed — картинка для нажатого состояния кнопки

hover и pressed можно не задавать, тогда кнопка просто не будет изменяться при клике и наведении курсора. Текст из переменной clipboard копируется в буфер при клике на кнопку.
Для примера взял две такие картинки:

картинкаЗеленая дефолтовая, синяя для нажатого состояния. Потому что зеленый круче.

И самый простой пример иллюстрирующий применение, там же и другие примеры. Фактически с помощью одного этого ролика можно сделать почти любую нужную кнопку. Для чего я, собственно, это все и затеял =)

Ссылки

Собственно пост я написал чтобы никто не пытался реализовать копирование в буфер с помощью старого джаваскрипта. И чтобы никогда больше не волноваться об этой проблеме самому. =)

Update: Как оказалось этот флэш-метод не работает на Ubuntu c Gnash/swfdec. Однако на этих эмуляторах не работают и никакие другие методы. Спасибо Владимиру за указание на проблему!

XHTML/CSS, Полезности

38 комментариев к “Копировать в буфер”

1. 16 апреля | Андрей Серебряков

Спасибо за решение. Осталось только исключить появление «Щёлкните, чтобы активировать и использовать этот элемент» ;)

2. 16 апреля | akella

Тут уж наверное ничего не поделаешь с настройками безопасности IE.
Можно через джаваскрипт обходить, но все так ненадежно… =( Остается только надеяться что пользователей ИЕ это все так задолбало что они отключили эту фичу.

3. 16 апреля | Юрко

Тупі теревені, кому воно потрібно? Хай жмакають Сtrl-c, а то всі такі ледащі, що скоро їм їсти буде лінно. Ще й той Флеш, що його треба заборонити!!! Він калічить комп’ютери, якщо ви не знали. В мого друга згорів новий Асус ноутбук через той флше!

4. 16 апреля | Вовко

Флеш ест детей!!!11адин
пыщь-пыщь

5. 16 апреля | Давид Мзареулян

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

Но вообще, проще не городить дизайн кнопки во флэше, а сделать прозрачную кнопку, которую и натягивать поверх любого нужного интерфейсного элемента (написанного уже на нормальном HTML).

6. 16 апреля | akella

Да-да, но при отображении прозрачной кнопки поверх не будет эффектов =(, а этот ролик сделан так, что и его можно отобразить прозрачно поверх чего-то, будет работать.

7. 16 апреля | DenisX

было бы круто, если бы по RSS приходили картинки :)

8. 16 апреля | Андрей Серебряков

В Опере тоже такая штука присутствует. Я попробовал внедрить пример через SWFObject, вроде работает. Сам скрипт в сжатом состоянии весит около 9 Кб, и работает достаточно надёжно.

9. 16 апреля | enternet

2 Андрей Серебряков
«Щёлкните, чтобы активировать и использовать этот элемент» на данный момент присутствует только в старых версиях IE6/IE7 без сервиспаков и в Опере. Так что проблемы в общем-то и нет никакой. Не хочет юзер обновляться - его проблемы, использует юзер Оперу - это или его проблемы или проблемы Оперы. Для нас как разработчиков этой прблемы уже и нет, по сути.

10. 16 апреля | Artem.Chertov

Круто, спасибо, Юра.

11. 16 апреля | akira

А у меня такая реализация :)
http://riamatic.com/2009/01/20/clipboard-javascript-flash/

12. 16 апреля | Genn

DenisX, зачем?

13. 18 апреля | Ivan Nemytchenko

Нет, таки можно обойтись без клика на флэше. И да, все сделано до вас: http://clck.ru/6Ic

14. 18 апреля | akella

Спасибо за ссылку! добавил ее в пост.

Нет, таки можно обойтись без клика на флэше.

Где именно? По вашей ссылке написано обратное, там просто реализовано джаваскриптом то, о чем говорил Давид в 5м комментарии.
Отличный универсальный способ для тех у кого будет много кнопок скопировать на страничке, и слишком громоздкий для тех у кого она будет одна или две.
Все равно большое спасибо! Я в своих поисках такого не нашел.

15. 18 апреля | olexiy

чтобы там не говорили в комментариях выше, Ваша реализация единственная, которая работает у меня.

16. 18 апреля | mega.genn.org » Flash 10 Antipasti и жизнь URL

[…] перестала работать. К счастью, akella придумал как с этим бороться: можно создать флеш-ролик, который будет вести себя […]

17. 20 апреля | alex

Сделал всё по вашему “рецепту” - работает, спасибо :)

18. 6 мая | u1tr0n

Спасибо огромное, но нашел один баг, если передать, к примеру, clipboard=http://site/upload/4F3KmtVdOP.jpg то кнопка перестает быть кнопкой и становится чем-то со скролингом (только в IE, В FF3 все норм) хз как с этим бороться, можно взять URL в одиночные ковычки но тогда и текст в буфере будет тоже с одиночной ковычкой, а мне это неподходит

19. 12 мая | MAN

по мне так бесполезная вообще штука, даже когда вижу на сайтах такое, по привычке копирую по старинке)

20. 14 мая | Simpledream

Не сказал бы что такая уж бесполезная, есть сервисы где така штука облегчает жизнь - промт например

21. 23 мая | NickSun

Копирует отлично, только вот прозрачность картинок не поддерживается :(
Добавте в примере в тег строчку bgcolor=”red” и все станет ясно.
Можно это как-то исправить?

22. 27 мая | shinkareff

Самый нужный вариант копирования ( а именно - код ссылки для публикации на другом сайте) не работает. Причина - повторяющиеся двойные кавычки, то о чём написал 6 мая “u1tr0n” в комменте №18. Для моего уровня подготовки задача нерешаемая. Поиск не помог.

Пример с таблицей от Ivan Nemytchenko из №13 громоздкий и очень специфичный. А ссылка на “Автоматизированный вариант с mootools” вообще не работает.

Итого: для меня задача не решена. Тем не менее, за публикацию спасибо. Если есть какой-то вариант выполнить копирование куска кода вида “гиперлинк” - подскажите, пожалуйста.

23. 10 июня | Елена

Самый нужный вариант копирования

24. 11 июня | Ваня

> Итого: для меня задача не решена. Тем не менее, за публикацию спасибо.

Объясните, что именно Вы не решили? Может, я смогу Вам помочь.

25. 15 июня | Vladimir

Ubuntu 9.04, FireFox 3.0.11, ни один из примеров не работает :-(

26. 16 июня | Vladimir

UPD: поставил плагин Adobe Flash Player, с ним работает; gnash и swfdec с буфером обмена работать не хотят.

27. 21 июня | chif

Ролик как-то неадекватно повел себя при первой загрузке, повторно уже все нормально (Firefox 3.5 rc2 / flash10). К сожалению толком не успел заметить что что-то не так, т.к. все-таки заметил ненормальное поведение и тут же обновил страницу :)

28. 21 июня | chif

Извиняюсь
*что что-то не так = что конкретно не так

29. 23 июня | GodCow

Спасибо за способ, давно искал

30. 7 июля | crazydima

Так интересно. Все общаются между собой…

31. 5 октября | ekwo

А как всем? Часто приходится использовать такие функции в проектах?

32. 24 февраля | Data:URL средствами браузера

[…] флэшки (флэшукапец, ага). Подробно об этом написано в блоге CSSing.org.ua, я же использовал слегка допиленную версию […]

33. 2 марта | guestar

Фича клевая, юзаю ее уже давно, спасибо, Akella!

Но недавно наткнулся на проблему - если в копируемом тексте есть знак процента (%) - то он, и неско следующих после него символов пытаются отобразиться как закодированный в 16ричной системе символ, и в итоге если в копируемом коде есть например

ф
то в буфере окажется

странная штука, как-то заквотить знак процента у меня не получилось. понять, собственно, из-за чего так происходит - тоже.
Может быть есть какое-нить решение?

34. 2 марта | guestar

Фича клевая, юзаю ее уже давно, спасибо, Akella!

Но недавно наткнулся на проблему - если в копируемом тексте есть знак процента (%) - то он, и неско следующих после него символов пытаются отобразиться как закодированный в 16ричной системе символ, и в итоге если в копируемом коде есть например

<div style=’width: 100%; overflow: hidden;’&ght;

то в буфере окажется

<div style=’width: 100 overflow: hidden;’&ght;

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

Может быть есть какое-нить решение?

35. 4 марта | Олег

Как-то загрузил Яндекс.Бар для теста на FF, запустил плагин Temper Data (которые позволяет контролировать HTTP запросы).
Так вот Яндекс подгружает clipboard.swf по которому я догадался, что они пытаются через Яндекс.Бар контролировать буфер обмена… без ведома юзера.

не понимаю почему из-за безопасности это отключили, ну из буфера копировать опасно, а в буфер не очень.

36. 4 марта | Олег

т.е. браузеры отключили возможность копирования.

о Я.баре написал как о “злоумышленнике” :-)

37. 8 июля | Alex

Всё вроде хорошо, но вот есть проблема!
Мне нужно чтоб кнопка скопировала [http://www.zippyshare.com/mediaplayer/mediaplayer.swf?file=http://www21.zippyshare.com/downloadMusic%3Fkey%3D29157749xx&volume=80&autostart=false&frontcolor=0×000000&backcolor=0xa63500&lightcolor=0xffffff&type=flv]

но копируется только [http://www.zippyshare.com/mediaplayer/mediaplayer.swf?file=http://www21.zippyshare.com/downloadMusic%3Fkey%3D29157749xx] - это.

Скрипт категорически отказывается копировать всё что находиться после символа &

Что делать?

38. 12 июля | akella

Попробуйте закодировать этот символ

Оставить комментарий

Комментировать

Обязательные поля