JSFiddle - React, Tailwind, and code Playground
by lid0
HTML
<progress id="prog1" value="10" max="100"></progress>
<p>
output(events):
</p>
<pre id="output"></pre>
CSS
#output {
font-size:12px;
background:#cfcfcf;
padding:1px;
}
JavaScript
/**
lidlanca - 2021 Mar
add ability to listen to value change of <progress> element
- hook to .value setter, to detect value set
- hook to getter of .setAttribute, and wrap call to spy on call
will dispatch customEvent 'change' preValue and newValue will be attached to the event detail property.
**/
function findDescriptor(obj, prop) {
return Object.hasOwnProperty.call(obj, prop) ?
Object.getOwnPropertyDescriptor(obj, prop) :
findDescriptor(Object.getPrototypeOf(obj), prop);
}
// log output
var output = document.getElementById("output")
// progress element
var el = document.getElementById("prog1")
// add value change event ( .value or via setAttribute )
supportValueChangeEvent(el)
// listen for change event, will fire even if value is the same, can be improved
el.addEventListener("change", function(ee) {
output.innerHTML += "<progress> event 'change' : " + JSON.stringify(ee.detail) + "\n"
})
function supportValueChangeEvent(el) {
var {
get: Vget,
set: Vset
} = findDescriptor(el, "value")
var {
value: SetAttributeGet,
} = findDescriptor(el, "setAttribute")
Object.defineProperty(el, "setAttribute", {
get() {
var origSetAttributeMethod = SetAttributeGet.bind(this); //bind original method
// proxy/wrap method
var _setAttribute = function(key, value) {
prevValue = el.getAttribute("value")
var ev = new CustomEvent('change', {
detail: {
prevValue: prevValue,
newValue: `${value}`
}
});
// call original set method
origSetAttributeMethod(key, value)
// dispatch change event, if changed
if (prevValue != value) el.dispatchEvent(ev);
return true
}
return _setAttribute;
}
})
Object.defineProperty(el, "value", {
configurable: true,
enumerable: true,
set(value) {
var prevValue = Vget.call(this)
var ev = new CustomEvent('change', {
detail:...