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