/* * Copyright (C) 2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ WI.SettingEditor = class SettingEditor extends WI.Object { constructor(type, label, options) { super(); this._type = type; this._value = null; this._editorElement = this._createEditorElement(options); console.assert(this._editorElement); this._element = document.createElement("div"); this._element.classList.add("setting-editor"); this._element.append(this._editorElement); this.label = label; } static createForSetting(setting, label, options) { let type; if (typeof setting.value === "boolean") type = WI.SettingEditor.Type.Checkbox; else if (typeof setting.value === "number") type = WI.SettingEditor.Type.Numeric; console.assert(type, "Cannot deduce editor type from setting value type.", setting); if (!type) return null; let editor = new WI.SettingEditor(type, label, options); editor.value = setting.value; editor.addEventListener(WI.SettingEditor.Event.ValueDidChange, function(event) { this.value = editor.value; }, setting); setting.addEventListener(WI.Setting.Event.Changed, function(event) { this.value = setting.value; }, editor); return editor; } // Public get element() { return this._element; } get type() { return this._type; } get label() { return this._label; } set label(label) { if (label === this._label) return; this._label = label; if (!this._label) { if (this._labelElement) this._labelElement.remove(); this._editorElement.removeAttribute("id"); this._labelElement = null; return; } if (!this._labelElement) { this._editorElement.id = "setting-editor-" + WI.SettingEditor._nextEditorIdentifier++; this._labelElement = this._element.appendChild(document.createElement("label")); this._labelElement.setAttribute("for", this._editorElement.id); } this._labelElement.textContent = this._label; } get value() { return this._value; } set value(value) { if (this._value === value) return; let oldValue = this._value; this._value = value; if (this._type === WI.SettingEditor.Type.Checkbox) this._editorElement.checked = !!this._value; else this._editorElement.value = this._value; this.dispatchEventToListeners(WI.SettingEditor.Event.ValueDidChange, {oldValue}); } // Private _createEditorElement(options) { let editorElement; switch (this._type) { case WI.SettingEditor.Type.Checkbox: editorElement = document.createElement("input"); editorElement.type = "checkbox"; editorElement.addEventListener("change", (event) => { this.value = event.target.checked; }); break; case WI.SettingEditor.Type.Numeric: editorElement = document.createElement("input"); editorElement.type = "number"; if (options.min !== undefined) editorElement.min = options.min; if (options.max !== undefined) editorElement.max = options.max; editorElement.addEventListener("change", (event) => { let currentValue = this._value; let newValue = parseInt(event.target.value); this.value = isNaN(newValue) ? currentValue : newValue; }); break; case WI.SettingEditor.Type.Select: editorElement = document.createElement("select"); var keyValuePairs = []; console.assert(Array.isArray(options.values), "Expected values array for select editor.", options); if (Array.isArray(options.values[0])) keyValuePairs = options.values; else keyValuePairs = options.values.map((value) => [value, value]); for (let [key, value] of keyValuePairs) { if (key === WI.SettingEditor.SelectSpacerKey) { editorElement.appendChild(document.createElement("hr")); continue; } let optionElement = editorElement.appendChild(document.createElement("option")); optionElement.value = key; optionElement.textContent = value; } editorElement.addEventListener("change", (event) => { this.value = event.target.value; }); break; default: console.error("Unknown editor type: " + this._type); } return editorElement; } }; WI.SettingEditor._nextEditorIdentifier = 1; WI.SettingEditor.Type = { Checkbox: "setting-editor-type-checkbox", Numeric: "setting-editor-type-numeric", Select: "setting-editor-type-select", }; WI.SettingEditor.SelectSpacerKey = Symbol("setting-editor-select-spacer-key"); WI.SettingEditor.Event = { ValueDidChange: "value-did-change", };