pseudo-dom 0.15.0 → 0.17.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/README.md +189 -4
- package/browser/pseudo-dom.js +187 -1
- package/browser/pseudo-dom.min.js +1 -1
- package/dist/interfaces/PseudoElement.d.ts +789 -765
- package/dist/services/ElementService.d.ts +527 -458
- package/dist/services/ElementService.js +1149 -1047
- package/dist/services/ElementService.min.js +1 -1
- package/dist/services/HTMLElementService.d.ts +154 -119
- package/dist/services/HTMLElementService.js +353 -269
- package/dist/services/HTMLElementService.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,18 @@ reflected properties (`ariaLabel`, `ariaExpanded`, `ariaValueNow`, ...) are real
|
|
|
59
59
|
matching `aria-*` attribute (`ariaLabel` <-> `aria-label`; the mapping isn't camelCase-to-kebab-case, so
|
|
60
60
|
`ariaColCount` <-> `aria-colcount`, not `aria-col-count`).
|
|
61
61
|
|
|
62
|
+
`getAttributeNode` / `setAttributeNode` / `removeAttributeNode` give and take real `Attr` nodes (backed by
|
|
63
|
+
`AttrService`) instead of plain strings - `setAttributeNode` returns whatever `Attr` previously held that name (or
|
|
64
|
+
`null` when it's new), and `removeAttributeNode` throws when the element has no attribute matching the one given, like
|
|
65
|
+
the DOM's. Every `*NS` method (`getAttributeNS`, `hasAttributeNS`, `setAttributeNS`, `removeAttributeNS`,
|
|
66
|
+
`getAttributeNodeNS`, `setAttributeNodeNS`) behaves exactly like its non-NS counterpart, ignoring the namespace
|
|
67
|
+
argument entirely - there's no real namespace parsing here, matching `getElementsByTagNameNS`.
|
|
68
|
+
|
|
69
|
+
**Form controls** have a real `value` (`input`, `textarea`, `select`, `button`, `option`, `output`) and `checked`
|
|
70
|
+
(`input`). Like the DOM's, they start from the `value` / `checked` attributes (a checkbox with no `value` reads
|
|
71
|
+
`'on'`), and once set they stop following the attribute - setting them never changes the attribute. `value` is always
|
|
72
|
+
a string, so `parseInt(input.value)` works on a number attribute. `cloneNode` keeps the current value and checkedness.
|
|
73
|
+
|
|
62
74
|
**`style`** is a real, live `CSSStyleDeclaration`:
|
|
63
75
|
|
|
64
76
|
- Named property access (`el.style.backgroundColor = 'red'`) alongside `getPropertyValue` / `setProperty` /
|
|
@@ -169,9 +181,6 @@ it) - useful for watching pseudo-dom-driven code run, or checking a final result
|
|
|
169
181
|
- There are text and comment nodes (`PseudoText`, `PseudoComment`); `textContent` works like the DOM's (the text of
|
|
170
182
|
everything below, and setting it replaces the children with a text node)
|
|
171
183
|
|
|
172
|
-
## Not implemented yet
|
|
173
|
-
|
|
174
|
-
- The `Attr`-node / namespaced attribute methods (`getAttributeNode`, `getAttributeNS`, ...)
|
|
175
184
|
## Modules
|
|
176
185
|
|
|
177
186
|
<dl>
|
|
@@ -2433,9 +2442,14 @@ Simulate the behaviour of the HTMLElement Class when there is no DOM available.
|
|
|
2433
2442
|
* [new HTMLElementService([elementOptions])](#new_HTMLElementService_new)
|
|
2434
2443
|
* [.style](#HTMLElementService+style) ⇒ [<code>CSSStyleDeclarationService</code>](#CSSStyleDeclarationService)
|
|
2435
2444
|
* [.dataset](#HTMLElementService+dataset) ⇒ <code>Object.<string, string></code>
|
|
2445
|
+
* [.value](#HTMLElementService+value) ⇒ <code>string</code> \| <code>undefined</code>
|
|
2446
|
+
* [.checked](#HTMLElementService+checked) ⇒ <code>boolean</code> \| <code>undefined</code>
|
|
2436
2447
|
* [.innerHTML](#HTMLElementService+innerHTML) ⇒ <code>undefined</code>
|
|
2437
2448
|
* [.outerHTML](#HTMLElementService+outerHTML) ⇒ <code>undefined</code>
|
|
2438
2449
|
* [.canFocus](#HTMLElementService+canFocus) ⇒ <code>boolean</code>
|
|
2450
|
+
* [.hasValueProperty()](#HTMLElementService+hasValueProperty) ⇒ <code>boolean</code>
|
|
2451
|
+
* [.hasCheckedProperty()](#HTMLElementService+hasCheckedProperty) ⇒ <code>boolean</code>
|
|
2452
|
+
* [.setExpando(name, value)](#HTMLElementService+setExpando) ⇒ <code>undefined</code>
|
|
2439
2453
|
* [.cloneShallow()](#HTMLElementService+cloneShallow) ⇒ [<code>NodeService</code>](#NodeService)
|
|
2440
2454
|
* [.equalsShallow(other)](#HTMLElementService+equalsShallow) ⇒ <code>boolean</code>
|
|
2441
2455
|
* [.parse(html)](#HTMLElementService+parse) ⇒ <code>Array.<\*></code>
|
|
@@ -2470,6 +2484,21 @@ and style.color = 'red' work.
|
|
|
2470
2484
|
The element's data-* attributes, live, under their camelCase names (data-foo-bar <-> dataset.fooBar). Backed
|
|
2471
2485
|
directly by getAttribute / setAttribute, so it is never out of sync with the attributes themselves.
|
|
2472
2486
|
|
|
2487
|
+
**Kind**: instance property of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2488
|
+
<a name="HTMLElementService+value"></a>
|
|
2489
|
+
|
|
2490
|
+
### htmlElementService.value ⇒ <code>string</code> \| <code>undefined</code>
|
|
2491
|
+
The current value of a form control. Until it is set (or edited), it is the value attribute (the default value),
|
|
2492
|
+
or '' when there is none ('on' for a checkbox or radio); setting it never changes the attribute, like the DOM's.
|
|
2493
|
+
Only form controls (input, textarea, select, button, option, output) have one.
|
|
2494
|
+
|
|
2495
|
+
**Kind**: instance property of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2496
|
+
<a name="HTMLElementService+checked"></a>
|
|
2497
|
+
|
|
2498
|
+
### htmlElementService.checked ⇒ <code>boolean</code> \| <code>undefined</code>
|
|
2499
|
+
Whether a checkbox or radio input is checked. Until it is set, it follows the checked attribute (which sets the
|
|
2500
|
+
default); setting it never changes the attribute, like the DOM's. Only input has one.
|
|
2501
|
+
|
|
2473
2502
|
**Kind**: instance property of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2474
2503
|
<a name="HTMLElementService+innerHTML"></a>
|
|
2475
2504
|
|
|
@@ -2501,10 +2530,35 @@ replaceWith. outerHTML's setter is here rather than on ElementService for the sa
|
|
|
2501
2530
|
Whether this element can have the focus: form controls and links which are not disabled, and anything with a tabindex.
|
|
2502
2531
|
|
|
2503
2532
|
**Kind**: instance property of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2533
|
+
<a name="HTMLElementService+hasValueProperty"></a>
|
|
2534
|
+
|
|
2535
|
+
### htmlElementService.hasValueProperty() ⇒ <code>boolean</code>
|
|
2536
|
+
Whether this tag has a `value` (the form controls which do).
|
|
2537
|
+
|
|
2538
|
+
**Kind**: instance method of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2539
|
+
<a name="HTMLElementService+hasCheckedProperty"></a>
|
|
2540
|
+
|
|
2541
|
+
### htmlElementService.hasCheckedProperty() ⇒ <code>boolean</code>
|
|
2542
|
+
Whether this tag has a `checked` (only input does).
|
|
2543
|
+
|
|
2544
|
+
**Kind**: instance method of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2545
|
+
<a name="HTMLElementService+setExpando"></a>
|
|
2546
|
+
|
|
2547
|
+
### htmlElementService.setExpando(name, value) ⇒ <code>undefined</code>
|
|
2548
|
+
Put a plain own property on the element, as assigning a property this element does not have does in the DOM.
|
|
2549
|
+
|
|
2550
|
+
**Kind**: instance method of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2551
|
+
|
|
2552
|
+
| Param | Type |
|
|
2553
|
+
| --- | --- |
|
|
2554
|
+
| name | <code>string</code> |
|
|
2555
|
+
| value | <code>\*</code> |
|
|
2556
|
+
|
|
2504
2557
|
<a name="HTMLElementService+cloneShallow"></a>
|
|
2505
2558
|
|
|
2506
2559
|
### htmlElementService.cloneShallow() ⇒ [<code>NodeService</code>](#NodeService)
|
|
2507
|
-
Style is not attribute-backed like most properties (see the constructor), so cloneNode needs its own copy of it
|
|
2560
|
+
Style is not attribute-backed like most properties (see the constructor), so cloneNode needs its own copy of it,
|
|
2561
|
+
and a form control keeps its current value and checkedness (as the DOM's cloneNode does).
|
|
2508
2562
|
|
|
2509
2563
|
**Kind**: instance method of [<code>HTMLElementService</code>](#HTMLElementService)
|
|
2510
2564
|
<a name="HTMLElementService+equalsShallow"></a>
|
|
@@ -2961,6 +3015,15 @@ Simulate the behaviour of the Element Class when there is no DOM available.
|
|
|
2961
3015
|
* [.removeAttribute(attributeName)](#ElementService+removeAttribute) ⇒ <code>undefined</code>
|
|
2962
3016
|
* [.getAttributeNames()](#ElementService+getAttributeNames) ⇒ <code>Array.<string></code>
|
|
2963
3017
|
* [.hasAttributes()](#ElementService+hasAttributes) ⇒ <code>boolean</code>
|
|
3018
|
+
* [.getAttributeNode(attributeName)](#ElementService+getAttributeNode) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3019
|
+
* [.getAttributeNodeNS(namespace, attributeName)](#ElementService+getAttributeNodeNS) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3020
|
+
* [.getAttributeNS(namespace, attributeName)](#ElementService+getAttributeNS) ⇒ <code>string</code> \| <code>null</code>
|
|
3021
|
+
* [.hasAttributeNS(namespace, attributeName)](#ElementService+hasAttributeNS) ⇒ <code>boolean</code>
|
|
3022
|
+
* [.removeAttributeNode(attr)](#ElementService+removeAttributeNode) ⇒ [<code>AttrService</code>](#AttrService)
|
|
3023
|
+
* [.removeAttributeNS(namespace, attributeName)](#ElementService+removeAttributeNS) ⇒ <code>undefined</code>
|
|
3024
|
+
* [.setAttributeNode(attr)](#ElementService+setAttributeNode) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3025
|
+
* [.setAttributeNodeNS(attr)](#ElementService+setAttributeNodeNS) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3026
|
+
* [.setAttributeNS(namespace, attributeName, attributeValue)](#ElementService+setAttributeNS) ⇒ <code>undefined</code>
|
|
2964
3027
|
* [.toggleAttribute(attributeName, [force])](#ElementService+toggleAttribute) ⇒ <code>boolean</code>
|
|
2965
3028
|
* [.getBoundingClientRect()](#ElementService+getBoundingClientRect) ⇒ <code>DOMRect</code>
|
|
2966
3029
|
* [.getClientRects()](#ElementService+getClientRects) ⇒ <code>Array.<DOMRect></code>
|
|
@@ -3272,6 +3335,128 @@ The name of every attribute on the element, in the order they were set.
|
|
|
3272
3335
|
Whether the element has any attributes at all.
|
|
3273
3336
|
|
|
3274
3337
|
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3338
|
+
<a name="ElementService+getAttributeNode"></a>
|
|
3339
|
+
|
|
3340
|
+
### elementService.getAttributeNode(attributeName) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3341
|
+
Retrieve the node representation of an attribute.
|
|
3342
|
+
|
|
3343
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3344
|
+
**Returns**: [<code>AttrService</code>](#AttrService) \| <code>null</code> - An Attr for the attribute, or null when there is no such attribute
|
|
3345
|
+
|
|
3346
|
+
| Param | Type |
|
|
3347
|
+
| --- | --- |
|
|
3348
|
+
| attributeName | <code>string</code> |
|
|
3349
|
+
|
|
3350
|
+
<a name="ElementService+getAttributeNodeNS"></a>
|
|
3351
|
+
|
|
3352
|
+
### elementService.getAttributeNodeNS(namespace, attributeName) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3353
|
+
Retrieve the node representation of an attribute. There is no real namespace parsing here, so this ignores
|
|
3354
|
+
the namespace and behaves exactly like getAttributeNode.
|
|
3355
|
+
|
|
3356
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3357
|
+
**Returns**: [<code>AttrService</code>](#AttrService) \| <code>null</code> - An Attr for the attribute, or null when there is no such attribute
|
|
3358
|
+
|
|
3359
|
+
| Param | Type | Description |
|
|
3360
|
+
| --- | --- | --- |
|
|
3361
|
+
| namespace | <code>string</code> | Ignored |
|
|
3362
|
+
| attributeName | <code>string</code> | |
|
|
3363
|
+
|
|
3364
|
+
<a name="ElementService+getAttributeNS"></a>
|
|
3365
|
+
|
|
3366
|
+
### elementService.getAttributeNS(namespace, attributeName) ⇒ <code>string</code> \| <code>null</code>
|
|
3367
|
+
Retrieve the value of an attribute. There is no real namespace parsing here, so this ignores the namespace
|
|
3368
|
+
and behaves exactly like getAttribute.
|
|
3369
|
+
|
|
3370
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3371
|
+
**Returns**: <code>string</code> \| <code>null</code> - The value, or null when there is no such attribute
|
|
3372
|
+
|
|
3373
|
+
| Param | Type | Description |
|
|
3374
|
+
| --- | --- | --- |
|
|
3375
|
+
| namespace | <code>string</code> | Ignored |
|
|
3376
|
+
| attributeName | <code>string</code> | |
|
|
3377
|
+
|
|
3378
|
+
<a name="ElementService+hasAttributeNS"></a>
|
|
3379
|
+
|
|
3380
|
+
### elementService.hasAttributeNS(namespace, attributeName) ⇒ <code>boolean</code>
|
|
3381
|
+
Check whether the element has an attribute by that name. There is no real namespace parsing here, so this
|
|
3382
|
+
ignores the namespace and behaves exactly like hasAttribute.
|
|
3383
|
+
|
|
3384
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3385
|
+
|
|
3386
|
+
| Param | Type | Description |
|
|
3387
|
+
| --- | --- | --- |
|
|
3388
|
+
| namespace | <code>string</code> | Ignored |
|
|
3389
|
+
| attributeName | <code>string</code> | |
|
|
3390
|
+
|
|
3391
|
+
<a name="ElementService+removeAttributeNode"></a>
|
|
3392
|
+
|
|
3393
|
+
### elementService.removeAttributeNode(attr) ⇒ [<code>AttrService</code>](#AttrService)
|
|
3394
|
+
Remove the node representation of an attribute from the element, and return it.
|
|
3395
|
+
|
|
3396
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3397
|
+
**Returns**: [<code>AttrService</code>](#AttrService) - The removed Attr
|
|
3398
|
+
**Throws**:
|
|
3399
|
+
|
|
3400
|
+
- <code>Error</code> When the element has no attribute matching attr.name
|
|
3401
|
+
|
|
3402
|
+
|
|
3403
|
+
| Param | Type |
|
|
3404
|
+
| --- | --- |
|
|
3405
|
+
| attr | [<code>AttrService</code>](#AttrService) |
|
|
3406
|
+
|
|
3407
|
+
<a name="ElementService+removeAttributeNS"></a>
|
|
3408
|
+
|
|
3409
|
+
### elementService.removeAttributeNS(namespace, attributeName) ⇒ <code>undefined</code>
|
|
3410
|
+
Remove an attribute from the element. There is no real namespace parsing here, so this ignores the namespace
|
|
3411
|
+
and behaves exactly like removeAttribute.
|
|
3412
|
+
|
|
3413
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3414
|
+
|
|
3415
|
+
| Param | Type | Description |
|
|
3416
|
+
| --- | --- | --- |
|
|
3417
|
+
| namespace | <code>string</code> | Ignored |
|
|
3418
|
+
| attributeName | <code>string</code> | |
|
|
3419
|
+
|
|
3420
|
+
<a name="ElementService+setAttributeNode"></a>
|
|
3421
|
+
|
|
3422
|
+
### elementService.setAttributeNode(attr) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3423
|
+
Set the node representation of an attribute, adding the attribute if it did not exist. Returns any previous
|
|
3424
|
+
Attr that had the same name, or null when there was none.
|
|
3425
|
+
|
|
3426
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3427
|
+
**Returns**: [<code>AttrService</code>](#AttrService) \| <code>null</code> - The replaced Attr, or null when the attribute was new
|
|
3428
|
+
|
|
3429
|
+
| Param | Type |
|
|
3430
|
+
| --- | --- |
|
|
3431
|
+
| attr | [<code>AttrService</code>](#AttrService) |
|
|
3432
|
+
|
|
3433
|
+
<a name="ElementService+setAttributeNodeNS"></a>
|
|
3434
|
+
|
|
3435
|
+
### elementService.setAttributeNodeNS(attr) ⇒ [<code>AttrService</code>](#AttrService) \| <code>null</code>
|
|
3436
|
+
Set the node representation of an attribute. There is no real namespace parsing here, so this behaves
|
|
3437
|
+
exactly like setAttributeNode (Attr.name already carries any prefix).
|
|
3438
|
+
|
|
3439
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3440
|
+
**Returns**: [<code>AttrService</code>](#AttrService) \| <code>null</code> - The replaced Attr, or null when the attribute was new
|
|
3441
|
+
|
|
3442
|
+
| Param | Type |
|
|
3443
|
+
| --- | --- |
|
|
3444
|
+
| attr | [<code>AttrService</code>](#AttrService) |
|
|
3445
|
+
|
|
3446
|
+
<a name="ElementService+setAttributeNS"></a>
|
|
3447
|
+
|
|
3448
|
+
### elementService.setAttributeNS(namespace, attributeName, attributeValue) ⇒ <code>undefined</code>
|
|
3449
|
+
Set the value of an attribute, adding the attribute if it did not exist. There is no real namespace parsing
|
|
3450
|
+
here, so this ignores the namespace and behaves exactly like setAttribute.
|
|
3451
|
+
|
|
3452
|
+
**Kind**: instance method of [<code>ElementService</code>](#ElementService)
|
|
3453
|
+
|
|
3454
|
+
| Param | Type | Description |
|
|
3455
|
+
| --- | --- | --- |
|
|
3456
|
+
| namespace | <code>string</code> | Ignored |
|
|
3457
|
+
| attributeName | <code>string</code> | |
|
|
3458
|
+
| attributeValue | <code>string</code> | |
|
|
3459
|
+
|
|
3275
3460
|
<a name="ElementService+toggleAttribute"></a>
|
|
3276
3461
|
|
|
3277
3462
|
### elementService.toggleAttribute(attributeName, [force]) ⇒ <code>boolean</code>
|
package/browser/pseudo-dom.js
CHANGED
|
@@ -2605,6 +2605,108 @@
|
|
|
2605
2605
|
return this.attributeList.length > 0
|
|
2606
2606
|
}
|
|
2607
2607
|
|
|
2608
|
+
/**
|
|
2609
|
+
* Retrieve the node representation of an attribute.
|
|
2610
|
+
* @param {string} attributeName
|
|
2611
|
+
* @returns {AttrService|null} An Attr for the attribute, or null when there is no such attribute
|
|
2612
|
+
*/
|
|
2613
|
+
getAttributeNode (attributeName) {
|
|
2614
|
+
return this.hasAttribute(attributeName) ? new AttrService_1.AttrService(attributeName, this.getAttribute(attributeName) || '', this) : null
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
/**
|
|
2618
|
+
* Retrieve the node representation of an attribute. There is no real namespace parsing here, so this ignores
|
|
2619
|
+
* the namespace and behaves exactly like getAttributeNode.
|
|
2620
|
+
* @param {string} namespace Ignored
|
|
2621
|
+
* @param {string} attributeName
|
|
2622
|
+
* @returns {AttrService|null} An Attr for the attribute, or null when there is no such attribute
|
|
2623
|
+
*/
|
|
2624
|
+
getAttributeNodeNS (namespace, attributeName) {
|
|
2625
|
+
return this.getAttributeNode(attributeName)
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
/**
|
|
2629
|
+
* Retrieve the value of an attribute. There is no real namespace parsing here, so this ignores the namespace
|
|
2630
|
+
* and behaves exactly like getAttribute.
|
|
2631
|
+
* @param {string} namespace Ignored
|
|
2632
|
+
* @param {string} attributeName
|
|
2633
|
+
* @returns {string|null} The value, or null when there is no such attribute
|
|
2634
|
+
*/
|
|
2635
|
+
getAttributeNS (namespace, attributeName) {
|
|
2636
|
+
return this.getAttribute(attributeName)
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
/**
|
|
2640
|
+
* Check whether the element has an attribute by that name. There is no real namespace parsing here, so this
|
|
2641
|
+
* ignores the namespace and behaves exactly like hasAttribute.
|
|
2642
|
+
* @param {string} namespace Ignored
|
|
2643
|
+
* @param {string} attributeName
|
|
2644
|
+
* @returns {boolean}
|
|
2645
|
+
*/
|
|
2646
|
+
hasAttributeNS (namespace, attributeName) {
|
|
2647
|
+
return this.hasAttribute(attributeName)
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
/**
|
|
2651
|
+
* Remove the node representation of an attribute from the element, and return it.
|
|
2652
|
+
* @param {AttrService} attr
|
|
2653
|
+
* @returns {AttrService} The removed Attr
|
|
2654
|
+
* @throws {Error} When the element has no attribute matching attr.name
|
|
2655
|
+
*/
|
|
2656
|
+
removeAttributeNode (attr) {
|
|
2657
|
+
if (!this.hasAttribute(attr.name)) {
|
|
2658
|
+
throw new Error(`Failed to execute 'removeAttributeNode': The node provided is owned by another element (no attribute named '${attr.name}')`)
|
|
2659
|
+
}
|
|
2660
|
+
const removed = this.getAttributeNode(attr.name)
|
|
2661
|
+
this.removeAttribute(attr.name)
|
|
2662
|
+
return removed
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
/**
|
|
2666
|
+
* Remove an attribute from the element. There is no real namespace parsing here, so this ignores the namespace
|
|
2667
|
+
* and behaves exactly like removeAttribute.
|
|
2668
|
+
* @param {string} namespace Ignored
|
|
2669
|
+
* @param {string} attributeName
|
|
2670
|
+
* @returns {undefined}
|
|
2671
|
+
*/
|
|
2672
|
+
removeAttributeNS (namespace, attributeName) {
|
|
2673
|
+
this.removeAttribute(attributeName)
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
/**
|
|
2677
|
+
* Set the node representation of an attribute, adding the attribute if it did not exist. Returns any previous
|
|
2678
|
+
* Attr that had the same name, or null when there was none.
|
|
2679
|
+
* @param {AttrService} attr
|
|
2680
|
+
* @returns {AttrService|null} The replaced Attr, or null when the attribute was new
|
|
2681
|
+
*/
|
|
2682
|
+
setAttributeNode (attr) {
|
|
2683
|
+
const existing = this.getAttributeNode(attr.name)
|
|
2684
|
+
this.setAttribute(attr.name, attr.value)
|
|
2685
|
+
return existing
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
/**
|
|
2689
|
+
* Set the node representation of an attribute. There is no real namespace parsing here, so this behaves
|
|
2690
|
+
* exactly like setAttributeNode (Attr.name already carries any prefix).
|
|
2691
|
+
* @param {AttrService} attr
|
|
2692
|
+
* @returns {AttrService|null} The replaced Attr, or null when the attribute was new
|
|
2693
|
+
*/
|
|
2694
|
+
setAttributeNodeNS (attr) {
|
|
2695
|
+
return this.setAttributeNode(attr)
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
/**
|
|
2699
|
+
* Set the value of an attribute, adding the attribute if it did not exist. There is no real namespace parsing
|
|
2700
|
+
* here, so this ignores the namespace and behaves exactly like setAttribute.
|
|
2701
|
+
* @param {string} namespace Ignored
|
|
2702
|
+
* @param {string} attributeName
|
|
2703
|
+
* @param {string} attributeValue
|
|
2704
|
+
* @returns {undefined}
|
|
2705
|
+
*/
|
|
2706
|
+
setAttributeNS (namespace, attributeName, attributeValue) {
|
|
2707
|
+
this.setAttribute(attributeName, attributeValue)
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2608
2710
|
/**
|
|
2609
2711
|
* Add the attribute (with an empty value) when it is not present, or remove it when it is - unless force says
|
|
2610
2712
|
* which of those to do instead. Returns whether the attribute is present after the call.
|
|
@@ -3806,6 +3908,8 @@
|
|
|
3806
3908
|
parent,
|
|
3807
3909
|
children
|
|
3808
3910
|
})
|
|
3911
|
+
this.dirtyValue = null
|
|
3912
|
+
this.dirtyChecked = null
|
|
3809
3913
|
this.styleDeclaration = (0, createStyleDeclaration_1.default)()
|
|
3810
3914
|
this.datasetProxy = (0, createDataset_1.default)(this)
|
|
3811
3915
|
}
|
|
@@ -3829,12 +3933,94 @@
|
|
|
3829
3933
|
}
|
|
3830
3934
|
|
|
3831
3935
|
/**
|
|
3832
|
-
*
|
|
3936
|
+
* Whether this tag has a `value` (the form controls which do).
|
|
3937
|
+
* @returns {boolean}
|
|
3938
|
+
*/
|
|
3939
|
+
hasValueProperty () {
|
|
3940
|
+
return ['input', 'textarea', 'select', 'button', 'option', 'output'].indexOf(this.tagName.toLowerCase()) >= 0
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
/**
|
|
3944
|
+
* Whether this tag has a `checked` (only input does).
|
|
3945
|
+
* @returns {boolean}
|
|
3946
|
+
*/
|
|
3947
|
+
hasCheckedProperty () {
|
|
3948
|
+
return this.tagName.toLowerCase() === 'input'
|
|
3949
|
+
}
|
|
3950
|
+
|
|
3951
|
+
/**
|
|
3952
|
+
* Put a plain own property on the element, as assigning a property this element does not have does in the DOM.
|
|
3953
|
+
* @param {string} name
|
|
3954
|
+
* @param {*} value
|
|
3955
|
+
* @returns {undefined}
|
|
3956
|
+
*/
|
|
3957
|
+
setExpando (name, value) {
|
|
3958
|
+
Object.defineProperty(this, name, {
|
|
3959
|
+
value,
|
|
3960
|
+
writable: true,
|
|
3961
|
+
configurable: true,
|
|
3962
|
+
enumerable: true
|
|
3963
|
+
})
|
|
3964
|
+
}
|
|
3965
|
+
|
|
3966
|
+
/**
|
|
3967
|
+
* The current value of a form control. Until it is set (or edited), it is the value attribute (the default value),
|
|
3968
|
+
* or '' when there is none ('on' for a checkbox or radio); setting it never changes the attribute, like the DOM's.
|
|
3969
|
+
* Only form controls (input, textarea, select, button, option, output) have one.
|
|
3970
|
+
* @returns {string|undefined}
|
|
3971
|
+
*/
|
|
3972
|
+
get value () {
|
|
3973
|
+
if (!this.hasValueProperty()) {
|
|
3974
|
+
return undefined
|
|
3975
|
+
}
|
|
3976
|
+
if (this.dirtyValue !== null) {
|
|
3977
|
+
return this.dirtyValue
|
|
3978
|
+
}
|
|
3979
|
+
const attribute = this.getAttribute('value')
|
|
3980
|
+
if (attribute !== null) {
|
|
3981
|
+
return String(attribute)
|
|
3982
|
+
}
|
|
3983
|
+
return this.tagName.toLowerCase() === 'input' && /^(checkbox|radio)$/i.test(String(this.getAttribute('type'))) ? 'on' : ''
|
|
3984
|
+
}
|
|
3985
|
+
|
|
3986
|
+
set value (value) {
|
|
3987
|
+
if (this.hasValueProperty()) {
|
|
3988
|
+
this.dirtyValue = String(value)
|
|
3989
|
+
} else {
|
|
3990
|
+
this.setExpando('value', value)
|
|
3991
|
+
}
|
|
3992
|
+
}
|
|
3993
|
+
|
|
3994
|
+
/**
|
|
3995
|
+
* Whether a checkbox or radio input is checked. Until it is set, it follows the checked attribute (which sets the
|
|
3996
|
+
* default); setting it never changes the attribute, like the DOM's. Only input has one.
|
|
3997
|
+
* @returns {boolean|undefined}
|
|
3998
|
+
*/
|
|
3999
|
+
get checked () {
|
|
4000
|
+
if (!this.hasCheckedProperty()) {
|
|
4001
|
+
return undefined
|
|
4002
|
+
}
|
|
4003
|
+
return this.dirtyChecked !== null ? this.dirtyChecked : this.hasAttribute('checked')
|
|
4004
|
+
}
|
|
4005
|
+
|
|
4006
|
+
set checked (checked) {
|
|
4007
|
+
if (this.hasCheckedProperty()) {
|
|
4008
|
+
this.dirtyChecked = Boolean(checked)
|
|
4009
|
+
} else {
|
|
4010
|
+
this.setExpando('checked', checked)
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
/**
|
|
4015
|
+
* Style is not attribute-backed like most properties (see the constructor), so cloneNode needs its own copy of it,
|
|
4016
|
+
* and a form control keeps its current value and checkedness (as the DOM's cloneNode does).
|
|
3833
4017
|
* @returns {NodeService}
|
|
3834
4018
|
*/
|
|
3835
4019
|
cloneShallow () {
|
|
3836
4020
|
const copy = super.cloneShallow()
|
|
3837
4021
|
copy.style.cssText = this.style.cssText
|
|
4022
|
+
copy.dirtyValue = this.dirtyValue
|
|
4023
|
+
copy.dirtyChecked = this.dirtyChecked
|
|
3838
4024
|
return copy
|
|
3839
4025
|
}
|
|
3840
4026
|
|