Strange Behaviour on changing the property of button in Jquery - javascript

I am disabling a button on click handler and it is strange that once the button is disabled, it doesn't get submitted after that.
It varies from browser to browser. Firefox allows the submission of the form after disabling the submit button but chrome and IE are blocking it
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
<script>
$(function(){
$("#btn").on("click",function(){
$(this).prop('disabled','true');
alert('clicked');
});
$("#frm").on("submit",function(){
alert("submit1");
});
$("#frm").on("submit",function(){
alert("submit2");
});
})
</script>
</head>
<body>
<form id="frm" action="#">
<input type='submit' id="btn"/>
</form>
</body>
This is a strange behavior that submit is being prevented on disabling the buttton.
what could be the probable reason.
output which i am getting in Chrome and IE are
click is executed and then script close
why isnt it in order
execution of click
then execution of submits

I think you're saying that when you disable the submit button as it is clicked, the form doesn't get submitted and you want it to.
I believe the reason for that is that the click event occurs before the button's activation behavior (which is the HTML5 spec's term for "what it does"). The activation behavior of an enabled ("mutable" as the spec puts it) submit button is, of course, to trigger form submission. But by the time the browser is deciding on the activation behavior, which is after the click handlers have been fired, you've disabled the button. According to the spec, a disabled ("non-mutable" as they put it) submit button has no activation behavior, and so the form is not submitted.
So the question becomes: When does the browser decide what activation behavior to use, before the click handlers or after them? For the answer to that, we turn to the DOM Events spec, which tells us that first the click occurs, then the activation behavior occurs. So it would appear that Chrome is deciding after the click event is complete, which is a reasonable read of the spec; Firefox would appear to be deciding before the click event is complete.
Pragmatically, though, the reality is that if you disable the button within the click handler, you are not guaranteed to get the form submission. To work around that, you can very briefly delay disabling the button, so the event completes without the button having been disabled:
$("#btn").on("click",function(){
var btn = this;
setTimeout(function() {
btn.disabled = true;
}, 0);
alert('clicked');
});
Live Example | Source
Side note: In the above, I've also (effectively) replaced $(this).prop("disabled", true"); with (effectively) this.disabled = true;. There's no reason to wrap the element in a jQuery wrapper just to set a simple property value.

Should fix your issue:
$("#btn").on("click", function (e) {
e.preventDefault();
$(this).prop('disabled', true).closest('form').submit();
//to submit FORM without firing jquery's attached handlers
//$(this).prop('disabled', true).closest('form').get(0).submit();
alert('clicked');
});
DEMO

Related

Why can't we bind functions to :disabled input fields?

