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
data/Buildfile CHANGED
@@ -17,9 +17,10 @@ mode :all do
17
17
  # REQUIRED CONFIGS
18
18
  # You will not usually need to override these configs, but the code
19
19
  # assumes they will be present, so you must support them.
20
- :build_prefix => 'tmp/build',
20
+ :build_prefix => 'tmp/build',
21
21
  :staging_prefix => 'tmp/staging',
22
- :url_prefix => 'static',
22
+ :cache_prefix => 'tmp/cache',
23
+ :url_prefix => 'static',
23
24
 
24
25
  # Defines the directories that may contain targets, and maps them to a
25
26
  # target type. When a project tries to find all of the targets in a
@@ -27,6 +28,7 @@ mode :all do
27
28
  :target_types => {
28
29
  :apps => :app,
29
30
  :clients => :app,
31
+ :pages => :app, # used for static pages with your site
30
32
  :frameworks => :framework,
31
33
  :themes => :theme
32
34
  },
@@ -111,7 +113,6 @@ mode :debug do
111
113
  # Do not pack javascripts in development mode, we want each file to
112
114
  # load independently.
113
115
  :use_packed => false
114
-
115
116
  end
116
117
 
117
118
 
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :minor: 0
3
- :patch: 20090721145281
4
- :digest: ba83b210ad765939b203da70844f9799493ef006
3
+ :patch: 20090721145282
4
+ :digest: 8d4f830b015e13e58d53e304b9cf421117d5c456
5
5
  :major: 1
@@ -53,6 +53,9 @@ namespace :entry do
53
53
  else
54
54
  ENTRY.staging_path ||= MANIFEST.unique_staging_path(File.join(MANIFEST.staging_root, filename_parts))
55
55
  end
56
+
57
+ ENTRY.cache_path = MANIFEST.unique_cache_path(File.join(MANIFEST.cache_root, filename_parts))
58
+
56
59
  end
57
60
 
58
61
  end
@@ -22,6 +22,10 @@ namespace :manifest do
22
22
  MANIFEST.staging_root = File.join(TARGET.staging_root,
23
23
  MANIFEST.language.to_s, TARGET.build_number.to_s)
24
24
 
25
+ # cache_root is target.cache_root + language + build_number
26
+ MANIFEST.cache_root = File.join(TARGET.cache_root,
27
+ MANIFEST.language.to_s, TARGET.build_number.to_s)
28
+
25
29
  # url_root
26
30
  MANIFEST.url_root =
27
31
  [TARGET.url_root, MANIFEST.language, TARGET.build_number].join('/')
@@ -369,7 +373,7 @@ namespace :manifest do
369
373
  entries.each do |entry|
370
374
  entry.entry_type = :html
371
375
  entry.resource = 'index'
372
-
376
+
373
377
  entry.render_task = case entry.ext
374
378
  when 'rhtml':
375
379
  'render:erubis'
@@ -379,13 +383,21 @@ namespace :manifest do
379
383
  'render:haml'
380
384
  end
381
385
 
