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 Chris Eldredge
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 webkitanimationstart event type, triggered by {@code webkitanimationstart} event handlers. */
190     public static final String TYPE_WEBANIMATIONSTART = "webkitanimationstart";
191 
192     /** The drag event type, triggered by {@code drag} event handlers. */
193     public static final String TYPE_DRAG = "drag";
194 
195     /** The seeked event type, triggered by {@code seeked} event handlers. */
196     public static final String TYPE_SEEKED = "seeked";
197 
198     /** The offline event type, triggered by {@code offline} event handlers. */
199     public static final String TYPE_OFFLINE = "offline";
200 
201     /** The deviceorientation event type, triggered by {@code deviceorientation} event handlers. */
202     public static final String TYPE_DEVICEORIENTATION = "deviceorientation";
203 
204     /** The toggle event type, triggered by {@code toggle} event handlers. */
205     public static final String TYPE_TOGGLE = "toggle";
206 
207     /** The play event type, triggered by {@code play} event handlers. */
208     public static final String TYPE_PLAY = "play";
209 
210     /** The loadedmetadata event type, triggered by {@code loadedmetadata} event handlers. */
211     public static final String TYPE_LOADEDMETADATA = "loadedmetadata";
212 
213     /** The pointermove event type, triggered by {@code pointermove} event handlers. */
214     public static final String TYPE_POINTERMOVE = "pointermove";
215 
216     /** The lostpointercapture event type, triggered by {@code lostpointercapture} event handlers. */
217     public static final String TYPE_LOSTPOINTERCAPTURE = "lostpointercapture";
218 
219     /** The pointerover event type, triggered by {@code pointerover} event handlers. */
220     public static final String TYPE_POINTEROVER = "pointerover";
221 
222     /** The animationcancel event type, triggered by {@code animationcancel} event handlers. */
223     public static final String TYPE_ANIMATIONCANCEL = "animationcancel";
224 
225     /** The animationend event type, triggered by {@code animationend} event handlers. */
226     public static final String TYPE_ANIMATIONEND = "animationend";
227 
228     /** The dragenter event type, triggered by {@code dragenter} event handlers. */
229     public static final String TYPE_DRAGENTER = "dragenter";
230 
231     /** The afterprint event type, triggered by {@code afterprint} event handlers. */
232     public static final String TYPE_AFTERPRINT = "afterprint";
233 
234     /** The mozfullscreenerror event type, triggered by {@code mozfullscreenerror} event handlers. */
235     public static final String TYPE_MOZFULLSCREENERROR = "mozfullscreenerror";
236 
237     /** The mouseleave event type, triggered by {@code mouseleave} event handlers. */
238     public static final String TYPE_MOUSELEAVE = "mouseleave";
239 
240     /** The mousewheel event type, triggered by {@code mousewheel} event handlers. */
241     public static final String TYPE_MOUSEWHEEL = "mousewheel";
242 
243     /** The seeking event type, triggered by {@code seeking} event handlers. */
244     public static final String TYPE_SEEKING = "seeking";
245 
246     /** The cuechange event type, triggered by {@code cuechange} event handlers. */
247     public static final String TYPE_CUECHANGE = "cuechange";
248 
249     /** The pageshow event type, triggered by {@code pageshow} event handlers. */
250     public static final String TYPE_PAGESHOW = "pageshow";
251 
252     /** The mozfullscreenchange event type, triggered by {@code mozfullscreenchange} event handlers. */
253     public static final String TYPE_MOZFULLSCREENCHANGE = "mozfullscreenchange";
254 
255     /** The durationchange event type, triggered by {@code durationchange} event handlers. */
256     public static final String TYPE_DURATIONCHANGE = "durationchange";
257 
258     /** The playing event type, triggered by {@code playing} event handlers. */
259     public static final String TYPE_PLAYING = "playing";
260 
261     /** The ended event type, triggered by {@code ended} event handlers. */
262     public static final String TYPE_ENDED = "ended";
263 
264     /** The loadeddata event type, triggered by {@code loadeddata} event handlers. */
265     public static final String TYPE_LOADEDDATA = "loadeddata";
266 
267     /** The unhandledrejection event type, triggered by {@code unhandledrejection} event handlers. */
268     public static final String TYPE_UNHANDLEDREJECTION = "unhandledrejection";
269 
270     /** The suspend event type, triggered by {@code suspend} event handlers. */
271     public static final String TYPE_SUSPEND = "suspend";
272 
273     /** The waiting event type, triggered by {@code waiting} event handlers. */
274     public static final String TYPE_WAITING = "waiting";
275 
276     /** The canplay event type, triggered by {@code canplay} event handlers. */
277     public static final String TYPE_CANPLAY = "canplay";
278 
279     /** The languagechange event type, triggered by {@code languagechange} event handlers. */
280     public static final String TYPE_LANGUAGECHANGE = "languagechange";
281 
282     /** The emptied event type, triggered by {@code emptied} event handlers. */
283     public static final String TYPE_EMPTIED = "emptied";
284 
285     /** The rejectionhandled event type, triggered by {@code rejectionhandled} event handlers. */
286     public static final String TYPE_REJECTIONHANDLED = "rejectionhandled";
287 
288     /** The pointercancel event type, triggered by {@code pointercancel} event handlers. */
289     public static final String TYPE_POINTERCANCEL = "pointercancel";
290 
291     /** The resize event type, triggered by {@code resize} event handlers. */
292     public static final String TYPE_RESIZE = "resize";
293 
294     /** The pause event type, triggered by {@code pause} event handlers. */
295     public static final String TYPE_PAUSE = "pause";
296 
297     /** The pointerup event type, triggered by {@code pointerup} event handlers. */
298     public static final String TYPE_POINTERUP = "pointerup";
299 
300     /** The wheel event type, triggered by {@code wheel} event handlers. */
301     public static final String TYPE_WHEEL = "wheel";
302 
303     /** The pointerleave event type, triggered by {@code pointerleave} event handlers. */
304     public static final String TYPE_POINTERLEAVE = "pointerleave";
305 
306     /** The beforeprint event type, triggered by {@code beforeprint} event handlers. */
307     public static final String TYPE_BEFOREPRINT = "beforeprint";
308 
309     /** The storage event type, triggered by {@code storage} event handlers. */
310     public static final String TYPE_STORAGE = "storage";
311 
312     /** The animationstart event type, triggered by {@code animationstart} event handlers. */
313     public static final String TYPE_ANIMATIONSTART = "animationstart";
314 
315     /** The timeupdate event type, triggered by {@code timeupdate} event handlers. */
316     public static final String TYPE_TIMEUPDATE = "timeupdate";
317 
318     /** The pagehide event type, triggered by {@code pagehide} event handlers. */
319     public static final String TYPE_PAGEHIDE = "pagehide";
320 
321     /** The webkitanimationiteration event type, triggered by {@code webkitanimationiteration} event handlers. */
322     public static final String TYPE_WEBKITANIMATIONITERATION = "webkitanimationiteration";
323 
324     /** The dragover event type, triggered by {@code dragover} event handlers. */
325     public static final String TYPE_DRAGOVER = "dragover";
326 
327     /** The online event type, triggered by {@code online} event handlers. */
328     public static final String TYPE_ONLINE = "online";
329 
330     /** The volumechange event type, triggered by {@code volumechange} event handlers. */
331     public static final String TYPE_VOLUMECHANGE = "volumechange";
332 
333     /** The gotpointercapture event type, triggered by {@code gotpointercapture} event handlers. */
334     public static final String TYPE_GOTPOINTERCAPTURE = "gotpointercapture";
335 
336     /** The webkittransitionend event type, triggered by {@code webkittransitionend} event handlers. */
337     public static final String TYPE_WEBKITTRANSITIONEND = "webkittransitionend";
338 
339     /** The webkitanimationend event type, triggered by {@code webkitanimationend} event handlers. */
340     public static final String TYPE_WEBKITANIMATIONEND = "webkitanimationend";
341 
342     /** The devicemotion event type, triggered by {@code devicemotion} event handlers. */
343     public static final String TYPE_DEVICEMOTION = "devicemotion";
344 
345     /** The stalled event type, triggered by {@code stalled} event handlers. */
346     public static final String TYPE_STALLED = "stalled";
347 
348     /** The mouseenter event type, triggered by {@code mouseenter} event handlers. */
349     public static final String TYPE_MOUDEENTER = "mouseenter";
350 
351     /** The dragleave event type, triggered by {@code dragleave} event handlers. */
352     public static final String TYPE_DRAGLEAVE = "dragleave";
353 
354     /** The pointerdown event type, triggered by {@code pointerdown} event handlers. */
355     public static final String TYPE_POINTERDOWN = "pointerdown";
356 
357     /** The drop event type, triggered by {@code drop} event handlers. */
358     public static final String TYPE_DROP = "drop";
359 
360     /** The dragstart event type, triggered by {@code dragstart} event handlers. */
361     public static final String TYPE_DRAGSTART = "dragstart";
362 
363     /** The transitionend event type, triggered by {@code transitionend} event handlers. */
364     public static final String TYPE_TRANSITIONEND = "transitionend";
365 
366     /** The deviceorientationabsolute event type, triggered by {@code deviceorientationabsolute} event handlers. */
367     public static final String TYPE_DEVICEORIENTATIONABSOLUTE = "deviceorientationabsolute";
368 
369     /** The beforecopy event type, triggered by {@code beforecopy} event handlers. */
370     public static final String TYPE_BEFORECOPY = "beforecopy";
371 
372     /** The beforecut event type, triggered by {@code beforecut} event handlers. */
373     public static final String TYPE_BEFORECUT = "beforecut";
374 
375     /** The beforepaste event type, triggered by {@code beforepaste} event handlers. */
376     public static final String TYPE_BEFOREPASTE = "beforepaste";
377 
378     /** The selectstart event type, triggered by {@code selectstart} event handlers. */
379     public static final String TYPE_SELECTSTART = "selectstart";
380 
381     /** The webkitfullscreenchange event type, triggered by {@code webkitfullscreenchange} event handlers. */
382     public static final String TYPE_WEBKITFULLSCREENCHANGE = "webkitfullscreenchange";
383 
384     /** The webkitfullscreenerror event type, triggered by {@code webkitfullscreenerror} event handlers. */
385     public static final String TYPE_WEBKITFULLSCREENERROR = "webkitfullscreenerror";
386 
387     /** The copy event type, triggered by {@code copy} event handlers. */
388     public static final String TYPE_COPY = "copy";
389 
390     /** The cut event type, triggered by {@code cut} event handlers. */
391     public static final String TYPE_CUT = "cut";
392 
393     /** The paste event type, triggered by {@code paste} event handlers. */
394     public static final String TYPE_PASTE = "paste";
395 
396     /** The onmessageerror event type, triggered by {@code onmessageerror} event handlers. */
397     public static final String TYPE_ONMESSAGEERROR = "onmessageerror";
398 
399     /** The pointerlockchange event type, triggered by {@code pointerlockchange} event handlers. */
400     public static final String TYPE_POINTERLOCKCHANGE = "pointerlockchange";
401 
402     /** The pointerlockerror event type, triggered by {@code pointerlockerror} event handlers. */
403     public static final String TYPE_POINTERLOCKERROR = "pointerlockerror";
404 
405     /** The selectionchange event type, triggered by {@code selectionchange} event handlers. */
406     public static final String TYPE_SELECTIONCHANGE = "selectionchange";
407 
408     /** The afterscriptexecute event type, triggered by {@code afterscriptexecute} event handlers. */
409     public static final String TYPE_AFTERSCRIPTEXECUTE = "afterscriptexecute";
410 
411     /** The beforescriptexecute event type, triggered by {@code beforescriptexecute} event handlers. */
412     public static final String TYPE_BEFORESCRIPTEXECUTE = "beforescriptexecute";
413 
414     /** The ontransitioncancel event type, triggered by {@code ontransitioncancel} event handlers. */
415     public static final String TYPE_ONTRANSITIONCANCEL = "ontransitioncancel";
416 
417     /** The ontransitionend event type, triggered by {@code ontransitionend} event handlers. */
418     public static final String TYPE_ONTRANSITIONEND = "ontransitionend";
419 
420     /** The ontransitionrun event type, triggered by {@code ontransitionrun} event handlers. */
421     public static final String TYPE_ONTRANSITIONRUN = "ontransitionrun";
422 
423     /** The ontransitionstart event type, triggered by {@code ontransitionstart} event handlers. */
424     public static final String TYPE_ONTRANSITIONSTART = "ontransitionstart";
425 
426     /** The ongamepadconnected event type, triggered by {@code ongamepadconnected} event handlers. */
427     public static final String TYPE_GAMEPAD_CONNECTED = "ongamepadconnected";
428 
429     /** The ongamepaddisconnected event type, triggered by {@code ongamepaddisconnected} event handlers. */
430     public static final String TYPE_GAMEPAD_DISCONNECTED = "ongamepaddisconnected";
431 
432     /** No event phase. */
433     @JsxConstant
434     public static final int NONE = 0;
435 
436     /** The first event phase: the capturing phase. */
437     @JsxConstant
438     public static final int CAPTURING_PHASE = 1;
439 
440     /** The second event phase: at the event target. */
441     @JsxConstant
442     public static final int AT_TARGET = 2;
443 
444     /** The third (and final) event phase: the bubbling phase. */
445     @JsxConstant
446     public static final int BUBBLING_PHASE = 3;
447 
448     /** Constant. */
449     @JsxConstant({FF, FF_ESR})
450     public static final int ALT_MASK = 0x1;
451 
452     /** Constant. */
453     @JsxConstant({FF, FF_ESR})
454     public static final int CONTROL_MASK = 0x2;
455 
456     /** Constant. */
457     @JsxConstant({FF, FF_ESR})
458     public static final int SHIFT_MASK = 0x4;
459 
460     /** Constant. */
461     @JsxConstant({FF, FF_ESR})
462     public static final int META_MASK = 0x8;
463 
464     private Object srcElement_;        // writable equivalent of target.
465     private EventTarget target_;       // W3C standard read-only equivalent of srcElement.
466     private Scriptable currentTarget_; // Changes during event capturing and bubbling.
467     private String type_ = "";         // The event type.
468     private int keyCode_;              // Key code for a keypress
469     private boolean shiftKey_;
470     private boolean ctrlKey_;
471     private boolean altKey_;
472     private String propertyName_;
473     private boolean stopPropagation_;
474     private boolean stopImmediatePropagation_;
475     private boolean preventDefault_;
476 
477     /**
478      * The current event phase. This is a W3C standard attribute. One of {@link #NONE},
479      * {@link #CAPTURING_PHASE}, {@link #AT_TARGET} or {@link #BUBBLING_PHASE}.
480      */
481     private int eventPhase_;
482 
483     /**
484      * Whether or not the event bubbles. The value of this attribute depends on the event type. To
485      * determine if a certain event type bubbles, see
486      * <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html">events</a>
487      * Most event types do bubble, so this is true by default; event types which do not bubble should
488      * overwrite this value in their constructors.
489      */
490     private boolean bubbles_ = true;
491 
492     /**
493      * Whether or not the event can be canceled. The value of this attribute depends on the event type. To
494      * determine if a certain event type can be canceled, see
495      * <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html">
496      * http://www.w3.org/TR/DOM-Level-2-Events/events.html</a>
497      * The more common event types are cancelable, so this is true by default; event types which cannot be
498      * canceled should overwrite this value in their constructors.
499      */
500     private boolean cancelable_ = true;
501 
502     /**
503      * The time at which the event was created.
504      */
505     private final long timeStamp_ = System.currentTimeMillis();
506 
507     /**
508      * Creates a new event instance.
509      * @param domNode the DOM node that triggered the event
510      * @param type the event type
511      */
512     public Event(final DomNode domNode, final String type) {
513         this((EventTarget) domNode.getScriptableObject(), type);
514         setDomNode(domNode, false);
515     }
516 
517     /**
518      * Creates a new event instance.
519      * @param target the target
520      * @param type the event type
521      */
522     public Event(final EventTarget target, final String type) {
523         this(type);
524 
525         srcElement_ = target;
526         target_ = target;
527         currentTarget_ = target;
528 
529         setParentScope(target);
530         setPrototype(getPrototype(getClass()));
531 
532         if (TYPE_CHANGE.equals(type)) {
533             cancelable_ = false;
534         }
535         else if (TYPE_LOAD.equals(type)
536                     || TYPE_CLOSE.equals(type)) {
537             bubbles_ = false;
538             cancelable_ = false;
539         }
540         else if (TYPE_ERROR.equals(type)) {
541             // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-error
542             bubbles_ = false;
543         }
544         else if (
545                 TYPE_FOCUS.equals(type)
546                 || TYPE_BLUR.equals(type)
547                 || TYPE_BEFOREPRINT.equals(type)
548                 || TYPE_AFTERPRINT.equals(type)) {
549             bubbles_ = false;
550             cancelable_ = false;
551         }
552     }
553 
554     /**
555      * Creates a new event instance.
556      * @param type the event type
557      */
558     public Event(final String type) {
559         super();
560         type_ = type;
561     }
562 
563     /**
564      * Creates a new Event with {@link #TYPE_PROPERTY_CHANGE} type.
565      * @param domNode the DOM node that triggered the event
566      * @param propertyName the property name that was changed
567      * @return the new Event object
568      */
569     public static Event createPropertyChangeEvent(final DomNode domNode, final String propertyName) {
570         final Event event = new Event(domNode, TYPE_PROPERTY_CHANGE);
571         event.propertyName_ = propertyName;
572         return event;
573     }
574 
575     /**
576      * Used to build the prototype.
577      */
578     public Event() {
579         super();
580     }
581 
582     /**
583      * Called whenever an event is created using <code>Document.createEvent(..)</code>.
584      * This method is called after the parent scope was set so you are able to access the browser version.
585      */
586     public void eventCreated() {
587         setBubbles(false);
588         setCancelable(false);
589     }
590 
591     /**
592      * JavaScript constructor.
593      *
594      * @param type the event type
595      * @param details the event details (optional)
596      */
597     @JsxConstructor
598     public void jsConstructor(final String type, final ScriptableObject details) {
599         boolean bubbles = false;
600         boolean cancelable = false;
601 
602         if (details != null && !JavaScriptEngine.isUndefined(details)) {
603             bubbles = JavaScriptEngine.toBoolean(details.get("bubbles"));
604             cancelable  = JavaScriptEngine.toBoolean(details.get("cancelable"));
605         }
606         initEvent(type, bubbles, cancelable);
607     }
608 
609     /**
610      * Called when the event starts being fired.
611      */
612     @SuppressWarnings("unchecked")
613     public void startFire() {
614         final Context context = Context.getCurrentContext();
615         ArrayList<Event> events = (ArrayList<Event>) context.getThreadLocal(KEY_CURRENT_EVENT);
616         if (events == null) {
617             events = new ArrayList<>();
618             context.putThreadLocal(KEY_CURRENT_EVENT, events);
619         }
620         events.add(this);
621     }
622 
623     /**
624      * Called when the event being fired ends.
625      */
626     @SuppressWarnings("unchecked")
627     public void endFire() {
628         final Context context = Context.getCurrentContext();
629         final ArrayList<Event> events = (ArrayList<Event>) context.getThreadLocal(KEY_CURRENT_EVENT);
630         if (events != null && !events.isEmpty()) {
631             events.remove(events.size() - 1);
632         }
633     }
634 
635     /**
636      * Returns the object that fired the event.
637      * @return the object that fired the event
638      */
639     @JsxGetter
640     public Object getSrcElement() {
641         return srcElement_;
642     }
643 
644     /**
645      * Sets the object that fired the event.
646      * @param srcElement the object that fired the event
647      */
648     public void setSrcElement(final Object srcElement) {
649         srcElement_ = srcElement;
650     }
651 
652     /**
653      * Returns the event target to which the event was originally dispatched.
654      * @return the event target to which the event was originally dispatched
655      */
656     @JsxGetter
657     public Object getTarget() {
658         return target_;
659     }
660 
661     /**
662      * Sets the event target.
663      * @param target the event target
664      */
665     public void setTarget(final EventTarget target) {
666         target_ = target;
667     }
668 
669     /**
670      * Returns the event target whose event listeners are currently being processed. This
671      * is useful during event capturing and event bubbling.
672      * @return the current event target
673      */
674     @JsxGetter
675     public Scriptable getCurrentTarget() {
676         return currentTarget_;
677     }
678 
679     /**
680      * Sets the current target.
681      * @param target the new value
682      */
683     public void setCurrentTarget(final Scriptable target) {
684         currentTarget_ = target;
685     }
686 
687     /**
688      * Returns the event type.
689      * @return the event type
690      */
691     @JsxGetter
692     public String getType() {
693         return type_;
694     }
695 
696     /**
697      * Sets the event type.
698      * @param type the event type
699      */
700     public void setType(final String type) {
701         type_ = type;
702     }
703 
704     /**
705      * Sets the event type.
706      * @param eventType the event type
707      */
708     public void setEventType(final String eventType) {
709         type_ = eventType;
710     }
711 
712     /**
713      * Returns the time at which this event was created.
714      * @return the time at which this event was created
715      */
716     @JsxGetter
717     public long getTimeStamp() {
718         return timeStamp_;
719     }
720 
721     /**
722      * Sets the key code.
723      * @param keyCode the virtual key code value of the key which was depressed, otherwise zero
724      */
725     protected void setKeyCode(final int keyCode) {
726         keyCode_ = keyCode;
727     }
728 
729     /**
730      * Returns the key code associated with the event.
731      * @return the key code associated with the event
732      */
733     public int getKeyCode() {
734         return keyCode_;
735     }
736 
737     /**
738      * Returns whether {@code SHIFT} has been pressed during this event or not.
739      * @return whether {@code SHIFT} has been pressed during this event or not
740      */
741     public boolean isShiftKey() {
742         return shiftKey_;
743     }
744 
745     /**
746      * Sets whether {@code SHIFT} key is pressed on not.
747      * @param shiftKey whether {@code SHIFT} has been pressed during this event or not
748      */
749     protected void setShiftKey(final boolean shiftKey) {
750         shiftKey_ = shiftKey;
751     }
752 
753     /**
754      * Returns whether {@code CTRL} has been pressed during this event or not.
755      * @return whether {@code CTRL} has been pressed during this event or not
756      */
757     public boolean isCtrlKey() {
758         return ctrlKey_;
759     }
760 
761     /**
762      * Sets whether {@code CTRL} key is pressed on not.
763      * @param ctrlKey whether {@code CTRL} has been pressed during this event or not
764      */
765     protected void setCtrlKey(final boolean ctrlKey) {
766         ctrlKey_ = ctrlKey;
767     }
768 
769     /**
770      * Returns whether {@code ALT} has been pressed during this event or not.
771      * @return whether {@code ALT} has been pressed during this event or not
772      */
773     public boolean isAltKey() {
774         return altKey_;
775     }
776 
777     /**
778      * Sets whether {@code ALT} key is pressed on not.
779      * @param altKey whether {@code ALT} has been pressed during this event or not
780      */
781     protected void setAltKey(final boolean altKey) {
782         altKey_ = altKey;
783     }
784 
785     /**
786      * Returns the current event phase for the event.
787      * @return the current event phase for the event
788      */
789     @JsxGetter
790     public int getEventPhase() {
791         return eventPhase_;
792     }
793 
794     /**
795      * Sets the current event phase. Must be one of {@link #CAPTURING_PHASE}, {@link #AT_TARGET} or
796      * {@link #BUBBLING_PHASE}.
797      *
798      * @param phase the phase the event is in
799      */
800     public void setEventPhase(final int phase) {
801         if (phase != CAPTURING_PHASE && phase != AT_TARGET && phase != BUBBLING_PHASE) {
802             throw new IllegalArgumentException("Illegal phase specified: " + phase);
803         }
804         eventPhase_ = phase;
805     }
806 
807     /**
808      * @return whether or not this event bubbles
809      */
810     @JsxGetter
811     public boolean isBubbles() {
812         return bubbles_;
813     }
814 
815     /**
816      * @param bubbles the bubbles to set
817      */
818     public void setBubbles(final boolean bubbles) {
819         bubbles_ = bubbles;
820     }
821 
822     /**
823      * @return whether or not this event can be canceled
824      */
825     @JsxGetter
826     public boolean isCancelable() {
827         return cancelable_;
828     }
829 
830     /**
831      * @param cancelable the cancelable to set
832      */
833     public void setCancelable(final boolean cancelable) {
834         cancelable_ = cancelable;
835     }
836 
837     /**
838      * Returns {@code true} if both <code>cancelable</code> is {@code true} and <code>preventDefault()</code> has been
839      * called for this event, otherwise this attribute must return {@code false}.
840      * @return {@code true} if this event has been cancelled or not
841      */
842     @JsxGetter
843     public boolean isDefaultPrevented() {
844         return cancelable_ && preventDefault_;
845     }
846 
847     /**
848      * @return indicates if event propagation is stopped
849      */
850     @JsxGetter
851     public boolean isCancelBubble() {
852         return stopPropagation_;
853     }
854 
855     /**
856      * @param newValue indicates if event propagation is stopped
857      */
858     @JsxSetter
859     public void setCancelBubble(final boolean newValue) {
860         stopPropagation_ = newValue;
861     }
862 
863     /**
864      * Stops the event from propagating.
865      */
866     @JsxFunction
867     public void stopPropagation() {
868         stopPropagation_ = true;
869     }
870 
871     /**
872      * Indicates if event propagation is stopped.
873      * @return the status
874      */
875     public boolean isPropagationStopped() {
876         return stopPropagation_;
877     }
878 
879     /**
880      * Prevents other listeners of the same event from being called.
881      */
882     @JsxFunction
883     public void stopImmediatePropagation() {
884         stopImmediatePropagation_ = true;
885         stopPropagation();
886     }
887 
888     /**
889      * Indicates if event immediate propagation is stopped.
890      * @return the status
891      */
892     public boolean isImmediatePropagationStopped() {
893         return stopImmediatePropagation_;
894     }
895 
896     /**
897      * Handles the return values of property handlers.
898      * @param returnValue the return value returned by the property handler
899      */
900     void handlePropertyHandlerReturnValue(final Object returnValue) {
901         if (Boolean.FALSE.equals(returnValue)) {
902             preventDefault();
903         }
904     }
905 
906     /**
907      * Returns the property name associated with the event.
908      * @return the property name associated with the event
909      */
910     public String getPropertyName() {
911         return propertyName_;
912     }
913 
914     /**
915      * Initializes this event.
916      * @param type the event type
917      * @param bubbles whether or not the event should bubble
918      * @param cancelable whether or not the event should be cancelable
919      */
920     @JsxFunction
921     public void initEvent(final String type, final boolean bubbles, final boolean cancelable) {
922         type_ = type;
923         bubbles_ = bubbles;
924         cancelable_ = cancelable;
925     }
926 
927     /**
928      * If, during any stage of event flow, this method is called the event is canceled.
929      * Any default action associated with the event will not occur.
930      * Calling this method for a non-cancelable event has no effect.
931      */
932     @JsxFunction
933     public void preventDefault() {
934         if (isCancelable()) {
935             preventDefault_ = true;
936         }
937     }
938 
939     /**
940      * Returns {@code true} if this event has been aborted via <code>preventDefault()</code> in
941      * standards-compliant browsers.
942      *
943      * @param result the event handler result (if {@code false}, the event is considered aborted)
944      * @return {@code true} if this event has been aborted
945      */
946     public boolean isAborted(final ScriptResult result) {
947         return ScriptResult.isFalse(result) || preventDefault_;
948     }
949 
950     /**
951      * {@inheritDoc}
952      */
953     @Override
954     public String toString() {
955         final StringBuilder builder = new StringBuilder(40);
956         builder.append("Event ")
957             .append(getType())
958             .append(" (Current Target: ")
959             .append(currentTarget_)
960             .append(");");
961         return builder.toString();
962     }
963 
964     /**
965      * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
966      *
967      * If we click on a label, we have to simulate a click on the element referenced by the 'for' attribute also.
968      * To support this for special events we have this method here.
969      * @return false in this default impl
970      */
971     public boolean processLabelAfterBubbling() {
972         return false;
973     }
974 
975     /**
976      * @return the return value property
977      */
978     @JsxGetter
979     public Object getReturnValue() {
980         return !preventDefault_;
981     }
982 
983     /**
984      * @param newValue the new return value
985      */
986     @JsxSetter
987     public void setReturnValue(final Object newValue) {
988         if (isCancelable()) {
989             final boolean bool = !JavaScriptEngine.toBoolean(newValue);
990             if (bool) {
991                 preventDefault_ = bool;
992             }
993         }
994     }
995 
996     /**
997      * @return the return composed property
998      */
999     @JsxGetter
1000     public boolean isComposed() {
1001         return false;
1002     }
1003 
1004     /**
1005      * Returns whether the given value indicates a missing or undefined property.
1006      * @param value the new value
1007      * @return whether the given value indicates a missing or undefined property
1008      */
1009     protected static boolean isMissingOrUndefined(final Object value) {
1010         return value == Scriptable.NOT_FOUND || JavaScriptEngine.isUndefined(value);
1011     }
1012 }