Recently I have been looking at jquery/javascript solutions to emulating the placeholder
attribute, but none of them seem to have it right. Common issues are:
- Native browser support is not used first
- The form may actually post the value of the placeholder text
- Inability to recognize between placeholder text and user input if the values are identical (Hey, my email IS user@example.com!! Why won't it submit? Hey I wanted to search for the string "Search" but it won't let me!)
- Difficult to style or distinguish between regular text and placeholder text
- Obtrusive implementation (almost always. I don't want to add 2 divs per input and a stylesheet to do this)
- Just doesn't work. At least 2 of those on the jQuery website.
I have played around a bit trying to get this to work properly (taking a few hints from some of the code I have seen already), but it still needs work. Particularly, the form may post the value of the placeholder. Comments and mods to the jsfiddle are welcome. (Note: Demo must be viewed in a browser without placeholder support) Most code I've seen takes the value of the placeholder
and stuffs it into the input itself which leads to this problem, I feel like there must be a better way.
Is there a nice clean solution that actually works?
EDIT: I want to stress this: it should behave the way you see it in browsers that natively support it as much as possible, and be as unobtrusive as possible, as demonstrated in my current code, which does not require anything other than including the script and开发者_C百科 using the placeholder
as you normally would for browsers that support it.
UPDATE: @DA's current solution is a couple of bug fixes away from perfect (see comments), would love to see this come together 100% and put all the bad & buggy code on the net to shame.
UPDATE: Got this working with a couple mods to DA's code but it's still not perfect, mostly in regards to dynamically added input fields and existing submit()
bindings. Thanks for all the help, I've decided for now that it's not worth it. I know a few people that will definitely use this though. It's a nice trick to have, but to me not worth even a 1% possibility of a form submit doing something its not intended to, or reading user input incorrectly. This minor feature is just not worth the headache, IE and pals can just deal with it, or it can be implemented on a case-by-case basis if it's really needed, like if the client demands it. @DA thanks again, this is the best implementation I've seen.
CONCLUSION: I think the only way to overcome all these issues is something like this:
- Copy the placeholder value to a new block level element
- Prepend the new element to the input
- Calculate the height border and padding of the input and move the new element over it as close as possible to the position that text would occur
- Use the standard blur/change/focus events to hide the element when the input has a value or is focused
This way you don't have to do anything on submit or deal with any of the other issues that can occur. Sorry no demo yet, I've got to get back to work - but I'll save a final edit for when this comes together.
"Most code I've seen takes the value of the placeholder and stuffs it into the input itself which leads to this problem"
Well, that's pretty much what the placeholder text does behind the scenes (albeit, it's not literally updating the value of the input).
One option is to something akin to this:
http://fuelyourcoding.com/scripts/infield/
The concept there is you move the LABEL with CSS so that's on top of the field and looks like placeholder text. Note that a LABEL isn't necessarily the same as placeholder text. A LABEL is important to have, especially for accessibility, while placeholder text can be thought more as 'help text' in addition to the label.
The other option is what you've been doing, take the content of the placeholder attribute and move it into the value of the input itself via JS.
Where you're getting hung up is you are submitting the form before checking to see if the fake placeholder text is still there.
To get around that, you want to attach an event to the submission of the form that, before submitting the form, will first look at all the input fields, grab their values, compare it to their placeholder attributes, and if it matches, set the value to blank.
UPDATE:
To address the issue you brought up in a comment of the user-inputted value matching the placeholder text, you could do something like this:
$('input[placeholder]').each(function(){
if($(this).val() === $(this).attr('placeholder')){
// in the odd situation where the field is prepopulated with
// a value and the value just happens to match the placeholder,
// then we need to flag it
$(this).data('skipCompare','true');
}
// move the placeholder text into the field for the rest of the blank inputs
if($(this).val().length===0){
$(this).val($(this).attr('placeholder'))
}
// move the placeholder text into the field for the rest of the blank inputs
if($(this).val().length===0){
$(this).val() = $(this).attr('placeholder');
}
$(this)
.focus(function(){
// remove placeholder text on focus
if($(this).val()==$(this).attr('placeholder')){
$(this).val('')
}
})
.blur(function(){
// flag fields that the user edits
if( $(this).val().length>0 && $(this).val()==$(this).attr('placeholder')){
$(this).data('skipCompare','true');
}
if ( $(this).val().length==0){
// put the placeholder text back
$(this).val($(this).attr('placeholder'));
}
})
})
$('#submitButton').click(function(){
$('input[placeholder]').each(function(){
if( !($(this).data('skipCompare')) && $(this).val() == $(this).attr('placeholder') ){
$(this).val('');
};
alert($(this).val());
})
})
It's late and I'm tired so all that might be completely wrong. No warranties given. ;)
jquery plugin I wrote a while ago:
(function(){
$.fn.inactiveText = function(inactiveClass, defaultValue){
var a, b;
this
.data ('defaultValue', defaultValue)
.addClass('inactive')
.focus(a=function(){
var $this = $(this);
if($this.hasClass(inactiveClass)){
(valFn.apply($this) == defaultValue) && $this.val('');
(valFn.apply($this) != defaultValue) && $this.removeClass(inactiveClass);
}
// $this.hasClass(inactiveClass) && $this.valueIs(defaultValue).val('').end().valueIsNot(defaultValue).removeClass(inactiveClass);
})
.blur(b=function(){
var $this = $(this);
this.value || $this.addClass(inactiveClass).val(defaultValue);
});
this.each(a);
this.each(b);
this.setDefaultValue = function(d){
this.each(a);
defaultValue = d;
this.each(b);
};
return this;
};
var valFn = $.fn.val;
$.fn.val = function(v){
if(typeof(v) == 'undefined'){
var val = valFn.apply(this, arguments);
return val == this.data('defaultValue') ? '' : val;
}
return valFn.apply(this, arguments);
};
})();
Define a css class for the inactive style (e.g. grey text) and you're good to go.
updated fiddle: http://jsfiddle.net/cwolves/At8cu/1/
Assume jQuery is defined.
$(document).ready(function() {
// Use native functionality if possible
if (document.createElement('input').placeholder !== undefined) return;
// Fallback code
$('form').each(function(i, form) {
var submitted = false;
$(form).find('input[placeholder]').each(function(j, input) {
addPlaceholder.call(input);
$(input)
.focus(removePlaceholder)
.blur(addPlaceholder)
;
});
$(form).submit(function() {
submitted = true;
$(this).find('input[placeholder]').each(function(j, input) {
removePlaceholder.call(input);
});
});
function addPlaceholder() {
if (!submitted && '' === $(this).val()) {
$(this).val($(this).attr('placeholder')).addClass('placeholder');
}
}
function removePlaceholder() {
if ( $(this).hasClass('placeholder') &&
$(this).attr('placeholder') === $(this).val()
) {
$(this).val('').removeClass('placeholder');
}
}
});
});
Style your placeholder with CSS to make it look the same in all browsers:
:-moz-placeholder { color: #bbb; opacity: 1; }
::-moz-placeholder { color: #bbb; opacity: 1; }
:-ms-input-placeholder { color: #bbb; }
::-webkit-input-placeholder { color: #bbb; }
.placeholder { color: #bbb; }
Tried these links?
HTML5 Forms Placeholder Fallback
jQuery Placeholder Text
Placeholder Attribute Support in ALL browsers
精彩评论