/*
* 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);