Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Повесить сеттер на input.value (https://javascript.ru/forum/misc/30240-povesit-setter-na-input-value.html)

FINoM 28.07.2012 19:33

Повесить сеттер на input.value
 
Подскажите, как вызвать некую функцию не только при вызове события (keydown, select, change...), но и при обычном присваивании элементу формы некоегого значения:
input.value = 'blah'; // ← должна вызываться определенная функция
(на старые браузеры можно забить)

Обычный Object.defineProperty здесь, наверно, не прокатит, так как убивает стандартный геттер и сеттер.

Тот же вопрос интересен и касательно innerHTML.

devote 28.07.2012 19:38

<input id="lala" type="text" />
<script>
    var inp = document.getElementById( 'lala' );
    var descriptor = Object.getOwnPropertyDescriptor( inp, 'value' );
    var oldSetter = descriptor.set;
    descriptor.set = function( value ) {
        alert( "Попытка назначить: " + value );
        oldSetter.apply( this, arguments );
    }
    Object.defineProperty( inp, "value", descriptor );

    inp.value = "test";;
</script>

FINoM 28.07.2012 19:41

devote,
Uncaught TypeError: Invalid property.  A property cannot both have accessors and be writable or have a value, #<Object>


Object.getOwnPropertyDescriptor ( ROOT.name.field, 'value' )
 → 
configurable: true
enumerable: true
value: "Jubilee"
writable: true


Тут нет сеттера, как видно.

devote 28.07.2012 19:48

Я так понимаю это хром тупит с первым вариантом.
<input id="lala" type="text" />
<script>
    var inp = document.getElementById( 'lala' );

    Object.defineProperty( inp, "value", {
        configurable: true,
        enumerable: true,
        set: function( value ) {
            alert( "Попытка назначить: " + value );
            this.setAttribute( "value", value );
        },
        get: function() {
            return this.getAttribute( "value" );
        }
    });
 
    inp.value = "test";

    alert( inp.value );
</script>

FINoM 28.07.2012 19:50

devote, хм, как-то не догадался использовать атрибут. Спасибо.

FINoM 28.07.2012 19:51

Цитата:

Сообщение от devote
Я так понимаю это хром тупит с первым вариантом.

Он не тупит, просто дескриптор не содержит акцессоров.

devote 28.07.2012 19:54

Цитата:

Сообщение от FINoM
Он не тупит, просто дескриптор не содержит акцессоров.

это я понял, а опера содержит.

FINoM 28.07.2012 19:57

С innerHTML вопрос еще открыт. Здесь никак не заюзаешь атрибут.
Хотя, в принципе, можно погеморроиться: при срабатывании сеттера превращать полученную строку в DOM элементы, затем аппендить в искомый элемент, предварительно удалив каждый тег внутри.
При геттере преобразовывать элементы внутри в строку.
Но это уж слишком геморройно.

FINoM 28.07.2012 20:18

Вот она, рыба:
<div>Blah</div>
<span></span>
<script>
var div = document.querySelector( 'div' ),
  span = document.querySelector( 'span' );

div.addEventListener( 'DOMSubtreeModified', function() {
  span.innerHTML = 'fuck yea';
});

div.innerHTML = 'New HTML';
</script>

devote 28.07.2012 20:18

Цитата:

Сообщение от FINoM
Но это уж слишком геморройно.

ну почему геморойно, не так и геморно:

<div id="lala"></div>
<script>
    var div = document.getElementById( 'lala' );
 
    (function( div ) {
        var currentInnerHTML = div.innerHTML;
        Object.defineProperty( div, "innerHTML", {
            configurable: true,
            enumerable: true,
            set: function( value ) {
                alert( "Попытка назначить: " + value );
                var div = document.createElement("DIV");
                div.innerHTML = value;
                currentInnerHTML = div.innerHTML;
                // очищаем от всего что есть сейчас
                while( this.firstChild ) {
                    this.removeChild( this.firstChild );
                }
                // добавляем новое
                while( div.firstChild ) {
                    this.appendChild( div.firstChild );
                }
            },
            get: function() {
                return currentInnerHTML;
            }
        });
    })( div );
  
    div.innerHTML = "<b>test</b> <i>italic</i>";
 
    alert( div.innerHTML );
</script>


Часовой пояс GMT +3, время: 22:39.