toggleSign() usciva subito a display vuoto: il segno del calibro, che arriva prima delle cifre, veniva scartato. Ora '-'/'+' impostano il segno in modo esplicito (non toggle) quando arrivano da tastiera/HID; toggleSign() (bottone manuale +/-) funziona anche a vuoto. _trackBurst riconosce l'inizio di una raffica solo dal secondo carattere: prima ripuliva il display in ritardo, concatenando cifre digitate a mano. Ora la raffica ripulisce il display fino al proprio inizio quando la pausa prima di essa è > 300ms. Parte intera oltre 6 cifre: rifiutata con evento numpad-error invece di essere troncata in silenzio. Test node in tests/js/test_numpad.js, lanciato da pytest (tests/test_numpad_js.py, skip se node manca). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,8 @@ function numpad(options) {
|
||||
_lastKeyTime: 0, // Timestamp of last keystroke
|
||||
_burstCount: 0, // Consecutive fast keystrokes
|
||||
_enterWasFast: false, // Enter arrived in the same burst as the digits
|
||||
_rejected: false, // Current reading refused (e.g. overflow); ignore the rest of it
|
||||
_runStart: null, // {value, gap} snapshot taken at the first key of the current run
|
||||
|
||||
/**
|
||||
* Get the display value with sign
|
||||
@@ -55,6 +57,8 @@ function numpad(options) {
|
||||
* @param {string} d - The digit to add (0-9)
|
||||
*/
|
||||
addDigit(d) {
|
||||
if (this._rejected) return;
|
||||
|
||||
// Validate: don't exceed max digits
|
||||
const parts = this.value.split('.');
|
||||
|
||||
@@ -63,7 +67,15 @@ function numpad(options) {
|
||||
if (parts[1] && parts[1].length >= this.maxDecDigits) return;
|
||||
} else {
|
||||
// Check integer part length
|
||||
if (parts[0] && parts[0].length >= this.maxIntDigits) return;
|
||||
if (parts[0] && parts[0].length >= this.maxIntDigits) {
|
||||
// A caliper reading whose integer part does not fit must not be
|
||||
// quietly cut down to something that does: refuse the whole
|
||||
// reading instead of saving a truncated number. Manual typing
|
||||
// (outside a burst) keeps the old, harmless behaviour of simply
|
||||
// not accepting more digits.
|
||||
if (this._burstCount >= 2) this._rejectReading('integer_overflow');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent leading zeros (except "0.")
|
||||
@@ -79,6 +91,8 @@ function numpad(options) {
|
||||
* Add a decimal point to the current value
|
||||
*/
|
||||
addDecimal() {
|
||||
if (this._rejected) return;
|
||||
|
||||
// Don't add decimal if one already exists
|
||||
if (this.hasDecimal) return;
|
||||
|
||||
@@ -90,10 +104,11 @@ function numpad(options) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the sign of the current value
|
||||
* Toggle the sign of the current value. Works on an empty display too -
|
||||
* the manual +/- key is pressed before the first digit as often as after
|
||||
* one, and used to be silently dropped in that case.
|
||||
*/
|
||||
toggleSign() {
|
||||
if (!this.value) return;
|
||||
this.negative = !this.negative;
|
||||
},
|
||||
|
||||
@@ -119,6 +134,8 @@ function numpad(options) {
|
||||
this.negative = false;
|
||||
this.hasDecimal = false;
|
||||
this._enterWasFast = false;
|
||||
this._rejected = false;
|
||||
this._runStart = null;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -138,6 +155,7 @@ function numpad(options) {
|
||||
* Confirm the current value and dispatch event
|
||||
*/
|
||||
confirm() {
|
||||
this._rejected = false;
|
||||
if (!this.hasValue) return;
|
||||
|
||||
const val = this.numericValue;
|
||||
@@ -239,11 +257,32 @@ function numpad(options) {
|
||||
this._enterWasFast = gap < 80;
|
||||
this.confirm();
|
||||
}
|
||||
// Minus sign - toggle sign
|
||||
// Minus / plus - the caliper's own sign character. Unlike the manual
|
||||
// +/- key (toggleSign(), bound to the on-screen button) these are
|
||||
// absolute rather than a toggle: a caliper transmission says which
|
||||
// sign the reading is, it never flips one already on screen.
|
||||
else if (e.key === '-') {
|
||||
e.preventDefault();
|
||||
this.toggleSign();
|
||||
this.negative = true;
|
||||
}
|
||||
else if (e.key === '+') {
|
||||
e.preventDefault();
|
||||
this.negative = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Refuse the reading in progress: say why with an event the page can show,
|
||||
* and wipe the display so the rejected digits do not linger as if valid.
|
||||
* Further keystrokes of the same burst are ignored until Enter or a clear.
|
||||
*/
|
||||
_rejectReading(reason) {
|
||||
this.$dispatch('numpad-error', { reason: reason });
|
||||
this.value = '';
|
||||
this.negative = false;
|
||||
this.hasDecimal = false;
|
||||
this._enterWasFast = false;
|
||||
this._rejected = true;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -253,12 +292,22 @@ function numpad(options) {
|
||||
*/
|
||||
_trackBurst() {
|
||||
const now = performance.now();
|
||||
const gap = now - this._lastKeyTime;
|
||||
const gap = this._lastKeyTime > 0 ? now - this._lastKeyTime : Infinity;
|
||||
|
||||
if (this._lastKeyTime > 0 && gap < 80) {
|
||||
if (gap < 80) {
|
||||
this._burstCount++;
|
||||
// The burst is only recognisable from its second character. If the
|
||||
// pause before the first one was long enough to be a human keystroke,
|
||||
// whatever was on display before this run began was typed by hand:
|
||||
// drop it now instead of letting the caliper's own digits
|
||||
// concatenate onto it.
|
||||
if (this._burstCount === 2 && this._runStart && this._runStart.gap > 300) {
|
||||
this.value = this.value.slice(this._runStart.value.length);
|
||||
this.hasDecimal = this.value.includes('.');
|
||||
}
|
||||
} else {
|
||||
this._burstCount = 1;
|
||||
this._runStart = { value: this.value, gap: gap };
|
||||
}
|
||||
|
||||
this._lastKeyTime = now;
|
||||
|
||||
Reference in New Issue
Block a user