Why do custom events need to be dispatched to an object? - javascript

I see that I can dispatch a custom event to an object.
I'm wondering why a custom event needs to be dispatched to an object at all.
I want to trigger an event at a set interval, and after reading documentation on custom events, I still haven't figured out how to trigger them with functions. How is it done?
For example, I want to use setInterval() to trigger my custom event 'nextTime' every 30 seconds.

dispatching events is the same as triggering them, and as they are custom events, they would never be naturally triggered by anything, so you have to trigger them yourself. To trigger an event from an interval just dispatch the event inside the interval.
The reason you need an object is because it's an event handler, if it wasn't attach to an element, you wouldn't really need an event handler, you could just use regular functions instead.
var event = new Event('custom'),
elem = document.getElementById('test');
elem.addEventListener('custom', function (e) {
console.log('custom triggered');
}, false);
setInterval(function() {
elem.dispatchEvent(event);
}, 30000);
FIDDLE

Related

How to trigger only one event 'change' or 'click'

I have a number input tag on which I have two event listeners 'on-click' and 'on-change'. When I am click on arrow it triggers both. I would like to have one whichever triggers first without removing any of the event listeners.
On clicking rapidly change event doesn't trigger until it looses focus from input tag(If I keep only change event). If I keep only click event then I won't be able to capture change event.
<input type="number" #click="function()" #change="function()" />
Use Observables. You can think about them as streams for events. Debouncing the output should give the result you want.
var event_a = Rx.Observable.fromEvent(document, 'mousemove');
var event_b = Rx.Observable.fromEvent(document, 'click'); // or in this case (input_element, 'click')
var debounce_ms = 100;
var debounced_event = merge(event_a, event_b).debounceTime(debounce_ms);
The debouncing step removes multiple events that happen in the specified time interval. If both events (or more than one copy of the same event) happens in less than 100 ms, only one event will be emitted.
On debouncing Observables: https://www.learnrxjs.io/operators/filtering/debouncetime.html
The above example uses different events from yours; just adapt it to listen to any of the events that you want. Lastly, subscribe to the Observable, and call the relevant event handling code there:
debounced_event.subscribe(() => {
// do event handling things here
});
To use Observables on your page, include rx.js somewhere. Here is example code to load it from a CDN.
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.1/rxjs.umd.js"></script>
You can add to data a boolian
(e.g isInvoked:false).
When the function run check:
if (this.isInvoked) return;
this.isInvoked=true;
//rest of your code here.....

How to implement event listener for any objects in JavaScript

I want to implement custom event with this functionality:
create custom event
after callback of ajax dispatch event
any object in document (div, grid, ...) can register listener of this custom event
when event is fired, all objects which have registered listener event call any methods
I tried created custom event (no problem):
var eventFilterRefresh = document.createEvent("CustomEvent");
eventFilterRefresh.initEvent("onFilterCancel", true, true);
Register event:
var dv = document.getElementById('myDiv');
dv.addEventListener('onFilterCancel', function (e) {
alert();
}, false);
Dispatch event - here is problem. I don't wont call dispatchEvent on conrete object. I want call generaly dispatchEvent and all objects which have registered event makes methods:
var myDiv= document.getElementById('myDiv');
myDiv.dispatchEvent(eventFilterCancel);
Thanks.
There is no way to fire an event from a single context so that listeners bound to a variety of other elements will trigger on it. You will need to fire the event from the context of each of the elements with the relevant listener.
The easiest way to do this is to add a hook like a class name to all of the elements that have the event listener and then use that hook to dispatch the event for each element.
//Add a hook when you register the listener
var dv = document.getElementById('myDiv');
dv.addEventListener('onFilterCancel', function (e) {
alert();
}, false);
dv.className += " js-filter-cancel";
//Use the hook to fire the event for all listeners
var myDivs= document.querySelectorAll('.js-filter-cancel');
for(var i in myDivs) {
if(!myDivs.hasOwnProperty(i))
continue;
myDivs[i].dispatchEvent(eventFilterCancel);
}

Access all event listeners in Javascript

