Vanilla JavaScript - Unbind - javascript

I have the following code which looks for a click event for all td elements:
[].forEach.call(document.querySelectorAll('td'), function(e) {
e.addEventListener('click', function(event) {
var clicked = [];
clicked.push(event.target.parentNode.getAttribute('data-a'));
clicked.push(event.target.getAttribute('data-b'));
this.callEvent(clicked, event.target);
}.bind(this));
}.bind(this));
Then I have a basic if else statement that checks the data attrs. It appears like the click function is staying bound as in the if statement I have logged to the console which condition is true.
After the very first run through, the true condition only runs, then if the next run through, the false runs, the true does also.. and then each time after, the conditions runs for each of the previous clicks.
What am I doing wrong? Do I need to somehow unbind the click function each time?

Related

How to prevents events from firing multiple time

For some reason I have to call the same function twice because of that my event are firing twice. How can I prevent this?
function renderSeats(movieImg, title, release_date, dummyPrice = '3000') {
// selected items
//this is only a part of the code .
contianer.addEventListener('click', function (e) {
if (
e.target.classList.contains('seat') &&
!e.target.classList.contains('unavailable')
) {
e.target.classList.toggle('selected');
payoutBtn.classList.add('active');
console.log('yes');
updateCountTotal(); //function call
}
contianer.setAttribute('listener', 'true');
});
const ticketOverlayClose = document.querySelector('.ticket__close-svg');
// overlay deactive
ticketOverlayClose.addEventListener('click', function (e) {
overlayseats.classList.add('hidden');
payoutBtn.classList.add('active');
ticketContainer.classList.remove('active');
});
}
Every time I am calling the function from another function because I have to update the dom, suppose 3 times the event then also fire 3 times
I also attached an image. In the console, you see after I clicking back (it is a single-page app) and again load by page calling our rendered seat function, and this time when I click on the seats the even is firing twice.
[gif][1]:https://i.stack.imgur.com/Ik1CG.gif

Click on button first time show alert, click second time execute code

