An invoice line
Type an amount, pick a currency and a language, and see the line an invoice or a cheque would print — including Arabic that agrees with its currency.
<div class="demo">
<div class="demo-grid-2">
<div class="demo-field">
<label class="demo-label" for="amount">Amount</label>
<input id="amount" class="demo-input" value="12345.50" autocomplete="off" inputmode="decimal">
</div>
<div class="demo-field">
<label class="demo-label" for="currency">Currency</label>
<select id="currency" class="demo-input"></select>
</div>
</div>
<div class="demo-seg" id="language">
<button class="is-on" data-lang="en">English</button>
<button data-lang="ar">العربية</button>
<button data-lang="ur">اردو</button>
</div>
<div class="demo-card">
<p class="demo-hint">In words</p>
<p class="demo-out" id="words"></p>
<p class="demo-hint">On a cheque</p>
<p class="demo-out" id="cheque"></p>
</div>
<p class="demo-hint" id="note"></p>
</div>
import { currencyCodes, toCheque, toMoney } from 'https://devix.pk/cdn/oss/number-words@1.0.0/index.js';
const NOTES = {
ar: 'Arabic agrees with its currency: two is a dual (درهمان), eleven to ninety-nine take the accusative (أحد عشر درهمًا), and a round two hundred drops the nūn (مئتا درهم).',
en: 'English and dirhams together — the commonest invoice in the Gulf, and the one other libraries refuse to spell.',
ur: 'Urdu counts in lakh and crore, and has its own word for every number up to ninety-nine.',
};
const amount = document.getElementById('amount');
const currency = document.getElementById('currency');
const words = document.getElementById('words');
const cheque = document.getElementById('cheque');
const note = document.getElementById('note');
let language = 'en';
for (const code of currencyCodes()) {
const option = document.createElement('option');
option.value = code;
option.textContent = code;
currency.append(option);
}
currency.value = 'AED';
function render() {
const rtl = language !== 'en';
for (const node of [words, cheque]) node.dir = rtl ? 'rtl' : 'ltr';
note.textContent = NOTES[language];
try {
const options = { currency: currency.value, language };
words.textContent = toMoney(amount.value, options);
cheque.textContent = toCheque(amount.value, options);
} catch (error) {
words.textContent = error.message;
cheque.textContent = '';
}
}
document.getElementById('language').addEventListener('click', (event) => {
const button = event.target.closest('button');
if (!button) return;
for (const sibling of button.parentElement.children) sibling.classList.toggle('is-on', sibling === button);
language = button.dataset.lang;
render();
});
amount.addEventListener('input', render);
currency.addEventListener('change', render);
render();
#words, #cheque { font-size: 15px; line-height: 1.6; min-height: 2.4em; }
[dir='rtl'] #words, [dir='rtl'] #cheque { text-align: right; }