jQuery override an on() event with another on() event - javascript

I have 2 files, file 1 (head.tpl) contains this default function operation
$(document).on("click", "#blackout", function(){
closeSkyBox();
});
That is the default operation I want to run, and it works.
On my second page, I would like to override the operation that is in head.tpl with this:
$(document).on("click", "#blackout", function(){
closeSkyBox(function(){
pev_for_country = '';
});
});
So, now when I test the code, each one runs, so If I were to place an alert (for testing reasons) I get two alert boxes. How can I make it so only the one in the second page runs, and the one in head.tpl is disabled. Then when I don't override it say on a third page, the one in head.tpl runs?

Looks like you're looking for jQuery's .off
$(document)
.off('click', '#blackout')
.on('click', '#blackout', function () {
// ...
});

You can use .off to remove all event handlers, but you should be cautious: what if other libraries add event handlers that you don't want to remove subscribe to this event? Also, if you add an additional event handler at a later date, this would obliterate it.
A better approach, I think, is to create a function that you can override:
function blackoutClick() {
closeSkyBox();
}
And set up your click handler:
$(document).on("click", "#blackout", function(){
blackoutClick();
});
Or, as Paul pointed out in the comments below, you don't even need to wrap that handler in an anonymous function, you can just use the cleaner:
$(document).on("click", "#blackout", blackoutClick );
Then, in your second page, you can just modify that function:
function blackoutClick() {
closeSkyBox(function(){
pev_for_country = '';
});

I believe another way to do it is also to set the event to null...
$(document).on('click', '#blackout', null);
before you re-set it on your second page.

Related

How to prevent jQuery duplicate function being called

I have a jQuery on('click') function like this:
function enabled_click() {
$('.btn_enabled').on('click', function() {
alert('CLICKED');
});
}
and then I have another post function like this
$(document).on('click', '.btn_add_link', function(e) {
var url = 'www.xxx.my-function';
post_data(url, function(data) {
if (data.status == 'success') {
$('#my_wrapper').append(data.response);
enabled_click();
} else {
alert('error');
}
});
return false;
});
The post function will append another .btn_enabled button. If i did not call the enabled_click() function on the success post, then the newly added .btn_enabled would not be able to trigger the onclick function.
But if I call the enabled_click() function like i did above, the already existing .btn_enable will then call the onclick function twice and alert CLICKED twice. Is there any way to make it so it only alerts once?
Event delegation by binding to a common parent, as answered by #qs1210, is a possible solution, and a very efficient one (because there's only one common handler instead of one per element). But depending on the code, it may require more changes.
As a compatible "drop-in replacment" just unbind the event handler before binding again. To achieve this in an easy and stable way, you can use jQuery's "namespace" feature for event names (see .on(), "Event names and namespaces"):
function enabled_click(){
$( '.btn_enabled' )
.off('click.some_namespace')
.on('click.some_namespace'), function() {
alert('CLICKED');
});
}
Note: if you extract the event handler into its own function and use that as second parameter to .off(), you could omit the namespace:
function click_handler(){
alert('CLICKED');
}
function enabled_click(){
$( '.btn_enabled' )
.off('click', click_handler)
.on('click', click_handler);
}
But this only works it the click_handler variable is "stable": depending where and when the click handler is defined, the variable (click_handler in this example) could be re-assigned and .off() couldn't detach the previous handler anymore.
Follow-up: in your example, you only apply the event handler to newly appended elements ($('#my_wrapper').append(data.response)). You could alter enabled_click to explicitly take the new element(s) as an argument:
function enabled_click($element){
$element.find('.btn_enabled' ).on('click', function() {
alert('CLICKED');
});
}
and call it like this:
var $newElement = $(data.response);
$('#my_wrapper').append($newElement);
enabled_click($newElement);
Now the event handler gets attached to new elements only, and not to already existing which have the event handler already attached.
(I'm using $ as prefix for all my variables holding jQuery collections, in order to distinguish them from pure DOM nodes)
Your can write like this
document.on('click', '.btn_enabled', function() {
alert('CLICKED');
})`
delegate event to dom, it makes everything harmony.

How to deactivate a nested anonymous function in Jquery

I have the following code:
$('#button-a').click(function(){
$('#button-b').click(function(){
alert('something');
});
});
$('#button-b').click(function(){
// do something
});
How can I deactivate the nested #button-b function after I have clicked #button-a, so only the last #button-b function (not nested) activates when i click #button-b and not them both?
Try this using .on() and .off() event handlers.
$('#button-a').click(function(){
$('#button-b').off('click'); //unbind the click event of the #button-b
$('#button-b').click(function(){
alert('something');
});
});
$('#button-b').on('click',function(){
// do something
});
In order to accomplish this, your function cannot be anonymous. You need to use the form of off which specifies the handler to remove. Rewriting your code a bit, it'd look something like this:
function myFunc() {
alert('something');
}
$("#button-a").click(function() {
$("#button-b").click(myFunc);
});
$("#button-b").click(function() {
// do something
});
To remove the handler, you'd use:
$("#button-b").off('click', myFunc);
I'm not quite sure where you want this to occur, but the above line of code will work anywhere that the DOM has been loaded and myFunc is in scope.
If you feel you definitely need an anonymous handler here, you can use event namespace for your task - http://api.jquery.com/on/
$('#button-b').on('click.nestedClick', function(){
alert('something');
});
// and unbind it at some point:
$('#button-b').off('click.nestedClick');
$('#button-a').click(function(){
$('#button-b').trigger('click');
});
$('#button-b').click(function(){
// do something
});
Change your code like this so it call your last function for button-b when you click on button-a

Onload fires no matter where I place it

Right, I'm getting quite aggitated with this. I'm probably doing something wrong, but here's what I'm doing:
$(document).ready(function () {
$('#somebutton').click(function () {
openPage1();
});
$('#someotherbutton').click(function () {
openPage2();
});
});
var openPage1 = function () {
$('#iframe').attr('src', 'someurl');
$('#iframe').load(function () {
$('#button').click();
});
};
var openPage2 = function () {
$('#iframe').attr('src', 'anotherurl');
$('#iframe').load(function () {
$('#anotherbutton').click();
});
}
Whenever I click somebutton everything goes as expected. However when I click someotherbutton. The .load() from openPage1() is called first and I can't find a way to stop that. The .load() from openPage1() has a button with the same name, however on openPage2() I need to modify the contents before clicking the buttons.
I need to use .load() because I can't click the buttons before the document is ready.
Basically what I need is two seperate .load() instances on the same iframe, that don't fire off on each other.
Besides that, maybe my understanding of jQuery/JS is wrong, but shouldn't the .load() events only be listening after clicking the corresponding button?
Can someone help me out, this has been keeping me busy all afternoon.
Try using on, and once loaded, unbind
$("#iframe").on("load", function(){
$(this).off("load");
$('#button').click();
});
That way you remove the handler you put up before the second button is clicked?
By writing : $('#iframe').load(function (){ $('#button').click(); });, you are adding a listener on the load event, which will stay and be re-executed on each subsequent reload of the iframe.
Here is a jsfiddle to demonstrate this : click on the "reload" button, and see how many times the "loaded" message appears in your console.
in your case, if you click on #somebutton, then on #someotherbutton, after the second click, you will have two handlers bound on the load event, and both will be triggered.
If you click 5 times on #somebutton, you should end up calling 5 times $('#button').click().
If you want to execute it once, you can follow Fred's suggestion, or use jQuery .one() binder :
$('#iframe').one('load', function(){ $('#button').click() });
Here is the updated jsfiddle : 'loaded' should be displayed only once per click.
Maybe try and replace the lines in both functions like this:
$('#iframe').load(function() {
$('#anotherbutton').click();
};
$('#iframe').attr('src', 'anotherurl');
Otherwise it might be firing the event before the new event-handler has been set.
This isn't really an answer to your problem Now it is an answer, but I think utilizing functions as they were intended could be beneficial here, i.e.:
//Utilize a single function that takes arguments
var openPage = function (frame, src, eventEl) {
frame.attr('src', src); // If you pass frame as a jQuery object, you don't
frame.on("load", function(){ // need to do it again
$(this).off("load");
evEl.click(); //Same for your buttons
});
}
//Simplify other code
$(document).ready(function () {
$('#somebutton').click(function () {
openPage($("#iframe"),somehref,$("#buttonelement"));
});
$('#someotherbutton').click(function () {
openPage($("#iframe"),anotherhref,$("#someotherbuttonelement"));
});
});

Prevent calling a function

I have two parts of scripts.
Part 1 :
$("mySelector").click(function() {
alert('you call me');
})
Part 2 :
$("mySelector").click(function() {
if(myCondition) {
//how can i prevent calling the first function from here ???
}
})
The whole problem, is that i have no access to part1. So i need to unbind the event allready specified in part 1, if myCondition is true, but otherwise i need to call the first function.
Thanks
UPDATE:
Thank you. I didn't know about stopImmediatePropagation(). But i feel, that there must be something like that :)
But actually in my case it doesn't work :(
Please have a look at my site
http://www.tours.am/en/outgoing/tours/%D5%80%D5%B6%D5%A4%D5%AF%D5%A1%D5%BD%D5%BF%D5%A1%D5%B6/Park-Hyatt-Goa/
Under the hotel description tab i have cloud carousel, when i click on not active image (not the front image), as you can see i'm consoling that i stopImmediatePropagation() there, but the event however calls :(
If your handler is registered first, then you can use event.stopImmediatePropagation like this:
$("mySelector").click(function(event) {
if(myCondition) {
event.stopImmediatePropagation();
}
})
Be aware that this will also stop event bubbling, so it will also prevent click handlers on parent elements from being invoked.
Update: If this does not work, then your handler is attached after the one you want to control. This is a problem that makes the solution much more difficult. I suggest seeing if you can bind "before the other guy", otherwise you will have to unbind the existing handler and then conditionally invoke it from within your own by retaining a reference to it. See jQuery find events handlers registered with an object.
No access:
$("#mySelector").click(function() {
alert('you call me');
})
Access:
var myCondition = true, //try false too
fFirstFunction = $("#mySelector").data("events").click[0].handler;
$("#mySelector").unbind("click");
$("#mySelector").click(function() {
if(myCondition) {
alert(myCondition);
} else {
$("#mySelector").click(fFirstFunction);
}
});
Look at this example
You can call
$('mySelector').unbind('click');
to get rid of all the click handlers. If your script is loaded after the other one (which appears to be the case), then that should do it. However note that it does unbind all "click" handlers, so make sure you call that before you add your own handler.
If you can't ensure your handler is attached first, try the following code:
var events = $('mySelector').data("events"); //all handlers bound to the element
var clickEvents = events ? events.click : null;//all click handlers bound to the element
$('mySelector').unbind('click'); //unbind all click handlers
//bind your handler
$("mySelector").click(function(e) {
if (myCondition) {
//do what you want
} else {
//call other handlers
if (clickEvents) {
for (var prop in clickEvents)
clickEvents[prop].call(this, e);
}
}
})
Update:
Above code is for jQuery 1.3.2
Above code is based on internal implementation of jQuery 1.3.2, so please check it carefully once you update jQuery.
return false;
-or-
event.preventDefault();

Javascript + jQuery, click handler returning false to stop browser from following link

I'm trying to stop the browser from following certain links, rather I want to unhide some Divs when they are clicked.
I'm having trouble just getting the links to not be followed though.
Here's what I have:
var titles = $('a.highlight');
jquery.each(titles, function(){
this.click(function(){
return false;
});
});
It seems like the click handler is not being assigned. What am I missing?
Try
this.click(function(e){ e.preventDefault(); }
Actually, it looks like you might need to use the jQuery constructor on this:
$(this).click(function(){ return false; }
You could also try using parameters on the each function instead of using this:
jQuery.each( titles, function(index, elem) { $(elem).click( function() { return false; } ) } );
Personally, I would just do titles.each( ... though. In that instance you can use this to bind the click handler. I am not sure off the top of my head what this binds to with jQuery.each
Or just calling click on titles:
titles.click( function() { return false; } )
That will bind click to every element in titles. You don't need to loop through them.
You can compress that jquery a bit:
$('a.highlight').click(function() { return false; });
You should also make sure that:
There are no other click handlers registered for those elements later on.
The code you have is attaching after the elements have loaded. If they're not completely loaded, they won't be found in the $('a.highlight') selector. The easiest way to do this is to put your code in a $(document).ready(function() { *** code here *** }); block.
Edit: As per other responses - the problem was that this represents a DOM object, while $(this) is a jquery object. To use the .click function to attach a handler, you need a jquery object.
In short, using this inside the each loop won't work with what you're trying to do. You'll need to get a jquery representation by using $(this) instead.

Categories

Resources