diff --git a/examples/widgetapp/application.e b/examples/widgetapp/application.e
index 82a22f54..c1e342a9 100644
--- a/examples/widgetapp/application.e
+++ b/examples/widgetapp/application.e
@@ -34,6 +34,7 @@ feature {NONE} -- Initialization
-- router.map (create {WSF_URI_MAPPING}.make ("/hello", create {WSF_AGENT_URI_HANDLER}.make (agent execute_hello)))
map_agent_uri ("/", agent execute_hello, Void)
map_agent_uri ("/grid", agent grid_demo, Void)
+ map_agent_uri ("/repeater", agent repeater_demo, Void)
map_agent_uri ("/widget.js", agent load_js, Void)
map_agent_uri ("/widget.css", agent load_css, Void)
map_agent_uri ("/bootstrap.min.css", agent load_bootstrap, Void)
@@ -68,6 +69,16 @@ feature -- Execution
page.execute
end
+ repeater_demo (req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ page: REPEATER_PAGE
+ do
+ -- To send a response we need to setup, the status code and
+ -- the response headers.
+ create page.make (req, res)
+ page.execute
+ end
+
load_js (req: WSF_REQUEST; res: WSF_RESPONSE)
local
f: WSF_FILE_RESPONSE
diff --git a/examples/widgetapp/google_news_repeater.e b/examples/widgetapp/google_news_repeater.e
new file mode 100644
index 00000000..44e54c68
--- /dev/null
+++ b/examples/widgetapp/google_news_repeater.e
@@ -0,0 +1,38 @@
+note
+ description: "Summary description for {GOOGLE_NEWS_REPEATER}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ GOOGLE_NEWS_REPEATER
+
+inherit
+
+ WSF_REPEATER_CONTROL [GOOGLE_NEWS]
+
+create
+ make_repeater
+
+feature
+
+ render_item (item: GOOGLE_NEWS): STRING
+ local
+ body: STRING
+ do
+ Result := ""
+ if attached item.image as image then
+ Result.append (render_tag_with_tagname ("a", render_tag_with_tagname ("img", "", "style=%"max-width: 200px;%" src=%"" + image + "%"", "media-object"), "href=%"#%"", "pull-left"))
+ end
+ body := ""
+ if attached item.title as title then
+ body.append (render_tag_with_tagname ("h4", title, "", "media-heading"))
+ end
+ if attached item.content as content then
+ body.append (content)
+ end
+ Result.append (render_tag_with_tagname ("div", body, "", "media-body"))
+ Result := render_tag_with_tagname ("div", Result, "", "media") + "
"
+ end
+
+end
diff --git a/examples/widgetapp/repeater_page.e b/examples/widgetapp/repeater_page.e
new file mode 100644
index 00000000..ee1d700b
--- /dev/null
+++ b/examples/widgetapp/repeater_page.e
@@ -0,0 +1,51 @@
+note
+ description: "Summary description for {REPEATER_PAGE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ REPEATER_PAGE
+inherit
+
+ WSF_PAGE_CONTROL
+
+create
+ make
+
+feature
+
+ initialize_controls
+ local
+ container: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
+ do
+ create container.make_multi_control ("container")
+ create datasource.make_news
+ create search_query.make_autocomplete ("query", create {GOOGLE_AUTOCOMPLETION}.make)
+ search_query.add_class ("form-control")
+ search_query.set_change_event (agent change_query)
+ container.add_control (search_query)
+ create repeater.make_repeater ("myrepeater", datasource)
+ container.add_control (repeater)
+ control := container
+ end
+
+ change_query
+ do
+ datasource.set_query (search_query.value)
+ datasource.set_page (1)
+ datasource.update
+ end
+
+ process
+ do
+ end
+
+ repeater: GOOGLE_NEWS_REPEATER
+
+ search_query: WSF_AUTOCOMPLETE_CONTROL
+
+ datasource: GOOGLE_NEWS_DATASOURCE
+
+end
+
diff --git a/examples/widgetapp/widget.coffee b/examples/widgetapp/widget.coffee
index c813480c..0aee32a2 100644
--- a/examples/widgetapp/widget.coffee
+++ b/examples/widgetapp/widget.coffee
@@ -277,7 +277,19 @@ class WSF_GRID_CONTROL extends WSF_CONTROL
if state.datasource?
window.states[@control_name]['datasource'] = state.datasource
if state._body?
- @$el.find('tbody').html($(state._body).html())
+ @$el.find('tbody').html(state._body)
+
+class WSF_REPEATER_CONTROL extends WSF_CONTROL
+ attach_events: ()->
+ self = @
+
+ update: (state) ->
+ if state.datasource?
+ window.states[@control_name]['datasource'] = state.datasource
+ if state._body?
+ @$el.find('.repeater_content').html(state._body)
+ console.log state._body
+
#map class name to effective class
typemap =
@@ -291,6 +303,7 @@ typemap =
"WSF_CHECKBOX_LIST_CONTROL": WSF_CHECKBOX_LIST_CONTROL
"WSF_PAGINATION_CONTROL": WSF_PAGINATION_CONTROL
"WSF_GRID_CONTROL": WSF_GRID_CONTROL
+ "WSF_REPEATER_CONTROL":WSF_REPEATER_CONTROL
#create a js class for each control
for name,state of window.states
diff --git a/examples/widgetapp/widget.js b/examples/widgetapp/widget.js
index e8c86b0d..226fa86d 100644
--- a/examples/widgetapp/widget.js
+++ b/examples/widgetapp/widget.js
@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.1
(function() {
- var $el, Mini, WSF_AUTOCOMPLETE_CONTROL, WSF_BUTTON_CONTROL, WSF_CHECKBOX_CONTROL, WSF_CHECKBOX_LIST_CONTROL, WSF_CONTROL, WSF_FORM_ELEMENT_CONTROL, WSF_GRID_CONTROL, WSF_HTML_CONTROL, WSF_INPUT_CONTROL, WSF_MAX_VALIDATOR, WSF_MIN_VALIDATOR, WSF_PAGINATION_CONTROL, WSF_REGEXP_VALIDATOR, WSF_TEXTAREA_CONTROL, WSF_VALIDATOR, cache, controls, name, state, template, tmpl, trigger_callback, type, typemap, validatormap, _ref, _ref1, _ref2,
+ var $el, Mini, WSF_AUTOCOMPLETE_CONTROL, WSF_BUTTON_CONTROL, WSF_CHECKBOX_CONTROL, WSF_CHECKBOX_LIST_CONTROL, WSF_CONTROL, WSF_FORM_ELEMENT_CONTROL, WSF_GRID_CONTROL, WSF_HTML_CONTROL, WSF_INPUT_CONTROL, WSF_MAX_VALIDATOR, WSF_MIN_VALIDATOR, WSF_PAGINATION_CONTROL, WSF_REGEXP_VALIDATOR, WSF_REPEATER_CONTROL, WSF_TEXTAREA_CONTROL, WSF_VALIDATOR, cache, controls, name, state, template, tmpl, 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; };
@@ -523,7 +523,7 @@
window.states[this.control_name]['datasource'] = state.datasource;
}
if (state._body != null) {
- return this.$el.find('tbody').html($(state._body).html());
+ return this.$el.find('tbody').html(state._body);
}
};
@@ -531,6 +531,33 @@
})(WSF_CONTROL);
+ WSF_REPEATER_CONTROL = (function(_super) {
+
+ __extends(WSF_REPEATER_CONTROL, _super);
+
+ function WSF_REPEATER_CONTROL() {
+ return WSF_REPEATER_CONTROL.__super__.constructor.apply(this, arguments);
+ }
+
+ WSF_REPEATER_CONTROL.prototype.attach_events = function() {
+ var self;
+ return self = this;
+ };
+
+ WSF_REPEATER_CONTROL.prototype.update = function(state) {
+ if (state.datasource != null) {
+ window.states[this.control_name]['datasource'] = state.datasource;
+ }
+ if (state._body != null) {
+ this.$el.find('.repeater_content').html(state._body);
+ return console.log(state._body);
+ }
+ };
+
+ return WSF_REPEATER_CONTROL;
+
+ })(WSF_CONTROL);
+
typemap = {
"WSF_BUTTON_CONTROL": WSF_BUTTON_CONTROL,
"WSF_INPUT_CONTROL": WSF_INPUT_CONTROL,
@@ -541,7 +568,8 @@
"WSF_HTML_CONTROL": WSF_HTML_CONTROL,
"WSF_CHECKBOX_LIST_CONTROL": WSF_CHECKBOX_LIST_CONTROL,
"WSF_PAGINATION_CONTROL": WSF_PAGINATION_CONTROL,
- "WSF_GRID_CONTROL": WSF_GRID_CONTROL
+ "WSF_GRID_CONTROL": WSF_GRID_CONTROL,
+ "WSF_REPEATER_CONTROL": WSF_REPEATER_CONTROL
};
_ref = window.states;
diff --git a/library/server/wsf_html/webcontrol/grid/wsf_grid_control.e b/library/server/wsf_html/webcontrol/grid/wsf_grid_control.e
index ba50519c..0dd39b37 100644
--- a/library/server/wsf_html/webcontrol/grid/wsf_grid_control.e
+++ b/library/server/wsf_html/webcontrol/grid/wsf_grid_control.e
@@ -9,11 +9,8 @@ class
inherit
- WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
+ WSF_REPEATER_CONTROL [G]
redefine
- set_state,
- state,
- handle_callback,
render
end
@@ -24,48 +21,23 @@ feature {NONE}
make_grid (n: STRING; a_columns: ITERABLE [WSF_GRID_COLUMN]; a_datasource: WSF_DATASOURCE [G])
do
- make_multi_control (n)
+ make_repeater (n, a_datasource)
columns := a_columns
- datasource := a_datasource
- datasource.set_on_update_agent (agent update)
- if attached {WSF_PAGABLE_DATASOURCE [G]} a_datasource as ds then
- create pagination_control.make_paging (n + "_paging", ds)
- add_control (pagination_control)
- end
- end
-
-feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT
-
- update
- do
- state_changes.replace (create {JSON_STRING}.make_json (render_body), create {JSON_STRING}.make_json ("_body"))
- state_changes.replace (datasource.state, create {JSON_STRING}.make_json ("datasource"))
- end
-
- set_state (new_state: JSON_OBJECT)
- -- Restore html from json
- do
- if attached {JSON_OBJECT} new_state.item (create {JSON_STRING}.make_json ("datasource")) as datasource_state then
- datasource.set_state (datasource_state)
- 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 (datasource.state, create {JSON_STRING}.make_json ("datasource"))
- end
-
-feature --EVENT HANDLING
-
- handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING)
- do
- Precursor (cname, event, event_parameter)
end
feature -- Implementation
+ render_item (item: G): STRING
+ do
+ Result := ""
+ across
+ columns as c
+ loop
+ Result.append (render_tag_with_tagname ("td", c.item.render_column (item), "", ""))
+ end
+ Result := render_tag_with_tagname ("tr", Result, "", "")
+ end
+
render_header: STRING
do
Result := ""
@@ -77,30 +49,11 @@ feature -- Implementation
Result := render_tag_with_tagname ("thead", render_tag_with_tagname ("tr", Result, "", ""), "", "")
end
- render_body: STRING
- local
- row: STRING
- do
- Result := ""
- across
- datasource.data as entity
- loop
- row := ""
- across
- columns as c
- loop
- row.append (render_tag_with_tagname ("td", c.item.render_column (entity.item), "", ""))
- end
- Result.append (render_tag_with_tagname ("tr", row, "", ""))
- end
- Result := render_tag_with_tagname ("tbody", Result, "", "")
- end
-
render: STRING
local
table: STRING
do
- table := render_tag_with_tagname ("table", render_header + render_body, "", "table table-striped")
+ table := render_tag_with_tagname ("table", render_header + render_tag_with_tagname ("tbody", render_body, "", ""), "", "table table-striped")
Result := ""
across
controls as c
@@ -114,8 +67,4 @@ feature
columns: ITERABLE [WSF_GRID_COLUMN]
- datasource: WSF_DATASOURCE [G]
-
- pagination_control: detachable WSF_PAGINATION_CONTROL [G]
-
end
diff --git a/library/server/wsf_html/webcontrol/grid/wsf_repeater_control.e b/library/server/wsf_html/webcontrol/grid/wsf_repeater_control.e
new file mode 100644
index 00000000..e4246dac
--- /dev/null
+++ b/library/server/wsf_html/webcontrol/grid/wsf_repeater_control.e
@@ -0,0 +1,100 @@
+note
+ description: "Summary description for {WSF_REPEATER_CONTROL}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_REPEATER_CONTROL [G -> WSF_ENTITY]
+
+inherit
+
+ WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
+ redefine
+ set_state,
+ state,
+ handle_callback,
+ render
+ end
+
+feature {NONE}
+
+ make_repeater (n: STRING; a_datasource: WSF_DATASOURCE [G])
+ do
+ make_multi_control (n)
+ datasource := a_datasource
+ datasource.set_on_update_agent (agent update)
+ if attached {WSF_PAGABLE_DATASOURCE [G]} a_datasource as ds then
+ create pagination_control.make_paging (n + "_paging", ds)
+ add_control (pagination_control)
+ end
+ end
+
+feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT
+
+ update
+ do
+ state_changes.replace (create {JSON_STRING}.make_json (render_body), create {JSON_STRING}.make_json ("_body"))
+ state_changes.replace (datasource.state, create {JSON_STRING}.make_json ("datasource"))
+ end
+
+ set_state (new_state: JSON_OBJECT)
+ -- Restore html from json
+ do
+ if attached {JSON_OBJECT} new_state.item (create {JSON_STRING}.make_json ("datasource")) as datasource_state then
+ datasource.set_state (datasource_state)
+ 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 (datasource.state, create {JSON_STRING}.make_json ("datasource"))
+ end
+
+feature --EVENT HANDLING
+
+ handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING)
+ do
+ Precursor (cname, event, event_parameter)
+ end
+
+feature -- Implementation
+
+ render_item (item: G): STRING
+ deferred
+ end
+
+ render_body: STRING
+ do
+ Result := ""
+ across
+ datasource.data as entity
+ loop
+ Result.append (render_item (entity.item))
+ end
+ end
+
+ render: STRING
+ local
+ content: STRING
+ do
+ content := render_tag_with_tagname ("div", render_body, "", "repeater_content")
+ Result := ""
+ across
+ controls as c
+ loop
+ Result := c.item.render + Result
+ end
+ -- Fix generator name since the user will extend this class to define item_render
+ Result := render_tag_with_generator_name ("WSF_REPEATER_CONTROL", content + Result, "")
+ end
+
+feature
+
+ datasource: WSF_DATASOURCE [G]
+
+ pagination_control: detachable WSF_PAGINATION_CONTROL [G]
+
+end
diff --git a/library/server/wsf_html/webcontrol/wsf_control.e b/library/server/wsf_html/webcontrol/wsf_control.e
index 53198959..10c8900a 100644
--- a/library/server/wsf_html/webcontrol/wsf_control.e
+++ b/library/server/wsf_html/webcontrol/wsf_control.e
@@ -1,4 +1,4 @@
- note
+note
description: "Summary description for {WSF_CONTROL}."
author: ""
date: "$Date$"
@@ -68,6 +68,11 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT
feature -- Rendering
render_tag (body, attrs: STRING): STRING
+ do
+ Result:=render_tag_with_generator_name (generator, body, attrs)
+ end
+
+ render_tag_with_generator_name (a_generator, body, attrs: STRING): STRING
local
css_classes_string: STRING
l_attributes: STRING
@@ -78,7 +83,7 @@ feature -- Rendering
loop
css_classes_string := css_classes_string + " " + c.item
end
- l_attributes := "id=%"" + control_name + "%" data-name=%"" + control_name + "%" data-type=%"" + generator + "%" " + attrs
+ l_attributes := "id=%"" + control_name + "%" data-name=%"" + control_name + "%" data-type=%"" + a_generator + "%" " + attrs
Result := render_tag_with_tagname (tag_name, body, l_attributes, css_classes_string)
end