Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Refactor FormBinder plugin. Add options for template locations

  • Loading branch information...
commit ad19161fc8494bf8a78a2f504b71a6a7571480cf 1 parent d5d7c92
Mihael Konjević authored August 17, 2011
2  README.md
Source Rendered
@@ -27,7 +27,7 @@ It will create fields for title and lead. Title will be rendered as a text input
27 27
 
28 28
 You can pass FormBuilder object from controller by instantiating it like this
29 29
 
30  
-    var f = FormBinderBuilder.getBuilder(model_instance);
  30
+    var f = FormBinder.Builder.getBuilder(model_instance);
31 31
 
32 32
 If you need more customization you can render each field on it's own:
33 33
 
194  form_binder.js
... ...
@@ -1,10 +1,12 @@
1  
-steal.plugins(
  1
+steal(
2 2
 	'jquery',
  3
+	'jquery/class',
3 4
 	'jquery/controller',
4 5
 	'jquery/view/ejs',
5 6
 	'jquery/model',
6  
-	'jquery/model/validations').then('form_binder_builder', function($){
7  
-	$.Controller.extend("FormBinder",{
  7
+	'jquery/model/validations').then(function($){
  8
+	
  9
+	$.Controller("FormBinder",{
8 10
 		
9 11
 	}, 
10 12
 	{
@@ -60,33 +62,175 @@ steal.plugins(
60 62
 			this.options.model.attr(attr, val, null, this.callback('addErrorsForAttr'));
61 63
 		},
62 64
 		modelAttrChanged : function(attr){
63  
-			var name = '[name="'+this.options.model.Class._shortName+'['+attr+']"]';
64  
-			if(this.options.model.Class.attributes[attr] == 'array'){
65  
-				var self = this;
66  
-				name = '[name="'+this.options.model.Class._shortName+'['+attr+'][]"]';
67  
-				this.element.find(name).each(function(i, el){
68  
-					if(self.options.model.attr(attr).indexOf($(el).val()) > -1) $(el).attr('checked', true)
69  
-					else $(el).attr('checked', false);
70  
-				}).parents('.input-wrapper').removeClass('has-errors').find('.errors').html('').hide();
71  
-			} else if(this.options.model.Class.attributes[attr] == 'boolean') {
72  
-				this.errorsElementForField(attr).html('').hide().parents('.input-wrapper').removeClass('has-errors');
73  
-				this.element.find(name).attr('checked', this.options.model.attr(attr));
74  
-			} else if(this.element.find(name).attr('type') == 'radio'){
75  
-				var self = this;
76  
-				var el = this.element.find(name).map(function(i, element){
77  
-					if($(element).val() == self.options.model.attr(attr))
78  
-					return element;
79  
-				})
80  
-				$(el).attr('checked', true);
81  
-			} else {
82  
-				this.errorsElementForField(attr).html('').hide().parents('.input-wrapper').removeClass('has-errors');
83  
-				this.element.find(name).val(this.options.model.attr(attr));
  65
+			if(typeof attr != 'undefined'){
  66
+				var name = '[name="'+this.options.model.Class._shortName+'['+attr+']"]';
  67
+				if(this.options.model.Class.attributes[attr] == 'array'){
  68
+					var self = this;
  69
+					name = '[name="'+this.options.model.Class._shortName+'['+attr+'][]"]';
  70
+					this.element.find(name).each(function(i, el){
  71
+						if(self.options.model.attr(attr).indexOf($(el).val()) > -1) $(el).attr('checked', true)
  72
+						else $(el).attr('checked', false);
  73
+					}).parents('.input-wrapper').removeClass('has-errors').find('.errors').html('').hide();
  74
+				} else if(this.options.model.Class.attributes[attr] == 'boolean') {
  75
+					this.errorsElementForField(attr).html('').hide().parents('.input-wrapper').removeClass('has-errors');
  76
+					this.element.find(name).attr('checked', this.options.model.attr(attr));
  77
+				} else if(this.element.find(name).attr('type') == 'radio'){
  78
+					var self = this;
  79
+					var el = this.element.find(name).map(function(i, element){
  80
+						if($(element).val() == self.options.model.attr(attr))
  81
+						return element;
  82
+					})
  83
+					$(el).attr('checked', true);
  84
+				} else {
  85
+					this.errorsElementForField(attr).html('').hide().parents('.input-wrapper').removeClass('has-errors');
  86
+					this.element.find(name).val(this.options.model.attr(attr));
  87
+				}
84 88
 			}
85  
-			
86 89
 		},
87 90
 		attrFromFieldName : function(el){
88 91
 			return el.attr('name').match(/\[[a-zA-Z0-9_-]+\]/g).pop().replace(/\[|\]/g, '');
89 92
 		}
90 93
 	})
  94
+	
  95
+	$.Class.extend('FormBinder.Builder', {
  96
+		getBuilder : function(model, options){
  97
+			return new FormBinder.Builder(model, options);
  98
+		},
  99
+		defaults : {
  100
+			// Wrappers
  101
+			
  102
+			generic_wrapper                : 'views/wrappers/generic.ejs',
  103
+			boolean_checkbox_radio_wrapper : 'views/wrappers/boolean_checkbox_radio.ejs',
  104
+			
  105
+			// Inputs
  106
+			boolean_input        : 'views/inputs/boolean.ejs',
  107
+			checkbox_group_input : 'views/inputs/checkbox_group.ejs',
  108
+			password_input       : 'views/inputs/password.ejs',
  109
+			radio_group_input    : 'views/inputs/radio_group.ejs',
  110
+			select_input         : 'views/inputs/select.ejs',
  111
+			string_input         : 'views/inputs/string.ejs',
  112
+			textarea_input       : 'views/inputs/textarea.ejs'
  113
+			
  114
+		}
  115
+	}, {
  116
+		setup : function(model, opts){
  117
+			var options = opts || {};
  118
+			this.options = $.extend($.extend(true, {}, this.Class.defaults), options);
  119
+			console.log(this.options)
  120
+		},
  121
+		init : function(model){
  122
+			this.model = model;
  123
+		},
  124
+		bindForm : function(){
  125
+			var self = this;
  126
+			return function( el ) {
  127
+				var shortName = self.model.Class._shortName,
  128
+							 models = $.data(el, "models") || $.data(el, "models", {});
  129
+				$(el).addClass(shortName + " " + self.model.identity());
  130
+				models[shortName] = self.model;
  131
+				$(el).form_binder({model: self.model});
  132
+				
  133
+			};
  134
+		},
  135
+		inputs : function(){
  136
+			var inputs = [];
  137
+			var fields = [];
  138
+			var modelAttrs = this.model.Class.attributes;
  139
+			var renderFields = $.makeArray(arguments);
  140
+			if(renderFields.length != 0){
  141
+				for(var i = 0; i < renderFields.length; i++){
  142
+					fields.push(renderFields[i])
  143
+				}
  144
+			} else {
  145
+				for(var k in modelAttrs){
  146
+					if(modelAttrs.hasOwnProperty(k)){
  147
+						fields.push(k)
  148
+					}
  149
+				}
  150
+			}
  151
+			for(var i = 0; i < fields.length; i++){
  152
+				inputs.push(this.input(fields[i]))
  153
+			}
  154
+			return inputs.join('');
  155
+		},
  156
+		input : function(field, options){
  157
+			var opts      = options || {};
  158
+			var name      = $.String.sub("{model.Class._shortName}[{field}]", {model: this.model, field: field});
  159
+			var id        = $.String.sub("{model.Class._shortName}_{field}", {model: this.model, field: field});
  160
+			var value     = this.model.attr(field) || null;
  161
+			
  162
+			var fieldType = opts.as || this.model.Class.attributes[field] || 'string';
  163
+			if(fieldType == 'array') 
  164
+				fieldType = 'checkboxGroup';
  165
+			
  166
+			opts = $.extend(opts, {id: id, name: name, value: value, field: field, model: this.model});
  167
+			if(typeof opts.label == 'undefined') 
  168
+				opts.label = $.String.niceName(field);
  169
+			
  170
+			var hint = opts.hint || null;
  171
+			
  172
+			//console.log(opts.label)
  173
+			
  174
+			return $.View(this._templateMethod(fieldType).apply(this), {
  175
+				input: this._renderMethod(fieldType).call(this, opts),
  176
+				fieldType : fieldType,
  177
+				fieldId : id,
  178
+				label : opts.label,
  179
+				hint : hint
  180
+			});
  181
+		},
  182
+		_renderMethod : function(f){
  183
+			return (typeof this['_'+f+'Input'] != 'undefined') ? this['_'+f+'Input'] : this['_stringInput'];
  184
+		},
  185
+		_templateMethod : function(f){
  186
+			return (typeof this['_'+f+'Template'] != 'undefined') ? this['_'+f+'Template'] : this._stringTemplate;
  187
+		},
  188
+		_passwordInput : function(opts){
  189
+			return $.View(this.options.password_input, opts);
  190
+		},
  191
+		_stringInput : function(opts){
  192
+			return $.View(this.options.string_input, opts);
  193
+		},
  194
+		_textInput : function(opts){
  195
+			return $.View(this.options.textarea_input, opts);
  196
+		},
  197
+		_booleanInput : function(opts){
  198
+			return $.View(this.options.boolean_input, opts);
  199
+		},
  200
+		_radioGroupInput : function(opts){
  201
+			opts.values  = opts.values || opts.model.Class['valuesFor' + $.String.capitalize(opts.field)];
  202
+			if($.isFunction(opts.values)) opts.values = opts.values(opts.model);
  203
+			return $.View(this.options.radio_group_input, opts);
  204
+		},
  205
+		_checkboxGroupInput : function(opts){
  206
+			opts.values  = opts.values || opts.model.Class['valuesFor' + $.String.capitalize(opts.field)];
  207
+			if($.isFunction(opts.values)) opts.values = opts.values(opts.model);
  208
+			opts.value = opts.value || [];
  209
+			if($.isFunction(opts.values)) opts.values = opts.values(opts.model);
  210
+			return $.View(this.options.checkbox_group_input, opts);
  211
+		},
  212
+		_selectInput : function(opts){
  213
+			var select  = '<select name="' + opts.name + '" id="' + opts.id + '">';
  214
+			var values  = opts.values || opts.model.Class['valuesFor' + $.String.classize(opts.field)];
  215
+			if($.isFunction(values)) values = values(opts.model);
  216
+			opts.values = values;
  217
+			return $.View(this.options.select_input, opts);
  218
+		},
  219
+		_booleanTemplate : function(){
  220
+			return this.options.boolean_checkbox_radio_wrapper; 
  221
+		},
  222
+		_checkboxGroupTemplate : function(){
  223
+			return this.options.boolean_checkbox_radio_wrapper; 
  224
+		},
  225
+		_radioGroupTemplate : function(){
  226
+			return this.options.boolean_checkbox_radio_wrapper; 
  227
+		},
  228
+		_stringTemplate : function(){
  229
+			return this.options.generic_wrapper;
  230
+		}
  231
+	});
  232
+	
  233
+	$.extend($.EJS.Helpers.prototype, {form_builder : FormBinder.Builder.getBuilder});
  234
+	
91 235
 });
92 236
 
118  form_binder_builder.js
... ...
@@ -1,118 +0,0 @@
1  
-steal.plugins(
2  
-	'jquery/class',
3  
-	'jquery/view',
4  
-	'jquery/view/ejs'
5  
-).then(function(){
6  
-	$.Class.extend('FormBinderBuilder', {
7  
-		getBuilder : function(model){
8  
-			return new FormBinderBuilder(model);
9  
-		}
10  
-	}, {
11  
-		init : function(model){
12  
-			this.model = model;
13  
-		},
14  
-		bindForm : function(){
15  
-			var self = this;
16  
-			return function( el ) {
17  
-				$(el).form_binder({model: self.model});
18  
-			};
19  
-		},
20  
-		inputs : function(){
21  
-			var inputs = [];
22  
-			var fields = [];
23  
-			var modelAttrs = this.model.Class.attributes;
24  
-			var renderFields = $.makeArray(arguments);
25  
-			if(renderFields.length != 0){
26  
-				for(var i = 0; i < renderFields.length; i++){
27  
-					fields.push(renderFields[i])
28  
-				}
29  
-			} else {
30  
-				for(var k in modelAttrs){
31  
-					if(modelAttrs.hasOwnProperty(k)){
32  
-						fields.push(k)
33  
-					}
34  
-				}
35  
-			}
36  
-			for(var i = 0; i < fields.length; i++){
37  
-				inputs.push(this.input(fields[i]))
38  
-			}
39  
-			return inputs.join('');
40  
-		},
41  
-		input : function(field, options){
42  
-			var opts      = options || {};
43  
-			var name      = $.String.sub("{model.Class._shortName}[{field}]", {model: this.model, field: field});
44  
-			var id        = $.String.sub("{model.Class._shortName}_{field}", {model: this.model, field: field});
45  
-			var value     = this.model.attr(field) || null;
46  
-			
47  
-			var fieldType = opts.as || this.model.Class.attributes[field] || 'string';
48  
-			if(fieldType == 'array') 
49  
-				fieldType = 'checkboxGroup';
50  
-			
51  
-			opts = $.extend(opts, {id: id, name: name, value: value, field: field, model: this.model});
52  
-			if(typeof opts.label == 'undefined') 
53  
-				opts.label = $.String.niceName(field);
54  
-			
55  
-			var hint = opts.hint || null;
56  
-			
57  
-			console.log(opts.label)
58  
-			
59  
-			return $.View('views/wrappers/' + this._templateMethod(fieldType).apply(this), {
60  
-				input: this._renderMethod(fieldType).call(this, opts),
61  
-				fieldType : fieldType,
62  
-				fieldId : id,
63  
-				label : opts.label,
64  
-				hint : hint
65  
-			});
66  
-		},
67  
-		_renderMethod : function(f){
68  
-			return (typeof this['_'+f+'Input'] != 'undefined') ? this['_'+f+'Input'] : this['_stringInput'];
69  
-		},
70  
-		_templateMethod : function(f){
71  
-			return (typeof this['_'+f+'Template'] != 'undefined') ? this['_'+f+'Template'] : this._stringTemplate;
72  
-		},
73  
-		_passwordInput : function(opts){
74  
-			return $.View('views/inputs/password', opts);
75  
-		},
76  
-		_stringInput : function(opts){
77  
-			return $.View('views/inputs/string', opts);
78  
-		},
79  
-		_textInput : function(opts){
80  
-			return $.View('views/inputs/textarea', opts);
81  
-		},
82  
-		_booleanInput : function(opts){
83  
-			return $.View('views/inputs/boolean', opts);
84  
-		},
85  
-		_radioGroupInput : function(opts){
86  
-			opts.values  = opts.values || opts.model.Class['valuesFor' + $.String.capitalize(opts.field)];
87  
-			if($.isFunction(opts.values)) opts.values = opts.values(opts.model);
88  
-			return $.View('views/inputs/radio_group', opts);
89  
-		},
90  
-		_checkboxGroupInput : function(opts){
91  
-			opts.values  = opts.values || opts.model.Class['valuesFor' + $.String.capitalize(opts.field)];
92  
-			if($.isFunction(opts.values)) opts.values = opts.values(opts.model);
93  
-			opts.value = opts.value || [];
94  
-			if($.isFunction(opts.values)) opts.values = opts.values(opts.model);
95  
-			return $.View('views/inputs/checkbox_group', opts);
96  
-		},
97  
-		_selectInput : function(opts){
98  
-			var select  = '<select name="' + opts.name + '" id="' + opts.id + '">';
99  
-			var values  = opts.values || opts.model.Class['valuesFor' + $.String.capitalize(opts.field)];
100  
-			if($.isFunction(values)) values = values(opts.model);
101  
-			opts.values = values;
102  
-			return $.View('views/inputs/select', opts);
103  
-		},
104  
-		_booleanTemplate : function(){
105  
-			return 'boolean_checkbox_radio'; 
106  
-		},
107  
-		_checkboxGroupTemplate : function(){
108  
-			return 'boolean_checkbox_radio'; 
109  
-		},
110  
-		_radioGroupTemplate : function(){
111  
-			return 'boolean_checkbox_radio'; 
112  
-		},
113  
-		_stringTemplate : function(){
114  
-			return 'generic';
115  
-		}
116  
-	});
117  
-	$.extend($.EJS.Helpers.prototype, {form_builder : FormBinderBuilder.getBuilder});
118  
-})
5  form_binder_test.js
... ...
@@ -1,4 +1,4 @@
1  
-steal.plugins(
  1
+steal(
2 2
 	"jquery/class", 
3 3
 	'jquery/controller', 
4 4
 	'jquery/model', 
@@ -9,8 +9,7 @@ steal.plugins(
9 9
 .then(function(){
10 10
 	
11 11
 	$.Controller.extend('Cntrlr', {
12  
-			init : function(){
13  
-			
  12
+		init : function(){
14 13
 			this.element.html($.View('form', {m: model}))
15 14
 		}
16 15
 	});
2  views/wrappers/boolean_checkbox_radio.ejs
... ...
@@ -1,4 +1,4 @@
1  
-<div class="<%= fieldType %> input-wrapper">
  1
+<div class="<%= fieldType %> input-wrapper wrapper-for-<%=fieldId%>">
2 2
   <%= input %>
3 3
   <span class="hint"><%= hint %></span>
4 4
   <span class="errors"></span>
2  views/wrappers/generic.ejs
... ...
@@ -1,4 +1,4 @@
1  
-<div class="<%= fieldType %> input-wrapper">
  1
+<div class="<%= fieldType %> input-wrapper wrapper-for-<%=fieldId%>">
2 2
   <label for="<%= fieldId %>"><%= label %></label>
3 3
   <%= input %>
4 4
   <span class="hint"><%= hint %></span>

0 notes on commit ad19161

Please sign in to comment.
Something went wrong with that request. Please try again.