Allow other bound element events to trigger first? - javascript

Is there a way to allow other bound events to the same object(ex. textbox) to fire/trigger first?
Say 2 events got bound to the same textbox. Both keyup events. In my case there is a plugin binding its own events, but the way the code is written, mine get bound first. I do not want mine to fire first.
$("#firstname").keyup(function() {
// ...is there anyway to allow the other keyup event to fire first, from here?
// do my work here...
}
$("#firstname").keyup(function() {
// the plugin work.
}
I need to use keyup, there is already key down events.

You should really rewrite your code to only have one keyup binding to that event but if that isn't feasible, you could do it dirty with semaphores and separate your functionality from the binding so it can be called from either bind...
var semaphore = 0; // on init
$("#firstname").keyup(function () { // this one should run first
semaphore++;
if (semaphore === 0) {
first_action();
}
}
$("#firstname").keyup(function () { // this one should run second
if (semaphore > 1) { // you know the first event fired
second_action();
}
else if (semaphore < 1) {
first_action();
second_action();
semaphore++;
}
}

Related

JavaScript: Add Event Listener to an Event Listener

I am working with ChartJS. I have a onClick function defined for the chart which changes the data for the chart and calls an update() function. It looks like the chart does not actually fully update until the onClick function has finished, so there is not way for me to access the new data in the chart in the onClick handler.
I am hoping there is a way to add an event handler on that onClick event handler, but I can't figure out how to do it. I tried adding a separate onClick event handler, but it looks like they run asynchronously, and I can't figure out a way to guarantee that the onClick event handler that is changing and updating the chart finishes first. Ideally, I would be able to create an event handler on the chart's event handler, but I don't know how to do that.
I found a similar question asked some years back, but it looks like they might have been able to add an event handler to their event handler because it was a custom event, and wasn't just 'click'. Does anyone know of a good solution to this?
function chartOnClickHandler(e) {
if (e.native.detail !== 2) return; // if not double click return
if (e.native.target.style.cursor === 'default') {
handleDoubleClickAddPoint(e);
}
else if (e.native.target.style.cursor === 'grab'){
handleDoubleClickRemovePoint(e);
}
} // I want to run code here, after chartOnClickHandler has finished executing.
// Below is my second event listener. Ideally, I could call the passed in function
// whenever chartOnClickHandler is called.
chartElement.addEventListener('chartOnClickHandler', (e) => {
// Handle event
});
99% chance this doesn't work so please someone kindly correct it so it works. Also I feel like this is not even on the right track.
function chartOnClickHandler(e) {
return new Promise((res, rej)=>{
if (e.native.detail !== 2) rej(0); // arbitrary reject value
if (e.native.target.style.cursor === 'default') {
res(handleDoubleClickAddPoint(e));
}
else if (e.native.target.style.cursor === 'grab'){
res(handleDoubleClickRemovePoint(e));
}
})
}
function handleSynchronously(e) {
chartOnClickHandler(e).then(
// do synchronous stuff here
);
}
I think I found a simple way around my issue. Instead of adding an event listener that waits for the function to finish, I found a way to mess around with the event queue. Using either queueMicrotask() or setTimeout(), I am able to add a function to the event queue that comes after the current running event.
Update: I ended up going with setTimeout(function, 1000) because I have to wait for the Chart's animation to end to properly get the data I need.
function chartOnClickHandler(e) {
if (e.native.detail !== 2) return; // if not double click return
if (e.native.target.style.cursor === 'default') {
handleDoubleClickAddPoint(e);
}
else if (e.native.target.style.cursor === 'grab'){
handleDoubleClickRemovePoint(e);
}
queueMicrotask( () => {
// Function to be run after the current task/event (chartOnClickHandler)
});
setTimeout( () => {
// Function to be run after the current task/event (chartOnClickHandler)
}, 0); // timeout can be 0, since we don't care about delay time, just to push the event down in the event queue.
} // Queued function will run here, after chartOnClickHandler has finished executing.
// Below event handler is not needed and can be removed.
chartElement.addEventListener('chartOnClickHandler', (e) => {
// This event handler is not needed anymore
});

custom event in JQuery not triggering

My custom event is very basic, I'm trying to see a console.log message when I click in a input (is a checkbox) inside a div. For any reason my event handler (by using .on) is never fired. Any idea?
// define custom event
$.event.special.selectnetwork = {
eventType : 'selectnetwork',
setup: function(data, namespaces) {
$(this).find('input').bind('change', $.event.special.selectnetwork.handler);
},
teardown: function(namespaces) {
},
handler: function(event) {
event.type = 'selectnetwork';
console.log('im here'); // I reach this poing
return $.event.dispatch.apply(this, arguments); // Something wrong?
}
};
// test the custom event
$('div#mydiv').on('selectnetwork', function(event) {
console.log('selected'); // never is printed
});
There's a mistake in your .log() that's probably a typo, but it'll stop your script. Other than that, supposedlly custom events need to be bound with .bind() instead of .on()
This doesn't answer your question directly, but because events bubble up to their parents, the following will accomplish what I believe your example intends to do.
$('div#mydiv').on('change', function (e) {
console.log('selected');
});

jQuery trigger() with keydown/up event on textarea

JSFiddle here - uses console.log().
window.evtqueue = [];
window.eventHold = function(e){
console.log(e.held);
if (typeof(e.held)==typeof(undefined)){
e.held = 1;
window.evtqueue.push(e);
console.log(e.type+" - "+e.which);
window.setTimeout(function(){
console.log("Triggering: "+e.type+" = "+e.which);
var evt = window.evtqueue.splice(0,1)[0];
$('#edittext').trigger(evt);
}, 1000);
return false;
} else {
console.log("Event actually triggered!");
}
}
$('#edittext').on('keydown keyup', window.eventHold)
I'm making a rich text editor, and was having some issues with quick keystrokes vs. asynchronous code (which is out of my control), so, I decided to make an event queue. However, I'm having trouble getting saved events to fire with .trigger(), and when I can manage that, they don't seem to fire their defaults.
What am I missing? Does this require more events to be bound to actually trigger the defaults, like keypress? Is it failing because the original bound event thing returns false, despite this being asynchronous?
Yes, it's because you returned false before you trigger the event
If you return false, the
event.isPropagationStopped() and event.isDefaultPrevented() is true
The source code show, if both of them is true, the trigger method will do nothing

jQuery function in two events

I have this code:
$('#email').keyup(function() {
if(true || false)) {
} else {
}
});
I need include this function also in blur event.
I've tried to create a jquery function but I could not. Somebody give me a light.
You can do this -
$('#email').on('keyup blur',function() {
http://api.jquery.com/on/
Use the on method to attach multiple events, which are specified in the first argument passed to the function.
$('#email').on('keyup blur', function() {
if(true || false) { //there was an extra ) here
} else {
}
});
Working Example http://jsfiddle.net/nv39M/
One thing to be aware of, the keyup event is going to fire prior to the blur event firing.
Make a separate function as follows
function funcName(){
//Your code
}
Now,use jQuery on
$("#email").on("keyup",funcName);
$("#email").on("blur",funcName);
For reference,check
http://api.jquery.com/on/
There are (at least) two ways you could achieve this.
Specify multiple, space separated events as the first argument:
$('#email').on('keyup blur',function() {
// your logic
});
Use a named function:
function yourFunction() {
// your logic
}
$('#email').on('keyup', yourFunction);
$('#email').on('blur', yourFunction);
Option 1 is probably the best choice assuming you don't want to use the function anywhere else, and that you want to bind the event handlers at the same time. If, however, you wanted to bind the blur event at a later point (perhaps in response to another event), or to a different element, then the named function method would be the best choice.

jQuery temporary unbinding events

Maybe I'm totally missing something about even handling in jQuery, but here's my problem.
Let's assume there are some event binding, like
$(element).bind("mousemove", somefunc);
Now, I'd like to introduce a new mousemove binding that doesn't override the previous one, but temporarily exclude (unbind) it. In other words, when I bind my function, I must be sure that no other functions will ever execute for that event, until I restore them.
I'm looking for something like:
$(element).bind("mousemove", somefunc);
// Somefunc is used regularly
var savedBinding = $(element).getCurrentBinding("mousemove");
$(element).unbind("mousemove").bind("mousemove", myfunc);
// Use myfunc instead
$(element).unbind("mousemove", myfunc).bind("mousemove", savedBindings);
Of course, the somefunc is not under my control, or this would be useless :)
Is my understanding that is possible to bind multiple functions to the same event, and that the execution of those functions can't be pre-determined.
I'm aware of stopping event propagation and immediate event propagation, but I'm thinking that they are useless in my case, as the execution order can't be determined (but maybe I'm getting these wrong).
How can I do that?
EDIT: I need to highlight this: I need that the previously installed handler (somefunc) isn't executed. I am NOT defining that handler, it may be or may be not present, but its installed by a third-party user.
EDIT2: Ok, this is not feasible right now, I think I'm needing the eventListenerList, which is not implemented in most browsers yet. http://www.w3.org/TR/2002/WD-DOM-Level-3-Events-20020208/changes.html
Another way could be to use custom events, something along these lines:
var flag = 0;
$(element).bind("mousemove", function() {
if(flag) {
$(this).trigger("supermousemove");
} else {
$(this).trigger("magicmousemove");
}
}).bind("supermousemove", function() {
// do something super
}).bind("magicmousemove", function() {
// do something magical
});
$("#foo").click(function() {
flag = flag == 1 ? 0 : 1; // simple switch
});
Highly annoying demo here: http://jsfiddle.net/SkFvW/
Good if the event is bound to multiple elements:
$('.foo').click(function() {
if ( ! $(this).hasClass('flag')) {
do something
}
});
(add class 'flag' to sort of unbind, add it to 'bind')

Categories

Resources