JavaScript button doesn't work on second click - javascript

I want to make a program changing background color of a div after clicking on a button.
After first click it should change one color to the second one. After second click the color should come back to the first option. And for the last time, the color should be switched again to the second option. So it should work for 3 times. But in my code it works just for the first click.
What did I do wrong?
var btn = document.getElementById('button');
var box = document.getElementById('sq');
function changeColor() {
var isPink = true;
var colorA = "#BA498B";
var colorB = "#5964E3";
var i = 0;
while (i < 3) {
if (isPink) {
change(colorB);
isPink = false;
i++;
} else {
change(colorA);
isPink = true;
i++;
}
}
}
function change(color) {
btn.addEventListener('click', function () {
box.style.backgroundColor = color;
});
}
window.onload = changeColor;

You're adding a new, identical event handler every time there's a click. Instead just add it once when the page loads, so that the redundant handlers don't cancel each other out.
var isPink = true;
function changeColor() {
var colorA = "#BA498B";
var colorB = "#5964E3";
if (isPink) {
change(colorB);
} else {
change(colorA);
}
isPink = !isPink;
}
function change(color) {
document.getElementById('sq').style.backgroundColor = color;
}
window.onload = function() {
document.getElementById('button').addEventListener('click', changeColor);
};
#sq {
width: 100px;
height: 100px;
position: relative;
}
<button id=button>CLICK</button>
<div id=sq></div>
Don't know what you wanted with the loop though, so I removed it. It runs immediately, and so you'd never see such a rapid color change.

try this:
var isPink = true;
var color = "#BA498B"
function changeColor() {
var colorA = "#BA498B";
var colorB = "#5964E3";
if (isPink) {
color = (colorB);
isPink = false;
} else {
color = (colorA);
isPink = true;
}
}
window.onload = function(){
var btn = document.getElementById('button');
var box = document.getElementById('sq');
btn.addEventListener('click', function () {
changeColor();
box.style.backgroundColor = color;
});
};
This way I'm only using 'addEventListener' on the button once

Here is an example which may help you:
var btn = document.getElementById('button');
var box = document.getElementById('sq');
var isPink = true;
function changeColor() {
var colorA = "#BA498B";
var colorB = "#5964E3";
var color=isPink?colorA:colorB;
isPink=isPink?false:true;
return color;
}
function change() {
box.style.backgroundColor = changeColor();
}
btn.addEventListener('click', change);
window.onload = change();
<h1 id="sq">Test Text for Example</h1>
<button id="button">Click</button>

Related

How to use local storage on append child

<button id="showlinks" onclick="myFunction">show</button>
<div id="buttonlinks"></div>
function myFunction() {
var button = document.createElement("button");
document.getElementById("buttonlinks").appendChild(button);
}
I used This Code to create buttons on clicking a button. when clicking the show button the buttons appear but after refresh they are gone.
can I store the buttons with localStorage?
You can store the information about your buttons in the localStorage whenever you create a button, and add an eventListener to window.onload to read the buttons from localStorage and append it to the page when page has loaded, in the below exmpale to keep it simple, I just store the length of buttons.
<button id="showlinks" onclick="myFunction">show</button> <div id="buttonlinks"></div>
js:
let buttonsLength = 0;
document.getElementById('showlinks').addEventListener('click', function () {
createButton();
buttonsLength++;
localStorage.setItem('buttonsLength', buttonsLength)
});
function createButton() {
var button = document.createElement('button');
button.innerHTML = 'click me';
document.getElementById('buttonlinks').appendChild(button);
}
window.addEventListener('load', (event) => {
buttonsLength = Number(localStorage.getItem('buttonsLength')) || 0;
for (let i = 0; i < buttonsLength; i++) {
createButton();
}
});
const showlinks = document.getElementById('showlinks')
showlinks.addEventListener("click", function () {
localStorage.setItem("showClicked", true)
displayButtonInDom()
})
function displayButtonInDom() {
const showClicked = localStorage.getItem("showClicked")
if (showClicked) {
const button = document.createElement("button");
button.innerText = "click me"
document.getElementById("buttonlinks").appendChild(button);
}
}
displayButtonInDom()
<button id="showlinks">show</button>
<div id="buttonlinks"></div>
Foreache button created you have to add the button information to the localstorage. And on page load you execute an init function that rebuild all button created from the localstorage
<button id="showlinks" onclick="createButton('')">show</button>
<div id="buttonlinks"></div>
<script>
function Initbutton() {
//on load check if the button has been already add using the localStorage
var buttons = getButtonInformationFromLocalStorage();
if(buttons != null){
buttons.forEach(function(btnName){
createButton(btnName);
})
}
}
// fo the purpose of having different button name
// i have picket this function here https://www.codegrepper.com/code-examples/javascript/find+random+name+javascript
function getRandomString(length) {
var randomChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var result = '';
for ( var i = 0; i < length; i++ ) {
result += randomChars.charAt(Math.floor(Math.random() * randomChars.length));
}
return result;
}
function createButton(btnName){
if(btnName == undefined || btnName == ""){
btnName = "button" + getRandomString(10);
updateButtonInformationToLocalStorage(btnName);
}
var button = document.createElement("button");
button.innerHTML = btnName;
document.getElementById("buttonlinks").appendChild(button);
}
function updateButtonInformationToLocalStorage(name){
var lstrg = localStorage.getItem("alreadyaddbuttontobuttonlinks");
if(lstrg == null){
localStorage.setItem("alreadyaddbuttontobuttonlinks", name);
return name;
}else{
var nLstrg = lstrg + "|" + name;
localStorage.setItem("alreadyaddbuttontobuttonlinks", nLstrg);
return nLstrg;
}
}
function getButtonInformationFromLocalStorage(){
var lstrg = localStorage.getItem("alreadyaddbuttontobuttonlinks");
if(lstrg == null){
return null;
}else{
return lstrg.split("|");
}
}
window.onload = Initbutton();
</script>

