Not calling click event - javascript

I have kind of strange problem.
I'm trying to add a couple of events to som DOM elements (all existing, some initially hidden:
$self.on("focus", function () {
$self.next().css("display", "inline-block");
});
$self.on("blur", function () {
$(this).next().hide();
});
$self.parent().find(".icon-ok").on("click", function() {
console.log("icon.ok")
});
You can see the relevant part of the DOM here (self is the span user-name):
Later on, the element eventually because visible and I can click on it. However, the event handler is never called. If I remove the blur event, than the click event works. However, I need both.
What's going on here?
How can I fix it?

Looks like the blur cancels out the click (due to event order) but using mousedown instead of blur may help you get both.
UPDATE: Added code based on comment
$self.parent().find(".icon-ok").on("mousedown", function() {
console.log("icon.ok")
});

Your problem might be the classic delegation problem, where in the element is not available in the DOM when the event is bound.
Delegate the event and see if that solves your problem.
$self.on("click", ".icon-ok", function() {
console.log("icon.ok")
});
User $self if that element is visible or any closest ancestor that you can find which is always present in the DOM.

Related

jQuery remove scroll listener after reach certain point [duplicate]

I have an input type="image". This acts like the cell notes in Microsoft Excel. If someone enters a number into the text box that this input-image is paired with, I setup an event handler for the input-image. Then when the user clicks the image, they get a little popup to add some notes to the data.
My problem is that when a user enters a zero into the text box, I need to disable the input-image's event handler. I have tried the following, but to no avail.
$('#myimage').click(function { return false; });
jQuery ≥ 1.7
With jQuery 1.7 onward the event API has been updated, .bind()/.unbind() are still available for backwards compatibility, but the preferred method is using the on()/off() functions. The below would now be,
$('#myimage').click(function() { return false; }); // Adds another click event
$('#myimage').off('click');
$('#myimage').on('click.mynamespace', function() { /* Do stuff */ });
$('#myimage').off('click.mynamespace');
jQuery < 1.7
In your example code you are simply adding another click event to the image, not overriding the previous one:
$('#myimage').click(function() { return false; }); // Adds another click event
Both click events will then get fired.
As people have said you can use unbind to remove all click events:
$('#myimage').unbind('click');
If you want to add a single event and then remove it (without removing any others that might have been added) then you can use event namespacing:
$('#myimage').bind('click.mynamespace', function() { /* Do stuff */ });
and to remove just your event:
$('#myimage').unbind('click.mynamespace');
This wasn't available when this question was answered, but you can also use the live() method to enable/disable events.
$('#myimage:not(.disabled)').live('click', myclickevent);
$('#mydisablebutton').click( function () { $('#myimage').addClass('disabled'); });
What will happen with this code is that when you click #mydisablebutton, it will add the class disabled to the #myimage element. This will make it so that the selector no longer matches the element and the event will not be fired until the 'disabled' class is removed making the .live() selector valid again.
This has other benefits by adding styling based on that class as well.
This can be done by using the unbind function.
$('#myimage').unbind('click');
You can add multiple event handlers to the same object and event in jquery. This means adding a new one doesn't replace the old ones.
There are several strategies for changing event handlers, such as event namespaces. There are some pages about this in the online docs.
Look at this question (that's how I learned of unbind). There is some useful description of these strategies in the answers.
How to read bound hover callback functions in jquery
If you want to respond to an event just one time, the following syntax should be really helpful:
$('.myLink').bind('click', function() {
//do some things
$(this).unbind('click', arguments.callee); //unbind *just this handler*
});
Using arguments.callee, we can ensure that the one specific anonymous-function handler is removed, and thus, have a single time handler for a given event. Hope this helps others.
maybe the unbind method will work for you
$("#myimage").unbind("click");
I had to set the event to null using the prop and the attr. I couldn't do it with one or the other. I also could not get .unbind to work. I am working on a TD element.
.prop("onclick", null).attr("onclick", null)
If event is attached this way, and the target is to be unattached:
$('#container').on('click','span',function(eo){
alert(1);
$(this).off(); //seams easy, but does not work
$('#container').off('click','span'); //clears click event for every span
$(this).on("click",function(){return false;}); //this works.
});​
You may be adding the onclick handler as inline markup:
<input id="addreport" type="button" value="Add New Report" onclick="openAdd()" />
If so, the jquery .off() or .unbind() won't work. You need to add the original event handler in jquery as well:
$("#addreport").on("click", "", function (e) {
openAdd();
});
Then the jquery has a reference to the event handler and can remove it:
$("#addreport").off("click")
VoidKing mentions this a little more obliquely in a comment above.
If you use $(document).on() to add a listener to a dynamically created element then you may have to use the following to remove it:
// add the listener
$(document).on('click','.element',function(){
// stuff
});
// remove the listener
$(document).off("click", ".element");
To remove ALL event-handlers, this is what worked for me:
To remove all event handlers mean to have the plain HTML structure without all the event handlers attached to the element and its child nodes. To do this, jQuery's clone() helped.
var original, clone;
// element with id my-div and its child nodes have some event-handlers
original = $('#my-div');
clone = original.clone();
//
original.replaceWith(clone);
With this, we'll have the clone in place of the original with no event-handlers on it.
Good Luck...
Updated for 2014
Using the latest version of jQuery, you're now able to unbind all events on a namespace by simply doing $( "#foo" ).off( ".myNamespace" );
Best way to remove inline onclick event is $(element).prop('onclick', null);
Thanks for the information. very helpful i used it for locking page interaction while in edit mode by another user. I used it in conjunction with ajaxComplete. Not necesarily the same behavior but somewhat similar.
function userPageLock(){
$("body").bind("ajaxComplete.lockpage", function(){
$("body").unbind("ajaxComplete.lockpage");
executePageLock();
});
};
function executePageLock(){
//do something
}
In case .on() method was previously used with particular selector, like in the following example:
$('body').on('click', '.dynamicTarget', function () {
// Code goes here
});
Both unbind() and .off() methods are not going to work.
However, .undelegate() method could be used to completely remove handler from the event for all elements which match the current selector:
$("body").undelegate(".dynamicTarget", "click")
I know this comes in late, but why not use plain JS to remove the event?
var myElement = document.getElementById("your_ID");
myElement.onclick = null;
or, if you use a named function as an event handler:
function eh(event){...}
var myElement = document.getElementById("your_ID");
myElement.addEventListener("click",eh); // add event handler
myElement.removeEventListener("click",eh); //remove it
This also works fine .Simple and easy.see http://jsfiddle.net/uZc8w/570/
$('#myimage').removeAttr("click");
if you set the onclick via html you need to removeAttr ($(this).removeAttr('onclick'))
if you set it via jquery (as the after the first click in my examples above) then you need to unbind($(this).unbind('click'))
All the approaches described did not work for me because I was adding the click event with on() to the document where the element was created at run-time:
$(document).on("click", ".button", function() {
doSomething();
});
My workaround:
As I could not unbind the ".button" class I just assigned another class to the button that had the same CSS styles. By doing so the live/on-event-handler ignored the click finally:
// prevent another click on the button by assigning another class
$(".button").attr("class","buttonOff");
Hope that helps.
Hope my below code explains all.
HTML:
(function($){
$("#btn_add").on("click",function(){
$("#btn_click").on("click",added_handler);
alert("Added new handler to button 1");
});
$("#btn_remove").on("click",function(){
$("#btn_click").off("click",added_handler);
alert("Removed new handler to button 1");
});
function fixed_handler(){
alert("Fixed handler");
}
function added_handler(){
alert("new handler");
}
$("#btn_click").on("click",fixed_handler);
$("#btn_fixed").on("click",fixed_handler);
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn_click">Button 1</button>
<button id="btn_add">Add Handler</button>
<button id="btn_remove">Remove Handler</button>
<button id="btn_fixed">Fixed Handler</button>
I had an interesting case relevant to this come up at work today where there was a scroll event handler for $(window).
// TO ELIMINATE THE RE-SELECTION AND
// RE-CREATION OF THE SAME OBJECT REDUNDANTLY IN THE FOLLOWING SNIPPETS
let $window = $(window);
$window.on('scroll', function() { .... });
But, to revoke that event handler, we can't just use
$window.off('scroll');
because there are likely other scroll event handlers on this very common target, and I'm not interested in hosing that other functionality (known or unknown) by turning off all of the scroll handlers.
My solution was to first abstract the handler functionality into a named function, and use that in the event listener setup.
function handleScrollingForXYZ() { ...... }
$window.on('scroll', handleScrollingForXYZ);
And then, conditionally, when we need to revoke that, I did this:
$window.off('scroll', $window, handleScrollingForXYZ);
The janky part is the 2nd parameter, which is redundantly selecting the original selector. But, the jquery documentation for .off() only provides one method signature for specifying the handler to remove, which requires this middle parameter to be
A selector which should match the one originally passed to .on() when attaching event handlers.
I haven't ventured to test it out with a null or '' as the 2nd parameter, but perhaps the redundant $window isn't necessary.

Prevent child's onclick after mouseup on parent?

I have a parent element with mouse up and mouse down events attached on it, and a child element with a click event attached.
Is there any way to prevent the click event from happening in the child, after the mouseup event has been triggered in the parent?
An example, on the JSfiddle here, the goal is to make the inner square not turn to green if I click on it.
Ideally I would like to do it without modifying the $('#inner').on('click', function(){}). I already know that I can set a boolean on mouseup and check it on click but i'm trying to find a way to do it without modifying the click event.
Using jquery(or any other library) is option and I don't really have any restrictions other than not modifying the click method.
EDIT
Thanks #adeneo for the suggestion, that looks promising but it made me realize I missed a big part of the problem. Inside mouseup there will be a conditional check to see if the click should be prevented or not. If I remove the event can I somehow add it back after the click has been avoided? In a setTimeout for example. I'm not sure how(or if it's possible) to get the reference to the removed click function and then re-add the handler.
Hopefully this new fiddle here helps me to explain it a little bit better!
$('#inner').on('mouseup', function(e) {
$(this).unbind("click");
$(this).css({'background': 'black'});
});
Did you try like this?
Try e.stopImmediatePropagation(); in your inner code.
Just replace your code with the below code and check. To stop the click event of the inner div you can use preventDefault() or stopPropagation(). Please check below
$('#inner').on('click', function(e) {
$(this).stopPropagation();
// or
// $(this).preventDefault();
alert('inner click');
});
$('#outer').on('mousedown', function(e) {
$(this).css({'background': 'green'});
});
$('#outer').on('mouseup', function(e) {
$(this).css({'background': 'yellow'});
});
I'm pretty sure that this is the answer you're looking for :
$($(this)).children().click(function (event) { // Preveu la propagació del click als fills
// event.stopPropagation();
});

Event Handling on multiple instances of the same class - need clarification

I need some guidance in understanding why these functions are doing what they are doing...
1.) On my web page, I have three different panels that utilize a Slider function, which creates an unordered list that has slider functionality using next and previous anchor links. See the code below:
function Slider(id) {
var _this = this;
this.id = id;
if (!id) return false;
this.index = 0;
this.slider = $(this.id);
this.length = this.slider.children().length;
this.width = $(this.id).outerWidth();
this.totalWidth = this.length * this.width;
$(id).addClass('slideWrapper').wrap('<div class="slideViewport">').after('<div class="sliderNav">PreviousNext</div>').css({
'width': this.totalWidth
}).children().addClass('slide').css({
'width': this.width
});
$('.slideViewport a.next').click(function(e) {
e.preventDefault();
return _this.next();
});
$('.slideViewport a.prev').on(function(e) {
e.preventDefault();
return _this.prev();
});
}
If I try to run more than one of these Slider instances on a page, clicking a .next anchor will cause the clicked element and any of the elements below it to more to the next list element in their slideshows. Going to the second panel would cause all but the first to run, the third panel causes all but the first and second to run, etc. I would have expected the handler to only run for the event that I clicked on, rather than all instances of the class after it, since I am using this in my event. Any explanation as to what is going on here would be immensely helpful.
2.) Now, I've been trying to make it such that all of the Slider events DO run next() when I click on any a.next anchor on the page, rather than just run an event for the one whose anchor I have clicked. I have figured out that this code works:
$('.slideshow').on("click", "a.next", function(e) {
e.preventDefault();
return _this.prev();
});
But truth me told, I'm not really sure why this is working. My understanding is that JQuery is only looking to see if the a.next anchor is clicked, and will then pass the handling function to the $('.slideshow') selector, which makes me assume that it is selecting all instances of $('slideshow') and running the .next() function for all of them. Is that the right way to think about it?
3.) Why does the following snippet of code cause all of the slideshows to run the next() function twice, as opposed to once? I don't really like that this isn't returning anything, so I don't really want to use this particular bit of code, but I'd just like to understand it a little bit better...
$('.slideViewport a.next').on("click", function(e) {
e.preventDefault();
$('.slideshow').each(function() {
_this.prev();
}
});
Help understanding any of this code would be much appreciated. I would really like to have a better understanding of what is going on in the DOM in terms of propagation in this scenario, but everything I've tried to read has just made me feel more confused. Thanks!
This bit of code attaches a click handler to all .slideshow elements in the document.
$('.slideshow').click(function(e) {
e.preventDefault();
return _this.prev();
});
What you might have wanted was to attach the handler only to the .slideshow elements that are descendants of the slider:
this.slider.find('.slideshow').click(function(e) {
// ... handle event here ...
});
Now, about your on() statement:
$('.slideshow a.next').on("click", function(e) {
e.preventDefault();
$('.slideshow').each(function() {
_this.prev();
}
});
What you've done here is bind a click event handler to all the .slideshow a.next elements, and what the handler does is run _prev() on all of them. But you already have another handler bound to the .slideshow element from when you called $('.slideshow').click(). When the "on" handler is finished, the event continues to propagate up the DOM tree, triggering all of the click handlers on its way up, including the one you bound to the .slideshow element. And of course that handler also calls _prev().
If you want to stop event propagation, you have two choices.
call e.stopPropagation()
return false from your event handler (this tells jQuery to stop propagation and prevent the default action).
You may ask yourself, "what is the difference between click() and on('click', ...). The on() method lets you use Event Delegation. Basically, that means using a single event handler attached to one DOM node to handle events on a lot of descendant elements.
As an example, imagine you have a div with some arbitrary number of images in it, and you need to do something whenever an image is clicked. You can either (a) bind a click event handler to each image or (b) bind a handler to the div that will handle all the click events for all the images as those events bubble up the DOM tree.
$('#imageDiv').on('click', 'img', function(evt) {
// ... "this" is the image that was clicked ...
});
Delegation has the added benefit that you can add and remove images from the container, and the delegate will continue to work.

Document click not in elements jQuery

Using jQuery how does one detect clicks not on specific elements, and perform an action consequently?
I have the following JavaScript
$('#master').click(function() {
$('#slave').toggle();
});
$(document).not('#master','#slave').click(function() {
$('#slave').hide();
});
and I cannot see where I am going wrong logically. You can see a live example here
Since you're binding to the click event on the document, you can use event.target to get the element that initiated the event:
$(document).click(function(event) {
if (!$(event.target).is("#master, #slave")) {
$("#slave").hide();
}
});
EDIT: As Mattias rightfully points out in his comment, the code above will fail to identify click events coming from descendants of #master and #slave (if there are any). In this situation, you can use closest() to check the event's target:
$(document).click(function(event) {
if (!$(event.target).closest("#master, #slave").length) {
$("#slave").hide();
}
});
Does this code do what you want? (not entirely sure if I understood correctly)
$('body').on('click', '*:not( #master, #slave )', function() {
$('#slave').hide();
});
http://jsfiddle.net/gZ4Hz/8/
Event delegation has long been supported natively by jQuery. The difficulty lies in creating the appropriate selector. Originally, delegate was used, but more recently the delegate form of on should be used.
The purpose of event delegation is to listen to events on child elements and invoke the bound event handlers on those elements as though they had been bound to the child element, instead of the parent. This means that instead of binding handlers to every element in the DOM, you're binding a handler to every element in the initial selection (document is a single element). This also makes for a simple way to use a single selector to bind to an ever changing set of elements, as new elements will propagate their events to document whether or not they existed when the initial event handler was bound:
$(document).on('click', '*:not(#master, #master *, #slave, #slave *)', function (e) {
//this will reference the clicked element
});
Additionally, note that I not only said the elements must not be #master or #slave, they must not be children of #master or #slave either.
Another thought, it may not be working because your browser may not be rendering body at 100% height; Try adjusting your base css to fix height of body and then a couple other thoughts.
e.stopPropagation(): Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
So if you change the first click code to the following:
$('#master').click(function(e) {
e.stopPropagation();
$('#slave').toggle();
});
Then you could change the call sign of the second too:
$("body, body *").not('#master, #slave').click(function(e) {
$('#slave').hide();
});
And that should cover it. Give it a try! or see this jsFiddle
Fredrik's answers works for elements already present in the document, but it didn't work for elements fetched by ajax calls.
I tried the following and it works for me. Sharing the code for future ajax coders.
$(document).on('click',function(event) {
if (!$(event.target).closest("#selector").length) {
if ($('#selector').is(":visible"))
$('#selector').slideUp();
}
});
Would have posted it as a comment but I don't have enough reputation for that.
$('.clickable-row').on("click",function(){
window.location = $(this).data('href');
return false;
});
$("td > a").on("click",function(e){
e.stopPropagation();
});
or
jQuery(document).ready(function($) {
$('.clickable-row').on("click",function(){
window.location = $(this).data('href');
return false;
});
$("td > a").on("click",function(e){
e.stopPropagation();
});
});

jQuery StopPropagation issue

I want to close the div if someone clicked outside that div. I have the below code:
$('body').click(function(e) {
$('div.test').slideUp('slow');
});
$('div.test').live('click',function(e) {
e.stopPropagation();
});
But the issue is that when someone click inside the div, the div itself is closing. I want to prevent that. After debugging I found a weird stuff the debugger is hitting the $(body).click first instead of $(div.test), May I know the reason for this? Can you help me in fixing the issue?
The problem is with your use of live.
live is a way of saying "bind a handler to the root element and capture any events that originated on an element matching a selector". It's a short form of delegate. This is possible because of "bubbling": events on elements are triggered on the element's ancestors as well.
If you do not specify otherwise, live binds the event handler to the document. The event handler on the body will be triggered first since the event won't have bubbled up to the document handler, where the e.stopPropagation() is.
The easiest solution would be to change live to click:
$('div.test').click(function(e) {
If you need to use live, introduce a container element, and handle the event there. I'll use delegate as I prefer its syntax, but you could use live if you preferred:
$('#container').delegate('div.test', 'click', function(e) {
e.stopPropagation();
});
The event is handled on #container and propagation is stopped, so the event never reaches the body's event handler.
What happens if you handle the body click with live() too?
I believe the live click handler doesn't propagate the event in the same way as a standard click. See this documentation.
I believe the problem arises because you are setting a click handler to <body>
I tried the same thing with <p> instead of <body> and it seems to work fine.
Here's a relevant fiddle:
http://jsfiddle.net/seNXV/7/
live() does not stop propagation. Says do in the jQuery docs.
You need to use delegate()

Categories