function ATM(balance, amount) {
this.receiver = document.createElement('template');
this.build();
this.balance = balance || 0;
this.amount = amount || 0;
}
ATM.prototype = {
build() {
this.receiver.insertAdjacentHTML('beforeend', `
<form id="atm-form">
<h1>ATM</h1>
<p><label>Balance: <input id="balance" value="0.00" readonly></label></p>
<p><label>Amount: <input id="amount" value="0.00"></label></p>
<p><button type="submit">Withdraw</button></p>
</form>
`);
this.nodes = {
form: this.receiver.querySelector('#atm-form'),
balance: this.receiver.querySelector('#balance'),
amount: this.receiver.querySelector('#amount')
};
this.nodes.form.addEventListener('submit', event => {
event.preventDefault();
const result = this.withdraw();
this.receiver.dispatchEvent(new CustomEvent('withdraw', { detail: { result } }));
});
this.nodes.balance.addEventListener('change', event => {
this.balance = this.nodes.balance.value;
});
this.nodes.amount.addEventListener('change', event => {
this.amount = this.nodes.amount.value;
});
},
attach(node) {
if(!(node instanceof Node)) return false;
node.appendChild(this.nodes.form);
return true;
},
validate() {
const result = { valid: false, error: null };
if(isNaN(this.amount)) {
result.error = 'Please enter a numeric value.';
} else if(this.amount > this.balance) {
result.error = 'Please enter a value less than the balance.';
} else if(this.amount <= 0) {
result.error = 'Please enter a value greater than 0.';
} else {
result.valid = true;
}
return result;
},
withdraw() {
let result = { success: false, error: null, amount: this.amount, balance: this.balance };
const { valid, error } = this.validate();
if(valid) {
this.balance = this.balance - this.amount;
result.balance = this.balance;
result.success = true;
} else {
result.error = error;
}
return result;
},
addEventListener(type, callback) {
this.receiver.addEventListener(type, callback);
},
removeEventListener(type, callback) {
this.receiver.removeEventListener(type, callback);
},
formatCurrency(value) {
return Number.parseFloat(value).toFixed(2);
},
set amount(value) {
this.nodes.amount.value = this.formatCurrency(value);
},
get amount() {
return this.formatCurrency(this.nodes.amount.value);
},
set balance(value) {
this.nodes.balance.value = this.formatCurrency(value);
},
get balance() {
return this.formatCurrency(this.nodes.balance.value);
}
}
const atm = new ATM(400.00);
atm.attach(document.body);
atm.addEventListener('withdraw', ({ detail: { result } }) => {
console.log('Withdraw event: ', result)
});