382
- # use a custom scan method since discover_build_directives! is too
383
- # general...
384
-
385
- entry.scan_source(/<%\s*sc_resource\(?\s*['"](.+)['"]\s*\)?/) do |m|
386
- entry.resource = m[0].ext ''
386
+ # items beginning with an underscore are partials. do not build
387
+ if entry.filename =~ /^_/
388
+ entry.hide!
389
+ entry.is_partial = true
390
+
391
+ # not a partial
392
+ else
393
+ # use a custom scan method since discover_build_directives! is too
394
+ # general...
395
+ entry.scan_source(/<%\s*sc_resource\(?\s*['"](.+)['"]\s*\)?/) do |m|
396
+ entry.resource = m[0].ext ''
397
+ end
398
+ (entries_by_resource[entry.resource] ||= []) << entry
387
399
  end
388
- (entries_by_resource[entry.resource] ||= []) << entry
400
+
389
401
  end
390
402
 
391
403
  # even if no resource was found for the index.html, add one anyway if
@@ -398,13 +410,27 @@ namespace :manifest do
398
410
  entries_by_resource.each do |resource_name, entries|
399
411
  resource_name = resource_name.ext('html')
400
412
  is_index = resource_name == 'index.html'
413
+
414
+ # compute the friendly_url assuming normal install process
415
+ friendly_url = [TARGET.index_root]
416
+ m_language = MANIFEST.language.to_sym
417
+ t_preferred = (TARGET.config.preferred_language || :en).to_sym
418
+ if is_index
419
+ friendly_url << m_language.to_s unless t_preferred == m_language
420
+ else
421
+ friendly_url << m_language.to_s
422
+ friendly_url << resource_name
423
+ end
424
+ friendly_url = friendly_url.join('/')
425
+
401
426
  MANIFEST.add_composite resource_name,
402
427
  :entry_type => :html,
403
428
  :combined => true,
404
429
  :build_task => 'build:html',
405
430
  :source_entries => entries,
406
431
  :hidden => !TARGET.loadable? && is_index,
407
- :include_required_targets => TARGET.loadable? && is_index
432
+ :include_required_targets => TARGET.loadable? && is_index,
433
+ :friendly_url => friendly_url
408
434
  end
409
435
  end
410
436
 
@@ -444,7 +470,7 @@ namespace :manifest do
444
470
  desc "adds a loc strings entry that generates a yaml file server-side functions can use"
445
471
  task :strings => %w(setup javascript) do
446
472
  # find the lproj/strings.js file...
447
- if entry = MANIFEST.entry_for('source/lproj/strings.js')
473
+ if entry = (MANIFEST.entry_for('source/lproj/strings.js') || MANIFEST.entry_for('source/lproj/strings.js', :hidden => true))
448
474
  MANIFEST.add_transform entry,
449
475
  :filename => 'strings.yaml',
450
476
  :build_path => File.join(MANIFEST.build_root, 'strings.yaml'),
@@ -13,24 +13,43 @@ namespace :target do
13
13
  task :prepare do
14
14
 
15
15
  # use url_root config or merge url_prefix + target_name
16
- TARGET.url_root = CONFIG.url_root ||
17
- [nil, CONFIG.url_prefix, TARGET.target_name].join('/').gsub(/\/+/,'/')
16
+ if (TARGET.url_root = CONFIG.url_root).nil?
17
+ url = [nil, CONFIG.url_prefix, TARGET.target_name].join('/')
18
+ url = url.gsub(/([^:])\/+/,'\1/').gsub(/^\/+/,'/') # remove extra //
19
+ url = url[1..-1] if url.match(/^\/[^\/]+:\/\//) # look for protocol
20
+ TARGET.url_root = url
21
+ end
22
+
18
23
 
19
24
  # use index_root config or merge index_prefix + target_name
20
- TARGET.index_root = CONFIG.index_root ||
21
- [nil, CONFIG.index_prefix, TARGET.target_name].join('/').gsub(/\/+/, '/')
25
+ if (TARGET.index_root = CONFIG.index_root).nil?
26
+ url = [nil, CONFIG.index_prefix, TARGET.target_name].join('/')
27
+ url = url.gsub(/([^:])\/+/,'\1/').gsub(/^\/+/,'/') # remove extra //
28
+ url = url[1..-1] if url.match(/^\/[^\/]+:\/\//) # look for protocol
29
+ TARGET.index_root = url
30
+ end
22
31
 
32
+ url_prefix = CONFIG.url_prefix
33
+ url_prefix = url_prefix.gsub(/^[^\/]+:\/\/[^\/]+\//,'') if url_prefix
34
+
23
35
  # Split all of these paths in case we are on windows...
24
36
  TARGET.build_root = File.expand_path(CONFIG.build_root ||
25
37
  File.join(PROJECT.project_root.to_s,
26
38
  (CONFIG.build_prefix || '').to_s.split('/'),
27
- (CONFIG.url_prefix || '').to_s.split('/'),
39
+ (url_prefix || '').to_s.split('/'),
28
40
  TARGET.target_name.to_s.split('/')))
29
41
 
30
42
  TARGET.staging_root = File.expand_path(CONFIG.staging_root ||
31
43
  File.join(PROJECT.project_root.to_s,
32
44
  (CONFIG.staging_prefix || '').to_s.split('/'),
33
- (CONFIG.url_prefix || '').to_s.split('/'),
45
+ (url_prefix || '').to_s.split('/'),
46
+ TARGET.target_name.to_s))
47
+
48
+ # cache is used to store intermediate files
49
+ TARGET.cache_root = File.expand_path(CONFIG.cache_root ||
50
+ File.join(PROJECT.project_root.to_s,
51
+ (CONFIG.cache_prefix || '').to_s.split('/'),
52
+ (url_prefix || '').to_s.split('/'),
34
53
  TARGET.target_name.to_s))
35
54
 
36
55
  TARGET.build_number = TARGET.compute_build_number
@@ -14,6 +14,15 @@ config :all,
14
14
  :test_required => ['sproutcore/testing', 'sproutcore/empty_theme'],
15
15
  :debug_required => ['sproutcore/debug', 'sproutcore/testing']
16
16
 
17
+ # in debug mode, combine the JS for SC by default. This will improve perf
18
+ # while working with apps. If you are hacking SC itself, you can turn this
19
+ # off in your project buildfile by referencing sproutcore specifically
20
+ mode :debug do
21
+ config :all,
22
+ :combine_javascript => true,
23
+ :combine_stylesheet => true
24
+ end
25
+
17
26
  # CORE FRAMEWORKS
18
27
  config :runtime, :required => []
19
28
  config :foundation, :required => [:runtime]
@@ -30,6 +39,7 @@ config :mobile,
30
39
 
31
40
  # WRAPPER FRAMEWORKS
32
41
  config :sproutcore, :required => :desktop
42
+ config :mini, :required => [:runtime, :datastore]
33
43
 
34
44
  # SPECIAL FRAMEWORKS AND THEMES
35
45
  # These do not require any of the built-in SproutCore frameworks
@@ -56,7 +56,8 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
56
56
  SC.Record or SC.Record.STORE_KEYS if invoked from store.retrieveRecords.
57
57
  Could also be an SC.Query if that was passed in to findAll()
58
58
  @param {Hash} params optional additonal fetch params. storeKeys if invoked
59
- from store.retrieveRecords
59
+ from store.retrieveRecords. this originated from the commitRecords()
60
+ call on the store
60
61
  @returns {SC.Array} result set with storeKeys. In case of SC.Array
61
62
  it may be sparse.
62
63
  */
@@ -70,11 +71,13 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
70
71
  @param {SC.Store} store the requesting store
71
72
  @param {Array} storeKeys
72
73
  @param {Array} ids - optional
74
+ @param {Hash} params to be passed down to data source. originated
75
+ from the commitRecords() call on the store
73
76
  @returns
74
77
  */
75
78
 
76
- retrieveRecords: function(store, storeKeys, ids) {
77
- return this._handleEach(store, storeKeys, this.retrieveRecord, ids);
79
+ retrieveRecords: function(store, storeKeys, ids, params) {
80
+ return this._handleEach(store, storeKeys, this.retrieveRecord, ids, params);
78
81
  },
79
82
 
80
83
  /**
@@ -102,13 +105,15 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
102
105
  @param {Array} createStoreKeys keys to create
103
106
  @param {Array} updateStoreKeys keys to update
104
107
  @param {Array} destroyStoreKeys keys to destroy
108
+ @param {Hash} params to be passed down to data source. originated
109
+ from the commitRecords() call on the store
105
110
  @returns {Boolean} YES if data source can handle keys
106
111
  */
107
- commitRecords: function(store, createStoreKeys, updateStoreKeys, destroyStoreKeys) {
112
+ commitRecords: function(store, createStoreKeys, updateStoreKeys, destroyStoreKeys, params) {
108
113
  var cret, uret, dret;
109
- if(createStoreKeys.length>0) cret = this.createRecords.call(this, store, createStoreKeys);
110
- if(updateStoreKeys.length>0) uret = this.updateRecords.call(this, store, updateStoreKeys);
111
- if(destroyStoreKeys.length>0) dret = this.destroyRecords.call(this, store, destroyStoreKeys);
114
+ if(createStoreKeys.length>0) cret = this.createRecords.call(this, store, createStoreKeys, params);
115
+ if(updateStoreKeys.length>0) uret = this.updateRecords.call(this, store, updateStoreKeys, params);
116
+ if(destroyStoreKeys.length>0) dret = this.destroyRecords.call(this, store, destroyStoreKeys, params);
112
117
  return (cret === uret === dret) ? (cret || uret || dret) : SC.MIXED_STATE ;
113
118
  },
114
119
 
@@ -149,9 +154,11 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
149
154
 
150
155
  @param {SC.Store} store the requesting store
151
156
  @param {Array} storeKeys keys to update
157
+ @param {Hash} params to be passed down to data source. originated
158
+ from the commitRecords() call on the store
152
159
  */
153
- updateRecords: function(store, storeKeys) {
154
- return this._handleEach(store, storeKeys, this.updateRecord);
160
+ updateRecords: function(store, storeKeys, params) {
161
+ return this._handleEach(store, storeKeys, this.updateRecord, null, params);
155
162
  },
156
163
 
157
164
  /**
@@ -166,9 +173,11 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
166
173
 
167
174
  @param {SC.Store} store the requesting store
168
175
  @param {Array} storeKeys keys to update
176
+ @param {Hash} params to be passed down to data source. originated
177
+ from the commitRecords() call on the store
169
178
  */
170
- createRecords: function(store, storeKeys) {
171
- return this._handleEach(store, storeKeys, this.createRecord);
179
+ createRecords: function(store, storeKeys, params) {
180
+ return this._handleEach(store, storeKeys, this.createRecord, null, params);
172
181
  },
173
182
 
174
183
  /**
@@ -183,20 +192,24 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
183
192
 
184
193
  @param {SC.Store} store the requesting store
185
194
  @param {Array} storeKeys keys to update
195
+ @param {Hash} params to be passed down to data source. originated
196
+ from the commitRecords() call on the store
186
197
  */
187
- destroyRecords: function(store, storeKeys) {
188
- return this._handleEach(store, storeKeys, this.destroyRecord);
198
+ destroyRecords: function(store, storeKeys, params) {
199
+ return this._handleEach(store, storeKeys, this.destroyRecord, null, params);
189
200
  },
190
201
 
191
202
  /** @private
192
203
  invokes the named action for each store key. returns proper value
193
204
  */
194
- _handleEach: function(store, storeKeys, action, ids) {
195
- var len = storeKeys.length, idx, ret, cur;
205
+ _handleEach: function(store, storeKeys, action, ids, params) {
206
+ var len = storeKeys.length, idx, ret, cur, lastArg;
196
207
  if(!ids) ids = [];
197
208
 
198
209
  for(idx=0;idx<len;idx++) {
199
- cur = action.call(this, store, storeKeys[idx], ids[idx]);
210
+ lastArg = ids[idx] ? ids[idx] : params;
211
+
212
+ cur = action.call(this, store, storeKeys[idx], lastArg, params);
200
213
  if (ret === undefined) {
201
214
  ret = cur ;
202
215
  } else if (ret === YES) {
@@ -222,9 +235,11 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
222
235
 
223
236
  @param {SC.Store} store the requesting store
224
237
  @param {Array} storeKey key to update
238
+ @param {Hash} params to be passed down to data source. originated
239
+ from the commitRecords() call on the store
225
240
  @returns {Boolean} YES if handled
226
241
  */
227
- updateRecord: function(store, storeKey) {
242
+ updateRecord: function(store, storeKey, params) {
228
243
  return NO ;
229
244
  },
230
245
 
@@ -234,9 +249,11 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
234
249
  @param {SC.Store} store the requesting store
235
250
  @param {Array} storeKey key to retrieve
236
251
  @param {String} id the id to retrieve
252
+ @param {Hash} params to be passed down to data source. originated
253
+ from the commitRecords() call on the store
237
254
  @returns {Boolean} YES if handled
238
255
  */
239
- retrieveRecord: function(store, storeKey, id) {
256
+ retrieveRecord: function(store, storeKey, id, params) {
240
257
  return NO ;
241
258
  },
242
259
 
@@ -249,9 +266,11 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
249
266
 
250
267
  @param {SC.Store} store the requesting store
251
268
  @param {Array} storeKey key to update
269
+ @param {Hash} params to be passed down to data source. originated
270
+ from the commitRecords() call on the store
252
271
  @returns {Boolean} YES if handled
253
272
  */
254
- createRecord: function(store, storeKey) {
273
+ createRecord: function(store, storeKey, params) {
255
274
  return NO ;
256
275
  },
257
276
 
@@ -264,9 +283,11 @@ SC.DataSource = SC.Object.extend( /** SC.DataSource.prototype */ {
264
283
 
265
284
  @param {SC.Store} store the requesting store
266
285
  @param {Array} storeKey key to update
286
+ @param {Hash} params to be passed down to data source. originated
287
+ from the commitRecords() call on the store
267
288
  @returns {Boolean} YES if handled
268
289
  */
269
- destroyRecord: function(store, storeKey) {
290
+ destroyRecord: function(store, storeKey, params) {
270
291
  return NO ;
271
292
  }
272
293
 
@@ -86,52 +86,17 @@ SC.FixturesDataSource = SC.DataSource.extend( {
86
86
 
87
87
  },
88
88
 
89
- /**
90
- Load fixtures for a given fetchKey into the store
91
- and push it to the ret array.
92
-
93
- @param {SC.Store} store
94
- @param {SC.Record} fetchKey
95
- @param {SC.Array} ret
96
- */
97
- loadFixturesFor: function(store, fetchKey, ret) {
98
- var dataHashes, i, storeKey, hashes = [];
99
- dataHashes = this.fixturesFor(fetchKey);
100
- for(i in dataHashes){
101
- storeKey = fetchKey.storeKeyFor(i);
102
- hashes.push(dataHashes[i]);
103
- ret.push(storeKey);
104
- }
105
- store.loadRecords(fetchKey, hashes);
106
- },
107
-
108
- /**
109
- Load fixtures for a given fetchKey into the store
110
- and push it to the ret array.
111
-
112
- @param {SC.Store} store
113
- @param {SC.Record} fetchKey
114
- @param {SC.Array} ret
115
- */
116
- loadFixturesFor: function(store, fetchKey, ret) {
117
- var dataHashes, i, storeKey, hashes = [];
118
- dataHashes = this.fixturesFor(fetchKey);
119
- for(i in dataHashes){
120
- storeKey = fetchKey.storeKeyFor(i);
121
- hashes.push(dataHashes[i]);
122
- ret.push(storeKey);
123
- }
124
- store.loadRecords(fetchKey, hashes);
125
- },
126
-
127
89
  /**
128
90
  Retrieve a record from fixtures.
129
91
 
130
92
  @param {SC.Store} store
131
93
  @param {Number} storeKey
132
94
  @param {SC.Array} ret
95
+ @param {Hash} params to be passed down to data source. originated
96
+ from the commitRecords() call on the store
97
+ @returns {Array} storeKeys
133
98
  */
134
- retrieveRecord: function(store, storeKey) {
99
+ retrieveRecord: function(store, storeKey, params) {
135
100
  var ret = [], recordType = SC.Store.recordTypeFor(storeKey),
136
101
  id = store.idFor(storeKey),
137
102
  hash = this.fixtureForStoreKey(store, storeKey);
@@ -157,9 +122,11 @@ SC.FixturesDataSource = SC.DataSource.extend( {
157
122
 
158
123
  @param {SC.Store} store
159
124
  @param {Number} storeKey
125
+ @param {Hash} params to be passed down to data source. originated
126
+ from the commitRecords() call on the store
160
127
  @returns {Boolean} YES if handled
161
128
  */
162
- updateRecord: function(store, storeKey) {
129
+ updateRecord: function(store, storeKey, params) {
163
130
  this.setFixtureForStoreKey(store, storeKey, store.readDataHash(storeKey));
164
131
  store.dataSourceDidComplete(storeKey);
165
132
  return YES ;
@@ -171,9 +138,11 @@ SC.FixturesDataSource = SC.DataSource.extend( {
171
138
 
172
139
  @param {SC.Store} store the store
173
140
  @param {Number} storeKey the store key
141
+ @param {Hash} params to be passed down to data source. originated
142
+ from the commitRecords() call on the store
174
143
  @returns {Boolean} YES if successful
175
144
  */
176
- createRecord: function(store, storeKey) {
145
+ createRecord: function(store, storeKey, params) {
177
146
  var id = store.idFor(storeKey),
178
147
  recordType = store.recordTypeFor(storeKey),
179
148
  dataHash = store.readDataHash(storeKey),
@@ -192,9 +161,11 @@ SC.FixturesDataSource = SC.DataSource.extend( {
192
161
 
193
162
  @param {SC.Store} store the store
194
163
  @param {Number} storeKey the store key
164
+ @param {Hash} params to be passed down to data source. originated
165
+ from the commitRecords() call on the store
195
166
  @returns {Boolean} YES if successful
196
167
  */
197
- destroyRecord: function(store, storeKey) {
168
+ destroyRecord: function(store, storeKey, params) {
198
169
  var id = store.idFor(storeKey),
199
170
  recordType = store.recordTypeFor(storeKey),
200
171
  fixtures = this.fixturesFor(recordType);
@@ -301,7 +272,7 @@ SC.FixturesDataSource = SC.DataSource.extend( {
301
272
  */
302
273
  _invalidateCachesFor: function(recordType, storeKey, id) {
303
274
  var cache = this._storeKeyCache;
304
- if (cache) delete cache[SC.guidFor(recordType)]
275
+ if (cache) delete cache[SC.guidFor(recordType)];
305
276
  return this ;
306
277
  }
307
278
 
@@ -341,6 +341,17 @@ SC.Record = SC.Object.extend(
341
341
  return this.readAttribute(key);
342
342
  },
343
343
 
344
+ /**
345
+ Lets you commit this specific record to the store which will trigger
346
+ the appropriate methods in the data source for you.
347
+
348
+ @param {Hash} params optional additonal params that will passed down
349
+ to the data source
350
+ */
351
+ commitRecord: function(params) {
352
+ this.get('store').commitRecord(undefined, undefined, this.get('storeKey'), params);
353
+ },
354
+
344
355
  // ...............................
345
356
  // PRIVATE
346
357
  //
@@ -185,11 +185,14 @@ SC.RecordAttribute = SC.Object.extend(
185
185
  @returns {Object} property value
186
186
  */
187
187
  call: function(record, key, value) {
188
- var attrKey = this.get('key') || key;
188
+ var attrKey = this.get('key') || key, nvalue;
189
189
 
190
190
  if (value !== undefined) {
191
- value = this.fromType(record, key, value) ; // convert to attribute.
192
- record.writeAttribute(attrKey, value);
191
+
192
+ // careful: don't overwrite value here. we want the return value to
193
+ // cache.
194
+ nvalue = this.fromType(record, key, value) ; // convert to attribute.
195
+ record.writeAttribute(attrKey, nvalue);
193
196
  } else {
194
197
  value = record.readAttribute(attrKey);
195
198
  if (SC.none(value) && (value = this.get('defaultValue'))) {
@@ -136,8 +136,10 @@ SC.NestedStore = SC.Store.extend(
136
136
  if (this.get('hasChanges')) {
137
137
  var pstore = this.get('parentStore');
138
138
  pstore.commitChangesFromNestedStore(this, this.chainedChanges, force);
139
- this.reset(); // clear out custom changes
140
139
  }
140
+
141
+ // clear out custom changes - even if there is nothing to commit.
142
+ this.reset();
141
143
  return this ;
142
144
  },
143
145
 
@@ -166,6 +168,7 @@ SC.NestedStore = SC.Store.extend(
166
168
  }
167
169
 
168
170
  this.reset();
171
+ this.flush();
169
172
  return this ;
170
173
  },
171
174
 
@@ -380,6 +383,7 @@ SC.NestedStore = SC.Store.extend(
380
383
 
381
384
  // Finally, mark store as dirty if we have changes
382
385
  this.setIfChanged('hasChanges', myChanges.get('length')>0);
386
+ this.flush();
383
387
 
384
388
  return this ;
385
389
  },
@@ -548,13 +548,15 @@ SC.Query = SC.Object.extend({
548
548
 
549
549
  if (!inputString) return [];
550
550
 
551
- for (var i=0; i < inputString.length; i++) {
551
+ var iStLength = inputString.length;
552
+
553
+ for (var i=0; i < iStLength; i++) {
552
554
 
553
555
  // end reached?
554
- endOfString = (i==inputString.length-1);
556
+ endOfString = (i===iStLength-1);
555
557
 
556
558
  // current character
557
- c = inputString[i];
559
+ c = inputString.charAt(i);
558
560
 
559
561
  // set true after end of delimeted token so that
560
562
  // final delimeter is not catched again
@@ -567,7 +569,7 @@ SC.Query = SC.Object.extend({
567
569
 
568
570
  // some helpers
569
571
  t = grammar[currentToken];
570
- endOfToken = t.delimeted ? c==currentDelimeter : t.notAllowed.test(c);
572
+ endOfToken = t.delimeted ? c===currentDelimeter : t.notAllowed.test(c);
571
573
 
572
574
  // if still in token
573
575
  if ( !endOfToken ) currentTokenValue += c;
@@ -859,10 +861,11 @@ SC.Query.mixin( /** @scope SC.Query */ {
859
861
 
860
862
  for(idx=0,len=storeKeys.length;idx<len;idx++) {
861
863
  rec = store.materializeRecord(storeKeys[idx]);
862
- status = rec.get('status');
864
+ if (rec) status = rec.get('status');
865
+
863
866
  // do not include EMPTY or DESTROYED records
864
- if(rec && !(status & K.EMPTY) && !(status & K.DESTROYED) && query.contains(rec)) {
865
- ret.push(storeKeys[idx]);
867
+ if (rec && !(status & K.EMPTY) && !(status & K.DESTROYED)) {
868
+ if (query.contains(rec)) ret.push(storeKeys[idx]);
866
869
  }
867
870
  }
868
871
 
@@ -151,6 +151,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
151
151
  // clear existing storeKeys, start over by applying all storekeys for
152
152
  // this recordType
153
153
  this.storeKeys = [];
154
+ query.parseQuery();
154
155
  this.applyQuery(storeKeys, recordTypes);
155
156
  }
156
157
 
@@ -163,13 +164,12 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
163
164
 
164
165
  @param {Array} storeKeys to evaluate against the query
165
166
  @param {SC.Set} recordTypes set of record types that changed
166
- @param {Boolean} notify to send length notifyPropertyChange()
167
167
  */
168
- applyQuery: function(changedStoreKeys, recordTypes, notify) {
169
- var newStoreKeys = this.get('storeKeys'), inChangedStoreKeys,
168
+ applyQuery: function(changedStoreKeys, recordTypes) {
169
+ var newStoreKeys = SC.clone(this.get('storeKeys')), inChangedStoreKeys,
170
170
  inMatchingStoreKeys, idx, len, storeKey, queryKey = this.get('queryKey'),
171
171
  store = this.get('store');
172
-
172
+
173
173
  // first check if these changes include any of the record types
174
174
  if(recordTypes && queryKey.recordType && !recordTypes.contains(queryKey.recordType)) return;
175
175
 
@@ -184,7 +184,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
184
184
  inMatchingStoreKeys = (matchingStoreKeys &&
185
185
  matchingStoreKeys.indexOf(storeKey)!==-1) ? YES: NO;
186
186
  var inRecArray = this.storeKeys.indexOf(storeKey)!==-1 ? YES : NO;
187
-
187
+
188
188
  if(inMatchingStoreKeys && !inRecArray) {
189
189
  newStoreKeys.push(storeKey);
190
190
  }
@@ -195,11 +195,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
195
195
  }
196
196
 
197
197
  SC.Query.orderStoreKeys(newStoreKeys, queryKey, store);
198
- // clear cache
199
- this._records = null;
200
-
201
- this.storeKeys = newStoreKeys.addObserver('[]', this, this._storeKeysContentDidChange);
202
- if(notify) this.notifyPropertyChange('length');
198
+ this.set('storeKeys', newStoreKeys);
203
199
  },
204
200
 
205
201
  /**
@@ -223,7 +219,6 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
223
219
  Invoked whenever the storeKeys array changes. Observes changes.
224
220
  */
225
221
  _storeKeysDidChange: function() {
226
-
227
222
  var storeKeys = this.get('storeKeys');
228
223
 
229
224
  var prev = this._prevStoreKeys,
@@ -263,13 +258,6 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
263
258
  */
264
259
  _storeKeysContentDidChange: function(target, key, value, rev) {
265
260
  this._records = null ; // clear cache
266
- // if this record array is based on a queryKey reapply the
267
- // the query before setting the storeKeys to ensure it always conforms
268
-
269
- if(SC.instanceOf(this.queryKey, SC.Query)) {
270
- this.storeKeys = SC.Query.containsStoreKeys(this.queryKey, value, this.store);
271
- this.notifyPropertyChange('length');
272
- }
273
261
 
274
262
  this.beginPropertyChanges()
275
263
  .notifyPropertyChange('length')
@@ -279,9 +267,20 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
279
267
 
280
268
  init: function() {
281
269
  sc_super();
282
- this._storeKeysDidChange();
270
+
271
+ // if this record array is based on a queryKey apply the
272
+ // the query before setting the storeKeys to ensure it always conforms
273
+ if(SC.instanceOf(this.queryKey, SC.Query)) {
274
+ var queryKey = this.get('queryKey'), recordTypes = SC.Set.create();
275
+ recordTypes.push(queryKey.get('recordType'));
276
+
277
+ this.applyQuery(this.get('storeKeys'), recordTypes);
278
+ }
279
+ else {
280
+ this._storeKeysDidChange();
281
+ }
282
+
283
283
  }
284
284
 
285
-
286
285
  });
287
286