javascript вырезать / скопировать / вставить в буфер обмена: как Google решил это? - PullRequest
22 голосов
/ 11 марта 2012

Да, этот вопрос задавался снова и снова: как копировать и вставлять из и в системный буфер обмена с помощью javascript?Пока я нашел только частичные решения и взломы.Причина, по которой его так часто спрашивали в прошлом, заключается в том, что до сих пор нет рабочего решения.Тем не менее, я увидел, что Google Docs теперь имеет работающее решение как для событий клавиатуры, так и для кнопок.Итак, это возможно, но как они это делают?Статья Software Salad, Доступ к системному буферу обмена с помощью JavaScript - Святой Грааль? , дает хороший обзор проблемы (но ей уже несколько лет).

Вкратце:

  • Вы можете использовать события клавиатуры ctrl + x, ctrl + c, ctrl + v, чтобы либо скопировать текст из скрытой текстовой области с подготовленными данными, либо перехватить вставленный текст в скрытомполе и затем что-то сделать с ним

  • вы можете использовать некоторые взломать через Flash или, возможно, Java-апплет, чтобы скопировать что-то в системный буфер обмена без необходимости одобрения пользователя.

  • вы можете использовать «реальное» решение с clipboardData.setData для IE и execCommand для других браузеров, что зависит от одобрения пользователя.

Любая идея, как Googleрешил проблему с буфером обмена?

Ответы [ 5 ]

25 голосов
/ 03 апреля 2014

Я знаю, что этот вопрос был опубликован давно, но мне нужно было проверить, как это делает Google, так что, возможно, кто-то найдет это полезным.

На самом деле Google использует также системный буфер обмена, но это немного сложно.В случае, когда вы используете сочетание клавиш, вы можете перехватить событие копирования / вставки / вырезания, например, в окне:

window.addEventListener('copy', function (ev) {
    console.log('copy event');
    // you can set clipboard data here, e.g.
    ev.clipboardData.setData('text/plain', 'some text pushed to clipboard');
    // you need to prevent default behaviour here, otherwise browser will overwrite your content with currently selected 
    ev.preventDefault();
});

живой пример сочетания клавиш: http://jsfiddle.net/tyk9U/

