In Javascript, how to determine and call inherited listeners?
If a change
listener is attached to an item, it can be called with item.onchange()
. But what if the change trigger emanates from a parent node?
The context: use a input
event to capture up/down changes on an INPUT type='number' item since change
does not capture them.
Theory of operation: use input
to capture, but wait 500 ms before calling normal change
listeners. Easy when the change
listener is attached directly to the target element. The problem is needed to call inherited change triggers as well - how do I know if any exist, and how do I call them?
HTML:
<form id='f'>
<input type='number' id='i' />
</form>
Javascript:
// attach main onchange trigger to form
document.getElementById('f').addEventListener('change',changeFunc,true);
// if user "scrolls" number value, do same as change trigger after 500 ms
var inputCt = 0;
function inputToChange(e) {
inputCt++;
setTimeout( next, 500 );
function next() {
inputCt--;
if( !inputCt ) {
// if element has it's own change trigger, call it
if( e.target.onchange ) e.target.onchange(e);
// PROBLEM - how to call inherited change triggers
}
}
}
document.getElementById('f').addEventListener('input',inputChange,true);
The only way I see to do this is to manually go through ancestors, checking for existence and calling as I go. But that leads to the next problem: any one of these listener functions may have issued as e.stopPropagation
, but I see now way of determining if this is indeed the case - which means climbing ancestors will not work.
as per @Andy E answer on How can I trigger an onchange event manually?, here is the solution:
Javascript:
// attach main onchange trigger to form
document.getElementById('f').addEventListener('change',changeFunc,false);
// if user "scrolls" number value, do same as change trigger after 500 ms
var inputCt = 0;
function inputToChange(e) {
inputCt++;
setTimeout( next, 500 );
function next() {
inputCt--;
if( inputCt ) return;
var change = var ch开发者_开发百科ange = document.createEvent("Event");
change.initEvent('change',true,true);
e.target.dispatchEvent(change);
}
}
document.getElementById('f').addEventListener('input',inputChange,false);
note 1: that the useCapture
(third) arg to addEventListener
was wrong - needs to be false so item triggers are called before form triggers.
note 2: this function would probably be better suited to 'click' than 'input' - the problem with 'click' is that focus and text positioning clicks need to be distinguished from click changing the value.
Using jQuery, $(e.target).change()
should do the job, I believe. Or $(e.target).trigger(eventname)
, with eventname = 'change'
in your case, and any other event name in general.
Apparently, change
event is valid only on input
s, textarea
s and select
s, which cannot be nested. So you cannot have a problem when parent defines change event handler that needs to be triggered after the child's one.
In the event listener, create reference to this
object (for example, var that = this;
). Then, you can use that.onchange(e);
in the next
's body.
A change even will not fire on "up/down" I make the assumption you mean arrow up/down?
If that is the case, you will need to capture the key event (key press, key up, key down etc) for those KEY events.
as per @Andy E in answer to How can I trigger an onchange event manually?, build an event and dispatch. have put details in the question.
btw, onchange
is set if and only if the change
trigger was set through an onchange
attribute, not with addEventListener('change',...)
精彩评论