I am dipping my toe in JavaScript (and CSS). New to asking questions here; open to feedback. I'm posting in part to help others find an answer to a challenge I was facing. I couldn't find an example of what I was trying to do via Googling and head scratching.
Multiple button groups ...independently styled ...can each update respective parts of a concatenated string with one click.
https://jsfiddle.net/ncarlton/by8ragpc/1/
I am using HTML, CSS and JavaScript.
Objectives of the code included:
JS:
//make default variables in UPPER to show that values should come from .js and not from .html
let _firstName = "MARTIN";
let _middleName = "LUTHER";
let _lastName = "KING";
//build the full Name
let fullName = _firstName + " " + _middleName + " " + _lastName;
//replace the <span>Need A. Change with the default values
//default values start as UPPERcase to show they came from variables and not innerHTML
document.getElementById("myName").innerHTML = fullName;
//swap out any of the name parts by a single button click: first, middle, last
//also style the buttons in each group to look different
function changeName() {
//First Name Selections and Style changes
const btnFirstSelect = function() {
this.parentNode.getElementsByClassName("btnSelFirst")[0].classList.remove("btnSelFirst");
this.classList.add("btnSelFirst");
_firstName = this.innerHTML;
fullName = _firstName + " " + _middleName + " " + _lastName;
document.getElementById("myName").innerHTML = fullName;
};
document.querySelectorAll(".btnsFirstName .btnFirst").forEach(btnFirst => btnFirst.addEventListener('click', btnFirstSelect));
//Middle Name Selections and Style changes
const btnMiddleSelect = function() {
this.parentNode.getElementsByClassName("btnSelMiddle")[0].classList.remove("btnSelMiddle");
this.classList.add("btnSelMiddle");
_middleName = this.innerHTML;
fullName = _firstName + " " + _middleName + " " + _lastName;
document.getElementById("myName").innerHTML = fullName;
};
document.querySelectorAll(".btnsMiddleName .btnMiddle").forEach(btnMiddle => btnMiddle.addEventListener('click', btnMiddleSelect));
//Last Name Selections and Syle changes
const btnLastSelect = function() {
this.parentNode.getElementsByClassName("btnSelLast")[0].classList.remove("btnSelLast");
this.classList.add("btnSelLast");
_lastName = this.innerHTML;
fullName = _firstName + " " + _middleName + " " + _lastName;
document.getElementById("myName").innerHTML = fullName;
};
document.querySelectorAll(".btnsLastName .btnLast").forEach(btnLast => btnLast.addEventListener('click', btnLastSelect));
}
window.onload = changeName;
//click a button and then reload the console with this
//confirm your selection changed the var by grabbing the innerHTML
//confirm the full name was also rebuilt
console.log(_firstName, _middleName, _lastName, fullName);
HMTL:
<body>
<h4>Name Builder from Button Choices</h4>
<div>My name is: <span id="myName">Need A. Change</span>
</div>
<hr />
<div class="btnsFirstName ">First name Choices:
<button class="btnFirst btnSelFirst">Martin</button>
<button class="btnFirst">Barack</button>
<button class="btnFirst">Jelly</button>
</div>
<div class="btnsMiddleName">Middle Name Choices:
<button class="btnMiddle btnSelMiddle">Luther</button>
<button class="btnMiddle">Hussein</button>
<button class="btnMiddle">Roll</button>
</div>
<div class="btnsLastName">Last Name Choices:
<button class="btnLast btnSelLast">King</button>
<button class="btnLast">Obama</button>
<button class="btnLast">Morton</button>
</div>
<p>(Each button click should build the full name by swapping out the value of the clicked button in the correct position. Ideally the button groups would change styles independently too.)</p>
</body>
CSS:
.btnFirst,
.btnMiddle,
.btnLast {
background-color: grey;
color: green;
}
.btnSelFirst {
background-color: black;
color: white;
outline: none;
}
.btnFirst:hover {
background-color: black;
color: white;
outline: none;
}
.btnSelMiddle {
background-color: white;
color: black;
outline: none;
}
.btnMiddle:hover {
background-color: white;
color: black;
outline: none;
}
.btnSelLast {
background-color: pink;
color: blue;
outline: none;
}
.btnLast:hover {
background-color: pink;
color: blue;
outline: none;
}
body {
font-family: Helvetica, Arial, Sans-Serif;
}
Using the following question, I sort of "tacked on" the additional redundant functional code to make the buttons "work" the way I wanted: How to apply javascript to multiple button groups
I've tried a couple things to reduce the code redundancy but I hope to learn various techniques.
Hey I come up with something.
HTML
Key Points:
<button ... name="firstname">
:<button ... onClick="changeName(this)">
:<body>
<h4>Name Builder from Button Choices</h4>
<div>My name is: <span id="myName">Need A. Change</span>
</div>
<hr />
<div class="btnsFirstName ">First name Choices:
<button class="btnFirst active" name="firstname" onClick="changeName(this)">Martin</button>
<button class="btnFirst" name="firstname" onClick="changeName(this)">Barack</button>
<button class="btnFirst" name="firstname" onClick="changeName(this)">Jelly</button>
</div>
<div class="btnsMiddleName">Middle Name Choices:
<button class="btnMiddle active" name="middlename" onClick="changeName(this)">Luther</button>
<button class="btnMiddle" name="middlename" onClick="changeName(this)">Hussein</button>
<button class="btnMiddle" name="middlename" onClick="changeName(this)">Roll</button>
</div>
<div class="btnsLastName">Last Name Choices:
<button class="btnLast active" name="lastname" onClick="changeName(this)">King</button>
<button class="btnLast" name="lastname" onClick="changeName(this)">Obama</button>
<button class="btnLast" name="lastname" onClick="changeName(this)">Morton</button>
</div>
<p>(Each button click should build the full name by swapping out the value of the clicked button in the correct position. Ideally the button groups would change styles independently too.)</p>
<script src="./script.js"></script>
</body>
JS
Key Points:
//make default variables in UPPER to show that values should come from .js and not from .html
let _firstName = "MARTIN";
let _middleName = "LUTHER";
let _lastName = "KING";
// set as a func to conveniently update fullname in the DOM
const setFullname = () => {
document.getElementById("myName").innerHTML = `${_firstName} ${_middleName} ${_lastName}`;
}
// refer this function in HTML, example:
// <button class="btnFirst" onClick="changeName(this)">Jelly</button>
const changeName = el => {
el.parentNode.getElementsByClassName("active")[0].classList.remove("active");
el.classList.add("active");
switch(el.name) {
// el.name is the <button ... name="firstname">
case 'firstname':
_firstName = el.innerHTML;
break;
case 'middlename':
_middleName = el.innerHTML;
break;
case 'lastname':
_lastName = el.innerHTML;
break;
}
setFullname();
}
// call once in the beginning to set default
setFullname()
console.log("firstname: ", _firstName)
console.log("middlename: ", _middleName)
console.log("lastname: ", _lastName)
CSS
Key Points:
cascading style sheet
means inheritance plays big part, style definition from .element
can cascade to .element.active
, element:hover
and so on.btnFirst,
.btnMiddle,
.btnLast {
background-color: grey;
color: green;
/* no need to set same css on every definition
* this will be also inherited to .btnFirst.active
* and so on
* */
outline: none;
}
.btnFirst.active,
.btnFirst:hover {
background-color: black;
color: white;
}
.btnMiddle.active,
.btnMiddle:hover {
background-color: white;
color: black;
}
.btnLast.active,
.btnLast:hover {
background-color: pink;
color: blue;
}
body {
font-family: Helvetica, Arial, Sans-Serif;
}