From 27964d0f8f054cbd48e9628939d093e7d1659abd Mon Sep 17 00:00:00 2001 From: Mark Simon Date: Thu, 2 Nov 2023 19:11:54 +1100 Subject: [PATCH] Version 0.7.1 Added shortcuts to phpMyAdmin patches. Reorganised the way Default Server paths work. Turn of spell checking in text area. --- data/data.txt | 0 data/sample-php.txt | 22 +++ data/servers.json | 18 ++- index.html | 33 +++-- main.js | 2 +- scripts/virtual-hosts.js | 238 +++++++++++++++++++------------ styles/main.css | 299 ++++++++++++++++++++++----------------- 7 files changed, 371 insertions(+), 241 deletions(-) create mode 100644 data/data.txt create mode 100644 data/sample-php.txt diff --git a/data/data.txt b/data/data.txt new file mode 100644 index 0000000..e69de29 diff --git a/data/sample-php.txt b/data/sample-php.txt new file mode 100644 index 0000000..61e9771 --- /dev/null +++ b/data/sample-php.txt @@ -0,0 +1,22 @@ + + +I got + hohoho +Good, innit? + + + Testing + + plan a + + plan b + + Finally + diff --git a/data/servers.json b/data/servers.json index ac9e80d..6297b5a 100644 --- a/data/servers.json +++ b/data/servers.json @@ -13,7 +13,8 @@ "mysql": "/xamppfiles/var/mysql", "phpini": "/xamppfiles/etc/php.ini", "phpmyadmin": "/xamppfiles/phpmyadmin/", - "phpcli": "/xamppfiles/bin/php" + "phpcli": "/xamppfiles/bin/php", + "phpmyadmin-config": "//\tAdditional Settings\n\t$cfg['AllowUserDropDatabase'] = true;\n\t$cfg['RetainQueryBox'] = true;\n" }, "win32": { "root": "C:/xampp", @@ -23,9 +24,11 @@ "mysql": "/mysql/data", "phpini": "/php/php.ini", "phpmyadmin": "/phpMyAdmin/", - "phpcli": "/php/php.exe" + "phpcli": "/php/php.exe", + "phpmyadmin-config": "\n" }, - "vhost": "" + "vhost": "", + "phpmyadmin-css": "/*\tAdditional Settings\n\t================================================ */\n\tform#sqlqueryform div.CodeMirror pre,\n\tform#sqlqueryform div.CodeMirror-linenumber {\n\t\tfont-size: 1.25rem;\n\t}\n" }, "mamp": { "darwin": { @@ -36,7 +39,8 @@ "mysql": "/db/mysql57", "phpini": "/bin/php/php{version}/conf/php.ini", "phpmyadmin": "/bin/phpmyadmin/", - "phpcli": "/bin/php/php{version}/bin/php" + "phpcli": "/bin/php/php{version}/bin/php", + "phpmyadmin-config": "\n" }, "win32": { "root": "C:/MAMP", @@ -46,9 +50,11 @@ "mysql": "/db/mysql", "phpini": "/conf/php{version}/php.ini", "phpmyadmin": "/bin/phpMyAdmin/", - "phpcli": "/bin/php/php{version}/php.exe" + "phpcli": "/bin/php/php{version}/php.exe", + "phpmyadmin-config": "\n" }, - "vhost": "" + "vhost": "", + "phpmyadmin-css": "/*\tAdditional Settings\n\t================================================ */\n\tform#sqlqueryform div.CodeMirror pre,\n\tform#sqlqueryform div.CodeMirror-linenumber {\n\t\tfont-size: 1.25rem;\n\t}\n" }, "ampps": { "darwin": { diff --git a/index.html b/index.html index 53eee8b..c8d17ba 100644 --- a/index.html +++ b/index.html @@ -41,6 +41,7 @@

Virtual Host Settings

  • Choose a Web Server Package
  • If you have installed the Web Server in a non-default location, select the folder.
  • If you prefer to use a different PHP Interpreter, choose the alternative interpreter executable.
  • +
  • Save the Settings for next time …
  • @@ -61,6 +62,7 @@

    Choose a Web Server Root Folder

    --> +

    Choose a PHP Interpreter

    @@ -70,6 +72,10 @@

    Choose a PHP Interpreter

    --> + +
    +
    +
    @@ -82,7 +88,7 @@

    Hosts File (etc/host)

    - +
    @@ -103,7 +109,7 @@

    Apache Configuration File (httpd.conf)

    - +
    @@ -117,7 +123,7 @@

    Virtual Hosts File (httpd-vhosts.conf)

    - +
    @@ -135,7 +141,7 @@

    Hosts Generator

    -
    +
    @@ -154,7 +160,7 @@

    PHP Configuration File (php.ini)

    - +
    @@ -162,7 +168,7 @@

    PHP Configuration File (php.ini)

    Miscellaeous Text File

    - +
    @@ -172,7 +178,7 @@

    Miscellaeous Actions

    -

    +

    @@ -180,16 +186,13 @@

    Miscellaeous Actions

    PHP Runner

    - + Content - -
    -
    diff --git a/main.js b/main.js index 53d0086..69b10b5 100644 --- a/main.js +++ b/main.js @@ -28,7 +28,7 @@ submenu: [ { label: `New Document`, accelerator: 'CmdOrCtrl+N', id:'NEW', click: send }, { label: `Open …`, accelerator: 'CmdOrCtrl+O', id:'OPEN', click: send }, - { label: `Reload`, accelerator: 'CmdOrCtrl+R', id:'LOAD', click: send }, + { label: `Reload`, accelerator: 'CmdOrCtrl+R', id:'RELOAD', click: send }, { label: `Save`, accelerator: 'CmdOrCtrl+S', id:'SAVE', click: send }, { label: `Save As …`, accelerator: 'CmdOrCtrl+Shift+S', id:'SAVEAS', click: send }, { type:'separator' }, diff --git a/scripts/virtual-hosts.js b/scripts/virtual-hosts.js index c76b803..7dc3d09 100644 --- a/scripts/virtual-hosts.js +++ b/scripts/virtual-hosts.js @@ -112,24 +112,24 @@ for(let f of forms) { if(f.elements['content']){ - tabs[f.id].content=f.elements['content']; - f.elements['content'].onkeydown=handleTab; - f.elements['content'].oninput=function(event) { + tabs[f.id].content = f.elements['content']; + f.elements['content'].onkeydown = handleTab; + f.elements['content'].oninput = event => { tabs[tab].button.setAttribute('data-status','edited'); tabMessage(tab,'Edited','edited'); }; - f.elements['content'].onblur=function(event) { - searchData.fromIndex=this.selectionStart; + f.elements['content'].onblur = function(event) { + searchData.fromIndex = this.selectionStart; }; - var lineNumbers=document.createElement('div'); + var lineNumbers = document.createElement('div'); lineNumbers.classList.add('line-numbers'); - tabs[f.id].lineNumbers=lineNumbers; + tabs[f.id].lineNumbers = lineNumbers; tabs[f.id].content.insertAdjacentElement('beforebegin',lineNumbers); - tabs[f.id].content.onscroll=function(event) { - tabs[f.id].lineNumbers.scrollTop=this.scrollTop; + tabs[f.id].content.onscroll = function(event) { + tabs[f.id].lineNumbers.scrollTop = this.scrollTop; }; - tabs[f.id].content.addEventListener('input',function(event) { + tabs[f.id].content.addEventListener('input', event => { setLineNumbers(f.id); }); setLineNumbers(f.id); @@ -165,12 +165,7 @@ ; // Server Menu - forms['settings'].elements['server'].addEventListener('change', event => { - server = event.target.value; - jf.write({ server: forms['settings'].elements['server'].value}); - - // TODO: Verify change if data-status is unsaved - + function chooseServer(server) { tabs['php-ini'].button.removeAttribute('data-status'); tabs['httpd-conf'].button.removeAttribute('data-status'); tabs['virtual-hosts'].button.removeAttribute('data-status'); @@ -192,8 +187,12 @@ forms['settings'].elements['server-root'].value = ''; forms['settings'].elements['php-interpreter'].value = ''; + } + } - // module.exports.server=server; + forms['settings'].elements['server'].addEventListener('change', event => { + server = event.target.value; + chooseServer(server); }); // On select server @@ -203,13 +202,15 @@ fsp.access(serverRoot) .then(() => load('httpd-conf')) .then(data => { - let phpini = serverRoot+servers[server][platform]['phpini']; - if(!phpcli) phpcli = serverRoot+servers[server][platform]['phpcli']; + let phpini = `${serverRoot}${servers[server][platform]['phpini']}`; + if(!phpcli) phpcli = `${serverRoot}${servers[server][platform]['phpcli']}`; let pattern = /php(\d\.\d+\.\d+)/; let version = data.match(pattern); if(version && phpini.match('{version}')) { phpini = phpini.replace('{version}',version[1]); phpcli = phpcli.replace('{version}',version[1]); + servers[server][platform]['phpini'] = phpini; + servers[server][platform]['phpcli'] = phpcli; } tabs['php-ini'].path = phpini; @@ -254,12 +255,16 @@ forms['settings'].elements['server-root'].value = path; localStorage.setItem('serverPath',path); // forms['settings'].elements['server'].value = ''; - jf.write({ - "server-root": forms['settings'].elements['server-root'].value, - server: '' - }); setServer(path); }); + forms['settings'].elements['server-path-default'].onclick = event => { // button + event.preventDefault(); + if(server) { + forms['settings'].elements['server-root'].value = servers[server][platform]['root']; + localStorage.setItem('serverPath',servers[server][platform]['root']); + setServer(servers[server][platform]['root']); + } + }; // PHP Interpreter Button forms['settings'].elements['php-interpreter-path'].onclick = event => { // button @@ -275,12 +280,25 @@ forms['settings'].elements['php-interpreter'].value = path; tabs['php-runner'].path = path; localStorage.setItem('phpInterpreterPath',path); + }); + forms['settings'].elements['php-interpreter-path-default'].onclick = event => { // button + event.preventDefault(); + if(server) { + forms['settings'].elements['php-interpreter'].value = servers[server][platform]['phpcli']; + tabs['php-runner'].path = servers[server][platform]['phpcli']; + localStorage.setItem('phpInterpreterPath',servers[server][platform]['phpcli']); + } + }; + + // Save Settings + forms['settings'].elements['save-settings'].onclick = event => { // button + event.preventDefault(); jf.write({ + "server": forms['settings'].elements['server'].value, "server-root": forms['settings'].elements['server-root'].value, - "php-interpreter": forms['settings'].elements['php-interpreter'].value, - server: '' + "php-interpreter": forms['settings'].elements['php-interpreter'].value }); - }); + }; /* Special Actions ================================================ */ @@ -318,7 +336,7 @@ case 'win32': // tabs['misc-text'].path=`${serverRoot}${servers[server][platform]['phpmyadmin']}/themes/pmahomme/css/theme.css`; break; default: tabs['misc-text'].path=`${serverRoot}${servers[server][platform]['phpmyadmin']}/js/vendor/codemirror/lib/codemirror.css`; } - load('misc-text', 'form#sqlqueryform div.CodeMirror pre,\nform#sqlqueryform div.CodeMirror-linenumber {\n\tfont-size: 1.25rem;\n}\n'); + load('misc-text', servers[server]['phpmyadmin-css']); buttons['misc-text'].click(); }; miscActions.elements['phpmyadmin-config'].onclick=function(event) { @@ -327,10 +345,10 @@ load('misc-text'); buttons['misc-text'].click(); }; - miscActions.elements['phpmyadmin-config-pappend'].onclick=function(event) { + miscActions.elements['phpmyadmin-config-append'].onclick=function(event) { if(!servers[server]) return; tabs['misc-text'].path = `${serverRoot}${servers[server][platform]['phpmyadmin']}/config.inc.php`; - load('misc-text', `$cfg['AllowUserDropDatabase'] = true;\n$cfg['RetainQueryBox'] = true;\n`); + load('misc-text', servers[server][platform]['phpmyadmin-config']); buttons['misc-text'].click(); }; @@ -348,18 +366,40 @@ let output = document.querySelector('div#php-result'); let result; - let php = spawn(interpreter,['-r', form.elements['code'].value]); + let cliArg = form.elements['php-tags'].checked ? '--' : '-r'; + + if(!form.elements['php-tags'].checked) { + + let php = spawn(interpreter,['-r', form.elements['code'].value]); + + php.stdout.on('data', data => { + results.push(data.toString()); + }); + php.stderr.on('data', data => { + console.log(`php oops:\n${data}`); + }); + php.on('close', code => { + output.textContent = results.join(''); + console.log(`php closed: ${code}`); + }); + } + else { + tmp = fsp.writeFile(`${os.tmpdir()}/tmp.php`,form.elements['code'].value).then(() => { + php = spawn(interpreter,[`${os.tmpdir()}/tmp.php`]); + php.stdout.on('data', data => { + results.push(data.toString()); + }); + php.stderr.on('data', data => { + console.log(`php oops:\n${data}`); + }); + php.on('close', code => { + output.textContent = results.join(''); + console.log(`php closed: ${code}`); + fsp.unlink(`${os.tmpdir()}/tmp.php`); + }); + }); + } - php.stdout.on('data', data => { - results.push(data.toString()); - }); - php.stderr.on('data', data => { - console.log(`php oops:\n${data}`); - }); - php.on('close', code => { - output.textContent = results.join(''); - console.log(`php closed: ${code}`); - }); } function doPHP() { @@ -375,40 +415,59 @@ event.preventDefault(); doPHP(); }; - function setLineNumbers2(code, lineNumbers) { + function setLineNumbers2(code, lineNumbers, suffix) { let lines = code.value.split(/\r?\n/).length; - lineNumbers.textContent = Array.from({length: lines},(v,i)=>i+1).join('\n'); + lineNumbers.textContent = Array.from({length: lines},(v,i) => `${i+1}${suffix?' '+suffix:''}`).join('\n'); } function handlePHPKeys(event) { - let key = event.key; - if(key == 'Tab') { - event.preventDefault(); - let text = event.target.value; - let [start,end] = [event.target.selectionStart,event.target.selectionEnd]; - if(start == end) { // simple tab - event.target.value = `${text.slice(0,start)}\t${text.slice(start)}`; - event.target.setSelectionRange(start+1, start+1); - } - else { // indent - start = text.lastIndexOf('\n',start); - event.target.value = `${text.slice(0,start)}${text.slice(start,end).replaceAll('\n','\n\t')}${text.slice(end)}`; - event.target.setSelectionRange(start+1, end+1); - } - } - else if(key == 'Enter' && (event.ctrlKey|| event.metaKey)) { - doPHP(); - return true; - } - else if(Object.keys(brackets).includes(key)) { - event.preventDefault(); - let text = event.target.value; - let [start,end] = [event.target.selectionStart,event.target.selectionEnd]; - event.target.value = `${text.slice(0,start)}${event.key}${text.slice(start,end)}${brackets[event.key]}${text.slice(end)}`; - event.target.setSelectionRange(start+1,end+1); - return true; - - } - else return true; + let brackets = {"'":"'",'"':'"','`':'`','(':')','{':'}','[':']','“':'”','‘':'’','«':'»'}; + let key = event.key; + let text = event.target.value; + let [start,end] = [event.target.selectionStart,event.target.selectionEnd]; + if(key == 'Tab') { + if(start == end) { // simple tab + event.target.value = `${text.slice(0,start)}\t${text.slice(start)}`; + event.target.setSelectionRange(start+1, start+1); + // return true; + } + else { // indent + start = text.lastIndexOf('\n',start); + event.target.value = `${text.slice(0,start)}${text.slice(start,end).replaceAll('\n','\n\t')}${text.slice(end)}`; + event.target.setSelectionRange(start+1, end+1); + } + event.preventDefault(); + } + else if(key == 'Enter') { + if(event.ctrlKey|| event.metaKey) { + doPHP(); + } + else { + let firstPart = event.target.value.slice(0,start); + let nl = firstPart.search(/\r?\n(?![\s\S]*\r?\n)/); + let indent = firstPart.slice(nl+1).match(/^\s*/)[0]; + event.target.value = `${firstPart}\n${indent}${text.slice(end)}`; + event.target.setSelectionRange(start+indent.length+1, start+indent.length+1); + } + event.preventDefault(); + } + else if(Object.keys(brackets).includes(key)) { +// if(start==end) { // && text.charAt(start-1)==brackets[key]) { + // console.log(`start == end ${start}: [${text.charAt(start-1)}]\n`); +// event.target.setSelectionRange(start+1,end+1); +// event.preventDefault(); +// } +// else { + event.target.value = `${text.slice(0,start)}${key}${text.slice(start,end)}${brackets[key]}${text.slice(end)}`; + event.target.setSelectionRange(start+1,end+1); + event.preventDefault(); +// } +// event.preventDefault(); + } + else if(Object.values(brackets).includes(key) && key==text.charAt(start)) { + event.target.setSelectionRange(start+1,end+1); + event.preventDefault(); + } + else return true; } let code = form.elements['code']; @@ -417,7 +476,7 @@ code.onkeydown = handlePHPKeys; code.oninput = event => { // Prism.highlightElement(code); - setLineNumbers2(code, lineNumbers); + setLineNumbers2(code, lineNumbers, '»'); }; code.onblur = event => { @@ -433,22 +492,18 @@ setLineNumbers2(code, lineNumbers); } - // Footer - footer=document.querySelector('footer'); footerPath=document.querySelector('p#path'); footerMessage=document.querySelector('p#message'); // Search - searchForm=document.querySelector('form#search'); searchForm.elements['find'].onclick=newSearch; // searchForm.elements['replace'].onclick=replace; searchForm.style.display='none'; // About etc - about=document.querySelector('div#about'); jx.draggable(about); doShowAbout=jx.popup(about,null,{escape: true}); @@ -468,13 +523,8 @@ if(DEVELOPMENT) { buttons['settings'].click(); - forms['php-runner'].elements['code'].value = `$a = 'This space for rent'; -$b = 'Watch this space …'; -$r = rand(0,1); -print $r ? $a : $b; -print PHP_EOL; -print PHP_VERSION; -`; + forms['php-runner'].elements['code'].value = fs.readFileSync(path.join(__dirname, '../data/sample-php.txt')).toString().normaliseBR(os.EOL);; + setLineNumbers('php-runner','»'); } else buttons['settings'].click(); @@ -525,9 +575,9 @@ console.log(204) }); } - function setLineNumbers(tab) { - var lines=tabs[tab].content.value.split(/\r?\n/).length; - tabs[tab].lineNumbers.textContent=Array.from({length: lines},(v,i)=>i+1).join('\n'); + function setLineNumbers(tab, suffix) { + var lines = tabs[tab].content.value.split(/\r?\n/).length; + tabs[tab].lineNumbers.textContent = Array.from({length: lines}, (v,i) => `${i+1}${suffix ? ' '+suffix : ''}`).join('\n'); } // Tab Key @@ -578,8 +628,8 @@ console.log(204) resolve(data); }) .catch(error=>{ - forms[tab].elements['content'].value=''; - tabMessage(tab,'Not available','not-available'); + forms[tab].elements['content'].value = ''; + tabMessage(tab,'Not available', 'not-available'); setLineNumbers(tab); console.log(error); @@ -674,13 +724,13 @@ console.log(204) } // IPC DOIT Actions - ipcRenderer.on('DOIT',(event,action,data,more)=>{ + ipcRenderer.on('DOIT', (event, action, data, more) => { console.log(action); console.log(data); console.log(more); switch(action) { case 'find': - searchData={ + searchData = { string: data, fromIndex: 0, caseSensitive: false @@ -691,11 +741,12 @@ console.log(more); ipcRenderer.send('open-file',{ title: 'Title', defaultPath: tabs[tab].path, - },'sendmail-path'); - ipcRenderer.on('sendmail-path',(event,result)=>{ + }, 'sendmail-path'); + ipcRenderer.on('sendmail-path',(event, result) => { console.log(result); if(result.canceled) return; var path = result.filePaths[0].toString(); + path = `"${path.replace(' ','\\ ')}"`; clipboard.writeText(path); }); break; @@ -722,8 +773,9 @@ console.log(more); case 'OPEN': openDialog(); break; - case 'LOAD': + case 'RELOAD': load(tab); + tabs[tab].button.removeAttribute('data-status'); break; case 'SAVE': save(); diff --git a/styles/main.css b/styles/main.css index 75b47d4..789836e 100644 --- a/styles/main.css +++ b/styles/main.css @@ -70,8 +70,8 @@ box-sizing: border-box; padding: 0; margin: 0; - height: 100vh; - width: 100vw; + qheight: 100vh; + qwidth: 100vw; font-size: 100%; } @@ -96,14 +96,19 @@ ================================================ */ body { - display: flex; - flex-direction: column; + display: grid; overflow: hidden; + grid-template-rows: auto 1fr auto auto; + grid-template-columns: 1fr; + box-sizing: border-box; + height: 100vh; } + form#controls { qflex: 1; display: flex; + grid-row: 1/2; } form#controls>div#tabs { @@ -116,7 +121,8 @@ } div#forms { - flex: 1; + grid-row: 2/3; + overflow: auto; } div#forms>form { font-family: var(--sans-serif); @@ -131,6 +137,7 @@ footer { qflex: 1; + grid-row: 4/5; } /* Forms @@ -138,7 +145,8 @@ div#forms { box-sizing: border-box; - height: calc(100vh - 14em); + qheight: calc(100vh - 14em); + qheight: 20em; } div#forms form { box-sizing: border-box; @@ -160,7 +168,7 @@ form#controls { background: linear-gradient(to bottom, #f8f8f8, #ccc); - height: 30px; + qheight: 30px; padding: 0; box-sizing: border-box; display: flex; @@ -399,6 +407,19 @@ outline: none; } +div#forms form#generator { + grid-template-columns: 24em 1fr; +} +div#forms form#generator input[type="text"] { + padding: .25rem .25rem; +} +div#forms form#generator div.line-numbers { + width: 3em !important +} +form#generator textarea { + padding-left: 0.5em !important; +} + /* php.ini ================================================ */ @@ -534,125 +555,142 @@ background-color: var(--misc-action-button-hover-background-color); } -/* PHP Runner - ================================================ - form#php-runner"> - div#php-help.help - h3 - div#php-code - textarea[name="code"] - code.language-php - div#php-control - label - input[name="html"] - button[name="doit"] - div#php-result - output[name="result"] - - ================================================ */ - - div#forms form#php-runner { - display: grid; - grid-template-rows: auto 1fr 1fr; - grid-template-columns: 1fr; - } - - div#forms form#php-runner * { - box-sizing: border-box; - } - - div#forms form#php-runner>div#php-help { - grid-column: 1/2; - grid-row: 1/2; - } - div#forms form#php-runner>div#php-code { - box-sizing: border-box; - - grid-column: 1/2; - grid-row: 2/3; - display: grid; - grid-template-rows: 1fr; - grid-template-columns: 6em 1fr; - - position: relative; - } - div#forms form#php-runner>div#php-control { - backgroiund-color: #f8f8f8; - border: thin #666; - border-style: solid none; - padding: 0.5em 1em; - grid-column: 1/2; - grid-row: 3/4; - - } - - div#forms form#php-runner>div#php-control>label { - border: thick solid red; - display: none; - } + /* PHP Runner + ================================================ + form#php-runner"> + div#php-help.help + h3 + div#php-code + textarea[name="code"] + code.language-php + div#php-control + label + input[name="html"] + button[name="doit"] + div#php-result + output[name="result"] + ================================================ */ + + div#forms form#php-runner { + /* display: grid; */ + grid-template-rows: auto 1fr 1fr; + grid-template-columns: 1fr; + } + + div#forms form#php-runner * { + box-sizing: border-box; + } + + div#forms form#php-runner>div#php-help { + grid-column: 1/2; + grid-row: 1/2; + } + div#forms form#php-runner>div#php-code { + box-sizing: border-box; + + grid-column: 1/2; + grid-row: 2/3; + display: grid; + grid-template-rows: 1fr; + grid-template-columns: 6em 1fr; + + position: relative; + overflow: scroll; + } + + div#forms form#php-runner>:is(div#php-result, div#php-code) { + overflow: scroll; + } + + qdiv#forms form#php-runner div#php-control { + backgroind-color: #f8f8f8; + border: thin #666; + border-style: solid none; + padding: 0.5em 1em; + grid-column: 1/2; + grid-row: 3/4; + + } + + div#forms form#php-runner div#php-control { + position: absolute; + background-color: darkgreen; + right: 2em; + bottom: 1em; + padding: 0.25em 0.75em; + opacity: 0.25; + transition: opacity 0.25s; + } + + div#forms form#php-runner div#php-code button[name="doit"] { + background-color: darkgreen; + color: white; + padding: 0.5em 1em; + border: darkgreen thin solid; + display: inline-block; + width: 6em; + box-sizing: border-box; + font-size: 1.2em; + opacity: 0.25; + transition: opacity 0.25s; + } + div#forms form#php-runner div#php-control:hover { + opacity: 1; + } + div#forms form#php-runner div#php-control button[name="doit"]:hover { + opacity: 1; + } + + div#forms form#php-runner div#php-control label { + background-color: white; + padding: 0.25em 0.5em; + } + + div#forms form#php-runner div#php-control input[type="checkbox"] { + accent-color: darkgreen; + } + + div#forms form#php-runner>div#php-result { + grid-column: 1/2; + grid-row: 3/4; + overflow: scroll; + } + + div#forms form#php-runner>div#php-code>code { + display: none; + } + + div#forms form#php-runner>div#php-code :is(div.line-numbers,textarea) { + white-space: pre; + font-family: "Source Code Pro"; + font-size: 1.2em; + } + + div#forms form#php-runner>div#php-code>div.line-numbers { + grid-column: 1/2; + grid-row: 1/2; + padding: 0.25em 0.375em 0 0; + text-align: right; + width: 4.5em; + } + div#forms form#php-runner>div#php-code>textarea { + padding: 0.25em 0.5em 0 0.25em; + grid-column: 2/3; + } + div#forms form#php-runner code { + grid-column: 2/3; + grid-row: 1/2; + } + div#forms form#php-runner>div#php-result { + box-sizing: border-box; + font-family: "Source Code Pro"; + font-size: 1.2em; + white-space: pre; + padding: 1em; + background-color: white; + border: 0.5em solid #ddd; + } - div#forms form#php-runner>div#php-code>button[name="doit"] { - background-color: darkgreen; - color: white; - padding: 0.5em 1em; - border: darkgreen thin solid; - display: inline-block; - width: 6em; - box-sizing: border-box; - position: absolute; - font-size: 1.2em; - right: 0.5em; - bottom: 0.5em; - } - div#forms form#php-runner>div#php-control>button[name="doit"] { - -margin-left: 4em; - background-color: darkgreen; - color: white; - padding: 0.5em 1em; - border: darkgreen thin solid; - display: inline-block; - qwidth: 6em; - box-sizing: border-box; - } - - div#forms form#php-runner>div#php-result { - grid-column: 1/2; - grid-row: 3/4; - } - - div#forms form#php-runner>div#php-code>code { - display: none; - } - - div#forms form#php-runner>div#php-code :is(div.line-numbers,textarea) { - white-space: pre; - font-family: "Source Code Pro"; - font-size: 1.2em; - } - - div#forms form#php-runner>div#php-code>div.line-numbers { - grid-column: 1/2; - grid-row: 1/2; - padding: 0.25em 0.5em 0 0; - text-align: right; - } - div#forms form#php-runner>div#php-code>textarea { - padding: 0.25em 0.5em 0 0.75em; - grid-column: 2/3; - } - div#forms form#php-runner code { - grid-column: 2/3; - grid-row: 1/2; - } - div#forms form#php-runner>div#php-result { - box-sizing: border-box; - font-family: "Source Code Pro"; - font-size: 1.2em; - white-space: pre; - padding: 1em; - background-color: white; - border: 0.5em solid #ddd; - } /* Settings ================================================ div#forms form#settings @@ -673,7 +711,7 @@ div#forms form#settings { grid-template-columns: 1fr; - grid-template-rows: auto auto auto auto 1fr; + grid-template-rows: auto auto auto auto auto 1fr; } div#forms form#settings :is(div#choose-server-root,div#misc,div#choose-php-interpreter) { @@ -730,3 +768,12 @@ div#forms form#settings>div#misc>select>option { background-color: var(--misc-select-option-color); } + div#forms form#settings>div#save-settings { + padding: 1em; + } + div#forms form#settings>div#save-settings>button { + background-color: darkgreen; + color: white; + width: 8em; + float: right; + }