hobo 0.5.3 → 0.6
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/bin/hobo +18 -4
- data/hobo_files/plugin/CHANGES.txt +511 -0
- data/hobo_files/plugin/README +8 -3
- data/hobo_files/plugin/Rakefile +81 -0
- data/hobo_files/plugin/generators/hobo/hobo_generator.rb +4 -4
- data/hobo_files/plugin/generators/hobo/templates/guest.rb +1 -1
- data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +1 -1
- data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +16 -22
- data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +4 -6
- data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +6 -5
- data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +4 -6
- data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +237 -0
- data/hobo_files/plugin/generators/hobo_migration/templates/migration.rb +9 -0
- data/hobo_files/plugin/generators/hobo_model/USAGE +2 -3
- data/hobo_files/plugin/generators/hobo_model/hobo_model_generator.rb +1 -14
- data/hobo_files/plugin/generators/hobo_model/templates/fixtures.yml +1 -6
- data/hobo_files/plugin/generators/hobo_model/templates/model.rb +10 -4
- data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +7 -6
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_base.css +68 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.css +93 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +11 -6
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/plus.png +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +24 -14
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +28 -44
- data/hobo_files/plugin/generators/hobo_user_model/USAGE +2 -12
- data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +1 -14
- data/hobo_files/plugin/generators/hobo_user_model/templates/fixtures.yml +0 -6
- data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +8 -1
- data/hobo_files/plugin/init.rb +6 -2
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +23 -12
- data/hobo_files/plugin/lib/extensions.rb +134 -40
- data/hobo_files/plugin/lib/extensions/test_case.rb +0 -1
- data/hobo_files/plugin/lib/hobo.rb +77 -46
- data/hobo_files/plugin/lib/hobo/authenticated_user.rb +24 -2
- data/hobo_files/plugin/lib/hobo/authentication_support.rb +2 -1
- data/hobo_files/plugin/lib/hobo/controller.rb +35 -12
- data/hobo_files/plugin/lib/hobo/define_tags.rb +4 -4
- data/hobo_files/plugin/lib/hobo/dryml.rb +33 -51
- data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +47 -34
- data/hobo_files/plugin/lib/hobo/dryml/scoped_variables.rb +37 -0
- data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +27 -5
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +545 -302
- data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +305 -135
- data/hobo_files/plugin/lib/hobo/email_address.rb +5 -0
- data/hobo_files/plugin/lib/hobo/field_spec.rb +66 -0
- data/hobo_files/plugin/lib/hobo/hobo_helper.rb +325 -0
- data/hobo_files/plugin/lib/hobo/html_string.rb +2 -0
- data/hobo_files/plugin/lib/hobo/lazy_hash.rb +13 -1
- data/hobo_files/plugin/lib/hobo/markdown_string.rb +3 -1
- data/hobo_files/plugin/lib/hobo/model.rb +185 -66
- data/hobo_files/plugin/lib/hobo/model_controller.rb +56 -49
- data/hobo_files/plugin/lib/hobo/password_string.rb +2 -0
- data/hobo_files/plugin/lib/hobo/plugins.rb +75 -0
- data/hobo_files/plugin/lib/hobo/rapid_helper.rb +98 -0
- data/hobo_files/plugin/lib/hobo/static_tags +0 -3
- data/hobo_files/plugin/lib/hobo/textile_string.rb +11 -1
- data/hobo_files/plugin/lib/hobo/undefined.rb +1 -1
- data/hobo_files/plugin/lib/rexml.rb +166 -75
- data/hobo_files/plugin/spec/fixtures/users.yml +9 -0
- data/hobo_files/plugin/spec/spec.opts +6 -0
- data/hobo_files/plugin/spec/spec_helper.rb +28 -0
- data/hobo_files/plugin/spec/unit/hobo/dryml/template_spec.rb +650 -0
- data/hobo_files/plugin/tags/core.dryml +58 -4
- data/hobo_files/plugin/tags/rapid.dryml +289 -135
- data/hobo_files/plugin/tags/rapid_document_tags.dryml +49 -0
- data/hobo_files/plugin/tags/rapid_editing.dryml +92 -69
- data/hobo_files/plugin/tags/rapid_forms.dryml +242 -0
- data/hobo_files/plugin/tags/rapid_navigation.dryml +65 -65
- data/hobo_files/plugin/tags/rapid_pages.dryml +197 -124
- data/hobo_files/plugin/tags/rapid_support.dryml +23 -0
- metadata +29 -22
- data/hobo_files/plugin/generators/hobo_model/templates/migration.rb +0 -13
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/default_mapping.rb +0 -11
- data/hobo_files/plugin/generators/hobo_user_model/templates/migration.rb +0 -15
- data/hobo_files/plugin/lib/hobo/HtmlString +0 -3
- data/hobo_files/plugin/lib/hobo/controller_helpers.rb +0 -135
- data/hobo_files/plugin/lib/hobo/core.rb +0 -475
- data/hobo_files/plugin/lib/hobo/rapid.rb +0 -447
- data/hobo_files/plugin/test/hobo_dryml_template_test.rb +0 -7
- data/hobo_files/plugin/test/hobo_test.rb +0 -7
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<def tag="field_list"><table class="field_list"><tagbody/></table></def>
|
|
2
|
+
|
|
3
|
+
<def tag="field_list_item"><tr merge_attrs><tagbody/></tr></def>
|
|
4
|
+
|
|
5
|
+
<def tag="item_label"><th merge_attrs><tagbody/></th></def>
|
|
6
|
+
|
|
7
|
+
<def tag="item_value"><td merge_attrs><tagbody/></td></def>
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
<def tag="heading">
|
|
11
|
+
<%= content_tag "h#{scope.heading_level || '1'}", tagbody.call, attributes %>
|
|
12
|
+
</def>
|
|
13
|
+
|
|
14
|
+
<def tag="nav">
|
|
15
|
+
<div class="nav" merge_attrs><tagbody/></div>
|
|
16
|
+
</def>
|
|
17
|
+
|
|
18
|
+
<!-- section represents a generic document or application section. -->
|
|
19
|
+
<def tag="section">
|
|
20
|
+
<set body="&tagbody ? tagbody.call : ''"/>
|
|
21
|
+
<div class="section" merge_attrs if="&body"><tagbody/></div>
|
|
22
|
+
</def>
|
|
23
|
+
|
|
24
|
+
<def tag="aside">
|
|
25
|
+
<set body="&tagbody ? tagbody.call : ''"/>
|
|
26
|
+
<div class="aside" merge_attrs if="&body"><tagbody/></div>
|
|
27
|
+
</def>
|
|
28
|
+
|
|
29
|
+
<def tag="header">
|
|
30
|
+
<set body="&tagbody ? tagbody.call : ''"/>
|
|
31
|
+
<div class="header" merge_attrs if="&body"><tagbody/></div>
|
|
32
|
+
</def>
|
|
33
|
+
|
|
34
|
+
<def tag="footer">
|
|
35
|
+
<set body="&tagbody ? tagbody.call : ''"/>
|
|
36
|
+
<div class="footer" merge_attrs if="&body"><tagbody/></div>
|
|
37
|
+
</def>
|
|
38
|
+
|
|
39
|
+
<!-- article represents an independent piece of content of a -->
|
|
40
|
+
<!-- document, such as a blog entry or newspaper article. -->
|
|
41
|
+
<def tag="article">
|
|
42
|
+
<set body="&tagbody ? tagbody.call : ''"/>
|
|
43
|
+
<div class="article" merge_attrs if="&body"><tagbody/></div>
|
|
44
|
+
</def>
|
|
45
|
+
|
|
46
|
+
<!-- temporary tag -->
|
|
47
|
+
<def tag="panel">
|
|
48
|
+
<div class="panel" merge_attrs><tagbody/></div>
|
|
49
|
+
</def>
|
|
@@ -1,6 +1,52 @@
|
|
|
1
|
+
<def tag="editor"><%=
|
|
2
|
+
if !can_edit?
|
|
3
|
+
view(attributes)
|
|
4
|
+
elsif this_type.respond_to?(:macro)
|
|
5
|
+
if this_type.macro == :belongs_to
|
|
6
|
+
belongs_to_editor(attributes)
|
|
7
|
+
else
|
|
8
|
+
has_many_editor(attributes)
|
|
9
|
+
end
|
|
10
|
+
else
|
|
11
|
+
attrs = add_classes(attributes, "#{type_and_field}", "#{type_name}", "editor")
|
|
12
|
+
call_polymorphic_tag("editor", attrs) or
|
|
13
|
+
raise HoboError.new("<editor> not implemented for #{this.class.name}\##{this_field} " +
|
|
14
|
+
"(#{this.inspect}:#{this_type})")
|
|
15
|
+
end
|
|
16
|
+
%></def>
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
<def tag="has_many_editor">
|
|
20
|
+
<% #TODO: Implement %>
|
|
21
|
+
<a merge_attrs/>
|
|
22
|
+
</def>
|
|
23
|
+
|
|
24
|
+
<def tag="belongs_to_editor"><%= belongs_to_menu_editor(attributes) %></def>
|
|
25
|
+
|
|
26
|
+
<def tag="editor" for="string"><%= in_place_editor "in_place_textfield_bhv", attributes %></def>
|
|
27
|
+
|
|
28
|
+
<def tag="editor" for="text"><%= in_place_editor "in_place_textarea_bhv", attributes %></def>
|
|
29
|
+
|
|
30
|
+
<def tag="editor" for="html"><%= in_place_editor "in_place_html_textarea_bhv", attributes %></def>
|
|
31
|
+
|
|
32
|
+
<def tag="editor" for="datetime"><%= in_place_editor "in_place_textfield_bhv", attributes %></def>
|
|
33
|
+
|
|
34
|
+
<def tag="editor" for="date"><%= in_place_editor "in_place_textfield_bhv", attributes %></def>
|
|
35
|
+
|
|
36
|
+
<def tag="editor" for="integer"><%= in_place_editor "in_place_textfield_bhv", attributes %></def>
|
|
37
|
+
|
|
38
|
+
<def tag="editor" for="float"><%= in_place_editor "in_place_textfield_bhv", attributes %></def>
|
|
39
|
+
|
|
40
|
+
<def tag="editor" for="password"><% raise HoboError, "passwords cannot be edited in place" %></def>
|
|
41
|
+
|
|
42
|
+
<def tag="editor" for="boolean"><boolean_checkbox_editor merge_attrs/></def>
|
|
43
|
+
|
|
1
44
|
|
|
2
|
-
<def tag="submit" attrs="label">
|
|
3
|
-
<input
|
|
45
|
+
<def tag="submit" attrs="label, image">
|
|
46
|
+
<input if="&image" type="image" src="&image" merge_attrs class="image_input submit_button"/>
|
|
47
|
+
<else>
|
|
48
|
+
<input type="submit" value="#{label}" merge_attrs class="button_input submit_button"/>
|
|
49
|
+
</else>
|
|
4
50
|
</def>
|
|
5
51
|
|
|
6
52
|
|
|
@@ -15,35 +61,21 @@
|
|
|
15
61
|
id ||= this_field_dom_id + "_completer"
|
|
16
62
|
url = object_url(completer_model, "completions",
|
|
17
63
|
{ :for => completer_attr },
|
|
18
|
-
|
|
64
|
+
attributes.select_hash {|k,v| k.to_s.starts_with? "where_"})
|
|
19
65
|
%>
|
|
20
|
-
<input type="text" name="
|
|
21
|
-
autocomplete_url="
|
|
22
|
-
|
|
66
|
+
<input type="text" name="#{name}" id="#{id}" class="autocomplete_bhv"
|
|
67
|
+
autocomplete_url="#{url}" value="#{value}"
|
|
68
|
+
merge_attrs/>
|
|
23
69
|
<div id="<%= id %>_completions" class="completions_popup" style="display:none"></div>
|
|
24
70
|
</def>
|
|
25
71
|
|
|
26
72
|
|
|
27
|
-
<def tag="belongs_to_menu_field"><%
|
|
28
|
-
raise HoboError.new("Not allowed to edit") unless can_edit_this?
|
|
29
|
-
#Todo: switch to autocompleter for id_name when too many records, and id_name supported
|
|
30
|
-
select_options = this_type.klass.find(:all).select {|x| can_view?(x)}.map { |x|
|
|
31
|
-
[ display_name(:obj => x, :no_span => true), x.id ]
|
|
32
|
-
}
|
|
33
|
-
select_options.insert(0, ["(No #{this_type.name.to_s.titleize})", ""]) if this.nil?
|
|
34
|
-
%>
|
|
35
|
-
<select name="<%= param_name_for_this(true) %>">
|
|
36
|
-
<%= options_for_select(select_options.sort, this ? this.id : "") %>
|
|
37
|
-
</select>
|
|
38
|
-
</def>
|
|
39
|
-
|
|
40
|
-
|
|
41
73
|
<def tag="belongs_to_menu_editor"><%
|
|
42
|
-
raise HoboError.new("Not allowed to edit") unless
|
|
74
|
+
raise HoboError.new("Not allowed to edit") unless can_edit?
|
|
43
75
|
link_id = "#{this_field_dom_id}_editor" %>
|
|
44
|
-
<span id="#link_id"
|
|
76
|
+
<span id="#{link_id}" part="rapid_belongs_to_edit">
|
|
45
77
|
<% select_options = this_type.klass.find(:all).select {|x| can_view?(x)}.map {|x|
|
|
46
|
-
[
|
|
78
|
+
[ name(:with => x, :no_wrapper => true), x.id ]
|
|
47
79
|
}
|
|
48
80
|
select_options.insert(0, ["(No #{this_type.name.to_s.titleize})", ""]) if this.nil?
|
|
49
81
|
link_id = "#{this_field_dom_id}_editor"
|
|
@@ -54,32 +86,17 @@
|
|
|
54
86
|
this_type.primary_key_name => Hobo.raw_js('this.value')
|
|
55
87
|
} })
|
|
56
88
|
%>
|
|
57
|
-
<select onchange="<%= f %>"
|
|
89
|
+
<select onchange="<%= f %>">
|
|
58
90
|
<%= options_for_select(select_options.sort, this ? this.id : "") %>
|
|
59
91
|
</select>
|
|
60
|
-
<
|
|
92
|
+
<a if="&this">View</a>
|
|
61
93
|
</span>
|
|
62
94
|
</def>
|
|
63
95
|
|
|
64
96
|
|
|
65
|
-
<def tag="belongs_to_autocompleting_field">
|
|
66
|
-
<% refl = this_type
|
|
67
|
-
completer_model ||= refl.klass
|
|
68
|
-
completer_attr ||= refl.klass.id_name_column
|
|
69
|
-
id ||= this_field_dom_id + "_completer"
|
|
70
|
-
where_options = options.select_hash {|k,v| k.to_s.starts_with? "where_"}
|
|
71
|
-
url = object_url(completer_model, :completions, { :for => completer_attr }.update(where_options))
|
|
72
|
-
%>
|
|
73
|
-
|
|
74
|
-
<input type="text" id="<%= id %>" class="autocomplete_bhv" autocomplete_url="<%= url %>"
|
|
75
|
-
name="<%= param_name_for_this %>" xattrs=""/>
|
|
76
|
-
<div id="<%= id %>_completions" class="completions_popup" style="display:none"></div>
|
|
77
|
-
</def>
|
|
78
|
-
|
|
79
|
-
|
|
80
97
|
<def tag="belongs_to_autocompleting_editor" attrs="update">
|
|
81
98
|
<if_can_edit><%
|
|
82
|
-
return object_link unless
|
|
99
|
+
return object_link unless can_edit?
|
|
83
100
|
|
|
84
101
|
id ||= this_field_dom_id + "_completer"
|
|
85
102
|
f = ajax_updater(object_url(this_parent),
|
|
@@ -93,12 +110,12 @@
|
|
|
93
110
|
completer_attr ||= refl.klass.id_name_column
|
|
94
111
|
url = object_url(completer_model, "completions",
|
|
95
112
|
{ :for => completer_attr },
|
|
96
|
-
|
|
113
|
+
attributes.select_hash {|k,v| k.to_s.starts_with? "where_"})
|
|
97
114
|
%>
|
|
98
|
-
<form onsubmit="
|
|
99
|
-
<input type="text" class="autocomplete_bhv autosubmit" id="
|
|
100
|
-
value="
|
|
101
|
-
<div id="
|
|
115
|
+
<form onsubmit="#{f}; $('#{id}').blur(); return false">
|
|
116
|
+
<input type="text" class="autocomplete_bhv autosubmit" id="#{id}" autocomplete_url="#{url}"
|
|
117
|
+
value="#{this && this.id_name}" merge_attrs />
|
|
118
|
+
<div id="#{id}_completions" class="completions_popup" style="display:none"></div>
|
|
102
119
|
</form>
|
|
103
120
|
</if_can_edit>
|
|
104
121
|
<else>
|
|
@@ -107,32 +124,43 @@
|
|
|
107
124
|
</def>
|
|
108
125
|
|
|
109
126
|
|
|
110
|
-
<def tag="
|
|
111
|
-
raise HoboError.new("Not allowed to edit") unless
|
|
127
|
+
<def tag="string_select_editor" attrs="update, values"><%
|
|
128
|
+
raise HoboError.new("Not allowed to edit") unless can_edit?
|
|
129
|
+
|
|
130
|
+
values = comma_split(values)
|
|
112
131
|
f = ajax_updater(object_url(this_parent),
|
|
113
132
|
"Change #{this_field.to_s.titleize}", update,
|
|
114
133
|
:method => "put",
|
|
115
134
|
:params => { this_parent.class.name.underscore => {
|
|
116
|
-
this_field => Hobo.raw_js('this.
|
|
135
|
+
this_field => Hobo.raw_js('this.value')
|
|
117
136
|
} })
|
|
118
|
-
|
|
137
|
+
html_attributes = add_classes(attributes, editor_class)
|
|
119
138
|
%>
|
|
120
|
-
<
|
|
121
|
-
|
|
139
|
+
<select onchange="#{f}" merge_attrs="&html_attributes">
|
|
140
|
+
<%= options_for_select(values, this) %>
|
|
141
|
+
</select>
|
|
122
142
|
</def>
|
|
123
143
|
|
|
124
144
|
|
|
125
|
-
<def tag="
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
145
|
+
<def tag="boolean_checkbox_editor" attrs="update"><%
|
|
146
|
+
raise HoboError.new("Not allowed to edit") unless can_edit?
|
|
147
|
+
f = ajax_updater(object_url(this_parent),
|
|
148
|
+
"Change #{this_field.to_s.titleize}", update,
|
|
149
|
+
:method => "put",
|
|
150
|
+
:params => { this_parent.class.name.underscore => {
|
|
151
|
+
this_field => Hobo.raw_js('this.checked')
|
|
152
|
+
} })
|
|
153
|
+
attributes = add_classes(attributes, editor_class)
|
|
154
|
+
%>
|
|
155
|
+
<input type="checkbox" value="1" onclick="#{f}"
|
|
156
|
+
merge_attrs="& this ? attributes.merge(:checked => 'checked') : attributes" />
|
|
129
157
|
</def>
|
|
130
158
|
|
|
131
|
-
|
|
159
|
+
|
|
132
160
|
<def tag="sti_type_editor" attrs="update">
|
|
133
161
|
<% base_class = this.class
|
|
134
162
|
base_class = base_class.superclass while base_class.superclass != ActiveRecord::Base
|
|
135
|
-
f = ajax_updater("#{
|
|
163
|
+
f = ajax_updater("#{base_url}/#{controller_for base_class}/#{this.id}",
|
|
136
164
|
"Change #{this_field.to_s.titleize}", update,
|
|
137
165
|
:method => "put",
|
|
138
166
|
:params => { base_class.name.underscore => {
|
|
@@ -140,8 +168,8 @@
|
|
|
140
168
|
} })
|
|
141
169
|
%>
|
|
142
170
|
|
|
143
|
-
<select onchange="
|
|
144
|
-
<if
|
|
171
|
+
<select onchange="#{f}">
|
|
172
|
+
<if test="&tagbody">
|
|
145
173
|
<tagbody/>
|
|
146
174
|
</if>
|
|
147
175
|
<else>
|
|
@@ -152,17 +180,12 @@
|
|
|
152
180
|
|
|
153
181
|
|
|
154
182
|
<def tag="integer_select_editor" attrs="min, max, update, nil_option, message">
|
|
155
|
-
<select class="number_editor_bhv" hobo_update="
|
|
156
|
-
hobo_model_id="
|
|
157
|
-
|
|
158
|
-
<if
|
|
183
|
+
<select class="number_editor_bhv" hobo_update="#{update}"
|
|
184
|
+
hobo_model_id="#{this_field_dom_id}"
|
|
185
|
+
merge_attrs="&message ? attributes.merge(:hobo_message => message) : attributes">
|
|
186
|
+
<if test="&this.nil?"><option value=""><%= nil_option || "Choose a value" %></option></if>
|
|
159
187
|
<%= options_for_select((min.to_i..max.to_i).to_a, this) %>
|
|
160
188
|
</select>
|
|
161
189
|
</def>
|
|
162
190
|
|
|
163
191
|
|
|
164
|
-
<def tag="select_field">
|
|
165
|
-
<select name="<%= param_name_for_this %>">
|
|
166
|
-
<tagbody/>
|
|
167
|
-
</select>
|
|
168
|
-
</def>
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
<def tag="hidden_fields" attrs="fields, skip"><%=
|
|
2
|
+
hiddens = case fields
|
|
3
|
+
when '*', nil
|
|
4
|
+
this.class.column_names - ['type', 'created_at', 'updated_at']
|
|
5
|
+
else
|
|
6
|
+
comma_split(fields)
|
|
7
|
+
end
|
|
8
|
+
hiddens -= comma_split(skip)
|
|
9
|
+
pname = this.class.name.underscore
|
|
10
|
+
hidden_tags = hiddens.map do |h|
|
|
11
|
+
val = this.send(h)
|
|
12
|
+
name = "#{pname}[#{h}]"
|
|
13
|
+
hidden_field_tag(name, val.to_s) if val
|
|
14
|
+
end.join("\n")
|
|
15
|
+
%></def>
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
<def tag="form" attrs="message, update, hidden_fields, action, method, web_method"><%=
|
|
19
|
+
ajax_attrs, html_attrs = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
|
|
20
|
+
|
|
21
|
+
html_attrs[:action] = action || object_url(this, web_method)
|
|
22
|
+
|
|
23
|
+
new_record = this.respond_to?(:new_record?) && this.new_record?
|
|
24
|
+
|
|
25
|
+
method = if method.nil?
|
|
26
|
+
(action || web_method || new_record) ? "post" : "put"
|
|
27
|
+
else
|
|
28
|
+
method.downcase
|
|
29
|
+
end
|
|
30
|
+
if method == "put"
|
|
31
|
+
http_method_hidden = hidden_field_tag("_method", "PUT")
|
|
32
|
+
html_attrs[:method] = "post"
|
|
33
|
+
else
|
|
34
|
+
html_attrs[:method] = method
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if update || !ajax_attrs.empty?
|
|
38
|
+
# add an onsubmit to convert to an ajax form if `update` is given
|
|
39
|
+
function = ajax_updater(:post_form, message, update, ajax_attrs)
|
|
40
|
+
html_attrs[:onsubmit] = [html_attrs[:onsubmit], "#{function}; return false;"].compact.join("; ")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
body, field_names = with_form_context { tagbody.call }
|
|
44
|
+
|
|
45
|
+
hiddens = hidden_fields(:fields => hidden_fields, :skip => field_names) if new_record
|
|
46
|
+
|
|
47
|
+
body = [http_method_hidden, hiddens, body].join
|
|
48
|
+
|
|
49
|
+
if web_method
|
|
50
|
+
add_classes!(html_attrs, "#{type_name}_#{web_method}_form")
|
|
51
|
+
else
|
|
52
|
+
add_classes!(html_attrs, "#{'new_' if new_record}#{type_name}")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
content_tag("form", body, html_attrs)
|
|
56
|
+
%></def>
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
<def tag="input"><%=
|
|
60
|
+
if attributes[:type]
|
|
61
|
+
tag :input, attributes
|
|
62
|
+
elsif !can_edit?
|
|
63
|
+
view
|
|
64
|
+
else
|
|
65
|
+
if this_type.respond_to?(:macro)
|
|
66
|
+
if this_type.macro == :belongs_to
|
|
67
|
+
belongs_to_input(attributes)
|
|
68
|
+
elsif this_type.macro == :has_many
|
|
69
|
+
has_many_input(attributes)
|
|
70
|
+
end
|
|
71
|
+
else
|
|
72
|
+
attrs = {}.update(attributes)
|
|
73
|
+
attrs[:name] ||= param_name_for_this
|
|
74
|
+
the_input = call_polymorphic_tag('input', attrs) or
|
|
75
|
+
raise HoboError, ("No input tag for #{this_field}:#{this_type} (this=#{this.inspect})")
|
|
76
|
+
if this_parent.errors[this_field]
|
|
77
|
+
"<div class='field_with_errors'>#{the_input}</div>"
|
|
78
|
+
else
|
|
79
|
+
the_input
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
%></def>
|
|
84
|
+
|
|
85
|
+
<def tag="input" for="text" attrs="name">
|
|
86
|
+
<%= text_area_tag(name, this, attributes) %>
|
|
87
|
+
</def>
|
|
88
|
+
|
|
89
|
+
<def tag="input" for="boolean" attrs="name">
|
|
90
|
+
<%= check_box_tag(name, '1', this, attributes) + hidden_field_tag(name, '0') %>
|
|
91
|
+
</def>
|
|
92
|
+
|
|
93
|
+
<def tag="input" for="password" attrs="name">
|
|
94
|
+
<%= password_field_tag(name, this) %>
|
|
95
|
+
</def>
|
|
96
|
+
|
|
97
|
+
<def tag="input" for="html" attrs="name">
|
|
98
|
+
<%= text_area_tag(name, this, add_classes(attributes, :tiny_mce)) %>
|
|
99
|
+
</def>
|
|
100
|
+
|
|
101
|
+
<def tag="input" for="date">
|
|
102
|
+
<%= select_date(this || Time.now, :prefix => param_name_for_this) %>
|
|
103
|
+
</def>
|
|
104
|
+
|
|
105
|
+
<def tag="input" for="datetime">
|
|
106
|
+
<%= select_datetime(this || Time.now, :prefix => param_name_for_this) %>
|
|
107
|
+
</def>
|
|
108
|
+
|
|
109
|
+
<def tag="input" for="integer" attrs="name">
|
|
110
|
+
<%= text_field_tag(name, this, attributes) %>
|
|
111
|
+
</def>
|
|
112
|
+
|
|
113
|
+
<def tag="input" for="float" attrs="name">
|
|
114
|
+
<%= text_field_tag(name, this, attributes) %>
|
|
115
|
+
</def>
|
|
116
|
+
|
|
117
|
+
<def tag="input" for="string" attrs="name">
|
|
118
|
+
<%= text_field_tag(name, this, attributes) %>
|
|
119
|
+
</def>
|
|
120
|
+
|
|
121
|
+
<def tag="belongs_to_input">
|
|
122
|
+
<%= belongs_to_menu_input(attributes) %>
|
|
123
|
+
</def>
|
|
124
|
+
|
|
125
|
+
<!--- Buttons --->
|
|
126
|
+
|
|
127
|
+
<def tag="remote_method_button" attrs="method, update, result_update, params, label, message"><%=
|
|
128
|
+
ajax_attributes, html_attributes = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
|
|
129
|
+
|
|
130
|
+
message ||= method.titleize
|
|
131
|
+
func = ajax_updater(object_url(this) + "/#{method}", message, update,
|
|
132
|
+
ajax_attributes.merge(:params => params, :result_update => result_update))
|
|
133
|
+
html_attributes.update(:type =>'button', :onclick => "var e = this; " + func, :value => label)
|
|
134
|
+
tag(:input, add_classes(html_attributes, "button_input remote_method_button #{method}_button"))
|
|
135
|
+
%></def>
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
<def tag="update_button" attrs="label, message, update, fields, params"><%=
|
|
139
|
+
raise HoboError.new("no update specified") unless update
|
|
140
|
+
message ||= label
|
|
141
|
+
func = ajax_updater(object_url(this), message, update,
|
|
142
|
+
:params => { this.class.name.underscore => fields }.merge(params || {}),
|
|
143
|
+
:method => :put)
|
|
144
|
+
tag :input, add_classes(attributes.merge(:type =>'button', :onclick => func, :value => label),
|
|
145
|
+
"button_input update_button update_#{this.class.name.underscore}_button") %>
|
|
146
|
+
</def>
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
<def tag="delete_button" attrs="label, message, update, in_place, image, confirm, fade"><%=
|
|
150
|
+
if can_delete?
|
|
151
|
+
attributes = attributes.merge(if image
|
|
152
|
+
{ :type => "image", :src => "#{base_url}/images/#{image}" }
|
|
153
|
+
else
|
|
154
|
+
{ :type => "button" }
|
|
155
|
+
end)
|
|
156
|
+
label ||= "Remove"
|
|
157
|
+
confirm ||= "Are you sure?"
|
|
158
|
+
|
|
159
|
+
add_classes!(attributes,
|
|
160
|
+
image ? "image_button_input" : "button_input",
|
|
161
|
+
"delete_button delete_#{this.class.name.underscore}_button")
|
|
162
|
+
url = object_url(this, "destroy")
|
|
163
|
+
if in_place == false
|
|
164
|
+
attributes[:confirm] = confirm
|
|
165
|
+
button_to(label, url, attributes)
|
|
166
|
+
else
|
|
167
|
+
fade = true if fade.nil?
|
|
168
|
+
attributes[:value] = label
|
|
169
|
+
attributes[:onclick] = "Hobo.removeButton(this, '#{url}', #{js_updates(update)}, #{fade ? 'true' : 'false'})"
|
|
170
|
+
tag(:input, attributes)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
%></def>
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
<def tag="create_button" attrs="model, update, label, message, fields"><%=
|
|
177
|
+
raise HoboError.new("no update specified") unless update
|
|
178
|
+
|
|
179
|
+
fields ||= {}
|
|
180
|
+
class_or_assoc = if model
|
|
181
|
+
model.is_a?(String) ? model.constantize : model
|
|
182
|
+
elsif Hobo.simple_has_many_association?(this)
|
|
183
|
+
fields[this.proxy_reflection.primary_key_name] = this.proxy_owner.id
|
|
184
|
+
this
|
|
185
|
+
else
|
|
186
|
+
raise HoboError.new("invalid context for <create_button>")
|
|
187
|
+
end
|
|
188
|
+
new = class_or_assoc.new(fields)
|
|
189
|
+
new.set_creator(current_user)
|
|
190
|
+
if can_create?(new)
|
|
191
|
+
label ||= "New #{new.class.name.titleize}"
|
|
192
|
+
message ||= label
|
|
193
|
+
class_name = new.class.name.underscore
|
|
194
|
+
func = ajax_updater(object_url(new.class), message, update,
|
|
195
|
+
({:params => { class_name => fields }} unless fields.empty?))
|
|
196
|
+
tag :input, add_classes(attributes.merge(:type =>'button', :onclick => func, :value => label),
|
|
197
|
+
"button_input create_button create_#{class_name}_button")
|
|
198
|
+
end
|
|
199
|
+
%></def>
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
<def tag="belongs_to_menu_input" attrs="include_none"><%
|
|
203
|
+
raise HoboError.new("Not allowed to edit") unless can_edit?
|
|
204
|
+
#Todo: switch to autocompleter for id_name when too many records, and id_name supported
|
|
205
|
+
select_options = this_type.klass.find(:all).select {|x| can_view?(x)}.map { |x|
|
|
206
|
+
[ name(:with => x, :no_wrapper => true), x.id ]
|
|
207
|
+
}
|
|
208
|
+
select_options.insert(0, ["(No #{this_type.name.to_s.titleize})", ""]) if this.nil? || include_none
|
|
209
|
+
%>
|
|
210
|
+
<select name="<%= param_name_for_this(true) %>">
|
|
211
|
+
<%= options_for_select(select_options.sort, this ? this.id : "") %>
|
|
212
|
+
</select>
|
|
213
|
+
</def>
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
<def tag="belongs_to_autocompleting_input">
|
|
217
|
+
<% refl = this_type
|
|
218
|
+
completer_model ||= refl.klass
|
|
219
|
+
completer_attr ||= refl.klass.id_name_column
|
|
220
|
+
id ||= this_field_dom_id + "_completer"
|
|
221
|
+
where_attributes = attributes.select_hash {|k,v| k.to_s.starts_with? "where_"}
|
|
222
|
+
url = object_url(completer_model, :completions, { :for => completer_attr }.update(where_attributes))
|
|
223
|
+
%>
|
|
224
|
+
|
|
225
|
+
<input type="text" id="#{id}" class="autocomplete_bhv" autocomplete_url="#{url}"
|
|
226
|
+
name="#{param_name_for_this}" merge_attrs/>
|
|
227
|
+
<div id="#{id}_completions" class="completions_popup" style="display:none"></div>
|
|
228
|
+
</def>
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
<def tag="sti_type_input">
|
|
232
|
+
<select name="<%= param_name_for(form_this, form_field_path + ['type']) %>">
|
|
233
|
+
<%= options_for_select(this.class.send(:subclasses).omap{[name.titleize, name]}, this.class.name) %>
|
|
234
|
+
</select>
|
|
235
|
+
</def>
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
<def tag="select_input">
|
|
239
|
+
<select name="#{param_name_for_this}">
|
|
240
|
+
<tagbody/>
|
|
241
|
+
</select>
|
|
242
|
+
</def>
|