Fossil SCM
Minor improvements to the copy-button logic.
Commit
759fbda4e8963d89d157ef45b7329f33fb1c5ec633130ffcd6442d8ecf8f72d6
Parent
647424d463c9186…
7 files changed
+1
+3
+12
-19
+85
-1
+4
-33
+1
-1
+1
-1
+1
| --- src/copybtn.js | ||
| +++ src/copybtn.js | ||
| @@ -30,10 +30,11 @@ | ||
| 30 | 30 | elButton.id = "copy-" + idTarget; |
| 31 | 31 | initCopyButton(elButton,idTarget,cchLength); |
| 32 | 32 | return elButton; |
| 33 | 33 | } |
| 34 | 34 | function initCopyButtonById(idButton,idTarget,cchLength){ |
| 35 | + idButton = idButton || "copy-" + idTarget; | |
| 35 | 36 | var elButton = document.getElementById(idButton); |
| 36 | 37 | if( elButton ) initCopyButton(elButton,idTarget,cchLength); |
| 37 | 38 | return elButton; |
| 38 | 39 | } |
| 39 | 40 | function initCopyButton(elButton,idTarget,cchLength){ |
| 40 | 41 |
| --- src/copybtn.js | |
| +++ src/copybtn.js | |
| @@ -30,10 +30,11 @@ | |
| 30 | elButton.id = "copy-" + idTarget; |
| 31 | initCopyButton(elButton,idTarget,cchLength); |
| 32 | return elButton; |
| 33 | } |
| 34 | function initCopyButtonById(idButton,idTarget,cchLength){ |
| 35 | var elButton = document.getElementById(idButton); |
| 36 | if( elButton ) initCopyButton(elButton,idTarget,cchLength); |
| 37 | return elButton; |
| 38 | } |
| 39 | function initCopyButton(elButton,idTarget,cchLength){ |
| 40 |
| --- src/copybtn.js | |
| +++ src/copybtn.js | |
| @@ -30,10 +30,11 @@ | |
| 30 | elButton.id = "copy-" + idTarget; |
| 31 | initCopyButton(elButton,idTarget,cchLength); |
| 32 | return elButton; |
| 33 | } |
| 34 | function initCopyButtonById(idButton,idTarget,cchLength){ |
| 35 | idButton = idButton || "copy-" + idTarget; |
| 36 | var elButton = document.getElementById(idButton); |
| 37 | if( elButton ) initCopyButton(elButton,idTarget,cchLength); |
| 38 | return elButton; |
| 39 | } |
| 40 | function initCopyButton(elButton,idTarget,cchLength){ |
| 41 |
+3
| --- src/default_css.txt | ||
| +++ src/default_css.txt | ||
| @@ -787,5 +787,8 @@ | ||
| 787 | 787 | .copy-button-flipped { |
| 788 | 788 | //Note: .16em is suitable for element grouping. |
| 789 | 789 | margin-left: .16em; |
| 790 | 790 | margin-right: 0; |
| 791 | 791 | } |
| 792 | +.nobr { | |
| 793 | + white-space: nowrap; | |
| 794 | +} | |
| 792 | 795 |
| --- src/default_css.txt | |
| +++ src/default_css.txt | |
| @@ -787,5 +787,8 @@ | |
| 787 | .copy-button-flipped { |
| 788 | //Note: .16em is suitable for element grouping. |
| 789 | margin-left: .16em; |
| 790 | margin-right: 0; |
| 791 | } |
| 792 |
| --- src/default_css.txt | |
| +++ src/default_css.txt | |
| @@ -787,5 +787,8 @@ | |
| 787 | .copy-button-flipped { |
| 788 | //Note: .16em is suitable for element grouping. |
| 789 | margin-left: .16em; |
| 790 | margin-right: 0; |
| 791 | } |
| 792 | .nobr { |
| 793 | white-space: nowrap; |
| 794 | } |
| 795 |
+12
-19
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -763,15 +763,14 @@ | ||
| 763 | 763 | " AND tag.tagid=tagxref.tagid " |
| 764 | 764 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 765 | 765 | while( db_step(&q2)==SQLITE_ROW ){ |
| 766 | 766 | const char *zTagName = db_column_text(&q2, 0); |
| 767 | 767 | if( fossil_strcmp(zTagName,zBrName)==0 ){ |
| 768 | - @ | <span class="copy-button" id="copy-name-br" | |
| 769 | - @ data-copytarget="name-br" data-copylength="0"> | |
| 770 | - @ </span><span id="name-br"><!-- | |
| 771 | - @ -->%z(href("%R/timeline?r=%T&unhide",zTagName))%h(zTagName)</a> | |
| 772 | - @ </span> | |
| 768 | + cgi_printf(" | "); | |
| 769 | + style_copy_button(1, "name-br", 0, 0, "%z%h</a>", | |
| 770 | + href("%R/timeline?r=%T&unhide",zTagName), zTagName); | |
| 771 | + cgi_printf("\n"); | |
| 773 | 772 | if( wiki_tagid2("branch",zTagName)!=0 ){ |
| 774 | 773 | blob_appendf(&wiki_read_links, " | %z%h</a>", |
| 775 | 774 | href("%R/wiki?name=branch/%h",zTagName), zTagName); |
| 776 | 775 | }else if( g.perm.Write && g.perm.WrWiki ){ |
| 777 | 776 | blob_appendf(&wiki_add_links, " | %z%h</a>", |
| @@ -798,15 +797,13 @@ | ||
| 798 | 797 | @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a> |
| 799 | 798 | @ </td> |
| 800 | 799 | @ </tr> |
| 801 | 800 | |
| 802 | 801 | @ <tr><th>%s(hname_alg(nUuid)):</th><td> |
| 803 | - @ <span class="copy-button" id="copy-hash-ci" | |
| 804 | - @ data-copytarget="hash-ci" data-copylength="%d(hash_digits(1))"> | |
| 805 | - @ </span><span id="hash-ci">%.32s(zUuid)<wbr>%s(zUuid+32)</span> | |
| 802 | + style_copy_button(1, "hash-ci", 0, 2, "%.32s<wbr>%s", zUuid, zUuid+32); | |
| 806 | 803 | if( g.perm.Setup ){ |
| 807 | - @ (Record ID: %d(rid)) | |
| 804 | + @ (Record ID: %d(rid)) | |
| 808 | 805 | } |
| 809 | 806 | @ </td></tr> |
| 810 | 807 | @ <tr><th>User & Date:</th><td> |
| 811 | 808 | hyperlink_to_user(zUser,zDate," on "); |
| 812 | 809 | hyperlink_to_date(zDate, "</td></tr>"); |
| @@ -1919,19 +1916,17 @@ | ||
| 1919 | 1916 | }else{ |
| 1920 | 1917 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1921 | 1918 | } |
| 1922 | 1919 | } |
| 1923 | 1920 | style_header("Hex Artifact Content"); |
| 1924 | - style_copy_button(); | |
| 1925 | 1921 | zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1926 | 1922 | @ <h2>Artifact |
| 1927 | - @ <span class="copy-button" id="copy-hash-ar" | |
| 1928 | - @ data-copytarget="hash-ar" data-copylength="%d(hash_digits(1))"> | |
| 1923 | + style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid); | |
| 1929 | 1924 | if( g.perm.Setup ){ |
| 1930 | - @ </span><span id="hash-ar">%s(zUuid)</span> (%d(rid)):</h2> | |
| 1925 | + @ (%d(rid)):</h2> | |
| 1931 | 1926 | }else{ |
| 1932 | - @ </span><span id="hash-ar">%s(zUuid)</span>:</h2> | |
| 1927 | + @ :</h2> | |
| 1933 | 1928 | } |
| 1934 | 1929 | blob_zero(&downloadName); |
| 1935 | 1930 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1936 | 1931 | object_description(rid, objdescFlags, &downloadName); |
| 1937 | 1932 | style_submenu_element("Download", "%s/raw/%T?name=%s", |
| @@ -2194,18 +2189,16 @@ | ||
| 2194 | 2189 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 2195 | 2190 | if( isFile ){ |
| 2196 | 2191 | @ <h2>Latest version of file '%h(zName)':</h2> |
| 2197 | 2192 | style_submenu_element("Artifact", "%R/artifact/%S", zUuid); |
| 2198 | 2193 | }else{ |
| 2199 | - style_copy_button(); | |
| 2200 | 2194 | @ <h2>Artifact |
| 2201 | - @ <span class="copy-button" id="copy-hash-ar" | |
| 2202 | - @ data-copytarget="hash-ar" data-copylength="%d(hash_digits(1))"> | |
| 2195 | + style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid); | |
| 2203 | 2196 | if( g.perm.Setup ){ |
| 2204 | - @ </span><span id="hash-ar">%s(zUuid)</span> (%d(rid)):</h2> | |
| 2197 | + @ (%d(rid)):</h2> | |
| 2205 | 2198 | }else{ |
| 2206 | - @ </span><span id="hash-ar">%s(zUuid)</span>:</h2> | |
| 2199 | + @ :</h2> | |
| 2207 | 2200 | } |
| 2208 | 2201 | } |
| 2209 | 2202 | blob_zero(&downloadName); |
| 2210 | 2203 | asText = P("txt")!=0; |
| 2211 | 2204 | if( asText ) objdescFlags &= ~OBJDESC_BASE; |
| 2212 | 2205 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -763,15 +763,14 @@ | |
| 763 | " AND tag.tagid=tagxref.tagid " |
| 764 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 765 | while( db_step(&q2)==SQLITE_ROW ){ |
| 766 | const char *zTagName = db_column_text(&q2, 0); |
| 767 | if( fossil_strcmp(zTagName,zBrName)==0 ){ |
| 768 | @ | <span class="copy-button" id="copy-name-br" |
| 769 | @ data-copytarget="name-br" data-copylength="0"> |
| 770 | @ </span><span id="name-br"><!-- |
| 771 | @ -->%z(href("%R/timeline?r=%T&unhide",zTagName))%h(zTagName)</a> |
| 772 | @ </span> |
| 773 | if( wiki_tagid2("branch",zTagName)!=0 ){ |
| 774 | blob_appendf(&wiki_read_links, " | %z%h</a>", |
| 775 | href("%R/wiki?name=branch/%h",zTagName), zTagName); |
| 776 | }else if( g.perm.Write && g.perm.WrWiki ){ |
| 777 | blob_appendf(&wiki_add_links, " | %z%h</a>", |
| @@ -798,15 +797,13 @@ | |
| 798 | @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a> |
| 799 | @ </td> |
| 800 | @ </tr> |
| 801 | |
| 802 | @ <tr><th>%s(hname_alg(nUuid)):</th><td> |
| 803 | @ <span class="copy-button" id="copy-hash-ci" |
| 804 | @ data-copytarget="hash-ci" data-copylength="%d(hash_digits(1))"> |
| 805 | @ </span><span id="hash-ci">%.32s(zUuid)<wbr>%s(zUuid+32)</span> |
| 806 | if( g.perm.Setup ){ |
| 807 | @ (Record ID: %d(rid)) |
| 808 | } |
| 809 | @ </td></tr> |
| 810 | @ <tr><th>User & Date:</th><td> |
| 811 | hyperlink_to_user(zUser,zDate," on "); |
| 812 | hyperlink_to_date(zDate, "</td></tr>"); |
| @@ -1919,19 +1916,17 @@ | |
| 1919 | }else{ |
| 1920 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1921 | } |
| 1922 | } |
| 1923 | style_header("Hex Artifact Content"); |
| 1924 | style_copy_button(); |
| 1925 | zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1926 | @ <h2>Artifact |
| 1927 | @ <span class="copy-button" id="copy-hash-ar" |
| 1928 | @ data-copytarget="hash-ar" data-copylength="%d(hash_digits(1))"> |
| 1929 | if( g.perm.Setup ){ |
| 1930 | @ </span><span id="hash-ar">%s(zUuid)</span> (%d(rid)):</h2> |
| 1931 | }else{ |
| 1932 | @ </span><span id="hash-ar">%s(zUuid)</span>:</h2> |
| 1933 | } |
| 1934 | blob_zero(&downloadName); |
| 1935 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1936 | object_description(rid, objdescFlags, &downloadName); |
| 1937 | style_submenu_element("Download", "%s/raw/%T?name=%s", |
| @@ -2194,18 +2189,16 @@ | |
| 2194 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 2195 | if( isFile ){ |
| 2196 | @ <h2>Latest version of file '%h(zName)':</h2> |
| 2197 | style_submenu_element("Artifact", "%R/artifact/%S", zUuid); |
| 2198 | }else{ |
| 2199 | style_copy_button(); |
| 2200 | @ <h2>Artifact |
| 2201 | @ <span class="copy-button" id="copy-hash-ar" |
| 2202 | @ data-copytarget="hash-ar" data-copylength="%d(hash_digits(1))"> |
| 2203 | if( g.perm.Setup ){ |
| 2204 | @ </span><span id="hash-ar">%s(zUuid)</span> (%d(rid)):</h2> |
| 2205 | }else{ |
| 2206 | @ </span><span id="hash-ar">%s(zUuid)</span>:</h2> |
| 2207 | } |
| 2208 | } |
| 2209 | blob_zero(&downloadName); |
| 2210 | asText = P("txt")!=0; |
| 2211 | if( asText ) objdescFlags &= ~OBJDESC_BASE; |
| 2212 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -763,15 +763,14 @@ | |
| 763 | " AND tag.tagid=tagxref.tagid " |
| 764 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 765 | while( db_step(&q2)==SQLITE_ROW ){ |
| 766 | const char *zTagName = db_column_text(&q2, 0); |
| 767 | if( fossil_strcmp(zTagName,zBrName)==0 ){ |
| 768 | cgi_printf(" | "); |
| 769 | style_copy_button(1, "name-br", 0, 0, "%z%h</a>", |
| 770 | href("%R/timeline?r=%T&unhide",zTagName), zTagName); |
| 771 | cgi_printf("\n"); |
| 772 | if( wiki_tagid2("branch",zTagName)!=0 ){ |
| 773 | blob_appendf(&wiki_read_links, " | %z%h</a>", |
| 774 | href("%R/wiki?name=branch/%h",zTagName), zTagName); |
| 775 | }else if( g.perm.Write && g.perm.WrWiki ){ |
| 776 | blob_appendf(&wiki_add_links, " | %z%h</a>", |
| @@ -798,15 +797,13 @@ | |
| 797 | @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a> |
| 798 | @ </td> |
| 799 | @ </tr> |
| 800 | |
| 801 | @ <tr><th>%s(hname_alg(nUuid)):</th><td> |
| 802 | style_copy_button(1, "hash-ci", 0, 2, "%.32s<wbr>%s", zUuid, zUuid+32); |
| 803 | if( g.perm.Setup ){ |
| 804 | @ (Record ID: %d(rid)) |
| 805 | } |
| 806 | @ </td></tr> |
| 807 | @ <tr><th>User & Date:</th><td> |
| 808 | hyperlink_to_user(zUser,zDate," on "); |
| 809 | hyperlink_to_date(zDate, "</td></tr>"); |
| @@ -1919,19 +1916,17 @@ | |
| 1916 | }else{ |
| 1917 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1918 | } |
| 1919 | } |
| 1920 | style_header("Hex Artifact Content"); |
| 1921 | zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1922 | @ <h2>Artifact |
| 1923 | style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid); |
| 1924 | if( g.perm.Setup ){ |
| 1925 | @ (%d(rid)):</h2> |
| 1926 | }else{ |
| 1927 | @ :</h2> |
| 1928 | } |
| 1929 | blob_zero(&downloadName); |
| 1930 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1931 | object_description(rid, objdescFlags, &downloadName); |
| 1932 | style_submenu_element("Download", "%s/raw/%T?name=%s", |
| @@ -2194,18 +2189,16 @@ | |
| 2189 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 2190 | if( isFile ){ |
| 2191 | @ <h2>Latest version of file '%h(zName)':</h2> |
| 2192 | style_submenu_element("Artifact", "%R/artifact/%S", zUuid); |
| 2193 | }else{ |
| 2194 | @ <h2>Artifact |
| 2195 | style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid); |
| 2196 | if( g.perm.Setup ){ |
| 2197 | @ (%d(rid)):</h2> |
| 2198 | }else{ |
| 2199 | @ :</h2> |
| 2200 | } |
| 2201 | } |
| 2202 | blob_zero(&downloadName); |
| 2203 | asText = P("txt")!=0; |
| 2204 | if( asText ) objdescFlags &= ~OBJDESC_BASE; |
| 2205 |
+85
-1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -366,10 +366,94 @@ | ||
| 366 | 366 | char *zConfigName = mprintf("%s-image", zImageName); |
| 367 | 367 | url_var(zVarPrefix, zConfigName, zImageName); |
| 368 | 368 | free(zVarPrefix); |
| 369 | 369 | free(zConfigName); |
| 370 | 370 | } |
| 371 | + | |
| 372 | +/* | |
| 373 | +** Output TEXT with a click-to-copy button next to it. Loads the copybtn.js | |
| 374 | +** Javascript module, and generates HTML elements with the following IDs: | |
| 375 | +** | |
| 376 | +** TARGETID: The <span> wrapper around TEXT. | |
| 377 | +** copy-TARGETID: The <span> for the copy button. | |
| 378 | +** | |
| 379 | +** If the FLIPPED argument is non-zero, the copy button is displayed after TEXT. | |
| 380 | +** | |
| 381 | +** The COPYLENGTH argument defines the length of the substring of TEXT copied to | |
| 382 | +** clipboard: | |
| 383 | +** | |
| 384 | +** <= 0: No limit (default if the argument is omitted). | |
| 385 | +** >= 3: Truncate TEXT after COPYLENGTH (single-byte) characters. | |
| 386 | +** 1: Use the "hash-digits" setting as the limit. | |
| 387 | +** 2: Use the length appropriate for URLs as the limit (defined at | |
| 388 | +** compile-time by FOSSIL_HASH_DIGITS_URL, defaults to 16). | |
| 389 | +*/ | |
| 390 | +char *style_copy_button( | |
| 391 | + int bOutputCGI, /* Don't return result, but send to cgi_printf(). */ | |
| 392 | + const char *zTargetId, /* The TARGETID argument. */ | |
| 393 | + int bFlipped, /* The FLIPPED argument. */ | |
| 394 | + int cchLength, /* The COPYLENGTH argument. */ | |
| 395 | + const char *zTextFmt, /* Formatting of the TEXT argument (htmlized). */ | |
| 396 | + ... /* Formatting parameters of the TEXT argument. */ | |
| 397 | +){ | |
| 398 | + va_list ap; | |
| 399 | + char *zText; | |
| 400 | + char *zResult = 0; | |
| 401 | + va_start(ap,zTextFmt); | |
| 402 | + zText = vmprintf(zTextFmt/*works-like:?*/,ap); | |
| 403 | + va_end(ap); | |
| 404 | + if( cchLength==1 ) cchLength = hash_digits(0); | |
| 405 | + else if( cchLength==2 ) cchLength = hash_digits(1); | |
| 406 | + if( !bFlipped ){ | |
| 407 | + const char *zBtnFmt = | |
| 408 | + "<span class=\"nobr\">" | |
| 409 | + "<span " | |
| 410 | + "class=\"copy-button\" " | |
| 411 | + "id=\"copy-%h\" " | |
| 412 | + "data-copytarget=\"%h\" " | |
| 413 | + "data-copylength=\"%d\">" | |
| 414 | + "</span>" | |
| 415 | + "<span id=\"%h\">" | |
| 416 | + "%s" | |
| 417 | + "</span>" | |
| 418 | + "</span>"; | |
| 419 | + if( bOutputCGI ){ | |
| 420 | + cgi_printf( | |
| 421 | + zBtnFmt/*works-like:"%h%h%d%h%s"*/, | |
| 422 | + zTargetId,zTargetId,cchLength,zTargetId,zText); | |
| 423 | + }else{ | |
| 424 | + zResult = mprintf( | |
| 425 | + zBtnFmt/*works-like:"%h%h%d%h%s"*/, | |
| 426 | + zTargetId,zTargetId,cchLength,zTargetId,zText); | |
| 427 | + } | |
| 428 | + }else{ | |
| 429 | + const char *zBtnFmt = | |
| 430 | + "<span class=\"nobr\">" | |
| 431 | + "<span id=\"%h\">" | |
| 432 | + "%s" | |
| 433 | + "</span>" | |
| 434 | + "<span " | |
| 435 | + "class=\"copy-button copy-button-flipped\" " | |
| 436 | + "id=\"copy-%h\" " | |
| 437 | + "data-copytarget=\"%h\" " | |
| 438 | + "data-copylength=\"%d\">" | |
| 439 | + "</span>" | |
| 440 | + "</span>"; | |
| 441 | + if( bOutputCGI ){ | |
| 442 | + cgi_printf( | |
| 443 | + zBtnFmt/*works-like:"%h%s%h%h%d"*/, | |
| 444 | + zTargetId,zText,zTargetId,zTargetId,cchLength); | |
| 445 | + }else{ | |
| 446 | + zResult = mprintf( | |
| 447 | + zBtnFmt/*works-like:"%h%s%h%h%d"*/, | |
| 448 | + zTargetId,zText,zTargetId,zTargetId,cchLength); | |
| 449 | + } | |
| 450 | + } | |
| 451 | + free(zText); | |
| 452 | + style_copybutton_control(); | |
| 453 | + return zResult; | |
| 454 | +} | |
| 371 | 455 | |
| 372 | 456 | /* |
| 373 | 457 | ** Return a random nonce that is stored in static space. For a particular |
| 374 | 458 | ** run, the same nonce is always returned. |
| 375 | 459 | */ |
| @@ -543,11 +627,11 @@ | ||
| 543 | 627 | } |
| 544 | 628 | |
| 545 | 629 | /* |
| 546 | 630 | ** Indicate that the copy button javascript is needed. |
| 547 | 631 | */ |
| 548 | -void style_copy_button(void){ | |
| 632 | +void style_copybutton_control(void){ | |
| 549 | 633 | needCopyBtnJs = 1; |
| 550 | 634 | } |
| 551 | 635 | |
| 552 | 636 | /* |
| 553 | 637 | ** Generate code to load a single javascript file |
| 554 | 638 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -366,10 +366,94 @@ | |
| 366 | char *zConfigName = mprintf("%s-image", zImageName); |
| 367 | url_var(zVarPrefix, zConfigName, zImageName); |
| 368 | free(zVarPrefix); |
| 369 | free(zConfigName); |
| 370 | } |
| 371 | |
| 372 | /* |
| 373 | ** Return a random nonce that is stored in static space. For a particular |
| 374 | ** run, the same nonce is always returned. |
| 375 | */ |
| @@ -543,11 +627,11 @@ | |
| 543 | } |
| 544 | |
| 545 | /* |
| 546 | ** Indicate that the copy button javascript is needed. |
| 547 | */ |
| 548 | void style_copy_button(void){ |
| 549 | needCopyBtnJs = 1; |
| 550 | } |
| 551 | |
| 552 | /* |
| 553 | ** Generate code to load a single javascript file |
| 554 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -366,10 +366,94 @@ | |
| 366 | char *zConfigName = mprintf("%s-image", zImageName); |
| 367 | url_var(zVarPrefix, zConfigName, zImageName); |
| 368 | free(zVarPrefix); |
| 369 | free(zConfigName); |
| 370 | } |
| 371 | |
| 372 | /* |
| 373 | ** Output TEXT with a click-to-copy button next to it. Loads the copybtn.js |
| 374 | ** Javascript module, and generates HTML elements with the following IDs: |
| 375 | ** |
| 376 | ** TARGETID: The <span> wrapper around TEXT. |
| 377 | ** copy-TARGETID: The <span> for the copy button. |
| 378 | ** |
| 379 | ** If the FLIPPED argument is non-zero, the copy button is displayed after TEXT. |
| 380 | ** |
| 381 | ** The COPYLENGTH argument defines the length of the substring of TEXT copied to |
| 382 | ** clipboard: |
| 383 | ** |
| 384 | ** <= 0: No limit (default if the argument is omitted). |
| 385 | ** >= 3: Truncate TEXT after COPYLENGTH (single-byte) characters. |
| 386 | ** 1: Use the "hash-digits" setting as the limit. |
| 387 | ** 2: Use the length appropriate for URLs as the limit (defined at |
| 388 | ** compile-time by FOSSIL_HASH_DIGITS_URL, defaults to 16). |
| 389 | */ |
| 390 | char *style_copy_button( |
| 391 | int bOutputCGI, /* Don't return result, but send to cgi_printf(). */ |
| 392 | const char *zTargetId, /* The TARGETID argument. */ |
| 393 | int bFlipped, /* The FLIPPED argument. */ |
| 394 | int cchLength, /* The COPYLENGTH argument. */ |
| 395 | const char *zTextFmt, /* Formatting of the TEXT argument (htmlized). */ |
| 396 | ... /* Formatting parameters of the TEXT argument. */ |
| 397 | ){ |
| 398 | va_list ap; |
| 399 | char *zText; |
| 400 | char *zResult = 0; |
| 401 | va_start(ap,zTextFmt); |
| 402 | zText = vmprintf(zTextFmt/*works-like:?*/,ap); |
| 403 | va_end(ap); |
| 404 | if( cchLength==1 ) cchLength = hash_digits(0); |
| 405 | else if( cchLength==2 ) cchLength = hash_digits(1); |
| 406 | if( !bFlipped ){ |
| 407 | const char *zBtnFmt = |
| 408 | "<span class=\"nobr\">" |
| 409 | "<span " |
| 410 | "class=\"copy-button\" " |
| 411 | "id=\"copy-%h\" " |
| 412 | "data-copytarget=\"%h\" " |
| 413 | "data-copylength=\"%d\">" |
| 414 | "</span>" |
| 415 | "<span id=\"%h\">" |
| 416 | "%s" |
| 417 | "</span>" |
| 418 | "</span>"; |
| 419 | if( bOutputCGI ){ |
| 420 | cgi_printf( |
| 421 | zBtnFmt/*works-like:"%h%h%d%h%s"*/, |
| 422 | zTargetId,zTargetId,cchLength,zTargetId,zText); |
| 423 | }else{ |
| 424 | zResult = mprintf( |
| 425 | zBtnFmt/*works-like:"%h%h%d%h%s"*/, |
| 426 | zTargetId,zTargetId,cchLength,zTargetId,zText); |
| 427 | } |
| 428 | }else{ |
| 429 | const char *zBtnFmt = |
| 430 | "<span class=\"nobr\">" |
| 431 | "<span id=\"%h\">" |
| 432 | "%s" |
| 433 | "</span>" |
| 434 | "<span " |
| 435 | "class=\"copy-button copy-button-flipped\" " |
| 436 | "id=\"copy-%h\" " |
| 437 | "data-copytarget=\"%h\" " |
| 438 | "data-copylength=\"%d\">" |
| 439 | "</span>" |
| 440 | "</span>"; |
| 441 | if( bOutputCGI ){ |
| 442 | cgi_printf( |
| 443 | zBtnFmt/*works-like:"%h%s%h%h%d"*/, |
| 444 | zTargetId,zText,zTargetId,zTargetId,cchLength); |
| 445 | }else{ |
| 446 | zResult = mprintf( |
| 447 | zBtnFmt/*works-like:"%h%s%h%h%d"*/, |
| 448 | zTargetId,zText,zTargetId,zTargetId,cchLength); |
| 449 | } |
| 450 | } |
| 451 | free(zText); |
| 452 | style_copybutton_control(); |
| 453 | return zResult; |
| 454 | } |
| 455 | |
| 456 | /* |
| 457 | ** Return a random nonce that is stored in static space. For a particular |
| 458 | ** run, the same nonce is always returned. |
| 459 | */ |
| @@ -543,11 +627,11 @@ | |
| 627 | } |
| 628 | |
| 629 | /* |
| 630 | ** Indicate that the copy button javascript is needed. |
| 631 | */ |
| 632 | void style_copybutton_control(void){ |
| 633 | needCopyBtnJs = 1; |
| 634 | } |
| 635 | |
| 636 | /* |
| 637 | ** Generate code to load a single javascript file |
| 638 |
+4
-33
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -1025,47 +1025,18 @@ | ||
| 1025 | 1025 | "copybtn TARGETID FLIPPED TEXT ?COPYLENGTH?"); |
| 1026 | 1026 | } |
| 1027 | 1027 | if( enableOutput ){ |
| 1028 | 1028 | int flipped = 0; |
| 1029 | 1029 | int copylength = 0; |
| 1030 | - char *zTargetId, *zText, *zResult; | |
| 1030 | + char *zResult; | |
| 1031 | 1031 | if( Th_ToInt(interp, argv[2], argl[2], &flipped) ) return TH_ERROR; |
| 1032 | 1032 | if( argc==5 ){ |
| 1033 | 1033 | if( Th_ToInt(interp, argv[4], argl[4], ©length) ) return TH_ERROR; |
| 1034 | 1034 | } |
| 1035 | - if( copylength==1 ) copylength = hash_digits(0); | |
| 1036 | - else if( copylength==2 ) copylength = hash_digits(1); | |
| 1037 | - zTargetId = htmlize((char*)argv[1], argl[1]); | |
| 1038 | - zText = htmlize((char*)argv[3], argl[3]); | |
| 1039 | - if( !flipped ){ | |
| 1040 | - zResult = mprintf( | |
| 1041 | - "<span " | |
| 1042 | - "class=\"copy-button\" " | |
| 1043 | - "id=\"copy-%s\" " | |
| 1044 | - "data-copytarget=\"%s\" " | |
| 1045 | - "data-copylength=\"%d\">" | |
| 1046 | - "</span>" | |
| 1047 | - "<span id=\"%s\">" | |
| 1048 | - "%s" | |
| 1049 | - "</span>", | |
| 1050 | - zTargetId, zTargetId, copylength, zTargetId, zText); | |
| 1051 | - }else{ | |
| 1052 | - zResult = mprintf( | |
| 1053 | - "<span id=\"%s\">" | |
| 1054 | - "%s" | |
| 1055 | - "</span>" | |
| 1056 | - "<span " | |
| 1057 | - "class=\"copy-button copy-button-flipped\" " | |
| 1058 | - "id=\"copy-%s\" " | |
| 1059 | - "data-copytarget=\"%s\" " | |
| 1060 | - "data-copylength=\"%d\">" | |
| 1061 | - "</span>", | |
| 1062 | - zTargetId, zText, zTargetId, zTargetId, copylength); | |
| 1063 | - } | |
| 1064 | - free(zTargetId); | |
| 1065 | - free(zText); | |
| 1066 | - style_copy_button(); | |
| 1035 | + zResult = style_copy_button( | |
| 1036 | + /*bOutputCGI==*/0, /*TARGETID==*/(char*)argv[1], | |
| 1037 | + flipped, copylength, "%h", /*TEXT==*/(char*)argv[3]); | |
| 1067 | 1038 | sendText(zResult, -1, 0); |
| 1068 | 1039 | free(zResult); |
| 1069 | 1040 | } |
| 1070 | 1041 | return TH_OK; |
| 1071 | 1042 | } |
| 1072 | 1043 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1025,47 +1025,18 @@ | |
| 1025 | "copybtn TARGETID FLIPPED TEXT ?COPYLENGTH?"); |
| 1026 | } |
| 1027 | if( enableOutput ){ |
| 1028 | int flipped = 0; |
| 1029 | int copylength = 0; |
| 1030 | char *zTargetId, *zText, *zResult; |
| 1031 | if( Th_ToInt(interp, argv[2], argl[2], &flipped) ) return TH_ERROR; |
| 1032 | if( argc==5 ){ |
| 1033 | if( Th_ToInt(interp, argv[4], argl[4], ©length) ) return TH_ERROR; |
| 1034 | } |
| 1035 | if( copylength==1 ) copylength = hash_digits(0); |
| 1036 | else if( copylength==2 ) copylength = hash_digits(1); |
| 1037 | zTargetId = htmlize((char*)argv[1], argl[1]); |
| 1038 | zText = htmlize((char*)argv[3], argl[3]); |
| 1039 | if( !flipped ){ |
| 1040 | zResult = mprintf( |
| 1041 | "<span " |
| 1042 | "class=\"copy-button\" " |
| 1043 | "id=\"copy-%s\" " |
| 1044 | "data-copytarget=\"%s\" " |
| 1045 | "data-copylength=\"%d\">" |
| 1046 | "</span>" |
| 1047 | "<span id=\"%s\">" |
| 1048 | "%s" |
| 1049 | "</span>", |
| 1050 | zTargetId, zTargetId, copylength, zTargetId, zText); |
| 1051 | }else{ |
| 1052 | zResult = mprintf( |
| 1053 | "<span id=\"%s\">" |
| 1054 | "%s" |
| 1055 | "</span>" |
| 1056 | "<span " |
| 1057 | "class=\"copy-button copy-button-flipped\" " |
| 1058 | "id=\"copy-%s\" " |
| 1059 | "data-copytarget=\"%s\" " |
| 1060 | "data-copylength=\"%d\">" |
| 1061 | "</span>", |
| 1062 | zTargetId, zText, zTargetId, zTargetId, copylength); |
| 1063 | } |
| 1064 | free(zTargetId); |
| 1065 | free(zText); |
| 1066 | style_copy_button(); |
| 1067 | sendText(zResult, -1, 0); |
| 1068 | free(zResult); |
| 1069 | } |
| 1070 | return TH_OK; |
| 1071 | } |
| 1072 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1025,47 +1025,18 @@ | |
| 1025 | "copybtn TARGETID FLIPPED TEXT ?COPYLENGTH?"); |
| 1026 | } |
| 1027 | if( enableOutput ){ |
| 1028 | int flipped = 0; |
| 1029 | int copylength = 0; |
| 1030 | char *zResult; |
| 1031 | if( Th_ToInt(interp, argv[2], argl[2], &flipped) ) return TH_ERROR; |
| 1032 | if( argc==5 ){ |
| 1033 | if( Th_ToInt(interp, argv[4], argl[4], ©length) ) return TH_ERROR; |
| 1034 | } |
| 1035 | zResult = style_copy_button( |
| 1036 | /*bOutputCGI==*/0, /*TARGETID==*/(char*)argv[1], |
| 1037 | flipped, copylength, "%h", /*TEXT==*/(char*)argv[3]); |
| 1038 | sendText(zResult, -1, 0); |
| 1039 | free(zResult); |
| 1040 | } |
| 1041 | return TH_OK; |
| 1042 | } |
| 1043 |
+1
-1
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1003,11 +1003,11 @@ | ||
| 1003 | 1003 | cgi_printf("\"h\":\"%!S\"}%s", |
| 1004 | 1004 | pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); |
| 1005 | 1005 | } |
| 1006 | 1006 | @ }</script> |
| 1007 | 1007 | style_graph_generator(); |
| 1008 | - style_copy_button(); /* Dependency: graph.js requires copybtn.js. */ | |
| 1008 | + style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */ | |
| 1009 | 1009 | graph_free(pGraph); |
| 1010 | 1010 | } |
| 1011 | 1011 | } |
| 1012 | 1012 | |
| 1013 | 1013 | /* |
| 1014 | 1014 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1003,11 +1003,11 @@ | |
| 1003 | cgi_printf("\"h\":\"%!S\"}%s", |
| 1004 | pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); |
| 1005 | } |
| 1006 | @ }</script> |
| 1007 | style_graph_generator(); |
| 1008 | style_copy_button(); /* Dependency: graph.js requires copybtn.js. */ |
| 1009 | graph_free(pGraph); |
| 1010 | } |
| 1011 | } |
| 1012 | |
| 1013 | /* |
| 1014 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1003,11 +1003,11 @@ | |
| 1003 | cgi_printf("\"h\":\"%!S\"}%s", |
| 1004 | pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); |
| 1005 | } |
| 1006 | @ }</script> |
| 1007 | style_graph_generator(); |
| 1008 | style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */ |
| 1009 | graph_free(pGraph); |
| 1010 | } |
| 1011 | } |
| 1012 | |
| 1013 | /* |
| 1014 |
+1
-1
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1003,11 +1003,11 @@ | ||
| 1003 | 1003 | cgi_printf("\"h\":\"%!S\"}%s", |
| 1004 | 1004 | pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); |
| 1005 | 1005 | } |
| 1006 | 1006 | @ }</script> |
| 1007 | 1007 | style_graph_generator(); |
| 1008 | - style_copy_button(); /* Dependency: graph.js requires copybtn.js. */ | |
| 1008 | + style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */ | |
| 1009 | 1009 | graph_free(pGraph); |
| 1010 | 1010 | } |
| 1011 | 1011 | } |
| 1012 | 1012 | |
| 1013 | 1013 | /* |
| 1014 | 1014 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1003,11 +1003,11 @@ | |
| 1003 | cgi_printf("\"h\":\"%!S\"}%s", |
| 1004 | pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); |
| 1005 | } |
| 1006 | @ }</script> |
| 1007 | style_graph_generator(); |
| 1008 | style_copy_button(); /* Dependency: graph.js requires copybtn.js. */ |
| 1009 | graph_free(pGraph); |
| 1010 | } |
| 1011 | } |
| 1012 | |
| 1013 | /* |
| 1014 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1003,11 +1003,11 @@ | |
| 1003 | cgi_printf("\"h\":\"%!S\"}%s", |
| 1004 | pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); |
| 1005 | } |
| 1006 | @ }</script> |
| 1007 | style_graph_generator(); |
| 1008 | style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */ |
| 1009 | graph_free(pGraph); |
| 1010 | } |
| 1011 | } |
| 1012 | |
| 1013 | /* |
| 1014 |