Подтвердить что ты не робот

JQuery обнаруживает программные изменения в поле

У меня есть скрытое поле, называемое #myHiddenField say.

Содержимое этого поля программно изменяется в разных местах.

Мне нужен метод, который обнаруживает это изменение. Событие изменения не будет срабатывать, если я не введу в поле, но это невозможно.

Есть ли способ jQuery для обнаружения изменения программного контента в поле?

4b9b3361

Ответ 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;