[英]Javascript - Copy string to clipboard as text/html
在 javascript 中有沒有辦法將 html 字符串(即<b>xx<b>
)作為文本/html 復制到剪貼板中,以便然后可以將其粘貼到例如具有格式的 gmail 消息中(即 xx 在膽大)
存在將文本(文本/純文本)復制到剪貼板的解決方案,例如https://stackoverflow.com/a/30810322/460084但不是文本/html
我需要一個非 Flash、非 jquery 解決方案,它至少可以在 IE11 FF42 和 Chrome 上運行。
理想情況下,我想在剪貼板中存儲字符串的文本和 html 版本,以便可以根據目標是否支持 html 粘貼正確的版本。
由於這個答案引起了一些關注,我將凌亂的原文完全重寫為更容易理解。 如果您想查看預修訂版本,可以在此處找到。
歸結起來的問題:
我可以使用 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 container 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 container
// [6]
document.body.removeChild(container)
}
解釋:
查看上面代碼中的注釋,了解您當前在以下過程中的位置:
我們自己進行復制。 這實際上是一個多步驟的過程:Chrome 將復制它看到的文本並應用 CSS 樣式,而其他瀏覽器將使用瀏覽器的默認樣式復制它。 因此,我們將在復制之前禁用所有用戶樣式,以獲得盡可能一致的結果。
copy
命令。 這是 IE11 的一個 hack:在這個瀏覽器中,復制必須手動確認一次。 直到用戶單擊“確認”按鈕,IE 用戶才會看到沒有任何樣式的頁面。 為了避免這種情況,我們先復制,等待確認,然后禁用樣式並再次復制。 那時我們不會收到確認對話框,因為 IE 會記住我們的最后選擇。copy
命令。我們已經完成了。
注意事項:
格式化的內容在瀏覽器之間不會完全一致。
如上所述,Chrome(即 Blink 引擎)將使用與 Firefox 和 IE 不同的策略:Chrome 將使用其 CSS 樣式復制內容,但省略任何未定義的樣式。
另一方面,Firefox 和 IE 不會應用特定於頁面的 CSS,它們將應用瀏覽器的默認樣式。 這也意味着它們將應用一些奇怪的樣式,例如默認字體(通常是Times New Roman )。
出於安全原因,瀏覽器將只允許該功能作為用戶交互(例如點擊、按鍵等)的效果執行。
有一個更簡單的解決方案。 復制頁面(元素)的一部分而不是復制 HTML。
使用這個簡單的功能,您可以將頁面或整個文檔上的任何內容(文本、圖像、表格等)復制到剪貼板。 該函數接收元素id或元素本身。
function copyElementToClipboard(element) {
window.getSelection().removeAllRanges();
let range = document.createRange();
range.selectNode(typeof element === 'string' ? document.getElementById(element) : element);
window.getSelection().addRange(range);
document.execCommand('copy');
window.getSelection().removeAllRanges();
}
如何使用:
copyElementToClipboard(document.body);
copyElementToClipboard('myImageId');
我對上面 Loilo 的回答做了一些修改:
設置(並稍后恢復)焦點到隱藏的 div 防止 FF 在從 textarea 復制時進入無限遞歸
將范圍設置為 div 的內部子級可防止 chrome 在開頭插入額外的<br>
getSelection() 上的 removeAllRanges 防止附加到現有選擇(可能不需要)
嘗試/抓住 execCommand
更好地隱藏復制 div
在 OSX 上,這將不起作用。 Safari 不支持 execCommand 並且 chrome 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 段輸入 textarea 並使用 ctrl+c 復制到剪貼板。
如果要使用新的Clipboard API ,請使用如下所示的write
方法:
var type = "text/html";
var blob = new Blob([text], { type });
var data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(
function () {
/* success */
},
function () {
/* failure */
}
);
當前(2021 年 9 月),問題是Firefox 不支持此方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.