Can I reversing these buttons easier on myself? - javascript

So, I'm wondering if i can make this any simpler (less repetition in the javascript) and whether or not I can make it so the title only turns black when hitting a button if it is that buttons color. If the second part of the question is possible it doesn't need to be simpler I'm just trying to figure out how to make the function target only tags with a specific attribute (style). Is this possible?
I'm new to coding I've been trying to figure this out for a few hours and can't find something already uploaded... possibly due to my lack of being able to condense the question.
<!DOCTYPE html>
<html>
<head>
<title>
Flood
</title>
<link rel="stylesheet" href="Style.css">
<style>
h1 {
text-align: center;
padding-left: 30%;
padding-right: 30%;
width: 40%;
}
p {
font-size: 14pt
}
</style>
</head>
<body>
<section class="mainpage">
<h1 id="FS"> Fun Stuff </h1>
<div>
<button id="Red"> Red</button>
<button id="Blue"> Blue</button>
<button id="Yellow"> Yellow</button>
<button id="Blink"> Blink</button>
</div>
<div id="explaination">
<p>Click the buttons at the top to see what I mean.
</p>
</div>
</section>
<script>
const a = document.getElementById("FS");
const b = document.getElementById("Red");
const c = document.getElementById("Blue");
const d = document.getElementById("Yellow");
const e = document.getElementById("Blink");
/*reset Functions*/
function blackFunctionB() {
a.style.color = "black";
b.removeEventListener("click", blackFunctionB,);
b.addEventListener("click", redFunction,);
}
function blackFunctionC() {
a.style.color = "black";
c.removeEventListener("click", blackFunctionC,);
c.addEventListener("click", blueFunction,);
}
function blackFunctionD() {
a.style.color = "black";
d.removeEventListener("click", blackFunctionD,);
d.addEventListener("click", yellowFunction,);
}
function showFunction() {
a.style.display = "block";
e.removeEventListener("click", showFunction,);
e.addEventListener("click", blinkFunction,)
}
/*end reset functions*/
b.addEventListener("click", redFunction,);
function redFunction() {
a.style.color = "Red";
b.removeEventListener("click", redFunction,);
b.addEventListener("click", blackFunctionB,);
}
c.addEventListener("click", blueFunction,);
function blueFunction() {
a.style.color = "Blue";
c.removeEventListener("click", blueFunction,);
c.addEventListener("click", blackFunctionC,);
}
d.addEventListener("click", yellowFunction,);
function yellowFunction() {
a.style.color = "Yellow";
d.removeEventListener("click", yellowFunction,);
d.addEventListener("click", blackFunctionD,);
}
e.addEventListener("click", blinkFunction,);
function blinkFunction() {
a.style.display = "none"
e.removeEventListener("click", blinkFunction,);
e.addEventListener("click", showFunction,);
}
</script>
</body>
So basically when you click on the yellow button it makes the block turn yellow, then if you hit the blue button it makes it blue, but if you hit the yellow button again it makes it black. Alternatively, when you hit the yellow then blue twice then yellow again it stays black. Is there a way to make it only turn black if you hit the yellow button when it is already yellow?

You could make one function that is more generic and can handle all the cases you have:
function toggleCss(elem, attrib, value) {
elem.style[attrib] = elem.style[attrib] === value ? "" : value;
}
const fs = document.getElementById("FS");
for (let color of ["red", "blue", "yellow"]) {
const button = document.getElementById(color);
button.addEventListener("click", () => toggleCss(fs, "color", color));
}
const button = document.getElementById("blink");
button.addEventListener("click", () => toggleCss(fs, "visibility", "hidden"));
<section class="mainpage">
<h1 id="FS"> Fun Stuff </h1>
<div>
<button id="red"> Red </button>
<button id="blue"> Blue </button>
<button id="yellow"> Yellow </button>
<button id="blink"> Blink </button>
</div>
<div id="explanation">
<p>Click the buttons at the top to see what I mean.</p>
</div>
</section>
You could even make it more generic by defining data attributes on the buttons which indicate which CSS property needs to toggle:
function toggleCss(elem, attrib, value) {
elem.style[attrib] = elem.style[attrib] === value ? "" : value;
}
const fs = document.getElementById("FS");
for (const button of document.querySelectorAll("button[data-attr]")) {
button.addEventListener("click", () =>
toggleCss(fs, button.dataset.attr, button.dataset.value)
);
}
<section class="mainpage">
<h1 id="FS"> Fun Stuff </h1>
<div>
<button data-attr="color" data-value="red">Red</button>
<button data-attr="color" data-value="blue">Blue</button>
<button data-attr="color" data-value="yellow">Yellow</button>
<button data-attr="visibility" data-value="hidden">Blink</button>
</div>
<div id="explanation">
<p>Click the buttons at the top to see what I mean.</p>
</div>
</section>

