raw 0.49.0
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/CONTRIBUTORS +106 -0
- data/doc/LICENSE +32 -0
- data/doc/coding_conventions.txt +11 -0
- data/lib/raw.rb +42 -0
- data/lib/raw/adapter.rb +113 -0
- data/lib/raw/adapter/cgi.rb +41 -0
- data/lib/raw/adapter/fastcgi.rb +48 -0
- data/lib/raw/adapter/mongrel.rb +146 -0
- data/lib/raw/adapter/script.rb +94 -0
- data/lib/raw/adapter/webrick.rb +144 -0
- data/lib/raw/adapter/webrick/vcr.rb +91 -0
- data/lib/raw/cgi.rb +323 -0
- data/lib/raw/cgi/cookie.rb +47 -0
- data/lib/raw/cgi/http.rb +62 -0
- data/lib/raw/compiler.rb +138 -0
- data/lib/raw/compiler/filter/cleanup.rb +21 -0
- data/lib/raw/compiler/filter/elements.rb +166 -0
- data/lib/raw/compiler/filter/elements/element.rb +210 -0
- data/lib/raw/compiler/filter/localization.rb +23 -0
- data/lib/raw/compiler/filter/markup.rb +32 -0
- data/lib/raw/compiler/filter/morph.rb +123 -0
- data/lib/raw/compiler/filter/morph/each.rb +34 -0
- data/lib/raw/compiler/filter/morph/for.rb +11 -0
- data/lib/raw/compiler/filter/morph/if.rb +26 -0
- data/lib/raw/compiler/filter/morph/selected_if.rb +43 -0
- data/lib/raw/compiler/filter/morph/standard.rb +55 -0
- data/lib/raw/compiler/filter/morph/times.rb +27 -0
- data/lib/raw/compiler/filter/script.rb +116 -0
- data/lib/raw/compiler/filter/squeeze.rb +16 -0
- data/lib/raw/compiler/filter/static_include.rb +74 -0
- data/lib/raw/compiler/filter/template.rb +121 -0
- data/lib/raw/compiler/reloader.rb +96 -0
- data/lib/raw/context.rb +154 -0
- data/lib/raw/context/flash.rb +157 -0
- data/lib/raw/context/global.rb +88 -0
- data/lib/raw/context/request.rb +338 -0
- data/lib/raw/context/response.rb +57 -0
- data/lib/raw/context/session.rb +198 -0
- data/lib/raw/context/session/drb.rb +11 -0
- data/lib/raw/context/session/file.rb +15 -0
- data/lib/raw/context/session/memcached.rb +13 -0
- data/lib/raw/context/session/memory.rb +12 -0
- data/lib/raw/context/session/og.rb +15 -0
- data/lib/raw/context/session/pstore.rb +13 -0
- data/lib/raw/control.rb +18 -0
- data/lib/raw/control/attribute.rb +91 -0
- data/lib/raw/control/attribute/checkbox.rb +25 -0
- data/lib/raw/control/attribute/datetime.rb +21 -0
- data/lib/raw/control/attribute/file.rb +20 -0
- data/lib/raw/control/attribute/fixnum.rb +26 -0
- data/lib/raw/control/attribute/float.rb +26 -0
- data/lib/raw/control/attribute/options.rb +38 -0
- data/lib/raw/control/attribute/password.rb +16 -0
- data/lib/raw/control/attribute/text.rb +16 -0
- data/lib/raw/control/attribute/textarea.rb +16 -0
- data/lib/raw/control/none.rb +16 -0
- data/lib/raw/control/relation.rb +59 -0
- data/lib/raw/control/relation/belongs_to.rb +0 -0
- data/lib/raw/control/relation/has_many.rb +97 -0
- data/lib/raw/control/relation/joins_many.rb +0 -0
- data/lib/raw/control/relation/many_to_many.rb +0 -0
- data/lib/raw/control/relation/refers_to.rb +29 -0
- data/lib/raw/controller.rb +37 -0
- data/lib/raw/controller/publishable.rb +160 -0
- data/lib/raw/dispatcher.rb +209 -0
- data/lib/raw/dispatcher/format.rb +108 -0
- data/lib/raw/dispatcher/format/atom.rb +31 -0
- data/lib/raw/dispatcher/format/css.rb +0 -0
- data/lib/raw/dispatcher/format/html.rb +42 -0
- data/lib/raw/dispatcher/format/json.rb +31 -0
- data/lib/raw/dispatcher/format/rss.rb +33 -0
- data/lib/raw/dispatcher/format/xoxo.rb +31 -0
- data/lib/raw/dispatcher/mounter.rb +60 -0
- data/lib/raw/dispatcher/router.rb +111 -0
- data/lib/raw/errors.rb +19 -0
- data/lib/raw/helper.rb +86 -0
- data/lib/raw/helper/benchmark.rb +23 -0
- data/lib/raw/helper/buffer.rb +60 -0
- data/lib/raw/helper/cookie.rb +32 -0
- data/lib/raw/helper/debug.rb +28 -0
- data/lib/raw/helper/default.rb +16 -0
- data/lib/raw/helper/feed.rb +451 -0
- data/lib/raw/helper/form.rb +284 -0
- data/lib/raw/helper/javascript.rb +59 -0
- data/lib/raw/helper/layout.rb +40 -0
- data/lib/raw/helper/navigation.rb +87 -0
- data/lib/raw/helper/pager.rb +305 -0
- data/lib/raw/helper/table.rb +247 -0
- data/lib/raw/helper/xhtml.rb +218 -0
- data/lib/raw/helper/xml.rb +125 -0
- data/lib/raw/mixin/magick.rb +35 -0
- data/lib/raw/mixin/sweeper.rb +71 -0
- data/lib/raw/mixin/thumbnails.rb +1 -0
- data/lib/raw/mixin/webfile.rb +165 -0
- data/lib/raw/render.rb +271 -0
- data/lib/raw/render/builder.rb +26 -0
- data/lib/raw/render/caching.rb +81 -0
- data/lib/raw/render/call.rb +43 -0
- data/lib/raw/render/send_file.rb +46 -0
- data/lib/raw/render/stream.rb +39 -0
- data/lib/raw/scaffold.rb +13 -0
- data/lib/raw/scaffold/controller.rb +25 -0
- data/lib/raw/scaffold/model.rb +157 -0
- data/lib/raw/test.rb +5 -0
- data/lib/raw/test/assertions.rb +169 -0
- data/lib/raw/test/context.rb +55 -0
- data/lib/raw/test/testcase.rb +79 -0
- data/lib/raw/util/attr.rb +128 -0
- data/lib/raw/util/encode_uri.rb +149 -0
- data/lib/raw/util/html_filter.rb +538 -0
- data/lib/raw/util/markup.rb +130 -0
- data/test/glue/tc_webfile.rb +1 -0
- data/test/nitro/CONFIG.rb +3 -0
- data/test/nitro/adapter/raw_post1.bin +9 -0
- data/test/nitro/adapter/tc_webrick.rb +16 -0
- data/test/nitro/cgi/tc_cookie.rb +14 -0
- data/test/nitro/cgi/tc_request.rb +61 -0
- data/test/nitro/compiler/tc_client_morpher.rb +47 -0
- data/test/nitro/compiler/tc_compiler.rb +25 -0
- data/test/nitro/dispatcher/tc_mounter.rb +47 -0
- data/test/nitro/helper/tc_feed.rb +135 -0
- data/test/nitro/helper/tc_navbar.rb +74 -0
- data/test/nitro/helper/tc_pager.rb +35 -0
- data/test/nitro/helper/tc_table.rb +68 -0
- data/test/nitro/helper/tc_xhtml.rb +19 -0
- data/test/nitro/tc_caching.rb +19 -0
- data/test/nitro/tc_cgi.rb +222 -0
- data/test/nitro/tc_context.rb +17 -0
- data/test/nitro/tc_controller.rb +103 -0
- data/test/nitro/tc_controller_aspect.rb +32 -0
- data/test/nitro/tc_controller_params.rb +885 -0
- data/test/nitro/tc_dispatcher.rb +109 -0
- data/test/nitro/tc_element.rb +85 -0
- data/test/nitro/tc_flash.rb +59 -0
- data/test/nitro/tc_helper.rb +47 -0
- data/test/nitro/tc_render.rb +119 -0
- data/test/nitro/tc_router.rb +61 -0
- data/test/nitro/tc_server.rb +35 -0
- data/test/nitro/tc_session.rb +66 -0
- data/test/nitro/tc_template.rb +71 -0
- data/test/nitro/util/tc_encode_url.rb +87 -0
- data/test/nitro/util/tc_markup.rb +31 -0
- data/test/public/blog/another/very_litle/index.xhtml +1 -0
- data/test/public/blog/inc1.xhtml +2 -0
- data/test/public/blog/inc2.xhtml +1 -0
- data/test/public/blog/list.xhtml +9 -0
- data/test/public/dummy_mailer/registration.xhtml +5 -0
- metadata +244 -0
@@ -0,0 +1,305 @@
|
|
1
|
+
require 'facets/more/settings'
|
2
|
+
|
3
|
+
require 'og/collection'
|
4
|
+
|
5
|
+
module Raw
|
6
|
+
|
7
|
+
# Displays a collection of entitities in multiple pages.
|
8
|
+
#
|
9
|
+
# === Design
|
10
|
+
#
|
11
|
+
# This pager is carefully designed for scaleability. It stores
|
12
|
+
# only the items for one page. The key parameter is needed,
|
13
|
+
# multiple pagers can coexist in a single page. The pager
|
14
|
+
# leverages the SQL LIMIT option to optimize database
|
15
|
+
# interaction.
|
16
|
+
|
17
|
+
class Pager
|
18
|
+
# Items per page.
|
19
|
+
|
20
|
+
setting :per_page, :default => 10, :doc => 'Items per page'
|
21
|
+
|
22
|
+
# The request key.
|
23
|
+
|
24
|
+
setting :key, :default => '_page', :doc => 'The request key'
|
25
|
+
|
26
|
+
# The current page.
|
27
|
+
|
28
|
+
attr_accessor :page
|
29
|
+
|
30
|
+
# Items per page.
|
31
|
+
|
32
|
+
attr_accessor :per_page
|
33
|
+
|
34
|
+
# The total number of pages.
|
35
|
+
|
36
|
+
attr_accessor :page_count
|
37
|
+
|
38
|
+
# Total count of items.
|
39
|
+
|
40
|
+
attr_accessor :total_count
|
41
|
+
|
42
|
+
def initialize(request, per_page, total_count, key = Pager.key)
|
43
|
+
raise 'per_page should be > 0' unless per_page > 0
|
44
|
+
|
45
|
+
@request, @key = request, key
|
46
|
+
@page = (request.query[key] || 1).to_i
|
47
|
+
@per_page = per_page
|
48
|
+
set_count(total_count)
|
49
|
+
@start_idx = (@page - 1) * per_page
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_count(total_count)
|
53
|
+
@total_count = total_count
|
54
|
+
@page_count = (@total_count.to_f / @per_page).ceil
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return the first page index.
|
58
|
+
|
59
|
+
def first_page
|
60
|
+
return 1
|
61
|
+
end
|
62
|
+
|
63
|
+
# Is the first page displayed?
|
64
|
+
|
65
|
+
def first_page?
|
66
|
+
@page == 1
|
67
|
+
end
|
68
|
+
|
69
|
+
# Return the last page index.
|
70
|
+
|
71
|
+
def last_page
|
72
|
+
return @page_count
|
73
|
+
end
|
74
|
+
|
75
|
+
# Is the last page displayed?
|
76
|
+
|
77
|
+
def last_page?
|
78
|
+
@page == @page_count
|
79
|
+
end
|
80
|
+
|
81
|
+
# Return the index of the previous page.
|
82
|
+
|
83
|
+
def previous_page
|
84
|
+
return [@page - 1, 1].max()
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return the index of the next page.
|
88
|
+
|
89
|
+
def next_page
|
90
|
+
return [@page + 1, @page_count].min()
|
91
|
+
end
|
92
|
+
|
93
|
+
# A set of helpers to create links to common pages.
|
94
|
+
|
95
|
+
for target in [:first, :last, :previous, :next]
|
96
|
+
eval %{
|
97
|
+
def link_#{target}_page
|
98
|
+
target_uri(#{target}_page)
|
99
|
+
end
|
100
|
+
alias_method :#{target}_page_uri, :link_#{target}_page
|
101
|
+
alias_method :#{target}_page_href, :link_#{target}_page
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
# Iterator
|
106
|
+
|
107
|
+
def each(&block)
|
108
|
+
@page_items.each(&block)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Iterator
|
112
|
+
# Returns 1-based index.
|
113
|
+
|
114
|
+
def each_with_index
|
115
|
+
idx = @start_idx
|
116
|
+
for item in @page_items
|
117
|
+
yield(idx + 1, item)
|
118
|
+
idx += 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Is the pager empty, ie has one page only?
|
123
|
+
|
124
|
+
def empty?
|
125
|
+
return @page_count < 1
|
126
|
+
end
|
127
|
+
|
128
|
+
# The items count.
|
129
|
+
|
130
|
+
def size
|
131
|
+
return @total_count
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns the range of the current page.
|
135
|
+
|
136
|
+
def page_range
|
137
|
+
s = @idx
|
138
|
+
e = [@idx + @items_per_page - 1, all_total_count].min
|
139
|
+
|
140
|
+
return [s, e]
|
141
|
+
end
|
142
|
+
|
143
|
+
# Override if needed.
|
144
|
+
|
145
|
+
def nav_range
|
146
|
+
# effective range = 10 pages.
|
147
|
+
s = [@page - 5, 1].max()
|
148
|
+
e = [@page + 9, @page_count].min()
|
149
|
+
|
150
|
+
d = 9 - (e - s)
|
151
|
+
e += d if d < 0
|
152
|
+
|
153
|
+
return (s..e)
|
154
|
+
end
|
155
|
+
|
156
|
+
# To be used with Og queries.
|
157
|
+
|
158
|
+
def limit
|
159
|
+
if @start_idx > 0
|
160
|
+
{ :limit => @per_page, :offset => @start_idx }
|
161
|
+
else
|
162
|
+
{ :limit => @per_page }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def offset
|
167
|
+
@start_idx
|
168
|
+
end
|
169
|
+
|
170
|
+
# Create an appropriate SQL limit clause.
|
171
|
+
# Returns postgres/mysql compatible limit.
|
172
|
+
|
173
|
+
def to_sql
|
174
|
+
if @start_idx > 0
|
175
|
+
return "LIMIT #{@per_page} OFFSET #{@start_idx}"
|
176
|
+
else
|
177
|
+
# gmosx: perhaps this is optimized ? naaaaaah...
|
178
|
+
return "LIMIT #{@per_page}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Override this method in your application if needed.
|
183
|
+
#--
|
184
|
+
# TODO: better markup.
|
185
|
+
#++
|
186
|
+
|
187
|
+
def navigation
|
188
|
+
nav = ""
|
189
|
+
|
190
|
+
unless first_page?
|
191
|
+
nav << %{
|
192
|
+
<div class="first"><a href="#{first_page_href}">First</a></div>
|
193
|
+
<div class="previous"><a href="#{previous_page_href}">Previous</a></div>
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
unless last_page?
|
198
|
+
nav << %{
|
199
|
+
<div class="last"><a href="#{last_page_href}">Last</a></div>
|
200
|
+
<div class="next"><a href="#{next_page_href}">Next</a></div>
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
nav << %{<ul>}
|
205
|
+
|
206
|
+
for i in nav_range()
|
207
|
+
if i == @page
|
208
|
+
nav << %{
|
209
|
+
<li class="active">#{i}</li>
|
210
|
+
}
|
211
|
+
else
|
212
|
+
nav << %{
|
213
|
+
<li><a href="#{target_uri(i)}">#{i}</a></li>
|
214
|
+
}
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
nav << %{</ul>}
|
219
|
+
|
220
|
+
return nav
|
221
|
+
end
|
222
|
+
alias_method :links, :navigation
|
223
|
+
|
224
|
+
def navigation_needed?
|
225
|
+
@page_count > 1
|
226
|
+
end
|
227
|
+
alias_method :navigation?, :navigation_needed?
|
228
|
+
|
229
|
+
private
|
230
|
+
|
231
|
+
# Generate the target URI.
|
232
|
+
|
233
|
+
def target_uri(page)
|
234
|
+
uri = @request.uri.to_s
|
235
|
+
|
236
|
+
if uri =~ /[?;]#{@key}=(\d*)/
|
237
|
+
return uri.gsub(/([?;]#{@key}=)\d*/) { |m| "#$1#{page}" }
|
238
|
+
elsif uri =~ /\?/
|
239
|
+
return "#{uri};#{@key}=#{page}"
|
240
|
+
else
|
241
|
+
return "#{uri}?#{@key}=#{page}"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
# Pager related helper methods.
|
248
|
+
|
249
|
+
module PagerHelper
|
250
|
+
|
251
|
+
private
|
252
|
+
|
253
|
+
# Helper method that generates a collection of items and the
|
254
|
+
# associated pager object.
|
255
|
+
#
|
256
|
+
# === Example
|
257
|
+
#
|
258
|
+
# entries, pager = paginate(Article, :condition => 'title LIKE %Ab%', :per_page => 10)
|
259
|
+
#
|
260
|
+
# or
|
261
|
+
#
|
262
|
+
# items = [ 'item1', 'item2', ... ]
|
263
|
+
# entries, pager = paginate(items, :per_page => 10)
|
264
|
+
#
|
265
|
+
# or
|
266
|
+
#
|
267
|
+
# entries, pager = paginate(article.comments, :per_page => 10)
|
268
|
+
#
|
269
|
+
# <ul>
|
270
|
+
# <?r for entry in entries ?>
|
271
|
+
# <li>#{entry.to_link}</li>
|
272
|
+
# <?r end ?>
|
273
|
+
# </ul>
|
274
|
+
# #{pager.links}
|
275
|
+
|
276
|
+
def paginate(items, options = {})
|
277
|
+
per_page = options.delete(:per_page) || options[:limit] || Pager.per_page
|
278
|
+
pager_key = options.delete(:pager_key) || Pager.key
|
279
|
+
|
280
|
+
case items
|
281
|
+
when Array
|
282
|
+
items = items.dup
|
283
|
+
pager = Pager.new(request, per_page, items.size, pager_key)
|
284
|
+
items = items.slice(pager.offset, pager.per_page) || []
|
285
|
+
return items, pager
|
286
|
+
|
287
|
+
when Og::Collection
|
288
|
+
collection = items
|
289
|
+
pager = Pager.new(request, per_page, collection.count, pager_key)
|
290
|
+
options.update(pager.limit)
|
291
|
+
items = collection.reload(options)
|
292
|
+
return items, pager
|
293
|
+
|
294
|
+
when Class
|
295
|
+
klass = items
|
296
|
+
pager = Pager.new(request, per_page, klass.count(options), pager_key)
|
297
|
+
options.update(pager.limit)
|
298
|
+
items = klass.all(options)
|
299
|
+
return items, pager
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require "facets/more/settings"
|
2
|
+
|
3
|
+
require "glue/uri"
|
4
|
+
|
5
|
+
module Raw
|
6
|
+
|
7
|
+
# The TableBuilder is a helper class that automates the creation
|
8
|
+
# of tables from collections of objects. The resulting html
|
9
|
+
# can be styled using css.
|
10
|
+
#
|
11
|
+
# === Example
|
12
|
+
#
|
13
|
+
# <?r
|
14
|
+
# users = User.all.map { |u| [u.name, u.first_name, u.last_name, u.email] }
|
15
|
+
# headers = ['Username', 'First name', 'Last name', 'Email']
|
16
|
+
# ?>
|
17
|
+
#
|
18
|
+
# <div class="custom-table-class">
|
19
|
+
# #{table :values => users, :headers => header}
|
20
|
+
# </div>
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# === Extended Example
|
24
|
+
#
|
25
|
+
# <?r
|
26
|
+
# users = User.all.map { |u| [u.name, u.first_name, u.last_name, u.email] }
|
27
|
+
# headers = ['Username', 'First name', 'Last name', 'Email']
|
28
|
+
# order_opts = { :right => true, # right align the order controls
|
29
|
+
# :values => [nil, 'first_name', 'last_name'], # column names from DB
|
30
|
+
# :asc_pic => "/images/asc.png",
|
31
|
+
# :desc_pic => "/images/desc.png" }
|
32
|
+
# ?>
|
33
|
+
#
|
34
|
+
# <div class="custom-table-class">
|
35
|
+
# #{table :values => users, :headers => header,
|
36
|
+
# :order => order_opts, :alternating_rows => true }
|
37
|
+
# </div>
|
38
|
+
#
|
39
|
+
#--
|
40
|
+
# TODO: legend, verbose... ?
|
41
|
+
# TODO, gmosx: Remove crappy, bloatware additions.
|
42
|
+
#++
|
43
|
+
|
44
|
+
module TableHelper
|
45
|
+
|
46
|
+
# The order by key.
|
47
|
+
|
48
|
+
setting :order_by_key, :default => '_order_by', :doc => 'The order key'
|
49
|
+
|
50
|
+
# The order by key.
|
51
|
+
|
52
|
+
setting :order_direction_key, :default => '_order_direction', :doc => 'The order direction key'
|
53
|
+
|
54
|
+
# [+options+]
|
55
|
+
# A hash of options.
|
56
|
+
#
|
57
|
+
# :id = id of the component.
|
58
|
+
# :class = class of the component
|
59
|
+
# :headers = an array of the header values
|
60
|
+
# :values = an array of arrays.
|
61
|
+
# :order = options hash (:left, :right, :asc_pic, :desc_pic, :values)
|
62
|
+
# :alternating_rows = alternating rows, use css to color row_even / row_odd
|
63
|
+
# :footers = an array of tfooter values
|
64
|
+
|
65
|
+
def table(options)
|
66
|
+
str = '<table'
|
67
|
+
str << %| id="#{options[:id]}"| if options[:id]
|
68
|
+
str << %| class="#{options[:class]}"| if options[:class]
|
69
|
+
str << '>'
|
70
|
+
|
71
|
+
str << table_rows(options)
|
72
|
+
|
73
|
+
str << '</table>'
|
74
|
+
end
|
75
|
+
alias_method :build_table, :table
|
76
|
+
|
77
|
+
# [+options+]
|
78
|
+
# A hash of options.
|
79
|
+
#
|
80
|
+
# :headers = an array of the header values
|
81
|
+
# :values = an array of arrays.
|
82
|
+
# :order = options hash (:left, :right, :asc_pic, :desc_pic, :values)
|
83
|
+
# :alternating_rows = alternating rows, use css to color row_even / row_odd
|
84
|
+
# :footers = an array of tfooter values
|
85
|
+
|
86
|
+
def table_rows(options)
|
87
|
+
# also accept :items, :rows
|
88
|
+
options[:values] = options[:values] || options[:items] || options[:rows]
|
89
|
+
|
90
|
+
str = ''
|
91
|
+
str << table_header(options) if options[:headers]
|
92
|
+
str << table_footer(options) if options[:footers]
|
93
|
+
|
94
|
+
items = options[:values]
|
95
|
+
|
96
|
+
row_state = 'odd' if options[:alternating_rows]
|
97
|
+
|
98
|
+
# when items is an array of arrays of arrays (meaning, several
|
99
|
+
# arrays deviding the table into several table parts (tbodys))
|
100
|
+
|
101
|
+
if create_tbody?(options)
|
102
|
+
for body in items
|
103
|
+
str << '<tbody>'
|
104
|
+
|
105
|
+
for row in body
|
106
|
+
str << '<tr'
|
107
|
+
|
108
|
+
if options[:alternating_rows]
|
109
|
+
str << %| class="row_#{row_state}"|
|
110
|
+
row_state = (row_state == "odd" ? "even" : "odd")
|
111
|
+
end
|
112
|
+
|
113
|
+
str << '>'
|
114
|
+
|
115
|
+
for value in row
|
116
|
+
str << %|<td>#{value}</td>|
|
117
|
+
end
|
118
|
+
|
119
|
+
str << '</tr>'
|
120
|
+
end
|
121
|
+
|
122
|
+
str << '</tbody>'
|
123
|
+
end
|
124
|
+
else
|
125
|
+
for row in items
|
126
|
+
str << '<tr'
|
127
|
+
|
128
|
+
if options[:alternating_rows]
|
129
|
+
str << %| class="row_#{row_state}"|
|
130
|
+
row_state = (row_state == "odd" ? "even" : "odd")
|
131
|
+
end
|
132
|
+
|
133
|
+
str << '>'
|
134
|
+
|
135
|
+
for value in row
|
136
|
+
str << %|<td>#{value}</td>|
|
137
|
+
end
|
138
|
+
|
139
|
+
str << '</tr>'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
return str
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
# [+options+]
|
149
|
+
# A hash of options.
|
150
|
+
#
|
151
|
+
# :id = id of the component.
|
152
|
+
# :headers = an array of the header values
|
153
|
+
# :values = an array of arrays.
|
154
|
+
# :order = options hash (:left, :right, :asc_pic, :desc_pic, :values)
|
155
|
+
# :alternating_rows = alternating rows, use css to color row_even / row_odd
|
156
|
+
# :footers = an array of tfooter values
|
157
|
+
|
158
|
+
def table_header(options)
|
159
|
+
str = ''
|
160
|
+
str << '<thead>' if create_tbody?(options) || options[:footers]
|
161
|
+
str << '<tr>'
|
162
|
+
|
163
|
+
options[:headers].each_with_index do |header, index|
|
164
|
+
if (options[:order] && options[:order][:values] &&
|
165
|
+
options[:order][:values][index])
|
166
|
+
order_by = options[:order][:values][index]
|
167
|
+
|
168
|
+
asc_val = if options[:order][:asc_pic]
|
169
|
+
%|<img src="#{options[:order][:asc_pic]}" alt="asc" />|
|
170
|
+
else
|
171
|
+
'^'
|
172
|
+
end
|
173
|
+
desc_val = if options[:order][:desc_pic]
|
174
|
+
%|<img src="#{options[:order][:desc_pic]}" alt="desc" />|
|
175
|
+
else
|
176
|
+
'v'
|
177
|
+
end
|
178
|
+
|
179
|
+
order_asc = "<a href='#{target_uri(order_by, 'ASC')}'>#{asc_val}</a>"
|
180
|
+
order_desc = "<a href='#{target_uri(order_by, 'DESC')}'>#{desc_val}</a>"
|
181
|
+
|
182
|
+
str << '<th><table width="100%" cellspacing="0" cellpadding="0"><tr>'
|
183
|
+
|
184
|
+
if options[:order][:left] || !options[:order][:right]
|
185
|
+
str << "<th>#{order_asc}<br />#{order_desc}</th>"
|
186
|
+
end
|
187
|
+
|
188
|
+
str << %|<th>#{header}</th>|
|
189
|
+
|
190
|
+
if options[:order][:right]
|
191
|
+
str << "<th>#{order_asc}<br />#{order_desc}</th>"
|
192
|
+
end
|
193
|
+
|
194
|
+
str << '</tr></table></th>'
|
195
|
+
else
|
196
|
+
str << %|<th>#{header}</th>|
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
str << '</tr>'
|
201
|
+
str << '</thead>' if create_tbody?(options) || options[:footers]
|
202
|
+
|
203
|
+
return str
|
204
|
+
end
|
205
|
+
|
206
|
+
# [+options+]
|
207
|
+
# A hash of options.
|
208
|
+
#
|
209
|
+
# :id = id of the component.
|
210
|
+
# :headers = an array of the header values
|
211
|
+
# :values = an array of arrays.
|
212
|
+
# :order = options hash (:left, :right, :asc_pic, :desc_pic, :values)
|
213
|
+
# :alternating_rows = alternating rows, use css to color row_even / row_odd
|
214
|
+
# :footers = an array of tfooter values
|
215
|
+
|
216
|
+
def table_footer(options)
|
217
|
+
str = '<tfoot><tr>'
|
218
|
+
|
219
|
+
for footer in options[:footers]
|
220
|
+
str << %|<td>#{footer}</td>|
|
221
|
+
end
|
222
|
+
|
223
|
+
str << '</tr></tfoot>'
|
224
|
+
|
225
|
+
return str
|
226
|
+
end
|
227
|
+
|
228
|
+
# Generate the target URI.
|
229
|
+
|
230
|
+
def target_uri(order_by, direction)
|
231
|
+
params = { TableHelper.order_by_key => order_by,
|
232
|
+
TableHelper.order_direction_key => direction }
|
233
|
+
|
234
|
+
return Glue::UriUtils.update_query_string(request.uri.to_s, params)
|
235
|
+
end
|
236
|
+
|
237
|
+
#--
|
238
|
+
# gmosx: Arrgh!! dangerous method, who added this?
|
239
|
+
#++
|
240
|
+
|
241
|
+
def create_tbody?(options)
|
242
|
+
options[:values][0][0].respond_to?(:to_ary)
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|