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