/* * This file is part of Toolkit. * * Toolkit 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. * * Toolkit 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU General * Public License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * The useraction event is emitted when a widget gets modified by user interaction. * The event is emitted for the option value. * * @event TK.Value#useraction * * @param {string} name - The name of the option which was changed due to the users action * @param {mixed} value - The new value of the option */ "use strict"; (function(w, TK){ function value_clicked(e) { var O = this.options; if (O.set === false) return; if (this.__editing) return false; TK.add_class(this.element, "toolkit-active"); this._input.setAttribute("value", O.value); this.__editing = true; this._input.focus(); if (O.auto_select) this._input.setSelectionRange(0, this._input.value.length) /** * Is fired when the value was clicked. * * @event TK.Value#valueclicked * * @param {number} value - The value of the widget. */ this.fire_event("valueclicked", O.value); } function value_typing(e) { var O = this.options; if (O.set === false) return; if (!this.__editing) return; switch (e.keyCode) { case 27: // ESC value_done.call(this); /** * Is fired when the ESC key was pressed while editing the value. * * @event TK.Value#valueescape * * @param {string} value - The new value of the widget. */ this.fire_event("valueescape", O.value); break; case 13: // ENTER this.userset("value", O.set ? O.set(this._input.value) : this._input.value); value_done.call(this); /** * Is fired after the value has been set and editing has ended. * * @event TK.Value#valueset * * @param {string} value - The new value of the widget. */ this.fire_event("valueset", O.value); e.preventDefault(); return false; break; } /** * Is fired when the user hits a key while editing the value. * * @event TK.Value#valuetyping * * @param {DOMEvent} event - The native DOM event. * @param {string} value - The new value of the widget. */ this.fire_event("valuetyping", e, O.value); } function value_input() { var O = this.options; if (O.set === false) return; if (!this.__editing) return; if (O.editmode == "immediate") this.userset("value", O.set ? O.set(this._input.value) : this._input.value); } function value_done() { if (!this.__editing) return; this.__editing = false; TK.remove_class(this.element, "toolkit-active"); this._input.blur(); /** * Is fired when editing of the value ends. * * @event TK.Value#valuedone * * @param {string} value - The new value of the widget. */ this.fire_event("valuedone", this.options.value); this.invalid.value = true; this.trigger_draw(); } function submit_cb(e) { e.preventDefault(); return false; } /** * TK.Value is a formatted text field displaying values and providing * an input field for editing the value. * * @class TK.Value * * @extends TK.Widget * * @param {Object} [options={ }] - An object containing initial options. * * @property {Number} [options.value=0] - The value. * @property {Function} [options.format=TK.FORMAT("%.2f")] - A formatting * function used to display the value. * @property {Integer} [options.size=5] - Size attribute of the INPUT element. * @property {Integer} [options.maxlength] - Maxlength attribute of the INPUT element. * @property {Function} [options.set=function (val) { return parseFloat(val || 0); }] - * A function which is called to parse user input. * @property {boolean} [options.auto_select=false] - Select the entire text in the entry field if clicked (new in v1.3). * @property {boolean} [options.readonly=false] - Sets the readonly attribute (new in v1.3). * @property {string} [options.placeholder=""] - Sets the placeholder attribute (new in v1.3). * @property {string} [options.type="text"] - Sets the type attribute. Type can be either `text` or `password` (new in v1.3). * @property {string} [options.editmode="onenter"] - Sets the event to trigger the userset event. Can be one out of `onenter` or `immediate`. * */ TK.Value = TK.class({ _class: "Value", Extends: TK.Widget, _options: Object.assign(Object.create(TK.Widget.prototype._options), { value: "number|string", format: "function", size: "number", maxlength: "int", set: "object|function|boolean", auto_select: "boolean", readonly: "boolean", placeholder: "string", type: "string", editmode: "string", }), options: { value: 0, format: TK.FORMAT("%.2f"), size: 5, container: false, // set a callback function if value is editable or // false to disable editing. A function has to return // the value treated by the parent widget. set: function (val) { return parseFloat(val || 0); }, auto_select: false, readonly: false, placeholder: "", type: "text", editmode: "onenter", }, static_events: { submit: submit_cb, click: value_clicked, }, initialize: function (options) { var E; TK.Widget.prototype.initialize.call(this, options); /** * @member {HTMLDivElement} TK.Value#element - The main DIV container. * Has class toolkit-value. */ if (!(E = this.element)) this.element = E = TK.element("div"); TK.add_class(E, "toolkit-value"); this.widgetize(E, true, true, true); /** * @member {HTMLInputElement} TK.Value#_input - The text input. * Has class toolkit-input. */ this._input = TK.element("input", "toolkit-input"); this._input.type = "text"; E.appendChild(this._input); this._value_typing = value_typing.bind(this); this._value_done = value_done.bind(this); this._value_input = value_input.bind(this); this._input.addEventListener("keyup", this._value_typing); this._input.addEventListener("input", this._value_input); this._input.addEventListener("blur", this._value_done); this.__editing = false; }, redraw: function () { var I = this.invalid; var O = this.options; var E = this._input; TK.Widget.prototype.redraw.call(this); if (I.size) { I.size = 0; E.setAttribute("size", O.size); } if (I.maxlength) { I.maxlength = 0; if (O.maxlength) E.setAttribute("maxlength", O.maxlength); else E.removeAttribute("maxlength"); } if (I.placeholder) { I.placeholder = 0; if (O.placeholder) E.setAttribute("placeholder", O.placeholder); else E.removeAttribute("placeholder"); } if ((I.value || I.format) && !this.__editing) { I.format = I.value = false; E.value = O.format(O.value); } if (I.readonly) { I.readonly = 0; if (O.readonly) E.setAttribute("readonly", "readonly"); else E.removeAttribute("readonly"); } if (I.type) { I.type = 0; E.setAttribute("type", O.type); } }, destroy: function () { this._input.removeEventListener("keyup", this._value_typing); this._input.removeEventListener("blur", this._value_done); this._input.removeEventListener("input", this._value_input); this._input.remove(); TK.Widget.prototype.destroy.call(this); }, }); })(this, this.TK);