cml 1.4.2 → 1.5.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/.rspec +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +33 -0
- data/README.rdoc +13 -3
- data/Rakefile +9 -49
- data/cml.gemspec +23 -125
- data/lib/cml/converters/jsawesome.rb +3 -3
- data/lib/cml/gold.rb +12 -7
- data/lib/cml/liquid_filters.rb +4 -0
- data/lib/cml/logic.rb +424 -0
- data/lib/cml/logic_tree/graph.rb +107 -0
- data/lib/cml/logic_tree/solver.rb +43 -0
- data/lib/cml/parser.rb +47 -7
- data/lib/cml/tag.rb +42 -21
- data/lib/cml/tags/checkbox.rb +14 -4
- data/lib/cml/tags/checkboxes.rb +4 -0
- data/lib/cml/tags/group.rb +4 -0
- data/lib/cml/tags/hours.rb +263 -0
- data/lib/cml/tags/iterate.rb +4 -0
- data/lib/cml/tags/meta.rb +4 -0
- data/lib/cml/tags/option.rb +4 -0
- data/lib/cml/tags/radio.rb +13 -4
- data/lib/cml/tags/radios.rb +4 -0
- data/lib/cml/tags/ratings.rb +9 -1
- data/lib/cml/tags/search.rb +8 -2
- data/lib/cml/tags/select.rb +6 -2
- data/lib/cml/tags/taxonomy.rb +148 -0
- data/lib/cml/tags/thumb.rb +4 -0
- data/lib/cml/tags/unknown.rb +4 -0
- data/lib/cml/version.rb +3 -0
- data/lib/cml.rb +3 -0
- data/spec/converters/jsawesome_spec.rb +0 -9
- data/spec/fixtures/logic_broken.cml +5 -0
- data/spec/fixtures/logic_circular.cml +5 -0
- data/spec/fixtures/logic_grouped.cml +7 -0
- data/spec/fixtures/logic_nested.cml +7 -0
- data/spec/fixtures/logic_none.cml +7 -0
- data/spec/fixtures/logic_not_nested.cml +7 -0
- data/spec/liquid_filter_spec.rb +19 -0
- data/spec/logic_depends_on_spec.rb +242 -0
- data/spec/logic_spec.rb +207 -0
- data/spec/logic_tree_graph_spec.rb +465 -0
- data/spec/logic_tree_solver_spec.rb +58 -0
- data/spec/meta_spec.rb +12 -2
- data/spec/show_data_spec.rb +3 -2
- data/spec/spec_helper.rb +22 -6
- data/spec/tags/checkboxes_spec.rb +2 -2
- data/spec/tags/group_spec.rb +5 -5
- data/spec/tags/hours_spec.rb +404 -0
- data/spec/tags/radios_spec.rb +2 -2
- data/spec/tags/ratings_spec.rb +1 -1
- data/spec/tags/select_spec.rb +45 -0
- data/spec/tags/tag_spec.rb +25 -0
- data/spec/tags/taxonomy_spec.rb +112 -0
- data/spec/validation_spec.rb +52 -0
- metadata +112 -17
- data/VERSION +0 -1
data/lib/cml/tag.rb
CHANGED
@@ -2,9 +2,28 @@ require 'cgi'
|
|
2
2
|
|
3
3
|
module CML
|
4
4
|
class Tag
|
5
|
+
|
6
|
+
include CML::TagLogic
|
7
|
+
|
5
8
|
attr_reader :attrs, :tag, :data, :cml, :opts
|
6
9
|
#liquid_methods :raw_label
|
7
10
|
|
11
|
+
#memoize hotness
|
12
|
+
def self.memoize(*methods)
|
13
|
+
methods.each do |m|
|
14
|
+
class_eval %Q{
|
15
|
+
alias :original_#{m} :#{m}
|
16
|
+
|
17
|
+
def #{m}(*args)
|
18
|
+
@#{m}_cache ||= {}
|
19
|
+
key = {:prefix => @opts[:prefix], :missed => @opts[:missed]}.merge(:_args => args)
|
20
|
+
return @#{m}_cache[key] if @#{m}_cache[key]
|
21
|
+
@#{m}_cache[key] = self.original_#{m}(*args)
|
22
|
+
end
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
8
27
|
def initialize(cml, opts = {})
|
9
28
|
@cml = cml.is_a?(String) ? Parser.parse(cml).at("/root/*") : cml
|
10
29
|
@attrs = @cml.attributes#Hash[*cml.attributes.map {|k,v| [k.intern,v]}.flatten]
|
@@ -16,10 +35,14 @@ module CML
|
|
16
35
|
def prefix(name)
|
17
36
|
if @opts[:iteration]
|
18
37
|
m = case @tag
|
19
|
-
when "checkbox"
|
20
|
-
|
21
|
-
when "
|
22
|
-
|
38
|
+
when "checkbox"
|
39
|
+
"[{{i}}][]"
|
40
|
+
when "radio"
|
41
|
+
"[{{i}}]"
|
42
|
+
when "rating"
|
43
|
+
@opts[:normalize] ? "[{{i}}][]" : "[{{i}}]"
|
44
|
+
when "text", "textarea"
|
45
|
+
@opts[:normalize] ? "[{{i}}][]" : "[]"
|
23
46
|
else
|
24
47
|
"[]"
|
25
48
|
end
|
@@ -52,7 +75,8 @@ module CML
|
|
52
75
|
#:list means an array of values in the result csv
|
53
76
|
#:columnlist means a new column that is a list
|
54
77
|
def multi_type
|
55
|
-
grouped =
|
78
|
+
grouped = self.parent_multiples
|
79
|
+
|
56
80
|
if @attrs["multiple"] || !grouped.empty?
|
57
81
|
if @cml.at(".//cml:checkboxes|.//cml:radios|.//cml:ratings")
|
58
82
|
:column
|
@@ -72,6 +96,11 @@ module CML
|
|
72
96
|
end
|
73
97
|
end
|
74
98
|
|
99
|
+
def parent_multiples
|
100
|
+
@cml.xpath("ancestor::cml:*[@multiple]")
|
101
|
+
end
|
102
|
+
memoize :parent_multiples
|
103
|
+
|
75
104
|
def gold?
|
76
105
|
@attrs["gold"] ? @cml : @cml.at("./cml:gold")
|
77
106
|
end
|
@@ -191,7 +220,7 @@ module CML
|
|
191
220
|
end
|
192
221
|
|
193
222
|
def validations
|
194
|
-
@validations ||= validators.map {|v| "validates-#{v}"}
|
223
|
+
@validations ||= validators.map {|v| v.to_s.empty? ? nil : "validates-#{v}"}.compact
|
195
224
|
end
|
196
225
|
|
197
226
|
def instructions
|
@@ -264,6 +293,10 @@ module CML
|
|
264
293
|
})
|
265
294
|
end
|
266
295
|
|
296
|
+
def finite_value?
|
297
|
+
(@attrs['is-finite'] && @attrs['is-finite'].value=='true') || false
|
298
|
+
end
|
299
|
+
|
267
300
|
protected
|
268
301
|
|
269
302
|
def data_attributes
|
@@ -288,21 +321,9 @@ module CML
|
|
288
321
|
|
289
322
|
attributes.join(" ")
|
290
323
|
end
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
methods.each do |m|
|
295
|
-
class_eval %Q{
|
296
|
-
alias :original_#{m} :#{m}
|
297
|
-
|
298
|
-
def #{m}(*args)
|
299
|
-
@#{m}_cache ||= {}
|
300
|
-
key = {:prefix => @opts[:prefix], :missed => @opts[:missed]}.merge(:_args => args)
|
301
|
-
return @#{m}_cache[key] if @#{m}_cache[key]
|
302
|
-
@#{m}_cache[key] = send(:original_#{m}, *args)
|
303
|
-
end
|
304
|
-
}
|
305
|
-
end
|
324
|
+
|
325
|
+
def title_attribute
|
326
|
+
@attrs['title'].nil? ? "" :"title=\"#{@attrs['title']}\""
|
306
327
|
end
|
307
328
|
end
|
308
329
|
end
|
data/lib/cml/tags/checkbox.rb
CHANGED
@@ -7,7 +7,7 @@ module CML
|
|
7
7
|
HTML
|
8
8
|
|
9
9
|
Template = <<-HTML.freeze
|
10
|
-
{{default_normalized}}<div class="cml_row"><label class="{{gold_class}}">#{BareTemplate} {{label}}</label></div>
|
10
|
+
{{default_normalized}}<div class="cml_row" {{title}}><label class="{{gold_class}}">#{BareTemplate} {{label}}</label></div>
|
11
11
|
HTML
|
12
12
|
|
13
13
|
def prefix(name)
|
@@ -20,6 +20,14 @@ module CML
|
|
20
20
|
@opts[:bare] || (@cml.parent && @cml.parent.name == "checkboxes")
|
21
21
|
end
|
22
22
|
|
23
|
+
def in_logic_graph?
|
24
|
+
!grouped?
|
25
|
+
end
|
26
|
+
|
27
|
+
def finite_value?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
23
31
|
def wrapper(parsed)
|
24
32
|
grouped? || @opts[:no_reason] ? parsed : super
|
25
33
|
end
|
@@ -47,7 +55,7 @@ module CML
|
|
47
55
|
end
|
48
56
|
elsif preload = preloaded_data
|
49
57
|
manipulated = true
|
50
|
-
if preload.map{|x| x.to_s.downcase }.include?(value.to_s.downcase)
|
58
|
+
if Array(preload).map{|x| x.to_s.downcase }.include?(value.to_s.downcase)
|
51
59
|
return "checked=\"checked\""
|
52
60
|
end
|
53
61
|
end
|
@@ -70,8 +78,10 @@ module CML
|
|
70
78
|
"default" => default,
|
71
79
|
"default_normalized" => default_normalized,
|
72
80
|
"checked" => c,
|
73
|
-
"label" => @attrs["label"].to_s
|
81
|
+
"label" => @attrs["label"].to_s,
|
82
|
+
"title" => title_attribute
|
83
|
+
})
|
74
84
|
end
|
75
85
|
end
|
76
86
|
end
|
77
|
-
end
|
87
|
+
end
|
data/lib/cml/tags/checkboxes.rb
CHANGED
data/lib/cml/tags/group.rb
CHANGED
@@ -0,0 +1,263 @@
|
|
1
|
+
module CML
|
2
|
+
|
3
|
+
class TimeSelect
|
4
|
+
HOURS = [12, 1.upto(11).to_a]
|
5
|
+
MINUTES = [0, 15, 30, 45]
|
6
|
+
SUFFIXES = [:am, :pm]
|
7
|
+
|
8
|
+
BlankOption = "<option value=\"\">Select one:</option>"
|
9
|
+
GoldBlankOption = "<option value=\"\">(Any)</option>"
|
10
|
+
NotListedOption = "<option{{selected_att}} value=\"not_listed\">(Not listed)</option>"
|
11
|
+
|
12
|
+
# Builds a time <select> input that submits military time values.
|
13
|
+
def self.build( name, gold=false, opts={} )
|
14
|
+
opts = {
|
15
|
+
:selected => nil,
|
16
|
+
:allow_unlisted => false
|
17
|
+
}.merge( opts )
|
18
|
+
|
19
|
+
time_options = SUFFIXES.map do |am_pm|
|
20
|
+
HOURS.flatten.map do |h|
|
21
|
+
h_mil = h
|
22
|
+
h_mil = 0 if h_mil == 12 && am_pm == :am
|
23
|
+
MINUTES.map do |m|
|
24
|
+
time_label = "#{h}:#{self.zero_pad(m)}#{am_pm}"
|
25
|
+
mil_time = self.to_military( h_mil, m, am_pm )
|
26
|
+
selected_att = mil_time == opts[:selected] ? " selected=\"selected\"" : ""
|
27
|
+
"<option#{selected_att} value=\"#{mil_time}\">#{time_label}</option>"
|
28
|
+
end.join("")
|
29
|
+
end.join("")
|
30
|
+
end.join("")
|
31
|
+
extras = gold ? GoldBlankOption : BlankOption
|
32
|
+
|
33
|
+
# Add the not listed field and select it if needed
|
34
|
+
if opts[:allow_unlisted]
|
35
|
+
selected_att = "not_listed" == opts[:selected] ? " selected=\"selected\"" : ""
|
36
|
+
not_listed_html = Liquid::Template.parse( NotListedOption ).render( "selected_att" => selected_att )
|
37
|
+
extras += not_listed_html
|
38
|
+
end
|
39
|
+
|
40
|
+
"<select name=\"#{name}\" class=\"cml_hours_time\">#{extras}#{time_options}</select>"
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def self.zero_pad( num )
|
46
|
+
'%02d' % num
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.to_military( hour, minute, am_pm )
|
50
|
+
if am_pm == :am
|
51
|
+
hour = 0 if minute == 0 && hour == 12
|
52
|
+
elsif hour < 12
|
53
|
+
hour = hour + 12
|
54
|
+
end
|
55
|
+
|
56
|
+
"#{self.zero_pad( hour )}:#{self.zero_pad( minute )}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# =============
|
61
|
+
# = CML:Hours =
|
62
|
+
# =============
|
63
|
+
|
64
|
+
module Tags
|
65
|
+
class Hours < Tag
|
66
|
+
|
67
|
+
DAYS = [
|
68
|
+
{ :key => 'mon', :label => "Monday" },
|
69
|
+
{ :key => 'tue', :label => "Tuesday" },
|
70
|
+
{ :key => 'wed', :label => "Wednesday" },
|
71
|
+
{ :key => 'thu', :label => "Thursday" },
|
72
|
+
{ :key => 'fri', :label => "Friday" },
|
73
|
+
{ :key => 'sat', :label => "Saturday" },
|
74
|
+
# { :key => 'cat', :label => "Caturday" },
|
75
|
+
{ :key => 'sun', :label => "Sunday" }
|
76
|
+
]
|
77
|
+
|
78
|
+
# =============
|
79
|
+
# = Templates =
|
80
|
+
# =============
|
81
|
+
|
82
|
+
Template = <<-HTML.freeze
|
83
|
+
{{label}}
|
84
|
+
<table class="cml_hours cml_row {{classes}}">
|
85
|
+
{{rows_html}}
|
86
|
+
</table>
|
87
|
+
HTML
|
88
|
+
|
89
|
+
RowTemplate = Liquid::Template.parse(<<-HTML.freeze)
|
90
|
+
<tr class="cml_hours_{{day_key}}">
|
91
|
+
<td class="cml_hours_day">{{day_label}}</td>
|
92
|
+
<td class="cml_hours_hours">
|
93
|
+
<p class="cml_hours_1">
|
94
|
+
<span class="cml_hours_selects">{{hours_open_1}}</span>
|
95
|
+
<span class="cml_hours_to">to</span>
|
96
|
+
<span class="cml_hours_selects">{{hours_close_1}}</span>
|
97
|
+
</p>
|
98
|
+
<p class="cml_hours_2">
|
99
|
+
<span class="cml_hours_selects">{{hours_open_2}}</span>
|
100
|
+
<span class="cml_hours_to">to</span>
|
101
|
+
<span class="cml_hours_selects">{{hours_close_2}}</span>
|
102
|
+
</p>
|
103
|
+
</td>
|
104
|
+
<td class="cml_hours_open_close">
|
105
|
+
<p class="cml_hours_openallday">
|
106
|
+
{{open_checkbox}}
|
107
|
+
</p>
|
108
|
+
<p class="cml_hours_closedallday">
|
109
|
+
{{closed_checkbox}}
|
110
|
+
</p>
|
111
|
+
</td>
|
112
|
+
</tr>
|
113
|
+
HTML
|
114
|
+
|
115
|
+
TrueFalseCheckboxTemplate = Liquid::Template.parse(<<-HTML)
|
116
|
+
<input type="hidden" name="{{name}}" value="FALSE" />
|
117
|
+
<input {{checked}}type="checkbox" name="{{name}}" id="{{id}}" value="TRUE" />
|
118
|
+
<label for="{{id}}">{{label}}</label>
|
119
|
+
HTML
|
120
|
+
|
121
|
+
TimeSelectTemplate = Liquid::Template.parse( TimeSelect.build( "{{name}}", false ) )
|
122
|
+
TimeSelectTemplateAllowUnlisted = Liquid::Template.parse( TimeSelect.build( "{{name}}", false, :allow_unlisted => true ) )
|
123
|
+
|
124
|
+
def initialize(cml, opts = {})
|
125
|
+
super( cml, opts )
|
126
|
+
@attrs["matcher"] = "hours"
|
127
|
+
@attrs["validates"] = @attrs["validates"].to_s + " hours"
|
128
|
+
@attrs["allowunlisted"] = !(@attrs["allowunlisted"].to_s =~ /^t/i).nil?
|
129
|
+
end
|
130
|
+
|
131
|
+
def finite_value?
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
# =============
|
136
|
+
# = Rendering =
|
137
|
+
# =============
|
138
|
+
|
139
|
+
def to_html
|
140
|
+
data = self.data.merge({
|
141
|
+
"rows_html" => rows_html
|
142
|
+
})
|
143
|
+
rendered = Liquid::Template.parse( Template ).render( data )
|
144
|
+
wrapper( rendered )
|
145
|
+
end
|
146
|
+
|
147
|
+
# =============
|
148
|
+
# = Normalize =
|
149
|
+
# =============
|
150
|
+
|
151
|
+
def normalize?
|
152
|
+
@opts[:normalize]
|
153
|
+
end
|
154
|
+
|
155
|
+
def raw_data
|
156
|
+
@opts[:data] || {}
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns data value as array of values or nil, if none.
|
160
|
+
def normalized_data_value( name )
|
161
|
+
val = raw_data[name]
|
162
|
+
if val && !val.empty?
|
163
|
+
Array( val )
|
164
|
+
else
|
165
|
+
nil
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# "true", true, "coolio" --> true
|
170
|
+
# "false", false, "", nil --> false
|
171
|
+
def truthy_checkbox_value?( value )
|
172
|
+
value = value.is_a?(Array) ? value[0].to_s : value.to_s
|
173
|
+
!( value.empty? || value =~ /^f/i )
|
174
|
+
end
|
175
|
+
|
176
|
+
# ===============
|
177
|
+
# = Field names =
|
178
|
+
# ===============
|
179
|
+
|
180
|
+
# Builds a field name for the given day and suffix. e.g:
|
181
|
+
# field_name( <tue>, "open_1" ) --> "u123[my_field_tue_open_1]"
|
182
|
+
def field_name( day, field_suffix )
|
183
|
+
prefix( name( true, "#{day[:key]}_#{field_suffix}" ) )
|
184
|
+
end
|
185
|
+
|
186
|
+
protected
|
187
|
+
|
188
|
+
# Render a time <select> for the given day and field suffix ("open_1",
|
189
|
+
# "closed_1", etc.)
|
190
|
+
def time_select_html( day, suffix )
|
191
|
+
key = name( true, "#{day[:key]}_#{suffix}" )
|
192
|
+
name = field_name( day, suffix )
|
193
|
+
allow_unlisted = @attrs["allowunlisted"]
|
194
|
+
|
195
|
+
if normalize?
|
196
|
+
if values = self.normalized_data_value( key )
|
197
|
+
# With preloaded values
|
198
|
+
values.map do |value|
|
199
|
+
TimeSelect.build( name, true, {
|
200
|
+
:selected => value,
|
201
|
+
:allow_unlisted => allow_unlisted
|
202
|
+
})
|
203
|
+
end.join( "\n" )
|
204
|
+
else
|
205
|
+
# No preloaded values
|
206
|
+
TimeSelect.build( name, true, :allow_unlisted => allow_unlisted )
|
207
|
+
end
|
208
|
+
else
|
209
|
+
template = allow_unlisted ? TimeSelectTemplateAllowUnlisted : TimeSelectTemplate
|
210
|
+
template.render( 'name' => name )
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Turn any string into a reasonable id attribute
|
215
|
+
def make_id( str )
|
216
|
+
"id_#{str}".gsub(/[^a-z0-9\{\}]/, "_").gsub(/_+/, "_").sub(/_+$/, "")
|
217
|
+
end
|
218
|
+
|
219
|
+
# Render HTML with a <tr> of inputs for every day of the week
|
220
|
+
def rows_html
|
221
|
+
DAYS.map do |day|
|
222
|
+
RowTemplate.render({
|
223
|
+
"day_key" => day[:key],
|
224
|
+
"day_label" => day[:label],
|
225
|
+
'open_checkbox' => self.open_all_day_html( day ),
|
226
|
+
'closed_checkbox' => self.closed_all_day_html( day ),
|
227
|
+
"hours_open_1" => self.time_select_html( day, "open_1" ),
|
228
|
+
"hours_close_1" => self.time_select_html( day, "close_1" ),
|
229
|
+
"hours_open_2" => self.time_select_html( day, "open_2" ),
|
230
|
+
"hours_close_2" => self.time_select_html( day, "close_2" )
|
231
|
+
})
|
232
|
+
end.join("\n")
|
233
|
+
end
|
234
|
+
|
235
|
+
def open_all_day_html( day )
|
236
|
+
self.checkbox_html( "Open all day", day, "openallday" )
|
237
|
+
end
|
238
|
+
|
239
|
+
def closed_all_day_html( day )
|
240
|
+
self.checkbox_html( "Closed all day", day, "closedallday" )
|
241
|
+
end
|
242
|
+
|
243
|
+
# Build HTML for a "TRUE" / "FALSE" checkbox with the usual hidden input
|
244
|
+
# hackery.
|
245
|
+
def checkbox_html( label, day, suffix )
|
246
|
+
key = name( true, "#{day[:key]}_#{suffix}" )
|
247
|
+
name = field_name( day, suffix )
|
248
|
+
if truthy_checkbox_value?( raw_data[key] )
|
249
|
+
checked = "checked=\"checked\" "
|
250
|
+
else
|
251
|
+
checked = ""
|
252
|
+
end
|
253
|
+
|
254
|
+
TrueFalseCheckboxTemplate.render({
|
255
|
+
'name' => name,
|
256
|
+
'id' => self.make_id( name ),
|
257
|
+
'label' => label,
|
258
|
+
'checked' => checked
|
259
|
+
})
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
data/lib/cml/tags/iterate.rb
CHANGED
data/lib/cml/tags/meta.rb
CHANGED
data/lib/cml/tags/option.rb
CHANGED
data/lib/cml/tags/radio.rb
CHANGED
@@ -6,7 +6,7 @@ module CML
|
|
6
6
|
HTML
|
7
7
|
|
8
8
|
Template = <<-HTML.freeze
|
9
|
-
<div class="cml_row"><label class="{{gold_class}}">#{BareTemplate} {{label}}</label></div>
|
9
|
+
<div class="cml_row" {{title}}><label class="{{gold_class}}">#{BareTemplate} {{label}}</label></div>
|
10
10
|
HTML
|
11
11
|
|
12
12
|
#Radios should always be grouped, but for consistency with checkboxes, we check
|
@@ -14,6 +14,14 @@ module CML
|
|
14
14
|
@opts[:bare] || (@cml.parent && ["radios","ratings"].include?(@cml.parent.name))
|
15
15
|
end
|
16
16
|
|
17
|
+
def in_logic_graph?
|
18
|
+
!grouped?
|
19
|
+
end
|
20
|
+
|
21
|
+
def finite_value?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
17
25
|
def wrapper(parsed)
|
18
26
|
grouped? ? parsed : super
|
19
27
|
end
|
@@ -30,7 +38,7 @@ module CML
|
|
30
38
|
manipulated = !@opts[:missed].nil?
|
31
39
|
if preload = preloaded_data
|
32
40
|
manipulated = true
|
33
|
-
if preload.map{|x| x.to_s.downcase }.include?(value.to_s.downcase)
|
41
|
+
if Array(preload).map{|x| x.to_s.downcase }.include?(value.to_s.downcase)
|
34
42
|
return "checked=\"checked\""
|
35
43
|
end
|
36
44
|
end
|
@@ -40,9 +48,10 @@ module CML
|
|
40
48
|
def data
|
41
49
|
super.merge({
|
42
50
|
"checked" => checked,
|
43
|
-
"label" => @attrs["label"].to_s
|
51
|
+
"label" => @attrs["label"].to_s,
|
52
|
+
"title" => title_attribute
|
44
53
|
})
|
45
54
|
end
|
46
55
|
end
|
47
56
|
end
|
48
|
-
end
|
57
|
+
end
|
data/lib/cml/tags/radios.rb
CHANGED
data/lib/cml/tags/ratings.rb
CHANGED
@@ -39,6 +39,10 @@ module CML
|
|
39
39
|
def gold_classes
|
40
40
|
ratings.map {|rating| rating.gold_class }
|
41
41
|
end
|
42
|
+
|
43
|
+
def children
|
44
|
+
ratings
|
45
|
+
end
|
42
46
|
|
43
47
|
def ratings
|
44
48
|
if @cml.xpath(".//cml:rating").empty?
|
@@ -56,6 +60,10 @@ module CML
|
|
56
60
|
end
|
57
61
|
end
|
58
62
|
memoize :ratings
|
63
|
+
|
64
|
+
def finite_value?
|
65
|
+
true
|
66
|
+
end
|
59
67
|
end
|
60
68
|
end
|
61
|
-
end
|
69
|
+
end
|
data/lib/cml/tags/search.rb
CHANGED
@@ -25,6 +25,10 @@ module CML
|
|
25
25
|
!(@attrs["field"] && @attrs["field"].to_s == "false")
|
26
26
|
end
|
27
27
|
|
28
|
+
def in_logic_graph?
|
29
|
+
is_field?
|
30
|
+
end
|
31
|
+
|
28
32
|
def search_terms_classes
|
29
33
|
(@attrs["default"] ? "default " : "") + engine + " no_validate"
|
30
34
|
end
|
@@ -46,11 +50,13 @@ module CML
|
|
46
50
|
end
|
47
51
|
|
48
52
|
def search_terms_value
|
49
|
-
((@opts[:data] || {})[search_terms_name] || @attrs["default"])
|
53
|
+
val = ((@opts[:data] || {})[search_terms_name] || @attrs["default"])
|
54
|
+
val.is_a?(Array) ? val[0].to_s : val.to_s
|
50
55
|
end
|
51
56
|
|
52
57
|
def search_result_value
|
53
|
-
(@attrs["value"] || (@opts[:data] || {})[name] || "")
|
58
|
+
val = (@attrs["value"] || (@opts[:data] || {})[name] || "")
|
59
|
+
val.is_a?(Array) ? val[0].to_s : val.to_s
|
54
60
|
end
|
55
61
|
|
56
62
|
def data
|
data/lib/cml/tags/select.rb
CHANGED
@@ -34,7 +34,7 @@ module CML
|
|
34
34
|
# Preloaded data
|
35
35
|
preload = preloaded_data
|
36
36
|
|
37
|
-
cloned.
|
37
|
+
cloned.children.first.add_previous_sibling(d[0].cml) if d.length > 0
|
38
38
|
cloned.xpath(".//cml:*[not(self::cml:option)]").remove
|
39
39
|
cloned.xpath(".//cml:option").each_with_index do |r,i|
|
40
40
|
r.namespace = nil
|
@@ -45,6 +45,10 @@ module CML
|
|
45
45
|
cloned.to_xhtml.gsub(/<\/?cml:select[^>]*?>|<\/?>/,'')
|
46
46
|
end
|
47
47
|
memoize :content
|
48
|
+
|
49
|
+
def finite_value?
|
50
|
+
true
|
51
|
+
end
|
48
52
|
end
|
49
53
|
end
|
50
|
-
end
|
54
|
+
end
|