diff --git a/_build_js.sh b/_build_js.sh
index 7122d5e..fa03512 100755
--- a/_build_js.sh
+++ b/_build_js.sh
@@ -5,17 +5,13 @@ mkdir -p out/js
echo 'Generating lang.js...'
php ./dump_js_lang.php
-if [[ $ESP_DEMO ]]; then
- demofile=js/demo.js
-else
- demofile=
-fi
-
echo 'Processing JS...'
if [[ $ESP_PROD ]]; then
smarg=
+ demofile=
else
smarg=--source-maps
+ demofile=js/demo.js
fi
npm run babel -- -o "out/js/app.$FRONT_END_HASH.js" ${smarg} js/lib \
diff --git a/_debug_replacements.php b/_debug_replacements.php
index 3ae64da..c7d4124 100644
--- a/_debug_replacements.php
+++ b/_debug_replacements.php
@@ -83,7 +83,7 @@ return [
'term_height' => '25',
'default_bg' => '0',
'default_fg' => '7',
- 'show_buttons' => '0',
+ 'show_buttons' => '1',
'show_config_links' => '1',
'uart_baud' => 115200,
diff --git a/base.php b/base.php
index 2e211d0..a049c68 100644
--- a/base.php
+++ b/base.php
@@ -12,19 +12,27 @@ if (!empty($argv[1])) {
parse_str($argv[1], $_GET);
}
-if (!file_exists(__DIR__ . '/_env.php')) {
- die("Copy _env.php.example to _env.php and check the settings inside!");
-}
-
define('GIT_HASH', trim(shell_exec('git rev-parse --short HEAD')));
-require_once __DIR__ . '/_env.php';
-
$prod = defined('STDIN');
define('DEBUG', !$prod);
-$root = DEBUG ? json_encode(ESP_IP) : 'location.host';
+
+// Resolve hostname for ajax etc
+$root = 'location.host';
+if (!file_exists(__DIR__ . '/_env.php')) {
+ if (DEBUG) {
+ die("No _env.php found! Copy _env.php.example to _env.php and check the settings inside!");
+ }
+} else {
+ if (DEBUG) {
+ require_once __DIR__ . '/_env.php';
+ $root = json_encode(ESP_IP);
+ }
+}
+
define('JS_WEB_ROOT', $root);
+
define('ESP_DEMO', (bool)getenv('ESP_DEMO'));
if (ESP_DEMO) {
define('DEMO_APS', << 550) {
$('.Box h2').forEach(function (x) {
x.removeAttribute('tabindex')
diff --git a/js/demo.js b/js/demo.js
index 48946ec..3c93ab8 100644
--- a/js/demo.js
+++ b/js/demo.js
@@ -82,7 +82,10 @@ class ANSIParser {
// something something nothing
this.currentSequence = 0
this.handler('write', character)
- } else if (code === 0x07) this.handler('bell')
+ } else if (code < 0x03) this.handler('_null')
+ else if (code === 0x03) this.handler('sigint')
+ else if (code <= 0x06) this.handler('_null')
+ else if (code === 0x07) this.handler('bell')
else if (code === 0x08) this.handler('back')
else if (code === 0x0a) this.handler('new-line')
else if (code === 0x0d) this.handler('return')
@@ -203,8 +206,8 @@ class ScrollingTerminal {
} else if (action === 'return') {
this.cursor.x = 0
} else if (action === 'set-cursor') {
- this.cursor.x = args[0]
- this.cursor.y = args[1]
+ this.cursor.x = args[1]
+ this.cursor.y = args[0]
this.clampCursor()
} else if (action === 'move-cursor-y') {
this.cursor.y += args[0]
@@ -370,7 +373,8 @@ let demoData = {
}
setTimeout(loop, 200)
}
- }
+ },
+ mouseReceiver: null
}
let demoshIndex = {
@@ -613,6 +617,115 @@ let demoshIndex = {
this.destroy()
}
},
+ mouse: class ShowMouse extends Process {
+ constructor (shell) {
+ super()
+ this.shell = shell
+ }
+ run () {
+ this.shell.terminal.trackMouse = true
+ demoData.mouseReceiver = this
+ this.randomData = []
+ this.highlighted = {}
+ let characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
+ for (let i = 0; i < 23; i++) {
+ let line = ''
+ for (let j = 0; j < 79; j++) {
+ line += characters[Math.floor(characters.length * Math.random())]
+ }
+ this.randomData.push(line)
+ }
+ this.scrollOffset = 0
+ this.render()
+ }
+ render () {
+ this.emit('write', '\x1b[m\x1b[2J\x1b[1;1H')
+ this.emit('write', '\x1b[97m\x1b[1mMouse Demo\r\n\x1b[mMouse movement, clicking and scrolling!')
+
+ // render random data for scrolling
+ for (let y = 0; y < 23; y++) {
+ let index = y + this.scrollOffset
+ // proper modulo:
+ index = ((index % this.randomData.length) + this.randomData.length) % this.randomData.length
+ let line = this.randomData[index]
+ let lineData = `\x1b[${3 + y};1H\x1b[38;5;239m`
+ for (let x in line) {
+ if (this.highlighted[(y + 2) * 80 + (+x)]) lineData += '\x1b[97m'
+ lineData += line[x]
+ if (this.highlighted[(y + 2) * 80 + (+x)]) lineData += '\x1b[38;5;239m'
+ }
+ this.emit('write', lineData)
+ }
+
+ // move cursor to mouse
+ if (this.mouse) {
+ this.emit('write', `\x1b[${this.mouse.y + 1};${this.mouse.x + 1}H`)
+ }
+ }
+ mouseMove (x, y) {
+ this.mouse = { x, y }
+ this.render()
+ }
+ mouseDown (x, y, button) {
+ if (button === 4) this.scrollOffset--
+ else if (button === 5) this.scrollOffset++
+ else this.highlighted[y * 80 + x] = !this.highlighted[y * 80 + x]
+ this.render()
+ }
+ mouseUp (x, y, button) {}
+ destroy () {
+ this.shell.terminal.write('\x1b[2J\x1b[1;1H')
+ this.shell.terminal.trackMouse = false
+ if (demoData.mouseReceiver === this) demoData.mouseReceiver = null
+ super.destroy()
+ }
+ },
+ sudo: class Sudo extends Process {
+ run (...args) {
+ if (args.length === 0) this.emit('write', '\x1b[31musage: sudo \x1b[0m\n')
+ else if (args.length === 4 && args.join(' ').toLowerCase() === 'make me a sandwich') {
+ const b = '\x1b[33m'
+ const r = '\x1b[0m'
+ const l = '\x1b[32m'
+ const c = '\x1b[38;5;229m'
+ const h = '\x1b[38;5;225m'
+ this.emit('write',
+ ` ${b}_.---._\r\n` +
+ ` _.-~ ~-._\r\n` +
+ ` _.-~ ~-._\r\n` +
+ ` _.-~ ~---._\r\n` +
+ ` _.-~ ~\\\r\n` +
+ ` .-~ _.;\r\n` +
+ ` :-._ _.-~ ./\r\n` +
+ ` \`-._~-._ _..__.-~ _.-~\r\n` +
+ ` ${c}/ ${b}~-._~-._ / .__..--${c}~-${l}---._\r\n` +
+ `${c} \\_____(_${b};-._\\. _.-~_/${c} ~)${l}.. . \\\r\n` +
+ `${l} /(_____ ${b}\\\`--...--~_.-~${c}______..-+${l}_______)\r\n` +
+ `${l} .(_________/${b}\`--...--~/${l} _/ ${h} ${b}/\\\r\n` +
+ `${b} /-._${h} \\_ ${l}(___./_..-~${h}__.....${b}__..-~./\r\n` +
+ `${b} \`-._~-._${h} ~\\--------~ .-~${b}_..__.-~ _.-~\r\n` +
+ `${b} ~-._~-._ ${h}~---------\` ${b}/ .__..--~\r\n` +
+ `${b} ~-._\\. _.-~_/\r\n` +
+ `${b} \\\`--...--~_.-~\r\n` +
+ `${b} \`--...--~${r}\r\n`)
+ } else {
+ this.emit('exec', args.join(' '))
+ return
+ }
+ this.destroy()
+ }
+ },
+ make: class Make extends Process {
+ run (...args) {
+ if (args.length === 0) this.emit('write', '\x1b[31mmake: *** No targets specified. Stop.\x1b[0m\r\n')
+ else if (args.length === 3 && args.join(' ').toLowerCase() === 'me a sandwich') {
+ this.emit('write', '\x1b[31mmake: me a sandwich : Permission denied\x1b[0m\r\n')
+ } else {
+ this.emit('write', `\x1b[31mmake: *** No rule to make target '${args.join(' ').toLowerCase()}'. Stop.\x1b[0m\r\n`)
+ }
+ this.destroy()
+ }
+ },
pwd: '/this/is/a/demo\r\n',
cd: '\x1b[38;5;239mNo directories to change to\r\n',
whoami: `${window.navigator.userAgent}\r\n`,
@@ -624,7 +737,13 @@ let demoshIndex = {
mv: '\x1b[38;5;239mNothing to move because this is a demo.\r\n',
ln: '\x1b[38;5;239mNothing to link because this is a demo.\r\n',
touch: '\x1b[38;5;239mNothing to touch\r\n',
- exit: '\x1b[38;5;239mNowhere to go\r\n'
+ exit: '\x1b[38;5;239mNowhere to go\r\n',
+ github: class GoToGithub extends Process {
+ run () {
+ window.open('https://github.com/espterm/espterm-firmware')
+ this.destroy()
+ }
+ }
}
class DemoShell {
@@ -632,7 +751,8 @@ class DemoShell {
this.terminal = terminal
this.terminal.reset()
this.parser = new ANSIParser((...args) => this.handleParsed(...args))
- this.input = ''
+ this.history = []
+ this.historyIndex = 0
this.cursorPos = 0
this.child = null
this.index = demoshIndex
@@ -651,38 +771,53 @@ class DemoShell {
this.terminal.write('\x1b[34;1mdemosh \x1b[m')
if (!success) this.terminal.write('\x1b[31m')
this.terminal.write('$ \x1b[m')
- this.input = ''
+ this.history.unshift('')
this.cursorPos = 0
}
+ copyFromHistoryIndex () {
+ if (!this.historyIndex) return
+ let current = this.history[this.historyIndex]
+ this.history[0] = current
+ this.historyIndex = 0
+ }
handleParsed (action, ...args) {
this.terminal.write('\b\x1b[P'.repeat(this.cursorPos))
if (action === 'write') {
- this.input = this.input.substr(0, this.cursorPos) + args[0] + this.input.substr(this.cursorPos)
+ this.copyFromHistoryIndex()
+ this.history[0] = this.history[0].substr(0, this.cursorPos) + args[0] + this.history[0].substr(this.cursorPos)
this.cursorPos++
} else if (action === 'back') {
- this.input = this.input.substr(0, this.cursorPos - 1) + this.input.substr(this.cursorPos)
+ this.copyFromHistoryIndex()
+ this.history[0] = this.history[0].substr(0, this.cursorPos - 1) + this.history[0].substr(this.cursorPos)
this.cursorPos--
if (this.cursorPos < 0) this.cursorPos = 0
} else if (action === 'move-cursor-x') {
- this.cursorPos = Math.max(0, Math.min(this.input.length, this.cursorPos + args[0]))
+ this.cursorPos = Math.max(0, Math.min(this.history[0].length, this.cursorPos + args[0]))
} else if (action === 'delete-line') {
- this.input = ''
+ this.copyFromHistoryIndex()
+ this.history[0] = ''
this.cursorPos = 0
} else if (action === 'delete-word') {
- let words = this.input.substr(0, this.cursorPos).split(' ')
+ this.copyFromHistoryIndex()
+ let words = this.history[0].substr(0, this.cursorPos).split(' ')
words.pop()
- this.input = words.join(' ') + this.input.substr(this.cursorPos)
+ this.history[0] = words.join(' ') + this.history[0].substr(this.cursorPos)
this.cursorPos = words.join(' ').length
+ } else if (action === 'move-cursor-y') {
+ this.historyIndex -= args[0]
+ if (this.historyIndex < 0) this.historyIndex = 0
+ if (this.historyIndex >= this.history.length) this.historyIndex = this.history.length - 1
+ this.cursorPos = this.history[this.historyIndex].length
}
- this.terminal.write(this.input)
- this.terminal.write('\b'.repeat(this.input.length))
+ this.terminal.write(this.history[this.historyIndex])
+ this.terminal.write('\b'.repeat(this.history[this.historyIndex].length))
this.terminal.moveForward(this.cursorPos)
this.terminal.write('') // dummy. Apply the moveFoward
if (action === 'return') {
this.terminal.write('\r\n')
- this.parse(this.input)
+ this.parse(this.history[this.historyIndex])
}
}
parse (input) {
@@ -719,9 +854,12 @@ class DemoShell {
if (Process instanceof Function) {
this.child = new Process(this)
let write = data => this.terminal.write(data)
+ let exec = line => this.run(line)
this.child.on('write', write)
+ this.child.on('exec', exec)
this.child.on('exit', code => {
if (this.child) this.child.off('write', write)
+ if (this.child) this.child.off('exec', exec)
this.child = null
this.prompt(!code)
})
@@ -748,7 +886,16 @@ window.demoInterface = {
else if (action instanceof Function) action(this.terminal, this.shell)
}
} else if (type === 'm' || type === 'p' || type === 'r') {
- console.log(JSON.stringify(data))
+ let row = parse2B(content, 0)
+ let column = parse2B(content, 2)
+ let button = parse2B(content, 4)
+ let modifiers = parse2B(content, 6)
+
+ if (demoData.mouseReceiver) {
+ if (type === 'm') demoData.mouseReceiver.mouseMove(column, row, button, modifiers)
+ else if (type === 'p') demoData.mouseReceiver.mouseDown(column, row, button, modifiers)
+ else if (type === 'r') demoData.mouseReceiver.mouseUp(column, row, button, modifiers)
+ }
}
},
init (screen) {
diff --git a/js/soft_keyboard.js b/js/soft_keyboard.js
index 5829033..7921e5d 100644
--- a/js/soft_keyboard.js
+++ b/js/soft_keyboard.js
@@ -4,6 +4,9 @@ window.initSoftKeyboard = function (screen, input) {
let keyboardOpen = false
+ // moves the input to where the cursor is on the canvas.
+ // this is because most browsers will always scroll to wherever the focused
+ // input is
let updateInputPosition = function () {
if (!keyboardOpen) return
@@ -20,16 +23,9 @@ window.initSoftKeyboard = function (screen, input) {
screen.on('cursor-moved', updateInputPosition)
- let kbOpen = function (open) {
- keyboardOpen = open
- updateInputPosition()
- if (open) keyInput.focus()
- else keyInput.blur()
- }
-
- qs('#term-kb-open').addEventListener('click', function () {
- kbOpen(true)
- return false
+ qs('#term-kb-open').addEventListener('click', e => {
+ e.preventDefault()
+ keyInput.focus()
})
// Chrome for Android doesn't send proper keydown/keypress events with
diff --git a/js/term.js b/js/term.js
index ddd05af..e9c5981 100644
--- a/js/term.js
+++ b/js/term.js
@@ -1,7 +1,5 @@
/** Init the terminal sub-module - called from HTML */
-window.termInit = function (opts) {
- let { labels, theme, allFn } = opts
-
+window.termInit = function ({ labels, theme, allFn }) {
const screen = new TermScreen()
const conn = Conn(screen)
const input = Input(conn)
diff --git a/js/term_conn.js b/js/term_conn.js
index 955fee1..37b2800 100644
--- a/js/term_conn.js
+++ b/js/term_conn.js
@@ -137,8 +137,8 @@ window.Conn = function (screen) {
return {
ws: null,
- init: init,
+ init,
send: doSend,
- canSend: canSend // check flood control
+ canSend // check flood control
}
}
diff --git a/js/term_input.js b/js/term_input.js
index e42ee35..2199f7e 100644
--- a/js/term_input.js
+++ b/js/term_input.js
@@ -32,7 +32,7 @@ window.Input = function (conn) {
/** Send a button event */
function sendBtnMsg (n) {
- conn.send('b' + Chr(n))
+ conn.send('b' + String.fromCharCode(n))
}
/** Fn alt choice for key message */
@@ -50,7 +50,7 @@ window.Input = function (conn) {
return cfg.np_alt ? alt : normal
}
- function _bindFnKeys (allFn) {
+ function bindFnKeys (allFn) {
const keymap = {
'tab': '\x09',
'backspace': '\x08',
@@ -106,7 +106,9 @@ window.Input = function (conn) {
'np_sub': na('\x1bOS', '-'),
'np_point': na('\x1bOn', '.'),
'np_div': na('\x1bOQ', '/')
- // we don't implement numlock key (should change in numpad_alt mode, but it's even more useless than the rest)
+ // we don't implement numlock key (should change in numpad_alt mode,
+ // but it's even more useless than the rest and also has the side
+ // effect of changing the user's numlock state)
}
const blacklist = [
@@ -139,9 +141,7 @@ window.Input = function (conn) {
}
/** Bind/rebind key messages */
- function _initKeys (opts) {
- let { allFn } = opts
-
+ function initKeys ({ allFn }) {
// This takes care of text characters typed
window.addEventListener('keypress', function (evt) {
if (cfg.no_keys) return
@@ -188,11 +188,11 @@ window.Input = function (conn) {
bind('⌥+right', '\x1bf') // ⌥→ to go forward one word (^[f)
bind('⌘+left', '\x01') // ⌘← to go to the beginning of a line (^A)
bind('⌘+right', '\x05') // ⌘→ to go to the end of a line (^E)
- bind('⌥+backspace', '\x17') // ⌥⌫ to delete a word (^W, I think)
- bind('⌘+backspace', '\x15') // ⌘⌫ to delete to the beginning of a line (possibly ^U)
+ bind('⌥+backspace', '\x17') // ⌥⌫ to delete a word (^W)
+ bind('⌘+backspace', '\x15') // ⌘⌫ to delete to the beginning of a line (^U)
/* eslint-enable */
- _bindFnKeys(allFn)
+ bindFnKeys(allFn)
}
// mouse button states
@@ -202,23 +202,23 @@ window.Input = function (conn) {
/** Init the Input module */
function init (opts) {
- _initKeys(opts)
+ initKeys(opts)
// Button presses
- $('#action-buttons button').forEach(function (s) {
- s.addEventListener('click', function () {
+ $('#action-buttons button').forEach(s => {
+ s.addEventListener('click', function (evt) {
sendBtnMsg(+this.dataset['n'])
})
})
// global mouse state tracking - for motion reporting
- window.addEventListener('mousedown', function (evt) {
+ window.addEventListener('mousedown', evt => {
if (evt.button === 0) mb1 = 1
if (evt.button === 1) mb2 = 1
if (evt.button === 2) mb3 = 1
})
- window.addEventListener('mouseup', function (evt) {
+ window.addEventListener('mouseup', evt => {
if (evt.button === 0) mb1 = 0
if (evt.button === 1) mb2 = 0
if (evt.button === 2) mb3 = 0
@@ -235,7 +235,7 @@ window.Input = function (conn) {
return {
/** Init the Input module */
- init: init,
+ init,
/** Send a literal string message */
sendString: sendStrMsg,
@@ -249,24 +249,24 @@ window.Input = function (conn) {
cfg.crlf_mode = crlf
// rebind keys - codes have changed
- _bindFnKeys()
+ bindFnKeys()
}
},
- setMouseMode: function (click, move) {
+ setMouseMode (click, move) {
cfg.mt_click = click
cfg.mt_move = move
},
// Mouse events
- onMouseMove: function (x, y) {
+ onMouseMove (x, y) {
if (!cfg.mt_move) return
const b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0
const m = packModifiersForMouse()
conn.send('m' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m))
},
- onMouseDown: function (x, y, b) {
+ onMouseDown (x, y, b) {
if (!cfg.mt_click) return
if (b > 3 || b < 1) return
const m = packModifiersForMouse()
@@ -274,7 +274,7 @@ window.Input = function (conn) {
// console.log("B ",b," M ",m);
},
- onMouseUp: function (x, y, b) {
+ onMouseUp (x, y, b) {
if (!cfg.mt_click) return
if (b > 3 || b < 1) return
const m = packModifiersForMouse()
@@ -282,7 +282,7 @@ window.Input = function (conn) {
// console.log("B ",b," M ",m);
},
- onMouseWheel: function (x, y, dir) {
+ onMouseWheel (x, y, dir) {
if (!cfg.mt_click) return
// -1 ... btn 4 (away from user)
// +1 ... btn 5 (towards user)
@@ -292,11 +292,11 @@ window.Input = function (conn) {
// console.log("B ",b," M ",m);
},
- mouseTracksClicks: function () {
- return cfg.mt_click
- },
-
- blockKeys: function (yes) {
+ /**
+ * Prevent capturing keys. This is used for text input
+ * modals on the terminal screen
+ */
+ blockKeys (yes) {
cfg.no_keys = yes
}
}
diff --git a/js/term_screen.js b/js/term_screen.js
index ad2fc17..21e280c 100644
--- a/js/term_screen.js
+++ b/js/term_screen.js
@@ -524,7 +524,8 @@ window.TermScreen = class TermScreen {
* Updates the canvas size if it changed
*/
updateSize () {
- this._window.devicePixelRatio = this._windowScale * (window.devicePixelRatio || 1)
+ // see below (this is just updating it)
+ this._window.devicePixelRatio = Math.round(this._windowScale * (window.devicePixelRatio || 1) * 2) / 2
let didChange = false
for (let key in this.windowState) {
@@ -573,7 +574,8 @@ window.TermScreen = class TermScreen {
// store new window scale
this._windowScale = realWidth / (width * cellSize.width)
- let devicePixelRatio = this._window.devicePixelRatio = this._windowScale * window.devicePixelRatio
+ // the DPR must be rounded to a very nice value to prevent gaps between cells
+ let devicePixelRatio = this._window.devicePixelRatio = Math.round(this._windowScale * (window.devicePixelRatio || 1) * 2) / 2
this.canvas.width = width * devicePixelRatio * cellSize.width
this.canvas.style.width = `${realWidth}px`
@@ -745,8 +747,8 @@ window.TermScreen = class TermScreen {
drawCellBackground ({ x, y, cellWidth, cellHeight, bg }) {
const ctx = this.ctx
ctx.fillStyle = this.getColor(bg)
- ctx.clearRect(x * cellWidth, y * cellHeight, Math.ceil(cellWidth), Math.ceil(cellHeight))
- ctx.fillRect(x * cellWidth, y * cellHeight, Math.ceil(cellWidth), Math.ceil(cellHeight))
+ ctx.clearRect(x * cellWidth, y * cellHeight, cellWidth, cellHeight)
+ ctx.fillRect(x * cellWidth, y * cellHeight, cellWidth, cellHeight)
}
/**
@@ -1150,8 +1152,6 @@ window.TermScreen = class TermScreen {
this.screenAttrs = new Array(screenLength).fill(' ')
}
- let bgcount = new Array(256).fill(0)
-
let strArray = !undef(Array.from) ? Array.from(str) : str.split('')
const MASK_LINE_ATTR = 0xC8
@@ -1173,7 +1173,6 @@ window.TermScreen = class TermScreen {
else this.blinkingCellCount--
}
- bgcount[bg]++
this.screen[cell] = lastChar
this.screenFG[cell] = fg
this.screenBG[cell] = bg
@@ -1230,18 +1229,6 @@ window.TermScreen = class TermScreen {
if (this.window.debug) console.log(`Blinky cells = ${this.blinkingCellCount}`)
- // work-around for the grid gaps bug
- // will mask the glitch if most of the screen uses the same background
- let mostCommonBg = 0
- let mcbIndex = 0
- for (let i = 255; i >= 0; i--) {
- if (bgcount[i] > mostCommonBg) {
- mostCommonBg = bgcount[i]
- mcbIndex = i
- }
- }
- this.canvas.style.backgroundColor = this.getColor(mcbIndex)
-
this.scheduleDraw('load', 16)
this.emit('load')
}
diff --git a/js/term_upload.js b/js/term_upload.js
index e399c4b..938b420 100644
--- a/js/term_upload.js
+++ b/js/term_upload.js
@@ -97,7 +97,6 @@ window.TermUpl = function (conn, input, screen) {
inline_pos += MAX_LINE_LEN
}
- console.log(chunk)
if (!input.sendString(chunk)) {
updateStatus('FAILED!')
return
@@ -134,10 +133,11 @@ window.TermUpl = function (conn, input, screen) {
qs('#fu_file').addEventListener('change', function (evt) {
let reader = new FileReader()
let file = evt.target.files[0]
- console.log('Selected file type: ' + file.type)
- if (!file.type.match(/text\/.*|application\/(json|csv|.*xml.*|.*script.*)/)) {
+ let ftype = file.type || 'application/octet-stream'
+ console.log('Selected file type: ' + ftype)
+ if (!ftype.match(/text\/.*|application\/(json|csv|.*xml.*|.*script.*|x-php)/)) {
// 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: ${ftype}\nReally load?`)) {
qs('#fu_file').value = ''
return
}
diff --git a/js/wifi.js b/js/wifi.js
index bd35fe4..8e90328 100644
--- a/js/wifi.js
+++ b/js/wifi.js
@@ -149,7 +149,7 @@
})
// Forget STA credentials
- $('#forget-sta').on('click', function () {
+ $('#forget-sta').on('click', () => {
selectSta('', '', '')
return false
})