sproutcore 0.9.14 → 0.9.15
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/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().
|