dom-rb 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|