diff --git a/draft/library/wsf_js_widget/kernel/input/wsf_file.e b/draft/library/wsf_js_widget/kernel/input/wsf_file.e new file mode 100644 index 00000000..9f6fd77b --- /dev/null +++ b/draft/library/wsf_js_widget/kernel/input/wsf_file.e @@ -0,0 +1,49 @@ +note + description: "Summary description for {WSF_FILE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_FILE + +create + make + +feature {NONE} + + make (a_name, a_type: STRING; a_size: INTEGER; a_id: detachable STRING) + do + name := a_name + type := a_type + size := a_size + id := a_id + end + +feature + + set_id (a_id: detachable STRING) + do + id := a_id + end + +feature --Properties + + is_uploaded: BOOLEAN + do + Result := attached id + end + + name: STRING + -- File name + + type: STRING + -- File mime type + + size: INTEGER + -- File size + + id: detachable STRING + -- Server side file id (e.g. S3 filename) + +end 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 index 8b2f57a5..4de584b4 100644 --- a/draft/library/wsf_js_widget/kernel/input/wsf_file_control.e +++ b/draft/library/wsf_js_widget/kernel/input/wsf_file_control.e @@ -9,7 +9,7 @@ class inherit - WSF_VALUE_CONTROL [detachable WSF_PENDING_FILE] + WSF_VALUE_CONTROL [detachable WSF_FILE] rename make as make_value_control end @@ -28,12 +28,14 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management set_state (new_state: JSON_OBJECT) -- Restore text from json + local + id: detachable STRING 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; + if attached {JSON_STRING} new_state.item ("file_name") as new_name and attached {JSON_STRING} new_state.item ("file_type") as new_type and attached {JSON_NUMBER} new_state.item ("file_size") as new_size then + if attached {JSON_STRING} new_state.item ("file_id") as a_id then + id := a_id.unescaped_string_32 + end + create file.make (new_name.unescaped_string_32, new_type.unescaped_string_32, new_size.item.to_integer_32, id); end end @@ -42,41 +44,44 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management 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") + Result.put_boolean (attached upload_done_event, "callback_uploaddone") + if attached file as f then + Result.put_string (f.name, "file_name") + Result.put_string (f.type, "file_type") + Result.put_integer (f.size, "file_size") + Result.put_string (f.id, "file_id") end + Result.put_boolean (disabled, "disabled") 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) + local + f_name: detachable STRING + f_type: detachable STRING + f_size: detachable INTEGER + f_id: detachable STRING do if Current.control_name.same_string (cname [1]) then - if attached change_event as cevent and event.same_string ("change") 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])) + elseif attached upload_done_event as udevent and event.same_string ("uploaddone") then + udevent.call (Void) + elseif event.same_string ("uploadfile") and attached {ITERABLE [WSF_UPLOADED_FILE]} event_parameter as files then + if attached file as f then + if attached upload_function as ufunction then + f.set_id (ufunction.item ([files])) + end + f_name := f.name + f_type := f.type + f_size := f.size + f_id := f.id + end + state_changes.replace_with_string (f_name, "file_name") + state_changes.replace_with_string (f_type, "file_type") + state_changes.replace_with_integer (f_size, "file_size") + state_changes.replace_with_string (f_id, "file_id") end end end @@ -94,28 +99,68 @@ feature -- Upload feature -- Implementation - value: detachable WSF_PENDING_FILE + value: detachable WSF_FILE do Result := file end render: STRING + local + attr: STRING do - Result := render_tag ("", "type=%"file%" ") + attr := "type=%"file%" " + if attached attributes as a then + attr.append (a) + end + if disabled then + attr.append ("disabled=%"disabled%" ") + end + Result := render_tag ("", attr) + end + +feature -- Change + + set_change_event (e: attached like change_event) + -- Set text change event handle + do + change_event := e + end + + set_upload_done_event (e: attached like upload_done_event) + -- Set text change event handle + do + upload_done_event := e + end + + set_upload_function (e: attached like upload_function) + -- Set button click event handle + do + upload_function := e + end + + set_disabled (b: BOOLEAN) + do + if disabled /= b then + disabled := b + state_changes.replace_with_boolean (disabled, "disabled") + end end feature -- Properties - file: detachable WSF_PENDING_FILE + disabled: BOOLEAN + -- Defines if the a file is selectable and if a file can be removed once it is uploaded + + file: detachable WSF_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_done_event: detachable PROCEDURE [ANY, TUPLE] + -- Procedure to be execued when upload was successful - upload_file: detachable STRING - -- Link to uploaded file + upload_function: detachable FUNCTION [ANY, TUPLE [ITERABLE [WSF_UPLOADED_FILE]], detachable STRING] + -- Store uploaded file and return server side file id 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 d243bd7d..546aaa42 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 @@ -22,7 +22,7 @@ feature {NONE} -- Initialization make (v: STRING) -- Initialize with specified name and value do - make_value_control ( "input") + make_value_control ("input") type := "text" text := v end @@ -42,6 +42,7 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management do create Result.make Result.put_string (text, "text") + Result.put_boolean (disabled, "disabled") Result.put_boolean (attached change_event, "callback_change") end @@ -53,9 +54,9 @@ feature --Event handling change_event := e end - 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 + 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 @@ -65,8 +66,17 @@ feature --Event handling feature -- Rendering render: STRING + local + attr: STRING do - Result := render_tag ("", "type=%"" + type + "%" value=%"" + text + "%"") + attr := "type=%"" + type + "%" value=%"" + text + "%" " + if attached attributes as a then + attr.append (a) + end + if disabled then + attr.append ("disabled=%"disabled%" ") + end + Result := render_tag ("", attr) end feature -- Change @@ -80,6 +90,14 @@ feature -- Change end end + set_disabled (b: BOOLEAN) + do + if disabled /= b then + disabled := b + state_changes.replace_with_boolean (disabled, "disabled") + end + end + feature -- Implementation value: STRING @@ -89,6 +107,9 @@ feature -- Implementation feature -- Properties + disabled: BOOLEAN + -- Defines if the input field is editable + text: STRING -- Text to be displayed 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 deleted file mode 100644 index 759d39f3..00000000 --- a/draft/library/wsf_js_widget/kernel/input/wsf_pending_file.e +++ /dev/null @@ -1,30 +0,0 @@ -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/validator/wsf_filesize_validator.e b/draft/library/wsf_js_widget/kernel/validator/wsf_filesize_validator.e index 517decdf..c0158b41 100644 --- a/draft/library/wsf_js_widget/kernel/validator/wsf_filesize_validator.e +++ b/draft/library/wsf_js_widget/kernel/validator/wsf_filesize_validator.e @@ -9,7 +9,7 @@ class inherit - WSF_VALIDATOR [detachable WSF_PENDING_FILE] + WSF_VALIDATOR [detachable WSF_FILE] rename make as make_validator redefine @@ -30,7 +30,7 @@ feature {NONE} -- Initialization feature -- Implementation - is_valid (input: detachable WSF_PENDING_FILE): BOOLEAN + is_valid (input: detachable WSF_FILE): BOOLEAN do Result := True if attached input as a_input then 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 3b49767e..5692d9ad 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 @@ -43,6 +43,7 @@ feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management do create Result.make Result.put_string (text, "text") + Result.put_boolean (disabled, "disabled") Result.put_boolean (attached click_event, "callback_click") end @@ -54,9 +55,9 @@ feature --Event handling click_event := e end - handle_callback (cname: LIST[STRING]; event: STRING; event_parameter: detachable ANY) + handle_callback (cname: LIST [STRING]; event: STRING; event_parameter: detachable ANY) do - if Current.control_name.same_string (cname[1]) 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 @@ -65,8 +66,17 @@ feature -- Rendering render: STRING -- HTML representation of this control + local + attr: STRING do - Result := render_tag (text, attributes) + create attr.make_empty + if attached attributes as a then + attr.append (a) + end + if disabled then + attr.append ("disabled=%"disabled%" ") + end + Result := render_tag (text, attr) end feature -- Change @@ -76,12 +86,23 @@ feature -- Change do if not t.same_string (text) then text := t - state_changes.replace (create {JSON_STRING}.make_json (text), "text") + state_changes.replace_with_string (text, "text") + end + end + + set_disabled (b: BOOLEAN) + do + if disabled /= b then + disabled := b + state_changes.replace_with_boolean (disabled, "disabled") end end feature -- Properties + disabled: BOOLEAN + -- Defines if the button is editable + text: STRING -- The text currently displayed on this button 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 81fc8796..8bc55a65 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 @@ -34,6 +34,7 @@ feature {NONE} -- Initialization make_multi_control tag_name := "form" label_width := w + add_class ("form-horizontal") end feature 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 1c759e94..1494a207 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 @@ -36,12 +36,13 @@ feature {NONE} -- Initialization do make_control ("div") add_class ("form-group") - if attached {WSF_HTML_CONTROL} c then - c.add_class ("form-control-static") - elseif not attached {WSF_VALUE_CONTROL [LIST[ANY]]} c then + if not attached {WSF_VALUE_CONTROL [LIST[ANY]]} c then c.add_class ("form-control") + else + c.add_class ("form-control-static") end + label_width := 2 value_control := c validators := v diff --git a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_json_object.e b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_json_object.e index a42e114e..c125181c 100644 --- a/draft/library/wsf_js_widget/kernel/webcontrol/wsf_json_object.e +++ b/draft/library/wsf_js_widget/kernel/webcontrol/wsf_json_object.e @@ -16,114 +16,133 @@ create feature - put_string (value: READABLE_STRING_GENERAL; key: JSON_STRING) + put_string (value: detachable READABLE_STRING_GENERAL; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. require key_not_present: not has_key (key) local - l_value: JSON_STRING + l_value: detachable JSON_STRING do - create l_value.make_json_from_string_32 (value.as_string_32) + if attached value as a_value then + create l_value.make_json_from_string_32 (a_value.as_string_32) + end put (l_value, key) end - put_integer (value: INTEGER_64; key: JSON_STRING) + put_integer (value: detachable INTEGER_64; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. require key_not_present: not has_key (key) local - l_value: JSON_NUMBER + l_value: detachable JSON_NUMBER do - create l_value.make_integer (value) + if attached value as a_value then + create l_value.make_integer (a_value) + end put (l_value, key) end - put_natural (value: NATURAL_64; key: JSON_STRING) + put_natural (value: detachable NATURAL_64; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. require key_not_present: not has_key (key) local - l_value: JSON_NUMBER + l_value: detachable JSON_NUMBER do - create l_value.make_natural (value) + if attached value as a_value then + create l_value.make_natural (a_value) + end put (l_value, key) end - put_real (value: DOUBLE; key: JSON_STRING) + put_real (value: detachable DOUBLE; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. require key_not_present: not has_key (key) local - l_value: JSON_NUMBER + l_value: detachable JSON_NUMBER do - create l_value.make_real (value) + if attached value as a_value then + create l_value.make_real (a_value) + end put (l_value, key) end - put_boolean (value: BOOLEAN; key: JSON_STRING) + put_boolean (value: detachable BOOLEAN; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. require key_not_present: not has_key (key) local - l_value: JSON_BOOLEAN + l_value: detachable JSON_BOOLEAN do - create l_value.make_boolean (value) + if attached value as a_value then + create l_value.make_boolean (a_value) + end put (l_value, key) end - replace_with_string (value: READABLE_STRING_GENERAL; key: JSON_STRING) + replace_with_string (value: detachable READABLE_STRING_GENERAL; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. local - l_value: JSON_STRING + l_value: detachable JSON_STRING do - create l_value.make_json_from_string_32 (value.as_string_32) + if attached value as a_value then + create l_value.make_json_from_string_32 (value.as_string_32) + end replace (l_value, key) end - replace_with_integer (value: INTEGER_64; key: JSON_STRING) + replace_with_integer (value: detachable INTEGER_64; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. local - l_value: JSON_NUMBER + l_value: detachable JSON_NUMBER do - create l_value.make_integer (value) + if attached value as a_value then + create l_value.make_integer (a_value) + end replace (l_value, key) end - replace_with_with_natural (value: NATURAL_64; key: JSON_STRING) + replace_with_with_natural (value: detachable NATURAL_64; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. local - l_value: JSON_NUMBER + l_value: detachable JSON_NUMBER do - create l_value.make_natural (value) + if attached value as a_value then + create l_value.make_natural (a_value) + end replace (l_value, key) end - replace_with_real (value: DOUBLE; key: JSON_STRING) + replace_with_real (value: detachable DOUBLE; key: JSON_STRING) -- Assuming there is no item of key `key', - -- insert `value' with `key'. + -- insert `value' with `key' local - l_value: JSON_NUMBER + l_value: detachable JSON_NUMBER do - create l_value.make_real (value) + if attached value as a_value then + create l_value.make_real (a_value) + end replace (l_value, key) end - - replace_with_boolean (value: BOOLEAN; key: JSON_STRING) + replace_with_boolean (value: detachable BOOLEAN; key: JSON_STRING) -- Assuming there is no item of key `key', -- insert `value' with `key'. local - l_value: JSON_BOOLEAN + l_value: detachable JSON_BOOLEAN do - create l_value.make_boolean (value) + if attached value as a_value then + create l_value.make_boolean (a_value) + end replace (l_value, key) end diff --git a/examples/widgetapp/application.e b/examples/widgetapp/application.e index 8e250c49..d1dbc466 100644 --- a/examples/widgetapp/application.e +++ b/examples/widgetapp/application.e @@ -81,6 +81,7 @@ feature -- Router and Filter map_agent_uri ("/grid", agent grid_demo, Void) map_agent_uri ("/repeater", agent repeater_demo, Void) map_agent_uri ("/slider", agent slider_demo, Void) + map_agent_uri ("/upload", agent upload_demo, Void) map_agent_uri ("/codeview", agent codeview, Void) -- NOTE: you could put all those files in a specific folder, and use WSF_FILE_SYSTEM_HANDLER with "/" @@ -137,6 +138,16 @@ feature -- Execution page.execute end + upload_demo (request: WSF_REQUEST; response: WSF_RESPONSE) + local + page: UPLOAD_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (request, response) + page.execute + end + codeview (request: WSF_REQUEST; response: WSF_RESPONSE) local page: CODEVIEW_PAGE diff --git a/examples/widgetapp/assets/widget.coffee b/examples/widgetapp/assets/widget.coffee index 0e7f7cc0..40d18030 100644 --- a/examples/widgetapp/assets/widget.coffee +++ b/examples/widgetapp/assets/widget.coffee @@ -166,6 +166,7 @@ class WSF_CONTROL @controls=(build_control(control_name, state, @) for control_name, state of @fullstate.controls) else @controls = [] + return attach_events: ()-> console.log "Attached #{@control_name}" @@ -190,6 +191,7 @@ class WSF_CONTROL fn(action) catch e console.log "Failed preforming action #{action.type}" + return process_update: (new_states)-> try @@ -204,8 +206,6 @@ class WSF_CONTROL return return - - get_context_state : ()-> if @parent_control? and not @isolation return @parent_control.get_context_state() @@ -340,6 +340,9 @@ class WSF_BUTTON_CONTROL extends WSF_CONTROL @trigger_callback(@control_name, 'click') update: (state) -> + if state.disabled != undefined + @state['disabled'] = state.disabled + @$el.prop('disabled', state.disabled) if state.text? @state['text'] = state.text @$el.text(state.text) @@ -362,6 +365,9 @@ class WSF_INPUT_CONTROL extends WSF_CONTROL return @$el.val() update: (state) -> + if state.disabled != undefined + @state['disabled'] = state.disabled + @$el.prop('disabled', state.disabled) if state.text? @state['text'] = state.text @$el.val(state.text) @@ -372,6 +378,8 @@ class WSF_FILE_CONTROL extends WSF_CONTROL @uploading = false start_upload: ()-> + if @$el[0].files.length==0 + return if @uploading return @uploading = true @@ -415,14 +423,15 @@ class WSF_FILE_CONTROL extends WSF_CONTROL change: ()-> #update local state - @state['file'] = null - @state['type'] = null - @state['size'] = null + @state['file_name'] = null + @state['file_type'] = null + @state['file_size'] = null + @state['file_id'] = null if @$el[0].files.length>0 file = @$el[0].files[0] - @state['file'] = file.name - @state['type'] = file.type - @state['size'] = file.size + @state['file_name'] = file.name + @state['file_type'] = file.type + @state['file_size'] = file.size if @state['callback_change'] @trigger_callback(@control_name, 'change') @trigger('change') @@ -431,10 +440,49 @@ class WSF_FILE_CONTROL extends WSF_CONTROL 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 + if state.disabled != undefined + @state['disabled'] = state.disabled + @$el.prop('disabled', state.disabled) + @refresh() + if state.file_name != undefined + @state['file_name'] = state.file_name + if state.file_type != undefined + @state['file_type'] = state.file_type + if state.file_size != undefined + @state['file_size'] = state.file_size + if state.file_id != undefined + if @state['file_id'] != state.file_id + @state['file_id'] = state.file_id + if @state['callback_uploaddone'] + @trigger_callback(@control_name, 'uploaddone') + @uploading = false + @refresh() + + refresh: ()-> + if @uploading + return + @progressbar.remove() + @$el.parent().find("p").remove() + if @state['file_id'] != null + @$el.hide() + fname = $("""""").addClass("form-control-static").text(@state['file_name']) + @$el.parent().append(fname) + if not @state['disabled'] + fname.append(" "); + removebtn = $("").text("Remove").addClass("btn btn-xs btn-danger") + self = @ + removebtn.click ()-> + self.progressbar.remove() + self.$el.parent().find("p").remove() + self.$el.show() + self.$el.val('') + self.change() + fname.append(removebtn) + else + @$el.show() + @$el.val('') + @change() + class WSF_PASSWORD_CONTROL extends WSF_INPUT_CONTROL diff --git a/examples/widgetapp/assets/widget.js b/examples/widgetapp/assets/widget.js index 2dac6b4d..9ee5396c 100644 --- a/examples/widgetapp/assets/widget.js +++ b/examples/widgetapp/assets/widget.js @@ -263,7 +263,7 @@ WSF_CONTROL = (function() { WSF_CONTROL.prototype.load_subcontrols = function() { var control_name, state; if (this.fullstate.controls != null) { - return this.controls = (function() { + this.controls = (function() { var _ref, _results; _ref = this.fullstate.controls; _results = []; @@ -274,7 +274,7 @@ WSF_CONTROL = (function() { return _results; }).call(this); } else { - return this.controls = []; + this.controls = []; } }; @@ -293,24 +293,22 @@ WSF_CONTROL = (function() { WSF_CONTROL.prototype.update = function(state) {}; WSF_CONTROL.prototype.process_actions = function(actions) { - var action, fn, _i, _len, _results; - _results = []; + var action, fn, _i, _len; for (_i = 0, _len = actions.length; _i < _len; _i++) { action = actions[_i]; try { fn = null; if (this[action.type] != null) { fn = this[action.type]; - _results.push(fn.call(this, action)); + fn.call(this, action); } else { fn = eval(action.type); - _results.push(fn(action)); + fn(action); } } catch (e) { - _results.push(console.log("Failed preforming action " + action.type)); + console.log("Failed preforming action " + action.type); } } - return _results; }; WSF_CONTROL.prototype.process_update = function(new_states) { @@ -552,6 +550,10 @@ WSF_BUTTON_CONTROL = (function(_super) { }; WSF_BUTTON_CONTROL.prototype.update = function(state) { + if (state.disabled !== void 0) { + this.state['disabled'] = state.disabled; + this.$el.prop('disabled', state.disabled); + } if (state.text != null) { this.state['text'] = state.text; return this.$el.text(state.text); @@ -592,6 +594,10 @@ WSF_INPUT_CONTROL = (function(_super) { }; WSF_INPUT_CONTROL.prototype.update = function(state) { + if (state.disabled !== void 0) { + this.state['disabled'] = state.disabled; + this.$el.prop('disabled', state.disabled); + } if (state.text != null) { this.state['text'] = state.text; return this.$el.val(state.text); @@ -613,6 +619,9 @@ WSF_FILE_CONTROL = (function(_super) { WSF_FILE_CONTROL.prototype.start_upload = function() { var action, file, formData; + if (this.$el[0].files.length === 0) { + return; + } if (this.uploading) { return; } @@ -665,14 +674,15 @@ WSF_FILE_CONTROL = (function(_super) { WSF_FILE_CONTROL.prototype.change = function() { var file; - this.state['file'] = null; - this.state['type'] = null; - this.state['size'] = null; + this.state['file_name'] = null; + this.state['file_type'] = null; + this.state['file_size'] = null; + this.state['file_id'] = 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; + this.state['file_name'] = file.name; + this.state['file_type'] = file.type; + this.state['file_size'] = file.size; } if (this.state['callback_change']) { this.trigger_callback(this.control_name, 'change'); @@ -685,10 +695,60 @@ WSF_FILE_CONTROL = (function(_super) { }; 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; + if (state.disabled !== void 0) { + this.state['disabled'] = state.disabled; + this.$el.prop('disabled', state.disabled); + this.refresh(); + } + if (state.file_name !== void 0) { + this.state['file_name'] = state.file_name; + } + if (state.file_type !== void 0) { + this.state['file_type'] = state.file_type; + } + if (state.file_size !== void 0) { + this.state['file_size'] = state.file_size; + } + if (state.file_id !== void 0) { + if (this.state['file_id'] !== state.file_id) { + this.state['file_id'] = state.file_id; + if (this.state['callback_uploaddone']) { + this.trigger_callback(this.control_name, 'uploaddone'); + } + this.uploading = false; + } + return this.refresh(); + } + }; + + WSF_FILE_CONTROL.prototype.refresh = function() { + var fname, removebtn, self; + if (this.uploading) { + return; + } + this.progressbar.remove(); + this.$el.parent().find("p").remove(); + if (this.state['file_id'] !== null) { + this.$el.hide(); + fname = $("").addClass("form-control-static").text(this.state['file_name']); + this.$el.parent().append(fname); + if (!this.state['disabled']) { + fname.append(" "); + removebtn = $("").text("Remove").addClass("btn btn-xs btn-danger"); + self = this; + removebtn.click(function() { + self.progressbar.remove(); + self.$el.parent().find("p").remove(); + self.$el.show(); + self.$el.val(''); + return self.change(); + }); + return fname.append(removebtn); + } + } else { + this.$el.show(); + this.$el.val(''); + return this.change(); } }; diff --git a/examples/widgetapp/base_page.e b/examples/widgetapp/base_page.e index 7e05d5d1..81d5b65e 100644 --- a/examples/widgetapp/base_page.e +++ b/examples/widgetapp/base_page.e @@ -32,6 +32,7 @@ feature 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_list_element (create {WSF_BASIC_CONTROL}.make_with_body ("a", "href=%"/upload%"", "File Upload")) navbar.add_element (dropdown) navbar.add_list_element_right (create {WSF_BASIC_CONTROL}.make_with_body ("a", "href=%"/about%"", "About")) create btn.make ("Show Code") diff --git a/examples/widgetapp/image_slider_page.e b/examples/widgetapp/image_slider_page.e index d2411873..e0b82880 100644 --- a/examples/widgetapp/image_slider_page.e +++ b/examples/widgetapp/image_slider_page.e @@ -20,13 +20,9 @@ create feature -- Implementation initialize_controls - local - form: WSF_FORM_CONTROL do Precursor 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/sample_page.e b/examples/widgetapp/sample_page.e index 2a1d4c49..89adfb68 100644 --- a/examples/widgetapp/sample_page.e +++ b/examples/widgetapp/sample_page.e @@ -26,14 +26,11 @@ 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 - form.add_class ("form-horizontal") + create form.make --Number 1 create textbox1.make ("1") create n1_container.make ("Number1", textbox1) @@ -66,21 +63,6 @@ feature 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 ("Update") button1.set_click_event (agent handle_click) @@ -105,23 +87,12 @@ feature 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 ("