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.
- 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);
|