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 }