Move wsf_js_widget library under draft/library/server/wsf_js_widget
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
note
|
||||
description: "Summary description for {WSF_AUTOCOMPLETION}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_AUTOCOMPLETION
|
||||
|
||||
feature -- Query
|
||||
|
||||
autocompletion (input: READABLE_STRING_GENERAL): JSON_ARRAY
|
||||
-- JSON array of suggestions that fit the specific input
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
template: detachable READABLE_STRING_32
|
||||
-- Customizable template
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,62 @@
|
||||
note
|
||||
description: "Summary description for {WSF_SIMPLE_AUTOCOMPLETION}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_SIMPLE_AUTOCOMPLETION
|
||||
|
||||
inherit
|
||||
WSF_AUTOCOMPLETION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_list: ITERABLE [READABLE_STRING_32])
|
||||
-- Initialize with collection `a_list'.
|
||||
do
|
||||
list := a_list
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
list: ITERABLE [READABLE_STRING_32]
|
||||
-- List containing suggestions
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
autocompletion (a_input: READABLE_STRING_GENERAL): JSON_ARRAY
|
||||
-- <Precursor>
|
||||
local
|
||||
o: WSF_JSON_OBJECT
|
||||
l_lowered_input: READABLE_STRING_GENERAL
|
||||
l_lowered_item: READABLE_STRING_GENERAL
|
||||
do
|
||||
create Result.make_array
|
||||
l_lowered_input := a_input.as_lower
|
||||
across
|
||||
list as c
|
||||
loop
|
||||
l_lowered_item := c.item.as_lower
|
||||
if l_lowered_item.has_substring (l_lowered_input) then
|
||||
create o.make
|
||||
o.put_string (c.item, "value")
|
||||
Result.add (o)
|
||||
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
|
||||
@@ -0,0 +1,84 @@
|
||||
note
|
||||
description: "[
|
||||
Represents a bootstrap dropdown control. This class contains
|
||||
facilities to add items or dividers.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_DROPDOWN_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
rename
|
||||
make as make_multi_control,
|
||||
make_with_tag_name as make_multi_control_with_tag_name
|
||||
end
|
||||
|
||||
create
|
||||
make, make_with_tag_name
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (title: STRING_32)
|
||||
-- Make a dropdown control with div tag name and specified menu title
|
||||
do
|
||||
make_with_tag_name (title, "div")
|
||||
end
|
||||
|
||||
make_with_tag_name (title, tag: STRING_32)
|
||||
-- Make a dropdown control with specified tag name (such as li) and menu title
|
||||
require
|
||||
tag_not_empty: not tag.is_empty
|
||||
do
|
||||
make_multi_control_with_tag_name (tag)
|
||||
add_class ("dropdown")
|
||||
create {WSF_BASIC_CONTROL} dropdown_toggle.make_with_body_class ("a", "data-toggle=%"dropdown%" href=%"#%" type=%"button%" id=%"" + control_name + "_toggle%"", "dropdown-toggle", title + " <strong class=%"caret%"></strong>")
|
||||
create dropdown_menu.make_with_tag_name ("ul")
|
||||
dropdown_menu.add_class ("dropdown-menu")
|
||||
dropdown_menu.append_attribute ("role=%"menu%" aria-labelledby=%"" + control_name + "_toggle%"")
|
||||
add_control (dropdown_toggle)
|
||||
add_control (dropdown_menu)
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
add_item (c: WSF_STATELESS_CONTROL)
|
||||
-- Wrap the specified control into a <li> tag and add it to the menu
|
||||
local
|
||||
li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
do
|
||||
create li.make_with_tag_name ("li")
|
||||
li.append_attribute ("role=%"presentation%"")
|
||||
c.append_attribute ("role=%"menuitem%" tabindex=%"-1%"")
|
||||
li.add_control (c)
|
||||
dropdown_menu.add_control (li)
|
||||
end
|
||||
|
||||
add_link_item (label, link: STRING_32)
|
||||
-- Add an item to the menu which redirects to the specified link
|
||||
local
|
||||
c: WSF_BASIC_CONTROL
|
||||
do
|
||||
create c.make_with_body ("a", "href=%"" + link + "%"", label)
|
||||
add_item (c)
|
||||
end
|
||||
|
||||
add_divider
|
||||
-- Append a horizontal divider to the menu
|
||||
do
|
||||
dropdown_menu.add_control (create {WSF_BASIC_CONTROL}.make_with_body_class ("li", "role=%"menuitem%"", "divider", ""))
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
dropdown_toggle: WSF_STATELESS_CONTROL
|
||||
-- The dropdown toggle which causes the menu to pop up or dispose
|
||||
|
||||
dropdown_menu: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
-- The dropdown menu which holds the single entries (controls and dividers)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,89 @@
|
||||
note
|
||||
description: "Summary description for {WSF_DATASOURCE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_DATASOURCE [G -> WSF_ENTITY]
|
||||
|
||||
feature --Event handling
|
||||
|
||||
set_on_update_agent (f: PROCEDURE [ANY, TUPLE])
|
||||
-- Set update listener
|
||||
do
|
||||
on_update_agent := f
|
||||
end
|
||||
|
||||
update
|
||||
-- Trigger update listener
|
||||
do
|
||||
if attached on_update_agent as a then
|
||||
a.call (Void)
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
-- Return state which contains the current sort_column and sort_direction
|
||||
do
|
||||
create Result.make
|
||||
if attached sort_column as a_sort_column then
|
||||
Result.put_string (a_sort_column, "sort_column")
|
||||
else
|
||||
Result.put (create {JSON_NULL}, "sort_column")
|
||||
end
|
||||
Result.put_boolean (sort_direction, "sort_direction")
|
||||
end
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- Restore sort_column and sort_direction from json
|
||||
do
|
||||
if attached {JSON_STRING} new_state.item ("sort_column") as new_sort_column then
|
||||
sort_column := new_sort_column.unescaped_string_32 -- Implicit Conversion !
|
||||
elseif attached {JSON_NULL} new_state.item ("sort_column") as new_sort_column then
|
||||
sort_column := Void
|
||||
end
|
||||
if attached {JSON_BOOLEAN} new_state.item ("sort_direction") as new_sort_direction then
|
||||
sort_direction := new_sort_direction.item
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_sort_column (a_sort_column: like sort_column)
|
||||
-- Set the column by which the data should be sorted
|
||||
do
|
||||
sort_column := a_sort_column
|
||||
end
|
||||
|
||||
set_sort_direction (a_sort_direction: like sort_direction)
|
||||
-- Set the sorting direction
|
||||
do
|
||||
sort_direction := a_sort_direction
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
sort_column: detachable STRING
|
||||
|
||||
sort_direction: BOOLEAN
|
||||
|
||||
data: ITERABLE [G]
|
||||
deferred
|
||||
end
|
||||
|
||||
on_update_agent: detachable PROCEDURE [ANY, TUPLE]
|
||||
|
||||
;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
|
||||
26
draft/library/server/wsf_js_widget/kernel/grid/wsf_entity.e
Normal file
26
draft/library/server/wsf_js_widget/kernel/grid/wsf_entity.e
Normal file
@@ -0,0 +1,26 @@
|
||||
note
|
||||
description: "Summary description for {WSF_ENTITY}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_ENTITY
|
||||
|
||||
feature -- Access
|
||||
|
||||
item alias "[]" (a_field: READABLE_STRING_GENERAL): detachable ANY
|
||||
-- Value for field item `a_field'.
|
||||
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
|
||||
@@ -0,0 +1,55 @@
|
||||
note
|
||||
description: "Summary description for {WSF_GRID_COLUMN}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_GRID_COLUMN
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_header, a_field: STRING_32)
|
||||
do
|
||||
header := a_header
|
||||
field_name := a_field
|
||||
sorting_name := a_field
|
||||
end
|
||||
|
||||
feature -- Render
|
||||
|
||||
render_column (e: WSF_ENTITY): STRING_32
|
||||
-- Return the rendered column cell for a specific entity (row)
|
||||
do
|
||||
if attached e.item (field_name) as data then
|
||||
--| FIXME: .out may not be the best rendering for objects...
|
||||
Result := data.out
|
||||
else
|
||||
Result := "[VOID]"
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
header: STRING_32
|
||||
|
||||
sortable: BOOLEAN
|
||||
|
||||
sorting_name: STRING_32
|
||||
|
||||
field_name: STRING_32
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,75 @@
|
||||
note
|
||||
description: "Summary description for {WSF_GRID_CONTROL}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_GRID_CONTROL [G -> WSF_ENTITY]
|
||||
|
||||
inherit
|
||||
|
||||
WSF_REPEATER_CONTROL [G]
|
||||
rename
|
||||
make as make_repeater
|
||||
redefine
|
||||
render
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_columns: ITERABLE [WSF_GRID_COLUMN]; a_datasource: WSF_DATASOURCE [G])
|
||||
do
|
||||
make_repeater (a_datasource)
|
||||
columns := a_columns
|
||||
end
|
||||
|
||||
feature -- Render
|
||||
|
||||
render_item (item: G): STRING_32
|
||||
-- Render table row
|
||||
do
|
||||
Result := ""
|
||||
across
|
||||
columns as c
|
||||
loop
|
||||
Result.append (render_tag_with_tagname ("td", c.item.render_column (item), "", ""))
|
||||
end
|
||||
Result := render_tag_with_tagname ("tr", Result, "", "")
|
||||
end
|
||||
|
||||
render_header: STRING_32
|
||||
-- Render table header
|
||||
do
|
||||
Result := ""
|
||||
across
|
||||
columns as c
|
||||
loop
|
||||
Result.append (render_tag_with_tagname ("th", c.item.header, "", ""))
|
||||
end
|
||||
Result := render_tag_with_tagname ("thead", render_tag_with_tagname ("tr", Result, "", ""), "", "")
|
||||
end
|
||||
|
||||
render: STRING_32
|
||||
-- Render entre table and subcontrols
|
||||
local
|
||||
table: STRING_32
|
||||
do
|
||||
table := render_tag_with_tagname ("table", render_header + render_tag_with_tagname ("tbody", render_body, "", ""), "", "table table-striped")
|
||||
Result := ""
|
||||
across
|
||||
controls as c
|
||||
loop
|
||||
Result.append (c.item.render)
|
||||
end
|
||||
Result := render_tag (table + Result, "")
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
columns: ITERABLE [WSF_GRID_COLUMN]
|
||||
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
note
|
||||
description: "Summary description for {WSF_GRID_IMAGE_COLUMN}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_GRID_IMAGE_COLUMN
|
||||
|
||||
inherit
|
||||
|
||||
WSF_GRID_COLUMN
|
||||
rename
|
||||
make as make_column
|
||||
redefine
|
||||
render_column
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_header, a_field: STRING_32)
|
||||
do
|
||||
make_column (a_header, a_field)
|
||||
end
|
||||
|
||||
feature -- Render
|
||||
|
||||
render_column (e: WSF_ENTITY): STRING_32
|
||||
-- Return the rendered column image cell for a specific entity (row)
|
||||
do
|
||||
if attached e.item (field_name) as data then
|
||||
Result := "<img src=%"" + data.out + "%" />"
|
||||
else
|
||||
Result := "[VOID]"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,92 @@
|
||||
note
|
||||
description: "Summary description for {WSF_PAGABLE_DATASOURCE}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_PAGABLE_DATASOURCE [G -> WSF_ENTITY]
|
||||
|
||||
inherit
|
||||
WSF_DATASOURCE [G]
|
||||
redefine
|
||||
state,
|
||||
set_state,
|
||||
update
|
||||
end
|
||||
|
||||
feature -- Event handling
|
||||
|
||||
set_on_update_page_agent (f: PROCEDURE [ANY, TUPLE])
|
||||
-- Set paging update listener
|
||||
do
|
||||
on_update_page_agent := f
|
||||
end
|
||||
|
||||
update
|
||||
-- Trigger update listeners
|
||||
do
|
||||
Precursor
|
||||
if attached on_update_page_agent as a then
|
||||
a.call (Void)
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
-- Return state which contains the current page, page_size and row_count
|
||||
do
|
||||
Result := Precursor
|
||||
Result.put_integer (page, "page")
|
||||
Result.put_integer (page_size, "page_size")
|
||||
Result.put_integer (row_count, "row_count")
|
||||
end
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- Restore page, page_size and row_count from json
|
||||
do
|
||||
Precursor (new_state)
|
||||
if attached {JSON_NUMBER} new_state.item ("page") as new_page then
|
||||
page := new_page.item.to_integer
|
||||
end
|
||||
if attached {JSON_NUMBER} new_state.item ("page_size") as new_page_size then
|
||||
page_size := new_page_size.item.to_integer
|
||||
end
|
||||
if attached {JSON_NUMBER} new_state.item ("row_count") as new_row_count then
|
||||
row_count := new_row_count.item.to_integer
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_page (p: INTEGER)
|
||||
do
|
||||
page := p.min (page_count).max (1)
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
page: INTEGER
|
||||
|
||||
page_size: INTEGER
|
||||
|
||||
row_count: INTEGER
|
||||
|
||||
page_count: INTEGER
|
||||
do
|
||||
Result := (row_count / page_size).ceiling
|
||||
end
|
||||
|
||||
on_update_page_agent: detachable PROCEDURE [ANY, TUPLE]
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,112 @@
|
||||
note
|
||||
description: "Summary description for {WSF_PAGINATION}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_PAGINATION_CONTROL [G -> WSF_ENTITY]
|
||||
|
||||
inherit
|
||||
|
||||
WSF_CONTROL
|
||||
rename
|
||||
make as make_control
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE}
|
||||
|
||||
make (ds: WSF_PAGABLE_DATASOURCE [G])
|
||||
do
|
||||
make_control ( "ul")
|
||||
add_class ("pagination")
|
||||
datasource := ds
|
||||
datasource.set_on_update_page_agent (agent update)
|
||||
end
|
||||
|
||||
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
-- Return empty
|
||||
do
|
||||
create Result.make
|
||||
end
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- There is no state to restore states
|
||||
do
|
||||
end
|
||||
|
||||
update
|
||||
-- Send new renederd control to client on update
|
||||
do
|
||||
state_changes.replace (create {JSON_STRING}.make_json_from_string_32 (render), "_html")
|
||||
end
|
||||
|
||||
feature --Event handling
|
||||
|
||||
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
|
||||
-- Handle goto/next/prev events
|
||||
do
|
||||
if control_name.same_string_general (cname.first) 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 {READABLE_STRING_GENERAL} event_parameter as p and then
|
||||
attached p.to_integer as i
|
||||
then
|
||||
datasource.set_page (i)
|
||||
end
|
||||
end
|
||||
datasource.update
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Render
|
||||
|
||||
render: STRING_32
|
||||
-- Render paging control
|
||||
local
|
||||
paging_start: INTEGER
|
||||
paging_end: INTEGER
|
||||
cssclass: STRING_32
|
||||
do
|
||||
Result := render_tag_with_tagname ("li", render_tag_with_tagname ("a", "«", "href=%"#%" data-nr=%"prev%"", ""), "", "")
|
||||
paging_start := (datasource.page - 4).max (1)
|
||||
paging_end := (paging_start + 8).min (datasource.page_count)
|
||||
paging_start := (paging_end - 8).max (1)
|
||||
across
|
||||
paging_start |..| paging_end as n
|
||||
loop
|
||||
if n.item = datasource.page then
|
||||
cssclass := "active"
|
||||
else
|
||||
cssclass := ""
|
||||
end
|
||||
Result.append (render_tag_with_tagname ("li", render_tag_with_tagname ("a", n.item.out, "href=%"#%" data-nr=%"" + n.item.out + "%"", ""), "", cssclass))
|
||||
end
|
||||
Result.append (render_tag_with_tagname ("li", render_tag_with_tagname ("a", "»", "href=%"#%" data-nr=%"next%"", ""), "", ""))
|
||||
Result := render_tag (Result, "")
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
datasource: WSF_PAGABLE_DATASOURCE [G]
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,112 @@
|
||||
note
|
||||
description: "Summary description for {WSF_REPEATER_CONTROL}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_REPEATER_CONTROL [G -> WSF_ENTITY]
|
||||
|
||||
inherit
|
||||
|
||||
WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
rename
|
||||
make as make_multi_control
|
||||
redefine
|
||||
set_state,
|
||||
state,
|
||||
render
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_datasource: WSF_DATASOURCE [G])
|
||||
local
|
||||
p: WSF_PAGINATION_CONTROL [G]
|
||||
do
|
||||
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 (ds)
|
||||
add_control (p)
|
||||
pagination_control := p
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
|
||||
|
||||
update
|
||||
-- Send new rendered control to client on update
|
||||
do
|
||||
state_changes.replace (create {JSON_STRING}.make_json_from_string_32 (render_body), "_body")
|
||||
state_changes.replace (datasource.state, "datasource")
|
||||
end
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- Restore datasource state from json
|
||||
do
|
||||
if attached {JSON_OBJECT} new_state.item ("datasource") as datasource_state then
|
||||
datasource.set_state (datasource_state)
|
||||
end
|
||||
end
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
-- Return state which contains the current datasource state
|
||||
do
|
||||
create Result.make
|
||||
Result.put (datasource.state, "datasource")
|
||||
end
|
||||
|
||||
feature -- Rendering
|
||||
|
||||
render_item (item: G): STRING_32
|
||||
-- Render item
|
||||
deferred
|
||||
end
|
||||
|
||||
render_body: STRING_32
|
||||
-- Render Body
|
||||
do
|
||||
create Result.make_empty
|
||||
across
|
||||
datasource.data as ic
|
||||
loop
|
||||
Result.append (render_item (ic.item))
|
||||
end
|
||||
end
|
||||
|
||||
render: STRING_32
|
||||
-- Render repeater inclusive paging if paging is available
|
||||
local
|
||||
content: STRING_32
|
||||
do
|
||||
content := render_tag_with_tagname ("div", render_body, "", "repeater_content")
|
||||
create Result.make_empty
|
||||
across
|
||||
controls as ic
|
||||
loop
|
||||
-- CHECK: Prepend ? or Append?
|
||||
Result.prepend (ic.item.render)
|
||||
end
|
||||
-- Fix generator name since the user will extend this class to define item_render
|
||||
Result := render_tag_with_generator_name ("WSF_REPEATER_CONTROL", content + Result, "")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
datasource: WSF_DATASOURCE [G]
|
||||
|
||||
pagination_control: detachable WSF_PAGINATION_CONTROL [G]
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,86 @@
|
||||
note
|
||||
description: "[
|
||||
A control that can be used for autocompletion. A customizable
|
||||
template can be passed to this class in a WSF_AUTOCOMPLETION
|
||||
instance.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_AUTOCOMPLETE_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_INPUT_CONTROL
|
||||
rename
|
||||
make as make_input
|
||||
redefine
|
||||
handle_callback,
|
||||
state
|
||||
end
|
||||
|
||||
create
|
||||
make, make_with_agent
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (c: WSF_AUTOCOMPLETION)
|
||||
-- Initialize with specified autocompletion
|
||||
do
|
||||
make_with_agent (agent c.autocompletion)
|
||||
if attached c.template as t then
|
||||
template := t
|
||||
end
|
||||
end
|
||||
|
||||
make_with_agent (c: FUNCTION [ANY, TUPLE [READABLE_STRING_GENERAL], JSON_ARRAY])
|
||||
-- Initialize with autocompletion function
|
||||
do
|
||||
make_input ("")
|
||||
create_json_list := c
|
||||
template := "{{=value}}"
|
||||
end
|
||||
|
||||
feature -- State
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
do
|
||||
Result := Precursor {WSF_INPUT_CONTROL}
|
||||
Result.put_string (template, "template")
|
||||
end
|
||||
|
||||
feature -- Callback
|
||||
|
||||
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor {WSF_INPUT_CONTROL} (cname, event, event_parameter)
|
||||
if
|
||||
cname.first.same_string (control_name) and
|
||||
event.same_string ("autocomplete")
|
||||
then
|
||||
state_changes.put (create_json_list.item ([text]), "suggestions")
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
create_json_list: FUNCTION [ANY, TUPLE [READABLE_STRING_GENERAL], JSON_ARRAY]
|
||||
-- The function which is called to give a list of suggestions to a given user input
|
||||
|
||||
template: READABLE_STRING_32
|
||||
-- The template
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,116 @@
|
||||
note
|
||||
description: "[
|
||||
Representation of an HTML checkbox.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_CHECKBOX_CONTROL
|
||||
|
||||
inherit
|
||||
WSF_VALUE_CONTROL [BOOLEAN]
|
||||
rename
|
||||
make as make_value_control,
|
||||
value as checked,
|
||||
set_value as set_checked
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_label, a_value: STRING_32)
|
||||
-- Initialize with specified label `a_label' and value `a_value'.
|
||||
require
|
||||
a_value_not_empty: not a_value.is_empty
|
||||
do
|
||||
make_value_control ("input")
|
||||
label := a_label
|
||||
checked_value := a_value
|
||||
end
|
||||
|
||||
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- Restore text from json
|
||||
do
|
||||
if attached {JSON_BOOLEAN} new_state.item ("checked") as new_checked then
|
||||
checked := new_checked.item
|
||||
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 (checked, "checked")
|
||||
Result.put_string (checked_value, "checked_value")
|
||||
Result.put_boolean (attached change_event, "callback_change")
|
||||
end
|
||||
|
||||
feature --Event handling
|
||||
|
||||
set_change_event (e: attached like change_event)
|
||||
-- Set text change event handle
|
||||
do
|
||||
change_event := e
|
||||
end
|
||||
|
||||
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
|
||||
do
|
||||
if
|
||||
control_name.same_string_general (cname.first) and
|
||||
attached change_event as cevent and then
|
||||
event.same_string ("change")
|
||||
then
|
||||
cevent.call (Void)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
render: STRING_32
|
||||
local
|
||||
attrs: STRING_32
|
||||
do
|
||||
attrs := "type=%"checkbox%""
|
||||
if checked then
|
||||
attrs := attrs + " checked"
|
||||
end
|
||||
Result := render_tag_with_tagname ("div", render_tag_with_tagname ("label", render_tag ("", attrs) + " " + label, "", ""), "", "checkbox")
|
||||
end
|
||||
|
||||
set_checked (v: BOOLEAN)
|
||||
-- Set if the checkbox is checked
|
||||
do
|
||||
checked := v
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
label: STRING_32
|
||||
-- The label of the checkbox control
|
||||
|
||||
checked: BOOLEAN
|
||||
-- The checked value of the checkbox control
|
||||
|
||||
checked_value: STRING_32
|
||||
-- The value of this checkbox
|
||||
|
||||
change_event: detachable PROCEDURE [ANY, TUPLE]
|
||||
-- Function to be executed on change
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,65 @@
|
||||
note
|
||||
description: "[
|
||||
Representation of a list of HTML checkboxes.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_CHECKBOX_LIST_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_VALUE_CONTROL [LIST [STRING_32]]
|
||||
rename
|
||||
make as make_control
|
||||
undefine
|
||||
load_state,
|
||||
full_state,
|
||||
read_state_changes
|
||||
end
|
||||
|
||||
WSF_MULTI_CONTROL [WSF_CHECKBOX_CONTROL]
|
||||
rename
|
||||
make as make_multi_control
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initializaton
|
||||
|
||||
make
|
||||
-- Initialize with specified control name
|
||||
do
|
||||
make_multi_control
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
value: LIST [STRING_32]
|
||||
-- Returns the values of all selected checkboxes in this list
|
||||
do
|
||||
create {ARRAYED_LIST [STRING_32]} Result.make (0)
|
||||
across
|
||||
controls as c
|
||||
loop
|
||||
if c.item.checked then
|
||||
Result.extend (c.item.checked_value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
set_value (v: LIST [STRING_32])
|
||||
-- Sets the checked state of each of the checkboxes in this list according to whether the value
|
||||
-- of a checkbox occurs in the specified list or not
|
||||
do
|
||||
across
|
||||
controls as c
|
||||
loop
|
||||
c.item.set_checked (v.has (c.item.checked_value))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
note
|
||||
description:"[
|
||||
This class is only used because the code viewer has a specific
|
||||
mapping in javascript. The Eiffel class does not provide
|
||||
special functionality itself.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_CODEVIEW_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_TEXTAREA_CONTROL
|
||||
rename
|
||||
make as make_codeview
|
||||
end
|
||||
|
||||
create
|
||||
make_codeview
|
||||
|
||||
end
|
||||
@@ -0,0 +1,231 @@
|
||||
note
|
||||
description: "[
|
||||
A control that represents a file upload.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_FILE_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_VALUE_CONTROL [detachable WSF_FILE_DEFINITION]
|
||||
rename
|
||||
make as make_value_control
|
||||
end
|
||||
|
||||
create
|
||||
make, make_with_image_preview
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize
|
||||
do
|
||||
make_value_control ("input")
|
||||
end
|
||||
|
||||
make_with_image_preview
|
||||
-- Initialize with image_preview set to true
|
||||
do
|
||||
make
|
||||
image_preview := True
|
||||
end
|
||||
|
||||
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- Restore text from json
|
||||
local
|
||||
id: detachable STRING_32
|
||||
do
|
||||
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
|
||||
if attached {JSON_BOOLEAN} new_state.item ("disabled") as a_disabled then
|
||||
disabled := a_disabled.item
|
||||
end
|
||||
if attached {JSON_BOOLEAN} new_state.item ("image_preview") as a_image_preview then
|
||||
image_preview := a_image_preview.item
|
||||
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")
|
||||
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")
|
||||
Result.put_boolean (image_preview, "image_preview")
|
||||
end
|
||||
|
||||
feature -- Event handling
|
||||
|
||||
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
|
||||
local
|
||||
f_name: detachable STRING_32
|
||||
f_type: detachable STRING_32
|
||||
f_size: detachable INTEGER
|
||||
f_id: detachable STRING_32
|
||||
do
|
||||
if control_name.same_string_general (cname.first) then
|
||||
if attached change_event as cevent and event.same_string ("change") then
|
||||
cevent.call (Void)
|
||||
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
|
||||
|
||||
feature -- Upload
|
||||
|
||||
start_upload
|
||||
-- Add start upload command to action list which then executes the javascript function to start upload on client side
|
||||
local
|
||||
upload: WSF_JSON_OBJECT
|
||||
do
|
||||
create upload.make
|
||||
upload.put_string ("start_upload", "type")
|
||||
actions.add (upload)
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
value: detachable WSF_FILE_DEFINITION
|
||||
do
|
||||
Result := file
|
||||
end
|
||||
|
||||
render: STRING_32
|
||||
local
|
||||
attr: STRING_32
|
||||
do
|
||||
attr := "type=%"file%" "
|
||||
if attached attributes as a then
|
||||
attr.append (a)
|
||||
end
|
||||
if disabled then
|
||||
attr.append ("disabled=%"disabled%" ")
|
||||
end
|
||||
Result := render_tag_with_tagname ("div", render_tag ("", attr), Void, "")
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_change_event (e: attached like change_event)
|
||||
-- Set text change event handle
|
||||
do
|
||||
change_event := e
|
||||
ensure
|
||||
change_event_set: change_event = e
|
||||
end
|
||||
|
||||
set_upload_done_event (e: attached like upload_done_event)
|
||||
-- Set text change event handle
|
||||
do
|
||||
upload_done_event := e
|
||||
ensure
|
||||
upload_done_event_set: upload_done_event = e
|
||||
end
|
||||
|
||||
set_upload_function (e: attached like upload_function)
|
||||
-- Set button click event handle
|
||||
do
|
||||
upload_function := e
|
||||
ensure
|
||||
upload_function_set: upload_function = e
|
||||
end
|
||||
|
||||
set_disabled (b: BOOLEAN)
|
||||
-- Set the disabled state of this file control
|
||||
do
|
||||
if disabled /= b then
|
||||
disabled := b
|
||||
state_changes.replace_with_boolean (disabled, "disabled")
|
||||
end
|
||||
ensure
|
||||
disabled_set: disabled = b
|
||||
state_changes_registered: old disabled /= disabled implies state_changes.has_key ("disabled")
|
||||
end
|
||||
|
||||
set_value (v: detachable WSF_FILE_DEFINITION)
|
||||
-- Set the file definition of this file control
|
||||
do
|
||||
file := v
|
||||
ensure then
|
||||
file_set: file = v
|
||||
end
|
||||
|
||||
set_image_preview (b: BOOLEAN)
|
||||
-- Set if the image should be previewed in the control
|
||||
do
|
||||
if image_preview /= b then
|
||||
image_preview := b
|
||||
state_changes.replace_with_boolean (image_preview, "image_preview")
|
||||
end
|
||||
ensure
|
||||
image_preview_set: image_preview = b
|
||||
state_changes_registered: old image_preview /= image_preview implies state_changes.has_key ("image_preview")
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
disabled: BOOLEAN
|
||||
-- Defines if the a file is selectable and if a file can be removed once it is uploaded
|
||||
|
||||
image_preview: BOOLEAN
|
||||
-- Preview uploaded image
|
||||
|
||||
file: detachable WSF_FILE_DEFINITION
|
||||
-- Text to be displayed
|
||||
|
||||
change_event: detachable PROCEDURE [ANY, TUPLE]
|
||||
-- Procedure to be execued on change
|
||||
|
||||
upload_done_event: detachable PROCEDURE [ANY, TUPLE]
|
||||
-- Procedure to be execued when upload was successful
|
||||
|
||||
upload_function: detachable FUNCTION [ANY, TUPLE [ITERABLE [WSF_UPLOADED_FILE]], detachable STRING_32]
|
||||
-- Store uploaded file and return server side file id
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,54 @@
|
||||
note
|
||||
description: "[
|
||||
A container to encapsulate file information which is used by
|
||||
WSF_FILE_CONTROL, such as name or type of the file.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_FILE_DEFINITION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE}
|
||||
|
||||
make (a_name, a_type: STRING_32; a_size: INTEGER; a_id: detachable STRING_32)
|
||||
do
|
||||
name := a_name
|
||||
type := a_type
|
||||
size := a_size
|
||||
id := a_id
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_id (a_id: detachable STRING_32)
|
||||
-- Set the id of this abstract file.
|
||||
do
|
||||
id := a_id
|
||||
end
|
||||
|
||||
feature --Properties
|
||||
|
||||
is_uploaded: BOOLEAN
|
||||
-- Whether the file denoted by this abstract file has been uploaded.
|
||||
do
|
||||
Result := attached id
|
||||
end
|
||||
|
||||
name: STRING_32
|
||||
-- File name
|
||||
|
||||
type: STRING_32
|
||||
-- File mime type
|
||||
|
||||
size: INTEGER
|
||||
-- File size
|
||||
|
||||
id: detachable STRING_32
|
||||
-- Server side file id (e.g. S3 filename)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,172 @@
|
||||
note
|
||||
description: "[
|
||||
The basic <input> HTML element is represented by this control.
|
||||
All controls that are used to gather some input from the user
|
||||
basically can inherit from this class.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_INPUT_CONTROL
|
||||
|
||||
inherit
|
||||
WSF_VALUE_CONTROL [STRING_32]
|
||||
rename
|
||||
make as make_value_control
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (v: STRING_32)
|
||||
-- Initialize with specified value
|
||||
do
|
||||
make_value_control ("input")
|
||||
type := "text"
|
||||
text := v
|
||||
ensure
|
||||
text_set: text = v
|
||||
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 change_event, "callback_change")
|
||||
end
|
||||
|
||||
feature --Event handling
|
||||
|
||||
set_change_event (e: attached like change_event)
|
||||
-- Set text change event handle
|
||||
do
|
||||
change_event := e
|
||||
ensure
|
||||
change_event_set: change_event = e
|
||||
end
|
||||
|
||||
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
|
||||
do
|
||||
if
|
||||
control_name.same_string_general (cname.first) and
|
||||
attached change_event as cevent and then
|
||||
event.same_string ("change")
|
||||
then
|
||||
cevent.call (Void)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Rendering
|
||||
|
||||
render: STRING_32
|
||||
local
|
||||
attr: STRING_32
|
||||
do
|
||||
create attr.make (25)
|
||||
attr.append ("type=%"")
|
||||
attr.append (type)
|
||||
attr.append ("%" value=%"")
|
||||
attr.append (text)
|
||||
attr.append ("%" ")
|
||||
if attached attributes as l_attributes then
|
||||
attr.append (l_attributes)
|
||||
end
|
||||
if disabled then
|
||||
attr.append (" disabled=%"disabled%" ")
|
||||
end
|
||||
Result := render_tag ("", attr)
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_text (t: STRING_32)
|
||||
-- Set text to be displayed
|
||||
do
|
||||
if not t.same_string (text) then
|
||||
text := t
|
||||
state_changes.replace (create {JSON_STRING}.make_json_from_string_32 (t), "text")
|
||||
end
|
||||
ensure
|
||||
text_same_string_as_t: text.same_string (t)
|
||||
state_changes_registered: old text /= text implies state_changes.has_key ("text")
|
||||
end
|
||||
|
||||
set_disabled (b: BOOLEAN)
|
||||
-- Set the disabled state of this control
|
||||
do
|
||||
if disabled /= b then
|
||||
disabled := b
|
||||
state_changes.replace_with_boolean (disabled, "disabled")
|
||||
else
|
||||
check has_key_disabled: (b = False) or else state_changes.has_key ("disabled") end
|
||||
end
|
||||
ensure
|
||||
disabled_set: disabled = b
|
||||
state_changes_registered: (old b) /= b implies state_changes.has_key ("disabled")
|
||||
end
|
||||
|
||||
set_type (t: READABLE_STRING_32)
|
||||
-- Set the type of this input control (HTML 'type' attribute)
|
||||
do
|
||||
type := t
|
||||
ensure
|
||||
type_set: type = t
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
value: STRING_32
|
||||
-- The value of this input control
|
||||
do
|
||||
Result := text
|
||||
end
|
||||
|
||||
set_value (v: STRING_32)
|
||||
-- Set the value of this input control
|
||||
do
|
||||
text := v
|
||||
ensure then
|
||||
value_set: text = v
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
disabled: BOOLEAN
|
||||
-- Defines if the input field is editable
|
||||
|
||||
text: READABLE_STRING_32
|
||||
-- Text to be displayed
|
||||
|
||||
type: READABLE_STRING_32
|
||||
-- Type of this input control
|
||||
|
||||
change_event: detachable PROCEDURE [ANY, TUPLE]
|
||||
-- Procedure to be execued on change
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description: "[
|
||||
This control represents an HTML input control with the 'type'
|
||||
attribute set to 'password'.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_PASSWORD_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_INPUT_CONTROL
|
||||
rename
|
||||
make as make_input
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (v: STRING_32)
|
||||
-- Initialize with specified control name and text
|
||||
do
|
||||
make_input (v)
|
||||
type := "password"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,42 @@
|
||||
note
|
||||
description: "[
|
||||
This control represents a textarea (the HTML 'textarea' tag).
|
||||
It basically just inherits the functionality of an input
|
||||
control.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_TEXTAREA_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_INPUT_CONTROL
|
||||
rename
|
||||
make as make_input
|
||||
redefine
|
||||
render
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (t: STRING_32)
|
||||
-- Initialize with specified control name and text to be displayed in this textarea
|
||||
do
|
||||
make_input (t)
|
||||
tag_name := "textarea"
|
||||
end
|
||||
|
||||
feature -- Rendering
|
||||
|
||||
render: STRING_32
|
||||
do
|
||||
Result := render_tag (text, "")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,156 @@
|
||||
note
|
||||
description: "[
|
||||
WSF_NAVBAR_CONTROL encapsulates the navbar provided by
|
||||
bootstrap. Simple menu items as well as dropdown lists and
|
||||
panels can be added to this control.
|
||||
See http://getbootstrap.com/components/#navbar
|
||||
]"
|
||||
EIS: "name=Bootstrap navbar", "protocol=URI", "src=http://getbootstrap.com/components/#navbar"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_NAVBAR_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
rename
|
||||
make as make_multi_control
|
||||
redefine
|
||||
render
|
||||
end
|
||||
|
||||
create
|
||||
make, make_with_brand
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize
|
||||
do
|
||||
make_multi_control
|
||||
active_set := False
|
||||
add_class ("navbar navbar-inverse navbar-fixed-top")
|
||||
create nav.make_with_tag_name ("ul")
|
||||
create nav_right.make_with_tag_name ("ul")
|
||||
add_control (nav)
|
||||
add_control (nav_right)
|
||||
nav.add_class ("nav navbar-nav")
|
||||
nav_right.add_class ("nav navbar-nav navbar-right")
|
||||
end
|
||||
|
||||
make_with_brand (a_brand: READABLE_STRING_32)
|
||||
-- Initialize with specified `a_brand' string.
|
||||
do
|
||||
make
|
||||
brand := a_brand
|
||||
ensure
|
||||
brand_set: brand = a_brand
|
||||
end
|
||||
|
||||
feature -- Rendering
|
||||
|
||||
render: STRING_32
|
||||
local
|
||||
temp: STRING_32
|
||||
nav_string: STRING_32
|
||||
do
|
||||
temp := render_tag_with_tagname ("span", "", "", "icon-bar")
|
||||
temp.multiply (3)
|
||||
temp := render_tag_with_tagname ("button", temp, "data-target=%".navbar-collapse%" data-toggle=%"collapse%" type=%"button%"", "navbar-toggle")
|
||||
if attached brand as l_brand then
|
||||
temp.append (render_tag_with_tagname ("a", l_brand, "href=%"#%"", "navbar-brand"))
|
||||
end
|
||||
temp := render_tag_with_tagname ("div", temp, "", "navbar-header")
|
||||
nav_string := nav.render
|
||||
if nav_right.controls.count > 0 then
|
||||
nav_string.append (nav_right.render)
|
||||
end
|
||||
temp.append (render_tag_with_tagname ("div", nav_string, "", "navbar-collapse collapse"))
|
||||
Result := render_tag_with_tagname ("div", temp, "", "container")
|
||||
Result := render_tag (Result, "")
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_active (tab: INTEGER)
|
||||
-- Sets the given tab as current active tab. This procedure must not be called more than once.
|
||||
require
|
||||
tab >= 1 and tab <= tab_count and not active_set
|
||||
do
|
||||
if tab <= nav.controls.count then
|
||||
nav.controls.i_th (tab).add_class ("active")
|
||||
else
|
||||
nav_right.controls.i_th (tab - nav.controls.count).add_class ("active")
|
||||
end
|
||||
active_set := true
|
||||
ensure
|
||||
active_set_set: active_set
|
||||
end
|
||||
|
||||
add_list_element_right (a_control: WSF_STATELESS_CONTROL)
|
||||
-- Add element in li tag to right aligned part of navbar
|
||||
local
|
||||
li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
do
|
||||
create li.make_with_tag_name ("li")
|
||||
li.add_control (a_control)
|
||||
add_element_right (li)
|
||||
end
|
||||
|
||||
add_list_element (a_control: WSF_STATELESS_CONTROL)
|
||||
-- Add element in li tag to main nav
|
||||
local
|
||||
li: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
do
|
||||
create li.make_with_tag_name ("li")
|
||||
li.add_control (a_control)
|
||||
add_element (li)
|
||||
end
|
||||
|
||||
add_element_right (a_control: WSF_STATELESS_CONTROL)
|
||||
-- Add element to right aligned part of navbar
|
||||
do
|
||||
nav_right.add_control (a_control)
|
||||
end
|
||||
|
||||
add_element (a_control: WSF_STATELESS_CONTROL)
|
||||
-- Add element to main nav
|
||||
do
|
||||
nav.add_control (a_control)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
tab_count: INTEGER
|
||||
-- Current sum of the number of items in left and right navbar
|
||||
do
|
||||
Result := nav.controls.count + nav_right.controls.count
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
active_set: BOOLEAN
|
||||
-- This flag is set once a tab has been set as active tab
|
||||
|
||||
brand: detachable READABLE_STRING_32
|
||||
-- Optional brand of the navbar
|
||||
|
||||
nav: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
-- Middle nav
|
||||
|
||||
nav_right: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
-- Right nav
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,53 @@
|
||||
note
|
||||
description: "[
|
||||
This class encapsulates the linked items provided by bootstrap.
|
||||
See http://getbootstrap.com/components/#list-group-linked
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_NAVLIST_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_MULTI_CONTROL [WSF_NAVLIST_ITEM_CONTROL]
|
||||
rename
|
||||
make as make_multi_control
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize
|
||||
do
|
||||
make_multi_control
|
||||
add_class ("list-group")
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
add_link (link, text: STRING_32)
|
||||
-- Add a link to nav list
|
||||
local
|
||||
c: WSF_NAVLIST_ITEM_CONTROL
|
||||
do
|
||||
create c.make (link, text)
|
||||
add_control (c)
|
||||
end
|
||||
|
||||
add_button (event: attached like {WSF_BUTTON_CONTROL}.click_event; text: STRING_32)
|
||||
-- Add a button control to navlist
|
||||
local
|
||||
c: WSF_NAVLIST_ITEM_CONTROL
|
||||
do
|
||||
create c.make ("", text)
|
||||
c.set_click_event (event)
|
||||
add_control (c)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,80 @@
|
||||
note
|
||||
description: "[
|
||||
This class represents a menu item in WSF_NAVLIST_CONTROL.
|
||||
]"
|
||||
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_32)
|
||||
-- Initialize with the given link and text
|
||||
do
|
||||
make_control ("a")
|
||||
text := t
|
||||
attributes := "href=%"" + link + "%"";
|
||||
add_class ("list-group-item")
|
||||
ensure
|
||||
text_set: text = t
|
||||
end
|
||||
|
||||
feature {WSF_PAGE_CONTROL, WSF_CONTROL} -- State management
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- Restore text and active state 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, if the control is active 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 whether this item should be displayed as active or not
|
||||
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
|
||||
ensure
|
||||
active_set: active = a
|
||||
state_changes_registered: old active /= active implies state_changes.has_key ("active")
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
active: BOOLEAN
|
||||
-- The active state of this item
|
||||
|
||||
end
|
||||
@@ -0,0 +1,133 @@
|
||||
note
|
||||
description: "[
|
||||
WSF_PROGRESS_CONTROL encapsulates the progress bar provided by bootstrap.
|
||||
The value of the progress bar can either be set directly using set_progress
|
||||
or it can be fetched from a progress source.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_PROGRESS_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_CONTROL
|
||||
rename
|
||||
make as make_control
|
||||
end
|
||||
|
||||
create
|
||||
make, make_with_source
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize
|
||||
do
|
||||
make_control ("div")
|
||||
add_class ("progress")
|
||||
progress := 0
|
||||
end
|
||||
|
||||
make_with_source (p: WSF_PROGRESS_SOURCE)
|
||||
-- Initialize with specified progresssource
|
||||
do
|
||||
make
|
||||
progress_source := p
|
||||
ensure
|
||||
progress_source_set: progress_source = p
|
||||
end
|
||||
|
||||
feature -- State handling
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
require else
|
||||
progress_in_range: attached {JSON_NUMBER} new_state.item ("progress") as new_progress implies new_progress.item.to_integer >= 0 and new_progress.item.to_integer <= 100
|
||||
do
|
||||
if attached {JSON_NUMBER} new_state.item ("progress") as new_progress then
|
||||
progress := new_progress.item.to_integer
|
||||
end
|
||||
end
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put_integer (progress_value, "progress")
|
||||
end
|
||||
|
||||
feature -- Event handling
|
||||
|
||||
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
|
||||
do
|
||||
if
|
||||
cname.first.same_string (control_name) and
|
||||
event.same_string ("progress_fetch")
|
||||
then
|
||||
state_changes.put_integer (progress_value, "progress")
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Rendering
|
||||
|
||||
render: STRING_32
|
||||
local
|
||||
p: STRING_32
|
||||
do
|
||||
p := progress_value.out
|
||||
-- FIXME: string 32 truncated to string 8 !!!
|
||||
Result := render_tag_with_tagname ("div", "", "role=%"progressbar%" aria-valuenow=%"" + p + "%" aria-valuemin=%"0%" aria-valuemax=%"100%" style=%"width: " + p + "%%;%"", "progress-bar")
|
||||
Result := render_tag (Result, "")
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_progress (p: INTEGER)
|
||||
-- Set current progress value to specified value. Must be between 0 and 100. Must only be called when no progresssource has been set to this progress control
|
||||
require
|
||||
no_progress_source: progress_source = Void
|
||||
valid_input_value: p >= 0 and p <= 100
|
||||
do
|
||||
progress := p
|
||||
state_changes.put_integer (progress, "progress")
|
||||
ensure
|
||||
progress_set: progress = p
|
||||
state_changes_registered: state_changes.has_key ("progress")
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
progress_value: INTEGER
|
||||
-- The progress value of this progress control
|
||||
do
|
||||
Result := progress
|
||||
if attached progress_source as ps then
|
||||
Result := ps.progress
|
||||
end
|
||||
ensure
|
||||
result_in_range: Result >= 0 and Result <= 100
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
progress_source: detachable WSF_PROGRESS_SOURCE
|
||||
-- The source which provides this progress control the progress value
|
||||
|
||||
progress: INTEGER
|
||||
-- The progress value of this progress control
|
||||
|
||||
invariant
|
||||
progress_in_range: progress >= 0 and progress <= 100
|
||||
|
||||
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
|
||||
@@ -0,0 +1,20 @@
|
||||
note
|
||||
description: "[
|
||||
Provides the WSF_PROGRESS_CONTROL with the current progress state.
|
||||
Represented by a number between 0 and 100
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_PROGRESS_SOURCE
|
||||
|
||||
feature -- Specification
|
||||
|
||||
progress: INTEGER
|
||||
-- Current value of progress between 0 and 100 of this progresssource
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,135 @@
|
||||
note
|
||||
description: "[
|
||||
Represents the bootstraps's 'carousel'.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_SLIDER_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_CONTROL
|
||||
rename
|
||||
make as make_control
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize
|
||||
do
|
||||
make_control ("div")
|
||||
add_class ("carousel slide")
|
||||
create list.make_with_tag_name ("ol")
|
||||
list.add_class ("carousel-indicators")
|
||||
create slide_wrapper.make_with_tag_name ("div")
|
||||
slide_wrapper.add_class ("carousel-inner")
|
||||
end
|
||||
|
||||
feature -- State handling
|
||||
|
||||
set_state (new_state: JSON_OBJECT)
|
||||
-- Just implementation, nothing special to do here
|
||||
do
|
||||
end
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
-- Just implementation, nothing special to do here
|
||||
do
|
||||
create Result.make
|
||||
end
|
||||
|
||||
feature -- Callback
|
||||
|
||||
handle_callback (cname: LIST [READABLE_STRING_GENERAL]; event: READABLE_STRING_GENERAL; event_parameter: detachable ANY)
|
||||
-- Just implementation, nothing special to do here
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Rendering
|
||||
|
||||
render: STRING_32
|
||||
local
|
||||
temp: STRING_32
|
||||
do
|
||||
temp := list.render
|
||||
temp.append (slide_wrapper.render)
|
||||
temp.append (render_tag_with_tagname ("a", "<span class=%"icon-prev%"></span>", "data-slide=%"prev%"", "left carousel-control"))
|
||||
temp.append (render_tag_with_tagname ("a", "<span class=%"icon-next%"></span>", "data-slide=%"next%"", "right carousel-control"))
|
||||
Result := render_tag (temp, "")
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
add_image_with_caption (src, alt, a_caption: STRING_32)
|
||||
-- Add a new image to the slider with specified url, alternative text and caption
|
||||
local
|
||||
caption_control: detachable WSF_BASIC_CONTROL
|
||||
do
|
||||
if
|
||||
a_caption /= Void and then
|
||||
not a_caption.is_empty
|
||||
then
|
||||
create caption_control.make_with_body ("p", "", a_caption)
|
||||
end
|
||||
add_image_with_caption_control (src, alt, caption_control)
|
||||
end
|
||||
|
||||
add_image_with_caption_control (src, alt: STRING_32; a_caption: detachable WSF_STATELESS_CONTROL)
|
||||
-- Add a new image to the slider, with specified url, alternative text and caption element
|
||||
do
|
||||
add_control (create {WSF_BASIC_CONTROL}.make_with_body_class ("img", "src=%"" + src + "%" alt=%"" + alt + "%"", "", ""), Void)
|
||||
end
|
||||
|
||||
add_image (src, alt: STRING_32)
|
||||
-- Add a new image to the slider, with specified url and alternative text
|
||||
do
|
||||
add_image_with_caption (src, alt, "")
|
||||
end
|
||||
|
||||
add_control (a_control: WSF_STATELESS_CONTROL; a_caption: detachable WSF_STATELESS_CONTROL)
|
||||
-- Add a new control to the slider
|
||||
local
|
||||
cl: STRING_32
|
||||
item: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
do
|
||||
create item.make
|
||||
item.add_class ("item")
|
||||
item.add_control (a_control)
|
||||
if a_caption /= Void then
|
||||
item.add_control (a_caption)
|
||||
end
|
||||
cl := ""
|
||||
if slide_wrapper.controls.count = 0 then
|
||||
cl := "active"
|
||||
item.add_class (cl)
|
||||
end
|
||||
slide_wrapper.add_control (item)
|
||||
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_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
-- List of slider links
|
||||
|
||||
slide_wrapper: WSF_STATELESS_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
-- List of the single slides
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,46 @@
|
||||
note
|
||||
description: "[
|
||||
Wrapper whit which a agent can be used as 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_32)
|
||||
-- Initialize with given validation function and error message
|
||||
do
|
||||
make_validator (e)
|
||||
handler := h
|
||||
ensure
|
||||
handler_set: handler = h
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
is_valid (input: G): BOOLEAN
|
||||
-- Tests if given input is valid
|
||||
do
|
||||
Result := handler.item ([input])
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
handler: FUNCTION [ANY, TUPLE [G], BOOLEAN]
|
||||
-- The function which is used to validate inputs
|
||||
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
note
|
||||
description: "[
|
||||
Validator implementation which make sure that the input is a decimal number
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_DECIMAL_VALIDATOR
|
||||
|
||||
inherit
|
||||
|
||||
WSF_REGEXP_VALIDATOR
|
||||
rename
|
||||
make as make_regexp_validator
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (e: STRING_32)
|
||||
-- Initialize with specified error message which will be displayed on validation failure
|
||||
do
|
||||
make_regexp_validator ("^[0-9]+(\.[0-9]*)?$|^\.[0-9]+$", e)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
note
|
||||
description: "[
|
||||
Validator implementation which make sure that the input has
|
||||
the format of an valid email address. This is just a very
|
||||
basic implementation that tests if the given input contains a '@'.
|
||||
|
||||
This is a simple checker, it does not handle all the cases.
|
||||
]"
|
||||
EIS: "name=Application Techniques for Checking and Transformation of Names RFC3696", "protocol=URI", "src=http://tools.ietf.org/html/rfc3696#section-3"
|
||||
EIS: "name=Email address (wikipedia)", "protocol=URI", "src=http://en.wikipedia.org/wiki/Email_address"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_EMAIL_VALIDATOR
|
||||
|
||||
inherit
|
||||
|
||||
WSF_REGEXP_VALIDATOR
|
||||
rename
|
||||
make as make_regexp_validator
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (e: STRING_32)
|
||||
-- Initialize with specified error message
|
||||
do
|
||||
make_regexp_validator ("^.*@.*$", e)
|
||||
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
|
||||
@@ -0,0 +1,63 @@
|
||||
note
|
||||
description: "[
|
||||
Validator implementation which make sure that the uploaded file is smaller than x bytes
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_FILESIZE_VALIDATOR
|
||||
|
||||
inherit
|
||||
|
||||
WSF_VALIDATOR [detachable WSF_FILE_DEFINITION]
|
||||
rename
|
||||
make as make_validator
|
||||
redefine
|
||||
state
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (m: INTEGER; e: STRING_32)
|
||||
-- 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 (a_input: detachable WSF_FILE_DEFINITION): BOOLEAN
|
||||
do
|
||||
Result := a_input /= Void implies a_input.size < max
|
||||
end
|
||||
|
||||
feature -- State
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
do
|
||||
Result := Precursor
|
||||
Result.put_integer (max, "max")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
max: INTEGER
|
||||
-- The maximal allowed value
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,63 @@
|
||||
note
|
||||
description: "[
|
||||
Validator implementation which make sure that the input is at most x long.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_MAX_VALIDATOR [G -> FINITE [ANY]]
|
||||
|
||||
inherit
|
||||
|
||||
WSF_VALIDATOR [G]
|
||||
rename
|
||||
make as make_validator
|
||||
redefine
|
||||
state
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (m: INTEGER; e: STRING_32)
|
||||
-- Initialize with specified minimum `m' and error message `e' which will be displayed on validation failure.
|
||||
do
|
||||
make_validator (e)
|
||||
max := m
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
is_valid (a_input: G): BOOLEAN
|
||||
do
|
||||
Result := a_input.count < max or a_input.count = max
|
||||
end
|
||||
|
||||
feature -- State
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
do
|
||||
Result := Precursor
|
||||
Result.put_integer (max, "max")
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
max: INTEGER
|
||||
-- The maximal allowed value
|
||||
|
||||
;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
|
||||
@@ -0,0 +1,53 @@
|
||||
note
|
||||
description: "[
|
||||
Validator implementation which make sure that the input is at least x long.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_MIN_VALIDATOR [G -> FINITE [ANY]]
|
||||
|
||||
inherit
|
||||
|
||||
WSF_VALIDATOR [G]
|
||||
rename
|
||||
make as make_validator
|
||||
redefine
|
||||
state
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (m: INTEGER; e: STRING_32)
|
||||
-- Initialize with specified minimum and error message which will be displayed on validation failure
|
||||
do
|
||||
make_validator (e)
|
||||
min := m
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
is_valid (input: G): BOOLEAN
|
||||
do
|
||||
Result := input.count > min or input.count = min
|
||||
end
|
||||
|
||||
feature -- State
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
do
|
||||
Result := Precursor
|
||||
Result.put_integer (min, "min")
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
min: INTEGER
|
||||
-- The minimal allowed value
|
||||
|
||||
end
|
||||
@@ -0,0 +1,64 @@
|
||||
note
|
||||
description: "[
|
||||
Validator implementation which validates the input based on a given regular expression
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_REGEXP_VALIDATOR
|
||||
|
||||
inherit
|
||||
|
||||
WSF_VALIDATOR [STRING_32]
|
||||
rename
|
||||
make as make_validator
|
||||
redefine
|
||||
state
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (r, e: STRING_32)
|
||||
-- Initialize with specified regular expression and error message which will be displayed on validation failure
|
||||
do
|
||||
make_validator (e)
|
||||
regexp_string := r
|
||||
create regexp
|
||||
ensure regexp_string_set: regexp_string = r
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
is_valid (input: STRING_32): BOOLEAN
|
||||
do
|
||||
--Only compile when used
|
||||
if not regexp.is_compiled then
|
||||
regexp.compile (regexp_string)
|
||||
end
|
||||
Result := (not input.is_empty) and regexp.matches (input)
|
||||
end
|
||||
|
||||
feature -- State
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put_string ("WSF_REGEXP_VALIDATOR", "name")
|
||||
Result.put_string (regexp_string, "expression")
|
||||
Result.put_string (error, "error")
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
regexp_string: STRING_32
|
||||
-- The regexp in string representation
|
||||
|
||||
regexp: REGULAR_EXPRESSION
|
||||
-- The regexp of this validator
|
||||
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
note
|
||||
description: "[
|
||||
Defines that control can be validated.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_VALIDATABLE
|
||||
|
||||
feature -- Specification
|
||||
|
||||
validate
|
||||
-- Perform validation
|
||||
deferred
|
||||
end
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Result of last validation
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
note
|
||||
description: "[
|
||||
Base validation class which can be added to the WSF_FORM_ELEMENT_CONTROL
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_VALIDATOR [G]
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (e: STRING_32)
|
||||
-- Initialize with specified error message `e' to be displayed on validation failure.
|
||||
do
|
||||
error := e
|
||||
ensure
|
||||
error_set: error = e
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
state: WSF_JSON_OBJECT
|
||||
-- JSON state of this validator
|
||||
do
|
||||
create Result.make
|
||||
Result.put_string (generator, "name")
|
||||
Result.put_string (error, "error")
|
||||
-- FIXME: is that correct to always send error message??
|
||||
end
|
||||
|
||||
is_valid (a_input: G): BOOLEAN
|
||||
-- Perform validation on given input and tell whether validation was successful or not
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
error: STRING_32
|
||||
-- The error message if validation fails.
|
||||
|
||||
;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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,74 @@
|
||||
note
|
||||
description: "[
|
||||
A very basic datepicker widget based on the datepicker from
|
||||
Stefan Petre (http://www.eyecon.ro/bootstrap-datepicker).
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_DATE_PICKER_CONTROL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
rename
|
||||
make as make_multi_control,
|
||||
make_with_tag_name as make_multi_control_with_tag_name
|
||||
select
|
||||
make_control
|
||||
end
|
||||
|
||||
WSF_VALUE_CONTROL [STRING_32]
|
||||
undefine
|
||||
load_state,
|
||||
full_state,
|
||||
read_state_changes,
|
||||
make
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (t: STRING_32)
|
||||
-- Make a date picker control with specified tag name (such as li) and menu title
|
||||
local
|
||||
span: WSF_MULTI_CONTROL [WSF_STATELESS_CONTROL]
|
||||
do
|
||||
make_multi_control_with_tag_name (t)
|
||||
add_class ("input-group date")
|
||||
create input.make ((create {DATE_TIME}.make_now).formatted_out ("[0]dd-[0]mm-yyyy"))
|
||||
input.add_class ("form-control")
|
||||
input.append_attribute ("size=%"16%" readonly=%"%"")
|
||||
add_control (input)
|
||||
create span.make_with_tag_name ("span")
|
||||
span.add_class ("input-group-addon add-on")
|
||||
span.add_control (create {WSF_BASIC_CONTROL}.make_with_body_class ("span", "", "glyphicon glyphicon-calendar", ""))
|
||||
add_control (span)
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
value: STRING_32
|
||||
-- The current value
|
||||
do
|
||||
Result := input.value
|
||||
end
|
||||
|
||||
set_value (v: STRING_32)
|
||||
-- Set the current date (has to be in format dd-mm-yyyy)
|
||||
do
|
||||
input.set_value (v)
|
||||
ensure then
|
||||
value_set: input.value = v
|
||||
end
|
||||
|
||||
feature -- Properties
|
||||
|
||||
input: WSF_INPUT_CONTROL
|
||||
-- The input control which is used to display the selected date
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user