Skip to content

Commit

Permalink
Make .val() work as expected
Browse files Browse the repository at this point in the history
* Use `jQuery.valHooks` to make sure `.val()` and `.val(value)` work as expected. Avoid using `.val()` internally. This fixes mathiasbynens#30.
* Tweak the syntax a bit here and there now that we’ve dropped support for pre-1.6 jQueries.
  • Loading branch information
mathiasbynens committed Feb 10, 2012
1 parent 06d8e67 commit b7a4199
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 27 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

### HTML

``` html
```html
<input type="text" name="name" placeholder="e.g. John Doe">
<input type="email" name="email" placeholder="e.g. [email protected]">
<input type="url" name="url" placeholder="e.g. http://mathiasbynens.be/">
Expand All @@ -20,28 +20,34 @@

### jQuery

``` js
Use the plugin as follows:

```js
$('input, textarea').placeholder();
```

You’ll still be able to use `jQuery#val()` to get and set the input values. If the element is currently showing a placeholder, `.val()` will return an empty string instead of the placeholder text, just like it does it browsers with a native `@placeholder` implementation. Calling `.val('')` to set an element’s value to the empty string will result in the placeholder text (re)appearing.

### CSS

The plugin automatically adds `class="placeholder"` to the elements who are currently showing their placeholder text. You can use this to style placeholder text differently:

``` css
```css
input, textarea { color: #000; }
.placeholder { color: #aaa; }
```

I’d suggest sticking to the `#aaa` color for placeholder text, as it’s the default in most browsers that support `@placeholder`. If you really want to, though, you can [style the placeholder text in some of the browsers that natively support it](http://stackoverflow.com/questions/2610497/change-an-inputs-html5-placeholder-color-with-css/2610741#2610741).

## Notes

* Requires jQuery 1.4.2+.
* Requires jQuery 1.6+. For an older version of this plugin that works under jQuery 1.4.2+, see [v1.8.7](https://github.com/mathiasbynens/jquery-placeholder/tree/1.8.7).
* Works in all A-grade browsers, including IE6.
* Automatically checks if the browser natively supports the HTML5 `placeholder` attribute for `input` and `textarea` elements. If this is the case, the plugin won’t do anything. If `@placeholder` is only supported for `input` elements, the plugin will leave those alone and apply to `textarea`s exclusively. (This is the case for Safari 4, Opera 11.00, and possibly other browsers.)
* Caches the results of its two feature tests in `jQuery.fn.placeholder.input` and `jQuery.fn.placeholder.textarea`. For example, if `@placeholder` is natively supported for `input` elements, `jQuery.fn.placeholder.input` will be `true`. After loading the plugin, you can re-use these properties in your own code.
* Makes sure it never causes duplicate IDs in your DOM, even in browsers that need an extra `input` element to fake `@placeholder` for password inputs. This means you can safely do stuff like:

``` html
```html
<label for="bar">Example label</label>
<input type="password" placeholder="foo" id="bar">
```
Expand Down
4 changes: 2 additions & 2 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ <h1>HTML5 Placeholder jQuery Plugin</h1>
<p><input type="submit" value="type=submit"></p>
</form>
<p><a href="http://mathiasbynens.be/" title="Mathias Bynens, front-end developer">Mathias</a></p>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script src="jquery.placeholder.js"></script>
<script>
// To test the @id toggling on password inputs in browsers that don’t support changing an input’s @type dynamically (e.g. Firefox 3.6 or IE), uncomment this:
// jQuery.fn.hide = function() { return this; }
// $.fn.hide = function() { return this; }
// Then uncomment the last rule in the <style> element (in the <head>).
$(function() {
// Invoke the plugin
Expand Down
79 changes: 61 additions & 18 deletions jquery.placeholder.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/*! http://mths.be/placeholder v1.8.7 by @mathias */
/*! http://mths.be/placeholder v2.0.0 by @mathias */
;(function(window, document, $) {

var isInputSupported = 'placeholder' in document.createElement('input'),
isTextareaSupported = 'placeholder' in document.createElement('textarea'),
prototype = $.fn,
valHooks = $.valHooks,
hooks,
placeholder;

if (isInputSupported && isTextareaSupported) {
Expand All @@ -20,14 +22,40 @@
return this
.filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
.not('.placeholder')
.bind('focus.placeholder', clearPlaceholder)
.bind('blur.placeholder', setPlaceholder)
.bind({
'focus.placeholder': clearPlaceholder,
'blur.placeholder': setPlaceholder
})
.trigger('blur.placeholder').end();
};

placeholder.input = isInputSupported;
placeholder.textarea = isTextareaSupported;

hooks = {
'get': function(element) {
var $element = $(element);
return $element.hasClass('placeholder') ? '' : element.value;
},
'set': function(element, value) {
var $element = $(element);
if (value == '') {
element.value = value;
// We can’t use `triggerHandler` here because of dummy text/password inputs :(
setPlaceholder.call(element);
} else if ($element.hasClass('placeholder')) {
clearPlaceholder.call(element, true, value) || (element.value = value);
} else {
element.value = value;
}
// `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
return $element;
}
};

isInputSupported || (valHooks.input = hooks);
isTextareaSupported || (valHooks.textarea = hooks);

$(function() {
// Look for forms
$(document).delegate('form', 'submit.placeholder', function() {
Expand All @@ -41,7 +69,9 @@

// Clear placeholder values upon page reload
$(window).bind('unload.placeholder', function() {
$('.placeholder').val('');
$('.placeholder').each(function() {
this.value = '';
});
});

}
Expand All @@ -58,24 +88,32 @@
return newAttrs;
}

function clearPlaceholder() {
var $input = $(this);
if ($input.val() === $input.attr('placeholder') && $input.hasClass('placeholder')) {
function clearPlaceholder(event, value) {
var input = this,
$input = $(input);
if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {
if ($input.data('placeholder-password')) {
$input.hide().next().show().focus().attr('id', $input.removeAttr('id').data('placeholder-id'));
$input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
// If `clearPlaceholder` was called from `$.valHooks.input.set`
if (event === true) {
return $input[0].value = value;
}
$input.focus();
} else {
$input.val('').removeClass('placeholder');
input.value = '';
$input.removeClass('placeholder');
}
}
}

function setPlaceholder() {
var $replacement,
$input = $(this),
input = this,
$input = $(input),
$origInput = $input,
id = this.id;
if ($input.val() === '') {
if ($input.is(':password')) {
if (input.value == '') {
if (input.type == 'password') {
if (!$input.data('placeholder-textinput')) {
try {
$replacement = $input.clone().attr({ 'type': 'text' });
Expand All @@ -84,18 +122,23 @@
}
$replacement
.removeAttr('name')
// We could just use the `.data(obj)` syntax here, but that wouldn’t work in pre-1.4.3 jQueries
.data('placeholder-password', true)
.data('placeholder-id', id)
.data({
'placeholder-password': true,
'placeholder-id': id
})
.bind('focus.placeholder', clearPlaceholder);
$input
.data('placeholder-textinput', $replacement)
.data('placeholder-id', id)
.data({
'placeholder-textinput': $replacement,
'placeholder-id': id
})
.before($replacement);
}
$input = $input.removeAttr('id').hide().prev().attr('id', id).show();
// Note: `$input[0] != input` now!
}
$input.addClass('placeholder').val($input.attr('placeholder'));
$input.addClass('placeholder');
$input[0].value = $input.attr('placeholder');
} else {
$input.removeClass('placeholder');
}
Expand Down
4 changes: 2 additions & 2 deletions jquery.placeholder.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b7a4199

Please sign in to comment.