how to change the color of the letters to white only when clicked

how to change the colour of the letters to white only when clicked and then changes to the beginning when it is no longer clicked.
I am really thank you for your help.
var drum = document.querySelectorAll("button"),
i;
for (i = 0; i <= drum.length; ++i) {
var drumi = drum[i];
var drummy = drumi.addEventListener("click", function() {
this.style.color = "white";
});
}
Just using CSS:
button:active {
color: white;
}
<button>Test</button>
I would suggest to use 2 different events
onmousedown for when the user click on the element
onmouseup for when the user release the mouse button
The suggested code would look like something like this:
var drum = document.querySelectorAll("button"),
i;
for (i = 0; i <= drum.length; ++i) {
var drumi = drum[i];
drumi.addEventListener("onmousedown", function() {
this.style.color = "white";
});
drumi.addEventListener("onmouseup", function() {
this.style.color = "black"; // put the original color here
});
}
When the button is clicked, the text turns white, then black. Is this what you wanted?
JS
let clicked = true
let turnWhite = (button) => {
clicked = !clicked
clicked ? button.style.color = "white" : button.style.color = "black"
}
HTML
<button onclick="turnWhite(this)">click</button>
I think Peter Collingridge has the best answer. But if you want to do it in js you could do it like this.
<button onmousedown="turn(this,'blue')" onmouseup="turn(this, 'red')" style="color:red">hello</button>
<script>
function turn(element, color) {
element.style.color = color;
}
</script>

Can a javascript function apply to all elements of a certain CSS class?