When i try to bind JavaScript/jQuery .hover or .click functions to an :disabled input field, none of the functions gets fired.
See the snippet below.
$(document).ready(function() {
var button_1 = $("#button_1");
button_1.hover( function() {
console.log("Hover event button 1");
});
button_1.click( function() {
console.log("Click event button 1");
});
});
function button_2_click() {
console.log("Click even button 3");
}
function button_2_hover() {
console.log("Hover even button 3");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Hover over one of the buttons, and you'll see none of the console messages gets logged. When removing the `disabled` property, all events are fired.</p>
<button id="button_1" disabled>Disabled 1</button>
<button id="button_2" onmouseover="button_2_hover();" onclick="button_2_click();" disabled>Disabled 2</button>
MDN says the following about the disabled property:
Indicates whether the element is disabled or not. If this attribute is
set to true the element is disabled. Disabled elements are usually
drawn with grayed-out text. If the element is disabled, it does not
respond to user actions, it cannot be focused, and the command event
will not fire.
What i tried to archieve is, when a user :hover's over an button:disabled, a message would be shown.
I know i could use a title="text" for that. However, thats not the case. I use an small popup at the right top corner with an message. The message is stored inside an javascript object.
My question:
How can i make an workaroud for this? Or is it just not possible to bind .hover() or onmousemove functions the disabled input fields?
The click part is per specification:
A form control that is disabled must prevent any click events that are queued on the user interaction task source from being dispatched on the element.
It would appear that the user agents you're testing in take it further and also prevent the events related to hovering (Chrome and IE seem to, for instance). Other user agents may not (Firefox allows the events related to hover, for instance.)
If you want those events, you could leave the buttons enabled and then style them to look disabled and prevent clicking them doing what they otherwise do, although it may make for a confusing user experience.
Alternately, you could put a span inside the button, and hook the events on that:
$(document).ready(function() {
var button_1 = $("#button_1 span");
button_1.hover( function() {
console.log("Hover event button 1");
});
button_1.click( function() {
console.log("Click event button 1");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Hover over one of the buttons, and you'll see none of the console messages gets logged. When removing the `disabled` property, all events are fired.</p>
<button id="button_1" disabled><span>Disabled 1</span></button>
There are parts of the button that won't trigger the events (bits of the surround), though you could probably fix that with CSS...

Clicking submit button using javascript and Firefox

I guess I have never tried to do this before ... I have a button on a page.
<input type="submit" id="btn" value="Submit">
And a javascript function that includes:
function clickit()
{
alert(document.getElementById('btn').value);
document.getElementById('btn').click();
}
Using Firefox, the button is not clicked - i.e. the form is not submitted. The alert shows, but the form does not get submitted. Why won't Firefox click a button?
Use a div or anything besides a INPUT element if you want to bind the click event to it. If <INPUT> is inside a form body, you might run into weird issues.
If you just need to submit a form with a button I would recommend that you just use a <div> element with a click handler rather than an input. It will give you a little more flexibility. If you do that then you should be able to just select your form and use the submit() API to submit the form.
If you really can't modify the code enough to do this and are having trouble selecting and submitting here is how you will need to do that using both jQuery and DOM.
The jQuery Way:
$("my selector").trigger("click")
You may run into issues around focus if you're running in PhantomJS or you've got a window like a test runner that is not in focus. In this case you can use:
$(<my selector>).triggerHandler(<my event>)
The DOM API way
This will just trigger the event (the equivalent of the first example)
// Create the event
var event = new CustomEvent("name-of-event", { "detail": "Example of an event" });
// Dispatch/Trigger/Fire the event
document.dispatchEvent(event);
You can also simulate a click with the actual DOM method
var button = document.getElementById('my-button');
button.click();
Why won't Firefox click a button?
I seem to recall that early versions of Firefox didn't allow calling of listeners that way for security reasons. However, I think those reasons have been addressed in other ways and now you should be able to call the click handler directly. The following submits the form in Firefox 34:
<form onsubmit="alert('submitted!!')">
<input name="foo" value="foo">
<input type="submit" id="aa">
</form>
<br>
<button onclick="document.getElementById('aa').click();">Click the submit button</button>
The form's submit listener is called and the form is submitted, so calling the submit button's click method is doing what it's supposed to.
This method doesn't work for all listeners though, click is a special case, see W3C DOM Level 3 Events Specification, ยง3.5 Activation triggers and behavior.

html-javascript: page refreshes whenever an event is fired

I have an html page with buttons and such, to which I assign event listeners. Whenever one of the buttons is clicked, the page goes back to its original state, as if the browser had been closed and opened again. So if I have text fields into which I've inputted some info, they will be cleared as soon as a button is clicked, even if its event listener does nothing.
Likewise, if I include this event listener into the html, <body onload="pageLoaded();">, the pageLoaded() function will be called whenever a button is clicked.
Why is this happening, and how can I prevent it from happening?
Presumably you are using submit buttons, which will submit the form they are in unless you cancel the default action.
eventObject.preventDefault();
See the documentation.
Maybe your click event listener was added to a link or a button within a form. If so, you may add return false a the end of the listener to prevent the default behaviour being executed.
var link = $("#mybutton");
link.click(function() {
alert("clicked");
return false;
});
Setting the button type to "button" will resolve this issue. The default type is "submit" which as the others have said will submit the form.
<button type="button">Button</button>

How to tell onBlur not to hide the submit button when clicked?

My blur event hides the submit button; but doing that seems to cancel the submit event. I only want to hide when the submit itself wasn't clicked. How can I determine if the focus was lost due to the submit, or due to just wandering off elsewhere?
<form action="" method="post">
<textarea id="message" name="message"></textarea>
<input type="submit" id="share" value="Share">
</form>
...
$('textarea').blur(function(){
$('#share').hide()
})
$('textarea').focus(function(){
$('#share').show()
})
Setting a timeout to allow the submit event to fire before coming back to the blur seems a bit hacky to me. Can't we do better than that? Can I tell the blur not to block other events? or search the dom for a pending submit event? or ... ?
Solution
for today is based on the ticked answer, but simpler. Use jquery's "fadeOut" routine to
delay the hidden status of the submit button until after the submit event has fired, and
make the user feel like their submission is being handled
.
$('textarea').blur(function(){
$('#share').fadeOut()
})
$('textarea').focus(function(){
$('#share').fadeIn()
})
It's indirect, and not really what I was looking for, but it seems clear that direct manipulation of the event queue - such as writing onBlur to say "if they did not click submit then hide the submit button" - is perhaps not technically possible.
This is one option, though a bit hacky using jQuery .queue() and .clearQueue() to set an animation queue and instantly clear it before anything happens:
$(function() {
$("#message").blur(function() {
$("#share").delay(100).fadeOut();
});
$("#share").click(function() {
$(this).clearQueue();
});
});
Note: Requires jQuery 1.4+
If you hide the Submit button, the submit will cancel.
Try making it completely transparent instead.
EDIT: For example:
$('#share').css({ opacity: 0, position: 'absolute' });

jQuery / JavaScript Bubbling and stopPropagation doesn't work

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.

Categories

Resources