jsdom
Version:
A JavaScript implementation of many web standards
111 lines (105 loc) • 3.41 kB
JavaScript
"use strict";
const idlUtils = require("../generated/utils.js");
const DOMException = require("../generated/DOMException");
const { DOCUMENT_POSITION_CONTAINS, DOCUMENT_POSITION_CONTAINED_BY } = require("../node-document-position");
const Element = require("../generated/Element");
const Node = require("../generated/Node");
const HTMLCollectionImpl = require("./HTMLCollection-impl").implementation;
exports.implementation = class HTMLOptionsCollectionImpl extends HTMLCollectionImpl {
// inherits supported property indices
get length() {
this._update();
return this._list.length;
}
set length(value) {
this._update();
if (value > this._list.length) {
const doc = this._element._ownerDocument;
for (let i = this._list.length; i < value; i++) {
const el = doc.createElement("option");
this._element.appendChild(el);
}
} else if (value < this._list.length) {
for (let i = this._list.length - 1; i >= value; i--) {
const el = this._list[i];
this._element.removeChild(el);
}
}
}
get [idlUtils.supportedPropertyNames]() {
this._update();
const result = new Set();
for (const element of this._list) {
result.add(element.getAttributeNS(null, "id"));
result.add(element.getAttributeNS(null, "name"));
}
return result;
}
[idlUtils.indexedSetNew](index, value) {
if (value === null) {
this.remove(index);
return;
}
this._update();
const { length } = this._list;
const n = index - length;
if (n > 0) {
const doc = this._element._ownerDocument;
const frag = doc.createDocumentFragment();
// Spec says n - 1, but n seems to be the right number here.
for (let i = 0; i < n; i++) {
const el = doc.createElement("option");
frag.appendChild(el);
}
this._element._append(frag);
}
if (n >= 0) {
this._element._append(value);
} else {
this._element._replace(value, this._list[index]);
}
}
[idlUtils.indexedSetExisting](index, value) {
return this[idlUtils.indexedSetNew](index, value);
}
add(element, before) {
if (this._element.compareDocumentPosition(element) & DOCUMENT_POSITION_CONTAINS) {
throw DOMException.create(this._globalObject, [
"The operation would yield an incorrect node tree.",
"HierarchyRequestError"
]);
}
if (Element.isImpl(before) && !(this._element.compareDocumentPosition(before) & DOCUMENT_POSITION_CONTAINED_BY)) {
throw DOMException.create(this._globalObject, ["The object can not be found here.", "NotFoundError"]);
}
if (element === before) {
return;
}
let reference = null;
if (Node.isImpl(before)) {
reference = before;
} else if (typeof before === "number") {
this._update();
reference = this._list[before] || null;
}
const parent = reference !== null ? reference.parentNode : this._element;
parent._preInsert(element, reference);
}
remove(index) {
this._update();
if (this._list.length === 0) {
return;
}
if (index < 0 || index >= this._list.length) {
return;
}
const element = this._list[index];
element.parentNode._remove(element);
}
get selectedIndex() {
return this._element.selectedIndex;
}
set selectedIndex(value) {
this._element.selectedIndex = value;
}
};