Is it possible cancel a JavaScript event from another event? - javascript

I would like to know, is it possible to cancel the next JavaScript event in the queue from another event?
Problem:
I have two ASP.Net controls,
Age - TextBox
Save - Button
There are two JavaScript validation functions,
ValidateAge() - checks for Valid age (0 >= Age <= 140), provides an alert if invalid
ValidatePage() - checks for all the required fields in the page and saves if all the required fields are filled in
<asp:TextBox ID="txtAge" TabIndex="1" DataType = "String" runat="server" MaxLength="50" CssClass="textBox" Style="width: 150px" CausesValidation="true" onblur="return ValidateAge();"></asp:TextBox>
and there is an access key defined for button,
<asp:Button ID="btnSave" AccessKey="S" AssociatedControlID="btnSave" TabIndex="1" runat="server" CssClass="ButtonSaveNew" onclick="return ValidatePage();"></asp:Button>
Now if I press Alt+S with an invalid age in the Age field first the onblur of Age gets called (as I have set the AssociatedControlID) and then the onclickof the save button is called.
Now what happens is that irrespective of the age is valid or invalid the save gets executed.
I need to cancel the onclick event of button from the onblur event of the textbox, if the age is not valid.

What is probably happening is that your form is submitting, and thus the button isn't actually firing the onclick event (since it's not being clicked as such!). You'll likely notice the same behaviour if you hit enter within one of the form fields (even with the txtAge field!), as this also causes a form submit.
The easiest thing to do in this case is register the ValidatePage function as a handler for the submit event on the form:
<form onsubmit="ValidatePage()">
Though i appreciate you're using WebForms and thus it's likely this will be difficult. Whenever i've done client-side validation in WebForms I've always relied on the jQuery.validation plugin. If you're already reliant on jQuery this provides a very neat model to do validation. It doesn't play well with WebForms out of the box and you need to do a little playing around to get it working. Dave Ward's post here will likely be of help: http://encosia.com/using-jquery-validation-with-asp-net-webforms/

Is it possible cancel a java script event from another event?
No, generally it is not. Also, the blur event can't be canceled, and according to how to prevent blur() running when clicking a link in jQuery? it is complicated to hold the focus.
Yet, I don't think holding the focus when the user tries to leave a element (and focus the next input) is very userfriendly - only show a validation fail for the leaved input. The only event you really should prevent is submit, when validation has failed, and you then could focus the first invalid field.
var ageValid;
$("#txtAge").change(function validateAge(e) {
if(!isNaN(this.value) && this.value >= 0) {
ageValid = true;
} else {
$(this).addClass("invalid");
ageValid = false;
}
}).change();
$("#formid").submit(function validatePage(e) {
// maybe calls to the single validation functions?
if (! ageValid) {
e.preventDefault();
$("#txtAge").focus();
return false;
}
});

Related

jQuery Validation with "formnovalidate" in submit button outside the <form>

