Capture "auto-suggest" event using JavaScript - javascript

I have created a nice cross-browser utility which ensures that form "placeholders" behave in the same way (including IE which does not implement them)
However, this has created a different problem when a user fills a form and the browser helpfully provides an auto-suggest for the remaining fields in the form, eg, for a registration form: You might type your name, and the browser will auto-suggest your surname, email address, postal address, etc...
I don't care what the auto-suggested values are, but I need find a way of capturing "event" on each field so I may hide my implementation of the place holder.
I've had a look at the DOM elements in Chrome to see if the auto-suggest value is stored in a custom attribute, but have been unsuccessful.
Has anyone else seen or experienced this? Does anyone know if its even possible to capture such an event?
NOTE: This issue disappears when the user accepts the auto-suggest, and this becomes an auto-complete, which fires a change event on the fields; so I only need to capture the suggest event

I have produced the following script which "detects" when the fields have become auto-suggested by Webkit:
I am assuming anyone using this knows Underscore and jQuery.
var $form = $('form'),
autoCompleteSetting = $form.attr('autocomplete');
if (_.isUndefined(autoCompleteSetting) || autoCompleteSetting === "on") {
_($form.find('input')).each(function($input){
setInterval(function() {
if ($input.is(":-webkit-autofill")) {
// do your code here to detect the webkit autofill setting
}
}, 100);
});
}
I personally have put the webkit-autofill check into a ternary operator.
Obviously use at your own risk; having these intervals running for every field on your page every millisecond may cause problems for some users!

Related

MVC 5 - Validate a specific field on client-side

