JQuery обнаруживает программные изменения в поле
У меня есть скрытое поле, называемое #myHiddenField
say.
Содержимое этого поля программно изменяется в разных местах.
Мне нужен метод, который обнаруживает это изменение. Событие изменения не будет срабатывать, если я не введу в поле, но это невозможно.
Есть ли способ jQuery для обнаружения изменения программного контента в поле?
Ответы
Ответ 1
Вы можете запустить событие изменения с помощью:
$('#myHiddenField').change();
ИЛИ
$('#myHiddenField').trigger('change');
Конечно, для этого потребуется блок кода, ответственный за обновление поданной заявки, чтобы сделать один из этих вызовов после того, как он выполнил свою работу.
Ответ 2
DOM не может обнаружить программное повышение событий. Я на самом деле столкнулся с этим вчера. Я не помню, где я его читал, но решение состояло в том, чтобы на самом деле вызвать .trigger()
в элементе jQuery. jQuery Doc
Ответ 3
Установка значения с использованием .val() в jQuery не вызывает событие изменения, поэтому вам нужно будет использовать .change() или .trigger('change'), чтобы вызвать событие изменения. Вы можете использовать либо .change(function() {...}), либо .on('change', function() {...}, чтобы обнаружить событие изменения в поле.
$('#myHiddenField').change(function() {
alert('content changed to: ' + $('#myHiddenField').val());
});
$('#btnChange').click(function() {
$('#myHiddenField').val("new content");
$('#myHiddenField').change();
});
https://jsfiddle.net/qeg5of2a/1/
или
$('#myHiddenField').on('change', function() {
alert('content changed to: ' + $('#myHiddenField').val());
});
$('#btnChange').click(function() {
$('#myHiddenField').val("new content");
$('#myHiddenField').trigger('change');
});
https://jsfiddle.net/qeg5of2a/2/
.change - это просто ярлык для .on('change', handler) и .trigger('change'), поэтому либо отлично
Ответ 4
Случай 1:
Вы хотите изменить значение программно самостоятельно и просто хотите отправить событие при изменении значения.
$('#myfield').text('New value');
//$('#myfield').val('New value');
$('#myfield').trigger('change');
Случай 2:
Предположим, вы хотите обнаружить программные изменения в поле, которое не написано вами. Таким образом, вы не можете инициировать событие "change".
В этом случае используйте "DOMSubtreeModified" для обнаружения программных изменений для элементов-потомков родительского элемента.
Пример:
<div id="product-addons-total">
<div id="total_price">200</div>
</div>
$(document).ready(function() {
jQuery('#product-addons-total').on("DOMSubtreeModified",function(){
console.log('content changed');
//tamp_price_change_handler();
});
});
Теперь, если значение "total_price" каким-то образом программным образом изменится, оно запустит событие "DOMSubtreeModified". Пример:
jQuery('#total_price').text('300');
Предостережение для случая 2: DOMSubtreeModified может создавать бесконечный цикл и значительно ухудшать производительность. Вместо этого рекомендуется использовать MutationObserver.
Пример с MutationObserver:
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// Let configure the observer
var config = { childList: true, subtree:true, attributes: true, characterData: true,
characterDataOldValue: true, attributeOldValue: true };
//Let get a node.
var target = jQuery('#product-addons-total').get(0);
// Let pass the target and configuration to the observe function.
observer.observe(target, config);
Случай 3:
Вышеуказанные способы могут обнаружить изменение в DOM. Но если вы хотите программно изменить значение поля ввода, то эти события не будут срабатывать. В этом случае единственный способ - запустить событие вручную.
Итак, сначала измените значение поля ввода, а затем запустите событие вручную.
$('#inputfield').val(456465).trigger('change');
//Now the change event will fire.
$('#inputfield').on('change', function() {
console.log('input filed has been changed');
});
Ответ 5
Вы можете поменять переопределенную версию объекта объекта JQ, например val
или html
, чтобы достичь этого (или, возможно, переопределить метод объекта "чистый JS" ). Лично я не могу работать MutationObserver
, и это решение, которое я предлагаю, может быть проще:
const jqInvoiceNo = $('#InvoiceNo');
const jqProto = Object.getPrototypeOf( jqInvoiceNo );
const valOverride = function( newVal ){
console.log( '£ override val, invoice no: ' + newVal );
// essential function 'call'... note usage
// we assume that if newVal is undefined this means we are using the
// parameterless JQ method signature version, which returns the value
if( newVal === undefined ){
return jqProto.val.call( this );
}
jqProto.val.call( this, newVal );
// ... then do something else, having intercepted the value-setting mechanism
};
jqInvoiceNo.val = valOverride;
... // later, in your code:
jqInvoiceNo.val( '99' );
Важно: этот код, как записано, только перезаписывает/переопределяет метод val для этого одного объекта JQ. Важно знать, что если вы идете $( '#InvoiceNo' )
где-то еще, вы фактически создадите полностью новый объект JQ без переопределенного метода val
. Другими словами, в этом случае вы должны отслеживать объекты JQ.
Вы также можете переопределить любые методы объекта "чистого JS" таким же образом, особенно (для этого случая) setAttribute
.
NB для тех, кто еще не знает, 1-й элемент JQ-объекта, т.е. [0]
, является "реальным" объектом JS, который он обертывает.
const invoiceNo = $('#InvoiceNo')[ 0 ];
const proto = Object.getPrototypeOf( invoiceNo );
const setAttributeOverride = function( attr, newVal ){
console.log( '£ override setAttribute, invoice no: ' + newVal );
// essential function 'call'... note usage:
proto.setAttribute.call( this, attr, newVal );
if( attr === 'value' ){
// ... then do something else, having intercepted the value-setting mechanism
}
};
// note that only this object 'invoiceNo' will be given the overridden method:
invoiceNo.setAttribute = setAttributeOverride;
.... // later, in your code:
$( '#InvoiceNo' )[ 0 ].setAttribute( 'value', '99' );
В отличие от приведенного выше примера JQ, существует один и только один такой "чистый JS" объект... поэтому переход $( '#InvoiceNo' )[ 0 ]
в любом месте вашего кода всегда даст вам тот же объект JS. Конечно, обычным способом установки атрибута (или, скорее, "свойства" ) в "чистом JS" является
object.value = newValue;
... какая команда, насколько я знаю, не может быть "переопределена". Предположительно это можно обнаружить с помощью MutationObserver
, если у вас больше успеха, чем у меня.
PS точно, как JQ задает значение своего "реального JS" объекта, когда вызывается метод JQ, такой как val
или html
. Я не знаю. Если вы хотите, чтобы мог фактически переопределить эти методы, чтобы "сделать это самостоятельно", воспользовавшись тем, что "эквивалентные" объекты JQ относятся к одному и тому же основному объекту JS, т.е. Поскольку $( '#InvoiceNo' )[ 0 ]
всегда ссылается к одному и тому же объекту JS. Но в этом случае вам придется переопределить val
или html
для объектов ВСЕ JQ, т.е. Изменить сам прототип:
const jqInvoiceNo = $('#InvoiceNo');
const jqProto = Object.getPrototypeOf( jqInvoiceNo );
jqProto.superValMethod = jqProto.val;
const valOverride = function( newVal ){
if( newVal === undefined ){
return jqProto.superValMethod.call( this );
}
jqProto.superValMethod.call( this, newVal );
const ourPureJSObject = this[ 0 ];
// do something with this ... it will always the right one!
};
jqProto.val = valOverride;