How Javascript control events - javascript

Let's say I have a simple code using onmouseover event
<div onmousemove="myMoveFunction()">
<p id="demo">I will demonstrate onmousemove!</p>
</div>
(from w3school)
I want to ask that, how does Javascript know mouse is on that div? Or when we use onclick, how does Js know button has been clicked. Is there automatic event listeners? or Is there any cycle controlling changes for events continually in the background?
Please help me I'm confused.
Any links to read would be okay too

A browser is responsible for gathering events as they appear on the page. When there's an event listener added for a given action, the listener's callback is added to the event loop. Event loop is an infinite loop that constantly checks if there's something to do (in a cpu optimized manner). On event loop there are two main tasks:
rendering the page if there's a change in DOM or CSSOM
executing callbacks when some specific action happens
It is important to know that javascript is single threaded, meaning if there's a long running callback, the browser won't be able to rerender the page so the page just freezes.
Another way to understand what's happening under the hood is to open chrome dev tools and go to performance panel. You can find there exactly what happens when you interact with the page:
There are a few ways to add an event listener:
in html using on[eventname]=action, i.e. <div onmousemove="myMoveFunction()">
in javascript by assigning a function to on[eventname] property, i.e. windows.onload = () => alert("hello");
in javascript by using addEventListener() method, i.e. element.addEventListener("click", () => alert("hello"));
If you want to know more about event loop, here are good resources:
Philip Roberts: What the heck is the event loop anyway?
Jake Archibald on ‘The Event Loop’ (more advanced)
There's also pretty good and free course that explains a lot about how browser works and most importantly shows you how to improve site's performance:
Browser Rendering Optimization

When you use e.g. <div onmousemove="myMoveFunction()">, as the browser reads the DOM on page load, behind the scenes it generates code for the event listener and there is not much else to it.

Related

Why is a DOM click event taking so long?

Clicking my button is taking >2s, before my code is reached (the code in the actual button handler runs in ~10ms).
It's bound as follows:
$('#my-div').find('.my-button').on('click', function(){ ... })
No other mouse event handlers are bound to this element or its parents or children.
There are a lot of these buttons, about a thousand on the page. I'm guessing that has something to do with it, but I still don't understand why it's quite so slow. Is there anything I can do?
You have a thousand buttons on your page, when a few dozen should be more than enough for most users. This is an accessibility problem for most users.
Your page is around 1.6MBs. The bigger a page gets, the slower the browser can render and manipulate it. Most programmers think that a page is slow because of javascript, actually 99% of the time the reason the page is slow is because the browser has to render and manipulate the html in the page. This is especially true for older versions of Internet Explorer.
You should set only one event handler, instead of setting up a thousand event handlers (which will have to be individually compiled by the browser)...
like so:
$('#my-div').on('click', '.my-button', function(){ ... })

Event Listeners Efficiency

