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,368 +1,170 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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/util/object/object.js
|
9
|
+
|
10
|
+
var isArray = can.isArray,
|
11
|
+
// essentially returns an object that has all the must have comparisons ...
|
12
|
+
// must haves, do not return true when provided undefined
|
13
|
+
cleanSet = function (obj, compares) {
|
14
|
+
var copy = can.extend({}, obj);
|
15
|
+
for (var prop in copy) {
|
16
|
+
var compare = compares[prop] === undefined ? compares["*"] : compares[prop];
|
17
|
+
if (same(copy[prop], undefined, compare)) {
|
18
|
+
delete copy[prop]
|
19
|
+
}
|
12
20
|
}
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
};
|
21
|
+
return copy;
|
22
|
+
},
|
23
|
+
propCount = function (obj) {
|
24
|
+
var count = 0;
|
25
|
+
for (var prop in obj) count++;
|
26
|
+
return count;
|
27
|
+
};
|
21
28
|
|
22
|
-
|
23
|
-
* @class can.Object
|
24
|
-
* @parent can.util
|
25
|
-
*
|
26
|
-
* Object contains several helper methods that
|
27
|
-
* help compare objects.
|
28
|
-
*
|
29
|
-
* ## same
|
30
|
-
*
|
31
|
-
* Returns true if two objects are similar.
|
32
|
-
*
|
33
|
-
* can.Object.same({foo: "bar"} , {bar: "foo"}) //-> false
|
34
|
-
*
|
35
|
-
* ## subset
|
36
|
-
*
|
37
|
-
* Returns true if an object is a set of another set.
|
38
|
-
*
|
39
|
-
* can.Object.subset({}, {foo: "bar"} ) //-> true
|
40
|
-
*
|
41
|
-
* ## subsets
|
42
|
-
*
|
43
|
-
* Returns the subsets of an object
|
44
|
-
*
|
45
|
-
* can.Object.subsets({userId: 20},
|
46
|
-
* [
|
47
|
-
* {userId: 20, limit: 30},
|
48
|
-
* {userId: 5},
|
49
|
-
* {}
|
50
|
-
* ])
|
51
|
-
* //-> [{userId: 20, limit: 30}]
|
52
|
-
*/
|
53
|
-
can.Object = {};
|
29
|
+
can.Object = {};
|
54
30
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
* // deep rule
|
78
|
-
* can.Object.same({ person : { name: "Justin" } },
|
79
|
-
* { person : { name: "JUSTIN" } },
|
80
|
-
* { person : { name: "i" } }) //-> true
|
81
|
-
*
|
82
|
-
* // supplied compare function
|
83
|
-
* can.Object.same({age: "Thirty"},
|
84
|
-
* {age: 30},
|
85
|
-
* {age: function( a, b ){
|
86
|
-
* if( a == "Thirty" ) {
|
87
|
-
* a = 30
|
88
|
-
* }
|
89
|
-
* if( b == "Thirty" ) {
|
90
|
-
* b = 30
|
91
|
-
* }
|
92
|
-
* return a === b;
|
93
|
-
* }}) //-> true
|
94
|
-
*
|
95
|
-
* @param {Object} a an object to compare
|
96
|
-
* @param {Object} b an object to compare
|
97
|
-
* @param {Object} [compares] an object that indicates how to
|
98
|
-
* compare specific properties.
|
99
|
-
* Typically this is a name / value pair
|
100
|
-
*
|
101
|
-
* can.Object.same({name: "Justin"},{name: "JUSTIN"},{name: "i"})
|
102
|
-
*
|
103
|
-
* There are two compare functions that you can specify with a string:
|
104
|
-
*
|
105
|
-
* - 'i' - ignores case
|
106
|
-
* - null - ignores this property
|
107
|
-
*
|
108
|
-
* @param {Object} [deep] used internally
|
109
|
-
*/
|
110
|
-
var same = can.Object.same = function(a, b, compares, aParent, bParent, deep){
|
111
|
-
var aType = typeof a,
|
112
|
-
aArray = isArray(a),
|
113
|
-
comparesType = typeof compares,
|
114
|
-
compare;
|
115
|
-
|
116
|
-
if(comparesType == 'string' || compares === null ){
|
117
|
-
compares = compareMethods[compares];
|
118
|
-
comparesType = 'function'
|
119
|
-
}
|
120
|
-
if(comparesType == 'function'){
|
121
|
-
return compares(a, b, aParent, bParent)
|
122
|
-
}
|
123
|
-
compares = compares || {};
|
124
|
-
|
125
|
-
if(a instanceof Date){
|
126
|
-
return a === b;
|
127
|
-
}
|
128
|
-
if(deep === -1){
|
129
|
-
return aType === 'object' || a === b;
|
130
|
-
}
|
131
|
-
if(aType !== typeof b || aArray !== isArray(b)){
|
132
|
-
return false;
|
133
|
-
}
|
134
|
-
if(a === b){
|
135
|
-
return true;
|
136
|
-
}
|
137
|
-
if(aArray){
|
138
|
-
if(a.length !== b.length){
|
31
|
+
var same = can.Object.same = function (a, b, compares, aParent, bParent, deep) {
|
32
|
+
var aType = typeof a,
|
33
|
+
aArray = isArray(a),
|
34
|
+
comparesType = typeof compares,
|
35
|
+
compare;
|
36
|
+
|
37
|
+
if (comparesType == 'string' || compares === null) {
|
38
|
+
compares = compareMethods[compares];
|
39
|
+
comparesType = 'function'
|
40
|
+
}
|
41
|
+
if (comparesType == 'function') {
|
42
|
+
return compares(a, b, aParent, bParent)
|
43
|
+
}
|
44
|
+
compares = compares || {};
|
45
|
+
|
46
|
+
if (a instanceof Date) {
|
47
|
+
return a === b;
|
48
|
+
}
|
49
|
+
if (deep === -1) {
|
50
|
+
return aType === 'object' || a === b;
|
51
|
+
}
|
52
|
+
if (aType !== typeof b || aArray !== isArray(b)) {
|
139
53
|
return false;
|
140
54
|
}
|
141
|
-
|
142
|
-
|
143
|
-
|
55
|
+
if (a === b) {
|
56
|
+
return true;
|
57
|
+
}
|
58
|
+
if (aArray) {
|
59
|
+
if (a.length !== b.length) {
|
144
60
|
return false;
|
145
61
|
}
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
62
|
+
for (var i = 0; i < a.length; i++) {
|
63
|
+
compare = compares[i] === undefined ? compares["*"] : compares[i]
|
64
|
+
if (!same(a[i], b[i], a, b, compare)) {
|
65
|
+
return false;
|
66
|
+
}
|
67
|
+
};
|
68
|
+
return true;
|
69
|
+
} else if (aType === "object" || aType === 'function') {
|
70
|
+
var bCopy = can.extend({}, b);
|
71
|
+
for (var prop in a) {
|
72
|
+
compare = compares[prop] === undefined ? compares["*"] : compares[prop];
|
73
|
+
if (!same(a[prop], b[prop], compare, a, b, deep === false ? -1 : undefined)) {
|
74
|
+
return false;
|
75
|
+
}
|
76
|
+
delete bCopy[prop];
|
154
77
|
}
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
! same( undefined, b[prop], compares[prop] , a, b, deep === false ? -1 : undefined )){
|
161
|
-
return false;
|
78
|
+
// go through bCopy props ... if there is no compare .. return false
|
79
|
+
for (prop in bCopy) {
|
80
|
+
if (compares[prop] === undefined || !same(undefined, b[prop], compares[prop], a, b, deep === false ? -1 : undefined)) {
|
81
|
+
return false;
|
82
|
+
}
|
162
83
|
}
|
84
|
+
return true;
|
163
85
|
}
|
164
|
-
return
|
165
|
-
}
|
166
|
-
|
167
|
-
|
86
|
+
return false;
|
87
|
+
};
|
88
|
+
|
89
|
+
can.Object.subsets = function (checkSet, sets, compares) {
|
90
|
+
var len = sets.length,
|
91
|
+
subsets = [],
|
92
|
+
checkPropCount = propCount(checkSet),
|
93
|
+
setLength;
|
168
94
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
can.Object.subsets = function(checkSet, sets, compares){
|
176
|
-
var len = sets.length,
|
177
|
-
subsets = [],
|
178
|
-
checkPropCount = propCount(checkSet),
|
179
|
-
setLength;
|
180
|
-
|
181
|
-
for(var i =0; i < len; i++){
|
182
|
-
//check this subset
|
183
|
-
var set = sets[i];
|
184
|
-
if( can.Object.subset(checkSet, set, compares) ){
|
185
|
-
subsets.push(set)
|
95
|
+
for (var i = 0; i < len; i++) {
|
96
|
+
//check this subset
|
97
|
+
var set = sets[i];
|
98
|
+
if (can.Object.subset(checkSet, set, compares)) {
|
99
|
+
subsets.push(set)
|
100
|
+
}
|
186
101
|
}
|
187
|
-
|
188
|
-
|
189
|
-
};
|
190
|
-
/**
|
191
|
-
* @function subset
|
192
|
-
* Compares if checkSet is a subset of set
|
193
|
-
* @param {Object} checkSet
|
194
|
-
* @param {Object} set
|
195
|
-
* @param {Object} [compares]
|
196
|
-
* @param {Object} [checkPropCount]
|
197
|
-
*/
|
198
|
-
can.Object.subset = function(subset, set, compares){
|
199
|
-
// go through set {type: 'folder'} and make sure every property
|
200
|
-
// is in subset {type: 'folder', parentId :5}
|
201
|
-
// then make sure that set has fewer properties
|
202
|
-
// make sure we are only checking 'important' properties
|
203
|
-
// in subset (ones that have to have a value)
|
204
|
-
|
205
|
-
var setPropCount =0,
|
206
|
-
compares = compares || {};
|
207
|
-
|
208
|
-
for(var prop in set){
|
102
|
+
return subsets;
|
103
|
+
};
|
209
104
|
|
210
|
-
|
211
|
-
|
212
|
-
}
|
213
|
-
|
214
|
-
|
215
|
-
|
105
|
+
can.Object.subset = function (subset, set, compares) {
|
106
|
+
// go through set {type: 'folder'} and make sure every property
|
107
|
+
// is in subset {type: 'folder', parentId :5}
|
108
|
+
// then make sure that set has fewer properties
|
109
|
+
// make sure we are only checking 'important' properties
|
110
|
+
// in subset (ones that have to have a value)
|
111
|
+
var setPropCount = 0,
|
112
|
+
compares = compares || {};
|
216
113
|
|
114
|
+
for (var prop in set) {
|
217
115
|
|
218
|
-
|
219
|
-
|
116
|
+
if (!same(subset[prop], set[prop], compares[prop], subset, set)) {
|
117
|
+
return false;
|
118
|
+
}
|
119
|
+
}
|
220
120
|
return true;
|
221
|
-
},
|
222
|
-
i : function(a, b){
|
223
|
-
return (""+a).toLowerCase() == (""+b).toLowerCase()
|
224
121
|
}
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
;
|
229
|
-
|
230
|
-
|
122
|
+
|
123
|
+
var compareMethods = {
|
124
|
+
"null": function () {
|
125
|
+
return true;
|
126
|
+
},
|
127
|
+
i: function (a, b) {
|
128
|
+
return ("" + a).toLowerCase() == ("" + b).toLowerCase()
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
// ## can/observe/backup/backup.js
|
133
|
+
var flatProps = function (a) {
|
231
134
|
var obj = {};
|
232
|
-
for(var prop in a){
|
233
|
-
if(typeof a[prop] !== 'object' || a[prop] === null || a[prop] instanceof Date){
|
135
|
+
for (var prop in a) {
|
136
|
+
if (typeof a[prop] !== 'object' || a[prop] === null || a[prop] instanceof Date) {
|
234
137
|
obj[prop] = a[prop]
|
235
138
|
}
|
236
139
|
}
|
237
140
|
return obj;
|
238
141
|
};
|
239
|
-
|
142
|
+
|
240
143
|
can.extend(can.Observe.prototype, {
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
* @plugin can/observe/backup
|
245
|
-
* @parent can.Observe.backup
|
246
|
-
*
|
247
|
-
* `observe.backup()` backs up a [can.Observe] instance, so it can be restored later
|
248
|
-
* by calling [can.Observe.prototype.restore] or checked if it
|
249
|
-
* has changed with [can.Observe.prototype.isDirty]:
|
250
|
-
*
|
251
|
-
* var recipe = new can.Observe({
|
252
|
-
* name : 'Pancakes',
|
253
|
-
* ingredients : [{
|
254
|
-
* name : "eggs",
|
255
|
-
* amount : '1'
|
256
|
-
* }, {
|
257
|
-
* name : "flour",
|
258
|
-
* amount : '1 cup'
|
259
|
-
* }, {
|
260
|
-
* name : "milk",
|
261
|
-
* amount : '1 1/4 cup'
|
262
|
-
* }]
|
263
|
-
* });
|
264
|
-
*
|
265
|
-
* recipe.backup();
|
266
|
-
*
|
267
|
-
* @return {can.Observe} The observe instance
|
268
|
-
*/
|
269
|
-
backup: function() {
|
144
|
+
|
145
|
+
|
146
|
+
backup: function () {
|
270
147
|
this._backupStore = this._attrs();
|
271
148
|
return this;
|
272
149
|
},
|
273
150
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
* @parent can.Observe.backup
|
278
|
-
*
|
279
|
-
* `observe.isDirty([checkAssociations])` returns if the observe has changed since the last
|
280
|
-
* [can.Observe.prototype.backup] call. If there is no backup it will return false. If you pass
|
281
|
-
* true, _isDirty_ also checks if any child properties or [can.Model] associations have changed.
|
282
|
-
*
|
283
|
-
* var recipe = new can.Observe({
|
284
|
-
* name : 'Pancakes',
|
285
|
-
* ingredients : [{
|
286
|
-
* name : "eggs",
|
287
|
-
* amount : '1'
|
288
|
-
* }, {
|
289
|
-
* name : "flour",
|
290
|
-
* amount : '1 cup'
|
291
|
-
* }, {
|
292
|
-
* name : "milk",
|
293
|
-
* amount : '1 1/4 cup'
|
294
|
-
* }]
|
295
|
-
* });
|
296
|
-
*
|
297
|
-
* recipe.backup();
|
298
|
-
* // Change the attribute of a nested property
|
299
|
-
* recipe.attr('ingredients.0.amount', '2');
|
300
|
-
* recipe.isDirty() // -> false
|
301
|
-
* recipe.isDirty(true) // -> true
|
302
|
-
* recipe.attr('name', 'Eggcakes');
|
303
|
-
* recipe.isDirty() // -> true
|
304
|
-
*
|
305
|
-
* @param {Boolean} [checkAssociations] Whether nested objects should be checked or
|
306
|
-
* not. Defaults to false.
|
307
|
-
* @return {Boolean} true if there are changes,
|
308
|
-
* false if not or there is no backup
|
309
|
-
*/
|
310
|
-
isDirty: function(checkAssociations) {
|
311
|
-
return this._backupStore &&
|
312
|
-
!can.Object.same(this._attrs(),
|
313
|
-
this._backupStore,
|
314
|
-
undefined,
|
315
|
-
undefined,
|
316
|
-
undefined,
|
317
|
-
!!checkAssociations);
|
151
|
+
|
152
|
+
isDirty: function (checkAssociations) {
|
153
|
+
return this._backupStore && !can.Object.same(this._attrs(), this._backupStore, undefined, undefined, undefined, !! checkAssociations);
|
318
154
|
},
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
* @parent can.Observe.backup
|
323
|
-
*
|
324
|
-
* `observe.restore([restoreAssociations])` restores the observe to the state of the last time
|
325
|
-
* [can.Observe.prototype.backup] was called if [can.Observe.prototype.isDirty]
|
326
|
-
* returns true. If you pass true, _restore_ will also check and restore all nested properties
|
327
|
-
* and [can.Model] associations.
|
328
|
-
*
|
329
|
-
* var recipe = new can.Observe({
|
330
|
-
* name : 'Pancakes',
|
331
|
-
* ingredients : [{
|
332
|
-
* name : "eggs",
|
333
|
-
* amount : '1'
|
334
|
-
* }, {
|
335
|
-
* name : "flour",
|
336
|
-
* amount : '1 cup'
|
337
|
-
* }, {
|
338
|
-
* name : "milk",
|
339
|
-
* amount : '1 1/4 cup'
|
340
|
-
* }]});
|
341
|
-
*
|
342
|
-
* recipe.backup();
|
343
|
-
*
|
344
|
-
* // Change the attribute of a nested observe
|
345
|
-
* recipe.attr('ingredients.0.amount', '2');
|
346
|
-
* recipe.attr('name', 'Eggcakes');
|
347
|
-
* recipe.attr('name') // -> Eggcakes
|
348
|
-
* recipe.attr('ingredients.0.amount') // -> 2
|
349
|
-
* recipe.restore(true);
|
350
|
-
* recipe.attr('name') // -> Pancakes
|
351
|
-
* recipe.attr('ingredients.0.amount') // -> 1
|
352
|
-
*
|
353
|
-
* @param {Boolean} [restoreAssociations] Whether nested objects should also
|
354
|
-
* be restored or not. Defaults to false.
|
355
|
-
* @return {can.Observe} The observe instance
|
356
|
-
*/
|
357
|
-
restore: function(restoreAssociations) {
|
155
|
+
|
156
|
+
|
157
|
+
restore: function (restoreAssociations) {
|
358
158
|
var props = restoreAssociations ? this._backupStore : flatProps(this._backupStore)
|
359
|
-
|
360
|
-
if(this.isDirty(restoreAssociations)){
|
361
|
-
this._attrs(props);
|
159
|
+
|
160
|
+
if (this.isDirty(restoreAssociations)) {
|
161
|
+
this._attrs(props);
|
362
162
|
}
|
363
|
-
|
163
|
+
|
364
164
|
return this;
|
365
165
|
}
|
366
|
-
|
367
|
-
|
368
|
-
|
166
|
+
|
167
|
+
})
|
168
|
+
|
169
|
+
|
170
|
+
})(can, this);
|