Upload modal

pull/111/merge
Ondřej Hruška 7 years ago
parent 6fdb23531b
commit 44ea1e5b49
  1. 92
      html_orig/css/app.css
  2. BIN
      html_orig/fontello/fontello.zip
  3. 5
      html_orig/fontello/unpack.sh
  4. 137
      html_orig/js/app.js
  5. 5
      html_orig/jssrc/modal.js
  6. 113
      html_orig/jssrc/term.js
  7. 19
      html_orig/jssrc/utils.js
  8. 2
      html_orig/lang/en.php
  9. 58
      html_orig/pages/term.php
  10. 10
      html_orig/sass/_fontello.scss
  11. 2
      html_orig/sass/app.scss
  12. 28
      html_orig/sass/layout/_modal.scss
  13. 93
      html_orig/sass/pages/_term.scss

File diff suppressed because one or more lines are too long

Binary file not shown.

@ -39,9 +39,12 @@ echo -e "@charset \"UTF-8\";\n\n/* Fontello data, processed by the unpack script
#grep -Pazo "(?s)@font-face.*?normal;\n\}" "$OUTPUT_DIR/fontello.css" \
# | sed 's/\x0//g' >> "$SASSFILE"
grep -Pazo "(?s)@font-face \{\n\s*font-family: 'fontello';\n\s*src: url\('data.*?truetype'\);\n\}" "$OUTPUT_DIR/fontello-embedded.css" \
grep -Pazo "(?s)@font-face \{\n\s*font-family: 'fontello';\n\s*src: url\('data.*?woff'\)" "$OUTPUT_DIR/fontello-embedded.css" \
| sed 's/\x0//g' >> "$SASSFILE"
echo -e ";\n}" >> "$SASSFILE"
grep -Pazo "(?s)$ICON_PREFIX-\"\]:before .*?\}" "$OUTPUT_DIR/fontello.css" \
| sed 's/\x0//g' \
| sed "s/$ICON_PREFIX-\"\]:before/\n\n%fontello-icon-base \{\n\&::before /g" \

