Move wsf_js_widget library under draft/library/server/wsf_js_widget

This commit is contained in:
2014-07-07 10:26:10 +02:00
parent 3c8dc0a9e1
commit fe4c283336
106 changed files with 16 additions and 16 deletions

View File

@@ -0,0 +1,93 @@
note
description: "[
Represents a simple basic element with a user specified html tag.
This control is lightweight and can be used to create custom
stateless controls, e.g. headers.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_BASIC_CONTROL
inherit
WSF_STATELESS_CONTROL
rename
make as make_stateless_control
redefine
attributes
end
create
make, make_with_body, make_with_body_class
feature {NONE} -- Initialization
make (a_tag: STRING_32)
-- Initialize
require
tag_not_empty: not a_tag.is_empty
do
make_with_body_class (a_tag, "", "", "")
end
make_with_body (a_tag, a_attribs, a_body: STRING_32)
-- Initialize with tag `a_tag', specific attributes `a_attribs' and body `a_body'.
require
tag_not_empty: not a_tag.is_empty
do
make_stateless_control (a_tag)
attributes := a_attribs
body := a_body
end
make_with_body_class (a_tag, a_attribs, a_css_class, a_body: STRING_32)
-- Initialize with tag `a_tag' specific class `a_css_class', attributes `a_attribs' and body `a_body'.
require
tag_not_empty: not a_tag.is_empty
do
make_with_body (a_tag, a_attribs, a_body)
if not a_css_class.is_empty then
css_classes.extend (a_css_class)
end
end
feature -- Rendering
render: STRING_32
-- HTML representation of this control
do
Result := render_tag (body, attributes)
end
feature -- Change
set_body (b: STRING_32)
-- Set the body of this control
do
body := b
ensure
body_set: body = b
end
feature -- Access
attributes: STRING_32
-- Attributes of this control
body: STRING_32
-- Body of this control
;note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,141 @@
note
description: "[
Represents a button control (button html keyword). Provides a
callback agent which will be invoked when the button is clicked.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_BUTTON_CONTROL
inherit
WSF_CONTROL
rename
make as make_control
end
create
make
feature {NONE} -- Initialization
make (a_text: STRING_32)
-- Initialize with specified text
do
make_control ("button")
add_class ("btn")
add_class ("btn-default")
text := a_text
ensure
text_set: text = a_text
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 ("text") as new_text then
text := new_text.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_string (text, "text")
Result.put_boolean (disabled, "disabled")
Result.put_boolean (attached click_event, "callback_click")
end
feature --Event handling
set_click_event (e: attached like click_event)
-- Set button click event handle
do
click_event := e
ensure
click_event_set: click_event = e
end
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
-- Called if the button is clicked.
do
if
control_name.same_string_general (cname.first) and
attached click_event as cevent
then
cevent.call (Void)
end
end
feature -- Rendering
render: STRING_32
-- HTML representation of this control
local
attr: STRING_32
do
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
set_text (t: STRING_32)
-- Set text of that button
do
if not t.same_string (text) then
text := t
state_changes.replace_with_string (text, "text")
end
ensure
text_set: text.same_string (t)
end
set_disabled (b: BOOLEAN)
-- Enables or disables this component, depending on the value of the parameter b.
-- A disabled button cannot be clicked.
do
if disabled /= b then
disabled := b
state_changes.replace_with_boolean (disabled, "disabled")
else
check (b = False) implies state_changes.has_key ("disabled") end
end
ensure
disabled_set: disabled = b
end
feature -- Properties
disabled: BOOLEAN
-- Defines if the button is clickable or not
text: STRING_32
-- The text currently displayed on this button
click_event: detachable PROCEDURE [ANY, TUPLE]
-- Event that is executed when button is clicked
;note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,235 @@
note
description: "[
This class is the base class for all stateful controls, like
buttons or forms.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
WSF_CONTROL
inherit
WSF_STATELESS_CONTROL
rename
make as make_stateless_control
redefine
render_tag
end
feature {NONE} -- Initialization
make (a_tag_name: STRING_32)
-- Initialize with specified tag
require
a_tag_name_not_empty: not a_tag_name.is_empty
do
make_stateless_control (a_tag_name)
create control_name_prefix.make_empty
create state_changes.make
create actions.make_array
ensure
state_changes_attached: attached state_changes
end
feature -- Actions
start_modal (url: STRING_32; title: STRING_32; big: BOOLEAN)
--Start a modal window containing an other or the same page
require
url_not_empty: not url.is_empty
title_not_empty: not title.is_empty
local
modal: WSF_JSON_OBJECT
do
create modal.make
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
show_alert (message: STRING_32)
--Start a modal window containg an other or the same page
require
message_not_empty: not message.is_empty
local
alert: WSF_JSON_OBJECT
do
create alert.make
alert.put_string ("show_alert", "type")
alert.put_string (message, "message")
actions.add (alert)
end
redirect (url: STRING_32)
--Redirect to an other page
require
url_not_empty: not url.is_empty
local
modal: WSF_JSON_OBJECT
do
create modal.make
modal.put_string ("redirect", "type")
modal.put_string (url, "url")
actions.add (modal)
end
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
load_state (new_states: JSON_OBJECT)
-- Select state stored with `control_name` as key
do
if attached {JSON_OBJECT} new_states.item ("state") as new_state_obj then
set_state (new_state_obj)
end
end
set_state (new_state: JSON_OBJECT)
-- Before we process the callback. We restore the state of control.
deferred
end
full_state: WSF_JSON_OBJECT
-- Return state of object
do
create Result.make
Result.put (state, "state")
end
read_state_changes (states: WSF_JSON_OBJECT)
-- Add a new entry in the `states_changes` JSON object with the `control_name` as key and the `state` as value
do
if state_changes.count > 0 then
states.put (state_changes, control_name)
end
if actions.count > 0 then
if states.item ("actions") = Void then
states.put (create {JSON_ARRAY}.make_array, "actions")
end
if attached {JSON_ARRAY} states.item ("actions") as action_list then
across
actions.array_representation as ic
loop
action_list.add (ic.item)
end
end
end
end
state: WSF_JSON_OBJECT
-- Returns the current state of the Control as JSON. This state will be transfered to the client.
deferred
ensure
controls_not_defined: Result.item ("controls") = Void
end
state_changes: WSF_JSON_OBJECT
feature -- Rendering
render_tag (body: READABLE_STRING_32; attrs: detachable READABLE_STRING_32): STRING_32
-- Render this control with the specified body and attributes
do
Result := render_tag_with_generator_name (js_class, body, attrs)
end
render_tag_with_generator_name (a_generator, body: READABLE_STRING_32; attrs: detachable READABLE_STRING_32): STRING_32
-- Render this control with the specified generator name, body and attributes
local
l_css_classes_string: STRING_32
l_attributes: STRING_32
do
create l_css_classes_string.make_empty
across
css_classes as ic
loop
l_css_classes_string.append_character (' ')
l_css_classes_string.append (ic.item)
end
l_attributes := " data-name=%"" + control_name + "%" data-type=%"" + a_generator + "%" "
if attached attrs as l_attrs then
l_attributes.append (l_attrs)
end
if isolate then
l_attributes.append (" data-isolation=%"1%"")
end
Result := render_tag_with_tagname (tag_name, body, l_attributes, l_css_classes_string)
end
js_class: READABLE_STRING_32
-- The js_class is the name of the corresponding javascript class for this control. If this query is not redefined, it just
-- returns the name of the Eiffel class. In case of customized controls, either the according javascript functionality has to
-- be written in a coffeescript class of the same name or this query has to bee redefined and has to return the name of the
-- control Eiffel class of which the javascript functionality should be inherited.
do
Result := generator
end
feature -- Event handling
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
-- Method called if any callback received.
-- In this method the callback can be routed to the event handler.
require
cname_is_not_empty: not cname.is_empty
deferred
end
feature -- Change
set_isolation (p: BOOLEAN)
-- Set the isolation state of this control
do
isolate := p
end
set_control_name_prefix (p: STRING_32)
-- Set the control name prefix
do
control_name_prefix := p
end
set_control_id (d: INTEGER)
-- Set the id of this control
do
control_id := d
end
feature -- Properties
isolate: BOOLEAN
-- The isolation state of this control
actions: JSON_ARRAY
-- An array of actions to be carried out, e.g. display a modal (see tutorial for more information about this)
control_id: INTEGER assign set_control_id
-- The id of this control
control_name: STRING_32
-- The name of this control which is composed of the control name prefix and the id of the control
do
Result := control_name_prefix + control_id.out
end
control_name_prefix: STRING_32 assign set_control_name_prefix
-- Used to avoid name conflicts since the children stateful controls of stateless controls are appended to the parent
-- control state and therefore could have the same name (Stateless multi controls do not add a hierarchy level)
;note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,206 @@
note
description: "[
Dynamic Mutli controls are multicontrols in which the subcontrols can be added or removed
on a callback. This is achived by ''serializing'' the subcrontrols using the tag array.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
WSF_DYNAMIC_MULTI_CONTROL [G -> WSF_CONTROL]
inherit
WSF_MULTI_CONTROL [G]
rename
add_control as add_control_internal
redefine
make_with_tag_name,
set_state,
state,
read_state_changes,
js_class
end
feature {NONE} -- Initialization
make_with_tag_name (tag: STRING_32)
-- Initialize with specified tag
do
Precursor (tag)
create items.make_array
create pending_removes.make (1)
ensure then
tag_set: tag_name.same_string (tag)
end
feature {WSF_DYNAMIC_MULTI_CONTROL} -- Internal functions
add_control (c: G; id: INTEGER_32)
-- Add a control to this multi control
do
controls.extend (c)
if attached {WSF_CONTROL} c as d then
d.control_id := id
end
max_id := id.max (max_id)
items_changed := True
ensure
control_added: controls.has (c)
id_set: attached {WSF_CONTROL} c as d implies d.control_id = id
items_changed: items_changed
end
execute_pending_removes
-- Execute pending removes
local
found: BOOLEAN
fitem: detachable G
frow: detachable JSON_OBJECT
do
across
pending_removes as id
loop
across
controls as c
until
found
loop
if c.item.control_id = id.item then
fitem := c.item
found := True
end
end
if attached fitem as i then
controls.prune (i)
end
found := False
across
items.array_representation as c
until
found
loop
if attached {JSON_OBJECT} c.item as row and then attached {JSON_NUMBER} row.item ("id") as rid and then rid.item.to_integer_32 = id.item then
frow := row
found := True
end
end
if attached frow as r then
items.array_representation.prune (r)
end
items_changed := True
end
pending_removes.wipe_out
ensure
pending_removes_empty: pending_removes.is_empty
end
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
set_state (new_state: JSON_OBJECT)
-- Before we process the callback, we restore the subcontrols
do
if attached {JSON_ARRAY} new_state.item ("items") as new_items then
items := new_items
create controls.make (items.count)
across
new_items.array_representation as n
loop
if attached {JSON_OBJECT} n.item as record and then attached {JSON_NUMBER} record.item ("id") as id and then attached {JSON_STRING} record.item ("tag") as tag then
if attached create_control_from_tag (tag.item) as control then
add_control (control, id.item.to_integer_32)
end
end
end
items_changed := False
end
end
state: WSF_JSON_OBJECT
-- Return state which contains the current text and if there is an event handle attached
local
do
create Result.make
Result.put (items, "items")
end
feature
create_control_from_tag (tag: STRING_32): detachable G
-- This function should return a control based on the tag string. The output of this function
-- should only be based on the tag argument.
deferred
end
add_control_from_tag (tag: STRING_32)
-- Adds a control based on the tag
local
item: WSF_JSON_OBJECT
do
if attached create_control_from_tag (tag) as control then
add_control (control, max_id + 1)
create item.make
item.put_integer (max_id, "id")
item.put_string (tag, "tag")
items.add (item)
end
end
remove_control_by_id (id: INTEGER)
-- Add removes to pending removes list
do
pending_removes.extend (id)
end
read_state_changes (states: WSF_JSON_OBJECT)
local
new_state: WSF_JSON_OBJECT
sub_state: WSF_JSON_OBJECT
do
Precursor (states)
execute_pending_removes
if items_changed then
new_state := state
create sub_state.make
add_sub_controls_states_to (sub_state)
new_state.put (sub_state, "newstate")
new_state.put_string (render, "render")
states.put (new_state, control_name)
end
end
js_class: STRING_32
-- The default behvaiour of subclasses of the dynamic multi control is that they inherit the javascript functionality of this class
do
Result := "WSF_DYNAMIC_MULTI_CONTROL"
end
feature -- Access
items: JSON_ARRAY
-- Holds the current items in this control
pending_removes: ARRAYED_LIST [INTEGER]
-- Stores the removes that have to be executed
items_changed: BOOLEAN
-- Indicates whether a change to the controls has happened since the last state readout
max_id: INTEGER
-- Largest id of the controls in this multi control
invariant
all_items_exist: items.count = controls.count
note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,90 @@
note
description: "[
Represents a standard html form. Provides facilities for
validation.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_FORM_CONTROL
inherit
WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
rename
make as make_stateless_multi_control
redefine
add_control
end
WSF_VALIDATABLE
create
make, make_with_label_width
feature {NONE} -- Initialization
make
-- Initialize with default label width 2
do
make_with_label_width (2)
end
make_with_label_width (w: INTEGER)
-- Initialize with the specified label width measured in Bootstrap columns
require
w_in_range: w >= 0 and w <= 12
do
make_stateless_multi_control
tag_name := "form"
label_width := w
add_class ("form-horizontal")
ensure
label_width_set: label_width = w
end
feature
add_control (c: WSF_STATELESS_CONTROL)
-- Add control to this form
do
Precursor (c)
if attached {WSF_FORM_ELEMENT_CONTROL [detachable ANY]} c as fec then
fec.set_label_width (label_width)
end
ensure then
control_added: controls.has (c)
end
feature -- Validation
validate
-- Perform form validation
do
is_valid := True
across
controls as c
loop
if attached {WSF_VALIDATABLE} c.item as elem then
elem.validate
if not elem.is_valid then
is_valid := False
end
end
end
end
is_valid: BOOLEAN
-- Tells whether the last validation was valid
feature
label_width: INTEGER
-- The label width in this form, measured in Bootstrap columns
invariant
label_width_in_range: label_width >= 0 and label_width <= 12
end

View File

@@ -0,0 +1,269 @@
note
description: "[
A container class which encapsulates a form element (like input
fields) and, optionally, the corresponding validators and an
optional label.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_FORM_ELEMENT_CONTROL [G]
inherit
WSF_CONTROL
rename
make as make_control
redefine
read_state_changes,
load_state,
full_state
end
WSF_VALIDATABLE
create
make, make_without_border, make_with_validators
feature {NONE} -- Initialization
make_without_border (a_label: detachable STRING_32; a_control: WSF_VALUE_CONTROL [G])
-- Initialize Current form element control with a specific label
-- (or 'Void' for no label) and value control `a_control'.
do
make_with_validators (a_label, False, a_control, create {ARRAYED_LIST [WSF_VALIDATOR [G]]}.make (0))
end
make (a_label: detachable STRING_32; a_control: WSF_VALUE_CONTROL [G])
-- Initialize Current form element control with a specific label
-- (or 'Void' for no label) and value control `a_control'.
do
make_with_validators (a_label, True, a_control, create {ARRAYED_LIST [WSF_VALIDATOR [G]]}.make (0))
end
make_with_validators (a_label: detachable STRING_32; show_border: BOOLEAN; a_control: WSF_VALUE_CONTROL [G]; a_validators: LIST [WSF_VALIDATOR [G]])
-- Initialize Current form element control with a specific label (or 'Void' for no label),
-- value control `a_control' and list of validators `a_validators'
do
make_control ("div")
add_class ("form-group")
if show_border then
if attached {WSF_VALUE_CONTROL [LIST [ANY]]} a_control then
a_control.add_class ("form-control-static")
else
a_control.add_class ("form-control")
end
end
label_width := 2
value_control := a_control
validators := a_validators
label := a_label
error := ""
end
feature -- Modify
set_label_width (w: INTEGER)
-- Set the label span (a value between 1 and 12 to specify the bootstrap column span or 0 for not displaying the label)
do
label_width := w
ensure
label_width_set: label_width = w
end
feature -- Access
value: G
-- Current value of this form element's value control
do
Result := value_control.value
ensure
result_set: Result = value_control.value
end
set_value (v: G)
-- Set the value of this form element's value control
do
value_control.set_value (v)
ensure
value_set: value_control.value = v
end
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
load_state (new_states: JSON_OBJECT)
-- Pass new_states to subcontrols
do
Precursor (new_states)
if
attached {JSON_OBJECT} new_states.item ("controls") as ct and then
attached {JSON_OBJECT} ct.item (value_control.control_name) as value_state
then
value_control.load_state (value_state)
end
end
set_state (new_state: JSON_OBJECT)
-- Set new state
do
value_control.set_state (new_state)
end
full_state: WSF_JSON_OBJECT
-- The full state of this form
local
controls_state: WSF_JSON_OBJECT
do
Result := Precursor
create controls_state.make
controls_state.put (value_control.full_state, value_control.control_name)
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
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
-- Read state
local
validator_description: JSON_ARRAY
do
create Result.make
create validator_description.make_array
across
validators as v
loop
validator_description.add (v.item.state)
end
Result.put_string (value_control.control_name, "value_control")
Result.put (validator_description, "validators")
end
feature -- Event handling
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
-- Pass callback to subcontrols
do
if cname.first.same_string (control_name) then
cname.start
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
end
end
feature -- Implementation
render: STRING_32
-- HTML Respresentation of this form element control
local
body: STRING_32
do
create body.make_empty
if attached label as l_label and then not l_label.is_empty then
body.append ("<label class=%"col-lg-" + label_width.out + " control-label%" for=%"" + value_control.control_name + "%">" + l_label + "</label>")
body.append ("<div class=%"col-lg-" + (12 - label_width).out + "%">")
else
body.append ("<div class=%"col-lg-12%">")
end
body.append (value_control.render)
body.append ("</div>")
Result := render_tag (body, "")
end
feature -- Validation
add_validator (v: WSF_VALIDATOR [G])
-- Add an additional validator that will check the input of the value control of this form element control on validation
do
validators.extend (v)
ensure
validator_added: validators.has (v)
end
set_error (e: STRING_32)
-- Set the error message that will be displayed upon failure of client side validation
do
error := e
state_changes.replace (create {JSON_STRING}.make_json_from_string_32 (e), "error")
ensure
error_set: error.same_string (e)
end
validate
-- Perform validation
local
current_value: G
do
current_value := value
is_valid := True
across
validators as c
until
not is_valid
loop
if not c.item.is_valid (current_value) then
is_valid := False
set_error (c.item.error)
end
end
if is_valid then
set_error ("")
end
end
is_valid: BOOLEAN
-- Tells whether the last validation was successful or not
feature -- Properties
value_control: WSF_VALUE_CONTROL [G]
-- The value control associated with this form element control
validators: LIST [WSF_VALIDATOR [G]]
-- The validators which check the input when validaton is performed
label: detachable STRING_32
-- The label of this form element control
error: STRING_32
-- The error message that is displayed when client side validation fails
label_width: INTEGER
-- The bootstrap column span of the label of this form element control
;note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,103 @@
note
description: "[
A convenience class that can be used to insert custom html code.
This class is a value control which means that the html text can
be updated.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_HTML_CONTROL
inherit
WSF_VALUE_CONTROL [STRING_32]
rename
make as make_value_control
end
create
make
feature {NONE} -- Initialization
make (tag, v: STRING_32)
-- Initialize with specified tag and HTML value
require
tag_not_empty: not tag.is_empty
do
make_value_control (tag)
html := v
ensure
html_set: html.same_string (v)
end
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
set_state (new_state: JSON_OBJECT)
-- Restore HTML from json
do
if attached {JSON_STRING} new_state.item ("html") as new_html then
html := new_html.unescaped_string_32
end
end
state: WSF_JSON_OBJECT
-- Return state which contains the current html and if there is an event handle attached
do
create Result.make
Result.put_string (html, "html")
end
feature --Event handling
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
-- By default, this does nothing
do
end
feature -- Implementation
render: STRING_32
-- HTML representation of this html control
do
Result := render_tag (html, "")
end
value: STRING_32
-- The HTML value of this HTML control
do
Result := html
ensure then
result_set: Result.same_string (html)
end
set_value (v: STRING_32)
-- Set HTML value of this control
do
if not v.same_string (html) then
html := v
state_changes.replace_with_string (html, "html")
end
ensure then
html_set: html.same_string (v)
end
feature -- Properties
html: STRING_32
-- The HTML value of this HTML control
;note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,173 @@
note
description: "[
Advanced implementation of JSON_OBJECT with some helper functions.
This class can be removed since the proposed changes where merged in
to https://github.com/eiffelhub/json
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_JSON_OBJECT
inherit
JSON_OBJECT
create
make
feature -- Change
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: detachable JSON_STRING
do
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)
ensure
has_key: has_key (key)
end
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: detachable JSON_NUMBER
do
if attached value as a_value then
create l_value.make_integer (a_value)
end
put (l_value, key)
ensure
has_key: has_key (key)
end
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: detachable JSON_NUMBER
do
if attached value as a_value then
create l_value.make_natural (a_value)
end
put (l_value, key)
ensure
has_key: has_key (key)
end
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: detachable JSON_NUMBER
do
if attached value as a_value then
create l_value.make_real (a_value)
end
put (l_value, key)
ensure
has_key: has_key (key)
end
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: detachable JSON_BOOLEAN
do
if attached value as a_value then
create l_value.make_boolean (a_value)
end
put (l_value, key)
ensure
has_key: has_key (key)
end
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: detachable JSON_STRING
do
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: detachable INTEGER_64; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'.
local
l_value: detachable JSON_NUMBER
do
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: detachable NATURAL_64; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'.
local
l_value: detachable JSON_NUMBER
do
if attached value as a_value then
create l_value.make_natural (a_value)
end
replace (l_value, key)
end
replace_with_real (value: detachable DOUBLE; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'
local
l_value: detachable JSON_NUMBER
do
if attached value as a_value then
create l_value.make_real (a_value)
end
replace (l_value, key)
end
replace_with_boolean (value: detachable BOOLEAN; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'.
local
l_value: detachable JSON_BOOLEAN
do
if attached value as a_value then
create l_value.make_boolean (a_value)
end
replace (l_value, key)
end
note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,72 @@
note
description: "[
A lightweight layout container to encapsulate the grid layout
provided by bootstrap.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_LAYOUT_CONTROL
inherit
WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
rename
make as make_stateless_multi_control,
add_control as add_control_raw
end
create
make
feature {NONE} -- Initialization
make
--Initialize
do
make_with_tag_name ("div")
add_class ("row")
end
feature -- Add control
add_control_with_offset (c: WSF_STATELESS_CONTROL; span, offset: INTEGER)
-- Add a control as column with the specified span and offset
require
offset_in_range: offset >= 0 and offset <= 12
span_in_range: span >= 0 and span <= 12 - offset
local
div: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
do
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 (col: INTEGER; c: WSF_STATELESS_CONTROL)
-- Add a control to the specified column
require
col >= 1 and col <= controls.count
attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]} controls [col]
do
if attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]} controls [col] as div then
div.add_control (c)
end
end
add_column (span: INTEGER)
-- Add a multi control as Bootstrap column with the specified span
require
span_in_range: span >= 0 and span <= 12
local
div: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
do
create div.make_with_tag_name ("div")
div.add_class ("col-md-" + span.out)
add_control_raw (div)
end
end