I have a nav bar where each button changes the background of the body. They each change it to a different color. I have created onmouseover and onmouseout functions for each button to achieve this. However, I wonder if there is a way to just write one of each function by just referring to them by their class? They all have the same class of button. Is there a way a function can apply to all elements of a certain class? My code:
function whichButton(x) {
if (x==1)
return "red";
if (x==2)
return "green";
if (x==3)
return "blue";
if (x==4)
return "orange";
if (x==0)
return initBG;
}
button1.onmouseover = function() {
document.body.style.backgroundColor = whichButton(1);
}
button1.onmouseout = function() {
document.body.style.backgroundColor = whichButton(0);
}
button2.onmouseover = function() {
document.body.style.backgroundColor = whichButton(2);
}
button2.onmouseout = function() {
document.body.style.backgroundColor = whichButton(0);
}
button3.onmouseover = function() {
document.body.style.backgroundColor = whichButton(3);
}
button3.onmouseout = function() {
document.body.style.backgroundColor = whichButton(0);
}
button4.onmouseover = function() {
document.body.style.backgroundColor = whichButton(4);
}
button4.onmouseout = function() {
document.body.style.backgroundColor = whichButton(0);
}
initBG just saves the initial background of the page.
I have tried this:
document.getElementsByClassName('button').onmouseover = function() {
document.body.style.backgroundColor = whichButton(1);
}
but it doesn't trigger the function. And I guess to do this, I'd also need to have a way to read the elements' ID as a string so I could get it's number...
This is more out of curiosity than necessity, just trying to find ways to keep my code small! I could see this being useful in many applications so I'd love to learn more about this!
Corresponding HTML:
<div id="navbar">
<p id="button1" class="button">Red</p><p id="button2" class="button">Blue</p><p id="button3" class="button">Green</p><p id="button4" class="button">Orange</p>
</div>
Here is my suggestion to solve it:
Use the data attribute and iterate over all elements with the given class.
function applyColor(element) {
var color = element.getAttribute('data-bg');
document.body.style.backgroundColor = color;
}
var buttons = document.getElementsByClassName("button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("mouseover", function() {
applyColor(this);
}, false);
}
<nav>
<button class="button" data-bg="red">red</button>
<button class="button" data-bg="blue">blue</button>
<button class="button" data-bg="yellow">yellow</button>
<button class="button" data-bg="green">green</button>
<button class="button" data-bg="pink">pink</button>
<button class="button" data-bg="magenta">magenta</button>
</nav>
As previously stated, getElementsByClassName returns a collection and you can't just add the event to the collection in a way that you can in jQuery. To do this is pure JS, you need to use a for loop and then attach the event to each individual element as below:
var buttons = document.getElementsByClassName('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].onmouseover = function (event) {
var colour = event.target.className.split(" ")[1];
document.body.style.backgroundColor = colour;
}
}
http://jsfiddle.net/andyfurniss/1n5vann9/
getElementsByClassName returns a collection. So you will have to loop over it and you shall be good.
var buttons = document.getElementsByClassName('button');
[].forEach.call(buttons, function (button){
var id = parseInt(button.id.split("").reverse().join("")); //This will give you the number from the id
button.onmouseover = = function() {
document.body.style.backgroundColor = whichButton(id);
}
button.onmouseout = function() {
document.body.style.backgroundColor = whichButton(0);
}
});
To ensure ES6 compatibility, there is much better way.
var buttons = document.getElementsByClassName("button");
for (button of buttons) {
var id = parseInt(button.id.split("").reverse().join("")); //This will give you the number from the id
button.onmouseover = = function() {
document.body.style.backgroundColor = whichButton(id);
}
button.onmouseout = function() {
document.body.style.backgroundColor = whichButton(0);
}
}
The first comment actually solved it for me. I did this:
document.onmouseover = function() {
var x = event.target;
y = x.id.toString().replace('button','');
if (y > 0 && y <= 4)
document.body.style.backgroundColor = whichButton(y);
}
document.onmouseout = function() {
var x = event.target;
y = x.id.toString().replace('button','');
if (y > 0 && y <= 4)
document.body.style.backgroundColor = whichButton(0);
}
If I mouse over a "button", it removes the word "button", leaving the number (1-4), then sends that to my whichButton function to decice which colour to use. Nice and simple, works for me.
You can use event delegation, which means attaching an event listener to an ancestor, then inspecting the event.target to decide what to do.
Demo: http://jsfiddle.net/a58tj1ak/
// given your HTML and whichButton function like this:
function whichButton(x) {
var initBG = '#fff';
if (x==1)
return "red";
if (x==2)
return "green";
if (x==3)
return "blue";
if (x==4)
return "orange";
if (x==0)
return initBG;
}
// get the buttons into an array
var buttons = [].slice.call(document.getElementsByClassName('button'));
// add event listener to the #navbar element
document.getElementById('navbar').addEventListener('mouseover', function(e){
// target is an element being hovered
var target = e.target;
// check if the target is in the array of buttons
var index = buttons.indexOf( e.target );
if( index > -1 ){
document.body.style.backgroundColor = whichButton(index + 1)
}
else {
document.body.style.backgroundColor = whichButton(0);
}
});

buttons added to table won't fire handler

