Прозрачный полифил атрибута 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, время: 11:06. |