UNPKG

enolib

Version:

The eno standard library

174 lines (141 loc) 5.88 kB
const empty_module = require('./empty.js'); const field_module = require('./field.js'); const fieldset_module = require('./fieldset.js'); const list_module = require('./list.js'); const section_module = require('./section.js'); const { ElementBase } = require('./element_base.js'); const { errors } = require('../errors/validation.js'); const { EMPTY, FIELD, FIELDSET, FIELD_OR_FIELDSET_OR_LIST, LIST, MULTILINE_FIELD_BEGIN, PRETTY_TYPES, SECTION } = require('../constants.js'); // TODO: If this SectionElement gets touched (this._touched = true;), // the touched flag needs to be propagated down the hierarchy // when toSomething() is called to typecast the SectionElement. // I.e. the constructors for Field/Fieldset/etc. need to accept // this extra init parameter probably and it has to be passed // on lazily all the way down to the terminal leaves of the tree. // (applies to all implementations) class SectionElement extends ElementBase { _untouched() { if(!this.hasOwnProperty('_yielded') && !this.hasOwnProperty('_touched')) return this._instruction; if(this.hasOwnProperty('_empty') && !this._empty.hasOwnProperty('_touched')) return this._instruction; if(this.hasOwnProperty('_field') && !this._field.hasOwnProperty('_touched')) return this._instruction; if(this.hasOwnProperty('_fieldset')) return this._fieldset._untouched(); if(this.hasOwnProperty('_list')) return this._list._untouched(); if(this.hasOwnProperty('_section')) return this._section._untouched(); } _yields() { if(this._instruction.type === FIELD_OR_FIELDSET_OR_LIST) return `${PRETTY_TYPES[FIELD]},${PRETTY_TYPES[FIELDSET]},${PRETTY_TYPES[LIST]}`; return PRETTY_TYPES[this._instruction.type]; } toEmpty() { if(!this.hasOwnProperty('_empty')) { if(this._instruction.type !== EMPTY) throw errors.unexpectedElementType(this._context, null, this._instruction, 'expectedEmpty'); this._empty = new empty_module.Empty(this._context, this._instruction, this._parent); this._yielded = EMPTY; } return this._empty; } toField() { if(!this.hasOwnProperty('_field')) { if(this.hasOwnProperty('_yielded')) throw new Error(`This element was already yielded as ${PRETTY_TYPES[this._yielded]} and can't be yielded again as a field.`); if(this._instruction.type != FIELD && this._instruction.type !== MULTILINE_FIELD_BEGIN && this._instruction.type !== FIELD_OR_FIELDSET_OR_LIST) throw errors.unexpectedElementType(this._context, null, this._instruction, 'expectedField'); this._field = new field_module.Field(this._context, this._instruction, this._parent); this._yielded = FIELD; } return this._field; } toFieldset() { if(!this.hasOwnProperty('_fieldset')) { if(this.hasOwnProperty('_yielded')) throw new Error(`This element was already yielded as ${PRETTY_TYPES[this._yielded]} and can't be yielded again as a fieldset.`); if(this._instruction.type !== FIELDSET && this._instruction.type !== FIELD_OR_FIELDSET_OR_LIST) throw errors.unexpectedElementType(this._context, null, this._instruction, 'expectedFieldset'); this._fieldset = new fieldset_module.Fieldset(this._context, this._instruction, this._parent); this._yielded = FIELDSET; } return this._fieldset; } toList() { if(!this.hasOwnProperty('_list')) { if(this.hasOwnProperty('_yielded')) throw new Error(`This element was already yielded as ${PRETTY_TYPES[this._yielded]} and can't be yielded again as a list.`); if(this._instruction.type !== LIST && this._instruction.type !== FIELD_OR_FIELDSET_OR_LIST) throw errors.unexpectedElementType(this._context, null, this._instruction, 'expectedList'); this._list = new list_module.List(this._context, this._instruction, this._parent); this._yielded = LIST; } return this._list; } toSection() { if(!this.hasOwnProperty('_section')) { if(this._instruction.type !== SECTION) throw errors.unexpectedElementType(this._context, null, this._instruction, 'expectedSection'); this._section = new section_module.Section(this._context, this._instruction, this._parent); this._yielded = SECTION; } return this._section; } /** * Returns a debug representation of this {@link SectionElement} in the form of `[object SectionElement key=foo yields=field]`. * * @return {string} A debug representation of this {@link SectionElement}. */ toString() { return `[object SectionElement key=${this._key()} yields=${this._yields()}]`; } touch() { if(!this.hasOwnProperty('_yielded')) { this._touched = true; } else if(this.hasOwnProperty('_empty')) { this._empty._touched = true; } else if(this.hasOwnProperty('_field')) { this._field._touched = true; } else if(this.hasOwnProperty('_fieldset')) { this._fieldset.touch(); } else if(this.hasOwnProperty('_list')) { this._list.touch(); } else if(this.hasOwnProperty('_section')) { this._section.touch(); } } yieldsEmpty() { return this._instruction.type === EMPTY; } yieldsField() { return this._instruction.type === FIELD || this._instruction.type === MULTILINE_FIELD_BEGIN || this._instruction.type === FIELD_OR_FIELDSET_OR_LIST; } yieldsFieldset() { return this._instruction.type === FIELDSET || this._instruction.type === FIELD_OR_FIELDSET_OR_LIST; } yieldsList() { return this._instruction.type === LIST || this._instruction.type === FIELD_OR_FIELDSET_OR_LIST; } yieldsSection() { return this._instruction.type === SECTION; } } exports.SectionElement = SectionElement;