clot_engine 1.2
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/lib/autotest/discover.rb +5 -0
- data/lib/clot/active_record/droppable.rb +22 -0
- data/lib/clot/base_drop.rb +116 -0
- data/lib/clot/date_tags.rb +342 -0
- data/lib/clot/deprecated.rb +11 -0
- data/lib/clot/form_filters.rb +130 -0
- data/lib/clot/form_for.rb +234 -0
- data/lib/clot/form_tag.rb +24 -0
- data/lib/clot/if_content_for.rb +32 -0
- data/lib/clot/link_filters.rb +101 -0
- data/lib/clot/model_date_tags.rb +82 -0
- data/lib/clot/model_form_tags.rb +205 -0
- data/lib/clot/mongo_mapper/droppable.rb +29 -0
- data/lib/clot/nav_bar.rb +154 -0
- data/lib/clot/no_model_form_tags.rb +233 -0
- data/lib/clot/protected.rb +25 -0
- data/lib/clot/tag_helper.rb +22 -0
- data/lib/clot/url_filters.rb +48 -0
- data/lib/clot/yield.rb +59 -0
- data/lib/clot_engine.rb +78 -0
- metadata +81 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'clot/model_form_tags'
|
2
|
+
|
3
|
+
module Clot
|
4
|
+
class ModelMultiDateTag < MultiDateTag
|
5
|
+
include ModelTag
|
6
|
+
|
7
|
+
def fill_zeros(val)
|
8
|
+
if val < 10
|
9
|
+
"0#{val}"
|
10
|
+
else
|
11
|
+
val
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def set_unit(unit)
|
17
|
+
order = get_unit_order(unit)
|
18
|
+
prompt = instance_variable_get("@#{unit}_prompt".to_sym)
|
19
|
+
id_string = %{id_string_val:"#{@first_attr}_#{@attribute_name}_#{order}i",}
|
20
|
+
name_string = %{name_string_val:"#{@first_attr}[#{@attribute_name}(#{order}i)]",}
|
21
|
+
@include_blank && (prompt ||= "prompt:'',")
|
22
|
+
line = "#{@time.send(time_unit(unit).to_sym).to_s},#{id_string} #{name_string}#{@minute_step}#{@start_year}#{@use_month_numbers}#{prompt || @prompt}"
|
23
|
+
instance_variable_set "@#{unit}",
|
24
|
+
"Clot::Select#{unit.capitalize}".constantize.new(".select_#{unit}", line,[])
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_unit_order(unit)
|
28
|
+
case unit
|
29
|
+
when "year" then 1
|
30
|
+
when "month" then 2
|
31
|
+
when "day" then 3
|
32
|
+
when "hour" then 4
|
33
|
+
when "minute" then 5
|
34
|
+
when "second" then 6
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class TimeSelect < ModelMultiDateTag
|
41
|
+
|
42
|
+
|
43
|
+
def render_nested(context)
|
44
|
+
@time = @value_string || Time.zone.now
|
45
|
+
time_units = ["hour", "minute"]
|
46
|
+
if @include_seconds
|
47
|
+
time_units << "second"
|
48
|
+
end
|
49
|
+
time_result = render_units(time_units, context, @time_separator)
|
50
|
+
year = %{<input id="#{@first_attr}_#{@attribute_name}_1i" name="#{@first_attr}[#{@attribute_name}(1i)]" type="hidden" value="#{@time.year}" />}
|
51
|
+
month = %{<input id="#{@first_attr}_#{@attribute_name}_2i" name="#{@first_attr}[#{@attribute_name}(2i)]" type="hidden" value="#{@time.month}" />}
|
52
|
+
day = %{<input id="#{@first_attr}_#{@attribute_name}_3i" name="#{@first_attr}[#{@attribute_name}(3i)]" type="hidden" value="#{@time.day}" />}
|
53
|
+
year + month + day + time_result
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class DateSelect < ModelMultiDateTag
|
61
|
+
def render_nested(context)
|
62
|
+
@time = @value_string || Time.zone.now
|
63
|
+
date_units = @order || ['year', 'month', 'day']
|
64
|
+
@discard_day && date_units.delete("day")
|
65
|
+
|
66
|
+
date_result = render_units(date_units, context, @date_separator)
|
67
|
+
date_result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class DatetimeSelect < ModelMultiDateTag
|
72
|
+
def render_nested(context)
|
73
|
+
@time = @value_string || Time.zone.now
|
74
|
+
date_units = ['year', 'month', 'day']
|
75
|
+
time_units = ["hour", "minute"]
|
76
|
+
time_result = render_units(time_units, context, @time_separator)
|
77
|
+
date_result = render_units(date_units, context, @date_separator)
|
78
|
+
date_result + @datetime_separator.to_s + time_result
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
module Clot
|
2
|
+
module ModelTag
|
3
|
+
def set_primary_attributes(context)
|
4
|
+
@item = context['form_model']
|
5
|
+
if @item
|
6
|
+
|
7
|
+
@attribute_name = resolve_value(@params.shift,context)
|
8
|
+
@first_attr = context['form_class_name']
|
9
|
+
else
|
10
|
+
@first_attr = @params.shift
|
11
|
+
|
12
|
+
if @params[0] && ! @params[0].match(/:/)
|
13
|
+
@attribute_name = resolve_value(@params.shift,context)
|
14
|
+
end
|
15
|
+
@item = context[@first_attr]
|
16
|
+
end
|
17
|
+
attribute_names = @attribute_name.split('.')
|
18
|
+
|
19
|
+
unless @item.source.respond_to?(:"#{attribute_names[0]}=")
|
20
|
+
raise "#{attribute_names[0]} is not a valid form field for #{@first_attr.camelize}."
|
21
|
+
end
|
22
|
+
|
23
|
+
if attribute_names.size == 3
|
24
|
+
@name_string = @first_attr + "[" + attribute_names[0].to_s + "_attributes][" + attribute_names[1].to_s + "_attributes][" + attribute_names[2].to_s + "]"
|
25
|
+
@id_string = @first_attr + "_" + attribute_names[0].to_s + "_attributes_" + attribute_names[1].to_s + "_" + attribute_names[2].to_s
|
26
|
+
@value_string = ""
|
27
|
+
if @item
|
28
|
+
@subitem = @item[attribute_names[0]][attribute_names[1]]
|
29
|
+
if @subitem
|
30
|
+
@value_string = @subitem[attribute_names[2].to_sym]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
elsif attribute_names.size == 2
|
34
|
+
@name_string = @first_attr + "[" + attribute_names[0].to_s + "_attributes][" + attribute_names[1].to_s + "]"
|
35
|
+
@id_string = @first_attr + "_" + attribute_names.join('_')
|
36
|
+
@value_string = ""
|
37
|
+
if @item
|
38
|
+
@subitem = @item[attribute_names[0]]
|
39
|
+
if @subitem
|
40
|
+
@value_string = @subitem[attribute_names[1].to_sym]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
else
|
44
|
+
@id_string = "#{@first_attr}_#{@attribute_name}"
|
45
|
+
@name_string = "#{@first_attr}[#{@attribute_name}]"
|
46
|
+
@value_string = @item[@attribute_name.to_sym]
|
47
|
+
end
|
48
|
+
@errors = context['form_errors'] || []
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def render(context)
|
53
|
+
result = super(context)
|
54
|
+
#if @errors.include? @attribute_name
|
55
|
+
# result = "<div class=\"fieldWithErrors\">#{result}</div>"
|
56
|
+
#end
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
class FileField < FileFieldTag
|
65
|
+
include ModelTag
|
66
|
+
|
67
|
+
def render_string
|
68
|
+
@value_string = nil
|
69
|
+
super
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class PasswordField < PasswordFieldTag
|
74
|
+
include ModelTag
|
75
|
+
end
|
76
|
+
|
77
|
+
class TextField < TextFieldTag
|
78
|
+
include ModelTag
|
79
|
+
end
|
80
|
+
class TextArea < TextAreaTag
|
81
|
+
include ModelTag
|
82
|
+
end
|
83
|
+
|
84
|
+
class Label < LabelTag
|
85
|
+
include ModelTag
|
86
|
+
|
87
|
+
def get_label_for(label)
|
88
|
+
label.humanize
|
89
|
+
end
|
90
|
+
|
91
|
+
def set_primary_attributes(context)
|
92
|
+
super context
|
93
|
+
if @params[0] && ! @params[0].match(/:/)
|
94
|
+
@value_string = resolve_value(@params.shift,context)
|
95
|
+
else
|
96
|
+
@value_string = get_label_for(@attribute_name)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class CollectionSelect < ClotTag
|
102
|
+
include ModelTag
|
103
|
+
def set_primary_attributes(context)
|
104
|
+
super context
|
105
|
+
if @params[0] && ! @params[0].match(/:/)
|
106
|
+
@collection = resolve_value(@params.shift,context)
|
107
|
+
end
|
108
|
+
@default_id = 'id'
|
109
|
+
@default_name = 'name'
|
110
|
+
if @params[0] && ! @params[0].match(/:/)
|
111
|
+
@default_id = resolve_value(@params.shift,context)
|
112
|
+
end
|
113
|
+
if @params[0] && ! @params[0].match(/:/)
|
114
|
+
@default_name = resolve_value(@params.shift,context)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def gen_option(item)
|
119
|
+
selection_string = ""
|
120
|
+
item_string = item
|
121
|
+
value_string = ""
|
122
|
+
|
123
|
+
# this line below is for BSON::ObjectId which doesn't respond to :id, but does :_id
|
124
|
+
@default_id = "_id" if @default_id == 'id' and item.respond_to?(:_id)
|
125
|
+
|
126
|
+
# @item = NationSignupDrop
|
127
|
+
# item = NationPlan
|
128
|
+
|
129
|
+
attribute_names = @attribute_name.split('.')
|
130
|
+
|
131
|
+
if item.is_a?(String) || item.is_a?(Fixnum) || item.is_a?(Float)
|
132
|
+
if (@item[@attribute_name.to_sym].to_s == item.to_s) || (@item.respond_to?(@attribute_name.to_sym) && @item.send(@attribute_name.to_sym).to_s == item.to_s)
|
133
|
+
selection_string = ' selected="selected"'
|
134
|
+
end
|
135
|
+
else
|
136
|
+
item_string = item[@default_name.to_sym] || (@item.respond_to?(@attribute_name.to_sym) && @item.send(@default_name.to_sym))
|
137
|
+
value_string = %{ value="#{item[@default_id.to_sym]}"}
|
138
|
+
if @item.class.to_s == "NationSignupDrop" and attribute_names.size == 3 and attribute_names[0] == 'payment_profile' # this is a special case just for 3dna nation signup mongo stuff
|
139
|
+
if attribute_names[1] == 'billing_address'
|
140
|
+
if item[@default_id.to_sym].to_s == @item.source.payment_profile.billing_address[attribute_names[2].to_sym].to_s
|
141
|
+
selection_string = ' selected="selected"'
|
142
|
+
end
|
143
|
+
else
|
144
|
+
if item[@default_id.to_sym].to_s == @item.source.payment_profile[attribute_names[1].to_sym][attribute_names[2].to_sym].to_s
|
145
|
+
selection_string = ' selected="selected"'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
elsif attribute_names.size == 3
|
149
|
+
if item[@default_id.to_sym].to_s == @item[attribute_names[0].to_sym][attribute_names[1].to_sym][attribute_names[2].to_sym].to_s
|
150
|
+
selection_string = ' selected="selected"'
|
151
|
+
end
|
152
|
+
elsif attribute_names.size == 2
|
153
|
+
if item[@default_id.to_sym].to_s == @item[attribute_names.first.to_sym][attribute_names.last.to_sym].to_s
|
154
|
+
selection_string = ' selected="selected"'
|
155
|
+
end
|
156
|
+
else
|
157
|
+
if item[@default_id.to_sym].to_s == @item[@attribute_name.to_sym].to_s
|
158
|
+
selection_string = ' selected="selected"'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
"<option#{value_string}#{selection_string}>#{item_string}</option>"
|
164
|
+
end
|
165
|
+
|
166
|
+
def personal_attributes(name,value)
|
167
|
+
case name
|
168
|
+
when 'prompt' then
|
169
|
+
@prompt_option = %{<option value="">#{value}</option>}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def render_string
|
174
|
+
@option_string = "#{@prompt_option}"
|
175
|
+
@collection.each do |item|
|
176
|
+
@option_string << gen_option(item)
|
177
|
+
end
|
178
|
+
|
179
|
+
%{<select id="#{@id_string}" name="#{@name_string}">#{@option_string}</select>}
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class CheckBox < ClotTag
|
184
|
+
include ModelTag
|
185
|
+
|
186
|
+
def set_primary_attributes(context)
|
187
|
+
super(context)
|
188
|
+
if @params.length > 1 && ! @params[0].match(/:/) && ! @params[1].match(/:/)
|
189
|
+
@true_val = resolve_value(@params.shift,context)
|
190
|
+
@false_val = resolve_value(@params.shift,context)
|
191
|
+
else
|
192
|
+
@true_val = 1
|
193
|
+
@false_val = 0
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def render_string
|
198
|
+
if @item[@attribute_name.to_sym]
|
199
|
+
@checked_value = %{checked="checked" }
|
200
|
+
end
|
201
|
+
%{<input name="#{@name_string}" type="hidden" value="#{@false_val}" />} + %{<input #{@disabled_string}#{@class_string}#{@checked_value}id="#{@id_string}" name="#{@name_string}" type="checkbox" value="#{@true_val}" />}
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Clot
|
2
|
+
module MongoMapper #:nodoc:
|
3
|
+
module Droppable
|
4
|
+
|
5
|
+
def get_drop_class(class_obj)
|
6
|
+
begin
|
7
|
+
drop_string = class_obj.to_s + "Drop"
|
8
|
+
drop_class = drop_string.constantize
|
9
|
+
drop_class
|
10
|
+
rescue
|
11
|
+
get_drop_class class_obj.superclass
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_liquid
|
16
|
+
drop_class = get_drop_class self.class
|
17
|
+
drop_class.new self
|
18
|
+
end
|
19
|
+
|
20
|
+
def collection_label
|
21
|
+
if respond_to? :label then return label end
|
22
|
+
if respond_to? :title then return title end
|
23
|
+
if respond_to? :name then return name end
|
24
|
+
"label for item number :#{id}"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/clot/nav_bar.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
module Clot
|
2
|
+
|
3
|
+
class LinkItem < Liquid::Tag
|
4
|
+
include UrlFilters
|
5
|
+
include LinkFilters
|
6
|
+
include TagHelper
|
7
|
+
|
8
|
+
cattr_accessor :has_predecessor
|
9
|
+
|
10
|
+
def render(context)
|
11
|
+
@tag_factory = context['tag_factory']
|
12
|
+
tag_generator(@params, context)
|
13
|
+
LinkItem.has_predecessor ||= {}
|
14
|
+
separator = ""
|
15
|
+
if LinkItem.has_predecessor[context['block_id']]
|
16
|
+
separator = @tag_factory[:list_item_separator] || ""
|
17
|
+
end
|
18
|
+
|
19
|
+
prefix = @tag_factory[:list_item_open_tag] || ""
|
20
|
+
postfix = @tag_factory[:list_item_close_tag] || ""
|
21
|
+
link = separator + prefix + raw_link + postfix
|
22
|
+
filter = @tag_factory[:link_filter] || lambda{|link,context| link}
|
23
|
+
tag = filter.call link, context
|
24
|
+
unless tag.blank? || !tag
|
25
|
+
LinkItem.has_predecessor[context['block_id']] = true
|
26
|
+
link
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(name, params, tokens)
|
31
|
+
@params = split_params(params)
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def tag_generator(params, context)
|
36
|
+
unless params[0].match /:/
|
37
|
+
@label = params.shift
|
38
|
+
@link = "/#{@label}"
|
39
|
+
end
|
40
|
+
apply_params(params, context)
|
41
|
+
end
|
42
|
+
|
43
|
+
def raw_link
|
44
|
+
@onclick ||= ""
|
45
|
+
"<a href=\"#{@link}\"#{@onclick}>#{@label}</a>"
|
46
|
+
end
|
47
|
+
|
48
|
+
def apply_params(params, context)
|
49
|
+
params.each do |pair|
|
50
|
+
pair_data = pair.split ":"
|
51
|
+
case pair_data[0]
|
52
|
+
when "label" then
|
53
|
+
@label = pair_data[1]
|
54
|
+
when "new" then
|
55
|
+
@label ||= "Create"
|
56
|
+
@link = "/#{pair_data[1]}/new"
|
57
|
+
when "index" then
|
58
|
+
@label ||= "Index"
|
59
|
+
@link = "/#{pair_data[1]}"
|
60
|
+
when "view" then
|
61
|
+
@label ||= "View"
|
62
|
+
obj = context[pair_data[1]]
|
63
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}"
|
64
|
+
when "nested_index" then
|
65
|
+
@label ||= "Index"
|
66
|
+
obj = context[pair_data[1]]
|
67
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}/#{pair_data[2]}"
|
68
|
+
when "nested_new" then
|
69
|
+
@label ||= "Create"
|
70
|
+
obj = context[pair_data[1]]
|
71
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}/#{pair_data[2]}/new"
|
72
|
+
when "nested_show" then
|
73
|
+
@label ||= "Show"
|
74
|
+
obj = context[pair_data[1]]
|
75
|
+
obj2 = context[pair_data[2]]
|
76
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}/#{obj2.dropped_class.to_s.tableize}/#{obj2.id}"
|
77
|
+
when "nested_edit" then
|
78
|
+
@label ||= "Edit"
|
79
|
+
obj = context[pair_data[1]]
|
80
|
+
obj2 = context[pair_data[2]]
|
81
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}/#{obj2.dropped_class.to_s.tableize}/#{obj2.id}/edit"
|
82
|
+
when "nested_delete" then
|
83
|
+
@label ||= "Delete"
|
84
|
+
obj = context[pair_data[1]]
|
85
|
+
obj2 = context[pair_data[2]]
|
86
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}/#{obj2.dropped_class.to_s.tableize}/#{obj2.id}"
|
87
|
+
@context = context
|
88
|
+
@onclick = " onclick=\"#{gen_delete_onclick}\""
|
89
|
+
when "edit" then
|
90
|
+
@label ||= "Edit"
|
91
|
+
obj = context[pair_data[1]]
|
92
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}/edit"
|
93
|
+
when "delete" then
|
94
|
+
@label ||= "Delete"
|
95
|
+
obj = context[pair_data[1]]
|
96
|
+
@link = "/#{obj.dropped_class.to_s.tableize}/#{obj.id}"
|
97
|
+
@context = context
|
98
|
+
@onclick = " onclick=\"#{gen_delete_onclick}\""
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
module Clot
|
109
|
+
class LinksBlock < Liquid::Block
|
110
|
+
include TagHelper
|
111
|
+
cattr_accessor :link_block
|
112
|
+
|
113
|
+
def initialize(name, params, tokens)
|
114
|
+
@params = split_params(params)
|
115
|
+
super
|
116
|
+
end
|
117
|
+
|
118
|
+
def get_nav_body(context)
|
119
|
+
context.stack do
|
120
|
+
LinksBlock.link_block ||= 1
|
121
|
+
context['block_id'] = LinksBlock.link_block += 1
|
122
|
+
context['tag_factory'] = @tag_factory
|
123
|
+
render_all(@nodelist, context) * ""
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def render(context)
|
128
|
+
@tag_factory = GenericTagFactory
|
129
|
+
@params.each do |pair|
|
130
|
+
pair_data = pair.split ":"
|
131
|
+
case pair_data[0]
|
132
|
+
when "factory_name" then @tag_factory = pair_data[1].constantize
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
result = @tag_factory[:list_open_tag] || ""
|
137
|
+
context['tag_factory'] = @tag_factory
|
138
|
+
result += get_nav_body(context)
|
139
|
+
result += @tag_factory[:list_close_tag] || ""
|
140
|
+
result
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
module Clot
|
146
|
+
class LinkSeparator < Liquid::Tag
|
147
|
+
def render(context)
|
148
|
+
factory = context['tag_factory'] || GenericTagFactory
|
149
|
+
factory[:list_item_separator] || ""
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
GenericTagFactory = {}
|