diff --git a/draft/library/wsf_js_widget/kernel/dropdown/wsf_dropdown_control.e b/draft/library/wsf_js_widget/kernel/dropdown/wsf_dropdown_control.e index 1b8a26e7..c7001da8 100644 --- a/draft/library/wsf_js_widget/kernel/dropdown/wsf_dropdown_control.e +++ b/draft/library/wsf_js_widget/kernel/dropdown/wsf_dropdown_control.e @@ -20,19 +20,19 @@ create feature {NONE} -- Initialization - make (n, title: STRING) + make ( title: STRING) -- Make a dropdown control with div tag name and specified menu title do - make_with_tag_name (n, title, "div") + make_with_tag_name ( title, "div") end - make_with_tag_name (n, title, t: STRING) + make_with_tag_name ( title, t: STRING) -- Make a dropdown control with specified tag name and menu title (such as li) do - make_multi_control_with_tag_name (n, t) + make_multi_control_with_tag_name ( t) add_class ("dropdown") create {WSF_BASIC_CONTROL} dropdown_toggle.make_with_body_class ("a", "data-toggle=%"dropdown%" href=%"#%"", "dropdown-toggle", title + " ") - create dropdown_menu.make_with_tag_name (n + "_menu", "ul") + create dropdown_menu.make_with_tag_name ( "ul") dropdown_menu.add_class ("dropdown-menu") add_control (dropdown_toggle) add_control (dropdown_menu) @@ -44,7 +44,7 @@ feature -- Change local li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - create li.make_with_tag_name (control_name + "_item" + dropdown_menu.controls.count.out, "li") + create li.make_with_tag_name ("li") li.add_control (c) dropdown_menu.add_control (li) end @@ -66,6 +66,6 @@ feature -- Properties dropdown_toggle: WSF_STATELESS_CONTROL - dropdown_menu: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + dropdown_menu: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] end diff --git a/draft/library/wsf_js_widget/kernel/grid/wsf_grid_control.e b/draft/library/wsf_js_widget/kernel/grid/wsf_grid_control.e index cab1e36c..77cfae25 100644 --- a/draft/library/wsf_js_widget/kernel/grid/wsf_grid_control.e +++ b/draft/library/wsf_js_widget/kernel/grid/wsf_grid_control.e @@ -21,9 +21,9 @@ create feature {NONE} -- Initialization - make (n: STRING; a_columns: ITERABLE [WSF_GRID_COLUMN]; a_datasource: WSF_DATASOURCE [G]) + make (a_columns: ITERABLE [WSF_GRID_COLUMN]; a_datasource: WSF_DATASOURCE [G]) do - make_repeater (n, a_datasource) + make_repeater (a_datasource) columns := a_columns end diff --git a/draft/library/wsf_js_widget/kernel/grid/wsf_pagination_control.e b/draft/library/wsf_js_widget/kernel/grid/wsf_pagination_control.e index 838f2a55..df09e443 100644 --- a/draft/library/wsf_js_widget/kernel/grid/wsf_pagination_control.e +++ b/draft/library/wsf_js_widget/kernel/grid/wsf_pagination_control.e @@ -19,9 +19,9 @@ create feature {NONE} - make (n: STRING; ds: WSF_PAGABLE_DATASOURCE [G]) + make (ds: WSF_PAGABLE_DATASOURCE [G]) do - make_control (n, "ul") + make_control ( "ul") add_class ("pagination") datasource := ds datasource.set_on_update_page_agent (agent update) @@ -48,16 +48,16 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management feature --Event handling - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) -- Handle goto/next/prev events do - if Current.control_name.same_string (cname) then + if Current.control_name.same_string (cname[1]) then if event.same_string ("next") then datasource.set_page (datasource.page + 1) elseif event.same_string ("prev") then datasource.set_page (datasource.page - 1) elseif event.same_string ("goto") then - if attached event_parameter as p and then attached p.to_integer as i then + if attached {STRING}event_parameter as p and then attached p.to_integer as i then datasource.set_page (i) end end diff --git a/draft/library/wsf_js_widget/kernel/grid/wsf_repeater_control.e b/draft/library/wsf_js_widget/kernel/grid/wsf_repeater_control.e index 88012bdd..785f8567 100644 --- a/draft/library/wsf_js_widget/kernel/grid/wsf_repeater_control.e +++ b/draft/library/wsf_js_widget/kernel/grid/wsf_repeater_control.e @@ -20,15 +20,15 @@ inherit feature {NONE} -- Initialization - make (n: STRING; a_datasource: WSF_DATASOURCE [G]) + make ( a_datasource: WSF_DATASOURCE [G]) local p: WSF_PAGINATION_CONTROL [G] do - make_multi_control (n) + make_multi_control datasource := a_datasource datasource.set_on_update_agent (agent update) if attached {WSF_PAGABLE_DATASOURCE [G]} a_datasource as ds then - create p.make (n + "_paging", ds) + create p.make ( ds) add_control (p) pagination_control := p end diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_autocomplete_control.e b/draft/library/wsf_js_widget/kernel/input/wsf_autocomplete_control.e index 35b86056..ae9de051 100644 --- a/draft/library/wsf_js_widget/kernel/input/wsf_autocomplete_control.e +++ b/draft/library/wsf_js_widget/kernel/input/wsf_autocomplete_control.e @@ -22,19 +22,19 @@ create feature {NONE} -- Initialization - make (n: STRING; c: WSF_AUTOCOMPLETION) + make (c: WSF_AUTOCOMPLETION) -- Initialize with specified name and autocompletion do - make_with_agent (n, agent c.autocompletion) + make_with_agent ( agent c.autocompletion) if attached c.template as t then template := t end end - make_with_agent (n: STRING; c: FUNCTION [ANY, TUPLE [STRING], JSON_ARRAY]) + make_with_agent (c: FUNCTION [ANY, TUPLE [STRING], JSON_ARRAY]) -- Initialize with specified name and autocompletion function do - make_input (n, "") + make_input ( "") create_json_list := c template := "{{=value}}" end @@ -49,10 +49,10 @@ feature -- State feature -- Callback - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) do Precursor {WSF_INPUT_CONTROL} (cname, event, event_parameter) - if cname.same_string (control_name) and event.same_string ("autocomplete") then + if cname[1].same_string (control_name) and event.same_string ("autocomplete") then state_changes.put (create_json_list.item ([text]), "suggestions") end end diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_control.e b/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_control.e index 6b9d1239..dbb35c61 100644 --- a/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_control.e +++ b/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_control.e @@ -19,10 +19,10 @@ create feature {NONE} -- Initialization - make (n, l, c: STRING) + make (l, c: STRING) -- Initialize with specified control name, do - make_value_control (n, "input") + make_value_control ( "input") label := l checked_value := c end @@ -54,9 +54,9 @@ feature --Event handling change_event := e end - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) do - if Current.control_name.same_string (cname) and attached change_event as cevent then + if Current.control_name.same_string (cname[1]) and attached change_event as cevent then if event.same_string ("change") then cevent.call (Void) end diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_list_control.e b/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_list_control.e index e99d91ee..6d9d2aff 100644 --- a/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_list_control.e +++ b/draft/library/wsf_js_widget/kernel/input/wsf_checkbox_list_control.e @@ -28,10 +28,10 @@ create feature {NONE} -- Initializaton - make (n: STRING) + make -- Initialize with specified control name do - make_multi_control (n) + make_multi_control end feature -- Implementation diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_file_control.e b/draft/library/wsf_js_widget/kernel/input/wsf_file_control.e new file mode 100644 index 00000000..8b2f57a5 --- /dev/null +++ b/draft/library/wsf_js_widget/kernel/input/wsf_file_control.e @@ -0,0 +1,121 @@ +note + description: "Summary description for {WSF_FILE_CONTROL}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_FILE_CONTROL + +inherit + + WSF_VALUE_CONTROL [detachable WSF_PENDING_FILE] + rename + make as make_value_control + end + +create + make + +feature {NONE} -- Initialization + + make + do + make_value_control ("input") + end + +feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management + + set_state (new_state: JSON_OBJECT) + -- Restore text from json + do + if attached {JSON_STRING} new_state.item ("file") as new_name and attached {JSON_STRING} new_state.item ("type") as new_type and attached {JSON_NUMBER} new_state.item ("size") as new_size then + create file.make (new_name.unescaped_string_32, new_type.unescaped_string_32, new_size.item.to_integer_32); + end + if attached {JSON_STRING} new_state.item ("upload_file") as f then + upload_file:=f.unescaped_string_32; + end + end + + state: WSF_JSON_OBJECT + -- Return state which contains the current text and if there is an event handle attached + do + create Result.make + Result.put_boolean (attached change_event, "callback_change") + end + +feature -- Uploaded Files + + set_uploaded_file (p: detachable STRING) + -- Store link to uploaded file in control state. In order to make it availabe for future callbacks + do + if attached p as a_p then + upload_file := a_p + state_changes.put_string (a_p, "upload_file") + end + end + +feature -- Event handling + + set_change_event (e: attached like change_event) + -- Set text change event handle + do + change_event := e + end + + set_upload_function (e: attached like upload_function) + -- Set button click event handle + do + upload_function := e + end + + handle_callback (cname: LIST [STRING]; event: STRING; event_parameter: detachable ANY) + do + if Current.control_name.same_string (cname [1]) then + if attached change_event as cevent and event.same_string ("change") then + cevent.call (Void) + elseif attached upload_function as ufunction and event.same_string ("uploadfile") and attached {ITERABLE[WSF_UPLOADED_FILE]}event_parameter as files then + + set_uploaded_file(ufunction.item ([files])) + end + end + end + +feature -- Upload + + start_upload + local + upload: WSF_JSON_OBJECT + do + create upload.make + upload.put_string ("start_upload", "type") + actions.add (upload) + end + +feature -- Implementation + + value: detachable WSF_PENDING_FILE + do + Result := file + end + + render: STRING + do + Result := render_tag ("", "type=%"file%" ") + end + +feature -- Properties + + file: detachable WSF_PENDING_FILE + -- Text to be displayed + + change_event: detachable PROCEDURE [ANY, TUPLE] + -- Procedure to be execued on change + + upload_function: detachable FUNCTION [ANY, TUPLE[ITERABLE[WSF_UPLOADED_FILE]],detachable STRING] + -- Procedure to be execued on change + + upload_file: detachable STRING + -- Link to uploaded file + +end diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_input_control.e b/draft/library/wsf_js_widget/kernel/input/wsf_input_control.e index c0223e3c..d243bd7d 100644 --- a/draft/library/wsf_js_widget/kernel/input/wsf_input_control.e +++ b/draft/library/wsf_js_widget/kernel/input/wsf_input_control.e @@ -19,10 +19,10 @@ create feature {NONE} -- Initialization - make (n, v: STRING) + make (v: STRING) -- Initialize with specified name and value do - make_value_control (n, "input") + make_value_control ( "input") type := "text" text := v end @@ -53,9 +53,9 @@ feature --Event handling change_event := e end - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) - do - if Current.control_name.same_string (cname) and attached change_event as cevent then + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) + do + if Current.control_name.same_string (cname[1]) and attached change_event as cevent then if event.same_string ("change") then cevent.call (Void) end diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_password_control.e b/draft/library/wsf_js_widget/kernel/input/wsf_password_control.e index 536f1b26..4bd84b97 100644 --- a/draft/library/wsf_js_widget/kernel/input/wsf_password_control.e +++ b/draft/library/wsf_js_widget/kernel/input/wsf_password_control.e @@ -19,10 +19,10 @@ create feature {NONE} -- Initialization - make (n, v: STRING) + make (v: STRING) -- Initialize with specified control name and text do - make_input (n, v) + make_input (v) type := "password" end diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_pending_file.e b/draft/library/wsf_js_widget/kernel/input/wsf_pending_file.e new file mode 100644 index 00000000..759d39f3 --- /dev/null +++ b/draft/library/wsf_js_widget/kernel/input/wsf_pending_file.e @@ -0,0 +1,30 @@ +note + description: "Summary description for {WSF_PENDING_FILE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_PENDING_FILE + +create + make + +feature {NONE} + + make (a_name, a_type: STRING; a_size: INTEGER) + do + name := a_name + type := a_type + size := a_size + end + +feature --Properties + + name: STRING + + type: STRING + + size: INTEGER + +end diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_textarea_control.e b/draft/library/wsf_js_widget/kernel/input/wsf_textarea_control.e index 440b8795..2b0318b4 100644 --- a/draft/library/wsf_js_widget/kernel/input/wsf_textarea_control.e +++ b/draft/library/wsf_js_widget/kernel/input/wsf_textarea_control.e @@ -21,10 +21,10 @@ create feature {NONE} -- Initialization - make (n, t: STRING) + make (t: STRING) -- Initialize with specified control name and text to be displayed in this textarea do - make_input (n, t) + make_input ( t) tag_name := "textarea" end diff --git a/draft/library/wsf_js_widget/kernel/navbar/wsf_navbar_control.e b/draft/library/wsf_js_widget/kernel/navbar/wsf_navbar_control.e index 06a70be2..4c7b69b9 100644 --- a/draft/library/wsf_js_widget/kernel/navbar/wsf_navbar_control.e +++ b/draft/library/wsf_js_widget/kernel/navbar/wsf_navbar_control.e @@ -21,24 +21,24 @@ create feature {NONE} -- Initialization - make (n: STRING) + make --Initialize do - make_multi_control (n) + make_multi_control active_set := false add_class ("navbar navbar-inverse navbar-fixed-top") - create nav.make_with_tag_name (control_name + "_nav", "ul") - create nav_right.make_with_tag_name (control_name + "_nav_right", "ul") + create nav.make_with_tag_name ("ul") + create nav_right.make_with_tag_name ( "ul") controls.extend (nav) controls.extend (nav_right) nav.add_class ("nav navbar-nav") nav_right.add_class ("nav navbar-nav navbar-right") end - make_with_brand (n, b: STRING) + make_with_brand ( b: STRING) -- Initialize with specified brand string do - make (n) + make brand := b end @@ -85,7 +85,7 @@ feature -- Change local li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - create li.make_with_tag_name (control_name + "_link" + nav.controls.count.out, "li") + create li.make_with_tag_name ("li") li.add_class ("dropdown") li.add_control (l) li.add_control (d) @@ -97,7 +97,7 @@ feature -- Change local li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - create li.make_with_tag_name (control_name + "_link" + nav.controls.count.out, "li") + create li.make_with_tag_name ("li") li.add_class ("dropdown") li.add_control (l) li.add_control (d) @@ -107,12 +107,9 @@ feature -- Change add_list_element_right (l: WSF_STATELESS_CONTROL) -- Add element in li tag to right aligned part of navbar local - name: STRING li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - name := control_name + "_rightlink"; - name := name + nav_right.controls.count.out - create li.make_with_tag_name (name, "li") + create li.make_with_tag_name ("li") li.add_control (l) add_element_right (li) end @@ -122,7 +119,7 @@ feature -- Change local li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - create li.make_with_tag_name (control_name + "_link" + nav.controls.count.out, "li") + create li.make_with_tag_name ("li") li.add_control (l) add_element (li) end @@ -155,10 +152,10 @@ feature -- Properties brand: detachable STRING -- Optional brand of the navbar - nav: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + nav: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] -- Middle nav - nav_right: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + nav_right: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] -- Right nav end diff --git a/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_control.e b/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_control.e index 0cb3f015..e2558c53 100644 --- a/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_control.e +++ b/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_control.e @@ -9,7 +9,7 @@ class inherit - WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + WSF_MULTI_CONTROL [WSF_NAVLIST_ITEM_CONTROL] rename make as make_multi_control end @@ -19,9 +19,9 @@ create feature {NONE} -- Initialization - make (n: STRING) + make do - make_multi_control (n) + make_multi_control add_class ("list-group") end @@ -31,7 +31,16 @@ feature -- Change local c: WSF_NAVLIST_ITEM_CONTROL do - create c.make (control_name + "_item_" + controls.count.out, link, text) + create c.make (link, text) + add_control(c) + end + + add_button (event:attached like {WSF_BUTTON_CONTROL}.click_event; text: STRING) + local + c: WSF_NAVLIST_ITEM_CONTROL + do + create c.make ("", text) + c.set_click_event(event) add_control(c) end diff --git a/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_item.e b/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_item.e deleted file mode 100644 index a2b338a9..00000000 --- a/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_item.e +++ /dev/null @@ -1,30 +0,0 @@ -note - description: "Summary description for {WSF_NAVLIST_ITEM}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - WSF_NAVLIST_ITEM_CONTROL - -inherit - - WSF_BUTTON_CONTROL - rename - make as make_button - end - -create - make - -feature {NONE} -- Initialization - - make (n, link, t: STRING) - do - make_control (n, "a") - text := t - attributes := "href=%"" + link + "%""; - add_class ("list-group-item") - end - -end diff --git a/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_item_control.e b/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_item_control.e new file mode 100644 index 00000000..5dcbb5f5 --- /dev/null +++ b/draft/library/wsf_js_widget/kernel/navlist/wsf_navlist_item_control.e @@ -0,0 +1,71 @@ +note + description: "Summary description for {WSF_NAVLIST_ITEM}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_NAVLIST_ITEM_CONTROL + +inherit + + WSF_BUTTON_CONTROL + rename + make as make_button + redefine + set_state, + state + end + +create + make + +feature {NONE} -- Initialization + + make (link, t: STRING) + do + make_control ("a") + text := t + attributes := "href=%"" + link + "%""; + add_class ("list-group-item") + end + +feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management + + set_state (new_state: JSON_OBJECT) + -- Restore text from json + do + Precursor {WSF_BUTTON_CONTROL} (new_state) + if attached {JSON_BOOLEAN} new_state.item ("active") as new_active then + active := new_active.item + end + end + + state: WSF_JSON_OBJECT + -- Return state which contains the current text and if there is an event handle attached + do + Result := Precursor {WSF_BUTTON_CONTROL} + Result.put_boolean (active, "active") + end + +feature -- Change + + set_active (a: BOOLEAN) + -- Set text of that button + do + if active /= a then + active := a + if a then + add_class ("active") + else + remove_class ("active") + end + state_changes.replace (create {JSON_BOOLEAN}.make_boolean (a), "active") + end + end + +feature -- Properties + + active: BOOLEAN + +end diff --git a/draft/library/wsf_js_widget/kernel/progressbar/wsf_progress_control.e b/draft/library/wsf_js_widget/kernel/progressbar/wsf_progress_control.e index 5e2ea58c..07113ecf 100644 --- a/draft/library/wsf_js_widget/kernel/progressbar/wsf_progress_control.e +++ b/draft/library/wsf_js_widget/kernel/progressbar/wsf_progress_control.e @@ -19,18 +19,18 @@ create feature {NONE} -- Initialization - make (n: STRING) + make -- Initialize with specified control name do - make_control (n, "div") + make_control ("div") add_class ("progress") progress := 0 end - make_with_source (n: STRING; p: WSF_PROGRESSSOURCE) + make_with_source ( p: WSF_PROGRESSSOURCE) -- Initialize with specified control name and progresssource do - make (n) + make progress_source := p end @@ -51,9 +51,9 @@ feature -- State handling feature -- Event handling - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) do - if cname.same_string (control_name) and event.same_string ("progress_fetch") then + if cname[1].same_string (control_name) and event.same_string ("progress_fetch") then state_changes.put_integer (progress_value, "progress") end end diff --git a/draft/library/wsf_js_widget/kernel/slider/wsf_image_slider_control.e b/draft/library/wsf_js_widget/kernel/slider/wsf_slider_control.e similarity index 76% rename from draft/library/wsf_js_widget/kernel/slider/wsf_image_slider_control.e rename to draft/library/wsf_js_widget/kernel/slider/wsf_slider_control.e index c34f35d5..c952977c 100644 --- a/draft/library/wsf_js_widget/kernel/slider/wsf_image_slider_control.e +++ b/draft/library/wsf_js_widget/kernel/slider/wsf_slider_control.e @@ -19,14 +19,14 @@ create feature {NONE} -- Initialization - make (n: STRING) + make -- Initialize with specified name do - make_control (n, "div") + make_control ( "div") add_class ("carousel slide") - create list.make_with_tag_name (control_name + "_links", "ol") + create list.make_with_tag_name ( "ol") list.add_class ("carousel-indicators") - create slide_wrapper.make (control_name + "_wrapper") + create slide_wrapper.make_with_tag_name ("div") slide_wrapper.add_class ("carousel-inner") end @@ -43,7 +43,7 @@ feature -- State handling feature -- Callback - handle_callback (cname, event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) do -- Do nothing here end @@ -56,8 +56,8 @@ feature -- Rendering do temp := list.render temp.append (slide_wrapper.render) - temp.append (render_tag_with_tagname ("a", "", "href=%"#" + control_name + "%" data-slide=%"prev%"", "left carousel-control")) - temp.append (render_tag_with_tagname ("a", "", "href=%"#" + control_name + "%" data-slide=%"next%"", "right carousel-control")) + temp.append (render_tag_with_tagname ("a", "", "data-slide=%"prev%"", "left carousel-control")) + temp.append (render_tag_with_tagname ("a", "", "data-slide=%"next%"", "right carousel-control")) Result := render_tag (temp, "") end @@ -91,7 +91,7 @@ feature -- Change cl: STRING item: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - create item.make (control_name + "_item" + slide_wrapper.controls.count.out) + create item.make () item.add_class ("item") item.add_control (c) if attached caption as capt then @@ -103,15 +103,15 @@ feature -- Change item.add_class (cl) end slide_wrapper.add_control (item) - list.add_control (create {WSF_BASIC_CONTROL}.make_with_body_class ("li", "data-target=%"#" + control_name + "%" data-slide-to=%"" + list.controls.count.out + "%"", cl, "")); + list.add_control (create {WSF_BASIC_CONTROL}.make_with_body_class ("li", "data-slide-to=%"" + list.controls.count.out + "%"", cl, "")); end feature -- Properties - list: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + list: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] -- List of slider links - slide_wrapper: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + slide_wrapper: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] -- List of the single slides end diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_agent_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_agent_validator.e new file mode 100644 index 00000000..779b4fd4 --- /dev/null +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_agent_validator.e @@ -0,0 +1,37 @@ +note + description: "Summary description for {WSF_AGENT_VALIDATOR}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_AGENT_VALIDATOR [G] + +inherit + + WSF_VALIDATOR [G] + rename + make as make_validator + end + +create + make + +feature {NONE} -- Initialization + + make (h: like handler; e: STRING) + do + make_validator (e) + handler := h + end + +feature + + is_valid (input: G): BOOLEAN + do + Result := handler.item ([input]) + end + + handler: FUNCTION [ANY, TUPLE [G], BOOLEAN] + +end diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_decimal_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_decimal_validator.e index 5c7f2939..bfb3fcd7 100644 --- a/draft/library/wsf_js_widget/kernel/validator/wsf_decimal_validator.e +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_decimal_validator.e @@ -10,13 +10,16 @@ class inherit WSF_REGEXP_VALIDATOR + rename + make as make_regexp_validator + end create - make_decimal_validator + make feature {NONE} -- Initialization - make_decimal_validator (e: STRING) + make (e: STRING) -- Initialize with specified error message which will be displayed on validation failure do make_regexp_validator ("^[0-9]+(\.[0-9]*)?$|^\.[0-9]+$", e) diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_email_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_email_validator.e index f3cd93b3..e5b64f41 100644 --- a/draft/library/wsf_js_widget/kernel/validator/wsf_email_validator.e +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_email_validator.e @@ -10,16 +10,19 @@ class inherit WSF_REGEXP_VALIDATOR + rename + make as make_regexp_validator + end create - make_email_validator + make feature {NONE} -- Initialization - make_email_validator (e: STRING) + make (e: STRING) -- Initialize with specified error message which will be displayed on validation failure do - make_regexp_validator ("^[a-zA-Z0-9._%%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$", e) + make_regexp_validator ("^[a-zA-Z0-9._%%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$", e) end end diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_filesize_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_filesize_validator.e new file mode 100644 index 00000000..517decdf --- /dev/null +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_filesize_validator.e @@ -0,0 +1,54 @@ +note + description: "Summary description for {WSF_FILESIZE_VALIDATOR}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_FILESIZE_VALIDATOR + +inherit + + WSF_VALIDATOR [detachable WSF_PENDING_FILE] + rename + make as make_validator + redefine + state + end + +create + make + +feature {NONE} -- Initialization + + make (m: INTEGER; e: STRING) + -- Initialize with specified maximum filesize and error message which will be displayed on validation failure + do + make_validator (e) + max := m + end + +feature -- Implementation + + is_valid (input: detachable WSF_PENDING_FILE): BOOLEAN + do + Result := True + if attached input as a_input then + Result := a_input.size < max or a_input.size = max + end + end + +feature -- State + + state: WSF_JSON_OBJECT + do + Result := Precursor + Result.put_integer (max, "max") + end + +feature -- Properties + + max: INTEGER + -- The maximal allowed value + +end diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_max_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_max_validator.e index 2dc91970..ad472e1b 100644 --- a/draft/library/wsf_js_widget/kernel/validator/wsf_max_validator.e +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_max_validator.e @@ -5,30 +5,32 @@ note revision: "$Revision$" class - WSF_max_VALIDATOR [G] + WSF_MAX_VALIDATOR [G -> FINITE [ANY]] inherit - WSF_VALIDATOR [LIST [G]] + WSF_VALIDATOR [G] + rename + make as make_validator redefine state end create - make_max_validator + make feature {NONE} -- Initialization - make_max_validator (m: INTEGER; e: STRING) + make (m: INTEGER; e: STRING) -- Initialize with specified maximum and error message which will be displayed on validation failure do - make (e) + make_validator (e) max := m end feature -- Implementation - is_valid (input: LIST [G]): BOOLEAN + is_valid (input: G): BOOLEAN do Result := input.count < max or input.count = max end diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_min_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_min_validator.e index 68d299d8..1175c147 100644 --- a/draft/library/wsf_js_widget/kernel/validator/wsf_min_validator.e +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_min_validator.e @@ -5,30 +5,32 @@ note revision: "$Revision$" class - WSF_MIN_VALIDATOR [G] + WSF_MIN_VALIDATOR [G -> FINITE [ANY]] inherit - WSF_VALIDATOR [LIST [G]] + WSF_VALIDATOR [G] + rename + make as make_validator redefine state end create - make_min_validator + make feature {NONE} -- Initialization - make_min_validator (m: INTEGER; e: STRING) + make (m: INTEGER; e: STRING) -- Initialize with specified minimum and error message which will be displayed on validation failure do - make (e) + make_validator (e) min := m end feature -- Implementation - is_valid (input: LIST [G]): BOOLEAN + is_valid (input: G): BOOLEAN do Result := input.count > min or input.count = min end diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_phone_number_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_phone_number_validator.e index e5ca0cc4..3f377d12 100644 --- a/draft/library/wsf_js_widget/kernel/validator/wsf_phone_number_validator.e +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_phone_number_validator.e @@ -10,6 +10,9 @@ class inherit WSF_REGEXP_VALIDATOR + rename + make as make_regexp_validator + end create make_with_message diff --git a/draft/library/wsf_js_widget/kernel/validator/wsf_regexp_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_regexp_validator.e index 95fd6d94..0914acd3 100644 --- a/draft/library/wsf_js_widget/kernel/validator/wsf_regexp_validator.e +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_regexp_validator.e @@ -10,19 +10,21 @@ class inherit WSF_VALIDATOR [STRING] + rename + make as make_validator redefine state end create - make_regexp_validator + make feature {NONE} -- Initialization - make_regexp_validator (r, e: STRING) + make (r, e: STRING) -- Initialize with specified regular expression and error message which will be displayed on validation failure do - make (e) + make_validator (e) regexp_string := r create regexp end @@ -35,7 +37,8 @@ feature -- Implementation if not regexp.is_compiled then regexp.compile (regexp_string) end - Result := regexp.matches (input) + + Result := (not input.is_empty) and regexp.matches (input) end feature -- State diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_button_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_button_control.e index 841537af..3b49767e 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_button_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_button_control.e @@ -19,13 +19,13 @@ create feature {NONE} -- Initialization - make (n: STRING; t: STRING) + make (a_text: STRING) -- Initialize with specified control name and text do - make_control (n, "button") + make_control ("button") add_class ("btn") add_class ("btn-default") - text := t + text := a_text end feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management @@ -54,9 +54,9 @@ feature --Event handling click_event := e end - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) do - if Current.control_name.same_string (cname) and attached click_event as cevent then + if Current.control_name.same_string (cname[1]) and attached click_event as cevent then cevent.call (Void) end end diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_control.e index f3ee1f54..102d8b5e 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_control.e @@ -18,14 +18,13 @@ inherit feature {NONE} -- Initialization - make (n, a_tag_name: STRING) + make (a_tag_name: STRING) -- Initialize with specified control name and tag require - not n.is_empty not a_tag_name.is_empty do make_stateless_control (a_tag_name) - control_name := n + create control_name_prefix.make_empty create state_changes.make create actions.make_array ensure @@ -34,38 +33,41 @@ feature {NONE} -- Initialization feature -- Actions - start_modal (url: STRING; title: STRING) + start_modal (url: STRING; title: STRING; big: BOOLEAN) --Start a modal window containg an other or the same page local modal: WSF_JSON_OBJECT do create modal.make - modal.put_string ("start_modal", "type") + if big then + modal.put_string ("start_modal_big", "type") + else + modal.put_string ("start_modal", "type") + end modal.put_string (url, "url") modal.put_string (title, "title") actions.add (modal) end - start_modal_big (url: STRING; title: STRING) + show_alert (message: STRING) --Start a modal window containg an other or the same page local - modal: WSF_JSON_OBJECT + alert: WSF_JSON_OBJECT do - create modal.make - modal.put_string ("start_modal_big", "type") - modal.put_string (url, "url") - modal.put_string (title, "title") - actions.add (modal) + create alert.make + alert.put_string ("show_alert", "type") + alert.put_string (message, "message") + actions.add (alert) end - show_alert (mesage: STRING) - --Start a modal window containg an other or the same page + redirect (url: STRING) + --Redirect to an other page local modal: WSF_JSON_OBJECT do create modal.make - modal.put_string ("show_alert", "type") - modal.put_string (mesage, "message") + modal.put_string ("redirect", "type") + modal.put_string (url, "url") actions.add (modal) end @@ -140,7 +142,7 @@ feature -- Rendering loop css_classes_string := css_classes_string + " " + c.item end - l_attributes := "id=%"" + control_name + "%" data-name=%"" + control_name + "%" data-type=%"" + a_generator + "%" " + l_attributes := " data-name=%"" + control_name + "%" data-type=%"" + a_generator + "%" " if attached attrs as a then l_attributes := l_attributes + a end @@ -152,7 +154,7 @@ feature -- Rendering feature -- Event handling - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST [STRING]; event: STRING; event_parameter: detachable ANY) -- Method called if any callback received. In this method you can route the callback to the event handler deferred end @@ -170,6 +172,24 @@ feature -- Properties actions: JSON_ARRAY + control_id: INTEGER assign set_control_id + + set_control_id (d: INTEGER) + do + control_id := d + end + control_name: STRING + do + Result := control_name_prefix + control_id.out + end + + control_name_prefix: STRING assign set_control_name_prefix + + + set_control_name_prefix (p: STRING) + do + control_name_prefix := p + end end diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_control.e index 14c094fb..81fc8796 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_control.e @@ -9,23 +9,41 @@ class inherit - WSF_MULTI_CONTROL [WSF_CONTROL] + WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] rename make as make_multi_control + redefine + add_control end WSF_VALIDATABLE create - make + make, make_with_label_width feature {NONE} -- Initialization - make (n: STRING) + make -- Initialize do - make_multi_control (n) + make_with_label_width (2) + end + + make_with_label_width (w: INTEGER) + do + make_multi_control tag_name := "form" + label_width := w + end + +feature + + add_control (c: WSF_STATELESS_CONTROL) + do + Precursor (c) + if attached {WSF_FORM_ELEMENT_CONTROL[ANY]} c as fec then + fec.set_label_width (label_width) + end end feature -- Validation @@ -36,8 +54,6 @@ feature -- Validation is_valid := True across controls as c - until - is_valid = False loop if attached {WSF_VALIDATABLE} c.item as elem then elem.validate @@ -51,4 +67,8 @@ feature -- Validation is_valid: BOOLEAN -- Tells whether the last validation was valid +feature + + label_width: INTEGER + end diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_element_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_element_control.e index b8fd1d9f..1c759e94 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_element_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_form_element_control.e @@ -34,20 +34,28 @@ feature {NONE} -- Initialization make_with_validators (a_label: STRING; c: WSF_VALUE_CONTROL [G]; v: LIST [WSF_VALIDATOR [G]]) -- Initialize form element control with a specific label, value control and list of validators do - make_control (c.control_name + "_container", "div") + make_control ("div") add_class ("form-group") - if attached {WSF_INPUT_CONTROL} c or attached {WSF_TEXTAREA_CONTROL} c then - c.add_class ("form-control") - end if attached {WSF_HTML_CONTROL} c then c.add_class ("form-control-static") + elseif not attached {WSF_VALUE_CONTROL [LIST[ANY]]} c then + + c.add_class ("form-control") end + label_width := 2 value_control := c validators := v label := a_label error := "" end +feature + + set_label_width (w: INTEGER) + do + label_width := w + end + feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management load_state (new_states: JSON_OBJECT) @@ -77,9 +85,22 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management read_state_changes (states: WSF_JSON_OBJECT) -- Read states_changes in subcontrols + local + sub_states: WSF_JSON_OBJECT + control_state: WSF_JSON_OBJECT do Precursor (states) - value_control.read_state_changes (states) + create sub_states.make + value_control.read_state_changes (sub_states) + if sub_states.count > 0 then + if attached {JSON_OBJECT} states.item (control_name) as changes then + changes.put (sub_states, "controls") + else + create control_state.make + control_state.put (sub_states, "controls") + states.put (control_state, control_name) + end + end end state: WSF_JSON_OBJECT @@ -100,15 +121,19 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management feature -- Event handling - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST [STRING]; event: STRING; event_parameter: detachable ANY) -- Pass callback to subcontrols do - if cname.same_string (control_name) then - if event.same_string ("validate") then - validate + if cname [1].same_string (control_name) then + cname.go_i_th (1) + cname.remove + if cname.is_empty then + if event.same_string ("validate") then + validate + end + else + value_control.handle_callback (cname, event, event_parameter) end - else - value_control.handle_callback (cname, event, event_parameter) end end @@ -121,9 +146,9 @@ feature -- Implementation do body := "" if not label.is_empty then - body.append ("") + body.append ("") end - body.append ("
") + body.append ("
") body.append (value_control.render) body.append ("
") Result := render_tag (body, "") @@ -183,4 +208,6 @@ feature -- Properties error: STRING -- The error message that is displayed when client side validation fails + label_width: INTEGER + end diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_html_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_html_control.e index 7d6a6f4c..59998e00 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_html_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_html_control.e @@ -17,10 +17,10 @@ create feature {NONE} -- Initialization - make (n, t, v: STRING) + make (t, v: STRING) -- Initialize do - make_value_control (n, t) + make_value_control ( t) html := v end @@ -43,7 +43,7 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management feature --Event handling - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) do end diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_layout_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_layout_control.e index d42708b0..0ce05128 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_layout_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_layout_control.e @@ -9,10 +9,10 @@ class inherit - WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] rename make as make_multi_control, - add_control as add_control_raw + add_control as add_control_raw end create @@ -22,7 +22,7 @@ feature {NONE} -- Initialization make (n: STRING) do - make_with_tag_name (n, "div") + make_with_tag_name ("div") add_class ("row") end @@ -30,21 +30,27 @@ feature -- Add control add_control_with_offset (c: WSF_STATELESS_CONTROL; span, offset: INTEGER) local - div: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + div: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] do - create div.make (control_name + "_item_" + controls.count.out) + create div.make_with_tag_name ("div") div.add_class ("col-md-" + span.out + " col-md-offset-" + offset.out) div.add_control (c) add_control_raw (div) end - add_control (c: WSF_STATELESS_CONTROL; span: INTEGER) - local - div: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL] + add_control (col:INTEGER; c: WSF_STATELESS_CONTROL) do - create div.make (control_name + "_item_" + controls.count.out) + if attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]}controls[col] as div then + div.add_control (c) + end + end + + add_column (span:INTEGER) + local + div: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL] + do + create div.make_with_tag_name ("div") div.add_class ("col-md-" + span.out) - div.add_control (c) add_control_raw (div) end diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_multi_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_multi_control.e index 719ed911..44da1df7 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_multi_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_multi_control.e @@ -23,16 +23,16 @@ create feature {NONE} -- Initialization - make (n: STRING) + make -- Initialize with specified control name and default tag "div" do - make_with_tag_name (n, "div") + make_with_tag_name ("div") end - make_with_tag_name (n, t: STRING) + make_with_tag_name (t: STRING) -- Initialize with specified control name and tag do - make_control (n, t) + make_control (t) controls := create {ARRAYED_LIST [G]}.make (5); end @@ -43,13 +43,20 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management do Precursor (new_states) if attached {JSON_OBJECT} new_states.item ("controls") as ct then - across - controls as c - loop - if attached {WSF_CONTROL} c.item as cont then - if attached {JSON_OBJECT} ct.item (cont.control_name) as value_state then - cont.load_state (value_state) - end + load_subcontrol_state (ct) + end + end + + load_subcontrol_state (newstate: JSON_OBJECT) + do + across + controls as c + loop + if attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]} c.item as cont then + cont.load_subcontrol_state (newstate) + elseif attached {WSF_CONTROL} c.item as cont then + if attached {JSON_OBJECT} newstate.item (cont.control_name) as value_state then + cont.load_state (value_state) end end end @@ -67,24 +74,51 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management do Result := Precursor create controls_state.make + read_subcontrol_state (controls_state) + Result.put (controls_state, "controls") + end + + read_subcontrol_state (controls_state: JSON_OBJECT) + do across controls as c loop - if attached {WSF_CONTROL} c.item as cont then + if attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]} c.item as mcont then + mcont.read_subcontrol_state (controls_state) + elseif attached {WSF_CONTROL} c.item as cont then controls_state.put (cont.full_state, cont.control_name) end end - Result.put (controls_state, "controls") end read_state_changes (states: WSF_JSON_OBJECT) -- Read states_changes in subcontrols + local + sub_states: WSF_JSON_OBJECT + control_state: WSF_JSON_OBJECT do Precursor (states) + create sub_states.make + read_subcontrol_state_changes (sub_states) + if sub_states.count > 0 then + if attached {JSON_OBJECT} states.item (control_name) as changes then + changes.put (sub_states, "controls") + else + create control_state.make + control_state.put (sub_states, "controls") + states.put (control_state, control_name) + end + end + end + + read_subcontrol_state_changes (states: WSF_JSON_OBJECT) + do across controls as c loop - if attached {WSF_CONTROL} c.item as cont then + if attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]} c.item as cont then + cont.read_subcontrol_state_changes (states) + elseif attached {WSF_CONTROL} c.item as cont then cont.read_state_changes (states) end end @@ -98,16 +132,21 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management feature -- Event handling - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST [STRING]; event: STRING; event_parameter: detachable ANY) -- Pass callback to subcontrols do - if equal (cname, control_name) then - else - across - controls as c - loop - if attached {WSF_CONTROL} c.item as cont then - cont.handle_callback (cname, event, event_parameter) + if equal (cname [1], control_name) then + cname.go_i_th (1) + cname.remove + if not cname.is_empty then + across + controls as c + until + cname.is_empty + loop + if attached {WSF_CONTROL} c.item as cont then + cont.handle_callback (cname, event, event_parameter) + end end end end @@ -124,19 +163,26 @@ feature -- Rendering loop Result := Result + c.item.render end - Result := render_tag (Result, "") + if not tag_name.is_empty then + Result := render_tag (Result, "") + end end -feature -- Change +feature add_control (c: G) -- Add a control to this multi control do controls.extend (c) + if attached {WSF_CONTROL} c as d then + d.control_id := controls.count + end end feature -- Properties + stateless: BOOLEAN + controls: ARRAYED_LIST [G] -- List of current controls in this multi control diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_page_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_page_control.e index 1c0c17a3..4b49e234 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_page_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_page_control.e @@ -13,6 +13,7 @@ inherit rename make as make_control redefine + control_name, full_state, read_state_changes end @@ -22,7 +23,8 @@ feature {NONE} -- Initialization make (req: WSF_REQUEST; res: WSF_RESPONSE) -- Initialize do - make_control (req.request_time_stamp.out, "body") + control_name := req.request_time_stamp.out + make_control ("body") request := req response := res initialize_controls @@ -57,7 +59,7 @@ feature -- Implementation -- If request is not a callback. Run process and render the html page local event: detachable STRING - event_parameter: detachable STRING + event_parameter: detachable ANY event_control_name: detachable STRING states: STRING states_changes: WSF_JSON_OBJECT @@ -67,13 +69,23 @@ feature -- Implementation event := get_parameter ("event") event_parameter := get_parameter ("event_parameter") if attached event and attached event_control_name and attached control then - create states.make_empty - request.read_input_data_into (states) - create json_parser.make_parser (states) - if attached {JSON_OBJECT} json_parser.parse_json as sp then - set_state (sp) + if not event.is_equal ("uploadfile") then + create states.make_empty + request.read_input_data_into (states) + create json_parser.make_parser (states) + if attached {JSON_OBJECT} json_parser.parse_json as sp then + set_state (sp) + end + else + if attached request.form_parameter ("state") as statedata then + create json_parser.make_parser (statedata.as_string.value) + if attached {JSON_OBJECT} json_parser.parse_json as sp then + set_state (sp) + end + end + event_parameter:=request.uploaded_files end - handle_callback (event_control_name, event, event_parameter) + handle_callback (event_control_name.split ('-'), event, event_parameter) create states_changes.make read_state_changes (states_changes) response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "application/json; charset=ISO-8859-1"]>>) @@ -121,7 +133,6 @@ feature -- Implementation Result.append (");page.initialize();});") Result.append ("
") end - end read_state_changes (states: WSF_JSON_OBJECT) @@ -145,7 +156,7 @@ feature -- Implementation feature -- Event handling - handle_callback (cname: STRING; event: STRING; event_parameter: detachable STRING) + handle_callback (cname: LIST [STRING]; event: STRING; event_parameter: detachable ANY) -- Forward callback to control do control.handle_callback (cname, event, event_parameter) @@ -179,6 +190,10 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management Result.put (state, "state") end +feature + + control_name: STRING + feature {NONE} -- Root control control: WSF_CONTROL diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_stateless_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_stateless_control.e index 6bfbd7be..9294e329 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_stateless_control.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_stateless_control.e @@ -37,6 +37,12 @@ feature -- Change css_classes.force (c) end + remove_class (cla: STRING) + -- Add a css class to this control + do + css_classes.prune (cla) + end + feature -- Rendering render_tag (body: STRING; attrs: detachable STRING): STRING @@ -69,7 +75,7 @@ feature -- Rendering l_attributes.append_character ('%"') end Result := "<" + tag + " " + l_attributes - if body.is_empty and not tag.same_string ("textarea") and not tag.same_string ("span") and not tag.same_string ("button") and not tag.same_string ("ul") then + if body.is_empty and not tag.same_string ("textarea") and not tag.same_string ("span") and not tag.same_string ("button") and not tag.same_string ("ul") and not tag.same_string ("div") then Result.append (" />") else Result.append (" >" + body + "") diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_stateless_multi_control.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_stateless_multi_control.e new file mode 100644 index 00000000..9e3579cd --- /dev/null +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_stateless_multi_control.e @@ -0,0 +1,93 @@ + +note + description: "Summary description for {WSF_STATELESS_MULTI_CONTROL}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_STATELESS_MULTI_CONTROL [G -> WSF_STATELESS_CONTROL] + +inherit + + WSF_MULTI_CONTROL [G] + rename + make_with_tag_name as make_with_tag_name_and_name + redefine + add_control, + set_control_name_prefix, + handle_callback, + set_control_id + end + +create + make_with_tag_name, make_tag_less + +feature {NONE} -- Initialization + + make_with_tag_name (t: STRING) + do + make_with_tag_name_and_name (t) + end + + make_tag_less + do + make_with_tag_name_and_name ("") + stateless := True + end + +feature + + + + set_control_id (d: INTEGER) + do + control_id := d + set_subcontrol_prefixes + end + + set_control_name_prefix (p: STRING) + do + control_name_prefix := p + set_subcontrol_prefixes + end + + set_subcontrol_prefixes + do + across + controls as e + loop + if attached {WSF_CONTROL} e.item as el then + el.control_name_prefix := control_name_prefix + control_id.out + "_" + end + end + end + +feature + + add_control (c: G) + -- Add a control to this multi control + do + controls.extend (c) + if attached {WSF_CONTROL} c as d then + d.control_id := controls.count + d.control_name_prefix := control_name_prefix + control_id.out + "_" + end + end +feature -- Event handling + + handle_callback (cname: LIST [STRING]; event: STRING; event_parameter: detachable ANY) + -- Pass callback to subcontrols + do + across + controls as c + until + cname.is_empty + loop + if attached {WSF_CONTROL} c.item as cont then + cont.handle_callback (cname, event, event_parameter) + end + end + end + +end diff --git a/examples/widgetapp/assets/widget.coffee b/examples/widgetapp/assets/widget.coffee index 323faf89..0e7f7cc0 100644 --- a/examples/widgetapp/assets/widget.coffee +++ b/examples/widgetapp/assets/widget.coffee @@ -69,7 +69,17 @@ Mini = { render:template(t) } +parseSuggestions = (data)-> + for a of data + if a == 'suggestions' + return data[a] + else + d = parseSuggestions(data[a]) + if d? + return d + return null loaded = {} + lazy_load = (requirements,fn,that)-> if requirements.length == 0 return ()-> @@ -97,7 +107,7 @@ lazy_load = (requirements,fn,that)-> done() build_control = (control_name, state, control)-> - $el = control.$el.find('[data-name='+control_name+']') + $el = control.$el.find('[data-name='+control_name+']').first() #get control type type = $el.data('type') #create class @@ -170,22 +180,45 @@ class WSF_CONTROL process_actions: (actions)-> for action in actions try - fn = eval(action.type) - fn(action) + fn = null + #Check if action exists in class then check global + if @[action.type]? + fn = @[action.type] + fn.call(@, action) + else + fn = eval(action.type) + fn(action) catch e console.log "Failed preforming action #{action.type}" process_update: (new_states)-> - if new_states[@control_name]? - @update(new_states[@control_name]) - for control in @controls - if control? - control.process_update(new_states) + try + if new_states.actions? + @process_actions(new_states.actions) + if new_states[@control_name]? + @update(new_states[@control_name]) + for control in @controls + if control? + control.process_update(new_states[this.control_name]['controls']) + catch e + return + return + + get_context_state : ()-> if @parent_control? and not @isolation return @parent_control.get_context_state() return @wrap(@control_name,@fullstate) + + get_full_control_name: ()-> + if @parent_control? + val = @parent_control.get_full_control_name() + if val != "" + val = val + "-" + return val+@control_name + return @control_name + wrap : (cname,state)-> ctrs = {} ctrs[cname] = state @@ -201,10 +234,18 @@ class WSF_CONTROL @url + '?' + $.param(params) trigger_callback: (control_name,event,event_parameter)-> + @run_trigger_callback(@get_full_control_name(),event,event_parameter) + + get_page:()-> + if @parent_control? + return @parent_control.get_page() + return @ + + run_trigger_callback: (control_name,event,event_parameter)-> if @parent_control? and not @isolation - return @parent_control.trigger_callback(control_name,event,event_parameter) + return @parent_control.run_trigger_callback(control_name,event,event_parameter) self = @ - $.ajax + return $.ajax type: 'POST', url: @callback_url control_name: control_name @@ -217,9 +258,7 @@ class WSF_CONTROL cache: no .done (new_states)-> #Update all classes - if new_states.actions? - self.process_actions(new_states.actions) - self.process_update(new_states) + self.get_page().process_update(new_states) #Simple event listener @@ -257,6 +296,16 @@ class WSF_PAGE_CONTROL extends WSF_CONTROL @initialize = lazy_load @requirements, @attach_events, @ @load_subcontrols() + process_update: (new_states)-> + for control in @controls + if control? + control.process_update(new_states) + + return + + get_full_control_name: ()-> + "" + wrap : (cname,state)-> state @@ -265,10 +314,16 @@ class WSF_PAGE_CONTROL extends WSF_CONTROL @$el.remove() class WSF_SLIDER_CONTROL extends WSF_CONTROL - requirements: ['assets/bootstrap.min.js'] + requirements: ['/assets/bootstrap.min.js'] + attach_events: ()-> + super + id = "slider"+Math.round(Math.random()*10000) + @$el.attr("id",id) + @$el.find("ol li").attr("data-target","#"+id) + @$el.find(".carousel-control").attr("href","#"+id) class WSF_DROPDOWN_CONTROL extends WSF_CONTROL - requirements: ['assets/bootstrap.min.js'] + requirements: ['/assets/bootstrap.min.js'] controls = {} @@ -311,14 +366,97 @@ class WSF_INPUT_CONTROL extends WSF_CONTROL @state['text'] = state.text @$el.val(state.text) +class WSF_FILE_CONTROL extends WSF_CONTROL + constructor: ()-> + super + @uploading = false + + start_upload: ()-> + if @uploading + return + @uploading = true + @$el.hide() + @progressbar = $ """
""" + @$el.parent().append(@progressbar) + + formData = new FormData(); + action = @callback_url + control_name: @get_full_control_name() + event: "uploadfile" + event_parameter: "" + file = @$el[0].files[0]; + formData.append('file', file) + formData.append('state', JSON.stringify(@get_context_state())) + @sendXHRequest(formData, action) + + sendXHRequest: (formData, uri)-> + #Get an XMLHttpRequest instance + xhr = new XMLHttpRequest(); + self = @ + onprogressHandler = (evt)-> + percent = evt.loaded/evt.total*100 + self.progressbar.find('.progress-bar').css {'width':percent+"%"} + onstatechange = (evt)-> + if xhr.readyState==4 && xhr.status==200 + self.get_page().process_update(JSON.parse(xhr.responseText)) + + xhr.upload.addEventListener('progress', onprogressHandler, false); + + + xhr.addEventListener('readystatechange', onstatechange, false); + xhr.open('POST', uri, true); + xhr.send(formData); + + attach_events: ()-> + super + self = @ + @$el.change ()-> + self.change() + + change: ()-> + #update local state + @state['file'] = null + @state['type'] = null + @state['size'] = null + if @$el[0].files.length>0 + file = @$el[0].files[0] + @state['file'] = file.name + @state['type'] = file.type + @state['size'] = file.size + if @state['callback_change'] + @trigger_callback(@control_name, 'change') + @trigger('change') + + value:()-> + return @$el.val() + + update: (state) -> + if state.upload_file? + @progressbar.hide() + @$el.parent().append($("""

