2015-12-10 5 views
14

Есть ли способ в javascript скопировать строку html (то есть <b>xx<b>) в буфер обмена как text/html, чтобы затем ее можно было вставить в, например, сообщение gmail с форматирование (т.е. хх выделены жирным шрифтом)Javascript - Скопируйте строку в буфер обмена как текст/html

Там существует решения для копирования в буфер обмена как текст (текст/обычный), например https://stackoverflow.com/a/30810322/460084, но не как текст/html

мне нужна нон вспышки, не JQuery решение который будет работать хотя бы на IE11 FF42 и Chrome.

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

+0

Возможный дубликат [javascript copy r ich текстовое содержимое в буфер обмена] (http://stackoverflow.com/questions/23934656/javascript-copy-rich-text-contents-to-clipboard) –

+0

Вы уверены, что он спрашивает, как скопировать раздел HTML как богатый текст, который, я думаю, является тем, что вы ищете. Ответы оставляют желать лучшего. –

+0

Ответ от другого вопроса, который может помочь: http://stackoverflow.com/a/31945909/3155639 –

ответ

3

Я сделал несколько изменений в ответе LoiLo в выше :

  • установки (а затем восстановление) фокус на скрытом DIV предотвращает FF происходит в бесконечную рекурсию при копировании из текстового поля

  • установки диапазона для внутренних детей DIV предотвращает хром вставив дополнительный <br> в начале

  • removeAllRanges на GetSelection() предотвращает добавления к существующему выбору (возможно, не требуется)

  • TRY/поймать вокруг ExecCommand

  • скрывает копию Див лучше

на OSX это не будет работать.Safari не поддерживает ExecCommand и хром OSX имеет известная ошибка https://bugs.chromium.org/p/chromium/issues/detail?id=552975

код:

clipboardDiv = document.createElement('div'); 
clipboardDiv.style.fontSize = '12pt'; // Prevent zooming on iOS 
// Reset box model 
clipboardDiv.style.border = '0'; 
clipboardDiv.style.padding = '0'; 
clipboardDiv.style.margin = '0'; 
// Move element out of screen 
clipboardDiv.style.position = 'fixed'; 
clipboardDiv.style['right'] = '-9999px'; 
clipboardDiv.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px'; 
// more hiding 
clipboardDiv.setAttribute('readonly', ''); 
clipboardDiv.style.opacity = 0; 
clipboardDiv.style.pointerEvents = 'none'; 
clipboardDiv.style.zIndex = -1; 
clipboardDiv.setAttribute('tabindex', '0'); // so it can be focused 
clipboardDiv.innerHTML = ''; 
document.body.appendChild(clipboardDiv); 

function copyHtmlToClipboard(html) { 
    clipboardDiv.innerHTML=html; 

    var focused=document.activeElement; 
    clipboardDiv.focus(); 

    window.getSelection().removeAllRanges(); 
    var range = document.createRange(); 
    range.setStartBefore(clipboardDiv.firstChild); 
    range.setEndAfter(clipboardDiv.lastChild); 
    window.getSelection().addRange(range); 

    var ok=false; 
    try { 
    if (document.execCommand('copy')) ok=true; else utils.log('execCommand returned false !'); 
    } catch (err) { 
    utils.log('execCommand failed ! exception '+err); 
    } 

    focused.focus(); 
} 

см jsfiddle, где вы можете ввести HTML сегмент в текстовое поле и скопировать в буфер обмена Ctrl + C.

16

Поскольку этот ответ получил некоторое внимание, я полностью переписал грязный оригинал, чтобы его было легче понять. Если вы хотите посмотреть предварительную версию, вы можете найти ее here.


Вареное вниз вопрос:

Могу ли я использовать JavaScript, чтобы скопировать форматированный вывод некоторых HTML-код в буфер обмена пользователей?


Ответ:

Да, с некоторыми ограничениями, вы можете.


Решение:

Ниже функция, которая будет делать именно это. Я тестировал его с помощью необходимых браузеров, он работает во всех них. IE 11 будет запрашивать подтверждение этого действия.

Объяснение, как это работает, можно найти ниже, вы можете в интерактивном режиме проверить функцию в этом jsFiddle.

// This function expects an HTML string and copies it as rich text. 

function copyFormatted (html) { 
    // Create container for the HTML 
    // [1] 
    var container = document.createElement('div') 
    container.innerHTML = html 

    // Hide element 
    // [2] 
    container.style.position = 'fixed' 
    container.style.pointerEvents = 'none' 
    container.style.opacity = 0 

    // Detect all style sheets of the page 
    var activeSheets = Array.prototype.slice.call(document.styleSheets) 
    .filter(function (sheet) { 
     return !sheet.disabled 
    }) 

    // Mount the iframe to the DOM to make `contentWindow` available 
    // [3] 
    document.body.appendChild(container) 

    // Copy to clipboard 
    // [4] 
    window.getSelection().removeAllRanges() 

    var range = document.createRange() 
    range.selectNode(container) 
    window.getSelection().addRange(range) 

    // [5.1] 
    document.execCommand('copy') 

    // [5.2] 
    for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = true 

    // [5.3] 
    document.execCommand('copy') 

    // [5.4] 
    for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = false 

    // Remove the iframe 
    // [6] 
    document.body.removeChild(container) 
} 

Объяснение:

Посмотрите на комментарии в коде выше, чтобы увидеть, где вы в настоящее время находятся в следующем процессе:

  1. Мы создаем контейнер поставить наш HTML-код в.
  2. Мы создаем контейнер для скрытия и обнаруживаем активные таблицы стилей страницы. Причина будет объяснена в ближайшее время.
  3. Мы помещаем контейнер в DOM страницы.
  4. Мы удаляем, возможно, существующие выборы и выбираем содержимое нашего контейнера.
  5. Мы делаем само копирование.На самом деле это многоступенчатый процесс: Chrome будет копировать текст, когда он его видит, с применением стилей CSS, в то время как другие браузеры будут копировать его со стилями по умолчанию в браузере. Поэтому мы будем отключать все пользовательские стили перед копированием, чтобы получить максимально согласованный результат.

    1. Прежде чем мы это сделаем, мы преждевременно выполним команду copy. Это взломать IE11: в этом браузере копирование должно быть подтверждено вручную один раз. Пока пользователь не нажмет кнопку «Подтвердить», пользователи IE будут видеть страницу без каких-либо стилей. Чтобы этого избежать, мы сначала копируем, дождитесь подтверждения, затем отключим стили и снова скопируем. В тот раз мы не получим диалог подтверждения, так как IE помнит наш последний выбор.
    2. Мы фактически отключили стили страницы.
    3. Теперь мы снова выполним команду copy.
    4. Мы снова включаем таблицы стилей.
  6. Мы удаляем контейнер из DOM страницы.

И все готово.


Предостережения:

  • Отформатированная содержание не будет полностью соответствовать во всех браузерах.

    Как объяснялось выше, Chrome (т. Е. Движок Blink) будет использовать другую стратегию, чем Firefox и IE: Chrome скопирует содержимое с помощью стилей CSS, но не укажет никаких стилей, которые не определены.

    С другой стороны, Firefox и IE не будут применять CSS для конкретных страниц, они будут применять стили по умолчанию для браузера. Это также означает, что у них будут какие-то странные стили, применяемые к ним, например. шрифт по умолчанию (обычно это Times New Roman).

  • По соображениям безопасности, браузеры позволяют только функции для выполнения как эффект взаимодействия с пользователем (например, щелчок, нажатие клавиши и т.д.)

+0

это выглядит фантастически Loilo! если вы можете использовать это в функции, которая принимает строку html (т.е. «xx bold yy») и помещает ее в буфер обмена как богатый текст, я помечаю его как ответ. Благодаря ! – kofifus

+0

thx! обозначил это как ответ. Как вы думаете, есть ли способ добавить как текст, так и html в буфер обмена одновременно, чтобы правильная версия была заблокирована в зависимости от цели (т.е. вставка в блокнот и вставка в gmail)? – kofifus

+1

Вы можете копировать только одну вещь в буфер обмена, всегда. Блокнот просто удаляет стилизованные части. Это будет происходить с вашим скопированным HTML точно так же (попробуйте вставить скопированный материал из JSFiddle в блокнот). – Loilo

1

Прошло почти два года, и в настоящее время существует более простой способ достичь этого, используя clipboard.js.

Для этого требуется современный браузер (Chrome 42+, Firefox 41+, Opera 29+, Internet Explorer 9+, Safari 10+), но он скрывает сложность вставки текста с расширенным текстом (меньше кода для записи) :

1) Ссылка clipboard.js

2) Создать кнопку и на его обработчик щелчка, построить как неотформатированный и отформатированный (богатые) текст и использовать в библиотеку, чтобы скопировать в буфер обмена:

clipboard.copy({ 
    "text/plain": "Normal text comes here", 
    "text/html": "<b>Normal text</b> comes <div style="color: blue;">here</div>" 
}) 
.then(
    function() { 
    // success code here 
    }, 
    function(err) { 
    // failure code here 
    } 
); 
Смежные вопросы