sproutit-sproutcore 1.0.20090721145281 → 1.0.20090721145282

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/Buildfile +4 -3
  2. data/VERSION.yml +2 -2
  3. data/buildtasks/entry.rake +3 -0
  4. data/buildtasks/manifest.rake +35 -9
  5. data/buildtasks/target.rake +25 -6
  6. data/frameworks/sproutcore/Buildfile +10 -0
  7. data/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +41 -20
  8. data/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +14 -43
  9. data/frameworks/sproutcore/frameworks/datastore/models/record.js +11 -0
  10. data/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +6 -3
  11. data/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +5 -1
  12. data/frameworks/sproutcore/frameworks/datastore/system/query.js +10 -7
  13. data/frameworks/sproutcore/frameworks/datastore/system/record_array.js +19 -20
  14. data/frameworks/sproutcore/frameworks/datastore/system/store.js +126 -93
  15. data/frameworks/sproutcore/frameworks/datastore/tests/data_sources/fixtures.js +9 -3
  16. data/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +6 -1
  17. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/core_methods.js +28 -3
  18. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/destroy.js +13 -5
  19. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/storeDidChangeProperties.js +46 -23
  20. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +29 -5
  21. data/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +13 -4
  22. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +109 -0
  23. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChanges.js +69 -15
  24. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +20 -1
  25. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/dataHashDidChange.js +4 -1
  26. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/find_all.js +56 -6
  27. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +9 -2
  28. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/core_methods.js +45 -2
  29. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/recordDidChange.js +0 -1
  30. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/retrieveRecord.js +53 -6
  31. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/writeDataHash.js +0 -5
  32. data/frameworks/sproutcore/frameworks/desktop/panes/menu.js +47 -27
  33. data/frameworks/sproutcore/frameworks/desktop/system/drag.js +5 -4
  34. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +23 -12
  35. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/render.js +92 -0
  36. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +104 -53
  37. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +2 -0
  38. data/frameworks/sproutcore/frameworks/desktop/views/button.js +4 -3
  39. data/frameworks/sproutcore/frameworks/desktop/views/collection.js +6 -2
  40. data/frameworks/sproutcore/frameworks/desktop/views/list.js +9 -0
  41. data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +2 -2
  42. data/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +3 -3
  43. data/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +9 -1
  44. data/frameworks/sproutcore/frameworks/desktop/views/select_field.js +80 -102
  45. data/frameworks/sproutcore/frameworks/foundation/controllers/array.js +0 -1
  46. data/frameworks/sproutcore/frameworks/foundation/english.lproj/text_field.css +5 -1
  47. data/frameworks/sproutcore/frameworks/foundation/panes/pane.js +8 -1
  48. data/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +0 -1
  49. data/frameworks/sproutcore/frameworks/foundation/system/datetime.js +31 -3
  50. data/frameworks/sproutcore/frameworks/foundation/system/event.js +0 -4
  51. data/frameworks/sproutcore/frameworks/foundation/system/render_context.js +3 -7
  52. data/frameworks/sproutcore/frameworks/foundation/system/request.js +3 -4
  53. data/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +78 -17
  54. data/frameworks/sproutcore/frameworks/foundation/system/utils.js +9 -0
  55. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/single_case.js +2 -2
  56. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_selector.js +2 -2
  57. data/frameworks/sproutcore/frameworks/foundation/tests/system/datetime.js +5 -0
  58. data/frameworks/sproutcore/frameworks/foundation/tests/system/request.js +2 -2
  59. data/frameworks/sproutcore/frameworks/foundation/tests/system/user_defaults.js +1 -4
  60. data/frameworks/sproutcore/frameworks/foundation/tests/validators/validator.js +20 -0
  61. data/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +13 -0
  62. data/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +132 -0
  63. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/isVisibleInWindow.js +6 -3
  64. data/frameworks/sproutcore/frameworks/foundation/validators/validator.js +8 -5
  65. data/frameworks/sproutcore/frameworks/foundation/views/image.js +18 -5
  66. data/frameworks/sproutcore/frameworks/foundation/views/text_field.js +292 -21
  67. data/frameworks/sproutcore/frameworks/foundation/views/view.js +13 -14
  68. data/frameworks/sproutcore/frameworks/mini/license.js +28 -0
  69. data/frameworks/sproutcore/frameworks/runtime/core.js +35 -0
  70. data/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
  71. data/frameworks/sproutcore/frameworks/runtime/system/sparse_array.js +79 -5
  72. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable.js +6 -6
  73. data/frameworks/sproutcore/frameworks/runtime/tests/system/sparse_array.js +53 -0
  74. data/frameworks/sproutcore/frameworks/testing/system/plan.js +4 -0
  75. data/frameworks/sproutcore/frameworks/testing/system/runner.js +1 -1
  76. data/frameworks/sproutcore/themes/standard_theme/english.lproj/radio.css +4 -0
  77. data/gen/design/Buildfile +23 -0
  78. data/gen/design/README +1 -0
  79. data/gen/design/USAGE +10 -0
  80. data/gen/design/templates/english.lproj/@filename@.js +16 -0
  81. data/gen/page/Buildfile +36 -0
  82. data/gen/page/README +1 -0
  83. data/gen/page/USAGE +15 -0
  84. data/gen/page/templates/pages/@target_name@/Buildfile +16 -0
  85. data/gen/page/templates/pages/@target_name@/core.js +22 -0
  86. data/gen/page/templates/pages/@target_name@/english.lproj/body.css +1 -0
  87. data/gen/page/templates/pages/@target_name@/english.lproj/body.rhtml +7 -0
  88. data/gen/page/templates/pages/@target_name@/english.lproj/strings.js +15 -0
  89. data/gen/view/README +1 -1
  90. data/gen/view/USAGE +5 -5
  91. data/lib/sproutcore/builders/base.rb +13 -2
  92. data/lib/sproutcore/builders/html.rb +28 -1
  93. data/lib/sproutcore/builders/minify.rb +84 -18
  94. data/lib/sproutcore/builders/test.rb +2 -1
  95. data/lib/sproutcore/helpers/entry_sorter.rb +16 -1
  96. data/lib/sproutcore/helpers/static_helper.rb +32 -4
  97. data/lib/sproutcore/helpers/tag_helper.rb +65 -0
  98. data/lib/sproutcore/models/manifest.rb +40 -6
  99. data/lib/sproutcore/models/target.rb +12 -3
  100. data/lib/sproutcore/rack/builder.rb +56 -4
  101. data/lib/sproutcore/tools/manifest.rb +1 -0
  102. data/lib/sproutcore/tools/server.rb +1 -0
  103. data/lib/sproutcore/tools.rb +21 -1
  104. data/lib/sproutcore.rb +13 -0
  105. metadata +16 -1
