Прозрачный полифил атрибута placeholder
Короче, я подумал, почему бы не использовать геттеры/сеттеры для скрытия фэйкового плейсхолдера от скрипта?
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. |
Вот моя реализация , если не брать к вниманию Кросс-браузерное добавление событий, получается 20 строк -+.
Емулятор ie показывает что даже в 5 работает , только я что то сомневаюсь ...
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<meta charset="utf-8">
<style>
input {
color: silver;
}
</style>
</head>
<div id="placeholder">
<input type="text" data-pl="abc" value='abc'>
<input type="text" data-pl="abc1" value='abc1'>
<input type="text" data-pl="abc11" value='abc11'>
<input type="text" data-pl="abc12" value='abc12'>
</div>
<div id="place">
<input type="text" data-pl="abc1" value='abc1'>
<input type="text" data-pl="abc2324" value='abc2324'>
</div>
[JS run]
<script>
function addevent(obj, e, h) {if (obj.addEventListener) { obj.addEventListener(e, h, false);} else if (obj.attachEvent) { obj.attachEvent('on'+e, h);} else { obj['on'+e]=function() { h();};}} function delevent(obj, e, h) { if (obj.removeEventListener) { obj.removeEventListener(e, h, false);} else if (obj.detachEvent) { obj.detachEvent('on'+e, h);} else {obj['on'+e]=null;}}
var fn = function (elem) {
var placeholder = document.getElementById(elem);
var o = {
focus: function (e) {
e = e.target || e.srcElement;
if(!e.type == 'text') return;
if(e.value == e.getAttribute('data-pl')) {
e.value = '';
e.style.color = 'black'
}
addevent(e, 'blur', o.blur);
},
blur: function (e) {
e = e.target || e.srcElement;
if(e.value === '' || e.value == ' ') {
e.value = e.getAttribute('data-pl');
e.style.color = 'silver';
}
delevent(e, 'blur', o.blur);
}
}
addevent(placeholder, 'click', o.focus);
}
var place1 = fn('placeholder')
var place2 = fn('place')
</script>
[/JS]
</html>
|
Цитата:
|
А кому-нибудь приходила в голову такая идея: при потере фокуса (blur), если value пустой, то сверху на поле накладывать div или span с текстом? :)
|
Ruslan_xDD,
проще не сверху, а снизу, сделав прозрачным поле. А если бы еще был селектор пустоты поля, то можно было бы переложить на css работу по скрытию/показу "плейсхолдера" |
Цитата:
и это давно было - сейчас можно, наверное, подхватить placeholder через селектор псевдоэлемента и проанимировать появление, например, через color (указав альфа канал) ну или ч-з opacity. хз, не пробовал |
BETEPAH,
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
input + span {
color: #AAA;
display: none;
font-style: italic;
line-height: 20px;
margin-left: -165px;
position: absolute;
}
input:not(:focus):invalid + span {
display: inline;
}
</style>
</head>
<body>
<input required="required" type="text">
<span>Placeholder</span>
</body>
</html>
|
Цитата:
Для jQuery есть плагин, он перехватывает функцию val(). Хотелось бы тоже самое, но для ванильного js. Цитата:
|
Цитата:
|
если я тебя правильно понял , ты хочешь вмести с placeholder сразу проверку всей формы ?
|
Все что я хочу - подключить некий magicPlaceholder.js и забыть об этом.
Далее работать как обычно - из js обращаться к input.value, менять input.placeholder (в принципе), в том числе и через атрибуты. Причем с динамически созданными инпутами все также должно работать. В IE9 по крайней мере это все реализуемо. Уже почти сделал. В IE8 возможно тоже, но будут некоторые ограничения. |
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<meta charset="utf-8">
<style>
#canvas {
border: solid black 1px;
display: block;
}
</style>
<body>
<input type="text" placeholder="dasda">
<input type="text" placeholder="dasda" >
<input type="text" placeholder="dasda" >
<script>
[JS]
function addevent(obj, e, h) {if (obj.addEventListener) { obj.addEventListener(e, h, false);} else if (obj.attachEvent) { obj.attachEvent('on'+e, h);} else { obj['on'+e]=function() { h();};}} function delevent(obj, e, h) { if (obj.removeEventListener) { obj.removeEventListener(e, h, false);} else if (obj.detachEvent) { obj.detachEvent('on'+e, h);} else {obj['on'+e]=null;}}
var fn = function(){
var inp = document.querySelectorAll('input[type="text"');
for(var i = 0; i < inp.length; i++) {
inp[i].setAttribute('data-pl', inp[i].getAttribute('placeholder'));
inp[i].value = inp[i].getAttribute('placeholder');
}
var o = {
focus: function (e) {
e = e.target || e.srcElement;
if(!e.type == 'text') return;
if(e.value == e.getAttribute('data-pl')) {
e.value = '';
e.style.color = 'black'
}
addevent(e, 'blur', o.blur);
},
blur: function (e) {
e = e.target || e.srcElement;
if(e.value === '' || e.value == ' ') {
e.value = e.getAttribute('data-pl');
e.style.color = 'silver';
}
delevent(e, 'blur', o.blur);
},
createPlaceholder: function (place) {
var input = document.createElement('input');
input.type = 'text';
if('placeholder' in document.createElement('input') input.placeholder = place;
else input.setAttribute('data-bl', plc);
return input;
},
event: function () {
if('placeholder' in document.createElement('input')) return;
addevent(document.body, 'click', o.focus);
addevent(document.body, 'blur', o.blur);
}
}
o.event();
return o;
};
var fn1 = fn()
console.log(fn1)
[/JS]
</script>
</html>
через createPlaceholder можно создавать смело input. |
у меня работает ie8+
|
caetus, ты не правильно понял.
В общем, вроде бы работает: http://learn.javascript.ru/play/rc5dBb Работает в IE8-9 и в последнем Firefox'е (отключил проверку для теста), надеюсь в старых версиях тоже получится. Пока не решил проблему с автозаполнением браузера по F5. |
Короче, все удалось с таким старьем как Firefox 3.6 и Opera 10.6.
В webkit-based браузерах облом - в них фэйковые дескрипторы нативных свойств DOM-элементов. Автозаполнение тоже победил. Чуть поправлю код и залью на гитхаб. Правда опоздал я на пару годков с этой темой)) |
| Часовой пояс GMT +3, время: 09:29. |