happy-dom 7.6.4 → 7.6.5
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.
Potentially problematic release.
This version of happy-dom might be problematic. Click here for more details.
- package/lib/nodes/element/Element.d.ts +4 -2
- package/lib/nodes/element/Element.js +8 -1
- package/lib/nodes/element/Element.js.map +1 -1
- package/lib/nodes/element/IElement.d.ts +4 -2
- package/lib/nodes/html-element/HTMLElement.d.ts +1 -12
- package/lib/nodes/html-element/HTMLElement.js +1 -11
- package/lib/nodes/html-element/HTMLElement.js.map +1 -1
- package/lib/nodes/html-option-element/HTMLOptionElement.d.ts +17 -0
- package/lib/nodes/html-option-element/HTMLOptionElement.js +55 -32
- package/lib/nodes/html-option-element/HTMLOptionElement.js.map +1 -1
- package/lib/nodes/html-option-element/HTMLOptionsCollection.d.ts +0 -1
- package/lib/nodes/html-option-element/HTMLOptionsCollection.js +2 -10
- package/lib/nodes/html-option-element/HTMLOptionsCollection.js.map +1 -1
- package/lib/nodes/html-select-element/HTMLSelectElement.d.ts +18 -2
- package/lib/nodes/html-select-element/HTMLSelectElement.js +99 -22
- package/lib/nodes/html-select-element/HTMLSelectElement.js.map +1 -1
- package/lib/nodes/svg-element/SVGElement.d.ts +1 -8
- package/lib/nodes/svg-element/SVGElement.js +1 -7
- package/lib/nodes/svg-element/SVGElement.js.map +1 -1
- package/package.json +2 -2
- package/src/nodes/element/Element.ts +15 -3
- package/src/nodes/element/IElement.ts +4 -2
- package/src/nodes/html-element/HTMLElement.ts +3 -12
- package/src/nodes/html-option-element/HTMLOptionElement.ts +69 -35
- package/src/nodes/html-option-element/HTMLOptionsCollection.ts +2 -9
- package/src/nodes/html-select-element/HTMLSelectElement.ts +109 -27
- package/src/nodes/svg-element/SVGElement.ts +3 -8
@@ -167,13 +167,14 @@ export default class HTMLSelectElement extends HTMLElement implements IHTMLSelec
|
|
167
167
|
* @returns Value.
|
168
168
|
*/
|
169
169
|
public get value(): string {
|
170
|
-
|
171
|
-
|
170
|
+
for (let i = 0, max = this.options.length; i < max; i++) {
|
171
|
+
const option = <HTMLOptionElement>this.options[i];
|
172
|
+
if (option._selectedness) {
|
173
|
+
return option.value;
|
174
|
+
}
|
172
175
|
}
|
173
176
|
|
174
|
-
|
175
|
-
|
176
|
-
return option instanceof HTMLOptionElement ? option.value : '';
|
177
|
+
return '';
|
177
178
|
}
|
178
179
|
|
179
180
|
/**
|
@@ -182,9 +183,15 @@ export default class HTMLSelectElement extends HTMLElement implements IHTMLSelec
|
|
182
183
|
* @param value Value.
|
183
184
|
*/
|
184
185
|
public set value(value: string) {
|
185
|
-
|
186
|
-
|
187
|
-
|
186
|
+
for (let i = 0, max = this.options.length; i < max; i++) {
|
187
|
+
const option = <HTMLOptionElement>this.options[i];
|
188
|
+
if (option.value === value) {
|
189
|
+
option._selectedness = true;
|
190
|
+
option._dirtyness = true;
|
191
|
+
} else {
|
192
|
+
option._selectedness = false;
|
193
|
+
}
|
194
|
+
}
|
188
195
|
}
|
189
196
|
|
190
197
|
/**
|
@@ -193,16 +200,31 @@ export default class HTMLSelectElement extends HTMLElement implements IHTMLSelec
|
|
193
200
|
* @returns Value.
|
194
201
|
*/
|
195
202
|
public get selectedIndex(): number {
|
196
|
-
|
203
|
+
for (let i = 0, max = this.options.length; i < max; i++) {
|
204
|
+
if ((<HTMLOptionElement>this.options[i])._selectedness) {
|
205
|
+
return i;
|
206
|
+
}
|
207
|
+
}
|
208
|
+
return -1;
|
197
209
|
}
|
198
210
|
|
199
211
|
/**
|
200
212
|
* Sets value.
|
201
213
|
*
|
202
|
-
* @param
|
214
|
+
* @param selectedIndex Selected index.
|
203
215
|
*/
|
204
|
-
public set selectedIndex(
|
205
|
-
|
216
|
+
public set selectedIndex(selectedIndex: number) {
|
217
|
+
if (typeof selectedIndex === 'number' && !isNaN(selectedIndex)) {
|
218
|
+
for (let i = 0, max = this.options.length; i < max; i++) {
|
219
|
+
(<HTMLOptionElement>this.options[i])._selectedness = false;
|
220
|
+
}
|
221
|
+
|
222
|
+
const selectedOption = <HTMLOptionElement>this.options[selectedIndex];
|
223
|
+
if (selectedOption) {
|
224
|
+
selectedOption._selectedness = true;
|
225
|
+
selectedOption._dirtyness = true;
|
226
|
+
}
|
227
|
+
}
|
206
228
|
}
|
207
229
|
|
208
230
|
/**
|
@@ -287,13 +309,10 @@ export default class HTMLSelectElement extends HTMLElement implements IHTMLSelec
|
|
287
309
|
|
288
310
|
if (element.tagName === 'OPTION' || element.tagName === 'OPTGROUP') {
|
289
311
|
this.options.push(<IHTMLOptionElement | IHTMLOptGroupElement>element);
|
290
|
-
|
291
|
-
if (this.options.length === 1) {
|
292
|
-
this.options.selectedIndex = 0;
|
293
|
-
}
|
294
312
|
}
|
295
313
|
|
296
314
|
this._updateIndexProperties(previousLength, this.options.length);
|
315
|
+
this._resetOptionSelectednes();
|
297
316
|
}
|
298
317
|
|
299
318
|
return super.appendChild(node);
|
@@ -332,15 +351,15 @@ export default class HTMLSelectElement extends HTMLElement implements IHTMLSelec
|
|
332
351
|
} else {
|
333
352
|
this.options.push(<IHTMLOptionElement | IHTMLOptGroupElement>newElement);
|
334
353
|
}
|
335
|
-
|
336
|
-
if (this.options.length === 1) {
|
337
|
-
this.options.selectedIndex = 0;
|
338
|
-
}
|
339
354
|
}
|
340
355
|
|
341
356
|
this._updateIndexProperties(previousLength, this.options.length);
|
342
357
|
}
|
343
358
|
|
359
|
+
if (newNode.nodeType === NodeTypeEnum.elementNode) {
|
360
|
+
this._resetOptionSelectednes();
|
361
|
+
}
|
362
|
+
|
344
363
|
return returnValue;
|
345
364
|
}
|
346
365
|
|
@@ -358,20 +377,83 @@ export default class HTMLSelectElement extends HTMLElement implements IHTMLSelec
|
|
358
377
|
if (index !== -1) {
|
359
378
|
this.options.splice(index, 1);
|
360
379
|
}
|
380
|
+
}
|
361
381
|
|
362
|
-
|
363
|
-
|
382
|
+
this._updateIndexProperties(previousLength, this.options.length);
|
383
|
+
this._resetOptionSelectednes();
|
384
|
+
}
|
385
|
+
|
386
|
+
return super.removeChild(node);
|
387
|
+
}
|
388
|
+
|
389
|
+
/**
|
390
|
+
* Resets the option selectedness.
|
391
|
+
*
|
392
|
+
* Based on:
|
393
|
+
* https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/nodes/HTMLSelectElement-impl.js
|
394
|
+
*
|
395
|
+
* @param [newOption] Optional new option element to be selected.
|
396
|
+
* @see https://html.spec.whatwg.org/multipage/form-elements.html#selectedness-setting-algorithm
|
397
|
+
*/
|
398
|
+
public _resetOptionSelectednes(newOption?: IHTMLOptionElement): void {
|
399
|
+
if (this.hasAttributeNS(null, 'multiple')) {
|
400
|
+
return;
|
401
|
+
}
|
402
|
+
|
403
|
+
const selected: HTMLOptionElement[] = [];
|
404
|
+
|
405
|
+
for (let i = 0, max = this.options.length; i < max; i++) {
|
406
|
+
if (newOption) {
|
407
|
+
(<HTMLOptionElement>this.options[i])._selectedness = this.options[i] === newOption;
|
408
|
+
}
|
409
|
+
|
410
|
+
if ((<HTMLOptionElement>this.options[i])._selectedness) {
|
411
|
+
selected.push(<HTMLOptionElement>this.options[i]);
|
412
|
+
}
|
413
|
+
}
|
414
|
+
|
415
|
+
const size = this._getDisplaySize();
|
416
|
+
|
417
|
+
if (size === 1 && !selected.length) {
|
418
|
+
for (let i = 0, max = this.options.length; i < max; i++) {
|
419
|
+
const option = <HTMLOptionElement>this.options[i];
|
420
|
+
|
421
|
+
let disabled = option.hasAttributeNS(null, 'disabled');
|
422
|
+
const parentNode = <IHTMLElement>option.parentNode;
|
423
|
+
if (
|
424
|
+
parentNode &&
|
425
|
+
parentNode.nodeType === NodeTypeEnum.elementNode &&
|
426
|
+
parentNode.tagName === 'OPTGROUP' &&
|
427
|
+
parentNode.hasAttributeNS(null, 'disabled')
|
428
|
+
) {
|
429
|
+
disabled = true;
|
364
430
|
}
|
365
431
|
|
366
|
-
if (!
|
367
|
-
|
432
|
+
if (!disabled) {
|
433
|
+
option._selectedness = true;
|
434
|
+
break;
|
368
435
|
}
|
369
436
|
}
|
370
|
-
|
371
|
-
|
437
|
+
} else if (selected.length >= 2) {
|
438
|
+
for (let i = 0, max = this.options.length; i < max; i++) {
|
439
|
+
(<HTMLOptionElement>this.options[i])._selectedness = i === selected.length - 1;
|
440
|
+
}
|
372
441
|
}
|
442
|
+
}
|
373
443
|
|
374
|
-
|
444
|
+
/**
|
445
|
+
* Returns display size.
|
446
|
+
*
|
447
|
+
* @returns Display size.
|
448
|
+
*/
|
449
|
+
protected _getDisplaySize(): number {
|
450
|
+
if (this.hasAttributeNS(null, 'size')) {
|
451
|
+
const size = parseInt(this.getAttributeNS(null, 'size'));
|
452
|
+
if (!isNaN(size) && size >= 0) {
|
453
|
+
return size;
|
454
|
+
}
|
455
|
+
}
|
456
|
+
return this.hasAttributeNS(null, 'multiple') ? 4 : 1;
|
375
457
|
}
|
376
458
|
|
377
459
|
/**
|
@@ -74,11 +74,7 @@ export default class SVGElement extends Element implements ISVGElement {
|
|
74
74
|
}
|
75
75
|
|
76
76
|
/**
|
77
|
-
* The setAttributeNode() method adds a new Attr node to the specified element.
|
78
|
-
*
|
79
77
|
* @override
|
80
|
-
* @param attribute Attribute.
|
81
|
-
* @returns Replaced attribute.
|
82
78
|
*/
|
83
79
|
public setAttributeNode(attribute: IAttr): IAttr {
|
84
80
|
const replacedAttribute = super.setAttributeNode(attribute);
|
@@ -91,16 +87,15 @@ export default class SVGElement extends Element implements ISVGElement {
|
|
91
87
|
}
|
92
88
|
|
93
89
|
/**
|
94
|
-
* Removes an Attr node.
|
95
|
-
*
|
96
90
|
* @override
|
97
|
-
* @param attribute Attribute.
|
98
91
|
*/
|
99
|
-
public removeAttributeNode(attribute: IAttr):
|
92
|
+
public removeAttributeNode(attribute: IAttr): IAttr {
|
100
93
|
super.removeAttributeNode(attribute);
|
101
94
|
|
102
95
|
if (attribute.name === 'style' && this._style) {
|
103
96
|
this._style.cssText = '';
|
104
97
|
}
|
98
|
+
|
99
|
+
return attribute;
|
105
100
|
}
|
106
101
|
}
|