View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.event;
16  
17  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
18  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
19  
20  import java.util.ArrayList;
21  
22  import org.htmlunit.ScriptResult;
23  import org.htmlunit.corejs.javascript.Context;
24  import org.htmlunit.corejs.javascript.Scriptable;
25  import org.htmlunit.corejs.javascript.ScriptableObject;
26  import org.htmlunit.html.DomNode;
27  import org.htmlunit.javascript.HtmlUnitScriptable;
28  import org.htmlunit.javascript.JavaScriptEngine;
29  import org.htmlunit.javascript.configuration.JsxClass;
30  import org.htmlunit.javascript.configuration.JsxConstant;
31  import org.htmlunit.javascript.configuration.JsxConstructor;
32  import org.htmlunit.javascript.configuration.JsxFunction;
33  import org.htmlunit.javascript.configuration.JsxGetter;
34  import org.htmlunit.javascript.configuration.JsxSetter;
35  
36  /**
37   * JavaScript object representing an event that is passed into event handlers when they are
38   * invoked. For general information on which properties and functions should be supported,
39   * see <a href="https://developer.mozilla.org/en-US/docs/DOM/event">the mozilla docs</a>,
40   * <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event">the W3C DOM
41   * Level 2 Event Documentation</a> or <a href="http://msdn2.microsoft.com/en-us/library/aa703876.aspx">IE's
42   * IHTMLEventObj interface</a>.
43   *
44   * @author <a href="mailto:chriseldredge@comcast.net">Chris Eldredge</a>
45   * @author Mike Bowler
46   * @author Chris Erskine
47   * @author Marc Guillemot
48   * @author Daniel Gredler
49   * @author Brad Murray
50   * @author Ahmed Ashour
51   * @author Rob Di Marco
52   * @author Ronald Brill
53   * @author Frank Danek
54   * @author Atsushi Nakagawa
55   * @author Thorsten Wendelmuth
56   */
57  @JsxClass
58  public class Event extends HtmlUnitScriptable {
59  
60      /**
61       * Key to place the event's target in the Context's scope during event processing
62       * to compute node coordinates compatible with those of the event.
63       */
64      protected static final String KEY_CURRENT_EVENT = "Event#current";
65  
66      /** The submit event type, triggered by {@code onsubmit} event handlers. */
67      public static final String TYPE_SUBMIT = "submit";
68  
69      /** The change event type, triggered by {@code onchange} event handlers. */
70      public static final String TYPE_CHANGE = "change";
71  
72      /** The load event type, triggered by {@code onload} event handlers. */
73      public static final String TYPE_LOAD = "load";
74  
75      /** The unload event type, triggered by {@code onunload} event handlers. */
76      public static final String TYPE_UNLOAD = "unload";
77  
78      /** The popstate event type, triggered by {@code onpopstate} event handlers. */
79      public static final String TYPE_POPSTATE = "popstate";
80  
81      /** The focus event type, triggered by {@code onfocus} event handlers. */
82      public static final String TYPE_FOCUS = "focus";
83  
84      /** The focus in event type, triggered by {@code onfocusin} event handlers. */
85      public static final String TYPE_FOCUS_IN = "focusin";
86  
87      /** The focus out event type, triggered by {@code onfocusout} event handlers. */
88      public static final String TYPE_FOCUS_OUT = "focusout";
89  
90      /** The blur event type, triggered by {@code onblur} event handlers. */
91      public static final String TYPE_BLUR = "blur";
92  
93      /** The key down event type, triggered by {@code onkeydown} event handlers. */
94      public static final String TYPE_KEY_DOWN = "keydown";
95  
96      /** The key down event type, triggered by {@code onkeypress} event handlers. */
97      public static final String TYPE_KEY_PRESS = "keypress";
98  
99      /** The input event type, triggered by {@code oninput} event handlers. */
100     public static final String TYPE_INPUT = "input";
101 
102     /** The key down event type, triggered by {@code onkeyup} event handlers. */
103     public static final String TYPE_KEY_UP = "keyup";
104 
105     /** The submit event type, triggered by {@code onreset} event handlers. */
106     public static final String TYPE_RESET = "reset";
107 
108     /** The beforeunload event type, triggered by {@code onbeforeunload} event handlers. */
109     public static final String TYPE_BEFORE_UNLOAD = "beforeunload";
110 
111     /** Triggered after the DOM has loaded but before images etc. */
112     public static final String TYPE_DOM_DOCUMENT_LOADED = "DOMContentLoaded";
113 
114     /** The event type triggered by {@code onpropertychange} event handlers. */
115     public static final String TYPE_PROPERTY_CHANGE = "propertychange";
116 
117     /** The event type triggered by {@code onhashchange} event handlers. */
118     public static final String TYPE_HASH_CHANGE = "hashchange";
119 
120     /** The event type triggered by {@code onreadystatechange} event handlers. */
121     public static final String TYPE_READY_STATE_CHANGE = "readystatechange";
122 
123     /** The event type triggered by {@code onerror} event handlers. */
124     public static final String TYPE_ERROR = "error";
125 
126     /** The message event type, triggered by postMessage. */
127     public static final String TYPE_MESSAGE = "message";
128 
129     /** The close event type, triggered by {@code onclose} event handlers. */
130     public static final String TYPE_CLOSE = "close";
131 
132     /** The open event type, triggered by {@code onopen} event handlers. */
133     public static final String TYPE_OPEN = "open";
134 
135     /** The load start event type, triggered by {@code onloadstart} event handlers. */
136     public static final String TYPE_LOAD_START = "loadstart";
137 
138     /** The load end event type, triggered by {@code onloadend} event handlers. */
139     public static final String TYPE_LOAD_END = "loadend";
140 
141     /** The progress event type, triggered by {@code onprogress} event handlers. */
142     public static final String TYPE_PROGRESS = "progress";
143 
144     /** The abort event type, triggered by {@code onabort} event handlers. */
145     public static final String TYPE_ABORT = "abort";
146 
147     /** The timeout event type, triggered by {@code ontimeout} event handlers. */
148     public static final String TYPE_TIMEOUT = "timeout";
149 
150     /** The scroll event type, triggered by {@code onscroll} event handlers. */
151     public static final String TYPE_SCROLL = "scroll";
152 
153     /** The scroll event type, triggered by {@code onscrollend} event handlers. */
154     public static final String TYPE_SCROLLEND = "scrollend";
155 
156     /** The search event type, triggered by {@code onsearch} event handlers. */
157     public static final String TYPE_SEARCH = "search";
158 
159     /** The dragend event type, triggered by {@code dragend} event handlers. */
160     public static final String TYPE_DRAGEND = "dragend";
161 
162     /** The invalid event type, triggered by {@code invalid} event handlers. */
163     public static final String TYPE_INVALID = "invalid";
164 
165     /** The pointerout event type, triggered by {@code pointerout} event handlers. */
166     public static final String TYPE_POINTEROUT = "pointerout";
167 
168     /** The ratechange event type, triggered by {@code ratechange} event handlers. */
169     public static final String TYPE_RATECHANGE = "ratechange";
170 
171     /** The animationiteration event type, triggered by {@code animationiteration} event handlers. */
172     public static final String TYPE_ANIMATIONITERATION = "animationiteration";
173 
174     /** The canplaythrough event type, triggered by {@code canplaythrough} event handlers. */
175     public static final String TYPE_CANPLAYTHROUGH = "canplaythrough";
176 
177     /** The cancel event type, triggered by {@code cancel} event handlers. */
178     public static final String TYPE_CANCEL = "cancel";
179 
180     /** The pointerenter event type, triggered by {@code pointerenter} event handlers. */
181     public static final String TYPE_POINTERENTER = "pointerenter";
182 
183     /** The select event type, triggered by {@code select} event handlers. */
184     public static final String TYPE_SELECT = "select";
185 
186     /** The auxclick event type, triggered by {@code auxclick} event handlers. */
187     public static final String TYPE_AUXCLICK = "auxclick";
188 
189 //    /** The mspointerleave event type, triggered by {@code mspointerleave} event handlers. */
190 //    public static final String TYPE_MSPOINTERLEAVE = "mspointerleave";
191 //
192     /** The webkitanimationstart event type, triggered by {@code webkitanimationstart} event handlers. */
193     public static final String TYPE_WEBANIMATIONSTART = "webkitanimationstart";
194 
195 //    /** The msgesturestart event type, triggered by {@code msgesturestart} event handlers. */
196 //    public static final String TYPE_MSGESTURESTART = "msgesturestart";
197 
198     /** The drag event type, triggered by {@code drag} event handlers. */
199     public static final String TYPE_DRAG = "drag";
200 
201     /** The seeked event type, triggered by {@code seeked} event handlers. */
202     public static final String TYPE_SEEKED = "seeked";
203 
204     /** The offline event type, triggered by {@code offline} event handlers. */
205     public static final String TYPE_OFFLINE = "offline";
206 
207     /** The deviceorientation event type, triggered by {@code deviceorientation} event handlers. */
208     public static final String TYPE_DEVICEORIENTATION = "deviceorientation";
209 
210     /** The toggle event type, triggered by {@code toggle} event handlers. */
211     public static final String TYPE_TOGGLE = "toggle";
212 
213     /** The play event type, triggered by {@code play} event handlers. */
214     public static final String TYPE_PLAY = "play";
215 
216     /** The loadedmetadata event type, triggered by {@code loadedmetadata} event handlers. */
217     public static final String TYPE_LOADEDMETADATA = "loadedmetadata";
218 
219     /** The pointermove event type, triggered by {@code pointermove} event handlers. */
220     public static final String TYPE_POINTERMOVE = "pointermove";
221 
222     /** The lostpointercapture event type, triggered by {@code lostpointercapture} event handlers. */
223     public static final String TYPE_LOSTPOINTERCAPTURE = "lostpointercapture";
224 
225     /** The pointerover event type, triggered by {@code pointerover} event handlers. */
226     public static final String TYPE_POINTEROVER = "pointerover";
227 
228     /** The animationcancel event type, triggered by {@code animationcancel} event handlers. */
229     public static final String TYPE_ANIMATIONCANCEL = "animationcancel";
230 
231     /** The animationend event type, triggered by {@code animationend} event handlers. */
232     public static final String TYPE_ANIMATIONEND = "animationend";
233 
234     /** The dragenter event type, triggered by {@code dragenter} event handlers. */
235     public static final String TYPE_DRAGENTER = "dragenter";
236 
237     /** The afterprint event type, triggered by {@code afterprint} event handlers. */
238     public static final String TYPE_AFTERPRINT = "afterprint";
239 
240     /** The mozfullscreenerror event type, triggered by {@code mozfullscreenerror} event handlers. */
241     public static final String TYPE_MOZFULLSCREENERROR = "mozfullscreenerror";
242 
243     /** The mouseleave event type, triggered by {@code mouseleave} event handlers. */
244     public static final String TYPE_MOUSELEAVE = "mouseleave";
245 
246     /** The mousewheel event type, triggered by {@code mousewheel} event handlers. */
247     public static final String TYPE_MOUSEWHEEL = "mousewheel";
248 
249     /** The seeking event type, triggered by {@code seeking} event handlers. */
250     public static final String TYPE_SEEKING = "seeking";
251 
252     /** The cuechange event type, triggered by {@code cuechange} event handlers. */
253     public static final String TYPE_CUECHANGE = "cuechange";
254 
255     /** The pageshow event type, triggered by {@code pageshow} event handlers. */
256     public static final String TYPE_PAGESHOW = "pageshow";
257 
258 //    /** The mspointerenter event type, triggered by {@code mspointerenter} event handlers. */
259 //    public static final String TYPE_MSPOINTENTER = "mspointerenter";
260 
261     /** The mozfullscreenchange event type, triggered by {@code mozfullscreenchange} event handlers. */
262     public static final String TYPE_MOZFULLSCREENCHANGE = "mozfullscreenchange";
263 
264     /** The durationchange event type, triggered by {@code durationchange} event handlers. */
265     public static final String TYPE_DURATIONCHANGE = "durationchange";
266 
267     /** The playing event type, triggered by {@code playing} event handlers. */
268     public static final String TYPE_PLAYING = "playing";
269 
270     /** The ended event type, triggered by {@code ended} event handlers. */
271     public static final String TYPE_ENDED = "ended";
272 
273     /** The loadeddata event type, triggered by {@code loadeddata} event handlers. */
274     public static final String TYPE_LOADEDDATA = "loadeddata";
275 
276     /** The unhandledrejection event type, triggered by {@code unhandledrejection} event handlers. */
277     public static final String TYPE_UNHANDLEDREJECTION = "unhandledrejection";
278 
279     /** The suspend event type, triggered by {@code suspend} event handlers. */
280     public static final String TYPE_SUSPEND = "suspend";
281 
282     /** The waiting event type, triggered by {@code waiting} event handlers. */
283     public static final String TYPE_WAITING = "waiting";
284 
285     /** The canplay event type, triggered by {@code canplay} event handlers. */
286     public static final String TYPE_CANPLAY = "canplay";
287 
288     /** The languagechange event type, triggered by {@code languagechange} event handlers. */
289     public static final String TYPE_LANGUAGECHANGE = "languagechange";
290 
291     /** The emptied event type, triggered by {@code emptied} event handlers. */
292     public static final String TYPE_EMPTIED = "emptied";
293 
294     /** The rejectionhandled event type, triggered by {@code rejectionhandled} event handlers. */
295     public static final String TYPE_REJECTIONHANDLED = "rejectionhandled";
296 
297     /** The pointercancel event type, triggered by {@code pointercancel} event handlers. */
298     public static final String TYPE_POINTERCANCEL = "pointercancel";
299 
300     /** The resize event type, triggered by {@code resize} event handlers. */
301     public static final String TYPE_RESIZE = "resize";
302 
303     /** The pause event type, triggered by {@code pause} event handlers. */
304     public static final String TYPE_PAUSE = "pause";
305 
306     /** The pointerup event type, triggered by {@code pointerup} event handlers. */
307     public static final String TYPE_POINTERUP = "pointerup";
308 
309     /** The wheel event type, triggered by {@code wheel} event handlers. */
310     public static final String TYPE_WHEEL = "wheel";
311 
312     /** The pointerleave event type, triggered by {@code pointerleave} event handlers. */
313     public static final String TYPE_POINTERLEAVE = "pointerleave";
314 
315     /** The beforeprint event type, triggered by {@code beforeprint} event handlers. */
316     public static final String TYPE_BEFOREPRINT = "beforeprint";
317 
318     /** The storage event type, triggered by {@code storage} event handlers. */
319     public static final String TYPE_STORAGE = "storage";
320 
321     /** The animationstart event type, triggered by {@code animationstart} event handlers. */
322     public static final String TYPE_ANIMATIONSTART = "animationstart";
323 
324     /** The timeupdate event type, triggered by {@code timeupdate} event handlers. */
325     public static final String TYPE_TIMEUPDATE = "timeupdate";
326 
327     /** The pagehide event type, triggered by {@code pagehide} event handlers. */
328     public static final String TYPE_PAGEHIDE = "pagehide";
329 
330     /** The webkitanimationiteration event type, triggered by {@code webkitanimationiteration} event handlers. */
331     public static final String TYPE_WEBKITANIMATIONITERATION = "webkitanimationiteration";
332 
333     /** The dragover event type, triggered by {@code dragover} event handlers. */
334     public static final String TYPE_DRAGOVER = "dragover";
335 
336     /** The online event type, triggered by {@code online} event handlers. */
337     public static final String TYPE_ONLINE = "online";
338 
339     /** The volumechange event type, triggered by {@code volumechange} event handlers. */
340     public static final String TYPE_VOLUMECHANGE = "volumechange";
341 
342     /** The gotpointercapture event type, triggered by {@code gotpointercapture} event handlers. */
343     public static final String TYPE_GOTPOINTERCAPTURE = "gotpointercapture";
344 
345     /** The webkittransitionend event type, triggered by {@code webkittransitionend} event handlers. */
346     public static final String TYPE_WEBKITTRANSITIONEND = "webkittransitionend";
347 
348     /** The webkitanimationend event type, triggered by {@code webkitanimationend} event handlers. */
349     public static final String TYPE_WEBKITANIMATIONEND = "webkitanimationend";
350 
351     /** The devicemotion event type, triggered by {@code devicemotion} event handlers. */
352     public static final String TYPE_DEVICEMOTION = "devicemotion";
353 
354     /** The stalled event type, triggered by {@code stalled} event handlers. */
355     public static final String TYPE_STALLED = "stalled";
356 
357     /** The mouseenter event type, triggered by {@code mouseenter} event handlers. */
358     public static final String TYPE_MOUDEENTER = "mouseenter";
359 
360     /** The dragleave event type, triggered by {@code dragleave} event handlers. */
361     public static final String TYPE_DRAGLEAVE = "dragleave";
362 
363     /** The pointerdown event type, triggered by {@code pointerdown} event handlers. */
364     public static final String TYPE_POINTERDOWN = "pointerdown";
365 
366     /** The drop event type, triggered by {@code drop} event handlers. */
367     public static final String TYPE_DROP = "drop";
368 
369     /** The dragstart event type, triggered by {@code dragstart} event handlers. */
370     public static final String TYPE_DRAGSTART = "dragstart";
371 
372     /** The transitionend event type, triggered by {@code transitionend} event handlers. */
373     public static final String TYPE_TRANSITIONEND = "transitionend";
374 
375 //    /** The msgesturehold event type, triggered by {@code msgesturehold} event handlers. */
376 //    public static final String TYPE_MSGESTUREHOLD = "msgesturehold";
377 
378     /** The deviceorientationabsolute event type, triggered by {@code deviceorientationabsolute} event handlers. */
379     public static final String TYPE_DEVICEORIENTATIONABSOLUTE = "deviceorientationabsolute";
380 
381     /** The beforecopy event type, triggered by {@code beforecopy} event handlers. */
382     public static final String TYPE_BEFORECOPY = "beforecopy";
383 
384     /** The beforecut event type, triggered by {@code beforecut} event handlers. */
385     public static final String TYPE_BEFORECUT = "beforecut";
386 
387     /** The beforepaste event type, triggered by {@code beforepaste} event handlers. */
388     public static final String TYPE_BEFOREPASTE = "beforepaste";
389 
390     /** The selectstart event type, triggered by {@code selectstart} event handlers. */
391     public static final String TYPE_SELECTSTART = "selectstart";
392 
393     /** The webkitfullscreenchange event type, triggered by {@code webkitfullscreenchange} event handlers. */
394     public static final String TYPE_WEBKITFULLSCREENCHANGE = "webkitfullscreenchange";
395 
396     /** The webkitfullscreenerror event type, triggered by {@code webkitfullscreenerror} event handlers. */
397     public static final String TYPE_WEBKITFULLSCREENERROR = "webkitfullscreenerror";
398 
399     /** The copy event type, triggered by {@code copy} event handlers. */
400     public static final String TYPE_COPY = "copy";
401 
402     /** The cut event type, triggered by {@code cut} event handlers. */
403     public static final String TYPE_CUT = "cut";
404 
405     /** The paste event type, triggered by {@code paste} event handlers. */
406     public static final String TYPE_PASTE = "paste";
407 
408     /** The onmessageerror event type, triggered by {@code onmessageerror} event handlers. */
409     public static final String TYPE_ONMESSAGEERROR = "onmessageerror";
410 
411     /** The pointerlockchange event type, triggered by {@code pointerlockchange} event handlers. */
412     public static final String TYPE_POINTERLOCKCHANGE = "pointerlockchange";
413 
414     /** The pointerlockerror event type, triggered by {@code pointerlockerror} event handlers. */
415     public static final String TYPE_POINTERLOCKERROR = "pointerlockerror";
416 
417     /** The selectionchange event type, triggered by {@code selectionchange} event handlers. */
418     public static final String TYPE_SELECTIONCHANGE = "selectionchange";
419 
420     /** The afterscriptexecute event type, triggered by {@code afterscriptexecute} event handlers. */
421     public static final String TYPE_AFTERSCRIPTEXECUTE = "afterscriptexecute";
422 
423     /** The beforescriptexecute event type, triggered by {@code beforescriptexecute} event handlers. */
424     public static final String TYPE_BEFORESCRIPTEXECUTE = "beforescriptexecute";
425 
426     /** The ontransitioncancel event type, triggered by {@code ontransitioncancel} event handlers. */
427     public static final String TYPE_ONTRANSITIONCANCEL = "ontransitioncancel";
428 
429     /** The ontransitionend event type, triggered by {@code ontransitionend} event handlers. */
430     public static final String TYPE_ONTRANSITIONEND = "ontransitionend";
431 
432     /** The ontransitionrun event type, triggered by {@code ontransitionrun} event handlers. */
433     public static final String TYPE_ONTRANSITIONRUN = "ontransitionrun";
434 
435     /** The ontransitionstart event type, triggered by {@code ontransitionstart} event handlers. */
436     public static final String TYPE_ONTRANSITIONSTART = "ontransitionstart";
437 
438     /** The ongamepadconnected event type, triggered by {@code ongamepadconnected} event handlers. */
439     public static final String TYPE_GAMEPAD_CONNECTED = "ongamepadconnected";
440 
441     /** The ongamepaddisconnected event type, triggered by {@code ongamepaddisconnected} event handlers. */
442     public static final String TYPE_GAMEPAD_DISCONNECTED = "ongamepaddisconnected";
443 
444     /**
445      * The mssitemodejumplistitemremoved event type, triggered
446      * by {@code mssitemodejumplistitemremoved} event handlers.
447      */
448     public static final String TYPE_MSSITEMODEJUMPLISTITEMREMOVED = "mssitemodejumplistitemremoved";
449 
450     /** No event phase. */
451     @JsxConstant
452     public static final int NONE = 0;
453 
454     /** The first event phase: the capturing phase. */
455     @JsxConstant
456     public static final int CAPTURING_PHASE = 1;
457 
458     /** The second event phase: at the event target. */
459     @JsxConstant
460     public static final int AT_TARGET = 2;
461 
462     /** The third (and final) event phase: the bubbling phase. */
463     @JsxConstant
464     public static final int BUBBLING_PHASE = 3;
465 
466     /** Constant. */
467     @JsxConstant({FF, FF_ESR})
468     public static final int ALT_MASK = 0x1;
469 
470     /** Constant. */
471     @JsxConstant({FF, FF_ESR})
472     public static final int CONTROL_MASK = 0x2;
473 
474     /** Constant. */
475     @JsxConstant({FF, FF_ESR})
476     public static final int SHIFT_MASK = 0x4;
477 
478     /** Constant. */
479     @JsxConstant({FF, FF_ESR})
480     public static final int META_MASK = 0x8;
481 
482     private Object srcElement_;        // writable equivalent of target.
483     private EventTarget target_;       // W3C standard read-only equivalent of srcElement.
484     private Scriptable currentTarget_; // Changes during event capturing and bubbling.
485     private String type_ = "";         // The event type.
486     private int keyCode_;              // Key code for a keypress
487     private boolean shiftKey_;
488     private boolean ctrlKey_;
489     private boolean altKey_;
490     private String propertyName_;
491     private boolean stopPropagation_;
492     private boolean stopImmediatePropagation_;
493     private boolean preventDefault_;
494 
495     /**
496      * The current event phase. This is a W3C standard attribute. One of {@link #NONE},
497      * {@link #CAPTURING_PHASE}, {@link #AT_TARGET} or {@link #BUBBLING_PHASE}.
498      */
499     private int eventPhase_;
500 
501     /**
502      * Whether or not the event bubbles. The value of this attribute depends on the event type. To
503      * determine if a certain event type bubbles, see
504      * <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html">events</a>
505      * Most event types do bubble, so this is true by default; event types which do not bubble should
506      * overwrite this value in their constructors.
507      */
508     private boolean bubbles_ = true;
509 
510     /**
511      * Whether or not the event can be canceled. The value of this attribute depends on the event type. To
512      * determine if a certain event type can be canceled, see
513      * <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html">
514      * http://www.w3.org/TR/DOM-Level-2-Events/events.html</a>
515      * The more common event types are cancelable, so this is true by default; event types which cannot be
516      * canceled should overwrite this value in their constructors.
517      */
518     private boolean cancelable_ = true;
519 
520     /**
521      * The time at which the event was created.
522      */
523     private final long timeStamp_ = System.currentTimeMillis();
524 
525     /**
526      * Creates a new event instance.
527      * @param domNode the DOM node that triggered the event
528      * @param type the event type
529      */
530     public Event(final DomNode domNode, final String type) {
531         this((EventTarget) domNode.getScriptableObject(), type);
532         setDomNode(domNode, false);
533     }
534 
535     /**
536      * Creates a new event instance.
537      * @param target the target
538      * @param type the event type
539      */
540     public Event(final EventTarget target, final String type) {
541         this(type);
542 
543         srcElement_ = target;
544         target_ = target;
545         currentTarget_ = target;
546 
547         setParentScope(target);
548         setPrototype(getPrototype(getClass()));
549 
550         if (TYPE_CHANGE.equals(type)) {
551             cancelable_ = false;
552         }
553         else if (TYPE_LOAD.equals(type)
554                     || TYPE_CLOSE.equals(type)) {
555             bubbles_ = false;
556             cancelable_ = false;
557         }
558         else if (TYPE_ERROR.equals(type)) {
559             // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-error
560             bubbles_ = false;
561         }
562         else if (
563                 TYPE_FOCUS.equals(type)
564                 || TYPE_BLUR.equals(type)
565                 || TYPE_BEFOREPRINT.equals(type)
566                 || TYPE_AFTERPRINT.equals(type)) {
567             bubbles_ = false;
568             cancelable_ = false;
569         }
570     }
571 
572     /**
573      * Creates a new event instance.
574      * @param type the event type
575      */
576     public Event(final String type) {
577         super();
578         type_ = type;
579     }
580 
581     /**
582      * Creates a new Event with {@link #TYPE_PROPERTY_CHANGE} type.
583      * @param domNode the DOM node that triggered the event
584      * @param propertyName the property name that was changed
585      * @return the new Event object
586      */
587     public static Event createPropertyChangeEvent(final DomNode domNode, final String propertyName) {
588         final Event event = new Event(domNode, TYPE_PROPERTY_CHANGE);
589         event.propertyName_ = propertyName;
590         return event;
591     }
592 
593     /**
594      * Used to build the prototype.
595      */
596     public Event() {
597         super();
598     }
599 
600     /**
601      * Called whenever an event is created using <code>Document.createEvent(..)</code>.
602      * This method is called after the parent scope was set so you are able to access the browser version.
603      */
604     public void eventCreated() {
605         setBubbles(false);
606         setCancelable(false);
607     }
608 
609     /**
610      * JavaScript constructor.
611      *
612      * @param type the event type
613      * @param details the event details (optional)
614      */
615     @JsxConstructor
616     public void jsConstructor(final String type, final ScriptableObject details) {
617         boolean bubbles = false;
618         boolean cancelable = false;
619 
620         if (details != null && !JavaScriptEngine.isUndefined(details)) {
621             bubbles = JavaScriptEngine.toBoolean(details.get("bubbles"));
622             cancelable  = JavaScriptEngine.toBoolean(details.get("cancelable"));
623         }
624         initEvent(type, bubbles, cancelable);
625     }
626 
627     /**
628      * Called when the event starts being fired.
629      */
630     @SuppressWarnings("unchecked")
631     public void startFire() {
632         final Context context = Context.getCurrentContext();
633         ArrayList<Event> events = (ArrayList<Event>) context.getThreadLocal(KEY_CURRENT_EVENT);
634         if (events == null) {
635             events = new ArrayList<>();
636             context.putThreadLocal(KEY_CURRENT_EVENT, events);
637         }
638         events.add(this);
639     }
640 
641     /**
642      * Called when the event being fired ends.
643      */
644     @SuppressWarnings("unchecked")
645     public void endFire() {
646         final Context context = Context.getCurrentContext();
647         final ArrayList<Event> events = (ArrayList<Event>) context.getThreadLocal(KEY_CURRENT_EVENT);
648         if (events != null && events.size() > 0) {
649             events.remove(events.size() - 1);
650         }
651     }
652 
653     /**
654      * Returns the object that fired the event.
655      * @return the object that fired the event
656      */
657     @JsxGetter
658     public Object getSrcElement() {
659         return srcElement_;
660     }
661 
662     /**
663      * Sets the object that fired the event.
664      * @param srcElement the object that fired the event
665      */
666     public void setSrcElement(final Object srcElement) {
667         srcElement_ = srcElement;
668     }
669 
670     /**
671      * Returns the event target to which the event was originally dispatched.
672      * @return the event target to which the event was originally dispatched
673      */
674     @JsxGetter
675     public Object getTarget() {
676         return target_;
677     }
678 
679     /**
680      * Sets the event target.
681      * @param target the event target
682      */
683     public void setTarget(final EventTarget target) {
684         target_ = target;
685     }
686 
687     /**
688      * Returns the event target whose event listeners are currently being processed. This
689      * is useful during event capturing and event bubbling.
690      * @return the current event target
691      */
692     @JsxGetter
693     public Scriptable getCurrentTarget() {
694         return currentTarget_;
695     }
696 
697     /**
698      * Sets the current target.
699      * @param target the new value
700      */
701     public void setCurrentTarget(final Scriptable target) {
702         currentTarget_ = target;
703     }
704 
705     /**
706      * Returns the event type.
707      * @return the event type
708      */
709     @JsxGetter
710     public String getType() {
711         return type_;
712     }
713 
714     /**
715      * Sets the event type.
716      * @param type the event type
717      */
718     public void setType(final String type) {
719         type_ = type;
720     }
721 
722     /**
723      * Sets the event type.
724      * @param eventType the event type
725      */
726     public void setEventType(final String eventType) {
727         type_ = eventType;
728     }
729 
730     /**
731      * Returns the time at which this event was created.
732      * @return the time at which this event was created
733      */
734     @JsxGetter
735     public long getTimeStamp() {
736         return timeStamp_;
737     }
738 
739     /**
740      * Sets the key code.
741      * @param keyCode the virtual key code value of the key which was depressed, otherwise zero
742      */
743     protected void setKeyCode(final int keyCode) {
744         keyCode_ = keyCode;
745     }
746 
747     /**
748      * Returns the key code associated with the event.
749      * @return the key code associated with the event
750      */
751     public int getKeyCode() {
752         return keyCode_;
753     }
754 
755     /**
756      * Returns whether {@code SHIFT} has been pressed during this event or not.
757      * @return whether {@code SHIFT} has been pressed during this event or not
758      */
759     public boolean isShiftKey() {
760         return shiftKey_;
761     }
762 
763     /**
764      * Sets whether {@code SHIFT} key is pressed on not.
765      * @param shiftKey whether {@code SHIFT} has been pressed during this event or not
766      */
767     protected void setShiftKey(final boolean shiftKey) {
768         shiftKey_ = shiftKey;
769     }
770 
771     /**
772      * Returns whether {@code CTRL} has been pressed during this event or not.
773      * @return whether {@code CTRL} has been pressed during this event or not
774      */
775     public boolean isCtrlKey() {
776         return ctrlKey_;
777     }
778 
779     /**
780      * Sets whether {@code CTRL} key is pressed on not.
781      * @param ctrlKey whether {@code CTRL} has been pressed during this event or not
782      */
783     protected void setCtrlKey(final boolean ctrlKey) {
784         ctrlKey_ = ctrlKey;
785     }
786 
787     /**
788      * Returns whether {@code ALT} has been pressed during this event or not.
789      * @return whether {@code ALT} has been pressed during this event or not
790      */
791     public boolean isAltKey() {
792         return altKey_;
793     }
794 
795     /**
796      * Sets whether {@code ALT} key is pressed on not.
797      * @param altKey whether {@code ALT} has been pressed during this event or not
798      */
799     protected void setAltKey(final boolean altKey) {
800         altKey_ = altKey;
801     }
802 
803     /**
804      * Returns the current event phase for the event.
805      * @return the current event phase for the event
806      */
807     @JsxGetter
808     public int getEventPhase() {
809         return eventPhase_;
810     }
811 
812     /**
813      * Sets the current event phase. Must be one of {@link #CAPTURING_PHASE}, {@link #AT_TARGET} or
814      * {@link #BUBBLING_PHASE}.
815      *
816      * @param phase the phase the event is in
817      */
818     public void setEventPhase(final int phase) {
819         if (phase != CAPTURING_PHASE && phase != AT_TARGET && phase != BUBBLING_PHASE) {
820             throw new IllegalArgumentException("Illegal phase specified: " + phase);
821         }
822         eventPhase_ = phase;
823     }
824 
825     /**
826      * @return whether or not this event bubbles
827      */
828     @JsxGetter
829     public boolean isBubbles() {
830         return bubbles_;
831     }
832 
833     /**
834      * @param bubbles the bubbles to set
835      */
836     protected void setBubbles(final boolean bubbles) {
837         bubbles_ = bubbles;
838     }
839 
840     /**
841      * @return whether or not this event can be canceled
842      */
843     @JsxGetter
844     public boolean isCancelable() {
845         return cancelable_;
846     }
847 
848     /**
849      * @param cancelable the cancelable to set
850      */
851     protected void setCancelable(final boolean cancelable) {
852         cancelable_ = cancelable;
853     }
854 
855     /**
856      * Returns {@code true} if both <code>cancelable</code> is {@code true} and <code>preventDefault()</code> has been
857      * called for this event. Otherwise this attribute must return {@code false}.
858      * @return {@code true} if this event has been cancelled or not
859      */
860     @JsxGetter
861     public boolean isDefaultPrevented() {
862         return cancelable_ && preventDefault_;
863     }
864 
865     /**
866      * @return indicates if event propagation is stopped
867      */
868     @JsxGetter
869     public boolean isCancelBubble() {
870         return stopPropagation_;
871     }
872 
873     /**
874      * @param newValue indicates if event propagation is stopped
875      */
876     @JsxSetter
877     public void setCancelBubble(final boolean newValue) {
878         stopPropagation_ = newValue;
879     }
880 
881     /**
882      * Stops the event from propagating.
883      */
884     @JsxFunction
885     public void stopPropagation() {
886         stopPropagation_ = true;
887     }
888 
889     /**
890      * Indicates if event propagation is stopped.
891      * @return the status
892      */
893     public boolean isPropagationStopped() {
894         return stopPropagation_;
895     }
896 
897     /**
898      * Prevents other listeners of the same event from being called.
899      */
900     @JsxFunction
901     public void stopImmediatePropagation() {
902         stopImmediatePropagation_ = true;
903         stopPropagation();
904     }
905 
906     /**
907      * Indicates if event immediate propagation is stopped.
908      * @return the status
909      */
910     public boolean isImmediatePropagationStopped() {
911         return stopImmediatePropagation_;
912     }
913 
914     /**
915      * Handles the return values of property handlers.
916      * @param returnValue the return value returned by the property handler
917      */
918     void handlePropertyHandlerReturnValue(final Object returnValue) {
919         if (Boolean.FALSE.equals(returnValue)) {
920             preventDefault();
921         }
922     }
923 
924     /**
925      * Returns the property name associated with the event.
926      * @return the property name associated with the event
927      */
928     public String getPropertyName() {
929         return propertyName_;
930     }
931 
932     /**
933      * Initializes this event.
934      * @param type the event type
935      * @param bubbles whether or not the event should bubble
936      * @param cancelable whether or not the event the event should be cancelable
937      */
938     @JsxFunction
939     public void initEvent(final String type, final boolean bubbles, final boolean cancelable) {
940         type_ = type;
941         bubbles_ = bubbles;
942         cancelable_ = cancelable;
943     }
944 
945     /**
946      * If, during any stage of event flow, this method is called the event is canceled.
947      * Any default action associated with the event will not occur.
948      * Calling this method for a non-cancelable event has no effect.
949      */
950     @JsxFunction
951     public void preventDefault() {
952         if (isCancelable()) {
953             preventDefault_ = true;
954         }
955     }
956 
957     /**
958      * Returns {@code true} if this event has been aborted via <code>preventDefault()</code> in
959      * standards-compliant browsers.
960      *
961      * @param result the event handler result (if {@code false}, the event is considered aborted)
962      * @return {@code true} if this event has been aborted
963      */
964     public boolean isAborted(final ScriptResult result) {
965         return ScriptResult.isFalse(result) || preventDefault_;
966     }
967 
968     /**
969      * {@inheritDoc}
970      */
971     @Override
972     public String toString() {
973         final StringBuilder builder = new StringBuilder(40);
974         builder.append("Event ")
975             .append(getType())
976             .append(" (Current Target: ")
977             .append(currentTarget_)
978             .append(");");
979         return builder.toString();
980     }
981 
982     /**
983      * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
984      *
985      * If we click on a label, we have to simulate a click on the element referenced by the 'for' attribute also.
986      * To support this for special events we have this method here.
987      * @return false in this default impl
988      */
989     public boolean processLabelAfterBubbling() {
990         return false;
991     }
992 
993     /**
994      * @return the return value property
995      */
996     @JsxGetter
997     public Object getReturnValue() {
998         return !preventDefault_;
999     }
1000 
1001     /**
1002      * @param newValue the new return value
1003      */
1004     @JsxSetter
1005     public void setReturnValue(final Object newValue) {
1006         if (isCancelable()) {
1007             final boolean bool = !JavaScriptEngine.toBoolean(newValue);
1008             if (bool) {
1009                 preventDefault_ = bool;
1010             }
1011         }
1012     }
1013 
1014     /**
1015      * @return the return composed property
1016      */
1017     @JsxGetter
1018     public boolean getComposed() {
1019         return false;
1020     }
1021 
1022     /**
1023      * Returns whether the given value indicates a missing or undefined property.
1024      * @param value the new value
1025      * @return whether the given value indicates a missing or undefined property
1026      */
1027     protected static boolean isMissingOrUndefined(final Object value) {
1028         return value == Scriptable.NOT_FOUND || JavaScriptEngine.isUndefined(value);
1029     }
1030 }