You can rely on the coder programmatically changing the element to know to trigger the onChange, but that's an iffy proposition. Looking through other posts, this looks very promising: for your text element, override the setters and getters, so that they automagically trigger for either keyed changes or programattic ones.
var btn1 = document.getElementById('button1');
var txt1 = document.getElementById('text1');
btn1.onclick = function() {
txt1.value = 'hello world'
}
txt1.addEventListener("change", function(e){
console.log(txt1.value);
})
//property mutation for hidden input
Object.defineProperty(txt1, "value", {
// Don't override the getter, but stub it in.
get: function() {
return this.getAttribute("value");
},
// In the setter, we want to set the value
// and also fire off the change event.
// By doing this, the coder changing the
// value never needs worry about it.
set: function(val) {
console.log("set");
// handle value change here
this.setAttribute("value", val);
//fire the event
if ("createEvent" in document) { //NON IE browsers
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
txt1.dispatchEvent(evt);
} else { //IE
var evt = document.createEventObject();
txt1.fireEvent("onchange", evt);
}
}
});
<input type="button" id="button1" value="button" />
<input type="text" id="text1" />
Or see it as a fiddle Here
So, to answer your question about why the click handler is showing the input as having a null value, it's because the getter/setter are overriding the default value behavior. The easiest way to work around this is to create a custom getter/setter to act as an interface to the value attribute:
var btn1 = document.getElementById('button1');
var txt1 = document.getElementById('text1');
btn1.onclick = function() {
console.log("in the button's click handler, ");
console.log("Value is: " + txt1.val);
console.log("--------------------------------")
txt1.val = 'hello world'
}
txt1.addEventListener("change", function(e) {
console.log("in txt1.onChange function...")
console.log(this.val);
console.log("--------------------------------")
})
//property mutation for hidden input
Object.defineProperty(txt1, "val", {
get: function() {
return this.value;
},
set: function(val) {
// handle value change here
this.value = val;
//fire the event
if ("createEvent" in document) { //NON IE browsers
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
txt1.dispatchEvent(evt);
} else { //IE
var evt = document.createEventObject();
txt1.fireEvent("onchange", evt);
}
}
});
<input type="button" id="button1" value="button" />
<input type="text" id="text1" />
What's happening here is, when the button is clicked, I get the val attribute of the input (which gets the value behind the scenes), then programmatically sets the val attribute of the same input (which, again, sets the value attribute). For some reason, you can't use get/set in object.defineProperty on an input's value attribute without completely breaking it. So in the console, you'll see THREE function calls: when you click the button, the input loses focus, triggering its change method, but then the button itself triggers its click handler, which then changes the value of the input and triggers the change handler one more time.
Hope this helps!
Again, to see this as a fiddle...