jQuery Validation and Placeholder conflict - javascript

I'm using the jQuery Validation plugin to validate a form on my site.
http://docs.jquery.com/Plugins/Validation
I'm also using the following code to provide Placeholder support for browsers that do not support the HTML5 placeholder="" attribute.
// To detect native support for the HTML5 placeholder attribute
var fakeInput = document.createElement("input"),
placeHolderSupport = ("placeholder" in fakeInput);
// Applies placeholder attribute behavior in web browsers that don't support it
if (!placeHolderSupport) {
$('[placeholder]').focus(function() {
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
input.removeClass('placeholder');
}
}).blur(function() {
var input = $(this);
if (input.val() == '') {
input.addClass('placeholder');
input.val(input.attr('placeholder'));
}
}).blur().parents('form').submit(function() {
$(this).find('[placeholder]').each(function() { //line 20
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
}
});
});
}
When I submit my form, the following things happen:
In browsers that support the placeholder attribute, the validate() function fires and everything works like it is supposed to.
In browsers that do not support the placeholder attribute, lines 20-25 clear all the "placeholders" and then the validate() function fires. If there are no errors, the page submits and everything works like it is supposed to.
In unsupported browsers, in the event that there are errors, the appropriate fields get applied class="error" like usual -- but the placeholder text doesn't come back until the blur() event happens on a particular field. This leaves those fields blank -- and since there's no labels (just the placeholder attribute) users are left to guess at what each empty field is supposed to contain until the blur() event happens.
The other problem that unsupported browsers have is that since the placeholder fix modifies the value attribute to display the placeholder, fields that are marked as required pass validation when they should be failing.
It seems there's no easy way to use the Validation plugin with the placeholder support code.
I'm looking to either modify the placeholder support code or add a submitHandler: {} function as a parameter to the validate() function to get this working in unsupported browsers.

I ran into a similar issue. Have you gotten yours to work? I'd love to compare notes.
FWIW, here's what I did:
jsfiddle demo here.
Add input placeholders to the jQuery support object:
$.support.placeholder = (function() {
var i = document.createElement( 'input' );
return 'placeholder' in i;
})();
The placeholder chain:
$('input')
.addClass('hint')
.val( function() {
if ( !$.support.placeholder ) {
return $(this).attr('placeholder');
}
})
.bind({
focus: function() {
var $this = $(this);
$this.removeClass('hint');
if ( $this.val() === $this.attr('placeholder') ) {
$this.val('');
}
},
blur: function() {
var $this = $(this),
// Trim whitespace if only space characters are entered,
// which breaks the placeholders.
val = $.trim( $this.val() ),
ph = $this.attr('placeholder');
if ( val === ph || val === '' ) {
$this.addClass('hint').val('');
if ( !$.support.placeholder ) {
$this.val(ph);
}
}
}
});
Add a new validation rule
addMethod docs
$.validator.addMethod('notPlaceholder', function(val, el) {
return this.optional(el) || ( val !== $(el).attr('placeholder') );
}, $.validator.messages.required);
Include the new method in the validate rules object
$('form').validate({
rules: {
name: {
required: true,
notPlaceholder: true
},
email: {
required: true,
notPlaceholder: true,
email: true
}
}
});

I think adding this to jquery.validate.js, to the required function (line 900), is best:
required: function(value, element, param) {
// Our change
if (element.value == element.defaultValue) {
return false;
}
// End our change

Placeholder plugin update solved my issue :)

you can solve this by binding this to the submit function (either through jQuery validate or manually)
if(element.val() == text){
element.val('');
}

Related

How to show native validation error for specific input on change event?

