I have a form that detects if all the text-fields are valid on each keyup() and focus(); if they're all valid, it will enable the submit button for the user to press. However, if the user fills in one of the text inputs with a browsers autocomplete feature, it prevents the submit button from being enabled.
Is there a way to detect if any of the input has changed regardless of how it's been changed, using jQuery?
You could try using on input to detect text-based changes (except keys like ctrl and shift) in <input>'s.
For example:
$(input).on('input', function() {
console.log($(this).val());
});
The jQuery change event will only fire on blur. The keyup event will fire as you type. Neither fire on clicking an auto-completion option. I am also searching for a way to detect this, but I'm currently going with
$(selector).bind("change keyup",function(){
//Do something, probably with $(this).val()
});
But it doesn't quite solve the problem...
Myself I used
$(selector).on("change keyup blur input", function() {});
which did the trick in Chrome. input is what made it work for autocomplete.
My issue was detecting auto-fill (via a plugin like lastpass or 1password) as well as the issue described above.
The solution that worked for me was:
$(function(){
function validate(){
if($('#email').val() !== '' && $('#password').val() !== '')
$('#submit').prop('disabled', false);
else
$('#submit').prop('disabled', true);
}
// Validate after user input
$('#email, #password').on('keyup change', validate);
// Validate on mouse enter of body and login form
// to catch auto-fills from roboform/1password etc...
$('body, #loginform').on('mouseenter', validate);
// Validate onload incase of autocomplete/autofill
validate();
});
See demo in JSFiddle.
You could use the jQuery .change() function.
After the page initially loads, you can validate the entire form, just to check that it is in fact not filled in. After that you can use .change() to check if things have changed on the form, and if anything has changed, validate the form again.
$(document).ready(function() {
// validate form once, just to be sure (if valid, activate submit button)
});
...
<form>
<input class="target" type="text" value="Field 1" />
<select class="target">
<option value="option1" selected="selected">Option 1</option>
<option value="option2">Option 2</option>
</select>
</form>
<script type="text/javascript">
$('.target').change(function() {
alert('Something changed');
// Try validating form again (if valid, activate submit button)
});
</script>
Plan B
Another option is to always have the submit button clickable, but use .submit() to bind it to the form validator. Then if the form IS valid, carry on. If the form IS NOT valid use .preventDefault() to stop the submission of the form..... and you'd display a warning message too, indicating the missing fields.
The answer has been given in this question. It doesn't use jQuery, but it works for Autocomplete:
Use js onpropertychange event.
I have a decent solution after having the same problem. Set keyup as normal to our form fields, then mouseover to the surrounding div. So once you click the autocomplete option, you mouse will be over the top of the div:
$("#emailaddress").bind("keyup", function() {
displayFullSubcribeForm();
});
$(".center_left_box").bind("mouseover", function() {
displayFullSubcribeForm();
});
I wanted a very good user experience on a field where it would not be invalid (turn red in my case) as long as the user was reasonably active e.g. still filling out the field.
To do this for normal input, I was able to hook up to keyup with a debounce function, while blur is connected for immediate validation. While it appears that keyup is triggered by lastpass, since I have debounced it, there was a delay in validation. Thanks to #peter-ajtai I tried to add the change event and it indeed catches last pass and leaves the other niceties alone.
Coffeescript example:
#fieldExp
.keyup($.debounce(#_onExpChange, 3000))
.blur(#_onExpChange)
.change(#_onExpChange)
This worked well and lastpass form fill triggers immediate validation.
this is the ultimate solution, guaranteed to work
$(document).bind('mouseover', function(){
liveValidate();
});
Related
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.
I have this code, basically I have <input id="register_username" type="text" name="username"> and I want to check if the users already exist in the database or not. The code works perfectly when the user type a username, but sometimes some browsers (for example Firefox) gives the user drop down menu and let them choose some values they already entered in the past (such as their name). The problem is when the chose the username from the drop down menu, the keyup function does not work. How can I fix this problem ?
$("#register_username").live('keyup', function() {
$.post('scripts/register/register_check.php', {
checkusername: $('#register_username').val()
}, function(data) {
if (data == "good") {
//do something
} else {
//do the other thing
}
});
});
I don't think all browers if any triggers an event after choosing an option from an autocomplete dropdown.
Your best bet is to use .change() which will trigger after the element loses focus. For example, when the user chooses an autocomplete option and move on to the next field.
I would use the onblur event to fire whenever the field loses focus.
I am handling ajax suggestions using keyboard and mouse, it is capturing every keyevent except enter key(13). What I want is to get the "selected suggestion value" into the text box. For this I am handling keyevent = 13. Now the problem is when I am pressing enter key, my form get submitted instead of going into the "if block" where I am checking (keyevent = 13).
I am using struts <html:submit> tag to submit my form. I guess, the browser automatically set the focus into first <html:submit> tag that comes in its place. How to defocus this? I tried setting focus at other fields but trick doesn't work.
The other way is, I can use simple <html:button> and can get the things working, but the system already using <html:submit>. So, getting approval and modification is quite hectic.
Code for submit button:
<html:submit styleClass="btn" property="method.saveVisaRequestForRMG" onclick="bCancel=false" styleId="submitBtn">
and code for event handling:
// Handle ENTER key
case 13: handleSelectedItem(obj, container, cur);
ev.cancelBubble = true;
break;
How to come out of this problem? Please suggest me.
If you use jquery there is a simple way to handle enter press events:
$(window).keypress(function(e) {
if(e.keyCode == 13) {
e.preventDefault();
alert('Enter!');
}
});
After you prevented the default event you can do whatever you want for example posting the data into the server, saying hello or whatever :)
Try to return false; to cancel the event handling of the submit?
Do you have something like:
onsubmit="return formValidator()"
i have a function that currently working on .keypress event when the user right something in the textbox it do some code, but i want the same event to be triggered also when the user clear the textbox .change doesn't help since it fires after the user change the focus to something else
Thanks
The keyup event will detect if the user has cleared the box as well (i.e. backspace raises the event but backspace does not raise the keypress event in IE)
$("#inputname").keyup(function() {
if (!this.value) {
alert('The box is empty');
}
});
jsFiddle
As Josh says, this gets fired for every character code that is pressed in the input. This is mostly just showing that you need to use the keyup event to trigger backspace, rather than the keypress event you are currently using.
The solution by Jonathon Bolster does not cover all cases. I adapted it to also cover modifications by cutting and pasting:
$("#inputname").on('change keyup copy paste cut', function() {
//!this.value ...
});
see http://jsfiddle.net/gonfidentschal/XxLq2/
Unfortunately it's not possible to catch the cases where the field's value is set using javascript. If you set the value yourself it's not an issue because you know when you do it... but when you're using a library such as AngularJS that updates the view when the state changes then it can be a bit more work. Or you have to use a timer to check the value.
Also see the answer for Detecting input change in jQuery? which suggests the 'input' event understood by modern browsers. So just:
$("#inputname").on('input', function() {
//!this.value ...
});
Another way that does this in a concise manner is listening for "input" event on textarea/input-type:text fields
/**
* Listens on textarea input.
* Considers: undo, cut, paste, backspc, keyboard input, etc
*/
$("#myContainer").on("input", "textarea", function() {
if (!this.value) {
}
});
You can check the value of the input field inside the on input' function() and combine it with an if/else statement and it will work very well as in the code below :
$( "#myinputid" ).on('input', function() {
if($(this).val() != "") {
//Do action here like in this example am hiding the previous table row
$(this).closest("tr").prev("tr").hide(); //hides previous row
}else{
$(this).closest("tr").prev("tr").show(); //shows previous row
}
});
Inside your .keypress or .keyup function, check to see if the value of the input is empty. For example:
$("#some-input").keyup(function(){
if($(this).val() == "") {
// input is cleared
}
});
<input type="text" id="some-input" />
I have some text inputs which I'm validating when a user tabs to the next one. I would like the focus to stay on a problematic input after showing an alert. I can't seem to nail down the correct syntax to have JQuery do this. Instead the following code shows the alert then focuses on the next text input. How can I prevent tabbing to the next element after showing an alert?
$('input.IosOverrideTextBox').bind({
blur: function(e) {
var val = $(this).val();
if (val.length == 0) return;
var pval = parseTicks(val);
if (isNaN(pval) || pval == 0.0) {
alert("Invalid override: " + val);
return false;
}
},
focus: function() {
$(this).select();
}
});
I don't like forced focus, but can't you just focus after the blur takes place?
element.focus();
If doing that in the blur event doesn't always work (I'm not sure exactly when it fires, before or after the actual blur takes place), a redundant timeout will do, as well: setTimeout(function () { element.focus() }, 0).
But please don't do this. Heck, you should never be using alert or any kind of modal dialog for a web interface, either. How about adding a invalid class to the form field, putting a message off to the side of it, and disabling submit until all fields are valid? That's a much less invasive solution that allows me to fill out the form in whatever way is best for me, rather than whatever way is simplest for you.
You can do this with the validation plugin by default.
focusInvalid default: true
Focus the last active or first invalid element on submit via validator.focusInvalid(). The last active element is the one that had focus when the form was submitted, avoiding to steal its focus. If there was no element focused, the first one in the form gets it, unless this option is turned off.
Then you'd only need to have the focus event handler do your select and let the plugin handle validation.