wheelhouse-forms 1.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.
Files changed (89) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +39 -0
  3. data/app/assets/images/wheelhouse-forms/checkbox.png +0 -0
  4. data/app/assets/images/wheelhouse-forms/checkboxes.png +0 -0
  5. data/app/assets/images/wheelhouse-forms/content.png +0 -0
  6. data/app/assets/images/wheelhouse-forms/countries.png +0 -0
  7. data/app/assets/images/wheelhouse-forms/csv.png +0 -0
  8. data/app/assets/images/wheelhouse-forms/custom.png +0 -0
  9. data/app/assets/images/wheelhouse-forms/drag.png +0 -0
  10. data/app/assets/images/wheelhouse-forms/field-set.png +0 -0
  11. data/app/assets/images/wheelhouse-forms/form.png +0 -0
  12. data/app/assets/images/wheelhouse-forms/radio-buttons.png +0 -0
  13. data/app/assets/images/wheelhouse-forms/select.png +0 -0
  14. data/app/assets/images/wheelhouse-forms/states.png +0 -0
  15. data/app/assets/images/wheelhouse-forms/submit-button.png +0 -0
  16. data/app/assets/images/wheelhouse-forms/text-area.png +0 -0
  17. data/app/assets/images/wheelhouse-forms/text-field.png +0 -0
  18. data/app/assets/javascripts/wheelhouse-forms/admin.js +125 -0
  19. data/app/assets/javascripts/wheelhouse-forms/jquery.autogrow.js +50 -0
  20. data/app/assets/javascripts/wheelhouse-forms/jquery.options.js +24 -0
  21. data/app/assets/stylesheets/wheelhouse-forms/admin.css.sass +244 -0
  22. data/app/controllers/forms/forms_controller.rb +9 -0
  23. data/app/controllers/forms/submissions_controller.rb +19 -0
  24. data/app/handlers/forms/form_handler.rb +17 -0
  25. data/app/helpers/forms/forms_helper.rb +36 -0
  26. data/app/helpers/forms/mailer_helper.rb +67 -0
  27. data/app/helpers/forms/submissions_helper.rb +71 -0
  28. data/app/mailers/forms/mailer.rb +11 -0
  29. data/app/models/forms/field_collection.rb +21 -0
  30. data/app/models/forms/fields/checkbox.rb +8 -0
  31. data/app/models/forms/fields/checkboxes.rb +10 -0
  32. data/app/models/forms/fields/content_field.rb +7 -0
  33. data/app/models/forms/fields/countries_dropdown.rb +14 -0
  34. data/app/models/forms/fields/custom_field.rb +8 -0
  35. data/app/models/forms/fields/field.rb +28 -0
  36. data/app/models/forms/fields/field_set.rb +14 -0
  37. data/app/models/forms/fields/optioned_field.rb +17 -0
  38. data/app/models/forms/fields/radio_buttons.rb +10 -0
  39. data/app/models/forms/fields/select_field.rb +10 -0
  40. data/app/models/forms/fields/states_dropdown.rb +15 -0
  41. data/app/models/forms/fields/submit_button.rb +7 -0
  42. data/app/models/forms/fields/text_area.rb +8 -0
  43. data/app/models/forms/fields/text_field.rb +21 -0
  44. data/app/models/forms/form.rb +65 -0
  45. data/app/models/forms/submission.rb +53 -0
  46. data/app/renderers/forms/checkbox_renderer.rb +7 -0
  47. data/app/renderers/forms/checkboxes_renderer.rb +18 -0
  48. data/app/renderers/forms/content_field_renderer.rb +5 -0
  49. data/app/renderers/forms/custom_field_renderer.rb +5 -0
  50. data/app/renderers/forms/field_collection_renderer.rb +13 -0
  51. data/app/renderers/forms/field_renderer.rb +57 -0
  52. data/app/renderers/forms/field_set_renderer.rb +10 -0
  53. data/app/renderers/forms/form_renderer.rb +30 -0
  54. data/app/renderers/forms/labelled_field_renderer.rb +10 -0
  55. data/app/renderers/forms/radio_buttons_renderer.rb +18 -0
  56. data/app/renderers/forms/select_field_renderer.rb +9 -0
  57. data/app/renderers/forms/submit_button_renderer.rb +5 -0
  58. data/app/renderers/forms/text_area_renderer.rb +7 -0
  59. data/app/renderers/forms/text_field_renderer.rb +7 -0
  60. data/app/templates/form.html.haml +9 -0
  61. data/app/templates/form.xhr.haml +4 -0
  62. data/app/templates/form/submission.html.haml +15 -0
  63. data/app/views/forms/forms/_checkbox.haml +3 -0
  64. data/app/views/forms/forms/_checkboxes.haml +10 -0
  65. data/app/views/forms/forms/_content_field.haml +3 -0
  66. data/app/views/forms/forms/_countries_dropdown.haml +4 -0
  67. data/app/views/forms/forms/_custom_field.haml +4 -0
  68. data/app/views/forms/forms/_field_set.haml +16 -0
  69. data/app/views/forms/forms/_radio_buttons.haml +10 -0
  70. data/app/views/forms/forms/_select_field.haml +10 -0
  71. data/app/views/forms/forms/_states_dropdown.haml +4 -0
  72. data/app/views/forms/forms/_submissions.haml +20 -0
  73. data/app/views/forms/forms/_submit_button.haml +2 -0
  74. data/app/views/forms/forms/_text_area.haml +3 -0
  75. data/app/views/forms/forms/_text_field.haml +4 -0
  76. data/app/views/forms/forms/designer.haml +56 -0
  77. data/app/views/forms/forms/edit.html.haml +5 -0
  78. data/app/views/forms/forms/form.haml +22 -0
  79. data/app/views/forms/forms/new.html.haml +4 -0
  80. data/app/views/forms/forms/show.html.haml +4 -0
  81. data/app/views/forms/submissions/form.haml +16 -0
  82. data/app/views/forms/submissions/show.html.haml +4 -0
  83. data/config/countries.yml +245 -0
  84. data/config/locales/en.yml +7 -0
  85. data/config/routes.rb +7 -0
  86. data/config/states.yml +62 -0
  87. data/lib/forms/csv_exporter.rb +41 -0
  88. data/lib/wheelhouse-forms.rb +26 -0
  89. metadata +149 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2011-12 Sam Pohlenz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ Forms Plugin for Wheelhouse CMS
