I have been coding up a page and come across something i do not understand.
the goal was to disable the context menu when a button was pressed and enable it again later.
the first example disables the contextmenu but cant enable it again after.
Note: the 'off' command is obviously not run right after the 'on' command, I have just pulled the relevant code out for readers convenience.
Can someone please explain to me why this doesnt work:
$(document).on("contextmenu",function(e){return false;});
$(document).off("contextmenu",function(e){return false;});
yet this does:
function returnFalse(e) {
return false;
}
$(document).on("contextmenu",returnFalse);
$(document).off("contextmenu",returnFalse);
The way that does not work is because you are saying "on contextmenu, run this anonymous function". Then you are saying "off contextmenu, dont do this new anonymous function"
Anytime you are writing an anonymous function, it is essentially a new function so you can't reference it later.
You have to save off your function for later use, so jQuery knows which function to actually remove.
Because off removes a function that is actually attached as a handler to the element. In your first example, you are trying to remove a facsimile anonymous function which has never been attached as a handler.
Related
I just got through figuring out that I need to watch out for duplicate event handlers in jquery if I'm dynamically assigning them multiple times as described here: http://www.parallaxinfotech.com/blog/preventing-duplicate-jquery-click-events
Do I need to watch out for this or handle it somehow if I'm declaring a function dynamically within another function multiple times? How does JavaScript really handle this? Does it only use the last function that was called or does it only instantiate a function once at load time? From what I can tell it's not running the function multiple times.
$(document).on("click",".button",function() {
function alertThem()
{
alert('Clicked!');
}
alertThem();
});
JavaScript will remember every function you're assigning it.
$('button').click(function(){
alert('hi')
})
$('button').click(function(){
alert('hi')
})
The code above will alert "hi" twice. If you're assign new function and you want to clear the old one, you can do unbind().click(). what it will do is it will unbind all events, or you can do unbind('click') which will unbind just the click. see https://jsfiddle.net/rznbtc1p/
$('button').click(function(){
alert('hi')
})
$('button').unbind().click(function(){
alert('hi')
})
The link you provided does not work (gives me timeout) so I hope I understood what you asked.
About what happens there:
In your script you created a closure and bound it to a click event. Each time you click on the element with class button, the anonymous function is triggered. Each time is triggered it defines function alertThem(), and calls it. Only once defines it, only once calls it. The scope of that function is its parent, the closure. That function is not defined outside that scope, so no need to worry about double definition.
Side note here: Personally as a rule of thumb don't think is a good idea to define functions like this, but if it suits your project... go for it.
Now about duplication. Since I cannot see the link, I think you are referring to double event binding.
In js can bind any number of events to the same element. You can for example bind on click something that says "Hi, you clicked me", then bind also on click something that says "Hi, you received a message before saying you clicked me". When you click that element, you will see both messages.
This can actually become a problem. You have 3 options:
Be really careful how you bind events
Keep tracking of what you bound
Check if events are already bound (although that is a bit unreliable). You can check how here: jQuery find events handlers registered with an object
In your code snippet, you aren't creating duplicate event handlers.
What is happening in your snippet is that you are creating a new function alertThem within the scope of your click handler function and then executing it in the line below.
Is it possible to have multiple click events for the same element? I have tried to simply have it like so:
$('#templates').click(function(e) {
do something..
});
$('#templates').click(function(e) {
do something else also..
});
Yet only the second event fires. I cannot find any decent answers explaining how to do this for a singular element in an on-click?
Note: the first click event calls server-side and loads a new PHP template (this may have an effect on what I can use in the second call I guess, as individually both clicks work but the server call does not work if I try a second click for the same element)
$('#templates').click(function(e) {
functionOne();
functionTwo();
});
function functionOne(){
}
function functionTwo(){
}
perhaps?
Please check this fiddle:
http://jsfiddle.net/DqSSd/
As you can see it should work well.
So please provide more information, and it would be better, if you provide JS fiddle as well.
Because so far the problem might be in:
second event is fired before first event returns the result
first event returns error from the server
some of events contains syntax error
etc
You may check something of those with investigation of NET calls to server (with Firebug or Chrome Developer toolbar).
Also for testing purposes you can type in console $('#templates').data("events"), so you will be able to see all events and handlers for particular element.
EDIT
Based on the number of views and the complete lack of responses I have to assume that I did a poor job of communicating my issue. I'm going to try to rectify that now.
I extended the HTMLElement prototype with a new tap method like so:
HTMLElement.prototype.tap = function (func) {
this.addEventListener("touchend", func, false);
};
I also created a custom tap event in jQuery:
$(document).delegate("*", "touchend", function (e) {
$(this).trigger("tap");
});
I also created a jQuery plugin called tap:
$.fn.tap = function (func) {
this.bind("tap", func);
};
If I try to use any of these with a callback function that includes an alert statement the callback executes twice. I tap the element to pop up the alert. I tap the "OK" button in the alert to close it. The next time I tap the screen no matter how long I wait the alert pops up again. This time tapping the "OK" button doesn't seem to set up another repeat.
However if the callback function doesn't include an alert statement (e.g. I use a console.log statement instead) the callback only executes the one time.
Does anyone know a way to deal with this? I'm about to try unhooking the event handler from within itself and then rebinding it afterwards, but that's nothing more than a hack if it's even successful.
I'd rather do things the "right" way. :-)
ORIGINAL
I just finished writing a "tap" function that I can use by extending the HTMLElement or Element prototypes as well as a custom "tap" event and "tap" plugin both for jQuery. I thought I had this in the bag until I decided to use a simple alert statement as test code.
When I use these with some element on my test page, they fire properly when I first "tap" the element, but the problem arises after I touch the alert's "OK" button and then, any amount of time later, tap the screen again at which point the event handler fires a second time.
At first I thought it was my custom code, but when I tried it with the following very basic JavaScript I was able to replicate the exact same issue.
document.getElementById("some-element").ontouchend = function (e) {
alert("Howdy doody!");
};
I imagine it must have something to do with the fact that I have to touch the screen again to execute the "OK" on the alert while still technically "inside" the event handler (since the alert is in effect "blocking" the completion of the handler function).
The fact that the behavior isn't replicated with the following slightly different code seems to support my imagination. :-)
document.getElementById("some-element").ontouchend = function (e) {
console.log("Howdy doody!");
};
If I include the above code in a page and touch that element after the callback fires I won't get a repeated firing of that callback function as opposed to the previous block of code where I'll see the alert pop up a second time the next time I tap the screen after hitting "OK" no matter where on the page I tap.
A strange issue indeed, and I haven't been able to find any information about why this might be happening. Does anyone have an idea what is happening?
I believe the visual, full-page alert being triggered on touch end is interfering with the touch event cycle. Try to call the alert after yielding to the DOM. eg.
setTimeout(function() {
alert('btn clicked');
}, 0);
I have a tooltip that I want to disable. It is from this site and is basically set and called as follows:
this.tooltip = function(){....}
$(document).ready(function(){
tooltip();
});
I don't want to unbind the hover or mouseover events since they are also tied to other effects. I have tried to disable without success as follows (at the bottom of the page):
$(document).ready(function(){
this.tooltip = function() {}
})
and
$(document).ready(function(){
function tooltip() {}
})
Am I missing something?
EDIT:
Heres a thought... try taking your override out of the ready statement. That way it should override the function definition before onReady is ever fired.
this.tooltip = function(){return false;};
That wont work because the script calls itself in an external file, thus if you try to make it a blank function before hand then it overrides it, and if you do it afterwards it has already run, so while you override it it has already added its event handlers to the stack. You could jsut not include the file on the pages where you dont want the tooltips.
An easy way to handle this is to make the event handlers named functions instead of anonymous, then you can easily unbine only those functions from the event stacks with $('a.tooltip').unbind('click', tooltipClick); Ofcourse the more thorough way is to refactor it in to your own plugin with remove option or something of that nature. Also there are several tooltip plugins for jQ out there and im sure at least one, if not all will allow for disabling.
You do not need to unbind the tooltip function (since its purpose is only to run once) but the anonymous functions that it adds to the events of some elements..
There is a way to do it, only if you can alter the original tooltip code to include a namespace when binding the anonymous functions..
some examples..
in the tooltip source code there is
$("a.tooltip").hover(function(e){...})
this should be
$("a.tooltip").bind('hover.tooltip',(function(e){...});
the .tooltip next to hover means that we have defined a namespace for this function and we can now unbind it with
$("a.tooltip").unbind('hover.tooltip');
Ok, I was able to do it with this function. But it seems kind of hackish and may not be the most elegant solution.
$(document).ready(function() {
$(".tooltip").mouseover(function(){ $('#tooltip').remove() });
});
I'll keep this question open in case any better ideas show up.
I found that a website does somewhat sneaky things. When you hover over a link, it shows you the real URL. WHen you click on it, it uses the click/mousedown event to rewrite the URL.
I want to override that behaviour in firefox, So I fired up firebug to see what it does. On a mouse click, it executes a function called window.tgs. Easy, I thought. I can override this function.
My first attempt was to do get the element via getELementsByTagName(), and then
element.removeEventListener("click",window.tgs, false);
To my surprise, this did nothing.
I tried redefining window.tgs
window.tgs = function() { return true; };
that did not do anything either.
I am not a JS expert. Your insights appreciated
thanks
Sid
Have you tried element.onclick = function(){}?
Depending on how the function operates you could "in theory" manipulate the windows close event and attach your own handler.
While this is horribly inefficient it would get the job done.
Something like this possibly could work
window.onUnload(function(){
});
I did not really figure out how to fix this, so worked my way around it. I added another eventlistener which reversed everything that the function in question did. Lousy hack, but it works