sproutcore 0.9.14 → 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +43 -0
- data/Manifest.txt +12 -3
- data/bin/sc-build +19 -3
- data/bin/sc-install +5 -0
- data/bin/sc-remove +5 -0
- data/bin/sc-update +5 -0
- data/frameworks/prototype/prototype.js +267 -230
- data/frameworks/sproutcore/HISTORY +281 -135
- data/frameworks/sproutcore/controllers/array.js +133 -22
- data/frameworks/sproutcore/controllers/collection.js +4 -5
- data/frameworks/sproutcore/controllers/object.js +8 -2
- data/frameworks/sproutcore/core.js +361 -159
- data/frameworks/sproutcore/{foundation → debug}/unittest.js +3 -3
- data/frameworks/sproutcore/english.lproj/detect-browser +1 -1
- data/frameworks/sproutcore/english.lproj/theme.css +2 -2
- data/frameworks/sproutcore/foundation/application.js +6 -1
- data/frameworks/sproutcore/foundation/benchmark.js +37 -11
- data/frameworks/sproutcore/foundation/date.js +1 -1
- data/frameworks/sproutcore/foundation/enumerator.js +105 -0
- data/frameworks/sproutcore/foundation/object.js +19 -20
- data/frameworks/sproutcore/foundation/responder.js +1 -1
- data/frameworks/sproutcore/foundation/set.js +164 -57
- data/frameworks/sproutcore/foundation/string.js +151 -47
- data/frameworks/sproutcore/foundation/utils.js +84 -3
- data/frameworks/sproutcore/lib/collection_view.rb +1 -0
- data/frameworks/sproutcore/license.js +28 -0
- data/frameworks/sproutcore/mixins/array.js +73 -209
- data/frameworks/sproutcore/mixins/delegate_support.js +1 -1
- data/frameworks/sproutcore/mixins/enumerable.js +1006 -0
- data/frameworks/sproutcore/mixins/observable.js +153 -84
- data/frameworks/sproutcore/mixins/selection_support.js +13 -1
- data/frameworks/sproutcore/models/record.js +74 -27
- data/frameworks/sproutcore/models/store.js +7 -3
- data/frameworks/sproutcore/server/rails_server.js +82 -0
- data/frameworks/sproutcore/server/rest_server.js +178 -0
- data/frameworks/sproutcore/{foundation → server}/server.js +101 -48
- data/frameworks/sproutcore/tests/core/guidFor.rhtml +114 -0
- data/frameworks/sproutcore/tests/foundation/array.rhtml +6 -7
- data/frameworks/sproutcore/tests/foundation/set.rhtml +254 -0
- data/frameworks/sproutcore/tests/mixins/enumerable.rhtml +421 -0
- data/frameworks/sproutcore/tests/mixins/observable.rhtml +127 -0
- data/frameworks/sproutcore/tests/models/model.rhtml +23 -22
- data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +2 -2
- data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +112 -109
- data/frameworks/sproutcore/tests/views/view/frame.rhtml +91 -88
- data/frameworks/sproutcore/validators/date.js +1 -7
- data/frameworks/sproutcore/views/collection/collection.js +7 -2
- data/frameworks/sproutcore/views/list_item.js +141 -3
- data/frameworks/sproutcore/views/split.js +14 -11
- data/frameworks/sproutcore/views/view.js +9 -6
- data/lib/sproutcore/build_tools/html_builder.rb +19 -3
- data/lib/sproutcore/build_tools/resource_builder.rb +9 -3
- data/lib/sproutcore/bundle.rb +21 -0
- data/lib/sproutcore/bundle_manifest.rb +64 -20
- data/lib/sproutcore/helpers/capture_helper.rb +2 -2
- data/lib/sproutcore/library.rb +33 -9
- data/lib/sproutcore/merb/bundle_controller.rb +16 -5
- data/lib/sproutcore/version.rb +1 -1
- data/lib/sproutcore/view_helpers.rb +1 -1
- data/{sc-config.rb → sc-config} +5 -2
- metadata +24 -5
@@ -24,6 +24,7 @@ until you call commitChanges().
|
|
24
24
|
SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
25
25
|
/** @scope SC.ArrayController.prototype */
|
26
26
|
{
|
27
|
+
|
27
28
|
/**
|
28
29
|
If YES the will return controllers for content objects.
|
29
30
|
|
@@ -44,23 +45,113 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
44
45
|
arrangedObjects: function() { return this; }.property('content'),
|
45
46
|
|
46
47
|
/**
|
47
|
-
The
|
48
|
-
|
48
|
+
The content array managed by this controller.
|
49
|
+
|
50
|
+
In general you can treat an instance of ArrayController as if it were
|
51
|
+
the array held in this property. Any changes you make to the controller
|
52
|
+
that are not specifically implemented in the controller will pass through
|
53
|
+
to the Array.
|
54
|
+
|
55
|
+
Also if you set commitsChangesImmediately to false, the controller will
|
56
|
+
buffer changes against this.
|
57
|
+
|
58
|
+
@property
|
49
59
|
@type {Array}
|
50
60
|
*/
|
51
61
|
content: null,
|
52
62
|
contentBindingDefault: SC.Binding.Multiple,
|
63
|
+
|
64
|
+
/**
|
65
|
+
Set to true if the controller has any content, even an empty array.
|
66
|
+
*/
|
67
|
+
hasContent: function() {
|
68
|
+
return this.get('content') != null ;
|
69
|
+
}.property('content'),
|
53
70
|
|
54
71
|
/**
|
55
72
|
Set to true if you want objects removed from the array to also be
|
56
73
|
deleted. This is a convenient way to manage lists of items owned
|
57
74
|
by a parent record object.
|
58
75
|
|
76
|
+
Note that even if this is set to NO, calling destroyObject() instead of
|
77
|
+
removeObject() will still destroy the object in question as well as
|
78
|
+
removing it from the parent array.
|
79
|
+
|
59
80
|
@field
|
60
81
|
@type {Boolean}
|
61
82
|
*/
|
62
83
|
destroyOnRemoval: NO,
|
84
|
+
|
85
|
+
/**
|
86
|
+
Defines the default class to use when creating new content.
|
63
87
|
|
88
|
+
This property should either contains a class or a string that resolves
|
89
|
+
to a class that responds to the newRecord() method.
|
90
|
+
|
91
|
+
@property
|
92
|
+
@type {Class}
|
93
|
+
*/
|
94
|
+
exampleContentObject: null,
|
95
|
+
|
96
|
+
/**
|
97
|
+
Creates a new record instance and adds it to the end of the current array.
|
98
|
+
|
99
|
+
This method works just like insertNewObjectAt() but always appends.
|
100
|
+
|
101
|
+
@param attributes {Hash} optional hash of attributes to pass to the new obejct.
|
102
|
+
@param objectType {Class} optional class of object to create.
|
103
|
+
@returns {Object} the newly created object (also added to the array)
|
104
|
+
*/
|
105
|
+
newObject: function(attributes, objectType) {
|
106
|
+
return this.insertNewObjectAt(null, attributes, objectType) ;
|
107
|
+
},
|
108
|
+
|
109
|
+
/**
|
110
|
+
Creates a new content object and inserts it at the passed index or appends
|
111
|
+
it at the end of the array if you pass null.
|
112
|
+
|
113
|
+
This method takes an optional hash of attributes which will be set on
|
114
|
+
the new record. You can also pass an optional objectType. If you do
|
115
|
+
not pass the objectType, you must instead set the exampleContentObject to
|
116
|
+
the class of the object you want to use. The object can be of any type
|
117
|
+
but it must respond to the newRecord() method.
|
118
|
+
|
119
|
+
Objects created using this method will be destroyed automatically if you
|
120
|
+
have set commitsChangesImmediately to false and call discardChanges().
|
121
|
+
|
122
|
+
@param index {Number} the index to insert at or null to append.
|
123
|
+
@param attributes {Hash} optional hash of attributes to pass to the new obejct.
|
124
|
+
@param objectType {Class} optional class of object to create.
|
125
|
+
@returns {Object} the newly created object (also added to the array)
|
126
|
+
*/
|
127
|
+
insertNewObjectAt: function(index, attributes, objectType) {
|
128
|
+
|
129
|
+
// compute the objectType
|
130
|
+
if (!objectType) objectType = this.get('exampleContentObject') ;
|
131
|
+
if ($type(objectType) === T_STRING) {
|
132
|
+
objectType = SC.Object.objectForPropertyPath(objectType) ;
|
133
|
+
}
|
134
|
+
if (objectType == null) {
|
135
|
+
throw "Invalid object type was provided" ;
|
136
|
+
}
|
137
|
+
|
138
|
+
if ($type(objectType.newObject) !== T_FUNCTION) {
|
139
|
+
throw "content object type does not support newRecord()" ;
|
140
|
+
}
|
141
|
+
|
142
|
+
// Create a new object...
|
143
|
+
var obj = objectType.newObject(attributes) ;
|
144
|
+
if (!this._createdObjects) this._createdObjects = [] ;
|
145
|
+
this._createdObjects.push(obj) ; // save for discard...
|
146
|
+
|
147
|
+
// Add to array.
|
148
|
+
if (index) {
|
149
|
+
this.insertAt(index, obj) ;
|
150
|
+
} else this.pushObject(obj) ;
|
151
|
+
|
152
|
+
return obj ;
|
153
|
+
},
|
154
|
+
|
64
155
|
/**
|
65
156
|
Watches changes to the content property updates the contentClone.
|
66
157
|
@private
|
@@ -94,7 +185,7 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
94
185
|
|
95
186
|
this.beginPropertyChanges();
|
96
187
|
this.contentCloneReset();
|
97
|
-
this.
|
188
|
+
this.enumerableContentDidChange() ;
|
98
189
|
this.notifyPropertyChange('length') ;
|
99
190
|
this.updateSelectionAfterContentChange();
|
100
191
|
this.endPropertyChanges() ;
|
@@ -140,8 +231,13 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
140
231
|
|
141
232
|
// in case the passed objects are controllers, convert to source objects.
|
142
233
|
var copyIdx = objects.length ;
|
143
|
-
var sourceObjects =
|
144
|
-
|
234
|
+
var sourceObjects = objects ;
|
235
|
+
if (copyIdx > 0) {
|
236
|
+
sourceObjects = [] ;
|
237
|
+
while(--copyIdx >= 0) {
|
238
|
+
sourceObjects[copyIdx] = this._sourceObjectFor(objects[copyIdx]) ;
|
239
|
+
}
|
240
|
+
}
|
145
241
|
|
146
242
|
// create clone of content array if needed
|
147
243
|
var contentClone = this.get('contentClone') ;
|
@@ -165,17 +261,16 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
165
261
|
contentClone.replace(idx, amt, sourceObjects);
|
166
262
|
|
167
263
|
this.editorDidChange() ;
|
168
|
-
this.
|
264
|
+
this.enumerableContentDidChange();
|
169
265
|
this.updateSelectionAfterContentChange();
|
170
266
|
|
171
267
|
return this;
|
172
268
|
},
|
269
|
+
|
173
270
|
/**
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
* The index of the item to return. If idx exceeds the current length,
|
178
|
-
* return null.
|
271
|
+
SC.Array interface implimentation.
|
272
|
+
@param idx {Number} The index of the item to return. If idx exceeds the
|
273
|
+
current length, return null.
|
179
274
|
*/
|
180
275
|
objectAt: function(idx) {
|
181
276
|
var obj = this._getSourceContent() ;
|
@@ -183,9 +278,9 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
183
278
|
return this._objectControllerFor(obj) ;
|
184
279
|
},
|
185
280
|
/**
|
186
|
-
|
187
|
-
|
188
|
-
|
281
|
+
SC.Array interface implimentation.
|
282
|
+
@property
|
283
|
+
@type {integer}
|
189
284
|
*/
|
190
285
|
length: function( key, value ) {
|
191
286
|
var ret = this._getSourceContent() ;
|
@@ -222,14 +317,15 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
222
317
|
|
223
318
|
|
224
319
|
// apply all the changes made to the clone
|
225
|
-
|
226
|
-
|
227
|
-
var
|
228
|
-
|
320
|
+
if (this._changelog) {
|
321
|
+
var changelog = this._changelog ;
|
322
|
+
var max = changelog.length;
|
323
|
+
for(var idx=0;idx<max;idx++) {
|
324
|
+
var change = changelog[idx];
|
325
|
+
content.replace(change.idx, change.amt, change.objects) ;
|
326
|
+
}
|
327
|
+
this._changelog.length = 0 ; // reset changelog
|
229
328
|
}
|
230
|
-
|
231
|
-
// done, flush the changelog
|
232
|
-
this._changelog = [] ;
|
233
329
|
|
234
330
|
// finally, destroy any removed objects if necessary. Make
|
235
331
|
// sure the objects have not been re-added before doing this.
|
@@ -241,9 +337,12 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
241
337
|
obj.destroy() ;
|
242
338
|
}
|
243
339
|
}
|
244
|
-
this._deletions =
|
340
|
+
this._deletions.length = 0; // clear array
|
245
341
|
}
|
246
342
|
|
343
|
+
// changes commited, clear any created objects from the internal array
|
344
|
+
if (this._createdObjects) this._createdObjects.length = 0 ;
|
345
|
+
|
247
346
|
// finish commiting changes.
|
248
347
|
if (content.endPropertyChanges) content.endPropertyChanges();
|
249
348
|
if (content.commitChanges) ret = content.commitChanges();
|
@@ -262,6 +361,18 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
262
361
|
{
|
263
362
|
this.contentCloneReset();
|
264
363
|
this.editorDidClearChanges();
|
364
|
+
|
365
|
+
// if any objects were created before the commit, destroy the objects
|
366
|
+
// and reset the array.
|
367
|
+
if (this._createdObjects && this._createdObjects.length > 0) {
|
368
|
+
var idx = this._createdObjects.length ;
|
369
|
+
while(--idx >= 0) {
|
370
|
+
var obj = this._createdObjects[idx] ;
|
371
|
+
if ($type(obj.destroy) === T_FUNCTION) obj.destroy() ;
|
372
|
+
}
|
373
|
+
this._createdObjects.length = 0 ;
|
374
|
+
}
|
375
|
+
|
265
376
|
return true;
|
266
377
|
},
|
267
378
|
|
@@ -17,8 +17,7 @@ require('controllers/object') ;
|
|
17
17
|
@extends SC.ObjectController
|
18
18
|
*/
|
19
19
|
SC.CollectionController = SC.ObjectController.extend(SC.SelectionSupport,
|
20
|
-
|
21
|
-
{
|
20
|
+
/** @scope SC.CollectionController.prototype */ {
|
22
21
|
|
23
22
|
// ...................................
|
24
23
|
// PROPERTIES
|
@@ -106,7 +105,7 @@ SC.CollectionController = SC.ObjectController.extend(SC.SelectionSupport,
|
|
106
105
|
var content = this.get('content') ;
|
107
106
|
if (!content || !this.get('canEditCollection')) return ; // only if allowed
|
108
107
|
try {
|
109
|
-
objects =
|
108
|
+
objects = SC.$A(arguments).flatten() ;
|
110
109
|
if (content.addRecords) {
|
111
110
|
content.addRecords(objects) ;
|
112
111
|
this.set('selection',(objects) ? objects : []) ;
|
@@ -127,7 +126,7 @@ SC.CollectionController = SC.ObjectController.extend(SC.SelectionSupport,
|
|
127
126
|
var content = this.get('content') ;
|
128
127
|
if (!content || !this.get('canEditCollection')) return ; // only if allowed
|
129
128
|
try {
|
130
|
-
objects =
|
129
|
+
objects = SC.$A(arguments).flatten() ;
|
131
130
|
if (content.removeRecords) {
|
132
131
|
var rec = content.removeRecords(objects) ;
|
133
132
|
var sel = (this.get('selection') || []).without(objects) ;
|
@@ -192,7 +191,7 @@ SC.CollectionController = SC.ObjectController.extend(SC.SelectionSupport,
|
|
192
191
|
// potentially the selection.
|
193
192
|
_recordsObserver: function(target,key,value) {
|
194
193
|
var old = this.get('arrangedObjects') ;
|
195
|
-
value = Array.
|
194
|
+
value = Array.from(target.get(key)) ;
|
196
195
|
|
197
196
|
this.set('arrangedObjects',value.slice()) ;
|
198
197
|
|
@@ -19,8 +19,7 @@ require('controllers/controller') ;
|
|
19
19
|
@extends SC.Controller
|
20
20
|
*/
|
21
21
|
SC.ObjectController = SC.Controller.extend(
|
22
|
-
|
23
|
-
{
|
22
|
+
/** @scope SC.ObjectController.prototype */ {
|
24
23
|
|
25
24
|
// ...............................
|
26
25
|
// PROPERTIES
|
@@ -57,6 +56,13 @@ SC.ObjectController = SC.Controller.extend(
|
|
57
56
|
*/
|
58
57
|
hasMultipleContent: false,
|
59
58
|
|
59
|
+
/**
|
60
|
+
Set to true if the controller has any content, even an empty array.
|
61
|
+
*/
|
62
|
+
hasContent: function() {
|
63
|
+
return this.get('content') != null ;
|
64
|
+
}.property('content'),
|
65
|
+
|
60
66
|
/**
|
61
67
|
Set this property to true and multiple content will be treated like a null
|
62
68
|
value. This will only impact use of get() and set().
|