MediaWiki:Gadget-fa-bid-calculator.js: Difference between revisions

Stack calculator rows on narrow screens
Thousands separators in the salary field
Line 17: Line 17:
function money( n ) {
function money( n ) {
return '$' + n.toLocaleString( 'en-US' );
return '$' + n.toLocaleString( 'en-US' );
}
/** Digits only, so "4,000,000" and "4000000" both read as 4000000. */
function parseMoney( v ) {
var digits = String( v ).replace( /[^0-9]/g, '' );
return digits === '' ? NaN : Number( digits );
}
/**
* Reformat a text input with thousands separators, keeping the caret where
* the typist left it. A plain reformat would send it to the end, which makes
* editing the middle of a figure unusable.
*/
function formatWithCaret( el ) {
var before = el.value.slice( 0, el.selectionStart ),
digitsBefore = before.replace( /[^0-9]/g, '' ).length,
n = parseMoney( el.value );
el.value = isNaN( n ) ? '' : n.toLocaleString( 'en-US' );
// Walk forward past the same number of digits to place the caret.
var pos = 0, seen = 0;
while ( pos < el.value.length && seen < digitsBefore ) {
if ( /[0-9]/.test( el.value[ pos ] ) ) {
seen++;
}
pos++;
}
el.setSelectionRange( pos, pos );
}
}


Line 117: Line 146:


var years = document.createElement( 'select' );
var years = document.createElement( 'select' );
// A number input cannot display separators — browsers reject a comma as
// invalid number syntax — so this is a text input formatted by hand.
var salary = document.createElement( 'input' );
var salary = document.createElement( 'input' );
salary.type = 'number';
salary.type = 'text';
salary.step = String( MIN_RAISE );
salary.inputMode = 'numeric';
salary.min = String( MIN_OFFER );
salary.autocomplete = 'off';
salary.value = String( MIN_OFFER );
salary.className = 'tc-calc-money';
salary.value = MIN_OFFER.toLocaleString( 'en-US' );
salary.addEventListener( 'input', function () {
formatWithCaret( salary );
} );


var age35 = document.createElement( 'input' );
var age35 = document.createElement( 'input' );
Line 174: Line 209:
function render() {
function render() {
var y = Number( years.value ),
var y = Number( years.value ),
s = Number( salary.value ),
s = parseMoney( salary.value ),
max = age35.checked ? MAX_YEARS_35 : MAX_YEARS;
max = age35.checked ? MAX_YEARS_35 : MAX_YEARS;


Line 240: Line 275:
use.textContent = 'Use ' + money( newSalary );
use.textContent = 'Use ' + money( newSalary );
use.addEventListener( 'click', function () {
use.addEventListener( 'click', function () {
salary.value = String( newSalary );
salary.value = newSalary.toLocaleString( 'en-US' );
render();
render();
} );
} );