View File

@@ -0,0 +1,211 @@
note
description: "[
Mutli controls are used as containers for multiple controls, for
example a form is a multi control.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_MULTI_CONTROL [G -> WSF_STATELESS_CONTROL]
inherit
WSF_CONTROL
rename
make as make_control
redefine
full_state,
read_state_changes,
load_state
end
create
make, make_with_tag_name
feature {NONE} -- Initialization
make
-- Initialize with default tag "div"
do
make_with_tag_name ("div")
end
make_with_tag_name (a_tag: STRING_32)
-- Initialize with specified tag `a_tag'.
require
a_tag_not_empty: not a_tag.is_empty
do
make_control (a_tag)
create {ARRAYED_LIST [G]} controls.make (5)
ensure
tag_name_set: tag_name.same_string (a_tag)
end
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
load_state (new_states: JSON_OBJECT)
-- Pass new_states to subcontrols
do
Precursor (new_states)
if attached {JSON_OBJECT} new_states.item ("controls") as ct then
load_subcontrol_state (ct)
end
end
load_subcontrol_state (newstate: JSON_OBJECT)
-- load the new state in to the subcontrols
-- If the subcontrol is a stateless multicontrol x. We load the controls_state in to the subcontrols of x directly. (Stateless multi controls do not add a hierarchy level)
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
end
set_state (new_state: JSON_OBJECT)
-- Before we process the callback. We restore the state of control.
do
end
full_state: WSF_JSON_OBJECT
-- Read states in subcontrols
local
l_state: WSF_JSON_OBJECT
do
Result := Precursor
create l_state.make
add_sub_controls_states_to (l_state)
Result.put (l_state, "controls")
end
add_sub_controls_states_to (a_controls_state: JSON_OBJECT)
-- Read add subcontrol state in to the `a_controls_state' json object.
-- If the subcontrol is a stateless multicontrol x,
-- the states of the subcontrols of x are directly added to `a_controls_state'.
-- (Stateless multi controls do not add a hierarchy level)
do
across
controls as c
loop
if attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]} c.item as mcont then
mcont.add_sub_controls_states_to (a_controls_state)
elseif attached {WSF_CONTROL} c.item as cont then
a_controls_state.put (cont.full_state, cont.control_name)
end
end
end
read_state_changes (states: WSF_JSON_OBJECT)
-- Read states_changes in subcontrols and add them to the states json object under `control name > "controls"
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 (sub_states: WSF_JSON_OBJECT)
-- Read add subcontrol changes in to the sub_states json object.
-- If the subcontrol is a stateless multicontrol x. We add the state changes of subcontrols of x directly to sub_states. (Stateless multi controls do not add a hierarchy level)
do
across
controls as ic
loop
if attached {WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]} ic.item as cont then
cont.read_subcontrol_state_changes (sub_states)
elseif attached {WSF_CONTROL} ic.item as cont then
cont.read_state_changes (sub_states)
end
end
end
state: WSF_JSON_OBJECT
--Read state
do
create Result.make
end
feature -- Event handling
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
-- Pass callback to subcontrols
do
if cname.first.same_string (control_name) then
cname.start
cname.remove
if not cname.is_empty then
across
controls as ic
until
cname.is_empty
loop
if attached {WSF_CONTROL} ic.item as cont then
cont.handle_callback (cname, event, event_parameter)
end
end
end
end
end
feature -- Rendering
render: STRING_32
-- HTML representation of this multi control
do
Result := ""
across
controls as c
loop
Result := Result + c.item.render
end
if not tag_name.is_empty then
Result := render_tag (Result, attributes)
end
end
feature
add_control (a_control: G)
-- Add a control `a_control' to this multi control.
do
controls.extend (a_control)
if attached {WSF_CONTROL} a_control as d then
d.control_id := controls.count
end
end
feature -- Properties
controls: ARRAYED_LIST [G]
-- List of current controls in this multi control
;note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,271 @@
note
description: "[
The skeleton for a page control which represents a single page
of the web application. This class is the starting point for
event distribution, rendering and state handling.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
WSF_PAGE_CONTROL
inherit
WSF_CONTROL
rename
make as make_control
redefine
control_name,
full_state,
read_state_changes
end
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE)
do
make_with_base_path (req, res, "/")
end
make_with_base_path (req: WSF_REQUEST; res: WSF_RESPONSE; a_base_path: STRING_32)
-- Initialize
do
base_path := a_base_path
control_name := req.request_time_stamp.out
make_control ("body")
request := req
response := res
initialize_controls
ensure
base_path_set: base_path.same_string (a_base_path)
end
feature -- Access
request: WSF_REQUEST
-- The http request
response: WSF_RESPONSE
-- The http response
feature -- Specific implementation
initialize_controls
-- Initalize all the controls, all the event handles must be set in this function.
deferred
ensure
attached control
end
process
-- Function called on page load (not on callback)
deferred
end
feature -- Implementation
execute
-- Entry Point: If request is a callback, restore control states and execute handle then return new state json.
-- If request is not a callback. Run process and render the html page
local
event: detachable STRING_32
event_parameter: detachable ANY
event_control_name: detachable STRING_32
states: STRING_8
states_changes: WSF_JSON_OBJECT
json_parser: JSON_PARSER
do
event_control_name := get_parameter ("control_name")
event := get_parameter ("event")
event_parameter := get_parameter ("event_parameter")
if attached event and attached event_control_name and attached control then
if not event.same_string_general ("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.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"]>>)
response.put_string (states_changes.representation)
else
process
render_page
end
end
render_page
-- Render and send the HTML page
local
page: WSF_PAGE_RESPONSE
do
create page.make
page.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html; charset=ISO-8859-1"]>>)
page.set_body (render)
response.send (page)
end
render: STRING_32
-- Render the HTML page
do
create Result.make_empty
if attached get_parameter ("ajax") as p_ajax then
Result.append ("<div data-name=%"" + control_name + "%" data-type=%"WSF_PAGE_CONTROL%">")
Result.append (control.render)
if attached additional_javascripts as l_additional_javascripts then
across
l_additional_javascripts as ic
loop
Result.append ("<script src=%"")
Result.append (base_path)
Result.append (ic.item)
Result.append ("%"></script>")
end
end
Result.append ("<script type=%"text/javascript%">$(function() {var page= new WSF_PAGE_CONTROL(")
Result.append (full_state.representation)
Result.append (");page.initialize();});</script>")
Result.append ("</div>")
else
Result.append ("<html><head>")
Result.append ("<link href=%"")
Result.append (base_path)
Result.append ("assets/bootstrap.min.css%" rel=%"stylesheet%">")
Result.append ("<link href=%"")
Result.append (base_path)
Result.append ("assets/widget.css%" rel=%"stylesheet%">")
Result.append ("</head><body data-name=%"" + control_name + "%" data-type=%"WSF_PAGE_CONTROL%">")
Result.append (control.render)
Result.append ("<script src=%"")
Result.append (base_path)
Result.append ("assets/jquery.min.js%"></script>")
Result.append ("<script src=%"")
Result.append (base_path)
Result.append ("assets/widget.js%"></script>")
if attached additional_javascripts as l_additional_javascripts then
across
l_additional_javascripts as ic
loop
Result.append ("<script src=%"")
Result.append (base_path)
Result.append (ic.item)
Result.append ("%"></script>")
end
end
Result.append ("<script type=%"text/javascript%">$(function() {var page= new WSF_PAGE_CONTROL(")
Result.append (full_state.representation)
Result.append (");page.initialize();});</script>")
Result.append ("</body></html>")
end
end
read_state_changes (states: WSF_JSON_OBJECT)
-- Add a new entry in the `states_changes` JSON object with the `control_name` as key and the `state` as value
do
Precursor (states)
control.read_state_changes (states)
end
get_parameter (key: READABLE_STRING_GENERAL): detachable STRING_32
-- Read query parameter as string
do
if
attached {WSF_STRING} request.query_parameter (key) as l_value
then
Result := l_value.value
end
end
add_javascript (path: STRING_32)
local
l_additional_javascripts: like additional_javascripts
do
l_additional_javascripts := additional_javascripts
if l_additional_javascripts = Void then
create l_additional_javascripts.make (1)
additional_javascripts := l_additional_javascripts
end
l_additional_javascripts.extend (path)
end
feature -- Event handling
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
-- Forward callback to control
do
control.handle_callback (cname, event, event_parameter)
end
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
state: WSF_JSON_OBJECT
-- State of the page
do
create Result.make
Result.put_string (control_name, "id")
Result.put_string (request.path_info, "url")
Result.put_string (request.query_string, "url_params")
end
set_state (sp: JSON_OBJECT)
-- Set state
do
if
attached {JSON_OBJECT} sp.item ("controls") as ct and then
attached {JSON_OBJECT} ct.item (control.control_name) as value_state
then
control.load_state (value_state)
end
end
full_state: WSF_JSON_OBJECT
local
controls_state: WSF_JSON_OBJECT
do
create Result.make
create controls_state.make
controls_state.put (control.full_state, control.control_name)
Result.put (controls_state, "controls")
Result.put (state, "state")
end
feature -- Access
control_name: STRING_32
-- Name of this page
base_path: STRING_32
-- The base path of the assets files
feature {NONE} -- Root control
control: WSF_CONTROL
-- The root control of this page
additional_javascripts: detachable ARRAYED_LIST [STRING_32]
-- List containing the additional javascipt files
;note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,156 @@
note
description: "[
This class is the base class of the framework.
Stateless controls are HTML elements which have no state (e.g.
headers, layout containers or static text fields. Stateful
controls (WSF_CONTROL) are subtypes of this class.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
WSF_STATELESS_CONTROL
feature {NONE} -- Initialization
make (a_tag_name: STRING_32)
-- Initialize with specified tag
require
a_tag_name_not_empty: not a_tag_name.is_empty
do
tag_name := a_tag_name
create css_classes.make (0)
ensure
tag_name_set: tag_name = a_tag_name
end
feature -- Change
add_class (a_css_class: STRING_32)
-- Add a css class to this control
require
a_css_class_not_empty: not a_css_class.is_empty
do
css_classes.force (a_css_class)
ensure
class_added: css_classes.has (a_css_class)
end
remove_class (a_css_class: STRING_32)
-- Remove a css class from this control
require
c_not_empty: not a_css_class.is_empty
do
css_classes.start
css_classes.prune_all (a_css_class)
ensure
c_removed: not css_classes.has (a_css_class)
end
append_attribute (att: READABLE_STRING_32)
-- Adds the specified attribute to the attribute string of this control
require
att_not_empty: not att.is_empty
do
if attached attributes as attr then
attr.append_character (' ')
attr.append (att)
else
create attributes.make_from_string (att)
end
end
feature -- Rendering
render_tag (a_body: READABLE_STRING_32; attrs: detachable READABLE_STRING_32): STRING_32
-- Generate HTML of this control with the specified body and attributes
local
css_classes_string: STRING_32
do
create css_classes_string.make_empty
across
css_classes as c
loop
css_classes_string.append (" " + c.item)
end
Result := render_tag_with_tagname (tag_name, a_body, attrs, css_classes_string)
end
render_tag_with_tagname (tag, a_body: READABLE_STRING_32; attrs: detachable READABLE_STRING_32; css_classes_string: READABLE_STRING_32): STRING_32
-- Generate HTML of the specified tag with specified body, attributes and css classes
local
l_attributes: STRING_32
do
if attached attrs as a then
create l_attributes.make_from_string (a)
else
l_attributes := ""
end
if not css_classes_string.is_empty then
l_attributes.append (" class=%"")
l_attributes.append (css_classes_string)
l_attributes.append_character ('%"')
end
create Result.make_empty
Result.append_character ('<')
Result.append (tag)
Result.append_character (' ')
Result.append (l_attributes)
-- Check if we have to render a body. For some elements, this is not the case (like textareas) or only if the body is not empty.
if
a_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
-- Note: it should be ok to close for textarea, span, ... and so on.
Result.append ("/>")
else
Result.append (" >")
Result.append (a_body)
Result.append ("</")
Result.append (tag)
Result.append (">")
end
end
render_tag_with_body (body: READABLE_STRING_32): STRING_32
-- Generate HTML of this control with the specified body
do
Result := render_tag (body, attributes)
end
render: STRING_32
-- Return html representation of control
deferred
end
feature -- Properties
tag_name: STRING_32
-- The tag name
css_classes: ARRAYED_LIST [STRING_32]
-- List of classes (appear in the "class" attribute)
attributes: detachable STRING_32
-- Attributes string (without classes)
invariant
tag_name_not_empty: not tag_name.is_empty
note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,126 @@
note
description: "[
Mutli controls are used as containers for multiple controls, for
example a form is a multi control.
]"
date: "$Date$"
revision: "$Revision$"
class
WSF_STATELESS_MULTI_CONTROL [G -> WSF_STATELESS_CONTROL]
inherit
WSF_MULTI_CONTROL [G]
rename
make as make_multi_control
redefine
add_control,
set_control_name_prefix,
handle_callback,
set_control_id,
render_tag
end
create
make_with_tag_name, make
feature {NONE} -- Initialization
make
-- Initialize
do
make_with_tag_name ("")
end
feature -- Change
set_control_id (d: INTEGER)
-- Set id of this control and update subcontrol prefixes
do
control_id := d
set_subcontrol_prefixes
ensure then
control_id_set: control_id.abs = d
end
set_control_name_prefix (p: STRING_32)
-- Set control name prefix of this control
do
control_name_prefix := p
set_subcontrol_prefixes
ensure then
control_name_prefix_set: control_name_prefix.same_string (p)
end
set_subcontrol_prefixes
-- Update subcontrol prefixes
local
s: STRING_32
do
across
controls as ic
loop
if attached {WSF_CONTROL} ic.item as l_control then
create s.make_from_string (control_name_prefix)
s.append_integer (control_id)
s.append_character ('_')
l_control.set_control_name_prefix (s)
end
end
end
feature -- Change
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
ensure then
control_added: controls.has (c)
end
render_tag (body: READABLE_STRING_32; attrs: detachable READABLE_STRING_32): STRING_32
-- Generate HTML of this control with the specified body and attributes
local
css_classes_string: STRING_32
do
create css_classes_string.make_empty
across
css_classes as c
loop
css_classes_string.append (" " + c.item)
end
Result := render_tag_with_tagname (tag_name, body, attrs, css_classes_string)
end
feature -- Event handling
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; 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
note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,38 @@
note
description: "[
Controls that can store a value inherit from this class.
Such controls are for example input fields, buttons or checkboxes.
]"
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
WSF_VALUE_CONTROL [G]
inherit
WSF_CONTROL
feature -- Access
value: G
-- The current value of this control
deferred
end
set_value (v: G)
-- Set `value' to `v'.
deferred
end
note
copyright: "2011-2014, Yassin Hassan, Severin Munger, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end