Повесить сеттер на input.value
Подскажите, как вызвать некую функцию не только при вызове события (keydown, select, change...), но и при обычном присваивании элементу формы некоегого значения:
input.value = 'blah'; // ← должна вызываться определенная функция(на старые браузеры можно забить) Обычный Object.defineProperty здесь, наверно, не прокатит, так как убивает стандартный геттер и сеттер. Тот же вопрос интересен и касательно innerHTML. |
<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> |
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 Тут нет сеттера, как видно. |
Я так понимаю это хром тупит с первым вариантом.
<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> |
devote, хм, как-то не догадался использовать атрибут. Спасибо.
|
Цитата:
|
Цитата:
|
С innerHTML вопрос еще открыт. Здесь никак не заюзаешь атрибут.
Хотя, в принципе, можно погеморроиться: при срабатывании сеттера превращать полученную строку в DOM элементы, затем аппендить в искомый элемент, предварительно удалив каждый тег внутри. При геттере преобразовывать элементы внутри в строку. Но это уж слишком геморройно. |
Вот она, рыба:
<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> |
Цитата:
<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> |
Цитата:
|
хотя не, в опере у меня не пашет твой вариант, в 12-й не тестил, у меня щас 11.64... но зато в опере есть дескрипторы сеттер/геттер, тоесть с ней вообще все проще.
|
http://help.dottoro.com/ljrmcldi.php ← тут пишут, что работает везде, кроме оперы.
|
для оперы этот вариант канает:
<div id="lala"></div> <script> var div = document.getElementById( 'lala' ); var descriptor = Object.getOwnPropertyDescriptor( div, 'innerHTML' ); var oldSetter = descriptor.set; descriptor.set = function( value ) { alert( "Попытка назначить: " + value ); oldSetter.apply( this, arguments ); } Object.defineProperty( div, "innerHTML", descriptor ); div.innerHTML = "<b>test</b> <i>italic</i>"; alert( div.innerHTML ); </script> |
Цитата:
|
ты просто проверяй присутствие дескриптора сеттер, если есть юзай defineProperty, в противном случае событие что ты показал.. и т.д.
|
FINoM,
а ты видел че пишет w3c? http://www.w3.org/TR/DOM-Level-3-Eve...ubtreeModified Цитата:
|
В жопу W3C :D
|
Цитата:
|
Вот, написал код, работает в IE, Firefox, Opera, но не в Chrome.
<!DOCTYPE html> <html><head> <title></title> </head><body> <p>asd</p> <script type="text/javascript"> //основной код var desc={ get: function () { delete this.innerHTML; var res=this.innerHTML; Object.defineProperty(this, "innerHTML", desc); return res; }, set: function (value) { this.oninnerHTML(value); delete this.innerHTML; this.innerHTML=value; Object.defineProperty(this, "innerHTML", desc); }, configurable: true }; function setInnerHTMLHandler(element) { Object.defineProperty(element, "innerHTML", desc); } //конец основного кода var p=document.getElementsByTagName("p")[0]; setInnerHTMLHandler(p); p.oninnerHTML=function (text) { alert(text); } p.innerHTML="123"; </script> </body></html> |
Работает везде
<!DOCTYPE html> <html> <body> <div id="test"></div> <div id="test2"></div> <script> function setInnerHTMLHandler( elem, setfn, getfn ) { var descriptor = Object.getOwnPropertyDescriptor( elem, "innerHTML" ), temp = document.createElement( 'div' ), currentHTML = elem.innerHTML; Object.defineProperty( elem, "innerHTML", { configurable: true, set: descriptor.set ? function( value ) { var result; if ( !setfn || ( result = setfn( value ) ) !== false ) { descriptor.set.call( this, result || value ); } } : function( value ) { var result; if ( !setfn || ( result = setfn( value ) ) !== false ) { temp.innerHTML = result || value; currentHTML = temp.innerHTML; while( this.firstChild ) { this.removeChild( this.firstChild ); } while( temp.firstChild ) { this.appendChild( temp.firstChild ); } } }, get: descriptor.get ? function() { var result; if ( !getfn || ( result = getfn() ) !== false ) { return result || descriptor.get.call( this ); } } : function() { var result; if ( !getfn || ( result = getfn() ) !== false ) { return result || currentHTML; } } }); } // тесты var div = document.getElementById('test'); setInnerHTMLHandler( div, function( value ) { alert( "Попытка установить значение: " + value ); }, function() { alert( "Попытка получить значение" ); }) div.innerHTML = "Hello World!!!"; alert( div.innerHTML ); var div2 = document.getElementById('test2'); setInnerHTMLHandler( div2, function( value ) { alert( "Попытка установить значение: " + value ); return "А вот и значение: " + value; }, function() { alert( "Попытка получить значение" ); return "Текущее не дам"; }) div2.innerHTML = "Hello World!!!"; alert( div2.innerHTML ); </script> </body> </html> |
Цитата:
Да и там, где работает, работает неправильно: innerHTML - это не единственный способ изменить содержимое элемента. Например appendChild не изменяет локальную переменную currentHTML. |
У меня вопрос: нужно отследить только записи innerHTML или любые изменения внутри элемента?
|
Часовой пояс GMT +3, время: 16:10. |