Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
522 views
in Technique[技术] by (71.8m points)

jquery - What is the most accurate way to emulate the "placeholder" attribute in browsers that don't support it natively?

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 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

"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. ;)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...