sproutcore 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ } ;