Повесить сеттер на 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, время: 08:23. |