К сожалению, это единственное решение дляСочетание клавиш и проблема с контекстным меню, потому что вы не можете получить доступ к данным буфера обмена без собственного (доверенного) события копирования / вырезания / вставки.Но Google делает интересный трюк.Существует API document.execCommand(), который позволяет вам запускать команды для contenteditable элемента, и есть команда 'copy', которую вы можете вызвать с помощью document.execCommand('copy').Но когда вы попробуете это в консоли в Chrome, он вернет false.Я потратил немного времени на изучение этого, и оказалось, что у них установлено расширение Chrome, которое называется «Диск Google» (перейдите к chrome: // apps /, и вы можете увидеть его там), которое обеспечивает доступ к буферу обмена для доменов drive.google.com и docs.google.com.Откройте какой-нибудь документ или электронную таблицу и введите в консоли document.execCommand('copy') - он вернет true.При удалении расширения вы не сможете использовать операции с буфером обмена из контекстного меню.

Вы можете создать такое приложение для себя с очень простым файлом манифеста (подробности здесь https://developer.chrome.com/apps/first_app):

{
    "manifest_version": 2,
    "name": "App name",
    "description": "App description",
    "version": "1.0",
    "app": {
        "urls": [
            "http://your.app.url.here/"
        ],
        "launch": {
            "web_url": "http://your.app.url.here/"
        }
    },
    "icons": {
        "128": "x-128.png"
    },
    "permissions": [
        "clipboardRead",
        "clipboardWrite"
    ]
}

Поле «Полномочия» здесь разрешает операции с буфером обмена.

Теперь, когда вы включили эту функцию, вы можете сделать document.execCommand('copy'), и она будет работать (вернет true). Но это еще не все - document.execCommand('copy')в chrome запускает событие копирования, и вы можете поймать его с тем же кодом, который используется для перехвата ярлыков буфера обмена клавиатуры. Теперь это делает Google.

Конечно, это описание действительно только для Chrome.

10 голосов
/ 11 марта 2012

[ Примечание: Этот ответ был точным на момент написания и правильно ответил на вопрос ОП. Тем не менее, технологии развивались с тех пор; если вы заинтересованы в поддержке копирования и вставки в своем веб-приложении, см. другие, более свежие ответы на этой странице. & Mdash; ruakh]


Тем не менее, я увидел, что Google Docs теперь имеет работающее решение как для событий клавиатуры, так и для кнопок.

Нет, это не так. На самом деле, нет. Для событий клавиатуры Google Docs ничего не делает; он просто не блокирует функцию копирования и вставки браузера по умолчанию; Таким образом, пользователи могут свободно копировать и вставлять документы, не мешая Google Docs. Что касается кнопок, Google Docs не поддерживает буфер обмена system , но имеет собственный «веб-буфер обмена», который полностью находится в Google Docs. Вы не можете использовать кнопки панели инструментов, чтобы скопировать текст для вставки в другую программу на вашем компьютере или вставить текст, скопированный из другой программы на вашем компьютере.

Подробнее об этом см. «Копирование и вставка в Документах Google» . (Это ориентировано на пользователя, а не на разработчика, но оно делает достойную работу, давая понять, что поддерживается и не поддерживается.)

4 голосов
/ 25 июня 2014

В дополнение к тому, что другие уже опубликовали в этой теме, я создал полностью рабочий пример, который демонстрирует подход сочетания клавиш (CTRL + C или CMD + C в Mac OS X), а также подход настраиваемой кнопки, который запускаеткопировать действие

Полная демонстрация может быть найдена здесь: http://jsfiddle.net/rve7d/

Я нашел ответ Mateusz W очень полезным при попытке создать эту демонстрацию, но он не принял во внимание поддержку IE, которая ведет себя немного иначеи использует различные типы данных в качестве первого параметра.

if(window.clipboardData) {
    // use just 'Text' or 'Url' as a first param otherwise strange exception is thrown
    window.clipboardData.setData('Text', 'Text that will be copied to CB');        
} else if(ev.originalEvent.clipboardData) {
    ev.originalEvent.clipboardData.setData('text/plain', 'Text that will be copied to CB');      
} else {
    alert('Clipboard Data are not supported in this browser. Sorry.');
}

PS: мне понадобилась эта функциональность для нашего пользовательского компонента просмотра электронных таблиц, и я проанализировал исходный код электронных таблиц Google, поэтому мое решение в основном соответствует их решению..

3 голосов
/ 13 апреля 2013

Google использует очень простой, но классный метод. Используя firebug, вы узнаете, что загруженный html-код имеет текстовую область в начале размера 1. Что делает документ Google, так это то, что когда пользователь выбирает текст и нажимает Ctrl + C, он захватывает событие и некоторым способом получает текст, который выбирается в контейнере документов и устанавливает значение текстовой области для этого содержимого. Чем он фокусируется и выделяет текстовую область. Теперь он выпускает событие ctrl + c. Но теперь текст выделен в текстовой области, поэтому при повторном выпуске события браузер копирует текст в текстовой области, и таким образом мы получаем скопированный текст

0 голосов
/ 30 мая 2016
<p>COPY : </p>
<p>Email me at <a class="js-emaillink" href="mailto:matt@example.co.uk">matt@example.co.uk</a></p>
<p><button class="js-emailcopybtn" value="clipboard" >clipboard</button></p>
<textarea rows="10" cols = "12"></textarea>
<p>CUT: </p>
<p><textarea class="js-cuttextarea">Hello I'm some text</textarea></p>
<p><button class="js-textareacutbtn" disable>Cut Textarea</button></p>
<script>
//copy clipboard
var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
  // Выборка ссылки с электронной почтой
  var emailLink = document.querySelector('.js-emaillink');
  var range = document.createRange();
  range.selectNode(emailLink);
  window.getSelection().addRange(range);
  try {
    // Теперь, когда мы выбрали текст ссылки, выполним команду копирования
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copy email command was ' + msg);
  } catch(err) {
    console.log('Oops, unable to copy');
  }
  // Снятие выделения - ВНИМАНИЕ: вы должны использовать
  // removeRange(range) когда это возможно
  window.getSelection().removeAllRanges();
});
//cut
var cutTextareaBtn = document.querySelector('.js-textareacutbtn');
cutTextareaBtn.addEventListener('click', function(event) {
  var cutTextarea = document.querySelector('.js-cuttextarea');
  cutTextarea.select();
  try {
    var successful = document.execCommand('cut');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Cutting text command was ' + msg);
  } catch(err) {
    console.log('Oops, unable to cut');
  }
});
</script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...