add js error handler with notify balloon, fix file upload

cpsdqs/unified-input
Ondřej Hruška 7 years ago
parent 3e4394f0cb
commit 2f0d0187a1
  1. 52
      js/notif.js
  2. 7
      js/soft_keyboard.js
  3. 21
      js/term.js
  4. 50
      js/term_upload.js
  5. 10
      pages/term.php
  6. 2
      sass/layout/_modal.scss

@ -1,34 +1,64 @@
window.Notify = (function () { window.Notify = (function () {
let nt = {} let nt = {}
const sel = '#notif' const sel = '#notif'
let $balloon
let hideTmeo1 // timeout to start hiding (transition) let timerHideBegin // timeout to start hiding (transition)
let hideTmeo2 // timeout to add the hidden class let timerHideEnd // timeout to add the hidden class
let timerCanCancel
let canCancel = false
nt.show = function (message, timeout) { let stopTimeouts = function () {
$(sel).html(message) clearTimeout(timerHideBegin)
Modal.show(sel) clearTimeout(timerHideEnd)
}
nt.show = function (message, timeout, isError) {
$balloon.toggleClass('error', isError === true)
$balloon.html(message)
Modal.show($balloon)
stopTimeouts()
clearTimeout(hideTmeo1) if (undef(timeout) || timeout === null || timeout <= 0) {
clearTimeout(hideTmeo2) timeout = 2500
}
if (undef(timeout)) timeout = 2500 timerHideBegin = setTimeout(nt.hide, timeout)
hideTmeo1 = setTimeout(nt.hide, timeout) canCancel = false
timerCanCancel = setTimeout(function () {
canCancel = true
}, 500)
} }
nt.hide = function () { nt.hide = function () {
let $m = $(sel) let $m = $(sel)
$m.removeClass('visible') $m.removeClass('visible')
hideTmeo2 = setTimeout(function () { timerHideEnd = setTimeout(function () {
$m.addClass('hidden') $m.addClass('hidden')
}, 250) // transition time }, 250) // transition time
} }
nt.init = function () { nt.init = function () {
$(sel).on('click', function () { $balloon = $(sel)
// close by click outside
$(document).on('click', function () {
if (!canCancel) return
nt.hide(this) nt.hide(this)
}) })
// click caused by selecting, prevent it from bubbling
$balloon.on('click', function (e) {
e.stopImmediatePropagation()
return false
})
// stop fading if moused
$balloon.on('mouseenter', function () {
stopTimeouts()
$balloon.removeClass('hidden').addClass('visible')
})
} }
return nt return nt

@ -20,13 +20,18 @@ window.initSoftKeyboard = function (screen, input) {
screen.on('cursor-moved', updateInputPosition) screen.on('cursor-moved', updateInputPosition)
window.kbOpen = function openSoftKeyboard (open) { let kbOpen = function (open) {
keyboardOpen = open keyboardOpen = open
updateInputPosition() updateInputPosition()
if (open) keyInput.focus() if (open) keyInput.focus()
else keyInput.blur() else keyInput.blur()
} }
qs('#term-kb-open').addEventListener('click', function () {
kbOpen(true)
return false
})
// Chrome for Android doesn't send proper keydown/keypress events with // Chrome for Android doesn't send proper keydown/keypress events with
// real key values instead of 229 “Unidentified,” so here's a workaround // real key values instead of 229 “Unidentified,” so here's a workaround
// that deals with the input composition events. // that deals with the input composition events.

@ -1,15 +1,21 @@
/** Init the terminal sub-module - called from HTML */ /** Init the terminal sub-module - called from HTML */
window.termInit = function (labels, theme) { window.termInit = function (labels, theme) {
const screen = new window.TermScreen() const screen = new TermScreen()
const conn = window.Conn(screen) const conn = Conn(screen)
const input = window.Input(conn) const input = Input(conn)
const termUpload = window.TermUpl(conn, input) const termUpload = TermUpl(conn, input)
screen.input = input screen.input = input
conn.init() conn.init()
input.init() input.init()
termUpload.init() termUpload.init()
Notify.init()
window.onerror = function (errorMsg, file, line, col) {
Notify.show(`<b>JS ERROR!</b><br>${errorMsg}<br>at ${file}:${line}:${col}`, 10000, true)
return false
}
qs('#screen').appendChild(screen.canvas) qs('#screen').appendChild(screen.canvas)
screen.load(labels, theme) // load labels and theme screen.load(labels, theme) // load labels and theme
@ -23,7 +29,7 @@ window.termInit = function (labels, theme) {
fitScreenIfNeeded() fitScreenIfNeeded()
window.addEventListener('resize', fitScreenIfNeeded) window.addEventListener('resize', fitScreenIfNeeded)
window.toggleFitScreen = function () { let toggleFitScreen = function () {
fitScreen = !fitScreen fitScreen = !fitScreen
const resizeButtonIcon = qs('#resize-button-icon') const resizeButtonIcon = qs('#resize-button-icon')
if (fitScreen) { if (fitScreen) {
@ -35,6 +41,11 @@ window.termInit = function (labels, theme) {
} }
fitScreenIfNeeded() fitScreenIfNeeded()
} }
qs('#term-fit-screen').addEventListener('click', function () {
toggleFitScreen()
return false
})
} }
window.initSoftKeyboard(screen, input) window.initSoftKeyboard(screen, input)

@ -12,25 +12,25 @@ window.TermUpl = function (conn, input) {
// 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
const MAX_LINE_LEN = 128 const MAX_LINE_LEN = 128
function fuOpen () { function openUploadDialog () {
fuStatus('Ready...') updateStatus('Ready...')
Modal.show('#fu_modal', onClose) Modal.show('#fu_modal', onDialogClose)
$('#fu_form').toggleClass('busy', false) $('#fu_form').toggleClass('busy', false)
input.blockKeys(true) input.blockKeys(true)
} }
function onClose () { function onDialogClose () {
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 updateStatus (msg) {
qs('#fu_prog').textContent = msg qs('#fu_prog').textContent = msg
} }
function fuSend () { function startUpload () {
let v = qs('#fu_text').value let v = qs('#fu_text').value
if (!v.length) { if (!v.length) {
fuClose() fuClose()
@ -55,11 +55,11 @@ window.TermUpl = function (conn, input) {
}[qs('#fu_crlf').value] }[qs('#fu_crlf').value]
$('#fu_form').toggleClass('busy', true) $('#fu_form').toggleClass('busy', true)
fuStatus('Starting...') updateStatus('Starting...')
fuSendLine() uploadLine()
} }
function fuSendLine () { function uploadLine () {
if (!$('#fu_modal').hasClass('visible')) { if (!$('#fu_modal').hasClass('visible')) {
// Modal is closed, cancel // Modal is closed, cancel
return return
@ -67,7 +67,7 @@ window.TermUpl = function (conn, input) {
if (!conn.canSend()) { if (!conn.canSend()) {
// postpone // postpone
fuTout = setTimeout(fuSendLine, 1) fuTout = setTimeout(uploadLine, 1)
return return
} }
@ -85,16 +85,16 @@ window.TermUpl = function (conn, input) {
} }
if (!input.sendString(chunk)) { if (!input.sendString(chunk)) {
fuStatus('FAILED!') updateStatus('FAILED!')
return return
} }
let all = lines.length let all = lines.length
fuStatus(line_i + ' / ' + all + ' (' + (Math.round((line_i / all) * 1000) / 10) + '%)') updateStatus(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(uploadLine, send_delay_ms)
} else { } else {
closeWhenReady() closeWhenReady()
} }
@ -103,10 +103,10 @@ window.TermUpl = function (conn, input) {
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...') updateStatus('Waiting for Tx buffer...')
setTimeout(closeWhenReady, 100) setTimeout(closeWhenReady, 100)
} else { } else {
fuStatus('Done.') updateStatus('Done.')
// delay to show it // delay to show it
setTimeout(function () { setTimeout(function () {
fuClose() fuClose()
@ -138,9 +138,21 @@ window.TermUpl = function (conn, input) {
console.log('Loading file...') console.log('Loading file...')
reader.readAsText(file) reader.readAsText(file)
}, false) }, false)
},
close: fuClose, qs('#term-fu-open').addEventListener('click', function () {
start: fuSend, openUploadDialog()
open: fuOpen return false
})
qs('#term-fu-start').addEventListener('click', function () {
startUpload()
return false
})
qs('#term-fu-close').addEventListener('click', function () {
fuClose()
return false
})
}
} }
} }

@ -33,8 +33,8 @@
</p> </p>
</div> </div>
<div class="fu-buttons"> <div class="fu-buttons">
<button onclick="TermUpl.start()" class="icn-ok x-fu-go">Start</button>&nbsp; <button id="term-fu-start" class="icn-ok x-fu-go">Start</button>&nbsp;
<button onclick="TermUpl.close()" class="icn-cancel x-fu-cancel">Cancel</button>&nbsp; <button id="term-fu-close" class="icn-cancel x-fu-cancel">Cancel</button>&nbsp;
<i class="fu-prog-box">Upload: <span id="fu_prog"></span></i> <i class="fu-prog-box">Upload: <span id="fu_prog"></span></i>
</div> </div>
</div> </div>
@ -60,9 +60,9 @@
</div> </div>
<nav id="term-nav"> <nav id="term-nav">
<a href="#" onclick="toggleFitScreen();return false" class="mq-tablet-max"><i id="resize-button-icon" class="icn-resize-small"></i></a><!-- <a href="#" id="term-fit-screen" class="mq-tablet-max"><i id="resize-button-icon" class="icn-resize-small"></i></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="#" id="term-kb-open" 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') ?></span></a><!-- --><a href="#" id="term-fu-open"><i class="icn-download"></i><span><?= tr('term_nav.upload') ?></span></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_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('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><!-- --><a href="<?= url('help') ?>" class="x-term-conf-btn"><i class="icn-help"></i><span><?= tr('term_nav.help') ?></span></a><!--

@ -82,7 +82,7 @@
box-shadow: 0 0 6px 0 rgba(black, .6); box-shadow: 0 0 6px 0 rgba(black, .6);
border-radius: 5px; border-radius: 5px;
max-width: 80%; max-width: 600px;
@include media($phone) { @include media($phone) {
width: calc(100% - #{dist(0)}); width: calc(100% - #{dist(0)});

Loading…
Cancel
Save