| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| (function(){ |
| 'use strict'; |
| |
| |
|
|
| const storage = (function(NS){ |
| |
| |
| |
| 'use strict'; |
| NS = NS||{}; |
|
|
| |
| |
| |
| |
| |
| const tryStorage = function f(obj){ |
| if(!f.key) f.key = 'storage.access.check'; |
| try{ |
| obj.setItem(f.key, 'f'); |
| const x = obj.getItem(f.key); |
| obj.removeItem(f.key); |
| if(x!=='f') throw new Error(f.key+" failed") |
| return obj; |
| }catch(e){ |
| return undefined; |
| } |
| }; |
|
|
| |
| const $storage = |
| tryStorage(window.localStorage) |
| || tryStorage(window.sessionStorage) |
| || tryStorage({ |
| |
| $$$:{}, |
| setItem: function(k,v){this.$$$[k]=v}, |
| getItem: function(k){ |
| return this.$$$.hasOwnProperty(k) ? this.$$$[k] : undefined; |
| }, |
| removeItem: function(k){delete this.$$$[k]}, |
| clear: function(){this.$$$={}} |
| }); |
|
|
| |
| |
| |
| |
| |
| const $storageHolder = $storage.hasOwnProperty('$$$') ? $storage.$$$ : $storage; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const storageKeyPrefix = ( |
| $storageHolder===$storage |
| ? ( |
| (NS.config ? |
| (NS.config.projectCode || NS.config.projectName |
| || NS.config.shortProjectName) |
| : false) |
| || window.location.pathname |
| )+'::' : ( |
| '' |
| ) |
| ); |
|
|
| |
| |
| |
| |
| |
| |
| |
| NS.storage = { |
| storageKeyPrefix: storageKeyPrefix, |
| |
| |
| set: (k,v)=>$storage.setItem(storageKeyPrefix+k,v), |
| |
| setJSON: (k,v)=>$storage.setItem(storageKeyPrefix+k,JSON.stringify(v)), |
| |
| |
| get: (k,dflt)=>$storageHolder.hasOwnProperty( |
| storageKeyPrefix+k |
| ) ? $storage.getItem(storageKeyPrefix+k) : dflt, |
| |
| |
| |
| |
| getBool: function(k,dflt){ |
| return 'true'===this.get(k,''+(!!dflt)); |
| }, |
| |
| |
| |
| getJSON: function f(k,dflt){ |
| try { |
| const x = this.get(k,f); |
| return x===f ? dflt : JSON.parse(x); |
| } |
| catch(e){return dflt} |
| }, |
| |
| |
| contains: (k)=>$storageHolder.hasOwnProperty(storageKeyPrefix+k), |
| |
| remove: function(k){ |
| $storage.removeItem(storageKeyPrefix+k); |
| return this; |
| }, |
| |
| clear: function(){ |
| this.keys().forEach((k)=>$storage.removeItem(k)); |
| return this; |
| }, |
| |
| keys: ()=>Object.keys($storageHolder).filter((v)=>(v||'').startsWith(storageKeyPrefix)), |
| |
| |
| |
| isTransient: ()=>$storageHolder!==$storage, |
| |
| storageImplName: function(){ |
| if($storage===window.localStorage) return 'localStorage'; |
| else if($storage===window.sessionStorage) return 'sessionStorage'; |
| else return 'transient'; |
| }, |
|
|
| |
| |
| |
| |
| storageHelpDescription: function(){ |
| return { |
| localStorage: "Browser-local persistent storage with an "+ |
| "unspecified long-term lifetime (survives closing the browser, "+ |
| "but maybe not a browser upgrade).", |
| sessionStorage: "Storage local to this browser tab, "+ |
| "lost if this tab is closed.", |
| "transient": "Transient storage local to this invocation of this page." |
| }[this.storageImplName()]; |
| } |
| }; |
| return NS.storage; |
| })({}); |
|
|
|
|
| |
| const configStorageKey = 'sqlite3-fiddle-config'; |
|
|
| |
| |
| |
| |
| |
| |
| const SF |
| = window.SqliteFiddle = { |
| |
| config: { |
| |
| |
| |
| autoScrollOutput: true, |
| |
| |
| autoClearOutput: false, |
| |
| |
| |
| echoToConsole: false, |
| |
| sideBySide: true, |
| |
| swapInOut: false |
| }, |
| |
| |
| |
| |
| |
| |
| |
| |
| echo: function f(text) { |
| |
| |
| |
| |
| |
| if(!f._){ |
| f._ = document.getElementById('output'); |
| f._.value = ''; |
| } |
| if(arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); |
| else if(1===arguments.length && Array.isArray(text)) text = text.join(' '); |
| |
| |
| |
| |
| |
| if(null===text){ |
| f._.value = ''; |
| return; |
| }else if(this.echo._clearPending){ |
| delete this.echo._clearPending; |
| f._.value = ''; |
| } |
| if(this.config.echoToConsole) console.log(text); |
| if(this.jqTerm) this.jqTerm.echo(text); |
| f._.value += text + "\n"; |
| if(this.config.autoScrollOutput){ |
| f._.scrollTop = f._.scrollHeight; |
| } |
| }, |
| _msgMap: {}, |
| |
| |
| addMsgHandler: function f(type,callback){ |
| if(Array.isArray(type)){ |
| type.forEach((t)=>this.addMsgHandler(t, callback)); |
| return this; |
| } |
| (this._msgMap.hasOwnProperty(type) |
| ? this._msgMap[type] |
| : (this._msgMap[type] = [])).push(callback); |
| return this; |
| }, |
| |
| runMsgHandlers: function(msg){ |
| const list = (this._msgMap.hasOwnProperty(msg.type) |
| ? this._msgMap[msg.type] : false); |
| if(!list){ |
| console.warn("No handlers found for message type:",msg); |
| return false; |
| } |
| |
| list.forEach((f)=>f(msg)); |
| return true; |
| }, |
| |
| clearMsgHandlers: function(type){ |
| delete this._msgMap[type]; |
| return this; |
| }, |
| |
| wMsg: function(type,data,transferables){ |
| this.worker.postMessage({type, data}, transferables || []); |
| return this; |
| }, |
| |
| |
| |
| |
| resetDb: function(){ |
| if(window.confirm("Really destroy all content and tables " |
| +"in the (transient) db?")){ |
| this.wMsg('db-reset'); |
| } |
| return this; |
| }, |
| |
| storeConfig: function(){ |
| storage.setJSON(configStorageKey,this.config); |
| } |
| }; |
|
|
| if(1){ |
| const storedConfig = storage.getJSON(configStorageKey); |
| if(storedConfig){ |
| |
| |
| |
| |
| Object.keys(SF.config).forEach(function(k){ |
| if(storedConfig.hasOwnProperty(k)){ |
| SF.config[k] = storedConfig[k]; |
| } |
| }); |
| } |
| } |
|
|
| SF.worker = new Worker('fiddle-worker.js'+self.location.search); |
| SF.worker.onmessage = (ev)=>SF.runMsgHandlers(ev.data); |
| SF.addMsgHandler(['stdout', 'stderr'], (ev)=>SF.echo(ev.data)); |
| SF.addMsgHandler('sqlite-version', (ev)=>{ |
| const v = ev.data; |
| const a = E('#sqlite-version-link'); |
| const li = v.srcId.split(' '); |
| a.setAttribute('href', |
| |
| 'https://sqlite.org/src/info/'+li[2].substr(0,20) |
| ); |
| a.setAttribute('target', '_blank'); |
| a.innerText = [ |
| v.lib, |
| v.srcId.substr(0,34) |
| ].join(' '); |
| SF.echo("SQLite version",a.innerText); |
| }); |
| SF.addMsgHandler('wasm-info', (ev)=>{ |
| const v = ev.data; |
| SF.e.wasmInfo.innerText = 'WASM: '+( |
| 4===v.pointerSize ? 32 : 64 |
| )+'-bit' |
| |
| |
| ; |
| }); |
|
|
| |
| const EAll = function(){ |
| return (arguments.length>1 ? arguments[0] : document) |
| .querySelectorAll(arguments[arguments.length-1]); |
| }; |
| |
| const E = function(){ |
| return (arguments.length>1 ? arguments[0] : document) |
| .querySelector(arguments[arguments.length-1]); |
| }; |
|
|
| |
| SF.addMsgHandler('module', function f(ev){ |
| ev = ev.data; |
| if('status'!==ev.type){ |
| console.warn("Unexpected module-type message:",ev); |
| return; |
| } |
| if(!f.ui){ |
| f.ui = { |
| status: E('#module-status'), |
| progress: E('#module-progress'), |
| spinner: E('#module-spinner') |
| }; |
| } |
| const msg = ev.data; |
| if(f.ui.progres){ |
| progress.value = msg.step; |
| progress.max = msg.step + 1; |
| } |
| if(1==msg.step){ |
| f.ui.progress.classList.remove('hidden'); |
| f.ui.spinner.classList.remove('hidden'); |
| } |
| if(msg.text){ |
| f.ui.status.classList.remove('hidden'); |
| f.ui.status.innerText = msg.text; |
| }else{ |
| if(f.ui.progress){ |
| f.ui.progress.remove(); |
| f.ui.spinner.remove(); |
| delete f.ui.progress; |
| delete f.ui.spinner; |
| } |
| f.ui.status.classList.add('hidden'); |
| |
| |
| |
| |
| } |
| }); |
|
|
| |
| |
| |
| |
| SF.addMsgHandler('fiddle-ready', function(){ |
| SF.clearMsgHandlers('fiddle-ready'); |
| self.onSFLoaded(); |
| }); |
|
|
| SF.e ={ |
| about: E('#view-about'), |
| split: E('#view-split'), |
| wasmInfo: E('#opt-wasm-info'), |
| terminal: E('#view-terminal'), |
| hideInTerminal: EAll('.hide-in-terminal' |
| ) |
| }; |
| SF.eViews = EAll('.app-view'); |
| SF.setMainView = function(eMain){ |
| if( SF.e.main === eMain ) return; |
| SF.eViews.forEach((e)=>{ |
| if( e===eMain ) e.classList.remove('hidden'); |
| else e.classList.add('hidden'); |
| }); |
| SF.e.hideInTerminal.forEach(e=>{ |
| if( eMain === SF.e.terminal ) e.classList.add('hidden'); |
| else e.classList.remove('hidden'); |
| }); |
| SF.e.main = eMain; |
| SF.ForceResizeKludge(); |
| }; |
|
|
| |
| SF.toggleAbout = function(){ |
| if( SF.e.about.classList.contains('hidden') ){ |
| SF.e.about.$returnTo = SF.e.main; |
| SF.setMainView( SF.e.about ); |
| }else{ |
| const e = SF.e.about.$returnTo; |
| delete SF.e.about.$returnTo; |
| SF.setMainView( e ); |
| } |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const effectiveHeight = function f(e){ |
| if(!e) return 0; |
| if(!f.measure){ |
| f.measure = function callee(e, depth){ |
| if(!e) return; |
| const m = e.getBoundingClientRect(); |
| if(0===depth){ |
| callee.top = m.top; |
| callee.bottom = m.bottom; |
| }else{ |
| callee.top = m.top ? Math.min(callee.top, m.top) : callee.top; |
| callee.bottom = Math.max(callee.bottom, m.bottom); |
| } |
| Array.prototype.forEach.call(e.children,(e)=>callee(e,depth+1)); |
| if(0===depth){ |
| |
| f.extra += callee.bottom - callee.top; |
| } |
| return f.extra; |
| }; |
| } |
| f.extra = 0; |
| f.measure(e,0); |
| return f.extra; |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const debounce = function f(func, wait, immediate) { |
| var timeout; |
| if(!wait) wait = f.$defaultDelay; |
| return function() { |
| const context = this, args = Array.prototype.slice.call(arguments); |
| const later = function() { |
| timeout = undefined; |
| if(!immediate) func.apply(context, args); |
| }; |
| const callNow = immediate && !timeout; |
| clearTimeout(timeout); |
| timeout = setTimeout(later, wait); |
| if(callNow) func.apply(context, args); |
| }; |
| }; |
| debounce.$defaultDelay = 500 ; |
|
|
| SF.ForceResizeKludge = (function(){ |
| |
| |
| |
| |
| |
| |
| const eVisibles = EAll('.app-view'); |
| const elemsToCount = [ |
| |
| |
| E('body > header'), |
| E('body > footer'), |
| E('body > fieldset.options') |
| ]; |
| const resized = function f(){ |
| if(f.$disabled) return; |
| const wh = window.innerHeight; |
| var ht; |
| var extra = 0; |
| elemsToCount.forEach((e)=>e ? extra += effectiveHeight(e) : false); |
| ht = wh - extra; |
| eVisibles.forEach(function(e){ |
| e.style.height = |
| e.style.maxHeight = [ |
| "calc(", (ht>=100 ? ht : 100), "px", |
| " - 2em",")" |
| |
| |
| |
| ].join(''); |
| }); |
| }; |
| resized.$disabled = true; |
| window.addEventListener('resize', debounce(resized, 250), false); |
| return resized; |
| })(); |
|
|
| |
| |
| |
| |
| |
| self.onSFLoaded = function(){ |
| delete this.onSFLoaded; |
|
|
| |
| EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden')); |
| SF.e.main = EAll('.app-view:not(.hidden)')[0] |
| |
| ; |
| if( (new URL(self.location.href).searchParams).has('about') ){ |
| SF.toggleAbout() ; |
| } |
| E('#btn-reset').addEventListener('click',()=>SF.resetDb()); |
| EAll('#btn-about, #btn-about-close').forEach((e)=>{ |
| e.addEventListener('click',()=>SF.toggleAbout()) |
| }); |
| const taInput = E('#input'); |
| const btnClearIn = E('#btn-clear'); |
| const selectExamples = E('#select-examples'); |
| btnClearIn.addEventListener('click',function(){ |
| taInput.value = ''; |
| selectExamples.selectedIndex = 0; |
| },false); |
| |
| taInput.addEventListener('keydown',function(ev){ |
| if((ev.ctrlKey || ev.shiftKey) && 13 === ev.keyCode){ |
| ev.preventDefault(); |
| ev.stopPropagation(); |
| btnShellExec.click(); |
| } |
| }, false); |
| const taOutput = E('#output'); |
| const btnClearOut = E('#btn-clear-output'); |
| btnClearOut.addEventListener('click',function(){ |
| taOutput.value = ''; |
| if(SF.jqTerm) SF.jqTerm.clear(); |
| },false); |
| const btnShellExec = E('#btn-shell-exec'); |
| btnShellExec.addEventListener('click',function(ev){ |
| let sql; |
| ev.preventDefault(); |
| if(taInput.selectionStart<taInput.selectionEnd){ |
| sql = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim(); |
| }else{ |
| sql = taInput.value.trim(); |
| } |
| if(sql) SF.dbExec(sql); |
| },false); |
|
|
| const btnInterrupt = E("#btn-interrupt"); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const preStartWork = function f(){ |
| if(!f._){ |
| const title = E('title'); |
| f._ = { |
| btnLabel: btnShellExec.innerText, |
| pageTitle: title, |
| pageTitleOrig: title.innerText |
| }; |
| } |
| f._.pageTitle.innerText = "[working...] "+f._.pageTitleOrig; |
| btnShellExec.setAttribute('disabled','disabled'); |
| btnInterrupt.removeAttribute('disabled','disabled'); |
| }; |
|
|
| |
| |
| |
| SF.dbExec = function f(sql){ |
| if(null!==sql && this.config.autoClearOutput){ |
| this.echo._clearPending = true; |
| } |
| preStartWork(); |
| this.wMsg('shellExec',sql); |
| }; |
|
|
| SF.addMsgHandler('working',function f(ev){ |
| switch(ev.data){ |
| case 'start': ; return; |
| case 'end': |
| preStartWork._.pageTitle.innerText = preStartWork._.pageTitleOrig; |
| btnShellExec.innerText = preStartWork._.btnLabel; |
| btnShellExec.removeAttribute('disabled'); |
| btnInterrupt.setAttribute('disabled','disabled'); |
| return; |
| } |
| console.warn("Unhandled 'working' event:",ev.data); |
| }); |
|
|
| |
| |
| |
| EAll('input[type=checkbox][data-csstgt]') |
| .forEach(function(e){ |
| const tgt = E(e.dataset.csstgt); |
| const cssClass = e.dataset.cssclass || 'error'; |
| e.checked = tgt.classList.contains(cssClass); |
| e.addEventListener('change', function(){ |
| tgt.classList[ |
| this.checked ? 'add' : 'remove' |
| ](cssClass) |
| }, false); |
| }); |
| |
| |
| |
| EAll('input[type=checkbox][data-config]') |
| .forEach(function(e){ |
| const confVal = !!SF.config[e.dataset.config]; |
| if(e.checked !== confVal){ |
| |
| |
| e.checked = confVal; |
| e.dispatchEvent(new Event('change')); |
| } |
| e.addEventListener('change', function(){ |
| SF.config[this.dataset.config] = this.checked; |
| SF.storeConfig(); |
| }, false); |
| }); |
| |
| |
| const cmdClick = function(){SF.dbExec(this.dataset.cmd);}; |
| EAll('button[data-cmd]').forEach( |
| e => e.addEventListener('click', cmdClick, false) |
| ); |
|
|
| btnInterrupt.addEventListener('click',function(){ |
| SF.wMsg('interrupt'); |
| }); |
|
|
| |
| const btnExport = E('#btn-export'); |
| const eLoadDb = E('#load-db'); |
| const btnLoadDb = E('#btn-load-db'); |
| btnLoadDb.addEventListener('click', ()=>eLoadDb.click()); |
| |
| |
| |
| |
| |
| const enableMutatingElements = function f(enable){ |
| if(!f._elems){ |
| f._elems = [ |
| |
| |
| |
| |
| |
| btnShellExec, btnExport, eLoadDb |
| ]; |
| } |
| f._elems.forEach( enable |
| ? (e)=>e.removeAttribute('disabled') |
| : (e)=>e.setAttribute('disabled','disabled') ); |
| }; |
| btnExport.addEventListener('click',function(){ |
| enableMutatingElements(false); |
| SF.wMsg('db-export'); |
| }); |
| SF.addMsgHandler('db-export', function(ev){ |
| enableMutatingElements(true); |
| ev = ev.data; |
| if(ev.error){ |
| SF.echo("Export failed:",ev.error); |
| return; |
| } |
| const blob = new Blob([ev.buffer], |
| {type:"application/x-sqlite3"}); |
| const a = document.createElement('a'); |
| document.body.appendChild(a); |
| a.href = window.URL.createObjectURL(blob); |
| a.download = ev.filename; |
| a.addEventListener('click',function(){ |
| setTimeout(function(){ |
| SF.echo("Exported (possibly auto-downloaded):",ev.filename); |
| window.URL.revokeObjectURL(a.href); |
| a.remove(); |
| },500); |
| }); |
| a.click(); |
| }); |
| |
| |
| |
| eLoadDb.addEventListener('change',function(){ |
| const f = this.files[0]; |
| const r = new FileReader(); |
| const status = {loaded: 0, total: 0}; |
| enableMutatingElements(false); |
| r.addEventListener('loadstart', function(){ |
| SF.echo("Loading",f.name,"..."); |
| }); |
| r.addEventListener('progress', function(ev){ |
| SF.echo("Loading progress:",ev.loaded,"of",ev.total,"bytes."); |
| }); |
| const that = this; |
| r.addEventListener('load', function(){ |
| enableMutatingElements(true); |
| SF.echo("Loaded",f.name+". Opening db..."); |
| SF.wMsg('open',{ |
| filename: f.name, |
| buffer: this.result |
| }, [this.result]); |
| }); |
| r.addEventListener('error',function(){ |
| enableMutatingElements(true); |
| SF.echo("Loading",f.name,"failed for unknown reasons."); |
| }); |
| r.addEventListener('abort',function(){ |
| enableMutatingElements(true); |
| SF.echo("Cancelled loading of",f.name+"."); |
| }); |
| r.readAsArrayBuffer(f); |
| }); |
|
|
| EAll('fieldset.collapsible').forEach(function(fs){ |
| const btnToggle = E(fs,'legend > .fieldset-toggle'), |
| content = EAll(fs,':scope > div'); |
| btnToggle.addEventListener('click', function(){ |
| fs.classList.toggle('collapsed'); |
| content.forEach((d)=>d.classList.toggle('hidden')); |
| }, false); |
| }); |
|
|
| |
| (function(){ |
| const xElem = E('#select-examples'); |
| const examples = [ |
| {name: "Help", sql: [ |
| "-- ================================================\n", |
| "-- Use ctrl-enter or shift-enter to execute sqlite3\n", |
| "-- shell commands and SQL.\n", |
| "-- If a subset of the text is currently selected,\n", |
| "-- only that part is executed.\n", |
| "-- ================================================\n", |
| ".help\n" |
| ]}, |
| |
| |
| {name: "Box Mode", sql: ".mode box"}, |
| {name: "Setup table T", sql:[ |
| ".nullvalue NULL\n", |
| "CREATE TABLE t(a,b);\n", |
| "INSERT INTO t(a,b) VALUES('abc',123),('def',456),(NULL,789),('ghi',012);\n", |
| "SELECT * FROM t;\n" |
| ]}, |
| {name: "sqlite_schema", sql: "select * from sqlite_schema"}, |
| {name: "Mandelbrot", sql:[ |
| "WITH RECURSIVE", |
| " xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+0.05 FROM xaxis WHERE x<1.2),\n", |
| " yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+0.1 FROM yaxis WHERE y<1.0),\n", |
| " m(iter, cx, cy, x, y) AS (\n", |
| " SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis\n", |
| " UNION ALL\n", |
| " SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m \n", |
| " WHERE (x*x + y*y) < 4.0 AND iter<28\n", |
| " ),\n", |
| " m2(iter, cx, cy) AS (\n", |
| " SELECT max(iter), cx, cy FROM m GROUP BY cx, cy\n", |
| " ),\n", |
| " a(t) AS (\n", |
| " SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') \n", |
| " FROM m2 GROUP BY cy\n", |
| " )\n", |
| "SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;\n", |
| ]}, |
| {name: "JSON pretty-print", |
| sql: "select json_pretty(json_object('ex',json('[52,3.14159]')))" |
| }, |
| {name: "JSON pretty-print (with tabs)", |
| sql: "select json_pretty(json_object('ex',json('[52,3.14159]')),char(0x09))" |
| } |
| ]; |
| const newOpt = function(lbl,val){ |
| const o = document.createElement('option'); |
| if(Array.isArray(val)) val = val.join(''); |
| o.value = val; |
| if(!val) o.setAttribute('disabled',true); |
| o.appendChild(document.createTextNode(lbl)); |
| xElem.appendChild(o); |
| }; |
| newOpt("Examples (replaces input!)"); |
| examples.forEach((o)=>newOpt(o.name, o.sql)); |
| |
| xElem.selectedIndex = 0; |
| xElem.addEventListener('change', function(){ |
| taInput.value = '-- ' + |
| this.selectedOptions[0].innerText + |
| '\n' + this.value; |
| SF.dbExec(this.value); |
| }); |
| })(); |
|
|
| |
| if(window.jQuery && window.jQuery.terminal && SF.e.terminal){ |
| |
| const jqeTerm = window.jQuery(SF.e.terminal).empty(); |
| SF.jqTerm = jqeTerm.terminal(SF.dbExec.bind(SF),{ |
| prompt: 'sqlite> ', |
| greetings: false |
| }); |
| EAll('.unhide-if-terminal-available').forEach(e=>{ |
| e.classList.remove('hidden'); |
| }); |
| EAll('.remove-if-terminal-available').forEach(e=>{ |
| e.parentElement.removeChild(e); |
| }); |
| |
| const ePlaceholder = E('#terminal-button-placeholder'); |
| ePlaceholder.classList.add('labeled-input'); |
| ePlaceholder.classList.remove('hidden'); |
| const btnToggleView = document.createElement('button'); |
| btnToggleView.innerText = "Toggle view"; |
| ePlaceholder.appendChild( btnToggleView ); |
| btnToggleView.addEventListener('click',function f(){ |
| const terminalOn = document.body.classList.toggle('terminal-mode'); |
| SF.setMainView( terminalOn ? SF.e.terminal : SF.e.split ); |
| }, false); |
| btnToggleView.click(); |
| } |
| const urlParams = new URL(self.location.href).searchParams; |
| SF.dbExec(urlParams.get('sql') || null); |
| delete SF.ForceResizeKludge.$disabled; |
| SF.ForceResizeKludge(); |
| }; |
| })(); |
|
|