Implement some basic client-side validation (required)

This commit is contained in:
Nathan Gray 2013-06-26 20:50:10 +00:00
parent a0cba996a0
commit 0c6f70005a
11 changed files with 81 additions and 29 deletions

View File

@ -112,7 +112,7 @@ var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned,
.addClass("message") .addClass("message")
.addClass(_type) .addClass(_type)
.addClass(_floating ? "floating" : "") .addClass(_floating ? "floating" : "")
.text(_text); .text(_text.valueOf() + "");
// Decide whether to prepend or append the div // Decide whether to prepend or append the div
if (_prepend) if (_prepend)
@ -152,10 +152,11 @@ var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned,
{ {
var surr = this.getSurroundings(); var surr = this.getSurroundings();
var self = this; var self = this;
var messageDiv = this._messageDiv;
self._messageDiv = null;
var _done = function() { var _done = function() {
surr.removeDOMNode(self._messageDiv[0]); surr.removeDOMNode(messageDiv[0]);
self._messageDiv = null;
// Update the surroundings manager // Update the surroundings manager
if (!_noUpdate) if (!_noUpdate)
@ -167,7 +168,7 @@ var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned,
// Either fade out or directly call the function which removes the div // Either fade out or directly call the function which removes the div
if (_fade) if (_fade)
{ {
this._messageDiv.fadeOut("fast", _done); messageDiv.fadeOut("fast", _done);
} }
else else
{ {

View File

@ -25,10 +25,10 @@
* *
* @augments et2_valueWidget * @augments et2_valueWidget
*/ */
var et2_inputWidget = et2_valueWidget.extend(et2_IInput, var et2_inputWidget = et2_valueWidget.extend([et2_IInput,et2_ISubmitListener],
{ {
attributes: { attributes: {
"required": { "needed": {
"name": "Required", "name": "Required",
"default": false, "default": false,
"type": "boolean", "type": "boolean",
@ -124,10 +124,17 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput,
}, },
change: function(_node) { change: function(_node) {
if (this.onchange) var messages = [];
var valid = this.isValid(messages);
// Passing false will clear any set messages
this.set_validation_error(valid ? false : messages);
if (valid && this.onchange)
{ {
return et2_compileLegacyJS(this.onchange, this, _node)(); return et2_compileLegacyJS(this.onchange, this, _node)();
} }
return valid;
}, },
set_value: function(_value) { set_value: function(_value) {
@ -218,7 +225,7 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput,
this.label = _value; this.label = _value;
}, },
set_required: function(_value) { set_needed: function(_value) {
var node = this.getInputNode(); var node = this.getInputNode();
if (node) if (node)
{ {
@ -281,7 +288,34 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput,
resetDirty: function() { resetDirty: function() {
this._oldValue = this.getValue(); this._oldValue = this.getValue();
} },
isValid: function(messages) {
var ok = true;
// Check for required
if(this.options.needed && (this.getValue() == null || this.getValue().valueOf() == ''))
{
messages.push(this.egw().lang('input required'));
ok = false;
}
return ok;
},
/**
* Called whenever the template gets submitted. We return false if the widget
* is not valid, which cancels the submission.
*
* @param _values contains the values which will be sent to the server.
* Listeners may change these values before they get submitted.
*/
submit: function(_values) {
var messages = [];
var valid = this.isValid(messages);
// Passing false will clear any set messages
this.set_validation_error(valid ? false : messages);
return valid;
}
}); });

View File

@ -57,7 +57,23 @@ var et2_IInput = new Interface({
/** /**
* Causes the dirty flag to be reseted. * Causes the dirty flag to be reseted.
*/ */
resetDirty: function() {} resetDirty: function() {},
/**
* Checks the data to see if it is valid, as far as the client side can tell.
* Return true if it's not possible to tell on the client side, because the server
* will have the chance to validate also.
*
* The messages array is to be populated with everything wrong with the data,
* so don't stop checking after the first problem unless it really makes sense
* to ignore other problems.
*
* @param {String[]} messages List of messages explaining the failure(s).
* messages should be fairly short, and already translated.
*
* @return {boolean} True if the value is valid (enough), false to fail
*/
isValid: function(messages) {}
}); });
/** /**

View File

@ -190,7 +190,7 @@ var et2_customfields_list = et2_valueWidget.extend([et2_IDetachedDOM, et2_IInput
var attrs = { var attrs = {
'id': id, 'id': id,
'statustext': field.help, 'statustext': field.help,
'required': field.needed, 'needed': field.needed,
'readonly': this.options.readonly, 'readonly': this.options.readonly,
'value': this.options.value[this.prefix+field_name] 'value': this.options.value[this.prefix+field_name]
}; };
@ -371,6 +371,11 @@ var et2_customfields_list = et2_valueWidget.extend([et2_IDetachedDOM, et2_IInput
} }
}, },
isValid: function() {
// Individual customfields will handle themselves
return true;
},
/** /**
* Adapt provided attributes to match options for widget * Adapt provided attributes to match options for widget
*/ */

View File

@ -248,6 +248,9 @@ var et2_button = et2_baseWidget.extend([et2_IInput, et2_IDetachedDOM],
// array. // array.
return null; return null;
}, },
isValid: function() {
return true;
},
/** /**
* et2_IDetachedDOM * et2_IDetachedDOM

View File

@ -867,7 +867,7 @@ var et2_link = et2_valueWidget.extend([et2_IDetachedDOM],
description: "Array with keys app, id, and optionally title", description: "Array with keys app, id, and optionally title",
type: "any" type: "any"
}, },
"required": { "needed": {
"ignore": true "ignore": true
} }
}, },

View File

@ -236,7 +236,7 @@ var et2_radioGroup = et2_valueWidget.extend([et2_IDetachedDOM],
"default": {}, "default": {},
"description": "Options for radio buttons. Should be {value: label, ...}" "description": "Options for radio buttons. Should be {value: label, ...}"
}, },
"required": { "needed": {
"name": "Required", "name": "Required",
"default": false, "default": false,
"type": "boolean", "type": "boolean",
@ -258,7 +258,7 @@ var et2_radioGroup = et2_valueWidget.extend([et2_IDetachedDOM],
this.node = $j(document.createElement("div")) this.node = $j(document.createElement("div"))
.addClass("et2_vbox") .addClass("et2_vbox")
.addClass("et2_box_widget"); .addClass("et2_box_widget");
if(this.options.required) if(this.options.needed)
{ {
// This isn't strictly allowed, but it works // This isn't strictly allowed, but it works
this.node.attr("required","required"); this.node.attr("required","required");
@ -298,7 +298,7 @@ var et2_radioGroup = et2_valueWidget.extend([et2_IDetachedDOM],
ro_true: this.options.ro_true, ro_true: this.options.ro_true,
ro_false: this.options.ro_false, ro_false: this.options.ro_false,
readonly: this.options.readonly, readonly: this.options.readonly,
required: this.options.required needed: this.options.needed
}; };
var radio = et2_createWidget("radio", attrs, this); var radio = et2_createWidget("radio", attrs, this);
} }

View File

@ -72,7 +72,7 @@ var et2_selectAccount = et2_selectbox.extend(
} }
// If not required, make sure there's an empty label // If not required, make sure there's an empty label
if(_attrs['rows'] == 1 && !_attrs['empty_label'] && !_attrs['required']) if(_attrs['rows'] == 1 && !_attrs['empty_label'] && !_attrs['needed'])
{ {
_attrs['empty_label'] = 'None'; _attrs['empty_label'] = 'None';
} }

View File

@ -304,6 +304,9 @@ var et2_tabbox = et2_valueWidget.extend([et2_IInput],
resetDirty: function() resetDirty: function()
{ {
this.value = this.selected_index; this.value = this.selected_index;
},
isValid: function(messages) {
return true;
} }
}); });
et2_register_widget(et2_tabbox, ["tabbox"]); et2_register_widget(et2_tabbox, ["tabbox"]);

View File

@ -208,7 +208,7 @@ var et2_textbox_ro = et2_valueWidget.extend([et2_IDetachedDOM],
"size": { "size": {
"ignore": true "ignore": true
}, },
"required": { "needed": {
"ignore": true "ignore": true
} }
}, },

View File

@ -115,7 +115,6 @@ etemplate2.prototype.clear = function()
{ {
if (this.widgetContainer != null) if (this.widgetContainer != null)
{ {
// $j(':input',this.DOMContainer).validator().data("validator").destroy();
this.widgetContainer.free(); this.widgetContainer.free();
this.widgetContainer = null; this.widgetContainer = null;
} }
@ -262,15 +261,6 @@ etemplate2.prototype.load = function(_name, _url, _data, _callback)
etemplate2.prototype.submit = function(button) etemplate2.prototype.submit = function(button)
{ {
// Validator
/*var valid = true;
var inputs = $j(':input',this.DOMContainer).each(function() {
if(typeof $j(this).data("validator") == "undefined") return true;
valid = valid && $j(this).data("validator").checkValidity();
return true;
});
if(!valid) return false;*/
// Get the form values // Get the form values
var values = this.getValues(this.widgetContainer); var values = this.getValues(this.widgetContainer);