jQuery / JavaScript Bubbling and stopPropagation doesn't work - javascript

I'm making an edit button which pops up a modal box with a form to edit it. jQuery then sends this form to my server and I get a JSON response back. However, due to my bubbling issue, if I click on, for example, all of the edit buttons and then click on the last one and change a field, it does it across all of them.
$('.edit').click(function(event){
//more code...
modal_submit(the_id);
event.stopPropagation();
});
and then the submit event:
function modal_submit(the_id){
$('#modal form').submit(function(){
//This will alert every time I have EVER clicked on an edit button
alert(the_id);
return false;
});
}
finally all of this is inside of a getScript:
$.getScript('js/edit.js',function(){
create_edit_btn();
});
I've only used this 1 other time, and it worked, but I also had to do this.event.stopPropagation, but if I do "this" now it says this.event is undefined, but like I said, this exact code worked before for another script I did.
Does anyone have any ideas? :\
EDIT:
the html is:
<li>
<input id="item1" type="checkbox" value="webhosting|15" title="Web Hosting">
<p>Hosting for your web site</p>
</li>

An event can have multiple event listeners. Each time you use $(element).submit(whateverFunction) you are adding another whateverFunction to the submit event. If you only want only the last listener to be the action that is taken upon envoking the event, try doing this:
function modal_submit(the_id){
$('#modal form').unbind(); // this will remove all other event listeners from this element
$('#modal form').submit(function(){
//This will alert every time I have EVER clicked on an edit button
alert(the_id);
return false;
});

I think you event.stoppropagation does its job already. It stopped all the bubbling on the click event of the button (ie, if you try checking the document body, it won't have mouse click event anymore). The reason why codes within submit of the form is still executed, is because this is called by the button's default action.
Together with event.stoppropagation(), I suggest you include this:
event.preventDefault();
So that the default action will not used and only the codes within your handler is executed.

Is this in the function that creates edit buttons?
$('.edit').click(function(event){
//more code...
modal_submit(the_id);
event.stopPropagation();
});
If it this, then it will add this handler multiple times to the same elements, causing a flurry of alerts. Use live, which will place the handler on every matched element, even if is is added later in execution.

Related

How do I stop a event propagation?

I understand I need to use the stopPropigation, but how do I get a reference to the event from an onClick function. And Also how do I find out how an event was attached to the element. So I have a simple button like this:
<button class="btn btn-default" onclick="addRoleToReportClicked()">
the function looks like this:
function addRoleToReportClicked() {
$('#addRoleDiv').show();
}
So Simple. And was working fine. Unitl I just did an update of code from work. Now it does show the div, but then proceeds to do other stuff, namely re-load the whole page.
I am using firefox and I see that the button now has a "bubbling" and "DOM0" event handlers. I would love to know how that got there, but more importantly 2 questions:
How do I stop this in the addRoleToReportClicked() function? (I assume that I can stopPropogation, but how do I get a handle to the event?
Is there any easy way to find what code is adding these event listeners? I tried the debug, but that did not show me anything. I don't want to go through 20+ js files and thousands of lines of code to find it. But I do want to hunt down the developer and shoot him.
UPDATE
I tried this:
$("#addRoleDivButton").unbind("click").on("click", function(e){
e.cancelBubble = true;
e.stopPropagation();
e.bubbles = false;
$('#addRoleDiv').show();
});
None of it worked. Taking the idea of a form submition, I noticed that all the other buttons on the page were working fine, but this one was inside a from. So I changed the tag from a "button" to an "a" and it works fine. Someone attached a submit() to every button inside a form tag. How do I stop a submit?
There are a bunch of ways you can stop bubbling, the most popular two ways are -
stop the propagation -
function addRoleToReportClicked(e) {
e.stopPropagation();
$('#addRoleDiv').show();
}
or, unbind the other handlers -
<button class="btn btn-default btn-1">
$(".btn-1").unbind("click").on("click", function(){
$('#addRoleDiv').show();
});
Since you haven't accepted any of the above answers, I'll add this here.
function addRoleToReportClicked(event) {
$('#addRoleDiv').show();
return false;
}
By adding the return false;, it should stop any other functions running. If this or any of the other solutions don't work then there must be something else refreshing the page.
Try and debug it yourself using the chrome or firefox debuggers.
1) the event is passed as argument to the callback function
function addRoleToReportClicked(event) {
event.stopPropagation();
$('#addRoleDiv').show();
}
stopPropagation() will prevent the event from trigger callbacks on parent elements.
You may want to use stopImmediatePropagation() in some cases: I leave to you to look for the difference
jquery: stopPropagation vs stopImmediatePropagation
Note that you may also/instead want to prevent the browser to execute its default actions: (for example a click on a link would also open the link, a click on a submit button would send the form).
In that case you have event.preventDefafult()
EDIT:
Note that if addRoleToReportClicked is invoked because you have
<button class="btn btn-default" onclick="addRoleToReportClicked()">
Then the event object is not passed to the function
You may remove the onclick attribute.
Then if you need to catch the click on the button use Jquery's on('click')
2) Google Chrome (Dev Tools) tells you what event listeners are attached to an element (just right-click and inspect the element).
AFAIK it doesn't tell you where on the code the event listener were set up.
But if you perform a global search on your sources for the name of the event listener you should find it.

Triggering button click in jQuery not working

Using dot.js I'm adding a button to a specific web page that, when clicked, should add some text to a text field and then trigger another button to also be clicked. I simulate this by adding a click handler to my button which has this code:
var button = $('.some-class').find('button')[0];
console.log(button); // element I expect
button.click();
However, this doesn't work and I'm not sure why. If instead of .click() I perform .remove(), the button is removed from the page. If I use the console to execute the same code, the button does get clicked. This tells me I do have the right element, but there is something wrong with the click() event specifically.
Can someone explain why this isn't working in either Safari or Chrome? I've tried a lot of different things, but I'm new to jQuery so I'm probably missing some detail in how that works.
We went to the bottom of this in the chat. What probably caused the problem was another event-handler attached to (possibly) body, that undid the click.
So the solution was to stop the event from propagating:
event.stopPropagation();
While assigning the click event handler to the button you should use jquery on
This should ensure that whenever a new button with added with same selector (as in when event was assigned), event handled will be assigned to that button
Some examples here
The problem is the click() function is from jquery and you're attempting to fire the click function from the DOM object.
Try
$(button).click();
Here's a plunk.
http://plnkr.co/edit/2pcgVt
You can use the following statement.
var button = $('.some-class').find('button')[0].trigger('click');
try jquery's trigger() function:
$(button).trigger('click');
see jsfiddle: https://jsfiddle.net/665hjqwk/

jQuery Simulate onClick

I am trying to simulate an onclick event on a drop down.
I have an IE object that is going to a page and I need to change a dropdown which has an onchange event:
$('select[name="blah"]').val(3).trigger('change');
$('select[name="blah"]').change(function(){
alert('changed');
});
When I try this, I would expect the alert to fire as it's technically an onchange.
http://jsfiddle.net/3y5hmyf0/
Is there a way to acomplish this?
More Details
My tool is controlling another IE page through an object. It navigates to the page and finds the select drop down on the page. From there, if you did it manually it has an onchange event when making a selection.
I am trying to get jQuery to simulate as if it was being clicked by a person to it triggers that on change event.
I have tried .trigger and .change and couldnt get either of them to work.
The only reason your code does not work is the order you are executing it. You need to connect the handler before triggering it:
JSFiddle: http://jsfiddle.net/3y5hmyf0/1/
// Wire up event handler
$('select[name="blah"]').change(function(){
alert('changed');
});
// Now generate the event
$('select[name="blah"]').val(3).trigger('change');
Note: Your manual change trigger is still required as a change event must normally be triggered by user interaction. Setting the value is not enough.
$('select[name="blah"]').change(function(){
NotifyChanged();
});
function NotifyChanged() {
alert('changed');
}
If you want to test the logic in the changed function, just call it.

JavaScript Click event fires via the Enter Key but not via the Mouse

Some code that looks like the following is firing the click event via the Enter key, but is not responding to the mouse click.
//a is an anchor element
a.addEventListener('click', function (e)
{
//Do Stuff...
});
This page demonstrates the problem. The relevant bit of code is at line 176. This is in the middle of development and currently only (sort of) works in Chrome.
Also, I just verified that it works if I use mousedown, so it's not just the case of an invisible element sitting in front of the anchor.
Any ideas?
Edit: Now that you've shown us the actual code you're using, the problem is related to the fact that the autoSuggest() function has it's own click handler and in that click handler, it is clearing the container which removes all <a> elements in the container so your link object gets destroyed (probably before your click event gets to process). So, you can get events that happen before the click (like mousedown), but after a click, the element is removed from the DOM.
If you tell us what you're trying to actually do when an auto-suggest item is clicked that is different than the default behavior of the autoSuggest() function and you point to any documentation for that function, then perhaps we could offer a better way to solve your issue.
The link may be firing and taking you off to a new page (or reloading the current page), thus preventing you from seeing the click code run. Usually when you process a click event on a link element, you need to prevent the default behavior:
//a is an anchor element
a.addEventListener('click', function (e) {
e.preventDefault();
//Do Stuff...
});
Another possibility is that you are trying to install the event handler too soon either before the DOM has been loaded or before this particular link has been created and thus no actual click event handler is attached to the DOM object. You can verify whether the event handler is even getting called by temporarily putting an alert("Click handler called"); in the event handler and see if that pops up or not.

How can I trigger an element's default event within an event handler?

I have an HTML button that needs to check several conditions, and if they pass allow the default action to occur.
The following works in Firefox, but it fails in IE. I setup a click handler on the button:
Ext.get('send').on('click', handleSend, this, {
preventDefault: true
});
which pops up one of several message boxes if one of the conditions isn't met. If all conditions are met, I remove the click listener from the button and click the button again:
Ext.get('send').un('click', handleSend, this);
Ext.getDom('send').click();
As far as I can tell, it fails in IE (and possibly other browsers) because click() isn't a standard function for a DOM element.
If the default action were a simple form submit, I could just do that after the checks pass, but we're using Tapestry 4 with a listener, which doesn't get executed on a normal form submit.
I've tried submitting the form with
tapestry.form.submit('composeForm', 'doSend');
but the doSend listener isn't getting called.
Conditionally allowing the default event is the best solution I've come up with, but there are a couple of options that may be possible:
Is there some other way to cause a Tapestry 4 listener to be fired from within Javascript?
Is there any way to recognize the normal form submit in my Tapestry Page and thereby trigger the listener?
JSFiddle added
In this jsfiddle, the default action is to submit the form; this is prevented when the checkbox is unchecked. When checked it removes the handler, but the call to click() doesn't work in IE.
Is there a way to simulate a click in IE?
Update
Another snag in the problem is that I have to display an 'are you sure' dialog, so in order to give them time to answer, the event has to be stopped. If they click OK, the default action needs to occur. JSFiddle doesn't seem to have ExtJS widgets like MessageBox, so I'm not sure how to demo this behavior.
At #Ivan's suggestion I tried
Ext.getDom('send').fireEvent('onclick');
but it returns false, meaning the event is being cancelled somewhere. I then tried
var evt = document.createEvent("Event");
evt.initEvent('click', false, false);
var cancelled = Ext.getDom('send').fireEvent('onclick', evt);
but IE9 says that document.createEvent doesn't exist, even though this is how MSDN says to do it.
If all conditions are met, I remove the click listener from the button
and click the button again:
Don't.
You should rather check the conditions in the click handler and call stopEvent there like so:
Ext.get('send').on('click', handleClick);
function handleClick(e) {
if (condition) {
e.stopEvent();
}
}
Internet explorer does not support click. You should use fireEvent method instead e.g.
Ext.getDom('send').fireEvent('onclick');
That should work for IE. For other browsers I guess click is ok. Anyway If I should do similar task I'll try to write an adapter for tapestry and use tapestry javascript library.
There's a listener parameter on Form components; from the Tapestry 4 doc:
Default listener to be invoked when the form is submitted. Invoked
only if another listener (success, cancel or refresh) is not invoked.
Setting this parameter to my listener method like so:
<binding name="listener" value="listener:doSend" />
causes a Tapestry form submit
tapestry.form.submit('myFormId');
to trigger the listener.

Categories

Resources