You are over complicating things. Simply check and toggle the black and 2nd color.
You don't have to register/de-register events again and again.
function yellowFunction() {
var clr = a.style.color;
if(clr.toLowerCase() === 'yellow')
a.style.color = "black";
else
a.style.color = "Yellow";
}

Related

Changing class of button and display of div with JavaScript

I have JavaScript to show/hide div on click. Inside that div are more buttons to show/hide PNGs.
I want the clicked button to have a bottom border line until another button in that div is clicked.
I have achieved this but each time I click on a button in the shown div the bottom border line stays on the button when I click the next button.
I've spent hours trying to fix this. please help
let wildCard = document.querySelectorAll(".element-select-container button");
for (let button of wildCard) {
button.addEventListener('click', (e) => {
const et = e.target;
const active = document.querySelector(".active");
let redline = (".redline");
if (active) {
active.classList.remove("redline");
active.classList.remove("active");
}
et.classList.add("active");
et.classList.add("redline");
let allContent = document.querySelectorAll('.button-wrapper');
for (let content of allContent) {
if(content.getAttribute('data-e') === button.getAttribute('data-e')) {
content.style.display = "block";
}
else {
content.style.display = "none";
}
}
});
}
HTML
<div class="element-select-container">
<button id="but81" class="but81 redline" data-e="81" type="button" name="">Doors</button>
<button id="but82" class="but82" data-e="82" type="button" name="">Windows</button>
<button id="but83" class="but83" data-e="83" type="button" name="">Facia</button>
<button id="but84" class="but84" data-e="84" type="button" name="">Guttering</button>
<button id="but85" class="but85" data-e="85" type="button" name="">Garage</button>
<button id="but86" class="but86" data-e="86" type="button" name="">Steps</button>
</div>
CSS
.redline {
border-bottom: 2px solid red;
}
The issue is, on first load, the first button is redline but not active - so, when you press a different button, the code to remove redline from active doesn't find active so redline isn't removed
simple fix
const active = document.querySelector(".active,.redline");
As follows
let wildCard = document.querySelectorAll(".element-select-container button");
for (let button of wildCard) {
button.addEventListener('click', (e) => {
const et = e.target;
const active = document.querySelector(".active,.redline");
if (active) {
active.classList.remove("redline");
active.classList.remove("active");
}
et.classList.add("active");
et.classList.add("redline");
let allContent = document.querySelectorAll('.button-wrapper');
for (let content of allContent) {
if(content.getAttribute('data-e') === button.getAttribute('data-e')) {
content.style.display = "block";
}
else {
content.style.display = "none";
}
}
});
}
.redline {
border-bottom: 2px solid red;
}
<div class="element-select-container">
<button id="but81" class="but81 redline" data-e="81" type="button" name="">Doors</button>
<button id="but82" class="but82" data-e="82" type="button" name="">Windows</button>
<button id="but83" class="but83" data-e="83" type="button" name="">Facia</button>
<button id="but84" class="but84" data-e="84" type="button" name="">Guttering</button>
<button id="but85" class="but85" data-e="85" type="button" name="">Garage</button>
<button id="but86" class="but86" data-e="86" type="button" name="">Steps</button>
</div>

button toggle display show hide

