Click event not firing with dynamically create buttons - javascript

I have dynamically created the buttons in a div. And binding the click and other events for the buttons. But the problem is, click event fired only one for first clicked button. It happens same for the other binding events. The sample code is
$('#divButtons input[type=button]').each(function () {
$(this).bind('mouseover', function (e) {
// some work
}).bind('mouseout', function (e) {
// some work
}).bind('click', function (e) {
// some work
});
});
It works good when bind it on document.ready() But in my case buttons created far after DOM ready.
I also want to know why it behaves like this...?

If using jQuery 1.7+ go for on(), and there's really no need for each() :
$(document).on({
mouseover: function(e) {
// some work
},
mouseout: function(e) {
// some work
},
click: function(e) {
// some work
}
}, '#divButtons input[type=button]');
replace document with nearest non dynamic element for delegated event handler.

Related

how to execute everything in jquery when something is done [duplicate]

Is there a way to have keyup, keypress, blur, and change events call the same function in one line or do I have to do them separately?
The problem I have is that I need to validate some data with a db lookup and would like to make sure validation is not missed in any case, whether it is typed or pasted into the box.
You can use .on() to bind a function to multiple events:
$('#element').on('keyup keypress blur change', function(e) {
// e.type is the type of event fired
});
Or just pass the function as the parameter to normal event functions:
var myFunction = function() {
...
}
$('#element')
.keyup(myFunction)
.keypress(myFunction)
.blur(myFunction)
.change(myFunction)
As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document. For earlier versions, the .bind() method is used for attaching an event handler directly to elements.
$(document).on('mouseover mouseout',".brand", function () {
$(".star").toggleClass("hovered");
})
I was looking for a way to get the event type when jQuery listens for several events at once, and Google put me here.
So, for those interested, event.type is my answer :
$('#element').on('keyup keypress blur change', function(event) {
alert(event.type); // keyup OR keypress OR blur OR change
});
More info in the jQuery doc.
You can use bind method to attach function to several events. Just pass the event names and the handler function as in this code:
$('#foo').bind('mouseenter mouseleave', function() {
$(this).toggleClass('entered');
});
Another option is to use chaining support of jquery api.
Is there a way to have keyup, keypress, blur, and change events call the same function in one line?
It's possible using .on(), which accepts the following structure: .on( events [, selector ] [, data ], handler ), so you can pass multiple events to this method. In your case it should look like this:
$('#target').on('keyup keypress blur change', function(e) {
// "e" is an event, you can detect the type of event using "e.type"
});
And here is the live example:
$('#target').on('keyup keypress blur change', function(e) {
console.log(`"${e.type.toUpperCase()}" event happened`)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="target">
If you attach the same event handler to several events, you often run into the issue of more than one of them firing at once (e.g. user presses tab after editing; keydown, change, and blur might all fire).
It sounds like what you actually want is something like this:
$('#ValidatedInput').keydown(function(evt) {
// If enter is pressed
if (evt.keyCode === 13) {
evt.preventDefault();
// If changes have been made to the input's value,
// blur() will result in a change event being fired.
this.blur();
}
});
$('#ValidatedInput').change(function(evt) {
var valueToValidate = this.value;
// Your validation callback/logic here.
});
This is how i do it.
$("input[name='title']").on({
"change keyup": function(e) {
var slug = $(this).val().split(" ").join("-").toLowerCase();
$("input[name='slug']").val(slug);
},
});
You could define the function that you would like to reuse as below:
var foo = function() {...}
And later you can set however many event listeners you want on your object to trigger that function using on('event') leaving a space in between as shown below:
$('#selector').on('keyup keypress blur change paste cut', foo);
The answer by Tatu is how I would intuitively do it, but I have experienced some problems in Internet Explorer with this way of nesting/binding the events, even though it is done through the .on() method.
I havn't been able to pinpoint exactly which versions of jQuery this is the problem with. But I sometimes see the problem in the following versions:
2.0.2
1.10.1
1.6.4
Mobile 1.3.0b1
Mobile 1.4.2
Mobile 1.2.0
My workaround have been to first define the function,
function myFunction() {
...
}
and then handle the events individually
// Call individually due to IE not handling binds properly
$(window).on("scroll", myFunction);
$(window).on("resize", myFunction);
This is not the prettiest solution, but it works for me, and I thought I would put it out there to help others that might stumble upon this issue
$("element").on("event1 event2 event..n", function() {
//execution
});
This tutorial is about handling multiple events.
It's simple to implement this with the built-in DOM methods without a big library like jQuery, if you want, it just takes a bit more code - iterate over an array of event names, and add a listener for each:
function validate(event) {
// ...
}
const element = document.querySelector('#element');
['keyup', 'keypress', 'blur', 'change'].forEach((eventName) => {
element.addEventListener(eventName, validate);
});
If you'd want to mimic adding to more than 1 element:
const elements = document.querySelectorAll('.commonSelector');
['keyup', 'keypress', 'blur', 'change'].forEach((eventName) => {
elements.forEach(element => {
element.addEventListener(eventName, validate);
});
});
Instead of:
$('#element').on('keyup keypress blur change', function(e) {
// e.type is the type of event fired
});
You can use:
$('#element').on('input', function(e) {
// e.type is the type of event fired
});
input is trigerred for keyup keypress blur change events even for paste!
But to prevent multiple triggering:
var a;
var foo = function() {
clearTimeout(a);
a=setTimeout(function(){
//your code
console.log("Runned")
},50);
}
$('textarea').on('blur change', foo);

Turning Off Specific Click Event

JSFIDDLE: http://jsfiddle.net/w55usyqk/
When you click the div there are two separate click events fired. They print out "click" and "clicked" respectively in the console log.
$("div").on("click", function() { console.log("click"); });
$("div").on("click", function() { console.log("clicked"); });
If you tap on the button it will remove both event declarations from the div object
$("button").on("click", function() { $("div").off("click"); });
However, what if I just needed to remove a single click event? Is this stored in some sort of event array where I could do something along the lines of $("div").off("click")[1]; or is it impossible to turn off one without turning off the other as well?
I did try looking for the answer if it's been posted before. I think this is one of those questions that's hard to word, so though there may be an answer out there, it's difficult to pin down.
You can use namespaces to easily do this. When you create your event handlers, add the namespace after the event. Ex:
$("div").on("click.namespace1", function() { console.log("click"); });
$("div").on("click.namespace2", function() { console.log("clicked"); });
then for your button, use the namespace of the event to remove:
// remove only the event for namespace2
$("button").on("click", function() { $("div").off(".namespace2"); });
jsFiddle example
Some more on namespaces for events:
An event name can be qualified by event namespaces that simplify
removing or triggering the event. For example, "click.myPlugin.simple"
defines both the myPlugin and simple namespaces for this particular
click event. A click event handler attached via that string could be
removed with .off("click.myPlugin") or .off("click.simple") without
disturbing other click handlers attached to the elements. Namespaces
are similar to CSS classes in that they are not hierarchical; only one
name needs to match. Namespaces beginning with an underscore are
reserved for jQuery's use.
Use named functions as event handlers, so you can then reference what handler you want to unbind:
function clicOne() {console.log("click");};
function clicTwo() {console.log("clicked");};
$("div").on("click", clickOne);
$("div").on("click", clicTwo);
$("button").on("click", function() { $("div").off("click", clickOne); });

Event delegation on parent only works with some events

Why am I able to listen to certain events using event delegation on window.parent.document but not others? Specifically I found that I was able to listen to a button's click event, but trying to do the same for the jQueryUI's dialogbeforeclose event wouldn't trigger the event handler.
For example binding to a click event for a button like the following worked
$(window.parent.document).on('click', '#btnTest', function () {
alert('Button clicked');
});
However trying to listen to the custom jQuery UI event like the following doesn't (the same code works on the parent page itself when binding to the document)
$(window.parent.document).on('dialogbeforeclose', function () {
alert('Dialog closing');
});
But binding it to the parent's body instead does
window.parent.$('body').on("dialogbeforeclose", function(event, ui) {
alert('Bound on body');
});
For some additional context, I have a parent html page that has a jQuery UI dialog which has a iFrame within it.
Parent HTML
<div id="btnCnt">
<input type="button" id="btnTest" value="Test 2"/>
</div>
<div id="popUpCnt" >
<iframe id="frmTest">
</iframe>
</div>
When an event is triggered using .trigger() (which is the case for custom events) jQuery goes through and triggers the events that are stored in that instance of jQuery's data cache. Since you bound to the event with a different instance of jQuery than the one that triggered the event, your event handler was never triggered. For example, see this fiddle:
http://jsfiddle.net/EJg8b/
jq2 = $.noConflict();
jq1 = $;
jq1('body').on('click', function () {
console.log('jq1 click event!');
});
jq2('body').on('click', function () {
console.log('jq2 click event!');
});
jq1('body').on('myCustomEvent', function () {
console.log('jq1 myCustomEvent event!');
});
jq2('body').on('myCustomEvent', function () {
console.log('jq2 myCustomEvent event!');
});
function onButtonClick() {
jq1('button').trigger('myCustomEvent');
}
Because the custom event was triggered with jq1, only the event bound with jq1 was able to receive it. The click on the other hand was a native event, and therefore was picked up by both.

stopPropagation() of a different event

How can I listen to a change event on a checkbox without triggering a click event on its container?
<label><input type="checkbox"> Hello world</label>
I want to trigger an action on the checkbox's change event, but I don't want it to bubble up to a click event on the label.
(function ($) {
$('input').change(function (v) {
v.stopPropagation();
});
$('label').click(function () {
alert('You should not see this message if you click the checkbox itself!');
});
})(jQuery);
http://jsfiddle.net/r49PA/
Any ideas? Thanks!
The issue is that two events are triggered when you click the checkbox -- a change and a click. You're only catching the change, so the click isn't ever being told to stop propagation. You need to either add a second handler on the checkbox for click events, or combine one handler to catch both types, like this:
$('input').on('change, click', function (v) {
v.stopPropagation();
});
Here's a jsFiddle demonstrating a combined handler: http://jsfiddle.net/r49PA/4/
You can stop propagation on click event instead of change event since you bind click event for the parent label:
$('input').click(function (v) {
v.stopPropagation();
});
Updated Fiddle
With plain javascript you can do something like this:
var stopPropagation = false;
selector.addEventListener('mousedown', function(event) {
// simulating hold event
setTimeout(function() {
stopPropagation = true;
// do whatever you want on the `hold` event
})
}
selector.addEventListener('click', function(event) {
if (stopPropagation) { event.stopPropagation(); return false; }
// regular event code continues here...
}
Since mousedown and click events are overlapping, we want the click event to not be triggered when we are trying to get the hold state. This little helper flag variable stopPropagation does the trick.

Set the mouseover Attribute of a div using JQuery

I would like to set an attribute for a div. I have done this:
$('#row-img_1').onmouseover = function (){ alert('foo'); };
$('#row-img_2').onmouseout = function (){ alert('foo2'); };
However, the above has not worked, it does not alert when mouse is over or when it moves out.
I have also tried the $('#row-img_1').attr(); and I could not get this to work either.
I am aware that I should be using a more effective event handling system but my divs are dynamically generated. Plus this is a small project. ;)
Thanks all for any help.
You need to bind the event function to the element. Setting the event attributes has no effect, as they are interpreted only when the page is loading. Therefore, you need to connect the event callback in a different manner:
$('#row-img_1').mouseover(function() {
alert('foo');
});
$('#row-img_2').mouseout(function() {
alert('foo2');
});
In jQuery, there are two more events: mouseenter and mouseleave. These are similar, but mouseenter does not fire upon moving the mouse from a child element to the main element, whereas mouseover will fire the event again. The same logic applies to mouseleave vs mouseout.
However, jquery provides a shortcut for this kind of usage: the .hover method.
$('#row-img_1').bind('mouseenter', function(event){
// event handler for mouseenter
});
$('#row-img_1').bind('mouseleave', function(event){
// event handler for mouseleave
});
or use jQuerys hover event which effectivly does the same
$('#row-img_1').hover(function(){
// event handler for mouseenter
}, function(){
// event handler for mouseleave
});
Events are registered as functions passed as attributes, like this:
$('#row-img_1').mouseover(function (){ alert('foo'); });
$('#row-img_2').mouseout(function (){ alert('foo2'); });
Also, note the missing on from the onmouseover.
$('#row-img_1').mouseover(function() {
alert('foo');
});

Categories