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 = ' | salary.type = 'text'; | ||
salary. | salary.inputMode = 'numeric'; | ||
salary. | salary.autocomplete = 'off'; | ||
salary. | 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 = | 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 = | salary.value = newSalary.toLocaleString( 'en-US' ); | ||
render(); | render(); | ||
} ); | } ); | ||