I want to show-hide the display of these layers with a button click. I can't figure out how to do it with 2 buttons, and 2 divs...
Html:
<div id="first">This is the FIRST div</div>
<div id="second">This is the SECOND div</div>
<button id="toggle">Show first div and hide second div</button>
<button id="toggletoo">Show second div and hide first div</button>
Css:
#first {
display: none;
}
#second {
display: none;
}
Js:
const targetDiv = document.getElementById("first");
const btn = document.getElementById("toggle");
btn.onclick = function () {
if (targetDiv.style.display !== "none") {
targetDiv.style.display = "block";
} else {
targetDiv.style.display = "none";
}
}
https://codepen.io/MaaikeNij/pen/YzrgbQw
Try with the following code:
#first{
display: block; /* <--- change */
}
#second {
display: none;
}
const firstDiv = document.getElementById("first");
const secondDiv = document.getElementById("second");
document.getElementById("toggle").onclick = function () {
if (firstDiv.style.display === "none") {
firstDiv.style.display = "block";
secondDiv.style.display = "none";
} else {
firstDiv.style.display = "none";
secondDiv.style.display = "block";
}
}
There's lots of ways to do this. One common way I've seen in various templates is to add and remove classes. Another way is to call the function from the button's onclick attribute. But my favorite is to write a function that requires no editing of the div HTML because I don't want to interfere with the HTML guy's work, I just want to put functioning code in there. (BTW, I am positive there is a more elegant way to write this, but here ya go!)
const firstDiv = document.querySelector("#first");
const secondDiv = document.querySelector("#second");
const firstButt = document.querySelector("#toggle");
const secondButt = document.querySelector("#toggletoo");
firstButt.addEventListener("click",toggleDivShowHide);
secondButt.addEventListener("click",toggleDivShowHide);
function toggleDivShowHide() {
if (firstDiv.style.display !== "none") {
firstDiv.style.display = "none";
secondDiv.style.display = "block";
} else {
firstDiv.style.display = "block";
secondDiv.style.display = "none";
}
}
You're saying "if the first div is set to none, then set it to block and set the second div to none. Otherwise, do the opposite."
I tried something different, this is working :)))
<div id="first" style="display:none;"> This is the FIRST div</div>
<div id="second" style="display:none;"> This is the SECONDdiv</div>
<input type="button" name="answer" value="Show first div and hide second div" onclick="showDivOne()" />
<input type="button" name="answer" value="Show second div and hide first div" onclick="showDivTwo()" />
function showDivOne() {
document.getElementById('first').style.display = "block";
document.getElementById('second').style.display = "none";
}
function showDivTwo() {
document.getElementById('second').style.display = "block";
document.getElementById('first').style.display = "none";
}
https://codepen.io/MaaikeNij/pen/vYeMGyN
Correction: you should add event Listener for both toggle & toggletoo.
Solution: solution with reusable code.
const Toggles = document.querySelectorAll('.toggle');
const Hides = document.querySelectorAll('.hide');
Toggles.forEach((el) => {
el.addEventListener("click", (e) => {
Hides.forEach((el) => {
el.parentElement.firstElementChild.classList.add('hide');
});
e.target.parentElement.firstElementChild.classList.toggle('hide');
});
})
.hide {
display: none;
}
<div>
<div class="hide">This is the FIRST div</div>
<button class="toggle">Show first div and hide first div</button>
</div>
<div>
<div class="hide">This is the SECOND div</div>
<button class="toggle">Show second div and hide first div</button>
</div>
<div>
<div class="hide">This is the Third div</div>
<button class="toggle">Show Third div and hide first div</button>
</div>
<div>
<div class="hide">This is the Fourth div</div>
<button class="toggle">Show Fourth div and hide first div</button>
</div>
For precisely such cases, javascript has the toggle function. I rewrite your code a little bit.
const btns = document.querySelectorAll(".toggleBtn");
btns.forEach(b => {
b.onclick = function (e) {
reset();
console.log(e.target.getAttribute('data-target'))
const target = e.target.getAttribute('data-target');
const t = document.querySelector('#' + target);
t.classList.toggle('hide');
}
});
function reset() {
const divs = document.querySelectorAll('.out');
divs.forEach(d => d.classList.add('hide'))
}
.hide {
display: none;
}
<div id="first" class="out hide">This is the FIRST div</div>
<div id="second" class="out hide">This is the SECOND div</div>
<button class="toggleBtn" data-target="first">Show first div and hide second div</button>
<button class="toggleBtn" data-target="second">Show second div and hide first div</button>

How to change the innerHTML of various divs when clicking on various buttons?

