nitro 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +350 -0
- data/INSTALL +2 -2
- data/ProjectInfo +61 -0
- data/README +5 -4
- data/Rakefile +5 -4
- data/bin/nitrogen +3 -1
- data/doc/AUTHORS +27 -3
- data/doc/RELEASES +193 -0
- data/doc/lhttpd.txt +4 -0
- data/lib/nitro.rb +1 -1
- data/lib/nitro/adapter/cgi.rb +6 -321
- data/lib/nitro/adapter/fastcgi.rb +2 -14
- data/lib/nitro/adapter/scgi.rb +237 -71
- data/lib/nitro/adapter/webrick.rb +25 -7
- data/lib/nitro/caching.rb +1 -0
- data/lib/nitro/cgi.rb +296 -0
- data/lib/nitro/{cookie.rb → cgi/cookie.rb} +0 -0
- data/lib/nitro/cgi/http.rb +62 -0
- data/lib/nitro/{request.rb → cgi/request.rb} +4 -1
- data/lib/nitro/{response.rb → cgi/response.rb} +0 -0
- data/lib/nitro/cgi/stream.rb +43 -0
- data/lib/nitro/cgi/utils.rb +38 -0
- data/lib/nitro/compiler.rb +23 -11
- data/lib/nitro/compiler/css.rb +8 -0
- data/lib/nitro/compiler/morphing.rb +66 -0
- data/lib/nitro/context.rb +21 -30
- data/lib/nitro/controller.rb +23 -100
- data/lib/nitro/dispatcher.rb +18 -8
- data/lib/nitro/element.rb +6 -2
- data/lib/nitro/flash.rb +2 -2
- data/lib/nitro/mixin/buffer.rb +2 -2
- data/lib/nitro/mixin/form.rb +204 -93
- data/lib/nitro/mixin/javascript.rb +170 -11
- data/lib/nitro/mixin/markup.rb +1 -0
- data/lib/nitro/mixin/pager.rb +7 -4
- data/lib/nitro/mixin/rss.rb +2 -0
- data/lib/nitro/mixin/table.rb +23 -6
- data/lib/nitro/mixin/xhtml.rb +2 -2
- data/lib/nitro/render.rb +19 -5
- data/lib/nitro/scaffold.rb +12 -6
- data/lib/nitro/server.rb +4 -6
- data/lib/nitro/server/runner.rb +2 -2
- data/lib/nitro/session.rb +8 -1
- data/lib/nitro/session/file.rb +40 -0
- data/lib/part/admin.rb +2 -0
- data/lib/part/admin/controller.rb +7 -3
- data/lib/part/admin/skin.rb +8 -1
- data/lib/part/admin/template/index.xhtml +39 -1
- data/proto/public/error.xhtml +5 -3
- data/proto/public/js/behaviour.js +254 -254
- data/proto/public/js/controls.js +427 -165
- data/proto/public/js/dragdrop.js +255 -276
- data/proto/public/js/effects.js +476 -277
- data/proto/public/js/prototype.js +561 -127
- data/proto/public/js/scaffold.js +74 -0
- data/proto/public/js/scriptaculous.js +44 -0
- data/proto/public/js/util.js +548 -0
- data/proto/public/scaffold/list.xhtml +4 -1
- data/proto/scgi.rb +333 -0
- data/script/scgi_ctl +221 -0
- data/script/scgi_service +120 -0
- data/test/nitro/adapter/raw_post1.bin +0 -0
- data/test/nitro/{tc_cookie.rb → cgi/tc_cookie.rb} +1 -1
- data/test/nitro/{tc_request.rb → cgi/tc_request.rb} +1 -1
- data/test/nitro/mixin/tc_xhtml.rb +1 -1
- data/test/nitro/{adapter/tc_cgi.rb → tc_cgi.rb} +12 -12
- data/test/nitro/tc_controller.rb +9 -5
- metadata +159 -169
- data/benchmark/bench.rb +0 -5
- data/benchmark/simple-webrick-n-200.txt +0 -44
- data/benchmark/static-webrick-n-200.txt +0 -43
- data/benchmark/tiny-lhttpd-n-200-c-5.txt +0 -43
- data/benchmark/tiny-webrick-n-200-c-5.txt +0 -44
- data/benchmark/tiny-webrick-n-200.txt +0 -44
- data/benchmark/tiny2-webrick-n-200.txt +0 -44
- data/examples/README +0 -7
data/lib/nitro/dispatcher.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'nano/
|
1
|
+
require 'nano/kernel/singleton'
|
2
2
|
|
3
3
|
require 'nitro/controller'
|
4
4
|
require 'nitro/routing'
|
@@ -51,7 +51,7 @@ class Dispatcher
|
|
51
51
|
if controllers and controllers.is_a?(Class) and controllers.ancestors.include?(Controller)
|
52
52
|
controllers = { '/' => controllers }
|
53
53
|
else
|
54
|
-
controllers ||= { '/' =>
|
54
|
+
controllers ||= { '/' => Controller }
|
55
55
|
end
|
56
56
|
|
57
57
|
mount(controllers)
|
@@ -90,13 +90,17 @@ class Dispatcher
|
|
90
90
|
# Perform mount-time initialization of the controller.
|
91
91
|
|
92
92
|
if c.respond_to? :mounted
|
93
|
-
c.mounted
|
93
|
+
c.mounted(path)
|
94
94
|
end
|
95
95
|
|
96
96
|
# Try to setup a template_root if none is defined:
|
97
97
|
|
98
98
|
unless c.template_root
|
99
|
-
c.
|
99
|
+
c.module_eval %{
|
100
|
+
def self.template_root
|
101
|
+
"#{Template.root}#{path}".gsub(/\\/$/, '')
|
102
|
+
end
|
103
|
+
}
|
100
104
|
end
|
101
105
|
end
|
102
106
|
|
@@ -130,11 +134,17 @@ class Dispatcher
|
|
130
134
|
|
131
135
|
def update_routes
|
132
136
|
@routes = []
|
137
|
+
|
133
138
|
@controllers.each do |base, c|
|
134
139
|
base = '' if base == '/'
|
135
|
-
|
136
|
-
if route =
|
137
|
-
|
140
|
+
for m in c.action_methods
|
141
|
+
if route = c.ann(:m).route and (!route.nil?)
|
142
|
+
unless c.ann(:m).params.nil?
|
143
|
+
keys = c.ann(:m).params.keys
|
144
|
+
else
|
145
|
+
keys = []
|
146
|
+
end
|
147
|
+
@routes << [route, "#{base}/#{action}", *keys]
|
138
148
|
end
|
139
149
|
end
|
140
150
|
end
|
@@ -167,7 +177,7 @@ class Dispatcher
|
|
167
177
|
klass = @controllers[key]
|
168
178
|
|
169
179
|
if klass and Compiler.reload
|
170
|
-
klass.instance_methods.grep(/(
|
180
|
+
klass.instance_methods.grep(/(_action$)|(_template$)/).each do |m|
|
171
181
|
klass.send(:remove_method, m) rescue nil
|
172
182
|
end
|
173
183
|
end
|
data/lib/nitro/element.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rexml/document'
|
2
2
|
require 'rexml/streamlistener'
|
3
3
|
|
4
|
-
require 'nano/string/capitalized
|
4
|
+
require 'nano/string/capitalized'
|
5
5
|
require 'nano/string/camelize'
|
6
6
|
|
7
7
|
require 'glue/configuration'
|
@@ -73,6 +73,8 @@ class Element
|
|
73
73
|
child._parent = self
|
74
74
|
@_children << child
|
75
75
|
end
|
76
|
+
|
77
|
+
alias_method :children, :_children
|
76
78
|
end
|
77
79
|
|
78
80
|
# Processes a page containing elements.
|
@@ -161,7 +163,9 @@ class ElementProcessor # :nodoc: all
|
|
161
163
|
def transform(source)
|
162
164
|
listener = Listener.new
|
163
165
|
REXML::Document.parse_stream(source, listener)
|
164
|
-
# gmosx, FIXME: optimize this, how?
|
166
|
+
# gmosx, FIXME: optimize this, how?
|
167
|
+
# gmosx, FIXME: this is a hack fix, improve.
|
168
|
+
listener.buffer.gsub! /<textarea ([^>]*)><\/textarea>/, '<textarea \1>#{}</textarea>'
|
165
169
|
listener.buffer.gsub! /<(.*) ([^>]*)><\/\1>/, '<\1 \2 />'
|
166
170
|
listener.buffer.gsub! /<(.*)><\/\1>/, '<\1 />'
|
167
171
|
return listener.buffer
|
data/lib/nitro/flash.rb
CHANGED
data/lib/nitro/mixin/buffer.rb
CHANGED
data/lib/nitro/mixin/form.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'nano/inflect'
|
2
2
|
|
3
|
+
require 'nitro/mixin/xhtml'
|
4
|
+
require 'og/relation/all'
|
5
|
+
|
3
6
|
module Nitro
|
4
7
|
|
5
8
|
# A collection of useful helpers for creating and manipulating
|
@@ -12,13 +15,22 @@ module Nitro
|
|
12
15
|
module FormMixin
|
13
16
|
|
14
17
|
def self.included(base)
|
18
|
+
super
|
15
19
|
base.send :include, XhtmlMixin
|
16
20
|
end
|
17
21
|
|
18
22
|
private
|
19
23
|
|
24
|
+
# Propagate the given parameter by using a form hidden field. The
|
25
|
+
# parameter value is tus passed to the next request.
|
26
|
+
|
27
|
+
def propagate_param(param)
|
28
|
+
%|<input type="hidden" name="#{param}" value="#{request[param.to_s]}" />|
|
29
|
+
end
|
30
|
+
alias_method :keep_param, :propagate_param
|
31
|
+
|
20
32
|
# Render a standard form for the given Object. The object
|
21
|
-
# should include attribute
|
33
|
+
# should include attribute annotations.
|
22
34
|
#--
|
23
35
|
# TODO: get info, for example localization mode from session,
|
24
36
|
# if this module is mixed in a Render.
|
@@ -28,25 +40,37 @@ private
|
|
28
40
|
method = options.fetch(:method, 'post')
|
29
41
|
action = options.fetch(:action, "save_#{obj.class.name.underscore}")
|
30
42
|
submit = options.fetch(:submit, 'Save')
|
31
|
-
|
43
|
+
cancel = options.fetch(:cancel, "#@base/#{Scaffolding.class_to_list(obj.class)}")
|
44
|
+
|
45
|
+
if enctype = options.fetch(:enctype, nil)
|
46
|
+
enctype_attribute = " enctype=\"#{enctype}\""
|
47
|
+
else
|
48
|
+
enctype_attribute = ''
|
49
|
+
for pr in obj.class.properties.values
|
50
|
+
if pr.klass.ancestors.include? Og::Blob
|
51
|
+
enctype_attribute = ' enctype="multipart/form-data"'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
32
56
|
action = "#{@base}/#{action}" unless action =~ /\//
|
33
57
|
|
34
58
|
str = %{<form action="#{action}" method="post">}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
str << %{
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
</form>
|
44
|
-
|
59
|
+
|
60
|
+
str = ''
|
61
|
+
|
62
|
+
str << %{<form action="#{action}" method="post"#{enctype_attribute}>}
|
63
|
+
str << %{<input type="hidden" name="oid" value="#{obj.oid}" />} if obj.oid
|
64
|
+
str << tags_for(obj, options)
|
65
|
+
str << %{<input type="submit" value="#{submit}" />}
|
66
|
+
str << %{ or <a href="#{cancel}">Cancel</a>} if cancel
|
67
|
+
str << %{</form>}
|
68
|
+
|
45
69
|
return str
|
46
70
|
end
|
47
71
|
|
48
72
|
# Render a standard form tags for the given Object. The object
|
49
|
-
# should include attribute
|
73
|
+
# should include attribute annotations.
|
50
74
|
#
|
51
75
|
# If show_all is false then apply field filtering.
|
52
76
|
#
|
@@ -65,113 +89,200 @@ private
|
|
65
89
|
def tags_for(obj, options = {})
|
66
90
|
str = prologue()
|
67
91
|
|
68
|
-
for p in obj.class.properties
|
69
|
-
|
92
|
+
for p in obj.class.properties.values
|
93
|
+
unless options[:all]
|
94
|
+
next if :oid == p.symbol or p.editor == :none #TODO check for real key
|
95
|
+
end
|
96
|
+
|
70
97
|
ancestors = p.klass.ancestors
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
98
|
+
|
99
|
+
tag = if p.editor and obj.respond_to?(p.editor.to_sym)
|
100
|
+
obj.send(p.editor.to_sym, p, options) #farms: send to custom _instance_ method
|
101
|
+
elsif ancestors.include? Numeric and !p.relation
|
102
|
+
field_tag(obj, p, options)
|
103
|
+
elsif ancestors.include? String
|
104
|
+
if p.editor == :textarea
|
105
|
+
textarea_tag(obj, p, options)
|
78
106
|
else
|
79
|
-
|
107
|
+
field_tag(obj, p, options)
|
80
108
|
end
|
81
|
-
elsif ancestors.include?
|
82
|
-
|
83
|
-
elsif ancestors.include?
|
84
|
-
|
109
|
+
elsif ancestors.include? TrueClass
|
110
|
+
checkbox_tag(obj, p, options)
|
111
|
+
elsif ancestors.include? Date
|
112
|
+
date_tag(obj, p, options)
|
113
|
+
elsif ancestors.include? Time
|
114
|
+
datetime_tag(obj, p, options)
|
115
|
+
elsif ancestors.include? Og::Blob
|
116
|
+
file_tag(obj, p, options)
|
117
|
+
elsif ancestors.include? Hash
|
118
|
+
hash_tag(obj, p, options)
|
119
|
+
else
|
120
|
+
nil #no tag
|
121
|
+
end
|
122
|
+
|
123
|
+
unless tag.nil?
|
124
|
+
#farms: TODO. way to override the general 'element' and disable per prop
|
125
|
+
str << element(p.symbol, tag)
|
85
126
|
end
|
86
127
|
end
|
87
128
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
129
|
+
if obj.class.relations and not options[:skip_relations]
|
130
|
+
for rel in obj.class.relations
|
131
|
+
next if rel.options[:editor] == :none unless options[:all]
|
132
|
+
|
133
|
+
tag = if rel.options[:editor] && obj.respond_to?(rel.options[:editor].to_sym)
|
134
|
+
obj.send(rel.options[:editor].to_sym, rel, options) #farms: allow custom relation editors
|
135
|
+
elsif rel.kind_of? Og::RefersTo
|
136
|
+
refers_to_control(obj, rel, options)
|
137
|
+
elsif rel.kind_of? Og::JoinsMany or rel.kind_of? Og::HasMany
|
138
|
+
if rel.options[:editor] == :twin_select or rel.options[:editor] == :twin
|
139
|
+
many_select_control(obj, rel, options)
|
140
|
+
else
|
141
|
+
many_list_control(obj, rel, options)
|
142
|
+
end
|
143
|
+
else
|
144
|
+
nil #no tag
|
145
|
+
end
|
146
|
+
|
147
|
+
unless tag.nil?
|
148
|
+
#farms: TODO. way to override the general 'element' and disable per rel
|
149
|
+
str << element(rel.name, tag)
|
150
|
+
end
|
94
151
|
end
|
95
152
|
end
|
96
|
-
|
153
|
+
|
97
154
|
str << epilogue()
|
98
155
|
|
99
156
|
return str
|
100
157
|
end
|
101
158
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
#{options(:labels => labels, :values => values, :selected => 1)}
|
111
|
-
</select>
|
112
|
-
}
|
113
|
-
)
|
114
|
-
end
|
115
|
-
|
116
|
-
def has_many_tag(obj, rel, options)
|
117
|
-
entities = obj.send(rel.target_plural_name) if obj.saved?
|
118
|
-
unless entities.empty?
|
119
|
-
str = entities.inject('') do |acc, e|
|
120
|
-
acc << "<tr><td>#{e.to_edit_link(@base)}</td></tr>"
|
121
|
-
end
|
122
|
-
str = "<table>#{str}</table>"
|
123
|
-
else
|
124
|
-
str = 'No entities found.<br /><br />'
|
159
|
+
def hash_tag(obj, p, options)
|
160
|
+
str = %{
|
161
|
+
<input type="text" id="#{p.symbol}_key" /> => <input type="text" id="#{p.symbol}_value" />
|
162
|
+
<input id="#{p.symbol}" class="naction_add_hash" type="button" value=" + " />
|
163
|
+
<ul id="#{p.symbol}_list">
|
164
|
+
}
|
165
|
+
obj.send(p.symbol).each do |k,v|
|
166
|
+
str << hash_tag_item(p.symbol, k, v)
|
125
167
|
end
|
126
|
-
|
127
|
-
label(rel.name) + ' <a href="#">Add</a>',
|
128
|
-
%{
|
129
|
-
#{str}
|
130
|
-
}
|
131
|
-
)
|
168
|
+
str << %{</ul>}
|
132
169
|
end
|
133
|
-
|
134
|
-
def
|
170
|
+
|
171
|
+
def hash_tag_item(name, key='', value='')
|
135
172
|
%{
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
173
|
+
<li>
|
174
|
+
<input type="text" value="#{key}" disabled="disabled" class="hash_item_key" /> => <input type="text" name="#{name}[#{key}]" id="#{name}_value" value="#{value}" class="hash_item_value" />
|
175
|
+
<span class="remove"><a href="#" class="naction_remove_hash" id="#{name}_remove">remove</a></span>
|
176
|
+
</li>
|
140
177
|
}
|
141
178
|
end
|
179
|
+
public :hash_tag_item # Allow ajax access
|
142
180
|
|
181
|
+
def file_tag(obj, p, options)
|
182
|
+
%{<input type="file" id="#{p.symbol}" name="#{p.symbol}" style="width: 250px" />}
|
183
|
+
end
|
184
|
+
|
185
|
+
def field_tag(obj, p, options)
|
186
|
+
%{<input type="text" id="#{p.symbol}" name="#{p.symbol}" value="#{obj.send(p.symbol)}" style="width: 250px" /> }
|
187
|
+
end
|
188
|
+
|
143
189
|
def textarea_tag(obj, p, options)
|
144
|
-
%{
|
145
|
-
<dt>#{label(p.symbol)}</dt>
|
146
|
-
<dd>
|
147
|
-
<textarea id="#{p.symbol}" name="#{p.symbol}">#{obj.send(p.symbol)}</textarea>
|
148
|
-
</dd>
|
149
|
-
}
|
190
|
+
%{<textarea id="#{p.symbol}" name="#{p.symbol}">#{obj.send(p.symbol)}</textarea> }
|
150
191
|
end
|
151
192
|
|
152
193
|
def checkbox_tag(obj, p, options)
|
153
|
-
|
154
|
-
|
155
|
-
<input type="checkbox" id="#{p.symbol}" name="#{p.symbol}" />
|
156
|
-
#{label(p.symbol)}
|
157
|
-
</dt>
|
158
|
-
<dd>#{}</dd>
|
159
|
-
}
|
194
|
+
checked_flag = obj.send(p.symbol) ? 'checked="checked" ' : ''
|
195
|
+
%{<input type="checkbox" id="#{p.symbol}" name="#{p.symbol}" #{checked_flag}/> }
|
160
196
|
end
|
161
|
-
|
197
|
+
|
198
|
+
def date_tag(obj, p, options)
|
199
|
+
date_select(obj.send(p.symbol), :name => p.symbol.to_s)
|
200
|
+
end
|
201
|
+
|
162
202
|
def datetime_tag(obj, p, options)
|
163
|
-
|
164
|
-
label(p.symbol),
|
165
|
-
datetime_select(obj.send(p.symbol), :name => p.symbol.to_s)
|
166
|
-
)
|
203
|
+
datetime_select(obj.send(p.symbol), :name => p.symbol.to_s)
|
167
204
|
end
|
168
205
|
|
169
206
|
def label(sym)
|
170
|
-
|
207
|
+
%{<label for="#{sym}">#{sym.to_s.humanize}</label>}
|
171
208
|
end
|
172
209
|
|
173
210
|
# :section: Relations.
|
174
211
|
|
212
|
+
def refers_to_control(obj, rel, options)
|
213
|
+
entities = rel.target_class.all
|
214
|
+
selected = obj.send(rel.name)
|
215
|
+
selected = selected.pk if selected
|
216
|
+
unless entities.empty?
|
217
|
+
str = %{<select id="#{rel.name}" name="#{rel.name}">}
|
218
|
+
str << %{<option value="null">None</option>} if rel.options[:allow_none]
|
219
|
+
str << %{#{options(:labels => entities.map{|e| e.to_s}, :values => entities.map{|e| e.oid}, :selected => selected)}</select>}
|
220
|
+
else
|
221
|
+
'No entities found.<br /><br />'
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def many_list_control(obj, rel, options)
|
226
|
+
entities = rel.target_class.all
|
227
|
+
|
228
|
+
unless entities.empty?
|
229
|
+
selected_entities = obj.send(rel.name)
|
230
|
+
selector_entities = entities.delete_if {|e| obj.saved? && selected_entities.include?(e)}
|
231
|
+
|
232
|
+
str = %{
|
233
|
+
<select id="#{rel.name}_selector">
|
234
|
+
#{options(:labels => selector_entities.map{|e| e.to_s}, :values => selector_entities.map{|e| e.oid})}
|
235
|
+
</select>
|
236
|
+
<input id="#{rel.name}" type="button" value=" + " class="naction_add_rel" />
|
237
|
+
<ul class="relation_list" id="#{rel.name}_list">
|
238
|
+
}
|
239
|
+
selected_entities.each do |e|
|
240
|
+
str << relation_item(rel.name, e.to_s, e.oid)
|
241
|
+
end
|
242
|
+
str << %{</ul>}
|
243
|
+
else
|
244
|
+
'No entities found.<br /><br />'
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def relation_item(name, display, oid)
|
249
|
+
%{
|
250
|
+
<li>
|
251
|
+
<input type="hidden" name="#{name}[]" value="#{oid}" />
|
252
|
+
<span class="display">#{display}</span>
|
253
|
+
<span class="remove"><a href="#" id="#{name}_remove" class="naction_remove_rel">remove</a></span>
|
254
|
+
</li>
|
255
|
+
}
|
256
|
+
end
|
257
|
+
public :relation_item # Allow ajax access.
|
258
|
+
|
259
|
+
def many_select_control(obj, rel, options)
|
260
|
+
entities = rel.target_class.all
|
261
|
+
|
262
|
+
unless entities.empty?
|
263
|
+
selected_entities = obj.send(rel.name)
|
264
|
+
selector_entities = entities.delete_if {|e| obj.saved? && selected_entities.include?(e)}
|
265
|
+
str = %{
|
266
|
+
<div id="#{rel.name}" class="has_many_control">
|
267
|
+
<select id="#{rel.name}_selector" multiple="multiple">
|
268
|
+
#{options(:labels => selector_entities.map{|e| e.to_s}, :values => selector_entities.map{|e| e.oid})}
|
269
|
+
</select>
|
270
|
+
|
271
|
+
<a href="javascript:multiSelectorMove('#{rel.name}','add');">add >></a>
|
272
|
+
<a href="javascript:multiSelectorMove('#{rel.name}','remove');"><< remove</a>
|
273
|
+
|
274
|
+
<select id="#{rel.name}_selected" multiple="multiple">
|
275
|
+
#{options(:labels => selected_entities.map{|e| e.to_s}, :values => selected_entities.map{|e| e.oid})}
|
276
|
+
</select>
|
277
|
+
}
|
278
|
+
selected_entities.each do |e|
|
279
|
+
str << %{<input type="hidden" name="#{rel.name}[]" id="#{rel.name}_#{e.oid}" value="#{e.oid}" />}
|
280
|
+
end
|
281
|
+
str << %{</div>}
|
282
|
+
else
|
283
|
+
'No entities found.<br /><br />'
|
284
|
+
end
|
285
|
+
end
|
175
286
|
|
176
287
|
# :section: General formating methods. Override to customize.
|
177
288
|
|
@@ -189,12 +300,10 @@ private
|
|
189
300
|
|
190
301
|
# Emit a form element.
|
191
302
|
|
192
|
-
def element(
|
303
|
+
def element(name, tag)
|
193
304
|
%{
|
194
|
-
|
195
|
-
|
196
|
-
#{element}
|
197
|
-
</dd>
|
305
|
+
<dt class="#{name}">#{label(name)}</dt>
|
306
|
+
<dd class="#{name}">#{tag}</dd>
|
198
307
|
}
|
199
308
|
end
|
200
309
|
end
|
@@ -202,3 +311,5 @@ end
|
|
202
311
|
end
|
203
312
|
|
204
313
|
# * George Moschovitis <gm@navel.gr>
|
314
|
+
# * Chris Farmiloe <chris.farmiloe@farmiloe.com>
|
315
|
+
# * Rob Pitt <rob@motionpath.co.uk>
|