Source: inputitemwrapper.js

"use strict";

/**
 * InputItemWrapper wraps InputItem to take care of displaying input labels and possible errors.
 * It isn't responsible for the dragging functionality itself, but takses care of actions that are related to it.
 */
class InputItemWrapper extends CommonFormMethods {
	/**
	 * Create InputItemWrapper. 
	 * @param {QueryDataBlock} queryData - An instance of QueryData.
	 * @param {number} index - Order index of the input item in a query.
	 */
	constructor(queryData, index) {
		if(!queryData) {
			throw new InputItemWrapperException("No data passed when creating a new instance of InputItemWrapper");
		}
		if(!queryData instanceof QueryDataBlock) {
			throw new InputItemWrapperException("Data passed when creating new instance of InputItemWrapper were not an instance of a QueryDataBlock");
		}
		
		super();
		
		this.queryData = queryData;
		this.index = !isNaN(index) ? index : null;
		this.input = null;
		this.errorTag = null;
		
		this.valid = true;
	}
	
	/**
	 * Creates InputItem and assigns it into this InputItemWrapper.
	 * @return {InputItemWrapper} - This instance.
	 */
	createInput() {
		this.dom = document.createElement("div");
		this.dom.classList.add("dt-section-container-wrapper");
		this.createLabel();
		
		this.input = new InputItem(this.queryData, this.index).createInput();
		this.input.validation = this.checkRule;
		this.dom.appendChild(this.input.dom);
		this.createErrorTag();
		
		return this;
	}
	
	/**
	 * Creates DOM label for this InputItemWrapper.
	 * @return {InputItemWrapper} - This instance.
	 */
	createLabel() {
		let containerLabel = this.queryData.label;
		let itemLabel = this.queryData.items.length > 0 && this.index != null;
		
		if(containerLabel || itemLabel) {
			let labelTag = document.createElement("label");
			
			if(containerLabel) {
				labelTag.classList.add("dt-section-container-label", this.queryData.type);
				labelTag.textContent = this.queryData.label;
			}
			if(itemLabel) {
				labelTag.textContent = this.queryData.items[this.index].label;
			}
			
			labelTag.setAttribute("for", this.htmlId);
			this.dom.appendChild(labelTag);
		}
		
		return this;
	}
	
	/*  */
	/**
	 * Creates Input Error Message DOM.
	 * @return {InputItemWrapper} - This instance.
	 */
	createErrorTag() {
		if(this.queryData.error) {
			this.errorTag = document.createElement("span");
			this.errorTag.classList.add("dt-section-container-error");
			this.dom.appendChild(this.errorTag);

			this.input.onInputValueChange(() => {
				this.setValid(true);
			});
		}
		
		return this;
	}
	
	/**
	 * Validates this InputItemWrapper, requests InputItem validation.
	 * @return {(Object|false)} - Data validation summary from the assigned InputItem {valid:boolean, data:inputData, inputWrapper:this, inputItem:InputItem} or false if none assigned.
	 */
	validate() {
		if(this.input) {
			var valid = this.input.validate();
			this.setValid();
			
			return {
				valid: valid,
				data: this.input.inputData,
				inputWrapper: this,
				inputItem: this.input
			};
		}
		return false;
	}
	
	/**
	 * Displays validation state using the errorTag, setting or unsetting classnames for them to by styllable.
	 * @param {boolean} [overwriteGraphicsTo] - If set to true, the InputItemWrapper will be force-set to valid.
	 * @return {OptionItem} - This instance.
	 */
	setValid(overwriteGraphicsTo) {
		if(this.input.valid || overwriteGraphicsTo == true) {
			if(this.queryData.error && this.errorTag) {
				this.errorTag.innerText = "";
			}
			this.dom.classList.remove("invalid");
		}
		else {
			if(this.errorTag) {
				this.errorTag.innerText = this.currentSubItem.error || this.queryData.error || "Bad content";
			}
			this.dom.classList.add("invalid");
		}
		
		return this;
	}
}

/**
 * Exception block for InputItemWrapper
 * @see {@link https://developer.mozilla.org/cs/docs/Web/JavaScript/Reference/Statements/throw|MDN Throw Statement}
 * @param {Object} message - Exception message Object.
 * @param {string} message.message - Message text.
 */
function InputItemWrapperException(message) {
	this.message = message;
	this.name = "InputItemWrapper";
}