How do you create a button that toggles between to events?
This is the code I've tried
function button (text, callback) {
var but = document.createElement('BUTTON');
var t = document.createTextNode(text);
but.appendChild(t);
var clicks = 0;
but.onclick = function () {
clicks += 1;
if (clicks % 2 !== 0) {
but.addEventListener('click', callback);
} else {
but.removeEventListener("click", callback);
}
}
As James Thorpe suggests in comments this could be done without turning on/off event listeners.
You could just use your existing click event like so:
but.onclick = function () {
clicks += 1;
if (clicks % 2 !== 0) {
callback();
}
}
Related
You have 3 buttons. On of them, randomly chosen, is a winner. Display if the winning button has been clicked or not. Bonus: Generate n buttons, from which one of them is winner.
My code so far:
let n = 3, buton
for (let i = 0; i < n; ++i) {
buton = document.createElement("button")
document.querySelector("body").appendChild(buton)
buton.id = i
buton.innerText = i
}
let winningButton = 1 // Math.floor(Math.random() * n)
let onClick = function() {
if (winningButton == buton.id) {
alert("Congratulations! You've guessed the button!")
}
}
buton.addEventListener("click", onClick)
Can you help me solve this problem?
In the onClick function, you are not checking against the clicked button, you can use the this keyword to access the button in the event handler
let onClick = function() {
if (winningButton == this.id) {
alert("Congratulations! You've guessed the button!")
}
}
If you use arrow functions this will not be work, so instead, you can use the event object to get the target element
let onClick = (event) => {
if (winningButton == event.target.id) {
alert("Congratulations! You've guessed the button!")
}
}
You can generate a random number when the user clicks.
let n = 3;
let winningButton;
const onClick = function() {
winningButton = winningButton ? winningButton : Math.floor(Math.random() * n);
if (winningButton == this.id) {
alert("Congratulations! You've guessed the button!")
}
}
for (let i = 0; i < n; ++i) {
const buton = document.createElement("button")
document.querySelector("body").appendChild(buton)
buton.id = i
buton.innerText = i;
buton.addEventListener("click", onClick);
}
I've been having issues where when I try to remove an event from the buttons it seems to only be removing the event for the one-button even though I have looped through the buttons and removed the event.
thank you.
function ChangeQuestions() {
let currentQuestion = getQuestion(); //another function to get the question from an array - returns an object with questions, answers and correctAnswer
const correctAnswer = currentQuestion.correct;
console.log(currentQuestion);
if (questionsArray.length === 0) {
//If the array is empty push the questions again
questionsArray.push(firstQuestion, secondQuestion, thirdQuestion);
}
document.querySelector('.question-header').textContent = currentQuestion.questions;
for (let i = 1; i < 4; i++) {
document.querySelector('.btn-Ans-' + i).textContent = currentQuestion.answers[i - 1];
document.querySelector('.btn-Ans-' + i).addEventListener('click', function checkAns(e) {
if (e.target.innerHTML === correctAnswer) {
score++;
console.log(score);
removeEvent('click', checkAns);
ChangeQuestions();
} else {
console.log(score);
removeEvent('click', checkAns);
ChangeQuestions();
}
});
}
}
function removeEvent(event, func) {
for (let i = 1; i < 4; i++) {
document.querySelector('.btn-Ans-' + i).removeEventListener(event, func);
}
}
With
for (let i = 1; i < 4; i++) {
document.querySelector('.btn-Ans-' + i).addEventListener('click', function checkAns(e) {
A new checkAns function is created inside every iteration of the loop, and removeEventListener must be passed the exact same function that addEventListener was called with. Since the different loop iterations have different functions passed into their respective addEventListener calls, the removeEvent function appears to only affect the element that was clicked, and none of the rest.
Here's a more minimal example:
const fns = [];
for (let i = 0; i < 2; i++) {
const foo = () => console.log('foo');
fns.push(foo);
window.addEventListener('click', foo);
}
// Not the same function:
console.log(fns[0] === fns[1]);
I'd add just a single listener to the container instead, and use event delegation to check which element was clicked on:
btnContainer.addEventListener('click', function handler(e) {
if (!e.target.matches('[class^="btn-Ans"]')) {
return;
}
btnContainer.removeEventListener('click', handler);
if (e.target.innerHTML === correctAnswer) {
score++;
}
console.log(score);
ChangeQuestions();
});
where btnContainer is a container for your btn-Ans-s.
I tried to count an element clicks, and, in the right number call some action.
var count = 0;
document.getElementById("rolarbaixo").onClick = function(e) {
if( count >= 3 ) {
var elem = document.getElementById("noticia");
elem.setAttribute("style","top: 0px;");
}
else {
count ++;
}
};
When i clicked 3 times in the link "rolarbaixo" the div "noticia" set the "top: 0px;", but this doesn't work.
Why?
count ++ should be count++. If you press F12, you will be able to get to the developer tools and debug the javascript.
It's onclick in lowercase
var count = 0;
document.getElementById("rolarbaixo").onclick = function (e) {
if (count >= 2) {
var elem = document.getElementById("noticia");
elem.style.top = "0px";
} else {
count++;
}
};
FIDDLE
And it's >= 2 for three clicks (zero based and all).
AS the question is tagged jQuery, this would be it
$('#rolarbaixo').on('click', function() {
var clicked = $(this).data('clicked') || 0;
if (clicked >= 2) $('#noticia').css('top', 0);
$(this).data('clicked', ++clicked);
});
FIDDLE
Misprint in else statement and change onclick to lowercase:
var count = 0;
document.getElementById("rolarbaixo").onclick = function(e) {
if( count >= 3 ) {
var elem = document.getElementById("noticia");
elem.setAttribute("style","top: 0px;");
} else {
count++;
}
};
I am trying to use Javascript to disable a button after it is clicked x amount of times. For simplicity sake lets say x = 2 for now. I cannot seem to get the counter to increment. Thank You for any help!
var $ = function (id) {
return document.getElementById(id);
}
window.onload = function () {
coke.onclick = function(){
var count =0;
if (count >= 1)
{
coke.disabled = true;
}
else
count++;
};
}
Where "coke" is the element ID. If i get rid of the if statement and just have coke.disabled = true, of course it works and disables after one click. I'm sure there is a core concept I am missing.
Thank You
This is happening because each time the onclick event is fired, your var count is being assigned to 0, so it will never be greater than or equal to one in your function. If you initialize the count var outside of the onclick function, it will behave as expected.
window.onload = function () {
var count = 0;
coke.onclick = function(){
if (count >= 1)
{
coke.disabled = true;
}
else
count++;
};
}
You need to define count outside the scope of your onclick function:
var $ = function (id) {
return document.getElementById(id);
}
var count = 0; // set initial count to 0
window.onload = function () {
coke.onclick = function(){
if (count >= 1)
{
coke.disabled = true;
}
else
count++;
};
}
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);
}
});