updated to latest backend, cursor variants setting, reformat some files

cpsdqs/unified-input
Ondřej Hruška 7 years ago
parent 963bfce9cc
commit 036a58ce12
  1. 349
      jssrc/appcommon.js
  2. 6
      jssrc/lang.js
  3. 70
      jssrc/modal.js
  4. 46
      jssrc/notif.js
  5. 40
      jssrc/soft_keyboard.js
  6. 8
      jssrc/term_input.js
  7. 122
      jssrc/term_screen.js
  8. 288
      jssrc/term_upload.js
  9. 144
      jssrc/utils.js
  10. 324
      jssrc/wifi.js
  11. 9
      lang/en.php
  12. 19
      pages/cfg_term.php

@ -1,189 +1,190 @@
/** Global generic init */ /** Global generic init */
$.ready(function () { $.ready(function () {
// Checkbox UI (checkbox CSS and hidden input with int value) // Checkbox UI (checkbox CSS and hidden input with int value)
$('.Row.checkbox').forEach(function(x) { $('.Row.checkbox').forEach(function (x) {
var inp = x.querySelector('input'); var inp = x.querySelector('input');
var box = x.querySelector('.box'); var box = x.querySelector('.box');
$(box).toggleClass('checked', inp.value); $(box).toggleClass('checked', inp.value);
var hdl = function() { var hdl = function () {
inp.value = 1 - inp.value; inp.value = 1 - inp.value;
$(box).toggleClass('checked', inp.value) $(box).toggleClass('checked', inp.value)
}; };
$(x).on('click', hdl).on('keypress', cr(hdl)); $(x).on('click', hdl).on('keypress', cr(hdl));
}); });
// Expanding boxes on mobile // Expanding boxes on mobile
$('.Box.mobcol,.Box.fold').forEach(function(x) { $('.Box.mobcol,.Box.fold').forEach(function (x) {
var h = x.querySelector('h2'); var h = x.querySelector('h2');
var hdl = function() { var hdl = function () {
$(x).toggleClass('expanded'); $(x).toggleClass('expanded');
}; };
$(h).on('click', hdl).on('keypress', cr(hdl)); $(h).on('click', hdl).on('keypress', cr(hdl));
}); });
$('form').forEach(function(x) { $('form').forEach(function (x) {
$(x).on('keypress', function(e) { $(x).on('keypress', function (e) {
if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey) { if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey) {
x.submit(); x.submit();
} }
}) })
}); });
// loader dots... // loader dots...
setInterval(function () { setInterval(function () {
$('.anim-dots').each(function (x) { $('.anim-dots').each(function (x) {
var $x = $(x); var $x = $(x);
var dots = $x.html() + '.'; var dots = $x.html() + '.';
if (dots.length == 5) dots = '.'; if (dots.length == 5) dots = '.';
$x.html(dots); $x.html(dots);
}); });
}, 1000); }, 1000);
// flipping number boxes with the mouse wheel // flipping number boxes with the mouse wheel
$('input[type=number]').on('mousewheel', function(e) { $('input[type=number]').on('mousewheel', function (e) {
var $this = $(this); var $this = $(this);
var val = +$this.val(); var val = +$this.val();
if (isNaN(val)) val = 1; if (isNaN(val)) val = 1;
var step = +($this.attr('step') || 1); var step = +($this.attr('step') || 1);
var min = +$this.attr('min'); var min = +$this.attr('min');
var max = +$this.attr('max'); var max = +$this.attr('max');
if(e.wheelDelta > 0) { if (e.wheelDelta > 0) {
val += step; val += step;
} else { } else {
val -= step; val -= step;
} }
if (typeof min != 'undefined') val = Math.max(val, +min); if (typeof min != 'undefined') val = Math.max(val, +min);
if (typeof max != 'undefined') val = Math.min(val, +max); if (typeof max != 'undefined') val = Math.min(val, +max);
$this.val(val); $this.val(val);
if ("createEvent" in document) { if ("createEvent" in document) {
var evt = document.createEvent("HTMLEvents"); var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true); evt.initEvent("change", false, true);
$this[0].dispatchEvent(evt); $this[0].dispatchEvent(evt);
} else { } else {
$this[0].fireEvent("onchange"); $this[0].fireEvent("onchange");
} }
e.preventDefault(); e.preventDefault();
}); });
var errAt = location.search.indexOf('err='); var errAt = location.search.indexOf('err=');
if (errAt !== -1 && qs('.Box.errors')) { if (errAt !== -1 && qs('.Box.errors')) {
var errs = location.search.substr(errAt+4).split(','); var errs = location.search.substr(errAt + 4).split(',');
var hres = []; var hres = [];
errs.forEach(function(er) { errs.forEach(function (er) {
var lbl = qs('label[for="'+er+'"]'); var lbl = qs('label[for="' + er + '"]');
if (lbl) { if (lbl) {
lbl.classList.add('error'); lbl.classList.add('error');
hres.push(lbl.childNodes[0].textContent.trim().replace(/: ?$/, '')); hres.push(lbl.childNodes[0].textContent.trim().replace(/: ?$/, ''));
} else { } else {
hres.push(er); hres.push(er);
} }
}); });
qs('.Box.errors .list').innerHTML = hres.join(', '); qs('.Box.errors .list').innerHTML = hres.join(', ');
qs('.Box.errors').classList.remove('hidden'); qs('.Box.errors').classList.remove('hidden');
} }
Modal.init(); Modal.init();
Notify.init(); Notify.init();
// remove tabindixes from h2 if wide // remove tabindixes from h2 if wide
if (window.innerWidth > 550) { if (window.innerWidth > 550) {
$('.Box h2').forEach(function (x) { $('.Box h2').forEach(function (x) {
x.removeAttribute('tabindex'); x.removeAttribute('tabindex');
}); });
// brand works as a link back to term in widescreen mode // brand works as a link back to term in widescreen mode
var br = qs('#brand'); var br = qs('#brand');
br && br.addEventListener('click', function() { br && br.addEventListener('click', function () {
location.href='/'; // go to terminal location.href = '/'; // go to terminal
}); });
} }
}); });
$._loader = function(vis) { $._loader = function (vis) {
$('#loader').toggleClass('show', vis); $('#loader').toggleClass('show', vis);
}; };
function showPage() { function showPage() {
$('#content').addClass('load'); $('#content').addClass('load');
} }
$.ready(function() { $.ready(function () {
if (window.noAutoShow !== true) { if (window.noAutoShow !== true) {
setTimeout(function () { setTimeout(function () {
showPage(); showPage();
}, 1); }, 1);
} }
}); });
/*! http://mths.be/fromcodepoint v0.1.0 by @mathias */ /*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
if (!String.fromCodePoint) { if (!String.fromCodePoint) {
(function() { (function () {
var defineProperty = (function() { var defineProperty = (function () {
// IE 8 only supports `Object.defineProperty` on DOM elements // IE 8 only supports `Object.defineProperty` on DOM elements
try { try {
var object = {}; var object = {};
var $defineProperty = Object.defineProperty; var $defineProperty = Object.defineProperty;
var result = $defineProperty(object, object, object) && $defineProperty; var result = $defineProperty(object, object, object) && $defineProperty;
} catch(error) {} } catch (error) {
return result; }
}()); return result;
var stringFromCharCode = String.fromCharCode; }());
var floor = Math.floor; var stringFromCharCode = String.fromCharCode;
var fromCodePoint = function() { var floor = Math.floor;
var MAX_SIZE = 0x4000; var fromCodePoint = function () {
var codeUnits = []; var MAX_SIZE = 0x4000;
var highSurrogate; var codeUnits = [];
var lowSurrogate; var highSurrogate;
var index = -1; var lowSurrogate;
var length = arguments.length; var index = -1;
if (!length) { var length = arguments.length;
return ''; if (!length) {
} return '';
var result = ''; }
while (++index < length) { var result = '';
var codePoint = Number(arguments[index]); while (++index < length) {
if ( var codePoint = Number(arguments[index]);
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` if (
codePoint < 0 || // not a valid Unicode code point !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
codePoint > 0x10FFFF || // not a valid Unicode code point codePoint < 0 || // not a valid Unicode code point
floor(codePoint) != codePoint // not an integer codePoint > 0x10FFFF || // not a valid Unicode code point
) { floor(codePoint) != codePoint // not an integer
throw RangeError('Invalid code point: ' + codePoint); ) {
} throw RangeError('Invalid code point: ' + codePoint);
if (codePoint <= 0xFFFF) { // BMP code point }
codeUnits.push(codePoint); if (codePoint <= 0xFFFF) { // BMP code point
} else { // Astral code point; split in surrogate halves codeUnits.push(codePoint);
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae } else { // Astral code point; split in surrogate halves
codePoint -= 0x10000; // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
highSurrogate = (codePoint >> 10) + 0xD800; codePoint -= 0x10000;
lowSurrogate = (codePoint % 0x400) + 0xDC00; highSurrogate = (codePoint >> 10) + 0xD800;
codeUnits.push(highSurrogate, lowSurrogate); lowSurrogate = (codePoint % 0x400) + 0xDC00;
} codeUnits.push(highSurrogate, lowSurrogate);
if (index + 1 == length || codeUnits.length > MAX_SIZE) { }
result += stringFromCharCode.apply(null, codeUnits); if (index + 1 == length || codeUnits.length > MAX_SIZE) {
codeUnits.length = 0; result += stringFromCharCode.apply(null, codeUnits);
} codeUnits.length = 0;
} }
return result; }
}; return result;
if (defineProperty) { };
defineProperty(String, 'fromCodePoint', { if (defineProperty) {
'value': fromCodePoint, defineProperty(String, 'fromCodePoint', {
'configurable': true, 'value': fromCodePoint,
'writable': true 'configurable': true,
}); 'writable': true
} else { });
String.fromCodePoint = fromCodePoint; } else {
} String.fromCodePoint = fromCodePoint;
}()); }
}());
} }

@ -1,8 +1,8 @@
// Generated from PHP locale file // Generated from PHP locale file
var _tr = { var _tr = {
"wifi.connected_ip_is": "Connected, IP is ", "wifi.connected_ip_is": "Connected, IP is ",
"wifi.not_conn": "Not connected.", "wifi.not_conn": "Not connected.",
"wifi.enter_passwd": "Enter password for \":ssid:\"" "wifi.enter_passwd": "Enter password for \":ssid:\""
}; };
function tr(key) { return _tr[key] || '?'+key+'?'; } function tr(key) { return _tr[key] || '?'+key+'?'; }

@ -1,44 +1,44 @@
/** Module for toggling a modal overlay */ /** Module for toggling a modal overlay */
(function () { (function () {
var modal = {}; var modal = {};
var curCloseCb = null; var curCloseCb = null;
modal.show = function (sel, closeCb) { modal.show = function (sel, closeCb) {
var $m = $(sel); var $m = $(sel);
$m.removeClass('hidden visible'); $m.removeClass('hidden visible');
setTimeout(function () { setTimeout(function () {
$m.addClass('visible'); $m.addClass('visible');
}, 1); }, 1);
curCloseCb = closeCb; curCloseCb = closeCb;
}; };
modal.hide = function (sel) { modal.hide = function (sel) {
var $m = $(sel); var $m = $(sel);
$m.removeClass('visible'); $m.removeClass('visible');
setTimeout(function () { setTimeout(function () {
$m.addClass('hidden'); $m.addClass('hidden');
if (curCloseCb) curCloseCb(); if (curCloseCb) curCloseCb();
}, 500); // transition time }, 500); // transition time
}; };
modal.init = function () { modal.init = function () {
// close modal by click outside the dialog // close modal by click outside the dialog
$('.Modal').on('click', function () { $('.Modal').on('click', function () {
if ($(this).hasClass('no-close')) return; // this is a no-close modal if ($(this).hasClass('no-close')) return; // this is a no-close modal
modal.hide(this); modal.hide(this);
}); });
$('.Dialog').on('click', function (e) { $('.Dialog').on('click', function (e) {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
}); });
// Hide all modals on esc // Hide all modals on esc
$(window).on('keydown', function (e) { $(window).on('keydown', function (e) {
if (e.which == 27) { if (e.which == 27) {
modal.hide('.Modal'); modal.hide('.Modal');
} }
}); });
}; };
window.Modal = modal; window.Modal = modal;
})(); })();

@ -1,32 +1,32 @@
(function (nt) { (function (nt) {
var sel = '#notif'; var sel = '#notif';
var hideTmeo1; // timeout to start hiding (transition) var hideTmeo1; // timeout to start hiding (transition)
var hideTmeo2; // timeout to add the hidden class var hideTmeo2; // timeout to add the hidden class
nt.show = function (message, timeout) { nt.show = function (message, timeout) {
$(sel).html(message); $(sel).html(message);
Modal.show(sel); Modal.show(sel);
clearTimeout(hideTmeo1); clearTimeout(hideTmeo1);
clearTimeout(hideTmeo2); clearTimeout(hideTmeo2);
if (undef(timeout)) timeout = 2500; if (undef(timeout)) timeout = 2500;
hideTmeo1 = setTimeout(nt.hide, timeout); hideTmeo1 = setTimeout(nt.hide, timeout);
}; };
nt.hide = function () { nt.hide = function () {
var $m = $(sel); var $m = $(sel);
$m.removeClass('visible'); $m.removeClass('visible');
hideTmeo2 = setTimeout(function () { hideTmeo2 = setTimeout(function () {
$m.addClass('hidden'); $m.addClass('hidden');
}, 250); // transition time }, 250); // transition time
}; };
nt.init = function() { nt.init = function () {
$(sel).on('click', function() { $(sel).on('click', function () {
nt.hide(this); nt.hide(this);
}); });
}; };
})(window.Notify = {}); })(window.Notify = {});

@ -1,27 +1,29 @@
$.ready(() => { $.ready(() => {
const input = qs('#softkb-input') const input = qs('#softkb-input');
let keyboardOpen = false if (!input) return; // abort, we're not on the terminal page
let keyboardOpen = false;
let updateInputPosition = function () { let updateInputPosition = function () {
if (!keyboardOpen) return if (!keyboardOpen) return;
let [x, y] = Screen.gridToScreen(Screen.cursor.x, Screen.cursor.y) let [x, y] = Screen.gridToScreen(Screen.cursor.x, Screen.cursor.y);
input.style.transform = `translate(${x}px, ${y}px)` input.style.transform = `translate(${x}px, ${y}px)`
} };
input.addEventListener('focus', () => { input.addEventListener('focus', () => {
keyboardOpen = true keyboardOpen = true;
updateInputPosition() updateInputPosition()
}) });
input.addEventListener('blur', () => (keyboardOpen = false)) input.addEventListener('blur', () => (keyboardOpen = false));
Screen.on('cursor-moved', updateInputPosition) Screen.on('cursor-moved', updateInputPosition);
window.kbOpen = function openSoftKeyboard (open) { window.kbOpen = function openSoftKeyboard (open) {
keyboardOpen = open keyboardOpen = open;
updateInputPosition() updateInputPosition();
if (open) input.focus() if (open) input.focus();
else input.blur() else input.blur()
} };
let lastCompositionString = ''; let lastCompositionString = '';
let compositing = false; let compositing = false;
@ -47,7 +49,7 @@ $.ready(() => {
newValue) newValue)
} }
lastCompositionString = newValue; lastCompositionString = newValue;
} };
input.addEventListener('keydown', e => { input.addEventListener('keydown', e => {
if (e.key === 'Unidentified') return; if (e.key === 'Unidentified') return;
@ -55,9 +57,9 @@ $.ready(() => {
e.preventDefault(); e.preventDefault();
input.value = ''; input.value = '';
if (e.key === 'Backspace') Input.sendString('\b') if (e.key === 'Backspace') Input.sendString('\b');
else if (e.key === 'Enter') Input.sendString('\x0d') else if (e.key === 'Enter') Input.sendString('\x0d')
}) });
input.addEventListener('input', e => { input.addEventListener('input', e => {
e.stopPropagation(); e.stopPropagation();
@ -66,11 +68,11 @@ $.ready(() => {
} else { } else {
if (e.data) Input.sendString(e.data); if (e.data) Input.sendString(e.data);
else if (e.inputType === 'deleteContentBackward') { else if (e.inputType === 'deleteContentBackward') {
lastCompositionString lastCompositionString = '';
sendInputDelta(''); sendInputDelta('');
} }
} }
}) });
input.addEventListener('compositionstart', e => { input.addEventListener('compositionstart', e => {
lastCompositionString = ''; lastCompositionString = '';
compositing = true; compositing = true;
@ -82,4 +84,4 @@ $.ready(() => {
}); });
Screen.on('open-soft-keyboard', () => input.focus()) Screen.on('open-soft-keyboard', () => input.focus())
}) });

@ -22,6 +22,7 @@ var Input = (function() {
mt_click: false, mt_click: false,
mt_move: false, mt_move: false,
no_keys: false, no_keys: false,
crlf_mode: false,
}; };
/** Send a literal message */ /** Send a literal message */
@ -53,7 +54,7 @@ var Input = (function() {
var keymap = { var keymap = {
'tab': '\x09', 'tab': '\x09',
'backspace': '\x08', 'backspace': '\x08',
'enter': '\x0d', 'enter': opts.crlf_mode ? '\x0d\x0a' : '\x0d',
'ctrl+enter': '\x0a', 'ctrl+enter': '\x0a',
'esc': '\x1b', 'esc': '\x1b',
'up': ca('\x1bOA', '\x1b[A'), 'up': ca('\x1bOA', '\x1b[A'),
@ -207,11 +208,12 @@ var Input = (function() {
sendString: sendStrMsg, sendString: sendStrMsg,
/** Enable alternate key modes (cursors, numpad, fn) */ /** Enable alternate key modes (cursors, numpad, fn) */
setAlts: function(cu, np, fn) { setAlts: function(cu, np, fn, crlf) {
if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) { if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn || opts.crlf_mode != crlf) {
opts.cu_alt = cu; opts.cu_alt = cu;
opts.np_alt = np; opts.np_alt = np;
opts.fn_alt = fn; opts.fn_alt = fn;
opts.crlf_mode = crlf;
// rebind keys - codes have changed // rebind keys - codes have changed
_bindFnKeys(); _bindFnKeys();

@ -64,6 +64,7 @@ class TermScreen {
visible: true, visible: true,
hanging: false, hanging: false,
style: 'block', style: 'block',
blinkEnable: true,
blinkInterval: 0, blinkInterval: 0,
}; };
@ -205,17 +206,17 @@ class TermScreen {
e.preventDefault(); e.preventDefault();
selectEnd(...touchPosition); selectEnd(...touchPosition);
let touchSelectMenu = qs('#touch-select-menu') let touchSelectMenu = qs('#touch-select-menu');
touchSelectMenu.classList.add('open'); touchSelectMenu.classList.add('open');
let rect = touchSelectMenu.getBoundingClientRect() let rect = touchSelectMenu.getBoundingClientRect();
// use middle position for x and one line above for y // use middle position for x and one line above for y
let selectionPos = this.gridToScreen( let selectionPos = this.gridToScreen(
(this.selection.start[0] + this.selection.end[0]) / 2, (this.selection.start[0] + this.selection.end[0]) / 2,
this.selection.start[1] - 1 this.selection.start[1] - 1
); );
selectionPos[0] -= rect.width / 2 selectionPos[0] -= rect.width / 2;
selectionPos[1] -= rect.height / 2 selectionPos[1] -= rect.height / 2;
touchSelectMenu.style.transform = `translate(${selectionPos[0]}px, ${ touchSelectMenu.style.transform = `translate(${selectionPos[0]}px, ${
selectionPos[1]}px)` selectionPos[1]}px)`
} }
@ -242,13 +243,15 @@ class TermScreen {
e.preventDefault(); e.preventDefault();
this.emit('open-soft-keyboard'); this.emit('open-soft-keyboard');
} }
}) });
$.ready(() => { $.ready(() => {
let copyButton = qs('#touch-select-copy-btn') let copyButton = qs('#touch-select-copy-btn');
copyButton.addEventListener('click', () => { if (copyButton) {
this.copySelectionToClipboard(); copyButton.addEventListener('click', () => {
}); this.copySelectionToClipboard();
});
}
}); });
this.canvas.addEventListener('mousemove', e => { this.canvas.addEventListener('mousemove', e => {
@ -274,7 +277,7 @@ class TermScreen {
this.canvas.addEventListener('contextmenu', e => { this.canvas.addEventListener('contextmenu', e => {
// prevent mouse keys getting stuck // prevent mouse keys getting stuck
e.preventDefault(); e.preventDefault();
}) });
// bind ctrl+shift+c to copy // bind ctrl+shift+c to copy
key('⌃+⇧+c', e => { key('⌃+⇧+c', e => {
@ -333,8 +336,8 @@ class TermScreen {
} }
getColor (i) { getColor (i) {
if (i === -1) return SELECTION_FG if (i === -1) return SELECTION_FG;
if (i === -2) return SELECTION_BG if (i === -2) return SELECTION_BG;
return this.colors[i] return this.colors[i]
} }
@ -398,29 +401,32 @@ class TermScreen {
const cellSize = this.getCellSize(); const cellSize = this.getCellSize();
// real height of the canvas element in pixels // real height of the canvas element in pixels
let realWidth = width * cellSize.width let realWidth = width * cellSize.width;
let realHeight = height * cellSize.height let realHeight = height * cellSize.height;
if (fitIntoWidth && fitIntoHeight) { if (fitIntoWidth && fitIntoHeight) {
if (realWidth > fitIntoWidth || realHeight > fitIntoHeight) { if (realWidth > fitIntoWidth || realHeight > fitIntoHeight) {
let terminalAspect = realWidth / realHeight let terminalAspect = realWidth / realHeight;
let fitAspect = fitIntoWidth / fitIntoHeight let fitAspect = fitIntoWidth / fitIntoHeight;
if (terminalAspect < fitAspect) { if (terminalAspect < fitAspect) {
// align heights // align heights
realHeight = fitIntoHeight realHeight = fitIntoHeight;
realWidth = realHeight * terminalAspect realWidth = realHeight * terminalAspect
} else { }
else {
// align widths // align widths
realWidth = fitIntoWidth realWidth = fitIntoWidth;
realHeight = realWidth / terminalAspect realHeight = realWidth / terminalAspect
} }
} }
} else if (fitIntoWidth && realWidth > fitIntoWidth) { }
realHeight = fitIntoWidth / (realWidth / realHeight) else if (fitIntoWidth && realWidth > fitIntoWidth) {
realHeight = fitIntoWidth / (realWidth / realHeight);
realWidth = fitIntoWidth realWidth = fitIntoWidth
} else if (fitIntoHeight && realHeight > fitIntoHeight) { }
realWidth = fitIntoHeight * (realWidth / realHeight) else if (fitIntoHeight && realHeight > fitIntoHeight) {
realWidth = fitIntoHeight * (realWidth / realHeight);
realHeight = fitIntoHeight realHeight = fitIntoHeight
} }
@ -552,11 +558,11 @@ class TermScreen {
let underline = false; let underline = false;
let blink = false; let blink = false;
let strike = false; let strike = false;
if (attrs & 1 << 1) ctx.globalAlpha = 0.5; if (attrs & (1 << 1)) ctx.globalAlpha = 0.5;
if (attrs & 1 << 3) underline = true; if (attrs & (1 << 3)) underline = true;
if (attrs & 1 << 4) blink = true; if (attrs & (1 << 4)) blink = true;
if (attrs & 1 << 5) text = TermScreen.alphaToFraktur(text); if (attrs & (1 << 5)) text = TermScreen.alphaToFraktur(text);
if (attrs & 1 << 6) strike = true; if (attrs & (1 << 6)) strike = true;
if (!blink || this.window.blinkStyleOn) { if (!blink || this.window.blinkStyleOn) {
ctx.fillStyle = this.getColor(fg); ctx.fillStyle = this.getColor(fg);
@ -618,14 +624,18 @@ class TermScreen {
// Map of (cell index) -> boolean, whether or not a cell needs to be redrawn // Map of (cell index) -> boolean, whether or not a cell needs to be redrawn
const updateMap = new Map(); const updateMap = new Map();
const cursorActive = (this.cursor.blinkOn || !this.cursor.blinkEnable);
for (let cell = 0; cell < screenLength; cell++) { for (let cell = 0; cell < screenLength; cell++) {
let x = cell % width; let x = cell % width;
let y = Math.floor(cell / width); let y = Math.floor(cell / width);
let isCursor = this.cursor.x === x && this.cursor.y === y && let isCursor = !this.cursor.hanging
!this.cursor.hanging; && this.cursor.x === x
let invertForCursor = isCursor && this.cursor.blinkOn && && this.cursor.y === y;
this.cursor.style === 'block';
let inSelection = this.isInSelection(x, y) let invertForCursor = isCursor && cursorActive && this.cursor.style === 'block';
let inSelection = this.isInSelection(x, y);
let text = this.screen[cell]; let text = this.screen[cell];
let fg = invertForCursor ? this.screenBG[cell] : this.screenFG[cell]; let fg = invertForCursor ? this.screenBG[cell] : this.screenFG[cell];
@ -636,7 +646,7 @@ class TermScreen {
if (invertForCursor && fg === bg) bg = fg === 0 ? 7 : 0; if (invertForCursor && fg === bg) bg = fg === 0 ? 7 : 0;
if (inSelection) { if (inSelection) {
fg = -1 fg = -1;
bg = -2 bg = -2
} }
@ -695,7 +705,7 @@ class TermScreen {
this.drawnScreenAttrs[cell] = attrs; this.drawnScreenAttrs[cell] = attrs;
} }
if (isCursor && this.cursor.blinkOn && this.cursor.style !== 'block') { if (isCursor && cursorActive && this.cursor.style !== 'block') {
ctx.save(); ctx.save();
ctx.beginPath(); ctx.beginPath();
if (this.cursor.style === 'bar') { if (this.cursor.style === 'bar') {
@ -748,20 +758,21 @@ class TermScreen {
} }
// attributes // attributes
let attributes = parse2B(str, i); let attributes = parse3B(str, i);
i += 2; i += 3;
this.cursor.visible = !!(attributes & 1); this.cursor.visible = !!(attributes & 1);
this.cursor.hanging = !!(attributes & 1 << 1); this.cursor.hanging = !!(attributes & (1 << 1));
Input.setAlts( Input.setAlts(
!!(attributes & 1 << 2), // cursors alt !!(attributes & (1 << 2)), // cursors alt
!!(attributes & 1 << 3), // numpad alt !!(attributes & (1 << 3)), // numpad alt
!!(attributes & 1 << 4) // fn keys alt !!(attributes & (1 << 4)), // fn keys alt
!!(attributes & (1 << 12)) // crlf mode
); );
let trackMouseClicks = !!(attributes & 1 << 5); let trackMouseClicks = !!(attributes & (1 << 5));
let trackMouseMovement = !!(attributes & 1 << 6); let trackMouseMovement = !!(attributes & (1 << 6));
Input.setMouseMode(trackMouseClicks, trackMouseMovement); Input.setMouseMode(trackMouseClicks, trackMouseMovement);
this.selection.selectable = !trackMouseMovement; this.selection.selectable = !trackMouseMovement;
@ -771,12 +782,19 @@ class TermScreen {
movement: trackMouseMovement movement: trackMouseMovement
}; };
let showButtons = !!(attributes & 1 << 7); let showButtons = !!(attributes & (1 << 7));
let showConfigLinks = !!(attributes & 1 << 8); let showConfigLinks = !!(attributes & (1 << 8));
$('.x-term-conf-btn').toggleClass('hidden', !showConfigLinks); $('.x-term-conf-btn').toggleClass('hidden', !showConfigLinks);
$('#action-buttons').toggleClass('hidden', !showButtons); $('#action-buttons').toggleClass('hidden', !showButtons);
let cursorStyle = (attributes >> 9) & 0x07;
// 0 - Block blink, 2 - Block steady
// 3 - Under blink, 4 - Under steady
// 5 - I-bar blink, 6 - I-bar steady
this.cursor.style = cursorStyle<3?'block':cursorStyle<5?'line':'bar';
this.cursor.blinkEnable = cursorStyle === 0 || cursorStyle === 3 || cursorStyle === 5;
// content // content
let fg = 7; let fg = 7;
let bg = 0; let bg = 0;
@ -932,23 +950,23 @@ Screen.once('load', () => {
} }
}); });
let fitScreen = false let fitScreen = false;
function fitScreenIfNeeded () { function fitScreenIfNeeded () {
Screen.window.fitIntoWidth = fitScreen ? window.innerWidth : 0 Screen.window.fitIntoWidth = fitScreen ? window.innerWidth : 0;
Screen.window.fitIntoHeight = fitScreen ? window.innerHeight : 0 Screen.window.fitIntoHeight = fitScreen ? window.innerHeight : 0
} }
fitScreenIfNeeded(); fitScreenIfNeeded();
window.addEventListener('resize', fitScreenIfNeeded) window.addEventListener('resize', fitScreenIfNeeded);
window.toggleFitScreen = function () { window.toggleFitScreen = function () {
fitScreen = !fitScreen; fitScreen = !fitScreen;
const resizeButtonIcon = qs('#resize-button-icon') const resizeButtonIcon = qs('#resize-button-icon');
if (fitScreen) { if (fitScreen) {
resizeButtonIcon.classList.remove('icn-resize-small') resizeButtonIcon.classList.remove('icn-resize-small');
resizeButtonIcon.classList.add('icn-resize-full') resizeButtonIcon.classList.add('icn-resize-full')
} else { } else {
resizeButtonIcon.classList.remove('icn-resize-full') resizeButtonIcon.classList.remove('icn-resize-full');
resizeButtonIcon.classList.add('icn-resize-small') resizeButtonIcon.classList.add('icn-resize-small')
} }
fitScreenIfNeeded(); fitScreenIfNeeded();
} };

@ -1,146 +1,146 @@
/** File upload utility */ /** File upload utility */
var TermUpl = (function() { var TermUpl = (function () {
var lines, // array of lines without newlines var lines, // array of lines without newlines
line_i, // current line index line_i, // current line index
fuTout, // timeout handle for line sending fuTout, // timeout handle for line sending
send_delay_ms, // delay between lines (ms) send_delay_ms, // delay between lines (ms)
nl_str, // newline string to use nl_str, // newline string to use
curLine, // current line (when using fuOil) curLine, // current line (when using fuOil)
inline_pos; // Offset in line (for long lines) inline_pos; // Offset in line (for long lines)
// lines longer than this are split to chunks // lines longer than this are split to chunks
// sending a super-ling string through the socket is not a good idea // sending a super-ling string through the socket is not a good idea
var MAX_LINE_LEN = 128; var MAX_LINE_LEN = 128;
function fuOpen() { function fuOpen() {
fuStatus("Ready..."); fuStatus("Ready...");
Modal.show('#fu_modal', onClose); Modal.show('#fu_modal', onClose);
$('#fu_form').toggleClass('busy', false); $('#fu_form').toggleClass('busy', false);
Input.blockKeys(true); Input.blockKeys(true);
} }
function onClose() { function onClose() {
console.log("Upload modal closed."); console.log("Upload modal closed.");
clearTimeout(fuTout); clearTimeout(fuTout);
line_i = 0; line_i = 0;
Input.blockKeys(false); Input.blockKeys(false);
} }
function fuStatus(msg) { function fuStatus(msg) {
qs('#fu_prog').textContent = msg; qs('#fu_prog').textContent = msg;
} }
function fuSend() { function fuSend() {
var v = qs('#fu_text').value; var v = qs('#fu_text').value;
if (!v.length) { if (!v.length) {
fuClose(); fuClose();
return; return;
} }
lines = v.split('\n'); lines = v.split('\n');
line_i = 0; line_i = 0;
inline_pos = 0; // offset in line inline_pos = 0; // offset in line
send_delay_ms = qs('#fu_delay').value; send_delay_ms = qs('#fu_delay').value;
// sanitize - 0 causes overflows // sanitize - 0 causes overflows
if (send_delay_ms < 0) { if (send_delay_ms < 0) {
send_delay_ms = 0; send_delay_ms = 0;
qs('#fu_delay').value = send_delay_ms; qs('#fu_delay').value = send_delay_ms;
} }
nl_str = { nl_str = {
'CR': '\r', 'CR': '\r',
'LF': '\n', 'LF': '\n',
'CRLF': '\r\n', 'CRLF': '\r\n',
}[qs('#fu_crlf').value]; }[qs('#fu_crlf').value];
$('#fu_form').toggleClass('busy', true); $('#fu_form').toggleClass('busy', true);
fuStatus("Starting..."); fuStatus("Starting...");
fuSendLine(); fuSendLine();
} }
function fuSendLine() { function fuSendLine() {
if (!$('#fu_modal').hasClass('visible')) { if (!$('#fu_modal').hasClass('visible')) {
// Modal is closed, cancel // Modal is closed, cancel
return; return;
} }
if (!Conn.canSend()) { if (!Conn.canSend()) {
// postpone // postpone
fuTout = setTimeout(fuSendLine, 1); fuTout = setTimeout(fuSendLine, 1);
return; return;
} }
if (inline_pos == 0) { if (inline_pos == 0) {
curLine = lines[line_i++] + nl_str; curLine = lines[line_i++] + nl_str;
} }
var chunk; var chunk;
if ((curLine.length - inline_pos) <= MAX_LINE_LEN) { if ((curLine.length - inline_pos) <= MAX_LINE_LEN) {
chunk = curLine.substr(inline_pos, MAX_LINE_LEN); chunk = curLine.substr(inline_pos, MAX_LINE_LEN);
inline_pos = 0; inline_pos = 0;
} else { } else {
chunk = curLine.substr(inline_pos, MAX_LINE_LEN); chunk = curLine.substr(inline_pos, MAX_LINE_LEN);
inline_pos += MAX_LINE_LEN; inline_pos += MAX_LINE_LEN;
} }
if (!Input.sendString(chunk)) { if (!Input.sendString(chunk)) {
fuStatus("FAILED!"); fuStatus("FAILED!");
return; return;
} }
var all = lines.length; var all = lines.length;
fuStatus(line_i+" / "+all+ " ("+(Math.round((line_i/all)*1000)/10)+"%)"); fuStatus(line_i + " / " + all + " (" + (Math.round((line_i / all) * 1000) / 10) + "%)");
if (lines.length > line_i || inline_pos > 0) { if (lines.length > line_i || inline_pos > 0) {
fuTout = setTimeout(fuSendLine, send_delay_ms); fuTout = setTimeout(fuSendLine, send_delay_ms);
} else { } else {
closeWhenReady(); closeWhenReady();
} }
} }
function closeWhenReady() { function closeWhenReady() {
if (!Conn.canSend()) { if (!Conn.canSend()) {
// stuck in XOFF still, wait to process... // stuck in XOFF still, wait to process...
fuStatus("Waiting for Tx buffer..."); fuStatus("Waiting for Tx buffer...");
setTimeout(closeWhenReady, 100); setTimeout(closeWhenReady, 100);
} else { } else {
fuStatus("Done."); fuStatus("Done.");
// delay to show it // delay to show it
setTimeout(function() { setTimeout(function () {
fuClose(); fuClose();
}, 100); }, 100);
} }
} }
function fuClose() { function fuClose() {
Modal.hide('#fu_modal'); Modal.hide('#fu_modal');
} }
return { return {
init: function() { init: function () {
qs('#fu_file').addEventListener('change', function (evt) { qs('#fu_file').addEventListener('change', function (evt) {
var reader = new FileReader(); var reader = new FileReader();
var file = evt.target.files[0]; var file = evt.target.files[0];
console.log("Selected file type: "+file.type); console.log("Selected file type: " + file.type);
if (!file.type.match(/text\/.*|application\/(json|csv|.*xml.*|.*script.*)/)) { if (!file.type.match(/text\/.*|application\/(json|csv|.*xml.*|.*script.*)/)) {
// Deny load of blobs like img - can crash browser and will get corrupted anyway // 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?")) { if (!confirm("This does not look like a text file: " + file.type + "\nReally load?")) {
qs('#fu_file').value = ''; qs('#fu_file').value = '';
return; return;
} }
} }
reader.onload = function(e) { reader.onload = function (e) {
var txt = e.target.result.replace(/[\r\n]+/,'\n'); var txt = e.target.result.replace(/[\r\n]+/, '\n');
qs('#fu_text').value = txt; qs('#fu_text').value = txt;
}; };
console.log("Loading file..."); console.log("Loading file...");
reader.readAsText(file); reader.readAsText(file);
}, false); }, false);
}, },
close: fuClose, close: fuClose,
start: fuSend, start: fuSend,
open: fuOpen, open: fuOpen,
} }
})(); })();

@ -1,15 +1,21 @@
/** Make a node */ /** Make a node */
function mk(e) {return document.createElement(e)} function mk(e) {
return document.createElement(e)
}
/** Find one by query */ /** Find one by query */
function qs(s) {return document.querySelector(s)} function qs(s) {
return document.querySelector(s)
}
/** Find all by query */ /** Find all by query */
function qsa(s) {return document.querySelectorAll(s)} function qsa(s) {
return document.querySelectorAll(s)
}
/** Convert any to bool safely */ /** Convert any to bool safely */
function bool(x) { function bool(x) {
return (x === 1 || x === '1' || x === true || x === 'true'); return (x === 1 || x === '1' || x === true || x === 'true');
} }
/** /**
@ -18,52 +24,52 @@ function bool(x) {
* use $(...).on('keypress', cr(handler)) * use $(...).on('keypress', cr(handler))
*/ */
function cr(hdl) { function cr(hdl) {
return function(e) { return function (e) {
if (e.which == 10 || e.which == 13 || e.which == 32) { if (e.which == 10 || e.which == 13 || e.which == 32) {
hdl(); hdl();
} }
}; };
} }
/** Extend an objects with options */ /** Extend an objects with options */
function extend(defaults, options) { function extend(defaults, options) {
var target = {}; var target = {};
Object.keys(defaults).forEach(function(k){ Object.keys(defaults).forEach(function (k) {
target[k] = defaults[k]; target[k] = defaults[k];
}); });
Object.keys(options).forEach(function(k){ Object.keys(options).forEach(function (k) {
target[k] = options[k]; target[k] = options[k];
}); });
return target; return target;
} }
/** Escape string for use as literal in RegExp */ /** Escape string for use as literal in RegExp */
function rgxe(str) { function rgxe(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
} }
/** Format number to N decimal places, output as string */ /** Format number to N decimal places, output as string */
function numfmt(x, places) { function numfmt(x, places) {
var pow = Math.pow(10, places); var pow = Math.pow(10, places);
return Math.round(x*pow) / pow; return Math.round(x * pow) / pow;
} }
/** Get millisecond timestamp */ /** Get millisecond timestamp */
function msNow() { function msNow() {
return +(new Date); return +(new Date);
} }
/** Get ms elapsed since msNow() */ /** Get ms elapsed since msNow() */
function msElapsed(start) { function msElapsed(start) {
return msNow() - start; return msNow() - start;
} }
/** Shim for log base 10 */ /** Shim for log base 10 */
Math.log10 = Math.log10 || function(x) { Math.log10 = Math.log10 || function (x) {
return Math.log(x) / Math.LN10; return Math.log(x) / Math.LN10;
}; };
/** /**
@ -78,84 +84,84 @@ Math.log10 = Math.log10 || function(x) {
* @returns {String} result * @returns {String} result
*/ */
String.prototype.format = function () { String.prototype.format = function () {
var out = this; var out = this;
var repl = arguments; var repl = arguments;
if (arguments.length == 1 && (Array.isArray(arguments[0]) || typeof arguments[0] == 'object')) { if (arguments.length == 1 && (Array.isArray(arguments[0]) || typeof arguments[0] == 'object')) {
repl = arguments[0]; repl = arguments[0];
} }
for (var ph in repl) { for (var ph in repl) {
if (repl.hasOwnProperty(ph)) { if (repl.hasOwnProperty(ph)) {
var ph_orig = ph; var ph_orig = ph;
if (!ph.match(/^\{.*\}$/)) { if (!ph.match(/^\{.*\}$/)) {
ph = '{' + ph + '}'; ph = '{' + ph + '}';
} }
// replace all occurrences // replace all occurrences
var pattern = new RegExp(rgxe(ph), "g"); var pattern = new RegExp(rgxe(ph), "g");
out = out.replace(pattern, repl[ph_orig]); out = out.replace(pattern, repl[ph_orig]);
} }
} }
return out; return out;
}; };
/** HTML escape */ /** HTML escape */
function e(str) { function e(str) {
return $.htmlEscape(str); return $.htmlEscape(str);
} }
/** Check for undefined */ /** Check for undefined */
function undef(x) { function undef(x) {
return typeof x == 'undefined'; return typeof x == 'undefined';
} }
/** Safe json parse */ /** Safe json parse */
function jsp(str) { function jsp(str) {
try { try {
return JSON.parse(str); return JSON.parse(str);
} catch(e) { } catch (e) {
console.error(e); console.error(e);
return null; return null;
} }
} }
/** Create a character from ASCII code */ /** Create a character from ASCII code */
function Chr(n) { function Chr(n) {
return String.fromCharCode(n); return String.fromCharCode(n);
} }
/** Decode number from 2B encoding */ /** Decode number from 2B encoding */
function parse2B(s, i=0) { function parse2B(s, i = 0) {
return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127; return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127;
} }
/** Decode number from 3B encoding */ /** Decode number from 3B encoding */
function parse3B(s, i=0) { function parse3B(s, i = 0) {
return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127; return (s.charCodeAt(i) - 1) + (s.charCodeAt(i + 1) - 1) * 127 + (s.charCodeAt(i + 2) - 1) * 127 * 127;
} }
/** Encode using 2B encoding, returns string. */ /** Encode using 2B encoding, returns string. */
function encode2B(n) { function encode2B(n) {
var lsb, msb; var lsb, msb;
lsb = (n % 127); lsb = (n % 127);
n = ((n - lsb) / 127); n = ((n - lsb) / 127);
lsb += 1; lsb += 1;
msb = (n + 1); msb = (n + 1);
return Chr(lsb) + Chr(msb); return Chr(lsb) + Chr(msb);
} }
/** Encode using 3B encoding, returns string. */ /** Encode using 3B encoding, returns string. */
function encode3B(n) { function encode3B(n) {
var lsb, msb, xsb; var lsb, msb, xsb;
lsb = (n % 127); lsb = (n % 127);
n = (n - lsb) / 127; n = (n - lsb) / 127;
lsb += 1; lsb += 1;
msb = (n % 127); msb = (n % 127);
n = (n - msb) / 127; n = (n - msb) / 127;
msb += 1; msb += 1;
xsb = (n + 1); xsb = (n + 1);
return Chr(lsb) + Chr(msb) + Chr(xsb); return Chr(lsb) + Chr(msb) + Chr(xsb);
} }

@ -1,163 +1,163 @@
(function(w) { (function (w) {
var authStr = ['Open', 'WEP', 'WPA', 'WPA2', 'WPA/WPA2']; var authStr = ['Open', 'WEP', 'WPA', 'WPA2', 'WPA/WPA2'];
var curSSID; var curSSID;
// Get XX % for a slider input // Get XX % for a slider input
function rangePt(inp) { function rangePt(inp) {
return Math.round(((inp.value / inp.max)*100)) + '%'; return Math.round(((inp.value / inp.max) * 100)) + '%';
} }
// Display selected STA SSID etc // Display selected STA SSID etc
function selectSta(name, password, ip) { function selectSta(name, password, ip) {
$('#sta_ssid').val(name); $('#sta_ssid').val(name);
$('#sta_password').val(password); $('#sta_password').val(password);
$('#sta-nw').toggleClass('hidden', name.length == 0); $('#sta-nw').toggleClass('hidden', name.length == 0);
$('#sta-nw-nil').toggleClass('hidden', name.length > 0); $('#sta-nw-nil').toggleClass('hidden', name.length > 0);
$('#sta-nw .essid').html(e(name)); $('#sta-nw .essid').html(e(name));
var nopw = undef(password) || password.length == 0; var nopw = undef(password) || password.length == 0;
$('#sta-nw .passwd').toggleClass('hidden', nopw); $('#sta-nw .passwd').toggleClass('hidden', nopw);
$('#sta-nw .nopasswd').toggleClass('hidden', !nopw); $('#sta-nw .nopasswd').toggleClass('hidden', !nopw);
$('#sta-nw .ip').html(ip.length>0 ? tr('wifi.connected_ip_is')+ip : tr('wifi.not_conn')); $('#sta-nw .ip').html(ip.length > 0 ? tr('wifi.connected_ip_is') + ip : tr('wifi.not_conn'));
} }
/** Update display for received response */ /** Update display for received response */
function onScan(resp, status) { function onScan(resp, status) {
//var ap_json = { //var ap_json = {
// "result": { // "result": {
// "inProgress": "0", // "inProgress": "0",
// "APs": [ // "APs": [
// {"essid": "Chlivek", "bssid": "88:f7:c7:52:b3:99", "rssi": "204", "enc": "4", "channel": "1"}, // {"essid": "Chlivek", "bssid": "88:f7:c7:52:b3:99", "rssi": "204", "enc": "4", "channel": "1"},
// {"essid": "TyNikdy", "bssid": "5c:f4:ab:0d:f1:1b", "rssi": "164", "enc": "3", "channel": "1"}, // {"essid": "TyNikdy", "bssid": "5c:f4:ab:0d:f1:1b", "rssi": "164", "enc": "3", "channel": "1"},
// ] // ]
// } // }
//}; //};
if (status != 200) { if (status != 200) {
// bad response // bad response
rescan(5000); // wait 5sm then retry rescan(5000); // wait 5sm then retry
return; return;
} }
try { try {
resp = JSON.parse(resp); resp = JSON.parse(resp);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
rescan(5000); rescan(5000);
return; return;
} }
var done = !bool(resp.result.inProgress) && (resp.result.APs.length > 0); var done = !bool(resp.result.inProgress) && (resp.result.APs.length > 0);
rescan(done ? 15000 : 1000); rescan(done ? 15000 : 1000);
if (!done) return; // no redraw yet if (!done) return; // no redraw yet
// clear the AP list // clear the AP list
var $list = $('#ap-list'); var $list = $('#ap-list');
// remove old APs // remove old APs
$('#ap-list .AP').remove(); $('#ap-list .AP').remove();
$list.toggleClass('hidden', !done); $list.toggleClass('hidden', !done);
$('#ap-loader').toggleClass('hidden', done); $('#ap-loader').toggleClass('hidden', done);
// scan done // scan done
resp.result.APs.sort(function (a, b) { resp.result.APs.sort(function (a, b) {
return b.rssi - a.rssi; return b.rssi - a.rssi;
}).forEach(function (ap) { }).forEach(function (ap) {
ap.enc = parseInt(ap.enc); ap.enc = parseInt(ap.enc);
if (ap.enc > 4) return; // hide unsupported auths if (ap.enc > 4) return; // hide unsupported auths
var item = mk('div'); var item = mk('div');
var $item = $(item) var $item = $(item)
.data('ssid', ap.essid) .data('ssid', ap.essid)
.data('pwd', ap.enc) .data('pwd', ap.enc)
.attr('tabindex', 0) .attr('tabindex', 0)
.addClass('AP'); .addClass('AP');
// mark current SSID // mark current SSID
if (ap.essid == curSSID) { if (ap.essid == curSSID) {
$item.addClass('selected'); $item.addClass('selected');
} }
var inner = mk('div'); var inner = mk('div');
$(inner).addClass('inner') $(inner).addClass('inner')
.htmlAppend('<div class="rssi">{0}</div>'.format(ap.rssi_perc)) .htmlAppend('<div class="rssi">{0}</div>'.format(ap.rssi_perc))
.htmlAppend('<div class="essid" title="{0}">{0}</div>'.format($.htmlEscape(ap.essid))) .htmlAppend('<div class="essid" title="{0}">{0}</div>'.format($.htmlEscape(ap.essid)))
.htmlAppend('<div class="auth">{0}</div>'.format(authStr[ap.enc])); .htmlAppend('<div class="auth">{0}</div>'.format(authStr[ap.enc]));
$item.on('click', function () { $item.on('click', function () {
var $th = $(this); var $th = $(this);
var conn_ssid = $th.data('ssid'); var conn_ssid = $th.data('ssid');
var conn_pass = ''; var conn_pass = '';
if (+$th.data('pwd')) { if (+$th.data('pwd')) {
// this AP needs a password // this AP needs a password
conn_pass = prompt(tr("wifi.enter_passwd").replace(":ssid:", conn_ssid)); conn_pass = prompt(tr("wifi.enter_passwd").replace(":ssid:", conn_ssid));
if (!conn_pass) return; if (!conn_pass) return;
} }
$('#sta_password').val(conn_pass); $('#sta_password').val(conn_pass);
$('#sta_ssid').val(conn_ssid); $('#sta_ssid').val(conn_ssid);
selectSta(conn_ssid, conn_pass, ''); selectSta(conn_ssid, conn_pass, '');
}); });
item.appendChild(inner); item.appendChild(inner);
$list[0].appendChild(item); $list[0].appendChild(item);
}); });
} }
function startScanning() { function startScanning() {
$('#ap-loader').removeClass('hidden'); $('#ap-loader').removeClass('hidden');
$('#ap-scan').addClass('hidden'); $('#ap-scan').addClass('hidden');
$('#ap-loader .anim-dots').html('.'); $('#ap-loader .anim-dots').html('.');
scanAPs(); scanAPs();
} }
/** Ask the CGI what APs are visible (async) */ /** Ask the CGI what APs are visible (async) */
function scanAPs() { function scanAPs() {
if (_demo) { if (_demo) {
onScan(_demo_aps, 200); onScan(_demo_aps, 200);
} else { } else {
$.get('http://' + _root + '/cfg/wifi/scan', onScan); $.get('http://' + _root + '/cfg/wifi/scan', onScan);
} }
} }
function rescan(time) { function rescan(time) {
setTimeout(scanAPs, time); setTimeout(scanAPs, time);
} }
/** Set up the WiFi page */ /** Set up the WiFi page */
function wifiInit(cfg) { function wifiInit(cfg) {
// Update slider value displays // Update slider value displays
$('.Row.range').forEach(function(x) { $('.Row.range').forEach(function (x) {
var inp = x.querySelector('input'); var inp = x.querySelector('input');
var disp1 = x.querySelector('.x-disp1'); var disp1 = x.querySelector('.x-disp1');
var disp2 = x.querySelector('.x-disp2'); var disp2 = x.querySelector('.x-disp2');
var t = rangePt(inp); var t = rangePt(inp);
$(disp1).html(t); $(disp1).html(t);
$(disp2).html(t); $(disp2).html(t);
$(inp).on('input', function() { $(inp).on('input', function () {
t = rangePt(inp); t = rangePt(inp);
$(disp1).html(t); $(disp1).html(t);
$(disp2).html(t); $(disp2).html(t);
}); });
}); });
// Forget STA credentials // Forget STA credentials
$('#forget-sta').on('click', function() { $('#forget-sta').on('click', function () {
selectSta('', '', ''); selectSta('', '', '');
return false; return false;
}); });
selectSta(cfg.sta_ssid, cfg.sta_password, cfg.sta_active_ip); selectSta(cfg.sta_ssid, cfg.sta_password, cfg.sta_active_ip);
curSSID = cfg.sta_active_ssid; curSSID = cfg.sta_active_ssid;
} }
w.init = wifiInit; w.init = wifiInit;
w.startScanning = startScanning; w.startScanning = startScanning;
})(window.WiFi = {}); })(window.WiFi = {});

@ -51,6 +51,7 @@ return [
'term.default_fg_bg' => 'Text / background', 'term.default_fg_bg' => 'Text / background',
'term.buttons' => 'Button labels', 'term.buttons' => 'Button labels',
'term.theme' => 'Color scheme', 'term.theme' => 'Color scheme',
'term.cursor_shape' => 'Cursor style',
'term.parser_tout_ms' => 'Parser timeout', 'term.parser_tout_ms' => 'Parser timeout',
'term.display_tout_ms' => 'Redraw delay', 'term.display_tout_ms' => 'Redraw delay',
'term.display_cooldown_ms' => 'Redraw cooldown', 'term.display_cooldown_ms' => 'Redraw cooldown',
@ -58,8 +59,16 @@ return [
'term.show_config_links' => 'Show nav links', 'term.show_config_links' => 'Show nav links',
'term.show_buttons' => 'Show buttons', 'term.show_buttons' => 'Show buttons',
'term.loopback' => 'Local Echo', 'term.loopback' => 'Local Echo',
'term.crlf_mode' => 'Enter sends CR+LF',
'term.button_msgs' => 'Button codes<br>(ASCII, dec, CSV)', 'term.button_msgs' => 'Button codes<br>(ASCII, dec, CSV)',
'cursor.block_blink' => 'Block, blinking',
'cursor.block_steady' => 'Block, steady',
'cursor.underline_blink' => 'Underline, blinking',
'cursor.underline_steady' => 'Underline, steady',
'cursor.bar_blink' => 'I-bar, blinking',
'cursor.bar_steady' => 'I-bar, steady',
// terminal color labels // terminal color labels
'color.0' => 'Black', 'color.0' => 'Black',
'color.1' => 'Red', 'color.1' => 'Red',

@ -108,6 +108,18 @@
<input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%"> <input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%">
</div> </div>
<div class="Row">
<label><?= tr("term.cursor_shape") ?></label>
<select name="cursor_shape" id="cursor_shape">
<option value="0"><?= tr("cursor.block_blink") ?></option>
<option value="2"><?= tr("cursor.block_steady") ?></option>
<option value="3"><?= tr("cursor.underline_blink") ?></option>
<option value="4"><?= tr("cursor.underline_steady") ?></option>
<option value="5"><?= tr("cursor.bar_blink") ?></option>
<option value="6"><?= tr("cursor.bar_steady") ?></option>
</select>
</div>
<div class="Row buttons"> <div class="Row buttons">
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a> <a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
</div> </div>
@ -153,6 +165,12 @@
<input type="hidden" id="fn_alt_mode" name="fn_alt_mode" value="%fn_alt_mode%"> <input type="hidden" id="fn_alt_mode" name="fn_alt_mode" value="%fn_alt_mode%">
</div> </div>
<div class="Row checkbox" >
<label><?= tr('term.crlf_mode') ?></label><!--
--><span class="box" tabindex=0 role=checkbox></span>
<input type="hidden" id="crlf_mode" name="crlf_mode" value="%crlf_mode%">
</div>
<div class="Row checkbox" > <div class="Row checkbox" >
<label><?= tr('term.show_buttons') ?></label><!-- <label><?= tr('term.show_buttons') ?></label><!--
--><span class="box" tabindex=0 role=checkbox></span> --><span class="box" tabindex=0 role=checkbox></span>
@ -179,6 +197,7 @@
<script> <script>
$('#default_fg').val(%default_fg%); $('#default_fg').val(%default_fg%);
$('#default_bg').val(%default_bg%); $('#default_bg').val(%default_bg%);
$('#cursor_shape').val(%cursor_shape%);
$('#theme').val(%theme%); $('#theme').val(%theme%);
function showColor() { function showColor() {

Loading…
Cancel
Save