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 ("")
- across
- cklist.value as s
- loop
- text.append ("- " + s.item + "
")
- end
- 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 ("")
+ across
+ cklist.value as s
+ loop
+ text.append ("- " + s.item + "
")
end
+ 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 @@
-
+