I'm new in learning HTML, JavaScript and CSS. I'm stuck at this JavaScript code.
I'm trying to match user input on the searchbar with some city array list I already prepared, when the search result match the script will change the display style of element into showing the result of their search value, but until now the result always showing false value.
Is there any better way to do this? Is there something wrong with my code?
function searchRespond() {
if (document.getElementById("myInput").value.match(cities))
{
document.getElementById("areaCovered").style.display = "block";
}
else {
document.getElementById("areaNotCovered").style.display = "block";
document.getElementById("searchResult").innerHTML = document.getElementById("myInput").value;
}
}
var cities = ["Banda Aceh", "Bandar Lampung", "Banyuwangi", "Bandung", "Bali", "Batam", "Batu", "Bekasi", "Bengkulu", "Binjai", "Blitar", "Bogor", "Bukittinggi", "Cimahi", "Cirebon", "Denpasar", "Depok", "Dumai", "Gunungsitoli", "Jakarta", "Jambi", "Kediri", "Langsa", "Lhokseumawe", "Lombok", "Lubuklinggau", "Madiun", "Magelang", "Malang", "Medan", "Metro", "Mojokerto", "Padang", "Padang Sidempuan", "Padangpanjang", "Pagar Alam", "Palembang", "Pangkal Pinang", "Pariaman", "Pasuruan", "Payakumbuh", "Pekalongan", "Pekanbaru", "Pematangsiantar", "Prabumulih", "Prigi", "Probolinggo", "Sabang", "Salatiga", "Sawahlunto", "Semarang", "Serang", "Sibolga", "Solo", "Subussalam", "Sukabumi", "Sumbawa", "Sungaipenuh", "Surabaya", "Surakarta", "Tangerang", "Tangerang Selatan", "Tanjungbalai", "Tanjungpinang", "Tasikmalaya", "Tebing Tinggi", "Tegal", "Yogyakarta"];
.HeadlineSearchContainer {
position: relative;
top: 100px;
margin: auto;
height: 159px;
}
.SearchCharacterStyle {
font-family: Roboto;
font-size: 12px;
line-height: 24.82px;
text-align: left;
}
.searchrespond {
font-family: Roboto;
font-size: 12px;
line-height: 24.82px;
text-align: left;
}
#areaCovered {
display: none;
}
#areaNotCovered {
display: none;
}
#fillArea {
display: none;
}
<div class="HeadlineSearchContainer">
<div class="SearchCharacterStyle">
<h>SEARCH FOR AREA COVERANGE</h>
</div>
<div id="mySearch" class="searchbox_box">
<form autocomplete="off" name="myForm">
<div class="autocomplete" style="width:300px;">
<input id="myInput" type="text" name="city" placeholder="Enter Your Destination City">
<i class="searchbutton"></i>
</div>
<input type="button" formtarget="_new" onclick="searchRespond()" name="input" value="Search">
<div class="searchrespond" id="searchRespond">
<h id="areaCovered">YES! We cover your area destination</h>
<h id="areaNotCovered">We don't cover your area destination yet
<p id="searchResult"></p>
</h>
<h id="fillArea">Please fill your area destination first</h>
</div>
</form>
</div>
</div>
To do what you require you can use filter() to match the user's input to values in your array. You would be best to perform a case-insensitive match, which can be done by converting both values to the same case.
Note that this logic sets the notifications as hidden before the logic runs, so that the previous state of the search is removed.
In addition, I made a couple of improvements to the code. Firstly I stored the relevant elements in variables instead of accessing the DOM every time. This is slightly more performant, and makes the code a lot easier to read. I also used addEventListener() to bind events instead of inline event handlers in the HTML, which are bad practice and shouldn't be used. Lastly I converted the <h> elements to <h2 /> in this demo, as there is no <h> element in HTML.
const input = document.querySelector('#myInput');
const areaCovered = document.querySelector('#areaCovered');
const areaNotCovered = document.querySelector('#areaNotCovered');
const searchResult = document.querySelector('#searchResult');
const fillArea = document.querySelector('#fillArea');
const cities = ["Banda Aceh", "Bandar Lampung", "Banyuwangi", "Bandung", "Bali", "Batam", "Batu", "Bekasi", "Bengkulu", "Binjai", "Blitar", "Bogor", "Bukittinggi", "Cimahi", "Cirebon", "Denpasar", "Depok", "Dumai", "Gunungsitoli", "Jakarta", "Jambi", "Kediri", "Langsa", "Lhokseumawe", "Lombok", "Lubuklinggau", "Madiun", "Magelang", "Malang", "Medan", "Metro", "Mojokerto", "Padang", "Padang Sidempuan", "Padangpanjang", "Pagar Alam", "Palembang", "Pangkal Pinang", "Pariaman", "Pasuruan", "Payakumbuh", "Pekalongan", "Pekanbaru", "Pematangsiantar", "Prabumulih", "Prigi", "Probolinggo", "Sabang", "Salatiga", "Sawahlunto", "Semarang", "Serang", "Sibolga", "Solo", "Subussalam", "Sukabumi", "Sumbawa", "Sungaipenuh", "Surabaya", "Surakarta", "Tangerang", "Tangerang Selatan", "Tanjungbalai", "Tanjungpinang", "Tasikmalaya", "Tebing Tinggi", "Tegal", "Yogyakarta"];
document.querySelector('#search-from').addEventListener('submit', e => {
e.preventDefault();
const searchTerm = input.value.trim().toLowerCase();
fillArea.style.display = 'none';
areaCovered.style.display = 'none';
areaNotCovered.style.display = 'none';
if (!searchTerm) {
fillArea.style.display = 'block';
return;
}
let matches = cities.filter(city => city.toLowerCase() == searchTerm);
if (matches.length) {
areaCovered.style.display = 'block';
} else {
areaNotCovered.style.display = 'block';
}
});
.HeadlineSearchContainer {
position: relative;
top: 100px;
margin: auto;
height: 159px;
}
.SearchCharacterStyle {
font-family: Roboto;
font-size: 12px;
line-height: 24.82px;
text-align: left;
}
.searchrespond {
font-family: Roboto;
font-size: 12px;
line-height: 24.82px;
text-align: left;
}
#areaCovered {
display: none;
}
#areaNotCovered {
display: none;
}
#fillArea {
display: none;
}
.autocomplete {
width: 300px;
}
<div class="HeadlineSearchContainer">
<div class="SearchCharacterStyle">
<h>SEARCH FOR AREA COVERANGE</h>
</div>
<div id="mySearch" class="searchbox_box">
<form autocomplete="off" name="myForm" id="search-from">
<div class="autocomplete">
<input id="myInput" type="text" name="city" placeholder="Enter Your Destination City">
<i class="searchbutton"></i>
</div>
<button type="submit">Search</button>
<div class="searchrespond" id="searchRespond">
<h2 id="areaCovered">YES! We cover your area destination</h2>
<h2 id="areaNotCovered">We don't cover your area destination yet</h2>
<h2 id="fillArea">Please fill your area destination first</h2>
</div>
</form>
</div>
</div>
You can use javascript includes().
<script>
const fruits = ["Banana Aceh", "Orange", "Apple", "Mango"];
let str = "Banana Aceh"; //document.getElementById("myInput").value
if(fruits.some(v => str.includes(v))) {
console.log("Exists");
} else {
console.log("Did not Exists");
}
</script>
function searchRespond() {
let searchTerm = document.getElementById("myInput").value;
if (cities.find(city => city == searchTerm))
{
document.getElementById("areaCovered").style.display = "block";
}
else {
document.getElementById("areaNotCovered").style.display = "block";
document.getElementById("searchResult").innerHTML = document.getElementById("myInput").value;
}
}
var cities = ["Banda Aceh", "Bandar Lampung", "Banyuwangi", "Bandung", "Bali", "Batam", "Batu", "Bekasi", "Bengkulu", "Binjai", "Blitar", "Bogor", "Bukittinggi", "Cimahi", "Cirebon", "Denpasar", "Depok", "Dumai", "Gunungsitoli", "Jakarta", "Jambi", "Kediri", "Langsa", "Lhokseumawe", "Lombok", "Lubuklinggau", "Madiun", "Magelang", "Malang", "Medan", "Metro", "Mojokerto", "Padang", "Padang Sidempuan", "Padangpanjang", "Pagar Alam", "Palembang", "Pangkal Pinang", "Pariaman", "Pasuruan", "Payakumbuh", "Pekalongan", "Pekanbaru", "Pematangsiantar", "Prabumulih", "Prigi", "Probolinggo", "Sabang", "Salatiga", "Sawahlunto", "Semarang", "Serang", "Sibolga", "Solo", "Subussalam", "Sukabumi", "Sumbawa", "Sungaipenuh", "Surabaya", "Surakarta", "Tangerang", "Tangerang Selatan", "Tanjungbalai", "Tanjungpinang", "Tasikmalaya", "Tebing Tinggi", "Tegal", "Yogyakarta"];
.HeadlineSearchContainer {
position: relative;
top: 100px;
margin: auto;
height: 159px;
}
.SearchCharacterStyle {
font-family: Roboto;
font-size: 12px;
line-height: 24.82px;
text-align: left;
}
.searchrespond {
font-family: Roboto;
font-size: 12px;
line-height: 24.82px;
text-align: left;
}
#areaCovered {
display: none;
}
#areaNotCovered {
display: none;
}
#fillArea {
display: none;
}
<div class="HeadlineSearchContainer">
<div class="SearchCharacterStyle">
<h>SEARCH FOR AREA COVERANGE</h>
</div>
<div id="mySearch" class="searchbox_box">
<form autocomplete="off" name="myForm">
<div class="autocomplete" style="width:300px;">
<input id="myInput" type="text" name="city" placeholder="Enter Your Destination City">
<i class="searchbutton"></i>
</div>
<input type="button" formtarget="_new" onclick="searchRespond()" name="input" value="Search">
<div class="searchrespond" id="searchRespond">
<h id="areaCovered">YES! We cover your area destination</h>
<h id="areaNotCovered">We don't cover your area destination yet
<p id="searchResult"></p>
</h>
<h id="fillArea">Please fill your area destination first</h>
</div>
</form>
</div>
</div>
suggest to validate input by making first letter uppercase and rest lowercase to match the array values
with javascript indexOf function
function searchRespond() {
var input = document.getElementById("myInput").value;
var area2search = input.charAt(0).toUpperCase() + input.slice(1).toLowerCase(); /* make fist letter capital and rest lower case to match array */
if (cities.indexOf(area2search) > -1) {
document.getElementById("areaCovered").style.display = "block";
//In the array!
} else {
document.getElementById("areaNotCovered").style.display = "block";
document.getElementById("searchResult").innerHTML = document.getElementById("myInput").value;
}
}
var cities = ["Banda Aceh", "Bandar Lampung", "Banyuwangi", "Bandung", "Bali", "Batam", "Batu", "Bekasi", "Bengkulu", "Binjai", "Blitar", "Bogor", "Bukittinggi", "Cimahi", "Cirebon", "Denpasar", "Depok", "Dumai", "Gunungsitoli", "Jakarta", "Jambi", "Kediri", "Langsa", "Lhokseumawe", "Lombok", "Lubuklinggau", "Madiun", "Magelang", "Malang", "Medan", "Metro", "Mojokerto", "Padang", "Padang Sidempuan", "Padangpanjang", "Pagar Alam", "Palembang", "Pangkal Pinang", "Pariaman", "Pasuruan", "Payakumbuh", "Pekalongan", "Pekanbaru", "Pematangsiantar", "Prabumulih", "Prigi", "Probolinggo", "Sabang", "Salatiga", "Sawahlunto", "Semarang", "Serang", "Sibolga", "Solo", "Subussalam", "Sukabumi", "Sumbawa", "Sungaipenuh", "Surabaya", "Surakarta", "Tangerang", "Tangerang Selatan", "Tanjungbalai", "Tanjungpinang", "Tasikmalaya", "Tebing Tinggi", "Tegal", "Yogyakarta"];
I'm not sure if it's possible, but I'd like to use one unique function to trigger 4 different buttons to count a value (+ and -). But there are four different span values, for example, if I trigger forest it will only add or remove from forest, if I do it for town it will only trigger for town, and so on.
// set inital value to zero
let count = 0;
// select value and buttons
const valueForest = document.querySelector("#valueForest");
const btns = document.querySelectorAll(".btn");
btns.forEach(function (btn) {
btn.addEventListener("click", function (e) {
const styles = e.currentTarget.classList;
if (styles.contains("decrease")) {
count--;
} else if (styles.contains("increase")) {
count++;
} else {
count = 0;
}
if (count > 0) {
valueForest.style.color = "green";
}
if (count < 0) {
valueForest.style.color = "red";
}
if (count === 0) {
valueForest.style.color = "#222";
}
valueForest.textContent = count;
});
});
<div class="scoreDiv">
<h3>Input below the quantity of each tile in the end of the game:</h3>
<div class="scoreItem">
<h4>Forest</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueForest">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Town</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueTown">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Production</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueProduction">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Factory</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueFactory">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
</div>
Since there is nothing to add to Mister Jojo's already perfectly answered event delegation based approach, I will focus on an approach that sees and treats repeatedly used DOM structures which feature a specific behavior as components
As for the OP's example there would be just a Score Item component which implements its specific behavior exactly once and independent from the semantics of the underlying HTML/CSS.
The amount of implemented/used JavaScript code is still small enough in comparison to what such a Score Item component actually is capable of.
Identifying component structures relies on data attributes which decouples this task from whatever provided HTML- and CSS- code/environment.
Each component encapsulates its state at initialization/creation time; thus it does not read the data from the DOM (it only does write to the latter), but it does read and write the data from/to its encapsulated state.
A component also can be configured via component specific data attributes for an initially displayed value as well as for distinct incrementing/decrementing values.
The color-schema for positive, negative or Zero values are described by component specific and data attribute based CSS rules; there is no reason for layout related scripting overhead ...
function incrementBoundItemScore() {
const { outputControl: ctrl, currentValue, incrementValue } = this;
ctrl.textContent = ctrl.dataset.currentValue = this.currentValue = (currentValue + incrementValue);
}
function decrementBoundItemScore() {
const { outputControl: ctrl, currentValue, decrementValue } = this;
ctrl.textContent = ctrl.dataset.currentValue = this.currentValue = (currentValue + decrementValue);
}
function initializeScoreItem(rootNode) {
const incrementControl = rootNode.querySelector('[data-increase]');
const decrementControl = rootNode.querySelector('[data-decrease]');
const outputControl = rootNode.querySelector('[data-output]');
const incrementValue = parseFloat(incrementControl.dataset.value, 10);
const decrementValue = parseFloat(decrementControl.dataset.value, 10);
const initialValue = parseFloat(outputControl.dataset.initialValue, 10);
const scoreItem = {
outputControl,
currentValue: initialValue,
incrementValue,
decrementValue,
}
outputControl.textContent = outputControl.dataset.currentValue = initialValue;
incrementControl
.addEventListener('click', incrementBoundItemScore.bind(scoreItem));
decrementControl
.addEventListener('click', decrementBoundItemScore.bind(scoreItem));
}
function initialize() {
document
.querySelectorAll('[data-score-item-component]')
.forEach(initializeScoreItem);
}
initialize();
body {
zoom: .8;
margin: 0;
}
ul, li {
list-style: none;
}
ul {
margin: 0;
}
fieldset {
padding: 0px 10px;
}
.score-group {
margin: 4px 0;
}
.score-item {
margin: 0 0 5px 0;
}
.score-item legend {
font-weight: bold;
}
.score-item strong {
position: relative;
top: -2px;
font-weight: normal;
font-size: small;
text-transform: uppercase
}
[data-output][data-current-value] {
display: inline-block;
width: 3em;
text-align: center;
font-weight: bold;
color: green;
}
[data-output][data-current-value="0"] {
color: #222;
}
[data-output][data-current-value^="-"] {
color: red;
}
<section class="score-board">
<!--
<h3>Input below the quantity of each tile in the end of the game:</h3>
//-->
<ul>
<li class="score-item">
<fieldset data-score-item-component>
<legend>Forest</legend>
<div class="score-group">
<button
type="button"
data-decrease
data-value='-1'
class="btn decrease"
>-</button>
<output
name="forest-score"
data-output
data-initial-value="9"
></output>
<button
type="button"
data-increase
data-value='1'
class="btn increase"
>+</button>
</div>
<strong>Soma</strong>
</fieldset>
</li>
<li class="score-item">
<fieldset data-score-item-component>
<legend>Town</legend>
<div class="score-group">
<button
type="button"
data-decrease
data-value='-2'
class="btn decrease"
>-</button>
<output
name="town-score"
data-output
data-initial-value="0"
></output>
<button
type="button"
data-increase
data-value='2'
class="btn increase"
>+</button>
</div>
<strong>Soma</strong>
</fieldset>
</li>
<li class="score-item">
<fieldset data-score-item-component>
<legend>Production</legend>
<div class="score-group">
<button
type="button"
data-decrease
data-value='-5'
class="btn decrease"
>-</button>
<output
name="production-score"
data-output
data-initial-value="-10"
></output>
<button
type="button"
data-increase
data-value='5'
class="btn increase"
>+</button>
</div>
<strong>Soma</strong>
</fieldset>
</li>
<li class="score-item">
<fieldset data-score-item-component>
<legend>Factory</legend>
<div class="score-group">
<button
type="button"
data-decrease
data-value='-2'
class="btn decrease"
>-</button>
<output
name="factory-score"
data-output
data-initial-value="-5"
></output>
<button
type="button"
data-increase
data-value='1'
class="btn increase"
>+</button>
</div>
<strong>Soma</strong>
</fieldset>
</li>
</ul>
</section>
yes, with event delegation
this way:
const scoreDiv = document.querySelector('div.scoreDiv') // the parent Div
scoreDiv.onclick = e => // get all clicks everywhere upon this parent Div
{
if (!e.target.matches('div.scoreItem > button.btn ')) return // ignore other clicks
let countEl = e.target.closest('div.scoreItem').querySelector('span.value')
, newVal = +countEl.textContent + (e.target.matches('.decrease') ? -1 : +1)
;
countEl.style.color = (newVal > 0) ? 'green' : (newVal < 0) ? 'red' : '#222'
countEl.textContent = newVal;
}
span.value {
display : inline-block;
width : 5em;
text-align : right;
padding-right : .5em;
font-weight : bold;
}
<div class="scoreDiv">
<h3>Input below the quantity of each tile in the end of the game:</h3>
<div class="scoreItem">
<h4>Forest</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueForest">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Town</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueTown">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Production</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueProduction">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Factory</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueFactory">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
</div>
Explanations about
if (!e.target.matches('div.scoreItem > button.btn')) return
First of all the event handler scoreDiv.onclick = e => concern everything inside
<div class="scoreDiv">
// everything inside
</div>
So this get any click event in this space is processed by this arrow function.
It could be a click:
on the H3 element
, or one of the span elements
, or any the H4 elements
, everything !
, even the spaces between any elements.
the event [e] have diffrents properties
e.currentTarget --> is a reference to the caller element (here it is scoreDiv [div.scoreItem])
e.target --> is a reference to the element where the click happen
for this job we need to do only increment / decrement operations.
that's mean we have to ignore any click event witch is not on the plus or minus buttons.
This 8 buttons are : <button class="btn decrease">-</button> or <button class="btn increase">-</button>
All this buttons correspond to CSS = div.scoreItem > button.btn
In javascript the code for testing that is
e.target.matches('div.scoreItem > button.btn')
will return a boolean value (true or false)
There is now a strategy: Instead of making a big
if ( e.target.matches('div.scoreItem > button.btn') )
{
//...
// with many lines of code
//until the closing
}
// and then quit the function
and because this is a function we use a Logical NOT (!)
to make a direct return from function, coded like that:
if (!e.target.matches('div.scoreItem > button.btn')) return
The main interest is to quickly free the event manager in case of another element (present in scoreDiv) have is own click eventHandler.
I looked up how to change the color directly via css and luckily Peter Seliger showed that.
I also added in css an output::before {content: attr(data-value)} allowing to directly attribute this value on the display, without JS code
This further simplifies the javascript code.
(I also took the liberty of changing the interface a little to lighten it up completely, which is of no interest for this demonstration)
const scoreBoard = document.querySelector('#score-board')
scoreBoard.onclick = e =>
{
if (!e.target.matches('#score-board button')) return
let countEl = e.target.closest('fieldset')
.querySelector('output[data-value]')
countEl.dataset.value = +countEl.dataset.value
+ (+e.target.dataset.increase)
}
body, textarea, input {
font-family : Helvetica, Arial sans-serif;
font-size : 12px;
}
#score-board fieldset {
width : 20em;
margin : .5em 1em;
}
#score-board legend {
font-size : 1.4em;
padding : 0 .7em;
}
#score-board output {
display : inline-block;
font-size : 1.4em;
width : 5em;
text-align : right;
padding-right : .5em;
color : green;
font-weight : bold;
border-bottom : 1px solid grey;
margin : 0 .8em 0 .2em;
}
#score-board output::before {
content : attr(data-value)
}
#score-board output[data-value="0"] {
color: #222;
}
#score-board output[data-value^="-"] {
color: red;
}
<section id="score-board">
<fieldset>
<legend>Forest</legend>
<output data-value="-10"></output>
<button data-increase="+1">π</button>
<button data-increase="-1">π</button>
</fieldset>
<fieldset>
<legend>Town</legend>
<output data-value="0"></output>
<button data-increase="+1">π</button>
<button data-increase="-1">π</button>
</fieldset>
<fieldset>
<legend>Production</legend>
<output data-value="-7"></output>
<button data-increase="+1">π</button>
<button data-increase="-1">π</button>
</fieldset>
<fieldset>
<legend>Factory</legend>
<output data-value="5"></output>
<button data-increase="+1">π</button>
<button data-increase="-1">π</button>
</fieldset>
</section>
// set inital value to zero
//let count = 0;
// select value and buttons
const btns = document.querySelectorAll(".btn");
btns.forEach(function (btn) {
btn.addEventListener("click", function (e) {
const styles = e.currentTarget.classList;
const SectionValue = e.currentTarget.parentNode.querySelector('span');
var count = Number( SectionValue.innerHTML );
if (styles.contains("decrease")) {
count--;
} else {
count++;
}
if (count > 0) {
SectionValue.style.color = "green";
} else if (count < 0) {
SectionValue.style.color = "red";
} else {
SectionValue.style.color = "#222";
}
SectionValue.innerHTML = count;
});
});
<div class="scoreDiv">
<h3>Input below the quantity of each tile in the end of the game:</h3>
<div class="scoreItem">
<h4>Forest</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueForest">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Town</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueTown">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Production</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueProduction">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
<div class="scoreItem">
<h4>Factory</h4>
<button class="btn decrease">-</button>
<span class="value" id="valueFactory">0</span>
<button class="btn increase">+</button>
<h4>SOMA</h4>
</div>
</div>
I'm trying to make it when my mouse hovers over my buttons, it will change the color to black, and then when the mouse is off the button, it will change back to the same colors as before. I want my color change to be done in javascript instead of CSS, just because I'm trying to get an understanding of events and event handlers.
JS:
//Changing colors of operation colors
//Multiply Color
const colorMultiply = document.getElementById('multiply')
colorMultiply.style.backgroundColor = "green" //Makes Color Green
//Divide Color
const colorDivide = document.getElementById('divide')
colorDivide.style.backgroundColor = "red"//Makes Color Red
//subtract color
const colorSubtract = document.getElementById('subtract')
colorSubtract.style.backgroundColor="blue"//Makes Color Blue
//add color
const colorAdd = document.getElementById('add')
colorAdd.style.backgroundColor="yellow"//Makes Color Yellow
//change font of numbers to blue (I did it like this incase anyone wants to color of a single number)
//Makes it easier for you to change a colour of one button
const number1 = document.getElementById('number1')
number1.style.color="blue"
const number2 = document.getElementById('number2')
number2.style.color="blue"
const number3 = document.getElementById('number3')
number3.style.color="blue"
const number4 = document.getElementById('number4')
number4.style.color="blue"
const number5 = document.getElementById('number5')
number5.style.color="blue"
const number6 = document.getElementById('number6')
number6.style.color="blue"
const number7 = document.getElementById('number7')
number7.style.color="blue"
const number8 = document.getElementById('number8')
number8.style.color="blue"
const number9 = document.getElementById('number9')
number9.style.color="blue"
const number0 = document.getElementById('number0')
number0.style.color="blue"
const decimal = document.getElementById('decimal')
decimal.style.color="blue"
//Changing color of the clear button
const clear = document.getElementById('clear')
clear.style.color="white"
clear.style.backgroundColor="black"
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Then we want to insert `memoryStoreButton` before the `clear` button:
var memoryStoreButton = document.createElement("BUTTON");
memoryStoreButton.innerHTML = "MS";
clear.before(memoryStoreButton); //puts button before clear
// Then we want the `memoryClearButton` before `memoryStoreButton`
var memoryClearButton = document.createElement("BUTTON");
memoryClearButton.innerHTML = "MC";
memoryStoreButton.before(memoryClearButton);//puts button before clear
// and finally, the `memoryRestoreButton` before `memoryClearButton`
var memoryRestoreButton = document.createElement("BUTTON");
memoryRestoreButton.innerHTML = "MR";
memoryClearButton.before(memoryRestoreButton);//puts button before clear
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//What number buttons are pressed
var numButton = document.querySelectorAll(".btn8");
var showNum = document.querySelector(".screen8");
numButton.forEach(function(button){
button.addEventListener('click', function(event){
if(event.target.innerHTML == "C"){
return showNum.value = "";
} else if (event.target.innerHTML == "=") {
return;
}
let view = event.target.dataset.num;
showNum.value += view;
});
});
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//When equal is pressed it calculates the numbers, and if no numbers were entered there will be a error mesage
var equalButton = document.querySelector("#equals")
equalButton.addEventListener('click', function(event){
if(showNum.value == ""){
return alert("Please Enter a Value"); // If no numbers are being displayed, error alert.
}
showNum.value = showNum.value + "=" + eval(showNum.value);
});
//Align test to the right of screen
document.getElementById("numberBox").style.textAlign = "right";
////////////////////////////////////////////////////////////////////////////////////////////////////////////
document.getElementsByTagName("BUTTON").addEventListener("mouseover", mouseOver);
document.getElementsByTagName("BUTTON").addEventListener("mouseout", mouseOut);
function mouseOver() {
document.getElementsByTagName("BUTTON").style.color = "black";
}
function mouseOut() {
document.getElementsByTagName("BUTTON").style.color = "grey";
}
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Calculator 8 </title>
<script src="fp.js" defer></script>
<link rel="stylesheet" href="fp.css">
</head>
<body>
<section class="calculator8">
<h1> Calculator 8 </h1>
<form>
<input type="text" name="calcScreeng" id="numberBox" class="screen8">
</form>
<div class="buttons8">
<!-- operation buttons -->
<button id="multiply" type="button" class="btn8 btn-mul" data-num="*">*</button>
<button id="divide" type="button" class="btn8 btn-div" data-num="/">/</button>
<button id="subtract" type="button" class="btn8 btn-sub" data-num="-">-</button>
<button id="add" type="button" class="btn8 btn-add" data-num="+">+</button>
<!-- number buttons -->
<button id="decimal" type="button" class="btn8 btn-grey" data-num=".">.</button>
<button id="number9" type="button" class="btn8 btn-grey" data-num="9">9</button>
<button id="number8" type="button" class="btn8 btn-grey" data-num="8">8</button>
<button id="number7" type="button" class="btn8 btn-grey" data-num="7">7</button>
<button id="number6" type="button" class="btn8 btn-grey" data-num="6">6</button>
<button id="number5" type="button" class="btn8 btn-grey" data-num="5">5</button>
<button id="number4" type="button" class="btn8 btn-grey" data-num="4">4</button>
<button id="number3" type="button" class="btn8 btn-grey" data-num="3">3</button>
<button id="number2" type="button" class="btn8 btn-grey" data-num="2">2</button>
<button id="number1" type="button" class="btn8 btn-grey" data-num="1">1</button>
<button id="number0" type="button" class="btn8 btn-grey" data-num="0">0</button>
<button id="equals" type="button" class="btn8 btn-grey">=</button>
<button id="clear" type="button" class="btn8 btn-grey">C</button>
</div>
</section>
</body>
</html>
CSS:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.calculator8{
flex: 0 0 40%;
}
.screen8{
width: 100%;
font-size: 5rem;
padding: 0.5rem;
background: rgb(41,41,56);
color: white;
border:none;
}
.buttons8{
display: flex;
flex-wrap: wrap;
transition: all 0.5s linear;
}
button{
flex:0 0 25%;
border: 1px solid black;
padding: 0.25rem 0;
transition: all 2s ease;
}
.btn-kground: rgb(224,224,224);
}
.btn8{
font-size: 4rem;
}
If you want to use JavaScript instead of CSS, you'll need to write event handlers for each button. One event handler will fire when a mouse is over the button ('mouseover'), the other event handler will fire when a mouse leaves the button ('mouseout').
This function will add event handlers to a single button:
function addButtonHandlers(btn) {
// make gray button on mouseover
btn.addEventListener('mouseover', () => {
btn.style.backgroundColor = 'gray';
btn.style.color = 'white';
});
// make white button on mouseout
btn.addEventListener('mouseout', () => {
btn.style.backgroundColor = 'white';
btn.style.color = 'black';
});
}
A working example:
function addButtonHandlers(btn) {
// make gray button on mouseover
btn.addEventListener('mouseover', () => {
btn.style.backgroundColor = 'gray';
btn.style.color = 'white';
});
// make white buton on mouseout
btn.addEventListener('mouseout', () => {
btn.style.backgroundColor = 'white';
btn.style.color = 'black';
});
}
const testBtn = document.getElementById('testbtn');
addButtonHandlers(testBtn);
button {
margin: 1rem;
padding: 1rem;
border: none;
color: black;
background-color: white;
}
<button id='testbtn'>Test Button</button>
Documentation on mouse events and addEventListener().
Lets say the id of the button is calcButton, you would do this:
<html>
<body>
<button id = "calcButton"></button>
<style>
#calcButton {
color: red;
}
#calcButton:hover {
color: black;
}
</style>
</body>
</html>
Use that, but change the colours to what you want.