From 26ec7d94c69c2432b80ca3cf4a81636c018a1388 Mon Sep 17 00:00:00 2001 From: YNH Webdev Date: Sat, 14 Sep 2013 17:46:57 +0200 Subject: [PATCH] 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