Source: optionitem.js

"use strict";

/**
 * OptionItem takes care of Draggable option elements on page.
 * It isn't responsible for the dragging functionality itself, but takses care of actions that are related to it.
 */
class OptionItem extends CommonFormMethods {
	/**
	 * Create OptionItem. 
	 * @param {QueryDataBlock} queryData - An instance of QueryData.
	 * @param {number} index - Order index of the option item in a query.
	 */
	constructor(queryData, index) {
		if(!queryData) {
			throw new OptionItemException("No data passed when creating a new instance of OptionItem");
		}
		if(!queryData instanceof QueryDataBlock) {
			throw new OptionItemException("Data passed when creating new instance of OptionItem were not an instance of a QueryDataBlock");
		}
		
		super();
		
		this.queryData = queryData;
		this.inputItem = null;
		this.index = index;
		
		return this;
	}
	
	/**
	 * Gets inputItem.
	 * @return {InputItem} - An InputItem object instance related to this OptionItem.
	 */
	get input() {
		return this.inputItem;
	}
	
	/**
	 * Gets data Object for this OptionItem.
	 * @return {Object} - This option data from QueryDataBlock instance.
	 */
	get scope() {
		return this.queryData.options[this.index];
	}

	/**
	 * Sets InputItem to be related with this instance of OptionItem.
	 * Eg. if this option item has been moved over the dom input element.
	 * @param {InputItem} inputItem - The InputItem instance.
	 */
	set input(inputItem) {
		this.inputItem = inputItem;
		this.inputItem.option = this;
		
		this.dom.classList.add("is-inside-container");
		this.dom.classList.remove("is-out-of-container");
	}
	
	/**
	 * Creates a dom representation of this OptionItem.
	 * @return {OptionItem} - This instance.
	 */
	createOption() {
		this.dom = document.createElement("div");
		this.dom.classList.add("dt-section-container-option-" + String(this.index));
		this.dom.setAttribute("id", this.scope.htmlId);
		this.dom.textContent = this.scope.text;
		CommonFormFunctions.appendStyle(this.dom, this.scope.css);
		
		return this;
	}
	
	/**
	 * Removes assigned InputItem from an OptionItem instance.
	 * Eg. if this option item has been moved outside of the dom input element.
	 * @return {OptionItem} - This instance.
	 */
	deleteInput() {
		if(this.input) {
			var optionIndex = this.inputItem.internalValue.assignedOptions.indexOf(this);
			this.inputItem.deleteOption(this);
			this.inputItem = null;
			
			this.dom.classList.add("is-out-of-container");
			this.dom.classList.remove("is-inside-container");
			return true;
		}
		return false;
	}
	
	/**
	 * Supposed to be called on OptionItem position change (user drag) and calls the other necessary methods.
	 * @param {InputItem} [inputItem] - If set to the instance of InputItem it will be assigned to this QueryItem an registered as "beign in its scope".
	 * @return {OptionItem} - This instance.
	 */
	positionChanged(inputItem) {
		this.dom.classList.remove("dt-option-reset");
		
		// Backup revious input before modifying it.
		var originalInput = this.input || null;
		
		if(typeof inputItem !== typeof undefined && inputItem instanceof InputItem) {
			this.input = inputItem;
			inputItem.changeAssignedOptionsValue();
		}
		
		if(originalInput !== inputItem && originalInput instanceof InputItem) {
			originalInput.deleteOption(this);
			originalInput.changeAssignedOptionsValue();
		}
		
		if(!inputItem) {
			this.deleteInput();
		}
		
		return this;
	}
}

/**
 * Exception block for OptionItem
 * @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 OptionItemException(message) {
	this.message = message;
	this.name = "OptionItem";
}