aurita-gui 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/LICENSE +19 -0
- data/aurita-gui-0.1.0.gem +0 -0
- data/aurita-gui.gemspec +37 -0
- data/lib/aurita-gui.rb +6 -0
- data/lib/aurita-gui/button.rb +85 -0
- data/lib/aurita-gui/element.rb +161 -0
- data/lib/aurita-gui/form.rb +232 -0
- data/lib/aurita-gui/form/checkbox_field.rb +34 -0
- data/lib/aurita-gui/form/date_field.rb +94 -0
- data/lib/aurita-gui/form/datetime_field.rb +101 -0
- data/lib/aurita-gui/form/fieldset.rb +55 -0
- data/lib/aurita-gui/form/file_field.rb +30 -0
- data/lib/aurita-gui/form/form_error.rb +10 -0
- data/lib/aurita-gui/form/form_field.rb +93 -0
- data/lib/aurita-gui/form/hidden_field.rb +43 -0
- data/lib/aurita-gui/form/input_field.rb +29 -0
- data/lib/aurita-gui/form/options_field.rb +115 -0
- data/lib/aurita-gui/form/radio_field.rb +35 -0
- data/lib/aurita-gui/form/select_field.rb +34 -0
- data/lib/aurita-gui/form/textarea_field.rb +22 -0
- data/lib/aurita-gui/html.rb +119 -0
- data/lib/aurita-gui/table.rb +192 -0
- data/test/tc_form.rb +30 -0
- data/test/tc_table.rb +23 -0
- metadata +86 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/form/form_field')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
# Usage:
|
8
|
+
#
|
9
|
+
# i = Input_Field.new(:name => :description,
|
10
|
+
# :label => 'Description',
|
11
|
+
# :value => 'Lorem ipsum dolor')
|
12
|
+
#
|
13
|
+
class Input_Field < Form_Field
|
14
|
+
def initialize(params, &block)
|
15
|
+
params[:tag] = :input
|
16
|
+
params[:type] = :text unless params[:type]
|
17
|
+
if block_given? then
|
18
|
+
params[:value] = yield
|
19
|
+
end
|
20
|
+
super(params)
|
21
|
+
end
|
22
|
+
def element
|
23
|
+
HTML.input(@attrib)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/form/form_field')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
# Abstract base class for all form elements containing
|
8
|
+
# options, like Select_Field, Radio_Field, Checkbox_Field
|
9
|
+
# or any custom implementation.
|
10
|
+
#
|
11
|
+
# Usage:
|
12
|
+
#
|
13
|
+
# r = Radio_Field.new(:options => { 1 => 'first',
|
14
|
+
# 2 => 'second',
|
15
|
+
# 3 => 'third' },
|
16
|
+
# :label => 'Which one?',
|
17
|
+
# :value => 1)
|
18
|
+
# Same as
|
19
|
+
#
|
20
|
+
# r = Radio_Field(:option_range => (1..3)
|
21
|
+
# :option_labels => ['First', 'Second', 'Third']
|
22
|
+
# :value => 1,
|
23
|
+
# :label => 'Which one?')
|
24
|
+
#
|
25
|
+
# Set a selected value using parameter :value
|
26
|
+
#
|
27
|
+
# r = Radio_Field.new(:value => 42, :name => :amount,
|
28
|
+
# :label => 'Select amount')
|
29
|
+
# r.value = 23
|
30
|
+
#
|
31
|
+
# If there may be more than one selected field, e.g. for Checkbox_Field,
|
32
|
+
# @value is an Array instance:
|
33
|
+
#
|
34
|
+
# c = Checkbox_Field.new(:value => [ 1, 3 ],
|
35
|
+
# :options => { 1 => 'first', 2 => 'second', 3 => 'third' },
|
36
|
+
# :label => 'Choose')
|
37
|
+
# c.value = [ 2, 3 ]
|
38
|
+
#
|
39
|
+
#
|
40
|
+
# There are many ways to define options:
|
41
|
+
#
|
42
|
+
# select = Select_Field.new(:name => :category, :label => 'Category')
|
43
|
+
# select.options = { 1 => 'first', 2 => 'second' }
|
44
|
+
# select.add_option(3 => 'third')
|
45
|
+
# select[3] = HTML.option(:value => 4) { 'fourth' }
|
46
|
+
# select[4] = { 5 => 'fifth' }
|
47
|
+
#
|
48
|
+
#
|
49
|
+
#
|
50
|
+
class Options_Field < Form_Field
|
51
|
+
|
52
|
+
attr_accessor :options, :options_range, :options_labels, :value
|
53
|
+
|
54
|
+
def initialize(params, &block)
|
55
|
+
@options = params[:options]
|
56
|
+
@options_range = params[:options_range]
|
57
|
+
@options_labels = params[:options_labels]
|
58
|
+
@options ||= {}
|
59
|
+
@options_range ||= []
|
60
|
+
@options_labels ||= []
|
61
|
+
@option_elements = []
|
62
|
+
@value = params[:value]
|
63
|
+
if block_given? then
|
64
|
+
yield.each { |option|
|
65
|
+
add_option(option)
|
66
|
+
}
|
67
|
+
elsif params[:options] then
|
68
|
+
add_option(params[:options])
|
69
|
+
end
|
70
|
+
params.delete(:options)
|
71
|
+
params.delete(:value) # Value is determined via selected value
|
72
|
+
params.delete(:options_range)
|
73
|
+
params.delete(:options_labels)
|
74
|
+
super(params)
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_option(option={})
|
78
|
+
if option.kind_of? Array then
|
79
|
+
@option_elements += option
|
80
|
+
elsif option.kind_of? Hash then
|
81
|
+
@option_elements << options
|
82
|
+
elsif option.kind_of? Range then
|
83
|
+
@option_elements += option.to_a
|
84
|
+
end
|
85
|
+
# @option_elements << option
|
86
|
+
end
|
87
|
+
|
88
|
+
def options=(options)
|
89
|
+
if options.kind_of? Array then
|
90
|
+
@option_elements = options
|
91
|
+
elsif options.kind_of? Hash then
|
92
|
+
@option_elements = [ options ]
|
93
|
+
elsif options.kind_of? Range then
|
94
|
+
@option_elements = options.to_a
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def [](index)
|
99
|
+
@option_elements[index]
|
100
|
+
end
|
101
|
+
def []=(index, option_element)
|
102
|
+
@option_elements[index] = option_element
|
103
|
+
end
|
104
|
+
|
105
|
+
def element
|
106
|
+
raise Form_Error.new('Method #element from Abstract class Options_Field has not been overloaded.')
|
107
|
+
end
|
108
|
+
|
109
|
+
def content
|
110
|
+
option_elements()
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/form/options_field')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
class Radio_Field < Options_Field
|
8
|
+
|
9
|
+
def option_elements
|
10
|
+
options = []
|
11
|
+
@option_elements.each { |option|
|
12
|
+
if option.kind_of? Hash then
|
13
|
+
option.each_pair { |k,v|
|
14
|
+
options << HTML.input(:type => :radio, :value => k, :name => @attrib[:name] ) { v }
|
15
|
+
}
|
16
|
+
elsif option.kind_of? Element then
|
17
|
+
option.name = @attrib[:name]
|
18
|
+
option.tag = :input
|
19
|
+
option.type = :radio
|
20
|
+
options << option
|
21
|
+
end
|
22
|
+
}
|
23
|
+
options
|
24
|
+
end
|
25
|
+
|
26
|
+
def element
|
27
|
+
HTML.ul(:class => :radio_options) {
|
28
|
+
option_elements().map { |o| HTML.li() { o } }
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/form/options_field')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
class Select_Field < Options_Field
|
8
|
+
def option_elements
|
9
|
+
options = []
|
10
|
+
@option_elements.each { |option|
|
11
|
+
if option.kind_of? Hash then
|
12
|
+
option.each_pair { |k,v|
|
13
|
+
selected = (@value && k.to_s == @value.to_s)? true : nil
|
14
|
+
options << HTML.option(:value => k, :selected => selected) { v }
|
15
|
+
}
|
16
|
+
elsif option.kind_of? Element then
|
17
|
+
option.tag = :option
|
18
|
+
options << option
|
19
|
+
else
|
20
|
+
selected = (@value && option.to_s == @value.to_s)? true : nil
|
21
|
+
options << HTML.option(:value => option, :selected => selected) { option }
|
22
|
+
end
|
23
|
+
}
|
24
|
+
options
|
25
|
+
end
|
26
|
+
def element
|
27
|
+
HTML.select(@attrib) {
|
28
|
+
option_elements()
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/form/form_field')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
class Textarea_Field < Form_Field
|
8
|
+
def initialize(params, &block)
|
9
|
+
params[:tag] = :textarea
|
10
|
+
# Move value parameter to @content:
|
11
|
+
@content = params[:value]
|
12
|
+
params.delete(:value)
|
13
|
+
super(params, &block)
|
14
|
+
@value = @content
|
15
|
+
end
|
16
|
+
def element
|
17
|
+
HTML.textarea(@attrib) { @value }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/element')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
# Aurita::GUI::HTML is a convenient factory for
|
8
|
+
# Aurita::GUI::Element. Almost every class method
|
9
|
+
# is redirected to generate a correspoding
|
10
|
+
# Element instance.
|
11
|
+
#
|
12
|
+
# It implements an object-oriented, minimalistic
|
13
|
+
# generator for HTML code.
|
14
|
+
# For tags without enclosed content (i.e. without
|
15
|
+
# closing tag):
|
16
|
+
#
|
17
|
+
# HTML.br
|
18
|
+
# # --> '<br />'
|
19
|
+
#
|
20
|
+
# HTML.hr(:class => 'divide')
|
21
|
+
# # --> '<hr class="divide" />'
|
22
|
+
#
|
23
|
+
# This is effectively a wrapper for
|
24
|
+
#
|
25
|
+
# Element.new(:tag => :hr, :class => 'divide')
|
26
|
+
#
|
27
|
+
# Enclosed content is passed in a block:
|
28
|
+
#
|
29
|
+
# HTML.a(:href => 'http://domain.com') { 'click me' }
|
30
|
+
# # --> '<a href="http://domain.com">click me</a>'
|
31
|
+
#
|
32
|
+
class HTML
|
33
|
+
|
34
|
+
def self.br
|
35
|
+
'<br />'
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.render(meth_name, attrib_hash={}, &block)
|
39
|
+
raise ::Exception.new('Missing attributes for HTML.' << meth_name.inspect) unless attrib_hash
|
40
|
+
attrib_hash[:tag] = meth_name
|
41
|
+
label = yield if block_given?
|
42
|
+
label = label.to_s unless label.kind_of? String
|
43
|
+
attrib_hash[:content] = label
|
44
|
+
Element.new(attrib_hash)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.a(attrib_hash={}, &block)
|
48
|
+
render(:a, attrib_hash, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.method_missing(meth_name, attrib_hash={}, &block)
|
52
|
+
render(meth_name, attrib_hash, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# A minimalistic generator for javascript calls.
|
58
|
+
# Usage:
|
59
|
+
#
|
60
|
+
# my_element.onclick = Javascript.new("alert('an alert message');")
|
61
|
+
#
|
62
|
+
# or just:
|
63
|
+
#
|
64
|
+
# my_element.onclick = Javascript.my_function('foo', 2, 'bar')
|
65
|
+
# --> my_function('foo', 2, 'bar');
|
66
|
+
#
|
67
|
+
# For namespaces:
|
68
|
+
#
|
69
|
+
# my_element.onclick = Javascript[:Foo].my_function(1,2)
|
70
|
+
# --> Foo.my_function('foo', 2, 'bar');
|
71
|
+
#
|
72
|
+
# Method #string renders the code passed in constructir,
|
73
|
+
# enclosed in <script> tags:
|
74
|
+
#
|
75
|
+
# Javascript.new("alert('message');").string
|
76
|
+
# -->
|
77
|
+
# <script language="Javascript" type="text/javascript">
|
78
|
+
# alert('message');
|
79
|
+
# </script>
|
80
|
+
#
|
81
|
+
class Javascript
|
82
|
+
|
83
|
+
def initialize(script)
|
84
|
+
@script = script
|
85
|
+
end
|
86
|
+
|
87
|
+
# Renders script to a <script> block.
|
88
|
+
def code_block
|
89
|
+
'<script language="Javascript" type="text/javascript">' << "\n" <<
|
90
|
+
@script + "\n" <<
|
91
|
+
'</script>'
|
92
|
+
end
|
93
|
+
|
94
|
+
def string
|
95
|
+
@script
|
96
|
+
end
|
97
|
+
alias to_s string
|
98
|
+
|
99
|
+
def self.[](namespace)
|
100
|
+
return self.new(namespace.to_s + '.')
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.method_missing(meth, *args)
|
104
|
+
args = args.collect { |arg|
|
105
|
+
if arg.instance_of? String then
|
106
|
+
'\'' << arg << '\''
|
107
|
+
else
|
108
|
+
arg
|
109
|
+
end
|
110
|
+
}
|
111
|
+
args_string = args.join(',')
|
112
|
+
meth.to_s << '(' << args_string + ');'
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end # module
|
118
|
+
end # module
|
119
|
+
|
@@ -0,0 +1,192 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/html')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# table = Table.new(:headers => [ 'user', 'phone', 'mobile', 'email' ])
|
11
|
+
# table.add_row('fuchsto', '+49 89 123456', '+49 89 987654', 'fuchst@wortundform.de')
|
12
|
+
#
|
13
|
+
# A row element may be of type Aurita::GUI::Element.
|
14
|
+
# In this case, method #string is invoked to render the cell.
|
15
|
+
#
|
16
|
+
# More examples:
|
17
|
+
#
|
18
|
+
# t = Table.new(:headers => ['user', 'phone', 'email'],
|
19
|
+
# :options => { :class => 'css_class', :id => 'test_table' })
|
20
|
+
# t.add_row([ 'a','b','c' ])
|
21
|
+
# t.add_row([ 'd','e','f' ])
|
22
|
+
|
23
|
+
# t[0][0].value = 'foo'
|
24
|
+
# t[0][0].value = 45
|
25
|
+
# t[1][0].onclick = 'test();'
|
26
|
+
# t[0][1] = HTML.a(:href => 'http://google.com') { 'google' }
|
27
|
+
|
28
|
+
# t[0][1].value.href = 'other'
|
29
|
+
# t[0][1].value.content = 'clickme'
|
30
|
+
|
31
|
+
# puts t[0][1].value.string
|
32
|
+
|
33
|
+
# t[0].class = 'highlighted'
|
34
|
+
#
|
35
|
+
class Table < Element
|
36
|
+
|
37
|
+
attr_accessor :columns, :headers, :rows, :template, :row_css_classes, :column_css_classes, :options
|
38
|
+
|
39
|
+
def initialize(params={}, &block)
|
40
|
+
@options = params[:options]
|
41
|
+
@options[:tag] = 'table'
|
42
|
+
@headers = params[:headers]
|
43
|
+
@num_columns = params[:num_columns]
|
44
|
+
@num_columns = @headers.length if (!@columns && @headers)
|
45
|
+
@columns = []
|
46
|
+
@rows = []
|
47
|
+
@row_css_classes = params[:row_css_classes]
|
48
|
+
@row_css_classes ||= []
|
49
|
+
@column_css_classes = params[:column_css_classes]
|
50
|
+
@column_css_classes ||= []
|
51
|
+
super(@options, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_row(row_data)
|
55
|
+
row = Table_Row.new(row_data, :parent => self)
|
56
|
+
@rows << row
|
57
|
+
|
58
|
+
# Add row content to columns
|
59
|
+
row_index = 0
|
60
|
+
@columns.each { |c|
|
61
|
+
c.add[row[row_index]]
|
62
|
+
row_index += 1
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def string
|
67
|
+
@content = "\n"
|
68
|
+
@content << HTML.tr { @headers.collect { |cell| HTML.th { cell } }.join }.string
|
69
|
+
@content << @rows.collect { |row| row.string }.join("\n")
|
70
|
+
super()
|
71
|
+
end
|
72
|
+
alias to_s string
|
73
|
+
|
74
|
+
def set_column_decorator(column_index, decorator)
|
75
|
+
end
|
76
|
+
|
77
|
+
def set_data(row_array)
|
78
|
+
row_array.each { |row|
|
79
|
+
@rows << Table_Row.new(row, :parent => self)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def cell(column, row)
|
84
|
+
@rows[row][column]
|
85
|
+
end
|
86
|
+
|
87
|
+
def [](row_index)
|
88
|
+
@rows[row_index]
|
89
|
+
end
|
90
|
+
def []=(row_index, row_data)
|
91
|
+
@rows[row_index] = row_data
|
92
|
+
end
|
93
|
+
|
94
|
+
def columns
|
95
|
+
Table_Column.new(@columns)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
class Table_Row < Element
|
101
|
+
def initialize(cell_data, params={})
|
102
|
+
@cell_data = cell_data
|
103
|
+
@cells = []
|
104
|
+
@cell_data.each { |cell|
|
105
|
+
@cells << Table_Cell.new(cell, :parent => self)
|
106
|
+
}
|
107
|
+
params[:tag] = 'tr'
|
108
|
+
super(params)
|
109
|
+
end
|
110
|
+
|
111
|
+
def table
|
112
|
+
@params[:parent]
|
113
|
+
end
|
114
|
+
|
115
|
+
def [](column_index)
|
116
|
+
@cells[column_index]
|
117
|
+
end
|
118
|
+
def []=(column_index, cell_data)
|
119
|
+
@cells[column_index].value = cell_data
|
120
|
+
end
|
121
|
+
|
122
|
+
def string
|
123
|
+
@content = "\n" << @cells.collect { |c| c.string }.join()
|
124
|
+
super()
|
125
|
+
end
|
126
|
+
|
127
|
+
def inspect
|
128
|
+
'[' << @cells.collect { |c| c.value }.join(',') + ']'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Virtual Element: There is no mapped HTML element
|
133
|
+
# for table columns.
|
134
|
+
class Table_Column
|
135
|
+
def initialize(cell_array)
|
136
|
+
@cells = cell_array
|
137
|
+
end
|
138
|
+
def [](row_index)
|
139
|
+
@cells[row_index]
|
140
|
+
end
|
141
|
+
def []=(row_index, cell_element)
|
142
|
+
@cells[row_index] = cell_element
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Accessor for a table cell.
|
147
|
+
# Usage:
|
148
|
+
#
|
149
|
+
# cell = my_table[row][column]
|
150
|
+
# cell.content = 'New cell content'
|
151
|
+
# cell.class = 'table_cell_css_class'
|
152
|
+
#
|
153
|
+
class Table_Cell < Element
|
154
|
+
|
155
|
+
attr_accessor :value, :presentation_class
|
156
|
+
|
157
|
+
def initialize(cell_element, params={})
|
158
|
+
params[:tag] = 'td'
|
159
|
+
@presentation_class = false
|
160
|
+
super(params)
|
161
|
+
@value = cell_element
|
162
|
+
@content = cell_element
|
163
|
+
end
|
164
|
+
|
165
|
+
def value=(val)
|
166
|
+
@value = val
|
167
|
+
@content = val.to_s
|
168
|
+
if @presentation_class then
|
169
|
+
@content = @presentation_class.new(@value).string
|
170
|
+
else
|
171
|
+
@content = @value.to_s
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def set_presentation(presentation_class)
|
176
|
+
@presentation_class = presentation_class
|
177
|
+
end
|
178
|
+
|
179
|
+
def string
|
180
|
+
if @presentation_class then
|
181
|
+
@content = @presentation_class.new(@value).string
|
182
|
+
else
|
183
|
+
@content = @value.to_s
|
184
|
+
end
|
185
|
+
super()
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|