canjs-rails 0.1.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,374 +1,199 @@
1
- (function(can, window, undefined){
2
- //validations object is by property. You can have validations that
3
- //span properties, but this way we know which ones to run.
4
- // proc should return true if there's an error or the error message
5
- var validate = function(attrNames, options, proc) {
6
- // normalize argumetns
7
- if(!proc){
8
- proc = options;
9
- options = {};
10
- }
11
-
12
- options = options || {};
13
- attrNames = can.makeArray(attrNames)
14
-
15
- // run testIf if it exists
16
- if(options.testIf && !options.testIf.call(this)){
17
- return;
18
- }
19
-
20
- var self = this;
21
- can.each(attrNames, function(attrName) {
22
- // Add a test function for each attribute
23
- if(!self.validations[attrName]){
24
- self.validations[attrName] = [];
1
+ /*
2
+ * CanJS - 1.1.2 (2012-11-28)
3
+ * http://canjs.us/
4
+ * Copyright (c) 2012 Bitovi
5
+ * Licensed MIT
6
+ */
7
+ (function (can, window, undefined) {
8
+ // ## can/observe/validations/validations.js
9
+ //validations object is by property. You can have validations that
10
+ //span properties, but this way we know which ones to run.
11
+ // proc should return true if there's an error or the error message
12
+ var validate = function (attrNames, options, proc) {
13
+ // normalize argumetns
14
+ if (!proc) {
15
+ proc = options;
16
+ options = {};
25
17
  }
26
-
27
- self.validations[attrName].push(function(newVal){
28
- // if options has a message return that, otherwise, return the error
29
- var res = proc.call(this, newVal, attrName);
30
- return res === undefined ? undefined : (options.message || res);
31
- })
32
- });
33
- };
34
-
35
- var old = can.Observe.prototype.__set;
36
- can.Observe.prototype.__set = function(prop, value, current, success, error){
37
- var self = this,
38
- validations = self.constructor.validations,
39
- errorCallback = function( errors ) {
40
- var stub = error && error.call(self, errors);
41
-
42
- // if 'setter' is on the page it will trigger
43
- // the error itself and we dont want to trigger
44
- // the event twice. :)
45
- if(stub !== false){
46
- can.trigger(self, "error", [prop, errors], true);
47
- }
48
-
49
- return false;
50
- };
51
-
52
- old.call(self, prop, value, current, success, errorCallback);
53
-
54
- if (validations && validations[prop]){
55
- var errors = self.errors(prop);
56
- errors && errorCallback(errors)
57
- }
58
-
59
- return this;
60
- }
61
-
62
- can.each([ can.Observe, can.Model ], function(clss){
63
- // in some cases model might not be defined quite yet.
64
- if(clss === undefined){
65
- return;
66
- }
67
- var oldSetup = clss.setup;
68
-
69
- can.extend(clss, {
70
- setup : function(superClass){
71
- oldSetup.apply(this, arguments);
72
- if (!this.validations || superClass.validations === this.validations) {
73
- this.validations = {};
18
+
19
+ options = options || {};
20
+ attrNames = can.makeArray(attrNames)
21
+
22
+ // run testIf if it exists
23
+ if (options.testIf && !options.testIf.call(this)) {
24
+ return;
25
+ }
26
+
27
+ var self = this;
28
+ can.each(attrNames, function (attrName) {
29
+ // Add a test function for each attribute
30
+ if (!self.validations[attrName]) {
31
+ self.validations[attrName] = [];
74
32
  }
75
- },
76
- /**
77
- * @function can.Observe.static.validate
78
- * @parent can.Observe.validations
79
- * `validate(attrNames, [options,] validateProc(value, attrName) )` validates each of the
80
- * specified attributes with the given `validateProc` function. The function
81
- * should return a value if there is an error. By default, the return value is
82
- * the error message. Validations should be set in the Constructor's static init method.
83
- *
84
- * The following example validates that a person's age is a number:
85
- *
86
- * Person = can.Observe({
87
- * init : function(){
88
- * this.validate(["age"], function(val){
89
- * if( typeof val === 'number' ){
90
- * return "must be a number"
91
- * }
92
- * })
93
- * }
94
- * },{})
95
- *
96
- *
97
- * The error message can be overwritten with `options` __message__ property:
98
- *
99
- * Person = can.Observe({
100
- * init : function(){
101
- * this.validate(
102
- * "age",
103
- * {message: "must be a number"},
104
- * function(val){
105
- * if( typeof val === 'number' ){
106
- * return true
107
- * }
108
- * })
109
- * }
110
- * },{})
111
- *
112
- * @param {Array|String} attrNames Attribute name(s) to to validate
113
- *
114
- * @param {Object} [options] Options for the
115
- * validations. Valid options include 'message' and 'testIf'.
116
- *
117
- * @param {Function} validateProc(value,attrName) Function used to validate each
118
- * given attribute. Returns nothing if valid and an error message
119
- * otherwise. Function is called in the instance context and takes the
120
- * `value` and `attrName` to validate.
121
- *
122
- */
123
- validate: validate,
124
-
125
- /**
126
- * @attribute can.Observe.static.validationMessages
127
- * @parent can.Observe.validations
128
- *
129
- * `validationMessages` has the default validation error messages that will be returned by the builtin
130
- * validation methods. These can be overwritten by assigning new messages
131
- * to `can.Observe.validationMessages` in your application setup.
132
- *
133
- * The following messages (with defaults) are available:
134
- *
135
- * * format - "is invalid"
136
- * * inclusion - "is not a valid option (perhaps out of range)"
137
- * * lengthShort - "is too short"
138
- * * lengthLong - "is too long"
139
- * * presence - "can't be empty"
140
- * * range - "is out of range"
141
- *
142
- * It is important to steal can/observe/validations before
143
- * overwriting the messages, otherwise the changes will
144
- * be lost once steal loads it later.
145
- *
146
- * ## Example
147
- *
148
- * can.Observe.validationMessages.format = "is invalid dummy!"
149
- */
150
- validationMessages : {
151
- format : "is invalid",
152
- inclusion : "is not a valid option (perhaps out of range)",
153
- lengthShort : "is too short",
154
- lengthLong : "is too long",
155
- presence : "can't be empty",
156
- range : "is out of range"
157
- },
158
-
159
- /**
160
- * @function can.Observe.static.validateFormatOf
161
- * @parent can.Observe.validations
162
- *
163
- * `validateFormatOf(attrNames, regexp, options)` validates where the values of
164
- * specified attributes are of the correct form by
165
- * matching it against the regular expression provided.
166
- *
167
- * init : function(){
168
- * this.validateFormatOf(["email"],/[\w\.]+@]w+\.\w+/,{
169
- * message : "invalid email"
170
- * })
171
- * }
172
- *
173
- * @param {Array|String} attrNames Attribute name(s) to to validate
174
- * @param {RegExp} regexp Regular expression used to match for validation
175
- * @param {Object} [options] Options for the validations. Valid options include 'message' and 'testIf'.
176
- */
177
- validateFormatOf: function(attrNames, regexp, options) {
178
- validate.call(this, attrNames, options, function(value) {
179
- if( (typeof value != 'undefined' && value != '')
180
- && String(value).match(regexp) == null ) {
181
- return this.constructor.validationMessages.format;
182
- }
183
- });
184
- },
185
-
186
- /**
187
- * @function can.Observe.static.validateInclusionOf
188
- * @parent can.Observe.validations
189
- *
190
- * Validates whether the values of the specified attributes are available in a particular
191
- * array.
192
- *
193
- * init : function(){
194
- * this.validateInclusionOf(["salutation"],["Mr.","Mrs.","Dr."])
195
- * }
196
- *
197
- * @param {Array|String} attrNames Attribute name(s) to to validate
198
- * @param {Array} inArray Array of options to test for inclusion
199
- * @param {Object} [options] Options for the validations. Valid options include 'message' and 'testIf'.
200
- */
201
- validateInclusionOf: function(attrNames, inArray, options) {
202
- validate.call(this, attrNames, options, function(value) {
203
- if(typeof value == 'undefined'){
204
- return;
205
- }
206
33
 
207
- if(can.grep(inArray, function(elm) { return (elm == value); }).length == 0){
208
- return this.constructor.validationMessages.inclusion;
209
- }
210
- });
211
- },
212
-
213
- /**
214
- * @function can.Observe.static.validateLengthOf
215
- * @parent can.Observe.validations
216
- *
217
- * Validates that the specified attributes' lengths are in the given range.
218
- *
219
- * init : function(){
220
- * this.validateInclusionOf(["suffix"],3,5)
221
- * }
222
- *
223
- * @param {Number} min Minimum length (inclusive)
224
- * @param {Number} max Maximum length (inclusive)
225
- * @param {Object} [options] Options for the validations. Valid options include 'message' and 'testIf'.
226
- */
227
- validateLengthOf: function(attrNames, min, max, options) {
228
- validate.call(this, attrNames, options, function(value) {
229
- if((typeof value == 'undefined' && min > 0) || value.length < min){
230
- return this.constructor.validationMessages.lengthShort + " (min=" + min + ")";
231
- } else if(typeof value != 'undefined' && value.length > max){
232
- return this.constructor.validationMessages.lengthLong + " (max=" + max + ")";
233
- }
234
- });
235
- },
236
-
237
- /**
238
- * @function can.Observe.static.validatePresenceOf
239
- * @parent can.Observe.validations
240
- *
241
- * Validates that the specified attributes are not blank.
242
- *
243
- * init : function(){
244
- * this.validatePresenceOf(["name"])
245
- * }
246
- *
247
- * @param {Array|String} attrNames Attribute name(s) to to validate
248
- * @param {Object} [options] Options for the validations. Valid options include 'message' and 'testIf'.
249
- */
250
- validatePresenceOf: function(attrNames, options) {
251
- validate.call(this, attrNames, options, function(value) {
252
- if(typeof value == 'undefined' || value == "" || value === null){
253
- return this.constructor.validationMessages.presence;
254
- }
255
- });
256
- },
257
-
258
- /**
259
- * @function can.Observe.static.validateRangeOf
260
- * @parent can.Observe.validations
261
- *
262
- * Validates that the specified attributes are in the given numeric range.
263
- *
264
- * init : function(){
265
- * this.validateRangeOf(["age"],21, 130);
266
- * }
267
- *
268
- * @param {Array|String} attrNames Attribute name(s) to to validate
269
- * @param {Number} low Minimum value (inclusive)
270
- * @param {Number} hi Maximum value (inclusive)
271
- * @param {Object} [options] (optional) Options for the validations. Valid options include 'message' and 'testIf'.
272
- */
273
- validateRangeOf: function(attrNames, low, hi, options) {
274
- validate.call(this, attrNames, options, function(value) {
275
- if(typeof value != 'undefined' && value < low || value > hi){
276
- return this.constructor.validationMessages.range + " [" + low + "," + hi + "]";
34
+ self.validations[attrName].push(function (newVal) {
35
+ // if options has a message return that, otherwise, return the error
36
+ var res = proc.call(this, newVal, attrName);
37
+ return res === undefined ? undefined : (options.message || res);
38
+ })
39
+ });
40
+ };
41
+
42
+ var old = can.Observe.prototype.__set;
43
+ can.Observe.prototype.__set = function (prop, value, current, success, error) {
44
+ var self = this,
45
+ validations = self.constructor.validations,
46
+ errorCallback = function (errors) {
47
+ var stub = error && error.call(self, errors);
48
+
49
+ // if 'setter' is on the page it will trigger
50
+ // the error itself and we dont want to trigger
51
+ // the event twice. :)
52
+ if (stub !== false) {
53
+ can.trigger(self, "error", [prop, errors], true);
277
54
  }
278
- });
279
- }
280
- });
281
- });
282
-
283
- can.extend(can.Observe.prototype, {
284
-
285
- /**
286
- * @function can.Observe.prototype.errors
287
- * @parent can.Observe.validations
288
- *
289
- * Runs the validations on this observe. You can
290
- * also pass it an array of attributes to run only those attributes.
291
- * It returns nothing if there are no errors, or an object
292
- * of errors by attribute.
293
- *
294
- * To use validations, it's suggested you use the
295
- * observe/validations plugin.
296
- *
297
- * can.Observe("Task",{
298
- * init : function(){
299
- * this.validatePresenceOf("dueDate")
300
- * }
301
- * },{});
302
- *
303
- * var task = new Task(),
304
- * errors = task.errors()
305
- *
306
- * errors.dueDate[0] //-> "can't be empty"
307
- *
308
- * @param {Array|String} [attrs] An optional list of attributes to get errors for:
309
- *
310
- * task.errors(['dueDate','name']);
311
- *
312
- * Or it can take a single attr name like:
313
- *
314
- * task.errors('dueDate')
315
- *
316
- * @param {Object} [newVal] An optional new value to test setting
317
- * on the observe. If `newVal` is provided,
318
- * it returns the errors on the observe if `newVal` was set.
319
- *
320
- * @return {Object} an object of attributeName : [errors] like:
321
- *
322
- * task.errors() // -> {dueDate: ["cant' be empty"]}
323
- *
324
- * or `null` if there are no errors.
325
- */
326
- errors: function( attrs , newVal) {
327
- // convert attrs to an array
328
- if ( attrs ) {
329
- attrs = can.isArray(attrs) ? attrs : [attrs];
55
+
56
+ return false;
57
+ };
58
+
59
+ old.call(self, prop, value, current, success, errorCallback);
60
+
61
+ if (validations && validations[prop]) {
62
+ var errors = self.errors(prop);
63
+ errors && errorCallback(errors)
330
64
  }
331
-
332
- var errors = {},
333
- self = this,
334
- attr,
335
- // helper function that adds error messages to errors object
336
- // attr - the name of the attribute
337
- // funcs - the validation functions
338
- addErrors = function( attr, funcs ) {
339
- can.each(funcs, function( func ) {
340
- var res = func.call(self, isTest ? ( self.__convert ?
341
- self.__convert(attr,newVal) :
342
- newVal ): self[attr]);
343
- if ( res ) {
344
- if (!errors[attr] ) {
345
- errors[attr] = [];
346
- }
347
- errors[attr].push(res);
65
+
66
+ return this;
67
+ }
68
+
69
+ can.each([can.Observe, can.Model], function (clss) {
70
+ // in some cases model might not be defined quite yet.
71
+ if (clss === undefined) {
72
+ return;
73
+ }
74
+ var oldSetup = clss.setup;
75
+
76
+ can.extend(clss, {
77
+ setup: function (superClass) {
78
+ oldSetup.apply(this, arguments);
79
+ if (!this.validations || superClass.validations === this.validations) {
80
+ this.validations = {};
81
+ }
82
+ },
83
+
84
+ validate: validate,
85
+
86
+
87
+ validationMessages: {
88
+ format: "is invalid",
89
+ inclusion: "is not a valid option (perhaps out of range)",
90
+ lengthShort: "is too short",
91
+ lengthLong: "is too long",
92
+ presence: "can't be empty",
93
+ range: "is out of range"
94
+ },
95
+
96
+
97
+ validateFormatOf: function (attrNames, regexp, options) {
98
+ validate.call(this, attrNames, options, function (value) {
99
+ if ((typeof value != 'undefined' && value != '') && String(value).match(regexp) == null) {
100
+ return this.constructor.validationMessages.format;
348
101
  }
102
+ });
103
+ },
104
+
349
105
 
106
+ validateInclusionOf: function (attrNames, inArray, options) {
107
+ validate.call(this, attrNames, options, function (value) {
108
+ if (typeof value == 'undefined') {
109
+ return;
110
+ }
111
+
112
+ if (can.grep(inArray, function (elm) {
113
+ return (elm == value);
114
+ }).length == 0) {
115
+ return this.constructor.validationMessages.inclusion;
116
+ }
350
117
  });
351
118
  },
352
- validations = this.constructor.validations,
353
- isTest = attrs && attrs.length === 1 && arguments.length === 2;
354
-
355
- // go through each attribute or validation and
356
- // add any errors
357
- can.each(attrs || validations || {}, function( funcs, attr ) {
358
- // if we are iterating through an array, use funcs
359
- // as the attr name
360
- if ( typeof attr == 'number' ) {
361
- attr = funcs;
362
- funcs = validations[attr];
119
+
120
+
121
+ validateLengthOf: function (attrNames, min, max, options) {
122
+ validate.call(this, attrNames, options, function (value) {
123
+ if ((typeof value == 'undefined' && min > 0) || value.length < min) {
124
+ return this.constructor.validationMessages.lengthShort + " (min=" + min + ")";
125
+ } else if (typeof value != 'undefined' && value.length > max) {
126
+ return this.constructor.validationMessages.lengthLong + " (max=" + max + ")";
127
+ }
128
+ });
129
+ },
130
+
131
+
132
+ validatePresenceOf: function (attrNames, options) {
133
+ validate.call(this, attrNames, options, function (value) {
134
+ if (typeof value == 'undefined' || value === "" || value === null) {
135
+ return this.constructor.validationMessages.presence;
136
+ }
137
+ });
138
+ },
139
+
140
+
141
+ validateRangeOf: function (attrNames, low, hi, options) {
142
+ validate.call(this, attrNames, options, function (value) {
143
+ if (typeof value != 'undefined' && value < low || value > hi) {
144
+ return this.constructor.validationMessages.range + " [" + low + "," + hi + "]";
145
+ }
146
+ });
363
147
  }
364
- // add errors to the
365
- addErrors(attr, funcs || []);
366
148
  });
367
-
368
- // return errors as long as we have one
369
- return can.isEmptyObject(errors) ? null : isTest ? errors[attrs[0]] : errors;
370
- }
371
-
372
- });
149
+ });
150
+
151
+ can.extend(can.Observe.prototype, {
152
+
153
+
154
+ errors: function (attrs, newVal) {
155
+ // convert attrs to an array
156
+ if (attrs) {
157
+ attrs = can.isArray(attrs) ? attrs : [attrs];
158
+ }
159
+
160
+ var errors = {},
161
+ self = this,
162
+ attr,
163
+ // helper function that adds error messages to errors object
164
+ // attr - the name of the attribute
165
+ // funcs - the validation functions
166
+ addErrors = function (attr, funcs) {
167
+ can.each(funcs, function (func) {
168
+ var res = func.call(self, isTest ? (self.__convert ? self.__convert(attr, newVal) : newVal) : self[attr]);
169
+ if (res) {
170
+ if (!errors[attr]) {
171
+ errors[attr] = [];
172
+ }
173
+ errors[attr].push(res);
174
+ }
175
+
176
+ });
177
+ },
178
+ validations = this.constructor.validations,
179
+ isTest = attrs && attrs.length === 1 && arguments.length === 2;
180
+
181
+ // go through each attribute or validation and
182
+ // add any errors
183
+ can.each(attrs || validations || {}, function (funcs, attr) {
184
+ // if we are iterating through an array, use funcs
185
+ // as the attr name
186
+ if (typeof attr == 'number') {
187
+ attr = funcs;
188
+ funcs = validations[attr];
189
+ }
190
+ // add errors to the
191
+ addErrors(attr, funcs || []);
192
+ });
193
+
194
+ // return errors as long as we have one
195
+ return can.isEmptyObject(errors) ? null : isTest ? errors[attrs[0]] : errors;
196
+ }
197
+ });
373
198
 
374
- })(this.can, this )
199
+ })(can, this);