2
+ ===============================
3
+
4
+ ![Screenshot of forms plugin](https://www.wheelhousecms.com/media/cdfaf962/Forms-Plugin.png)
5
+
6
+ This gem makes it easy to add customizable forms (such as contact forms) into your [Wheelhouse CMS](https://www.wheelhousecms.com/) site, via an easy-to-use form builder. Form submissions are saved within the CMS and may optionally be emailed to one or more recipients.
7
+
8
+ The following field types are supported:
9
+
10
+ - single-line text (with HTML5 input types)
11
+ - text areas
12
+ - select/dropdown box
13
+ - single checkboxes
14
+ - checkbox set
15
+ - radio button set
16
+ - US/Australian states dropdown
17
+ - countries dropdown
18
+ - HTML content
19
+ - custom fields
20
+ - nesting within field sets
21
+
22
+ Other features include:
23
+
24
+ - server-side and HTML5 form validation
25
+ - CSV export of submissions
26
+
27
+
28
+ Installation & Usage
29
+ --------------------
30
+
31
+ **1. Add `wheelhouse-forms` to your Gemfile:**
32
+
33
+ gem "wheelhouse-forms"
34
+
35
+ Then run `bundle install`.
36
+
37
+ **2. Create a new form from the New Page dropdown.**
38
+
39
+ **3. To customize, copy the `form.html.haml` template from `app/templates` to your theme templates folder.**
@@ -0,0 +1,125 @@
1
+ //= require ./jquery.autogrow
2
+ //= require ./jquery.options
3
+
4
+ $(function() {
5
+
6
+ var root = $('#fields');
7
+ var target;
8
+
9
+ function resetTarget() {
10
+ target = $('.fields:last', root);
11
+ if (target.length < 1) target = root;
12
+ }
13
+ resetTarget();
14
+
15
+ function prefixFor(container, index) {
16
+ return container.attr('data-prefix') + "[" + index + "]";
17
+ }
18
+
19
+ function insertFieldHandler(template, optionize, callback) {
20
+ return function() {
21
+ var nextIndex = parseInt($('> :last-child', target).attr('data-index')) + 1 || 0;
22
+ var field = $(template).tmpl({ index: nextIndex, prefix: prefixFor(target, nextIndex) });
23
+
24
+ field.appendTo(target);
25
+ $('input[placeholder]', field).placeholder().click();
26
+
27
+ if (optionize) { $('ul.options', field).options(); }
28
+ if ($.isFunction(callback)) { callback(field); }
29
+
30
+ return false;
31
+ }
32
+ }
33
+
34
+ $('.tools li.text-field a').click(insertFieldHandler("#text-field-template"));
35
+ $('.tools li.text-area a').click(insertFieldHandler("#text-area-template"));
36
+ $('.tools li.select-field a').click(insertFieldHandler("#select-field-template", true));
37
+ $('.tools li.checkbox a').click(insertFieldHandler("#checkbox-template"));
38
+ $('.tools li.checkboxes a').click(insertFieldHandler("#checkboxes-template", true));
39
+ $('.tools li.submit-button a').click(insertFieldHandler("#submit-button-template"));
40
+ $('.tools li.radio-buttons a').click(insertFieldHandler("#radio-buttons-template", true));
41
+ $('.tools li.states-dropdown a').click(insertFieldHandler("#states-dropdown-template"));
42
+ $('.tools li.countries-dropdown a').click(insertFieldHandler("#countries-dropdown-template"));
43
+ $('.tools li.content-field a').click(insertFieldHandler("#content-field-template", false, function(field) {
44
+ $('textarea.editor', field).editor();
45
+ }));
46
+ $('.tools li.custom-field a').click(insertFieldHandler("#custom-field-template"));
47
+
48
+ $('.tools li.field-set a').click(function() {
49
+ var nextIndex = parseInt($('#fields > :last-child').attr('data-index')) + 1 || 0;
50
+ var fieldset = $('#field-set-template').tmpl({ index: nextIndex, prefix: prefixFor(root, nextIndex) });
51
+ fieldset.appendTo(root);
52
+
53
+ target = $('.fields', fieldset);
54
+ target.sortable(SortableOptions);
55
+
56
+ return false;
57
+ });
58
+
59
+ $('ul.options', root).options();
60
+
61
+ root.delegate('a.delete', 'click', function() {
62
+ if (confirm("Are you sure you want to remove this field?")) {
63
+ var field = $(this).parent();
64
+ var isCurrentTarget = field.find('.fields').get(0) == target.get(0);
65
+
66
+ field.remove();
67
+ if (isCurrentTarget) { resetTarget(); }
68
+
69
+ refreshFields();
70
+ }
71
+
72
+ return false;
73
+ });
74
+
75
+
76
+ function refreshFields() {
77
+ function replacePrefix(input, prefix) {
78
+ var name = $(input).attr('name').replace(/.*(\[[^\[\]]+\](\[\])?)$/, "$1");
79
+ $(input).attr('name', prefix + name);
80
+ }
81
+
82
+ $('#fields > div').each(function(index) {
83
+ var prefix = $('#fields').attr("data-prefix") + "[" + index + "]";
84
+ $(this).attr('data-index', index);
85
+
86
+ $('input:not(.fields input), textarea:not(.fields textarea), select:not(.fields select)', this).each(function() {
87
+ replacePrefix(this, prefix);
88
+ });
89
+ $('> .fields', this).attr('data-prefix', prefix + "[fields]");
90
+ });
91
+
92
+ $('.fields').each(function() {
93
+ var fieldsPrefix = $(this).attr('data-prefix');
94
+
95
+ $('> div', this).each(function(index) {
96
+ var prefix = fieldsPrefix + "[" + index + "]";
97
+ $(this).attr('data-index', index);
98
+
99
+ $('input, textarea, select', this).each(function() { replacePrefix(this, prefix); });
100
+ });
101
+ });
102
+ }
103
+
104
+ var BaseSortableOptions = {
105
+ items: '> div',
106
+ handle: '> .drag',
107
+ placeholder: 'drag-placeholder',
108
+ tolerance: 'intersect',
109
+ toleranceElement: '> .drag-area',
110
+ connectWith: '.fields',
111
+ forcePlaceholderSize: true,
112
+ start: function(e, ui) {
113
+ $('textarea.editor', ui.item).removeEditor();
114
+ },
115
+ stop: function(e, ui) {
116
+ $('textarea.editor', ui.item).editor();
117
+ refreshFields();
118
+ }
119
+ };
120
+ var SortableOptions = $.extend({}, BaseSortableOptions, { connectWith: '#fields, .fields' });
121
+
122
+ $('#fields').sortable(BaseSortableOptions); // Top-level
123
+ $('.fields').sortable(SortableOptions); // Fieldsets
124
+
125
+ });
@@ -0,0 +1,50 @@
1
+ $.fn.autoGrowInput = function(o) {
2
+ o = $.extend({
3
+ maxWidth: 400,
4
+ minWidth: 150,
5
+ comfortZone: 40
6
+ }, o);
7
+
8
+ this.filter('input:text').each(function() {
9
+ var minWidth = o.minWidth || $(this).width(),
10
+ val = '',
11
+ input = $(this),
12
+ testSubject = $('<div />').css({
13
+ position: 'absolute',
14
+ top: -9999,
15
+ left: -9999,
16
+ width: 'auto',
17
+ fontSize: input.css('fontSize'),
18
+ fontFamily: input.css('fontFamily'),
19
+ fontWeight: input.css('fontWeight'),
20
+ letterSpacing: input.css('letterSpacing'),
21
+ whiteSpace: 'nowrap'
22
+ }),
23
+ check = function() {
24
+ if (val === (val = input.val())) {return;}
25
+
26
+ // Enter new content into testSubject
27
+ var escaped = val.replace(/&/g, '&amp;').replace(/\s/g,'&nbsp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
28
+ testSubject.html(escaped);
29
+
30
+ // Calculate new width + whether to change
31
+ var testerWidth = testSubject.width(),
32
+ newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
33
+ currentWidth = input.width(),
34
+ isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
35
+ || (newWidth > minWidth && newWidth < o.maxWidth);
36
+
37
+ // Animate width
38
+ if (isValidWidthChange) {
39
+ input.width(newWidth);
40
+ }
41
+ };
42
+
43
+ testSubject.insertAfter(input);
44
+
45
+ $(this).bind('keyup keydown blur update', check);
46
+ check();
47
+ });
48
+
49
+ return this;
50
+ };
@@ -0,0 +1,24 @@
1
+ $.fn.options = function() {
2
+ return $(this).each(function() {
3
+ $(this).delegate("li input", "blur", function() {
4
+ var li = $(this).parent();
5
+
6
+ if ($(this).val() == "" && !li.is(":last-child")) {
7
+ li.remove();
8
+ }
9
+ });
10
+
11
+ $(this).delegate("li:last-child input", "keydown", function(e) {
12
+ // Tab key pressed
13
+ if (e.keyCode == '9' && $(this).val() != '') {
14
+ e.preventDefault();
15
+
16
+ var li = $(this).parent();
17
+ var next = li.clone().find('div').remove().end().insertAfter(li);
18
+ next.find('input').val('').width('auto').autoGrowInput().focus();
19
+ }
20
+ });
21
+
22
+ $("input:text", this).autoGrowInput();
23
+ });
24
+ };
@@ -0,0 +1,244 @@
1
+ @import compass
2
+
3
+ =field
4
+ position: relative
5
+ margin: 10px 0
6
+ padding: 0 0 0 32px
7
+ +border-radius(4px)
8
+
9
+ =colored-field( $background, $border, $text )
10
+ background: $background
11
+ border: 1px solid $border
12
+
13
+ label
14
+ color: $text
15
+
16
+ .drag
17
+ border-right: 1px solid $border
18
+
19
+ =blue
20
+ +colored-field(#f3f7fa, #cbd4da, #76828a)
21
+
22
+ =green
23
+ +colored-field(#f3f8f4, #d3dbd2, #748572)
24
+
25
+ =orange
26
+ +colored-field(#faf8f0, #e1ddc8, #8c8977)
27
+
28
+ =purple
29
+ +colored-field(#fdfafd, #e3d2e3, #987898)
30
+
31
+ .drag-area
32
+ padding: 6px
33
+ margin-left: -32px
34
+ padding-left: 38px
35
+
36
+ .field-set > &
37
+ margin-left: -14px
38
+ padding-left: 20px
39
+
40
+ #fields
41
+ label
42
+ display: inline
43
+
44
+ input[type=text]
45
+ width: 40%
46
+ display: inline
47
+
48
+ select
49
+ margin: 0.4em 0
50
+ padding: 0.5% 0.2% 0.2% 0.2%
51
+ font-size: 110%
52
+
53
+ input, select
54
+ font-size: 100%
55
+
56
+ &.placeholder
57
+ color: #ccc
58
+
59
+ label
60
+ color: #545454
61
+ font-weight: bold
62
+ margin-right: 0.5em
63
+
64
+ &.required
65
+ float: right
66
+ margin: 0.5em 0
67
+ margin-right: 10%
68
+ font-weight: normal
69
+ font-size: 95%
70
+
71
+ input
72
+ margin-right: 4px
73
+
74
+ span.note
75
+ font-size: 95%
76
+ color: #a9a9a9
77
+
78
+ .field-set
79
+ +field
80
+ background: #fdfefe
81
+ border: 1px solid #ccc
82
+ padding-left: 14px
83
+
84
+ .placeholder, .text-field, .text-area, .select-field, .checkbox, .submit-button, .states-dropdown, .countries-dropdown, .radio-buttons, .checkboxes, .custom-field, .content-field
85
+ margin-left: 0
86
+ margin-right: 0
87
+
88
+ .fields
89
+ margin-right: 5px
90
+
91
+ .text-field, .text-area, .select-field, .checkbox, .submit-button, .states-dropdown, .countries-dropdown, .radio-buttons, .checkboxes, .custom-field, .content-field
92
+ +field
93
+ min-height: 26px
94
+
95
+ input[type=text]
96
+ width: 47%
97
+
98
+ select
99
+ display: inline
100
+ width: 17%
101
+ margin-left: 2%
102
+
103
+ .drag
104
+ width: 24px
105
+
106
+ a.delete
107
+ top: 12px
108
+ right: 8px
109
+
110
+ .text-field, .text-area, .content-field
111
+ +blue
112
+
113
+ .checkbox, .radio-buttons, .checkboxes
114
+ +orange
115
+
116
+ .select-field, .states-dropdown, .countries-dropdown
117
+ +green
118
+
119
+ .submit-button, .custom-field
120
+ +purple
121
+
122
+ .drag-placeholder
123
+ +field
124
+ border: 1px dashed #ccc
125
+ padding: 6px 6px 6px 38px
126
+
127
+ .content-field
128
+ a.delete
129
+ top: 14px
130
+ right: 14px
131
+
132
+ .field-set .content-field
133
+ a.delete
134
+ right: 12px
135
+
136
+ .custom-field
137
+ input[type=text]
138
+ width: 40%
139
+
140
+ ul.options
141
+ line-height: 2.6em
142
+ min-height: 2em
143
+ margin-top: 0.5em
144
+
145
+ li
146
+ display: inline
147
+ margin-right: 5px
148
+
149
+ input[type=text]
150
+ width: auto
151
+ min-width: 8em
152
+
153
+ .drag
154
+ position: absolute
155
+ top: 0
156
+ left: 0
157
+ cursor: move
158
+ width: 7px
159
+ height: 100%
160
+ background: image-url("wheelhouse/backgrounds/drag.png") repeat
161
+ border-right: 1px solid #dfdfdf
162
+ +border-left-radius(4px)
163
+
164
+ img
165
+ margin: 12px 4px
166
+
167
+ .fields
168
+ min-height: 100px
169
+
170
+ a.delete
171
+ position: absolute
172
+ right: 14px
173
+ top: 16px
174
+ z-index: 99
175
+ width: 16px
176
+ height: 16px
177
+ background: image-url("wheelhouse/icons/delete-item.png") no-repeat
178
+ text-indent: -9999px
179
+ opacity: 0.5
180
+
181
+ &:hover
182
+ opacity: 1.0
183
+
184
+ .tools li
185
+ a
186
+ padding-left: 45px
187
+ background-position: 17px center
188
+
189
+ &:hover
190
+ background-color: #d3dadf
191
+
192
+ &.text-field a
193
+ background-image: image-url("wheelhouse-forms/text-field.png")
194
+
195
+ &.text-area a
196
+ background-image: image-url("wheelhouse-forms/text-area.png")
197
+
198
+ &.select-field a
199
+ background-image: image-url("wheelhouse-forms/select.png")
200
+
201
+ &.checkbox a
202
+ background-image: image-url("wheelhouse-forms/checkbox.png")
203
+
204
+ &.checkboxes a
205
+ background-image: image-url("wheelhouse-forms/checkboxes.png")
206
+
207
+ &.radio-buttons a
208
+ background-image: image-url("wheelhouse-forms/radio-buttons.png")
209
+
210
+ &.field-set a
211
+ background-image: image-url("wheelhouse-forms/field-set.png")
212
+
213
+ &.submit-button a
214
+ background-image: image-url("wheelhouse-forms/submit-button.png")
215
+
216
+ &.states-dropdown a
217
+ background-image: image-url("wheelhouse-forms/states.png")
218
+
219
+ &.countries-dropdown a
220
+ background-image: image-url("wheelhouse-forms/countries.png")
221
+
222
+ &.content-field a
223
+ background-image: image-url("wheelhouse-forms/content.png")
224
+
225
+ &.custom-field a
226
+ background-image: image-url("wheelhouse-forms/custom.png")
227
+
228
+ .sidebar li a.export-csv
229
+ background-image: image-url("wheelhouse-forms/csv.png")
230
+ padding-left: 40px
231
+
232
+ .field
233
+ li
234
+ margin-bottom: 0.2em
235
+
236
+ .shaded
237
+ h2
238
+ border-bottom: 1px solid #ddd
239
+ padding-bottom: 5px
240
+ margin-right: 6%
241
+
242
+ .inline input
243
+ margin-right: 1em
244
+