diff options
| author | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
| commit | 4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch) | |
| tree | c296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /src/copybtn.js | |
| download | relic-master.tar.gz | |
Diffstat (limited to 'src/copybtn.js')
| -rw-r--r-- | src/copybtn.js | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/copybtn.js b/src/copybtn.js new file mode 100644 index 0000000..869e318 --- /dev/null +++ b/src/copybtn.js @@ -0,0 +1,99 @@ +/* Manage "Copy Buttons" linked to target elements, to copy the text (or, parts +** thereof) of the target elements to the clipboard. +** +** Newly created buttons are <button> elements plus a nested <span> element with +** an SVG background icon, defined by the "copy-button" class in the default CSS +** style sheet, and are assigned the element ID "copy-<idTarget>". +** +** For HTML-defined buttons, either initCopyButtonById(), or initCopyButton(), +** needs to be called to attach the "onclick" handler (done automatically from +** a handler attached to the "DOMContentLoaded" event). These functions create +** the nested <span> element if the <button> element has no child nodes. Using +** static HTML for the <span> element ensures the buttons are visible if there +** are script errors, which may be useful for Fossil JS hackers (as good parts +** of the Fossil web UI come down on JS errors, anyway). +** +** The initialization functions do not overwrite the "data-copytarget" and +** "data-copylength" attributes with empty or null values for <idTarget> and +** <cchLength>, respectively. Set <cchLength> to "-1" to explicitly remove the +** previous copy length limit. +** +** HTML snippet for statically created buttons: +** +** <button +** class="copy-button" +** id="copy-<idTarget>" +** data-copytarget="<idTarget>" +** data-copylength="<cchLength>" +** data-content="<content>"> +** <span></span> +** </button> +*/ +function makeCopyButton(idTarget,bFlipped,cchLength){ + var elButton = document.createElement("button"); + elButton.className = "copy-button"; + if( bFlipped ) elButton.className += " copy-button-flipped"; + elButton.id = "copy-" + idTarget; + initCopyButton(elButton,idTarget,cchLength); + return elButton; +} +function initCopyButtonById(idButton,idTarget,cchLength){ + idButton = idButton || "copy-" + idTarget; + var elButton = document.getElementById(idButton); + if( elButton ) initCopyButton(elButton,idTarget,cchLength); + return elButton; +} +function initCopyButton(elButton,idTarget,cchLength){ + if( idTarget ) elButton.setAttribute("data-copytarget",idTarget); + if( cchLength ) elButton.setAttribute("data-copylength",cchLength); + elButton.onclick = clickCopyButton; + /* Make sure the <button> contains a single nested <span>. */ + if( elButton.childElementCount!=1 || elButton.firstChild.tagName!="SPAN" ){ + while( elButton.firstChild ) elButton.removeChild(elButton.lastChild); + elButton.appendChild(document.createElement("span")); + } + return elButton; +} +setTimeout(function(){ + var elButtons = document.getElementsByClassName("copy-button"); + for ( var i=0; i<elButtons.length; i++ ){ + initCopyButton(elButtons[i],0,0); + } +},1); +/* The onclick handler for the "Copy Button". */ +function clickCopyButton(e){ + e.preventDefault(); /* Mandatory for <a> and <button>. */ + e.stopPropagation(); + if( this.disabled ) return; /* This check is probably redundant. */ + var idTarget = this.getAttribute("data-copytarget"); + var elTarget = document.getElementById(idTarget); + if( elTarget ){ + var text = this.getAttribute("data-content"); + if( !text ){ + text = elTarget.innerText.replace(/^\s+|\s+$/g,""); + var cchLength = parseInt(this.getAttribute("data-copylength")); + if( !isNaN(cchLength) && cchLength>0 ){ + text = text.slice(0,cchLength); /* Assume single-byte chars. */ + } + } + copyTextToClipboard(text); + } +} +/* Create a temporary <textarea> element and copy the contents to clipboard. */ +function copyTextToClipboard(text){ + if( window.clipboardData && window.clipboardData.setData ){ + window.clipboardData.setData("Text",text); + }else{ + var elTextarea = document.createElement("textarea"); + elTextarea.style.position = "fixed"; + elTextarea.value = text; + document.body.appendChild(elTextarea); + elTextarea.select(); + try{ + document.execCommand("copy"); + }catch(err){ + }finally{ + document.body.removeChild(elTextarea); + } + } +} |