I want to show users, when they click on a button for the first time, an alert when in a date field a value is chosen which lies before the current date. When they insist to this choice for good reasons, I want them to give a second chance to click on the same button, and then the value has to be submitted.
The click event is defined in a function:
$("#edit_date_btn").click(function(){
// do something and save
}
In an other function the comparing is handled. The basic code is:
function edit_date_compare() {
....
if(usersDate < today)
{ //show alert
return false; // needed for the first click so the input is not submitted
}
I've tried several options e.g. with a count on the click function (on a second click 'return true;' instead of 'return false;') but it seems difficult to handle this situation. Any ideas how to make this successful? It could be with Javascript or jQuery.
You have the right idea with the count on the click function. I suspect you might have difficulty implementing it. You need a separate variable that tracks the number of clicks. Here's a working fiddle: http://jsfiddle.net/zwmquxaL/
$(document).ready(function () {
var clickCount = 0;
$("#btnSave").click(function () {
if (clickCount > 0) {
AlertSave();
} else {
AlertFirst();
clickCount++;
}
});
});
function AlertSave() {
alert("Some code has been executed!");
}
function AlertFirst() {
alert("Are you sure you want to perform this operation?");
}

Toggled boolean variable evaluated in conditional statement on click event

I am toggling the boolean variable "userTurn". There are two functions that set the value of "userTurn":
runGame(), which sets "userTurn" to true after the last sound in the current round is played.
buttonClick(), which should only be executed if "userTurn" is true. buttonClick sets "userTurn" to false after the user successfully copies the current pattern, or if the user makes a mistake.
I am evaluating the value of "userTurn" in a conditional statement that is inside of a click event.
$(".quarter").on('click', function(){
if( userTurn===true && isOn===true){
var color = $(this).attr('id');
clearTimeout(buzz);
buttonClick(color);
}
})
After the user successfully copies the current pattern, or if the user makes a mistake, "userTurn" is set to false. The problem I am running into is, after "userTurn" is set to false, the code inside the conditional statement is still executing. The goal is for ".quarter" to only be clickable when "userTurn" is true. Why is the buttonClick() function still executing when ".quarter" is clicked even when "userTurn" is false??
Here are the two functions that set the value of "userTurn":
runGame():
function runGame(){
if(isOn===true){
userTurn = false;
count();
playPattern(order, index);
if(index===counter-1&&userTurn===false){
userTurn=true;
clearInterval(play);
buzz = setTimeout(buzzer, 10000);
}else{
index++;
}
} else {
clearInterval(play);
clearTimeout(buzz);
}
}
2.buttonClick():
function buttonClick(color){
var yellowSound = document.getElementById("horseSound");
var redSound = document.getElementById("endFx");
var greenSound = document.getElementById("westernRicochet");
var blueSound = document.getElementById("robotBlip");
$("#red").mousedown(function(){
$("#red").css("background-color", "#ff4d4d");
redSound.play();
});
$("#red").mouseup(function(){
$("#red").css("background-color", "#ff0000");
redSound.pause();
});
$("#blue").mousedown(function(){
$("#blue").css("background-color", "#0000e6");
blueSound.play();
});
$("#blue").mouseup(function(){
$("#blue").css("background-color", "#000099");
blueSound.pause();
});
$("#green").mousedown(function(){
$("#green").css("background-color", "#00e600");
greenSound.play();
});
$("#green").mouseup(function(){
$("#green").css("background-color", "#009900");
greenSound.pause();
});
$("#yellow").mousedown(function(){
$("#yellow").css("background-color", "#ffff4d");
yellowSound.play();
});
$("#yellow").mouseup(function(){
$("#yellow").css("background-color", "#ffff00");
yellowSound.pause();
});
if(color===order[compareIndex]){
userPattern.push(color);
console.log(userPattern, "match");
buzz = setTimeout(buzzer, 10000);
compareIndex++;
if(userPattern.length===counter){
userTurn=false;
compareIndex=0;
index=0;
counter++;
count();
userPattern.length=0;
play = setInterval(runGame, 2000);
clearTimeout(buzz);
}
} else {
userTurn=false;
console.log('don\'t match');
clearTimeout(buzz);
index=0;
compareIndex = 0;
userPattern.length=0;
buzz = setTimeout(buzzer, 1);
}
}
TURN DOWN YOUR VOLUME BEFORE GOING TO THE CODEPEN!!
Here is a link to the codepen.
To start the game click "On Off" and then click "start". The timing is slow so you have to wait for the pattern to play, then click the buttons in the same order as they were played. The problem is seen after the first sound is played. From that point on any click the user makes will play the sound and light up the button, even when the game is playing the pattern and "userTurn" is false. Also be warned, this is still a work in progress, there are a couple of other bugs I'm working on, for example the the first turn the user makes will not light up or play the sound, but the selection is pushed into the correct array and the game will proceed properly based on your selection. I know this is a lot of info but I'm stuck on this so any feed back will be very appreciated. Thanks!
You're using buttonClick to handle clicking the buttons, but inside buttonClick you're setting mouseup and mousedown event listeners for each button as well. Since the individual buttons have their own mouseup and mousedown listeners, the events will happen whether or not buttonClick is called again.
You would have to check if userTurn is true inside of each of those event handlers as well to prevent them from triggering. Also, it would better to set these outside of buttonClick so you won't be adding new listeners every time buttonClick gets called.

jQuery: Prevent bound js from running on click, then running it if condition is met

Sorry for the weird title, I couldn't think of a better way to word it.
The situation is: I have a link that is generated by a complex system (can't be changed), which fires a JS function when clicked.
Instead, when the link is clicked I want a modal box to appear asking the user if they are sure. If they choose yes then the original JS function will run. If not then the modal closes and nothing happens.
Is it possible to unbind, capture, and rebind the original function like this?
Pseudo-code would be as follows, hopefully it's possible:
$('a.link').click(function(){
// *** Capture original JS function bound to link ***
// *** var agree = Run new function (open modal box) ***
if(agree === true){
// *** Run original function ***
}else{
// *** Close modal box ***
}
});
I'm probably thinking about this the wrong way, if there is a better one please let me know!
Your event handlers are going to fire in the order they are attached. If you can insert yourself in the first position of the queue, then on the callback parameter you can call e.stopImmediatePropagation(). It will prevent other events from firing. Set a variable record the response, and trigger a click on the link again.
var check = null; //store user's response
$(".preventable").on("click", function(e) {
if(check == null) {
e.stopImmediatePropagation();
alert("hijacked")
check = true; //confirm here
if(check)
$('.preventable').click();
}
}
$(".preventable").on("click", function(e) { alert("clicked2"); })
jsfiddle

Is there any method to pause a function in the middle waiting for input in javascript?

I need to pause a JavaScript function execution in the middle and then resume it after a table cell is clicked. For example : I have to put 'A' into a one of the table cells. So, I have to click add() (add() is a function) and then wait for the user to click on the table cell to pass the cell id to function. I have thought of bind a click event to each cell to trigger the add() function. But then I have to do a delete function too. It is the same that I click on the delete button and then wait for the user to click on the table cell to pass the cell id to the function.
So how can I pause the function to wait for the input just like C++ : cin>>x which the program waits until user inputs the value of x.
Edited:
Finally I work it out. Every time when I click on the add button, I bind a addtd function to every td. And after I click on the cell, I unbind the addtd function. So that next time I click on the delete button, I can bind a deltd function on each cell.
I do not understand the problem completely. You cannot pause execution (without blocking the whole browser). You can only set up event listeners where you finish the work.
You can set up click event delegation to avoid binding click event listeners to each cell.
var textToAdd = 'A';
table.addEventListener('click', function (e) {
var td = e.target;
while (td !== this && td.tagName !== 'TD') { td = td.parentNode; }
if (td.tagName !== 'TD') return;
td.innerHTML += textToAdd;
});
There is no way to pause a function the way you describe. Have you thought about doing it the other way around? That is, when the user clicks a cell you can highlight it in some manner, and then Add and Delete buttons/functions will apply to the currently highlighted cell.
Alternatively you can do your add or delete "preprocessing" and then set some sort of flag to indicate that you're waiting for input, and then set an event handler for the cell click event that checks that flag to decide what processing comes next. So assuming you've setup your Add and Delete event handlers to call add() and delete(), and set your table cell click handler to call cellClick(), you could try something like this:
var clickCallback = null;
function add() {
// do your preprocessing here
clickCallback = function(clickedCell) {
// do further processing here
};
}
function delete() {
// do your delete preprocessing here
clickCallback = function(clickedCell) {
// do further processing here
};
}
function cellClick(e) {
e = e || window.event;
var clickedElement = e.srcElement || e.target;
if (clickCallback != null) {
clickCallback(clickedElement);
clickCallback = null;
}
}
After processing the click the callback is set back to null so that multiple clicks don't do anything. Obviously if some other action that the user takes should cancel the rest of the processing then just set the callback back to null then too.
Note that by defining the callback directly inside the add() and delete() functions they (the callbacks) will have access to local variables of add() and delete(), even though the callback isn't executed until later (the magic of closures).

Categories

Resources