Reputation: 43
Scenario: Using jQuery multiple binds are done for a specific event. When event is triggered specified function should fire once PER trigger.
Challenge: The way jQuery trigger works is that when trigger is called the associated function is fired same number of times as number of binds that event has. On EACH trigger the function should be fired only once. How can this be achieved. "one" does not work in the scenario because the function should be fired each time the event is triggered.
Thanks in advance.
UPDATE: Apologize for not being more specific.
The requirement is that when page loads, different elements on the page to register so when a custom event occurs they will participate in it.
When the the custom event is triggered/raised, a function is to be called that will perform some task on the all the registered elements.
Eg. Please note, the elements embedded from different Partial Views (MVC).
<html>
<a href="#" id="triggerelement">Trigger element</a>
<div id="element1" data-join="aevent">something 1</div>
<div id="element2" data-join="aevent">something 2</div>
<div id="element3" data-join="aevent">something 3</div>
<div id="element4" data-join="aevent">something 4</div>
</html>
Two issues I am running into:
What element to "bind" to - $(?).bind. Reason: Multiple elements can raise this custom event and elements raising the event would/should not be known. One thought was - $(document).bind/$(document).trigger. Is this is the best approach?
Using jQuery when $().trigger is called how can I ensure that it invokes the associated function only once per call rather than for each element bound to that event.
Upvotes: 2
Views: 19890
Reputation: 2491
If you’re using jQuery, there’s a little-known one() event binding method which implements one-time events.
$("#myelement").one( "click", function() { alert("You'll only see this once!"); } );
Self-Removing Handlers
If you’re using raw JavaScript, any handler function can remove itself using a single line of code:
document.getElementById("myelement").addEventListener("click", handler);
// handler function
function handler(e) {
// remove this handler
e.target.removeEventListener(e.type, arguments.callee);
alert("You'll only see this once!");
}
Presuming your handler event argument is named ‘e’, the line:
e.target.removeEventListener(e.type, arguments.callee);
will remove the handler the first time it’s invoked. It doesn’t matter what event type or name you use for your handler — it may even be an in-line anonymous function.
Note I’ve used standard event calls which won’t work in IE8 and below. OldIE’s require a call to detachEvent and the type requires an “on” prefix, e.g. “onclick”. But, if you’re supporting oldIE’s, you’re probably using jQuery or your own custom event handler.
Self-removing handlers may be the best option if you require some flexibility, e.g. you only want to unhook certain event types or remove the handler after different conditions, e.g. two or more clicks.
A One-Time Event Creation Function
you may be too lazy or forgetful to add an event removal line to every handler function. Let’s create a onetime function which does the hard work for us:
// create a one-time event
function onetime(node, type, callback) {
// create event
node.addEventListener(type, function(e) {
// remove event
e.target.removeEventListener(e.type, arguments.callee);
// call handler
return callback(e);
});
}
We can now use this function whenever we require a one-time only event:
// one-time event
onetime(document.getElementById("myelement"), "click", handler);
// handler function
function handler(e) {
alert("You'll only see this once!");
}
While you won’t require one-time events in every page, it’s good to find there are several options available to JavaScript developers.
Upvotes: 4
Reputation: 12730
I haven't a clue if this is what you're thinking of, but here's something to give you ideas of what's possible. You can easily maintain and control your own callstack. This will add three functions to the callstack and when you click on the pop link, it'll execute whatever's on the top of the stack.
var callstack = [];
function popcallstack(e)
{
e.preventDefault();
return callstack.pop()();
}
//bind once
$('#foo').click(popcallstack);
callstack.push(function() { alert('executed1') });
callstack.push(function() { alert('executed2') });
callstack.push(function() { alert('executed3') });
Perhaps this will give you the control you're after. Oh, and you should know that jQuery will basically do this sort of thing for you, this is merely demonstrative if you're trying to do something wonky and you need to "take control" as it were.
Upvotes: 1
Reputation: 47099
have you tried to use namespaces when binding your functions?
$('a').bind("click.name1", function() {
alert("name1");
});
$('a').bind("click.name2", function() {
alert("name2");
$("a").unbind("click.name1");
});
Upvotes: 4