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/demo_data.e b/examples/widgetapp/demo_data.e index c0e484f7..90171076 100644 --- a/examples/widgetapp/demo_data.e +++ b/examples/widgetapp/demo_data.e @@ -21,6 +21,7 @@ feature {NONE} id := a_id name := a_name description := a_description + image := "http://placehold.it/20x20&text=" + id.out end feature @@ -31,6 +32,8 @@ feature description: STRING + image: STRING + get (field: STRING): detachable ANY do if field.is_equal ("id") then @@ -39,6 +42,8 @@ feature Result := name elseif field.is_equal ("description") then Result := description + elseif field.is_equal ("image") then + Result := image end end diff --git a/examples/widgetapp/demo_datasource.e b/examples/widgetapp/demo_datasource.e index 87f9f4ec..c26f635e 100644 --- a/examples/widgetapp/demo_datasource.e +++ b/examples/widgetapp/demo_datasource.e @@ -9,7 +9,7 @@ class inherit - WSF_DATASOURCE [DEMO_DATA] + WSF_PAGABLE_DATASOURCE [DEMO_DATA] create make_demo @@ -28,11 +28,12 @@ feature do create list.make across - ((page - 1) * page_size) |..| (page * page_size - 1) as c + ((page - 1) * page_size + 1) |..| (page * page_size).min (131) as c loop list.extend (create {DEMO_DATA}.make (c.item, "Name" + c.item.out, "desc " + c.item.out)) end Result := list + row_count := 132 end end diff --git a/examples/widgetapp/demo_progresssource.e b/examples/widgetapp/demo_progresssource.e deleted file mode 100644 index ce023d33..00000000 --- a/examples/widgetapp/demo_progresssource.e +++ /dev/null @@ -1,36 +0,0 @@ -note - description: "Summary description for {DEMO_PROGRESSSOURCE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - DEMO_PROGRESSSOURCE - -inherit - - WSF_PROGRESSSOURCE - -create - make - -feature {NONE} -- Initialization - - make - do - prog := 20 - end - -feature -- Implementation - - progress: INTEGER - do - if prog < 100 then - prog := prog + 1 - end - Result := prog - end - - prog: INTEGER - -end diff --git a/examples/widgetapp/google_autocompletion.e b/examples/widgetapp/google_autocompletion.e new file mode 100644 index 00000000..75979911 --- /dev/null +++ b/examples/widgetapp/google_autocompletion.e @@ -0,0 +1,72 @@ +note + description: "Summary description for {GOOGLE_AUTOCOMPLETION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + GOOGLE_AUTOCOMPLETION + +inherit + + WSF_AUTOCOMPLETION + +create + make + +feature {NONE} -- Initialization + + make () + do + template := "{{=value}}"; + end + +feature -- Implementation + + autocompletion (input: STRING): JSON_ARRAY + local + o: JSON_OBJECT + l_result: INTEGER + l_curl_string: CURL_STRING + json_parser: JSON_PARSER + query_str: STRING + do + query_str := input + query_str.replace_substring_all (" ", "+") + curl_handle := curl_easy.init + create Result.make_array + if curl_handle /= default_pointer then + create l_curl_string.make_empty + curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_url, "http://google.com/complete/search?client=chrome&q=" + query_str) + curl_easy.set_write_function (curl_handle) + curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_writedata, l_curl_string.object_id) + l_result := curl_easy.perform (curl_handle) + + -- Always cleanup + curl_easy.cleanup (curl_handle) + create json_parser.make_parser (l_curl_string.out) + if attached {JSON_ARRAY} json_parser.parse_json as data and then attached {JSON_ARRAY} data.i_th (2) as list then + across + 1 |..| list.count as c + loop + if attached {JSON_STRING} list.i_th (c.item) as row then + create o.make + o.put (create {JSON_STRING}.make_json (row.unescaped_string_32), "value") + Result.add (o) + end + end + end + end + end + +feature {NONE} -- Implementation + + curl_easy: CURL_EASY_EXTERNALS + once + create Result + end + + curl_handle: POINTER; + -- cURL handle + +end diff --git a/examples/widgetapp/google_news.e b/examples/widgetapp/google_news.e new file mode 100644 index 00000000..232e9571 --- /dev/null +++ b/examples/widgetapp/google_news.e @@ -0,0 +1,51 @@ +note + description: "Summary description for {GOOGLE_NEWS}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + GOOGLE_NEWS + +inherit + + WSF_ENTITY + +create + make_from_json + +feature {NONE} + + make_from_json (json: JSON_OBJECT) + do + if attached {JSON_STRING} json.item (create {JSON_STRING}.make_json ("title")) as a_title then + title := a_title.unescaped_string_32 + end + if attached {JSON_STRING} json.item (create {JSON_STRING}.make_json ("content")) as a_content then + content := a_content.unescaped_string_32 + end + if attached {JSON_OBJECT} json.item (create {JSON_STRING}.make_json ("image")) as img and then attached {JSON_STRING} img.item (create {JSON_STRING}.make_json ("url")) as a_image then + image := a_image.item + end + end + +feature + + title: detachable STRING + + content: detachable STRING + + image: detachable STRING + + get (field: STRING): detachable ANY + do + if field.is_equal ("title") then + Result := title + elseif field.is_equal ("content") then + Result := content + elseif field.is_equal ("image") then + Result := image + end + end + +end diff --git a/examples/widgetapp/google_news_datasource.e b/examples/widgetapp/google_news_datasource.e new file mode 100644 index 00000000..9a575887 --- /dev/null +++ b/examples/widgetapp/google_news_datasource.e @@ -0,0 +1,107 @@ +note + description: "Summary description for {GOOGLE_NEWS_DATASOURCE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + GOOGLE_NEWS_DATASOURCE + +inherit + + WSF_PAGABLE_DATASOURCE [GOOGLE_NEWS] + redefine + state, + set_state + end + +create + make_news + +feature --States + + state: JSON_OBJECT + -- Return state which contains the current html and if there is an event handle attached + do + Result := Precursor + Result.put (create {JSON_STRING}.make_json (query), create {JSON_STRING}.make_json ("query")) + end + + set_state (new_state: JSON_OBJECT) + do + Precursor (new_state) + if attached {JSON_STRING} new_state.item (create {JSON_STRING}.make_json ("query")) as new_query then + query := new_query.item + end + end + +feature + + make_news + do + page := 1 + page_size := 8 + query := "eiffel" + end + + data: ITERABLE [GOOGLE_NEWS] + local + list: LINKED_LIST [GOOGLE_NEWS] + l_result: INTEGER + l_curl_string: CURL_STRING + json_parser: JSON_PARSER + query_str: STRING + do + curl_handle := curl_easy.init + create list.make + row_count := 0 + if curl_handle /= default_pointer then + create l_curl_string.make_empty + query_str := query.out + query_str.replace_substring_all (" ", "+") + curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_url, "https://ajax.googleapis.com/ajax/services/search/news?v=1.0&q=" + query_str + "&rsz=" + page_size.out + "&start=" + (page_size * (page - 1)).out) + curl_easy.set_write_function (curl_handle) + curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_writedata, l_curl_string.object_id) + l_result := curl_easy.perform (curl_handle) + + -- Always cleanup + curl_easy.cleanup (curl_handle) + create json_parser.make_parser (l_curl_string.out) + if attached {JSON_OBJECT} json_parser.parse_json as sp then + if attached {JSON_OBJECT} sp.item (create {JSON_STRING}.make_json ("responseData")) as responsedata and then attached {JSON_ARRAY} responsedata.item (create {JSON_STRING}.make_json ("results")) as results then + if attached {JSON_OBJECT} responsedata.item (create {JSON_STRING}.make_json ("cursor")) as cursor and then attached {JSON_STRING} cursor.item (create {JSON_STRING}.make_json ("estimatedResultCount")) as count then + row_count := count.item.to_integer.min (64) + end + across + 1 |..| results.count as c + loop + if attached {JSON_OBJECT} results.i_th (c.item) as j then + list.extend (create {GOOGLE_NEWS}.make_from_json (j)) + end + end + end + end + end + Result := list + end + +feature + + set_query (q: STRING) + do + query := q + end + + query: STRING + +feature {NONE} -- Implementation + + curl_easy: CURL_EASY_EXTERNALS + once + create Result + end + + curl_handle: POINTER; + -- cURL handle + +end 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/grid_page.e b/examples/widgetapp/grid_page.e index 98ef14ed..5e2eafbd 100644 --- a/examples/widgetapp/grid_page.e +++ b/examples/widgetapp/grid_page.e @@ -18,17 +18,37 @@ feature initialize_controls local - ds: DEMO_DATASOURCE + container: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - create ds.make_demo - create grid.make_grid ("mygrid", <>, ds) - control := grid + create container.make_multi_control ("container") + container.add_class ("container") + container.add_control (create {WSF_BASIC_CONTROL}.make_with_body("h1","","Grid Demo")) + 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) + container.add_control (create {WSF_BASIC_CONTROL}.make_with_body("h2","","Results")) + create grid.make_grid ("mygrid", <>, datasource) + container.add_control (grid) + control := container + end + + change_query + do + datasource.set_query (search_query.value) + datasource.set_page (1) + datasource.update end process do end - grid: WSF_GRID_CONTROL [DEMO_DATA] + grid: WSF_GRID_CONTROL [GOOGLE_NEWS] + + search_query: WSF_AUTOCOMPLETE_CONTROL + + datasource: GOOGLE_NEWS_DATASOURCE end diff --git a/examples/widgetapp/repeater_page.e b/examples/widgetapp/repeater_page.e new file mode 100644 index 00000000..911315e8 --- /dev/null +++ b/examples/widgetapp/repeater_page.e @@ -0,0 +1,54 @@ +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") + container.add_class ("container") + container.add_control (create {WSF_BASIC_CONTROL}.make_with_body("h1","","Repeater Demo")) + 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) + container.add_control (create {WSF_BASIC_CONTROL}.make_with_body("h2","","Results")) + 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/sample_page.e b/examples/widgetapp/sample_page.e index fd684c81..43a0e2a7 100644 --- a/examples/widgetapp/sample_page.e +++ b/examples/widgetapp/sample_page.e @@ -20,35 +20,27 @@ feature local container: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] navbar: WSF_NAVBAR_CONTROL - form: WSF_FORM_CONTROL n1_container: WSF_FORM_ELEMENT_CONTROL [STRING] n2_container: WSF_FORM_ELEMENT_CONTROL [STRING] n3_container: WSF_FORM_ELEMENT_CONTROL [STRING] cats_container: WSF_FORM_ELEMENT_CONTROL [LIST [STRING]] - progress: WSF_PROGRESS_CONTROL - progress_source: WSF_PROGRESSSOURCE - link1: WSF_BASIC_CONTROL - link2: WSF_BASIC_CONTROL + s: FLAG_AUTOCOMPLETION do create s.make (<<["dz", "Algeria"], ["be", "Belgium"], ["ca", "Canada"], ["de", "Deutschland"], ["england", "England"], ["fi", "Finland"], ["gr", "Greece"], ["hu", "Hungary"]>>) create container.make_multi_control ("container") + container.add_class ("container") create navbar.make_navbar ("Sample Page") create textbox1.make_input ("txtBox1", "1") create textbox2.make_input ("txtBox2", "2") create autocompletion1.make_autocomplete ("autocompletion1", s) create button1.make_button ("sample_button1", "SUM") create textbox_result.make_html ("txtBox3", "p", "") - create {DEMO_PROGRESSSOURCE} progress_source.make - create progress.make_progress ("progress1", progress_source) - create link1.make_control ("a") - create link2.make_control ("a") - link1.set_content ("Home") - link1.set_attributes ("href=%"#%"") - link2.set_content ("About") - link2.set_attributes ("href=%"#%"") - navbar.add_element (link1) - navbar.add_element_right (link2) + create progress.make_progress ("progress1") + navbar.add_element (create {WSF_BASIC_CONTROL}.make_with_body("a","href=%"/%"","Home")) + navbar.add_element (create {WSF_BASIC_CONTROL}.make_with_body("a","href=%"/grid%"","Grid")) + navbar.add_element (create {WSF_BASIC_CONTROL}.make_with_body("a","href=%"/repeater%"","Repeater")) + navbar.add_element_right (create {WSF_BASIC_CONTROL}.make_with_body("a","href=%"#%"","About")) button1.set_click_event (agent handle_click) button1.add_class ("col-lg-offset-2") create form.make_form_control ("panel") @@ -81,21 +73,20 @@ feature local text: STRING do - 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 - text.append ("") - textbox_result.set_html (text) - else - textbox_result.set_html ("VALIDATION ERROR") + form.validate + if form.is_valid then + progress.set_progress ((textbox1.text.to_integer_64 / textbox2.text.to_integer_64*100).ceiling) + text := textbox1.text + " + " + textbox2.text + " = " + (textbox1.text.to_integer_64 + textbox2.text.to_integer_64).out + text.append ("") + textbox_result.set_html (text) + else + textbox_result.set_html ("VALIDATION ERROR") end end @@ -115,4 +106,7 @@ feature textbox_result: WSF_HTML_CONTROL + form: WSF_FORM_CONTROL + + progress: WSF_PROGRESS_CONTROL end diff --git a/examples/widgetapp/widget.coffee b/examples/widgetapp/widget.coffee index b570e09e..7c6b2d18 100644 --- a/examples/widgetapp/widget.coffee +++ b/examples/widgetapp/widget.coffee @@ -11,11 +11,12 @@ Mini = render:template(t) } -trigger_callback = (control_name,event)-> +trigger_callback = (control_name,event,event_parameter)-> $.ajax data: control_name: control_name event: event + event_parameter: event_parameter states: JSON.stringify(window.states) cache: no .done (new_states)-> @@ -131,7 +132,6 @@ class WSF_TEXTAREA_CONTROL extends WSF_INPUT_CONTROL class WSF_AUTOCOMPLETE_CONTROL extends WSF_INPUT_CONTROL attach_events: () -> - super self = @ @$el.typeahead({ name: @control_name @@ -148,6 +148,10 @@ class WSF_AUTOCOMPLETE_CONTROL extends WSF_INPUT_CONTROL filter: (parsedResponse) -> parsedResponse[self.control_name]['suggestions'] }) + @$el.on 'typeahead:closed',()-> + self.change() + @$el.on 'typeahead:blured',()-> + self.change() class WSF_CHECKBOX_CONTROL extends WSF_CONTROL attach_events: ()-> @@ -255,6 +259,47 @@ class WSF_PROGRESS_CONTROL extends WSF_CONTROL window.states[@control_name]['progress'] = state.progress $('#' + @control_name).children('.progress-bar').attr('aria-valuenow', state.progress).width(state.progress + '%') +class WSF_PAGINATION_CONTROL extends WSF_CONTROL + attach_events: ()-> + self = @ + @$el.on 'click', 'a', (e)-> + e.preventDefault() + self.click(e) + + click: (e)-> + nr = $(e.target).data('nr') + if nr == "next" + trigger_callback(@control_name, "next") + else if nr == "prev" + trigger_callback(@control_name, "prev") + else + trigger_callback(@control_name, "goto", nr) + + update: (state) -> + if state._html? + @$el.html($(state._html).html()) + +class WSF_GRID_CONTROL extends WSF_CONTROL + attach_events: ()-> + self = @ + + update: (state) -> + if state.datasource? + window.states[@control_name]['datasource'] = state.datasource + if state._body? + @$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 = "WSF_BUTTON_CONTROL": WSF_BUTTON_CONTROL @@ -266,6 +311,9 @@ typemap = "WSF_HTML_CONTROL": WSF_HTML_CONTROL "WSF_CHECKBOX_LIST_CONTROL": WSF_CHECKBOX_LIST_CONTROL "WSF_PROGRESS_CONTROL": WSF_PROGRESS_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 8d0122c5..db7554dc 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_HTML_CONTROL, WSF_INPUT_CONTROL, WSF_MAX_VALIDATOR, WSF_MIN_VALIDATOR, WSF_PROGRESS_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_PROGRESS_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; }; @@ -24,11 +24,12 @@ } }; - trigger_callback = function(control_name, event) { + trigger_callback = function(control_name, event, event_parameter) { return $.ajax({ data: { control_name: control_name, event: event, + event_parameter: event_parameter, states: JSON.stringify(window.states) }, cache: false @@ -262,9 +263,8 @@ WSF_AUTOCOMPLETE_CONTROL.prototype.attach_events = function() { var self; - WSF_AUTOCOMPLETE_CONTROL.__super__.attach_events.apply(this, arguments); self = this; - return this.$el.typeahead({ + this.$el.typeahead({ name: this.control_name, template: window.states[this.control_name]['template'], engine: Mini, @@ -283,6 +283,12 @@ } } }); + this.$el.on('typeahead:closed', function() { + return self.change(); + }); + return this.$el.on('typeahead:blured', function() { + return self.change(); + }); }; return WSF_AUTOCOMPLETE_CONTROL; @@ -482,6 +488,98 @@ })(WSF_CONTROL); + WSF_PAGINATION_CONTROL = (function(_super) { + + __extends(WSF_PAGINATION_CONTROL, _super); + + function WSF_PAGINATION_CONTROL() { + return WSF_PAGINATION_CONTROL.__super__.constructor.apply(this, arguments); + } + + WSF_PAGINATION_CONTROL.prototype.attach_events = function() { + var self; + self = this; + return this.$el.on('click', 'a', function(e) { + e.preventDefault(); + return self.click(e); + }); + }; + + WSF_PAGINATION_CONTROL.prototype.click = function(e) { + var nr; + nr = $(e.target).data('nr'); + if (nr === "next") { + return trigger_callback(this.control_name, "next"); + } else if (nr === "prev") { + return trigger_callback(this.control_name, "prev"); + } else { + return trigger_callback(this.control_name, "goto", nr); + } + }; + + WSF_PAGINATION_CONTROL.prototype.update = function(state) { + if (state._html != null) { + return this.$el.html($(state._html).html()); + } + }; + + return WSF_PAGINATION_CONTROL; + + })(WSF_CONTROL); + + WSF_GRID_CONTROL = (function(_super) { + + __extends(WSF_GRID_CONTROL, _super); + + function WSF_GRID_CONTROL() { + return WSF_GRID_CONTROL.__super__.constructor.apply(this, arguments); + } + + WSF_GRID_CONTROL.prototype.attach_events = function() { + var self; + return self = this; + }; + + WSF_GRID_CONTROL.prototype.update = function(state) { + if (state.datasource != null) { + window.states[this.control_name]['datasource'] = state.datasource; + } + if (state._body != null) { + return this.$el.find('tbody').html(state._body); + } + }; + + return WSF_GRID_CONTROL; + + })(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, @@ -491,7 +589,10 @@ "WSF_FORM_ELEMENT_CONTROL": WSF_FORM_ELEMENT_CONTROL, "WSF_HTML_CONTROL": WSF_HTML_CONTROL, "WSF_CHECKBOX_LIST_CONTROL": WSF_CHECKBOX_LIST_CONTROL, - "WSF_PROGRESS_CONTROL": WSF_PROGRESS_CONTROL + "WSF_PROGRESS_CONTROL": WSF_PROGRESS_CONTROL, + "WSF_PAGINATION_CONTROL": WSF_PAGINATION_CONTROL, + "WSF_GRID_CONTROL": WSF_GRID_CONTROL, + "WSF_REPEATER_CONTROL": WSF_REPEATER_CONTROL }; _ref = window.states; diff --git a/examples/widgetapp/widgetapp.ecf b/examples/widgetapp/widgetapp.ecf index 082b483f..983564b1 100644 --- a/examples/widgetapp/widgetapp.ecf +++ b/examples/widgetapp/widgetapp.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/wsf_html/webcontrol/grid/wsf_datasource.e b/library/server/wsf_html/webcontrol/grid/wsf_datasource.e index 66328760..8f19529a 100644 --- a/library/server/wsf_html/webcontrol/grid/wsf_datasource.e +++ b/library/server/wsf_html/webcontrol/grid/wsf_datasource.e @@ -7,14 +7,28 @@ note deferred class WSF_DATASOURCE [G -> WSF_ENTITY] +feature -- Update event + + set_on_update_agent (f: PROCEDURE [ANY, TUPLE []]) + do + on_update_agent := f + end + + update + do + if attached on_update_agent as a then + a.call ([]) + end + end + + on_update_agent: detachable PROCEDURE [ANY, TUPLE []] + feature --State 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_NUMBER}.make_integer (page), create {JSON_STRING}.make_json ("page")) - Result.put (create {JSON_NUMBER}.make_integer (page_size), create {JSON_STRING}.make_json ("page_size")) if attached sort_column as a_sort_column then Result.put (create {JSON_STRING}.make_json (a_sort_column), create {JSON_STRING}.make_json ("sort_column")) else @@ -43,16 +57,6 @@ feature --State feature - set_page (a_page: like page) - do - page := a_page - end - - set_page_size (a_page_size: like page_size) - do - page_size := a_page_size - end - set_sort_column (a_sort_column: like sort_column) do sort_column := a_sort_column 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 6492cb6d..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,7 +9,10 @@ class inherit - WSF_CONTROL + WSF_REPEATER_CONTROL [G] + redefine + render + end create make_grid @@ -18,40 +21,23 @@ feature {NONE} make_grid (n: STRING; a_columns: ITERABLE [WSF_GRID_COLUMN]; a_datasource: WSF_DATASOURCE [G]) do - make_control (n, "div") + make_repeater (n, a_datasource) columns := a_columns - datasource := a_datasource - end - -feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT - - update - do - 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) - do 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 := "" @@ -63,34 +49,22 @@ feature -- Implementation Result := render_tag_with_tagname ("thead", render_tag_with_tagname ("tr", Result, "", ""), "", "") end - render_body: STRING + render: STRING local - row: STRING + table: STRING do + table := render_tag_with_tagname ("table", render_header + render_tag_with_tagname ("tbody", render_body, "", ""), "", "table table-striped") Result := "" across - datasource.data as entity + controls as c 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, "", "")) + Result := c.item.render + Result end - Result := render_tag_with_tagname ("tbody", Result, "", "") - end - - render: STRING - do - Result := render_tag (render_tag_with_tagname ("table", render_header + render_body, "", "table table-striped"), "") + Result := render_tag (table + Result, "") end feature columns: ITERABLE [WSF_GRID_COLUMN] - datasource: WSF_DATASOURCE [G] - end diff --git a/library/server/wsf_html/webcontrol/grid/wsf_grid_image_column.e b/library/server/wsf_html/webcontrol/grid/wsf_grid_image_column.e new file mode 100644 index 00000000..d1824013 --- /dev/null +++ b/library/server/wsf_html/webcontrol/grid/wsf_grid_image_column.e @@ -0,0 +1,38 @@ +note + description: "Summary description for {WSF_GRID_IMAGE_COLUMN}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_GRID_IMAGE_COLUMN + +inherit + + WSF_GRID_COLUMN + redefine + render_column + end + +create + make_image_column + +feature {NONE} + + make_image_column (a_header, a_field: STRING) + do + make_column (a_header, a_field) + end + +feature + + render_column (e: WSF_ENTITY): STRING + do + if attached e.get (field_name) as data then + Result := "" + else + Result := "[VOID]" + end + end + +end diff --git a/library/server/wsf_html/webcontrol/grid/wsf_pagable_datasource.e b/library/server/wsf_html/webcontrol/grid/wsf_pagable_datasource.e new file mode 100644 index 00000000..547b7269 --- /dev/null +++ b/library/server/wsf_html/webcontrol/grid/wsf_pagable_datasource.e @@ -0,0 +1,77 @@ +note + description: "Summary description for {WSF_PAGABLE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_PAGABLE_DATASOURCE [G -> WSF_ENTITY] + +inherit + + WSF_DATASOURCE [G] + redefine + state, + set_state, + update + end + +feature -- Update event + + set_on_update_page_agent (f: PROCEDURE [ANY, TUPLE []]) + do + on_update_page_agent := f + end + + update + do + if attached on_update_agent as a then + a.call ([]) + end + if attached on_update_page_agent as a then + a.call ([]) + end + end + + on_update_page_agent: detachable PROCEDURE [ANY, TUPLE []] + +feature --States + + state: JSON_OBJECT + -- Return state which contains the current html and if there is an event handle attached + do + Result := Precursor + Result.put (create {JSON_NUMBER}.make_integer (page), create {JSON_STRING}.make_json ("page")) + Result.put (create {JSON_NUMBER}.make_integer (page_size), create {JSON_STRING}.make_json ("page_size")) + Result.put (create {JSON_NUMBER}.make_integer (row_count), create {JSON_STRING}.make_json ("row_count")) + end + + set_state (new_state: JSON_OBJECT) + do + Precursor (new_state) + if attached {JSON_NUMBER} new_state.item (create {JSON_STRING}.make_json ("page")) as new_page then + page := new_page.item.to_integer + end + if attached {JSON_NUMBER} new_state.item (create {JSON_STRING}.make_json ("page_size")) as new_page_size then + page_size := new_page_size.item.to_integer + end + if attached {JSON_NUMBER} new_state.item (create {JSON_STRING}.make_json ("row_count")) as new_row_count then + row_count := new_row_count.item.to_integer + end + end + +feature + + set_page (p: INTEGER) + do + page := p.min (page_count).max (1) + end + + row_count: INTEGER + + page_count: INTEGER + do + Result := (row_count / page_size).ceiling + end + +end diff --git a/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e b/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e new file mode 100644 index 00000000..2024746d --- /dev/null +++ b/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e @@ -0,0 +1,92 @@ +note + description: "Summary description for {WSF_PAGINATION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_PAGINATION_CONTROL [G -> WSF_ENTITY] + +inherit + + WSF_CONTROL + +create + make_paging + +feature {NONE} + + make_paging (n: STRING; ds: WSF_PAGABLE_DATASOURCE [G]) + do + make_control (n, "ul") + add_class ("pagination") + datasource := ds + datasource.set_on_update_page_agent (agent update) + end + +feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT + + state: JSON_OBJECT + -- Return state which contains the current html and if there is an event handle attached + do + create Result.make + end + + set_state (new_state: JSON_OBJECT) + do + end + +feature --EVENT HANDLING + + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + do + if Current.control_name.is_equal (cname) then + if event.is_equal ("next") then + datasource.set_page (datasource.page + 1) + elseif event.is_equal ("prev") then + datasource.set_page (datasource.page - 1) + elseif event.is_equal ("goto") then + if attached event_parameter as p and then attached p.to_integer as i then + datasource.set_page (i) + end + end + datasource.update + end + end + +feature + + update + do + state_changes.replace (create {JSON_STRING}.make_json (render), create {JSON_STRING}.make_json ("_html")) + end + + render: STRING + local + paging_start: INTEGER + paging_end: INTEGER + cssclass: STRING + do + Result := render_tag_with_tagname ("li", render_tag_with_tagname ("a", "«", "href=%"#%" data-nr=%"prev%"", ""), "", "") + paging_start := (datasource.page - 4).max (1) + paging_end := (paging_start + 8).min (datasource.page_count) + paging_start := (paging_end - 8).max (1) + across + paging_start |..| paging_end as n + loop + if n.item = datasource.page then + cssclass := "active" + else + cssclass := "" + end + Result := Result + render_tag_with_tagname ("li", render_tag_with_tagname ("a", n.item.out, "href=%"#%" data-nr=%"" + n.item.out + "%"", ""), "", cssclass) + end + Result := Result + render_tag_with_tagname ("li", render_tag_with_tagname ("a", "»", "href=%"#%" data-nr=%"next%"", ""), "", "") + Result := render_tag (Result, "") + end + +feature + + datasource: WSF_PAGABLE_DATASOURCE [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/input/wsf_autocomplete_control.e b/library/server/wsf_html/webcontrol/input/wsf_autocomplete_control.e index 5ff19533..c6f1c586 100644 --- a/library/server/wsf_html/webcontrol/input/wsf_autocomplete_control.e +++ b/library/server/wsf_html/webcontrol/input/wsf_autocomplete_control.e @@ -45,9 +45,9 @@ feature -- State feature -- Callback - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) do - Precursor {WSF_INPUT_CONTROL} (cname, event) + Precursor {WSF_INPUT_CONTROL} (cname, event, event_parameter) if cname.is_equal (control_name) and event.is_equal ("autocomplete") then state_changes.put (create_json_list.item ([text]), create {JSON_STRING}.make_json ("suggestions")) end diff --git a/library/server/wsf_html/webcontrol/input/wsf_checkbox_control.e b/library/server/wsf_html/webcontrol/input/wsf_checkbox_control.e index 99af55bc..38bf4bf4 100644 --- a/library/server/wsf_html/webcontrol/input/wsf_checkbox_control.e +++ b/library/server/wsf_html/webcontrol/input/wsf_checkbox_control.e @@ -50,7 +50,7 @@ feature --EVENT HANDLING change_event := e end - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) do if Current.control_name.is_equal (cname) and attached change_event as cevent then if event.is_equal ("change") then diff --git a/library/server/wsf_html/webcontrol/input/wsf_input_control.e b/library/server/wsf_html/webcontrol/input/wsf_input_control.e index 731d55e6..2c729508 100644 --- a/library/server/wsf_html/webcontrol/input/wsf_input_control.e +++ b/library/server/wsf_html/webcontrol/input/wsf_input_control.e @@ -49,7 +49,7 @@ feature --EVENT HANDLING change_event := e end - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) do if Current.control_name.is_equal (cname) and attached change_event as cevent then if event.is_equal ("change") then diff --git a/library/server/wsf_html/webcontrol/progressbar/wsf_progress_control.e b/library/server/wsf_html/webcontrol/progressbar/wsf_progress_control.e index f41fe96b..a7431b56 100644 --- a/library/server/wsf_html/webcontrol/progressbar/wsf_progress_control.e +++ b/library/server/wsf_html/webcontrol/progressbar/wsf_progress_control.e @@ -12,14 +12,20 @@ inherit WSF_CONTROL create - make_progress + make_progress, make_progress_with_source feature {NONE} -- Initialization - make_progress (n: STRING; p: WSF_PROGRESSSOURCE) + make_progress (n: STRING) do make_control (n, "div") add_class ("progress") + progress := 0 + end + + make_progress_with_source (n: STRING; p: WSF_PROGRESSSOURCE) + do + make_progress (n) progress_source := p end @@ -32,15 +38,15 @@ feature -- State handling state: JSON_OBJECT do create Result.make - Result.put (create {JSON_NUMBER}.make_integer (progress_source.progress), "progress") + Result.put (create {JSON_NUMBER}.make_integer (progress_value), "progress") end feature -- Event handling - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) do if cname.is_equal (control_name) and event.is_equal ("progress_fetch") then - state_changes.put (create {JSON_NUMBER}.make_integer (progress_source.progress), create {JSON_STRING}.make_json ("progress")) + state_changes.put (create {JSON_NUMBER}.make_integer (progress_value), create {JSON_STRING}.make_json ("progress")) end end @@ -48,12 +54,32 @@ feature -- Rendering render: STRING do - Result := render_tag_with_tagname ("div", "", "role=%"progressbar%" aria-valuenow=%"" + progress_source.progress.out + "%" aria-valuemin=%"0%" aria-valuemax=%"100%" style=%"width: " + progress_source.progress.out + "%%;%"", "progress-bar") + Result := render_tag_with_tagname ("div", "", "role=%"progressbar%" aria-valuenow=%"" + progress_value.out + "%" aria-valuemin=%"0%" aria-valuemax=%"100%" style=%"width: " + progress_value.out + "%%;%"", "progress-bar") Result := render_tag (Result, "") end +feature --Change progress + + set_progress (p: INTEGER) + require + no_progress_source: not (attached progress_source) + do + progress := p + state_changes.put (create {JSON_NUMBER}.make_integer (progress), create {JSON_STRING}.make_json ("progress")) + end + feature - progress_source: WSF_PROGRESSSOURCE + progress_source: detachable WSF_PROGRESSSOURCE + + progress: INTEGER + + progress_value: INTEGER + do + Result := progress + if attached progress_source as ps then + Result := ps.progress + end + end end diff --git a/library/server/wsf_html/webcontrol/wsf_basic_control.e b/library/server/wsf_html/webcontrol/wsf_basic_control.e index 9b423a3e..d789b35a 100644 --- a/library/server/wsf_html/webcontrol/wsf_basic_control.e +++ b/library/server/wsf_html/webcontrol/wsf_basic_control.e @@ -12,7 +12,8 @@ inherit WSF_STATELESS_CONTROL create - make_control + make_control, + make_with_body feature {NONE} -- Initialization @@ -27,6 +28,13 @@ feature {NONE} -- Initialization content := "" end + make_with_body (t,attr,a_content: STRING) + do + make (t) + attributes := attr + content := a_content + end + feature -- Rendering render: STRING diff --git a/library/server/wsf_html/webcontrol/wsf_button_control.e b/library/server/wsf_html/webcontrol/wsf_button_control.e index b4aab2ed..cfbbbf3f 100644 --- a/library/server/wsf_html/webcontrol/wsf_button_control.e +++ b/library/server/wsf_html/webcontrol/wsf_button_control.e @@ -50,7 +50,7 @@ feature --EVENT HANDLING click_event := e end - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) do if Current.control_name.is_equal (cname) and attached click_event as cevent then cevent.call ([]) diff --git a/library/server/wsf_html/webcontrol/wsf_control.e b/library/server/wsf_html/webcontrol/wsf_control.e index 8f1dadc9..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,13 +83,13 @@ 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 feature --EVENT HANDLING - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) -- Method called if any callback received. In this method you can route the callback to the event handler deferred 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 a57f6403..c58f095c 100644 --- a/library/server/wsf_html/webcontrol/wsf_form_element_control.e +++ b/library/server/wsf_html/webcontrol/wsf_form_element_control.e @@ -41,7 +41,6 @@ feature {NONE} if attached {WSF_HTML_CONTROL} c then c.add_class ("form-control-static") end - value_control := c validators := v label := a_label @@ -94,7 +93,7 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT feature --EVENT HANDLING - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) -- Pass callback to subcontrols do if equal (cname, control_name) then @@ -102,7 +101,7 @@ feature --EVENT HANDLING validate end else - value_control.handle_callback (cname, event) + value_control.handle_callback (cname, event, event_parameter) end end diff --git a/library/server/wsf_html/webcontrol/wsf_html_control.e b/library/server/wsf_html/webcontrol/wsf_html_control.e index 9a7554bc..f8d1d17f 100644 --- a/library/server/wsf_html/webcontrol/wsf_html_control.e +++ b/library/server/wsf_html/webcontrol/wsf_html_control.e @@ -41,7 +41,7 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT feature --EVENT HANDLING - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) do end diff --git a/library/server/wsf_html/webcontrol/wsf_multi_control.e b/library/server/wsf_html/webcontrol/wsf_multi_control.e index b31c7f39..5cec2c3c 100644 --- a/library/server/wsf_html/webcontrol/wsf_multi_control.e +++ b/library/server/wsf_html/webcontrol/wsf_multi_control.e @@ -48,16 +48,11 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT end set_state (new_state: JSON_OBJECT) + -- Before we process the callback. We restore the state of control. do - across - controls as c - loop - if attached {WSF_CONTROL} c.item as cont then - cont.set_state (new_state) - end - end end + read_state (states: JSON_OBJECT) -- Read states in subcontrols do @@ -92,7 +87,7 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- STATE MANAGEMENT feature --EVENT HANDLING - handle_callback (cname: STRING; event: STRING) + handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) -- Pass callback to subcontrols do if equal (cname, control_name) then @@ -101,7 +96,7 @@ feature --EVENT HANDLING controls as c loop if attached {WSF_CONTROL} c.item as cont then - cont.handle_callback (cname, event) + cont.handle_callback (cname, event, event_parameter) end end end @@ -120,9 +115,11 @@ feature Result := render_tag (Result, "") end - add_control (c: G) + add_control (c: detachable G) do - controls.put_front (c) + if attached c as d then + controls.put_front (d) + end end controls: LINKED_LIST [G] diff --git a/library/server/wsf_html/webcontrol/wsf_page_control.e b/library/server/wsf_html/webcontrol/wsf_page_control.e index 846069b7..856a51c9 100644 --- a/library/server/wsf_html/webcontrol/wsf_page_control.e +++ b/library/server/wsf_html/webcontrol/wsf_page_control.e @@ -43,6 +43,7 @@ feature -- If request is not a callback. Run process and render the html page local event: detachable STRING + event_parameter: detachable STRING control_name: detachable STRING states: detachable STRING states_changes: JSON_OBJECT @@ -50,13 +51,14 @@ feature do control_name := get_parameter ("control_name") event := get_parameter ("event") + event_parameter := get_parameter ("event_parameter") states := get_parameter ("states") if attached event and attached control_name and attached control and attached states then create json_parser.make_parser (states) if attached {JSON_OBJECT} json_parser.parse_json as sp then control.load_state (sp) end - control.handle_callback (control_name, event) + control.handle_callback (control_name, event, event_parameter) create states_changes.make control.read_state_changes (states_changes) response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "application/json"]>>) @@ -74,14 +76,14 @@ feature page: WSF_PAGE_RESPONSE states: JSON_OBJECT do - create states.make - control.read_state (states) data := "" data.append ("") data.append ("") data.append ("") data.append (control.render) data.append ("") data.append ("") diff --git a/library/server/wsf_html/wsf_html-safe.ecf b/library/server/wsf_html/wsf_html-safe.ecf index 5de37699..d441e72f 100644 --- a/library/server/wsf_html/wsf_html-safe.ecf +++ b/library/server/wsf_html/wsf_html-safe.ecf @@ -25,7 +25,7 @@ - +