Rewriting the TextBoxWatermarkExtender as an ASP.NET AJAX Plugin

I couldn't help but continue exploring the ASP.NET AJAX JavaScript component topic I wrote about yesterday.  So this afternoon I picked one of the simplest AjaxControlToolkit extender controls, the TextBoxWatermarkExtender, and rewrote it using the plugin approach I wrote about yesterday.  Again, I am very happy with how it turned out.  Read on for the details and don't forget to check out the live demo and download links as well.

Live Demo | Download

image

Step 1: Find an existing jQuery watermark plugin in that does what I want

So I googled a bit and ended up following a link here.  This looked like exactly what I wanted so I downloaded the JavaScript and took a look at it.  And I was very happy to see that it was incredibly simple - only ~20 lines of code.  The script uses some selectors to identify the textbox elements on the page.  Once the elements are identified it wires up the focus, blur and click to some JavaScript handlers that add or remove the watermark based on the current value of the element. 

Here the script is in all of its glory ...

   1: $(document).ready(function(){
   2:     $("input:text, textarea, input:password").each(function(){
   3:         if(this.value == '')
   4:             this.value = this.title;
   5:     });
   6:     $("input:text, textarea, input:password").focus(function(){
   7:         if(this.value == this.title)
   8:             this.value = '';
   9:     });
  10:     $("input:text, textarea, input:password").blur(function(){
  11:         if(this.value == '')
  12:             this.value = this.title;
  13:     });
  14:     $("input:image, input:button, input:submit").click(function(){
  15:         $(this.form.elements).each(function(){
  16:             if(this.type =='text' || this.type =='textarea' || this.type =='password' ){
  17:                 if(this.value == this.title && this.title != ''){
  18:                     this.value='';
  19:                 }
  20:             }
  21:         });
  22:     });
  23: });

 

Step 2: Rearrange the code so it fits into an ASP.NET AJAX JavaScript based Component

So I implemented a very simple Sys.Component JavaScript object that uses the getElementsByClassName function to pull out all of the input elements with the watermark CSS class applied to them.  The jQuery version extracts the elements by tag names, but I thought this might be grabbing elements I don't want to apply the watermark to so I chose to use a css class instead. 

To do this I setup my majax.watermark Component to handle the Sys.Application.load event.  When this event fires I grab all of the elements that have the watermark class applied to them and apply the watermark logic to them as follows:

  • If the element doesn't currently have a value, set the value to the title attribute and add the watermark CSS class to the element
  • When the focus event for the element fires check to see if the value is the same as the title.  If it is remove the watermark text and as well as the watermark CSS class
  • When the blur event fires check to see if the value is empty.  If it is reapply the title value and add the watermark CSS class back
   1: apply : function(e) {
   2:     
   3:     //  if the field is empty, show the watermark
   4:     if(e.value == '') {
   5:         e.value = e.title;
   6:         Sys.UI.DomElement.addCssClass(e, 'watermark');
   7:     }
   8:     
   9:     //  when the field has focus hide the watermark
  10:     $addHandler(e, 'focus', function(){  
  11:         if(e.value == e.title) {
  12:             e.value = '';
  13:             Sys.UI.DomElement.removeCssClass(e, 'watermark');
  14:         }
  15:     });
  16:     
  17:     //  when the field loses focus and the
  18:     //  input is empty, show the watermark
  19:     $addHandler(e, 'blur', function(){  
  20:         if(e.value == '') {
  21:             e.value = e.title;
  22:             Sys.UI.DomElement.addCssClass(e, 'watermark');
  23:         }
  24:     });  
  25:                   
  26: }

 

Step 3: Add the Script References to your Page

After the watermark plugin component is written all we have to do to use it is let the ScriptManager know about it like so ...

image

And of course make sure the scripts have been saved to the appropriate file paths on the web server ...

image

And finally, just set the ToolTip and CssClass attributes for all of the ASP.NET TextBox controls that should have the watermark applied to them ...

   1: <asp:TextBox ID="TextBox1" runat="server" CssClass="watermark" ToolTip="First Name" />
   2: <br />
   3: <br />
   4:  
   5: <asp:TextBox ID="TextBox2" runat="server" CssClass="watermark" ToolTip="Password" TextMode="Password" />
   6: <br />    
   7: <br />
   8:  
   9: <asp:TextBox ID="TextBox3" runat="server" CssClass="watermark" ToolTip="Example Text" TextMode="MultiLine" />
  10: <br />        
  11: <br />

 

Step 4: Enjoy!

 image

 

Conclusion

Well I am pretty much sold on this as a potential plugin pattern for getting some of the jQuery goodness into ASP.NET AJAX.  What about you?

 

That's it.  Enjoy!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/129

Comments


Wat happens if you add an RequiredFieldValidator on the field and submits it. Does it go off? Well I can Try my self of course :-)

Posted by: Doug Rees on June 13, 2008 12:00 AM

Hi Matt,
As always a useful set of information.