I want to populate a city/state drop down list based on the postal code a user types into a textbox. So when the text changes, I'm going to make an ajax call to retrieve the data. However, I only want to perform that ajax request for valid postal codes. The field already validates using the DataAnnotations.RegularExpression attribute and jquery.validate.unobtrusive validation library. I'm unclear on what can and can't be used from jquery.validate when using unobtrusive. I've looked at the unobtrusive code, but haven't gotten an understanding of it yet. So two questions:
Using javascript,
is there a way to force validation on a specific field, not the whole form?
is there a way to check whether a specific field is valid?
After digging around in the source code, I've come to these conclusions. First, the purpose of unobtrusive is to wire up the rules and messages, defined as data- attributes on the form elements by MVC, to jQuery.validation. It's for configuring/wiring up validation, not a complete wrapper around it, so when it comes to performing validation that is already set up, you don't have to worry about "circumventing", or not involving, unobtrusive.
So to answer the questions:
Yes, there are two ways. The Validator.element(element) function and the $.fn.valid() extension method. .valid actually calls Validator.element internally. The difference is .valid works on a jQuery which allows you to perform the validation on one or more fields (or the form itself). Validator.element performs validation on only a single element and requires you to have an instance of the validator object. Although the documentation states .validate() "validates the selected form", it actually appears to initialize validation for the form, and if it has already been called, it simply returns the validator for the form. So here are examples of two ways to validate an input (below #2).
Yes, but not without also performing the validation. Both of the methods from #1 return a boolean so you can use them to determine whether a field is valid. Unfortunately there doesn't appear to be anything exposed by the library that allows you to check the validation without, in effect, showing or hiding the validation message. You would have to get at and run the rule(s) for the field from your code, which may be possible, but my need didn't justify spending the time on it.
Example:
<form>
<input id="txtDemo" type="text"></input>
</form>
...
<script type="text/javascript">
$("#txtDemo").valid();
//or
//Get the form however it makes sense (probably not like this)
var validator = $("form").validate();
//Note: while .element can accept a selector,
//it will only work on the first item matching the selector.
validator.element("#txtDemo");
</script>
you can find if a single field is valid and trigger this validation this way:
$("#myform").validate().element("#elem1");
details here http://docs.jquery.com/Plugins/Validation/Validator/element#element
Use like this:
$('#Create').on('click', function () {
var form = $('#test').closest('form');
$(form).validate();
if (!$(form).valid()) {
return
} else {
// Bide the data
}
});
Hope it works for you

Appending input element to the DOM in safari transfers focus to the new input

I'm having trouble with the Safari browser, in that it, unlike other browsers including Chrome and Firefox, seems to be transferring focus to a newly created input field when it's appended to the DOM.
The use case is this:
I have a single email input field, into which users type an email (for sending invites). On the keyup event, we append a new email field underneath, to allow them to fill that one out too.
The logic (not exact code) is as follows:
$(document).on("keyup", ".invites input[type='email']", function(){
if("there isn't an empty email field, we'll add one"){
var parent = $(this).closest('wrapper');
var cloned_parent = parent.clone(); // we also remove content and classes here
$('.invites-container').append(cloned_parent);
}
})
It's at this point that the newly created element takes focus in Safari, but not in Chrome or Firefox. This is a problem, as the user may be typing an email address in the first input box, when the focus is snatched away, and all of a sudden they're typing in the second box, and so on. The end result is that multiple email fields are very quickly created just when typing a normal email address.
Strangley, I can't see much documentation around this difference - as appending a new element seems to be a very common function. I'm obviously missing something simple - can anyone advise what might be happening?
Things I've already tried:
Removing all javascript on the page, then cloning just the element
using .cloneNode() (no jquery) in the console - same issue, only in
safari
Removing all site css - same issue in safari
Cloning the input element itself, instead of the parent - same issue
Text inputs instead of email inputs - same issue
Please help!

Pointing to first field after validation

I have a webpage which has check-boxes, input fields, dropdowns etc.,
Mandatory conditions are checked using javascript. If anyone fails to fill these fields and press next button validation errors popup.
Now what I want to achieve is when someone fails to enter information in the mandatory fields, the cursor should go to the first field which caused the error.
Can anyone suggest me how to do this?
Add a class (something like input-error) for every invalid field. Then use something like:
var errors = document.querySelectorAll(".input-error");
if (errors.length > 0) {
errors[0].focus();
}
Here's an example: http://jsfiddle.net/NtHzV/1/
It really all depends on the structure of your code, how you're validating, what you're actually doing with validation, and what your HTML is.
At the same time, if you're doing something similar to my example, you might as well keep track of the first input with an error, then focus() it at the end of validation. Something like this:
http://jsfiddle.net/NtHzV/2/
UPDATE:
Bergi pointed out that querySelector might as well be used (instead of querySelectorAll) because you're only looking for the first input with errors. So here's an update:
var error_input = input_area.querySelector(".input-error");
if (error_input !== null) {
error_input.focus();
}
http://jsfiddle.net/NtHzV/3/
Here's specs on querySelector: https://developer.mozilla.org/en-US/docs/DOM/element.querySelector - Note that < IE8 does not support it.
The use of ".input-error" is because that is the CSS class selector, and will find the first (if any) element in a specific area with the class "input-error".
This line will focus the page on the element you specify. You should be able to implement this into your validation checks to focus on the bad elements.
document.getElementById("ID_Of_bad_field").focus();

"Mimic" placeholder attribute in jQuery?

Background
I've got a couple of jQuery functions that set a search field to contain the word "Search" and clear it / reset it when the field is clicked in and out of....
// Search Box Placeholder
jQuery('#q').focus(function() {
if(jQuery(this).val() == 'Search') {
jQuery(this).val('');
}
else if(jQuery(this).val() == '') {
jQuery(this).val('Search');
}
});
jQuery('#q').blur(function() {
if(jQuery(this).val() == '') {
jQuery(this).val('Search');
}
});
jQuery('#q').val('Search');
Question ?
The only issue is I'm not sure how to clear the word Search if the search form is submitted without an alternative search term being set. Is there a way to check and clear the contents before the form submission if the contents are equal to 'Search' ?
You can prevent the submission of form if the value is equal to 'Search'.
$('form').on('submit', function(){
return $('#q').val() !== 'Search';
});
If you want to support older browsers that do not support placeholder attribute, you can also use a plugin.
https://github.com/parndt/jquery-html5-placeholder-shim
The key to finding the answer to this kind of thing is often more about knowing the terminology than anything else.
In this case, if you'd searched for the word "polyfill" rather than "mimic", you'd have found the solution. "Polyfill" is web developer speak for a browser script that implements a feature of newer browsers so that it works in older browsers.
The placeholder feature is a classic one for this, because it's very useful and easily done.
Modernizr is a Javascript library that aims to simplify the process of working with polyfills. It detects whether a feature is supported, so that you can know whether or not to load the polyfill for that feature.
It's a useful tool, but the main reason I mention Modernizr is because they also maintain a big list of polyfill scripts.
Click that link and search for 'placeholder'... you'll find there's a whole stack of scripts that can do it for you. Just pick the one that works best for you, or crib from the techniques they use.
Hope that helps.
An alternative you may want to consider is not adding the placeholder text as the value of the control. Instead, use another element, possibly the input label or a span, absolutely positioned over the text input, and hide it when the corresponding input has the control. Also, when the user clicks on this label, you should hide it and set the focus to the control. This will also let you change the placeholder color.

Trigger JavaScript event when using Google auto fill on Firefox

I have a form, in which I am disabling the submit button until an user has typed in all the mandatory fields. I was initially using onkeyup to keep a tab on the mandatory fields and enable the button when all the mandatory fields are filled.
But I had users complaining that they filled in the form using AutoFill button on the Google toolbar and the submit button was still disabled.
I fixed this problem in IE by calling the onpropertychange event for each input element and it worked nicely.
But in Firefox, I couldn't find an event which will get triggered when the Google autofill button is clicked.
Help much appreciated.
Thanks for your answers. I had to respond quickly to this issue hence I used the 'setTimeOut()' function to check for mandatory fields and enable the submit button.
$().ready(function() {
CheckRequiredFields();
timeOutRtn = setTimeout("AutoMonitorMandatoryField()", "3000");
});
function AutoMonitorMandatoryField() {
if ($("#btnSave").attr("disabled")) {
CheckRequiredFields();
timeOutRtn = setTimeout("AutoMonitorMandatoryField()", "3000");
}
}
crescentfresh - I will look into the DOMAttrModified event and see if I can get it to work for me.Thanks
Judging from this google toolbar support thread, it seems autofill is not only a huge PITA for developers, but also very difficult to turn off. As of Aug 09 google claims it will honor the autocomplete="off" attribute on the containing form but as of today this feature does not seem to be released yet.
You used to be able to give your input elements non-sensical names (eg name="xx_Address_32423423") to confuse autofill (and thereby effectively disable it), but they've made autofill more "intelligent" by looking at substrings within your element names in order to determine if the field can be autofilled or not (again, judging from complaints in that thread).
In your case, you may as well roll with the punches and find an equivalent for onpropertychange for Firefox. Have a look at the DOMAttrModified event. Specifially, try checking the event.attrName property to see if the value has been changed by autofill:
function realOnChange(event) {
var attrName = event.propertyName || event.attrName;
if(attrName === 'value') {
// etc
}
}
The check for event.propertyName is to stay compatible with your current onpropertychange implementation (if that is even possible).
There's no need to add complex setTimeOut nor setInterval.
Just catch the "change" event of any refillable textbox of the form, go through every refillable field and if it's not empty hide the label

Categories

Resources