/* * Copyright (C) 2019 Alex Yatskov * Author: Alex Yatskov * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ class ConditionsUI { static instantiateTemplate(templateSelector) { const template = document.querySelector(templateSelector); const content = document.importNode(template.content, true); return $(content.firstChild); } } ConditionsUI.Container = class Container { constructor(conditionDescriptors, conditionNameDefault, conditionGroups, container, addButton) { this.children = []; this.conditionDescriptors = conditionDescriptors; this.conditionNameDefault = conditionNameDefault; this.conditionGroups = conditionGroups; this.container = container; this.addButton = addButton; this.container.empty(); for (const conditionGroup of toIterable(conditionGroups)) { this.children.push(new ConditionsUI.ConditionGroup(this, conditionGroup)); } this.addButton.on('click', () => this.onAddConditionGroup()); } cleanup() { for (const child of this.children) { child.cleanup(); } this.addButton.off('click'); this.container.empty(); } save() { // Override } isolate(object) { // Override return object; } remove(child) { const index = this.children.indexOf(child); if (index < 0) { return; } child.cleanup(); this.children.splice(index, 1); this.conditionGroups.splice(index, 1); } onAddConditionGroup() { const conditionGroup = this.isolate({ conditions: [this.createDefaultCondition(this.conditionNameDefault)] }); this.conditionGroups.push(conditionGroup); this.save(); this.children.push(new ConditionsUI.ConditionGroup(this, conditionGroup)); } createDefaultCondition(type) { let operator = ''; let value = ''; if (this.conditionDescriptors.hasOwnProperty(type)) { const conditionDescriptor = this.conditionDescriptors[type]; operator = conditionDescriptor.defaultOperator; ({value} = this.getOperatorDefaultValue(type, operator)); if (typeof value === 'undefined') { value = ''; } } return {type, operator, value}; } getOperatorDefaultValue(type, operator) { if (this.conditionDescriptors.hasOwnProperty(type)) { const conditionDescriptor = this.conditionDescriptors[type]; if (conditionDescriptor.operators.hasOwnProperty(operator)) { const operatorDescriptor = conditionDescriptor.operators[operator]; if (operatorDescriptor.hasOwnProperty('defaultValue')) { return {value: operatorDescriptor.defaultValue, fromOperator: true}; } } if (conditionDescriptor.hasOwnProperty('defaultValue')) { return {value: conditionDescriptor.defaultValue, fromOperator: false}; } } return {fromOperator: false}; } }; ConditionsUI.ConditionGroup = class ConditionGroup { constructor(parent, conditionGroup) { this.parent = parent; this.children = []; this.conditionGroup = conditionGroup; this.container = $('
').addClass('condition-group').appendTo(parent.container); this.options = ConditionsUI.instantiateTemplate('#condition-group-options-template').appendTo(parent.container); this.separator = ConditionsUI.instantiateTemplate('#condition-group-separator-template').appendTo(parent.container); this.addButton = this.options.find('.condition-add'); for (const condition of toIterable(conditionGroup.conditions)) { this.children.push(new ConditionsUI.Condition(this, condition)); } this.addButton.on('click', () => this.onAddCondition()); } cleanup() { for (const child of this.children) { child.cleanup(); } this.addButton.off('click'); this.container.remove(); this.options.remove(); this.separator.remove(); } save() { this.parent.save(); } isolate(object) { return this.parent.isolate(object); } remove(child) { const index = this.children.indexOf(child); if (index < 0) { return; } child.cleanup(); this.children.splice(index, 1); this.conditionGroup.conditions.splice(index, 1); if (this.children.length === 0) { this.parent.remove(this, false); } } onAddCondition() { const condition = this.isolate(this.parent.createDefaultCondition(this.parent.conditionNameDefault)); this.conditionGroup.conditions.push(condition); this.children.push(new ConditionsUI.Condition(this, condition)); } }; ConditionsUI.Condition = class Condition { constructor(parent, condition) { this.parent = parent; this.condition = condition; this.container = ConditionsUI.instantiateTemplate('#condition-template').appendTo(parent.container); this.input = this.container.find('input'); this.typeSelect = this.container.find('.condition-type'); this.operatorSelect = this.container.find('.condition-operator'); this.removeButton = this.container.find('.condition-remove'); this.updateTypes(); this.updateOperators(); this.updateInput(); this.input.on('change', () => this.onInputChanged()); this.typeSelect.on('change', () => this.onConditionTypeChanged()); this.operatorSelect.on('change', () => this.onConditionOperatorChanged()); this.removeButton.on('click', () => this.onRemoveClicked()); } cleanup() { this.input.off('change'); this.typeSelect.off('change'); this.operatorSelect.off('change'); this.removeButton.off('click'); this.container.remove(); } save() { this.parent.save(); } updateTypes() { const conditionDescriptors = this.parent.parent.conditionDescriptors; const optionGroup = this.typeSelect.find('optgroup'); optionGroup.empty(); for (const type of Object.keys(conditionDescriptors)) { const conditionDescriptor = conditionDescriptors[type]; $('