How do event listeners in any programming language actually work internally?
The point of this post is to get an overall idea of how event listeners in general work. A while back, when I first started playing with Javascript and Html, every time I needed to create a button to perform an action, lets say execute function 'my_func();', I would simply go...
<button onclick="my_func();">Click me</button>
That is just wonderful, a button, staying idle for the majority of the time, except when clicked. Then, it would execute the corresponding function.
Then I came across Event Listeners. Basically, an event listener is a procedure or function in a computer program that waits for an event to occur.
The first thing that came into my mind was the following: When you create an event listener, does that basically just create an infinite loop that checks whether something has been triggered or not? Isn't this inefficient if you have dozens or hundreds of events to listen for? Hundreds of loops checking for a different specific condition every second? Why would you use this instead of the beautiful 'onclick'?
I will proceed to post the answers that I found, (not in StackOverflow, that's why I decided to post it here, so as to enlarge the already vast content of this site). This answer, of all the ones I read, was the one that convinced me the most. However, if you know something that you think would add to the topic, feel free to share your knowledge (the more the better).
The core question was the following: Isn't this inefficient if you have dozens or hundreds of events to listen for?
And the truth is, if that was the case, it would be really inefficient. That is why it doesn't work that way.
The program (in the case of Java), or browser (in the case of Javascript), receives events from the operating system every time something happens — when the mouse is moved, when a key is pressed, when the window is resized, when a timer event expires, and so on. For each of those events, the browser needs to figure out if an event handler needs to be dispatched. For example, on a mouse left button down event, it needs to take the coordinates of the mouse and figure out what elements are underneath it, and then check if there are any event listeners registered for those events, and if so add them to the event queue to be executed the next time the engine becomes free.
Once again, feel free to add information, or correct me if you think there is something wrong or somehow inaccurate.
There's very little difference between running an event handler from onclick and from addEventListener. In both cases, it simply attaches the handler to the DOM element in question. The only significant difference between them is that you can only have one onclick attribute, but every time you call addEventListener() it adds to the list of listeners on that element -- internally there's an array of listeners that addEventListener() pushes onto.
But the way these event handlers are processed is essentially the same. When a click event is sent to an element, the browser looks up its onclick attribute and list of click listeners, and executes all of them. There's no difference in efficiency between them. The only infinite loop is the browser's main event loop, which is processing all events that are received from the OS, finding the appropriate DOM elements, seeing if they have handlers for that event, and calling the handlers.
As what others have said, internally there is no difference between the two. But using the addEventListener() method you can easily attach multiple functions on a single event rather than going through concatenations when you have lots of scripts.
with addEventListener()
Script 1
myEle.addEventLister('click', myFunc);
Script 2
myEle.addEventLister('click', myFunc2);
You see how easy it is to attach functions on an element's event.
using setAttribute()
Script 1
myEle.setAttribute('onclick', myFunc);
Script 2
myEle.setAttribute('onclick', myEle.getAttribute('onclick') + myFunc2);
The extra code is a bit of a hassle
For practical purposes, there is no difference between the 'onclick' and the 'EventListener' attributes. All in all, that's just what they are, attributes that you add or remove from a specific object. As a consequences, since they are attributes, not mere methods, they do not loop themselves, but instead serve as parameters for the "general event loop" that constantly occur in your window. Hence the lack of difference in efficiency.
However, if you have a ton of event listeners, or onclick attributes on a ton of different objects, it may reduce the overall execution speed, as the general loop has to go through more elements to check, for a specific occurred event, if there is anything listening to it; but this happens indistinctelly of how you address your events (with a listener, onclick attributes, etc.)
So, I will conclude by saying that there is no practical difference in the way these event handlers are processed. When a particular event is sent to an element, the browser looks up on its attributes and/or list of listeners related to that particular event, and executes each one of them. There's no difference in efficiency between them. The only infinite loop is the "general window loop" or the main event loop, which is processes all the events that happen, and looks for the appropriate object to check for any handlers related to that event, and should any be found, it calls the function attached to them.

Detect if an Input has Changed dynamically

Other javascript is changing the value of an input and I was wondering if there was a way to detect the change.
This question has nothing to do with Keyup or Change. This is not being typed in by the user it is being changed by other javascript though various actions of the user.
When changing an event programatically, you can trigger a change event to make sure event handlers that are attached to the element are fired. jQuery has a trigger() method to do this:
$('#elementID').on('change', function() {
alert( this.value );
});
$('#elementID').val('some new value').trigger('change');
The quick run-down of what I am going to say is: there is no way other than to modify the third-party scripts to output stuff, or to use setInterval (costly).
The bottom line of this issue is a simple one, that does not appear to be so at first: How can you get your scrips to communicate with each other?
When a script modifies the value of an input through JS methods (i.e. not user input), they have to go through specific hoops to get the "change" event to fire (they can fire it manually by calling it, which most devs never do and is easily forgotten when writing code). In practice, people tend to rely on the observation events (user-defined ones) to track code changes. This is very similar to DOM events - you bind callbacks to your script, which allow you to tap callbacks in that will fire whenever your scripts do something interesting (like modifying inputs. This is just one example). You then teach your scripts and developers to fire events on useful stuff using the callbacks to notify other scripts.
A great library for this is Postal, which is originally a Node library. jQuery also has an event system you can tap into. However, if you want to roll your own, all you have to read into is the Observer design pattern. It is trivial: you bind a function to your object to pick up callbacks, and another to fire them. Whenever you change the thing, you fire the callback. Simples.
Failure to do so means setInterval. Sucks, but there you go :-(

How to pause javascript execution during rollover?

I'm looking for a way to capture HTML of objects that are rendered on rollover. An example would be:
Mouse over object to get popup
Press button or key to pause js (to prevent mouse out trigger)
Right click and inspect element to get HTML
Does anyone know of a way to do this?
To your main question, there are two ways to pause the execution of a Javascript thread:
Hit a breakpoint in a debugger
Insert an alert() into the javascript thread and when it fires, it will suspend the execution of that javascript thread until the alert dialog is dismissed.
You haven't described the environment you're operating in and what types of modifications you can or can't make to the host page for us to advise more specifically.
To approach the problem differently, to capture some dynamically inserted HTML there are other strategies. For example, you can use your own javascript (like a bookmarklet) to attach an event handler to the mouse over. You can then set a timer that will watch for when the dynamically generated HTML seems to be present and grab a copy of it. Keep in mind that javascript is single threaded so your own timer will only run when the other javascript thread is waiting for user input, but if the general model is that it pops something up on mouseover and then waits for additional mouse events, then this could work.
yes, <object onmouseover="functionPopup();" onmouseout="functionWrap();">
then place your onkeyup-event to detect the button/key.
The trick is to leave the functionWrap on the object ALONE!!! and OVERWRITE this function functionWrap() (that is referenced by object's onmouseout) with the updated instructions (this works pretty good crossbrowser -even older ones-, since this uses the traditional event model :P ).
Happy tweaking!!

How to identify the next running javascript statement or function entry point?

In many website pages, there are a lot of javascript codes to support the functionalities. The programmer can attach the event on the element via many methods. They can add the event directly in the element definition like
<input type="button" onclick="dosomething();">
or they can do this by javascript codes like:
<script>
document.getElementById('ele').onclick = function(){};
</script>
And usually there are so many codes here so that it's sometimes difficult for us to identify which event function are called after the element event is triggered.
So my question is: is there any method or plug-in can help to identify the next running javascript statement or function entry point after one element event is triggered?
One thing you could do is, define a function that will grasp all events assigned to each type of elements and show them somewhere on the page(preferably at the bottom). To trigger that, function you may add a button which should be clicked.
Of course, all this must be done in debugging state and you would certainly want to remove the button and the display panel when releasing the App.
We used to do this for our project, may not be elegant but it does serve the purpose.
There's no code that "emulates" the debugging of plugins like Firebug - however in case of "simple" onclick function simple alert will just show it:
var element = document.getElementById('ele');
alert(element.onclick);
And to programmatically trigger it:
element.onclick();

Categories