In my table, I'm trying to include an Edit button at the end of each row. The idea is for the user to click one of these to alter the row's content. I can build and populate the table just fine, but I cannot get the buttons to fire off their handler.
Here's a code snippet:
window.onload = function (){
// a bunch of stuff happens correctly...
while (!Rs.EOF)
{
var oRow = oTicketsTable.insertRow();
for (j=0; j < field.length; j++)
{
var oCell = oRow.insertCell();
oCell.style.fontSize = "10";
oCell.style.fontWeight = "normal";
oCell.style.border = "thin black solid";
oCell.innerText = Rs(field[j]);
}
var oCell = oRow.insertCell();
oCell.style.border = "thin black solid";
var oBtn = document.createElement("button");
oCell.appendChild(oBtn);
oBtn.innerHTML = Rs('idnum');
oBtn.onClick = function () { alert("oBtn.onClick"); }
Rs.MoveNext();
}
Rs.Close ();
delete Rs;
var btn = document.createElement("button");
btn.style.height = "50px";
btn.style.width = "150px";
document.body.appendChild(btn);
btn.innerHTML="button1";
btn.onclick = function() { alert("button1 calling");
}
The code at the end creates a test button which fires off just fine. But none of the buttons in the table work.
The onclick function in the table is camel case: try changing it to lower case? Change obtn.onClick to obtn.onclick.
oBtn.onclick = function () { alert("oBtn.onClick"); }
Try:
oBtn.onclick = function () { alert("oBtn.onClick"); }
Rs.MoveNext();
}
Instead of:
oBtn.onClick = function () { alert("oBtn.onClick"); }
Rs.MoveNext();
}
capitalized 'C', should be just 'c'
If I not mistaken, you should place your event outside, as global.
var oBtn,btn;
window.onload = function (){
// other code
// other code
oBtn = document.createElement("button");
oBtn.innerHTML = Rs('idnum');
btn = document.createElement("button");
btn.style.height = "50px";
btn.style.width = "150px";
document.body.appendChild(btn);
btn.innerHTML="button1";
}
// make your event global
oBtn.onClick = function () { alert("oBtn.onClick"); }
btn.onclick = function() { alert("button1 calling"); }
.onClick is an old practice. But I think it would just prompt you a warning, not an error.

Register a click except on a certain element

I have a javasccript function that shows or hides "spans" when I click an input to show hints when a user fills out forms:
function prepareInputsForHints() {
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){
// test to see if the hint span exists first
if (inputs[i].parentNode.getElementsByTagName("span")[0]) {
// the span exists! on focus, show the hint
inputs[i].onfocus = function () {
this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
}
// when the cursor moves away from the field, hide the hint
inputs[i].onblur = function () {
this.parentNode.getElementsByTagName("span")[0].style.display = "none";
}
}
}
}
My problem is that when I try to add a link to the hints text, the user cannot click it because it registers first with the onblur event and the hint dissapears, so I would like to know how to modify this function so that it does not hide when I click the hint.
You can use a boolean var to test if the user is with mouse over your hint, then if onblur and not mouseOver you hide your hint.
Something like this inside your loop:
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){
(function(i) {
// Let the code cleaner :)
var span = inputs[i].nextElementSibling;
span.onmouseover = function() { this.isOver = true; }
span.onmouseout = function() { this.isOver = false; if(!inputs[i].isFocus) inputs[i].onblur(); }
// the span exists! on focus, show the hint
inputs[i].onfocus = function () {
this.isFocus = true;
span.style.display = "inline";
}
// when the cursor moves away from the field, hide the hint
inputs[i].onblur = function () {
this.isFocus = false;
if(!span.isOver) span.style.display = "none";
}
})(i);
}
I put a self executing function just to keep the var i scope, you don't have troubles onmouseout function.
EDIT: Updated the example
Your code for get the next span will not work, so I changed to nextElementSibling, because the example you put in the jsfiddler.
This is the new working code:
$(function(prepareInputsForHints) {
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){
(function(i) {
// Let the code cleane
var span = inputs[i].nextElementSibling;
if(span instanceof HTMLSpanElement) {
if(span.className == "hint") {
span.onmouseover = function() { this.isOver = true; }
span.onmouseout = function() { this.isOver = false; if(!inputs[i].isFocus) inputs[i].onblur(); }
// the span exists! on focus, show the hint
inputs[i].onfocus = function () {
this.isFocus = true;
span.style.display = "inline";
}
// when the cursor moves away from the field, hide the hint
inputs[i].onblur = function () {
this.isFocus = false;
if(!span.isOver) span.style.display = "none";
}
}
}
})(i);
}
});

Categories