diff --git a/examples/widgetapp/own_validator.e b/examples/widgetapp/own_validator.e
new file mode 100644
index 00000000..1ba0395a
--- /dev/null
+++ b/examples/widgetapp/own_validator.e
@@ -0,0 +1,31 @@
+note
+ description: "Summary description for {OWN_VALIDATOR}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ OWN_VALIDATOR
+
+inherit
+
+ WSF_VALIDATOR [STRING]
+
+create
+ make_own
+
+feature {NONE}
+
+ make_own
+ do
+ error := "Input to long"
+ end
+
+feature
+
+ is_valid (input: STRING): BOOLEAN
+ do
+ Result := input.count < 5
+ end
+
+end
diff --git a/examples/widgetapp/sample_page.e b/examples/widgetapp/sample_page.e
index 6aec5cdf..91aa91de 100644
--- a/examples/widgetapp/sample_page.e
+++ b/examples/widgetapp/sample_page.e
@@ -19,19 +19,27 @@ feature
initialize_controls
local
form: WSF_FORM_CONTROL
+ n1_container: WSF_FORM_ELEMENT_CONTROL [STRING]
+ n2_container: WSF_FORM_ELEMENT_CONTROL [STRING]
do
- create textbox1.make_text ("txtBox1", "1")
- create textbox2.make_text ("txtBox2", "2")
+ create textbox1.make_input ("txtBox1", "1")
+ create textbox2.make_input ("txtBox2", "2")
create button1.make_button ("sample_button1", "SUM")
- create textbox_result.make_textarea ("txtBox3", "")
+ create textbox_result.make_html ("txtBox3","p", "")
button1.set_click_event (agent handle_click)
+ button1.add_class ("col-lg-offset-2")
create form.make_form_control ("panel")
form.add_class ("form-horizontal")
create cklist.make_checkbox_list_control ("categories")
cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make_checkbox ("net", "Network", "net"))
cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make_checkbox ("os", "Operating Systems", "os"))
- form.add_control (create {WSF_FORM_ELEMENT_CONTROL [STRING]}.make_form_element ("Number1", textbox1))
- form.add_control (create {WSF_FORM_ELEMENT_CONTROL [STRING]}.make_form_element ("Number2", textbox2))
+ create n1_container.make_form_element ("Number1", textbox1)
+ n1_container.add_validator (create {WSF_DECIMAL_VALIDATOR}.make_decimal_validator ("Invalid Number"))
+ n1_container.add_validator (create {OWN_VALIDATOR}.make_own)
+ create n2_container.make_form_element ("Number2", textbox2)
+ n2_container.add_validator (create {WSF_DECIMAL_VALIDATOR}.make_decimal_validator ("Invalid Number"))
+ form.add_control (n1_container)
+ form.add_control (n2_container)
form.add_control (create {WSF_FORM_ELEMENT_CONTROL [LIST [STRING]]}.make_form_element ("Categories", cklist))
form.add_control (button1)
form.add_control (create {WSF_FORM_ELEMENT_CONTROL [STRING]}.make_form_element ("Result", textbox_result))
@@ -42,13 +50,20 @@ feature
local
text: STRING
do
- text := textbox1.text + " + " + textbox2.text + " = " + (textbox1.text.to_integer_16 + textbox2.text.to_integer_16).out
- across
- cklist.value as s
- loop
- text.append ("%N-" + s.item)
+ if attached {WSF_FORM_CONTROL} control as form then
+ form.validate
+ if form.is_valid then
+ text := textbox1.text + " + " + textbox2.text + " = " + (textbox1.text.to_integer_64 + textbox2.text.to_integer_64).out
+ across
+ cklist.value as s
+ loop
+ text.append ("
-" + s.item)
+ end
+ textbox_result.set_html (text)
+ else
+ textbox_result.set_html ("VALIDATION ERROR")
+ end
end
- textbox_result.set_text (text)
end
process
@@ -57,12 +72,12 @@ feature
button1: WSF_BUTTON_CONTROL
- textbox1: WSF_TEXT_CONTROL
+ textbox1: WSF_INPUT_CONTROL
- textbox2: WSF_TEXT_CONTROL
+ textbox2: WSF_INPUT_CONTROL
cklist: WSF_CHECKBOX_LIST_CONTROL
- textbox_result: WSF_TEXTAREA_CONTROL
+ textbox_result: WSF_HTML_CONTROL
end
diff --git a/examples/widgetapp/widget.coffee b/examples/widgetapp/widget.coffee
index 9ca48ee9..417c5eb9 100644
--- a/examples/widgetapp/widget.coffee
+++ b/examples/widgetapp/widget.coffee
@@ -10,17 +10,56 @@ trigger_callback = (control_name,event)->
for name,state of new_states
controls[name]?.update(state)
return
+class WSF_VALIDATOR
+ constructor: (@parent_control, @settings)->
+ @error = @settings.error
+ return
+
+ validate: ()->
+ return true
+
+class WSF_REGEXP_VALIDATOR extends WSF_VALIDATOR
+ constructor: ()->
+ super
+ @pattern = new RegExp(@settings.expression,'g')
+
+ validate: ()->
+ val = @parent_control.value()
+ res = val.match(@pattern)
+ return (res!=null)
+
+validatormap =
+ "WSF_REGEXP_VALIDATOR":WSF_REGEXP_VALIDATOR
class WSF_CONTROL
constructor: (@control_name, @$el)->
- @attach_events()
return
attach_events: ()->
return
update: (state)->
- return
+ return
+
+ #Simple event listener
+
+ #subscribe to an event
+ on: (name, callback, context)->
+ if not @_events?
+ @_events = {}
+ if not @_events[name]?
+ @_events[name] = []
+ @_events[name].push({callback:callback,context:context})
+ return @
+
+ #trigger an event
+ trigger: (name)->
+ if not @_events?[name]?
+ return @
+ for ev in @_events[name]
+ ev.callback.call(ev.context)
+ return @
+
controls = {}
@@ -39,16 +78,21 @@ class WSF_BUTTON_CONTROL extends WSF_CONTROL
window.states[@control_name]['text'] = state.text
@$el.text(state.text)
-class WSF_TEXT_CONTROL extends WSF_CONTROL
+class WSF_INPUT_CONTROL extends WSF_CONTROL
attach_events: ()->
self = @
@$el.change ()->
self.change()
+
change: ()->
#update local state
window.states[@control_name]['text'] = @$el.val()
if window.states[@control_name]['callback_change']
trigger_callback(@control_name, 'change')
+ @trigger('change')
+
+ value:()->
+ return @$el.val()
update: (state) ->
if state.text?
@@ -65,6 +109,30 @@ class WSF_TEXTAREA_CONTROL extends WSF_CONTROL
window.states[@control_name]['text'] = @$el.val()
if window.states[@control_name]['callback_change']
trigger_callback(@control_name, 'change')
+ @trigger('change')
+
+ value:()->
+ return @$el.val()
+
+ update: (state) ->
+ if state.text?
+ window.states[@control_name]['text'] = state.text
+ @$el.val(state.text)
+
+class WSF_TEXTAREA_CONTROL extends WSF_CONTROL
+ attach_events: () ->
+ self = @
+ @$el.change () ->
+ self.change()
+
+ change: () ->
+ window.states[@control_name]['text'] = @$el.val()
+ if window.states[@control_name]['callback_change']
+ trigger_callback(@control_name, 'change')
+ @trigger('change')
+
+ value:()->
+ return @$el.val()
update: (state) ->
if state.text?
@@ -76,23 +144,85 @@ class WSF_CHECKBOX_CONTROL extends WSF_CONTROL
self = @
@$el.change ()->
self.change()
+
change: ()->
#update local state
window.states[@control_name]['checked'] = @$el.is(':checked')
if window.states[@control_name]['callback_change']
trigger_callback(@control_name, 'change')
+ @trigger('change')
+
+ value:()->
+ return @$el.is(':checked')
update: (state) ->
if state.text?
window.states[@control_name]['checked'] = state.checked
@$el.prop('checked',state.checked)
+class WSF_FORM_ELEMENT_CONTROL extends WSF_CONTROL
+ attach_events: ()->
+ self = @
+ @value_control = controls[window.states[@control_name]['value_control']]
+ if @value_control?
+ #subscribe to change event on value_control
+ @value_control.on('change',@change,@)
+ @serverside_validator = false
+ #Initialize validators
+ @validators = []
+ for validator in window.states[@control_name]['validators']
+ if validatormap[validator.name]?
+ @validators.push new validatormap[validator.name](@,validator)
+ else
+ #Use serverside validator if no js implementation
+ @serverside_validator = true
+ return
+
+ #value_control changed run validators
+ change: ()->
+ for validator in @validators
+ if not validator.validate()
+ @showerror(validator.error)
+ return
+ @showerror("")
+ #If there is validator which is not implemented in js ask server to validate
+ if @serverside_validator
+ trigger_callback(@control_name, 'validate')
+ return
+
+ showerror: (message)->
+ @$el.removeClass("has-error")
+ @$el.find(".validation").remove()
+ if message.length>0
+ @$el.addClass("has-error")
+ errordiv = $("
").addClass('help-block').addClass('validation').text(message)
+ @$el.find(".col-lg-10").append(errordiv)
+
+ update: (state) ->
+ if state.error?
+ @showerror(state.error)
+
+ value: ()->
+ @value_control.value()
+
+class WSF_HTML_CONTROL extends WSF_CONTROL
+
+ value:()->
+ return @$el.html()
+
+ update: (state) ->
+ if state.html?
+ window.states[@control_name]['html'] = state.html
+ @$el.html(state.html)
+
#map class name to effective class
typemap =
"WSF_BUTTON_CONTROL":WSF_BUTTON_CONTROL
- "WSF_TEXT_CONTROL":WSF_TEXT_CONTROL
+ "WSF_INPUT_CONTROL":WSF_INPUT_CONTROL
"WSF_TEXTAREA_CONTROL":WSF_TEXTAREA_CONTROL
"WSF_CHECKBOX_CONTROL":WSF_CHECKBOX_CONTROL
+ "WSF_FORM_ELEMENT_CONTROL": WSF_FORM_ELEMENT_CONTROL
+ "WSF_HTML_CONTROL": WSF_HTML_CONTROL
#create a js class for each control
for name,state of window.states
@@ -103,4 +233,6 @@ for name,state of window.states
#create class
if type? and typemap[type]?
controls[name]=new typemap[type](name,$el)
+for name,state of window.states
+ controls[name]?.attach_events()
diff --git a/examples/widgetapp/widget.js b/examples/widgetapp/widget.js
index 9cda85af..cab1a948 100644
--- a/examples/widgetapp/widget.js
+++ b/examples/widgetapp/widget.js
@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.1
(function() {
- var $el, WSF_BUTTON_CONTROL, WSF_CHECKBOX_CONTROL, WSF_CONTROL, WSF_TEXTAREA_CONTROL, WSF_TEXT_CONTROL, controls, name, state, trigger_callback, type, typemap, _ref,
+ var $el, WSF_BUTTON_CONTROL, WSF_CHECKBOX_CONTROL, WSF_CONTROL, WSF_FORM_ELEMENT_CONTROL, WSF_HTML_CONTROL, WSF_INPUT_CONTROL, WSF_REGEXP_VALIDATOR, WSF_TEXTAREA_CONTROL, WSF_VALIDATOR, controls, name, state, trigger_callback, type, typemap, validatormap, _ref, _ref1, _ref2,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
@@ -23,12 +23,52 @@
});
};
+ WSF_VALIDATOR = (function() {
+
+ function WSF_VALIDATOR(parent_control, settings) {
+ this.parent_control = parent_control;
+ this.settings = settings;
+ this.error = this.settings.error;
+ return;
+ }
+
+ WSF_VALIDATOR.prototype.validate = function() {
+ return true;
+ };
+
+ return WSF_VALIDATOR;
+
+ })();
+
+ WSF_REGEXP_VALIDATOR = (function(_super) {
+
+ __extends(WSF_REGEXP_VALIDATOR, _super);
+
+ function WSF_REGEXP_VALIDATOR() {
+ WSF_REGEXP_VALIDATOR.__super__.constructor.apply(this, arguments);
+ this.pattern = new RegExp(this.settings.expression, 'g');
+ }
+
+ WSF_REGEXP_VALIDATOR.prototype.validate = function() {
+ var res, val;
+ val = this.parent_control.value();
+ res = val.match(this.pattern);
+ return res !== null;
+ };
+
+ return WSF_REGEXP_VALIDATOR;
+
+ })(WSF_VALIDATOR);
+
+ validatormap = {
+ "WSF_REGEXP_VALIDATOR": WSF_REGEXP_VALIDATOR
+ };
+
WSF_CONTROL = (function() {
function WSF_CONTROL(control_name, $el) {
this.control_name = control_name;
this.$el = $el;
- this.attach_events();
return;
}
@@ -36,6 +76,33 @@
WSF_CONTROL.prototype.update = function(state) {};
+ WSF_CONTROL.prototype.on = function(name, callback, context) {
+ if (this._events == null) {
+ this._events = {};
+ }
+ if (this._events[name] == null) {
+ this._events[name] = [];
+ }
+ this._events[name].push({
+ callback: callback,
+ context: context
+ });
+ return this;
+ };
+
+ WSF_CONTROL.prototype.trigger = function(name) {
+ var ev, _i, _len, _ref, _ref1;
+ if (((_ref = this._events) != null ? _ref[name] : void 0) == null) {
+ return this;
+ }
+ _ref1 = this._events[name];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ ev = _ref1[_i];
+ ev.callback.call(ev.context);
+ }
+ return this;
+ };
+
return WSF_CONTROL;
})();
@@ -76,15 +143,15 @@
})(WSF_CONTROL);
- WSF_TEXT_CONTROL = (function(_super) {
+ WSF_INPUT_CONTROL = (function(_super) {
- __extends(WSF_TEXT_CONTROL, _super);
+ __extends(WSF_INPUT_CONTROL, _super);
- function WSF_TEXT_CONTROL() {
- return WSF_TEXT_CONTROL.__super__.constructor.apply(this, arguments);
+ function WSF_INPUT_CONTROL() {
+ return WSF_INPUT_CONTROL.__super__.constructor.apply(this, arguments);
}
- WSF_TEXT_CONTROL.prototype.attach_events = function() {
+ WSF_INPUT_CONTROL.prototype.attach_events = function() {
var self;
self = this;
return this.$el.change(function() {
@@ -92,21 +159,26 @@
});
};
- WSF_TEXT_CONTROL.prototype.change = function() {
+ WSF_INPUT_CONTROL.prototype.change = function() {
window.states[this.control_name]['text'] = this.$el.val();
if (window.states[this.control_name]['callback_change']) {
- return trigger_callback(this.control_name, 'change');
+ trigger_callback(this.control_name, 'change');
}
+ return this.trigger('change');
};
- WSF_TEXT_CONTROL.prototype.update = function(state) {
+ WSF_INPUT_CONTROL.prototype.value = function() {
+ return this.$el.val();
+ };
+
+ WSF_INPUT_CONTROL.prototype.update = function(state) {
if (state.text != null) {
window.states[this.control_name]['text'] = state.text;
return this.$el.val(state.text);
}
};
- return WSF_TEXT_CONTROL;
+ return WSF_INPUT_CONTROL;
})(WSF_CONTROL);
@@ -129,8 +201,52 @@
WSF_TEXTAREA_CONTROL.prototype.change = function() {
window.states[this.control_name]['text'] = this.$el.val();
if (window.states[this.control_name]['callback_change']) {
- return trigger_callback(this.control_name, 'change');
+ trigger_callback(this.control_name, 'change');
}
+ return this.trigger('change');
+ };
+
+ WSF_TEXTAREA_CONTROL.prototype.value = function() {
+ return this.$el.val();
+ };
+
+ WSF_TEXTAREA_CONTROL.prototype.update = function(state) {
+ if (state.text != null) {
+ window.states[this.control_name]['text'] = state.text;
+ return this.$el.val(state.text);
+ }
+ };
+
+ return WSF_TEXTAREA_CONTROL;
+
+ })(WSF_CONTROL);
+
+ WSF_TEXTAREA_CONTROL = (function(_super) {
+
+ __extends(WSF_TEXTAREA_CONTROL, _super);
+
+ function WSF_TEXTAREA_CONTROL() {
+ return WSF_TEXTAREA_CONTROL.__super__.constructor.apply(this, arguments);
+ }
+
+ WSF_TEXTAREA_CONTROL.prototype.attach_events = function() {
+ var self;
+ self = this;
+ return this.$el.change(function() {
+ return self.change();
+ });
+ };
+
+ WSF_TEXTAREA_CONTROL.prototype.change = function() {
+ window.states[this.control_name]['text'] = this.$el.val();
+ if (window.states[this.control_name]['callback_change']) {
+ trigger_callback(this.control_name, 'change');
+ }
+ return this.trigger('change');
+ };
+
+ WSF_TEXTAREA_CONTROL.prototype.value = function() {
+ return this.$el.val();
};
WSF_TEXTAREA_CONTROL.prototype.update = function(state) {
@@ -163,8 +279,13 @@
WSF_CHECKBOX_CONTROL.prototype.change = function() {
window.states[this.control_name]['checked'] = this.$el.is(':checked');
if (window.states[this.control_name]['callback_change']) {
- return trigger_callback(this.control_name, 'change');
+ trigger_callback(this.control_name, 'change');
}
+ return this.trigger('change');
+ };
+
+ WSF_CHECKBOX_CONTROL.prototype.value = function() {
+ return this.$el.is(':checked');
};
WSF_CHECKBOX_CONTROL.prototype.update = function(state) {
@@ -178,11 +299,105 @@
})(WSF_CONTROL);
+ WSF_FORM_ELEMENT_CONTROL = (function(_super) {
+
+ __extends(WSF_FORM_ELEMENT_CONTROL, _super);
+
+ function WSF_FORM_ELEMENT_CONTROL() {
+ return WSF_FORM_ELEMENT_CONTROL.__super__.constructor.apply(this, arguments);
+ }
+
+ WSF_FORM_ELEMENT_CONTROL.prototype.attach_events = function() {
+ var self, validator, _i, _len, _ref;
+ self = this;
+ this.value_control = controls[window.states[this.control_name]['value_control']];
+ if (this.value_control != null) {
+ this.value_control.on('change', this.change, this);
+ }
+ this.serverside_validator = false;
+ this.validators = [];
+ _ref = window.states[this.control_name]['validators'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ validator = _ref[_i];
+ if (validatormap[validator.name] != null) {
+ this.validators.push(new validatormap[validator.name](this, validator));
+ } else {
+ this.serverside_validator = true;
+ }
+ }
+ };
+
+ WSF_FORM_ELEMENT_CONTROL.prototype.change = function() {
+ var validator, _i, _len, _ref;
+ _ref = this.validators;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ validator = _ref[_i];
+ if (!validator.validate()) {
+ this.showerror(validator.error);
+ return;
+ }
+ }
+ this.showerror("");
+ if (this.serverside_validator) {
+ trigger_callback(this.control_name, 'validate');
+ }
+ };
+
+ WSF_FORM_ELEMENT_CONTROL.prototype.showerror = function(message) {
+ var errordiv;
+ this.$el.removeClass("has-error");
+ this.$el.find(".validation").remove();
+ if (message.length > 0) {
+ this.$el.addClass("has-error");
+ errordiv = $("").addClass('help-block').addClass('validation').text(message);
+ return this.$el.find(".col-lg-10").append(errordiv);
+ }
+ };
+
+ WSF_FORM_ELEMENT_CONTROL.prototype.update = function(state) {
+ if (state.error != null) {
+ return this.showerror(state.error);
+ }
+ };
+
+ WSF_FORM_ELEMENT_CONTROL.prototype.value = function() {
+ return this.value_control.value();
+ };
+
+ return WSF_FORM_ELEMENT_CONTROL;
+
+ })(WSF_CONTROL);
+
+ WSF_HTML_CONTROL = (function(_super) {
+
+ __extends(WSF_HTML_CONTROL, _super);
+
+ function WSF_HTML_CONTROL() {
+ return WSF_HTML_CONTROL.__super__.constructor.apply(this, arguments);
+ }
+
+ WSF_HTML_CONTROL.prototype.value = function() {
+ return this.$el.html();
+ };
+
+ WSF_HTML_CONTROL.prototype.update = function(state) {
+ if (state.html != null) {
+ window.states[this.control_name]['html'] = state.html;
+ return this.$el.html(state.html);
+ }
+ };
+
+ return WSF_HTML_CONTROL;
+
+ })(WSF_CONTROL);
+
typemap = {
"WSF_BUTTON_CONTROL": WSF_BUTTON_CONTROL,
- "WSF_TEXT_CONTROL": WSF_TEXT_CONTROL,
+ "WSF_INPUT_CONTROL": WSF_INPUT_CONTROL,
"WSF_TEXTAREA_CONTROL": WSF_TEXTAREA_CONTROL,
- "WSF_CHECKBOX_CONTROL": WSF_CHECKBOX_CONTROL
+ "WSF_CHECKBOX_CONTROL": WSF_CHECKBOX_CONTROL,
+ "WSF_FORM_ELEMENT_CONTROL": WSF_FORM_ELEMENT_CONTROL,
+ "WSF_HTML_CONTROL": WSF_HTML_CONTROL
};
_ref = window.states;
@@ -195,4 +410,12 @@
}
}
+ _ref1 = window.states;
+ for (name in _ref1) {
+ state = _ref1[name];
+ if ((_ref2 = controls[name]) != null) {
+ _ref2.attach_events();
+ }
+ }
+
}).call(this);
diff --git a/library/server/wsf_html/webcontrol/validators/wsf_decimal_validator.e b/library/server/wsf_html/webcontrol/validators/wsf_decimal_validator.e
index f7fd7f6d..ad68866d 100644
--- a/library/server/wsf_html/webcontrol/validators/wsf_decimal_validator.e
+++ b/library/server/wsf_html/webcontrol/validators/wsf_decimal_validator.e
@@ -18,7 +18,7 @@ feature {NONE}
make_decimal_validator (e: STRING)
do
- make_regexp_validator ("[0-9]+(\\.[0-9]*)?|\\.[0-9]+", e)
+ make_regexp_validator ("^[0-9]+(\.[0-9]*)?$|^\.[0-9]+$", e)
end
end
diff --git a/library/server/wsf_html/webcontrol/validators/wsf_email_validator.e b/library/server/wsf_html/webcontrol/validators/wsf_email_validator.e
index 68ff9360..552aead7 100644
--- a/library/server/wsf_html/webcontrol/validators/wsf_email_validator.e
+++ b/library/server/wsf_html/webcontrol/validators/wsf_email_validator.e
@@ -14,7 +14,7 @@ inherit
create
make_email_validator
-feature{NONE}
+feature {NONE}
make_email_validator (e: STRING)
do
diff --git a/library/server/wsf_html/webcontrol/validators/wsf_regexp_validator.e b/library/server/wsf_html/webcontrol/validators/wsf_regexp_validator.e
index 8e20b710..5dcc6e7c 100644
--- a/library/server/wsf_html/webcontrol/validators/wsf_regexp_validator.e
+++ b/library/server/wsf_html/webcontrol/validators/wsf_regexp_validator.e
@@ -10,6 +10,9 @@ class
inherit
WSF_VALIDATOR [STRING]
+ redefine
+ state
+ end
create
make_regexp_validator
@@ -18,21 +21,32 @@ feature {NONE}
make_regexp_validator (r, e: STRING)
do
- make(e)
+ make (e)
regexp_string := r
create regexp
- regexp.compile (r)
end
feature -- Implementation
- validate (input: STRING): BOOLEAN
+ is_valid (input: STRING): BOOLEAN
do
+ --Only compile when used
+ if not regexp.is_compiled then
+ regexp.compile (regexp_string)
+ end
Result := regexp.matches (input)
end
feature
+ state: JSON_OBJECT
+ do
+ create Result.make
+ Result.put (create {JSON_STRING}.make_json ("WSF_REGEXP_VALIDATOR"), create {JSON_STRING}.make_json ("name"))
+ Result.put (create {JSON_STRING}.make_json (regexp_string), create {JSON_STRING}.make_json ("expression"))
+ Result.put (create {JSON_STRING}.make_json (error), create {JSON_STRING}.make_json ("error"))
+ end
+
regexp_string: STRING
regexp: REGULAR_EXPRESSION
diff --git a/library/server/wsf_html/webcontrol/validators/wsf_validatable.e b/library/server/wsf_html/webcontrol/validators/wsf_validatable.e
new file mode 100644
index 00000000..4b7a60fa
--- /dev/null
+++ b/library/server/wsf_html/webcontrol/validators/wsf_validatable.e
@@ -0,0 +1,20 @@
+note
+ description: "Summary description for {WSF_VALIDATABLE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_VALIDATABLE
+
+feature
+
+ validate
+ deferred
+ end
+
+ is_valid: BOOLEAN
+ deferred
+ end
+
+end
diff --git a/library/server/wsf_html/webcontrol/validators/wsf_validator.e b/library/server/wsf_html/webcontrol/validators/wsf_validator.e
index 58415781..ad3f27bd 100644
--- a/library/server/wsf_html/webcontrol/validators/wsf_validator.e
+++ b/library/server/wsf_html/webcontrol/validators/wsf_validator.e
@@ -16,7 +16,14 @@ feature {NONE}
feature
- validate (input: G): BOOLEAN
+ state: JSON_OBJECT
+ do
+ create Result.make
+ Result.put (create {JSON_STRING}.make_json (generator), create {JSON_STRING}.make_json ("name"))
+ Result.put (create {JSON_STRING}.make_json (error), create {JSON_STRING}.make_json ("error"))
+ end
+
+ is_valid (input: G): BOOLEAN
deferred
end
diff --git a/library/server/wsf_html/webcontrol/wsf_button_control.e b/library/server/wsf_html/webcontrol/wsf_button_control.e
index 2e9a901d..cfd5ec05 100644
--- a/library/server/wsf_html/webcontrol/wsf_button_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_button_control.e
@@ -19,6 +19,8 @@ feature {NONE}
make_button (n: STRING; t: STRING)
do
make (n, "button")
+ add_class ("btn")
+ add_class ("btn-default")
text := t
end
diff --git a/library/server/wsf_html/webcontrol/wsf_checkbox_control.e b/library/server/wsf_html/webcontrol/wsf_checkbox_control.e
index b1281ac2..42233d74 100644
--- a/library/server/wsf_html/webcontrol/wsf_checkbox_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_checkbox_control.e
@@ -68,7 +68,7 @@ feature -- Implementation
if checked then
attributes := attributes + " checked"
end
- Result := render_tag_with_tagname ("div",render_tag_with_tagname ("label", render_tag ("", attributes) + " " + label, "",""), "","checkbox")
+ Result := render_tag_with_tagname ("div", render_tag_with_tagname ("label", render_tag ("", attributes) + " " + label, "", ""), "", "checkbox")
end
value: BOOLEAN
diff --git a/library/server/wsf_html/webcontrol/wsf_control.e b/library/server/wsf_html/webcontrol/wsf_control.e
index 9032e940..6f61e0b3 100644
--- a/library/server/wsf_html/webcontrol/wsf_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_control.e
@@ -97,7 +97,7 @@ feature
do
l_attributes := attributes
if not css_classes_string.is_empty then
- l_attributes := " class=%"" + css_classes_string + "%""
+ l_attributes := l_attributes + " class=%"" + css_classes_string + "%""
end
Result := "<" + tag + " id=%"" + control_name + "%" data-name=%"" + control_name + "%" data-type=%"" + generator + "%" " + l_attributes
if body.is_empty and not tag.is_equal ("textarea") then
diff --git a/library/server/wsf_html/webcontrol/wsf_form_control.e b/library/server/wsf_html/webcontrol/wsf_form_control.e
index dec7fa21..e4048080 100644
--- a/library/server/wsf_html/webcontrol/wsf_form_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_form_control.e
@@ -11,6 +11,8 @@ inherit
WSF_MULTI_CONTROL [WSF_CONTROL]
+ WSF_VALIDATABLE
+
create
make_form_control
@@ -24,22 +26,23 @@ feature {NONE}
feature -- Validation
- validate: BOOLEAN
+ validate
do
- Result := True
+ is_valid := True
across
controls as c
until
- Result = False
+ is_valid = False
loop
- -- TODO: Change generic parameter of elm from ANY to if something like that is available in Eiffel.
- -- Otherwise, check separately for STRING, LIST...
- if attached {WSF_FORM_ELEMENT_CONTROL[ANY]} c.item as elem then
+ if attached {WSF_VALIDATABLE} c.item as elem then
+ elem.validate
if not elem.is_valid then
- Result := False
+ is_valid := False
end
end
end
end
+ is_valid: BOOLEAN
+
end
diff --git a/library/server/wsf_html/webcontrol/wsf_form_element_control.e b/library/server/wsf_html/webcontrol/wsf_form_element_control.e
index 2550e79d..3fbf7d98 100644
--- a/library/server/wsf_html/webcontrol/wsf_form_element_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_form_element_control.e
@@ -11,9 +11,13 @@ inherit
WSF_CONTROL
redefine
- read_state_changes,load_state,read_state
+ read_state_changes,
+ load_state,
+ read_state
end
+ WSF_VALIDATABLE
+
create
make_form_element, make_form_element_with_validators
@@ -31,31 +35,19 @@ feature {NONE}
do
make (c.control_name + "_container", "div")
add_class ("form-group")
- if attached {WSF_TEXT_CONTROL}c or attached {WSF_TEXTAREA_CONTROL}c then
+ if attached {WSF_INPUT_CONTROL} c or attached {WSF_TEXTAREA_CONTROL} c then
c.add_class ("form-control")
-
end
+ if attached {WSF_HTML_CONTROL} c then
+ c.add_class ("form-control-static")
+ end
+
value_control := c
validators := v
label := a_label
error := ""
end
-feature
-
- is_valid (): BOOLEAN
- do
- Result := True
- across
- validators as c
- until
- not Result
- loop
- if not c.item.validate (value_control.value) then
- Result := False
- end
- end
- end
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT
load_state (new_states: JSON_OBJECT)
@@ -67,27 +59,37 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT
set_state (new_state: JSON_OBJECT)
do
- value_control.set_state(new_state)
+ value_control.set_state (new_state)
end
read_state (states: JSON_OBJECT)
-- Read states in subcontrols
do
Precursor (states)
- value_control.read_state(states)
+ value_control.read_state (states)
end
read_state_changes (states: JSON_OBJECT)
-- Read states_changes in subcontrols
do
Precursor (states)
- value_control.read_state_changes(states)
+ value_control.read_state_changes (states)
end
state: JSON_OBJECT
--Read state
+ local
+ validator_description: JSON_ARRAY
do
create Result.make
+ create validator_description.make_array
+ across
+ validators as v
+ loop
+ validator_description.add (v.item.state)
+ end
+ Result.put (create {JSON_STRING}.make_json (value_control.control_name), create {JSON_STRING}.make_json ("value_control"))
+ Result.put (validator_description, create {JSON_STRING}.make_json ("validators"))
end
feature --EVENT HANDLING
@@ -96,12 +98,15 @@ feature --EVENT HANDLING
-- Pass callback to subcontrols
do
if equal (cname, control_name) then
+ if event.is_equal ("validate") then
+ validate
+ end
else
value_control.handle_callback (cname, event)
end
end
-feature --Implementation
+feature --Implementation
render: STRING
local
@@ -117,6 +122,42 @@ feature --Implementation
Result := render_tag (body, "")
end
+feature -- Validation
+
+ add_validator (v: WSF_VALIDATOR [G])
+ do
+ validators.extend (v)
+ end
+
+ set_error (e: STRING)
+ do
+ error := e
+ state_changes.replace (create {JSON_STRING}.make_json (e), create {JSON_STRING}.make_json ("error"))
+ end
+
+ validate
+ local
+ current_value: G
+ do
+ current_value := value_control.value
+ is_valid := True
+ across
+ validators as c
+ until
+ not is_valid
+ loop
+ if not c.item.is_valid (current_value) then
+ is_valid := False
+ set_error (c.item.error)
+ end
+ end
+ if is_valid then
+ set_error ("")
+ end
+ end
+
+ is_valid: BOOLEAN
+
feature
value_control: WSF_VALUE_CONTROL [G]
diff --git a/library/server/wsf_html/webcontrol/wsf_html_control.e b/library/server/wsf_html/webcontrol/wsf_html_control.e
new file mode 100644
index 00000000..0df4ebf6
--- /dev/null
+++ b/library/server/wsf_html/webcontrol/wsf_html_control.e
@@ -0,0 +1,74 @@
+note
+ description: "Summary description for {WSF_html_CONTROL}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WSF_HTML_CONTROL
+
+inherit
+
+ WSF_VALUE_CONTROL [STRING]
+
+create
+ make_html
+
+feature {NONE}
+
+ make_html (n,t,v: STRING)
+ do
+ make (n, t)
+ html := v
+ end
+
+feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT
+
+ set_state (new_state: JSON_OBJECT)
+ -- Restore html from json
+ do
+ if attached {JSON_STRING} new_state.item (create {JSON_STRING}.make_json ("html")) as new_html then
+ html := new_html.unescaped_string_32
+ end
+ end
+
+ state: JSON_OBJECT
+ -- Return state which contains the current html and if there is an event handle attached
+ do
+ create Result.make
+ Result.put (create {JSON_STRING}.make_json (html), create {JSON_STRING}.make_json ("html"))
+ end
+
+feature --EVENT HANDLING
+
+ handle_callback (cname: STRING; event: STRING)
+ do
+ end
+
+feature -- Implementation
+
+ render: STRING
+ do
+ Result := render_tag (html,"")
+ end
+
+ set_html (t: STRING)
+ do
+ if not t.is_equal (html) then
+ html := t
+ state_changes.replace (create {JSON_STRING}.make_json (html), create {JSON_STRING}.make_json ("html"))
+ end
+ end
+
+ value: STRING
+ do
+ Result := html
+ end
+
+feature
+
+ html: STRING
+
+
+end
+
diff --git a/library/server/wsf_html/webcontrol/wsf_text_control.e b/library/server/wsf_html/webcontrol/wsf_input_control.e
similarity index 90%
rename from library/server/wsf_html/webcontrol/wsf_text_control.e
rename to library/server/wsf_html/webcontrol/wsf_input_control.e
index 3a03340f..0499a1d9 100644
--- a/library/server/wsf_html/webcontrol/wsf_text_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_input_control.e
@@ -5,20 +5,21 @@ note
revision: "$Revision$"
class
- WSF_TEXT_CONTROL
+ WSF_INPUT_CONTROL
inherit
WSF_VALUE_CONTROL [STRING]
create
- make_text
+ make_input
feature {NONE}
- make_text (n: STRING; v: STRING)
+ make_input (n: STRING; v: STRING)
do
make (n, "input")
+ type := "text"
text := v
end
@@ -61,7 +62,7 @@ feature -- Implementation
render: STRING
do
- Result := render_tag ("", "type=%"text%" value=%"" + text + "%"")
+ Result := render_tag ("", "type=%"" + type + "%" value=%"" + text + "%"")
end
set_text (t: STRING)
@@ -81,6 +82,8 @@ feature
text: STRING
+ type: STRING
+
change_event: detachable PROCEDURE [ANY, TUPLE []]
end
diff --git a/library/server/wsf_html/webcontrol/wsf_multi_control.e b/library/server/wsf_html/webcontrol/wsf_multi_control.e
index 20521e12..be5c952c 100644
--- a/library/server/wsf_html/webcontrol/wsf_multi_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_multi_control.e
@@ -5,7 +5,7 @@ note
revision: "$Revision$"
class
- WSF_MULTI_CONTROL[G -> WSF_CONTROL]
+ WSF_MULTI_CONTROL [G -> WSF_CONTROL]
inherit
diff --git a/library/server/wsf_html/webcontrol/wsf_page_control.e b/library/server/wsf_html/webcontrol/wsf_page_control.e
index 615118b9..d15e1ff7 100644
--- a/library/server/wsf_html/webcontrol/wsf_page_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_page_control.e
@@ -78,7 +78,6 @@ feature
control.read_state (states)
data := ""
data.append ("")
-
data.append ("")
data.append (control.render)
data.append ("