In my web-page I have various buttons (in the class .addbutton). When the first of these is clicked, a <div> appears with a drop-down, from which the user can select any of 2 options (#p1, `#p2), which vary depending on which button was clicked.
When each of these options is clicked, I want it to appear in the <div> that corresponds with the initial .addbutton that was clicked. (e.g if the first .addbutton is clicked (#bradd) I want the options selected in the first div (#bdiv))I managed to do this so that they always appear in the #bdiv, no matter what .addbutton was clicked, but I can't work out how to make each appear in the corresponding one.
JS to set the innerHTML of the 2 options
document.getElementById("bradd").onclick = function() {
document.getElementById("p1").innerHTML = "Cereal"
document.getElementById("p2").innerHTML = "Juice"
}
document.getElementById("mmadd").onclick = function() {
document.getElementById("p1").innerHTML = "2x small fruit"
document.getElementById("p2").innerHTML = "Big fruit"
}
JS to change the innerHTML of the first div (#bdiv)
document.getElementById("p1").onclick = function() {
var newItem = document.createElement("div")
newItem.innerHTML = document.getElementById("p1").innerHTML document.getElementById("bdiv").appendChild(newItem)
}
document.getElementById("p2").onclick = function() {
var newItem = document.createElement("div")
newItem.innerHTML = document.getElementById("p2").innerHTML
document.getElementById("bdiv").appendChild(newItem)
}
My HTML:
<h1>Meal Plan Customizer</h1>
<div id="list">
<input type="checkbox">
<p>Breakfast:</p>
<button class="addbutton" id="bradd">+</button>
<div id="bdiv"></div>
<br>
<input type="checkbox">
<p>Mid-Morning:</p>
<button class="addbutton" id="mmadd">+</button>
<div id="mdiv"></div>
<br>
<input type="checkbox">
<div id="dropdownList">
<p id="p1">Option1</p><br><br>
<p id="p2">Option2</p><br><br>
</div>
</div>
</div>
Your code should work.
Please check this:
https://jsfiddle.net/oliverdev/3wsfgov1/
If your code is not working, it is because Javascript code is loaded before loading the HTML.
You can modify the Javascript code like this:
window.onload = function(e){
document.getElementById("bradd").onclick = function() {
document.getElementById("p1").innerHTML = "Cereal"
document.getElementById("p2").innerHTML = "Juice"
}
document.getElementById("mmadd").onclick = function() {
document.getElementById("p1").innerHTML = "2x small fruit"
document.getElementById("p2").innerHTML = "Big fruit"
}
}
It will work for you
You are making this far more complicated and repetitive than necessary.
By storing your data in a structured object and using classes for the content elements you can make generic event listeners for all of this
Following is by no means complete but will give you a good idea how to approach something like this
var data = {
bradd: {
p1: "Cereal",
p2: "Juice"
},
mmadd: {
p1: "2x small fruit",
p2: "Big fruit"
}
}
var selectedButton = null;
var opts = document.querySelectorAll('#dropdownList p');
for (let p of opts) {
p.addEventListener('click', updateContent)
}
// generic event handler for all the options
function updateContent() {
const content = selectedButton.closest('.item').querySelector('.content')
content.innerHTML = this.innerHTML
togglePopup()
}
document.querySelector('#xbutton').addEventListener('click', togglePopup)
// generic event handler for all buttons
function addButtonClicked() {
selectedButton = this;// store selected for use when option selected
var wantedData = data[selectedButton.id];
for (let p of opts) {
p.innerHTML = wantedData[p.id]
}
togglePopup();
}
for (let btn of document.getElementsByClassName("addbutton")) {
btn.addEventListener("click", addButtonClicked)
}
function togglePopup() {
var popStyle = document.getElementById("addPopUp").style;
popStyle.display = popStyle.display === "block" ? 'none' : 'block'
}
#addPopUp {
display: none
}
<h1>Meal Plan Customizer</h1>
<div id="list">
<div class="item">
<p>Breakfast:</p>
<button class="addbutton" id="bradd">+</button>
<div class="content"></div>
</div>
<div class="item">
<p>Mid-Morning:</p>
<button class="addbutton" id="mmadd">+</button>
<div class="content"></div>
</div>
</div>
<div id="addPopUp">
<h3 id="h3">Select what you would like to add:</h3>
<span id="xbutton"><strong>×</strong></span>
<div class="dropdown">
<div id="dropdownList">
<p id="p1">Option1</p>
<p id="p2">Option2</p>
<!-- <p id="p3">Option3</p><br><br>
<p id="p4">Option4</p>-->
</div>
</div>
</div>

How to create an event button

I am currently working on a project. Basically, there is a big grid square and inside of it, there are lots of little squares. When users move their mouse over these little squares they turn into black. However, I want to create a clear button that turns the color of these squares into their original color. I have a code but it doesn't work. I can turn their color into black but I cannot create an event button which clears everything.
Alter the code, tried different methods.
//set values
let tiles = document.getElementsByClassName('newDiv');
let buttons = document.getElementsById('clearbutton');
//make squares black using mouseover event
if(black){
for (const tile of tiles) {
tile.addEventListener('mouseover', e => {
tile.style.backgroundColor = "black";
});
}
}
//turn squares background-color into their original color
for (const cbutton of clearbutton) {
button.addEventListener('click', e => {
tiles.style.backgroundColor = "#eee";
});
}
<nav id="navbar">
<ul>
<li><button id = "clearbutton" type="button" style= "width: 200px; height; 150px; background-color: #99CCFF;">Clear</button></li>
</ul>
</nav>
<div id="container">
</div>
getElementById is not a function.
Use the code below
let tiles = document.getElementsByClassName('newDiv');
let clearbutton = document.getElementById('clearbutton');
if (black) {
for (const tile of tiles) {
tile.addEventListener('mouseover', e => {
tile.style.backgroundColor = "black";
});
}
}
clearbutton.addEventListener('click', e => {
for (const tile of tiles) {
tile.style.backgroundColor = "#eee";
}
});
Here is a full working example
var black = true;
let tiles = document.getElementsByClassName('newDiv');
let clearbutton = document.getElementById('clearbutton');
if (black) {
for (const tile of tiles) {
tile.addEventListener('mouseover', e => {
tile.style.backgroundColor = "black";
});
}
}
clearbutton.addEventListener('click', e => {
for (const tile of tiles) {
tile.style.backgroundColor = "#eee";
}
});
.newDiv {
width: 100px;
height: 100px;
display: inline-block;
background: #eeeeee;
}
<button id="clearbutton">Clear All</button>
<div id="container">
<div class="newDiv"></div>
<div class="newDiv"></div>
<div class="newDiv"></div>
<div class="newDiv"></div>
<div class="newDiv"></div>
<div class="newDiv"></div>
<div class="newDiv"></div>
</div>

Javascript if and else runs simultaneously

I want a link to select by onclick, when the link is clicked so selected, the background should change. When I click the selected link again then the background should be transparent again.
My Script:
<div style="background: transparent;" onclick="click()" id="0">
HTML:
Click
function click() {
var click = document.getElementById("0");
if(click.style.background == "transparent") {
click.style.background = "red";
}
else {
click.style.background = "transparent";
}
}
As far as I understand, you simply want a toggle. Functional code as follows.
2 important notes:
ID must not be zero (or it breaks): I replaced it by 10;
don't use click() as it's a reserved name: I replaced it by toggle().
Not much change to your code apart from the above.
Cheers.
Update to handle multiple divs: I now pass the object:
<html>
<body>
<div style="background: red;" onclick="toggle(this)" id="10">
CLICK ON 10 TO TOGGLE MY BACKGROUND COLOR
</div>
<div style="background: red;" onclick="toggle(this)" id="20">
CLICK ON 20 TO TOGGLE MY BACKGROUND COLOR
</div>
<script>
function toggle(o) {
if(o.style.background == "transparent") {
o.style.background = "red";
alert("red on "+o.id);
}
else {
o.style.background = "transparent";
alert("transparent on "+o.id);
}
}
</script>
</body>
</html>
Two things here, don't call the function click, and use the backgroundColor property, not background as background is a compound property expecting more values than just the color, so comparing it to just a color (i.e. = 'transparent") may not work
so
HTML:
<div style="background-color: transparent;" onclick="notclick()" id="0">
Javascript
function notclick() {
var click = document.getElementById("0");
if(click.style.backgroundColor == "transparent") {
click.style.backgroundColor = "red";
}
else {
click.style.backgroundColor = "transparent";
}
}
EDIT
to handle mutliple div
every div that you want the behaviour, should be like this (i.e. with the onclick(this))
<div style="background-color: transparent;" onclick="notclick(this)" id="0">
<div style="background-color: transparent;" onclick="notclick(this)" id="1">
<div style="background-color: transparent;" onclick="notclick(this)" id="2">
and the javascript should be
function notclick(ele) {
if(ele.style.backgroundColor == "transparent") {
ele.style.backgroundColor = "red";
}
else {
ele.style.backgroundColor = "transparent";
}
}
or better still
function notclick(ele) {
ele.style.backgroundColor = (ele.style.backgroundColor == "transparent" ? "red" :"transparent");
}
The problem is the method name click, inside the onclick handler it refers to the internal click method - fiddle - here click is a native method, not our method
Rename it and it should be fine - you need to use backgroundColor
<button onclick="testme()">Test</button>
then
function testme() {
var click = document.getElementById("0");
if (click.style.background == "red") {
click.style.background = "transparent";
} else {
click.style.background = "red";
}
}
Demo: Fiddle

Categories