radiant-library-extension 2.0.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.
@@ -0,0 +1,276 @@
1
+ module Library
2
+ module LibraryTags
3
+ include Radiant::Taggable
4
+
5
+ class TagError < StandardError; end
6
+
7
+ ############### tags for use on library pages
8
+ # usually to build a faceted browser
9
+
10
+ tag "library" do |tag|
11
+ raise TagError, "library:* tags can only be used on a LibraryPage" unless tag.locals.page && tag.locals.page.is_a?(LibraryPage)
12
+ tag.expand
13
+ end
14
+
15
+ desc %{
16
+ Displays a list of the tags that can be used to narrow the set of results displayed. This begins as a list of
17
+ all available tags, and as they are chosen it shrinks to show only the coincident tags that will further reduce the set.
18
+
19
+ This is normally used to display a list or cloud of facets that can be added to a search. The default is to show a cloud.
20
+
21
+ <pre><code>
22
+ <r:library:tags:each><li><r:tag:link /></li></r:library:tags:each>
23
+ <r:library:tags:list />
24
+ <r:library:tags:cloud />
25
+ <r:library:tags />
26
+ </code></pre>
27
+
28
+ To show only those tags attached to a particular kind of object, supply a 'for' parameter.
29
+ The parameter can be 'pages', 'assets' or the plural of any asset type. If you're displaying an image gallery,
30
+ you may want to start with a cloud of all the tags that have been applied to images:
31
+
32
+ <pre><code>
33
+ <r:library:tags for="images" />
34
+ </code></pre>
35
+
36
+ You can still display pages associated with those tags, but the list will not include tags that only have pages.
37
+ }
38
+ tag "library:tags" do |tag|
39
+ tag.locals.tags = _get_coincident_tags(tag)
40
+ if tag.double?
41
+ tag.expand
42
+ else
43
+ tag.render('tags:cloud', tag.attr.dup)
44
+ end
45
+ end
46
+ tag "library:tags:each" do |tag|
47
+ tag.render('tags:each', tag.attr.dup, &tag.block)
48
+ end
49
+ tag "library:tags:list" do |tag|
50
+ tag.render('tags:list', tag.attr.dup)
51
+ end
52
+ tag "library:tags:cloud" do |tag|
53
+ tag.render('tags:cloud', tag.attr.dup)
54
+ end
55
+
56
+
57
+ desc %{
58
+ Expands if there are is more than one tag to show.
59
+ (If there is only one tag coincident with the present set then it offers no reduction).
60
+
61
+ *Usage:*
62
+ <pre><code>
63
+ <r:library:if_tags>
64
+ Displaying items tagged with all of <r:requested_tags />
65
+ <r:library:if_requested_tags>
66
+ </code></pre>
67
+ }
68
+ tag "library:unless_tags" do |tag|
69
+ tag.locals.tags = _get_coincident_tags(tag)
70
+ tag.expand if tag.locals.tags.length > 1
71
+ end
72
+ desc %{
73
+ Expands if there are is more than one tag to show.
74
+ (If there is only one tag coincident with the present set then it offers no reduction, so we don't show it).
75
+
76
+ *Usage:*
77
+ <pre><code>
78
+ <r:library:if_tags><r:library:tags /></r:library:if_tags>
79
+ </code></pre>
80
+ }
81
+ tag "library:if_tags" do |tag|
82
+ tag.locals.tags = _get_coincident_tags(tag)
83
+ tag.expand if tag.locals.tags.length > 1
84
+ end
85
+
86
+ desc %{
87
+ Expands if there are is one or no coincident tags to show.
88
+ }
89
+ tag "library:unless_tags" do |tag|
90
+ tag.expand unless _get_coincident_tags(tag).length > 1
91
+ end
92
+
93
+ desc %{
94
+ Displays a list of the tags requested by the user.
95
+ To offer links that remove the tag from the current set, these will both work:
96
+
97
+ *Usage:*
98
+ <pre><code>
99
+ <r:library:requested_tags:each><li><r:tag:unlink /></li></r:library:requested_tags:each>
100
+ <r:library:requested_tags />
101
+ </code></pre>
102
+ }
103
+ tag "library:requested_tags" do |tag|
104
+ tag.locals.tags = _get_requested_tags(tag)
105
+ if tag.double?
106
+ tag.expand
107
+ else
108
+ tag.render('tags:unlink_list', tag.attr.dup)
109
+ end
110
+ end
111
+ tag "library:requested_tags:each" do |tag|
112
+ tag.render('tags:each', tag.attr.dup, &tag.block)
113
+ end
114
+
115
+ desc %{
116
+ Expands if any tags have been specified:
117
+
118
+ *Usage:*
119
+ <pre><code>
120
+ <r:library:if_requested_tags>
121
+ Displaying items tagged with all of <r:requested_tags />
122
+ <r:library:if_requested_tags>
123
+ </code></pre>
124
+ }
125
+ tag "library:if_requested_tags" do |tag|
126
+ tag.locals.tags = _get_requested_tags(tag)
127
+ tag.expand if tag.locals.tags.any?
128
+ end
129
+
130
+ desc %{
131
+ Expands if no tags have been specified:
132
+
133
+ *Usage:*
134
+ <pre><code>
135
+ <r:library:unless_requested_tags>
136
+ Showing everything. Choose a tag to start narrowing down the list.
137
+ <r:library:unless_requested_tags>
138
+ </code></pre>
139
+ }
140
+ tag "library:unless_requested_tags" do |tag|
141
+ tag.expand unless _get_requested_tags(tag).any?
142
+ end
143
+
144
+ desc %{
145
+ Displays a list of the pages associated with the current tag set. If no tags are specified, this will show all pages.
146
+ You can use all the usual r:page tags within the list.
147
+
148
+ *Usage:*
149
+ <pre><code>
150
+ <r:library:pages:each><li><r:link /><br /><r:content part="description" /></li></r:library:pages:each>
151
+ </code></pre>
152
+ }
153
+ tag "library:pages" do |tag|
154
+ tag.locals.pages = _get_pages(tag)
155
+ tag.expand
156
+ end
157
+ tag "library:pages:each" do |tag|
158
+ tag.render('page_list', tag.attr.dup, &tag.block) # r:page_list is defined in taggable
159
+ end
160
+
161
+ desc %{
162
+ Expands if there are any pages associated with all of the current tag set.
163
+
164
+ *Usage:*
165
+ <pre><code>
166
+ <r:library:if_pages><h2>Pages</h2>...</r:library:if_pages>
167
+ </code></pre>
168
+ }
169
+ tag "library:if_pages" do |tag|
170
+ tag.expand if _get_pages(tag).any?
171
+ end
172
+
173
+ desc %{
174
+ Displays a list of the assets associated with the current tag set. If no tags are specified, this will show all assets.
175
+ You can use all the usual r:assets tags within the list.
176
+
177
+ *Usage:*
178
+ <pre><code>
179
+ <r:library:assets:each><li><r:assets:thumbnail /></li></r:library:assets:each>
180
+ </code></pre>
181
+ }
182
+ tag "library:assets" do |tag|
183
+ tag.locals.assets = _get_assets(tag)
184
+ tag.expand
185
+ end
186
+ tag "library:assets:each" do |tag|
187
+ tag.render('asset_list', tag.attr.dup, &tag.block)
188
+ end
189
+
190
+ desc %{
191
+ Expands if there are any assets associated with all of the current tag set.
192
+
193
+ *Usage:*
194
+ <pre><code>
195
+ <r:library:if_assets><h2>Assets</h2>...</r:library:if_assets>
196
+ </code></pre>
197
+ }
198
+ tag "library:if_assets" do |tag|
199
+ tag.expand if _get_assets(tag).any?
200
+ end
201
+
202
+ Asset.known_types.each do |type|
203
+ these = type.to_s.pluralize
204
+
205
+ desc %{
206
+ Displays a list of the all the #{these} associated with the current tag set. If no tags are specified, this will show all such assets.
207
+ You can use all the usual r:assets tags within the list.
208
+
209
+ *Usage:*
210
+ <pre><code>
211
+ <r:library:#{these}:each><li><r:assets:link /></li></r:library:#{these}:each>
212
+ </code></pre>
213
+ }
214
+ tag "library:#{these}" do |tag|
215
+ tag.locals.assets = _get_assets(tag).send(these.intern)
216
+ tag.expand
217
+ end
218
+ tag "library:#{these}:each" do |tag|
219
+ tag.render('asset_list', tag.attr.dup, &tag.block)
220
+ end
221
+
222
+ desc %{
223
+ Expands if there are any #{these} associated with all of the current tag set.
224
+
225
+ *Usage:*
226
+ <pre><code>
227
+ <r:library:if_#{these}><h2>#{these.titlecase}</h2>...</r:library:if_#{these}>
228
+ </code></pre>
229
+ }
230
+ tag "library:if_#{these}" do |tag|
231
+ tag.locals.assets = _get_assets(tag).send(these.intern)
232
+ tag.expand if tag.locals.assets.any?
233
+ end
234
+
235
+ private
236
+
237
+ def _get_requested_tags(tag)
238
+ tag.locals.page.requested_tags
239
+ end
240
+
241
+ def _get_coincident_tags(tag)
242
+ requested = _get_requested_tags(tag)
243
+ limit = tag.attr['limit'] || 50
244
+ if requested.any?
245
+ Tag.coincident_with(requested)
246
+ else
247
+ Tag.most_popular(limit)
248
+ end
249
+ end
250
+ end
251
+
252
+ # in the absence of any requested tags we default to all, not none
253
+
254
+ def _get_pages(tag)
255
+ requested = _get_requested_tags(tag)
256
+ if requested.any?
257
+ Page.tagged_with(requested)
258
+ else
259
+ Page.scoped({}) # there must be a better way to return a new scope
260
+ end
261
+ end
262
+
263
+ def _get_assets(tag)
264
+ requested = _get_requested_tags(tag)
265
+ if requested.any?
266
+ Asset.tagged_with(requested)
267
+ else
268
+ Asset.scoped({})
269
+ end
270
+ end
271
+
272
+ end
273
+
274
+ end
275
+
276
+
@@ -0,0 +1,22 @@
1
+ # This handy simplification is adapted from SphinxSearch (thanks)
2
+ # and originally came from Ultrasphinx
3
+ # it saves us a lot of including and bodging to make will_paginate's template calls work in the Page model
4
+
5
+ module Library
6
+ class LinkRenderer < WillPaginate::LinkRenderer
7
+ def initialize(tag)
8
+ @tag = tag
9
+ end
10
+
11
+ def page_link(page, text, attributes = {})
12
+ linkclass = %{ class="#{attributes[:class]}"} if attributes[:class]
13
+ linkrel = %{ rel="#{attributes[:rel]}"} if attributes[:rel]
14
+ %Q{<a href="#{@tag.locals.page.url}?page=#{page}"#{linkrel}#{linkclass}>#{text}</a>}
15
+ end
16
+
17
+ def page_span(page, text, attributes = {})
18
+ spanclass = attributes[:class]
19
+ %{<span class="#{attributes[:class]}">#{text}</span>}
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,151 @@
1
+ module Library
2
+ module MoreAssetTags
3
+ include Radiant::Taggable
4
+
5
+ class TagError < StandardError; end
6
+
7
+ ############### assets: tags for displaying tags and relatives when we have an asset
8
+ # similar tags already exist for pages
9
+
10
+ desc %{
11
+ Cycles through all tags attached to present asset.
12
+
13
+ *Usage:*
14
+ <pre><code><r:assets:tags><r:tag:title /></r:assets:tags></code></pre>
15
+ }
16
+ tag 'assets:tags' do |tag|
17
+ raise TagError, "asset must be defined for asset:tags tag" unless tag.locals.asset
18
+ tag.locals.tags = tag.locals.asset.tags
19
+ tag.expand
20
+ end
21
+ tag 'assets:tags:each' do |tag|
22
+ tag.render('tags:each', tag.attr.dup, &tag.block)
23
+ end
24
+
25
+ desc %{
26
+ Lists all the assets similar to this asset (based on its tagging), in descending order of relatedness.
27
+
28
+ *Usage:*
29
+ <pre><code><r:related_assets:each>...</r:related_assets:each></code></pre>
30
+ }
31
+ tag 'related_assets' do |tag|
32
+ raise TagError, "asset must be defined for related_assets tag" unless tag.locals.asset
33
+ tag.locals.assets = tag.locals.asset.related_assets
34
+ tag.expand
35
+ end
36
+ tag 'related_assets:each' do |tag|
37
+ tag.render('assets:each', tag.attr.dup, &tag.block)
38
+ end
39
+
40
+ ############### extra asset fields
41
+
42
+ [:copyright].each do |method|
43
+ desc %{
44
+ Expands if the asset has a #{method} notice.
45
+ The 'title' attribute is required on this tag or the parent tag.
46
+ }
47
+ tag "assets:if_#{method.to_s}" do |tag|
48
+ options = tag.attr.dup
49
+ asset = find_asset(tag, options)
50
+ tag.expand if asset.respond_to?(method) && asset.send(method)
51
+ end
52
+
53
+ desc %{
54
+ Expands unless the asset has a #{method} notice.
55
+ The 'title' attribute is required on this tag or the parent tag.
56
+ }
57
+ tag "assets:unless_#{method.to_s}" do |tag|
58
+ options = tag.attr.dup
59
+ asset = find_asset(tag, options)
60
+ tag.expand unless asset.respond_to?(method) && asset.send(method)
61
+ end
62
+
63
+ desc %{
64
+ Renders the `#{method.to_s}' attribute of the asset.
65
+ The 'title' attribute is required on this tag or the parent tag.
66
+ }
67
+ tag "assets:#{method.to_s}" do |tag|
68
+ options = tag.attr.dup
69
+ asset = find_asset(tag, options)
70
+ asset.send(method) rescue nil
71
+ end
72
+ end
73
+
74
+ ############### useful shorthands
75
+
76
+ desc %{
77
+ Renders an illustration block for the asset, with image and caption.
78
+
79
+ *Usage:*
80
+ <pre><code><r:assets:image [title="asset_title"] [size="icon|thumbnail"]></code></pre>
81
+ }
82
+ tag "assets:illustration" do |tag|
83
+ options = tag.attr.dup
84
+ options['size'] ||= 'illustration'
85
+ tag.locals.asset = find_asset(tag, options)
86
+ if tag.locals.asset.image?
87
+ result = %{<div class="illustration">}
88
+ result << tag.render('assets:image', options)
89
+ result << %{<p class="caption">#{tag.render('assets:caption', options)}</p>}
90
+ result << "</div>"
91
+ result
92
+ end
93
+ end
94
+
95
+ desc %{
96
+ Presents a standard marginal gallery block suitable for turning unobtrusively into a rollover or lightbox gallery.
97
+ We need to be able to work out a collection of assets: that can be defined already (eg by assets:all) or come from the current page.
98
+ Default preview size is 'large' and thumbnail size 'thumbnail' but you can specify any of your asset sizes.
99
+
100
+ *Usage:*
101
+ <pre><code>
102
+ <r:assets:images>
103
+ <r:assets:minigallery [size="..."] [thumbnail_size="..."] [tags="one,or,more,tags"] />
104
+ </r:assets:images>
105
+ </code></pre>
106
+
107
+ }
108
+ tag 'assets:minigallery' do |tag|
109
+ options = tag.attr.dup.symbolize_keys
110
+ raise TagError, "asset collection must be available for assets:minigallery tag" unless tag.locals.assets or tag.locals.page or tag.attr[:tags]
111
+ if options[:tags] && tags = Tag.from_list(options[:tags])
112
+ tag.locals.assets = Asset.images.from_all_tags(tags)
113
+ else
114
+ tag.locals.assets = tag.locals.page.assets
115
+ end
116
+ tag.locals.assets.images.to_a # because we can't let empty? trigger a call to count
117
+
118
+ unless tag.locals.assets.empty?
119
+ size = tag.attr['size'] || 'illustration'
120
+ thumbsize = tag.attr['thumbnail_size'] || 'icon'
121
+ result = ""
122
+ result << %{
123
+ <div class="minigallery">}
124
+ tag.locals.asset = tag.locals.assets.first
125
+ result << tag.render('assets:image', {'size' => size})
126
+ result << %{
127
+ <p class="caption">#{tag.render('assets:caption')}</p>
128
+ <ul class="thumbnails">}
129
+ if tag.locals.assets.size > 1
130
+ tag.locals.assets.each do |asset|
131
+ tag.locals.asset = asset
132
+ result << %{
133
+ <li class="thumbnail">
134
+ <a href="#{tag.render('assets:url', 'size' => 'illustration')}" title="#{asset.caption}" id="thumbnail_#{asset.id}">
135
+ }
136
+ result << tag.render('assets:image', {'size' => thumbsize, 'alt' => asset.title})
137
+ result << %{
138
+ </a>
139
+ </li>}
140
+ end
141
+ end
142
+ result << %{
143
+ </ul>
144
+ </div>}
145
+ result
146
+ end
147
+ end
148
+
149
+ end
150
+ end
151
+