I'm totally new to html, css and javascript.
I'm trying to create a simple interest rate calculator and I want to style the result so that the numbers in the result message are highlighted like this:
Interest : If you deposit 10,
at an interest rate of 10.25.
You will receive an amount of 11.025,
in the year 2023.
What I get is the <b> elements rendered as text, for example:
Interest : If you deposit <b>10</b>,
at an interest rate of <b>10.25</b>.
You will receive an amount of <b>11.025</b>,
in the year <b>2023</b>.
My code is this:
function compute()
{
var principal = document.getElementById("principal").value;
var rate = document.getElementById("rate").value;
var years = document.getElementById("years").value;
var interest = principal * (rate / 100) * years;
// add amount to principal
let amount = interest parseInt(principal);
var year = new Date().getFullYear() parseInt(years);
var interestString = "If you deposit " principal.bold() ",\n at an interest rate of " rate ".\n You will receive an amount of " amount ",\n in the year " year ".";
document.getElementById("result").innerText = interestString
}
body {
background-color:black;
font-family: arial;
color:white
}
h1 {
color: grey;
font-family: verdana
}
.maindiv {
background-color: white;
color:black;
width:300px;
padding: 20px;
border-radius: 25px;
margin: auto;
}
<div >
<h1>Simple Interest Calculator</h1>
Amount <input type="number" id="principal">
<br/>
Rate <input type="range" id="rate" min="1" max="20" step="0.25" value="10.25" oninput="this.nextElementSibling.value = this.value">
<output>10.25</output>
<br/>
No. of Years
<select id="years">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<button onclick="compute()">Compute Interest</button>
<br>
<br>
Interest : <span id="result"></span>
</div>
I would be happy for a way to solve this. Thank you!
CodePudding user response:
Change innerText to innerHTML.
CodePudding user response:
- The
String.prototype.bold()method (which wraps any JavaScriptstringvalue in a<b>element) is deprecated and should not be used - unless you suddenly found yourself time-warped back to 1995. - Instead, I recommend making your "template" into normal HTML, and use
<output>elements as placeholders, and use CSS to make all<output>elements bold.
Something like this:
- My code uses
Intl.NumberFormatto format monetary-amounts and percentages appropriately- When formatting percentages, remember that
numberpercentage values have to be normalized to0-1.0; so10%is0.1and250%is2.5, and1.25%is0.0125.
- When formatting percentages, remember that
- Because JavaScript doesn't have compile-time (or parse-time) type-checking, my code employs defensive-programming techniques to preemptively fast-fail if anything goes wrong by doing
throw new Error, including:- Verifying that HTML elements referenced by
getElementByIdorquerySelectoractually exist (withfunction getElement). - Precondition validation that verifies parameter argument value types and other value things (e.g. numeric range bounds-checking).
- JSDoc (
/** @param */, etc) is used to document parameter types in a machine-readable format.
- Verifying that HTML elements referenced by
- I cleaned-up the HTML and wrapped related form fields in
<div >) and added a currency-symbol to the<input id="principal" />field.
const fmtUsd = new Intl.NumberFormat( 'en-US', { style: 'currency', currency: 'USD' } );
const fmtPerc = new Intl.NumberFormat( 'en-US', { style: 'percent', minimumFractionDigits: 2, maximumFractionDigits: 2 } );
function compute( e ) {
const errorOutput = getElement( 'errorOutput' , 'div' );
const outputContainer = getElement( 'outputContainer', 'div' );
try {
const principalInput = getElement( 'principal', 'input[type="number"]' );
const rateInput = getElement( 'rate' , 'input[type="range"]' );
const yearsSelect = getElement( 'years' , 'select' );
const principalAmount = getNumberValue( principalInput );
const ratePercDbl = getNumberValue( rateInput ) / 100.0;
const yearsCount = getNumberValue( yearsSelect );
computeInner( principalAmount, ratePercDbl, yearsCount );
// No errors, so show the output div and hide any previous error messages:
outputContainer.hidden = false;
errorOutput .hidden = true;
}
catch( err ) {
// Something went wrong! So hide the normal output <div> and show the error details:
errorOutput.hidden = false;
errorOutput.textContent = ( err || "(Unknown error)" ).toString() "\r\n\r\n" ( err.stack );
outputContainer.hidden = true;
}
}
/**
* @param {number} principalAmount
* @param {number} interestRatePerc
* @param {number} yearsCount
*/
function computeInner( principalAmount, interestRatePerc, yearsCount ) {
// Preconditions:
if( typeof principalAmount != 'number' ) throw new Error( "Expected `principalAmount` to be `number` but encountered " typeof principalAmount );
if( typeof interestRatePerc != 'number' ) throw new Error( "Expected `interestRatePerc` to be `number` but encountered " typeof interestRatePerc );
if( typeof yearsCount != 'number' || yearsCount <= 0 ) throw new Error( "Expected `yearsCount` to be a positive `number` but encountered " ( typeof yearsCount ) " \"" yearsCount.toString() "\" instead." );
//
const interest = principalAmount * interestRatePerc * yearsCount;
const totalAmount = interest principalAmount;
const endYear = new Date().getFullYear() yearsCount;
//
setOutput( 'principal', principalAmount , fmtUsd );
setOutput( 'rate' , interestRatePerc, fmtPerc );
setOutput( 'years' , endYear );
const amountOut = getElement( 'receiveAmountOut', 'output' );
amountOut.value = fmtUsd.format( totalAmount );
}
/**
* @param {string} outputFor
* @param {number} value
* @param {Intl.NumberFormat} formatter
*/
function setOutput( outputFor, value, formatter ) {
const formattedValue = formatter ? ( formatter.format( value ) ) : ( value.toString() );
const selector = 'output[for~="' CSS.escape( outputFor ) '"]';
const outputs = document.querySelectorAll( selector );
for( const outputEl of outputs ) {
outputEl.value = formattedValue;
}
}
/**
* @param {string} id
* @param {string} validationSelector
* @returns {HTMLElement}
*/
function getElement( id, validationSelector ) {
const el = document.getElementById( id );
if( el === null ) throw new Error( "No element with `id=\"" id "\"` was found." );
if( !el.matches( validationSelector ) ) throw new Error( "The element with `id=\"" id "\"` does not match selector \"" validationSelector "\"." );
return el;
}
/**
* @param {HTMLInputElement | HTMLSelectElement} input
* @returns {number}
*/
function getNumberValue( input ) {
// Preconditions:
if( !( input instanceof HTMLElement ) ) throw new Error( 'Expected `input` to be a HTML element.' );
if( !( input.tagName === 'SELECT' || input.tagName === 'INPUT' ) ) throw new Error( 'Expected `input` to be a HTML <input /> or <select> element.' );
//
let valueNumber;
if( input.tagName === 'SELECT' ) {
valueNumber = parseInt( input.value, /*radix:*/ 10 );
}
else if( input.type === 'number' ) { // Can't use valueAsNumber with type="range", grr.
valueNumber = input.valueAsNumber;
}
else {
valueNumber = parseFloat( input.value );
}
if( isNaN( valueNumber ) ) {
throw new Error( "Form <input> or <select> has invalid value: \"" input.value "\"." );
}
return valueNumber;
}
body {
background-color: black;
font-family: sans-serif;
color: white
}
.maindiv {
background-color: white;
color: black;
width: 300px;
padding: 20px;
border-radius: 25px;
margin: auto;
}
h1 {
color: grey;
font-family: verdana
}
.field {
padding: 1em;
margin: 1em 0;
background-color: #eee;
border-radius: 5px;
}
.field > label,
.field > input,
.field > div > input {
display: block;
}
#principalField.field > div {
display: flex;
justify-content: stretch;
align-items: stretch;
}
#principalField.field > div > span.symbol {
display: inline-block;
/* Width is 1em with negative right margin of -1.5em to make the currency symbol appear "inside" the <input />. Also, identical font-size, padding and border as Chrome's default style for <input />: */
width: 1em;
margin: 0 -1.5em 0 0;
border: 1px solid transparent;
padding: 1px 2px;
z-index: 10;
pointer-events: none;
user-select: none;
color: #999;
font-size: 90%;
}
#errorOutput {
border: 1px solid red;
border-radius: 7px;
white-space: pre-line;
}
output {
font-weight: bold;
}
output:empty {
display: none;
}
input[type="number"] {
text-align: right;
}
<div >
<h1>Simple Interest Calculator</h1>
<div id="principalField">
<label for="principal">Principal amount</label>
<div>
<span >$</span>
<input type="number" id="principal" oninput="compute(event)" value="123.00" size="6" />
</div>
</div>
<div >
<label for="rate">Interest rate (<output for="rate">10.25%</output>)</label>
<input type="range" id="rate" min="1" max="20" step="0.25" value="10.25" oninput="compute(event)" />
</div>
<div >
<label for="years">No. of Years </label>
<select id="years" oninput="compute(event)">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</div>
<button hidden type="button" onclick="compute(event)">Compute Interest</button>
<div id="outputContainer" hidden>
If you deposit <output for="principal"></output>
at an interest rate of <output for="rate"></output>
you will receive an amount of <output id="receiveAmountOut"></output> in the year <output for="years"></output>.
</div>
<div id="errorOutput" hidden></div>
</div>
CodePudding user response:
You can change the interestString to this
var interestString = `If you deposit <b>${principal}</b>,<br>
at aninterest rate of <b>${rate}</b>.<br>
You will receive an amount of <b>${amount}</b>,<br>
in the year <b>${year}</b>.`;
document.getElementById("result").innerHTML=interestString
and use innerHTML instead of innerText and it will look exactly like the example you gave above!
CodePudding user response:
you should put innerHTML instead of innerText
function compute()
{
var principal = document.getElementById("principal").value;
var rate = document.getElementById("rate").value;
var years = document.getElementById("years").value;
var interest = principal * (rate / 100) * years;
// add amount to principal
let amount = interest parseInt(principal);
var year = new Date().getFullYear() parseInt(years);
var interestString = "If you deposit " principal.bold() ",\n at an interest rate of " rate ".\n You will receive an amount of " amount ",\n in the year " year ".";
document.getElementById("result").innerHTML = interestString
}
body {background-color:black;font-family:arial;color:white}
h1{color:grey;font-family: verdana}
.maindiv {
background-color: white;
color:black;
width:300px;
padding: 20px;
border-radius: 25px;
margin: auto;
}
<div >
<h1>Simple Interest Calculator</h1>
Amount <input type="number" id="principal">
<br/>
Rate <input type="range" id="rate" min="1" max="20" step="0.25" value="10.25" oninput="this.nextElementSibling.value = this.value">
<output>10.25</output>
<br/>
No. of Years
<select id="years">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<button onclick="compute()">Compute Interest</button>
<br>
<br>
Interest : <span id="result"></span>
</div>
