wheelhouse-forms 1.0

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