I have an edit form using the jQuery Validation plugin. It's part of an ASP.NET Core project, also using ASP.NET's Unobtrusive Validation plugin. The form has two submit buttons, posting to different handlers server-side:
Submit changes
Delete entry
"Submit changes" is working fine, however I'd like the "Delete" button to skip any client-side validation. Currently it won't post the form if any required fields are missing (or any other validation condition doesn't pass).
I've tried the HTML5 formnovalidate attribute on the "Delete" button without success. Is there an equivalent feature in the jQuery Validation plugin? If not, how would you bypass validation only for a specific submit button?
EDIT:
The "Delete" button is actually outside the <form> tag, but referencing the form by ID through the form attribute:
<form id="my-form">
<!-- form fields and submit button here -->
</form>
<button type="submit" form="my-form" noformvalidate asp-page-handler="Delete">
Delete entry
</button>
I've found that when moving the "Delete" button inside the <form>, the noformvalidate attribute works as expected. I would really like to keep this button outside the <form> tag (due to the page's layout), though I might be able to work around it if there's no other way.
Any ideas on how to make it skip validation while placed outside the form?
The problem you have seems to be summarized in this issue:
Typical save vs submit button where save does not validate and submit
does. Save button is declared with the formnovalidate attrribute. Only
thing is that these buttons are outside of the form itself.
See, the plugin expects the submit buttons to be inside your form. It actually still handles both 'preventing' flags - cancel class and formnovalidate attribute - within click handler propagated from buttons to the top of the form (source):
// "this" is jQuery-wrapped HTMLFormElement with validator attaching
this.on( "click.validate", ":submit", function( event ) {
// Track the used submit button to properly handle scripted
// submits later.
validator.submitButton = event.currentTarget;
// Allow suppressing validation by adding a cancel class to the submit button
if ( $( this ).hasClass( "cancel" ) ) {
validator.cancelSubmit = true;
}
// Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
validator.cancelSubmit = true;
}
} );
... which clearly doesn't work if buttons are outside of form DOM hierarchy, like in your case. Only submit.validate handler is fired, but it expects to check validator.cancelSubmit flag (and set it to false if it's truthy).
One idea that comes to mind is to place your own click handler on Delete button that will override that flag. Validator instance is accessible through form $.data, as usually with jQuery plugins:
const validator = $.data(form, 'validator');
Perhaps you are looking for something like this:
var $frm = $('#my-form')
, frm = $frm[0]
, $btnsubmit = $('button[type="submit"]');
frm.addEventListener('submit', (evt) => {
var skipValidation = evt.submitter.hasAttribute('formnovalidate')
, validator = $frm.data('validator');
skipValidation && validator !== undefined
? (validator.cancelSubmit = true)
: ($frm.valid() && $btnsubmit.prop('disabled', true));
})
here I'm using a mix of vanilla JS and JQuery because not all submit-event properties are available in JQuery and is not so recommended to access JQuery data using vanilla JS.
In this case, there is no matter where are declared your submit-buttons but... you should be sure to execute the above script before $.validator.unobtrusive.parse(document) that mean before validator.unobtrusive become obtrusive.

Run code when user presses certain key in a textbox

I have an ASP.net textbox that the user needs to enter emails. I need to detect when the user types a semi-colon(;) then unhide a textbox and set the focus to that textbox.
Disclaimer: This might seem a little "hacky" and I'm sure there are better ways of doing this.
You can use the onkeypress of the textbox, set that to a JavaScript function. In the JavaScript function, programmatically "unhide" and give focus to your other textbox on the client-side. No post-back required.
JavaScript:
function checkForSemicolons(event) {
var txtEmail = document.getElementById("<%= txtEmail.ClientID %>");
if (event.keyCode === 59) {
// unhide other textbox and give focus to it
}
}
ASPX:
<asp:TextBox ID="txtEmail" onkeypress="checkForSemicolons(event)" runat="server" />
OnKeypress event is fired from the client side, so you need do catch that from the client script.
You can use javascript to cause a postback and than send the parameters to the server-side, but usually you can handle all from the client.
On jquery you would have somethig like this:
$("TextboxID").keypress(function(e){
//do something
//If you want to cause a postback use " __doPostBack('EventTaarget','Parameters');"
//you can capture the key that was pressed on e.keycode (for keycodes list, check: http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes)
})
On the code behind you can add some code to capture this event on page_load.
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Me.Request("__EVENTTARGET") Is Nothing Then
'do something - you can use the Parameter with: Me.Request("__EVENTARGUMENT")
end if
end sub

jQuery disable double click prevention breaking functionality of a PHP function in a form

