Skip to content

Instantly share code, notes, and snippets.

@swanson
Last active April 19, 2022 19:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save swanson/d4c4e9cde0ecd154711c836652b35001 to your computer and use it in GitHub Desktop.
Save swanson/d4c4e9cde0ecd154711c836652b35001 to your computer and use it in GitHub Desktop.
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["source"];
copy() {
const range = document.createRange();
window.getSelection().removeAllRanges();
this.sourceTarget.classList.remove("hidden");
range.selectNode(this.sourceTarget);
window.getSelection().addRange(range);
document.execCommand("copy");
this.sourceTarget.classList.add("hidden");
window.getSelection().removeAllRanges();
}
}
%div(data-controller="copy-html")
%button.btn-teal(data-action="copy-html#copy")
Copy
.hidden(data-copy-html-target="source")
%div(style="background: white; font-size: 11pt; font-family: Calibri; color: black;")
%br
%b(style="border: none;") Recent Changes
%br
%table(style="width: 800px")
%thead
%tr(style="font-weight: bold; color: white; background: #9F5B94; text-align: center;")
%td(style="border: 1.5pt solid black;")
Author
%td(style="border: 1.5pt solid black;")
Comments
%tbody
- @changes.each do |change|
%tr(style="background: white;")
%td(style="width: 200px; border: 1.5pt solid black; padding: 2px 10px")
= change.author.display_name
%td(style="border: 1.5pt solid black; padding: 2px 10px")
%ul
- change.comments.each do |c|
%li(style="border: none; margin: 0;")= c
%br
@KonnorRogers
Copy link

Async clipboard API alternative.

import { Controller } from "stimulus";
export default class extends Controller {  
  static targets = ["source"];

  async copy() {    
    const range = document.createRange();

    window.getSelection().removeAllRanges();

    this.sourceTarget.classList.remove("hidden");    
    range.selectNode(this.sourceTarget);    
    window.getSelection().addRange(range);

    await navigator.clipboard.writeText(range.toString()); 

    this.sourceTarget.classList.add("hidden");    
    window.getSelection().removeAllRanges();  
  }
}

@DamnedScholar
Copy link

DamnedScholar commented Jun 4, 2021

Wouldn't this code copy the outer <div data-copy-html-target="source"></div> as well? It seems like the whole virtual selection step could be skipped with a line like await navigator.clipboard.writeText(this.sourceTarget.innerHTML);, which would leave cleaner clipboard output since the root of the copied content would be the styled %div. innerHTML also works if the target is hidden, so you don't have to mess with classes at all.

@swanson
Copy link
Author

swanson commented Jun 4, 2021

Wouldn't this code copy the outer <div data-copy-html-target="source"></div> as well? It seems like the whole virtual selection step could be skipped with a line like await navigator.clipboard.writeText(this.sourceTarget.innerHTML);, which would leave cleaner clipboard output since the root of the copied content would be the styled %div. innerHTML also works if the target is hidden, so you don't have to mess with classes at all.

oh nice, I will have to explore that. definitely didn't intend for that outer div to be copied.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment