The jsTree hover_node callback doesn't return the original ('mouseenter') event.
I'd like to get the mouse position (Client.Y) from the event.
Any suggestions, which don't involve hacking the core?
thanks,
BBZ
After going through the documentation I thought about writting a plugin.
$.jstree.plugin('custom-plugin', {
_fn: {
hover_node: function () {
console.log(arguments);
this.__call_old();
}
}
});
This could be a start (for future reference).
But the argument passed was a node not the event.
Finally I thought of binding to the mouseenter.jstree event.
Which gives me the original event.
Related
UPDATE turns out the code is actually working see my answer below
I'm having some troubles here. I thought I found my answer in the .one method, but apparently, .one means ONLY ONCE PER PAGE PER ANYTHING EVER which isn't exactly what I was going for. Here's what my intention was:
$("#someID").one('mouseover', function() {
//do some stuff
});
$("#someOtherID").one('mouseover', function() {
//do some stuff
});
My expectation was that once that first one fired, that mouseover event would no longer fire for THAT ELEMENT.
The problem with this is that once the first one fires, the second one will not fire either. So the .one method appears to be disabling ALL mouseover events for ALL elements after that first one fires.
I did not expect this, I expected the .one to only apply to that first element. Is this just a flaw in my understanding of the .one method or am I coding wrong?
If it's just a flaw in my understanding, could someone point me in the right direction to correct my code?
Thank you in advance!
This is embarassing, I hope I don't get dinged for this and blocked again from stackoverflow (the easiest thing ever to get blocked from and the hardest to get unblocked).
First, #CertainPerformance, thanks for taking the time to look at my question. My real code didn't have the two mistakes you mentioned, I updated my post to reflect the correct syntax.
I'll be honest, my code is working now, and I have no idea why. I suspect I've been dealing with some crazy caching issues which frustrates me because I'm using inMotionHosting which has really great reviews, and I have caching disabled in cPanel.
If anything, maybe this thread will benefit somebody searching "how to make event fire only once in javascript".
You could make the callback run once like this:
// Extend the function prototype
Function.prototype.once = function() {
// Variables
var func = this, // Current function
result;
// Returns the function
return function() {
// If function is set
if(func) {
// Executes the function
result = func.apply(this, arguments);
// Unset the function, so it will not be called again
func = null;
}
// (:
return result;
};
};
// Bind the event to the function you will use as a callback
$("#someID").on('mouseover', function() {
console.log('just once');
}.once());
I am a somewhat green programmer, and quite new to javascript/jquery, but I thought I understood javascript events. Apparently not. I am not able to get event listeners to work as I'd like.
Given javascript:
var Thing = {
//stuff
update: function() {
$.event.trigger({type:'stateUpdate', more:stuff});
}
};
var Room = {
//more stuff
updateHandler: function (e) {
//handle event here
}
};
If I do jquery:
$(document).on('stateUpdate', $Room.updateHandler);
then it works fine, but I can't do either
$(Room).on('stateUpdate', $Room.updateHandler);
or
Room.addEventListerner('stateUpdate', $Room.updateHandler);
The first does nothing, the second gives .addEventListerner is not a function error.
I've googled for hours and can't figure it out. I found something that said .addEventListener only works on objects that implement EventListener, something about handleEvent, and something about functions automatically implementing EventListener. Nothing on how to make an object implement it. Is there no way to add listeners to javascript objects that aren't functions? Am I going to have to create an event handler object, or use 'document' or 'window' and have it call handlers? That seems really ugly.
Should the objects be functions in the first place? Would that work? It seems the current opinion is that making everything functions is just trying to make javascript into something it isn't.
AFAIK there are no way to add a event listener to the plain object, as it is not placed inside DOM. Events are firing inside DOM, and bubbling so your event listener for custom object won't receive it.
There is a http://www.bobjs.com/ framework that can help you implement custom events.
In response to #Barmar (sort of) I believe I worked this out. Confirmation on if this is a a good alternative or not would be nice, though. Basically, I have to do a subscriber thing, right? Almost event/listener, but not quite.
var thing = {
callbacks: {},
regCallback: function (key, which) {
callbacks[key] = which;
},
remCallback: function (key) {
callbacks[key].delete;
}
update: function(e) {
for(var i = 0, len = callbacks.length; i < len;i++){
callbacks[i](e);
};
}
};
var Room = {
updateHandler: function () {
//handle stuff
},
subscribe: function (which, callback) {
which.regCallback('room', callback);
}
unsub: function (which) {
which.remCallback('room');
}
};
//wherever/whenever I need to get updates something like
Room.subscribe(thing, Room.updateHandler);
//unsub
Room.unsub(thing);
Second error is caused by typo: addEventListerner has extra r in it.
I have a situation where I need to use jQuery's $.fn.one() function for a click event, but I don't want it to apply to the next occurrence of the event (like it usually does), I want it to apply to the occurrence immediately after that, and then unbind itself (like .one() normally does).
The reason I don't want .one() to apply to the first occurrence is because I'm binding to the document from an event handler invoked earlier in the bubbling phase, so the first time it gets to document it'll be part of the same event. I want to know when the very next click event occurs.
Note: I do not want to use .stopPropagation() because it will potentially break other parts of my app.
Here are the two options I've come up with, though it seems like there must be a more elegant solution.
The double bind method:
$(document).one('click', function() {
$(document).one('click', callback);
});
The setTimeout method:
setTimeout(function() {
$(document).one('click', callback);
}, 1);
Both methods work just fine, but here's my question. I have no idea what the performance implications are for either setTimeout or frequent event binding and unbinding. If anyone knows, I'd love to hear it. But more importantly, I'd like some suggestions on how to measure this stuff myself for future situations like this.
I love sites like http://jsperf.com, but I don't know if it would really be helpful for measuring stuff like this.
And obviously, if someone sees a much better solution, I've love to hear it.
I find the double-bind method quite elegant - I think it accurately reflects your actual intent, and it only takes two lines of code.
But another approach is rather than using .one() you could use .on() and update the event object associated with the first event, adding a flag so that the callback will ignore the first time it is called:
function oneCallback(e) {
if (e.originalEvent.firstTimeIn)
return;
alert("This is the one after the current event");
$(document).off("click", oneCallback);
}
$("div.source").click(function(e) {
e.originalEvent.firstTimeIn = true;
$(document).on("click", oneCallback);
});
Demo: http://jsfiddle.net/q5LG4/
EDIT: To address your concerns about not modifying the event object (or any object you don't own) you could store a firstTime flag in a closure. Here's a rather dodgy .oneAfterThis() plugin that takes that approach:
jQuery.fn.oneAfterThis = function(eventName, callback) {
this.each(function() {
var first = true;
function cb() {
if(first){
first = false;
return;
}
callback.apply(this,[].slice.call(arguments));
$(this).off(eventName,cb);
}
$(this).on(eventName, cb);
});
};
$(someseletor).oneAfterThis("click", function() { ... });
I'm sure that could've done that more elegantly (perhaps I should've bothered to look at how jQuery implements .one()), but I just wanted to whip something up quickly as a proof of concept.
Demo: http://jsfiddle.net/q5LG4/1/
I was building a slide-menu with javascript using classes and objects and a little bit of jquery as part of my efforts to learn javascript more deeply.
Everything went right until I wanted to bind a mouseleave to the initiator of my menu.
So here's my code block
var el;
function generate(obj){
return function(){obj.slidein();}
}
function slider(arg1,arg2){
...//Some junk
el=this;
for(i=0;i<this.nsubs;i++){ ...
$("#"+this.id+i).bind('mouseleave',function(){setTimeout("generate(el)",500)});
}
...
}
Well, I get no error on firefox error console but somehow the slidein() function which I want to be attached to the mouseleave is not being called when mouse leaves the element in question.
Can Someone explain what I am doing wrong here?
Try passing a function rather than a string to setTimeout:
$("#"+this.id+i).bind('mouseleave', function() {
setTimeout(function() {
generate(el);
}, 500)
});
Alright, I sorted it out on my own, what I actually needed was a closure that returns a function with 'setTimeout(generate(ObjPassedToClosure))'
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')