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
data/History.txt
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
Copyright (c) 2008-2009 Tobias Fuchs (fuchs@wortundform.de)
|
3
|
+
Aurita::GUI is a core module of Aurita, Copyright (c) 2004-2009 Tobias Fuchs (fuchs@wortundform.de)
|
4
|
+
|
5
|
+
(MIT Licence)
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
8
|
+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
9
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
10
|
+
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
13
|
+
the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
16
|
+
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
18
|
+
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
19
|
+
DEALINGS IN THE SOFTWARE.
|
File without changes
|
data/aurita-gui.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
spec = Gem::Specification.new { |s|
|
5
|
+
|
6
|
+
s.name = 'aurita-gui'
|
7
|
+
s.rubyforge_project = 'aurita'
|
8
|
+
s.summary = 'Dead-simple object-oriented creation of HTML elements, including forms, tables and many more. '
|
9
|
+
s.description = <<-EOF
|
10
|
+
Aurita::GUI provides an intuitive and flexible API for object-oriented creation
|
11
|
+
of primitive and complex HTML elements, such as tables and forms.
|
12
|
+
It is a core module of the Aurita application framework, but it can be used
|
13
|
+
as stand-alone library in any context (such as rails).
|
14
|
+
As there seems to be a lack of ruby form generators, i decided to release this
|
15
|
+
part of Aurita in a single gem with no dependencies.
|
16
|
+
EOF
|
17
|
+
s.version = '0.1.0'
|
18
|
+
s.author = 'Tobias Fuchs'
|
19
|
+
s.email = 'fuchs@atomnode.net'
|
20
|
+
s.date = Time.now
|
21
|
+
s.files = '*.rb'
|
22
|
+
# s.add_dependency('postgres', '>= 0.1')
|
23
|
+
s.files = FileList['*',
|
24
|
+
'lib/*',
|
25
|
+
'lib/aurita-gui/*',
|
26
|
+
'lib/aurita-gui/form/*',
|
27
|
+
'bin/*',
|
28
|
+
'test/*'].to_a
|
29
|
+
|
30
|
+
s.has_rdoc = true
|
31
|
+
s.rdoc_options << '--title' << 'Aurita::GUI' <<
|
32
|
+
'--main' << 'Aurita::GUI::HTML' <<
|
33
|
+
'--line-numbers'
|
34
|
+
|
35
|
+
s.homepage = 'http://aurita.wortundform.de/'
|
36
|
+
|
37
|
+
}
|
data/lib/aurita-gui.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/element')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
# Specialization of Aurita::GUI::Element, extending
|
8
|
+
# it by @icon to display in the button.
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
#
|
12
|
+
# b = Button.new(:type => :submit, # default is :button
|
13
|
+
# :icon => '/path/to/icon.png', # default is no icon
|
14
|
+
# :onclick => 'alert('button clicked'); ") {
|
15
|
+
# 'click me'
|
16
|
+
# }
|
17
|
+
#
|
18
|
+
# Change button text:
|
19
|
+
#
|
20
|
+
# b.content = 'Custom button text'
|
21
|
+
#
|
22
|
+
# Disable icon again:
|
23
|
+
#
|
24
|
+
# b.icon = false
|
25
|
+
#
|
26
|
+
class Button < Element
|
27
|
+
attr_accessor :icon
|
28
|
+
|
29
|
+
def initialize(params, &block)
|
30
|
+
params[:tag] = :button
|
31
|
+
params[:type] = :button unless params[:type]
|
32
|
+
@icon = params[:icon]
|
33
|
+
params.delete(:icon)
|
34
|
+
super(params, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def content
|
38
|
+
if @icon then
|
39
|
+
return [ HTML.img(:src => @icon), @content ]
|
40
|
+
end
|
41
|
+
return @content
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# Specialization of Aurita::GUI::Element for
|
47
|
+
# submit buttons. Set @tag to :input, @type to :submit.
|
48
|
+
# Block argument will be used as button label (:value)
|
49
|
+
# Example:
|
50
|
+
#
|
51
|
+
# b = Submit_Button.new(:class => :css_class) { 'click me' }
|
52
|
+
#
|
53
|
+
class Submit_Button < Element
|
54
|
+
def initialize(params, &block)
|
55
|
+
params[:tag] = :input
|
56
|
+
params[:type] = :submit unless params[:type]
|
57
|
+
if block_given? then
|
58
|
+
params[:value] = yield
|
59
|
+
end
|
60
|
+
super(params)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Specialization of Aurita::GUI::Element for
|
65
|
+
# submit buttons. Set @tag to :input, @type to :reset.
|
66
|
+
# Block argument will be used as button label (:value)
|
67
|
+
# Example:
|
68
|
+
#
|
69
|
+
# b = Reset_Button.new(:class => :css_class) { 'click me' }
|
70
|
+
#
|
71
|
+
# Note that reset buttons in forms are considered
|
72
|
+
# bad style in terms of usability.
|
73
|
+
class Reset_Button < Element
|
74
|
+
def initialize(params, &block)
|
75
|
+
params[:tag] = :input
|
76
|
+
params[:type] = :reset unless params[:type]
|
77
|
+
if block_given? then
|
78
|
+
params[:value] = yield
|
79
|
+
end
|
80
|
+
super(params)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
|
2
|
+
module Aurita
|
3
|
+
module GUI
|
4
|
+
|
5
|
+
# GUI::Element is the base class for any rendering
|
6
|
+
# implementation.
|
7
|
+
# It consists of the following members:
|
8
|
+
#
|
9
|
+
# * @tag: The HTML tag to render.
|
10
|
+
# * @attrib: A hash storing tag attributes, like
|
11
|
+
# { :href => '/link/to/somewhere' }
|
12
|
+
# * @content: Content this element is wrapping.
|
13
|
+
# Content can be set in the constructor
|
14
|
+
# via parameter :content or using a
|
15
|
+
# block or by #content and #content=.
|
16
|
+
#
|
17
|
+
# Most methods invoked on an Element instance are
|
18
|
+
# redirected to return or set a tag attribute.
|
19
|
+
# Example:
|
20
|
+
#
|
21
|
+
# link = Element(:tag => :a) { 'klick me' }
|
22
|
+
# link.href = '/link/to/somewhere'
|
23
|
+
#
|
24
|
+
# Same as
|
25
|
+
#
|
26
|
+
# link = Element(:tag => :a,
|
27
|
+
# :content => 'click me',
|
28
|
+
# :href => '/link/to/somewhere')
|
29
|
+
#
|
30
|
+
# An Element instance can wrap one or more other
|
31
|
+
# elements:
|
32
|
+
#
|
33
|
+
# image_link = Element.new(:tag => :a, :href => '/link/') {
|
34
|
+
# Element.new(:tag => :img, :src => '/an_image.png')
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
# In case an element has no content, it will render
|
38
|
+
# a self-closing tag, like <img ... />.
|
39
|
+
#
|
40
|
+
# In most cases you won't use class Element directly,
|
41
|
+
# but by using a factory like Aurita::GUI::HTML or
|
42
|
+
# by any derived class like Aurita::GUI::Form or
|
43
|
+
# Aurita::GUI::Table.
|
44
|
+
#
|
45
|
+
class Element
|
46
|
+
|
47
|
+
@@element_count = 0
|
48
|
+
|
49
|
+
attr_accessor :attrib, :type, :content, :parent, :tag
|
50
|
+
|
51
|
+
def initialize(params={}, &block)
|
52
|
+
@@element_count += 1
|
53
|
+
@id = @@element_count
|
54
|
+
@parent = params[:parent]
|
55
|
+
params.delete(:parent)
|
56
|
+
|
57
|
+
params[:tag] = :div if params[:tag].nil?
|
58
|
+
|
59
|
+
if block_given? then
|
60
|
+
@content = yield
|
61
|
+
else
|
62
|
+
@content = params[:content].to_s
|
63
|
+
end
|
64
|
+
params.delete(:content)
|
65
|
+
@tag = params[:tag]
|
66
|
+
params.delete(:tag)
|
67
|
+
# params[:id] = self.class.to_s.split('::')[-1].downcase + '_' << @@element_count.to_s if params[:id].nil?
|
68
|
+
params[:onclick] << ';' unless params[:onclick].nil? or params[:onclick].include?(';')
|
69
|
+
|
70
|
+
@attrib = params
|
71
|
+
# @attrib[:id] = @attrib[:id].to_s
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
# Return DOM id of this element.
|
76
|
+
def dom_id
|
77
|
+
@attrib[:id]
|
78
|
+
end
|
79
|
+
# Set DOM id of this element.
|
80
|
+
def dom_id=(value)
|
81
|
+
@attrib[:id] = value
|
82
|
+
end
|
83
|
+
|
84
|
+
# Render this element to a string and append another
|
85
|
+
# element.
|
86
|
+
def +(other)
|
87
|
+
return string << other.string if other.kind_of? Element
|
88
|
+
return string << other
|
89
|
+
end
|
90
|
+
alias << +
|
91
|
+
|
92
|
+
# Redirect methods to setting or retreiving tag
|
93
|
+
# attributes.
|
94
|
+
def method_missing(meth, value=nil)
|
95
|
+
return @attrib[meth] unless value or meth.to_s.include? '='
|
96
|
+
@attrib[meth.to_s.gsub('=','').intern] = value
|
97
|
+
end
|
98
|
+
|
99
|
+
# Define explicitly so built-in method #type
|
100
|
+
# is not invoked instead
|
101
|
+
def type=(type)
|
102
|
+
@attrib[:type] = type
|
103
|
+
end
|
104
|
+
# Alias definition for #dom_id=(value)
|
105
|
+
# Define explicitly so built-in method #id
|
106
|
+
# is not invoked instead
|
107
|
+
def id=(value)
|
108
|
+
@attrib[:id] = value
|
109
|
+
end
|
110
|
+
# Alias definition for #dom_id()
|
111
|
+
def id
|
112
|
+
@attrib[:id]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Do not redirect random access operators.
|
116
|
+
def [](a)
|
117
|
+
raise ::Exception.new('Undefined method [] for ' << self.class.to_s)
|
118
|
+
end
|
119
|
+
# Do not redirect random access operators.
|
120
|
+
def []=(a,b)
|
121
|
+
raise ::Exception.new('Undefined method []= for ' << self.class.to_s)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Static helper definition for clearing
|
125
|
+
# CSS floats.
|
126
|
+
def clear_floating
|
127
|
+
'<div style="clear: both;" />'
|
128
|
+
end
|
129
|
+
|
130
|
+
# Render this element to a string.
|
131
|
+
def string
|
132
|
+
attrib_string = ''
|
133
|
+
@attrib.each_pair { |name,value|
|
134
|
+
if value.instance_of?(Array) then
|
135
|
+
value = value.join(' ')
|
136
|
+
elsif
|
137
|
+
value.instance_of?(TrueClass) then
|
138
|
+
value = name
|
139
|
+
end
|
140
|
+
if !value.nil? then
|
141
|
+
value = value.to_s
|
142
|
+
attrib_string << name.to_s + '="' << value + '" '
|
143
|
+
end
|
144
|
+
}
|
145
|
+
|
146
|
+
if content.to_s != '' then
|
147
|
+
'<' << @tag.to_s << ' ' << attrib_string << '>' << "\n" <<
|
148
|
+
content.to_s +
|
149
|
+
'</' << @tag.to_s << '>' << "\n"
|
150
|
+
else
|
151
|
+
'<' << @tag.to_s << ' ' << attrib_string << '/>' << "\n"
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
alias to_s string
|
156
|
+
|
157
|
+
end # class
|
158
|
+
|
159
|
+
end # module
|
160
|
+
end # module
|
161
|
+
|
@@ -0,0 +1,232 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/element')
|
3
|
+
require('aurita-gui/html')
|
4
|
+
require('aurita-gui/form/form_field')
|
5
|
+
require('aurita-gui/form/form_error')
|
6
|
+
require('aurita-gui/form/input_field')
|
7
|
+
require('aurita-gui/form/hidden_field')
|
8
|
+
require('aurita-gui/form/options_field')
|
9
|
+
require('aurita-gui/form/select_field')
|
10
|
+
require('aurita-gui/form/radio_field')
|
11
|
+
require('aurita-gui/form/checkbox_field')
|
12
|
+
require('aurita-gui/form/fieldset')
|
13
|
+
require('aurita-gui/form/textarea_field')
|
14
|
+
require('aurita-gui/form/date_field')
|
15
|
+
require('aurita-gui/form/datetime_field')
|
16
|
+
require('aurita-gui/form/file_field')
|
17
|
+
|
18
|
+
module Aurita
|
19
|
+
module GUI
|
20
|
+
|
21
|
+
|
22
|
+
class Form_Field_Wrapper < Aurita::GUI::Element
|
23
|
+
attr_accessor :field
|
24
|
+
|
25
|
+
def initialize(field)
|
26
|
+
label_params = { :for => field.dom_id }
|
27
|
+
label_params[:id] = field.dom_id.to_s + '_label'
|
28
|
+
@content = [ HTML.label(label_params) { field.label }, field ]
|
29
|
+
params = { :tag => :li,
|
30
|
+
:content => @content,
|
31
|
+
:id => field.dom_id + '_wrap',
|
32
|
+
:class => field.class.to_s.split('::')[-1].downcase + '_wrap form_field' }
|
33
|
+
super(params)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class Form < Element
|
39
|
+
|
40
|
+
attr_accessor :method, :target, :action, :fields, :elements, :element_map
|
41
|
+
|
42
|
+
# Usage examples:
|
43
|
+
#
|
44
|
+
# form = Form.new(:method => :put # default: :post
|
45
|
+
# :action => '/where/to/send/form/'
|
46
|
+
# :onsubmit => "alert('submitting');") {
|
47
|
+
# [
|
48
|
+
# Input_Field.new(:name => :description, :label => 'Description'),
|
49
|
+
# Select_Field.new(:name => :category, :label => 'Select category')
|
50
|
+
# ]
|
51
|
+
# }
|
52
|
+
# textarea = GUI::Textarea.new(:name => :comment, :label => 'Comment')
|
53
|
+
# form.add(textarea)
|
54
|
+
#
|
55
|
+
# In case you want to override the form action (default: /aurita/dispatch),
|
56
|
+
# use :action_url:
|
57
|
+
#
|
58
|
+
# Form.new(:action_url => '/where/to/send/form')
|
59
|
+
# or
|
60
|
+
# Form.action_url = '/where/to/send/form'
|
61
|
+
#
|
62
|
+
#
|
63
|
+
def initialize(params, &block)
|
64
|
+
@action = params[:action]
|
65
|
+
@method = params[:method]
|
66
|
+
@fields = params[:fields]
|
67
|
+
@values = params[:values]
|
68
|
+
@method ||= :post
|
69
|
+
@fields ||= []
|
70
|
+
@elements = []
|
71
|
+
@element_map = {}
|
72
|
+
@values ||= {}
|
73
|
+
@title = false
|
74
|
+
if block_given? then
|
75
|
+
yield.each { |e| add(e) }
|
76
|
+
end
|
77
|
+
params.delete(:fields)
|
78
|
+
params.delete(:values)
|
79
|
+
params[:tag] = 'form'
|
80
|
+
params[:content] = content()
|
81
|
+
super(params)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns field element map.
|
85
|
+
# An element map maps field names to elements of
|
86
|
+
# this form.
|
87
|
+
def attributes
|
88
|
+
@element_map
|
89
|
+
end
|
90
|
+
|
91
|
+
# Access form element by index or name (by index if
|
92
|
+
# parameter is of type Numeric, by name otherwhise)
|
93
|
+
def [](index)
|
94
|
+
return @elements[index] if index.kind_of? Numeric
|
95
|
+
return @element_map[index.to_s]
|
96
|
+
end
|
97
|
+
|
98
|
+
# Assign / overwrite field element with index form_index.
|
99
|
+
def []=(index, form_field)
|
100
|
+
@elements[index] = form_field
|
101
|
+
@content = false # Invalidate
|
102
|
+
end
|
103
|
+
|
104
|
+
# Delete form field with name field_name from
|
105
|
+
# this form.
|
106
|
+
def delete(field_name)
|
107
|
+
@element_map.delete(field_name.to_s)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Iterate over form field elements.
|
111
|
+
# This would add a CSS class to all elements without
|
112
|
+
# a value:
|
113
|
+
#
|
114
|
+
# form.each { |element|
|
115
|
+
# element.class = 'missing' unless element.value
|
116
|
+
# }
|
117
|
+
#
|
118
|
+
def each(&block)
|
119
|
+
@elements.each(&block)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Add form field element to this form.
|
123
|
+
def add(form_field_element)
|
124
|
+
if !form_field_element.dom_id then
|
125
|
+
form_field_element.dom_id = form_field_element.name.to_s.gsub('.','_')
|
126
|
+
end
|
127
|
+
@element_map[form_field_element.name.to_s] = form_field_element
|
128
|
+
@elements << form_field_element
|
129
|
+
@content = false # Invalidate
|
130
|
+
end
|
131
|
+
|
132
|
+
# Set field configuration. Form fields will be
|
133
|
+
# rendered in the same order as field names in the
|
134
|
+
# parameter array.
|
135
|
+
# In case an element's field name is not included
|
136
|
+
# in the array, it will not be rendered.
|
137
|
+
# Example:
|
138
|
+
#
|
139
|
+
# form.fields = [ :name, :description, :date ]
|
140
|
+
#
|
141
|
+
def fields=(attrib_array)
|
142
|
+
@fields = attrib_array.flatten.collect { |fieldname| fieldname.to_s }
|
143
|
+
@elements.each { |field|
|
144
|
+
@element_map[field.name.to_s] = field
|
145
|
+
}
|
146
|
+
end
|
147
|
+
alias set_field_config fields=
|
148
|
+
|
149
|
+
# Set field values for this form.
|
150
|
+
# Expects hash mapping field names to values.
|
151
|
+
# Example:
|
152
|
+
#
|
153
|
+
# form.values = { :name => 'Foo', :description => 'Bar', :date => '20081012' }
|
154
|
+
#
|
155
|
+
def values=(value_hash={})
|
156
|
+
@values = value_hash
|
157
|
+
end
|
158
|
+
alias set_values values=
|
159
|
+
|
160
|
+
# Set all elements to readonly rendering mode.
|
161
|
+
def readonly!
|
162
|
+
@elements.each { |e|
|
163
|
+
e.readonly!
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
# Return array of field names currently
|
168
|
+
# available for rendering.
|
169
|
+
def fields()
|
170
|
+
if !@fields || @fields.length == 0 then
|
171
|
+
@elements.each { |field|
|
172
|
+
@fields << field.name.to_s
|
173
|
+
@element_map[field.name.to_s] = field
|
174
|
+
}
|
175
|
+
end
|
176
|
+
return @fields
|
177
|
+
end
|
178
|
+
|
179
|
+
# Return underlying HTML element instance (HTML.ul),
|
180
|
+
# without wrapping HTML.form element.
|
181
|
+
def content
|
182
|
+
# TODO: Provide Fieldset instances
|
183
|
+
@content = []
|
184
|
+
if @title then
|
185
|
+
@content << HTML.h1(:class => :form_title) { @title }
|
186
|
+
end
|
187
|
+
fields().each { |field|
|
188
|
+
element = @element_map[field.to_s]
|
189
|
+
if element then
|
190
|
+
value = @values[element.name.to_s]
|
191
|
+
value ||= @values[element.name.to_s.intern]
|
192
|
+
element.value = value if value
|
193
|
+
if element.kind_of? Aurita::GUI::Hidden_Field then
|
194
|
+
@content << element
|
195
|
+
else
|
196
|
+
@content << Form_Field_Wrapper.new(element)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
}
|
200
|
+
@content = HTML.ul(:class => :form_fields) { @content }
|
201
|
+
return @content
|
202
|
+
end
|
203
|
+
|
204
|
+
# Render this form to an HTML.form instance.
|
205
|
+
# Wraps result of #content.
|
206
|
+
def element
|
207
|
+
HTML.form(@params, :content => @content)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Render this form to a string
|
211
|
+
def string
|
212
|
+
element().to_s
|
213
|
+
end
|
214
|
+
alias to_s string
|
215
|
+
|
216
|
+
# Set all form elements to readonly mode.
|
217
|
+
def readonly!
|
218
|
+
elements.each { |e|
|
219
|
+
e.readonly!
|
220
|
+
}
|
221
|
+
end
|
222
|
+
# Set all form elements to editable mode.
|
223
|
+
def editable!
|
224
|
+
elements.each { |e|
|
225
|
+
e.editable!
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
end
|