Fossil SCM

fossil-scm / src / copybtn.js
Blame History Raw 93 lines
1
/* Manage "Copy Buttons" linked to target elements, to copy the text (or, parts
2
** thereof) of the target elements to the clipboard.
3
**
4
** Newly created buttons are <button> elements plus a nested <span> element with
5
** an SVG background icon, defined by the "copy-button" class in the default CSS
6
** style sheet, and are assigned the element ID "copy-<idTarget>".
7
**
8
** For HTML-defined buttons, either initCopyButtonById(), or initCopyButton(),
9
** needs to be called to attach the "onclick" handler (done automatically from
10
** a handler attached to the "DOMContentLoaded" event). These functions create
11
** the nested <span> element if the <button> element has no child nodes. Using
12
** static HTML for the <span> element ensures the buttons are visible if there
13
** are script errors, which may be useful for Fossil JS hackers (as good parts
14
** of the Fossil web UI come down on JS errors, anyway).
15
**
16
** The initialization functions do not overwrite the "data-copytarget" and
17
** "data-copylength" attributes with empty or null values for <idTarget> and
18
** <cchLength>, respectively. Set <cchLength> to "-1" to explicitly remove the
19
** previous copy length limit.
20
**
21
** HTML snippet for statically created buttons:
22
**
23
** <button class="copy-button" id="copy-<idTarget>"
24
** data-copytarget="<idTarget>" data-copylength="<cchLength>">
25
** <span></span>
26
** </button>
27
*/
28
function makeCopyButton(idTarget,bFlipped,cchLength){
29
var elButton = document.createElement("button");
30
elButton.className = "copy-button";
31
if( bFlipped ) elButton.className += " copy-button-flipped";
32
elButton.id = "copy-" + idTarget;
33
initCopyButton(elButton,idTarget,cchLength);
34
return elButton;
35
}
36
function initCopyButtonById(idButton,idTarget,cchLength){
37
idButton = idButton || "copy-" + idTarget;
38
var elButton = document.getElementById(idButton);
39
if( elButton ) initCopyButton(elButton,idTarget,cchLength);
40
return elButton;
41
}
42
function initCopyButton(elButton,idTarget,cchLength){
43
if( idTarget ) elButton.setAttribute("data-copytarget",idTarget);
44
if( cchLength ) elButton.setAttribute("data-copylength",cchLength);
45
elButton.onclick = clickCopyButton;
46
/* Make sure the <button> contains a single nested <span>. */
47
if( elButton.childElementCount!=1 || elButton.firstChild.tagName!="SPAN" ){
48
while( elButton.firstChild ) elButton.removeChild(elButton.lastChild);
49
elButton.appendChild(document.createElement("span"));
50
}
51
return elButton;
52
}
53
setTimeout(function(){
54
var elButtons = document.getElementsByClassName("copy-button");
55
for ( var i=0; i<elButtons.length; i++ ){
56
initCopyButton(elButtons[i],0,0);
57
}
58
},1);
59
/* The onclick handler for the "Copy Button". */
60
function clickCopyButton(e){
61
e.preventDefault(); /* Mandatory for <a> and <button>. */
62
e.stopPropagation();
63
if( this.disabled ) return; /* This check is probably redundant. */
64
var idTarget = this.getAttribute("data-copytarget");
65
var elTarget = document.getElementById(idTarget);
66
if( elTarget ){
67
var text = elTarget.innerText.replace(/^\s+|\s+$/g,"");
68
var cchLength = parseInt(this.getAttribute("data-copylength"));
69
if( !isNaN(cchLength) && cchLength>0 ){
70
text = text.slice(0,cchLength); /* Assume single-byte chars. */
71
}
72
copyTextToClipboard(text);
73
}
74
}
75
/* Create a temporary <textarea> element and copy the contents to clipboard. */
76
function copyTextToClipboard(text){
77
if( window.clipboardData && window.clipboardData.setData ){
78
window.clipboardData.setData("Text",text);
79
}else{
80
var elTextarea = document.createElement("textarea");
81
elTextarea.style.position = "fixed";
82
elTextarea.value = text;
83
document.body.appendChild(elTextarea);
84
elTextarea.select();
85
try{
86
document.execCommand("copy");
87
}catch(err){
88
}finally{
89
document.body.removeChild(elTextarea);
90
}
91
}
92
}
93

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button