I have a classic HTML5 form. I would like using jquery/javscript to show the browser native error tooltip when the user change a specific input value. I would like to avoid the user try to submit the form to see all errors.
For that, I tried with the functions checkValidity() and reportValidity() but it works only if I add alert('test'); in my condition...so weird
JS script
myInputJqueryObject.on('change', function() {
if ( !this.checkValidity() ) {
this.setCustomValidity( 'Custom error !!!' );
var $form = $('#my-form');
if( $form[0].checkValidity() === false) {
$form[0].reportValidity();
//alert('test'); <-- works only if I active this line code
return true;
}
}
});
You do not need to check the form validity when you know that the input is invalid. You can omit if( $form[0].checkValidity() === false). Also you can reportValidity on the input itself.
And setCustomValidity takes some time to be applied to the input field. So you have to wrap reportValidity into setTimeout:
$('input').on('change', function() {
var self = this;
if (!self.checkValidity()) {
self.setCustomValidity('Custom error !!!');
setTimeout(function() {
self.reportValidity();
self.setCustomValidity('');
}, 1);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="my-form"><input value="del me" required></form>
Based on 'Kosh Very' answer, I found the solution. It sounds good without bugs.
JS Script :
$('input').on('focusout', function() {
var self = this;
var validity = self.checkValidity();
if( !validity ){
if( self.validity.patternMismatch ){ //<-- Optionnal : Condition to keep others native message errors except Pattern.
self.setCustomValidity( 'Custom Error about pattern!!!' );
}
setTimeout(function() {
self.reportValidity();
self.setCustomValidity( '' ); //<-- Important to reinit
}, 1);
}
});

Javascript: programmatically change onfocus function

I have several text boxes that can auto-fill with data and I am using a javascript function to clear the text box one time, then revert to a javascript function that only clears when certain text is input.
For instance: A text box with standard input as "ADDRESS" will be auto-filled with "ABC123" then onfocus be cleared. If the text box remains empty, then onblur, it will return to "ADDRESS"
This is similar to the question at Change an element's onfocus handler with Javascript? but I couldn't get it to work. Any suggestions?
My text boxes are just ASP.NET text boxes and the onfocus/onblur events are set in the code behind:
<asp:TextBox ID="txtAddress" Text="ADDRESS" runat="server" CssClass="txtboxwrong" />
Code Behind:
txtAddress.Attributes.Add("onFocus", "clearOnce(this,'ADDRESS');")
txtAddress.Attributes.Add("onBlur", "restoreText(this,'ADDRESS');")
My javascript is as follows:
function clearText(obj, deftext, defclass, defvalue) {
if (obj.value == deftext) {
if (!defvalue) { defvalue = '' }
obj.value = defvalue;
if (!defclass) { defclass = 'txtbox' }
obj.className = defclass;
}
};
function restoreText(obj, deftext, defclass, defvalue) {
if (!defvalue) { defvalue = '' }
if (obj.value == defvalue || obj.value == '') {
obj.value = deftext;
if (!defclass) { defclass = 'txtboxwrong' }
obj.className = defclass;
}
};
function clearOnce(obj, deftext) {
obj.value = '';
obj.className = 'txtbox';
obj.onfocus = function () { clearText(obj, deftext); };
};
EDIT:
Thanks to #rescuecreative, I have fixed the probem. By returning the onfocus change in clearOnce, it sets the element's onfocus to the right function and works properly! Edit below:
function clearOnce(obj, deftext) {
obj.value = '';
obj.className = 'txtbox';
return function () { clearText(obj, deftext); };
};
Can your asp textbox use the placeholder attribute? In html5, the placeholder attribute automatically creates the exact functionality you're looking for.
<input type="text" placeholder="ADDRESS" />
The above text field will show the word "ADDRESS" until focused at which point it will empty out and allow the user to type. If the user leaves the field and it remains empty, the placeholder reappears. If you can't depend on html5, there is a JavaScript plugin that will create that functionality in browsers that don't support it natively.
It seems like you wanted to do something similler to watermarks. You can achiever it in much simpler way. Try this.
function clearOnce(obj, deftext) {
if(obj.value == deftext) {
obj.value = '';
obj.className = 'txtbox';
}
}
function restoreText(obj, deftext) {
if(obj.value == '') {
obj.value = deftext;
obj.className = 'txtboxwrong';
}
}
Ideally you would just use the placeholder attribute, but that may not be supported on older browsers. If you can use jQuery, something like this would work for you:
$('[placeholder]').focus(function() {
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
input.removeClass('placeholder');
}
}).blur(function() {
var input = $(this);
if (input.val() == '' || input.val() == input.attr('placeholder')) {
input.addClass('placeholder');
input.val(input.attr('placeholder'));
}
}).blur();
If nothing is ever entered into the field, the code below will ensure the placeholder text doesn't get submitted with the form:
$('[placeholder]').parents('form').submit(function() {
$(this).find('[placeholder]').each(function() {
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
}
})
});

Creating a custom rule in jQuery Validate

I would like to add a custom rule to jQuery validate, and while I have checked the docs I have not been able to find out how to do this.
I want to loop over a set of hidden form fields. If the fields value is "X", then I would like to append an error class to a field.
So essentially this, but added as a rule to jQuery validate.
$(".myHiddenField").each( function() {
if($(this).val() == "x") {
$(this).closest(".foo").appendClass("error");
}
});
You may use addMethod()
$.validator.addMethod('yourRuleName', function (value, element, param) {
//Your Validation Here
return isValid; // return bool here if valid or not.
}, 'Your error message!');
$('#myform').validate({
rules: {
field1: {
yourRuleName: true
}
}
});
If you want to show some custom error messages without adding an actual rule then you can use the showErrors() method, but if you are working on a hidden field it may not work
var validator = $( "<form-selector>" ).validate();
var errors = {};
$(".myHiddenField").each( function() {
var $this = $(this);
if($this.val() == "x") {
errors[$this.attr('name')] = 'Some error message';
}
});
validator.showErrors(errors);
$.validator.addMethod("NOTx", function(element,value) {
return value != "x";
}, 'warning word"!');

emptyText in HTML

Is there any way to have something similar to emptyText in input fields as in ExtJS?
I tried setting values with changed CSS. But, the value is submitted with the form and it is not disappearing as soon as I click the input field. I need to support IE7 and above
Any help would be appreciated.
What you are looking for is placeholder..W3School
<input type="text" placeholder="Hii" />
You can find polyfills for ie and old versions of other browser who don't support placeholder..
You can add this code for browser who dont support placeholder to make it work same way it works in good browsers..*It needs JQuery
// This adds 'placeholder' to the items listed in the jQuery .support object.
jQuery(function() {
jQuery.support.placeholder = false;
test = document.createElement('input');
if('placeholder' in test) jQuery.support.placeholder = true;
});
// This adds placeholder support to browsers that wouldn't otherwise support it.
$(function() {
if(!$.support.placeholder) {
var active = document.activeElement;
$(':text').focus(function () {
if ($(this).attr('placeholder') != '' && $(this).attr('placeholder') != undefined && $(this).val() == $(this).attr('placeholder')) {
$(this).val('').removeClass('hasPlaceholder');
}
}).blur(function () {
if ($(this).attr('placeholder') != '' && $(this).attr('placeholder') != undefined && ($(this).val() == '' || $(this).val() == $(this).attr('placeholder'))) {
$(this).val($(this).attr('placeholder')).addClass('hasPlaceholder');
}
});
$(':text').blur();
$(active).focus();
$('form:eq(0)').submit(function () {
$(':text.hasPlaceholder').val('');
});
}
});
Rajat answer is correct, but only for HTML5.
You can look at this question if you want an answer that work on IE (and other browsers) using only pure javascript without any library.

Showing Placeholder text for password field in IE

I know there is a ton of placeholder questions, but I am trying to perfect mine.
My current code works great and does what it's supposed to. The problem is, when I go to place the "password" placeholder, it puts the placeholder in the masking characters. Any ideas on how to get around that?
$(function() {
if(!$.support.placeholder) {
var active = document.activeElement;
$(':text').focus(function () {
if ($(this).attr('placeholder') != '' && $(this).val() == $(this).attr('placeholder')) {
$(this).val('').removeClass('hasPlaceholder');
}
}).blur(function () {
if ($(this).attr('placeholder') != '' && ($(this).val() == '' || $(this).val() == $(this).attr('placeholder'))) {
$(this).val($(this).attr('placeholder')).addClass('hasPlaceholder');
}
});
$(':text').blur();
$(active).focus();
$('form').submit(function () {
$(this).find('.hasPlaceholder').each(function() { $(this).val(''); });
});
var active = document.activeElement;
$(':password').focus(function () {
if ($(this).attr('placeholder') != '' && $(this).val() == $(this).attr('placeholder')) {
$(this).val('').removeClass('hasPlaceholder');
}
}).blur(function () {
if ($(this).attr('placeholder') != '' && ($(this).val() == '' || $(this).val() == $(this).attr('placeholder'))) {
$(this).val($(this).attr('placeholder')).addClass('hasPlaceholder');
}
});
$(':password').blur();
$(active).focus();
$('form').submit(function () {
$(this).find('.hasPlaceholder').each(function() { $(this).val(''); });
});
}
});
My field for the pass:
<div id="loginform_pass"><input class="login" tabindex="2" type="password" placeholder="Password" name="password" maxlength="30"></div>
You could also try this... it detects that the browser does not have support for placeholder and works for all input types
function FauxPlaceholder() {
if(!ElementSupportAttribute('input','placeholder')) {
$("input[placeholder]").each(function() {
var $input = $(this);
$input.after('<input id="'+$input.attr('id')+'-faux" style="display:none;" type="text" value="' + $input.attr('placeholder') + '" />');
var $faux = $('#'+$input.attr('id')+'-faux');
$faux.show().attr('class', $input.attr('class')).attr('style', $input.attr('style'));
$input.hide();
$faux.focus(function() {
$faux.hide();
$input.show().focus();
});
$input.blur(function() {
if($input.val() === '') {
$input.hide();
$faux.show();
}
});
});
}
}
function ElementSupportAttribute(elm, attr) {
var test = document.createElement(elm);
return attr in test;
}
Could you just swap out the original text field with a password field?
$('#pass').focus(
function(){
var pass = $('<input id="pass" type="password">');
$(this).replaceWith(pass);
pass.focus();
}
);
<input id="pass" type="text" value="Passowrd">
http://jsfiddle.net/UrNFV/
I ran into this problem with IE before. Here's my solution :)
http://jsfiddle.net/mNchn/
If I'm understanding this right, you want the field to say "Password" when nothing has been typed into it; however, "Password" gets displayed as "********".
A decent fix to that (which also degrades gracefully, depending on how you code it) is to:
Put a LABEL before the password INPUT. Set the LABEL's text to "Password", and set its for attribute to point to the INPUT's ID, so that the INPUT is focused when the LABEL is clicked.
Use CSS to position the LABEL on top of the INPUT, so that they overlap, and it looks like "Password" is inside of the INPUT.
Make it so that the LABEL is only visible when some CSS class (.showMe, for example) is applied to it.
Use JavaScript to hide the LABEL
...if the INPUT's value is an empty string
...or if the user has selected (focused) the INPUT.
Depending on whether or not you want to be able to dynamically change the text inside the placeholder, your simplest solution might be to have the placeholder text be an image.
input {
background: url(_img/placeholder.png) 50% 5px no-repeat;
.
.
.
}
input:focus {
background: none;
}
Clearly there are many different ways of using this method, and you will have to use some kind of a fix to get :focus to work on the browsers that don't support it.
Here my plugin :
if(jQuery.support.placeholder==false){
// No default treatment
$('[placeholder]').focus(function(){
if($(this).val()==$(this).attr('placeholder'))
$(this).val('');
if($(this).data('type')=='password')
$(this).get(0).type='password';
});
$('[placeholder]').blur(function(){
if($(this).val()==''){
if($(this).attr('type')=='password'){
$(this).data('type','password').get(0).type='text';
}
$(this).val($(this).attr('placeholder'));
}
}).blur();
}
I had the same problem so i wrote a little plugin
$.fn.passLabel = function(){
var
T = $(this),
P = T.find('input[type=password]'),
V = pass.val();
P.attr('type','text');
P.focus(function(){
if(V == "")
P.attr('type','password');
});
}
now you just call it for the from at it will find all input fields with the password
attribute.
eg.
$('form').passLabel();
A bit late however same here, i was working on the issue too IE9 doesnot show the password placeholder as text, in almost all the answers on the internet some suggest changing the type some but if u do this u will have another issue on the login page like when you will see with double click on password field as its type changed to text from password, btw it works with prop. e.g. prop("type","password") if you want to change the type of an element.
on the other hand i think most answers come from a single solution its like focus and blur actions of elements. but when u apply this plugin other text fields will also be effected there is no specific or i can say generlized solution, i have still a minor issue on the login page with the password field but its showing the text correctly. anyway. here is how i have configured, copied,changed and/or another inherited anwers here.
(function($) {
$.fn.placeholder = function() {
$('input[placeholder], textarea[placeholder]').focus(function() {
var input = $(this);
if (input.val() === input.attr('placeholder')) {
if (input.prop("id") === "password") {
input.prop("type", "password");
}
input.val('');
input.removeClass('placeholder');
}
}).blur(function() {
var input = $(this);
if (input.val() === '' || input.val() === input.attr('placeholder')) {
input.addClass('placeholder');
if (input.prop("type") === "password") {
input.prop("type", "text");
}
input.val(input.attr('placeholder'));
}
}).blur().parents('form').submit(function() {
$(this).find('input[placeholder], textarea[placeholder]').each(function() {
var input = $(this);
if (input.val() === input.attr('placeholder')) {
input.val('');
}
});
});
};
})(jQuery);
still an active prolem ... :D

Categories

Resources