|
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- const HTMLElement_1 = __importDefault(require("../html-element/HTMLElement"));
- const ValidityState_1 = __importDefault(require("../validity-state/ValidityState"));
- const HTMLOptionsCollection_1 = __importDefault(require("../html-option-element/HTMLOptionsCollection"));
- const NodeTypeEnum_1 = __importDefault(require("../node/NodeTypeEnum"));
- /**
- * HTML Select Element.
- *
- * Reference:
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement.
- */
- class HTMLSelectElement extends HTMLElement_1.default {
- constructor() {
- super(...arguments);
- this.options = new HTMLOptionsCollection_1.default(this);
- // Events
- this.onchange = null;
- this.oninput = null;
- }
- /**
- * Returns name.
- *
- * @returns Name.
- */
- get name() {
- return this.getAttributeNS(null, 'name') || '';
- }
- /**
- * Sets name.
- *
- * @param name Name.
- */
- set name(name) {
- this.setAttributeNS(null, 'name', name);
- }
- /**
- * Returns disabled.
- *
- * @returns Disabled.
- */
- get disabled() {
- return this.getAttributeNS(null, 'disabled') !== null;
- }
- /**
- * Sets disabled.
- *
- * @param disabled Disabled.
- */
- set disabled(disabled) {
- if (!disabled) {
- this.removeAttributeNS(null, 'disabled');
- }
- else {
- this.setAttributeNS(null, 'disabled', '');
- }
- }
- /**
- * Returns multiple.
- *
- * @returns Multiple.
- */
- get multiple() {
- return this.getAttributeNS(null, 'multiple') !== null;
- }
- /**
- * Sets multiple.
- *
- * @param multiple Multiple.
- */
- set multiple(multiple) {
- if (!multiple) {
- this.removeAttributeNS(null, 'multiple');
- }
- else {
- this.setAttributeNS(null, 'multiple', '');
- }
- }
- /**
- * Returns autofocus.
- *
- * @returns Autofocus.
- */
- get autofocus() {
- return this.getAttributeNS(null, 'autofocus') !== null;
- }
- /**
- * Sets autofocus.
- *
- * @param autofocus Autofocus.
- */
- set autofocus(autofocus) {
- if (!autofocus) {
- this.removeAttributeNS(null, 'autofocus');
- }
- else {
- this.setAttributeNS(null, 'autofocus', '');
- }
- }
- /**
- * Returns length.
- *
- * @returns length.
- */
- get length() {
- return this.options.length;
- }
- /**
- * Sets length.
- *
- * @param length Length.
- */
- set length(length) {
- this.options.length = length;
- }
- /**
- * Returns required.
- *
- * @returns Required.
- */
- get required() {
- return this.getAttributeNS(null, 'required') !== null;
- }
- /**
- * Sets required.
- *
- * @param required Required.
- */
- set required(required) {
- if (!required) {
- this.removeAttributeNS(null, 'required');
- }
- else {
- this.setAttributeNS(null, 'required', '');
- }
- }
- /**
- * Returns type.
- *
- * @returns type.
- */
- get type() {
- return this.hasAttributeNS(null, 'multiple') ? 'select-multiple' : 'select-one';
- }
- /**
- * Returns value.
- *
- * @returns Value.
- */
- get value() {
- for (let i = 0, max = this.options.length; i < max; i++) {
- const option = this.options[i];
- if (option._selectedness) {
- return option.value;
- }
- }
- return '';
- }
- /**
- * Sets value.
- *
- * @param value Value.
- */
- set value(value) {
- for (let i = 0, max = this.options.length; i < max; i++) {
- const option = this.options[i];
- if (option.value === value) {
- option._selectedness = true;
- option._dirtyness = true;
- }
- else {
- option._selectedness = false;
- }
- }
- }
- /**
- * Returns value.
- *
- * @returns Value.
- */
- get selectedIndex() {
- for (let i = 0, max = this.options.length; i < max; i++) {
- if (this.options[i]._selectedness) {
- return i;
- }
- }
- return -1;
- }
- /**
- * Sets value.
- *
- * @param selectedIndex Selected index.
- */
- set selectedIndex(selectedIndex) {
- if (typeof selectedIndex === 'number' && !isNaN(selectedIndex)) {
- for (let i = 0, max = this.options.length; i < max; i++) {
- this.options[i]._selectedness = false;
- }
- const selectedOption = this.options[selectedIndex];
- if (selectedOption) {
- selectedOption._selectedness = true;
- selectedOption._dirtyness = true;
- }
- }
- }
- /**
- * Returns the parent form element.
- *
- * @returns Form.
- */
- get form() {
- let parent = this.parentNode;
- while (parent && parent.tagName !== 'FORM') {
- parent = parent.parentNode;
- }
- return parent;
- }
- /**
- * Returns validity state.
- *
- * @returns Validity state.
- */
- get validity() {
- return new ValidityState_1.default(this);
- }
- /**
- * Returns "true" if it will validate.
- *
- * @returns "true" if it will validate.
- */
- get willValidate() {
- return (this.type !== 'hidden' &&
- this.type !== 'reset' &&
- this.type !== 'button' &&
- !this.disabled &&
- !this['readOnly']);
- }
- /**
- * Returns item from options collection by index.
- *
- * @param index Index.
- */
- item(index) {
- return this.options.item(index);
- }
- /**
- * Adds new option to options collection.
- *
- * @param element HTMLOptionElement or HTMLOptGroupElement to add.
- * @param before HTMLOptionElement or index number.
- */
- add(element, before) {
- this.options.add(element, before);
- }
- /**
- * Removes indexed element from collection or the select element.
- *
- * @param [index] Index.
- */
- remove(index) {
- if (typeof index === 'number') {
- this.options.remove(index);
- }
- else {
- super.remove();
- }
- }
- /**
- * @override
- */
- appendChild(node) {
- if (node.nodeType === NodeTypeEnum_1.default.elementNode) {
- const element = node;
- const previousLength = this.options.length;
- if (element.tagName === 'OPTION' || element.tagName === 'OPTGROUP') {
- this.options.push(element);
- }
- this._updateIndexProperties(previousLength, this.options.length);
- this._resetOptionSelectednes();
- }
- return super.appendChild(node);
- }
- /**
- * @override
- */
- insertBefore(newNode, referenceNode) {
- const returnValue = super.insertBefore(newNode, referenceNode);
- if (newNode.nodeType === NodeTypeEnum_1.default.elementNode &&
- referenceNode?.nodeType === NodeTypeEnum_1.default.elementNode) {
- const newElement = newNode;
- const previousLength = this.options.length;
- if (newElement.tagName === 'OPTION' || newElement.tagName === 'OPTGROUP') {
- const referenceElement = referenceNode;
- if (referenceElement &&
- (referenceElement.tagName === 'OPTION' || referenceElement.tagName === 'OPTGROUP')) {
- const referenceIndex = this.options.indexOf(referenceElement);
- if (referenceIndex !== -1) {
- this.options.splice(referenceIndex, 0, newElement);
- }
- }
- else {
- this.options.push(newElement);
- }
- }
- this._updateIndexProperties(previousLength, this.options.length);
- }
- if (newNode.nodeType === NodeTypeEnum_1.default.elementNode) {
- this._resetOptionSelectednes();
- }
- return returnValue;
- }
- /**
- * @override
- */
- removeChild(node) {
- if (node.nodeType === NodeTypeEnum_1.default.elementNode) {
- const element = node;
- const previousLength = this.options.length;
- if (element.tagName === 'OPTION' || element.tagName === 'OPTION') {
- const index = this.options.indexOf(node);
- if (index !== -1) {
- this.options.splice(index, 1);
- }
- }
- this._updateIndexProperties(previousLength, this.options.length);
- this._resetOptionSelectednes();
- }
- return super.removeChild(node);
- }
- /**
- * Resets the option selectedness.
- *
- * Based on:
- * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/nodes/HTMLSelectElement-impl.js
- *
- * @param [newOption] Optional new option element to be selected.
- * @see https://html.spec.whatwg.org/multipage/form-elements.html#selectedness-setting-algorithm
- */
- _resetOptionSelectednes(newOption) {
- if (this.hasAttributeNS(null, 'multiple')) {
- return;
- }
- const selected = [];
- for (let i = 0, max = this.options.length; i < max; i++) {
- if (newOption) {
- this.options[i]._selectedness = this.options[i] === newOption;
- }
- if (this.options[i]._selectedness) {
- selected.push(this.options[i]);
- }
- }
- const size = this._getDisplaySize();
- if (size === 1 && !selected.length) {
- for (let i = 0, max = this.options.length; i < max; i++) {
- const option = this.options[i];
- let disabled = option.hasAttributeNS(null, 'disabled');
- const parentNode = option.parentNode;
- if (parentNode &&
- parentNode.nodeType === NodeTypeEnum_1.default.elementNode &&
- parentNode.tagName === 'OPTGROUP' &&
- parentNode.hasAttributeNS(null, 'disabled')) {
- disabled = true;
- }
- if (!disabled) {
- option._selectedness = true;
- break;
- }
- }
- }
- else if (selected.length >= 2) {
- for (let i = 0, max = this.options.length; i < max; i++) {
- this.options[i]._selectedness = i === selected.length - 1;
- }
- }
- }
- /**
- * Returns display size.
- *
- * @returns Display size.
- */
- _getDisplaySize() {
- if (this.hasAttributeNS(null, 'size')) {
- const size = parseInt(this.getAttributeNS(null, 'size'));
- if (!isNaN(size) && size >= 0) {
- return size;
- }
- }
- return this.hasAttributeNS(null, 'multiple') ? 4 : 1;
- }
- /**
- * Updates index properties.
- *
- * @param previousLength Length before the update.
- * @param newLength Length after the update.
- */
- _updateIndexProperties(previousLength, newLength) {
- if (previousLength > newLength) {
- for (let i = newLength; i < previousLength; i++) {
- if (this.hasOwnProperty(String(i))) {
- delete this[String(i)];
- }
- }
- }
- else if (previousLength < newLength) {
- for (let i = previousLength; i < newLength; i++) {
- Object.defineProperty(this, String(i), {
- get: () => {
- return this.options[i];
- },
- enumerable: true,
- configurable: true
- });
- }
- }
- }
- }
- exports.default = HTMLSelectElement;
- //# sourceMappingURL=HTMLSelectElement.js.map
|