canjs-rails 0.1.0 → 1.1.2
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.
- data/CHANGELOG.md +5 -0
- data/canjs-rails.gemspec +1 -1
- data/lib/canjs/rails/version.rb +2 -2
- data/vendor/assets/javascripts/can.construct.proxy.js +27 -26
- data/vendor/assets/javascripts/can.construct.super.js +40 -36
- data/vendor/assets/javascripts/can.control.plugin.js +92 -229
- data/vendor/assets/javascripts/can.control.view.js +37 -31
- data/vendor/assets/javascripts/can.fixture.js +277 -570
- data/vendor/assets/javascripts/can.jquery.js +2396 -1792
- data/vendor/assets/javascripts/can.jquery.min.js +70 -52
- data/vendor/assets/javascripts/can.observe.attributes.js +137 -276
- data/vendor/assets/javascripts/can.observe.backup.js +137 -335
- data/vendor/assets/javascripts/can.observe.delegate.js +97 -250
- data/vendor/assets/javascripts/can.observe.setter.js +53 -52
- data/vendor/assets/javascripts/can.observe.validations.js +187 -362
- data/vendor/assets/javascripts/can.view.modifiers.js +57 -190
- data/vendor/assets/javascripts/can.view.mustache.js +758 -0
- data/vendor/assets/javascripts/download_canjs.sh +18 -13
- metadata +4 -3
@@ -1,374 +1,199 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
34
|
-
|
35
|
-
var
|
36
|
-
can.
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
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
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
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
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
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
|
-
|
369
|
-
|
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
|
-
})(
|
199
|
+
})(can, this);
|