sproutcore 0.9.0

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 (270) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +269 -0
  4. data/README.txt +67 -0
  5. data/Rakefile +4 -0
  6. data/app_generators/sproutcore/USAGE +5 -0
  7. data/app_generators/sproutcore/sproutcore_generator.rb +66 -0
  8. data/app_generators/sproutcore/templates/README +77 -0
  9. data/app_generators/sproutcore/templates/environment.yml +4 -0
  10. data/bin/sc-build +145 -0
  11. data/bin/sc-gen +24 -0
  12. data/bin/sc-server +63 -0
  13. data/bin/sproutcore +21 -0
  14. data/clients/sc_docs/controllers/docs.js +118 -0
  15. data/clients/sc_docs/core.js +19 -0
  16. data/clients/sc_docs/english.lproj/body.css +159 -0
  17. data/clients/sc_docs/english.lproj/body.rhtml +33 -0
  18. data/clients/sc_docs/english.lproj/controls.css +0 -0
  19. data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
  20. data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
  21. data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
  22. data/clients/sc_docs/english.lproj/images/indicator.gif +0 -0
  23. data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
  24. data/clients/sc_docs/english.lproj/no_docs.rhtml +7 -0
  25. data/clients/sc_docs/english.lproj/strings.js +14 -0
  26. data/clients/sc_docs/english.lproj/warning.rhtml +6 -0
  27. data/clients/sc_docs/fixtures/doc.js +11 -0
  28. data/clients/sc_docs/main.js +21 -0
  29. data/clients/sc_docs/models/doc.js +9 -0
  30. data/clients/sc_docs/tests/controllers/docs.rhtml +21 -0
  31. data/clients/sc_docs/tests/models/doc.rhtml +21 -0
  32. data/clients/sc_docs/tests/views/doc_frame.rhtml +21 -0
  33. data/clients/sc_docs/tests/views/doc_label_view.rhtml +21 -0
  34. data/clients/sc_docs/views/doc_frame.js +33 -0
  35. data/clients/sc_docs/views/doc_label.js +20 -0
  36. data/clients/sc_test_runner/controllers/runner.js +175 -0
  37. data/clients/sc_test_runner/core.js +19 -0
  38. data/clients/sc_test_runner/english.lproj/body.css +151 -0
  39. data/clients/sc_test_runner/english.lproj/body.rhtml +35 -0
  40. data/clients/sc_test_runner/english.lproj/controls.css +0 -0
  41. data/clients/sc_test_runner/english.lproj/icons/small/next.png +0 -0
  42. data/clients/sc_test_runner/english.lproj/icons/small/reset.png +0 -0
  43. data/clients/sc_test_runner/english.lproj/images/gradients.png +0 -0
  44. data/clients/sc_test_runner/english.lproj/images/indicator.gif +0 -0
  45. data/clients/sc_test_runner/english.lproj/images/toolbar.png +0 -0
  46. data/clients/sc_test_runner/english.lproj/no_tests.rhtml +6 -0
  47. data/clients/sc_test_runner/english.lproj/strings.js +14 -0
  48. data/clients/sc_test_runner/english.lproj/warning.rhtml +6 -0
  49. data/clients/sc_test_runner/fixtures/test.js +12 -0
  50. data/clients/sc_test_runner/main.js +26 -0
  51. data/clients/sc_test_runner/models/test.js +11 -0
  52. data/clients/sc_test_runner/views/runner_frame.js +72 -0
  53. data/clients/sc_test_runner/views/test_label.js +20 -0
  54. data/config/hoe.rb +70 -0
  55. data/config/requirements.rb +17 -0
  56. data/environment.yml +9 -0
  57. data/frameworks/prototype/prototype.js +4186 -0
  58. data/frameworks/sproutcore/Core.js +378 -0
  59. data/frameworks/sproutcore/README +3 -0
  60. data/frameworks/sproutcore/controllers/array.js +236 -0
  61. data/frameworks/sproutcore/controllers/collection.js +305 -0
  62. data/frameworks/sproutcore/controllers/controller.js +323 -0
  63. data/frameworks/sproutcore/controllers/object.js +372 -0
  64. data/frameworks/sproutcore/drag/drag.js +549 -0
  65. data/frameworks/sproutcore/drag/drag_data_source.js +32 -0
  66. data/frameworks/sproutcore/drag/drag_source.js +64 -0
  67. data/frameworks/sproutcore/drag/drop_target.js +153 -0
  68. data/frameworks/sproutcore/english.lproj/blank.gif +0 -0
  69. data/frameworks/sproutcore/english.lproj/buttons.css +589 -0
  70. data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
  71. data/frameworks/sproutcore/english.lproj/inline_text_editor.css +21 -0
  72. data/frameworks/sproutcore/english.lproj/menu.css +121 -0
  73. data/frameworks/sproutcore/english.lproj/panels/background-fat.jpg +0 -0
  74. data/frameworks/sproutcore/english.lproj/panels/background-thin.jpg +0 -0
  75. data/frameworks/sproutcore/english.lproj/panels/bottom-edge.png +0 -0
  76. data/frameworks/sproutcore/english.lproj/panels/bottom-left-corner.png +0 -0
  77. data/frameworks/sproutcore/english.lproj/panels/bottom-right-corner.png +0 -0
  78. data/frameworks/sproutcore/english.lproj/panels/left-edge.png +0 -0
  79. data/frameworks/sproutcore/english.lproj/panels/overlay.png +0 -0
  80. data/frameworks/sproutcore/english.lproj/panels/right-edge.png +0 -0
  81. data/frameworks/sproutcore/english.lproj/panels/top-edge.png +0 -0
  82. data/frameworks/sproutcore/english.lproj/panels/top-left-corner.png +0 -0
  83. data/frameworks/sproutcore/english.lproj/panels/top-right-corner.png +0 -0
  84. data/frameworks/sproutcore/english.lproj/panes.css +155 -0
  85. data/frameworks/sproutcore/english.lproj/picker.css +22 -0
  86. data/frameworks/sproutcore/english.lproj/strings.js +15 -0
  87. data/frameworks/sproutcore/english.lproj/tab.css +23 -0
  88. data/frameworks/sproutcore/english.lproj/tests.css +67 -0
  89. data/frameworks/sproutcore/english.lproj/theme.css +77 -0
  90. data/frameworks/sproutcore/foundation/animator.js +670 -0
  91. data/frameworks/sproutcore/foundation/application.js +199 -0
  92. data/frameworks/sproutcore/foundation/array.js +348 -0
  93. data/frameworks/sproutcore/foundation/benchmark.js +211 -0
  94. data/frameworks/sproutcore/foundation/binding.js +384 -0
  95. data/frameworks/sproutcore/foundation/date.js +357 -0
  96. data/frameworks/sproutcore/foundation/error.js +39 -0
  97. data/frameworks/sproutcore/foundation/input_manager.js +153 -0
  98. data/frameworks/sproutcore/foundation/json.js +296 -0
  99. data/frameworks/sproutcore/foundation/mock.js +42 -0
  100. data/frameworks/sproutcore/foundation/node_descriptor.js +56 -0
  101. data/frameworks/sproutcore/foundation/object.js +777 -0
  102. data/frameworks/sproutcore/foundation/observable.js +451 -0
  103. data/frameworks/sproutcore/foundation/page.js +63 -0
  104. data/frameworks/sproutcore/foundation/path_module.js +413 -0
  105. data/frameworks/sproutcore/foundation/responder.js +310 -0
  106. data/frameworks/sproutcore/foundation/routes.js +371 -0
  107. data/frameworks/sproutcore/foundation/run_loop.js +21 -0
  108. data/frameworks/sproutcore/foundation/server.js +491 -0
  109. data/frameworks/sproutcore/foundation/set.js +96 -0
  110. data/frameworks/sproutcore/foundation/string.js +149 -0
  111. data/frameworks/sproutcore/foundation/undo_manager.js +186 -0
  112. data/frameworks/sproutcore/foundation/unittest.js +622 -0
  113. data/frameworks/sproutcore/foundation/utils.js +61 -0
  114. data/frameworks/sproutcore/globals/panels.js +182 -0
  115. data/frameworks/sproutcore/globals/popups.js +60 -0
  116. data/frameworks/sproutcore/globals/window.js +381 -0
  117. data/frameworks/sproutcore/lib/index.rhtml +66 -0
  118. data/frameworks/sproutcore/models/collection.js +395 -0
  119. data/frameworks/sproutcore/models/record.js +622 -0
  120. data/frameworks/sproutcore/models/store.js +295 -0
  121. data/frameworks/sproutcore/panes/dialog.js +16 -0
  122. data/frameworks/sproutcore/panes/manager.js +164 -0
  123. data/frameworks/sproutcore/panes/menu.js +45 -0
  124. data/frameworks/sproutcore/panes/overlay.js +231 -0
  125. data/frameworks/sproutcore/panes/pane.js +90 -0
  126. data/frameworks/sproutcore/panes/panel.js +19 -0
  127. data/frameworks/sproutcore/panes/picker.js +45 -0
  128. data/frameworks/sproutcore/tests/controllers/array.rhtml +86 -0
  129. data/frameworks/sproutcore/tests/controllers/controller.rhtml +273 -0
  130. data/frameworks/sproutcore/tests/controllers/object.rhtml +327 -0
  131. data/frameworks/sproutcore/tests/foundation/application.rhtml +125 -0
  132. data/frameworks/sproutcore/tests/foundation/array.rhtml +221 -0
  133. data/frameworks/sproutcore/tests/foundation/object.rhtml +69 -0
  134. data/frameworks/sproutcore/tests/globals/window.rhtml +45 -0
  135. data/frameworks/sproutcore/tests/panes/pane.rhtml +88 -0
  136. data/frameworks/sproutcore/tests/views/collection.rhtml +137 -0
  137. data/frameworks/sproutcore/tests/views/popup_button.rhtml +115 -0
  138. data/frameworks/sproutcore/tests/views/text_field.rhtml +37 -0
  139. data/frameworks/sproutcore/validators/credit_card.js +92 -0
  140. data/frameworks/sproutcore/validators/date.js +36 -0
  141. data/frameworks/sproutcore/validators/email.js +29 -0
  142. data/frameworks/sproutcore/validators/not_empty.js +24 -0
  143. data/frameworks/sproutcore/validators/number.js +55 -0
  144. data/frameworks/sproutcore/validators/password.js +78 -0
  145. data/frameworks/sproutcore/validators/validator.js +304 -0
  146. data/frameworks/sproutcore/views/button.js +425 -0
  147. data/frameworks/sproutcore/views/checkbox_field.js +30 -0
  148. data/frameworks/sproutcore/views/collection.js +1521 -0
  149. data/frameworks/sproutcore/views/container.js +62 -0
  150. data/frameworks/sproutcore/views/error_explanation.js +45 -0
  151. data/frameworks/sproutcore/views/field.js +214 -0
  152. data/frameworks/sproutcore/views/filter_button.js +29 -0
  153. data/frameworks/sproutcore/views/form.js +591 -0
  154. data/frameworks/sproutcore/views/image.js +141 -0
  155. data/frameworks/sproutcore/views/inline_text_editor.js +96 -0
  156. data/frameworks/sproutcore/views/label.js +176 -0
  157. data/frameworks/sproutcore/views/menu_item.js +90 -0
  158. data/frameworks/sproutcore/views/pagination.js +54 -0
  159. data/frameworks/sproutcore/views/popup_button.js +86 -0
  160. data/frameworks/sproutcore/views/popup_menu.js +137 -0
  161. data/frameworks/sproutcore/views/progress.js +100 -0
  162. data/frameworks/sproutcore/views/radio_field.js +107 -0
  163. data/frameworks/sproutcore/views/radio_group.js +48 -0
  164. data/frameworks/sproutcore/views/segmented.js +80 -0
  165. data/frameworks/sproutcore/views/select_field.js +272 -0
  166. data/frameworks/sproutcore/views/spinner.js +11 -0
  167. data/frameworks/sproutcore/views/tab.js +126 -0
  168. data/frameworks/sproutcore/views/text_field.js +179 -0
  169. data/frameworks/sproutcore/views/textarea_field.js +14 -0
  170. data/frameworks/sproutcore/views/toolbar.js +29 -0
  171. data/frameworks/sproutcore/views/view.js +1389 -0
  172. data/frameworks/sproutcore/views/workspace.js +170 -0
  173. data/generators/client/README +3 -0
  174. data/generators/client/USAGE +12 -0
  175. data/generators/client/client_generator.rb +53 -0
  176. data/generators/client/templates/core.js +19 -0
  177. data/generators/client/templates/english.lproj/body.css +0 -0
  178. data/generators/client/templates/english.lproj/body.rhtml +3 -0
  179. data/generators/client/templates/english.lproj/controls.css +0 -0
  180. data/generators/client/templates/english.lproj/strings.js +14 -0
  181. data/generators/client/templates/main.js +37 -0
  182. data/generators/controller/USAGE +16 -0
  183. data/generators/controller/controller_generator.rb +51 -0
  184. data/generators/controller/templates/controller.js +21 -0
  185. data/generators/controller/templates/test.rhtml +21 -0
  186. data/generators/framework/README +7 -0
  187. data/generators/framework/USAGE +12 -0
  188. data/generators/framework/framework_generator.rb +53 -0
  189. data/generators/framework/templates/core.js +20 -0
  190. data/generators/framework/templates/english.lproj/body.css +0 -0
  191. data/generators/framework/templates/english.lproj/body.rhtml +3 -0
  192. data/generators/framework/templates/english.lproj/controls.css +0 -0
  193. data/generators/framework/templates/english.lproj/strings.js +14 -0
  194. data/generators/language/USAGE +16 -0
  195. data/generators/language/language_generator.rb +47 -0
  196. data/generators/language/templates/strings.js +10 -0
  197. data/generators/model/USAGE +24 -0
  198. data/generators/model/model_generator.rb +55 -0
  199. data/generators/model/templates/fixture.js +11 -0
  200. data/generators/model/templates/model.js +20 -0
  201. data/generators/model/templates/test.rhtml +21 -0
  202. data/generators/test/USAGE +16 -0
  203. data/generators/test/templates/test.rhtml +21 -0
  204. data/generators/test/test_generator.rb +47 -0
  205. data/generators/view/USAGE +16 -0
  206. data/generators/view/templates/test.rhtml +21 -0
  207. data/generators/view/templates/view.js +20 -0
  208. data/generators/view/view_generator.rb +51 -0
  209. data/jsdoc/README.txt +119 -0
  210. data/jsdoc/app/DocFile.js +137 -0
  211. data/jsdoc/app/DocTag.js +110 -0
  212. data/jsdoc/app/Doclet.js +63 -0
  213. data/jsdoc/app/Dumper.js +143 -0
  214. data/jsdoc/app/JsDoc.js +103 -0
  215. data/jsdoc/app/JsHilite.js +45 -0
  216. data/jsdoc/app/JsIO.js +163 -0
  217. data/jsdoc/app/JsParse.js +385 -0
  218. data/jsdoc/app/JsPlate.js +130 -0
  219. data/jsdoc/app/JsTestrun.js +129 -0
  220. data/jsdoc/app/JsToke.js +564 -0
  221. data/jsdoc/app/Symbol.js +298 -0
  222. data/jsdoc/app/Transformer.js +14 -0
  223. data/jsdoc/app/Util.js +97 -0
  224. data/jsdoc/app/js.jar +0 -0
  225. data/jsdoc/app/run.js +144 -0
  226. data/jsdoc/plugins/min.js +316 -0
  227. data/jsdoc/plugins/strip.js +20 -0
  228. data/jsdoc/templates/sproutcore/class.tmpl +438 -0
  229. data/jsdoc/templates/sproutcore/default.css +241 -0
  230. data/jsdoc/templates/sproutcore/index.html +13 -0
  231. data/jsdoc/templates/sproutcore/index.tmpl +21 -0
  232. data/jsdoc/templates/sproutcore/prototype.js +4186 -0
  233. data/jsdoc/templates/sproutcore/publish.js +236 -0
  234. data/jsdoc/templates/sproutcore/splash.html +7 -0
  235. data/lib/sproutcore/build_tools/html_builder.rb +88 -0
  236. data/lib/sproutcore/build_tools/resource_builder.rb +194 -0
  237. data/lib/sproutcore/build_tools.rb +44 -0
  238. data/lib/sproutcore/bundle.rb +517 -0
  239. data/lib/sproutcore/bundle_manifest.rb +397 -0
  240. data/lib/sproutcore/generator_helper.rb +170 -0
  241. data/lib/sproutcore/helpers/capture_helper.rb +42 -0
  242. data/lib/sproutcore/helpers/static_helper.rb +80 -0
  243. data/lib/sproutcore/helpers/tag_helper.rb +110 -0
  244. data/lib/sproutcore/helpers/text_helper.rb +336 -0
  245. data/lib/sproutcore/helpers.rb +3 -0
  246. data/lib/sproutcore/jsdoc.rb +40 -0
  247. data/lib/sproutcore/jsmin.rb +247 -0
  248. data/lib/sproutcore/library.rb +258 -0
  249. data/lib/sproutcore/merb/bundle_controller.rb +179 -0
  250. data/lib/sproutcore/merb/router.rb +43 -0
  251. data/lib/sproutcore/merb.rb +27 -0
  252. data/lib/sproutcore/version.rb +9 -0
  253. data/lib/sproutcore/view_helpers/button_views.rb +302 -0
  254. data/lib/sproutcore/view_helpers/core_views.rb +284 -0
  255. data/lib/sproutcore/view_helpers/form_views.rb +258 -0
  256. data/lib/sproutcore/view_helpers/menu_views.rb +94 -0
  257. data/lib/sproutcore/view_helpers.rb +628 -0
  258. data/lib/sproutcore.rb +30 -0
  259. data/script/destroy +14 -0
  260. data/script/generate +14 -0
  261. data/script/txt2html +74 -0
  262. data/setup.rb +1585 -0
  263. data/spec/spec.opts +1 -0
  264. data/spec/spec_helper.rb +7 -0
  265. data/spec/sproutcore_spec.rb +11 -0
  266. data/tasks/deployment.rake +34 -0
  267. data/tasks/environment.rake +7 -0
  268. data/tasks/rspec.rake +21 -0
  269. data/tasks/website.rake +17 -0
  270. metadata +365 -0