I want to do something like this:
function('string', function2(){})
where I leave the to user to write what he wants in the string parameter and than execute function2.
The catch is here: string is an event listener. When the user writes click, I want to call onClick(), when the user writes mouse I want to call onMouseOver and so on.
I have in mind doing something with case, but how can I access all event listeners?
You should use addEventListener.
element.addEventListener("string", function() {}, false);
However, in the case of IE <= 8, you will need to use attachEvent as it does not follow the standard:
element.attachEvent("string", function() {});
Finally, as kybernetikos mentions in his comment, you can then use a simple dictionary to map mouse to mouseover.
If you wish to fire events, you should use dispatchEvent.
If you add the event listeners using the old model (i.e. elem.onclick = function(){ /* */ };), you can use
elem['on' + event]();
Keep in mind that this only fires the event listeners, but doesn't create an event (e.g. it won't bubble).
If you won't to create a event, which fires event listeners added using addEventlistener, and bubbles, and does all things a real event does, you must
Create your event using event constructors: Event or CustomEvent
Fire it with dispatchEvent
See MDN page for more information and examples.
you can use .trigger to do this. Check out this example in jsfiddle. type "dblclick" in the input box.
http://jsfiddle.net/jspatel/Suj4H/1/
<input id="writehere"> </input>
$('#writehere').dblclick(function() {
alert ('dblclick');
});
$('#writehere').bind('keypress', function(e) {
if(e.keyCode==13){
$(this).trigger( $(this).val() );
}
});

jQuery .one() with same function for different events on different elements

I have an introduction on my page which shall disappear when a key is pressed or a certain elements is clicked on. I'll use the same function for both events but as the page is heavily modified the event shall fire only once regardless which way it was triggered.
My function:
function start() {
$('.intro').remove();
$('.something-else').show();
}
How I bind the events:
$('body').keypress(start);
$('.intro').click(start);
If the events were the same I could say
$('body, .intro').one('click', start);
If both events were to happen to the same element I could say:
$('.intro').one('click keypress', start);
How to combine both things: having different elements and different events and the function must only be called once?
The simplest solution would be to store whether your function has been called or not.
var started = false;
function start() {
if(started) return;
$('.intro').remove();
$('.something-else').show();
started = true;
}
Then your function can only be called once, every other call will be ignored.
I don't think this solution is a clean as an explicit approach, but is done using a combination of .one() and .trigger(). Because you call $(".intro").remove() on one of the bound items the event handler is implicitly unbound. Sample Fiddle
Excluding the html seen in fiddle, this is the code.
// Your event handler
function start() {
$("#intro").remove();
$("#main").show();
console.log("start handler called");
}
// Handle the keypress event
$("body").one( "keypress", start );
// Allow user to click through the intro, but trigger the keypress handler on the body which is a one-time event handler)
$("#intro").one( "click", function () { $("body").trigger( "keypress" ); });
Use two lines of code and be done ;)
$('body').one('keypress', start);
$('.intro').one('click', start);
Edit:
You should manually unbind the other callback, lest it runs later, unexpectedly.

jQuery - How do I make custom event fire only once?

I need to control the order in which events are fired. To ensure that my custom event is fired only after another event has finished I am triggering the custom event in the handler of the first event.
$(".HwRadioButton").click(function(event) {
//Stuff that needs to happen before custom event
...
//trigger custom event
$(".HwRadioButton").trigger("onAnswerChange");
});
Custom event binding:
$(document).ready(function() {
$(".HwRadioButton").bind("onAnswerChange",function(event) {
//custom event stuff
});
});
The problem is that I have 12 elements that have a class attribute value of ".HwRadioButton". The event, "onAnswerChange" is triggered 12 times. Why is that? Should I even need to select any elements? I just want to define a custom event and explicitly trigger it.
Thanks!
In your code try:
$(".HwRadioButton").click(function(event) {
//Stuff that needs to happen before custom event
...
//trigger custom event
$(this).trigger("onAnswerChange");
});
that will trigger the onAnswerChange on the one element that was clicked.
You should use one like
$('.HwRadioButton').one('click', function() {
alert('This will be displayed only once.');
});
$(".HwRadioButton").trigger("onAnswerChange") triggers onAnswerChange for all items selected by that selector. Trigger the event only for $(this).trigger("onAnswerChange").

Categories