0

I have a certain requirement where I want to be notified about all changes in HTML input on a page specifically value of all input elements on page, if value change by any means

So far what all I have tried is

  1. Approach1: Hooking into all input elements on page with input or change event (this only emits values if you are interacting with particular input field & does not emit other input value changes on page even if you hook event into all of them)
  2. Approach2: MutationObserver - this only hooks into elements on page if there is any visible or html attribute change on page. in case input value gets updated, this does not notify about change

With this I ran out of depth for achieving end result. If you have already gone through similar situations or have a direction to follow through, help is appreciated!!

Edit: To elaborate more with example enter image description here

If I change input with red marker that changes value of blue marker element as well. I am more interested in getting notified by any sort of event when there is change in value of blue marker element when its value is changed by red one.

Edit2:

Approach1 Above

// hook into all input events and listen to their changed value
const inputs = document.querySelectorAll("input");
for (const inp of inputs) {
  inp.addEventListener("input", function(ev) {
    console.log("changed", ev.target)
  })
}

/* 
  Input1 and input2 are interconnected
  scenario: enter any number in input1 that multiplies its number by 2 & populates its value in number2
*/
const input1 = document.getElementById('input1') 
const input2 = document.getElementById('input2') 
input1.addEventListener('input', (event) => { input2.value = event.target.value * 2 })

/* 
 Expectation: If i change value of input1, automatically input2 value is getting changed because of the way they are internconnected
 
 If you check console logs now, Even though we added Listners on both input on line 4 (javascript), and even though both inputs are getting changed. only one value is getting logged. i.e. of input1
 
Although I know input event does not work this way, I am looking into other ways of listening to both input changes
*/
<!-- We will call this input1 -->
<input type="number" id="input1" />
<!-- We will call this input2 -->
<input type="number" id="input2" />

Approach2

// hook into container with MutationObserver and listen to all mutations of container
var mutationObserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation);
  });
});

const container = document.getElementById('container');
mutationObserver.observe(container, {
  attributes: true,
  characterData: true,
  childList: true,
  subtree: true,
  attributeOldValue: true,
  characterDataOldValue: true
});

/* 
  Input1 and input2 are interconnected
  scenario: enter any number in input1 that multiplies its number by 2 & populates its value in number2
*/
const input1 = document.getElementById('input1') 
const input2 = document.getElementById('input2') 
input1.addEventListener('input', (event) => { input2.value = event.target.value * 2 })

/* 
 Expectation: If i change value of input1, automatically input2 value is getting changed because of the way they are internconnected
 
 If you check console logs now, it will only observe mutations of input1, it won't log any mutations of input2
 
Expectation is it should also detect changes/mutations happending in input2 since that is also changing
*/
<section id="container">
  <!-- We will call this input1 -->
  <input type="number" id="input1" />
  <!-- We will call this input2 -->
  <input type="number" id="input2" />
</section>

PS: I do not have any control over DOM, so Its not in my hand to modify property of DOM as explained in related question, My use case is around a chrome extension, which is only allowed to read and process DOM

With suggested answer, it does not really listens to typing event, it only relies on value being changed by calling .value on element, which is not necessarily case in my question, change of input can be done by any possible approach by developers of different websites. so basically - input value changed by javascript is not realy use case I am looking for

Rohit
  • 337
  • 7
  • 17
  • 1
    Please clarify what you mean by `does not care about all other inputs on page` and add a [mre] to your question. –  May 12 '22 at 12:24
  • Thanks Chris, I have updated it with example, hope it is even more clear now – Rohit May 12 '22 at 12:38
  • So listen for the change on the red and when the red changes, you know the blue changes. Now if they are making a call that takes time you might need to add something that polls the other input until the value changes. MutationObserver can not detect the value property change. – epascarello May 12 '22 at 12:39
  • If some other script is updating other inputs, just grab all input values after a small timeout or something. I still don't understand what the problem is tbh. –  May 12 '22 at 12:40
  • @epascrello I have already tried with MutationObserver, It does not emit anything for input value change, but rest of the changes it captures well, Do let me know if you have already tried it specifically this way – Rohit May 12 '22 at 12:46
  • @Chris G, https://thewebdev.info/2021/03/03/how-to-watch-for-dom-changes-with-javascript/ similar approach is also suggested by this article. I am more interested in event based notification than gabbing of values on interval, with Timeout/Interval approach, there is a possibility that i might lose some data. And data is very important – Rohit May 12 '22 at 12:48
  • Please clarify what the specific issue of your first approach is. Given the example of two currency inputs, how did it fail to work when you tried to listen for input or change events? Were you getting an old value? –  May 12 '22 at 13:02
  • 1
    @ChrisG input/change event does not fire when JavaScript changes the value. That is the OPs issue. MutationObserver does not listen to property changes. – epascarello May 12 '22 at 13:23
  • @Chris G, Added both examples above to demonstrate what I have already tried. Please go through comment, I have tried my best to explain it there – Rohit May 12 '22 at 13:29
  • 1
    Got it, thanks for all that effort. The only solution I can see is to repeatedly check all values in an interval. –  May 12 '22 at 13:31
  • You can override the setter for the `value` property as demonstrated in the answers to [this question](https://stackoverflow.com/questions/16013024/detect-programmatic-changes-on-input-type-text). – Besworks Jul 05 '22 at 18:28

1 Answers1

1

The following code will hook the input event of all <input> elements on the page:

const inputs = document.querySelectorAll("input");
for (const inp of inputs) {
  inp.addEventListener("input", function(ev) {
    console.log("changed", ev.target, ev.target.value)
  })
}
hello
<input type="text" /> 
world
<input type="text" />
spender
  • 117,338
  • 33
  • 229
  • 351
  • Thanks for the answer, but this is not tracking changes of all input elements, this is only tracking for currently interacted one – Rohit May 12 '22 at 12:31
  • I have edited my question to explain it even better – Rohit May 12 '22 at 12:36
  • Ok thanks. `MutationObserver` comes very close to what I need, Only problem I have is it does not observe on javascript internal values of element. However, there is a way suggested by this article using setInterval, but that is not really ideal solution https://javascript.tutorialink.com/detect-input-value-change-with-mutationobserver/ – Rohit May 12 '22 at 12:42