@remote-dom/polyfill 1.4.6 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/build/cjs/ClipboardEvent.cjs +15 -0
- package/build/cjs/FocusEvent.cjs +15 -0
- package/build/cjs/ToggleEvent.cjs +16 -0
- package/build/cjs/Window.cjs +6 -0
- package/build/cjs/selectors.cjs +48 -13
- package/build/esm/ClipboardEvent.mjs +11 -0
- package/build/esm/FocusEvent.mjs +11 -0
- package/build/esm/ToggleEvent.mjs +12 -0
- package/build/esm/Window.mjs +6 -0
- package/build/esm/selectors.mjs +48 -13
- package/build/esnext/ClipboardEvent.esnext +11 -0
- package/build/esnext/FocusEvent.esnext +11 -0
- package/build/esnext/ToggleEvent.esnext +13 -0
- package/build/esnext/Window.esnext +6 -0
- package/build/esnext/selectors.esnext +43 -13
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/ClipboardEvent.d.ts +6 -0
- package/build/typescript/ClipboardEvent.d.ts.map +1 -0
- package/build/typescript/FocusEvent.d.ts +6 -0
- package/build/typescript/FocusEvent.d.ts.map +1 -0
- package/build/typescript/ToggleEvent.d.ts +7 -0
- package/build/typescript/ToggleEvent.d.ts.map +1 -0
- package/build/typescript/Window.d.ts +6 -0
- package/build/typescript/Window.d.ts.map +1 -1
- package/build/typescript/selectors.d.ts.map +1 -1
- package/build/typescript/tests/selectors.test.d.ts +2 -0
- package/build/typescript/tests/selectors.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/source/ClipboardEvent.ts +12 -0
- package/source/FocusEvent.ts +12 -0
- package/source/ToggleEvent.ts +14 -0
- package/source/Window.ts +6 -0
- package/source/selectors.ts +52 -13
- package/source/tests/selectors.test.ts +280 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @remote-dom/polyfill
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#593](https://github.com/Shopify/remote-dom/pull/593) [`61f5cba`](https://github.com/Shopify/remote-dom/commit/61f5cbaa9965f7befbea3d3dfc2d2b2a0798c958) Thanks [@developit](https://github.com/developit)! - Add support for `not` in query-selectors
|
|
8
|
+
|
|
9
|
+
## 1.4.7
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#594](https://github.com/Shopify/remote-dom/pull/594) [`789a7c7`](https://github.com/Shopify/remote-dom/commit/789a7c7480a445d1e5973bd6e2aa4e8889ec6f85) Thanks [@robin-drexler](https://github.com/robin-drexler)! - add `FocusEvent`, `ClipboardEvent` and `ToggleEvent` to polyfill
|
|
14
|
+
|
|
3
15
|
## 1.4.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const Event = require('./Event.cjs');
|
|
6
|
+
|
|
7
|
+
// https://w3c.github.io/clipboard-apis/#clipboardevent-interface
|
|
8
|
+
class ClipboardEvent extends Event.Event {
|
|
9
|
+
constructor(type, eventInitDict = {}) {
|
|
10
|
+
super(type, eventInitDict);
|
|
11
|
+
this.clipboardData = eventInitDict.clipboardData ?? null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exports.ClipboardEvent = ClipboardEvent;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const Event = require('./Event.cjs');
|
|
6
|
+
|
|
7
|
+
// https://w3c.github.io/uievents/#interface-focusevent
|
|
8
|
+
class FocusEvent extends Event.Event {
|
|
9
|
+
constructor(type, eventInitDict = {}) {
|
|
10
|
+
super(type, eventInitDict);
|
|
11
|
+
this.relatedTarget = eventInitDict.relatedTarget ?? null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exports.FocusEvent = FocusEvent;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const Event = require('./Event.cjs');
|
|
6
|
+
|
|
7
|
+
// https://html.spec.whatwg.org/multipage/popover.html#toggleevent
|
|
8
|
+
class ToggleEvent extends Event.Event {
|
|
9
|
+
constructor(type, eventInitDict) {
|
|
10
|
+
super(type, eventInitDict);
|
|
11
|
+
this.oldState = eventInitDict.oldState;
|
|
12
|
+
this.newState = eventInitDict.newState;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.ToggleEvent = ToggleEvent;
|
package/build/cjs/Window.cjs
CHANGED
|
@@ -8,6 +8,9 @@ const EventTarget = require('./EventTarget.cjs');
|
|
|
8
8
|
const CustomEvent = require('./CustomEvent.cjs');
|
|
9
9
|
const ErrorEvent = require('./ErrorEvent.cjs');
|
|
10
10
|
const PromiseRejectionEvent = require('./PromiseRejectionEvent.cjs');
|
|
11
|
+
const ToggleEvent = require('./ToggleEvent.cjs');
|
|
12
|
+
const FocusEvent = require('./FocusEvent.cjs');
|
|
13
|
+
const ClipboardEvent = require('./ClipboardEvent.cjs');
|
|
11
14
|
const Node = require('./Node.cjs');
|
|
12
15
|
const ParentNode = require('./ParentNode.cjs');
|
|
13
16
|
const ChildNode = require('./ChildNode.cjs');
|
|
@@ -37,6 +40,9 @@ class Window extends EventTarget.EventTarget {
|
|
|
37
40
|
Event = (() => Event.Event)();
|
|
38
41
|
ErrorEvent = (() => ErrorEvent.ErrorEvent)();
|
|
39
42
|
PromiseRejectionEvent = (() => PromiseRejectionEvent.PromiseRejectionEvent)();
|
|
43
|
+
ToggleEvent = (() => ToggleEvent.ToggleEvent)();
|
|
44
|
+
FocusEvent = (() => FocusEvent.FocusEvent)();
|
|
45
|
+
ClipboardEvent = (() => ClipboardEvent.ClipboardEvent)();
|
|
40
46
|
EventTarget = (() => EventTarget.EventTarget)();
|
|
41
47
|
CustomEvent = (() => CustomEvent.CustomEvent)();
|
|
42
48
|
Node = (() => Node.Node)();
|
package/build/cjs/selectors.cjs
CHANGED
|
@@ -53,7 +53,7 @@ function parseSelector(selector) {
|
|
|
53
53
|
matchers: []
|
|
54
54
|
};
|
|
55
55
|
const parts = [part];
|
|
56
|
-
const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[
|
|
56
|
+
const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[>:+~]+)|:(\w+)(?:\((.*?)\))?)/gi;
|
|
57
57
|
let token;
|
|
58
58
|
while (token = tokenizer.exec(selector)) {
|
|
59
59
|
// [1]: ancestor/parent/sibling/adjacent
|
|
@@ -80,8 +80,12 @@ function parseSelector(selector) {
|
|
|
80
80
|
type = token[5] === '#' ? MatcherType.Id : MatcherType.Class;
|
|
81
81
|
} else if (token[7]) {
|
|
82
82
|
type = token[8] == null ? MatcherType.Pseudo : MatcherType.Function;
|
|
83
|
-
} else if (token[6]
|
|
84
|
-
|
|
83
|
+
} else if (token[6]) {
|
|
84
|
+
if (token[6] === '*') {
|
|
85
|
+
type = MatcherType.Unknown; // Universal selector matches all
|
|
86
|
+
} else if (ELEMENT_SELECTOR_TEST.test(token[6])) {
|
|
87
|
+
type = MatcherType.Element;
|
|
88
|
+
}
|
|
85
89
|
}
|
|
86
90
|
part.matchers.push({
|
|
87
91
|
type,
|
|
@@ -127,19 +131,34 @@ function matchesSelectorRecursive(element, parts) {
|
|
|
127
131
|
}
|
|
128
132
|
const link = combinator === Combinator.Child || combinator === Combinator.Descendant ? constants.PARENT : constants.PREV;
|
|
129
133
|
let ref = element[link];
|
|
130
|
-
if (!ref
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
134
|
+
if (!ref) return false;
|
|
133
135
|
if (combinator === Combinator.Descendant || combinator === Combinator.Sibling) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
// For descendant/sibling combinators, search through all ancestors/siblings
|
|
137
|
+
while (ref) {
|
|
138
|
+
if (shared.isElementNode(ref) && matchesSelectorMatcher(ref, matchers)) {
|
|
136
139
|
const pp = parts.slice(0, -1);
|
|
137
140
|
if (pp.length === 0) return true;
|
|
138
141
|
if (matchesSelectorRecursive(element, pp)) return true;
|
|
139
142
|
}
|
|
143
|
+
ref = ref[link];
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
} else {
|
|
147
|
+
// For child/adjacent combinators, check only the immediate parent/sibling
|
|
148
|
+
// For sibling combinators, skip non-element siblings
|
|
149
|
+
if (combinator === Combinator.Adjacent && !shared.isElementNode(ref)) {
|
|
150
|
+
// Skip to next element sibling
|
|
151
|
+
while (ref && !shared.isElementNode(ref)) {
|
|
152
|
+
ref = ref[link];
|
|
153
|
+
}
|
|
154
|
+
if (!ref) return false;
|
|
155
|
+
}
|
|
156
|
+
if (!shared.isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
|
|
157
|
+
return false;
|
|
140
158
|
}
|
|
159
|
+
const pp = parts.slice(0, -1);
|
|
160
|
+
return pp.length === 0 || matchesSelectorRecursive(element, pp);
|
|
141
161
|
}
|
|
142
|
-
return false;
|
|
143
162
|
}
|
|
144
163
|
function matchesSelectorPart(element, {
|
|
145
164
|
combinator,
|
|
@@ -150,15 +169,24 @@ function matchesSelectorPart(element, {
|
|
|
150
169
|
}
|
|
151
170
|
const link = combinator === Combinator.Child || combinator === Combinator.Descendant ? constants.PARENT : constants.PREV;
|
|
152
171
|
let ref = element[link];
|
|
153
|
-
if (!ref
|
|
172
|
+
if (!ref) return false;
|
|
173
|
+
|
|
174
|
+
// For sibling combinators, skip non-element siblings
|
|
175
|
+
if (combinator === Combinator.Adjacent && !shared.isElementNode(ref)) {
|
|
176
|
+
while (ref && !shared.isElementNode(ref)) {
|
|
177
|
+
ref = ref[link];
|
|
178
|
+
}
|
|
179
|
+
if (!ref) return false;
|
|
180
|
+
}
|
|
181
|
+
if (!shared.isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
|
|
154
182
|
return false;
|
|
155
183
|
}
|
|
156
184
|
if (combinator === Combinator.Descendant || combinator === Combinator.Sibling) {
|
|
157
185
|
while (ref = ref[link]) {
|
|
158
|
-
if (matchesSelectorMatcher(ref, matchers)) return true;
|
|
186
|
+
if (shared.isElementNode(ref) && matchesSelectorMatcher(ref, matchers)) return true;
|
|
159
187
|
}
|
|
160
188
|
}
|
|
161
|
-
return
|
|
189
|
+
return true;
|
|
162
190
|
}
|
|
163
191
|
function matchesSelectorMatcher(element, matcher) {
|
|
164
192
|
if (!element) return false;
|
|
@@ -174,12 +202,17 @@ function matchesSelectorMatcher(element, matcher) {
|
|
|
174
202
|
value
|
|
175
203
|
} = matcher;
|
|
176
204
|
switch (type) {
|
|
205
|
+
case MatcherType.Unknown:
|
|
206
|
+
return name === '*';
|
|
207
|
+
// Universal selector
|
|
177
208
|
case MatcherType.Element:
|
|
178
209
|
return element.localName === name;
|
|
179
210
|
case MatcherType.Id:
|
|
180
211
|
return element.getAttribute('id') === name;
|
|
181
212
|
case MatcherType.Class:
|
|
182
|
-
|
|
213
|
+
const classAttr = element.getAttribute('class');
|
|
214
|
+
if (!classAttr) return false;
|
|
215
|
+
return classAttr.split(/\s+/).includes(name);
|
|
183
216
|
case MatcherType.Attribute:
|
|
184
217
|
return value == null ? element.hasAttribute(name) : element.getAttribute(name) === value;
|
|
185
218
|
case MatcherType.Pseudo:
|
|
@@ -191,6 +224,8 @@ function matchesSelectorMatcher(element, matcher) {
|
|
|
191
224
|
switch (name) {
|
|
192
225
|
case 'has':
|
|
193
226
|
return matchesSelector(element, value || '');
|
|
227
|
+
case 'not':
|
|
228
|
+
return !matchesSelector(element, value || '');
|
|
194
229
|
default:
|
|
195
230
|
throw Error(`Function :${name}(${value}) not implemented`);
|
|
196
231
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Event } from './Event.mjs';
|
|
2
|
+
|
|
3
|
+
// https://w3c.github.io/clipboard-apis/#clipboardevent-interface
|
|
4
|
+
class ClipboardEvent extends Event {
|
|
5
|
+
constructor(type, eventInitDict = {}) {
|
|
6
|
+
super(type, eventInitDict);
|
|
7
|
+
this.clipboardData = eventInitDict.clipboardData ?? null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { ClipboardEvent };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Event } from './Event.mjs';
|
|
2
|
+
|
|
3
|
+
// https://w3c.github.io/uievents/#interface-focusevent
|
|
4
|
+
class FocusEvent extends Event {
|
|
5
|
+
constructor(type, eventInitDict = {}) {
|
|
6
|
+
super(type, eventInitDict);
|
|
7
|
+
this.relatedTarget = eventInitDict.relatedTarget ?? null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { FocusEvent };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Event } from './Event.mjs';
|
|
2
|
+
|
|
3
|
+
// https://html.spec.whatwg.org/multipage/popover.html#toggleevent
|
|
4
|
+
class ToggleEvent extends Event {
|
|
5
|
+
constructor(type, eventInitDict) {
|
|
6
|
+
super(type, eventInitDict);
|
|
7
|
+
this.oldState = eventInitDict.oldState;
|
|
8
|
+
this.newState = eventInitDict.newState;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { ToggleEvent };
|
package/build/esm/Window.mjs
CHANGED
|
@@ -4,6 +4,9 @@ import { EventTarget } from './EventTarget.mjs';
|
|
|
4
4
|
import { CustomEvent } from './CustomEvent.mjs';
|
|
5
5
|
import { ErrorEvent } from './ErrorEvent.mjs';
|
|
6
6
|
import { PromiseRejectionEvent } from './PromiseRejectionEvent.mjs';
|
|
7
|
+
import { ToggleEvent } from './ToggleEvent.mjs';
|
|
8
|
+
import { FocusEvent } from './FocusEvent.mjs';
|
|
9
|
+
import { ClipboardEvent } from './ClipboardEvent.mjs';
|
|
7
10
|
import { Node } from './Node.mjs';
|
|
8
11
|
import { ParentNode } from './ParentNode.mjs';
|
|
9
12
|
import { ChildNode } from './ChildNode.mjs';
|
|
@@ -33,6 +36,9 @@ class Window extends EventTarget {
|
|
|
33
36
|
Event = (() => Event)();
|
|
34
37
|
ErrorEvent = (() => ErrorEvent)();
|
|
35
38
|
PromiseRejectionEvent = (() => PromiseRejectionEvent)();
|
|
39
|
+
ToggleEvent = (() => ToggleEvent)();
|
|
40
|
+
FocusEvent = (() => FocusEvent)();
|
|
41
|
+
ClipboardEvent = (() => ClipboardEvent)();
|
|
36
42
|
EventTarget = (() => EventTarget)();
|
|
37
43
|
CustomEvent = (() => CustomEvent)();
|
|
38
44
|
Node = (() => Node)();
|
package/build/esm/selectors.mjs
CHANGED
|
@@ -49,7 +49,7 @@ function parseSelector(selector) {
|
|
|
49
49
|
matchers: []
|
|
50
50
|
};
|
|
51
51
|
const parts = [part];
|
|
52
|
-
const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[
|
|
52
|
+
const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[>:+~]+)|:(\w+)(?:\((.*?)\))?)/gi;
|
|
53
53
|
let token;
|
|
54
54
|
while (token = tokenizer.exec(selector)) {
|
|
55
55
|
// [1]: ancestor/parent/sibling/adjacent
|
|
@@ -76,8 +76,12 @@ function parseSelector(selector) {
|
|
|
76
76
|
type = token[5] === '#' ? MatcherType.Id : MatcherType.Class;
|
|
77
77
|
} else if (token[7]) {
|
|
78
78
|
type = token[8] == null ? MatcherType.Pseudo : MatcherType.Function;
|
|
79
|
-
} else if (token[6]
|
|
80
|
-
|
|
79
|
+
} else if (token[6]) {
|
|
80
|
+
if (token[6] === '*') {
|
|
81
|
+
type = MatcherType.Unknown; // Universal selector matches all
|
|
82
|
+
} else if (ELEMENT_SELECTOR_TEST.test(token[6])) {
|
|
83
|
+
type = MatcherType.Element;
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
part.matchers.push({
|
|
83
87
|
type,
|
|
@@ -123,19 +127,34 @@ function matchesSelectorRecursive(element, parts) {
|
|
|
123
127
|
}
|
|
124
128
|
const link = combinator === Combinator.Child || combinator === Combinator.Descendant ? PARENT : PREV;
|
|
125
129
|
let ref = element[link];
|
|
126
|
-
if (!ref
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
130
|
+
if (!ref) return false;
|
|
129
131
|
if (combinator === Combinator.Descendant || combinator === Combinator.Sibling) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
// For descendant/sibling combinators, search through all ancestors/siblings
|
|
133
|
+
while (ref) {
|
|
134
|
+
if (isElementNode(ref) && matchesSelectorMatcher(ref, matchers)) {
|
|
132
135
|
const pp = parts.slice(0, -1);
|
|
133
136
|
if (pp.length === 0) return true;
|
|
134
137
|
if (matchesSelectorRecursive(element, pp)) return true;
|
|
135
138
|
}
|
|
139
|
+
ref = ref[link];
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
} else {
|
|
143
|
+
// For child/adjacent combinators, check only the immediate parent/sibling
|
|
144
|
+
// For sibling combinators, skip non-element siblings
|
|
145
|
+
if (combinator === Combinator.Adjacent && !isElementNode(ref)) {
|
|
146
|
+
// Skip to next element sibling
|
|
147
|
+
while (ref && !isElementNode(ref)) {
|
|
148
|
+
ref = ref[link];
|
|
149
|
+
}
|
|
150
|
+
if (!ref) return false;
|
|
151
|
+
}
|
|
152
|
+
if (!isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
|
|
153
|
+
return false;
|
|
136
154
|
}
|
|
155
|
+
const pp = parts.slice(0, -1);
|
|
156
|
+
return pp.length === 0 || matchesSelectorRecursive(element, pp);
|
|
137
157
|
}
|
|
138
|
-
return false;
|
|
139
158
|
}
|
|
140
159
|
function matchesSelectorPart(element, {
|
|
141
160
|
combinator,
|
|
@@ -146,15 +165,24 @@ function matchesSelectorPart(element, {
|
|
|
146
165
|
}
|
|
147
166
|
const link = combinator === Combinator.Child || combinator === Combinator.Descendant ? PARENT : PREV;
|
|
148
167
|
let ref = element[link];
|
|
149
|
-
if (!ref
|
|
168
|
+
if (!ref) return false;
|
|
169
|
+
|
|
170
|
+
// For sibling combinators, skip non-element siblings
|
|
171
|
+
if (combinator === Combinator.Adjacent && !isElementNode(ref)) {
|
|
172
|
+
while (ref && !isElementNode(ref)) {
|
|
173
|
+
ref = ref[link];
|
|
174
|
+
}
|
|
175
|
+
if (!ref) return false;
|
|
176
|
+
}
|
|
177
|
+
if (!isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
|
|
150
178
|
return false;
|
|
151
179
|
}
|
|
152
180
|
if (combinator === Combinator.Descendant || combinator === Combinator.Sibling) {
|
|
153
181
|
while (ref = ref[link]) {
|
|
154
|
-
if (matchesSelectorMatcher(ref, matchers)) return true;
|
|
182
|
+
if (isElementNode(ref) && matchesSelectorMatcher(ref, matchers)) return true;
|
|
155
183
|
}
|
|
156
184
|
}
|
|
157
|
-
return
|
|
185
|
+
return true;
|
|
158
186
|
}
|
|
159
187
|
function matchesSelectorMatcher(element, matcher) {
|
|
160
188
|
if (!element) return false;
|
|
@@ -170,12 +198,17 @@ function matchesSelectorMatcher(element, matcher) {
|
|
|
170
198
|
value
|
|
171
199
|
} = matcher;
|
|
172
200
|
switch (type) {
|
|
201
|
+
case MatcherType.Unknown:
|
|
202
|
+
return name === '*';
|
|
203
|
+
// Universal selector
|
|
173
204
|
case MatcherType.Element:
|
|
174
205
|
return element.localName === name;
|
|
175
206
|
case MatcherType.Id:
|
|
176
207
|
return element.getAttribute('id') === name;
|
|
177
208
|
case MatcherType.Class:
|
|
178
|
-
|
|
209
|
+
const classAttr = element.getAttribute('class');
|
|
210
|
+
if (!classAttr) return false;
|
|
211
|
+
return classAttr.split(/\s+/).includes(name);
|
|
179
212
|
case MatcherType.Attribute:
|
|
180
213
|
return value == null ? element.hasAttribute(name) : element.getAttribute(name) === value;
|
|
181
214
|
case MatcherType.Pseudo:
|
|
@@ -187,6 +220,8 @@ function matchesSelectorMatcher(element, matcher) {
|
|
|
187
220
|
switch (name) {
|
|
188
221
|
case 'has':
|
|
189
222
|
return matchesSelector(element, value || '');
|
|
223
|
+
case 'not':
|
|
224
|
+
return !matchesSelector(element, value || '');
|
|
190
225
|
default:
|
|
191
226
|
throw Error(`Function :${name}(${value}) not implemented`);
|
|
192
227
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Event } from './Event.esnext';
|
|
2
|
+
|
|
3
|
+
class ClipboardEvent extends Event {
|
|
4
|
+
clipboardData;
|
|
5
|
+
constructor(type, eventInitDict = {}) {
|
|
6
|
+
super(type, eventInitDict);
|
|
7
|
+
this.clipboardData = eventInitDict.clipboardData ?? null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { ClipboardEvent };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Event } from './Event.esnext';
|
|
2
|
+
|
|
3
|
+
class FocusEvent extends Event {
|
|
4
|
+
relatedTarget;
|
|
5
|
+
constructor(type, eventInitDict = {}) {
|
|
6
|
+
super(type, eventInitDict);
|
|
7
|
+
this.relatedTarget = eventInitDict.relatedTarget ?? null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { FocusEvent };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Event } from './Event.esnext';
|
|
2
|
+
|
|
3
|
+
class ToggleEvent extends Event {
|
|
4
|
+
oldState;
|
|
5
|
+
newState;
|
|
6
|
+
constructor(type, eventInitDict) {
|
|
7
|
+
super(type, eventInitDict);
|
|
8
|
+
this.oldState = eventInitDict.oldState;
|
|
9
|
+
this.newState = eventInitDict.newState;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { ToggleEvent };
|
|
@@ -4,6 +4,9 @@ import { EventTarget } from './EventTarget.esnext';
|
|
|
4
4
|
import { CustomEvent } from './CustomEvent.esnext';
|
|
5
5
|
import { ErrorEvent } from './ErrorEvent.esnext';
|
|
6
6
|
import { PromiseRejectionEvent } from './PromiseRejectionEvent.esnext';
|
|
7
|
+
import { ToggleEvent } from './ToggleEvent.esnext';
|
|
8
|
+
import { FocusEvent } from './FocusEvent.esnext';
|
|
9
|
+
import { ClipboardEvent } from './ClipboardEvent.esnext';
|
|
7
10
|
import { Node } from './Node.esnext';
|
|
8
11
|
import { ParentNode } from './ParentNode.esnext';
|
|
9
12
|
import { ChildNode } from './ChildNode.esnext';
|
|
@@ -33,6 +36,9 @@ class Window extends EventTarget {
|
|
|
33
36
|
Event = Event;
|
|
34
37
|
ErrorEvent = ErrorEvent;
|
|
35
38
|
PromiseRejectionEvent = PromiseRejectionEvent;
|
|
39
|
+
ToggleEvent = ToggleEvent;
|
|
40
|
+
FocusEvent = FocusEvent;
|
|
41
|
+
ClipboardEvent = ClipboardEvent;
|
|
36
42
|
EventTarget = EventTarget;
|
|
37
43
|
CustomEvent = CustomEvent;
|
|
38
44
|
Node = Node;
|
|
@@ -28,7 +28,7 @@ function querySelectorAll(within, selector) {
|
|
|
28
28
|
function parseSelector(selector) {
|
|
29
29
|
let part = { combinator: 4 /* Inner */, matchers: [] };
|
|
30
30
|
const parts = [part];
|
|
31
|
-
const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[
|
|
31
|
+
const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[>:+~]+)|:(\w+)(?:\((.*?)\))?)/gi;
|
|
32
32
|
let token;
|
|
33
33
|
while (token = tokenizer.exec(selector)) {
|
|
34
34
|
if (token[1]) {
|
|
@@ -46,8 +46,12 @@ function parseSelector(selector) {
|
|
|
46
46
|
type = token[5] === "#" ? 2 /* Id */ : 3 /* Class */;
|
|
47
47
|
} else if (token[7]) {
|
|
48
48
|
type = token[8] == null ? 5 /* Pseudo */ : 6 /* Function */;
|
|
49
|
-
} else if (token[6]
|
|
50
|
-
|
|
49
|
+
} else if (token[6]) {
|
|
50
|
+
if (token[6] === "*") {
|
|
51
|
+
type = 0 /* Unknown */;
|
|
52
|
+
} else if (ELEMENT_SELECTOR_TEST.test(token[6])) {
|
|
53
|
+
type = 1 /* Element */;
|
|
54
|
+
}
|
|
51
55
|
}
|
|
52
56
|
part.matchers.push({
|
|
53
57
|
type,
|
|
@@ -90,19 +94,30 @@ function matchesSelectorRecursive(element, parts) {
|
|
|
90
94
|
}
|
|
91
95
|
const link = combinator === 1 /* Child */ || combinator === 0 /* Descendant */ ? PARENT : PREV;
|
|
92
96
|
let ref = element[link];
|
|
93
|
-
if (!ref
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
97
|
+
if (!ref) return false;
|
|
96
98
|
if (combinator === 0 /* Descendant */ || combinator === 2 /* Sibling */) {
|
|
97
|
-
while (ref
|
|
98
|
-
if (matchesSelectorMatcher(ref, matchers)) {
|
|
99
|
+
while (ref) {
|
|
100
|
+
if (isElementNode(ref) && matchesSelectorMatcher(ref, matchers)) {
|
|
99
101
|
const pp = parts.slice(0, -1);
|
|
100
102
|
if (pp.length === 0) return true;
|
|
101
103
|
if (matchesSelectorRecursive(element, pp)) return true;
|
|
102
104
|
}
|
|
105
|
+
ref = ref[link];
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
} else {
|
|
109
|
+
if (combinator === 3 /* Adjacent */ && !isElementNode(ref)) {
|
|
110
|
+
while (ref && !isElementNode(ref)) {
|
|
111
|
+
ref = ref[link];
|
|
112
|
+
}
|
|
113
|
+
if (!ref) return false;
|
|
114
|
+
}
|
|
115
|
+
if (!isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
|
|
116
|
+
return false;
|
|
103
117
|
}
|
|
118
|
+
const pp = parts.slice(0, -1);
|
|
119
|
+
return pp.length === 0 || matchesSelectorRecursive(element, pp);
|
|
104
120
|
}
|
|
105
|
-
return false;
|
|
106
121
|
}
|
|
107
122
|
function matchesSelectorPart(element, { combinator, matchers }) {
|
|
108
123
|
if (combinator === 4 /* Inner */) {
|
|
@@ -110,15 +125,23 @@ function matchesSelectorPart(element, { combinator, matchers }) {
|
|
|
110
125
|
}
|
|
111
126
|
const link = combinator === 1 /* Child */ || combinator === 0 /* Descendant */ ? PARENT : PREV;
|
|
112
127
|
let ref = element[link];
|
|
113
|
-
if (!ref
|
|
128
|
+
if (!ref) return false;
|
|
129
|
+
if (combinator === 3 /* Adjacent */ && !isElementNode(ref)) {
|
|
130
|
+
while (ref && !isElementNode(ref)) {
|
|
131
|
+
ref = ref[link];
|
|
132
|
+
}
|
|
133
|
+
if (!ref) return false;
|
|
134
|
+
}
|
|
135
|
+
if (!isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
|
|
114
136
|
return false;
|
|
115
137
|
}
|
|
116
138
|
if (combinator === 0 /* Descendant */ || combinator === 2 /* Sibling */) {
|
|
117
139
|
while (ref = ref[link]) {
|
|
118
|
-
if (matchesSelectorMatcher(ref, matchers))
|
|
140
|
+
if (isElementNode(ref) && matchesSelectorMatcher(ref, matchers))
|
|
141
|
+
return true;
|
|
119
142
|
}
|
|
120
143
|
}
|
|
121
|
-
return
|
|
144
|
+
return true;
|
|
122
145
|
}
|
|
123
146
|
function matchesSelectorMatcher(element, matcher) {
|
|
124
147
|
if (!element) return false;
|
|
@@ -130,12 +153,17 @@ function matchesSelectorMatcher(element, matcher) {
|
|
|
130
153
|
}
|
|
131
154
|
const { type, name, value } = matcher;
|
|
132
155
|
switch (type) {
|
|
156
|
+
case 0 /* Unknown */:
|
|
157
|
+
return name === "*";
|
|
158
|
+
// Universal selector
|
|
133
159
|
case 1 /* Element */:
|
|
134
160
|
return element.localName === name;
|
|
135
161
|
case 2 /* Id */:
|
|
136
162
|
return element.getAttribute("id") === name;
|
|
137
163
|
case 3 /* Class */:
|
|
138
|
-
|
|
164
|
+
const classAttr = element.getAttribute("class");
|
|
165
|
+
if (!classAttr) return false;
|
|
166
|
+
return classAttr.split(/\s+/).includes(name);
|
|
139
167
|
case 4 /* Attribute */:
|
|
140
168
|
return value == null ? element.hasAttribute(name) : element.getAttribute(name) === value;
|
|
141
169
|
case 5 /* Pseudo */:
|
|
@@ -147,6 +175,8 @@ function matchesSelectorMatcher(element, matcher) {
|
|
|
147
175
|
switch (name) {
|
|
148
176
|
case "has":
|
|
149
177
|
return matchesSelector(element, value || "");
|
|
178
|
+
case "not":
|
|
179
|
+
return !matchesSelector(element, value || "");
|
|
150
180
|
default:
|
|
151
181
|
throw Error(`Function :${name}(${value}) not implemented`);
|
|
152
182
|
}
|