Fossil SCM

Rearranged the pikchrshow controls a bit to make better use of space and reduce flickering of the preview mode label/controls. Adapted CSS for pikchr error reporting structure changes. Code renaming for consistency/clarity. fossil.copyButton() click handler is now a no-op if the pseudo-button element has the 'disabled' CSS class and added style to grey such a button out.

stephan 2020-09-11 23:56 trunk
Commit c304b4ffdf163aed2b7ab42084a87ce5dadc7a4c057ce827137db9562ac15d6d
--- src/default.css
+++ src/default.css
@@ -903,10 +903,13 @@
903903
d='M10,4.4v1.6h1.6zm-4,-0.6h3v3h-3zm0,3h6v5.4h-6z'/%3E%3Cpath style='fill:rgb(80,128,208)' \
904904
d='M7,8h4v1h-4zm0,2h4v1h-4z'/%3E%3C/svg%3E");
905905
background-repeat: no-repeat;
906906
background-position: center;
907907
cursor: pointer;
908
+}
909
+.copy-button.disabled {
910
+ opacity: 0.4;
908911
}
909912
.copy-button-flipped {
910913
/*Note: .16em is suitable for element grouping.*/
911914
margin-left: .16em;
912915
margin-right: 0;
913916
--- src/default.css
+++ src/default.css
@@ -903,10 +903,13 @@
903 d='M10,4.4v1.6h1.6zm-4,-0.6h3v3h-3zm0,3h6v5.4h-6z'/%3E%3Cpath style='fill:rgb(80,128,208)' \
904 d='M7,8h4v1h-4zm0,2h4v1h-4z'/%3E%3C/svg%3E");
905 background-repeat: no-repeat;
906 background-position: center;
907 cursor: pointer;
 
 
 
908 }
909 .copy-button-flipped {
910 /*Note: .16em is suitable for element grouping.*/
911 margin-left: .16em;
912 margin-right: 0;
913
--- src/default.css
+++ src/default.css
@@ -903,10 +903,13 @@
903 d='M10,4.4v1.6h1.6zm-4,-0.6h3v3h-3zm0,3h6v5.4h-6z'/%3E%3Cpath style='fill:rgb(80,128,208)' \
904 d='M7,8h4v1h-4zm0,2h4v1h-4z'/%3E%3C/svg%3E");
905 background-repeat: no-repeat;
906 background-position: center;
907 cursor: pointer;
908 }
909 .copy-button.disabled {
910 opacity: 0.4;
911 }
912 .copy-button-flipped {
913 /*Note: .16em is suitable for element grouping.*/
914 margin-left: .16em;
915 margin-right: 0;
916
--- src/fossil.copybutton.js
+++ src/fossil.copybutton.js
@@ -57,10 +57,16 @@
5757
successfully copied text to the clipboard. The event's "detail"
5858
member is an object with a "text" property holding the copied
5959
text. Other properties may be added in the future. The event is
6060
not fired if copying to the clipboard fails (e.g. is not
6161
available in the current environment).
62
+
63
+ As a special case, the copy button's click handler is suppressed
64
+ (becomes a no-op) for as long as the element has the CSS class
65
+ "disabled". This allows elements which cannot be disabled via
66
+ HTML attributes, e.g. a SPAN, to act as a copy button while still
67
+ providing a way to disable them.
6268
6369
Returns the copy-initialized element.
6470
6571
Example:
6672
@@ -91,10 +97,11 @@
9197
);
9298
D.copyStyle(e, opt.style);
9399
e.addEventListener(
94100
'click',
95101
function(){
102
+ if(e.classList.contains('disabled')) return;
96103
const txt = extract.call(opt);
97104
if(txt && D.copyTextToClipboard(txt)){
98105
e.dispatchEvent(new CustomEvent('text-copied',{
99106
detail: {text: txt}
100107
}));
101108
--- src/fossil.copybutton.js
+++ src/fossil.copybutton.js
@@ -57,10 +57,16 @@
57 successfully copied text to the clipboard. The event's "detail"
58 member is an object with a "text" property holding the copied
59 text. Other properties may be added in the future. The event is
60 not fired if copying to the clipboard fails (e.g. is not
61 available in the current environment).
 
 
 
 
 
 
62
63 Returns the copy-initialized element.
64
65 Example:
66
@@ -91,10 +97,11 @@
91 );
92 D.copyStyle(e, opt.style);
93 e.addEventListener(
94 'click',
95 function(){
 
96 const txt = extract.call(opt);
97 if(txt && D.copyTextToClipboard(txt)){
98 e.dispatchEvent(new CustomEvent('text-copied',{
99 detail: {text: txt}
100 }));
101
--- src/fossil.copybutton.js
+++ src/fossil.copybutton.js
@@ -57,10 +57,16 @@
57 successfully copied text to the clipboard. The event's "detail"
58 member is an object with a "text" property holding the copied
59 text. Other properties may be added in the future. The event is
60 not fired if copying to the clipboard fails (e.g. is not
61 available in the current environment).
62
63 As a special case, the copy button's click handler is suppressed
64 (becomes a no-op) for as long as the element has the CSS class
65 "disabled". This allows elements which cannot be disabled via
66 HTML attributes, e.g. a SPAN, to act as a copy button while still
67 providing a way to disable them.
68
69 Returns the copy-initialized element.
70
71 Example:
72
@@ -91,10 +97,11 @@
97 );
98 D.copyStyle(e, opt.style);
99 e.addEventListener(
100 'click',
101 function(){
102 if(e.classList.contains('disabled')) return;
103 const txt = extract.call(opt);
104 if(txt && D.copyTextToClipboard(txt)){
105 e.dispatchEvent(new CustomEvent('text-copied',{
106 detail: {text: txt}
107 }));
108
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -315,10 +315,14 @@
315315
const a = argsToArray(arguments);
316316
a.unshift('remove');
317317
return domAddRemoveClass.apply(this, a);
318318
};
319319
320
+ /**
321
+ Returns true if DOM element e contains CSS class c, else
322
+ false.
323
+ */
320324
dom.hasClass = function(e,c){
321325
return (e && e.classList) ? e.classList.contains(c) : false;
322326
};
323327
324328
/**
@@ -542,10 +546,15 @@
542546
if(afterFlashCallback) afterFlashCallback();
543547
}, howLongMs);
544548
return e;
545549
};
546550
dom.flashOnce.defaultTimeMs = 400;
551
+ /**
552
+ A DOM event handler which simply passes event.target
553
+ to dom.flashOnce().
554
+ */
555
+ dom.flashOnce.eventHandler = (event)=>dom.flashOnce(event.target)
547556
548557
/**
549558
Attempts to copy the given text to the system clipboard. Returns
550559
true if it succeeds, else false.
551560
*/
552561
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -315,10 +315,14 @@
315 const a = argsToArray(arguments);
316 a.unshift('remove');
317 return domAddRemoveClass.apply(this, a);
318 };
319
 
 
 
 
320 dom.hasClass = function(e,c){
321 return (e && e.classList) ? e.classList.contains(c) : false;
322 };
323
324 /**
@@ -542,10 +546,15 @@
542 if(afterFlashCallback) afterFlashCallback();
543 }, howLongMs);
544 return e;
545 };
546 dom.flashOnce.defaultTimeMs = 400;
 
 
 
 
 
547
548 /**
549 Attempts to copy the given text to the system clipboard. Returns
550 true if it succeeds, else false.
551 */
552
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -315,10 +315,14 @@
315 const a = argsToArray(arguments);
316 a.unshift('remove');
317 return domAddRemoveClass.apply(this, a);
318 };
319
320 /**
321 Returns true if DOM element e contains CSS class c, else
322 false.
323 */
324 dom.hasClass = function(e,c){
325 return (e && e.classList) ? e.classList.contains(c) : false;
326 };
327
328 /**
@@ -542,10 +546,15 @@
546 if(afterFlashCallback) afterFlashCallback();
547 }, howLongMs);
548 return e;
549 };
550 dom.flashOnce.defaultTimeMs = 400;
551 /**
552 A DOM event handler which simply passes event.target
553 to dom.flashOnce().
554 */
555 dom.flashOnce.eventHandler = (event)=>dom.flashOnce(event.target)
556
557 /**
558 Attempts to copy the given text to the system clipboard. Returns
559 true if it succeeds, else false.
560 */
561
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -19,22 +19,28 @@
1919
};
2020
F.onPageLoad(function() {
2121
document.body.classList.add('pikchrshow');
2222
P.e = { /* various DOM elements we work with... */
2323
previewTarget: E('#pikchrshow-output'),
24
- previewModeLabel: E('#pikchrshow-output-wrapper > legend'),
25
- btnCopy: E('#pikchrshow-output-wrapper > legend > .copy-button'),
24
+ previewLegend: E('#pikchrshow-output-wrapper > legend'),
25
+ previewModeLabel: D.span(/*holds the text for the preview mode label*/),
26
+ previewCopyButton: D.addClass(D.span(), 'copy-button'),
2627
btnSubmit: E('#pikchr-submit-preview'),
2728
cbDarkMode: E('#flipcolors-wrapper > input[type=checkbox]'),
2829
taContent: E('#content'),
2930
taPreviewText: D.attr(D.textarea(), 'rows', 20, 'cols', 60,
3031
'readonly', true),
3132
uiControls: E('#pikchrshow-controls'),
32
- btnTogglePreviewMode: D.button("Preview mode"),
33
+ previewModeToggle: D.button("Preview mode"),
3334
selectMarkupAlignment: D.select()
3435
};
35
- D.append(P.e.uiControls, P.e.btnTogglePreviewMode);
36
+ ////////////////////////////////////////////////////////////
37
+ // Setup the preview fieldset's LEGEND element...
38
+ D.append( P.e.previewLegend,
39
+ P.e.previewModeToggle,
40
+ P.e.previewModeLabel,
41
+ P.e.previewCopyButton );
3642
3743
////////////////////////////////////////////////////////////
3844
// Setup markup alignment selection...
3945
D.append(P.e.uiControls, P.e.selectMarkupAlignment);
4046
D.disable(D.option(P.e.selectMarkupAlignment, '', 'Markup Alignment'));
@@ -42,14 +48,12 @@
4248
D.option(P.e.selectMarkupAlignment, ndx ? val : '', val);
4349
});
4450
4551
////////////////////////////////////////////////////////////
4652
// Setup clipboard-copy of markup/SVG...
47
- F.copyButton(P.e.btnCopy, {copyFromElement: P.e.taPreviewText});
48
- P.e.btnCopy.addEventListener('text-copied',function(ev){
49
- D.flashOnce(ev.target);
50
- },false);
53
+ F.copyButton(P.e.previewCopyButton, {copyFromElement: P.e.taPreviewText});
54
+ P.e.previewCopyButton.addEventListener('text-copied', D.flashOnce.eventHandler, false);
5155
5256
////////////////////////////////////////////////////////////
5357
// Set up dark mode simulator...
5458
P.e.cbDarkMode.addEventListener('change', function(ev){
5559
if(ev.target.checked) D.addClass(P.e.previewTarget, 'dark-mode');
@@ -58,11 +62,11 @@
5862
if(P.e.cbDarkMode.checked) D.addClass(P.e.previewTarget, 'dark-mode');
5963
6064
////////////////////////////////////////////////////////////
6165
// Set up preview update and preview mode toggle...
6266
P.e.btnSubmit.addEventListener('click', ()=>P.preview(), false);
63
- P.e.btnTogglePreviewMode.addEventListener('click', function(){
67
+ P.e.previewModeToggle.addEventListener('click', function(){
6468
/* Rotate through the 4 available preview modes */
6569
P.previewMode = ++P.previewMode % 4;
6670
P.renderPreview();
6771
}, false);
6872
P.e.selectMarkupAlignment.addEventListener('change', function(ev){
@@ -186,11 +190,12 @@
186190
D.addClass(preTgt, 'error');
187191
this.e.previewModeLabel.innerText = "Error";
188192
return;
189193
}
190194
D.removeClass(preTgt, 'error');
191
- D.enable(this.e.btnTogglePreviewMode);
195
+ D.removeClass(P.e.previewCopyButton, 'disabled');
196
+ D.enable(this.e.previewModeToggle);
192197
let label;
193198
switch(this.previewMode){
194199
case 0:
195200
label = "Rendered SVG";
196201
preTgt.innerHTML = this.response.raw;
@@ -218,12 +223,11 @@
218223
label = "Raw SVG";
219224
this.e.taPreviewText.value = this.response.raw.replace(f.rxNonce, '');
220225
D.append(D.clearElement(preTgt), this.e.taPreviewText);
221226
break;
222227
}
223
- D.append(D.clearElement(this.e.previewModeLabel),
224
- label, this.e.btnCopy);
228
+ this.e.previewModeLabel.innerText = label;
225229
};
226230
227231
/**
228232
Fetches the preview from the server and updates the preview to
229233
the rendered SVG content or error report.
@@ -233,11 +237,11 @@
233237
fp.toDisable = [
234238
/* input elements to disable during ajax operations */
235239
this.e.btnSubmit, this.e.taContent,
236240
this.e.selectMarkupAlignment,
237241
this.e.cbAutoPreview, this.e.selectScript
238
- /* this.e.btnTogglePreviewMode is handled separately */
242
+ /* this.e.previewModeToggle is handled separately */
239243
];
240244
fp.target = this.e.previewTarget;
241245
fp.updateView = function(c,isError){
242246
P.previewMode = 0;
243247
P.response.raw = c;
@@ -244,11 +248,12 @@
244248
P.response.isError = isError;
245249
D.enable(fp.toDisable);
246250
P.renderPreview();
247251
};
248252
}
249
- D.disable(fp.toDisable, this.e.btnTogglePreviewMode);
253
+ D.disable(fp.toDisable, this.e.previewModeToggle);
254
+ D.addClass(this.e.previewCopyButton, 'disabled');
250255
const content = this.e.taContent.value.trim();
251256
this.response.raw = undefined;
252257
this.response.inputText = content;
253258
if(!content){
254259
fp.updateView("No pikchr content!",true);
255260
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -19,22 +19,28 @@
19 };
20 F.onPageLoad(function() {
21 document.body.classList.add('pikchrshow');
22 P.e = { /* various DOM elements we work with... */
23 previewTarget: E('#pikchrshow-output'),
24 previewModeLabel: E('#pikchrshow-output-wrapper > legend'),
25 btnCopy: E('#pikchrshow-output-wrapper > legend > .copy-button'),
 
26 btnSubmit: E('#pikchr-submit-preview'),
27 cbDarkMode: E('#flipcolors-wrapper > input[type=checkbox]'),
28 taContent: E('#content'),
29 taPreviewText: D.attr(D.textarea(), 'rows', 20, 'cols', 60,
30 'readonly', true),
31 uiControls: E('#pikchrshow-controls'),
32 btnTogglePreviewMode: D.button("Preview mode"),
33 selectMarkupAlignment: D.select()
34 };
35 D.append(P.e.uiControls, P.e.btnTogglePreviewMode);
 
 
 
 
 
36
37 ////////////////////////////////////////////////////////////
38 // Setup markup alignment selection...
39 D.append(P.e.uiControls, P.e.selectMarkupAlignment);
40 D.disable(D.option(P.e.selectMarkupAlignment, '', 'Markup Alignment'));
@@ -42,14 +48,12 @@
42 D.option(P.e.selectMarkupAlignment, ndx ? val : '', val);
43 });
44
45 ////////////////////////////////////////////////////////////
46 // Setup clipboard-copy of markup/SVG...
47 F.copyButton(P.e.btnCopy, {copyFromElement: P.e.taPreviewText});
48 P.e.btnCopy.addEventListener('text-copied',function(ev){
49 D.flashOnce(ev.target);
50 },false);
51
52 ////////////////////////////////////////////////////////////
53 // Set up dark mode simulator...
54 P.e.cbDarkMode.addEventListener('change', function(ev){
55 if(ev.target.checked) D.addClass(P.e.previewTarget, 'dark-mode');
@@ -58,11 +62,11 @@
58 if(P.e.cbDarkMode.checked) D.addClass(P.e.previewTarget, 'dark-mode');
59
60 ////////////////////////////////////////////////////////////
61 // Set up preview update and preview mode toggle...
62 P.e.btnSubmit.addEventListener('click', ()=>P.preview(), false);
63 P.e.btnTogglePreviewMode.addEventListener('click', function(){
64 /* Rotate through the 4 available preview modes */
65 P.previewMode = ++P.previewMode % 4;
66 P.renderPreview();
67 }, false);
68 P.e.selectMarkupAlignment.addEventListener('change', function(ev){
@@ -186,11 +190,12 @@
186 D.addClass(preTgt, 'error');
187 this.e.previewModeLabel.innerText = "Error";
188 return;
189 }
190 D.removeClass(preTgt, 'error');
191 D.enable(this.e.btnTogglePreviewMode);
 
192 let label;
193 switch(this.previewMode){
194 case 0:
195 label = "Rendered SVG";
196 preTgt.innerHTML = this.response.raw;
@@ -218,12 +223,11 @@
218 label = "Raw SVG";
219 this.e.taPreviewText.value = this.response.raw.replace(f.rxNonce, '');
220 D.append(D.clearElement(preTgt), this.e.taPreviewText);
221 break;
222 }
223 D.append(D.clearElement(this.e.previewModeLabel),
224 label, this.e.btnCopy);
225 };
226
227 /**
228 Fetches the preview from the server and updates the preview to
229 the rendered SVG content or error report.
@@ -233,11 +237,11 @@
233 fp.toDisable = [
234 /* input elements to disable during ajax operations */
235 this.e.btnSubmit, this.e.taContent,
236 this.e.selectMarkupAlignment,
237 this.e.cbAutoPreview, this.e.selectScript
238 /* this.e.btnTogglePreviewMode is handled separately */
239 ];
240 fp.target = this.e.previewTarget;
241 fp.updateView = function(c,isError){
242 P.previewMode = 0;
243 P.response.raw = c;
@@ -244,11 +248,12 @@
244 P.response.isError = isError;
245 D.enable(fp.toDisable);
246 P.renderPreview();
247 };
248 }
249 D.disable(fp.toDisable, this.e.btnTogglePreviewMode);
 
250 const content = this.e.taContent.value.trim();
251 this.response.raw = undefined;
252 this.response.inputText = content;
253 if(!content){
254 fp.updateView("No pikchr content!",true);
255
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -19,22 +19,28 @@
19 };
20 F.onPageLoad(function() {
21 document.body.classList.add('pikchrshow');
22 P.e = { /* various DOM elements we work with... */
23 previewTarget: E('#pikchrshow-output'),
24 previewLegend: E('#pikchrshow-output-wrapper > legend'),
25 previewModeLabel: D.span(/*holds the text for the preview mode label*/),
26 previewCopyButton: D.addClass(D.span(), 'copy-button'),
27 btnSubmit: E('#pikchr-submit-preview'),
28 cbDarkMode: E('#flipcolors-wrapper > input[type=checkbox]'),
29 taContent: E('#content'),
30 taPreviewText: D.attr(D.textarea(), 'rows', 20, 'cols', 60,
31 'readonly', true),
32 uiControls: E('#pikchrshow-controls'),
33 previewModeToggle: D.button("Preview mode"),
34 selectMarkupAlignment: D.select()
35 };
36 ////////////////////////////////////////////////////////////
37 // Setup the preview fieldset's LEGEND element...
38 D.append( P.e.previewLegend,
39 P.e.previewModeToggle,
40 P.e.previewModeLabel,
41 P.e.previewCopyButton );
42
43 ////////////////////////////////////////////////////////////
44 // Setup markup alignment selection...
45 D.append(P.e.uiControls, P.e.selectMarkupAlignment);
46 D.disable(D.option(P.e.selectMarkupAlignment, '', 'Markup Alignment'));
@@ -42,14 +48,12 @@
48 D.option(P.e.selectMarkupAlignment, ndx ? val : '', val);
49 });
50
51 ////////////////////////////////////////////////////////////
52 // Setup clipboard-copy of markup/SVG...
53 F.copyButton(P.e.previewCopyButton, {copyFromElement: P.e.taPreviewText});
54 P.e.previewCopyButton.addEventListener('text-copied', D.flashOnce.eventHandler, false);
 
 
55
56 ////////////////////////////////////////////////////////////
57 // Set up dark mode simulator...
58 P.e.cbDarkMode.addEventListener('change', function(ev){
59 if(ev.target.checked) D.addClass(P.e.previewTarget, 'dark-mode');
@@ -58,11 +62,11 @@
62 if(P.e.cbDarkMode.checked) D.addClass(P.e.previewTarget, 'dark-mode');
63
64 ////////////////////////////////////////////////////////////
65 // Set up preview update and preview mode toggle...
66 P.e.btnSubmit.addEventListener('click', ()=>P.preview(), false);
67 P.e.previewModeToggle.addEventListener('click', function(){
68 /* Rotate through the 4 available preview modes */
69 P.previewMode = ++P.previewMode % 4;
70 P.renderPreview();
71 }, false);
72 P.e.selectMarkupAlignment.addEventListener('change', function(ev){
@@ -186,11 +190,12 @@
190 D.addClass(preTgt, 'error');
191 this.e.previewModeLabel.innerText = "Error";
192 return;
193 }
194 D.removeClass(preTgt, 'error');
195 D.removeClass(P.e.previewCopyButton, 'disabled');
196 D.enable(this.e.previewModeToggle);
197 let label;
198 switch(this.previewMode){
199 case 0:
200 label = "Rendered SVG";
201 preTgt.innerHTML = this.response.raw;
@@ -218,12 +223,11 @@
223 label = "Raw SVG";
224 this.e.taPreviewText.value = this.response.raw.replace(f.rxNonce, '');
225 D.append(D.clearElement(preTgt), this.e.taPreviewText);
226 break;
227 }
228 this.e.previewModeLabel.innerText = label;
 
229 };
230
231 /**
232 Fetches the preview from the server and updates the preview to
233 the rendered SVG content or error report.
@@ -233,11 +237,11 @@
237 fp.toDisable = [
238 /* input elements to disable during ajax operations */
239 this.e.btnSubmit, this.e.taContent,
240 this.e.selectMarkupAlignment,
241 this.e.cbAutoPreview, this.e.selectScript
242 /* this.e.previewModeToggle is handled separately */
243 ];
244 fp.target = this.e.previewTarget;
245 fp.updateView = function(c,isError){
246 P.previewMode = 0;
247 P.response.raw = c;
@@ -244,11 +248,12 @@
248 P.response.isError = isError;
249 D.enable(fp.toDisable);
250 P.renderPreview();
251 };
252 }
253 D.disable(fp.toDisable, this.e.previewModeToggle);
254 D.addClass(this.e.previewCopyButton, 'disabled');
255 const content = this.e.taContent.value.trim();
256 this.response.raw = undefined;
257 this.response.inputText = content;
258 if(!content){
259 fp.updateView("No pikchr content!",true);
260
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -86,11 +86,11 @@
8686
CX("#pikchrshow-output {flex: 5 1 auto; padding: 0}");
8787
CX("#pikchrshow-output > pre, "
8888
"#pikchrshow-output > pre > div, "
8989
"#pikchrshow-output > pre > div > pre "
9090
"{margin: 0; padding: 0}");
91
- CX("#pikchrshow-output > pre > div > pre "
91
+ CX("#pikchrshow-output.error > pre "
9292
/* Server-side error report */
9393
"{padding: 0.5em}");
9494
CX("#pikchrshow-controls {" /* where the buttons live */
9595
"display: flex; flex-direction: row; "
9696
"align-items: center; flex-wrap: wrap;"
@@ -106,11 +106,11 @@
106106
"filter: invert(1) hue-rotate(180deg);"
107107
"}");
108108
CX("#sbs-wrapper > fieldset {"
109109
"padding: 0.25em 0.5em; border-radius: 0.25em;"
110110
"}");
111
- CX("fieldset > legend > .copy-button {margin-left: 0.25em}");
111
+ CX("fieldset > legend > * {margin-right: 0.25em}");
112112
CX(".dragover {border: 0.5em dotted rgba(0,255,0,0.6)}");
113113
CX("</style>");
114114
CX("<div>Input pikchr code and tap Preview to render it:</div>");
115115
CX("<div id='sbs-wrapper'>");
116116
CX("<div id='pikchrshow-form'>");
@@ -122,11 +122,11 @@
122122
"Dark mode?",
123123
"1", flipColors, 0);
124124
CX("</div>"/*#pikchrshow-controls*/);
125125
CX("</div>"/*#pikchrshow-form*/);
126126
CX("<fieldset id='pikchrshow-output-wrapper'>");
127
- CX("<legend>Preview <span class='copy-button'></span></legend>");
127
+ CX("<legend></legend>");
128128
CX("<div id='pikchrshow-output'>");
129129
if(*zContent){
130130
int w = 0, h = 0;
131131
char *zOut = pikchr(zContent, "pikchr", 0, &w, &h);
132132
if( w>0 && h>0 ){
133133
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -86,11 +86,11 @@
86 CX("#pikchrshow-output {flex: 5 1 auto; padding: 0}");
87 CX("#pikchrshow-output > pre, "
88 "#pikchrshow-output > pre > div, "
89 "#pikchrshow-output > pre > div > pre "
90 "{margin: 0; padding: 0}");
91 CX("#pikchrshow-output > pre > div > pre "
92 /* Server-side error report */
93 "{padding: 0.5em}");
94 CX("#pikchrshow-controls {" /* where the buttons live */
95 "display: flex; flex-direction: row; "
96 "align-items: center; flex-wrap: wrap;"
@@ -106,11 +106,11 @@
106 "filter: invert(1) hue-rotate(180deg);"
107 "}");
108 CX("#sbs-wrapper > fieldset {"
109 "padding: 0.25em 0.5em; border-radius: 0.25em;"
110 "}");
111 CX("fieldset > legend > .copy-button {margin-left: 0.25em}");
112 CX(".dragover {border: 0.5em dotted rgba(0,255,0,0.6)}");
113 CX("</style>");
114 CX("<div>Input pikchr code and tap Preview to render it:</div>");
115 CX("<div id='sbs-wrapper'>");
116 CX("<div id='pikchrshow-form'>");
@@ -122,11 +122,11 @@
122 "Dark mode?",
123 "1", flipColors, 0);
124 CX("</div>"/*#pikchrshow-controls*/);
125 CX("</div>"/*#pikchrshow-form*/);
126 CX("<fieldset id='pikchrshow-output-wrapper'>");
127 CX("<legend>Preview <span class='copy-button'></span></legend>");
128 CX("<div id='pikchrshow-output'>");
129 if(*zContent){
130 int w = 0, h = 0;
131 char *zOut = pikchr(zContent, "pikchr", 0, &w, &h);
132 if( w>0 && h>0 ){
133
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -86,11 +86,11 @@
86 CX("#pikchrshow-output {flex: 5 1 auto; padding: 0}");
87 CX("#pikchrshow-output > pre, "
88 "#pikchrshow-output > pre > div, "
89 "#pikchrshow-output > pre > div > pre "
90 "{margin: 0; padding: 0}");
91 CX("#pikchrshow-output.error > pre "
92 /* Server-side error report */
93 "{padding: 0.5em}");
94 CX("#pikchrshow-controls {" /* where the buttons live */
95 "display: flex; flex-direction: row; "
96 "align-items: center; flex-wrap: wrap;"
@@ -106,11 +106,11 @@
106 "filter: invert(1) hue-rotate(180deg);"
107 "}");
108 CX("#sbs-wrapper > fieldset {"
109 "padding: 0.25em 0.5em; border-radius: 0.25em;"
110 "}");
111 CX("fieldset > legend > * {margin-right: 0.25em}");
112 CX(".dragover {border: 0.5em dotted rgba(0,255,0,0.6)}");
113 CX("</style>");
114 CX("<div>Input pikchr code and tap Preview to render it:</div>");
115 CX("<div id='sbs-wrapper'>");
116 CX("<div id='pikchrshow-form'>");
@@ -122,11 +122,11 @@
122 "Dark mode?",
123 "1", flipColors, 0);
124 CX("</div>"/*#pikchrshow-controls*/);
125 CX("</div>"/*#pikchrshow-form*/);
126 CX("<fieldset id='pikchrshow-output-wrapper'>");
127 CX("<legend></legend>");
128 CX("<div id='pikchrshow-output'>");
129 if(*zContent){
130 int w = 0, h = 0;
131 char *zOut = pikchr(zContent, "pikchr", 0, &w, &h);
132 if( w>0 && h>0 ){
133

Keyboard Shortcuts

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