From 95f823e7a158466a4c99a56eb8c545a709bff192 Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sat, 14 Sep 2013 14:27:11 +0200 Subject: [PATCH 1/7] - Add event paramenter - Implement Paging control --- examples/widgetapp/demo_datasource.e | 5 +- examples/widgetapp/sample_page.e | 33 ++++--- examples/widgetapp/widget.coffee | 35 +++++++- examples/widgetapp/widget.js | 74 +++++++++++++++- .../wsf_html/webcontrol/grid/wsf_datasource.e | 28 +++--- .../webcontrol/grid/wsf_grid_control.e | 33 ++++++- .../webcontrol/grid/wsf_pagable_datasource.e | 57 ++++++++++++ .../webcontrol/grid/wsf_pagination_control.e | 88 +++++++++++++++++++ .../input/wsf_autocomplete_control.e | 4 +- .../webcontrol/input/wsf_checkbox_control.e | 2 +- .../webcontrol/input/wsf_input_control.e | 2 +- .../wsf_html/webcontrol/wsf_button_control.e | 2 +- .../server/wsf_html/webcontrol/wsf_control.e | 2 +- .../webcontrol/wsf_form_element_control.e | 5 +- .../wsf_html/webcontrol/wsf_html_control.e | 2 +- .../wsf_html/webcontrol/wsf_multi_control.e | 19 ++-- .../wsf_html/webcontrol/wsf_page_control.e | 8 +- 17 files changed, 336 insertions(+), 63 deletions(-) create mode 100644 library/server/wsf_html/webcontrol/grid/wsf_pagable_datasource.e create mode 100644 library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e diff --git a/examples/widgetapp/demo_datasource.e b/examples/widgetapp/demo_datasource.e index 87f9f4ec..22057e60 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) |..| (page * page_size - 1).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/sample_page.e b/examples/widgetapp/sample_page.e index 90c6b1a7..a84b6170 100644 --- a/examples/widgetapp/sample_page.e +++ b/examples/widgetapp/sample_page.e @@ -18,16 +18,15 @@ feature initialize_controls local - container: WSF_MULTI_CONTROL[WSF_STATELESS_CONTROL] + 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]] s: FLAG_AUTOCOMPLETION do - create s.make(<<["dz", "Algeria"], ["be", "Belgium"] , ["ca", "Canada"],["de", "Deutschland"], ["england", "England"], ["fi", "Finland"], ["gr", "Greece"], ["hu", "Hungary"]>>) + 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") create navbar.make_navbar ("Sample Page") create textbox1.make_input ("txtBox1", "1") @@ -66,21 +65,19 @@ 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 + 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 @@ -100,4 +97,6 @@ feature textbox_result: WSF_HTML_CONTROL + form: WSF_FORM_CONTROL + end diff --git a/examples/widgetapp/widget.coffee b/examples/widgetapp/widget.coffee index 5e652bfb..03687ac6 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)-> @@ -247,6 +248,36 @@ class WSF_CHECKBOX_LIST_CONTROL extends WSF_CONTROL result.push(subc.checked_value) return result +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).html()) + #map class name to effective class typemap = "WSF_BUTTON_CONTROL":WSF_BUTTON_CONTROL @@ -257,6 +288,8 @@ typemap = "WSF_FORM_ELEMENT_CONTROL": WSF_FORM_ELEMENT_CONTROL "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 #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 76efbde4..a6740784 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_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_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 @@ -463,6 +464,71 @@ })(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).html()); + } + }; + + return WSF_GRID_CONTROL; + + })(WSF_CONTROL); + typemap = { "WSF_BUTTON_CONTROL": WSF_BUTTON_CONTROL, "WSF_INPUT_CONTROL": WSF_INPUT_CONTROL, @@ -471,7 +537,9 @@ "WSF_CHECKBOX_CONTROL": WSF_CHECKBOX_CONTROL, "WSF_FORM_ELEMENT_CONTROL": WSF_FORM_ELEMENT_CONTROL, "WSF_HTML_CONTROL": WSF_HTML_CONTROL, - "WSF_CHECKBOX_LIST_CONTROL": WSF_CHECKBOX_LIST_CONTROL + "WSF_CHECKBOX_LIST_CONTROL": WSF_CHECKBOX_LIST_CONTROL, + "WSF_PAGINATION_CONTROL": WSF_PAGINATION_CONTROL, + "WSF_GRID_CONTROL": WSF_GRID_CONTROL }; _ref = window.states; diff --git a/library/server/wsf_html/webcontrol/grid/wsf_datasource.e b/library/server/wsf_html/webcontrol/grid/wsf_datasource.e index 66328760..e37d1c1c 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..ba50519c 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,13 @@ class inherit - WSF_CONTROL + WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + redefine + set_state, + state, + handle_callback, + render + end create make_grid @@ -18,15 +24,22 @@ feature {NONE} make_grid (n: STRING; a_columns: ITERABLE [WSF_GRID_COLUMN]; a_datasource: WSF_DATASOURCE [G]) do - make_control (n, "div") + make_multi_control (n) 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) @@ -46,8 +59,9 @@ 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 + Precursor (cname, event, event_parameter) end feature -- Implementation @@ -83,8 +97,17 @@ feature -- Implementation end render: STRING + local + table: STRING do - Result := render_tag (render_tag_with_tagname ("table", render_header + render_body, "", "table table-striped"), "") + table := render_tag_with_tagname ("table", render_header + render_body, "", "table table-striped") + Result := "" + across + controls as c + loop + Result := c.item.render + Result + end + Result := render_tag (table + Result, "") end feature @@ -93,4 +116,6 @@ feature datasource: WSF_DATASOURCE [G] + pagination_control: detachable WSF_PAGINATION_CONTROL [G] + 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..a0f28e4e --- /dev/null +++ b/library/server/wsf_html/webcontrol/grid/wsf_pagable_datasource.e @@ -0,0 +1,57 @@ +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 + end + +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..85bbd099 --- /dev/null +++ b/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e @@ -0,0 +1,88 @@ +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 + 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 + state_changes.replace (create {JSON_STRING}.make_json (render), create {JSON_STRING}.make_json ("_html")) + datasource.update + end + end + +feature + + render: STRING + local + page_count: INTEGER + 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/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/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..53198959 100644 --- a/library/server/wsf_html/webcontrol/wsf_control.e +++ b/library/server/wsf_html/webcontrol/wsf_control.e @@ -84,7 +84,7 @@ feature -- Rendering 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 ("") From 26ec7d94c69c2432b80ca3cf4a81636c018a1388 Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sat, 14 Sep 2013 17:46:57 +0200 Subject: [PATCH 2/7] Google news example --- examples/widgetapp/demo_data.e | 5 + examples/widgetapp/demo_datasource.e | 4 +- examples/widgetapp/google_autocompletion.e | 72 ++++++++++++ examples/widgetapp/google_news.e | 51 +++++++++ examples/widgetapp/google_news_datasource.e | 107 ++++++++++++++++++ examples/widgetapp/grid_page.e | 27 ++++- examples/widgetapp/widget.coffee | 3 +- examples/widgetapp/widget.js | 6 +- examples/widgetapp/widgetapp.ecf | 1 + .../wsf_html/webcontrol/grid/wsf_datasource.e | 4 +- .../webcontrol/grid/wsf_grid_image_column.e | 38 +++++++ .../webcontrol/grid/wsf_pagable_datasource.e | 22 +++- .../webcontrol/grid/wsf_pagination_control.e | 8 +- 13 files changed, 333 insertions(+), 15 deletions(-) create mode 100644 examples/widgetapp/google_autocompletion.e create mode 100644 examples/widgetapp/google_news.e create mode 100644 examples/widgetapp/google_news_datasource.e create mode 100644 library/server/wsf_html/webcontrol/grid/wsf_grid_image_column.e 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 22057e60..c26f635e 100644 --- a/examples/widgetapp/demo_datasource.e +++ b/examples/widgetapp/demo_datasource.e @@ -28,12 +28,12 @@ feature do create list.make across - ((page - 1) * page_size) |..| (page * page_size - 1).min(131) 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 + row_count := 132 end end diff --git a/examples/widgetapp/google_autocompletion.e b/examples/widgetapp/google_autocompletion.e new file mode 100644 index 00000000..89f35696 --- /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://suggestqueries.google.com/complete/search?client=firefox&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/grid_page.e b/examples/widgetapp/grid_page.e index 98ef14ed..42f02a0e 100644 --- a/examples/widgetapp/grid_page.e +++ b/examples/widgetapp/grid_page.e @@ -18,17 +18,34 @@ 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") + 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 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/widget.coffee b/examples/widgetapp/widget.coffee index 03687ac6..c813480c 100644 --- a/examples/widgetapp/widget.coffee +++ b/examples/widgetapp/widget.coffee @@ -131,7 +131,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 +147,8 @@ class WSF_AUTOCOMPLETE_CONTROL extends WSF_INPUT_CONTROL filter: (parsedResponse) -> parsedResponse[self.control_name]['suggestions'] }) + @$el.on 'typeahead:closed',()-> + self.change() class WSF_CHECKBOX_CONTROL extends WSF_CONTROL attach_events: ()-> diff --git a/examples/widgetapp/widget.js b/examples/widgetapp/widget.js index a6740784..e8c86b0d 100644 --- a/examples/widgetapp/widget.js +++ b/examples/widgetapp/widget.js @@ -263,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, @@ -284,6 +283,9 @@ } } }); + return this.$el.on('typeahead:closed', function() { + return self.change(); + }); }; return WSF_AUTOCOMPLETE_CONTROL; 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 e37d1c1c..8f19529a 100644 --- a/library/server/wsf_html/webcontrol/grid/wsf_datasource.e +++ b/library/server/wsf_html/webcontrol/grid/wsf_datasource.e @@ -16,8 +16,8 @@ feature -- Update event update do - if attached on_update_agent as a then - a.call([]) + if attached on_update_agent as a then + a.call ([]) end 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 index a0f28e4e..547b7269 100644 --- a/library/server/wsf_html/webcontrol/grid/wsf_pagable_datasource.e +++ b/library/server/wsf_html/webcontrol/grid/wsf_pagable_datasource.e @@ -12,9 +12,29 @@ inherit WSF_DATASOURCE [G] redefine state, - set_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 diff --git a/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e b/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e index 85bbd099..2024746d 100644 --- a/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e +++ b/library/server/wsf_html/webcontrol/grid/wsf_pagination_control.e @@ -21,6 +21,7 @@ feature {NONE} 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 @@ -49,16 +50,19 @@ feature --EVENT HANDLING datasource.set_page (i) end end - state_changes.replace (create {JSON_STRING}.make_json (render), create {JSON_STRING}.make_json ("_html")) 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 - page_count: INTEGER paging_start: INTEGER paging_end: INTEGER cssclass: STRING From cfe452543a5f88f7babe5328b5a5dcefe51c47ad Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sat, 14 Sep 2013 18:41:49 +0200 Subject: [PATCH 3/7] Implement repeater --- examples/widgetapp/application.e | 11 ++ examples/widgetapp/google_news_repeater.e | 38 +++++++ examples/widgetapp/repeater_page.e | 51 +++++++++ examples/widgetapp/widget.coffee | 15 ++- examples/widgetapp/widget.js | 34 +++++- .../webcontrol/grid/wsf_grid_control.e | 79 +++----------- .../webcontrol/grid/wsf_repeater_control.e | 100 ++++++++++++++++++ .../server/wsf_html/webcontrol/wsf_control.e | 9 +- 8 files changed, 266 insertions(+), 71 deletions(-) create mode 100644 examples/widgetapp/google_news_repeater.e create mode 100644 examples/widgetapp/repeater_page.e create mode 100644 library/server/wsf_html/webcontrol/grid/wsf_repeater_control.e 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 From 6230d643c8e259d0c880d79a3dc6ef8f164fd341 Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sat, 14 Sep 2013 19:39:08 +0200 Subject: [PATCH 4/7] Style demo pages --- examples/widgetapp/grid_page.e | 3 ++ examples/widgetapp/repeater_page.e | 3 ++ .../webcontrol/wsf_stateless_html_control.e | 40 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 library/server/wsf_html/webcontrol/wsf_stateless_html_control.e diff --git a/examples/widgetapp/grid_page.e b/examples/widgetapp/grid_page.e index 42f02a0e..7ca591d6 100644 --- a/examples/widgetapp/grid_page.e +++ b/examples/widgetapp/grid_page.e @@ -21,11 +21,14 @@ feature container: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do create container.make_multi_control ("container") + container.add_class ("container") + container.add_control (create {WSF_STATELESS_HTML_CONTROL}.make_html("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_STATELESS_HTML_CONTROL}.make_html("h2","Results")) create grid.make_grid ("mygrid", <>, datasource) container.add_control (grid) control := container diff --git a/examples/widgetapp/repeater_page.e b/examples/widgetapp/repeater_page.e index ee1d700b..afd0dcf3 100644 --- a/examples/widgetapp/repeater_page.e +++ b/examples/widgetapp/repeater_page.e @@ -20,11 +20,14 @@ feature container: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do create container.make_multi_control ("container") + container.add_class ("container") + container.add_control (create {WSF_STATELESS_HTML_CONTROL}.make_html("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_STATELESS_HTML_CONTROL}.make_html("h2","Results")) create repeater.make_repeater ("myrepeater", datasource) container.add_control (repeater) control := container diff --git a/library/server/wsf_html/webcontrol/wsf_stateless_html_control.e b/library/server/wsf_html/webcontrol/wsf_stateless_html_control.e new file mode 100644 index 00000000..7d1f4c5d --- /dev/null +++ b/library/server/wsf_html/webcontrol/wsf_stateless_html_control.e @@ -0,0 +1,40 @@ +note + description: "Summary description for {WSF_STATELESS_HTML_CONTROL}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_STATELESS_HTML_CONTROL + +inherit + + WSF_STATELESS_CONTROL + +create + make_html + +feature {NONE} + + make_html (t, v: STRING) + do + make ( t) + html := v + end + + +feature -- Implementation + + render: STRING + do + Result := render_tag (html, "") + end + + + +feature + + html: STRING + +end + From 0f8444a585559d21ed472641ceeada70bc807c4b Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sat, 14 Sep 2013 20:39:07 +0200 Subject: [PATCH 5/7] Remove column from grid --- examples/widgetapp/grid_page.e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/widgetapp/grid_page.e b/examples/widgetapp/grid_page.e index 7ca591d6..b035ff1e 100644 --- a/examples/widgetapp/grid_page.e +++ b/examples/widgetapp/grid_page.e @@ -29,7 +29,7 @@ feature search_query.set_change_event (agent change_query) container.add_control (search_query) container.add_control (create {WSF_STATELESS_HTML_CONTROL}.make_html("h2","Results")) - create grid.make_grid ("mygrid", <>, datasource) + create grid.make_grid ("mygrid", <>, datasource) container.add_control (grid) control := container end From 15dd993b957b1a8192d428c6dcbc7fccc478925d Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sat, 14 Sep 2013 22:45:58 +0200 Subject: [PATCH 6/7] Fix change event --- examples/widgetapp/widget.coffee | 2 ++ examples/widgetapp/widget.js | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/widgetapp/widget.coffee b/examples/widgetapp/widget.coffee index 0aee32a2..1fcb81c6 100644 --- a/examples/widgetapp/widget.coffee +++ b/examples/widgetapp/widget.coffee @@ -149,6 +149,8 @@ class WSF_AUTOCOMPLETE_CONTROL extends WSF_INPUT_CONTROL }) @$el.on 'typeahead:closed',()-> self.change() + @$el.on 'typeahead:blured',()-> + self.change() class WSF_CHECKBOX_CONTROL extends WSF_CONTROL attach_events: ()-> diff --git a/examples/widgetapp/widget.js b/examples/widgetapp/widget.js index 226fa86d..53f59f4e 100644 --- a/examples/widgetapp/widget.js +++ b/examples/widgetapp/widget.js @@ -283,7 +283,10 @@ } } }); - return this.$el.on('typeahead:closed', function() { + this.$el.on('typeahead:closed', function() { + return self.change(); + }); + return this.$el.on('typeahead:blured', function() { return self.change(); }); }; From 1ba9792547097f87b10940a4e5957fc150aec596 Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sun, 15 Sep 2013 13:33:43 +0200 Subject: [PATCH 7/7] Fix suggestions --- examples/widgetapp/google_autocompletion.e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/widgetapp/google_autocompletion.e b/examples/widgetapp/google_autocompletion.e index 89f35696..75979911 100644 --- a/examples/widgetapp/google_autocompletion.e +++ b/examples/widgetapp/google_autocompletion.e @@ -37,7 +37,7 @@ feature -- Implementation 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://suggestqueries.google.com/complete/search?client=firefox&q=" + query_str) + 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)