sproutit-sproutcore 1.0.20090721145281 → 1.0.20090721145282

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.
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