` element.
17 |
18 | ### [Mouse Event Viewer](https://garykac.github.io/dom-event-viewer/mouse-event-viewer.html)
19 |
20 | View MouseEvents on a set of overlapping `
`s:
21 |
22 | `mousedown`, `mouseenter`, `mouseleave`, `mousemove`, `mouseout`, `mouseover`, `mouseup`
23 |
24 | #### [Mouse Event Viewer (with shadow DOM)](https://garykac.github.io/dom-event-viewer/mouse-event-viewer-shadow.html)
25 |
26 | Same as the standard Mouse Event Viewer except with additional shadow DOM elements.
27 |
28 | ### [Focus Event Viewer](https://garykac.github.io/dom-event-viewer/focus-event-viewer.html)
29 |
30 | View FocusEvents between two edit fields:
31 |
32 | `blur`, `focus`, `focusin`, `focusout`, `DOMFocusIn`, `DOMFocusOut`
33 |
--------------------------------------------------------------------------------
/mouse-event-viewer.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
Mouse Event Viewer
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
DOM Event Viewers
22 |
23 |
Mouse Event Viewer
24 |
25 |
UserAgent:
26 |
27 |
28 |
29 |
30 |
31 | Show Options
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/index.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | font-family: "Arial Black";
3 | font-size: 24pt;
4 | text-align: center;
5 | }
6 |
7 | body {
8 | font-family: "Arial";
9 | font-size: 10pt;
10 | margin: 40px auto;
11 | background-color: #ffffff;
12 | max-width: 800px;
13 | }
14 |
15 | img {
16 | padding: 0;
17 | margin: 0;
18 | display: block;
19 | vertical-align: top;
20 | }
21 |
22 | .container {
23 | display: flex;
24 | flex-direction: column;
25 | flex-wrap: nowrap;
26 | justify-content: flex-start;
27 | width: 100%;
28 | padding: 0;
29 | margin: 0;
30 | }
31 |
32 | .row {
33 | border: 1px solid black;
34 | border-collapse: collapse;
35 | display: flex;
36 | flex-direction: row;
37 | flex-wrap: nowrap;
38 | justify-content: flex-start;
39 | padding: 0;
40 | margin: 0;
41 | }
42 |
43 | .row:not(:first-child) {
44 | margin-top: -1px;
45 | }
46 |
47 | .sideimage {
48 | flex-basis: 100px;
49 | }
50 |
51 | .viewer-list {
52 | flex-basis: auto;
53 | }
54 |
55 | code {
56 | font-size: 10pt;
57 | font-style: bold;
58 | }
59 |
60 | .name {
61 | display: block;
62 | font-family: "Arial Black";
63 | font-size: 16pt;
64 | font-style: bold;
65 | margin: 5px 10px;
66 | }
67 |
68 | .name a {
69 | text-decoration: none;
70 | }
71 |
72 | .name2 {
73 | display: block;
74 | font-family: "Arial Black";
75 | font-size: 12pt;
76 | font-style: bold;
77 | margin: 5px 10px;
78 | }
79 |
80 | .name2 a {
81 | text-decoration: none;
82 | }
83 |
84 | .desc {
85 | display: block;
86 | margin: 5px 10px 8px 10px;
87 | }
88 |
--------------------------------------------------------------------------------
/key-event-viewer-ce.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
Keyboard Event Viewer
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
DOM Event Viewers
21 |
22 |
Keyboard Event Viewer for contenteditable
23 |
24 |
UserAgent:
25 |
26 |
div with contenteditable="true":
27 |
Initial text
28 |
29 |
30 |
31 | Show Options
32 |
33 |
34 |
35 |
36 |
38 |
39 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/mouse-event-viewer-shadow.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
Mouse Event Viewer
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
DOM Event Viewers
22 |
23 |
Mouse Event Viewer with shadow dom content
24 |
25 |
UserAgent:
26 |
27 |
28 |
29 |
30 |
31 | Show Options
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/focus-event-viewer.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
Focus Event Viewer
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
DOM Event Viewers
21 |
22 |
Focus Event Viewer
23 |
24 |
UserAgent:
25 |
26 |
32 |
33 |
34 |
35 | Show Options
36 |
37 |
38 |
39 |
40 |
42 |
43 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/key-event-viewer.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
Keyboard Event Viewer
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
DOM Event Viewers
21 |
22 |
Keyboard Event Viewer
23 |
24 |
UserAgent:
25 |
26 |
27 | input element with type="text":
28 |
29 |
30 |
31 | Show Options
32 |
33 |
34 |
35 |
36 |
37 |
38 |
40 |
41 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/mouse-event-viewer.css:
--------------------------------------------------------------------------------
1 | .hilite_div_a {
2 | background-color: #c0ffc0;
3 | padding: 0 10px;
4 | }
5 |
6 | .hilite_div_b {
7 | background-color: #ffc0ff;
8 | padding: 0 10px;
9 | }
10 |
11 | .hilite_div_c {
12 | background-color: #c0ffff;
13 | padding: 0 10px;
14 | }
15 |
16 | .hilite_div_d {
17 | background-color: #c0c0c0;
18 | padding: 0 10px;
19 | }
20 |
21 | .hilite_div_e {
22 | background-color: #808080;
23 | padding: 0 10px;
24 | }
25 |
26 | .hilite_related_a {
27 | background-color: #e0ffe0;
28 | padding: 0 10px;
29 | }
30 |
31 | .hilite_related_b {
32 | background-color: #ffe0ff;
33 | padding: 0 10px;
34 | }
35 |
36 | .hilite_related_c {
37 | background-color: #e0ffff;
38 | padding: 0 10px;
39 | }
40 |
41 | .hilite_related_d {
42 | background-color: #e0e0e0;
43 | padding: 0 10px;
44 | }
45 |
46 | .hilite_related_e {
47 | background-color: #a0a0a0;
48 | padding: 0 10px;
49 | }
50 |
51 | .hilite_handler_a {
52 | padding: 0 10px;
53 | }
54 |
55 | .hilite_handler_b {
56 | padding: 0 10px;
57 | }
58 |
59 | .hilite_handler_c {
60 | padding: 0 10px;
61 | }
62 |
63 | #div_a {
64 | background-color: #c0ffc0;
65 | border-left: 1px solid black;
66 | border-top: 1px solid black;
67 | border-bottom: 1px solid black;
68 | margin-left: 30px;
69 | padding: 10px 0 10px 10px;
70 | display: inline-block;
71 | }
72 |
73 | #div_b {
74 | background-color: #ffc0ff;
75 | border-left: 1px solid black;
76 | border-top: 1px solid black;
77 | border-bottom: 1px solid black;
78 | margin: 10px 0 10px 10px;
79 | padding: 10px 0 10px 10px;
80 | display: inline-block;
81 | }
82 |
83 | #div_c {
84 | background-color: #c0ffff;
85 | border-left: 1px solid black;
86 | border-top: 1px solid black;
87 | border-bottom: 1px solid black;
88 | margin: 10px 0 10px 10px;
89 | padding: 10px 0 10px 10px;
90 | display: inline-block;
91 | min-width: 200px;
92 | min-height: 30px;
93 | }
94 |
--------------------------------------------------------------------------------
/shared.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | font-family: "Arial Black";
3 | font-size: 20pt;
4 | }
5 |
6 | .subtitle {
7 | font-size: 12pt;
8 | font-style: italic;
9 | }
10 |
11 | body {
12 | font-family: "Arial";
13 | font-size: 10pt;
14 | margin: 10px;
15 | padding: 0 20px;
16 | background-color: #ffffff;
17 | }
18 |
19 | .main_link {
20 | float: right;
21 | border: 1px solid black;
22 | border-radius: 4px;
23 | font-size: 9pt;
24 | padding: 2px 4px;
25 | text-decoration: none;
26 | background-color: #e0e0ff;
27 | }
28 |
29 | /* Options table */
30 |
31 | #options {
32 | display: none;
33 | margin: 20px;
34 | }
35 |
36 | #optionstoggle {
37 | font-size: 10pt;
38 | }
39 |
40 | .opttable {
41 | border: 1px solid black;
42 | }
43 |
44 | .optcell {
45 | vertical-align: top;
46 | padding: 0 10px;
47 | }
48 |
49 | .opttitle {
50 | font-weight: bold;
51 | }
52 |
53 | input[type=checkbox]:disabled+label {
54 | color: #a0a0a0;
55 | }
56 |
57 | .showfieldoption {
58 | font-weight: normal;
59 | padding: 0 5px 0 5px;
60 | display: inline-block;
61 | min-width: 90px;
62 | text-align: center;
63 | }
64 |
65 | /* Event table */
66 |
67 | .empty {
68 | background-color: #ffffff;
69 | }
70 |
71 | .subheader {
72 | font-size: 10pt;
73 | }
74 |
75 | .keycell {
76 | padding: 0 5px 0 5px;
77 | }
78 |
79 | .modOff {
80 | color: #ffd0d0;
81 | }
82 |
83 | .modOn {
84 | color: green;
85 | }
86 |
87 | .undef {
88 | color: #a0a0a0;
89 | }
90 |
91 | #output tr:hover, tr.highlight {
92 | background-color: #e0e0e0;
93 | }
94 |
95 | /* Common event highlighting */
96 | .event_hilight {
97 | border: 1px solid #404040;
98 | border-radius: 4px;
99 | padding: 0 3px 0 3px;
100 | margin-left: 3px;
101 | }
102 |
103 | /* Fix for black background in Fullscreen (Chrome). */
104 |
105 | html {
106 | background-color: #ffffff;
107 | }
108 |
109 | *:fullscreen, *:-webkit-full-screen, *:-moz-full-screen, *:-ms-fullscreen {
110 | background-color: rgba(255,255,255,0);
111 | width: 100%;
112 | height: 100%;
113 | }
114 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
DOM Event Viewing Tools
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
DOM Event Viewers
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Key Event Viewer
22 |
View KeyboardEvents on a <input type="text"> element.
23 |
keydown, keypress, keyup, textinput, beforeinput, input, compositionstart, compositionupdate, compositionend
24 |
25 |
Key Event Viewer (for contenteditable)
26 |
Same as the standard Key Event Viewer except targetting a <div contenteditable="true"> element.
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Mouse Event Viewer
34 |
View MouseEvents on a set of overlapping <div>s.
35 |
mousedown, mouseenter, mouseleave, mousemove, mouseout, mouseover, mouseup
36 |
37 |
Mouse Event Viewer (with shadow DOM)
38 |
Same as the standard Mouse Event Viewer except with additional shadow DOM elements.
39 |
40 |
Wheel Event Viewer
41 |
View mouse scroll wheel events.
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Focus Event Viewer
49 |
View FocusEvents between two <input> fields enclosed in a <div>.
50 |
blur, focus, focusin, focusout, DOMFocusIn, DOMFocusOut
51 |
52 |
53 |
54 |
55 |
56 |
57 | To report a bug or a submit feature request for any of these tools,
58 | file an issue on Github.
59 |
60 |
61 |
62 | Interested in viewing dome vents? Try this search instead.
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/shared.js:
--------------------------------------------------------------------------------
1 | // Shared helper
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | function clearChildren(e) {
5 | while (e.firstChild !== null) {
6 | e.removeChild(e.firstChild);
7 | }
8 | }
9 |
10 | function setText(e, text) {
11 | clearChildren(e);
12 | e.appendChild(document.createTextNode(text));
13 | }
14 |
15 | function addEventListener(obj, etype, handler) {
16 | if (obj.addEventListener) {
17 | obj.addEventListener(etype, handler, false);
18 | } else if (obj.attachEvent) {
19 | obj.attachEvent("on" + etype, handler);
20 | } else {
21 | obj["on" + etype] = handler;
22 | }
23 | }
24 |
25 | function handleDefaultPropagation(etype, e) {
26 | var preventDefault = document.getElementById("pd_" + etype);
27 | if (preventDefault.checked && e.preventDefault) {
28 | e.preventDefault();
29 | }
30 | var stopPropagation = document.getElementById("sp_" + etype);
31 | if (stopPropagation.checked && e.stopPropagation) {
32 | e.stopPropagation();
33 | }
34 | // Always prevent default for Tab.
35 | if (e.keyCode == 9 || e.code == "Tab") {
36 | e.preventDefault();
37 | }
38 | }
39 |
40 | function getModifierState(e) {
41 | Modifiers = [
42 | "Alt", "AltGraph", "Control", "Shift", "Meta",
43 | // Locking keys
44 | "CapsLock", "NumLock", "ScrollLock",
45 | // Linux
46 | "Hyper", "Super",
47 | // Virtual keyboards
48 | "Symbol", "SymbolLock",
49 | // Not valid, but check anyway
50 | "Fn", "FnLock",
51 | ];
52 |
53 | // Safari doesn't define getModifierState for mouse events.
54 | if (e.getModifierState === undefined) {
55 | return "Undefined";
56 | }
57 |
58 | mods = undefined;
59 | for (var mod of Modifiers) {
60 | if (e.getModifierState(mod)) {
61 | if (!mods) {
62 | mods = mod;
63 | } else {
64 | mods += ", " + mod;
65 | }
66 | }
67 | }
68 | return mods;
69 | }
70 |
71 | function getEventPhase(e) {
72 | var p = e.eventPhase;
73 | var phase = '?';
74 | if (p == 0)
75 | phase = 'None';
76 | else if (p == 1)
77 | phase = 'Capturing';
78 | else if (p == 2)
79 | phase = 'AtTarget';
80 | else if (p == 3)
81 | phase = 'Bubbling';
82 | return phase;
83 | }
84 |
85 | function calcString(data) {
86 | if (data === undefined) {
87 | return data;
88 | }
89 | return "'" + data + "'";
90 | }
91 |
92 | function calcHilightString(eventType, data, addArrow) {
93 | if (data === undefined) {
94 | return null;
95 | }
96 |
97 | var keySpan = document.createElement("span");
98 | var enableHilight = document.getElementById("hl_" + eventType);
99 | if (enableHilight && enableHilight.checked) {
100 | keySpan.classList.add("event_hilight");
101 | keySpan.classList.add(eventType.toLowerCase() + "_hilight");
102 |
103 | // Extra classes for keyboard event viewer.
104 | if (addArrow && (eventType == "keydown" || eventType == "keyup")) {
105 | keySpan.classList.add(eventType + "_arrow");
106 | }
107 | }
108 | keySpan.textContent = data;
109 | return keySpan;
110 | }
111 |
112 | // CSS Stylesheet management
113 |
114 | function injectCustomCSS(event_info, table_info) {
115 | // Find style sheet to inject into.
116 | var sheet = undefined;
117 | for (var i = 0; i < document.styleSheets.length; i++) {
118 | if (document.styleSheets[i].title == "inject") {
119 | sheet = document.styleSheets[i];
120 | }
121 | }
122 |
123 | if (sheet) {
124 | for (var event of event_info) {
125 | var ename = event[0];
126 | var options = event[1][name];
127 | var background = event[2];
128 | if (background != "") {
129 | sheet.insertRule("." + ename.toLowerCase() + "_hilight { background: " + background + "; }", 0);
130 | }
131 | }
132 |
133 | for (var group of table_info) {
134 | var name = group[0];
135 | var type = group[1];
136 | var options = group[3];
137 | if (options && options['header-background']) {
138 | var background = options['header-background'];
139 | var cssRule = "." + type + "_header { background-color: " + background + "; font-weight: bold; border: 1px solid black; }";
140 | sheet.insertRule(cssRule, 0);
141 | }
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/mouse-event-viewer-core.js:
--------------------------------------------------------------------------------
1 | // Mouse event viewer
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | var _mouse_table_info = [
5 | // Unlabeled group
6 | ["", "etype", [
7 | ["#", "etype", "text"],
8 | ["Event type", "etype", "html"],
9 | ["Count", "etype", "text"],
10 | ], {
11 | 'grouplabel': false,
12 | 'header-background': "#e0e0e0"
13 | }],
14 |
15 | // MouseEvent - Target
16 | ["Target", "target", [
17 | ["A", "target", "text", {'style': 'hilite_div_a'}],
18 | ["B", "target", "text", {'style': 'hilite_div_b'}],
19 | ["C", "target", "text", {'style': 'hilite_div_c'}],
20 | ], {
21 | 'checked': true,
22 | 'header-background': "#ffffff"
23 | }],
24 |
25 | // MouseEvent - relatedTarget
26 | ["relatedTarget", "relatedTarget", [
27 | ["rA", "relatedTarget", "text", {'style': 'hilite_related_a'}],
28 | ["rB", "relatedTarget", "text", {'style': 'hilite_related_b'}],
29 | ["rC", "relatedTarget", "text", {'style': 'hilite_related_c'}],
30 | ], {
31 | 'checked': false,
32 | 'header-background': "#ffffff"
33 | }],
34 |
35 | // MouseEvent - Handler
36 | ["Handler", "handler", [
37 | ["hA", "handler", "text", {'style': 'hilite_handler_a'}],
38 | ["hB", "handler", "text", {'style': 'hilite_handler_b'}],
39 | ["hC", "handler", "text", {'style': 'hilite_handler_c'}],
40 | ], {
41 | 'checked': false,
42 | 'header-background': "#c0c0ff"
43 | }],
44 |
45 | // Event
46 | ["Event", "event", [
47 | ["eventPhase", "event", "text"],
48 | ["bubbles", "event", "bool"],
49 | ["cancelable", "event", "bool"],
50 | ["defaultPrevented", "event", "bool"],
51 | ["composed", "event", "bool"],
52 | ["isTrusted", "event", "bool"],
53 | ["timeStamp", "event", "text"],
54 | ], {
55 | 'checked': false,
56 | 'header-background': "#a0ffff"
57 | }],
58 |
59 | // UIEvent
60 | ["UIEvent", "uievent", [
61 | ["view", "uievent", "text"],
62 | ["detail", "uievent", "text"],
63 | ], {
64 | 'checked': false,
65 | 'header-background': "#ffffff"
66 | }],
67 |
68 | // MouseEvent - UI Events
69 | ["MouseEvent", "mouseevent", [
70 | ["screenX", "mouseevent", "text"],
71 | ["screenY", "mouseevent", "text"],
72 | ["clientX", "mouseevent", "text"],
73 | ["clientY", "mouseevent", "text"],
74 | ], {
75 | 'checked': true,
76 | 'header-background': "#ffffc0"
77 | }],
78 |
79 | // PointerLock
80 | ["PointerLock", "plock", [
81 | ["movementX", "plock", "text"],
82 | ["movementY", "plock", "text"],
83 | ], {
84 | 'checked': true,
85 | 'header-background': "#e0a0e0"
86 | }],
87 |
88 | // CSSOM
89 | ["CSSOM", "cssom", [
90 | ["offsetX", "cssom", "text"],
91 | ["offsetY", "cssom", "text"],
92 | ["pageX", "cssom", "text"],
93 | ["pageY", "cssom", "text"],
94 | ["x", "cssom", "text"],
95 | ["y", "cssom", "text"],
96 | ], {
97 | 'checked': true,
98 | 'header-background': "#c0f0c0"
99 | }],
100 |
101 | // MouseEvent - UI Events
102 | ["Buttons", "buttons", [
103 | ["button", "buttons", "text"],
104 | ["buttons", "buttons", "text"],
105 | ], {
106 | 'checked': true,
107 | 'header-background': "#e0e0e0"
108 | }],
109 |
110 | // KeyboardEvent - Modifiers
111 | ["Modifiers", "modifiers", [
112 | ["getModifierState", "modifiers", "text"],
113 | ["shift", "modifiers", "bool"],
114 | ["ctrl", "modifiers", "bool"],
115 | ["alt", "modifiers", "bool"],
116 | ["meta", "modifiers", "bool"],
117 | ], {
118 | 'checked': true,
119 | 'header-background': "#ffc0c0"
120 | }],
121 | ];
122 |
123 | function init() {
124 | init_shared();
125 |
126 | var div_a = document.getElementById("div_a");
127 | var div_b = document.getElementById("div_b");
128 | var div_c = document.getElementById("div_c");
129 | for (var div of [div_a, div_b, div_c]) {
130 | addEventListener(div, "mousedown", onMouseDown.bind(null, div));
131 | addEventListener(div, "mouseenter", onMouseEnter.bind(null, div));
132 | addEventListener(div, "mouseleave", onMouseLeave.bind(null, div));
133 | addEventListener(div, "mousemove", onMouseMove.bind(null, div));
134 | addEventListener(div, "mouseout", onMouseOut.bind(null, div));
135 | addEventListener(div, "mouseover", onMouseOver.bind(null, div));
136 | addEventListener(div, "mouseup", onMouseUp.bind(null, div));
137 | addEventListener(div, "auxclick", onAuxClick.bind(null, div));
138 | addEventListener(div, "click", onClick.bind(null, div));
139 | addEventListener(div, "dblclick", onDblClick.bind(null, div));
140 | addEventListener(div, "contextmenu", onContextMenu.bind(null, div));
141 | }
142 |
143 | addEventListener(document.getElementById("body"), "keydown", onKeyDown);
144 | addEventListener(div_a, "contextmenu", onContextMenu);
145 | }
146 |
--------------------------------------------------------------------------------
/window-size.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
Window Size
6 |
7 |
8 |
9 |
60 |
61 |
62 |
63 |
71 |
72 |
73 |
Mouse click
74 |
75 |
76 |
77 |
85 |
86 |
87 |
88 |
89 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/mouse-event-viewer-shadow.js:
--------------------------------------------------------------------------------
1 | // Mouse event viewer
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | var _mouse_table_info = [
5 | // Unlabeled group
6 | ["", "etype", [
7 | ["#", "etype", "text"],
8 | ["Event type", "etype", "html"],
9 | ["Count", "etype", "text"],
10 | ], {
11 | 'grouplabel': false,
12 | 'header-background': "#e0e0e0"
13 | }],
14 |
15 | // MouseEvent - Target
16 | ["Target", "target", [
17 | ["A", "target", "text", {'style': 'hilite_div_a'}],
18 | ["B", "target", "text", {'style': 'hilite_div_b'}],
19 | ["C", "target", "text", {'style': 'hilite_div_c'}],
20 | ["sD", "target", "text", {'style': 'hilite_div_d'}],
21 | ["sE", "target", "text", {'style': 'hilite_div_e'}],
22 | ], {
23 | 'checked': true,
24 | 'header-background': "#ffffff"
25 | }],
26 |
27 | // MouseEvent - relatedTarget
28 | ["relatedTarget", "relatedTarget", [
29 | ["rA", "relatedTarget", "text", {'style': 'hilite_related_a'}],
30 | ["rB", "relatedTarget", "text", {'style': 'hilite_related_b'}],
31 | ["rC", "relatedTarget", "text", {'style': 'hilite_related_c'}],
32 | ["srD", "relatedTarget", "text", {'style': 'hilite_related_d'}],
33 | ["srE", "relatedTarget", "text", {'style': 'hilite_related_e'}],
34 | ], {
35 | 'checked': true,
36 | 'header-background': "#ffffff"
37 | }],
38 |
39 | // Event
40 | ["Event", "event", [
41 | ["eventPhase", "event", "text"],
42 | ["bubbles", "event", "bool"],
43 | ["cancelable", "event", "bool"],
44 | ["defaultPrevented", "event", "bool"],
45 | ["composed", "event", "bool"],
46 | ["isTrusted", "event", "bool"],
47 | ["timeStamp", "event", "text"],
48 | ], {
49 | 'checked': false,
50 | 'header-background': "#a0ffff"
51 | }],
52 |
53 | // UIEvent
54 | ["UIEvent", "uievent", [
55 | ["view", "uievent", "text"],
56 | ["detail", "uievent", "text"],
57 | ], {
58 | 'checked': false,
59 | 'header-background': "#e0e0e0"
60 | }],
61 |
62 | // MouseEvent - UI Events
63 | ["MouseEvent", "mouseevent", [
64 | ["screenX", "mouseevent", "text"],
65 | ["screenY", "mouseevent", "text"],
66 | ["clientX", "mouseevent", "text"],
67 | ["clientY", "mouseevent", "text"],
68 | ], {
69 | 'checked': true,
70 | 'header-background': "#ffffc0"
71 | }],
72 |
73 | // PointerLock
74 | ["PointerLock", "plock", [
75 | ["movementX", "plock", "text"],
76 | ["movementY", "plock", "text"],
77 | ], {
78 | 'checked': true,
79 | 'header-background': "#e0a0e0"
80 | }],
81 |
82 | // CSSOM
83 | ["CSSOM", "cssom", [
84 | ["offsetX", "cssom", "text"],
85 | ["offsetY", "cssom", "text"],
86 | ["pageX", "cssom", "text"],
87 | ["pageY", "cssom", "text"],
88 | ["x", "cssom", "text"],
89 | ["y", "cssom", "text"],
90 | ], {
91 | 'checked': true,
92 | 'header-background': "#c0f0c0"
93 | }],
94 |
95 | // MouseEvent - UI Events
96 | ["Buttons", "buttons", [
97 | ["button", "buttons", "text"],
98 | ["buttons", "buttons", "text"],
99 | ], {
100 | 'checked': true,
101 | 'header-background': "#e0e0e0"
102 | }],
103 |
104 | // KeyboardEvent - Modifiers
105 | ["Modifiers", "modifiers", [
106 | ["getModifierState", "modifiers", "text"],
107 | ["shift", "modifiers", "bool"],
108 | ["ctrl", "modifiers", "bool"],
109 | ["alt", "modifiers", "bool"],
110 | ["meta", "modifiers", "bool"],
111 | ], {
112 | 'checked': true,
113 | 'header-background': "#ffc0c0"
114 | }],
115 | ];
116 |
117 | function init() {
118 | init_shared();
119 |
120 | var div_a = document.getElementById("div_a");
121 | var div_b = document.getElementById("div_b");
122 | var div_c = document.getElementById("div_c");
123 |
124 | const shadow_root = div_c.attachShadow({ mode: 'open'});
125 | shadow_root.innerHTML =
126 | '' +
138 | 'C (sHost)' +
139 | '
sD' +
140 | '
sE
' +
141 | '
';
142 | var div_d = shadow_root.getElementById("div_d");
143 | var div_e = shadow_root.getElementById("div_e");
144 |
145 | for (var div of [div_a, div_b, div_c, div_d, div_e]) {
146 | addEventListener(div, "mousedown", onMouseDown.bind(null, div));
147 | addEventListener(div, "mouseenter", onMouseEnter.bind(null, div));
148 | addEventListener(div, "mouseleave", onMouseLeave.bind(null, div));
149 | addEventListener(div, "mousemove", onMouseMove.bind(null, div));
150 | addEventListener(div, "mouseout", onMouseOut.bind(null, div));
151 | addEventListener(div, "mouseover", onMouseOver.bind(null, div));
152 | addEventListener(div, "mouseup", onMouseUp.bind(null, div));
153 | addEventListener(div, "auxclick", onAuxClick.bind(null, div));
154 | addEventListener(div, "click", onClick.bind(null, div));
155 | addEventListener(div, "dblclick", onDblClick.bind(null, div));
156 | addEventListener(div, "contextmenu", onContextMenu.bind(null, div));
157 | }
158 |
159 | addEventListener(document.getElementById("body"), "keydown", onKeyDown);
160 | addEventListener(div_a, "contextmenu", onContextMenu);
161 | }
162 |
--------------------------------------------------------------------------------
/output-table.js:
--------------------------------------------------------------------------------
1 | // Event test output table
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | // Output table
5 | // Assumes:
6 | // * The html contains and empty
with id="output".
7 | //
8 | // * First column of table is '#' and will contain an auto-generated sequence id.
9 | // * For each group-type, there is a CSS class with that name and one for the header
10 | // with a '_header' suffix.
11 | // * There is a 'subheader' CSS class for the 2nd header row.
12 |
13 | var NUM_HEADER_ROWS = 2;
14 | var MAX_OUTPUT_ROWS = 100 + NUM_HEADER_ROWS;
15 |
16 | // Sequence ID for numbering events.
17 | var _seqId = 1;
18 |
19 |
20 | // Output table info
21 | // Format:
22 | // array of
23 | // : [ , , , , ]
24 | // :
25 | // : cell type for style
26 | // : an array of
27 | // : [ , , ]
28 | // : dict of options:
29 | // 'align': left
30 | var _table_info;
31 |
32 | function initOutputTable(table_info) {
33 | _table_info = table_info;
34 | createTableHeader();
35 | _seqId = 1;
36 | }
37 |
38 | function createTableHeader(table_info) {
39 | var table = document.getElementById("output");
40 | var head = table.createTHead();
41 | var row1 = head.insertRow(-1); // For column group names
42 | var row2 = head.insertRow(-1); // For column names
43 |
44 | for (var group of _table_info) {
45 | var group_title = group[0];
46 | var group_type = group[1];
47 | var group_style = group_type + '_header';
48 | var columns = group[2];
49 | var options = group[3];
50 | if (options.grouplabel != undefined && !options.grouplabel) {
51 | group_title = "";
52 | group_style = "";
53 | }
54 | addTableCellText(row1, group_title, group_type, group_style, columns.length);
55 |
56 | for (var col of columns) {
57 | var title = col[0];
58 | var type = col[1];
59 | var format = col[2];
60 | var options = col[3];
61 |
62 | var style = [type + '_header', 'subheader'];
63 | if (options && options['style']) {
64 | style.push(options['style']);
65 | }
66 |
67 | addTableCellText(row2, title, type, style);
68 | }
69 | }
70 | }
71 |
72 | function clearTable() {
73 | clearChildren(document.getElementById("output"));
74 | }
75 |
76 | /* Create the event table row from the event info */
77 | function addEventToOutput(eventinfo, extra_class) {
78 | var row = addOutputRow(extra_class);
79 |
80 | for (var group of _table_info) {
81 | var columns = group[2];
82 | for (var col of columns) {
83 | var title = col[0];
84 | var type = col[1];
85 | var format = col[2];
86 | var options = col[3];
87 |
88 | var val = eventinfo[title];
89 | if (title == '#') {
90 | val = _seqId;
91 | }
92 |
93 | var style = undefined;
94 | var align = undefined;
95 | if (options && val != "") {
96 | style = options['style'];
97 | align = options['align'];
98 | }
99 |
100 | if (format == 'text')
101 | addTableCellText(row, val, type, style, undefined, align);
102 | else if (format == 'bool')
103 | addTableCellBoolean(row, val, type, style, undefined, align);
104 | else
105 | addTableCell(row, val, type, style, undefined, align);
106 | }
107 | }
108 |
109 | _seqId++;
110 | }
111 |
112 | // Delete the most recent output row.
113 | function deleteLastOutputRow() {
114 | var table = document.getElementById("output");
115 | table.deleteRow(NUM_HEADER_ROWS);
116 | }
117 |
118 | // extra_class: Additional CSS class to add to this row.
119 | function addOutputRow(extra_class) {
120 | var table = document.getElementById("output");
121 |
122 | while (table.rows.length >= MAX_OUTPUT_ROWS) {
123 | table.deleteRow(-1);
124 | }
125 | // Insert after the header rows.
126 | var row = table.insertRow(NUM_HEADER_ROWS);
127 | if (extra_class) {
128 | row.classList.add(extra_class);
129 | }
130 | return row;
131 | }
132 |
133 | function addTableCellBoolean(row, key, celltype) {
134 | var modstyle = key ? "modOn" : "modOff";
135 | addTableCellText(row, calcBoolean(key), celltype, modstyle);
136 | }
137 |
138 | function calcBoolean(key) {
139 | return key ? "✓" : "✗";
140 | }
141 |
142 | function addTableCellText(row, textdata, celltype, style, span, align) {
143 | var data = null;
144 | if (textdata !== undefined) {
145 | data = document.createTextNode(textdata);
146 | }
147 | addTableCell(row, data, celltype, style, span, align);
148 | }
149 |
150 | function addTableCell(row, data, celltype, style, span, align) {
151 | var cell = row.insertCell(-1);
152 | if (data === undefined || data == null) {
153 | data = document.createTextNode("-");
154 | style = "undef";
155 | }
156 | cell.appendChild(data);
157 | if (align === undefined) {
158 | align = "center";
159 | }
160 | cell.setAttribute("align", align);
161 | if (span !== undefined) {
162 | cell.setAttribute("colspan", span);
163 | }
164 | cell.classList.add("keycell");
165 | cell.classList.add(celltype);
166 | if (style !== undefined && style != "") {
167 | if (style instanceof Array) {
168 | for (var i = 0; i < style.length; i++) {
169 | cell.classList.add(style[i]);
170 | }
171 | } else {
172 | cell.classList.add(style);
173 | }
174 | }
175 | if (celltype == "etype") {
176 | return;
177 | }
178 | // Hide this cell if it belongs to a hidden celltype.
179 | var show = document.getElementById("show_" + celltype).checked;
180 | if (!show) {
181 | cell.style.display = "none";
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/wheel-event-viewer.js:
--------------------------------------------------------------------------------
1 | // Mouse event viewer - shared
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | var _wheel_event_info = [
5 | ["mousedown", {
6 | 'preventDefault': {'checked': false},
7 | 'stopPropagation': {},
8 | 'ShowEvents': {},
9 | 'Highlight': {'checked': false},
10 | },
11 | "#ccffcc"],
12 | ["mouseup", {
13 | 'preventDefault': {'checked': false},
14 | 'stopPropagation': {},
15 | 'ShowEvents': {},
16 | 'Highlight': {'checked': false},
17 | },
18 | "#ffcccc"],
19 | ["wheel", {
20 | 'preventDefault': {'checked': true},
21 | 'stopPropagation': {},
22 | 'ShowEvents': {},
23 | 'Highlight': {},
24 | },
25 | "#e0e0e0"],
26 | ];
27 |
28 | var _wheel_table_info = [
29 | // Unlabeled group
30 | ["", "etype", [
31 | ["#", "etype", "text"],
32 | ["Event type", "etype", "html"],
33 | ], {
34 | 'grouplabel': false,
35 | 'header-background': "#e0e0e0"
36 | }],
37 |
38 | // Event
39 | ["Event", "event", [
40 | ["eventPhase", "event", "text"],
41 | ["bubbles", "event", "bool"],
42 | ["cancelable", "event", "bool"],
43 | ["defaultPrevented", "event", "bool"],
44 | ["composed", "event", "bool"],
45 | ["isTrusted", "event", "bool"],
46 | ["timeStamp", "event", "text"],
47 | ], {
48 | 'checked': false,
49 | 'header-background': "#a0ffff"
50 | }],
51 |
52 | // UIEvent
53 | ["UIEvent", "uievent", [
54 | ["view", "uievent", "text"],
55 | ["detail", "uievent", "text"],
56 | ], {
57 | 'checked': false,
58 | 'header-background': "#ffffff"
59 | }],
60 |
61 | // MouseEvent - UI Events
62 | ["MouseEvent", "mouseevent", [
63 | ["screenX", "mouseevent", "text"],
64 | ["screenY", "mouseevent", "text"],
65 | ["clientX", "mouseevent", "text"],
66 | ["clientY", "mouseevent", "text"],
67 | ], {
68 | 'checked': true,
69 | 'header-background': "#ffffc0"
70 | }],
71 |
72 | // MouseEvent - UI Events
73 | ["Buttons", "buttons", [
74 | ["button", "buttons", "text"],
75 | ["buttons", "buttons", "text"],
76 | ], {
77 | 'checked': true,
78 | 'header-background': "#e0e0e0"
79 | }],
80 |
81 | // WheelEvent - UI Events
82 | ["Wheel", "wheel", [
83 | ["deltaX", "wheel", "text"],
84 | ["deltaY", "wheel", "text"],
85 | ["deltaZ", "wheel", "text"],
86 | ["deltaMode", "wheel", "text"],
87 | ], {
88 | 'checked': true,
89 | 'header-background': "#c0f0c0"
90 | }],
91 | ];
92 |
93 | function setUserAgentText() {
94 | var userAgent = navigator.userAgent;
95 | uaDiv = document.getElementById("useragent");
96 | setText(uaDiv, userAgent);
97 | }
98 |
99 | function resetTable() {
100 | clearTable();
101 | initOutputTable(_wheel_table_info);
102 | }
103 |
104 | function init() {
105 | setUserAgentText();
106 | var extra_options = [
107 | ["text", "Note: Options apply to new events only."],
108 | ["text", "Press 'c' to Clear Table."],
109 | ];
110 | createOptions(document.getElementById("options"), _wheel_event_info, _wheel_table_info, extra_options);
111 | injectCustomCSS(_wheel_event_info, _wheel_table_info);
112 | resetTable();
113 |
114 | var target = document.getElementById("target");
115 | addEventListener(target, "mousedown", onMouseDown);
116 | addEventListener(target, "mouseup", onMouseUp);
117 | addEventListener(target, "wheel", onWheel);
118 |
119 | addEventListener(document.getElementById("body"), "keydown", onKeyDown);
120 | addEventListener(target, "contextmenu", onContextMenu);
121 | }
122 |
123 | function onKeyDown(e) {
124 | if (e.code == "KeyC") {
125 | resetTable();
126 | }
127 | }
128 |
129 | function onContextMenu(e) {
130 | e.preventDefault();
131 | e.stopPropagation();
132 | }
133 |
134 | function onMouseDown(e) {
135 | handleMouseEvent("mousedown", e);
136 | }
137 |
138 | function onMouseUp(e) {
139 | handleMouseEvent("mouseup", e);
140 | }
141 |
142 | function onWheel(e) {
143 | handleMouseEvent("wheel", e);
144 | }
145 |
146 | function handleMouseEvent(etype, e) {
147 | var show = document.getElementById("show_" + etype);
148 | if (show.checked) {
149 | addMouseEvent(etype, e);
150 | }
151 | handleDefaultPropagation(etype, e);
152 | }
153 |
154 | function addMouseEvent(etype, e) {
155 | if (!e) {
156 | e = window.event;
157 | }
158 | var target = e.target.id;
159 | var eventinfo = {};
160 | eventinfo["Event type"] = calcHilightString(etype, e.type, true);
161 |
162 | eventinfo["eventPhase"] = getEventPhase(e);
163 | eventinfo["bubbles"] = e.bubbles;
164 | eventinfo["cancelable"] = e.cancelable;
165 | eventinfo["defaultPrevented"] = e.defaultPrevented;
166 | eventinfo["composed"] = e.composed;
167 | eventinfo["isTrusted"] = e.isTrusted;
168 | eventinfo["timeStamp"] = e.timeStamp;
169 |
170 | eventinfo["view"] = calcString(e.view !== null ? e.view.name : "null");
171 | eventinfo["detail"] = e.detail;
172 |
173 | eventinfo["screenX"] = e.screenX;
174 | eventinfo["screenY"] = e.screenY;
175 | eventinfo["clientX"] = e.clientX;
176 | eventinfo["clientY"] = e.clientY;
177 |
178 | var button = "-";
179 | if (etype == "mousedown" || etype == "mouseup") {
180 | button = e.button;
181 | }
182 | eventinfo["button"] = button;
183 | eventinfo["buttons"] = e.buttons;
184 |
185 | eventinfo["getModifierState"] = getModifierState(e);
186 | eventinfo["shift"] = e.shiftKey;
187 | eventinfo["ctrl"] = e.ctrlKey;
188 | eventinfo["alt"] = e.altKey;
189 | eventinfo["meta"] = e.metaKey;
190 |
191 | eventinfo["deltaX"] = e.deltaX;
192 | eventinfo["deltaY"] = e.deltaY;
193 | eventinfo["deltaZ"] = e.deltaZ;
194 |
195 | var deltaMode = "-";
196 | if (etype == "wheel") {
197 | if (e.deltaMode == 0)
198 | deltaMode = "PIXEL";
199 | else if (e.deltaMode == 1)
200 | deltaMode = "LINE";
201 | else if (e.deltaMode == 2)
202 | deltaMode = "PAGE";
203 | else
204 | deltaMode = "??? (" + e.deltaMode + ")";
205 | }
206 | eventinfo["deltaMode"] = deltaMode;
207 |
208 | addEventToOutput(eventinfo);
209 | }
210 |
--------------------------------------------------------------------------------
/options.js:
--------------------------------------------------------------------------------
1 | // Event test options block
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | _column_info = [
5 | ["preventDefault", "pd_"],
6 | ["stopPropagation", "sp_"],
7 | ["ShowEvents", "show_"],
8 | ["Highlight", "hl_"],
9 | ];
10 |
11 | function createOptions(options_div, event_info, table_info, extra) {
12 | var table = document.createElement('table');
13 | var row, cell;
14 |
15 | table.classList.add("opttable");
16 | row = document.createElement('tr');
17 |
18 | for (var col of _column_info) {
19 | var name = col[0];
20 | var prefix = col[1];
21 |
22 | cell = document.createElement('td');
23 | cell.classList.add("optcell");
24 | addOptionTitle(cell, name);
25 | for (var event of event_info) {
26 | var e = event[0];
27 | var options = event[1][name];
28 | if (name == "Highlight" && (options.enabled == undefined || options.enabled)) {
29 | var classes = "event_hilight " + e.toLowerCase() + "_hilight";
30 | if (options.class != undefined)
31 | classes += " " + options.class;
32 | options.class = classes;
33 | }
34 | options.onclick = 'onOptionClick(this)';
35 | addOptionCheckbox(cell, prefix + e, e, options);
36 | }
37 | row.appendChild(cell);
38 | }
39 |
40 | cell = document.createElement('td');
41 | cell.classList.add("optcell");
42 | addOptionTitle(cell, "Show Fields");
43 | for (var group of table_info) {
44 | var name = group[0];
45 | var type = group[1];
46 | var options = group[3];
47 | options.enabled = true;
48 | options.class = type + "_header showfieldoption";
49 | options.onclick = 'showFieldClick(this)';
50 | if (name != "") {
51 | addOptionCheckbox(cell, "show_" + type, name, options);
52 | }
53 | }
54 | row.appendChild(cell);
55 | table.appendChild(row);
56 |
57 | if (extra != undefined && extra.length != 0) {
58 | var addTitle = true;
59 | for (var opt of extra) {
60 | row = document.createElement('tr');
61 | cell = document.createElement('td');
62 | cell.classList.add("optcell");
63 | cell.setAttribute("colspan", "5");
64 |
65 | if (addTitle) {
66 | addOptionTitle(cell, "General Options");
67 | addTitle = false;
68 | }
69 |
70 | var type = opt[0];
71 | if (type == "checkbox") {
72 | var name = opt[1];
73 | var label = opt[2];
74 | var options = opt[3];
75 | if (options.onclick === undefined) {
76 | options.onclick = 'onOptionClick(this)';
77 | }
78 | addOptionCheckbox(cell, name, label, options);
79 | } else if (type == "text") {
80 | var text = opt[1];
81 | cell.appendChild(document.createTextNode(text));
82 | }
83 |
84 | row.appendChild(cell);
85 | table.appendChild(row);
86 | }
87 | }
88 |
89 | options_div.appendChild(table);
90 | }
91 |
92 | function addOptionTitle(cell, title) {
93 | var span = document.createElement('span');
94 | span.classList.add("opttitle");
95 | span.textContent = title;
96 | cell.appendChild(span);
97 | cell.appendChild(document.createElement("br"));
98 | }
99 |
100 | function addOptionCheckbox(cell, id, text, options) {
101 | if (options.enabled === undefined)
102 | options.enabled = true;
103 | if (options.checked === undefined)
104 | options.checked = true;
105 |
106 | // Apply previously saved value (if any).
107 | var savedValue = window.localStorage.getItem(id);
108 | if (savedValue != null) {
109 | options.checked = (savedValue == "true");
110 | }
111 |
112 | var input = document.createElement("input");
113 | input.type = "checkbox";
114 | input.id = id;
115 | input.checked = options.checked;
116 | input.disabled = !options.enabled;
117 | if (options.onclick != undefined && options.onclick != "") {
118 | input.setAttribute("onclick", options.onclick);
119 | }
120 | cell.appendChild(input);
121 |
122 | var label = document.createElement("label");
123 | label.setAttribute("for", id);
124 | var span = document.createElement('span');
125 | if (options.class !== undefined) {
126 | for (var c of options.class.split(' ')) {
127 | span.classList.add(c);
128 | }
129 | }
130 | span.appendChild(document.createTextNode(text));
131 | label.appendChild(span);
132 | cell.appendChild(label);
133 |
134 | cell.appendChild(document.createElement("br"));
135 | }
136 |
137 | function addOptionText(cell, prefix, id, text) {
138 | var span1 = document.createElement('span');
139 | span1.classList.add("opttext");
140 | span1.appendChild(document.createTextNode(prefix));
141 |
142 | var span2 = document.createElement('span');
143 | span2.id = id;
144 | span2.textContent = 0;
145 | span1.appendChild(span2);
146 | span1.appendChild(document.createTextNode(text));
147 |
148 | cell.appendChild(span1);
149 | cell.appendChild(document.createElement("br"));
150 | }
151 |
152 | function toggleOptions() {
153 | var link = document.getElementById("optionsToggle");
154 | var options = document.getElementById("options");
155 | clearChildren(link);
156 | if (options.style.display == "block") {
157 | options.style.display = "none";
158 | link.appendChild(document.createTextNode("Show Options"));
159 | }
160 | else {
161 | options.style.display = "block";
162 | link.appendChild(document.createTextNode("Hide Options"));
163 | }
164 | }
165 |
166 | function onOptionClick(cb) {
167 | window.localStorage.setItem(cb.id, cb.checked);
168 | }
169 |
170 | function showFieldClick(cb) {
171 | onOptionClick(cb);
172 |
173 | var celltype = cb.id.split('_')[1];
174 | var show = cb.checked;
175 |
176 | var table = document.getElementById("output");
177 | for (var ir = 0, row; row = table.rows[ir]; ir++) {
178 | for (var ic = 0, cell; cell = row.cells[ic]; ic++) {
179 | if (cell.classList.contains(celltype)) {
180 | if (show) {
181 | cell.style.display = "";
182 | } else {
183 | cell.style.display = "none";
184 | }
185 | }
186 | }
187 | }
188 | }
189 |
190 |
--------------------------------------------------------------------------------
/focus-event-viewer.js:
--------------------------------------------------------------------------------
1 | // Keyboard event viewer
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | var _focus_table_info = [
5 | // Unlabeled group
6 | ["", "etype", [
7 | ["#", "etype", "text"],
8 | ["Event type", "etype", "html"],
9 | ], {
10 | 'grouplabel': false,
11 | 'header-background': "#e0e0e0"
12 | }],
13 |
14 | // Event - Target
15 | ["Target", "target", [
16 | ["A", "target", "text", {'style': 'hilite_target_a'}],
17 | ["B", "target", "text", {'style': 'hilite_target_b'}],
18 | ["Outer", "target", "text", {'style': 'hilite_target_outer'}],
19 | ], {
20 | 'checked': true,
21 | 'header-background': "#ffffc0"
22 | }],
23 |
24 | // FocusEvent - relatedTarget
25 | ["relatedTarget", "focusevent", [
26 | ["rA", "focusevent", "text", {'style': 'hilite_related_a'}],
27 | ["rB", "focusevent", "text", {'style': 'hilite_related_b'}],
28 | ["rOuter", "focusevent", "text", {'style': 'hilite_related_outer'}],
29 | ], {
30 | 'checked': true,
31 | 'header-background': "#c0ffff"
32 | }],
33 |
34 | // FocusEvent - Handler
35 | ["Handler", "handler", [
36 | ["hA", "handler", "text", {'style': 'hilite_handler_a'}],
37 | ["hB", "handler", "text", {'style': 'hilite_handler_b'}],
38 | ["hOuter", "handler", "text", {'style': 'hilite_handler_outer'}],
39 | ], {
40 | 'checked': true,
41 | 'header-background': "#c0c0ff"
42 | }],
43 | ];
44 |
45 | var _focus_event_info = [
46 | ["blur", {
47 | 'preventDefault': {'checked': false},
48 | 'stopPropagation': {'checked': false},
49 | 'ShowEvents': {},
50 | 'Highlight': {'checked': true},
51 | },
52 | "#ffa0a0"],
53 | ["focus", {
54 | 'preventDefault': {'checked': false},
55 | 'stopPropagation': {'checked': false},
56 | 'ShowEvents': {},
57 | 'Highlight': {'checked': true},
58 | },
59 | "#a0ffa0"],
60 | ["focusin", {
61 | 'preventDefault': {'checked': false},
62 | 'stopPropagation': {'checked': false},
63 | 'ShowEvents': {},
64 | 'Highlight': {'checked': false},
65 | },
66 | "#ccffcc"],
67 | ["focusout", {
68 | 'preventDefault': {'checked': false},
69 | 'stopPropagation': {'checked': false},
70 | 'ShowEvents': {},
71 | 'Highlight': {'checked': false},
72 | },
73 | "#ffcccc"],
74 | ["DOMFocusIn", {
75 | 'preventDefault': {'checked': false},
76 | 'stopPropagation': {'checked': false},
77 | 'ShowEvents': {},
78 | 'Highlight': {'checked': false},
79 | },
80 | "repeating-linear-gradient(-45deg, #cfc, #cfc 8px, #fff 8px, #fff 16px)"],
81 | ["DOMFocusOut", {
82 | 'preventDefault': {'checked': false},
83 | 'stopPropagation': {'checked': false},
84 | 'ShowEvents': {},
85 | 'Highlight': {'checked': false},
86 | },
87 | "repeating-linear-gradient(-45deg, #fcc, #fcc 8px, #fff 8px, #fff 16px)"],
88 | ];
89 |
90 |
91 | function setUserAgentText() {
92 | var userAgent = navigator.userAgent;
93 | uaDiv = document.getElementById("useragent");
94 | setText(uaDiv, userAgent);
95 | }
96 |
97 | function resetTable(resetData=true) {
98 | // Reset focus first so the we clear out the events related to it.
99 | setInputFocus(resetData);
100 |
101 | clearTable();
102 | initOutputTable(_focus_table_info);
103 | }
104 |
105 | function init() {
106 | setUserAgentText();
107 |
108 | createOptions(document.getElementById("options"), _focus_event_info, _focus_table_info, []);
109 | injectCustomCSS(_focus_event_info, _focus_table_info);
110 | resetTable(false);
111 |
112 | var input_a = document.getElementById("input_a");
113 | var input_b = document.getElementById("input_b");
114 | var outer = document.getElementById("outer");
115 | for (var div of [input_a, input_b, outer]) {
116 | addEventListener(div, "blur", onBlur.bind(null, div));
117 | addEventListener(div, "focus", onFocus.bind(null, div));
118 | addEventListener(div, "focusin", onFocusIn.bind(null, div));
119 | addEventListener(div, "focusout", onFocusOut.bind(null, div));
120 | addEventListener(div, "DOMFocusIn", onDomFocusIn.bind(null, div));
121 | addEventListener(div, "DOMFocusOut", onDomFocusOut.bind(null, div));
122 | }
123 | }
124 |
125 | // =====
126 | // Focus events: blur, focusin, focusout
127 | // =====
128 |
129 | function onBlur(handler, e) {
130 | handleFocusEvent("blur", handler, e);
131 | }
132 |
133 | function onFocus(handler, e) {
134 | handleFocusEvent("focus", handler, e);
135 | }
136 |
137 | function onFocusIn(handler, e) {
138 | handleFocusEvent("focusin", handler, e);
139 | }
140 |
141 | function onFocusOut(handler, e) {
142 | handleFocusEvent("focusout", handler, e);
143 | }
144 |
145 | function onDomFocusIn(handler, e) {
146 | handleFocusEvent("DOMFocusIn", handler, e);
147 | }
148 |
149 | function onDomFocusOut(handler, e) {
150 | handleFocusEvent("DOMFocusOut", handler, e);
151 | }
152 |
153 | function handleFocusEvent(etype, handler, e) {
154 | var show = document.getElementById("show_" + etype);
155 | if (show.checked) {
156 | addFocusEvent(etype, handler, e);
157 | }
158 | handleDefaultPropagation(etype, e);
159 | }
160 |
161 | function addFocusEvent(etype, handler, e) {
162 | if (!e) {
163 | e = window.event;
164 | }
165 | var target = e.target.id;
166 | var relatedTarget = e.relatedTarget ? e.relatedTarget.id : "";
167 | var handler = handler.id;
168 | var eventinfo = {};
169 |
170 | eventinfo["Event type"] = calcHilightString(etype, e.type);
171 |
172 | eventinfo["A"] = (target == "input_a" ? "A" : "");
173 | eventinfo["B"] = (target == "input_b" ? "B" : "");
174 | eventinfo["Outer"] = (target == "outer" ? "Outer" : "");
175 |
176 | eventinfo["rA"] = (relatedTarget == "input_a" ? "A" : "");
177 | eventinfo["rB"] = (relatedTarget == "input_b" ? "B" : "");
178 | eventinfo["rOuter"] = (relatedTarget == "outer" ? "Outer" : "");
179 |
180 | eventinfo["hA"] = (handler == "input_a" ? (handler == target ? "-" : "A") : "");
181 | eventinfo["hB"] = (handler == "input_b" ? (handler == target ? "-" : "B") : "");
182 | eventinfo["hOuter"] = (handler == "outer" ? (handler == target ? "-" : "Outer") : "");
183 |
184 | addEventToOutput(eventinfo);
185 | }
186 |
187 | // =====
188 | // Helper functions
189 | // =====
190 |
191 | /* Set the focus to the input box. */
192 | function setInputFocus(resetData) {
193 | var input = document.getElementById("input_a");
194 |
195 | if (resetData) {
196 | input.value = "";
197 | }
198 |
199 | // Set focus.
200 | input.focus();
201 | }
202 |
--------------------------------------------------------------------------------
/mouse-event-viewer-shared.js:
--------------------------------------------------------------------------------
1 | // Mouse event viewer - shared
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | var _mouse_event_info = [
5 | ["mousedown", {
6 | 'preventDefault': {'checked': false},
7 | 'stopPropagation': {},
8 | 'ShowEvents': {},
9 | 'Highlight': {},
10 | },
11 | "#e0e0e0"],
12 | ["mouseenter", {
13 | 'preventDefault': {'checked': false},
14 | 'stopPropagation': {'enabled': false, 'checked': false},
15 | 'ShowEvents': {},
16 | 'Highlight': {},
17 | },
18 | "#ccffcc"],
19 | ["mouseleave", {
20 | 'preventDefault': {'checked': false},
21 | 'stopPropagation': {'enabled': false, 'checked': false},
22 | 'ShowEvents': {},
23 | 'Highlight': {},
24 | },
25 | "#ffcccc"],
26 | ["mousemove", {
27 | 'preventDefault': {'checked': false},
28 | 'stopPropagation': {},
29 | 'ShowEvents': {},
30 | 'Highlight': {'checked': false},
31 | },
32 | "#ffffff"],
33 | ["mouseout", {
34 | 'preventDefault': {'checked': false},
35 | 'stopPropagation': {},
36 | 'ShowEvents': {},
37 | 'Highlight': {'checked': false},
38 | },
39 | "repeating-linear-gradient(-45deg, #fcc, #fcc 8px, #fff 8px, #fff 16px)"],
40 | ["mouseover", {
41 | 'preventDefault': {'checked': false},
42 | 'stopPropagation': {},
43 | 'ShowEvents': {},
44 | 'Highlight': {'checked': false},
45 | },
46 | "repeating-linear-gradient(-45deg, #cfc, #cfc 8px, #fff 8px, #fff 16px)"],
47 | ["mouseup", {
48 | 'preventDefault': {'checked': false},
49 | 'stopPropagation': {},
50 | 'ShowEvents': {},
51 | 'Highlight': {},
52 | },
53 | "#e0e0e0"],
54 | ["auxclick", {
55 | 'preventDefault': {'checked': false},
56 | 'stopPropagation': {},
57 | 'ShowEvents': {},
58 | 'Highlight': {},
59 | },
60 | "#ccccff"],
61 | ["click", {
62 | 'preventDefault': {'checked': false},
63 | 'stopPropagation': {},
64 | 'ShowEvents': {},
65 | 'Highlight': {},
66 | },
67 | "#ccccff"],
68 | ["dblclick", {
69 | 'preventDefault': {'checked': false},
70 | 'stopPropagation': {},
71 | 'ShowEvents': {},
72 | 'Highlight': {},
73 | },
74 | "#ccccff"],
75 | ["contextmenu", {
76 | 'preventDefault': {'checked': true},
77 | 'stopPropagation': {},
78 | 'ShowEvents': {},
79 | 'Highlight': {},
80 | },
81 | "#ccffff"],
82 | ];
83 |
84 | var _lastMouseMoveTarget = "";
85 | var _mouseMoveCount = 0;
86 |
87 | function setUserAgentText() {
88 | var userAgent = navigator.userAgent;
89 | uaDiv = document.getElementById("useragent");
90 | setText(uaDiv, userAgent);
91 | }
92 |
93 | function resetTable() {
94 | clearTable();
95 | initOutputTable(_mouse_table_info);
96 | }
97 |
98 | function init_shared() {
99 | setUserAgentText();
100 | var extra_options = [
101 | ["checkbox", "combine_mousemove", "Combine mousemove events with same target", {}],
102 | ["text", "Note: Options apply to new events only."],
103 | ["text", "Press 'c' to Clear Table."],
104 | ];
105 | createOptions(document.getElementById("options"), _mouse_event_info, _mouse_table_info, extra_options);
106 | injectCustomCSS(_mouse_event_info, _mouse_table_info);
107 | resetTable();
108 | }
109 |
110 | function onKeyDown(e) {
111 | if (e.code == "KeyC") {
112 | resetTable();
113 | _lastMouseMoveTarget = "";
114 | }
115 | }
116 |
117 | function onContextMenu(handler, e) {
118 | handleMouseEvent("contextmenu", handler, e);
119 | }
120 |
121 | function onMouseDown(handler, e) {
122 | handleMouseEvent("mousedown", handler, e);
123 | }
124 |
125 | function onMouseEnter(handler, e) {
126 | handleMouseEvent("mouseenter", handler, e);
127 | }
128 |
129 | function onMouseLeave(handler, e) {
130 | handleMouseEvent("mouseleave", handler, e);
131 | }
132 |
133 | function onMouseMove(handler, e) {
134 | _mouseMoveCount++;
135 | var saveMouseMoveCount = _mouseMoveCount;
136 |
137 | // Combine duplicate move moves in the same target by removing last one.
138 | var combine = document.getElementById("combine_mousemove");
139 | var show = document.getElementById("show_mousemove");
140 | if (show.checked && combine.checked && _lastMouseMoveTarget == e.target.id)
141 | deleteLastOutputRow();
142 |
143 | handleMouseEvent("mousemove", handler, e);
144 |
145 | _lastMouseMoveTarget = e.target.id;
146 | _mouseMoveCount = saveMouseMoveCount;
147 | }
148 |
149 | function onMouseOut(handler, e) {
150 | handleMouseEvent("mouseout", handler, e);
151 | }
152 |
153 | function onMouseOver(handler, e) {
154 | handleMouseEvent("mouseover", handler, e);
155 | }
156 |
157 | function onMouseUp(handler, e) {
158 | handleMouseEvent("mouseup", handler, e);
159 | }
160 |
161 | function onAuxClick(handler, e) {
162 | handleMouseEvent("auxclick", handler, e);
163 | }
164 |
165 | function onClick(handler, e) {
166 | handleMouseEvent("click", handler, e);
167 | }
168 |
169 | function onDblClick(handler, e) {
170 | handleMouseEvent("dblclick", handler, e);
171 | }
172 |
173 | function handleMouseEvent(etype, handler, e) {
174 | var show = document.getElementById("show_" + etype);
175 | if (show.checked) {
176 | addMouseEvent(etype, handler, e);
177 | }
178 | handleDefaultPropagation(etype, e);
179 |
180 | _lastMouseMoveTarget = "";
181 | _mouseMoveCount = 0;
182 | }
183 |
184 | function addMouseEvent(etype, handler, e) {
185 | if (!e) {
186 | e = window.event;
187 | }
188 | var target = e.target.id;
189 | var relatedTarget = e.relatedTarget ? e.relatedTarget.id : "";
190 | var handler = handler.id;
191 | var eventinfo = {};
192 | eventinfo["Event type"] = calcHilightString(etype, e.type, true);
193 | eventinfo["Count"] = (etype == "mousemove" ? _mouseMoveCount : "");
194 |
195 | eventinfo["A"] = (target == "div_a" ? "A" : "");
196 | eventinfo["B"] = (target == "div_b" ? "B" : "");
197 | eventinfo["C"] = (target == "div_c" ? "C" : "");
198 | eventinfo["sD"] = (target == "div_d" ? "sD" : "");
199 | eventinfo["sE"] = (target == "div_e" ? "sE" : "");
200 |
201 | eventinfo["rA"] = (relatedTarget == "div_a" ? "A" : "");
202 | eventinfo["rB"] = (relatedTarget == "div_b" ? "B" : "");
203 | eventinfo["rC"] = (relatedTarget == "div_c" ? "C" : "");
204 | eventinfo["srD"] = (relatedTarget == "div_d" ? "sD" : "");
205 | eventinfo["srE"] = (relatedTarget == "div_e" ? "sE" : "");
206 |
207 | eventinfo["hA"] = (handler == "div_a" ? (handler == target ? "-" : "A") : "");
208 | eventinfo["hB"] = (handler == "div_b" ? (handler == target ? "-" : "B") : "");
209 | eventinfo["hC"] = (handler == "div_c" ? (handler == target ? "-" : "C") : "");
210 |
211 | eventinfo["eventPhase"] = getEventPhase(e);
212 | eventinfo["bubbles"] = e.bubbles;
213 | eventinfo["cancelable"] = e.cancelable;
214 | eventinfo["defaultPrevented"] = e.defaultPrevented;
215 | eventinfo["composed"] = e.composed;
216 | eventinfo["isTrusted"] = e.isTrusted;
217 | eventinfo["timeStamp"] = e.timeStamp;
218 |
219 | eventinfo["view"] = calcString(e.view !== null ? e.view.name : "null");
220 | eventinfo["detail"] = e.detail;
221 |
222 | eventinfo["screenX"] = e.screenX;
223 | eventinfo["screenY"] = e.screenY;
224 | eventinfo["clientX"] = e.clientX;
225 | eventinfo["clientY"] = e.clientY;
226 |
227 | eventinfo["movementX"] = e.movementX;
228 | eventinfo["movementY"] = e.movementY;
229 |
230 | eventinfo["offsetX"] = e.offsetX;
231 | eventinfo["offsetY"] = e.offsetY;
232 | eventinfo["pageX"] = e.pageX;
233 | eventinfo["pageY"] = e.pageY;
234 | eventinfo["x"] = e.x;
235 | eventinfo["y"] = e.y;
236 |
237 | var button = "-";
238 | if (etype == "mousedown" || etype == "mouseup") {
239 | button = e.button;
240 | }
241 | eventinfo["button"] = button;
242 | eventinfo["buttons"] = e.buttons;
243 |
244 | eventinfo["getModifierState"] = getModifierState(e);
245 | eventinfo["shift"] = e.shiftKey;
246 | eventinfo["ctrl"] = e.ctrlKey;
247 | eventinfo["alt"] = e.altKey;
248 | eventinfo["meta"] = e.metaKey;
249 |
250 | addEventToOutput(eventinfo);
251 | }
252 |
--------------------------------------------------------------------------------
/key-event-viewer.js:
--------------------------------------------------------------------------------
1 | // Keyboard event viewer
2 | // Gary Kacmarcik - garykac@{gmail|google}.com
3 |
4 | var _key_table_info = [
5 | // Unlabeled group
6 | ["", "etype", [
7 | ["#", "etype", "text"],
8 | ["Event type", "etype", "html"],
9 | ], {
10 | 'grouplabel': false,
11 | 'header-background': "#e0e0e0"
12 | }],
13 |
14 | // KeyboardEvent - Legacy
15 | ["Legacy", "legacy", [
16 | ["charCode", "legacy", "html"],
17 | ["keyCode", "legacy", "html"],
18 | ["which", "legacy", "text"],
19 | ], {
20 | 'checked': true,
21 | 'header-background': "#c0ffc0"
22 | }],
23 |
24 | // KeyboardEvent - Modifiers
25 | ["Modifiers", "modifiers", [
26 | ["getModifierState", "modifiers", "text"],
27 | ["shift", "modifiers", "bool"],
28 | ["ctrl", "modifiers", "bool"],
29 | ["alt", "modifiers", "bool"],
30 | ["meta", "modifiers", "bool"],
31 | ], {
32 | 'checked': true,
33 | 'header-background': "#ffc0ff"
34 | }],
35 |
36 | // KeyboardEvent - Old DOM3
37 | ["Old DOM3", "olddom3", [
38 | ["keyIdentifier", "olddom3", "text"],
39 | ["keyLocation", "olddom3", "text"],
40 | ["char", "olddom3", "text"],
41 | ], {
42 | 'checked': false,
43 | 'header-background': "#ffc0c0"
44 | }],
45 |
46 | // KeyboardEvent - UI Events
47 | ["UI Events", "uievents", [
48 | ["key", "uievents", "html"],
49 | ["code", "uievents", "text"],
50 | ["location", "uievents", "text"],
51 | ["repeat", "uievents", "bool"],
52 | ["isComposing", "uievents", "bool"],
53 | ["inputType", "uievents", "text"],
54 | ["data", "uievents", "text"],
55 | ], {
56 | 'checked': true,
57 | 'header-background': "#c0ffff"
58 | }],
59 |
60 | // KeyboardEvent - Proposed
61 | ["Proposed", "proposed", [
62 | ["locale", "proposed", "text"],
63 | ], {
64 | 'checked': false,
65 | 'header-background': "#ffffc0"
66 | }],
67 |
68 | // Input
69 | ["Input", "inputbox", [
70 | ["Input field", "inputbox", "text", {'align': 'left'}],
71 | ], {
72 | 'checked': true,
73 | 'grouplabel': false,
74 | 'header-background': "#e0e0e0"
75 | }],
76 | ];
77 |
78 | var _key_event_info = [
79 | ["keydown", {
80 | 'preventDefault': {'checked': false},
81 | 'stopPropagation': {},
82 | 'ShowEvents': {},
83 | 'Highlight': {'class': "keydown_arrow"},
84 | },
85 | "#c0ffc0"],
86 | ["keypress", {
87 | 'preventDefault': {'checked': false},
88 | 'stopPropagation': {},
89 | 'ShowEvents': {},
90 | 'Highlight': {'checked': false},
91 | },
92 | "#c0c0ff"],
93 | ["keyup", {
94 | 'preventDefault': {'checked': false},
95 | 'stopPropagation': {},
96 | 'ShowEvents': {},
97 | 'Highlight': {'class': "keyup_arrow"},
98 | },
99 | "#ffc0c0"],
100 | ["textinput", {
101 | 'preventDefault': {'checked': false},
102 | 'stopPropagation': {'checked': false},
103 | 'ShowEvents': {'checked': false},
104 | 'Highlight': {'enabled': false, 'checked': false},
105 | },
106 | ""],
107 | ["beforeinput", {
108 | 'preventDefault': {'checked': false},
109 | 'stopPropagation': {},
110 | 'ShowEvents': {},
111 | 'Highlight': {'enabled': false, 'checked': false},
112 | },
113 | "repeating-linear-gradient(-45deg, #fcc, #fcc 8px, #fff 8px, #fff 16px)"],
114 | ["input", {
115 | 'preventDefault': {'checked': false},
116 | 'stopPropagation': {},
117 | 'ShowEvents': {},
118 | 'Highlight': {'enabled': false, 'checked': false},
119 | },
120 | "repeating-linear-gradient(-45deg, #cfc, #cfc 8px, #fff 8px, #fff 16px)"],
121 | ["compositionstart", {
122 | 'preventDefault': {'checked': false},
123 | 'stopPropagation': {},
124 | 'ShowEvents': {},
125 | 'Highlight': {'enabled': false, 'checked': false},
126 | },
127 | "#e0e0e0"],
128 | ["compositionupdate", {
129 | 'preventDefault': {'checked': false},
130 | 'stopPropagation': {},
131 | 'ShowEvents': {},
132 | 'Highlight': {'enabled': false, 'checked': false},
133 | },
134 | "#e0e0e0"],
135 | ["compositionend", {
136 | 'preventDefault': {'checked': false},
137 | 'stopPropagation': {},
138 | 'ShowEvents': {},
139 | 'Highlight': {'enabled': false, 'checked': false},
140 | },
141 | "#e0e0e0"],
142 | ];
143 |
144 |
145 | // True if the current row is a 'keydown' event.
146 | // This is used to set the background for the entire row when 'keydown' events are
147 | // highlighted.
148 | var _isKeydown = false;
149 |
150 | function setUserAgentText() {
151 | var userAgent = navigator.userAgent;
152 | uaDiv = document.getElementById("useragent");
153 | setText(uaDiv, userAgent);
154 | }
155 |
156 | function resetTable(resetData=true) {
157 | clearTable();
158 | initOutputTable(_key_table_info);
159 |
160 | setInputFocus(resetData);
161 | }
162 |
163 | var _inFullscreen = false;
164 |
165 | function toggleFullscreen() {
166 | var button = document.getElementById("toggleFullscreen");
167 | if (_inFullscreen) {
168 | document.exitFullscreen();
169 | _inFullscreen = false;
170 | button.value = "Enter Fullscreen"
171 | } else {
172 | document.body.requestFullscreen();
173 | _inFullscreen = true;
174 | button.value = "Exit Fullscreen"
175 | }
176 | }
177 |
178 | var _isKeyboardLock = false;
179 |
180 | function toggleKeyboardLock() {
181 | var button = document.getElementById("toggleKeyboardLock");
182 | if (_isKeyboardLock) {
183 | navigator.keyboard.unlock();
184 | _isKeyboardLock = false;
185 | button.value = "Enable KeyboardLock"
186 | } else {
187 | navigator.keyboard.lock();
188 | _isKeyboardLock = true;
189 | button.value = "Disable KeyboardLock"
190 | }
191 | }
192 |
193 | function init() {
194 | setUserAgentText();
195 | var extra_options = [
196 | ["checkbox", "readonlyToggle", "Read only ", {
197 | 'onclick': "updateReadonly()",
198 | 'checked': false,
199 | }],
200 | ["text", "Note: Options apply to new events only."],
201 | ];
202 |
203 | var isContentEditable = false;
204 | var el = document.getElementById("input");
205 | if (el.tagName == "DIV") {
206 | isContentEditable = true;
207 | }
208 |
209 | // Remove read-only option for contenteditable.
210 | if (isContentEditable) {
211 | extra_options.shift();
212 | }
213 |
214 | createOptions(document.getElementById("options"), _key_event_info, _key_table_info, extra_options);
215 | injectCustomCSS(_key_event_info, _key_table_info);
216 | if (!isContentEditable) {
217 | updateReadonly();
218 | }
219 | resetTable(false);
220 |
221 | var input = document.getElementById("input");
222 | addEventListener(input, "keydown", onKeyDown);
223 | addEventListener(input, "keypress", onKeyPress);
224 | addEventListener(input, "keyup", onKeyUp);
225 | addEventListener(input, "textInput", onTextInput);
226 | addEventListener(input, "textinput", onTextInput); // For IE9
227 | addEventListener(input, "beforeinput", onBeforeInput);
228 | addEventListener(input, "input", onInput);
229 | addEventListener(input, "compositionstart", onCompositionStart);
230 | addEventListener(input, "compositionupdate", onCompositionUpdate);
231 | addEventListener(input, "compositionend", onCompositionEnd);
232 | }
233 |
234 | // =====
235 | // Key events: keydown, keypress, keyup
236 | // =====
237 |
238 | function onKeyDown(e) {
239 | _isKeydown = true;
240 | handleKeyEvent("keydown", e);
241 | _isKeydown = false;
242 | }
243 |
244 | function onKeyPress(e) {
245 | handleKeyEvent("keypress", e);
246 | }
247 |
248 | function onKeyUp(e) {
249 | handleKeyEvent("keyup", e);
250 | }
251 |
252 | function handleKeyEvent(etype, e) {
253 | var show = document.getElementById("show_" + etype);
254 | if (show.checked) {
255 | addKeyEvent(etype, e);
256 | }
257 | handleDefaultPropagation(etype, e);
258 | }
259 |
260 | function addKeyEvent(etype, e) {
261 | if (!e) {
262 | e = window.event;
263 | }
264 | var eventinfo = {};
265 | eventinfo["Event type"] = calcHilightString(etype, e.type, true);
266 | eventinfo["charCode"] = calcRichKeyVal(etype, "charCode", e.charCode);
267 | eventinfo["keyCode"] = calcRichKeyVal(etype, "keyCode", e.keyCode);
268 | eventinfo["which"] = e.which;
269 | eventinfo["getModifierState"] = getModifierState(e);
270 | eventinfo["shift"] = e.shiftKey;
271 | eventinfo["ctrl"] = e.ctrlKey;
272 | eventinfo["alt"] = e.altKey;
273 | eventinfo["meta"] = e.metaKey;
274 | eventinfo["keyIdentifier"] = e.keyIdentifier;
275 | eventinfo["keyLocation"] = calcLocation(e.keyLocation);
276 | eventinfo["char"] = calcString(e.char);
277 | eventinfo["key"] = calcHilightString(etype, e.key, false);
278 | eventinfo["code"] = e.code;
279 | eventinfo["location"] = calcLocation(e.location);
280 | eventinfo["repeat"] = e.repeat;
281 | eventinfo["isComposing"] = e.isComposing;
282 | eventinfo["Input field"] = calcInput();
283 |
284 | extra_class = undefined;
285 | if (_isKeydown && document.getElementById("hl_keydown").checked) {
286 | extra_class = "keydown_row_hilight";
287 | }
288 | addEventToOutput(eventinfo, extra_class);
289 | }
290 |
291 | // =====
292 | // Input events: textinput, beforeinput, input
293 | // =====
294 |
295 | function onTextInput(e) {
296 | handleInputEvent("textinput", e);
297 | }
298 |
299 | function onBeforeInput(e) {
300 | handleInputEvent("beforeinput", e);
301 | }
302 |
303 | function onInput(e) {
304 | handleInputEvent("input", e);
305 | }
306 |
307 | function handleInputEvent(etype, e) {
308 | var show = document.getElementById("show_" + etype);
309 | if (show.checked) {
310 | addInputEvent(etype, e);
311 | }
312 | handleDefaultPropagation(etype, e);
313 | }
314 |
315 | function addInputEvent(etype, e) {
316 | if (!e) {
317 | e = window.event;
318 | }
319 | var eventinfo = {};
320 | eventinfo["Event type"] = calcHilightString(etype, e.type, true);
321 | eventinfo["isComposing"] = e.isComposing;
322 | eventinfo["inputType"] = e.inputType;
323 | eventinfo["data"] = calcString(e.data);
324 | eventinfo["Input field"] = calcInput();
325 | addEventToOutput(eventinfo);
326 | }
327 |
328 | // =====
329 | // Composition events: compositionstart, compositionupdate, compositionend
330 | // =====
331 |
332 | function onCompositionStart(e) {
333 | handleCompositionEvent("compositionstart", e);
334 | }
335 |
336 | function onCompositionUpdate(e) {
337 | handleCompositionEvent("compositionupdate", e);
338 | }
339 |
340 | function onCompositionEnd(e) {
341 | handleCompositionEvent("compositionend", e);
342 | }
343 |
344 | function handleCompositionEvent(etype, e) {
345 | var show = document.getElementById("show_"+etype);
346 | if (show.checked) {
347 | addCompositionEvent(etype, e);
348 | }
349 | handleDefaultPropagation(etype, e);
350 | }
351 |
352 | function addCompositionEvent(etype, e) {
353 | if (!e) {
354 | e = window.event;
355 | }
356 | var eventinfo = {};
357 | eventinfo["Event type"] = calcHilightString(etype, e.type, true);
358 | eventinfo["isComposing"] = e.isComposing;
359 | eventinfo["data"] = calcString(e.data);
360 | eventinfo["Input field"] = calcInput();
361 | addEventToOutput(eventinfo);
362 | }
363 |
364 | // =====
365 | // Helper functions
366 | // =====
367 |
368 | function calcInput() {
369 | var el = document.getElementById("input");
370 | var value = "";
371 | if (el.tagName == "DIV") {
372 | //