0

i'm trying to write unobtrusive default/placeholder text in input (actually, relatively placed label over input, which hides on onFocus, and stays hidden if input isn't empty on onBlur), but I don't want to use jQuery, because this is the only javascript used on page - therefore using jQuery seems a bit over the top.

Please, how can I do this without jQuery?

Thank you.

EDIT: I know the idea (getElementByID), but I'm more looking into how to add it to document - preferably something you have used before. Thank you.

EDIT: Thank you all, I finally went with jQuery, seeing answers :] (my example is here: http://jsbin.com/ehega/3 - it's concept, I'll probably add more eye candy. As an answer I Robert Koritnik - because of valid points... and styling ;])

Adam Kiss
  • 11,811
  • 9
  • 48
  • 81
  • 1
    Having implemented hints on bare metal in the past I will advise you that you are running headlong into a world of pain. The xbrowser aspect of this task is going to eat you alive. An xbrowser library is essential for these sorts of tasks. – Sky Sanders May 18 '10 at 11:28
  • 2
    Please note that this is a bad idea from a UX perspective, see http://www.uxmatters.com/mt/archives/2010/03/dont-put-hints-inside-text-boxes-in-web-forms.php – Svante Svenson May 18 '10 at 11:33
  • @svinto - I haven't designed it, I'm not client, on this page i figure only as a coder. – Adam Kiss May 18 '10 at 12:49
  • @svinto: [That article](http://www.uxmatters.com/mt/archives/2010/03/dont-put-hints-inside-text-boxes-in-web-forms.php) seemed to concentrate on poor implementations of this. It completely ignored user experience with grayed-out hints or other aids to make it clear that the hint is not actual input. – palswim Sep 01 '10 at 22:57

7 Answers7

3

you will need to manually attach the onfocus and onblur events, having got a handle on the input with getElementById.

here is an example: http://www.aspsnippets.com/Articles/Watermark-TextBox-using-JavaScript.aspx

Andrew Bullock
  • 36,616
  • 34
  • 155
  • 231
  • ...having got the reference to the input *somehow*; doesn't have to be `getElementById`. – T.J. Crowder May 18 '10 at 11:11
  • so that means that either I have to use inline `onBlur="myFunc()"` or add another JS file to add custom `addEvent` function? – Adam Kiss May 18 '10 at 11:13
  • @Adam: You can always define a script block that defines your `addEvent()` function. No need to define it in a separate file, but it does make it easier to maintain and reuse though so it is a good practice to keep scripts in separate files outside from content ones. – Robert Koritnik May 18 '10 at 11:29
2

I suggest you use jQuery

jQuery is nothing more than a cross-browser library that makes it easier for developers to achieve something and not worry about browser particularities. And when you load it once (it's rather small) it's cached so I wouldn't worry because it will save you lots of development/testing time later.

No? Then do it manually but make it more reusable

But if you do decide to do something manually you can always use regular Javascript and manipulate DOM as you wish. You best friends in this case would of course be (as Andrew pointed out):

  • getElementById() and
  • getElementsByTagName()

functions, but since you'll be manipulating DOM and styles, make sure you test your code against all common browsers. If you use custom attributes on INPUT elements it's good to use the second function, so you'll attach additional functionality to all inputs at once and only to those that define that particular custom attribute like:

<input type=text id="inputX" name="inputX" placeholder="Enter something">

Your script would then get all inputs and you'd check for the custom attribute existance and attach events to those elements that do define that attribute. This way you won't depend on IDs and make your code universal so you can reuse it app wide. Or even on other projects.

Just a sidenote: Andrew's example works somehow differently than what you said would like to do (using labels), but I suggest you use the same approach, because you'll be running scripts anyway. For the sake of unobtrusiveness make sure that you set default content using Javascript so default values and styles on textboxes won't be set for those users that are not running Javascript.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
  • 1
    well, adding `JS` (or `hasJS`) class on body and then using different `CSS` (something like `.hasJS #thisInput`) is unobtrusive enough. However, it seems, that 24kB of jQuery isn't that much when compared to amount of things I have to keep in mind - custom `addEvent` function (I hate inline JS), custom blur function... Seems not worth it. – Adam Kiss May 18 '10 at 11:17
  • I would use the `placeholder` attribute instead of `empty-value`, because some browsers already support this html5 attribute. You can do a check if the Browser support this and if not you can add your own javascript to emulate: http://stackoverflow.com/questions/2856573/unobtrusive-default-text-in-input-without-jquery/2856806#2856806 – jigfox May 18 '10 at 11:46
  • @Jens: You can name your attributes whatever you prefer, I just added one as an example. Your suggestion is of course much better. I'll amend my answer. – Robert Koritnik May 18 '10 at 11:50
2

You can use jQuery and still be unobtrusive and use the ability of HTML5 Browsers, make your input like this:

<input type="whatever" placeholder="Your Default Text"/>

I user Modernizr to check the html5 capabilities of the browser and if the browser doesn't understand the placeholder attribute than I use this little javascript to emulate this function.

if (!Modernizr.input.placeholder) {
  $('input').each(function(){
    var obj = $(this);
    var placeholder = obj.attr('placeholder');
    if (placeholder) {
      obj.val(placeholder);
      obj.focus(function(){
        var obj2 = $(this);
        if (obj2.val() == obj2.attr('placeholder')) obj2.val('');
      });
      obj.blur(function(){
        var obj2 = $(this);
        if (obj2.val() == '') obj2.val(obj2.attr('placeholder'));
      });
    }
  });
}

It is unobtrusive, because you don't need any javascript in your html code. the function above can easily changed if you want to use any other framework. I wouldn't use a solution without any Framework, because the frameworks do a great job in working around the incompatibilities between browsers.

jigfox
  • 18,057
  • 3
  • 60
  • 73
  • not using jQuery was not because it couldn't be unobtrusive, but rather because I thought it's overkill for this small task (it's basically js for login/password and search inputs on whole page). Actually, it seems it isn't overkill. – Adam Kiss May 18 '10 at 12:26
2

This is how I would do it, without JQuery. It grays out the control when it shows the default text, and allows entering the default text if need be. The "title" tag will fallback to a tooltip for people who disable JavaScript:

<html>
<body>
<input type="text" value="" title="default text"  />

<script type="text/javascript">
function DefaultInput(e) {
    // Get the elements
    this.e = e
    this.d = e.title
    this.s = e.style
    e.removeAttribute('title') // remove the tooltip
    e.value = '' // IE cached value remove HACK!

    // Bind the events
    e.onblur = this.bind(this.onblur)
    e.onfocus = this.bind(this.onfocus)

    // Show the initial value in gray
    this.onblur()
}

DefaultInput.prototype = {
    bind: function(f) {
        // Return `f` so it's always called as an object of DefaultInput
        var o = this
        return function(){
            f.apply(o, arguments)
        }
    },

    onblur: function() {
        // Gray out my value and show the default text if my value's blank
        if (!this.h && !this.e.value) {
            this.s.color = 'gray'
            this.e.value = this.d
            this.h = true // true -> help text displayed
                          // false -> help text hidden/user entered value
        }
    },

    onfocus: function() {
        // Make the text black and blank the text if in "help" mode
        if (this.h) {
            this.s.color = 'black'
            this.e.value = ''
            this.h = false
        }
    }   
}

// Make sure the page is loaded before 
// running for twitchy browsers like IE
window.onload = function() {
    // Add defaults for all text input elements which have a `title`
    var L = document.getElementsByTagName('input')
    for (var i=0; i<L.length; i++) {
        var e = L[i]
        if (e.type=='text' && 'title' in e)
            new DefaultInput(e)
    }
}
</script>
</body>

EDIT: Cleared up the comments a bit, fixed some IE bugs and made it so it looks for <input> tags with title's to make it so different pages have less conversion time rather than individually intitializing the input controls ;-)

cryo
  • 14,219
  • 4
  • 32
  • 35
1

I think that you need something like this:

<input type="text" onfocus="if (this.value == this.getAttribute('mydefaulttext')) this.value = '';" onblur="if (this.value == '') this.value = this.getAttribute('mydefaulttext');" mydefaulttext="click here..." value="click here..."/>

Zsolti
  • 1,571
  • 1
  • 11
  • 22
1
<input name="test" type="text" id="test" value="testValue" />

<script type="text/javascript">
 var myInput = document.getElementById("test");
 myInput.onfocus = function() {
   this.value = '';
 }
  myInput.onblur = function() {
   if(this.value == '') this.value = "testValue";
}
</script>
Aneesh
  • 1,193
  • 3
  • 16
  • 26
1

Here's how I do:

Online Working Example

http://jsbin.com/ehivo3 (source code)

HTML

<input type="text" name="myfield" id="myfield" value="Please, fill my field!!!" />

jQuery

$(document).ready(function() {
  // Handle each input on focus() and blug()
  $('input[type="text"]').each(function() {
    $(this)
      // Store the default value internally
      // Don't use .val() because browser autofill will poison it
      .data('defaultValue', $(this).attr('value'))
      // Handle the focus() (when you enter the field)
      .focus(function() {
        if ($(this).val() == $(this).data('defaultValue'))
          $(this).val('');
      })
      // Handle the blur() (when you leave the field)
      .blur(function() {
        if ($(this).val() == '')
          $(this).val($(this).data('defaultValue'));
      });
  });

  // Clear all fields with "default value" on submit
  $('form').submit(function() {
    $('input[type="text"]', $(this)).each(function() {
      // If the input still with default value, clean it before the submit
      if ($(this).val() == $(this).data('defaultValue'))
        $(this).val('');
    });
  });
});

And that's all! No invalid or extra attributes, valid markup and all handled in your jQuery file. :)

Thiago Belem
  • 7,732
  • 5
  • 43
  • 64