1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

fiddle: modernized the UI based on related code in fossil's /pikchrshow. Changed the color scheme to match sqlite.org.

FossilOrigin-Name: c4523ffcc076e9cddba62c3b832f9a04d4f3c5595a312ac74099927aae085a52
This commit is contained in:
stephan
2022-06-10 09:31:12 +00:00
parent 65458dc146
commit 0c2b00b0d6
5 changed files with 139 additions and 112 deletions

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>sqlite3 fiddle</title> <title>SQLite3 Fiddle</title>
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon"> <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<!-- to add a togglable terminal-style view, uncomment the following <!-- to add a togglable terminal-style view, uncomment the following
two lines and ensure that these files are on the web server. --> two lines and ensure that these files are on the web server. -->
@ -12,50 +12,91 @@
<link rel="stylesheet" href="emscripten.css"/> <link rel="stylesheet" href="emscripten.css"/>
<style> <style>
/* The following styles are for app-level use. */ /* The following styles are for app-level use. */
:root {
--sqlite-blue: #044a64;
}
textarea { textarea {
font-family: monospace; font-family: monospace;
flex: 1 1 auto; flex: 1 1 auto;
background-color: var(--sqlite-blue);
color: white;
} }
header { header {
font-size: 130%; display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--sqlite-blue);
color: white;
font-size: 120%;
font-weight: bold; font-weight: bold;
border-radius: 0.25em;
padding: 0.2em 0.5em;
}
header > .powered-by {
font-size: 80%;
}
header a, header a:visited, header a:hover {
color: inherit;
} }
#main-wrapper { #main-wrapper {
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;
flex: 20 1 auto; flex: 1 1 auto;
margin: 0.5em 0;
overflow: hidden;
} }
#main-wrapper.side-by-side { #main-wrapper.side-by-side {
flex-direction: row-reverse; flex-direction: row;
}
#main-wrapper.side-by-side > fieldset {
margin-left: 0.25em;
margin-right: 0.25em;
}
#main-wrapper:not(.side-by-side) > fieldset {
margin-bottom: 0.25em;
} }
#main-wrapper.swapio { #main-wrapper.swapio {
flex-direction: column; flex-direction: column;
} }
#main-wrapper.side-by-side.swapio { #main-wrapper.side-by-side.swapio {
flex-direction: row; flex-direction: row-reverse;
} }
.ta-wrapper{ .zone-wrapper{
display: flex; display: flex;
flex-direction: column; margin: 0;
align-items: stretch; flex: 1 1 0%;
margin: 0 0.25em; border-radius: 0.5em;
min-width: inherit/*important: resolves inability to scroll fieldset child element!*/;
padding: 0.35em 0 0 0;
}
.zone-wrapper textarea {
border-radius: 0.5em;
flex: 1 1 auto; flex: 1 1 auto;
/*min/max width resolve an inexplicable margin on the RHS. The -1em
is for the padding, else we overlap the parent boundaries.*/
/*min-width: calc(100% - 1em);
max-width: calc(100% - 1em);
padding: 0 0.5em;*/
} }
.ta-wrapper.input { flex: 10 1 auto; }
.ta-wrapper.output { flex: 20 1 auto; } .zone-wrapper.input { flex: 10 1 auto; }
.ta-wrapper textarea { .zone-wrapper.output { flex: 20 1 auto; }
font-size: 110%; .zone-wrapper > div {
filter: invert(100%); display:flex;
flex: 10 1 auto; flex: 1 1 0%;
} }
.zone-wrapper.output {}
.button-bar { .button-bar {
display: flex; display: flex;
justify-content: center;
flex: 0 1 auto;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center;
align-content: space-between;
justify-content: flex-start;
} }
.button-bar button { .button-bar > * {
margin: 0.25em 1em; margin: 0.05em 0.5em 0.05em 0;
flex: 0 1 auto;
align-self: auto;
} }
label[for] { label[for] {
cursor: pointer; cursor: pointer;
@ -70,86 +111,52 @@
pointer-events: none !important; pointer-events: none !important;
display: none !important; display: none !important;
} }
/* Safari supports neither styling of nor event handling on a fieldset.options {
fieldset legend, so we emulate a fieldset-like widget. */
.fieldset {
border-radius: 0.5em; border-radius: 0.5em;
border: 1px inset; border: 1px inset;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0.25em;
} }
.fieldset > .legend { fieldset.options > div {
position: relative;
top: -1.5ex;
padding: 0 0.5em;
font-size: 85%;
margin-left: 0.5em;
flex: 0 1 auto;
align-self: self-start;
cursor: pointer;
}
.fieldset.options > div {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
font-size: 70%; font-size: 85%;
margin: 0 0.5em 0.5em 0.5em;
} }
.fieldset > .legend > span { fieldset > legend {
position: relative; font-size: 85%;
} }
.fieldset > .legend::before { fieldset.collapsible > legend > .fieldset-toggle::after {
/* Hide the parent element's top border where this
element intersects it. */
content: ' ';
width: 100%;
height: 100%;
background-color: white
/* REALLY want to 'inherit' the color from the fieldset's
parent, but inherit leads to a transparent bg, which is
exactly what we're trying to avoid here. */;
opacity: 1;
position: absolute;
top: 0;
left: 0;
}
.fieldset > .legend::after {
content: " [hide]"; content: " [hide]";
position: relative; position: relative;
} }
.fieldset.collapsed > .legend::after { fieldset.collapsible.collapsed > legend > .fieldset-toggle::after {
content: " [show]"; content: " [show]";
position: relative; position: relative;
} }
span.labeled-input { span.labeled-input {
padding: 0.25em; padding: 0.25em;
margin: 0.25em 0.5em; margin: 0.05em 0.25em;
border-radius: 0.25em; border-radius: 0.25em;
white-space: nowrap; white-space: nowrap;
background: #0002; background: #0002;
display: flex;
align-items: center;
} }
#notes-caveats { span.labeled-input > *:nth-child(2) {
border-top: 1px dotted; margin-left: 0.3em;
padding-top: 0.25em;
margin-top: 0.5em;
} }
.center { text-align: center; } .center { text-align: center; }
body.terminal-mode { body.terminal-mode {
max-height: calc(100% - 2em); max-height: calc(100% - 2em);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
} }
#view-terminal { #view-terminal {}
}
.app-view { .app-view {
flex: 20 1 auto; flex: 20 1 auto;
} }
#titlebar {
display: flex;
justify-content: space-between;
margin-bottom: 0.5em;
}
#view-split { #view-split {
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;
@ -160,7 +167,11 @@
</style> </style>
</head> </head>
<body> <body>
<header id='titlebar'><span>sqlite3 fiddle</span></header> <header id='titlebar'>
<span>SQLite3 Fiddle</span>
<span class='powered-by'>Powered by
<a href='https://sqlite.org'>SQLite3</a></span>
</header>
<!-- emscripten bits --> <!-- emscripten bits -->
<figure id="module-spinner"> <figure id="module-spinner">
<div class="spinner"></div> <div class="spinner"></div>
@ -177,12 +188,13 @@
</div><!-- /emscripten bits --> </div><!-- /emscripten bits -->
<div id='view-terminal' class='app-view hidden initially-hidden'> <div id='view-terminal' class='app-view hidden initially-hidden'>
This is a placeholder for a terminal-like view. This is a placeholder for a terminal-like view which is not in
the default build.
</div> </div>
<div id='view-split' class='app-view initially-hidden'> <div id='view-split' class='app-view initially-hidden'>
<div class='fieldset options collapsible'> <fieldset class='options collapsible'>
<span class='legend'><span>Options</span></span> <legend><button class='fieldset-toggle'>Options</button></legend>
<div class=''> <div class=''>
<span class='labeled-input'> <span class='labeled-input'>
<input type='checkbox' id='opt-cb-sbs' <input type='checkbox' id='opt-cb-sbs'
@ -218,40 +230,40 @@
<span class='labeled-input'> <span class='labeled-input'>
<button id='btn-reset'>Reset DB</button> <button id='btn-reset'>Reset DB</button>
</span> </span>
<span class='labeled-input'>
<select id='select-examples'></select>
</span>
</div> </div>
</div><!-- .fieldset --> </fieldset><!-- .options -->
<div id='main-wrapper' class=''> <div id='main-wrapper' class=''>
<div class='ta-wrapper input'> <fieldset class='zone-wrapper input'>
<textarea id="input" <legend><div class='button-bar'>
placeholder="Shell input. Ctrl-enter/shift-enter runs it.">
-- Use ctrl-enter or shift-enter to execute SQL. If only a subset
-- is currently selected, only that part is executed.
.nullvalue NULL
.mode box
CREATE TABLE t(a,b);
INSERT INTO t(a,b) VALUES('abc',123),('def',456),(NULL,789),('ghi',012);
SELECT * FROM t;</textarea>
<div class='button-bar'>
<button id='btn-shell-exec'>Run</button> <button id='btn-shell-exec'>Run</button>
<button id='btn-clear'>Clear Input</button> <button id='btn-clear'>Clear Input</button>
<button data-cmd='.help'>Help</button> <!--button data-cmd='.help'>Help</button-->
</div> <select id='select-examples'></select>
</div> </div></legend>
<div class='ta-wrapper output'> <div><textarea id="input"
<textarea id="output" readonly placeholder="Shell input. Ctrl-enter/shift-enter runs it.">
placeholder="Shell output."></textarea> -- ==================================================
<div class='button-bar'> -- Use ctrl-enter or shift-enter to execute sqlite3
-- shell commands and SQL.
-- If a subset of the text is currently selected,
-- only that part is executed.
-- ==================================================
.nullvalue NULL
.headers on
</textarea></div>
</fieldset>
<fieldset class='zone-wrapper output'>
<legend><div class='button-bar'>
<button id='btn-clear-output'>Clear Output</button> <button id='btn-clear-output'>Clear Output</button>
<button id='btn-interrupt' class='hidden' disabled>Interrupt</button> <button id='btn-interrupt' class='hidden' disabled>Interrupt</button>
<!-- interruption cannot work in the current configuration <!-- interruption cannot work in the current configuration
because we cannot send an interrupt message when work because we cannot send an interrupt message when work
is currently underway. At that point the Worker is is currently underway. At that point the Worker is
tied up and will not receive the message. --> tied up and will not receive the message. -->
</div> </div></legend>
</div> <div><textarea id="output" readonly
placeholder="Shell output."></textarea></div>
</fieldset>
</div> </div>
</div> <!-- #view-split --> </div> <!-- #view-split -->
<!-- Maintenance notes: <!-- Maintenance notes:

View File

@ -216,7 +216,7 @@
That slows it down but is useful for testing. */ That slows it down but is useful for testing. */
echoToConsole: false, echoToConsole: false,
/* If true, display input/output areas side-by-side. */ /* If true, display input/output areas side-by-side. */
sideBySide: false, sideBySide: true,
/* If true, swap positions of the input/output areas. */ /* If true, swap positions of the input/output areas. */
swapInOut: false swapInOut: false
}, },
@ -607,15 +607,15 @@
r.readAsArrayBuffer(f); r.readAsArrayBuffer(f);
}); });
EAll('.fieldset.collapsible').forEach(function(fs){ EAll('fieldset.collapsible').forEach(function(fs){
const legend = E(fs,'span.legend'), const btnToggle = E(fs,'legend > .fieldset-toggle'),
content = EAll(fs,':scope > div'); content = EAll(fs,':scope > div');
legend.addEventListener('click', function(){ btnToggle.addEventListener('click', function(){
fs.classList.toggle('collapsed'); fs.classList.toggle('collapsed');
content.forEach((d)=>d.classList.toggle('hidden')); content.forEach((d)=>d.classList.toggle('hidden'));
}, false); }, false);
}); });
/** /**
Given a DOM element, this routine measures its "effective Given a DOM element, this routine measures its "effective
height", which is the bounding top/bottom range of this element height", which is the bounding top/bottom range of this element
@ -722,6 +722,14 @@
(function(){ (function(){
const xElem = E('#select-examples'); const xElem = E('#select-examples');
const examples = [ const examples = [
{name: "Help", sql:
`-- ================================================
-- Use ctrl-enter or shift-enter to execute sqlite3
-- shell commands and SQL.
-- If a subset of the text is currently selected,
-- only that part is executed.
-- ================================================
.help`},
{name: "Timer on", sql: ".timer on"}, {name: "Timer on", sql: ".timer on"},
{name: "Setup table T", sql:`.nullvalue NULL {name: "Setup table T", sql:`.nullvalue NULL
CREATE TABLE t(a,b); CREATE TABLE t(a,b);
@ -795,5 +803,7 @@ SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;`}
'any number of changes or outright removal at any time.\n'); 'any number of changes or outright removal at any time.\n');
delete ForceResizeKludge.$disabled; delete ForceResizeKludge.$disabled;
ForceResizeKludge(); ForceResizeKludge();
btnShellExec.click();
}/*onSFLoaded()*/; }/*onSFLoaded()*/;
})(); })();

