dom-rb 0.1.1
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.
- checksums.yaml +7 -0
- data/csr/dom/browser_ext/node.rb +101 -0
- data/csr/dom/builder/base.rb +210 -0
- data/csr/dom/builder/binding.rb +44 -0
- data/csr/dom/builder/helpers.rb +343 -0
- data/csr/dom/builder.rb +7 -0
- data/csr/dom/content.rb +269 -0
- data/csr/dom/debug.rb +61 -0
- data/csr/dom/globals.rb +19 -0
- data/csr/dom/root.rb +37 -0
- data/csr/dom/table/base.rb +300 -0
- data/csr/dom/table/caption.rb +59 -0
- data/csr/dom/table/column.rb +84 -0
- data/csr/dom/table/row.rb +118 -0
- data/csr/dom/table/section.rb +208 -0
- data/csr/dom/table.rb +1 -0
- data/csr/dom/util.rb +86 -0
- data/csr/dom.rb +5 -0
- data/lib/dom/version.rb +5 -0
- data/lib/dom-rb.rb +11 -0
- metadata +78 -0
data/csr/dom/content.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'dom/builder'
|
2
|
+
require 'dom/util'
|
3
|
+
require 'dom/debug'
|
4
|
+
|
5
|
+
module CSR
|
6
|
+
module DOM
|
7
|
+
class Content
|
8
|
+
include CSR::DOM::Builder
|
9
|
+
include CSR::DOM::Util
|
10
|
+
include CSR::DOM::Debug
|
11
|
+
|
12
|
+
# options
|
13
|
+
#
|
14
|
+
# :value # object appropriate to type or proc(context) or proc(value) or proc(context, value)
|
15
|
+
# :sort_value # object appropriate to type or proc(context) or proc(value) or proc(context, value)
|
16
|
+
# :type # :container, :media, :string, :integer, :decimal, :bool, :count, :percent, :sign, :date
|
17
|
+
# :css # string with valid css classes or proc(value) or proc(context, value)
|
18
|
+
# :style # { } hash of styles per Clearwater or proc(value) or proc(context, value)
|
19
|
+
# :format # string or proc(value) or proc(context, value) for :decimal, :percent, :date
|
20
|
+
# :comma # boolean for numeric values (default true)
|
21
|
+
# :events # { click: ->{ clicked }, ... } - hash or proc(value) or proc(context, value)
|
22
|
+
# # event names per 'developer.mozilla.org/en-US/docs/Web/Events'
|
23
|
+
|
24
|
+
attr_reader :options, :type
|
25
|
+
|
26
|
+
def initialize(**options)
|
27
|
+
# self.debug_level = 1
|
28
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "options=#{options}" ]}
|
29
|
+
@options = options
|
30
|
+
@type = @options[:type] ||= :container
|
31
|
+
@options[:css] ||= ''
|
32
|
+
@options[:style] ||= {}
|
33
|
+
@options[:events] ||= {}
|
34
|
+
@is_numeric = [:integer, :decimal, :percent, :count].include?(@type)
|
35
|
+
@is_text = !(container? || media?)
|
36
|
+
@options[:comma] = true if @options[:comma].nil?
|
37
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
38
|
+
set_format_defaults
|
39
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
40
|
+
set_css_defaults
|
41
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
42
|
+
set_style_defaults
|
43
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
44
|
+
end
|
45
|
+
|
46
|
+
def container?
|
47
|
+
@type == :container
|
48
|
+
end
|
49
|
+
|
50
|
+
def media?
|
51
|
+
@type == :media
|
52
|
+
end
|
53
|
+
|
54
|
+
def text?
|
55
|
+
@is_text
|
56
|
+
end
|
57
|
+
|
58
|
+
def date?
|
59
|
+
@type == :date
|
60
|
+
end
|
61
|
+
|
62
|
+
def numeric?
|
63
|
+
@is_numeric
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns a DOM element.
|
67
|
+
# Context may be anything meaningful to procs.
|
68
|
+
def element(tag_name, attributes: {}, context: nil)
|
69
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "tag_name=#{tag_name} attributes=#{attributes} context=#{context}" ]}
|
70
|
+
result = tag(
|
71
|
+
tag_name,
|
72
|
+
attributes: ->{
|
73
|
+
attributes.merge.({
|
74
|
+
id: id(context: context, value: value),
|
75
|
+
class: css(context: context, value: value),
|
76
|
+
style: style(context: context, value: value),
|
77
|
+
})
|
78
|
+
},
|
79
|
+
content: ->{
|
80
|
+
formatted_value(context: context)
|
81
|
+
},
|
82
|
+
model: self
|
83
|
+
)
|
84
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "result=#{result}" ]}
|
85
|
+
result
|
86
|
+
end
|
87
|
+
|
88
|
+
# Context may be anything meaningful to procs.
|
89
|
+
# Returned value will be formatted (if applicable).
|
90
|
+
def value_and_attributes(context: nil)
|
91
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "context=#{context}" ]}
|
92
|
+
value = formatted_value(context: context)
|
93
|
+
result = [
|
94
|
+
value,
|
95
|
+
{
|
96
|
+
class: css(context: context, value: value),
|
97
|
+
style: style(context: context, value: value),
|
98
|
+
}.merge(
|
99
|
+
events(context: context, value: value)
|
100
|
+
)
|
101
|
+
]
|
102
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "context=#{context} result=#{result}" ]}
|
103
|
+
result
|
104
|
+
end
|
105
|
+
|
106
|
+
def sort_value(context: nil)
|
107
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "context=#{context.class.name}" ]}
|
108
|
+
option(:sort_value, context: context)
|
109
|
+
end
|
110
|
+
|
111
|
+
def value(context: nil)
|
112
|
+
option(:value, context: context)
|
113
|
+
end
|
114
|
+
|
115
|
+
def css(context: nil, value: nil)
|
116
|
+
option(:css, context: context, value: value)
|
117
|
+
end
|
118
|
+
|
119
|
+
def id(context: nil, value: nil)
|
120
|
+
option(:id, context: context, value: value) || hex_id
|
121
|
+
end
|
122
|
+
|
123
|
+
def style(context: nil, value: nil)
|
124
|
+
option(:style, context: context, value: value)
|
125
|
+
end
|
126
|
+
|
127
|
+
def events(context: nil, value: nil)
|
128
|
+
result = {}
|
129
|
+
events = option(:events, context: context, value: value)
|
130
|
+
if events && events.size > 0
|
131
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "events=#{events}" ]}
|
132
|
+
events.each do |event, proc|
|
133
|
+
event = event[0,2] == 'on' ? event : :"on#{event}"
|
134
|
+
result[event] = ->(_) {
|
135
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "event=#{event} context=#{context} value=#{value}" ]}
|
136
|
+
resolve(proc, context: context, value: nil)
|
137
|
+
}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "result=#{result}" unless result.empty? ]}
|
141
|
+
result
|
142
|
+
end
|
143
|
+
|
144
|
+
def formatted_value(context: nil)
|
145
|
+
v = value(context: context)
|
146
|
+
if v
|
147
|
+
if text?
|
148
|
+
format = format(context: context, value: v)
|
149
|
+
if numeric?
|
150
|
+
comma_numeric(format % v.to_f)
|
151
|
+
elsif date?
|
152
|
+
parse_date(v).strftime(value)
|
153
|
+
else
|
154
|
+
v.to_s
|
155
|
+
end
|
156
|
+
else
|
157
|
+
v
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def format(context: nil, value: nil)
|
163
|
+
option(:format, context: context, value: value)
|
164
|
+
end
|
165
|
+
|
166
|
+
def option(name, context: nil, value: nil)
|
167
|
+
option = @options[name]
|
168
|
+
resolve(option, context: context, value: value)
|
169
|
+
end
|
170
|
+
|
171
|
+
def resolve(thing, context: nil, value: nil)
|
172
|
+
if Proc === thing
|
173
|
+
if thing.arity == 2
|
174
|
+
thing.call(context, value)
|
175
|
+
elsif thing.arity == 1
|
176
|
+
thing.call(value || context)
|
177
|
+
else
|
178
|
+
thing.call
|
179
|
+
end
|
180
|
+
else
|
181
|
+
thing
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def comma_numeric(s)
|
186
|
+
@options[comma] ? s.comma_numeric : s
|
187
|
+
end
|
188
|
+
|
189
|
+
def parse_date(d)
|
190
|
+
self.class.parse_date(d)
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.parse_date(d)
|
194
|
+
return d if d.is_a?(Date)
|
195
|
+
# csr Date.parse can't handle strings with named months
|
196
|
+
# nor can it parse YYYYMMDD without separators!
|
197
|
+
if RUBY_PLATFORM == 'csr'
|
198
|
+
t = Time.parse(d)
|
199
|
+
Date.new(t.year, t.month, t.day)
|
200
|
+
else
|
201
|
+
Date.parse(d)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
private
|
206
|
+
|
207
|
+
def set_tag_defaults
|
208
|
+
@options[:tag] ||= 'div'
|
209
|
+
end
|
210
|
+
|
211
|
+
def set_style_defaults
|
212
|
+
if text? && options[:style].nil?
|
213
|
+
@options[:style] = case @options[:type]
|
214
|
+
when :integer, :decimal, :count, :percent
|
215
|
+
{ text_align: 'right' }
|
216
|
+
else
|
217
|
+
{ text_align: 'center' }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def set_css_defaults
|
223
|
+
# ?
|
224
|
+
end
|
225
|
+
|
226
|
+
def set_format_defaults
|
227
|
+
if text? && @options[:format].nil?
|
228
|
+
@options[:format] = case @options[:type]
|
229
|
+
when :decimal
|
230
|
+
->(v) {
|
231
|
+
comma_numeric('%0.2f' % v)
|
232
|
+
}
|
233
|
+
when :integer, :count
|
234
|
+
->(v) {
|
235
|
+
comma_numeric(v.to_i.to_s)
|
236
|
+
}
|
237
|
+
when :percent
|
238
|
+
->(v) {
|
239
|
+
comma_numeric((v * 100).round(0).to_s)
|
240
|
+
}
|
241
|
+
when :sign
|
242
|
+
->(v) {
|
243
|
+
if v == 0
|
244
|
+
'0'
|
245
|
+
else
|
246
|
+
v < 0 ? '-' : '+'
|
247
|
+
end
|
248
|
+
}
|
249
|
+
when :date
|
250
|
+
->(v) {
|
251
|
+
v.strftime('%Y/%m/%d')
|
252
|
+
}
|
253
|
+
when :bool
|
254
|
+
->(v) {
|
255
|
+
v ? 'T' : 'F'
|
256
|
+
}
|
257
|
+
else # :text, ...
|
258
|
+
->(v) {
|
259
|
+
v.to_s
|
260
|
+
}
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
data/csr/dom/debug.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module CSR
|
2
|
+
module DOM
|
3
|
+
module Debug
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def stack_trace
|
7
|
+
callback = ->(stackframes) {
|
8
|
+
%x(
|
9
|
+
var stringifiedStack = stackframes.map(function(sf) {
|
10
|
+
return sf.toString();
|
11
|
+
}).join('\n');
|
12
|
+
console.log(stringifiedStack);
|
13
|
+
)
|
14
|
+
}
|
15
|
+
errback = ->(err) {
|
16
|
+
`console.log(err.message)`
|
17
|
+
}
|
18
|
+
`StackTrace.get().then(callback).catch(errback)`
|
19
|
+
end
|
20
|
+
|
21
|
+
def debug_level=(l)
|
22
|
+
@debug_level = l
|
23
|
+
end
|
24
|
+
|
25
|
+
def debug_level
|
26
|
+
@debug_level ||= 0
|
27
|
+
end
|
28
|
+
|
29
|
+
def debug_method_missing=(v)
|
30
|
+
@debug_method_missing = v
|
31
|
+
end
|
32
|
+
|
33
|
+
def debug_method_missing?
|
34
|
+
!!@debug_method_missing
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing(name, *args, &block)
|
38
|
+
if true # debug_method_missing?
|
39
|
+
debug 0, ->{[__FILE__, __LINE__, __method__, "METHOD_MISSING: self=#{self} method=#{name}"]}
|
40
|
+
# debug 0, ->{[__FILE__, __LINE__, __method__, "called by: #{caller.first.to_s}"]}
|
41
|
+
stack_trace
|
42
|
+
end
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def debug(level, proc)
|
47
|
+
if level == 0 || level <= debug_level
|
48
|
+
file, line, method, msg = proc.call
|
49
|
+
s = "#{file}[#{line}] #{self.is_a?(Class) ? (self.name + '#') : self.class.name}##{method}"
|
50
|
+
s = s + " >> #{msg}" if msg
|
51
|
+
if RUBY_PLATFORM == 'opal'
|
52
|
+
`console.log(s)`
|
53
|
+
else
|
54
|
+
puts s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/csr/dom/globals.rb
ADDED
data/csr/dom/root.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'dom/globals'
|
2
|
+
require 'dom/util'
|
3
|
+
require 'dom/debug'
|
4
|
+
|
5
|
+
module CSR
|
6
|
+
module DOM
|
7
|
+
module Root
|
8
|
+
include CSR::DOM::Globals
|
9
|
+
include CSR::DOM::Util
|
10
|
+
include CSR::DOM::Debug
|
11
|
+
|
12
|
+
module_function
|
13
|
+
|
14
|
+
# TODO: should this be here?
|
15
|
+
def dom_root
|
16
|
+
unless @dom_root
|
17
|
+
if respond_to? :first_element # or container, Volt methods
|
18
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "setting @dom_root to first_element=#{first_element}" ]}
|
19
|
+
self.dom_root = first_element
|
20
|
+
else
|
21
|
+
# in a separate model?
|
22
|
+
fail "#{self.class.name}##{__method__}:#{__LINE_} : dom_root= must be called first"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
@dom_root
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO: should this be here?
|
29
|
+
def dom_root=(element)
|
30
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "element = #{element}" ]}
|
31
|
+
@dom_root = DOM(element)
|
32
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "element = #{element}" ]}
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require 'dom/table/caption'
|
2
|
+
require 'dom/table/section'
|
3
|
+
require 'dom/table/column'
|
4
|
+
require 'dom/builder'
|
5
|
+
require 'dom/util'
|
6
|
+
require 'dom/debug'
|
7
|
+
|
8
|
+
module CSR
|
9
|
+
module DOM
|
10
|
+
class Table
|
11
|
+
include CSR::DOM::Builder
|
12
|
+
include CSR::DOM::Util
|
13
|
+
include CSR::DOM::Debug
|
14
|
+
|
15
|
+
# TODO: other than bootstrap, ...
|
16
|
+
DEFAULT_CSS = 'table table-condensed table-bordered table-hover'
|
17
|
+
DEFAULT_STYLE = {}
|
18
|
+
|
19
|
+
# :id, # dom id - optional
|
20
|
+
# :css, # table css class string or nil
|
21
|
+
# :style, # table style hash or nil
|
22
|
+
# :caption_content, # string or ComponentSpec with tag => 'caption'
|
23
|
+
# :head_rows, # Proc or array of objects or nil
|
24
|
+
# :body_rows, # Proc or array of objects or nil
|
25
|
+
# :foot_rows, # Proc or array of objects or nil
|
26
|
+
# :sort_column_id, # default sort column or nil
|
27
|
+
# :sort_order, # nil, 1 or -1
|
28
|
+
# :accordion, # whether table has master column which can be collapsed
|
29
|
+
# :context, # something meaningful to column content procs or nil
|
30
|
+
# :reactive # is the table reactive, default false
|
31
|
+
|
32
|
+
attr_reader :id
|
33
|
+
attr_reader :sort_column_id, :sort_column, :sort_orders, :sort_order
|
34
|
+
attr_reader :accordion
|
35
|
+
attr_reader :css
|
36
|
+
attr_reader :style
|
37
|
+
attr_reader :caption_content
|
38
|
+
attr_reader :context
|
39
|
+
attr_reader :section_ids
|
40
|
+
|
41
|
+
def initialize(**options)
|
42
|
+
# self.debug_level = 1
|
43
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "options: #{options}" ]}
|
44
|
+
@id = options[:id] || hex_id
|
45
|
+
@rooted = false
|
46
|
+
init_sections(options)
|
47
|
+
@raw_columns = options[:columns]
|
48
|
+
@context = options[:context]
|
49
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
50
|
+
init_caption(options)
|
51
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
52
|
+
init_css_style(options)
|
53
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
54
|
+
init_row_sources(options)
|
55
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
56
|
+
init_visibility
|
57
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
58
|
+
init_sorting(options)
|
59
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
60
|
+
init_accordion(options)
|
61
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
62
|
+
end
|
63
|
+
|
64
|
+
def columns
|
65
|
+
unless @columns
|
66
|
+
@columns = if Proc === @raw_columns
|
67
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "@raw_columns=#{@raw_columns}"]}
|
68
|
+
c = @raw_columns.call
|
69
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "@columns=#{@columns}"]}
|
70
|
+
c
|
71
|
+
else
|
72
|
+
@raw_columns
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@columns
|
76
|
+
end
|
77
|
+
|
78
|
+
def rooted?
|
79
|
+
@rooted
|
80
|
+
end
|
81
|
+
|
82
|
+
def root
|
83
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
84
|
+
@root ||= tag(
|
85
|
+
:table,
|
86
|
+
attributes: attributes,
|
87
|
+
content: content
|
88
|
+
)
|
89
|
+
@rooted = true
|
90
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "@root=#{@root}" ]}
|
91
|
+
@root
|
92
|
+
end
|
93
|
+
|
94
|
+
def attributes
|
95
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
96
|
+
result = {
|
97
|
+
class: css,
|
98
|
+
style: style
|
99
|
+
}
|
100
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "result=#{result}" ]}
|
101
|
+
result
|
102
|
+
end
|
103
|
+
|
104
|
+
def content
|
105
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
106
|
+
content = arrify(caption, sections)
|
107
|
+
result = content.map {|e| e.root }
|
108
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "result=#{result}" ]}
|
109
|
+
result
|
110
|
+
end
|
111
|
+
|
112
|
+
def caption
|
113
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__]}
|
114
|
+
@caption ||= caption_content ? CSR::DOM::Table::Caption.new(self, caption_content) : nil
|
115
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "@caption=#{@caption}" ]}
|
116
|
+
@caption
|
117
|
+
end
|
118
|
+
|
119
|
+
def sections
|
120
|
+
@sections ||= section_ids.map do |id|
|
121
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "id=#{id}"]}
|
122
|
+
section = CSR::DOM::Table::Section.new(self, id)
|
123
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "section=#{section}"]}
|
124
|
+
section
|
125
|
+
end.reject do |section|
|
126
|
+
section.empty?
|
127
|
+
end
|
128
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "@sections=#{@sections}"]}
|
129
|
+
@sections
|
130
|
+
end
|
131
|
+
|
132
|
+
def section(id)
|
133
|
+
@sections ? @sections.detect {|e| e.id == id} : nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def visible_columns
|
137
|
+
@visible_columns ||= visible_column_indexes.map {|i| columns[i]}
|
138
|
+
end
|
139
|
+
|
140
|
+
def visible_column_indexes
|
141
|
+
@visible_column_indexes
|
142
|
+
end
|
143
|
+
|
144
|
+
def column_ids
|
145
|
+
columns.map(&:id)
|
146
|
+
end
|
147
|
+
|
148
|
+
def caption_attributes
|
149
|
+
# TODO:
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
|
153
|
+
def cell_attributes(section_id)
|
154
|
+
# TODO:
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def section_attributes(section_id)
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
|
162
|
+
def sorted?
|
163
|
+
!!@sort_column_id
|
164
|
+
end
|
165
|
+
|
166
|
+
# set or toggle the sort order to/of the given column
|
167
|
+
def sort!(sort_column_id)
|
168
|
+
update_sorting(sort_column_id)
|
169
|
+
update_sections
|
170
|
+
end
|
171
|
+
|
172
|
+
def row_source(section_id)
|
173
|
+
@row_sources[section_id]
|
174
|
+
end
|
175
|
+
|
176
|
+
def update
|
177
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
178
|
+
@root = nil
|
179
|
+
init_sorting
|
180
|
+
update_caption
|
181
|
+
update_sections
|
182
|
+
end
|
183
|
+
|
184
|
+
def update_caption
|
185
|
+
@caption.update if @caption
|
186
|
+
end
|
187
|
+
|
188
|
+
def update_sections(ids = nil)
|
189
|
+
ids = ids || section_ids
|
190
|
+
ids.each do |id|
|
191
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "id=#{id} " ]}
|
192
|
+
update_section(id)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def update_section(id)
|
197
|
+
section = section(id)
|
198
|
+
if section
|
199
|
+
section.update
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def update_head
|
204
|
+
update_section :head
|
205
|
+
end
|
206
|
+
|
207
|
+
def update_body
|
208
|
+
update_section :body
|
209
|
+
end
|
210
|
+
|
211
|
+
def update_foot
|
212
|
+
update_section :foot
|
213
|
+
end
|
214
|
+
|
215
|
+
# source should be source (unsorted) index or row source (model)
|
216
|
+
# columns may be visible column indexes or Column's
|
217
|
+
def update_row(section_id, source, columns = nil)
|
218
|
+
section = section(section_id)
|
219
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "section_id=#{section_id} source=#{source} columns=#{columns} section=#{section}" ]}
|
220
|
+
if section
|
221
|
+
section.update_row(source, columns)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# source should be source (unsorted) index or row source (model)
|
226
|
+
# column may be visible column index or a Column
|
227
|
+
def update_cell(section_id, source, column)
|
228
|
+
section = section(section_id)
|
229
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "section_id=#{section_id} source=#{source} column=#{column} section=#{section}" ]}
|
230
|
+
if section
|
231
|
+
section.update_cell(source, column)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
236
|
+
|
237
|
+
def init_sections(options)
|
238
|
+
# TODO: from options
|
239
|
+
@section_ids = [:head, :body, :foot]
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
def init_row_sources(options)
|
244
|
+
@row_sources = {}
|
245
|
+
section_ids.each do |id|
|
246
|
+
@row_sources[id] = options[:"#{id}_rows"]
|
247
|
+
end
|
248
|
+
debug 1, ->{[ __FILE__, __LINE__, __method__, "@row_sources=#{@row_sources}" ]}
|
249
|
+
end
|
250
|
+
|
251
|
+
def init_accordion(options)
|
252
|
+
@accordion = !!options[:accordion]
|
253
|
+
end
|
254
|
+
|
255
|
+
def init_css_style(options)
|
256
|
+
@css = options[:css] || DEFAULT_CSS
|
257
|
+
@style = options[:style] || DEFAULT_STYLE
|
258
|
+
end
|
259
|
+
|
260
|
+
def init_caption(options)
|
261
|
+
@caption_content = options[:caption]
|
262
|
+
end
|
263
|
+
|
264
|
+
def init_sorting(options = nil)
|
265
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__ ]}
|
266
|
+
if options
|
267
|
+
@initial_sort_column_id = options[:sort_column_id]
|
268
|
+
@initial_sort_order = options[:sort_order]
|
269
|
+
end
|
270
|
+
@sort_column_id = sort_column_id unless
|
271
|
+
@sort_column = @sort_column_id ? columns.detect {|c| c.id == @sort_column_id} : columns.detect {|c| c.sort?}
|
272
|
+
@sort_column_id = @sort_column ? @sort_column.id : nil
|
273
|
+
@sort_order = @initial_sort_order || 1 unless @sort_order
|
274
|
+
@sort_orders = {}
|
275
|
+
if @sort_column_id
|
276
|
+
columns.each { |c| sort_orders[c.id] = c.id == sort_column_id ? @sort_order : 1 }
|
277
|
+
end
|
278
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "@sort_column_id=#{@sort_column_id}" ]}
|
279
|
+
end
|
280
|
+
|
281
|
+
def update_sorting(sort_column_id)
|
282
|
+
# debug 1, ->{[ __FILE__, __LINE__, __method__, "column_id=#{column_id}" ]}
|
283
|
+
if @sort_column_id == sort_column_id
|
284
|
+
sort_orders[@sort_column_id] *= -1
|
285
|
+
else
|
286
|
+
@sort_column_id = sort_column_id
|
287
|
+
@sort_column = columns.detect {|c| c.id == @sort_column_id}
|
288
|
+
end
|
289
|
+
@sort_order = sort_orders[@sort_column_id]
|
290
|
+
end
|
291
|
+
|
292
|
+
def init_visibility
|
293
|
+
@visible_column_indexes = columns.size.times.to_a
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
end # module DOM
|
299
|
+
end # module CSR
|
300
|
+
|