Can someone explain the program flow of this JavaScript code:
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a);
console.log("check");
a++;
$leaveRoom.click();
console.log(a);
a++;
});
<button id="leave-button">Leave Room</button>
The Output was:
1
check
2
check
3
4
This question may sound dumb but I am new to JavaScript. I am not able to understand the program flow of this code. I want to know how did I get 3 & 4 in the output.
If you just need to trigger a click event, you can omit the line that begins with for( . @Parag: Read it again. The loop is to click the same link 50 times, which is what it does.
The removeEventListener() is an inbuilt function in JavaScript which removes an event handler from an element for a attached event. for example, if a button is disabled after one click you can use removeEventListener() to remove a click event listener.
If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded.
You can add many event handlers to one element. You can add many event handlers of the same type to one element, i.e two "click" events. You can add event listeners to any DOM object not only HTML elements. i.e the window object.
The key to this question is the presence of a hidden Flag on each
element.click()
method.Each element has an associated click in progress flag, which is initially unset.
the doc: https://html.spec.whatwg.org/multipage/interaction.html#dom-click
As soon as this method is activated, this flag changes from progess Status == unset
to progess Status == active
(pseudo code)
(then it returns to its initial status once the code it contains is fully executed)
When this flag is in the active
state, then any call to this method is ignored.
const bt_leaveRoom = document.querySelector('#leave-button')
var counter = 0
var origin = 'event clic'
bt_leaveRoom.addEventListener('click', () =>
{
let source = origin
console.log(`_first console.log(): counter = ${ ++counter }, origin = ${source}`)
origin = 'call'
bt_leaveRoom.click()
console.log(`second console.log(): counter = ${ ++counter }, origin = ${source}`)
})
<button id="leave-button">Leave Room</button>
the Hidden Flag act like in the same way if I have coded this way :
replace this line:bt_leaveRoom.click()
to:if (source !== 'call') bt_leaveRoom.click()
But in fact the system use the method hidden flag (named progress flag
?)
which can be (in pseudo code)
if (progress_flag_of_bt_leaveRoom.click() is unset) do { bt_leaveRoom.click() }
I tried a couple of things to find an answer to this question. I haven't really found a definitive answer to what's going on here, but I do believe that what I share here feeds into this excellent problem.
I simplified the code to focus on the recursive triggering of events.
Simplified Code
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
$leaveRoom.click();
});
<button id="leave-button">Leave Room</button>
We can see here that we have two calls for console.log
, the first one is for the actual clicking of the button, and the second one is for the call to $leaveRoom.click();
. It seems to stop there for some reason.
Using dispatchEvent
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
$leaveRoom.dispatchEvent(new Event('click'));
});
<button id="leave-button">Leave Room</button>
Here, the event is triggered multiple times (44 for me), this could be due to how fast your machine is. It seems to stop triggering eventually though, so I'm thinking the same phenomenon is happening here as well.
Using setTimeout
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
setTimeout(() => { $leaveRoom.click(); });
});
<button id="leave-button">Leave Room</button>
If you are looking for a way to infinitely trigger the click event, regardless of why the previous methods fail. This does seem to do the trick.
Having said all this, I still have no clue about this hidden force that stops the recursion for the previous methods. Maybe someone could shed some light on this.
const click1 = document.querySelector('#click1')
const click2 = document.querySelector('#click2')
const click3 = document.querySelector('#click3')
click1.addEventListener('click', (event) => {
console.log("click1")
click2.click()
});
click2.addEventListener('click', (event) => {
console.log("click2")
click3.click()
});
click3.addEventListener('click', (event) => {
console.log("click3")
click1.click()
});
<button id="click1">Click 1</button>
<button id="click2">Click 2</button>
<button id="click3">Click 3</button>
Actually it appears there is loop breaking logic in the event handling. The handlers will happily daisy chain user input events until the initial interaction dispatches a duplicate event. Then it will no longer dispatch any.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With