View File

@ -119,11 +119,17 @@ INSERT INTO t(a,b) VALUES(1,2),(3,4),(?,?);`,
assert(3===db.selectValue("select bar(1,2)")). assert(3===db.selectValue("select bar(1,2)")).
assert(-1===db.selectValue("select bar(1,2,-4)")); assert(-1===db.selectValue("select bar(1,2,-4)"));
const eqApprox = function(v1,v2,factor=0.05){
return v1>=(v2-factor) && v1<=(v2+factor);
};
T.assert('hi' === db.selectValue("select ?",'hi')). T.assert('hi' === db.selectValue("select ?",'hi')).
assert(null===db.selectValue("select null")). assert(null===db.selectValue("select null")).
assert(null === db.selectValue("select ?",null)). assert(null === db.selectValue("select ?",null)).
assert(null === db.selectValue("select ?",[null])). assert(null === db.selectValue("select ?",[null])).
assert(null === db.selectValue("select $a",{$a:null})); assert(null === db.selectValue("select $a",{$a:null})).
assert(eqApprox(3.1,db.selectValue("select 3.0 + 0.1")))
;
}; };
const testAttach = function(db){ const testAttach = function(db){

View File

@ -1,5 +1,5 @@
C Do\snot\sallow\sthe\ssubtype\sof\sa\svalue\sto\scross\sa\ssubquery\sboundary.\s\sThis\nfixes\sthe\sproblem\sidentified\sby\n[forum:/forumpost/3d9caa45cbe38c78|forum\spost\s3d9caa45cbe38c78]. C fiddle:\smodernized\sthe\sUI\sbased\son\srelated\scode\sin\sfossil's\s/pikchrshow.\sChanged\sthe\scolor\sscheme\sto\smatch\ssqlite.org.
D 2022-06-09T20:26:06.297 D 2022-06-10T09:31:12.484
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -62,14 +62,14 @@ F ext/fiddle/Makefile e25d34a0e1324f771d64c09c592601b97219282011587e6ce410fa8acd
F ext/fiddle/SqliteTestUtil.js 559731c3e8e0de330ec7d292e6c1846566408caee6637acc8a119ac338a8781c F ext/fiddle/SqliteTestUtil.js 559731c3e8e0de330ec7d292e6c1846566408caee6637acc8a119ac338a8781c
F ext/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/fiddle/fiddle-worker.js 88bc2193a6cb6a3f04d8911bed50a4401fe6f277de7a71ba833865ab64a1b4ae F ext/fiddle/fiddle-worker.js 88bc2193a6cb6a3f04d8911bed50a4401fe6f277de7a71ba833865ab64a1b4ae
F ext/fiddle/fiddle.html c44f86abf286231fccfed9fd080fd17b200f5e5c05939e8080c810b6920a9326 F ext/fiddle/fiddle.html 78db023d56d04d12b4566864711ef34312c53ff25a0778d55dfd2a0a8a9f9f8d
F ext/fiddle/fiddle.js 6c20bf264cf26a570f9bf22e533adcc7250a6f183d482eaa725ccd0fa83a6d95 F ext/fiddle/fiddle.js 812f9954cc7c4b191884ad171f36fcf2d0112d0a7ecfdf6087896833a0c079a8
F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf
F ext/fiddle/sqlite3-api.js ccf4bd0c1c5bbb3be3469573423d6c53991941bec497eac63e9f17ea13bf8952 F ext/fiddle/sqlite3-api.js ccf4bd0c1c5bbb3be3469573423d6c53991941bec497eac63e9f17ea13bf8952
F ext/fiddle/sqlite3-worker.js a9c2b614beca187dbdd8c053ec2770cc61ec1ac9c0ec6398ceb49a79f705a421 F ext/fiddle/sqlite3-worker.js a9c2b614beca187dbdd8c053ec2770cc61ec1ac9c0ec6398ceb49a79f705a421
F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a
F ext/fiddle/testing1.html ea1f3be727f78e420007f823912c1a03b337ecbb8e79449abc2244ad4fe15d9a F ext/fiddle/testing1.html ea1f3be727f78e420007f823912c1a03b337ecbb8e79449abc2244ad4fe15d9a
F ext/fiddle/testing1.js 68715f4716a30aa4dab0ce954d465f662486c8bc96a19a4fc8edbea4ac211fd2 F ext/fiddle/testing1.js e2fa02ac8adbd21c69bc50cfcb79bfc26af0d30a8d6b95ac473a17e0dc9de733
F ext/fiddle/testing2.html 9063b2430ade2fe9da4e711addd1b51a2741cf0c7ebf6926472a5e5dd63c0bc4 F ext/fiddle/testing2.html 9063b2430ade2fe9da4e711addd1b51a2741cf0c7ebf6926472a5e5dd63c0bc4
F ext/fiddle/testing2.js 7b45b4e7fddbd51dbaf89b6722c02758051b34bac5a98c11b569a7e7572f88ee F ext/fiddle/testing2.js 7b45b4e7fddbd51dbaf89b6722c02758051b34bac5a98c11b569a7e7572f88ee
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
@ -1976,9 +1976,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 5abb5ef500f52c52dac33e54d824cf89481fec1643c27943f34f0ca4560a7e00 9e51a6c0fbfb1899b2b01888430125fba6d4da9bad9eeaa3ad41e29fca54bbe5 P bbaf1f2eb1e1637b356ed7ab1d1cf5bbc8e1fe3bb2fb46a8f37de091726f38af
R c35df4ec51cfa3b0337adabea0f5033f R 4297b03f01cbe8b046ff1e0ad3f9bad5
T +closed 9e51a6c0fbfb1899b2b01888430125fba6d4da9bad9eeaa3ad41e29fca54bbe5 U stephan
U drh Z 3f16792acb3b181df964e73f925d42be
Z 82d5ec3076328af16c21723acf89deff
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
bbaf1f2eb1e1637b356ed7ab1d1cf5bbc8e1fe3bb2fb46a8f37de091726f38af c4523ffcc076e9cddba62c3b832f9a04d4f3c5595a312ac74099927aae085a52