Couple of points however, with your implementation the postback to the server contains the text of the watermark whereas the tookit extender version does not.

Also your version stops the requiredfieldvalidator control from letting the post go back to the server unless you also update the validators InitialValue property to the same as the watermark value.

But I am not criticising at all as I always think the work you do is great. Just food for thought...

Regards,
Doug

Ughh – great point’s guys. I completely left out handling required field validators. And that is something that the Toolkit’s watermark extender handles and makes this plugin pretty useless - looks like it needs another rev to support this.

But let me ask you – suppose validation was supported and there was complete feature parity between the Toolkit’s watermark extender and the jQuery plugin one. Which one would you use? And Why?

And one more thing Doug – Keep criticism coming. That’s one of the reasons I enjoy blogging so much. It is great to bounce ideas off people and get real feedback.

Ive been sold on using JQuery long time ago. As for validators i guess you will have to write your own validators to make it work with plug in.

@George -

Yea - here is where I am at. The team I work on is not switching from WebForms to MVC any time soon. And I am fine with that - we have a bunch of good devs all with plenty of years of WebForms experience so we understand all of the quirks and can get past any of the wierdness that sometimes pops up.

And I dont really want to use 3 ajax libraries (jQuery, ASP.NET AJAX and the Toolkit). But I like how easy it is to author and distribute jQuery plugins and I wish there was a similar pattern for ASP.NET AJAX. And I figure the Watermark extender is a perfect example where a plugin model would work better. There really is no need to interact with the control from the server and I hate adding a seperate TextBoxWatermarkExtender to the page because you can only attach to a sinlge TextBox at a time.

So that explains the background of this post and my previous one. I would like to explore a plugin model for ASP.NET AJAX cuz it feels like there are an large enough set of use cases like this one where it makes a lot of sense ...

Matt,

First of all great work. It sounds like I am in the same boat as you with keeping it down to just ASP.NET Ajax and the Toolkit. Our team has said it does not want to use any more external libraries like jQuery or Ext-js, 2 is enough. So I think this is a great idea to create a plugin type system to ASP.NET Ajax. Keep it coming.

Posted by: Josh M on June 13, 2008 12:00 AM

I think Id prefer use this plugin because it cuts down on the amount of typing I have to do in the designer as well as the amount of processing overhead.

Posted by: Doug Rees on June 13, 2008 12:00 AM

The plugin is a good option as you can specify the script on the pages that need it and skip it for those that dont. Using css to link it is ideal and saves a lot of (design) space on the page. As you say applying it to multiple controls is very easy.

Might be worth figuring out how the required field validator ignores the watermark. I havent looked at it in detail but could it be as simple as adding the watermark value as the initial value of the validator?

Removing the value from the post to the server might be more challenging I think...

@Doug -

Yea - After reading your comment I couldnt help but take a peek at how the Toolkit watermark control does it. It is pretty crafty. It renders a dummy element over the the top of the input element. And it applies the watermark to this element. Then when you enter text into it it forwards that on to the underlying (now hidden) textbox. This way all of the same validation log runs and eveything is cool.

So I was thinking of 2 ways for doing this:
- copy this dummy element logic into a plugin whole sale. This would be nice because you could use the plugin without paying for the all of the other Toolkit scripts that get loaded with the watermark.
- just pull down the behavior for the watermark toolkit control and use $create to create the control on the fly for all of the elements that match the selector

For the applications I work on, option 2 would be just fine with me. I use many of the Toolkit controls anyway ...

Posted by: Petr Snobelt on June 26, 2008 12:00 AM

Hi,
You should first check if there is associated label and if so use it. This way peoples without javascript can have page still accessible.

Something similar to http://www.456bereastreet.com/archive/200710/autopopulating_text_input_fields_with_javascript/

Posted by: CodeBoy on September 1, 2008 07:44 AM

hi Matt.. Great Work..

This plugin was very useful, kindly clarify if this plugin would work fine with AJAX Extension 1.1.

I tried using the same with .NET framework 2.0 & AJAX Extension 1.1 (web.config modified accordingly) but i endedup with 'null is null or not an object' javascript error.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • CodeBoy wrote: hi Matt.. Great Work.. This plugin was very useful, kindly clarify if this plugin would work fine ...
  • Petr Snobelt wrote: Hi, You should first check if there is associated label and if so use it. This way peoples without j...
  • Bjorn van der Neut wrote: Wat happens if you add an RequiredFieldValidator on the field and submits it. Does it go off? Well I...
  • Doug Rees wrote: Hi Matt, As always a useful set of information. Couple of points however, with your implementation ...
  • Matt Berseth wrote: Ughh – great point’s guys. I completely left out handling required field validators. And that is s...
  • Matt Berseth wrote: And one more thing Doug – Keep criticism coming. That’s one of the reasons I enjoy blogging so much...
  • George wrote: Ive been sold on using JQuery long time ago. As for validators i guess you will have to write your o...
  • Matt Berseth wrote: @George - Yea - here is where I am at. The team I work on is not switching from WebForms to MVC an...