adding multiple event listeners to one element
Maybe you can use a helper function like this:
// events and args should be of type Array
function addMultipleListeners(element,events,handler,useCapture,args){
if (!(events instanceof Array)){
throw 'addMultipleListeners: '+
'please supply an array of eventstrings '+
'(like ["click","mouseover"])';
}
//create a wrapper to be able to use additional arguments
var handlerFn = function(e){
handler.apply(this, args && args instanceof Array ? args : []);
}
for (var i=0;i<events.length;i+=1){
element.addEventListener(events[i],handlerFn,useCapture);
}
}
function handler(e) {
// do things
};
// usage
addMultipleListeners(
document.getElementById('first'),
['touchstart','click'],
handler,
false);
[Edit nov. 2020] This answer is pretty old. The way I solve this nowadays is by using an actions
object where handlers are specified per event type, a data-attribute
for an element to indicate which action should be executed on it and one generic document wide handler method (so event delegation).
const firstElemHandler = (elem, evt) =>
elem.textContent = `You ${evt.type === "click" ? "clicked" : "touched"}!`;
const actions = {
click: {
firstElemHandler,
},
touchstart: {
firstElemHandler,
},
mouseover: {
firstElemHandler: elem => elem.textContent = "Now ... click me!",
outerHandling: elem => {
console.clear();
console.log(`Hi from outerHandling, handle time ${
new Date().toLocaleTimeString()}`);
},
}
};
Object.keys(actions).forEach(key => document.addEventListener(key, handle));
function handle(evt) {
const origin = evt.target.closest("[data-action]");
return origin &&
actions[evt.type] &&
actions[evt.type][origin.dataset.action] &&
actions[evt.type][origin.dataset.action](origin, evt) ||
true;
}
[data-action]:hover {
cursor: pointer;
}
<div data-action="outerHandling">
<div id="first" data-action="firstElemHandler">
<b>Hover, click or tap</b>
</div>
this is handled too (on mouse over)
</div>
how can I set up multiple listeners for one event?
class CompositeListener implements OnEventListener {
private List<OnEventListener> registeredListeners = new ArrayList<OnEventListener>();
public void registerListener (OnEventListener listener) {
registeredListeners.add(listener);
}
public void onEvent(Event e) {
for(OnEventListener listener:registeredListeners) {
listener.onEvent(e);
}
}
}
.....
CompositeListener composite = new CompositeListener();
composite.registerListener(listener1);
composite.registerListener(listener2);
component.setOnEventListener(composite);
How does multiple listeners for the same window events affect performance?
In Javascript you have an event loop. The mechanism consists of a loop, which represents the plan to call certain functions in a given order. However, user event, such as click or resize cannot be planned before it happens. As a result, there is also a message queue (also called callback queue), where your events are waiting to be executed.
When the event queue runs out of functions to be executed, the message queue's items start to be processed. At this point your events will be processed.
Basically we are talking of a forever loop where you put some functions. Of course it affects performance, because everything to be done affects the performance versus the case when it is not done. However, this in most cases does not mean a meaningful difference in any way that could be felt.
If we assume that the functions you associate with these events is of very low (maybe constant) complexity, then we still have a linear complexity due to the event loop and you would have to add MANY events to this loop to have any performance difference that could be felt.
However, if the functions that you add are very complex, that will significantly decrease performance and note, Javascript is (mostly) single-threaded. So, if you experience performance issues, then you need to check the complexity of your functions first.
It is worth noting that your event handlers will only be executed when the given event is triggered, probably by the user. So, if you add a million of resize handlers, by themselves they will not affect performance (except at the time when they are added, but that's insignificant), but when a resize happens, all your event handlers attached to this event will be executed.
So, if you experience performance issues at a given event, then you will need to analyze the event handlers associated to that event. If your event handlers are too many or too complex, then you can use web workers (which are running in separate threads) to execute the more time-consuming jobs, so your UI will remain responsive in terms of handling events.
EDIT
This is how one can test the two scenarios. In this code we will assume that event
is a String
variable, which can be a click, a key event or anything.
Measurement functionality
var count = 1000; //you can change this value whenever you need
var startDate;
var endDate;
var diff;
function happened() {
if (!startDate) startDate = performance.now();
if (!(--count)) {
endDate = performance.now();
diff = endDate - startDate; //in milliseconds
console.log(diff);
}
}
Many Listeners
for (var i = 0; i < count; i++) window.addEventListener("resize", function() {happened()});
61 milliseconds in my test (event was "resize" in my case)
Single listener
window.addEventListener("resize", function() {
while (count > 0) happened();
});
55 milliseconds in my test (event was "resize" in my case)
Adding multiple event listeners in javascript to element
Javascript is a language where functions are "first-class objects". This means, possibly contrary to other programming languages that you may have experience in, that you can treat a function like any other object: you can pass it around, you can return it, you can have a function with a function inside it with a function inside it, and so on.
The consequence of this may be a very unexpected programming style required to be successful in Javascript. In other languages, UI event binding occurs in a variety of ways (such as C#'s Button1.Click += new System.EventHandler(this.myEventHandler);
, or Classic VB's Button_Click()
). In C#, you can pass around delegates, which are special objects with a specifically defined set of parameters and return values, to which a function can be bound. But all that disappears in javascript because you can simply attach a function to a property directly. For browser DOM event handling, the property is assumed to be a function reference, and during the native event handling code for that event, it calls the function attached to the property with the same name as the event.
Okay, you say, we have functions. And we can pass them around and treat them just like variables. Now what?
First, please take special note that the following two functions declarations are identical. They yield the exact same result, of declaring a function named myfun
in the current scope (in a browser, the window
object or the current function that is running).
function myfun(param1, param2) {
//do some stuff
};
var myfun = function (param1, param2) {
//do some stuff
};
(Actually, the first one will end up with a name
property that the second one won't, and possibly some other minor differences, but for all practical intents and purposes they are identical).
The first one is just a shortcut for the second one. Basically, you create a function (that may or may not have a name) and assign it to a variable. Programmers use the convenient shortcut of calling the result "the myfun
function", but in reality the case is "the myfun
variable--which contains a particular function right now".
You can get many references to the same function--which is a true object--just by assigning it to other variables:
function myfun(param1, param2) {
//do some stuff
};
var a = myfun, b = myfun, c = myfun;
a(); // runs `myfun`
b(); // runs `myfun`
c(); // runs `myfun`
The next thing to notice is that to invoke a function, you must use parentheses after its name, and any parameters go inside the parentheses.
var result = myfun('a', 1); // invoke the `myfun` function
// and store its return value in variable `result`
But take a look back at our assignment statement making a
, b
, and c
all be aliases of the myfun
function: in those cases we didn't use parentheses, because--and here is where it gets really important, so pay attention:
To invoke a function (and get the function's return value), use parentheses after its name.
To pass a function reference, do not use parentheses.
What if we had done this instead:
var a = myfun(), b = myfun(), c = myfun();
a
, b
, and c
would no longer be pointers to the myfun
function. They would all be the result of myfun
and would contain whatever myfun
returned--or undefined
if it didn't return anything. If you tried to invoke one of these, say a()
you would get some error similar to:
> TypeError: a is not a function
Now that I've painted all that background, there is one simple thing to know that will get you on track to being successful with addEventListener
: it expects a function as the second parameter. In your example code, you've put the contents of functions you'd like to run when addEventListener calls them, but no actual functions.
You can solve that by actually declaring the functions first, such as:
function doNothing() {
return false;
}
titles.addEventListener('dragenter', doNothing);
// Note: this is not invocation like `doNothing()`, but passing a reference
Or, you can simply wrap your function statements into an anonymous function. Remember, functions in javascript don't actually have names, we just have variables that contain functions. An anonymous function is one that has no name at all, and it is invoked either by an implicit name assignment (such as being passed as a parameter--where it will have the parameter's name) or by being directly invoked by doing the magic invocation action of putting parentheses after it.
That would look something like this:
titles.addEventListener('dragenter', function () { // anonymous function
return false;
});
If you want to invoke an anonymous function, you do have to let javascript know you want to treat it like a value as opposed to the normal shortcut-method of creating a named function in the current scope (where function myfun
is treated like var myfun = function
). That is done by wrapping the entire thing in one more set of parentheses, like this:
(function () { // begin a function value containing an anonymous function
// do something
}()); //invoke it, and close the function value
I hope this helps you understand more about javascript, why your code was not working, and what you need to do to make it work.
CreateEvent multiple listeners
This probably happens because CreateEvent uses the same name for all thread instances. That way all threads use the same event. As the event is created with automatic reset, the first thread getting the event will reset it and the others aren't noticed anymore.
From the docs:
If this parameter is FALSE, the function creates an auto-reset event
object, and system automatically resets the event state to nonsignaled
after a single waiting thread has been released.
Related Topics
Sqlite Query in Android to Count Rows
Saving Arraylists in SQLite Databases
How to Make Layouts for Several Android Screen Sizes
Android - Loop Part of the Code Every 5 Seconds
How to Handle Basic Authentication in Webview
Uploading Image from Android to Gcs
Stop Fragment Refresh in Bottom Nav Using Navhost
Dagger 2 Injecting Android Application Context
Dependency Ignored Because of Conflict Android Studio
Clear Application Cache on Exit in Android
Gcm Push Notification with ASP.NET
Capturing Images with Mediastore.Action_Image_Capture Intent in Android
Android:Load Svg File from Web and Show It on Image View
Error: Mapfragment Cannot Be Cast to Android.Support.V4.App.Fragment
How to Check the Internet Connection Periodically in Whole Application