sproutcore 0.9.2 → 0.9.3
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 +33 -0
- data/Manifest.txt +3 -14
- data/clients/sc_docs/controllers/docs.js +1 -0
- data/clients/sc_docs/core.js +1 -1
- data/clients/sc_test_runner/controllers/runner.js +5 -0
- data/clients/sc_test_runner/core.js +1 -1
- data/frameworks/sproutcore/english.lproj/core.css +41 -0
- data/frameworks/sproutcore/english.lproj/theme.css +20 -0
- data/frameworks/sproutcore/foundation/animator.js +11 -2
- data/frameworks/sproutcore/foundation/date.js +2 -2
- data/frameworks/sproutcore/foundation/object.js +2 -2
- data/frameworks/sproutcore/foundation/server.js +4 -3
- data/frameworks/sproutcore/foundation/set.js +1 -1
- data/frameworks/sproutcore/foundation/unittest.js +12 -9
- data/frameworks/sproutcore/lib/collection_view.rb +1 -0
- data/frameworks/sproutcore/lib/core_views.rb +4 -0
- data/frameworks/sproutcore/mixins/editable.js +144 -0
- data/frameworks/sproutcore/mixins/inline_editor_delegate.js +72 -0
- data/frameworks/sproutcore/mixins/observable.js +45 -16
- data/frameworks/sproutcore/mixins/scrollable.js +0 -1
- data/frameworks/sproutcore/tests/controllers/controller.rhtml +12 -12
- data/frameworks/sproutcore/tests/controllers/object.rhtml +2 -2
- data/frameworks/sproutcore/views/collection/collection.js +122 -68
- data/frameworks/sproutcore/views/collection/source_list.js +5 -0
- data/frameworks/sproutcore/views/field/text_field.js +7 -1
- data/frameworks/sproutcore/views/inline_text_field.js +397 -0
- data/frameworks/sproutcore/views/label.js +78 -68
- data/frameworks/sproutcore/views/list_item.js +184 -31
- data/frameworks/sproutcore/views/view.js +41 -9
- data/generators/client/templates/core.js +1 -1
- data/generators/client/templates/english.lproj/body.css +74 -0
- data/generators/framework/templates/core.js +1 -1
- data/lib/sproutcore/version.rb +1 -1
- metadata +5 -16
- data/clients/view_builder/builders/builder.js +0 -339
- data/clients/view_builder/builders/button.js +0 -81
- data/clients/view_builder/controllers/document.js +0 -21
- data/clients/view_builder/core.js +0 -19
- data/clients/view_builder/english.lproj/body.css +0 -77
- data/clients/view_builder/english.lproj/body.rhtml +0 -41
- data/clients/view_builder/english.lproj/controls.css +0 -0
- data/clients/view_builder/english.lproj/strings.js +0 -14
- data/clients/view_builder/main.js +0 -38
- data/clients/view_builder/tests/controllers/document.rhtml +0 -20
- data/clients/view_builder/tests/views/builder.rhtml +0 -20
- data/clients/view_builder/views/builder.js +0 -23
- data/frameworks/sproutcore/english.lproj/inline_text_editor.css +0 -21
- data/frameworks/sproutcore/views/inline_text_editor.js +0 -96
@@ -0,0 +1,72 @@
|
|
1
|
+
// ========================================================================
|
2
|
+
// SproutCore
|
3
|
+
// copyright 2006-2008 Sprout Systems, Inc.
|
4
|
+
// ========================================================================
|
5
|
+
|
6
|
+
/**
|
7
|
+
@namespace
|
8
|
+
|
9
|
+
The inline editor delegate receives notifications from the inline text
|
10
|
+
editor before, during, and after the user completes inline editing.
|
11
|
+
|
12
|
+
The inline editor delegate is used by views that work with the inline
|
13
|
+
editor. You may need to implement this protocol if you want to
|
14
|
+
use the inline editor in your own custom views.
|
15
|
+
|
16
|
+
@since SproutCore 1.0
|
17
|
+
*/
|
18
|
+
SC.InlineEditorDelegate = {
|
19
|
+
|
20
|
+
/**
|
21
|
+
Called just before the inline edit displays itself but after it has been
|
22
|
+
configured for display.
|
23
|
+
|
24
|
+
You can use this method to make last minute changes to the display of
|
25
|
+
the inline editor or to collect its value.
|
26
|
+
|
27
|
+
@param inlineEditor {SC.InlineTextFieldView} The inline editor.
|
28
|
+
@returns {void}
|
29
|
+
*/
|
30
|
+
inlineEditorWillBeginEditing: function(inlineEditor) {},
|
31
|
+
|
32
|
+
/**
|
33
|
+
Called just after an inline editor displays itself.
|
34
|
+
|
35
|
+
You can use this method to perform any hiding or other view changes
|
36
|
+
you need to perform on your own view to make room for the new editor.
|
37
|
+
|
38
|
+
Note tht editors are placed over the top of views in the page, not
|
39
|
+
inside of them from a DOM perspective.
|
40
|
+
|
41
|
+
@param inlineEditor {SC.InlineTextFieldView} The inline editor.
|
42
|
+
@returns {void}
|
43
|
+
*/
|
44
|
+
inlineEditorDidBeginEditing: function(inlineEditor) {},
|
45
|
+
|
46
|
+
/**
|
47
|
+
Called just before an inline editor tries to end editing and hide
|
48
|
+
itself.
|
49
|
+
|
50
|
+
You can use this method to control whether the inline editor will
|
51
|
+
actually be allowed to end editing. For example, you might disallow
|
52
|
+
the editor to end editing if the new value fails validation.
|
53
|
+
|
54
|
+
@param inlineEditor {SC.InlineTextFieldView} the inline editor
|
55
|
+
@param finalValue {Object} the final value
|
56
|
+
@returns {Boolean} YES to allow the editor to end editing.
|
57
|
+
*/
|
58
|
+
inlineEditorShouldEndEditing: function(inlineEditor, finalValue) {
|
59
|
+
return YES ;
|
60
|
+
},
|
61
|
+
|
62
|
+
/**
|
63
|
+
Called just after the inline editor has ended editing. You can use this
|
64
|
+
method to save the final value of the inline editor and to perform any
|
65
|
+
other cleanup you need to do.
|
66
|
+
|
67
|
+
@param inlineEditor {SC.InlineTextFieldView} the inline editor
|
68
|
+
@param finalValue {Object} the final value
|
69
|
+
@returns {void}
|
70
|
+
*/
|
71
|
+
inlineEditorDidEndEditing: function(inlineEditor, finalValue) {}
|
72
|
+
};
|
@@ -6,9 +6,11 @@
|
|
6
6
|
/**
|
7
7
|
@namespace
|
8
8
|
|
9
|
-
Key-Value
|
10
|
-
|
11
|
-
|
9
|
+
Key-Value-Observing (KVO) simply allows one object to observe changes to a
|
10
|
+
property on another object. It is one of the fundamental ways that models,
|
11
|
+
controllers and views communicate with each other in a SproutCore
|
12
|
+
application. Any object that has this module applied to it can be used in
|
13
|
+
KVO-operations.
|
12
14
|
|
13
15
|
This module is applied automatically to all objects that inherit from
|
14
16
|
SC.Object, which includes most objects bundled with the SproutCore
|
@@ -16,21 +18,22 @@
|
|
16
18
|
but you will use the features provided by this module frequently, so it is
|
17
19
|
important to understand how to use it.
|
18
20
|
|
19
|
-
h2.
|
21
|
+
h2. Enabling Key Value Observing
|
20
22
|
|
21
|
-
|
22
|
-
property on
|
23
|
-
|
23
|
+
With KVO, you can write functions that will be called automatically whenever
|
24
|
+
a property on a particular object changes. You can use this feature to
|
25
|
+
reduce the amount of "glue code" that you often write to tie the various
|
26
|
+
parts of your application together.
|
24
27
|
|
25
|
-
|
26
|
-
properties. Instead of writing:
|
28
|
+
To use KVO, just use the KVO-aware methods get() and set() to access
|
29
|
+
properties instead of accessing properties directly. Instead of writing:
|
27
30
|
|
28
31
|
{{{
|
29
32
|
var aName = contact.firstName ;
|
30
33
|
contact.firstName = 'Charles' ;
|
31
34
|
}}}
|
32
|
-
|
33
|
-
|
35
|
+
|
36
|
+
use:
|
34
37
|
|
35
38
|
{{{
|
36
39
|
var aName = contact.get('firstName') ;
|
@@ -40,8 +43,36 @@
|
|
40
43
|
get() and set() work just like the normal "dot operators" provided by
|
41
44
|
JavaScript but they provide you with much more power, including not only
|
42
45
|
observing but computed properties as well.
|
46
|
+
|
47
|
+
h2. Observing Property Changes
|
48
|
+
|
49
|
+
You typically observe property changes simply by adding the observes()
|
50
|
+
call to the end of your method declarations in classes that you write. For
|
51
|
+
example:
|
52
|
+
|
53
|
+
{{{
|
54
|
+
SC.Object.create({
|
55
|
+
valueObserver: function() {
|
56
|
+
// Executes whenever the "Value" property changes
|
57
|
+
}.observes('value')
|
58
|
+
}) ;
|
59
|
+
}}}
|
60
|
+
|
61
|
+
Although this is the most common way to add an observer, this capability is
|
62
|
+
actually built into the SC.Object class on top of two methods defined in
|
63
|
+
this mixin called addObserver() and removeObserver(). You can use these two
|
64
|
+
methods to add and remove observers yourself if you need to do so at run
|
65
|
+
time.
|
66
|
+
|
67
|
+
To add an observer for a property, just call:
|
68
|
+
|
69
|
+
{{{
|
70
|
+
object.addObserver('propertyKey', targetObject, targetAction) ;
|
71
|
+
}}}
|
72
|
+
|
73
|
+
This will call the 'targetAction' method on the targetObject to be called
|
74
|
+
whenever the value of the propertyKey changes.
|
43
75
|
|
44
|
-
INCOMPLETE
|
45
76
|
|
46
77
|
*/
|
47
78
|
SC.Observable = {
|
@@ -674,9 +705,7 @@ SC.NotificationQueue = {
|
|
674
705
|
this._flushing = false ;
|
675
706
|
|
676
707
|
if (this.queue.length > 0) {
|
677
|
-
|
708
|
+
SC.NotificationQueue.flush.invokeLater(SC.NotificationQueue, 1) ;
|
678
709
|
}
|
679
|
-
}
|
680
|
-
|
681
|
-
_reflush: function() { SC.NotificationQueue.flush(); }
|
710
|
+
}
|
682
711
|
} ;
|
@@ -135,16 +135,16 @@ Test.context("Chained SC.Controllers", {
|
|
135
135
|
this.root.discardChanges() ;
|
136
136
|
this.child.get('hasChanges').shouldEqual(NO) ;
|
137
137
|
},
|
138
|
-
|
138
|
+
|
139
139
|
"root.hasChanges should be FALSE after child.commit if root DOES NOT have other changes": function() {
|
140
140
|
// edit child only
|
141
141
|
this.child.editorDidChange() ;
|
142
142
|
this.root.get('hasChanges').shouldEqual(YES) ;
|
143
|
-
|
143
|
+
|
144
144
|
this.child.commitChanges() ;
|
145
145
|
this.root.get('hasChanges').shouldEqual(NO) ;
|
146
146
|
},
|
147
|
-
|
147
|
+
|
148
148
|
"root.hasChanges should be TRUE after child.commit if root DOES have other changes": function() {
|
149
149
|
// edit child and root
|
150
150
|
this.child.editorDidChange() ;
|
@@ -154,7 +154,7 @@ Test.context("Chained SC.Controllers", {
|
|
154
154
|
this.child.commitChanges() ;
|
155
155
|
this.root.get('hasChanges').shouldEqual(YES) ;
|
156
156
|
},
|
157
|
-
|
157
|
+
|
158
158
|
"root.hasChanges should be FALSE after child.discard if root DOES NOT have other changes": function() {
|
159
159
|
// edit child only
|
160
160
|
this.child.editorDidChange() ;
|
@@ -173,8 +173,8 @@ Test.context("Chained SC.Controllers", {
|
|
173
173
|
this.child.discardChanges() ;
|
174
174
|
this.root.get('hasChanges').shouldEqual(YES) ;
|
175
175
|
},
|
176
|
-
|
177
|
-
|
176
|
+
|
177
|
+
|
178
178
|
"child.hasChanges should be TRUE if another child cannot commit": function() {
|
179
179
|
// edit child and child2
|
180
180
|
this.child.editorDidChange() ;
|
@@ -191,7 +191,7 @@ Test.context("Chained SC.Controllers", {
|
|
191
191
|
this.child.get('hasChanges').shouldEqual(YES) ;
|
192
192
|
this.root.get('hasChanges').shouldEqual(YES) ;
|
193
193
|
},
|
194
|
-
|
194
|
+
|
195
195
|
"child.hasChanges should be TRUE if another child cannot discard": function() {
|
196
196
|
// edit child and child2
|
197
197
|
this.child.editorDidChange() ;
|
@@ -208,12 +208,12 @@ Test.context("Chained SC.Controllers", {
|
|
208
208
|
this.child.get('hasChanges').shouldEqual(YES) ;
|
209
209
|
this.root.get('hasChanges').shouldEqual(YES) ;
|
210
210
|
},
|
211
|
-
|
211
|
+
|
212
212
|
"root.hasChanges should be TRUE if any child fails to commit": function() {
|
213
213
|
// NOTE: Commits are not atomic. IN this case, child2 fails while child1 succeeds.
|
214
214
|
// the hasChanges state of child2 and root must both be TRUE in this case, but
|
215
215
|
// child1's state is undefined. It may have commited or it may not.
|
216
|
-
|
216
|
+
|
217
217
|
this.child.editorDidChange() ;
|
218
218
|
this.child2.editorDidChange() ;
|
219
219
|
this.child2.isCommitSuccessful = NO ;
|
@@ -222,12 +222,12 @@ Test.context("Chained SC.Controllers", {
|
|
222
222
|
this.root.get('hasChanges').shouldEqual(YES) ;
|
223
223
|
this.child2.get('hasChanges').shouldEqual(YES) ;
|
224
224
|
},
|
225
|
-
|
225
|
+
|
226
226
|
"root.hasChanges should be TRUE if any child fails to discard": function() {
|
227
227
|
// NOTE: Commits are not atomic. IN this case, child2 fails while child1 succeeds.
|
228
228
|
// the hasChanges state of child2 and root must both be TRUE in this case, but
|
229
229
|
// child1's state is undefined. It may have commited or it may not.
|
230
|
-
|
230
|
+
|
231
231
|
this.child.editorDidChange() ;
|
232
232
|
this.child2.editorDidChange() ;
|
233
233
|
this.child2.isDiscardSuccessful = NO ;
|
@@ -236,7 +236,7 @@ Test.context("Chained SC.Controllers", {
|
|
236
236
|
this.root.get('hasChanges').shouldEqual(YES) ;
|
237
237
|
this.child2.get('hasChanges').shouldEqual(YES) ;
|
238
238
|
},
|
239
|
-
|
239
|
+
|
240
240
|
"child.commitChangesImmediately should be inherited from the root": function()
|
241
241
|
{
|
242
242
|
var Klass = SC.Controller.extend({ commitChangesImmediately: NO });
|
@@ -86,7 +86,7 @@ Test.context("SC.ObjectController", {
|
|
86
86
|
this.c.get('value').shouldEqualEnum([0,1]) ;
|
87
87
|
this.c.get('flag').shouldEqualEnum([YES, NO]) ;
|
88
88
|
|
89
|
-
// get('array').shouldEqual
|
89
|
+
// get('array').shouldEqual() [ [0,0,0], [1,1,1] ];
|
90
90
|
var ar = this.c.get('array') ;
|
91
91
|
ar.length.shouldEqual(2) ;
|
92
92
|
ar[0].shouldEqualEnum([0,0,0]) ;
|
@@ -244,7 +244,7 @@ Test.context("SC.ObjectController", {
|
|
244
244
|
this.c.get('value').shouldEqualEnum([0,1]) ;
|
245
245
|
this.c.get('flag').shouldEqualEnum([YES, NO]) ;
|
246
246
|
|
247
|
-
// get('array').shouldEqual: [ [0,0,0], [1,1,1] ];
|
247
|
+
// get('array').shouldEqual(): [ [0,0,0], [1,1,1] ];
|
248
248
|
var ar = this.c.get('array') ;
|
249
249
|
ar.length.shouldEqual(2) ;
|
250
250
|
ar[0].shouldEqualEnum([0,0,0]) ;
|
@@ -186,11 +186,11 @@ SC.CollectionView = SC.View.extend(
|
|
186
186
|
Trigger the action method on a single click.
|
187
187
|
|
188
188
|
Normally, clicking on an item view in a collection will select the content
|
189
|
-
object and double clicking will trigger the action method on the
|
190
|
-
view.
|
189
|
+
object and double clicking will trigger the action method on the
|
190
|
+
collection view.
|
191
191
|
|
192
|
-
If you set this property to true, then clicking on a view will both select
|
193
|
-
(if isSelected is true) and trigger the action method.
|
192
|
+
If you set this property to true, then clicking on a view will both select
|
193
|
+
it (if isSelected is true) and trigger the action method.
|
194
194
|
|
195
195
|
Use this if you are using the collection view as a menu of items.
|
196
196
|
|
@@ -206,9 +206,9 @@ SC.CollectionView = SC.View.extend(
|
|
206
206
|
passed property key. The exampleGroupView will be used to display the
|
207
207
|
items in groups.
|
208
208
|
|
209
|
-
If this property is set, you MUST ensure the items in the content array
|
210
|
-
already sorted by the group key. Otherwise item view groups might
|
211
|
-
than once.
|
209
|
+
If this property is set, you MUST ensure the items in the content array
|
210
|
+
are already sorted by the group key. Otherwise item view groups might
|
211
|
+
appear more than once.
|
212
212
|
|
213
213
|
@type {String}
|
214
214
|
*/
|
@@ -217,25 +217,25 @@ SC.CollectionView = SC.View.extend(
|
|
217
217
|
/**
|
218
218
|
The view class to use when creating new item views.
|
219
219
|
|
220
|
-
The collection view will automatically create an instance of the view
|
221
|
-
you set here for each item in its content array. You should provide
|
222
|
-
subclass for this property to display the type of content you
|
220
|
+
The collection view will automatically create an instance of the view
|
221
|
+
class you set here for each item in its content array. You should provide
|
222
|
+
your own subclass for this property to display the type of content you
|
223
|
+
want.
|
223
224
|
|
224
225
|
For best results, the view you set here should understand the following
|
225
226
|
properties:
|
226
227
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
isSelected: True if the view should appear selected
|
231
|
-
}}}
|
228
|
+
- *content* The content object from the content array your view should display
|
229
|
+
- *isEnabled* True if the view should appear enabled
|
230
|
+
- *isSelected* True if the view should appear selected
|
232
231
|
|
233
|
-
In general you do not want your child views to actually respond to mouse
|
234
|
-
keyboard events themselves. It is better to let the collection view
|
232
|
+
In general you do not want your child views to actually respond to mouse
|
233
|
+
and keyboard events themselves. It is better to let the collection view
|
234
|
+
do that.
|
235
235
|
|
236
|
-
If you do implement your own event handlers such as mouseDown or mouseUp,
|
237
|
-
should be sure to actually call the same method on the collection view
|
238
|
-
give it the chance to perform its own selection housekeeping.
|
236
|
+
If you do implement your own event handlers such as mouseDown or mouseUp,
|
237
|
+
you should be sure to actually call the same method on the collection view
|
238
|
+
to give it the chance to perform its own selection housekeeping.
|
239
239
|
|
240
240
|
@type {SC.View}
|
241
241
|
*/
|
@@ -245,21 +245,21 @@ SC.CollectionView = SC.View.extend(
|
|
245
245
|
The view class to use when displaying item views in groups.
|
246
246
|
|
247
247
|
If the groupBy property is not null, then the collection view will create
|
248
|
-
an instance of this view class with the item views that belong to the
|
249
|
-
as child nodes for each distinct group value it encounters.
|
248
|
+
an instance of this view class with the item views that belong to the
|
249
|
+
group as child nodes for each distinct group value it encounters.
|
250
250
|
|
251
251
|
Your groupView should have two outlets:
|
252
252
|
|
253
253
|
{{{
|
254
|
-
labelView: The view to display the group label. The group value will be
|
255
|
-
as the content property of this view.
|
254
|
+
labelView: The view to display the group label. The group value will be
|
255
|
+
set as the content property of this view.
|
256
256
|
|
257
|
-
itemView: This is the view the item views will be added to as children
|
258
|
-
this view.
|
257
|
+
itemView: This is the view the item views will be added to as children
|
258
|
+
to this view.
|
259
259
|
}}}
|
260
260
|
|
261
|
-
If groupBy is null, then this property will not be used. The default
|
262
|
-
provided here simply displays the group value in an H1 tag.
|
261
|
+
If groupBy is null, then this property will not be used. The default
|
262
|
+
class provided here simply displays the group value in an H1 tag.
|
263
263
|
|
264
264
|
@type {SC.View}
|
265
265
|
*/
|
@@ -271,20 +271,21 @@ SC.CollectionView = SC.View.extend(
|
|
271
271
|
}),
|
272
272
|
|
273
273
|
/**
|
274
|
-
Invoked when the user double clicks on an item (or single clicks of
|
274
|
+
Invoked when the user double clicks on an item (or single clicks of
|
275
|
+
actOnSelect is true)
|
275
276
|
|
276
277
|
Set this to the name of the action you want to send down the
|
277
|
-
responder chain when the user double clicks on an item (or single clicks
|
278
|
-
actOnSelect is true). You can optionally specify a specific target as
|
279
|
-
using the target property.
|
278
|
+
responder chain when the user double clicks on an item (or single clicks
|
279
|
+
if actOnSelect is true). You can optionally specify a specific target as
|
280
|
+
well using the target property.
|
280
281
|
|
281
282
|
If you do not specify an action, then the collection view will also try to
|
282
283
|
invoke the action named on the target item view.
|
283
284
|
|
284
|
-
Older versions of SproutCore expected the action property to contain an
|
285
|
-
function that would be run. This format is still supported but is
|
286
|
-
for future use. You should generally use the responder chain
|
287
|
-
action for you.
|
285
|
+
Older versions of SproutCore expected the action property to contain an
|
286
|
+
actual function that would be run. This format is still supported but is
|
287
|
+
deprecated for future use. You should generally use the responder chain
|
288
|
+
to handle your action for you.
|
288
289
|
|
289
290
|
@type {String}
|
290
291
|
*/
|
@@ -293,10 +294,10 @@ SC.CollectionView = SC.View.extend(
|
|
293
294
|
/**
|
294
295
|
Optional target to send the action to when the user double clicks.
|
295
296
|
|
296
|
-
If you set the action property to the name of an action, you can
|
297
|
-
specify the target object you want the action to be sent to.
|
298
|
-
either an actual object or a property path that will resolve
|
299
|
-
the time that the action is invoked.
|
297
|
+
If you set the action property to the name of an action, you can
|
298
|
+
optionally specify the target object you want the action to be sent to.
|
299
|
+
This can be either an actual object or a property path that will resolve
|
300
|
+
to an object at the time that the action is invoked.
|
300
301
|
|
301
302
|
This property is ignored if you use the deprecated approach of making the
|
302
303
|
action property a function.
|
@@ -309,7 +310,8 @@ SC.CollectionView = SC.View.extend(
|
|
309
310
|
Set to true whenever the content changes and remains true until
|
310
311
|
the content has been rerendered.
|
311
312
|
|
312
|
-
You can also set this to true yourself to be notified when it is
|
313
|
+
You can also set this to true yourself to be notified when it is
|
314
|
+
completed.
|
313
315
|
*/
|
314
316
|
isDirty: false,
|
315
317
|
|
@@ -355,8 +357,8 @@ SC.CollectionView = SC.View.extend(
|
|
355
357
|
The CollectionView will use this property to support keyboard navigation
|
356
358
|
using the arrow keys.
|
357
359
|
|
358
|
-
If your collection view is simply a vertical list of items then you do not
|
359
|
-
to edit this property.
|
360
|
+
If your collection view is simply a vertical list of items then you do not
|
361
|
+
need to edit this property.
|
360
362
|
*/
|
361
363
|
itemsPerRow: 1,
|
362
364
|
|
@@ -770,13 +772,15 @@ SC.CollectionView = SC.View.extend(
|
|
770
772
|
},
|
771
773
|
|
772
774
|
/**
|
773
|
-
Update the selection state for the item views to reflect the selection
|
775
|
+
Update the selection state for the item views to reflect the selection
|
776
|
+
array.
|
774
777
|
|
775
|
-
This will update the isSelected property of all item views so that only
|
776
|
-
representing content objects found in the selection array are
|
778
|
+
This will update the isSelected property of all item views so that only
|
779
|
+
those representing content objects found in the selection array are
|
780
|
+
selected.
|
777
781
|
|
778
|
-
This method is called automatically whenever your content or selection
|
779
|
-
changed. You should not need to call or override it often.
|
782
|
+
This method is called automatically whenever your content or selection
|
783
|
+
properties changed. You should not need to call or override it often.
|
780
784
|
*/
|
781
785
|
updateSelectionStates: function() {
|
782
786
|
if (!this._itemViews) return ;
|
@@ -1275,12 +1279,15 @@ SC.CollectionView = SC.View.extend(
|
|
1275
1279
|
|
1276
1280
|
/**
|
1277
1281
|
Select one or more items before the current selection, optionally
|
1278
|
-
extending the current selection. Also scrolls the selected item into
|
1282
|
+
extending the current selection. Also scrolls the selected item into
|
1283
|
+
view.
|
1279
1284
|
|
1280
1285
|
Selection does not wrap around.
|
1281
1286
|
|
1282
|
-
@param extend {Boolean} (Optional) If true, the selection will be extended
|
1283
|
-
|
1287
|
+
@param extend {Boolean} (Optional) If true, the selection will be extended
|
1288
|
+
instead of replaced. Defaults to false.
|
1289
|
+
@param numberOfItems {Integer} (Optional) The number of previous to be
|
1290
|
+
selected. Defaults to 1
|
1284
1291
|
@returns {void}
|
1285
1292
|
*/
|
1286
1293
|
selectPreviousItem: function(extend, numberOfItems)
|
@@ -1341,8 +1348,10 @@ SC.CollectionView = SC.View.extend(
|
|
1341
1348
|
|
1342
1349
|
Selection does not wrap around.
|
1343
1350
|
|
1344
|
-
@param extend {Boolean} (Optional) If true, the selection will be extended
|
1345
|
-
|
1351
|
+
@param extend {Boolean} (Optional) If true, the selection will be extended
|
1352
|
+
instead of replaced. Defaults to false.
|
1353
|
+
@param numberOfItems {Integer} (Optional) The number of items to be
|
1354
|
+
selected. Defaults to 1.
|
1346
1355
|
@returns {void}
|
1347
1356
|
*/
|
1348
1357
|
selectNextItem: function(extend, numberOfItems)
|
@@ -1398,9 +1407,9 @@ SC.CollectionView = SC.View.extend(
|
|
1398
1407
|
},
|
1399
1408
|
|
1400
1409
|
/**
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1410
|
+
Scroll the rootElement (if needed) to ensure that the item is visible.
|
1411
|
+
@param {SC.Record} record The record to scroll to
|
1412
|
+
@returns {void}
|
1404
1413
|
*/
|
1405
1414
|
scrollToContent: function(record) {
|
1406
1415
|
// find the itemView. if not present, add one.
|
@@ -1414,9 +1423,9 @@ SC.CollectionView = SC.View.extend(
|
|
1414
1423
|
if (itemView) this.scrollToItemView(itemView);
|
1415
1424
|
},
|
1416
1425
|
/**
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1426
|
+
Scroll the rootElement (if needed) to ensure that the item is visible.
|
1427
|
+
@param {SC.View} view The item view to scroll to
|
1428
|
+
@returns {void}
|
1420
1429
|
*/
|
1421
1430
|
scrollToItemView: function( view )
|
1422
1431
|
{
|
@@ -1434,7 +1443,8 @@ SC.CollectionView = SC.View.extend(
|
|
1434
1443
|
current selection.
|
1435
1444
|
|
1436
1445
|
@param items {Array} The item or items to select.
|
1437
|
-
@param extendSelection {Boolean} If true, extends the selection instead of
|
1446
|
+
@param extendSelection {Boolean} If true, extends the selection instead of
|
1447
|
+
replacing it.
|
1438
1448
|
*/
|
1439
1449
|
selectItems: function(items, extendSelection) {
|
1440
1450
|
var base = (extendSelection) ? this.get('selection') : [] ;
|
@@ -1537,7 +1547,7 @@ SC.CollectionView = SC.View.extend(
|
|
1537
1547
|
// Make sure that saved mouseDown state is always reset in case we do
|
1538
1548
|
// not get a paired mouseUp. (Only happens if subclass does not call us
|
1539
1549
|
// like it should)
|
1540
|
-
this._mouseDownAt = this._shouldDeselect =
|
1550
|
+
this._mouseDownAt = this._shouldDeselect =
|
1541
1551
|
this._shouldReselect = this._refreshSelection = false;
|
1542
1552
|
|
1543
1553
|
var mouseDownView = this._mouseDownView = this.itemViewForEvent(ev);
|
@@ -1574,8 +1584,8 @@ SC.CollectionView = SC.View.extend(
|
|
1574
1584
|
selection = this._findSelectionExtendedByShift(selection, mouseDownContent) ;
|
1575
1585
|
this.selectItems(selection) ;
|
1576
1586
|
|
1577
|
-
// If no modifier key was pressed, then clicking on the selected item
|
1578
|
-
// the selection and reselect only the clicked on item.
|
1587
|
+
// If no modifier key was pressed, then clicking on the selected item
|
1588
|
+
// should clear the selection and reselect only the clicked on item.
|
1579
1589
|
} else if (!modifierKeyPressed && isSelected) {
|
1580
1590
|
this._shouldReselect = mouseDownContent;
|
1581
1591
|
|
@@ -1608,12 +1618,33 @@ SC.CollectionView = SC.View.extend(
|
|
1608
1618
|
|
1609
1619
|
} else {
|
1610
1620
|
if (this._shouldDeselect) this.deselectItems(this._shouldDeselect);
|
1611
|
-
if (this._shouldReselect) this.selectItems(this._shouldReselect,false) ;
|
1612
1621
|
|
1613
|
-
//
|
1614
|
-
//
|
1615
|
-
if (this.
|
1622
|
+
// begin editing of an item view IF all of the following is true:
|
1623
|
+
// otherwise, just reselect.
|
1624
|
+
if (this._shouldReselect) {
|
1625
|
+
|
1626
|
+
// - contentValueIsEditable is true
|
1627
|
+
var canEdit = this.get('contentValueIsEditable') ;
|
1628
|
+
|
1629
|
+
// - the user clicked on an item that was already selected
|
1630
|
+
// - is the only item selected
|
1631
|
+
if (canEdit) {
|
1632
|
+
var sel = this.get('selection') ;
|
1633
|
+
canEdit = sel && (sel.get('length') === 1) && (sel.objectAt(0) === this._shouldReselect) ;
|
1634
|
+
}
|
1635
|
+
|
1636
|
+
// - the item view responds to contentHitTest() and returns YES.
|
1637
|
+
// - the item view responds to beginEditing and returns YES.
|
1638
|
+
if (canEdit) {
|
1639
|
+
var itemView = this.itemViewForContent(this._shouldReselect) ;
|
1640
|
+
canEdit = itemView && (!itemView.contentHitTest || itemView.contentHitTest(ev)) ;
|
1641
|
+
canEdit = (canEdit && itemView.beginEditing) ? itemView.beginEditing() : NO ;
|
1642
|
+
}
|
1643
|
+
|
1644
|
+
// if cannot edit, just reselect
|
1645
|
+
if (!canEdit) this.selectItems(this._shouldReselect,false) ;
|
1616
1646
|
}
|
1647
|
+
|
1617
1648
|
this._cleanupMouseDown() ;
|
1618
1649
|
}
|
1619
1650
|
|
@@ -1713,6 +1744,29 @@ SC.CollectionView = SC.View.extend(
|
|
1713
1744
|
},
|
1714
1745
|
|
1715
1746
|
|
1747
|
+
// if content value is editable and we have one item selected, then edit.
|
1748
|
+
// otherwise, invoke action.
|
1749
|
+
insertNewline: function() {
|
1750
|
+
if (this.get('contentValueIsEditable')) {
|
1751
|
+
var sel = this.get('selection') ;
|
1752
|
+
if (sel && sel.get('length') === 1) {
|
1753
|
+
var itemView = this.itemViewForContent(sel.objectAt(0)) ;
|
1754
|
+
if (itemView && itemView.beginEditing) {
|
1755
|
+
this.scrollToItemView(itemView) ;
|
1756
|
+
itemView.beginEditing() ;
|
1757
|
+
}
|
1758
|
+
}
|
1759
|
+
|
1760
|
+
// invoke action!
|
1761
|
+
} else {
|
1762
|
+
var sel = this.get('selection') ;
|
1763
|
+
var itemView = (sel && sel.get('length') === 1) ? this.itemViewForContent(sel.objectAt(0)) : null ;
|
1764
|
+
this._action(itemView, null) ;
|
1765
|
+
}
|
1766
|
+
|
1767
|
+
return YES ; // always handle
|
1768
|
+
},
|
1769
|
+
|
1716
1770
|
// ......................................
|
1717
1771
|
// FIRST RESPONDER
|
1718
1772
|
//
|
@@ -1898,7 +1952,7 @@ SC.CollectionView = SC.View.extend(
|
|
1898
1952
|
if ((Date.now() - this._mouseDownAt) < 123) return true ;
|
1899
1953
|
|
1900
1954
|
// OK, they must be serious, start a drag if possible.
|
1901
|
-
if (this.get('canReorderContent')) {
|
1955
|
+
if (this.get('canReorderContent') && this._mouseDownEvent != null) {
|
1902
1956
|
|
1903
1957
|
// First, get the selection to drag. Drag an array of selected
|
1904
1958
|
// items appearing in this collection, in the order of the
|