@@ -262,6 +262,7 @@ SC.View = SC.Responder.extend(SC.DelegateSupport,
262
262
  // if the state has changed, update it and notify children
263
263
  if (last !== cur) {
264
264
  this.set('isVisibleInWindow', cur) ;
265
+ this._needsVisibiltyChange = YES ; // update even if we aren't visible
265
266
 
266
267
  var childViews = this.get('childViews'), len = childViews.length, idx;
267
268
  for(idx=0;idx<len;idx++) {
@@ -271,20 +272,14 @@ SC.View = SC.Responder.extend(SC.DelegateSupport,
271
272
  // if we just became visible, update layer + layout if needed...
272
273
  if (cur) {
273
274
  if (this.parentViewDidResize) this.parentViewDidResize();
274
- this.set('layerNeedsUpdate', YES);
275
- this.invokeOnce(this.updateLayerIfNeeded);
276
275
 
277
276
  if (this.get('childViewsNeedLayout')) {
278
277
  this.invokeOnce(this.layoutChildViewsIfNeeded);
279
278
  }
280
-
281
- // if we just became invisible, force an update to hide the layer
282
- } else {
283
- var that = this;
284
- this.set('layerNeedsUpdate', YES);
285
- this.invokeOnce(function() { that.updateLayerIfNeeded(YES); });
286
279
  }
287
280
 
281
+ this.set('layerNeedsUpdate', YES) ;
282
+
288
283
  // if we were firstResponder, resign firstResponder also if no longer
289
284
  // visible.
290
285
  if (!cur && this.get('isFirstResponder')) this.resignFirstResponder();
@@ -670,19 +665,19 @@ SC.View = SC.Responder.extend(SC.DelegateSupport,
670
665
  @returns {SC.View} receiver
671
666
  @test in updateLayer
672
667
  */
673
- updateLayerIfNeeded: function(isVisible) {
674
- if (!isVisible) isVisible = this.get('isVisibleInWindow') ;
675
- if (isVisible && this.get('layerNeedsUpdate')) {
668
+ updateLayerIfNeeded: function() {
669
+ var viz = this.get('isVisibleInWindow') ;
670
+ if ((viz || this._needsVisibiltyChange) && this.get('layerNeedsUpdate')) {
671
+ this._needsVisibiltyChange = NO ;
676
672
  // only update a layer if it already exists
677
673
  if (this.get('layer')) {
678
674
  this.beginPropertyChanges() ;
679
675
  this.set('layerNeedsUpdate', NO) ;
680
676
  this.updateLayer() ;
681
677
  this.endPropertyChanges() ;
682
-
683
- // clear our layerNeedsUpdate flag so we can respond to changes later
684
- } else this.set('layerNeedsUpdate', NO) ;
678
+ }
685
679
  }
680
+ else this.set('layerNeedsUpdate', NO) ;
686
681
  return this ;
687
682
  },
688
683
 
@@ -707,6 +702,7 @@ SC.View = SC.Responder.extend(SC.DelegateSupport,
707
702
  var context = this.renderContext(this.get('layer')) ;
708
703
  this.prepareContext(context, NO) ;
709
704
  context.update() ;
705
+ if (this.didUpdateLayer) this.didUpdateLayer(); // call to update DOM
710
706
  return this ;
711
707
  },
712
708
 
@@ -870,11 +866,14 @@ SC.View = SC.Responder.extend(SC.DelegateSupport,
870
866
  cursor = this.get('cursor') ;
871
867
  if (cursor) context.addClass(cursor.get('className')) ;
872
868
 
869
+ this.beginPropertyChanges() ;
870
+ this.set('layerNeedsUpdate', NO) ;
873
871
  this.render(context, firstTime) ;
874
872
  if (mixins = this.renderMixin) {
875
873
  len = mixins.length;
876
874
  for(idx=0; idx<len; ++idx) mixins[idx].call(this, context, firstTime) ;
877
875
  }
876
+ this.endPropertyChanges() ;
878
877
  },
879
878
 
880
879
  /**
@@ -0,0 +1,28 @@
1
+ /*! @license
2
+ ==========================================================================
3
+ SproutCore -- JavaScript Application Framework
4
+ copyright 2006-2008, Sprout Systems, Inc. and contributors.
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a
7
+ copy of this software and associated documentation files (the "Software"),
8
+ to deal in the Software without restriction, including without limitation
9
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ and/or sell copies of the Software, and to permit persons to whom the
11
+ Software is furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information about SproutCore, visit http://www.sproutcore.com
25
+
26
+
27
+ ==========================================================================
28
+ @license */
@@ -597,6 +597,27 @@ SC.mixin(/** @scope SC */ {
597
597
  }
598
598
 
599
599
  return root ;
600
+ },
601
+
602
+
603
+ // ..........................................................
604
+ // LOCALIZATION SUPPORT
605
+ //
606
+
607
+ /**
608
+ Known loc strings
609
+ */
610
+ STRINGS: {},
611
+
612
+ /**
613
+ This is a simplified handler for installing a bunch of strings. This
614
+ ignores the language name and simply applies the passed strings hash.
615
+
616
+ @param {String} lang the language the strings are for
617
+ @param {Hash} strings hash of strings
618
+ */
619
+ stringsFor: function(lang, strings) {
620
+ SC.mixin(SC.STRINGS, strings);
600
621
  }
601
622
 
602
623
 
@@ -854,3 +875,17 @@ String.prototype.fmt = function() {
854
875
  }) ;
855
876
  };
856
877
 
878
+ /**
879
+ Localizes the string. This will look up the reciever string as a key
880
+ in the current Strings hash. If the key matches, the loc'd value will be
881
+ used. The resulting string will also be passed through fmt() to insert
882
+ any variables.
883
+
884
+ @param args {Object...} optional arguments to interpolate also
885
+ @returns {String} the localized and formatted string.
886
+ */
887
+ String.prototype.loc = function() {
888
+ var str = SC.STRINGS[this] || this;
889
+ return str.fmt.apply(str,arguments) ;
890
+ };
891
+
@@ -834,7 +834,7 @@ SC.Reducers = {
834
834
  */
835
835
  reducedProperty: function(key, value, generateProperty) {
836
836
 
837
- if (key[0] !== '@') return undefined ; // not a reduced property
837
+ if (!key || key.charAt(0) !== '@') return undefined ; // not a reduced property
838
838
 
839
839
  // get the reducer key and the reducer
840
840
  var matches = key.match(/^@([^(]*)(\(([^)]*)\))?$/) ;
@@ -97,6 +97,13 @@ SC.SparseArray = SC.Object.extend(SC.Observable, SC.Enumerable, SC.Array,
97
97
  */
98
98
  rangeWindowSize: 1,
99
99
 
100
+ /*
101
+ This array contains all the start_indexes of ranges requested. This is to
102
+ avoid calling sparseArrayDidRequestRange to often. Indexes are removed and
103
+ added as range requests are completed.
104
+ */
105
+ requestedRangeIndex: [],
106
+
100
107
  /**
101
108
  Returns the object at the specified index. If the value for the index
102
109
  is currently undefined, invokes the didRequestIndex() method to notify
@@ -115,6 +122,37 @@ SC.SparseArray = SC.Object.extend(SC.Observable, SC.Enumerable, SC.Array,
115
122
  return ret ;
116
123
  },
117
124
 
125
+ /**
126
+ Returns the set of indexes that are currently defined on the sparse array.
127
+ If you pass an optional index set, the search will be limited to only
128
+ those indexes. Otherwise this method will return an index set containing
129
+ all of the defined indexes. Currently this can be quite expensive if
130
+ you have a lot of indexes defined.
131
+
132
+ @param {SC.IndexSet} indexes optional from indexes
133
+ @returns {SC.IndexSet} defined indexes
134
+ */
135
+ definedIndexes: function(indexes) {
136
+ var ret = SC.IndexSet.create(),
137
+ content = this._sa_content,
138
+ idx, len;
139
+
140
+ if (!content) return ret.freeze(); // nothing to do
141
+
142
+ if (indexes) {
143
+ indexes.forEach(function(idx) {
144
+ if (content[idx] !== undefined) ret.add(idx);
145
+ });
146
+ } else {
147
+ len = content.length;
148
+ for(idx=0;idx<len;idx++) {
149
+ if (content[idx] !== undefined) ret.add(idx);
150
+ }
151
+ }
152
+
153
+ return ret.freeze();
154
+ },
155
+
118
156
  _TMP_RANGE: {},
119
157
 
120
158
  /**
@@ -122,6 +160,8 @@ SC.SparseArray = SC.Object.extend(SC.Observable, SC.Enumerable, SC.Array,
122
160
  loaded. This will possibly expand the index into a range and then invoke
123
161
  an appropriate method on the delegate to request the data.
124
162
 
163
+ It will check if the range has been already requested.
164
+
125
165
  @param {SC.SparseArray} receiver
126
166
  */
127
167
  requestIndex: function(idx) {
@@ -130,17 +170,19 @@ SC.SparseArray = SC.Object.extend(SC.Observable, SC.Enumerable, SC.Array,
130
170
 
131
171
  // adjust window
132
172
  var len = this.get('rangeWindowSize'), start = idx;
133
- if (len > 1) start = Math.floor(start / windowSize);
173
+ if (len > 1) start = start - Math.floor(start % len);
134
174
  if (len < 1) len = 1 ;
135
175
 
136
176
  // invoke appropriate callback
137
177
  this._requestingIndex++;
138
178
  if (del.sparseArrayDidRequestRange) {
139
179
  var range = this._TMP_RANGE;
140
- range.start = start;
141
- range.length = len;
142
- del.sparseArrayDidRequestRange(this, range);
143
-
180
+ if(this.wasRangeRequested(start)===-1){
181
+ range.start = start;
182
+ range.length = len;
183
+ del.sparseArrayDidRequestRange(this, range);
184
+ this.requestedRangeIndex.push(start);
185
+ }
144
186
  } else if (del.sparseArrayDidRequestIndex) {
145
187
  while(--len >= 0) del.sparseArrayDidRequestIndex(this, start + len);
146
188
  }
@@ -149,6 +191,38 @@ SC.SparseArray = SC.Object.extend(SC.Observable, SC.Enumerable, SC.Array,
149
191
  return this ;
150
192
  },
151
193
 
194
+ /*
195
+ This method is called by requestIndex to check if the range has already
196
+ been requested. We assume that rangeWindowSize is not changed often.
197
+
198
+ @param {Number} startIndex
199
+ @return {Number} index in requestRangeIndex
200
+ */
201
+ wasRangeRequested: function(rangeStart) {
202
+ var i, ilen;
203
+ for(i=0, ilen=this.requestedRangeIndex.length; i<ilen; i++){
204
+ if(this.requestedRangeIndex[i]===rangeStart) return i;
205
+ }
206
+ return -1;
207
+ },
208
+
209
+ /*
210
+ This method has to be called after a request for a range has completed.
211
+ To remove the index from the sparseArray to allow future updates on the
212
+ range.
213
+
214
+ @param {Number} startIndex
215
+ @return {Number} index in requestRangeIndex
216
+ */
217
+ rangeRequestCompleted: function(start) {
218
+ var i = this.wasRangeRequested(start);
219
+ if(i>=0) {
220
+ this.requestedRangeIndex.removeAt(i,1);
221
+ return YES;
222
+ }
223
+ return NO;
224
+ },
225
+
152
226
  /**
153
227
  This method sets the content for the specified to the objects in the
154
228
  passed array. If you change the way SparseArray implements its internal
@@ -98,7 +98,7 @@ module("Real Array & DummyEnumerable", {
98
98
  },
99
99
 
100
100
  teardown: function() {
101
- delete enumerables ;
101
+ delete enumerables;
102
102
  delete Array.prototype["@max(balance)"] ; // remove cached value
103
103
  delete Array.prototype["@min(balance)"] ;
104
104
  }
@@ -153,7 +153,7 @@ test("should run forEach() to go through objects", function() {
153
153
  }, this);
154
154
 
155
155
  var len = src.get('length') ;
156
- for(var idx=0;idx<len;idx++) {
156
+ for(idx=0;idx<len;idx++) {
157
157
  equals(items[idx], src.objectAt(idx)) ;
158
158
  equals(indexes[idx], idx) ;
159
159
  equals(arrays[idx], src) ;
@@ -187,7 +187,7 @@ test("should map to values while passing proper params", function() {
187
187
  }, this);
188
188
 
189
189
  var len = src.get('length') ;
190
- for(var idx=0;idx<len;idx++) {
190
+ for(idx=0;idx<len;idx++) {
191
191
  equals(src.objectAt(idx), items[idx], "items") ;
192
192
  equals(idx, indexes[idx], "indexes") ;
193
193
  equals(src, arrays[idx], 'arrays') ;
@@ -220,7 +220,7 @@ test("should filter to items that return for callback", function() {
220
220
  }, this);
221
221
 
222
222
  var len = src.get('length') ;
223
- for(var idx=0;idx<len;idx++) {
223
+ for(idx=0;idx<len;idx++) {
224
224
  equals(src.objectAt(idx), items[idx], "items") ;
225
225
  equals(idx, indexes[idx], "indexes") ;
226
226
  equals(src, arrays[idx], 'arrays') ;
@@ -254,7 +254,7 @@ test("should return true if function for every() returns true", function() {
254
254
  }, this);
255
255
 
256
256
  var len = src.get('length') ;
257
- for(var idx=0;idx<len;idx++) {
257
+ for(idx=0;idx<len;idx++) {
258
258
  equals(src.objectAt(idx), items[idx], "items") ;
259
259
  equals(idx, indexes[idx], "indexes") ;
260
260
  equals(src, arrays[idx], 'arrays') ;
@@ -298,7 +298,7 @@ test("should return false if all functions for some() returns false", function()
298
298
  }, this);
299
299
 
300
300
  var len = src.get('length') ;
301
- for(var idx=0;idx<len;idx++) {
301
+ for(idx=0;idx<len;idx++) {
302
302
  equals(src.objectAt(idx), items[idx], "items") ;
303
303
  equals(idx, indexes[idx], "indexes") ;
304
304
  equals(src, arrays[idx], 'arrays') ;
@@ -84,6 +84,59 @@ test("element to be added is at idx > length of array ", function() {
84
84
  });
85
85
 
86
86
 
87
+ test("Check that requestIndex works with a rangeWindowSize larger than 1", function() {
88
+ var ary = SC.SparseArray.array(10) ;
89
+ var didRequestRange=NO;
90
+
91
+ var DummyDelegate = SC.Object.extend({
92
+ content: [], // source array
93
+
94
+ sparseArrayDidRequestLength: function(sparseArray) {
95
+ sparseArray.provideLength(this.content.length);
96
+ },
97
+
98
+ sparseArrayDidRequestIndex: function(sparseArray, index) {
99
+ sparseArray.provideObjectAtIndex(index, this.content[index]);
100
+ },
101
+
102
+ sparseArrayDidRequestIndexOf: function(sparseArray, object) {
103
+ return this.content.indexOf(object);
104
+ },
105
+
106
+ sparseArrayShouldReplace: function(sparseArray, idx, amt, objects) {
107
+ this.content.replace(idx, amt, objects) ; // keep internal up-to-date
108
+ return YES ; // allow anything
109
+ },
110
+ sparseArrayDidRequestRange: function(sparseArray, range) {
111
+ didRequestRange=YES;
112
+ }
113
+
114
+ });
115
+ ary.set('delegate', DummyDelegate.create());
116
+ ary.set('rangeWindowSize', 4);
117
+ equals(10, ary.get('length'), "length") ;
118
+ ary.objectAt(7);
119
+ equals(didRequestRange, YES, "The range was requested") ;
120
+ });
121
+
122
+
123
+ // ..........................................................
124
+ // definedIndexes
125
+ //
126
+
127
+ test("definedIndexes", function() {
128
+ var ary = SC.SparseArray.array(10);
129
+ ary.provideObjectAtIndex(5, "foo");
130
+
131
+ var expected = SC.IndexSet.create().add(5);
132
+ same(ary.definedIndexes(), expected, 'definedIndexes() should return all defined indexes');
133
+
134
+ same(ary.definedIndexes(SC.IndexSet.create().add(2, 10)), expected, 'definedIndexes([2..11]) should return indexes within');
135
+
136
+ same(ary.definedIndexes(SC.IndexSet.create().add(2)), SC.IndexSet.EMPTY, 'definedIndexes([2]) should return empty set (since does not overlap with defined index)');
137
+
138
+ });
139
+
87
140
  // ..........................................................
88
141
  // TEST SC.ARRAY COMPLIANCE
89
142
  //
@@ -226,6 +226,10 @@ CoreTest.Plan = {
226
226
  @returns {CoreTest.Plan} receiver
227
227
  */
228
228
  module: function(desc, lifecycle) {
229
+ if (typeof SC !== 'undefined' && SC.filename) {
230
+ desc = SC.filename.replace(/^.+?\/current\/tests\//,'') + '\n' + desc;
231
+ }
232
+
229
233
  this.currentModule = desc;
230
234
 
231
235
  if (!lifecycle) lifecycle = {};
@@ -141,7 +141,7 @@ CoreTest.Runner = {
141
141
  for(idx=0;idx<len;idx++) s[assertions[idx].result]++;
142
142
  if ((s.failed + s.errors + s.warnings) === 0) clean = "clean" ;
143
143
 
144
- if (module) name = module + " module: " + test ;
144
+ if (module) name = module.replace(/\n/g, '<br />') + " module: " + test ;
145
145
  name = CoreTest.fmt('%@ - %@msec', name, timings.total_end - timings.total_begin);
146
146
  // place results into a single string to append all at once.
147
147
  var logstr = this.logstr ;
@@ -34,6 +34,10 @@
34
34
  margin-bottom: 3px;
35
35
  }
36
36
 
37
+ .sc-radio-view.sc-layout-horizontal .sc-radio-button {
38
+ padding-right: 8px;
39
+ }
40
+
37
41
  .sc-theme .sc-radio-view.sc-layout-vertical .sc-radio-button img.button {
38
42
  position: absolute ;
39
43
  margin: 0;
@@ -0,0 +1,23 @@
1
+ # ==========================================================================
2
+ # Generator: Controller
3
+ # Copyright: ©2006-2009 Sprout Systems, Inc. and contributors
4
+ # portions copyright ©2009 Apple, Inc.
5
+ # ==========================================================================
6
+
7
+ namespace :generator do
8
+
9
+ # - Verify required properties are present
10
+ # - Accept second argument as base class
11
+ # - If file name end in "_design" strip it off.
12
+ # - Make sure filename ends in _page.
13
+ task :prepare do
14
+ GENERATOR.requires! :target_project, :target, :namespace, :class_name
15
+ GENERATOR.base_class_name ||= GENERATOR.arguments[2]
16
+
17
+ filename = GENERATOR.filename.sub(/_design$/,'')
18
+ filename = "#{filename}_page" unless filename =~ /_page$/
19
+ GENERATOR.filename = filename
20
+
21
+ end
22
+
23
+ end
data/gen/design/README ADDED
@@ -0,0 +1 @@
1
+ Your design is now ready to use!
data/gen/design/USAGE ADDED
@@ -0,0 +1,10 @@
1
+ design - Create a new page design for your SproutCore app.
2
+
3
+ USAGE:
4
+
5
+ sc-gen design AppName.designName [--filename=FILENAME] [--target=TARGET_NAME]
6
+
7
+ DISCUSSION:
8
+
9
+ This generator will create a new SproutCore page design, similar to the main_page design that comes with all new apps.
10
+
@@ -0,0 +1,16 @@
1
+ // ==========================================================================
2
+ // Project: <%= namespace_instance_name %>
3
+ // Copyright: ©<%= Time.now.year %> My Company, Inc.
4
+ // ==========================================================================
5
+ /*globals <%= namespace %> */
6
+
7
+ // This page describes a part of the interface for your application.
8
+ <%= namespace_instance_name %> = SC.Page.design({
9
+
10
+ // Add your views here. Ex:
11
+
12
+ // mainView: SC.View.design({
13
+ // layout: { top: 0, left: 0, right: 0, height: 0 }
14
+ // })
15
+
16
+ });
@@ -0,0 +1,36 @@
1
+ # ==========================================================================
2
+ # Generator: APP
3
+ # Copyright: ©2006-2009 Sprout Systems, Inc. and contributors
4
+ # portions copyright ©2009 Apple, Inc.
5
+ # ==========================================================================
6
+
7
+ namespace :generator do
8
+
9
+ # Require a project then make sure the build root is always the project
10
+ # root.
11
+ task :prepare do
12
+ GENERATOR.requires! :target_project
13
+
14
+ # if the target name has a slash in it, then we are trying to create a
15
+ # nested target. extract the final part (since this is the target name)
16
+ # and then set the build root to the parent target.
17
+ if GENERATOR.target_name && GENERATOR.target_name =~ /\//
18
+ parent_target_name = GENERATOR.target_name.split('/')
19
+ GENERATOR.target_name = parent_target_name.pop
20
+
21
+ parent_target_name = parent_target_name * "/"
22
+ project = GENERATOR.target_project
23
+
24
+ GENERATOR.parent_target_name = parent_target_name
25
+ GENERATOR.parent_target = project.target_for(parent_target_name)
26
+ GENERATOR.requires! :parent_target, :parent_target_name
27
+
28
+ GENERATOR.build_root = GENERATOR.parent_target.source_root
29
+
30
+ # otherwise just use project_root
31
+ else
32
+ GENERATOR.build_root = GENERATOR.target_project.project_root
33
+ end
34
+ end
35
+
36
+ end
data/gen/page/README ADDED
@@ -0,0 +1 @@
1
+ Your page target is now ready to use!
data/gen/page/USAGE ADDED
@@ -0,0 +1,15 @@
1
+ page - Create a new SproutCore page target.
2
+
3
+ USAGE:
4
+
5
+ sc-gen page PageName [--filename=FILENAME] [--target=TARGET_NAME]
6
+
7
+ DISCUSSION:
8
+
9
+ *IMPORTANT:* This generator does not create a page design (e.g. main_page.js) in an app. Use "sc-gen design" instead.
10
+
11
+ This generator will create a new SproutCore page for a particular project. A page is much like an app but you will often place primarily static content here. You should pass as the first parameter your PageName you want to create. For example:
12
+
13
+ sc-gen page NotFound
14
+
15
+ defines a new page called NotFound in the file pages/not_found/.
@@ -0,0 +1,16 @@
1
+ # ==========================================================================
2
+ # Project: <%= namespace %> Buildfile
3
+ # Copyright: ©<%= Time.now.year %> My Company, Inc.
4
+ # ==========================================================================
5
+
6
+ # You can use to buildfile to add a custom page title, set environment
7
+ # variables, and require any specific JavaScript or other libraries you want
8
+ # to use.
9
+ #
10
+ # The default configuration just sets the page title and also requires
11
+ # SproutCore-Mini (a smaller version of SproutCore)
12
+ #
13
+ config :<%= target_name %>,
14
+ :required => ['sproutcore/mini'],
15
+ :title => '<%= target_name.split('_').map { |x| x.capitalize }.join(" ") %>'
16
+
@@ -0,0 +1,22 @@
1
+ // ==========================================================================
2
+ // Project: <%= namespace %>
3
+ // Copyright: ©<%= Time.now.year %> My Company, Inc.
4
+ // ==========================================================================
5
+ /*globals <%= namespace %> */
6
+
7
+ /** @namespace
8
+
9
+ Static page JavaScript
10
+
11
+ @extends SC.Object
12
+ */
13
+ <%= namespace %> = SC.Object.create(
14
+ /** @scope <%= namespace %>.prototype */ {
15
+
16
+ NAMESPACE: '<%= namespace %>',
17
+ VERSION: '0.1.0'
18
+
19
+ // TODO: You can place any JavaScript you need on your page here. If you
20
+ // don't want any JavaScript, just delete this file.
21
+
22
+ }) ;
@@ -0,0 +1 @@
1
+ /* Add any extra CSS for this page here. You can also add other CSS files if you want */
@@ -0,0 +1,7 @@
1
+ <%% content_for :body do %>
2
+ <%% # Any HTML inside this area will be placed into the main body of the HTML
3
+ # page.
4
+ %>
5
+ <h1><%= target_name.split('_').map { |x| x.capitalize }.join(" ") %></h1>
6
+
7
+ <%% end %>
@@ -0,0 +1,15 @@
1
+ // ==========================================================================
2
+ // Project: <%= namespace %> Strings
3
+ // Copyright: ©<%= Time.now.year %> My Company, Inc.
4
+ // ==========================================================================
5
+ /*globals <%= namespace %> */
6
+
7
+ // Place strings you want to localize here. In your app, use the key and
8
+ // localize it using "key string".loc(). HINT: For your key names, use the
9
+ // english string with an underscore in front. This way you can still see
10
+ // how your UI will look and you'll notice right away when something needs a
11
+ // localized string added to this file!
12
+ //
13
+ SC.stringsFor('English', {
14
+ // "_String Key": "Localized String"
15
+ }) ;
data/gen/view/README CHANGED
@@ -1 +1 @@
1
- Your controller is now ready to use!
1
+ Your view is now ready to use!
data/gen/view/USAGE CHANGED
@@ -1,13 +1,13 @@
1
- model - Create a new controller class in your SproutCore app.
1
+ view - Create a new view class in your SproutCore app.
2
2
 
3
3
  USAGE:
4
4
 
5
- sc-gen controller AppName.ClassNameController [--filename=FILENAME] [--target=TARGET_NAME]
5
+ sc-gen view AppName.NewView [--filename=FILENAME] [--target=TARGET_NAME]
6
6
 
7
7
  DISCUSSION:
8
8
 
9
- This generator will create a new SproutCore controller file in your app. You should pass as the first parameter your AppName.ClassNameController combination you want to create. For example:
9
+ This generator will create a new SproutCore view in your app. You should pass as the first parameter your AppName.NewView combination you want to create. For example:
10
10
 
11
- sc-gen controller Todos.TaskController
11
+ sc-gen view Todos.TaskView
12
12
 
13
- defines a new class called Todos.TaskController in the file apps/todos/controllers/task.js .
13
+ defines a new class called Todos.TaskView in the file apps/todos/views/task.js .
@@ -61,9 +61,20 @@ module SC
61
61
 
62
62
  # Handles occurances of sc_static() or static_url()
63
63
  def replace_static_url(line)
64
- line.gsub(/(sc_static|static_url)\(\s*['"](.+)['"]\s*\)/) do | rsrc |
64
+ line.gsub(/(sc_static|static_url|sc_target)\(\s*['"](.+)['"]\s*\)/) do | rsrc |
65
+ entry_name = $2
66
+ entry_name = "#{$2}:index.html" if $1 == 'sc_target'
65
67
  static_entry = entry.manifest.find_entry($2)
66
- static_url(static_entry.nil? ? '' : static_entry.cacheable_url)
68
+
69
+ if static_entry.nil?
70
+ url = ''
71
+ elsif $1 == 'sc_target'
72
+ url = static_entry.friendly_url || static_entry.cacheable_url
73
+ else
74
+ url = static_entry.cacheable_url
75
+ end
76
+
77
+ static_url(url)
67
78
  end
68
79
  end
69
80