clot 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.
@@ -0,0 +1,11 @@
1
+ module Clot
2
+ module Deprecated
3
+ def unknown_tag(name, params, tokens)
4
+ if name == "field" || name == "text" || name == "file" || name == "select"
5
+ raise Error.new("USING DEPRECATED TAG")
6
+ else
7
+ super name,params,tokens
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,130 @@
1
+ module Clot
2
+ module FormFilters
3
+
4
+ def form_item(tag, message, required = false)
5
+ tag_id = get_attribute_value("id", tag)
6
+
7
+ form_string = ""
8
+ if tag_id
9
+ form_string = " for=\"#{tag_id}\""
10
+ end
11
+
12
+ if required
13
+ required_string = "<span class=\"required\">*</span>"
14
+ else
15
+ required_string = ""
16
+ end
17
+
18
+ "<p><label#{form_string}>#{message}#{required_string}</label>#{tag}</p>"
19
+ end
20
+
21
+ #################
22
+
23
+ #note - must reconstruct from scratch...
24
+ def input_to_text(input)
25
+
26
+ value_match = /value="([^"]*)"/.match input
27
+ if value_match
28
+ value_text = value_match[1]
29
+ else
30
+ value_text = ""
31
+ end
32
+
33
+ name_match = /name="[^"]*"/.match input
34
+ if name_match
35
+ name_text = " #{name_match[0]}"
36
+ else
37
+ name_text = ""
38
+ end
39
+
40
+ "<textarea#{name_text}>#{value_text}</textarea>"
41
+ end
42
+
43
+ def concat(string1, string2)
44
+ "#{string1}#{string2}"
45
+ end
46
+
47
+
48
+ def get_id_from_name(name)
49
+ name.sub("[", "_").sub("]","")
50
+ end
51
+
52
+ def drop_class_to_table_item(clazz)
53
+ match = /_drops/.match clazz.name.tableize
54
+ match.pre_match
55
+ end
56
+
57
+ def get_attribute_value(prop, input)
58
+ prop_match = /#{prop}="([^"]*)"/.match input
59
+ if prop_match
60
+ prop_match[1]
61
+ end
62
+ end
63
+
64
+
65
+ def set_param(tag, key, value)
66
+ match = /#{key}="[^"]*"/.match tag
67
+ if match
68
+ return match.pre_match + "#{key}=\"#{value}\"" + match.post_match
69
+ end
70
+
71
+ match = /(\/>|>)/.match tag
72
+ if match
73
+ match.pre_match + " #{key}=\"#{value}\"" + match.to_s + match.post_match
74
+ else
75
+ tag
76
+ end
77
+ end
78
+
79
+ def submit_button(message)
80
+ '<div class="form-submit-button"><input type="submit" value="' + message + '"/></div>'
81
+ end
82
+
83
+ def form_input_item(name, value, errors )
84
+ input = "<input type=\"text\" id=\"#{get_id_from_name(name)}\" name=\"#{name}\" value=\"#{value}\"#{get_error_class(errors)}/>"
85
+ input
86
+ end
87
+
88
+ def form_text_item(name, value, errors )
89
+ text = "<textarea id=\"#{get_id_from_name(name)}\" name=\"#{name}\"#{get_error_class(errors)}>#{value}</textarea>"
90
+ text
91
+ end
92
+
93
+ def form_file_item(name, errors )
94
+ input = "<input type=\"file\" id=\"#{get_id_from_name(name)}\" name=\"#{name}\" />"
95
+ input
96
+ end
97
+
98
+ def form_select_item(name, value, collection, errors, blank_option = nil)
99
+ prompt = ""
100
+ if blank_option
101
+ prompt = "<option>#{blank_option}</option>"
102
+ end
103
+
104
+ select = "<select id=\"#{get_id_from_name(name)}\" name=\"#{name}\"#{get_error_class(errors)}>"
105
+ select += prompt
106
+ collection.each do |item|
107
+ @_id = @_label = item.to_s
108
+ if item.respond_to?(:id) && item.respond_to?(:collection_label)
109
+ @_id = item.id
110
+ @_label = item.collection_label
111
+ end
112
+ select += "<option value=\"#{@_id}\"#{get_selection_value(value, item)}>#{@_label}</option>"
113
+
114
+ end
115
+ select += "</select>"
116
+ end
117
+
118
+ def get_selection_value(value,item)
119
+ matched_value = item.to_s
120
+ if item.respond_to?(:collection_label)
121
+ matched_value = item.id
122
+ end
123
+ value.to_s == matched_value.to_s ? ' selected="true"' : ''
124
+ end
125
+
126
+ def get_error_class(errors)
127
+ errors.blank? ? "" : ' class="error-item"'
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,279 @@
1
+ require 'clot/url_filters'
2
+ require 'clot/link_filters'
3
+ require 'clot/form_filters'
4
+ require 'clot/tag_helper'
5
+
6
+ module Clot
7
+ class LiquidForm < Liquid::Block
8
+ include UrlFilters
9
+ include LinkFilters
10
+ include FormFilters
11
+ include TagHelper
12
+
13
+ Syntax = /([^\s]+)\s+/
14
+
15
+ def initialize(tag_name, markup, tokens)
16
+ if markup =~ Syntax
17
+ @form_object = $1
18
+ @attributes = {}
19
+ markup.scan(Liquid::TagAttributes) do |key, value|
20
+ @attributes[key] = value
21
+ end
22
+ else
23
+ syntax_error tag_name, markup, tokens
24
+ end
25
+ super
26
+ end
27
+
28
+ def render(context)
29
+ set_variables context
30
+ render_form context
31
+ end
32
+
33
+ def render_form(context)
34
+ result = get_form_header(context)
35
+ result += get_form_body(context)
36
+ result += get_form_footer
37
+ result
38
+ end
39
+
40
+ def syntax_error
41
+ raise SyntaxError.new("Syntax Error in form tag")
42
+ end
43
+
44
+ def get_form_body(context)
45
+ context.stack do
46
+ render_all(@nodelist, context) * ""
47
+ end
48
+ end
49
+
50
+ def get_form_footer
51
+ "</form>"
52
+ end
53
+
54
+ def set_upload
55
+ if @attributes["uploading"] || @attributes["multipart"] == "true"
56
+ @upload_info = ' enctype="multipart/form-data"'
57
+ else
58
+ @upload_info = ''
59
+ end
60
+ end
61
+
62
+ def set_variables(context)
63
+ set_controller_action
64
+ set_form_action(context)
65
+ set_class
66
+ set_upload
67
+ end
68
+
69
+ end
70
+
71
+
72
+ class LiquidFormFor < LiquidForm
73
+
74
+ def get_errors(model)
75
+ errors = []
76
+ model.errors.each do |attr,msg|
77
+ errors << attr
78
+ end
79
+ errors
80
+
81
+ end
82
+
83
+
84
+ def get_form_body(context)
85
+ context.stack do
86
+ context['form_model'] = @model
87
+ context['form_class_name'] = @class_name
88
+ context['form_errors'] = get_errors @model
89
+ return render_all(@nodelist, context)
90
+ end
91
+ end
92
+
93
+
94
+ private
95
+
96
+ def set_controller_action
97
+ silence_warnings {
98
+ if @model.nil? || @model.source.nil?
99
+ @activity = "new"
100
+ elsif @model.dropped_class == Searchlogic::Search
101
+ @activity = "search"
102
+ elsif @form_object.include?("_change")
103
+ @activity = "change"
104
+ elsif @model.source.new_record? || @model.source.id.nil?
105
+ @activity = "new"
106
+ elsif @model.dropped_class == NationSignup
107
+ @activity = "new"
108
+ else
109
+ @activity = "edit"
110
+ end
111
+ }
112
+ end
113
+
114
+ def set_form_action(context)
115
+ if @activity == "edit"
116
+ @form_action = object_url @model
117
+ elsif @activity == "new"
118
+ @form_action = "/" + @model.dropped_class.to_s.tableize.pluralize
119
+ elsif ['search', 'change'].include?(@activity)
120
+ @form_action = ""
121
+ else
122
+ syntax_error
123
+ end
124
+ if @attributes["parent"]
125
+ @form_action = object_url(context[@attributes["parent"]]) + @form_action
126
+ end
127
+ if context.registers[:controller].params[:controller].split('/').first == 'users' or @form_action == '/accounts'
128
+ @form_action = "/users" + @form_action.gsub("/forms","")
129
+ elsif @activity != 'change'
130
+ @form_action = "/forms" + @form_action if not @form_action[0..5] == '/forms'
131
+ end
132
+ unless @attributes["post_method"].nil?
133
+ @form_action += '/' + @attributes["post_method"]
134
+ @activity = @attributes["post_method"]
135
+ end
136
+
137
+ end
138
+
139
+ def set_class
140
+ @class_string = ""
141
+ unless @attributes["class"].nil?
142
+ @class_string += 'class="' + @attributes["class"] + '" '
143
+ end
144
+ unless @attributes["autocomplete"].nil?
145
+ @class_string += 'autocomplete="' + @attributes["autocomplete"] + '" '
146
+ end
147
+
148
+ @class_name = drop_class_to_table_item @model.class
149
+ end
150
+
151
+ def set_model(context)
152
+ @model = context[@form_object] || nil
153
+ if not @model
154
+ if @form_object.include?("_search")
155
+ search_object_name = @form_object.gsub('_search',"").classify.constantize
156
+ search_object = search_object_name.search
157
+ search_object_name = (search_object_name.to_s + "SearchDrop").constantize
158
+ @model = search_object_name.new(search_object)
159
+ @model.defaults(context)
160
+ context[@form_object] = @model
161
+ elsif @form_object.include?("_change")
162
+ change_object = @form_object.gsub('_change',"").pluralize.classify.constantize
163
+ change_object_name = (change_object.to_s + "ChangeDrop").constantize
164
+ @model = change_object_name.new(change_object.new)
165
+ @model.defaults(context)
166
+ context[@form_object] = @model
167
+ else
168
+ @model = @form_object.classify.constantize.new.to_liquid
169
+ if @model.source.new_record?
170
+ @model.defaults(context)
171
+ context[@form_object] = @model
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+ def get_form_header(context)
178
+ cs = @class_name + "_form"
179
+ # temporarily taking out 'survey_question_response' from this list because i can't figure out why the javascript
180
+ # response on cagreens survey http://cagreens.nationbuilder.com/ga_dec2011_survey doesn't seem to work (it works everywhere else)
181
+ if ['comment', 'survey_response', 'face_tweet', 'feedback', 'volunteer_signup', 'event_rsvp', 'event_page', 'signup',
182
+ 'password_reset', 'password', 'flag', 'nation_signup', 'blog_post_page', 'nation_signin', 'pledge', 'unsubscribe',
183
+ 'account', 'petition_signature', 'suggestion_page', 'endorsement'].include?(@class_name) # hacky thing to make ajax forms work
184
+ cs = 'ajaxForm ' + cs
185
+ end
186
+ if ['endorsement', 'suggestion_page', 'petition_signature'].include?(@class_name)
187
+ @upload_info = ' enctype="multipart/form-data"'
188
+ end
189
+ if ['search', 'change'].include?(@activity)
190
+ method_type = "GET"
191
+ else
192
+ method_type = "POST"
193
+ end
194
+ result = '<form class="' + cs + '" method="' + method_type + '" ' + @class_string + 'action="' + @form_action + '"' + @upload_info + '>'
195
+ if @activity == "edit"
196
+ result += '<input type="hidden" name="_method" value="PUT"/>'
197
+ end
198
+
199
+ # this will get replaced with a real authenticity token by rake middleware
200
+ if not ['search', 'change'].include?(@activity)
201
+ result += '<input name="authenticity_token" type="hidden" value="__CROSS_SITE_REQUEST_FORGERY_PROTECTION_TOKEN__"/>'
202
+ end
203
+
204
+ # jim change... add current page
205
+ if context['page'] and not ['search', 'change'].include?(@activity)
206
+ result += '<input name="page_id" type="hidden" value="' + context['page'].id.to_s + '"/>'
207
+ result += '<input name="return_to" type="hidden" value="' + context['page'].full_url + '"/>'
208
+ end
209
+
210
+ if context['signup'] and ['profiles'].include?(context.registers[:controller].controller_name)
211
+ result += '<input name="signup_id" type="hidden" value="' + context['signup'].id.to_s + '"/>'
212
+ end
213
+
214
+ # this is a honeypot field
215
+ result += '<div class="email_address_form" style="display:none;">'
216
+ result += '<p><label for "email_address">Optional email code</label><br/><input name="email_address" type="text" class="text" id="email_address" autocomplete="off"/></p>'
217
+ result += '</div>'
218
+
219
+ result
220
+ end
221
+
222
+ def set_variables(context)
223
+ set_model(context)
224
+ super
225
+ end
226
+
227
+ end
228
+
229
+
230
+ class ErrorMessagesFor < Liquid::Tag
231
+
232
+ include TagHelper
233
+ def initialize(name, params, tokens)
234
+ @_params = split_params(params)
235
+ super
236
+ end
237
+
238
+
239
+ def render(context)
240
+ @params = @_params.clone
241
+ @model = context[@params.shift]
242
+
243
+ result = ""
244
+ if @model and @model.errors.count > 0
245
+ @suffix = @model.errors.count > 1 ? "s" : ""
246
+ @default_message = @model.errors.count.to_s + " error#{@suffix} occurred while processing information"
247
+
248
+ @params.each do |pair|
249
+ pair = pair.split /:/
250
+ value = resolve_value(pair[1],context)
251
+
252
+ case pair[0]
253
+ when "header_message" then
254
+ @default_message = value
255
+ end
256
+ end
257
+
258
+ result += '<div class="errorExplanation" id="errorExplanation"><h2>' + @default_message + '</h2><ul>'
259
+
260
+ @model.errors.each do |attr, msg|
261
+ result += "<li>#{error_message(attr, msg)}</li>"
262
+ end
263
+
264
+ result += "</ul></div>"
265
+ end
266
+ result
267
+ end
268
+
269
+ def error_message(attr, msg)
270
+ unless attr == :base
271
+ "#{attr} - #{msg}"
272
+ else
273
+ msg
274
+ end
275
+ end
276
+
277
+ end
278
+
279
+ end
@@ -0,0 +1,24 @@
1
+ module Clot
2
+ class FormTag < LiquidForm
3
+
4
+ def get_form_header(context)
5
+ "<form action=\"#{resolve_value @form_object,context}\" method=\"#{@http_method}\"#{@upload_info}>"
6
+ end
7
+ def get_form_errors
8
+ ""
9
+ end
10
+
11
+ def set_variables(context)
12
+ set_method
13
+ set_upload
14
+ #super
15
+ end
16
+
17
+ def set_method
18
+ @http_method = @attributes['method'] ||= 'post'
19
+ end
20
+
21
+ end
22
+
23
+
24
+ end
@@ -0,0 +1,32 @@
1
+ module Clot
2
+ class IfContentFor < Liquid::Block
3
+ include Liquid
4
+
5
+ Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/
6
+
7
+ def initialize(tag_name, markup, tokens)
8
+ @blocks = []
9
+
10
+ if markup =~ Syntax
11
+
12
+ @template_name = $1
13
+ @variable_name = $3
14
+ @attributes = {}
15
+
16
+ markup.scan(TagAttributes) do |key, value|
17
+ @attributes[key] = value
18
+ end
19
+
20
+ else
21
+ raise SyntaxError.new("Syntax error in tag 'yield' - Valid syntax: content_for '[template]' (with|for) [object|collection]")
22
+ end
23
+
24
+ super
25
+ end
26
+
27
+ def render(context)
28
+ @template_name
29
+ super
30
+ end
31
+ end
32
+ end