""").addClass("form-control-static").text(@state['file'])) + @state['upload_file'] = state.upload_file + +class WSF_PASSWORD_CONTROL extends WSF_INPUT_CONTROL + +class WSF_NAVLIST_ITEM_CONTROL extends WSF_BUTTON_CONTROL + update: (state) -> + super + if state.active? + @state['active'] = state.active + if state.active + @$el.addClass("active") + else + @$el.removeClass("active") + + class WSF_TEXTAREA_CONTROL extends WSF_INPUT_CONTROL class WSF_CODEVIEW_CONTROL extends WSF_INPUT_CONTROL constructor:()-> super #load codemirror and then eiffel syntax - @initialize = lazy_load ['assets/codemirror/codemirror.js','assets/codemirror/codemirror.css','assets/codemirror/estudio.css'], - (lazy_load ['assets/codemirror/eiffel.js'], @attach_events, @), + @initialize = lazy_load ['/assets/codemirror/codemirror.js','/assets/codemirror/codemirror.css','/assets/codemirror/estudio.css'], + (lazy_load ['/assets/codemirror/eiffel.js'], @attach_events, @), @ attach_events: () -> @@ -341,8 +479,9 @@ class WSF_AUTOCOMPLETE_CONTROL extends WSF_INPUT_CONTROL attach_events: () -> super self = @ + console.log @$el @$el.typeahead({ - name: @control_name + name: @control_name+Math.random() template: @state['template'] engine: Mini remote: @@ -354,7 +493,7 @@ class WSF_AUTOCOMPLETE_CONTROL extends WSF_INPUT_CONTROL event: 'autocomplete' states: JSON.stringify(self.get_context_state()) filter: (parsedResponse) -> - parsedResponse[self.control_name]['suggestions'] + return parseSuggestions(parsedResponse) fn: ()-> self.trigger_callback(self.control_name, 'autocomplete') }) @@ -426,7 +565,7 @@ class WSF_FORM_ELEMENT_CONTROL extends WSF_CONTROL if message.length>0 @$el.addClass("has-error") errordiv = $("
").addClass('help-block').addClass('validation').text(message) - @$el.find(".col-lg-10").append(errordiv) + @$el.children("div").append(errordiv) update: (state) -> if state.error? @@ -536,11 +675,13 @@ class WSF_REPEATER_CONTROL extends WSF_CONTROL #### actions +redirect = (action) -> + document.location.href = action.url show_alert = (action)-> alert(action.message) -start_modal = lazy_load ['assets/bootstrap.min.js'], (action)-> +start_modal = lazy_load ['/assets/bootstrap.min.js'], (action)-> cssclass = "" if action.type == "start_modal_big" cssclass = " big" diff --git a/examples/widgetapp/assets/widget.css b/examples/widgetapp/assets/widget.css index 3f27bf68..9c215361 100644 --- a/examples/widgetapp/assets/widget.css +++ b/examples/widgetapp/assets/widget.css @@ -97,4 +97,9 @@ body { .CodeMirror-code{ line-height: 1.4em; +} + +.upload.progress{ + margin-top: 7px; + margin-bottom: 0px; } \ No newline at end of file diff --git a/examples/widgetapp/assets/widget.js b/examples/widgetapp/assets/widget.js index 5cb134cd..2dac6b4d 100644 --- a/examples/widgetapp/assets/widget.js +++ b/examples/widgetapp/assets/widget.js @@ -1,5 +1,5 @@ // Generated by CoffeeScript 1.6.1 -var Mini, WSF_AUTOCOMPLETE_CONTROL, WSF_BUTTON_CONTROL, WSF_CHECKBOX_CONTROL, WSF_CHECKBOX_LIST_CONTROL, WSF_CODEVIEW_CONTROL, WSF_CONTROL, WSF_DROPDOWN_CONTROL, WSF_FORM_ELEMENT_CONTROL, WSF_GRID_CONTROL, WSF_HTML_CONTROL, WSF_INPUT_CONTROL, WSF_MAX_VALIDATOR, WSF_MIN_VALIDATOR, WSF_PAGE_CONTROL, WSF_PAGINATION_CONTROL, WSF_PROGRESS_CONTROL, WSF_REGEXP_VALIDATOR, WSF_REPEATER_CONTROL, WSF_SLIDER_CONTROL, WSF_TEXTAREA_CONTROL, WSF_VALIDATOR, build_control, cache, controls, lazy_load, loaded, show_alert, start_modal, start_modal_big, template, tmpl, +var Mini, WSF_AUTOCOMPLETE_CONTROL, WSF_BUTTON_CONTROL, WSF_CHECKBOX_CONTROL, WSF_CHECKBOX_LIST_CONTROL, WSF_CODEVIEW_CONTROL, WSF_CONTROL, WSF_DROPDOWN_CONTROL, WSF_FILE_CONTROL, WSF_FORM_ELEMENT_CONTROL, WSF_GRID_CONTROL, WSF_HTML_CONTROL, WSF_INPUT_CONTROL, WSF_MAX_VALIDATOR, WSF_MIN_VALIDATOR, WSF_NAVLIST_ITEM_CONTROL, WSF_PAGE_CONTROL, WSF_PAGINATION_CONTROL, WSF_PASSWORD_CONTROL, WSF_PROGRESS_CONTROL, WSF_REGEXP_VALIDATOR, WSF_REPEATER_CONTROL, WSF_SLIDER_CONTROL, WSF_TEXTAREA_CONTROL, WSF_VALIDATOR, build_control, cache, controls, lazy_load, loaded, parseSuggestions, redirect, show_alert, start_modal, start_modal_big, template, tmpl, __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; }; @@ -101,6 +101,21 @@ Mini = { } }; +parseSuggestions = function(data) { + var a, d; + for (a in data) { + if (a === 'suggestions') { + return data[a]; + } else { + d = parseSuggestions(data[a]); + if (d != null) { + return d; + } + } + } + return null; +}; + loaded = {}; lazy_load = function(requirements, fn, that) { @@ -141,7 +156,7 @@ lazy_load = function(requirements, fn, that) { build_control = function(control_name, state, control) { var $el, type, typeclass; - $el = control.$el.find('[data-name=' + control_name + ']'); + $el = control.$el.find('[data-name=' + control_name + ']').first(); type = $el.data('type'); typeclass = null; try { @@ -283,8 +298,14 @@ WSF_CONTROL = (function() { for (_i = 0, _len = actions.length; _i < _len; _i++) { action = actions[_i]; try { - fn = eval(action.type); - _results.push(fn(action)); + fn = null; + if (this[action.type] != null) { + fn = this[action.type]; + _results.push(fn.call(this, action)); + } else { + fn = eval(action.type); + _results.push(fn(action)); + } } catch (e) { _results.push(console.log("Failed preforming action " + action.type)); } @@ -293,21 +314,24 @@ WSF_CONTROL = (function() { }; WSF_CONTROL.prototype.process_update = function(new_states) { - var control, _i, _len, _ref, _results; - if (new_states[this.control_name] != null) { - this.update(new_states[this.control_name]); - } - _ref = this.controls; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - control = _ref[_i]; - if (control != null) { - _results.push(control.process_update(new_states)); - } else { - _results.push(void 0); + var control, _i, _len, _ref; + try { + if (new_states.actions != null) { + this.process_actions(new_states.actions); } + if (new_states[this.control_name] != null) { + this.update(new_states[this.control_name]); + _ref = this.controls; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + control = _ref[_i]; + if (control != null) { + control.process_update(new_states[this.control_name]['controls']); + } + } + } + } catch (e) { + return; } - return _results; }; WSF_CONTROL.prototype.get_context_state = function() { @@ -317,6 +341,18 @@ WSF_CONTROL = (function() { return this.wrap(this.control_name, this.fullstate); }; + WSF_CONTROL.prototype.get_full_control_name = function() { + var val; + if (this.parent_control != null) { + val = this.parent_control.get_full_control_name(); + if (val !== "") { + val = val + "-"; + } + return val + this.control_name; + } + return this.control_name; + }; + WSF_CONTROL.prototype.wrap = function(cname, state) { var ctrs; ctrs = {}; @@ -339,9 +375,20 @@ WSF_CONTROL = (function() { }; WSF_CONTROL.prototype.trigger_callback = function(control_name, event, event_parameter) { + return this.run_trigger_callback(this.get_full_control_name(), event, event_parameter); + }; + + WSF_CONTROL.prototype.get_page = function() { + if (this.parent_control != null) { + return this.parent_control.get_page(); + } + return this; + }; + + WSF_CONTROL.prototype.run_trigger_callback = function(control_name, event, event_parameter) { var self; if ((this.parent_control != null) && !this.isolation) { - return this.parent_control.trigger_callback(control_name, event, event_parameter); + return this.parent_control.run_trigger_callback(control_name, event, event_parameter); } self = this; return $.ajax({ @@ -356,10 +403,7 @@ WSF_CONTROL = (function() { contentType: 'application/json', cache: false }).done(function(new_states) { - if (new_states.actions != null) { - self.process_actions(new_states.actions); - } - return self.process_update(new_states); + return self.get_page().process_update(new_states); }); }; @@ -416,6 +460,21 @@ WSF_PAGE_CONTROL = (function(_super) { this.load_subcontrols(); } + WSF_PAGE_CONTROL.prototype.process_update = function(new_states) { + var control, _i, _len, _ref; + _ref = this.controls; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + control = _ref[_i]; + if (control != null) { + control.process_update(new_states); + } + } + }; + + WSF_PAGE_CONTROL.prototype.get_full_control_name = function() { + return ""; + }; + WSF_PAGE_CONTROL.prototype.wrap = function(cname, state) { return state; }; @@ -437,7 +496,16 @@ WSF_SLIDER_CONTROL = (function(_super) { return WSF_SLIDER_CONTROL.__super__.constructor.apply(this, arguments); } - WSF_SLIDER_CONTROL.prototype.requirements = ['assets/bootstrap.min.js']; + WSF_SLIDER_CONTROL.prototype.requirements = ['/assets/bootstrap.min.js']; + + WSF_SLIDER_CONTROL.prototype.attach_events = function() { + var id; + WSF_SLIDER_CONTROL.__super__.attach_events.apply(this, arguments); + id = "slider" + Math.round(Math.random() * 10000); + this.$el.attr("id", id); + this.$el.find("ol li").attr("data-target", "#" + id); + return this.$el.find(".carousel-control").attr("href", "#" + id); + }; return WSF_SLIDER_CONTROL; @@ -451,7 +519,7 @@ WSF_DROPDOWN_CONTROL = (function(_super) { return WSF_DROPDOWN_CONTROL.__super__.constructor.apply(this, arguments); } - WSF_DROPDOWN_CONTROL.prototype.requirements = ['assets/bootstrap.min.js']; + WSF_DROPDOWN_CONTROL.prototype.requirements = ['/assets/bootstrap.min.js']; return WSF_DROPDOWN_CONTROL; @@ -534,6 +602,136 @@ WSF_INPUT_CONTROL = (function(_super) { })(WSF_CONTROL); +WSF_FILE_CONTROL = (function(_super) { + + __extends(WSF_FILE_CONTROL, _super); + + function WSF_FILE_CONTROL() { + WSF_FILE_CONTROL.__super__.constructor.apply(this, arguments); + this.uploading = false; + } + + WSF_FILE_CONTROL.prototype.start_upload = function() { + var action, file, formData; + if (this.uploading) { + return; + } + this.uploading = true; + this.$el.hide(); + this.progressbar = $("
"); + this.$el.parent().append(this.progressbar); + formData = new FormData(); + action = this.callback_url({ + control_name: this.get_full_control_name(), + event: "uploadfile", + event_parameter: "" + }); + file = this.$el[0].files[0]; + formData.append('file', file); + formData.append('state', JSON.stringify(this.get_context_state())); + return this.sendXHRequest(formData, action); + }; + + WSF_FILE_CONTROL.prototype.sendXHRequest = function(formData, uri) { + var onprogressHandler, onstatechange, self, xhr; + xhr = new XMLHttpRequest(); + self = this; + onprogressHandler = function(evt) { + var percent; + percent = evt.loaded / evt.total * 100; + return self.progressbar.find('.progress-bar').css({ + 'width': percent + "%" + }); + }; + onstatechange = function(evt) { + if (xhr.readyState === 4 && xhr.status === 200) { + return self.get_page().process_update(JSON.parse(xhr.responseText)); + } + }; + xhr.upload.addEventListener('progress', onprogressHandler, false); + xhr.addEventListener('readystatechange', onstatechange, false); + xhr.open('POST', uri, true); + return xhr.send(formData); + }; + + WSF_FILE_CONTROL.prototype.attach_events = function() { + var self; + WSF_FILE_CONTROL.__super__.attach_events.apply(this, arguments); + self = this; + return this.$el.change(function() { + return self.change(); + }); + }; + + WSF_FILE_CONTROL.prototype.change = function() { + var file; + this.state['file'] = null; + this.state['type'] = null; + this.state['size'] = null; + if (this.$el[0].files.length > 0) { + file = this.$el[0].files[0]; + this.state['file'] = file.name; + this.state['type'] = file.type; + this.state['size'] = file.size; + } + if (this.state['callback_change']) { + this.trigger_callback(this.control_name, 'change'); + } + return this.trigger('change'); + }; + + WSF_FILE_CONTROL.prototype.value = function() { + return this.$el.val(); + }; + + WSF_FILE_CONTROL.prototype.update = function(state) { + if (state.upload_file != null) { + this.progressbar.hide(); + this.$el.parent().append($("

").addClass("form-control-static").text(this.state['file'])); + return this.state['upload_file'] = state.upload_file; + } + }; + + return WSF_FILE_CONTROL; + +})(WSF_CONTROL); + +WSF_PASSWORD_CONTROL = (function(_super) { + + __extends(WSF_PASSWORD_CONTROL, _super); + + function WSF_PASSWORD_CONTROL() { + return WSF_PASSWORD_CONTROL.__super__.constructor.apply(this, arguments); + } + + return WSF_PASSWORD_CONTROL; + +})(WSF_INPUT_CONTROL); + +WSF_NAVLIST_ITEM_CONTROL = (function(_super) { + + __extends(WSF_NAVLIST_ITEM_CONTROL, _super); + + function WSF_NAVLIST_ITEM_CONTROL() { + return WSF_NAVLIST_ITEM_CONTROL.__super__.constructor.apply(this, arguments); + } + + WSF_NAVLIST_ITEM_CONTROL.prototype.update = function(state) { + WSF_NAVLIST_ITEM_CONTROL.__super__.update.apply(this, arguments); + if (state.active != null) { + this.state['active'] = state.active; + if (state.active) { + return this.$el.addClass("active"); + } else { + return this.$el.removeClass("active"); + } + } + }; + + return WSF_NAVLIST_ITEM_CONTROL; + +})(WSF_BUTTON_CONTROL); + WSF_TEXTAREA_CONTROL = (function(_super) { __extends(WSF_TEXTAREA_CONTROL, _super); @@ -552,7 +750,7 @@ WSF_CODEVIEW_CONTROL = (function(_super) { function WSF_CODEVIEW_CONTROL() { WSF_CODEVIEW_CONTROL.__super__.constructor.apply(this, arguments); - this.initialize = lazy_load(['assets/codemirror/codemirror.js', 'assets/codemirror/codemirror.css', 'assets/codemirror/estudio.css'], lazy_load(['assets/codemirror/eiffel.js'], this.attach_events, this), this); + this.initialize = lazy_load(['/assets/codemirror/codemirror.js', '/assets/codemirror/codemirror.css', '/assets/codemirror/estudio.css'], lazy_load(['/assets/codemirror/eiffel.js'], this.attach_events, this), this); } WSF_CODEVIEW_CONTROL.prototype.attach_events = function() { @@ -590,8 +788,9 @@ WSF_AUTOCOMPLETE_CONTROL = (function(_super) { var self; WSF_AUTOCOMPLETE_CONTROL.__super__.attach_events.apply(this, arguments); self = this; + console.log(this.$el); this.$el.typeahead({ - name: this.control_name, + name: this.control_name + Math.random(), template: this.state['template'], engine: Mini, remote: { @@ -605,7 +804,7 @@ WSF_AUTOCOMPLETE_CONTROL = (function(_super) { }); }, filter: function(parsedResponse) { - return parsedResponse[self.control_name]['suggestions']; + return parseSuggestions(parsedResponse); }, fn: function() { return self.trigger_callback(self.control_name, 'autocomplete'); @@ -718,7 +917,7 @@ WSF_FORM_ELEMENT_CONTROL = (function(_super) { if (message.length > 0) { this.$el.addClass("has-error"); errordiv = $("
").addClass('help-block').addClass('validation').text(message); - return this.$el.find(".col-lg-10").append(errordiv); + return this.$el.children("div").append(errordiv); } }; @@ -930,11 +1129,15 @@ WSF_REPEATER_CONTROL = (function(_super) { })(WSF_CONTROL); +redirect = function(action) { + return document.location.href = action.url; +}; + show_alert = function(action) { return alert(action.message); }; -start_modal = lazy_load(['assets/bootstrap.min.js'], function(action) { +start_modal = lazy_load(['/assets/bootstrap.min.js'], function(action) { var cssclass, modal; cssclass = ""; if (action.type === "start_modal_big") { diff --git a/examples/widgetapp/base_page.e b/examples/widgetapp/base_page.e index 9dd713d4..7e05d5d1 100644 --- a/examples/widgetapp/base_page.e +++ b/examples/widgetapp/base_page.e @@ -21,20 +21,20 @@ feature btn: WSF_BUTTON_CONTROL dropdown:WSF_DROPDOWN_CONTROL do - create control.make ("container") + create control.make control.add_class ("container") - create dropdown.make_with_tag_name ("mydropdown", "Dropdown", "li") + create dropdown.make_with_tag_name ( "Dropdown", "li") dropdown.add_link_item ("Example link 1", "#") dropdown.add_divider dropdown.add_link_item ("Example link 2", "#") - create navbar.make_with_brand ("navbar1", "Example") + create navbar.make_with_brand ("Example") navbar.add_list_element (create {WSF_BASIC_CONTROL}.make_with_body ("a", "href=%"/%"", "Home")) navbar.add_list_element (create {WSF_BASIC_CONTROL}.make_with_body ("a", "href=%"/grid%"", "Grid")) navbar.add_list_element (create {WSF_BASIC_CONTROL}.make_with_body ("a", "href=%"/repeater%"", "Repeater")) navbar.add_list_element (create {WSF_BASIC_CONTROL}.make_with_body ("a", "href=%"/slider%"", "Slider")) navbar.add_element (dropdown) navbar.add_list_element_right (create {WSF_BASIC_CONTROL}.make_with_body ("a", "href=%"/about%"", "About")) - create btn.make ("scode", "Show Code") + create btn.make ("Show Code") btn.set_click_event (agent show_code) btn.set_isolation (true) btn.add_class ("btn-success") @@ -46,7 +46,7 @@ feature show_code do - start_modal_big ("/codeview?file=" + generator.as_lower, "Eiffel code " + generator) + start_modal ("/codeview?file=" + generator.as_lower, "Eiffel code " + generator, true) end feature diff --git a/examples/widgetapp/codeview_page.e b/examples/widgetapp/codeview_page.e index 75e4e554..dd6ea7d7 100644 --- a/examples/widgetapp/codeview_page.e +++ b/examples/widgetapp/codeview_page.e @@ -20,7 +20,7 @@ feature initialize_controls do - create control.make_codeview ("textarea", "") + create control.make_codeview ("") end process diff --git a/examples/widgetapp/grid_page.e b/examples/widgetapp/grid_page.e index f68bf164..124f31ff 100644 --- a/examples/widgetapp/grid_page.e +++ b/examples/widgetapp/grid_page.e @@ -24,12 +24,12 @@ feature Precursor control.add_control (create {WSF_BASIC_CONTROL}.make_with_body ("h1", "", "Grid Demo")) create datasource.make_news - create search_query.make ("query", create {GOOGLE_AUTOCOMPLETION}.make) + create search_query.make (create {GOOGLE_AUTOCOMPLETION}.make) search_query.add_class ("form-control") search_query.set_change_event (agent change_query) control.add_control (search_query) control.add_control (create {WSF_BASIC_CONTROL}.make_with_body ("h2", "", "Results")) - create grid.make ("mygrid", <>, datasource) + create grid.make (<>, datasource) control.add_control (grid) navbar.set_active (2) end diff --git a/examples/widgetapp/image_slider_page.e b/examples/widgetapp/image_slider_page.e index caf93308..d2411873 100644 --- a/examples/widgetapp/image_slider_page.e +++ b/examples/widgetapp/image_slider_page.e @@ -24,9 +24,9 @@ feature -- Implementation form: WSF_FORM_CONTROL do Precursor - create slider.make ("myslider") - create form.make ("sliderform") - form.add_control (create {WSF_FORM_ELEMENT_CONTROL [STRING]}.make ("Input", create {WSF_INPUT_CONTROL}.make ("sliderformtext", "Test"))) + create slider.make + create form.make + form.add_control (create {WSF_FORM_ELEMENT_CONTROL [STRING]}.make ("Input", create {WSF_INPUT_CONTROL}.make ("Test"))) --slider.add_control (form, Void) --slider.add_image ("http://www.placesmustseen.com/wp-content/uploads/2013/01/paris-eiffel-tower.jpg", "Eiffel Tower") slider.add_image ("http://31.media.tumblr.com/43f3edae3fb569943047077cddf93c79/tumblr_mtw7wdX9cm1st5lhmo1_1280.jpg", "car") diff --git a/examples/widgetapp/repeater_page.e b/examples/widgetapp/repeater_page.e index c56ee8d0..3af98551 100644 --- a/examples/widgetapp/repeater_page.e +++ b/examples/widgetapp/repeater_page.e @@ -24,12 +24,12 @@ feature Precursor control.add_control (create {WSF_BASIC_CONTROL}.make_with_body ("h1", "", " Repeater Demo")) create datasource.make_news - create search_query.make ("query", create {GOOGLE_AUTOCOMPLETION}.make) + create search_query.make (create {GOOGLE_AUTOCOMPLETION}.make) search_query.add_class ("form-control") search_query.set_change_event (agent change_query) control.add_control (search_query) control.add_control (create {WSF_BASIC_CONTROL}.make_with_body ("h2", "", "Results")) - create repeater.make ("myrepeater", datasource) + create repeater.make (datasource) control.add_control (repeater) navbar.set_active (3) end diff --git a/examples/widgetapp/sample_page.e b/examples/widgetapp/sample_page.e index 9e2a9260..2a1d4c49 100644 --- a/examples/widgetapp/sample_page.e +++ b/examples/widgetapp/sample_page.e @@ -26,74 +26,102 @@ feature n3_container: WSF_FORM_ELEMENT_CONTROL [STRING] n4_container: WSF_FORM_ELEMENT_CONTROL [STRING] n5_container: WSF_FORM_ELEMENT_CONTROL [STRING] + n6_container: WSF_FORM_ELEMENT_CONTROL [detachable WSF_PENDING_FILE] + n7_container: WSF_FORM_ELEMENT_CONTROL [detachable WSF_PENDING_FILE] cats_container: WSF_FORM_ELEMENT_CONTROL [LIST [STRING]] source: INCREASING_PROGRESSSOURCE do Precursor - create form.make ("panel") + create form.make form.add_class ("form-horizontal") --Number 1 - create textbox1.make ("txtBox1", "1") + create textbox1.make ("1") create n1_container.make ("Number1", textbox1) - n1_container.add_validator (create {WSF_DECIMAL_VALIDATOR}.make_decimal_validator ("Invalid Number")) + n1_container.add_validator (create {WSF_DECIMAL_VALIDATOR}.make ("Invalid Number")) n1_container.add_validator (create {OWN_VALIDATOR}.make_own) form.add_control (n1_container) --Number 2 - create textbox2.make ("txtBox2", "2") + create textbox2.make ("2") create n2_container.make ("Number2", textbox2) - n2_container.add_validator (create {WSF_DECIMAL_VALIDATOR}.make_decimal_validator ("Invalid Number")) + n2_container.add_validator (create {WSF_DECIMAL_VALIDATOR}.make ("Invalid Number")) form.add_control (n2_container) --Flag autocomplete - create autocompletion1.make ("autocompletion1", create {FLAG_AUTOCOMPLETION}.make) + create autocompletion1.make (create {FLAG_AUTOCOMPLETION}.make) create n3_container.make ("Flag Autocomplete", autocompletion1) form.add_control (n3_container) --Contact autocomplete - create autocompletion2.make ("autocompletion2", create {CONTACT_AUTOCOMPLETION}.make) + create autocompletion2.make (create {CONTACT_AUTOCOMPLETION}.make) create n4_container.make ("Contact Autocomplete", autocompletion2) form.add_control (n4_container) --Google autocomplete - create autocompletion3.make ("autocompletion4", create {GOOGLE_AUTOCOMPLETION}.make) + create autocompletion3.make (create {GOOGLE_AUTOCOMPLETION}.make) create n5_container.make ("Google Autocomplete", autocompletion3) form.add_control (n5_container) --Categories - create cklist.make ("categories") - cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make ("net", "Network", "net")) - cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make ("os", "Operating Systems", "os")) - cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make ("fmfp", "Formal Methods and Functional Programming", "fmfp")) + create cklist.make + cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make ("Network", "net")) + cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make ("Operating Systems", "os")) + cklist.add_control (create {WSF_CHECKBOX_CONTROL}.make ("Formal Methods and Functional Programming", "fmfp")) create cats_container.make ("Categories", cklist) - cats_container.add_validator (create {WSF_MIN_VALIDATOR [STRING]}.make_min_validator (1, "Choose at least one category")) - cats_container.add_validator (create {WSF_MAX_VALIDATOR [STRING]}.make_max_validator (2, "Choose at most two category")) + cats_container.add_validator (create {WSF_MIN_VALIDATOR [LIST [STRING]]}.make (1, "Choose at least one category")) + cats_container.add_validator (create {WSF_MAX_VALIDATOR [LIST [STRING]]}.make (2, "Choose at most two category")) form.add_control (cats_container) + --File + create filebox.make + filebox.set_upload_function (agent upload_file) + create n6_container.make ("File Upload", filebox) + n6_container.add_validator (create {WSF_FILESIZE_VALIDATOR}.make (10000000, "File must be smaller than 10MB")) + form.add_control (n6_container) + --File + create filebox2.make + filebox2.set_upload_function (agent upload_file) + filebox2.set_change_event (agent do + filebox2.start_upload + end) + create n7_container.make ("Auto Upload", filebox2) + n7_container.add_validator (create {WSF_FILESIZE_VALIDATOR}.make (10000000, "File must be smaller than 10MB")) + form.add_control (n7_container) --Button 1 - create button1.make ("sample_button1", "Update") + create button1.make ("Update") button1.set_click_event (agent handle_click) button1.add_class ("col-lg-offset-2") form.add_control (button1) --Button 2 - create button2.make ("sample_button2", "Start Modal Grid") - button2.set_click_event (agent handle_click) + create button2.make ("Start Modal Grid") + button2.set_click_event (agent run_modal) form.add_control (button2) --Result - create result_html.make ("txtBox3", "p", "") + create result_html.make ("p", "") form.add_control (create {WSF_FORM_ELEMENT_CONTROL [STRING]}.make ("Result", result_html)) control.add_control (form) --Progress bar control.add_control (create {WSF_BASIC_CONTROL}.make_with_body ("h4", "", "Autoincrementing progressbar")) create source.make - create progress.make_with_source ("progress1", source) + create progress.make_with_source (source) source.set_control (progress) progress.set_isolation (true) control.add_control (progress) navbar.set_active (1) end + upload_file (f: ITERABLE [WSF_UPLOADED_FILE]): detachable String + do + -- Store file on server and return link + across + f as i + loop + Result:=i.item.filename + end + end + handle_click local text: STRING do form.validate if form.is_valid then + filebox.start_upload --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 ("
    ") @@ -109,6 +137,11 @@ feature end end + run_modal + do + start_modal ("/", "Test Modal", true); + end + process do end @@ -117,6 +150,10 @@ feature button2: WSF_BUTTON_CONTROL + filebox: WSF_FILE_CONTROL + + filebox2: WSF_FILE_CONTROL + textbox1: WSF_INPUT_CONTROL textbox2: WSF_INPUT_CONTROL