@@ -0,0 +1,491 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('Core') ;
7
+
8
+ // The Server object knows how to send requests to the server and how to
9
+ // get things back from the server. It automatically handles situations
10
+ // such as 304 caching and queuing requests to send to the server later if
11
+ // the computer becomes disconnected from the internet.
12
+
13
+ // The Server object is designed to work with a resource oriented application.
14
+ // That is, you do someting like this:
15
+ //
16
+ // Server.request('resource','verb',{ parameters })
17
+ // or
18
+ // Server.create('resource',{ parameters })
19
+ // Server.refresh('resource',{ parameters })
20
+ // Server.update('resource',{ parameters })
21
+ // Server.destroy('resource',{ parameters })
22
+ //
23
+ // parameters include:
24
+ // onSuccess -- passes back returned text
25
+ // onFailure --
26
+ //
27
+ //
28
+ // SC.Record.refresh
29
+ // SC.Record.commit --> create/update
30
+ // SC.Record.destroy
31
+ SC.Server = SC.Object.extend({
32
+
33
+ // Set this to the prefix for your app. Server will use this to convert
34
+ // record_type properties into recordTypes.
35
+ prefix: null,
36
+
37
+ // Set this string to the format to be used to set your resource and verb.
38
+ urlFormat: '/%@/%@',
39
+
40
+ // call this in your main to preload any data sent from the server with the
41
+ // initial page load.
42
+ preload: function(clientData) {
43
+ if ((!clientData) || (clientData.size == 0)) return ;
44
+ this.refreshRecordsWithData(clientData,SC.Record,null,false);
45
+ },
46
+
47
+ // This is the root method for accessing a server resource. Pass in the
48
+ // resource URL, verb name, and any parameters. There are several special-
49
+ // purpose parameters used also:
50
+ //
51
+ // onSuccess -- function invoked when request completes. Expects the format
52
+ // didSucceed(status,ajaxRequest,cacheCode,context)
53
+ // onFailure -- function invoked when request fails. Same format.
54
+ // requestContext -- simply passed back.
55
+ // cacheCode -- String indicating the time of the last refresh.
56
+ //
57
+ request: function(resource, verb, ids, params, method) {
58
+
59
+ // Get Settings and Options
60
+ if (!params) params = {} ;
61
+ var opts = {} ;
62
+ var onSuccess = params.onSuccess; delete params.onSuccess;
63
+ var onNotModified = params.onNotModified; delete params.onNotModified ;
64
+ var onFailure = params.onFailure ; delete params.onFailure ;
65
+ var context = params.requestContext ; delete params.requestContext ;
66
+ var cacheCode = params.cacheCode; delete params.cacheCode ;
67
+
68
+ // handle ids
69
+ var idPart = '' ;
70
+ if (ids) if (ids.length > 1) {
71
+ params.ids = [ids].flatten().join(',') ;
72
+ } else if (ids.length == 1) {
73
+ idPart = '/' + ids[0] ;
74
+ }
75
+
76
+ // convert parameters.
77
+ var parameters = this._toQueryString(params) ;
78
+ if (parameters && parameters.length > 0) opts.parameters = parameters ;
79
+
80
+ // prepare request headers and options
81
+ if (cacheCode) opts.requestHeaders = ['Sproutit-Cache',cacheCode] ;
82
+ opts.method = method || 'get' ;
83
+ var url = this.urlFormat.format(resource,verb) + idPart;
84
+ var request = null ; //will container the ajax request
85
+
86
+ // Save callback functions.
87
+ opts.onSuccess = function(transport) {
88
+ var cacheCode = request.getHeader('Last-Modified') ;
89
+ if ((transport.status == '200') && (transport.responseText == '304 Not Modified')) {
90
+ if (onNotModified) onNotModified(transport.status, transport, cacheCode,context);
91
+ } else {
92
+ if (onSuccess) onSuccess(transport.status, transport, cacheCode,context);
93
+ }
94
+ } ;
95
+
96
+ opts.onFailure = function(transport) {
97
+ var cacheCode = request.getHeader('Last-Modified') ;
98
+ if (onFailure) onFailure(transport.status, transport, cacheCode,context);
99
+ } ;
100
+
101
+ request = new Ajax.Request(url,opts) ;
102
+ },
103
+
104
+
105
+ // RECORD METHODS
106
+ // These methods do the basic record changes.
107
+
108
+
109
+ // ..........................................
110
+ // LIST
111
+ // This is the method called by a collection to get an updated list of
112
+ // records.
113
+ listFor: function(opts) {
114
+ var recordType = opts.recordType ;
115
+ var resource = recordType.resourceURL() ;
116
+ if (!resource) return false ;
117
+
118
+ var order = opts.order || 'id' ;
119
+ if (!(order instanceof Array)) order = [order] ;
120
+ order = order.map(function(str){
121
+ return str.decamelize() ; //rubyify
122
+ }).join(',') ;
123
+
124
+ params = {} ;
125
+ if (opts.conditions) {
126
+ var conditions = this._decamelizeData(opts.conditions) ;
127
+ for(var key in conditions) {
128
+ params[key] = conditions[key] ;
129
+ }
130
+ }
131
+
132
+ params.requestContext = opts ;
133
+ params.onSuccess = this._listSuccess.bind(this) ;
134
+ params.onNotModified = this._listNotModified.bind(this) ;
135
+ params.onFailure = this._listFailure.bind(this) ;
136
+ if (opts.cacheCode) params.cacheCode = opts.cacheCode ;
137
+ if (opts.offset) params.offset = opts.offset;
138
+ if (opts.limit) params.limit = opts.limit ;
139
+ if (order) params.order = order ;
140
+
141
+ this.request(resource,'list',null,params) ;
142
+ },
143
+
144
+ _listSuccess: function(status, transport, cacheCode, context) {
145
+ var json = eval('json='+transport.responseText) ;
146
+ if (!json) { console.log('invalid json!'); return; }
147
+
148
+ // first, build any records passed back
149
+ if (json.records) {
150
+ this.refreshRecordsWithData(json.records,context.recordType,cacheCode,false);
151
+ }
152
+
153
+ // next, convert the list of ids into records.
154
+ var recs = (json.ids) ? json.ids.map(function(guid) {
155
+ return SC.Store.getRecordFor(guid,context.recordType) ;
156
+ }) : [] ;
157
+
158
+ // now invoke callback
159
+ if (context.callback) context.callback(recs,json.count,cacheCode) ;
160
+ },
161
+
162
+ _listNotModified: function(status, transport, cacheCode, context) {
163
+ if (context.callback) context.callback(null,null,null) ;
164
+ },
165
+
166
+ _listFailure: function(status, transport, cacheCode, records) {
167
+ console.log('listFailed!') ;
168
+ },
169
+
170
+
171
+ // ..........................................
172
+ // CREATE
173
+
174
+ // send the records back to create them. added a special parameter to
175
+ // the hash for each record, _guid, which will be used onSuccess.
176
+ createRecords: function(records) {
177
+ if (!records || records.length == 0) return ;
178
+
179
+ records = this._recordsByResource(records) ; // sort by resource.
180
+ for(var resource in records) {
181
+ if (resource == '*') continue ;
182
+
183
+ var curRecords = records[resource] ;
184
+
185
+ // collect data for records
186
+ var server = this ; var context = {} ;
187
+ var data = curRecords.map(function(rec) {
188
+ var recData = server._decamelizeData(rec.getPropertyData()) ;
189
+ recData._guid = rec._guid ;
190
+ context[rec._guid] = rec ;
191
+ rec.set('newRecord',false) ;
192
+ return recData ;
193
+ }) ;
194
+
195
+ // issue request
196
+ this.request(resource,'create',null,{
197
+ requestContext: context,
198
+ onSuccess: this._createSuccess.bind(this),
199
+ onFailure: this._createFailure.bind(this),
200
+ records: data
201
+ },'post') ;
202
+ }
203
+ },
204
+
205
+ // This method is called when a create is successful. It first goes through
206
+ // and assigns the primaryKey to each record.
207
+ _createSuccess: function(status, transport, cacheCode, context) {
208
+ var json = eval('json='+transport.responseText) ;
209
+ if (!(json instanceof Array)) json = [json] ;
210
+
211
+ // first go through and assign the primaryKey to each record.
212
+ if (!context) context = {} ;
213
+ json.each(function(data) {
214
+ var guid = data._guid ;
215
+ var rec = (guid) ? context[guid] : null ;
216
+ if (rec) {
217
+ var pk = rec.get('primaryKey') ;
218
+ var dataKey = (pk == 'guid') ? 'id' : pk.decamelize().toLowerCase().replace(/\-/g,'_') ;
219
+ rec.set(pk,data[dataKey]) ;
220
+ }
221
+ }) ;
222
+
223
+ // now this method will work so go do it.
224
+ this.refreshRecordsWithData(json,context._recordType,cacheCode,true) ;
225
+ },
226
+
227
+ _createFailure: function(status, transport, cacheCode, records) {
228
+ console.log('createFailed!') ;
229
+ },
230
+
231
+
232
+ // ..........................................
233
+ // REFRESH
234
+
235
+ refreshRecords: function(records) {
236
+ if (!records || records.length == 0) return ;
237
+
238
+ records = this._recordsByResource(records) ; // sort by resource.
239
+ for(var resource in records) {
240
+ if (resource == '*') continue ;
241
+
242
+ var curRecords = records[resource] ;
243
+
244
+ // collect resource ids, sort records into hash, and get cacheCode.
245
+ var cacheCode = null ; var ids = [] ; var context = {} ;
246
+ var primaryKey = curRecords[0].get('primaryKey') ; // assumes all the same
247
+ curRecords.each(function(r) {
248
+ cacheCode = cacheCode || r._cacheCode ;
249
+ var key = r.get(primaryKey);
250
+ if (key) { ids.push(key); context[key] = r; }
251
+ });
252
+ context._recordType = curRecords[0].recordType ; // default rec type.
253
+
254
+ // issue request
255
+ this.request(resource,'show',ids,{
256
+ requestContext: context,
257
+ cacheCode: ((cacheCode=='') ? null : cacheCode),
258
+ onSuccess: this._refreshSuccess.bind(this),
259
+ onFailure: this._refreshFailure.bind(this)
260
+ }) ;
261
+ }
262
+ },
263
+
264
+ // This method is called when a refresh is successful. It expects an array
265
+ // of hashes, which it will convert to records.
266
+ _refreshSuccess: function(status, transport, cacheCode, context) {
267
+ var json = eval('json='+transport.responseText) ;
268
+ if (!(json instanceof Array)) json = [json] ;
269
+ this.refreshRecordsWithData(json,context._recordType,cacheCode,true) ;
270
+ },
271
+
272
+ _refreshFailure: function(status, transport, cacheCode, records) {
273
+ console.log('refreshFailed!') ;
274
+ },
275
+
276
+ // ..........................................
277
+ // COMMIT
278
+
279
+ commitRecords: function(records) {
280
+ if (!records || records.length == 0) return ;
281
+
282
+ records = this._recordsByResource(records) ; // sort by resource.
283
+ for(var resource in records) {
284
+ if (resource == '*') continue ;
285
+
286
+ var curRecords = records[resource] ;
287
+
288
+ // collect data for records
289
+ var server = this ;
290
+ var data = curRecords.map(function(rec) {
291
+ return server._decamelizeData(rec.getPropertyData()) ;
292
+ }) ;
293
+
294
+ // issue request
295
+ this.request(resource,'update',null,{
296
+ requestContext: records,
297
+ onSuccess: this._commitSuccess.bind(this),
298
+ onFailure: this._commitFailure.bind(this),
299
+ records: data
300
+ },'post') ;
301
+ }
302
+ },
303
+
304
+ // This method is called when a refresh is successful. It expects an array
305
+ // of hashes, which it will convert to records.
306
+ _commitSuccess: function(status, transport, cacheCode, context) {
307
+ var json = eval('json='+transport.responseText) ;
308
+ if (!(json instanceof Array)) json = [json] ;
309
+ this.refreshRecordsWithData(json,context._recordType,cacheCode,true) ;
310
+ },
311
+
312
+ _commitFailure: function(status, transport, cacheCode, records) {
313
+ console.log('commitFailed!') ;
314
+ },
315
+
316
+ // ..........................................
317
+ // DESTROY
318
+
319
+ destroyRecords: function(records) {
320
+ if (!records || records.length == 0) return ;
321
+
322
+ records = this._recordsByResource(records) ; // sort by resource.
323
+ for(var resource in records) {
324
+ var curRecords = records[resource] ;
325
+
326
+ if (resource == '*') {
327
+ curRecords.each(function(rec){
328
+ rec.set('isDeleted',true) ;
329
+ SC.Store.removeRecord(rec) ;
330
+ });
331
+ continue ;
332
+ }
333
+
334
+ // collect resource ids, sort records into hash, and get cacheCode.
335
+ var ids = [] ; var key ;
336
+ var primaryKey = curRecords[0].get('primaryKey') ;
337
+
338
+ curRecords.each(function(rec) {
339
+ if ((key = rec.get(primaryKey)) && (!rec.get('newRecord'))) {
340
+ ids.push(key) ;
341
+ }
342
+ rec.set('isDeleted',true) ;
343
+ SC.Store.removeRecord(rec) ;
344
+ }) ;
345
+
346
+ // issue request -- we may not have ids to send tho (for ex, if all
347
+ // records were newRecords.)
348
+ if (ids && ids.length > 0) this.request(resource,'destroy',ids,{
349
+ requestContext: records,
350
+ onSuccess: this._destroySuccess.bind(this),
351
+ onFailure: this._destroyFailure.bind(this)
352
+ },'post') ;
353
+ }
354
+ },
355
+
356
+ _destroySuccess: function(status, transport, cacheCode, records) {
357
+ console.log('destroySuccess!') ;
358
+ },
359
+
360
+ _destroyFailure: function(status, transport, cacheCode, records) {
361
+ console.log('destroyFailed!') ;
362
+ },
363
+
364
+ // ..........................................
365
+ // SUPPORT
366
+
367
+ // This method is called by the various handlers once they have extracted
368
+ // their data.
369
+ refreshRecordsWithData: function(dataAry,recordType,cacheCode,loaded) {
370
+ var server = this ;
371
+ // first, prepare each data item in the Ary.
372
+ dataAry = dataAry.map(function(data) {
373
+
374
+ // camelize the keys received back.
375
+ data = server._camelizeData(data) ;
376
+
377
+ // convert the 'id' property to 'guid'
378
+ if (data.id) { data.guid = data.id; delete data.id; }
379
+
380
+ // find the recordType
381
+ if (data.type) {
382
+ var recordName = data.type.capitalize()
383
+ if (server.prefix) for(var prefixLoc=0;prefixLoc < server.prefix.length; prefixLoc++) {
384
+ var namespace = window[server.prefix[prefixLoc]] ;
385
+ if (namespace) data.recordType = namespace[recordName] ;
386
+ if (data.recordType) break ;
387
+ } else data.recordType = window[recordName] ;
388
+ if (!data.recordType) console.log('skipping undefined recordType:'+recordName) ;
389
+ } else data.recordType = recordType ;
390
+ if (!data.recordType) return null; // could not process.
391
+
392
+ return data ;
393
+ }).compact() ;
394
+
395
+ // now update.
396
+ SC.Store.updateRecords(dataAry,server,recordType,loaded) ;
397
+ },
398
+
399
+ // ................................
400
+ // PRIVATE METHODS
401
+
402
+ // places records from array into hash, sorted by resourceURL.
403
+ _recordsByResource: function(records) {
404
+ var ret = {} ;
405
+ records.each(function(rec) {
406
+ var recs = ret[rec.resourceURL || '*'] || [] ;
407
+ recs.push(rec)
408
+ ret[rec.resourceURL || '*'] = recs ;
409
+ }) ;
410
+ return ret ;
411
+ },
412
+
413
+ _camelizeData: function(data) {
414
+ if (data == null) return data ;
415
+
416
+ // handle array
417
+ var that = this ;
418
+ if (data instanceof Array) return data.map(function(d){
419
+ return that._camelizeData(d) ;
420
+ }) ;
421
+
422
+ // handle other objects
423
+ if (typeof(data) == "object") {
424
+ var ret = {} ;
425
+ for(var key in data) {
426
+ var value = that._camelizeData(data[key]) ;
427
+ if (key == 'id') key = 'guid' ;
428
+ ret[key.replace(/_/g,'-').camelize()] = value ;
429
+ }
430
+ return ret ;
431
+ }
432
+
433
+ // otherwise just return value
434
+ return data ;
435
+ },
436
+
437
+ _decamelizeData: function(data) {
438
+ if (data == null) return data ;
439
+
440
+ // handle array
441
+ var that = this ;
442
+ if (data instanceof Array) return data.map(function(d){
443
+ return that._decamelizeData(d) ;
444
+ }) ;
445
+
446
+ // handle other objects
447
+ if (typeof(data) == "object") {
448
+ var ret = {} ;
449
+ for(var key in data) {
450
+ var value = that._decamelizeData(data[key]) ;
451
+ if (key == 'guid') key = 'id' ;
452
+ ret[key.decamelize()] = value ;
453
+ }
454
+ return ret ;
455
+ }
456
+
457
+ // otherwise just return value
458
+ return data ;
459
+ },
460
+
461
+ // converts a string, array, or hash into a query string. root is the
462
+ // root string applied to each element key. Used for nesting.
463
+ _toQueryString: function(params,rootKey) {
464
+
465
+ // handle nulls
466
+ if (params == null) {
467
+ return rootKey + '=';
468
+
469
+ // handle arrays
470
+ } else if (params instanceof Array) {
471
+ var ret = [] ;
472
+ for(var loc=0;loc<params.length;loc++) {
473
+ var key = (rootKey) ? (rootKey + '['+loc+']') : loc ;
474
+ ret.push(this._toQueryString(params[loc],key)) ;
475
+ }
476
+ return ret.join('&') ;
477
+
478
+ // handle objects
479
+ } else if (typeof(params) == "object") {
480
+ var ret = []
481
+ for(var cur in params) {
482
+ var key = (rootKey) ? (rootKey + '['+cur+']') : cur ;
483
+ ret.push(this._toQueryString(params[cur],key)) ;
484
+ }
485
+ return ret.join('&') ;
486
+
487
+ // handle other values
488
+ } else return [rootKey,params].join('=') ;
489
+ }
490
+
491
+ }) ;
@@ -0,0 +1,96 @@
1
+ // ==========================================================================
2
+ // SproutCore -- JavaScript Application Framework
3
+ // copyright 2006-2007, Sprout Systems, Inc. and contributors.
4
+ // ==========================================================================
5
+
6
+ require('foundation/array') ;
7
+
8
+ /**
9
+ @class An unordered collection for keeping objects.
10
+
11
+ A Set works a bit like an array except that its items are not ordered.
12
+ You can create a set to efficiently test for membership for an object.
13
+
14
+ @extends SC.Object
15
+
16
+ */
17
+ SC.Set = SC.Object.extend(Enumerable,
18
+ /** @scope SC.Set.prototype */
19
+ {
20
+
21
+ /**
22
+ This property will change as the number of objects in the set changes.
23
+
24
+ @type number
25
+ */
26
+ length: 0,
27
+
28
+ /**
29
+ Changes each time an object is updated or removed. Observe this to be notified of changes to the set.
30
+
31
+ @type number
32
+ */
33
+ revision: 0,
34
+
35
+ /**
36
+ Call this method to test for membership.
37
+ */
38
+ contains: function(obj) {
39
+ if (obj == null) return false ;
40
+ return [this._guidFor(obj)] == obj ;
41
+ },
42
+
43
+ /**
44
+ Call this method to add an object. performs a basic add.
45
+ */
46
+ add: function(obj) {
47
+ if (obj == null) return; // cannot add null to a set.
48
+ this[this._guidFor(obj)] = obj ;
49
+ this.incrementProperty('length') ;
50
+ this.incrementProperty('revision') ;
51
+ },
52
+
53
+ /**
54
+ Performs a basic remove
55
+ */
56
+ remove: function(obj) {
57
+ if (obj == null) return ;
58
+ delete this[this._guidFor(obj)] ;
59
+ this.decrementProperty('length') ;
60
+ this.incrementProperty('revision') ;
61
+ },
62
+
63
+ // .......................................
64
+ // PRIVATE
65
+ _guidFor: function(obj) {
66
+ return '@' + SC.getGUID(obj);
67
+ },
68
+
69
+ _each: function(iterator) {
70
+ for (var key in this) {
71
+ if (!this.hasOwnProperty(key)) continue ;
72
+ if (key[0] == '@') iterator(this[key]) ;
73
+ }
74
+ }
75
+
76
+ }) ;
77
+
78
+ SC.Set.prototype.push = SC.Set.prototype.unshift = SC.Set.prototype.add;
79
+ SC.Set.prototype.pop = SC.Set.prototype.shift = SC.Set.prototype.remove;
80
+
81
+ SC.Set._create = SC.Set.create ;
82
+
83
+ /**
84
+ To create a set, pass an array of items instead of a hash.
85
+ */
86
+ SC.Set.create = function(items) {
87
+ if (!items) items = [] ;
88
+ var hash = {}, loc = items.length ;
89
+ while(--loc >= 0) {
90
+ var item = items[loc];
91
+ if (item == null) continue ;
92
+ hash[SC.Set.prototype._guidFor(item)] = item ;
93
+ }
94
+ hash.length = items.length ;
95
+ return SC.Set._create(hash) ;
96
+ } ;