Skip to content

Commit b7a4199

Browse files
committed
Make .val() work as expected
* 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.
1 parent 06d8e67 commit b7a4199

File tree

4 files changed

+76
-27
lines changed

4 files changed

+76
-27
lines changed

README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
### HTML
1010

11-
``` html
11+
```html
1212
<input type="text" name="name" placeholder="e.g. John Doe">
1313
<input type="email" name="email" placeholder="e.g. address@example.ext">
1414
<input type="url" name="url" placeholder="e.g. http://mathiasbynens.be/">
@@ -20,28 +20,34 @@
2020

2121
### jQuery
2222

23-
``` js
23+
Use the plugin as follows:
24+
25+
```js
2426
$('input, textarea').placeholder();
2527
```
2628

29+
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.
30+
2731
### CSS
2832

2933
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:
3034

31-
``` css
35+
```css
3236
input, textarea { color: #000; }
3337
.placeholder { color: #aaa; }
3438
```
3539

40+
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).
41+
3642
## Notes
3743

38-
* Requires jQuery 1.4.2+.
44+
* 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).
3945
* Works in all A-grade browsers, including IE6.
4046
* 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.)
4147
* 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.
4248
* 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:
4349

44-
``` html
50+
```html
4551
<label for="bar">Example label</label>
4652
<input type="password" placeholder="foo" id="bar">
4753
```

demo.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ <h1>HTML5 Placeholder jQuery Plugin</h1>
2929
<p><input type="submit" value="type=submit"></p>
3030
</form>
3131
<p><a href="http://mathiasbynens.be/" title="Mathias Bynens, front-end developer">Mathias</a></p>
32-
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
32+
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
3333
<script src="jquery.placeholder.js"></script>
3434
<script>
3535
// 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:
36-
// jQuery.fn.hide = function() { return this; }
36+
// $.fn.hide = function() { return this; }
3737
// Then uncomment the last rule in the <style> element (in the <head>).
3838
$(function() {
3939
// Invoke the plugin

jquery.placeholder.js

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
/*! http://mths.be/placeholder v1.8.7 by @mathias */
1+
/*! http://mths.be/placeholder v2.0.0 by @mathias */
22
;(function(window, document, $) {
33

44
var isInputSupported = 'placeholder' in document.createElement('input'),
55
isTextareaSupported = 'placeholder' in document.createElement('textarea'),
66
prototype = $.fn,
7+
valHooks = $.valHooks,
8+
hooks,
79
placeholder;
810

911
if (isInputSupported && isTextareaSupported) {
@@ -20,14 +22,40 @@
2022
return this
2123
.filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
2224
.not('.placeholder')
23-
.bind('focus.placeholder', clearPlaceholder)
24-
.bind('blur.placeholder', setPlaceholder)
25+
.bind({
26+
'focus.placeholder': clearPlaceholder,
27+
'blur.placeholder': setPlaceholder
28+
})
2529
.trigger('blur.placeholder').end();
2630
};
2731

2832
placeholder.input = isInputSupported;
2933
placeholder.textarea = isTextareaSupported;
3034

35+
hooks = {
36+
'get': function(element) {
37+
var $element = $(element);
38+
return $element.hasClass('placeholder') ? '' : element.value;
39+
},
40+
'set': function(element, value) {
41+
var $element = $(element);
42+
if (value == '') {
43+
element.value = value;
44+
// We can’t use `triggerHandler` here because of dummy text/password inputs :(
45+
setPlaceholder.call(element);
46+
} else if ($element.hasClass('placeholder')) {
47+
clearPlaceholder.call(element, true, value) || (element.value = value);
48+
} else {
49+
element.value = value;
50+
}
51+
// `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
52+
return $element;
53+
}
54+
};
55+
56+
isInputSupported || (valHooks.input = hooks);
57+
isTextareaSupported || (valHooks.textarea = hooks);
58+
3159
$(function() {
3260
// Look for forms
3361
$(document).delegate('form', 'submit.placeholder', function() {
@@ -41,7 +69,9 @@
4169

4270
// Clear placeholder values upon page reload
4371
$(window).bind('unload.placeholder', function() {
44-
$('.placeholder').val('');
72+
$('.placeholder').each(function() {
73+
this.value = '';
74+
});
4575
});
4676

4777
}
@@ -58,24 +88,32 @@
5888
return newAttrs;
5989
}
6090

61-
function clearPlaceholder() {
62-
var $input = $(this);
63-
if ($input.val() === $input.attr('placeholder') && $input.hasClass('placeholder')) {
91+
function clearPlaceholder(event, value) {
92+
var input = this,
93+
$input = $(input);
94+
if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {
6495
if ($input.data('placeholder-password')) {
65-
$input.hide().next().show().focus().attr('id', $input.removeAttr('id').data('placeholder-id'));
96+
$input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
97+
// If `clearPlaceholder` was called from `$.valHooks.input.set`
98+
if (event === true) {
99+
return $input[0].value = value;
100+
}
101+
$input.focus();
66102
} else {
67-
$input.val('').removeClass('placeholder');
103+
input.value = '';
104+
$input.removeClass('placeholder');
68105
}
69106
}
70107
}
71108

72109
function setPlaceholder() {
73110
var $replacement,
74-
$input = $(this),
111+
input = this,
112+
$input = $(input),
75113
$origInput = $input,
76114
id = this.id;
77-
if ($input.val() === '') {
78-
if ($input.is(':password')) {
115+
if (input.value == '') {
116+
if (input.type == 'password') {
79117
if (!$input.data('placeholder-textinput')) {
80118
try {
81119
$replacement = $input.clone().attr({ 'type': 'text' });
@@ -84,18 +122,23 @@
84122
}
85123
$replacement
86124
.removeAttr('name')
87-
// We could just use the `.data(obj)` syntax here, but that wouldn’t work in pre-1.4.3 jQueries
88-
.data('placeholder-password', true)
89-
.data('placeholder-id', id)
125+
.data({
126+
'placeholder-password': true,
127+
'placeholder-id': id
128+
})
90129
.bind('focus.placeholder', clearPlaceholder);
91130
$input
92-
.data('placeholder-textinput', $replacement)
93-
.data('placeholder-id', id)
131+
.data({
132+
'placeholder-textinput': $replacement,
133+
'placeholder-id': id
134+
})
94135
.before($replacement);
95136
}
96137
$input = $input.removeAttr('id').hide().prev().attr('id', id).show();
138+
// Note: `$input[0] != input` now!
97139
}
98-
$input.addClass('placeholder').val($input.attr('placeholder'));
140+
$input.addClass('placeholder');
141+
$input[0].value = $input.attr('placeholder');
99142
} else {
100143
$input.removeClass('placeholder');
101144
}

jquery.placeholder.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)