@ -1126,29 +1126,31 @@ function undef(x) {
}
/** Safe json parse */
function jsp() {
function jsp(str) {
try {
return JSON.parse(e);
return JSON.parse(str);
} catch(e) {
console.error(e);
return null;
}
}
/** Decode two-byte number */
/** Create a character from ASCII code */
function Chr(n) {
return String.fromCharCode(n);
}
/** Decode number from 2B encoding */
function parse2B(s, i) {
return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127;
}
/** Decode three-byte number */
/** Decode number from 3B encoding */
function parse3B(s, i) {
return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127;
}
function Chr(n) {
return String.fromCharCode(n);
}
/** Encode using 2B encoding, returns string. */
function encode2B(n) {
var lsb, msb;
lsb = (n % 127);
@ -1158,6 +1160,7 @@ function encode2B(n) {
return Chr(lsb) + Chr(msb);
}
/** Encode using 3B encoding, returns string. */
function encode3B(n) {
var lsb, msb, xsb;
lsb = (n % 127);
@ -1172,13 +1175,15 @@ function encode3B(n) {
/** Module for toggling a modal overlay */
(function () {
var modal = {};
var curCloseCb = null;
modal.show = function (sel) {
modal.show = function (sel, closeCb) {
var $m = $(sel);
$m.removeClass('hidden visible');
setTimeout(function () {
$m.addClass('visible');
}, 1);
curCloseCb = closeCb;
};
modal.hide = function (sel) {
@ -1186,6 +1191,7 @@ function encode3B(n) {
$m.removeClass('visible');
setTimeout(function () {
$m.addClass('hidden');
if (curCloseCb) curCloseCb();
}, 500); // transition time
};
@ -2010,17 +2016,18 @@ var Conn = (function() {
}
function doSend(message) {
console.log("TX: ", message);
//console.log("TX: ", message);
if (!ws) return; // for dry testing
if (!ws) return false; // for dry testing
if (ws.readyState != 1) {
console.error("Socket not ready");
return;
return false;
}
if (typeof message != "string") {
message = JSON.stringify(message);
}
ws.send(message);
return true;
}
function init() {
@ -2095,11 +2102,12 @@ var Input = (function() {
fn_alt: false,
mt_click: false,
mt_move: false,
no_keys: false,
};
/** Send a literal message */
function sendStrMsg(str) {
Conn.send("s"+str);
return Conn.send("s"+str);
}
/** Send a button event */
@ -2199,6 +2207,7 @@ var Input = (function() {
key.unbind(combo);
key(combo, function (e) {
if (opts.no_keys) return;
e.preventDefault();
sendStrMsg(str)
});
@ -2208,6 +2217,7 @@ var Input = (function() {
function _initKeys() {
// This takes care of text characters typed
window.addEventListener('keypress', function(evt) {
if (opts.no_keys) return;
var str = '';
if (evt.key) str = evt.key;
else if (evt.which) str = String.fromCodePoint(evt.which);
@ -2325,11 +2335,112 @@ var Input = (function() {
mouseTracksClicks: function() {
return opts.mt_click;
},
blockKeys: function(yes) {
opts.no_keys = yes;
}
};
})();
/** File upload utility */
var TermUpl = (function() {
var fuLines, fuPos, fuTout, fuDelay, fuNL;
function fuOpen() {
fuStatus("Ready...");
Modal.show('#fu_modal', onClose);
$('#fu_form').toggleClass('busy', false);
Input.blockKeys(true);
}
function onClose() {
console.log("Upload modal closed.");
clearTimeout(fuTout);
fuPos = 0;
Input.blockKeys(false);
}
function fuStatus(msg) {
qs('#fu_prog').textContent = msg;
}
function fuSend() {
var v = qs('#fu_text').value;
if (!v.length) {
fuClose();
return;
}
fuLines = v.split('\n');
fuPos = 0;
fuDelay = qs('#fu_delay').value;
fuNL = {
'CR': '\r',
'LF': '\n',
'CRLF': '\r\n',
}[qs('#fu_crlf').value];
$('#fu_form').toggleClass('busy', true);
fuStatus("Starting...");
fuSendLine();
}
function fuSendLine() {
if (!$('#fu_modal').hasClass('visible')) {
// Modal is closed, cancel
return;
}
if (!Input.sendString(fuLines[fuPos++] + fuNL)) {
fuStatus("FAILED!");
return;
}
var all = fuLines.length;
fuStatus(fuPos+" / "+all+ " ("+(Math.round((fuPos/all)*1000)/10)+"%)");
if (fuLines.length > fuPos) {
setTimeout(fuSendLine, fuDelay);
} else {
fuClose();
}
}
function fuClose() {
Modal.hide('#fu_modal');
}
return {
init: function() {
qs('#fu_file').addEventListener('change', function (evt) {
var reader = new FileReader();
var file = evt.target.files[0];
console.log("Selected file type: "+file.type);
if (!file.type.match(/text\/.*|application\/(json|x?html|csv|.*xml.*|.*script.*)|image\/(.*xml.*)/)) {
// Deny load of blobs like img - can crash browser and will get corrupted anyway
if (!confirm("This does not look like a text file: "+file.type+"\nReally load?")) {
qs('#fu_file').value = '';
return;
}
}
reader.onload = function(e) {
var txt = e.target.result.replace(/[\r\n]+/,'\n');
qs('#fu_text').value = txt;
};
console.log("Loading file...");
reader.readAsText(file);
}, false);
},
close: fuClose,
start: fuSend,
open: fuOpen,
}
})();
/** Init the terminal sub-module - called from HTML */
window.termInit = function () {
Conn.init();
Input.init();
TermUpl.init();
};

@ -1,13 +1,15 @@
/** Module for toggling a modal overlay */
(function () {
var modal = {};
var curCloseCb = null;
modal.show = function (sel) {
modal.show = function (sel, closeCb) {
var $m = $(sel);
$m.removeClass('hidden visible');
setTimeout(function () {
$m.addClass('visible');
}, 1);
curCloseCb = closeCb;
};
modal.hide = function (sel) {
@ -15,6 +17,7 @@
$m.removeClass('visible');
setTimeout(function () {
$m.addClass('hidden');
if (curCloseCb) curCloseCb();
}, 500); // transition time
};

@ -410,17 +410,18 @@ var Conn = (function() {
}
function doSend(message) {
console.log("TX: ", message);
//console.log("TX: ", message);
if (!ws) return; // for dry testing
if (!ws) return false; // for dry testing
if (ws.readyState != 1) {
console.error("Socket not ready");
return;
return false;
}
if (typeof message != "string") {
message = JSON.stringify(message);
}
ws.send(message);
return true;
}
function init() {
@ -495,11 +496,12 @@ var Input = (function() {
fn_alt: false,
mt_click: false,
mt_move: false,
no_keys: false,
};
/** Send a literal message */
function sendStrMsg(str) {
Conn.send("s"+str);
return Conn.send("s"+str);
}
/** Send a button event */
@ -599,6 +601,7 @@ var Input = (function() {
key.unbind(combo);
key(combo, function (e) {
if (opts.no_keys) return;
e.preventDefault();
sendStrMsg(str)
});
@ -608,6 +611,7 @@ var Input = (function() {
function _initKeys() {
// This takes care of text characters typed
window.addEventListener('keypress', function(evt) {
if (opts.no_keys) return;
var str = '';
if (evt.key) str = evt.key;
else if (evt.which) str = String.fromCodePoint(evt.which);
@ -725,11 +729,112 @@ var Input = (function() {
mouseTracksClicks: function() {
return opts.mt_click;
},
blockKeys: function(yes) {
opts.no_keys = yes;
}
};
})();
/** File upload utility */
var TermUpl = (function() {
var fuLines, fuPos, fuTout, fuDelay, fuNL;
function fuOpen() {
fuStatus("Ready...");
Modal.show('#fu_modal', onClose);
$('#fu_form').toggleClass('busy', false);
Input.blockKeys(true);
}
function onClose() {
console.log("Upload modal closed.");
clearTimeout(fuTout);
fuPos = 0;
Input.blockKeys(false);
}
function fuStatus(msg) {
qs('#fu_prog').textContent = msg;
}
function fuSend() {
var v = qs('#fu_text').value;
if (!v.length) {
fuClose();
return;
}
fuLines = v.split('\n');
fuPos = 0;
fuDelay = qs('#fu_delay').value;
fuNL = {
'CR': '\r',
'LF': '\n',
'CRLF': '\r\n',
}[qs('#fu_crlf').value];
$('#fu_form').toggleClass('busy', true);
fuStatus("Starting...");
fuSendLine();
}
function fuSendLine() {
if (!$('#fu_modal').hasClass('visible')) {
// Modal is closed, cancel
return;
}
if (!Input.sendString(fuLines[fuPos++] + fuNL)) {
fuStatus("FAILED!");
return;
}
var all = fuLines.length;
fuStatus(fuPos+" / "+all+ " ("+(Math.round((fuPos/all)*1000)/10)+"%)");
if (fuLines.length > fuPos) {
setTimeout(fuSendLine, fuDelay);
} else {
fuClose();
}
}
function fuClose() {
Modal.hide('#fu_modal');
}
return {
init: function() {
qs('#fu_file').addEventListener('change', function (evt) {
var reader = new FileReader();
var file = evt.target.files[0];
console.log("Selected file type: "+file.type);
if (!file.type.match(/text\/.*|application\/(json|x?html|csv|.*xml.*|.*script.*)|image\/(.*xml.*)/)) {
// Deny load of blobs like img - can crash browser and will get corrupted anyway
if (!confirm("This does not look like a text file: "+file.type+"\nReally load?")) {
qs('#fu_file').value = '';
return;
}
}
reader.onload = function(e) {
var txt = e.target.result.replace(/[\r\n]+/,'\n');
qs('#fu_text').value = txt;
};
console.log("Loading file...");
reader.readAsText(file);
}, false);
},
close: fuClose,
start: fuSend,
open: fuOpen,
}
})();
/** Init the terminal sub-module - called from HTML */
window.termInit = function () {
Conn.init();
Input.init();
TermUpl.init();
};

@ -113,29 +113,31 @@ function undef(x) {
}
/** Safe json parse */
function jsp() {
function jsp(str) {
try {
return JSON.parse(e);
return JSON.parse(str);
} catch(e) {
console.error(e);
return null;
}
}
/** Decode two-byte number */
/** Create a character from ASCII code */
function Chr(n) {
return String.fromCharCode(n);
}
/** Decode number from 2B encoding */
function parse2B(s, i) {
return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127;
}
/** Decode three-byte number */
/** Decode number from 3B encoding */
function parse3B(s, i) {
return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127;
}
function Chr(n) {
return String.fromCharCode(n);
}
/** Encode using 2B encoding, returns string. */
function encode2B(n) {
var lsb, msb;
lsb = (n % 127);
@ -145,6 +147,7 @@ function encode2B(n) {
return Chr(lsb) + Chr(msb);
}
/** Encode using 3B encoding, returns string. */
function encode3B(n) {
var lsb, msb, xsb;
lsb = (n % 127);

@ -21,6 +21,8 @@ return [
'term_nav.help' => 'Help',
'term_nav.about' => 'About',
'term_nav.paste' => 'Paste',
'term_nav.upload' => 'Upload',
'term_nav.keybd' => 'Keyboard',
'term_nav.paste_prompt' => 'Paste text to send:',
'net.ap' => 'DHCP Server (AP)',

@ -8,29 +8,58 @@
}, 3000);
</script>
<div class="Modal light hidden" id="fu_modal">
<div id="fu_form" class="Dialog">
<div class="fu-content">
<h2>Text Upload</h2>
<p>
<label for="fu_file">Load a text file:</label>
<input type="file" id="fu_file" accept="text/*" /><br>
<textarea id="fu_text"></textarea>
</p>
<p>
<label for="fu_crlf">Line Endings:</label>
<select id="fu_crlf">
<option value="CR">CR (Enter key)</option>
<option value="CRLF">CR LF (Windows)</option>
<option value="LF">LF (Linux)</option>
</select>
</p>
<p>
<label for="fu_delay">Line Delay (ms):</label>
<input id="fu_delay" type="number" value=0 min=0 max=500>
</p>
</div>
<div class="fu-buttons">
<button onclick="TermUpl.start()" class="icn-ok x-fu-go">Start</button>&nbsp;
<button onclick="TermUpl.close()" class="icn-cancel x-fu-cancel">Cancel</button>&nbsp;
<i class="fu-prog-box">Upload: <span id="fu_prog"></span></i>
</div>
</div>
</div>
<h1><!-- Screen title gets loaded here by JS --></h1>
<div id="term-wrap">
<div id="screen" class="theme-%theme%"></div>
<div id="action-buttons">
<button data-n="1" class="btn-blue"></button><!--
--><button data-n="2" class="btn-blue"></button><!--
--><button data-n="3" class="btn-blue"></button><!--
--><button data-n="4" class="btn-blue"></button><!--
--><button data-n="5" class="btn-blue"></button>
<button data-n="1"></button><!--
--><button data-n="2"></button><!--
--><button data-n="3"></button><!--
--><button data-n="4"></button><!--
--><button data-n="5"></button>
</div>
</div>
<textarea id="softkb-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
<nav id="term-nav">
<a href="#" onclick="toggleSoftKb(true);return false" class="icn-keyboard mq-tablet-max"></a><!--
--><a href="#" onclick="termPaste();return false"><?= tr('term_nav.paste') ?></a><!--
--><a href="<?= url('cfg_term') ?>" class="x-term-conf-btn"><?= tr('term_nav.config') ?></a><!--
--><a href="<?= url('cfg_wifi') ?>" class="x-term-conf-btn"><?= tr('term_nav.wifi') ?></a><!--
--><a href="<?= url('help') ?>" class="x-term-conf-btn"><?= tr('term_nav.help') ?></a><!--
--><a href="<?= url('about') ?>" class="x-term-conf-btn"><?= tr('term_nav.about') ?></a>
<a href="#" onclick="kbOpen(true);return false" class="mq-tablet-max"><i class="icn-keyboard"></i><span><?= tr('term_nav.keybd') ?></span></a><!--
--><a href="#" onclick="TermUpl.open();return false"><i class="icn-download"></i><span><?= tr('term_nav.upload') ?></a><!--
--><a href="<?= url('cfg_term') ?>" class="x-term-conf-btn"><i class="icn-configure"></i><span><?= tr('term_nav.config') ?></span></a><!--
--><a href="<?= url('cfg_wifi') ?>" class="x-term-conf-btn"><i class="icn-wifi"></i><span><?= tr('term_nav.wifi') ?></span></a><!--
--><a href="<?= url('help') ?>" class="x-term-conf-btn"><i class="icn-help"></i><span><?= tr('term_nav.help') ?></span></a>
</nav>
<script>
@ -55,14 +84,9 @@
}, 3000);
}
function toggleSoftKb(yes) {
function kbOpen(yes) {
var i = qs('#softkb-input');
if (yes) i.focus();
else i.blur();
}
function termPaste() {
var t = prompt(<?= je(tr('term_nav.paste_prompt')) ?>);
if (t !== null && t.length) Input.sendString(t);
}
</script>

File diff suppressed because one or more lines are too long

@ -18,6 +18,8 @@ $c-form-field-fg: white;
$c-form-highlight: #2972ba;
$c-form-highlight-a: #2ea1f9;
$c-modal-bg: #242426;
$screen-stack: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace;
@function dist($x) {

@ -1,4 +1,5 @@
.Modal {
z-index: 100;
position: fixed;
width: 100%; height: 100%;
left: 0; top: 0; right: 0; bottom: 0;
@ -12,6 +13,21 @@
opacity: 0;
&.visible { opacity: 1 }
&.hidden { display: none }
&.light {
background: rgba(black, .25);
}
@include media($phone) {
flex-direction: column;
justify-content: flex-start;
overflow-y: auto;
.Dialog {
margin-top: dist(-1) !important;
flex-basis: unset;
flex-shrink: 0;
}
}
}
.Dialog {
@ -19,16 +35,16 @@
padding: dist(0);
overflow: hidden;
max-width: 100%;
max-height: 100%;
flex: 0 1 30rem;
//max-width: 100%;
//max-height: 100%;
flex-basis: 35rem;
//min-height: 15rem;
background: #1c1c1e;
background: $c-modal-bg;//#1c1c1e;
border-left: 6px solid $c-form-highlight;
border-right: 6px solid $c-form-highlight;
border-top: 1px solid $c-form-highlight;
border-bottom: 1px solid $c-form-highlight;
//border-top: 1px solid $c-form-highlight;
//border-bottom: 1px solid $c-form-highlight;
box-shadow: 0 0 6px 0 black;
border-radius: 6px;

@ -71,8 +71,10 @@ body.term {
text-align: center;
a {
padding: 0 dist(-2);
text-decoration: underline;
text-decoration: none;
padding: 5px 5px;
border-radius: 2px;
position: relative;
&, &:visited, &:link {
color: #336085;
@ -80,12 +82,34 @@ body.term {
&:hover {
color: #5abfff;
background: #1b273c;
}
&:active {
top: 1px;
}
i::before {
display: inline;
}
span {
margin-left: .2em;
}
@include media($phone) {
span {
display: none;
}
font-size: 130%;
padding: 6px;
}
}
.icn-keyboard {
text-decoration: none;
font-size: 150%;
font-size: 130%; // make it bigger - icon is too small to be recognizable
vertical-align: middle;
}
}
@ -100,6 +124,69 @@ body.term {
top: -9999px;
}
#fu_modal {
align-items: flex-start;
}
#fu_form {
//border: 1px solid #3983CD;
//border-radius: 2px;
//padding: 0 dist(0);
//background: #333e58;
padding: dist(0);
margin-top: 100px; // offset
z-index: 1000;
label {
width: 8em;
display: inline-block;
}
input[type="number"], select {
width: 10em;
}
textarea {
width: 100%;
min-height: 8em;
margin-top: dist(-1);
resize: vertical;
}
.fu-buttons {
text-align: center;
padding: dist(-2);
margin-top: dist(-2);
border-radius: 3px;
}
.fu-prog-box {
display: none;
}
&.busy {
background: rgba($c-modal-bg, .3);
border-left-color: rgba($c-form-highlight, .3);
border-right-color: rgba($c-form-highlight, .3);
.fu-content {
@include click-through;
opacity: .3;
}
.fu-buttons {
text-align: left;
background: $c-modal-bg;
border: 1px solid $c-form-highlight;
}
.fu-prog-box {
display: inline-block;
}
}
}
// Tango
.theme-0 {
$term-colors:

Loading…
Cancel
Save