cheveret 2.0.0.rc5 → 3.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.
- data/cheveret.gemspec +14 -9
- data/lib/cheveret.rb +24 -8
- data/lib/cheveret/{filtering.rb → adapter/active_record.rb} +5 -16
- data/lib/cheveret/adapter/sunspot.rb +57 -0
- data/lib/cheveret/{config.rb → builder/divider.rb} +16 -19
- data/lib/cheveret/column.rb +10 -25
- data/lib/cheveret/helper.rb +47 -8
- data/lib/cheveret/table.rb +47 -0
- data/lib/cheveret/table/columns.rb +77 -0
- data/lib/cheveret/table/data.rb +62 -0
- data/lib/cheveret/{base.rb → table/locale.rb} +24 -27
- data/lib/cheveret/table/mapping.rb +88 -0
- data/lib/cheveret/table/rendering.rb +122 -0
- data/lib/cheveret/table/sizing.rb +136 -0
- data/lib/cheveret/table/sorting.rb +124 -0
- data/lib/cheveret/version.rb +2 -3
- metadata +20 -18
- data/lib/cheveret/dsl.rb +0 -124
- data/lib/cheveret/rendering.rb +0 -85
- data/lib/cheveret/resizing.rb +0 -97
@@ -21,37 +21,34 @@
|
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
23
|
|
24
|
-
require 'active_support/ordered_hash'
|
25
|
-
|
26
24
|
module Cheveret
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def initialize(template, &block)
|
31
|
-
@template = template
|
32
|
-
@columns = ::ActiveSupport::OrderedHash.new
|
33
|
-
|
34
|
-
instance_eval(&block) if block_given?
|
35
|
-
end
|
25
|
+
module Table
|
26
|
+
module Locale
|
36
27
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
28
|
+
##
|
29
|
+
#
|
30
|
+
#
|
31
|
+
def render_th(column, options={})
|
32
|
+
unless options[:title]
|
33
|
+
scope = self.class.to_s.sub(/Table\Z/, '').underscore
|
34
|
+
hint = ::I18n.translate("cheveret.hints.#{scope}.#{column.name}",
|
35
|
+
:default => '')
|
43
36
|
|
44
|
-
|
37
|
+
options[:title] = hint.squish unless hint.blank?
|
38
|
+
end
|
45
39
|
|
46
|
-
# since the define_table block gets instance_eval'd in the context of this object
|
47
|
-
# we need to proxy view methods (e.g. check_box_tag) back to the template
|
48
|
-
def method_missing(method_name, *args, &block) #:nodoc:
|
49
|
-
if @template.respond_to?(method_name)
|
50
|
-
@template.send(method_name, *args, &block)
|
51
|
-
else
|
52
40
|
super
|
53
41
|
end
|
54
|
-
end
|
55
42
|
|
56
|
-
|
57
|
-
|
43
|
+
##
|
44
|
+
#
|
45
|
+
#
|
46
|
+
def table_header_for(column)
|
47
|
+
scope = self.class.to_s.sub(/Table\Z/, '').underscore
|
48
|
+
header = ::I18n.translate("cheveret.headers.#{scope}.#{column.name}",
|
49
|
+
:default => column.name.to_s.humanize).squish
|
50
|
+
end
|
51
|
+
|
52
|
+
end # Locale
|
53
|
+
end # Table
|
54
|
+
end # Cheveret
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2010 RateCity Pty. Ltd.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module Cheveret
|
25
|
+
module Table
|
26
|
+
module Mapping
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
::Cheveret::Column.send :include, Mappable
|
30
|
+
end
|
31
|
+
|
32
|
+
module Mappable
|
33
|
+
attr_accessor :data, :header
|
34
|
+
end # Mappable
|
35
|
+
|
36
|
+
##
|
37
|
+
#
|
38
|
+
#
|
39
|
+
def table_data(column, item)
|
40
|
+
args = [ item ]
|
41
|
+
|
42
|
+
case column.data
|
43
|
+
when Symbol
|
44
|
+
args.unshift(column) if method(column.data).arity > 1
|
45
|
+
send(column.data, *args)
|
46
|
+
when Proc
|
47
|
+
args.unshift(column) if column.data.arity > 1
|
48
|
+
template.capture(*args, &column.data)
|
49
|
+
else
|
50
|
+
if respond_to?(column.name)
|
51
|
+
args.unshift(column) if method(column.name).arity > 1
|
52
|
+
send(column.name, *args)
|
53
|
+
else
|
54
|
+
table_data_for(column, item)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
#
|
61
|
+
#
|
62
|
+
def table_data_for(column, item)
|
63
|
+
raise NotImplementedError
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
#
|
68
|
+
#
|
69
|
+
def table_header(column)
|
70
|
+
case column.header
|
71
|
+
when Symbol then send(column.header)
|
72
|
+
when Proc then template.capture(&column.header)
|
73
|
+
when String then column.header
|
74
|
+
else
|
75
|
+
table_header_for(column) unless column.header == false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
#
|
81
|
+
#
|
82
|
+
def table_header_for(column)
|
83
|
+
raise NotImplementedError
|
84
|
+
end
|
85
|
+
|
86
|
+
end # Mapping
|
87
|
+
end # Table
|
88
|
+
end # Cheveret
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2010 RateCity Pty. Ltd.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module Cheveret
|
25
|
+
module Table
|
26
|
+
module Rendering
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.module_eval do
|
30
|
+
extend ClassMethods
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_accessor :template
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
end # ClassMethods
|
38
|
+
|
39
|
+
##
|
40
|
+
#
|
41
|
+
#
|
42
|
+
def render_table(options={})
|
43
|
+
table_tag(options) do
|
44
|
+
render_thead << render_tbody
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
#
|
50
|
+
#
|
51
|
+
def render_thead(options={})
|
52
|
+
thead_tag(options) do
|
53
|
+
tr_tag do
|
54
|
+
columns.values.map do |column|
|
55
|
+
render_th(column) { table_header(column) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
#
|
63
|
+
#
|
64
|
+
def render_tbody(options={})
|
65
|
+
tbody_tag(options) { render_rows }
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
#
|
70
|
+
#
|
71
|
+
def render_rows(options={})
|
72
|
+
template.reset_cycle('cheveret')
|
73
|
+
|
74
|
+
collection.map do |item|
|
75
|
+
cycle = template.cycle('', 'alt', :name => 'cheveret')
|
76
|
+
|
77
|
+
tr_tag(:class => cycle) do
|
78
|
+
columns.values.map do |column|
|
79
|
+
render_td(column) { table_data(column, item) }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end.join("\n")
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# generates a <th> tag for the specified column using the configured builder
|
87
|
+
#
|
88
|
+
def render_th(column, options={})
|
89
|
+
options.reverse_merge!(column.th_html) if column.th_html
|
90
|
+
|
91
|
+
# phwarrrgg!
|
92
|
+
options[:class] = ([ column.name, options[:class],
|
93
|
+
column.th_html ? column.th_html[:class] : nil
|
94
|
+
]).flatten.join(' ').strip
|
95
|
+
|
96
|
+
th_tag(options) { yield }
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
#
|
101
|
+
#
|
102
|
+
def render_td(column, options={})
|
103
|
+
options.reverse_merge!(column.td_html) if column.td_html
|
104
|
+
options[:class] = [ column.name, *options[:class] ].flatten.join(' ').strip
|
105
|
+
|
106
|
+
td_tag(options) { yield }
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
#
|
111
|
+
#
|
112
|
+
def render(*args, &block)
|
113
|
+
if args.empty? && block_given?
|
114
|
+
template.instance_eval(&block)
|
115
|
+
else
|
116
|
+
template.render(*args, &block)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end # Rendering
|
121
|
+
end # Table
|
122
|
+
end # Cheveret
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2010 RateCity Pty. Ltd.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module Cheveret
|
25
|
+
module Table
|
26
|
+
module Sizing
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.module_eval do
|
30
|
+
extend ClassMethods
|
31
|
+
end
|
32
|
+
|
33
|
+
# allow columns to be flexible and/or have their width set
|
34
|
+
::Cheveret::Column.send :include, Sizable
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :width
|
38
|
+
|
39
|
+
module ClassMethods
|
40
|
+
|
41
|
+
# todo: set width?
|
42
|
+
|
43
|
+
end # ClassMethods
|
44
|
+
|
45
|
+
module Sizable
|
46
|
+
attr_accessor :flexible, :size, :width
|
47
|
+
|
48
|
+
##
|
49
|
+
#
|
50
|
+
#
|
51
|
+
def flexible?
|
52
|
+
@flexible == true
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
#
|
57
|
+
#
|
58
|
+
def size
|
59
|
+
@size || width
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
#
|
64
|
+
#
|
65
|
+
def width
|
66
|
+
@width || 0
|
67
|
+
end
|
68
|
+
|
69
|
+
end # Sizable
|
70
|
+
|
71
|
+
##
|
72
|
+
#
|
73
|
+
#
|
74
|
+
def width
|
75
|
+
@width ||= 0
|
76
|
+
end
|
77
|
+
|
78
|
+
[ :table, :thead, :tbody, :rows].each do |elem|
|
79
|
+
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
80
|
+
def render_#{elem}(options={})
|
81
|
+
resize! if needs_resize?
|
82
|
+
|
83
|
+
options[:style] = "width:\#{width}px;" if width > 0
|
84
|
+
super
|
85
|
+
end
|
86
|
+
RUBY_EVAL
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
#
|
91
|
+
#
|
92
|
+
def render_th(column, options={})
|
93
|
+
options[:style] = "width:#{column.size}px;" if column.size > 0
|
94
|
+
super
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
#
|
99
|
+
#
|
100
|
+
def render_td(column, options={})
|
101
|
+
options[:style] = "width:#{column.size}px;" if column.size > 0
|
102
|
+
super
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
#
|
107
|
+
#
|
108
|
+
def resize!
|
109
|
+
columns_width, flexibles = 0, []
|
110
|
+
|
111
|
+
columns.values.each do |column|
|
112
|
+
columns_width += column.width
|
113
|
+
flexibles << column if column.flexible?
|
114
|
+
end
|
115
|
+
|
116
|
+
# todo: handle too-many/too-wide columns
|
117
|
+
raise "uh-oh spaghettio-s" if columns_width > width
|
118
|
+
|
119
|
+
# todo: fix rounding in with calculation
|
120
|
+
if columns_width < width && !flexibles.empty?
|
121
|
+
padding = (width - columns_width) / flexibles.length
|
122
|
+
flexibles.each { |column| column.size = column.width + padding }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
#
|
128
|
+
#
|
129
|
+
def needs_resize?
|
130
|
+
columns.map(&:size).sum != width
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
end # Sizing
|
135
|
+
end # Table
|
136
|
+
end # Cheveret
|
@@ -0,0 +1,124 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2010 RateCity Pty. Ltd.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module Cheveret
|
25
|
+
module Table
|
26
|
+
module Sorting
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.module_eval do
|
30
|
+
extend ClassMethods
|
31
|
+
end
|
32
|
+
|
33
|
+
# make sure our column objects can be configured as sortable
|
34
|
+
::Cheveret::Column.send :include, Sortable
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :sort_column, :sort_direction, :sort_param, :sort_url
|
38
|
+
|
39
|
+
module ClassMethods
|
40
|
+
|
41
|
+
##
|
42
|
+
# defines which table columns can be sorted by the user
|
43
|
+
#
|
44
|
+
def sortable_on(*args)
|
45
|
+
args.each do |column_name|
|
46
|
+
raise "unrecognised column #{column_name}" unless columns[column_name]
|
47
|
+
columns[column_name].sortable = true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# TODO: depricate
|
53
|
+
#
|
54
|
+
def default_sort(column_name, direction)
|
55
|
+
raise ArgumentError 'Column not found' unless columns.has_key?(column_name)
|
56
|
+
|
57
|
+
@default_sort_column = columns[column_name]
|
58
|
+
@default_sort_direction = direction
|
59
|
+
end
|
60
|
+
|
61
|
+
end # ClassMethods
|
62
|
+
|
63
|
+
module Sortable
|
64
|
+
attr_accessor :default_sort_direction, :sortable
|
65
|
+
|
66
|
+
##
|
67
|
+
# whether or not sorting the table by this column is allowed. default +false+
|
68
|
+
#
|
69
|
+
def sortable?
|
70
|
+
sortable == true
|
71
|
+
end
|
72
|
+
|
73
|
+
def default_sort_direction
|
74
|
+
@default_sort_direction ||= :desc
|
75
|
+
end
|
76
|
+
|
77
|
+
end # Sortable
|
78
|
+
|
79
|
+
##
|
80
|
+
#
|
81
|
+
#
|
82
|
+
def sort_param
|
83
|
+
@sort_param ||= '%s'
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
#
|
88
|
+
#
|
89
|
+
def render_th(column, options={})
|
90
|
+
return super unless column.sortable?
|
91
|
+
|
92
|
+
options[:class] = [ 'sortable', *options[:class] ]
|
93
|
+
options[:class] << 'sorted' if column.name == sort_column
|
94
|
+
options[:class].flatten.join(' ').strip
|
95
|
+
|
96
|
+
super
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
#
|
101
|
+
#
|
102
|
+
def table_header(column)
|
103
|
+
# wrap unsortable columns in a <span> tag
|
104
|
+
return template.content_tag(:span, super) unless column.sortable?
|
105
|
+
|
106
|
+
column_key = sort_param % 'sort_column'
|
107
|
+
direction_key = sort_param % 'sort_direction'
|
108
|
+
|
109
|
+
attrs = {}
|
110
|
+
query = { column_key => column.name,
|
111
|
+
direction_key => column.default_sort_direction }
|
112
|
+
|
113
|
+
if column.name == sort_column
|
114
|
+
query[direction_key] = ( sort_direction == :asc ? :desc : :asc )
|
115
|
+
attrs[:class] = "#{sort_direction}"
|
116
|
+
end
|
117
|
+
|
118
|
+
attrs[:href] = template.url_for(sort_url.merge(query))
|
119
|
+
template.content_tag(:a, super, attrs)
|
120
|
+
end
|
121
|
+
|
122
|
+
end # Sorting
|
123
|
+
end # Table
|
124
|
+
end # Cheveret
|