hobo_rapid 1.4.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +5 -0
- data/VERSION +1 -0
- data/app/controllers/dev_controller.rb +25 -0
- data/app/helpers/hobo_rapid_helper.rb +197 -0
- data/hobo_rapid.gemspec +26 -0
- data/lib/hobo_rapid/railtie.rb +6 -0
- data/lib/hobo_rapid.rb +13 -0
- data/taglibs/buttons/buttons.dryml +1 -0
- data/taglibs/buttons/create_button.dryml +40 -0
- data/taglibs/buttons/delete-button.dryml +75 -0
- data/taglibs/buttons/remote_method_button.dryml +34 -0
- data/taglibs/buttons/transition_button.dryml +71 -0
- data/taglibs/buttons/transition_link.dryml +22 -0
- data/taglibs/buttons/update_button.dryml +29 -0
- data/taglibs/cache/cache.dryml +1 -0
- data/taglibs/cache/nested_cache.dryml +332 -0
- data/taglibs/cards/card.dryml +7 -0
- data/taglibs/cards/cards.dryml +1 -0
- data/taglibs/cards/search_card.dryml +4 -0
- data/taglibs/editors/click_editor.dryml +60 -0
- data/taglibs/editors/editors.dryml +27 -0
- data/taglibs/editors/live_editor.dryml +37 -0
- data/taglibs/forms/error_messages.dryml +21 -0
- data/taglibs/forms/form.dryml +101 -0
- data/taglibs/forms/formlet.dryml +48 -0
- data/taglibs/forms/forms.dryml +5 -0
- data/taglibs/forms/submit.dryml +14 -0
- data/taglibs/hobo_rapid.dryml +14 -0
- data/taglibs/html/a.dryml +156 -0
- data/taglibs/html/aside.dryml +5 -0
- data/taglibs/html/doctype.dryml +39 -0
- data/taglibs/html/empty_tag.dryml +23 -0
- data/taglibs/html/footer.dryml +5 -0
- data/taglibs/html/header.dryml +5 -0
- data/taglibs/html/html.dryml +18 -0
- data/taglibs/html/if_ie.dryml +11 -0
- data/taglibs/html/image.dryml +11 -0
- data/taglibs/html/javascript.dryml +12 -0
- data/taglibs/html/section.dryml +12 -0
- data/taglibs/html/section_group.dryml +11 -0
- data/taglibs/html/stylesheet.dryml +5 -0
- data/taglibs/html/table.dryml +174 -0
- data/taglibs/i18n/ht.dryml +48 -0
- data/taglibs/i18n/human_attribute_name +18 -0
- data/taglibs/i18n/human_collection_name.dryml +69 -0
- data/taglibs/i18n/i18n.dryml +1 -0
- data/taglibs/i18n/model_name_human.dryml +16 -0
- data/taglibs/i18n/t.dryml +12 -0
- data/taglibs/inputs/after_submit.dryml +32 -0
- data/taglibs/inputs/check_many.dryml +25 -0
- data/taglibs/inputs/collection_input.dryml +10 -0
- data/taglibs/inputs/hidden_field.dryml +48 -0
- data/taglibs/inputs/hot_input.dryml +50 -0
- data/taglibs/inputs/input.dryml +76 -0
- data/taglibs/inputs/input_all.dryml +14 -0
- data/taglibs/inputs/input_for.dryml +38 -0
- data/taglibs/inputs/input_for_date.dryml +86 -0
- data/taglibs/inputs/input_for_enum_string.dryml +26 -0
- data/taglibs/inputs/input_many.dryml +131 -0
- data/taglibs/inputs/inputs.dryml +1 -0
- data/taglibs/inputs/name_one.dryml +74 -0
- data/taglibs/inputs/or_cancel.dryml +8 -0
- data/taglibs/inputs/select_input.dryml +13 -0
- data/taglibs/inputs/select_many.dryml +58 -0
- data/taglibs/inputs/select_menu.dryml +23 -0
- data/taglibs/inputs/select_one.dryml +46 -0
- data/taglibs/inputs/sortable_input_many.dryml +31 -0
- data/taglibs/inputs/sti_type_input.dryml +6 -0
- data/taglibs/lists/collection.dryml +26 -0
- data/taglibs/lists/empty_collection_message.dryml +13 -0
- data/taglibs/lists/feckless_fieldset.dryml +94 -0
- data/taglibs/lists/field_list.dryml +21 -0
- data/taglibs/lists/field_list_v1.dryml +64 -0
- data/taglibs/lists/labelled_item_list.dryml +11 -0
- data/taglibs/lists/lists.dryml +2 -0
- data/taglibs/lists/with_fields.dryml +98 -0
- data/taglibs/pages/account.dryml +30 -0
- data/taglibs/pages/account_disabled.dryml +19 -0
- data/taglibs/pages/flash_message.dryml +23 -0
- data/taglibs/pages/forgot_password.dryml +62 -0
- data/taglibs/pages/login.dryml +57 -0
- data/taglibs/pages/not_found_page.dryml +18 -0
- data/taglibs/pages/page_nav.dryml +17 -0
- data/taglibs/pages/pages.dryml +12 -0
- data/taglibs/pages/permission_denied_page.dryml +24 -0
- data/taglibs/plus/collection_preview.dryml +23 -0
- data/taglibs/plus/filter_menu.dryml +103 -0
- data/taglibs/plus/gravatar.dryml +12 -0
- data/taglibs/plus/live_search.dryml +40 -0
- data/taglibs/plus/plus.dryml +1 -0
- data/taglibs/plus/sortable_collection.dryml +36 -0
- data/taglibs/plus/table_plus.dryml +63 -0
- data/taglibs/views/a_or_an.dryml +10 -0
- data/taglibs/views/collection_name.dryml +28 -0
- data/taglibs/views/comma_list.dryml +2 -0
- data/taglibs/views/count.dryml +99 -0
- data/taglibs/views/links_for_collection.dryml +2 -0
- data/taglibs/views/name.dryml +30 -0
- data/taglibs/views/nil_view.dryml +10 -0
- data/taglibs/views/record_flags.dryml +5 -0
- data/taglibs/views/type_name.dryml +24 -0
- data/taglibs/views/view.dryml +79 -0
- data/taglibs/views/view_for.dryml +42 -0
- data/taglibs/views/views.dryml +1 -0
- data/taglibs/views/you.dryml +150 -0
- data/vendor/assets/javascripts/hobo_rapid.js +1 -0
- data/vendor/assets/stylesheets/feckless-fieldset.css +40 -0
- data/vendor/assets/stylesheets/hobo-rapid.css +94 -0
- data/vendor/assets/stylesheets/hobo_rapid.css +1 -0
- metadata +174 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
<!-- This comment shouldn't appear in the cookbook -->
|
2
|
+
|
3
|
+
<include src="buttons/*"/>
|
4
|
+
<include src="cache/*"/>
|
5
|
+
<include src="cards/*"/>
|
6
|
+
<include src="editors/*"/>
|
7
|
+
<include src="forms/*"/>
|
8
|
+
<include src="html/*"/>
|
9
|
+
<include src="i18n/*"/>
|
10
|
+
<include src="inputs/*"/>
|
11
|
+
<include src="lists/*"/>
|
12
|
+
<include src="pages/*"/>
|
13
|
+
<include src="plus/*"/>
|
14
|
+
<include src="views/*"/>
|
@@ -0,0 +1,156 @@
|
|
1
|
+
<!--
|
2
|
+
`<a>` is extended in Rapid to automatically provide URLs for Hobo model routes
|
3
|
+
|
4
|
+
### Usage
|
5
|
+
|
6
|
+
The tag behaves as a regular HTML link or anchor if either the href or name attribute is given:
|
7
|
+
|
8
|
+
<a href="/admin">Admin</a> -> Output is exactly as provided, untouched by Rapid
|
9
|
+
|
10
|
+
If no href or name is given then the _context_ is used to determine the link URL.
|
11
|
+
The helper method `object_url` is used to construct the URL using restful routing:
|
12
|
+
|
13
|
+
If the context is a class then the link will be an index page:
|
14
|
+
|
15
|
+
<a with="&BlogPost">My Blog</a> -> <a href="/blog_posts">My Blog</a>
|
16
|
+
|
17
|
+
If the context is a hobo model instance then the link will be a show page:
|
18
|
+
|
19
|
+
<% blog_post = BlogPost.find(1) %>
|
20
|
+
<a with="&blog_post">My Blog Post</a> -> <a href="/blog_posts/1">My Blog Post</a>
|
21
|
+
|
22
|
+
An action can be provided for an alternative show page:
|
23
|
+
|
24
|
+
<a with="&blog_post" action="edit">Edit Post</a> -> <a href="/blog_posts/1/edit">Edit Post</a>
|
25
|
+
|
26
|
+
Or a new page if the context is a class:
|
27
|
+
|
28
|
+
<a with="&BlogPost" action="new">New Blog Post</a> -> <a href="/blog_posts/new">New Blog Post</a>
|
29
|
+
|
30
|
+
### Additional Features
|
31
|
+
|
32
|
+
* If the constructed route does not exist then the link will not be created, but the content of the link will still be output. E.g. when `/blog_posts` does not exist (because the hobo model controller does not exist or the index action is disabled):
|
33
|
+
|
34
|
+
<a with="&BlogPost">My Blog</a> -> My Blog
|
35
|
+
|
36
|
+
when the show action `/blog_posts/:id` does not exist:
|
37
|
+
|
38
|
+
<a with="&blog_post">My Blog Post</a> -> My Blog Post
|
39
|
+
* If no content text is provided then `<a>` will use the name method on the context to provide the text. E.g.
|
40
|
+
|
41
|
+
<a with="&blog_post"/> -> <a href="/blog_posts/1">My First Blog Post</a>`
|
42
|
+
<a with="&BlogPost"/> -> <a href="/blog_posts">Blog Posts</a>`
|
43
|
+
* If `action="new"` then `<a>` will check that the current user has permission to create the object
|
44
|
+
* Several useful classes are added automatically to the output `<a>`.
|
45
|
+
|
46
|
+
### AJAX
|
47
|
+
|
48
|
+
The standard AJAX form attributes are supported. This can be used for conventional Ajax:
|
49
|
+
|
50
|
+
<a href="&refresh_path" update="results">Refresh results</a>
|
51
|
+
|
52
|
+
Or it can be used with push-state to provide faster links:
|
53
|
+
|
54
|
+
<a href="somewhere/else" update="body" push-state new-title="Somewhere else">Go somewhere else.</a>
|
55
|
+
|
56
|
+
In this case the entire body is being refreshed but the headers
|
57
|
+
aren't, so will work to link between two dissimilar pages as long as
|
58
|
+
the headers are identical.
|
59
|
+
|
60
|
+
AJAX attributes are supported in both modes: in the "magic" mode where
|
61
|
+
RAPID determines the href target or in "passthrough" where you supply
|
62
|
+
the href or name.
|
63
|
+
|
64
|
+
### Attributes
|
65
|
+
|
66
|
+
The standard AJAX attributes are supported.
|
67
|
+
|
68
|
+
* action: If "new", triggers the special behaviour listed above. Otherwise, contains the action to be performed on the context. If neither `action` nor `method` are specified, the action will be "index" or "show", as appropriate.
|
69
|
+
|
70
|
+
* to: Use this item as the target instead of the current context.
|
71
|
+
|
72
|
+
* params: These are appended to the target as a query string after a "?". Params are passed as a ruby hash. Example: `params="&{id=>17, name=>'joe'}"`
|
73
|
+
|
74
|
+
* query-params: if set, current query parameters are mirrored onto the link. If true or blank, all non-ajax query parameters are used. (`query-params`, `query-params="&true"` or `query-params=""`) Otherwise, the specified query parameters are used. (`query-params="page,sort,search"`)
|
75
|
+
|
76
|
+
* href, name: If either of these attributes are present, the smart features of this tag are turned off.
|
77
|
+
|
78
|
+
* format: this adds ".#{format}" to the end of the url
|
79
|
+
|
80
|
+
* subsite: routes the URL using the subsite
|
81
|
+
|
82
|
+
* force: overrides the permission check if `action` is "new"
|
83
|
+
|
84
|
+
* method: "get", "put", "post" or "delete". "get" is the default
|
85
|
+
|
86
|
+
-->
|
87
|
+
<def tag="a" attrs="action, to, params, query-params, href, format, subsite, force"><%=
|
88
|
+
content = parameters.default
|
89
|
+
|
90
|
+
ajax_attrs, attributes = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS)
|
91
|
+
unless ajax_attrs.blank?
|
92
|
+
add_data_rapid!(attributes, "a", :ajax_attrs => ajax_attrs)
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
if query_params
|
97
|
+
if query_params==true || query_params.blank?
|
98
|
+
query_params = query_parameters_filtered
|
99
|
+
else
|
100
|
+
query_params = query_parameters_filtered(:only => comma_split(query_params))
|
101
|
+
end
|
102
|
+
params = query_params.merge(params || HashWithIndifferentAccess.new)
|
103
|
+
end
|
104
|
+
|
105
|
+
if href || attributes[:name]
|
106
|
+
# Regular link
|
107
|
+
href += "?" + params.map { |n, v| "#{n}=#{v}" }.join('&') if !params.blank?
|
108
|
+
element(:a, attributes.update(:href => href), content)
|
109
|
+
else
|
110
|
+
target = to || this
|
111
|
+
|
112
|
+
if target.nil?
|
113
|
+
Dryml.last_if = false
|
114
|
+
nil_view
|
115
|
+
elsif action == "new"
|
116
|
+
# Link to a new object form
|
117
|
+
new_record = target.new
|
118
|
+
new_record.set_creator(current_user)
|
119
|
+
href = object_url(target, "new", params._?.merge(:subsite => subsite))
|
120
|
+
|
121
|
+
if href && (force || can_create?(new_record))
|
122
|
+
new_class_name = if target.respond_to?(:proxy_reflection)
|
123
|
+
target.proxy_association.reflection.klass.name
|
124
|
+
else
|
125
|
+
target.name
|
126
|
+
end
|
127
|
+
|
128
|
+
add_classes!(attributes, "new-#{new_class_name.underscore}-link")
|
129
|
+
content = "New #{new_class_name.titleize}" if content.blank?
|
130
|
+
Dryml.last_if = true
|
131
|
+
element(:a, attributes.update(:href => href), content)
|
132
|
+
else
|
133
|
+
Dryml.last_if = false
|
134
|
+
""
|
135
|
+
end
|
136
|
+
else
|
137
|
+
# Link to an existing object
|
138
|
+
|
139
|
+
content = name if content.blank?
|
140
|
+
|
141
|
+
href = object_url(target, action, (params || {}).merge(:subsite => subsite)) unless (action.nil? && target.try.new_record?)
|
142
|
+
if href.nil?
|
143
|
+
# This target is registered with Hobo::Routes as not linkable
|
144
|
+
content
|
145
|
+
else
|
146
|
+
css_class = target.try.origin_attribute || target.class.name.underscore.dasherize
|
147
|
+
add_classes!(attributes, "#{css_class}-link")
|
148
|
+
|
149
|
+
href.sub!(/\?|$/, ".#{format}\\0") unless format.blank?
|
150
|
+
|
151
|
+
# Set default link text if none given
|
152
|
+
element(:a, attributes.update(:href => href), content)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
%></def>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<!-- A proposed HTML 5 semantic tag. Outputs `<div class="aside">` and works in the same way as `<section>` with empty content. -->
|
2
|
+
<def tag="aside" attrs="empty">
|
3
|
+
<set body="¶meters.default"/>
|
4
|
+
<div class="aside" merge-attrs if="&!body.blank? || empty"><%= body %></div>
|
5
|
+
</def>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<!-- Renders one of five HTML DOCTYPE declarations, according to the `version` attribute.
|
2
|
+
|
3
|
+
### Attributes
|
4
|
+
- 'version' - the doctype version, must be one of:
|
5
|
+
|
6
|
+
- HTML 4.01 STRICT
|
7
|
+
- HTML 4.01 TRANSITIONAL
|
8
|
+
- XHTML 1.0 STRICT
|
9
|
+
- XHTML 1.0 TRANSITIONAL
|
10
|
+
- XHTML 1.1
|
11
|
+
- HTML
|
12
|
+
- html
|
13
|
+
- HTML5
|
14
|
+
- html5
|
15
|
+
|
16
|
+
See the source for the actual output
|
17
|
+
|
18
|
+
-->
|
19
|
+
<def tag="doctype" attrs="version"><%=raw(
|
20
|
+
case version.upcase
|
21
|
+
when "HTML 4.01 STRICT"
|
22
|
+
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ' +
|
23
|
+
'"http://www.w3.org/TR/html4/strict.dtd">'
|
24
|
+
when "HTML 4.01 TRANSITIONAL"
|
25
|
+
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ' +
|
26
|
+
'"http://www.w3.org/TR/html4/loose.dtd">'
|
27
|
+
when "XHTML 1.0 STRICT"
|
28
|
+
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
|
29
|
+
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
|
30
|
+
when "XHTML 1.0 TRANSITIONAL"
|
31
|
+
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' +
|
32
|
+
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
|
33
|
+
when "XHTML 1.1"
|
34
|
+
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" ' +
|
35
|
+
'"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
|
36
|
+
when "HTML", "html", "HTML5", "html5"
|
37
|
+
'<!DOCTYPE html>'
|
38
|
+
end)
|
39
|
+
%></def>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!-- empty tags should be written as <br> in HTML and <br /> in XHTML -->
|
2
|
+
<!-- nodoc. -->
|
3
|
+
<def tag="empty-tag" attrs="tag-name"><%= element(tag_name, attributes, nil, true, true) %></def>
|
4
|
+
<!-- nodoc. -->
|
5
|
+
<def tag="base"><empty-tag tag-name="base" merge/></def>
|
6
|
+
<!-- nodoc. -->
|
7
|
+
<def tag="meta"><empty-tag tag-name="meta" merge/></def>
|
8
|
+
<!-- nodoc. -->
|
9
|
+
<def tag="link"><empty-tag tag-name="link" merge/></def>
|
10
|
+
<!-- nodoc. -->
|
11
|
+
<def tag="img"><empty-tag tag-name="img" merge/></def>
|
12
|
+
<!-- nodoc. -->
|
13
|
+
<def tag="br"><empty-tag tag-name="br" merge/></def>
|
14
|
+
<!-- nodoc. -->
|
15
|
+
<def tag="hr"><empty-tag tag-name="hr" merge/></def>
|
16
|
+
<!-- nodoc. -->
|
17
|
+
<def tag="frame"><empty-tag tag-name="frame" merge/></def>
|
18
|
+
<!-- nodoc. -->
|
19
|
+
<def tag="area"><empty-tag tag-name="area" merge/></def>
|
20
|
+
<!-- nodoc. -->
|
21
|
+
<def tag="param"><empty-tag tag-name="param" merge/></def>
|
22
|
+
<!-- nodoc. -->
|
23
|
+
<def tag="col"><empty-tag tag-name="col" merge/></def>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<!-- A proposed HTML 5 semantic tag. Outputs `<div class="footer">` and works in the same way as `<section>` with empty content. -->
|
2
|
+
<def tag="footer" attrs="empty">
|
3
|
+
<set body="¶meters.default"/>
|
4
|
+
<div class="footer" merge-attrs if="&!body.blank? || empty"><%= body %></div>
|
5
|
+
</def>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<!-- A proposed HTML 5 semantic tag. Outputs `<div class="header">` and works in the same way as `<section>` with empty content. -->
|
2
|
+
<def tag="header" attrs="empty">
|
3
|
+
<set body="¶meters.default"/>
|
4
|
+
<div class="header" merge-attrs if="&!body.blank? || empty"><%= body %></div>
|
5
|
+
</def>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!-- Standard HTML tags that have been enhanced in RAPID, as well as
|
2
|
+
closely related tags -->
|
3
|
+
|
4
|
+
|
5
|
+
<!-- Renders an `<html>` tag along with the DOCTYPE specified in the `doctype` attribute.
|
6
|
+
|
7
|
+
### Attributes
|
8
|
+
|
9
|
+
- `doctype` - the version of the DOCTYPE required. See the `version` attribute to `<doctype>`
|
10
|
+
-->
|
11
|
+
<def tag="html" attrs="doctype">
|
12
|
+
<% doctype ||= 'html' -%>
|
13
|
+
<doctype version="&doctype"/>
|
14
|
+
<% attributes.reverse_merge!(:xmlns => "http://www.w3.org/1999/xhtml") if doctype.upcase =~ /^XHTML/ -%>
|
15
|
+
<%=raw "<html#{tag_options(attributes, true)}>" %>
|
16
|
+
<set-scoped xmldoctype="&doctype.upcase =~ /^XHTML/"><do param="default"/></set-scoped>
|
17
|
+
<%=raw "</html>" %>
|
18
|
+
</def>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!-- Renders a conditional comment in order to have some content ignored by all browsers other than Internet Explorer
|
2
|
+
|
3
|
+
### Example
|
4
|
+
|
5
|
+
|
6
|
+
<if-ie version="lt IE 7"> ... </if-ie>
|
7
|
+
|
8
|
+
-->
|
9
|
+
<def tag="if-ie" attrs="version">
|
10
|
+
<%=raw "<!--[if #{version || 'IE'}]>" %><do param="default"/><%=raw "<![endif]-->" %>
|
11
|
+
</def>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!--
|
2
|
+
Provides a short hand way of displaying images. All attributes supported by `image_tag` are supported.
|
3
|
+
|
4
|
+
### Usage
|
5
|
+
|
6
|
+
<image src="hobo.png"/> -> <img src="/images/hobo.png"/>
|
7
|
+
<image src="blog/funny.jpg" alt="Funny Scene"/> -> <img src="/images/blog/funny.jpg" alt="Funny Scene"/>
|
8
|
+
-->
|
9
|
+
<def tag="image" attrs="src"><%=
|
10
|
+
image_tag(src, Hash[deunderscore_attributes(attributes)])
|
11
|
+
%></def>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<!-- Simple wrapper for the `javascript_include_tag` helper. The `name` attribute can be a comma-separated list of script file names.
|
2
|
+
-->
|
3
|
+
<def tag="javascript" attrs="name">
|
4
|
+
<if test="&name.is_a?(Symbol)">
|
5
|
+
<%= javascript_include_tag name %>
|
6
|
+
</if>
|
7
|
+
<else>
|
8
|
+
<repeat with="&comma_split(name)">
|
9
|
+
<%= javascript_include_tag this %>
|
10
|
+
</repeat>
|
11
|
+
</else>
|
12
|
+
</def>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<!-- A proposed HTML 5 tag for representing a generic document or application section. Slightly more semantic than `<div>` for indicating document structure. For the time being, `<section>` is output as `<div class="section">`. In Hobo, `<section>` also has one other important behaviour which is different to using `<div>` directly, when the content of the section is empty, the wrapper tag will disappear. e.g.
|
2
|
+
|
3
|
+
<section>My Section</section> -> <div class="section">My Section</div>
|
4
|
+
<section><%# empty %></section> -> (nothing is generated)
|
5
|
+
-->
|
6
|
+
<def tag="section" attrs="empty, with-flash-messages">
|
7
|
+
<set body="¶meters.default" flash="&with_flash_messages && !scope.flash_rendered"/>
|
8
|
+
<div class="section #{'with-flash' if flash}" merge-attrs if="&!body.blank? || empty || flash">
|
9
|
+
<flash-messages if="&flash"/>
|
10
|
+
<%= body %>
|
11
|
+
</div>
|
12
|
+
</def>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!-- Used as a semantic wrapper around a group of sections and asides. CSS layouts can be provided based on this structure.
|
2
|
+
|
3
|
+
### Usage
|
4
|
+
|
5
|
+
<section-group>
|
6
|
+
<section>My First Section</section>
|
7
|
+
<section>My Second Section</section>
|
8
|
+
<aside>My Aside</aside>
|
9
|
+
</section-group>
|
10
|
+
-->
|
11
|
+
<def tag="section-group"><div class="section-group"><div class="section-group-inner" merge-attrs param="default"></div></div></def>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<!-- Simple wrapper for the `stylesheet_link_tag` helper. The `name` attribute can be a comma-separated list of stylesheet names.
|
2
|
+
-->
|
3
|
+
<def tag="stylesheet" attrs="name">
|
4
|
+
<%= stylesheet_link_tag *(comma_split(name) + [deunderscore_attributes(attributes)]) %>
|
5
|
+
</def>
|
@@ -0,0 +1,174 @@
|
|
1
|
+
<!--
|
2
|
+
`<table>` is extended in Rapid to provide a shorthand way to output a set of fields for a given collection. This is enabled using the `field` attribute (without the `field` attribute this is just the regular HTML `<table>` tag)
|
3
|
+
|
4
|
+
### Usage
|
5
|
+
|
6
|
+
If the context is an array of blog posts...
|
7
|
+
|
8
|
+
<table fields="name, created_at, description"/>
|
9
|
+
|
10
|
+
This will output a header row containing "Name", "Created At" and "Description" followed by a row for each record in the collection. By default, the `<view/>` tag is called for each field in the row. This can be altered with the `field-tag` attribute, e.g.
|
11
|
+
|
12
|
+
<table fields="name, created_at, description" field-tag="input"/>
|
13
|
+
|
14
|
+
This will use `<input/>` as the tag in each table cell instead of `<view/>`
|
15
|
+
|
16
|
+
### Additional Notes
|
17
|
+
|
18
|
+
* `<table>` provides parameters based on the names of the fields which can be used to further customise the output. For each field a heading parameter is provided, e.g. name-heading, created-at-heading, description-heading. These can be used to customise the headings:
|
19
|
+
|
20
|
+
<table fields="name, created_at, description">
|
21
|
+
<created-at-heading:>Creation Date</created-at-heading:>
|
22
|
+
</table>
|
23
|
+
* Similarly, "view" parameters are provided as an additional way to customise the table cells of the table body, e.g. `name-view`, `created-at-view`, `description-view`:
|
24
|
+
|
25
|
+
<table fields="name, created_at, description">
|
26
|
+
<created-at-view:><view format="%d %B %Y"/></created-at-view:>
|
27
|
+
</table>
|
28
|
+
* By adding an empty `control` parameter, the default control column is enable adding an edit link and delete button for each table row:
|
29
|
+
|
30
|
+
<table fields="name, created_at, description">
|
31
|
+
<controls:/>
|
32
|
+
</table>
|
33
|
+
|
34
|
+
The controls can be further customised using the "edit-link" and "delete-button" parameters:
|
35
|
+
|
36
|
+
<table fields="name, created_at, description">
|
37
|
+
<controls:/>
|
38
|
+
<delete-button: label="Nuke Me"/>
|
39
|
+
</table>
|
40
|
+
|
41
|
+
or by providing completely new content for the control column:
|
42
|
+
|
43
|
+
<table fields="name, created_at, description">
|
44
|
+
<controls:>my controls!</controls:>
|
45
|
+
</table>
|
46
|
+
|
47
|
+
### Using table without ActiveRecord
|
48
|
+
|
49
|
+
Typical usage for table is to supply the results of an ActiveRecord query as the context. However, it is possible to supply a more generic array as the context instead.
|
50
|
+
|
51
|
+
#### using the tr parameter
|
52
|
+
|
53
|
+
If you use the tr parameter you can pass pretty much anything in the array, since you then are supplying the formatting for the row. Giving:
|
54
|
+
|
55
|
+
<table with="&[1,2,3]">
|
56
|
+
<thead:><tr><th>Heading</th></tr></thead:>
|
57
|
+
<tr:><td><%= this+7 %></td></tr:>
|
58
|
+
</table>
|
59
|
+
|
60
|
+
Produces:
|
61
|
+
|
62
|
+
<table>
|
63
|
+
<thead>
|
64
|
+
<tr><th>Heading</th></tr>
|
65
|
+
</thead>
|
66
|
+
<tbody>
|
67
|
+
<tr class='odd fixnum'><td>8</td></tr>
|
68
|
+
<tr class='even fixnum'><td>9</td></tr>
|
69
|
+
<tr class='odd fixnum'><td>10</td></tr>
|
70
|
+
</tbody>
|
71
|
+
</table>
|
72
|
+
|
73
|
+
#### using OpenStruct
|
74
|
+
|
75
|
+
If you supply an array of generic objects, you can supply method names to fields and `<table>` will produce a valid table. The only major difference from passing ActiveRecord objects is that this mechanism will not translate table headings.
|
76
|
+
|
77
|
+
If you've got a Hash, you can use OpenStruct to make the data available via methods. Giving:
|
78
|
+
|
79
|
+
<% require 'ostruct' %>
|
80
|
+
{: .hidden}
|
81
|
+
|
82
|
+
<table fields="a,b" with="&[OpenStruct.new(:a => 1, :b => 2), OpenStruct.new(:a => 3, :b => 4)]">
|
83
|
+
<a-heading:>A</a-heading:>
|
84
|
+
<b-heading:>B</b-heading:>
|
85
|
+
</table>
|
86
|
+
|
87
|
+
Produces:
|
88
|
+
|
89
|
+
<table>
|
90
|
+
<thead>
|
91
|
+
<tr class='field-heading-row'>
|
92
|
+
<th class='a-heading'>A</th>
|
93
|
+
<th class='b-heading'>B</th>
|
94
|
+
</tr>
|
95
|
+
</thead>
|
96
|
+
<tbody>
|
97
|
+
<tr class='odd open_struct'>
|
98
|
+
<td class='a-view'><span class='view '>1</span></td>
|
99
|
+
<td class='b-view'><span class='view '>2</span></td>
|
100
|
+
</tr>
|
101
|
+
<tr class='even open_struct'>
|
102
|
+
<td class='a-view'><span class='view '>3</span></td>
|
103
|
+
<td class='b-view'><span class='view '>4</span></td>
|
104
|
+
</tr>
|
105
|
+
</tbody>
|
106
|
+
</table>
|
107
|
+
|
108
|
+
#### without the magic
|
109
|
+
|
110
|
+
If you don't use either the fields attribute or the tr parameter, all processing is turned off, and your table is emitted verbatim. Giving:
|
111
|
+
|
112
|
+
<table>
|
113
|
+
<thead>
|
114
|
+
<tr><th>a</th></tr>
|
115
|
+
</thead>
|
116
|
+
<tbody>
|
117
|
+
<tr><td>b</td></tr>
|
118
|
+
</tbody>
|
119
|
+
</table>
|
120
|
+
|
121
|
+
Will emit the above table verbatim.
|
122
|
+
|
123
|
+
Produces:
|
124
|
+
{: .hidden}
|
125
|
+
|
126
|
+
<table>
|
127
|
+
<thead>
|
128
|
+
<tr><th>a</th></tr>
|
129
|
+
</thead>
|
130
|
+
<tbody>
|
131
|
+
<tr><td>b</td></tr>
|
132
|
+
</tbody>
|
133
|
+
</table>
|
134
|
+
{: .hidden}
|
135
|
+
-->
|
136
|
+
<def tag="table" attrs="fields, field-tag, empty">
|
137
|
+
<if test="&!(fields || all_parameters.tr?)">
|
138
|
+
<%= element("table", attributes, all_parameters.default) %>
|
139
|
+
</if>
|
140
|
+
<else>
|
141
|
+
<% field_tag ||= "view" %>
|
142
|
+
<unless test="&this.empty? && !empty">
|
143
|
+
<%= element "table", attributes - attrs_for(:with_fields) do %>
|
144
|
+
<thead if="&all_parameters[:thead] || fields" param>
|
145
|
+
<tr param="field-heading-row">
|
146
|
+
<with-field-names merge-attrs="&all_attributes & attrs_for(:with_fields)">
|
147
|
+
<th param="#{scope.field_name}-heading"><%= this.member_class ? this.member_class.human_attribute_name(scope.field_name) : scope.field_name.to_s.titleize %></th>
|
148
|
+
</with-field-names>
|
149
|
+
<th if="&all_parameters[:controls]" class="controls"/>
|
150
|
+
</tr>
|
151
|
+
</thead>
|
152
|
+
<tbody param>
|
153
|
+
<repeat>
|
154
|
+
<tr param if="&can_view?"
|
155
|
+
class="#{scope.even_odd} #{this_type.name.underscore}" data-rapid-context="&typed_id">
|
156
|
+
<if test="&fields">
|
157
|
+
<with-fields merge-attrs="&all_attributes & attrs_for(:with_fields)" force-all>
|
158
|
+
<td param="#{scope.field_name.to_s.sub('?', '').gsub('.', '-')}-view"><call-tag tag="&field_tag"/></td>
|
159
|
+
</with-fields>
|
160
|
+
<td class="controls" param="controls" if="&all_parameters[:controls]">
|
161
|
+
<a param="edit-link" action="edit" if="&can_edit?">
|
162
|
+
<t key="hobo.actions.edit_control">Edit</t>
|
163
|
+
</a>
|
164
|
+
<delete-button param/>
|
165
|
+
</td>
|
166
|
+
</if>
|
167
|
+
</tr>
|
168
|
+
</repeat>
|
169
|
+
</tbody>
|
170
|
+
<tfoot if="&all_parameters[:tfoot]" param/>
|
171
|
+
<% end %>
|
172
|
+
</unless>
|
173
|
+
</else>
|
174
|
+
</def>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<!--
|
2
|
+
Wrapper around the Rails :translate helper with hobo added features.
|
3
|
+
|
4
|
+
It can be used as a regular helper or as a dryml tag.
|
5
|
+
|
6
|
+
### Hobo Added Features
|
7
|
+
|
8
|
+
`ht` adds some conventions for easier hobo translation.
|
9
|
+
|
10
|
+
1. Assumes the first part of the key to be a model name (e.g.: users.index.title -> user)
|
11
|
+
2. Tries to translate the model by lookup for: (e.g.: user-> activerecord.models.user)
|
12
|
+
3. Adds a default fallback to the beginning of the fallback chain by replacing the first part of the key with "hobo" and using the translated model name as additional attribute. This allows us to have default translations (e.g.: hobo.index.title: "{{model}} Index")
|
13
|
+
|
14
|
+
You can also pass any other :translate option like for example :count.
|
15
|
+
|
16
|
+
Is also used as a tag in the dryml-view files. The syntax is:
|
17
|
+
|
18
|
+
<ht key="my.app">My Application</ht>
|
19
|
+
|
20
|
+
Will lookup the "my.app"-key for your locale and replaces the "My Application" content if found.
|
21
|
+
|
22
|
+
<ht key="my" app="Program">My Application</ht>
|
23
|
+
|
24
|
+
Will look up both the "my"- and "app"-key for your locale, and replaces the "My Application" with the "my"-key contents (interpolated using the "app"-key.
|
25
|
+
|
26
|
+
sample.no.yml-file:
|
27
|
+
|
28
|
+
"no":
|
29
|
+
my: "Mitt {{app}}"
|
30
|
+
|
31
|
+
The output should be: Mitt Program
|
32
|
+
|
33
|
+
Another example:
|
34
|
+
|
35
|
+
<%= ht :key=>'user.index.title', :default=>'Index' %>
|
36
|
+
<ht key="user.index.title">Index</ht>
|
37
|
+
#=> "Index" # if "user.index.title" or "hobo.index.title" is not found
|
38
|
+
#=> "User Index" # with the below en.yml file
|
39
|
+
|
40
|
+
=== en.yml ===
|
41
|
+
en:
|
42
|
+
hobo:
|
43
|
+
index:
|
44
|
+
title: %{model} Index
|
45
|
+
-->
|
46
|
+
<fakedef tag="ht">
|
47
|
+
<!-- actually defined in translations.rb -->
|
48
|
+
</fakedef>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!-- Wrapper around ActiveRecord::Base.human_attribute_name.
|
2
|
+
|
3
|
+
#### Attributes
|
4
|
+
|
5
|
+
- attribute - the attribute to lookup
|
6
|
+
- model - (optional) should be a model class or a record object (default to this)
|
7
|
+
- count - (optional) should be an integer
|
8
|
+
|
9
|
+
-->
|
10
|
+
<def tag="human-attribute-name" attrs="attribute, model"><%=
|
11
|
+
model ||= this
|
12
|
+
model = model.class unless model.kind_of? Class
|
13
|
+
# prepare symbolized attributes for merging
|
14
|
+
attrs = {}
|
15
|
+
all_attributes.each_pair{|k,v| attrs[k.to_sym] = v}
|
16
|
+
model.human_attribute_name( attribute.to_sym, attrs )
|
17
|
+
%>
|
18
|
+
</def>
|
@@ -0,0 +1,69 @@
|
|
1
|
+
<!-- Used to localize and pluralize collection names.
|
2
|
+
A collection name is a special case of an attribute name, (indeed you should store the collection names as attribute names in the locale files), so this tag internally uses human_attribute_name to return them.
|
3
|
+
|
4
|
+
With the `your` attribute and in the special case the context is a Hobo::Model::UserMixin instance it automatically embeds the `your` tag funtionality. (note: :name is added by default as an interpolable variable)
|
5
|
+
|
6
|
+
### Attributes
|
7
|
+
|
8
|
+
- collection - the attribute/collection key to lookup in the `activerecord.attributes` namespace. (e.g. 'roles')
|
9
|
+
- count - used to pick the inflected string for the collection. It should be an integer.
|
10
|
+
- your - wraps the collection name in a `Your` tag
|
11
|
+
|
12
|
+
### Example
|
13
|
+
|
14
|
+
|
15
|
+
it:
|
16
|
+
activerecord:
|
17
|
+
attributes:
|
18
|
+
post:
|
19
|
+
comments:
|
20
|
+
one: "Commento"
|
21
|
+
other: "Commenti"
|
22
|
+
user:
|
23
|
+
roles:
|
24
|
+
one: "Ruolo"
|
25
|
+
other: "Ruoli"
|
26
|
+
tags:
|
27
|
+
your:
|
28
|
+
roles:
|
29
|
+
current_user:
|
30
|
+
one: "Il tuo Ruolo"
|
31
|
+
other: "I tuoi Ruoli"
|
32
|
+
other_user:
|
33
|
+
one: "Ruolo di {{name}}"
|
34
|
+
other: Ruoli di {{name}}"
|
35
|
+
|
36
|
+
context is a Post instance ('your' is ignored)
|
37
|
+
|
38
|
+
<human-collection-name collection="comments" count="&user.comments.count" your/>
|
39
|
+
I18n.locale = :en => "Comment" or "Comments"
|
40
|
+
I18n.locale = :it => "Commento" or "Commenti"
|
41
|
+
|
42
|
+
context is a User instance
|
43
|
+
|
44
|
+
<human-collection-name collection="roles' count="&user.roles.count" your/>
|
45
|
+
I18n.locale = :en => "Your Role" or "Jim's Role" or "Your Roles" or "Jim's Roles"
|
46
|
+
I18n.locale = :it => "Il tuo Ruolo" or "Il Ruolo di Jim" or "I tuoi Ruoli" or "I Ruoli di Jim"
|
47
|
+
|
48
|
+
(output is the same as `<Your key="roles" count=>"&user.roles.count"/>`)
|
49
|
+
|
50
|
+
<human-collection-name collection="roles" count="&user.roles.count"/>
|
51
|
+
I18n.locale = :en => "Role" or "Roles"
|
52
|
+
I18n.locale = :it => "Ruolo" or "Ruoli"
|
53
|
+
-->
|
54
|
+
<def tag="human-collection-name" attrs="collection, count, your"><%
|
55
|
+
raise Hobo::Error, "The 'collection' attribute must be defined" if collection.blank?
|
56
|
+
belong_class = this.kind_of?(Class) ? this : this.class
|
57
|
+
raise Hobo::Error, "The context is not an ActiveRecord::Base instance or class. (this = #{this.typed_id rescue this.inspect})" unless belong_class < ActiveRecord::Base
|
58
|
+
# prepare symbolized attributes for merging
|
59
|
+
attrs = {}
|
60
|
+
all_attributes.each_pair{|k,v| attrs[k.to_sym] = v} -%>
|
61
|
+
<% if your && belong_class < Hobo::Model::UserBase && this.kind_of?(Hobo::Model::UserBase) && I18n.locale == :en -%>
|
62
|
+
<your key="&collection" merge-attrs="&{:name=>name(:no_wrapper => true)}.merge(attrs)" capitalize>
|
63
|
+
<%= belong_class.human_attribute_name(collection.to_sym, attrs) %>
|
64
|
+
</your>
|
65
|
+
<% else -%>
|
66
|
+
<%= belong_class.human_attribute_name( collection.to_sym, attrs ) %>
|
67
|
+
<% end %>
|
68
|
+
</def>
|
69
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
<!-- Rapid i18n provides tags related with the Rails-I18n project -->
|