Fossil SCM

Add a TH1 command to output text with a copy button, and modify the default View Ticket Page template to include a copy button for the ticket hash (UUID).

florian 2019-06-02 11:30 copybtn.js-demonstration
Commit 68405c3f5b2d1dbaba859590e1d9694f4fc29218f488a4ef20f43906acf976f3
3 files changed +61 -1 +4 -4 +22 -1
+61 -1
--- src/th_main.c
+++ src/th_main.c
@@ -267,11 +267,11 @@
267267
static int enableOutput = 1;
268268
269269
/*
270270
** TH1 command: enable_output BOOLEAN
271271
**
272
-** Enable or disable the puts and wiki commands.
272
+** Enable or disable the puts, wiki, combobox and copybtn commands.
273273
*/
274274
static int enableOutputCmd(
275275
Th_Interp *interp,
276276
void *p,
277277
int argc,
@@ -990,10 +990,69 @@
990990
sendText("</select>", -1, 0);
991991
Th_Free(interp, azElem);
992992
}
993993
return TH_OK;
994994
}
995
+
996
+/*
997
+** TH1 command: copybtn TARGETID TEXT ?COPYLENGTH?
998
+**
999
+** Output TEXT with a click-to-copy button next to it. Loads the copybtn.js
1000
+** Javascript module, and generates HTML elements with the following IDs:
1001
+**
1002
+** TARGETID: The <span> wrapper around TEXT.
1003
+** copy-TARGETID: The <span> for the copy button.
1004
+**
1005
+** The optional COPYLENGTH argument defines the length of the substring of TEXT
1006
+** copied to clipboard:
1007
+**
1008
+** <= 0: No limit (default if the argument is omitted).
1009
+** >= 3: Truncate TEXT after COPYLENGTH (single-byte) characters.
1010
+** 1: Use the "hash-digits" setting as the limit.
1011
+** 2: Use the length appropriate for URLs as the limit (defined at
1012
+** compile-time by FOSSIL_HASH_DIGITS_URL, defaults to 16).
1013
+*/
1014
+static int copybtnCmd(
1015
+ Th_Interp *interp,
1016
+ void *p,
1017
+ int argc,
1018
+ const char **argv,
1019
+ int *argl
1020
+){
1021
+ if( argc!=3 && argc!=4 ){
1022
+ return Th_WrongNumArgs(interp, "copybtn TARGETID TEXT COPYLENGTH");
1023
+ }
1024
+ if( enableOutput ){
1025
+ int copylength = 0;
1026
+ char *zTargetId, *zText, *zResult;
1027
+ if( argc==4 && Th_ToInt(interp, argv[3], argl[3], &copylength) ){
1028
+ return TH_ERROR;
1029
+ }
1030
+ if( copylength==1 ) copylength = hash_digits(0);
1031
+ else if( copylength==2 ) copylength = hash_digits(1);
1032
+ zTargetId = htmlize((char*)argv[1], argl[1]);
1033
+ zText = htmlize((char*)argv[2], argl[2]);
1034
+ zResult = mprintf(
1035
+ "<span "
1036
+ "class=\"copy-button\" "
1037
+ "id=\"copy-%s\" "
1038
+ "data-copytarget=\"%s\" "
1039
+ "data-copylength=\"%d\">"
1040
+ "</span>"
1041
+ "&nbsp;"
1042
+ "<span id=\"%s\">"
1043
+ "%s"
1044
+ "</span>",
1045
+ zTargetId, zTargetId, copylength, zTargetId, zText);
1046
+ free(zTargetId);
1047
+ free(zText);
1048
+ style_copy_button();
1049
+ sendText(zResult, -1, 0);
1050
+ free(zResult);
1051
+ }
1052
+ return TH_OK;
1053
+}
9951054
9961055
/*
9971056
** TH1 command: linecount STRING MAX MIN
9981057
**
9991058
** Return one more than the number of \n characters in STRING. But
@@ -2024,10 +2083,11 @@
20242083
{"anycap", anycapCmd, 0},
20252084
{"artifact", artifactCmd, 0},
20262085
{"cgiHeaderLine", cgiHeaderLineCmd, 0},
20272086
{"checkout", checkoutCmd, 0},
20282087
{"combobox", comboboxCmd, 0},
2088
+ {"copybtn", copybtnCmd, 0},
20292089
{"date", dateCmd, 0},
20302090
{"decorate", wikiCmd, (void*)&aFlags[2]},
20312091
{"dir", dirCmd, 0},
20322092
{"enable_output", enableOutputCmd, 0},
20332093
{"encode64", encode64Cmd, 0},
20342094
--- src/th_main.c
+++ src/th_main.c
@@ -267,11 +267,11 @@
267 static int enableOutput = 1;
268
269 /*
270 ** TH1 command: enable_output BOOLEAN
271 **
272 ** Enable or disable the puts and wiki commands.
273 */
274 static int enableOutputCmd(
275 Th_Interp *interp,
276 void *p,
277 int argc,
@@ -990,10 +990,69 @@
990 sendText("</select>", -1, 0);
991 Th_Free(interp, azElem);
992 }
993 return TH_OK;
994 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
995
996 /*
997 ** TH1 command: linecount STRING MAX MIN
998 **
999 ** Return one more than the number of \n characters in STRING. But
@@ -2024,10 +2083,11 @@
2024 {"anycap", anycapCmd, 0},
2025 {"artifact", artifactCmd, 0},
2026 {"cgiHeaderLine", cgiHeaderLineCmd, 0},
2027 {"checkout", checkoutCmd, 0},
2028 {"combobox", comboboxCmd, 0},
 
2029 {"date", dateCmd, 0},
2030 {"decorate", wikiCmd, (void*)&aFlags[2]},
2031 {"dir", dirCmd, 0},
2032 {"enable_output", enableOutputCmd, 0},
2033 {"encode64", encode64Cmd, 0},
2034
--- src/th_main.c
+++ src/th_main.c
@@ -267,11 +267,11 @@
267 static int enableOutput = 1;
268
269 /*
270 ** TH1 command: enable_output BOOLEAN
271 **
272 ** Enable or disable the puts, wiki, combobox and copybtn commands.
273 */
274 static int enableOutputCmd(
275 Th_Interp *interp,
276 void *p,
277 int argc,
@@ -990,10 +990,69 @@
990 sendText("</select>", -1, 0);
991 Th_Free(interp, azElem);
992 }
993 return TH_OK;
994 }
995
996 /*
997 ** TH1 command: copybtn TARGETID TEXT ?COPYLENGTH?
998 **
999 ** Output TEXT with a click-to-copy button next to it. Loads the copybtn.js
1000 ** Javascript module, and generates HTML elements with the following IDs:
1001 **
1002 ** TARGETID: The <span> wrapper around TEXT.
1003 ** copy-TARGETID: The <span> for the copy button.
1004 **
1005 ** The optional COPYLENGTH argument defines the length of the substring of TEXT
1006 ** copied to clipboard:
1007 **
1008 ** <= 0: No limit (default if the argument is omitted).
1009 ** >= 3: Truncate TEXT after COPYLENGTH (single-byte) characters.
1010 ** 1: Use the "hash-digits" setting as the limit.
1011 ** 2: Use the length appropriate for URLs as the limit (defined at
1012 ** compile-time by FOSSIL_HASH_DIGITS_URL, defaults to 16).
1013 */
1014 static int copybtnCmd(
1015 Th_Interp *interp,
1016 void *p,
1017 int argc,
1018 const char **argv,
1019 int *argl
1020 ){
1021 if( argc!=3 && argc!=4 ){
1022 return Th_WrongNumArgs(interp, "copybtn TARGETID TEXT COPYLENGTH");
1023 }
1024 if( enableOutput ){
1025 int copylength = 0;
1026 char *zTargetId, *zText, *zResult;
1027 if( argc==4 && Th_ToInt(interp, argv[3], argl[3], &copylength) ){
1028 return TH_ERROR;
1029 }
1030 if( copylength==1 ) copylength = hash_digits(0);
1031 else if( copylength==2 ) copylength = hash_digits(1);
1032 zTargetId = htmlize((char*)argv[1], argl[1]);
1033 zText = htmlize((char*)argv[2], argl[2]);
1034 zResult = mprintf(
1035 "<span "
1036 "class=\"copy-button\" "
1037 "id=\"copy-%s\" "
1038 "data-copytarget=\"%s\" "
1039 "data-copylength=\"%d\">"
1040 "</span>"
1041 "&nbsp;"
1042 "<span id=\"%s\">"
1043 "%s"
1044 "</span>",
1045 zTargetId, zTargetId, copylength, zTargetId, zText);
1046 free(zTargetId);
1047 free(zText);
1048 style_copy_button();
1049 sendText(zResult, -1, 0);
1050 free(zResult);
1051 }
1052 return TH_OK;
1053 }
1054
1055 /*
1056 ** TH1 command: linecount STRING MAX MIN
1057 **
1058 ** Return one more than the number of \n characters in STRING. But
@@ -2024,10 +2083,11 @@
2083 {"anycap", anycapCmd, 0},
2084 {"artifact", artifactCmd, 0},
2085 {"cgiHeaderLine", cgiHeaderLineCmd, 0},
2086 {"checkout", checkoutCmd, 0},
2087 {"combobox", comboboxCmd, 0},
2088 {"copybtn", copybtnCmd, 0},
2089 {"date", dateCmd, 0},
2090 {"decorate", wikiCmd, (void*)&aFlags[2]},
2091 {"dir", dirCmd, 0},
2092 {"enable_output", enableOutputCmd, 0},
2093 {"encode64", encode64Cmd, 0},
2094
+4 -4
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -446,16 +446,16 @@
446446
static const char zDefaultView[] =
447447
@ <table cellpadding="5">
448448
@ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
449449
@ <th1>
450450
@ if {[info exists tkt_uuid]} {
451
+@ html "<td class='tktDspValue' colspan='3'>"
452
+@ copybtn tkt_uuid $tkt_uuid 1
451453
@ if {[hascap s]} {
452
-@ html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
453
-@ html "($tkt_id)</td></tr>\n"
454
-@ } else {
455
-@ html "<td class='tktDspValue' colspan='3'>$tkt_uuid</td></tr>\n"
454
+@ html " ($tkt_id)"
456455
@ }
456
+@ html "</td></tr>\n"
457457
@ } else {
458458
@ if {[hascap s]} {
459459
@ html "<td class='tktDspValue' colspan='3'>Deleted "
460460
@ html "(0)</td></tr>\n"
461461
@ } else {
462462
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -446,16 +446,16 @@
446 static const char zDefaultView[] =
447 @ <table cellpadding="5">
448 @ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
449 @ <th1>
450 @ if {[info exists tkt_uuid]} {
 
 
451 @ if {[hascap s]} {
452 @ html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
453 @ html "($tkt_id)</td></tr>\n"
454 @ } else {
455 @ html "<td class='tktDspValue' colspan='3'>$tkt_uuid</td></tr>\n"
456 @ }
 
457 @ } else {
458 @ if {[hascap s]} {
459 @ html "<td class='tktDspValue' colspan='3'>Deleted "
460 @ html "(0)</td></tr>\n"
461 @ } else {
462
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -446,16 +446,16 @@
446 static const char zDefaultView[] =
447 @ <table cellpadding="5">
448 @ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
449 @ <th1>
450 @ if {[info exists tkt_uuid]} {
451 @ html "<td class='tktDspValue' colspan='3'>"
452 @ copybtn tkt_uuid $tkt_uuid 1
453 @ if {[hascap s]} {
454 @ html " ($tkt_id)"
 
 
 
455 @ }
456 @ html "</td></tr>\n"
457 @ } else {
458 @ if {[hascap s]} {
459 @ html "<td class='tktDspValue' colspan='3'>Deleted "
460 @ html "(0)</td></tr>\n"
461 @ } else {
462
+22 -1
--- www/th1.md
+++ www/th1.md
@@ -170,10 +170,11 @@
170170
* anycap
171171
* artifact
172172
* cgiHeaderLine
173173
* checkout
174174
* combobox
175
+ * copybtn
175176
* date
176177
* decorate
177178
* dir
178179
* enable\_output
179180
* encode64
@@ -277,10 +278,30 @@
277278
CGI parameter and the name of a variable that contains the currently
278279
selected value. TEXT-LIST is a list of possible values for the
279280
combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater
280281
than one then the display is a listbox with the number of lines given.
281282
283
+<a name="copybtn"></a>TH1 copybtn Command
284
+-----------------------------------------
285
+
286
+ * copybtn TARGETID TEXT ?COPYLENGTH?
287
+
288
+Output TEXT with a click-to-copy button next to it. Loads the copybtn.js
289
+Javascript module, and generates HTML elements with the following IDs:
290
+
291
+ * TARGETID: The `<span>` wrapper around TEXT.
292
+ * copy-TARGETID: The `<span>` for the copy button.
293
+
294
+The optional COPYLENGTH argument defines the length of the substring of TEXT
295
+copied to clipboard:
296
+
297
+ * <= 0: No limit (default if the argument is omitted).
298
+ * >= 3: Truncate TEXT after COPYLENGTH (single-byte) characters.
299
+ * 1: Use the "hash-digits" setting as the limit.
300
+ * 2: Use the length appropriate for URLs as the limit (defined at
301
+ compile-time by `FOSSIL_HASH_DIGITS_URL`, defaults to 16).
302
+
282303
<a name="date"></a>TH1 date Command
283304
-----------------------------------
284305
285306
* date ?-local?
286307
@@ -310,11 +331,11 @@
310331
<a name="enable_output"></a>TH1 enable\_output Command
311332
------------------------------------------------------
312333
313334
* enable\_output BOOLEAN
314335
315
-Enable or disable sending output when the combobox, puts, or wiki
336
+Enable or disable sending output when the combobox, copybtn, puts, or wiki
316337
commands are used.
317338
318339
<a name="encode64"></a>TH1 encode64 Command
319340
-------------------------------------------
320341
321342
--- www/th1.md
+++ www/th1.md
@@ -170,10 +170,11 @@
170 * anycap
171 * artifact
172 * cgiHeaderLine
173 * checkout
174 * combobox
 
175 * date
176 * decorate
177 * dir
178 * enable\_output
179 * encode64
@@ -277,10 +278,30 @@
277 CGI parameter and the name of a variable that contains the currently
278 selected value. TEXT-LIST is a list of possible values for the
279 combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater
280 than one then the display is a listbox with the number of lines given.
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282 <a name="date"></a>TH1 date Command
283 -----------------------------------
284
285 * date ?-local?
286
@@ -310,11 +331,11 @@
310 <a name="enable_output"></a>TH1 enable\_output Command
311 ------------------------------------------------------
312
313 * enable\_output BOOLEAN
314
315 Enable or disable sending output when the combobox, puts, or wiki
316 commands are used.
317
318 <a name="encode64"></a>TH1 encode64 Command
319 -------------------------------------------
320
321
--- www/th1.md
+++ www/th1.md
@@ -170,10 +170,11 @@
170 * anycap
171 * artifact
172 * cgiHeaderLine
173 * checkout
174 * combobox
175 * copybtn
176 * date
177 * decorate
178 * dir
179 * enable\_output
180 * encode64
@@ -277,10 +278,30 @@
278 CGI parameter and the name of a variable that contains the currently
279 selected value. TEXT-LIST is a list of possible values for the
280 combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater
281 than one then the display is a listbox with the number of lines given.
282
283 <a name="copybtn"></a>TH1 copybtn Command
284 -----------------------------------------
285
286 * copybtn TARGETID TEXT ?COPYLENGTH?
287
288 Output TEXT with a click-to-copy button next to it. Loads the copybtn.js
289 Javascript module, and generates HTML elements with the following IDs:
290
291 * TARGETID: The `<span>` wrapper around TEXT.
292 * copy-TARGETID: The `<span>` for the copy button.
293
294 The optional COPYLENGTH argument defines the length of the substring of TEXT
295 copied to clipboard:
296
297 * <= 0: No limit (default if the argument is omitted).
298 * >= 3: Truncate TEXT after COPYLENGTH (single-byte) characters.
299 * 1: Use the "hash-digits" setting as the limit.
300 * 2: Use the length appropriate for URLs as the limit (defined at
301 compile-time by `FOSSIL_HASH_DIGITS_URL`, defaults to 16).
302
303 <a name="date"></a>TH1 date Command
304 -----------------------------------
305
306 * date ?-local?
307
@@ -310,11 +331,11 @@
331 <a name="enable_output"></a>TH1 enable\_output Command
332 ------------------------------------------------------
333
334 * enable\_output BOOLEAN
335
336 Enable or disable sending output when the combobox, copybtn, puts, or wiki
337 commands are used.
338
339 <a name="encode64"></a>TH1 encode64 Command
340 -------------------------------------------
341
342

Keyboard Shortcuts

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