Показать сообщение отдельно
  #1 (permalink)  
Старый 11.01.2015, 20:19
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Прозрачный полифил атрибута 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.
__________________
В личку только с интересными предложениями

Последний раз редактировалось danik.js, 11.01.2015 в 20:24.
Ответить с цитированием