I have a jquery bug that I cant solve - hoping for help with a solution. Dont know if it is browser bug related (probably not), jQuery related, or Yii (our backend) related - but I need to try to solve it with the jQuery portion. Code at bottom of message.
Requirement: Disable accidental double submissions on forms.
Current Solution: Check for form submission state through a delegate and when the DOM form state changes to submit - append the disable attribute to the form submit button to prevent accident double form submission.
jQuery double click disabler:
$( document ).ready(function() {
$('html').delegate('form', 'submit', function() {
$(this).find(':submit').attr('disabled', true);
});
});
Problem: This works perfectly on every part of the CRM we are developing EXCEPT for a single timekeeper (clock in/clock out) feature. With the timekeeper the form has two submit buttons (one for clock in, one for clock out). Only one submit button shows at a time (Either "In" or "Out". When you click the button - it submits the form and changes the submit button to the other state by checking a session var to determine what state it is in and determines which of the two submit buttons are to be displayed. Problem is if you click it, the form appears to submit, but the state don't change. If you click it really fast a few times you can get it to change state. I suspect this is a timing or order of operations issue, but I have no idea how to fix it. The fix MUST be done on the front end, so here is the code (both the PHP being impacted and jQuery double click prevention). Perhaps a different method of disabling double submissions may work, please post your solution if you have one to try. Commenting out the current jQuery allows the form to function as designed. What might be causing this, and how might I change the jQuery double click prevention to solve it?
On page PHP for the time clock:
<form action = "<?=$clockUrl?>" method = "post" >
<input type = "hidden" name = "previousUrl" value = "<?=$currentUrl?>">
<?php if ($sessionVar->timeclockin) {?>
<input type = "submit" name = "submit-clockout" value = "Out">
<class="clock-time" ><?=$sessionVar->timeclockin?></class="clock-time">
<?php } else {?>
<input type = "submit" name = "submit-clockin" value = "In">
<?php }?>
</form>
Thank you for pointing me in the right direction Tyler! I was able to fix the issue with the following alteration to my script.
function do_nothing() {
console.log("click prevented");
return false;
}
$('html').delegate('form', 'submit', function(e) {
$(e.target).find(':submit').click(do_nothing);
setTimeout(function(){
$(e.target).unbind('click', do_nothing);
}, 10000);
});
Update 1:
If you are looking to prevent the button from being pressed twice then inside of your onclick or submit function, you should use something similar to the following:
$('#yourButton').prop('disabled', true);
If the page then redirects then you won't have to undo this. If it does, then do the opposite by changing true to false.
The submit function should instead disable the submit button until it either returns or fails.
An alternative is to use a lambda style function and replace it temporarily with an empty function until the request returns or fails.

Unable to submit a form on the first click event

Well, I spent hours on this problem and scanned the whole stackoverflow, but still do not know what to do. But what really gets me nuts is that such a trivial and the simplest in the world thing is not working. So, what I have now is a form with inputs and a button:
<form id="frm" action="/accent/login/enter/">
{% csrf_token %}
<div draggable="true" id="panel" class="panel" title="">
<input id="login" name="login" type="text" placeholder="" class="required" /> <br/>
<input id="pswd" name="pswd" type="password" placeholder="" class="required" /> <br/>
<button id="btn" value="">ENTER</button>
</div>
</form>
And I have this code which is supposed to send the form:
$('#btn').one("click",function(){ // prevent from multiple submits
$('#frm').validate({ // validate the form before submission
...general stuff: rules, messages, etc
submitHandler:function(form){
$('#frm').submit(function(e){ //submitted on the second click. why???
...prepare parameters for ajax call
$.ajax({
type:'POST',
...general stuff
});
e.preventDefault();
})
}
});
});
The problem is, when a user clicks on submit button for the first time, then the form is not submitted, if, however, he or she clicks it for the second time, then it is submitted ok. I can't understand the logic behind such behaviour implemented in jquery. Besides, I should say, that I have tried many other tricks, like:
form.submit(...
$('#frm')[0].submit(...
But they work not as expected, as if there is no callback function - I'm redirected to the url, but do not stay on the same page - just what I expect from e.preventDefault. I guess there is some sacred method or magic properties in jquery that I should use to make it work (like method one which prevents terrible multiple submits). But at this moment I do not know them.
EDIT
I also tried this trick:
jQuery('#frm').submit(...
but it works exactly like the first method - $('#frm').submit(...
EDIT
I found the third method which works like the previous one:
$('form').submit(...
To sum up, I have three different methods, but all of them work only when a user clicks on the button for the second time. And I have two methods that work in a standard manner and do not make it possible to use a callback function.
The problem is, you are registering for form submit after the form validation.
so,
1) On first click of button validation, the submit event is registered to a handler.
2) On second click of the button, the registered handler will be called. that is why it get submitted on second click. But note that you are registering again for the submit event. which means, on third click the form will be submitted twice, on fourth click the form will be submitted thrice..... and so on...
Solution
1) remove the $("#frm").submit() code from the submitHandler and put it outside.
2) use e.preventDefault(); in $("#frm").submit() so the default action is prevented and page doesn't get reloaded.
3) put the AJAX code directly in submitHandler
$('#btn').one("click",function(){ // prevent from multiple submits
$('#frm').validate({ // validate the form before submission
...general stuff: rules, messages, etc
submitHandler:function(form){
...prepare parameters for ajax call
$.ajax({
type:'POST',
...general stuff
});
}
});
});
$('#frm').submit(function (e) {
e.preventDefault();
});
I guess you are using the jqueryvalidation plugin. If it's true, then your using of $().validate() may be wrong.
The $().validate() function is to initialize the validation, it tells the script how to validate the form value and what to do if the validation is passed(the submitHandler property).
So maybe you should edit your code like this:
<form id='frm'>
...
</form>
$('#frm').validate({
//...general stuff: rules, messages, etc
submitHandler: function (form) {
//blahblah before doing the submitting...
form.submit();
}
});
$('#btn').one('click', function (){
$('#frm').submit();
});
But, actually there's still a problem with your $btn.one() event handler: if you click the button while the form values doesn't meet your validation rules, the one chance to fire the handler is consumed and even if you re-input the right value, the button will never response your clicking unless refreshing the page.
So maybe you should check your business logic again and redesign the form submitting flow, but that's not what this question is discussing, good luck ;)

jQuery validation - multiple groups

Im designing a user control that has the following:
a textbox called 'AddressInput'
a google maps plugin
a linkbutton
a textbox for the marker title called 'MarkerTitleInput'
a "Submit" button
The problem is this:
When the linkbutton is clicked, I need to validate that AddressInput was completed, but nothing else
When the submit button is clicked, I need to validate that AddressInput and MarkerTitleInput were both completed.
So my first two problems are:
1) How do i validate certain fields from a linkbutton, without submitting the form
2) How do i validate all fields from the form being submitted
My other problem is that when the linkbutton is clicked, my code runs a lookup against Google's Geocode to get an address. I was going to create an additional validation method to handle when an address is not found, but using a validator means the json request is sent everytime a key is pressed, which is too much - i only want the validation to run when the linkbutton is clicked. I have tried (selector).validate({ onkeyup:false }) with no avail. Is it perhaps possible to manually set whether the .valid() method thinks the form is valid?
Thanks
Al
$("form").validate({
groups:{
pg1:"_Phone1 _Phone2 _Phone3",
pg2:"dob_month dob_day dob_year"
},
errorPlacement:function(error, element){
if(element.attr("name")=="_Phone1"|| element.attr("name")=="_Phone2" || element.attr("name")=="_Phone3"){
error.insertAfter("#_Phone3")
}
else if
(element.attr("name")=="dob_month"|| element.attr("name")=="dob_day" || element.attr("name")=="dob_year"){
error.insertAfter("#dob_year")
}
else
error.insertAfter(element);
},
});
});
Give each of the two buttons a unique class (for ease of targeting in jQuery).
Give each class an OnClick event.
Validate in the OnClick event.
If the validation succeeds, return true.
Else return false.

Categories

Resources