简体   繁体   English

使用来自 css-classes 的样式将富文本复制到剪贴板

[英]Copy rich text to clipboard with styles from css-classes

I've used this method to copy rich text from an html element.我已经使用这种方法从 html 元素复制富文本。 The problem is that if styles are not inlined in the html, but come from css, this method doesn't work.问题是,如果样式不是内联在 html 中,而是来自 css,则此方法不起作用。 The existing code breaks the formatting and doesn't take the styles into account.现有代码破坏了格式并且没有考虑样式。 Here's the code.这是代码。

HTML HTML

<button onclick="copyToClip(document.getElementById('foo').innerHTML)">
  Copy the stuff
  </button>

<div id=foo>
  You can write some JS to generate this data. 
  It can contain rich stuff.
  <b> test </b> me <i> also </i>
  <div class="green">Hello world</div> You can use setData to put TWO COPIES into the same clipboard, one that is plain and one that is rich. That way your users can paste into either a
  <ul>
    <li>plain text editor</li>
    <li>or into a rich text editor</li>
  </ul>
</div>

CSS CSS

.green {
  display: inline;
  color: green;
}

JavaScript JavaScript

function copyToClip(str) {
  function listener(e) {
    e.clipboardData.setData("text/html", str);
    e.clipboardData.setData("text/plain", str);
    e.preventDefault();
  }
  document.addEventListener("copy", listener);
  document.execCommand("copy");
  document.removeEventListener("copy", listener);
};

The example in Codepen . Codepen 中的示例。

The line break added to copied text happen because the " block level elements " even if you add "display : inline" in css sheet添加到复制文本的换行符是因为“块级元素”,即使您在 css 表中添加"display : inline"

See W3 HTML Block and Inline Elements请参阅W3 HTML 块和内联元素

To avoid this we need to change any block level elements that has display inline and restore all style include default style to new tag为了避免这种情况,我们需要更改任何具有内联显示的块级元素并将所有样式包括默认样式恢复为新标签

Finally the code will be like :最后的代码将是这样的:

Codepen代码笔

Note : explanation in code comment注意:代码注释中的解释

 function CopyToClipboard(element) { // array off all block level elements var block_level_elements = ['P','H1', 'H2', 'H3', 'H4', 'H5', 'H6','OL', 'UL','DIV','FORM','HR','TABLE']; //create new Element so we can change elments like we need var newelment = document.createElement("div"); //copy target Element to the new Element newelment.innerHTML = document.getElementById(element).innerHTML; //hide new Element to body newelment.style.opacity = 0; // add new Element to body document.body.appendChild(newelment); //get all element childs var descendents = newelment.getElementsByTagName('*'); //loop in childs for (var i = 0; i < descendents.length; ++i) { //get defult Style var style = window.getComputedStyle(descendents[i]); var dis = style.getPropertyValue('display'); //get defult tag name var tagname = descendents[i].tagName; //--------------------------- //this part is little tricky //--------------------------- //true : Element is a block level elements and css display is inline if(dis.includes("inline") && block_level_elements.includes(tagname)){ //get all Element style include default style var defultcss = document.defaultView.getComputedStyle(descendents[i], "").cssText; //chang Element tag from block level elements to inline level elements (span) descendents[i].outerHTML = descendents[i].outerHTML.replace(new RegExp(tagname, "ig"),"span"); //todo: need to change RegExp to tag name only not inner text //add all Element style include default style to new tag descendents[i].style.cssText = defultcss; } } //-----------------copy new Element-------------- var doc = document; var range, selection; if (doc.body.createTextRange) { range = doc.body.createTextRange(); range.moveToElementText(newelment); range.select(); } else if (window.getSelection) { selection = window.getSelection(); range = doc.createRange(); range.selectNodeContents(newelment); selection.removeAllRanges(); selection.addRange(range); } document.execCommand('copy'); window.getSelection().removeAllRanges(); // remove new Element from document document.body.removeChild(newelment); document.getElementById("copybtn").innerHTML="Copied"; }
 .green { display: inline; color: green; white-space: nowrap; }
 <button id='copybtn' onclick="CopyToClipboard('foo')"> Copy the stuff </button> <div id='foo'> You can write some JS to generate this data. It can contain rich stuff. <b> test </b> me <i> also </i> <div class="green" style="color: green;">Hello world</div> , <h3 class="green" style="color: green;">header3</h3> You can use setData to put TWO COPIES into the same clipboard, one that is plain and one that is rich. That way your users can paste into either a <ul> <li>plain text editor</li> <li>or into a rich text editor</li> </ul> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM