Короче, я подумал, почему бы не использовать геттеры/сеттеры для скрытия фэйкового плейсхолдера от скрипта?
input.value = '';
input.placeholder = 'placeholder';
alert(input.value); // пустая строка, не смотря на то, что в инпуте отображается 'placeholder'
Работает в IE8-9. В других браузерах - не знаю. Но знаю что подход работает в опере последней старой и в файрфоксе последнем. А значит, скорее всего будет работать и в старых версиях этих браузеров. В хроме облом. Хотя есть некоторые мысли, возможно и получится.
IE6-7 вот в пролете, да. Но это не многих огорчит.
Вот набросок:
<!DOCTYPE html>
<meta charset="utf-8" />
<style>
input.placeholder{
color: #999;
}
</style>
<form action="">
<p><input type="text" placeholder="abc" /></p>
</form>
<script>
var input = document.getElementsByTagName('input')[0];
var object = 'value' in input.constructor.prototype ? input.constructor.prototype : input;
var nativeValueDescriptor = Object.getOwnPropertyDescriptor(object, 'value');
input._value = input.value;
input._placeholder = input.getAttribute('placeholder') || '';
input.removeAttribute('placeholder'); // для теста в новых браузерах
input._placeholderVisible = false;
function showPlaceholder() {
input._placeholderVisible = true;
input.className += ' placeholder';
nativeValueDescriptor.set.call(input, input._placeholder);
}
function hidePlaceholder() {
input._placeholderVisible = false;
input.className = (' ' + input.className + ' ').replace(/\s+placeholder\s+/);
nativeValueDescriptor.set.call(input, '');
}
var phDescriptor = {
set: function(value) {
this._placeholder = value;
if (this._placeholderVisible)
nativeValueDescriptor.set.call(input, this._placeholder);
},
get: function() {
return this._placeholder;
}
};
var valueDescriptor = {
set: function(value) {
input._placeholderVisible = false;
nativeValueDescriptor.set.call(this, value);
},
get: function() {
if (this._placeholderVisible)
return '';
return nativeValueDescriptor.get.call(this);
}
};
Object.defineProperty(input, 'value', valueDescriptor);
Object.defineProperty(input, 'placeholder', phDescriptor);
if (!input._value) {
showPlaceholder();
}
input.onfocus = function(e) {
if (this._placeholderVisible)
hidePlaceholder();
};
input.onblur = function(e) {
if (!nativeValueDescriptor.get.call(this))
showPlaceholder();
};
</script>
Почему-то в IE input.getAttribute('placeholder') дает null
Причем setAttribute на самом деле устанавливает свойство, а не атрибут.
Наверно в IE не нужно ставить setter на placeholder, достаточно слушать propertychange.