2

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 change = 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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
cc young
  • 18,939
  • 31
  • 90
  • 148
  • " how do I know if any exit" do you MEAN EXIT or do you MEAN EXIST? quite different in this context. – Mark Schultheiss Aug 31 '11 at 13:40
  • @Mark Schultheiss - "exist" - thanks – cc young Aug 31 '11 at 13:51
  • You are dealing with events. You should NOT need to "call" events on ancesters, they should have event handlers to "handle" the events, although you MIGHT consider "triggering" those events - the stopPropagation is there for some reason by the author of that event, thus I would foresee the trigger of "new" events approriate for the parent elements to handle, although here I would prefer to see the event bubble and refactor that event propagation. – Mark Schultheiss Aug 31 '11 at 14:49
  • @Mark Schultheiss - I think we are going in circles a little. do you know how to create a chat for us - that is, if you would be kind enough to take the time? – cc young Aug 31 '11 at 15:33

4 Answers4

0

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 inputs, textareas and selects, 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.

Michael Sagalovich
  • 2,539
  • 19
  • 26
  • using javascript - open jQuery source and copy the way they trigger events. why on earth not use jQuery? – Michael Sagalovich Aug 31 '11 at 13:37
  • Although `change` event is not valid at the FORM level, it can be _applied_ at the form level, and then all ITEMs in the form will use it – cc young Aug 31 '11 at 13:45
  • personally I am very comfortable with js as a language and with it's level of abstraction. personally do not care for jQuery's hiding functionality from me, nor do I find its notation aesthetically pleasing. I realize this is a minority report probably only favored by other graybeards as myself. – cc young Aug 31 '11 at 14:00
  • ok, do not use jQuery. just look at how they trigger events and steal it. – Michael Sagalovich Aug 31 '11 at 14:39
  • and if you do not like using jQuery, do not use it anywhere - all your scripts will still work. use it just in this particular case to ease your life. why not? – Michael Sagalovich Aug 31 '11 at 14:41
  • what I am working on is a library with no outside dependencies – cc young Aug 31 '11 at 15:32
0

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.

duri
  • 14,991
  • 3
  • 44
  • 49
  • am not understanding you at all. to the best of my knowledge, `this` in an event is the `window`. – cc young Aug 31 '11 at 14:01
  • @cc young It is not. If you use `addEventListener`, the `this` object in the event handler refers to the element which "owns" the handler (`document.getElementById('f')` in your case). – duri Aug 31 '11 at 14:05
  • in this case the handler function is part of the Render class. within the function, `this` references that class, not `document.getElementById('f')` – cc young Sep 01 '11 at 06:00
0

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.

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • for example, in chrome , the input box has up/down arrows to the right - clicking on these increments/decrements the value. could use `click` to capture the activity, but it seems the problem remains the same. – cc young Aug 31 '11 at 13:49
  • See my note on the question regarding events, event triggers etc. – Mark Schultheiss Aug 31 '11 at 14:55
  • FYI, IF you have the desire to not use a library, you might want to start with a reference page for events such as: http://www.quirksmode.org/dom/events/index.html – Mark Schultheiss Aug 31 '11 at 15:01
  • appreciate the reference to quirksmode - that page and I are very good friends. recently found http://help.dottoro.com/lagstsiq.php/#Event which has been a great reference. what I'm working on is a library that has no outside dependencies. – cc young Aug 31 '11 at 15:31
0

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',...)

Community
  • 1
  • 1
cc young
  • 18,939
  • 31
  • 90
  • 148