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,295 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('foundation/object') ;
7
+
8
+ // The Store is where you can find all of your records. You should also
9
+ // use this to define your various types of records, since this will be
10
+ // used to automatically update from data coming from the server.
11
+ //
12
+ // You should create a store for each application. This allows the records
13
+ // for apps to be kept separate, even if they live in the same page.
14
+ //
15
+ SC.Store = SC.Object.create({
16
+
17
+ // This can be passed in from a Server to push updated data to all the
18
+ // named records. The parameter should be an array of hashes. Each hash
19
+ // can contain arrays or strings. Each one should also have a recordType
20
+ // property, which points to the record type. dataSource is the server.
21
+ // this will be automatically set on all the objects so that their future
22
+ // refreshes will come from the server.
23
+ updateRecords: function(dataHashes, dataSource, recordType, isLoaded) {
24
+
25
+ this.set('updateRecordsInProgress',true) ;
26
+ var store = this ;
27
+ var ret = [] ;
28
+ if (!recordType) recordType = SC.Record ;
29
+ this.beginPropertyChanges() ;
30
+
31
+ //SC.Benchmark._bench(function() {
32
+ dataHashes.each(function(data) {
33
+ var rt = data.recordType || recordType;
34
+ if (data.recordType !== undefined) delete data.recordType;
35
+
36
+ var pkValue = data[rt.primaryKey()] ;
37
+ var rec = store.getRecordFor(pkValue,rt,true) ;
38
+ rec.dataSource = dataSource ;
39
+ rec.updateAttributes(data, isLoaded, isLoaded) ;
40
+ if (rec.needsAddToStore) store.addRecord(rec) ;
41
+ ret.push(rec) ;
42
+ });
43
+ // },'dataHashes') ;
44
+
45
+ this.endPropertyChanges() ;
46
+ this.set('updateRecordsInProgress',false) ;
47
+ return ret ;
48
+ },
49
+
50
+ // ....................................
51
+ // Record dataSource methods
52
+ //
53
+
54
+ refreshRecords: function(records) {},
55
+
56
+ createRecords: function(recs) {
57
+ recs.invoke('set','newRecord','false') ;
58
+ this.commitRecords(recs);
59
+ },
60
+
61
+ commitRecords: function(recs) { recs.invoke('set','isDirty','false'); },
62
+
63
+ destroyRecords: function(recs) {
64
+ var store = this ;
65
+ recs.each(function(r) {
66
+ r.set('isDeleted',true); store.removeRecord(r);
67
+ });
68
+ },
69
+
70
+ // ....................................
71
+ // Record Helpers
72
+ //
73
+
74
+ // add a record instance to the store. The record will now be monitored for
75
+ // changes.
76
+ addRecord: function(rec) {
77
+ // save record in a cache
78
+ rec.needsAddToStore = false;
79
+ var guid = rec._storeKey();
80
+ var records = this._records[guid] || [];
81
+ records.push(rec);
82
+ this._records[guid] = records;
83
+
84
+ // global record cache
85
+ if (!this._quickCache) this._quickCache = {};
86
+
87
+ // records are cached by Class type
88
+ var records = this._quickCache[guid] || {};
89
+ var pkey = rec.get(rec.primaryKey);
90
+ records[pkey] = rec;
91
+ this._quickCache[guid] = records;
92
+
93
+ // and start observing it.
94
+ rec.addObserver('*',this._boundRecordObserver) ;
95
+ this.recordDidChange(rec) ;
96
+ },
97
+
98
+ // remove a record instance from the store. The record will no longer be
99
+ // monitored for changes and may be deleted.
100
+ removeRecord: function(rec) {
101
+ // remove from cache
102
+ var guid = rec._storeKey();
103
+ var records = this._records[guid] || [];
104
+ records = records.without(rec);
105
+ this._records[guid] = records;
106
+
107
+ // remove from quick cache
108
+ if (this._quickCache)
109
+ {
110
+ var records = this._quickCache[guid] || {};
111
+ var pkey = rec.get(rec.primaryKey);
112
+ delete records[pkey];
113
+ this._quickCache[guid] = records;
114
+ }
115
+
116
+ // and stop observing it.
117
+ rec.removeObserver('*',this._boundRecordObserver) ;
118
+ this.recordDidChange(rec) ; // this will remove from cols since destroyed.
119
+ },
120
+
121
+ /**
122
+ * Since records are cached by primaryKey, whenever that key changes we need to re-cache it in the proper place
123
+ * @param {string} oldkey Previous primary key
124
+ * @param {string} newkey New primary key
125
+ * @param {SC.Record} rec The object to relocate
126
+ * @return {SC.Record} The record passed in
127
+ **/
128
+ relocateRecord: function( oldkey, newkey, rec )
129
+ {
130
+ if (!this._quickCache) return rec;
131
+
132
+ var classKey = rec._storeKey();
133
+ var records = this._quickCache[classKey] || {};
134
+
135
+ records[newkey] = rec;
136
+ delete records[oldkey];
137
+
138
+ this._quickCache[classKey] = records;
139
+
140
+ return rec;
141
+ },
142
+
143
+
144
+ // You can pass any number of condition hashes to this, ending with a
145
+ // recordType. It will AND the results of each condition hash.
146
+ findRecords: function() {
147
+ var allConditions = $A(arguments) ;
148
+ var recordType = allConditions.pop() ;
149
+ var guid = recordType._storeKey() ;
150
+
151
+ // initial set of records.
152
+ var records = this._records[guid] ;
153
+
154
+ while(allConditions.length > 0) {
155
+ var conditions = allConditions.pop() ;
156
+ var ret = [] ; var loc = (records) ? records.length : 0;
157
+ while(--loc >= 0) {
158
+ var rec = records[loc] ;
159
+ if ((rec._type == recordType) || (rec._type.coreRecordType == recordType)) {
160
+ if (rec.matchConditions(conditions)) ret.push(rec) ;
161
+ }
162
+ }
163
+ records = ret ;
164
+ }
165
+
166
+ return records ;
167
+ },
168
+
169
+ // private method used by Record and Store. Returns null if the record does not exist.
170
+ _getRecordFor: function(pkValue,recordType) {
171
+ var guid = recordType._storeKey() ;
172
+ var records = (this._quickCache) ? this._quickCache[guid] : null;
173
+ var ret = (records) ? records[pkValue] : null ;
174
+ return ret ;
175
+ },
176
+
177
+ // finds the record with the primary key value. If the record does not
178
+ // exist, creates it.
179
+ getRecordFor: function(pkValue,recordType,dontAutoaddRecord) {
180
+ var ret = this._getRecordFor(pkValue,recordType) ;
181
+ if (!ret) {
182
+ var opts = {}; opts[recordType.primaryKey()] = pkValue;
183
+ ret = recordType.create(opts) ;
184
+ if (dontAutoaddRecord) {
185
+ ret.needsAddToStore = true ;
186
+ } else this.addRecord(ret) ;
187
+ }
188
+ return ret ;
189
+ },
190
+
191
+ // ....................................
192
+ // Collection Helpers
193
+ //
194
+
195
+ addCollection: function(collection) {
196
+ var guid = collection.recordType._storeKey() ;
197
+ var collections = this._collections[guid] || [] ;
198
+ collections.push(collection) ;
199
+ this._collections[guid] = collections ;
200
+ },
201
+
202
+ removeCollection: function(collection) {
203
+ var guid = collection.recordType._storeKey() ;
204
+ var collections = this._collections[guid] || [] ;
205
+ collections = collections.without(collection) ;
206
+ this._collections[guid] = collections ;
207
+ },
208
+
209
+ listFor: function(opts) {
210
+ var conditions = opts.conditions || {} ;
211
+ var order = opts.order || ['guid'] ;
212
+ var records = this.findRecords(conditions,opts.recordType) ;
213
+ var count = records.length ;
214
+
215
+ // sort
216
+ records = records.sort(function(a,b) { return a.compareTo(b,order); }) ;
217
+
218
+ // slice if needed.
219
+ if (opts.limit && (opts.limit > 0)) {
220
+ var start = (opts.offset) ? opts.offset : 0 ;
221
+ var end = start + opts.limit ;
222
+ records = records.slice(start,end) ;
223
+ }
224
+
225
+ // now run callback.
226
+ if (opts.callback) opts.callback(records,count) ;
227
+ },
228
+
229
+ // ....................................
230
+ // PRIVATE
231
+ //
232
+ _records: {}, _changedRecords: null, _collections: {},
233
+
234
+ // called whenever properties on a record change.
235
+ recordDidChange: function(rec) {
236
+ // add to changed records. This will eventually notify collections.
237
+ var guid = rec._storeKey() ;
238
+ changed = this.get('_changedRecords') || {};
239
+ records = changed[guid] || {} ;
240
+ records[rec._guid] = rec ;
241
+
242
+ changed[guid] = records ;
243
+ this.set('_changedRecords',changed) ;
244
+ },
245
+
246
+ // invoked whenever the changedRecords hash is updated. This will notify
247
+ // collections.
248
+ _changedRecordsObserver: function() {
249
+ // process changedRecords to notify collections.
250
+ for(var guid in this._changedRecords) {
251
+ var collections = this._collections[guid] ;
252
+ if (collections && collections.length>0) {
253
+
254
+ // collect records into array. Faster than using uniq.
255
+ var records = [] ;
256
+ for(var key in this._changedRecords[guid]) {
257
+ records.push(this._changedRecords[guid][key]) ;
258
+ }
259
+ var cloc = collections.length ;
260
+ while(--cloc >= 0) {
261
+
262
+ // for each collection watching this type of record, notify.
263
+ var col = collections[cloc] ;
264
+ col.beginPropertyChanges() ;
265
+ try {
266
+ // for each record...
267
+ var rloc = records.length ;
268
+ while(--rloc >= 0) {
269
+ var record = records[rloc] ;
270
+ // notify only if record type matches.
271
+ if (col.recordType == record._type) {
272
+ col.recordDidChange(record) ;
273
+ }
274
+ }
275
+ }
276
+ catch (e) {
277
+ console.log('EXCEPTION: While notifying collection') ;
278
+ }
279
+ col.endPropertyChanges() ;
280
+
281
+ }
282
+ }
283
+ }
284
+
285
+ // then clear changed records to start again.
286
+ this._changedRecords = {} ;
287
+
288
+ }.observes('_changedRecords'),
289
+
290
+ init: function() {
291
+ arguments.callee.base.call(this) ;
292
+ this._boundRecordObserver = this.recordDidChange.bind(this) ;
293
+ }
294
+
295
+ }) ;
@@ -0,0 +1,16 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('panes/overlay') ;
7
+
8
+ SC.DIALOG_PANE = 'dialog';
9
+ SC.DialogPaneView = SC.OverlayPaneView.extend({
10
+
11
+ emptyElement: '<div class="pane dialog-pane"><div class="pane-wrapper"><div class="pane-root"></div></div>',
12
+
13
+ layer: 200
14
+
15
+ }) ;
16
+
@@ -0,0 +1,164 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('views/view') ;
7
+
8
+ // The PaneManager is responsible for displaying pane that appear over your
9
+ // regular content. You can register your own pane types by calling
10
+ // PaneManager.registerPane('type',PaneClass) on app load.
11
+ //
12
+ // One instance of the PaneManager view is created the first time you try
13
+ // to show a pane.
14
+ SC.PaneManager = SC.View.extend({
15
+
16
+ emptyElement: '<div id="panes"></div>',
17
+
18
+ // this method will show a pane. Pass the content view and the paneType.
19
+ // if the pane is already visible, it will be hidden first. The optional
20
+ // event and root element will be set as properties on the wrapper pane
21
+ // before the pane is made visible so that it can position itself.
22
+ showPaneView: function(view, paneType, anchorView, triggerEvent) {
23
+
24
+ // if pane is already showing, hide the pane first...
25
+ this.hidePaneView(view) ;
26
+
27
+ // now get a pane instance for the specified paneType and add view to it.
28
+ var pane = this.getPaneFor(paneType) ;
29
+ pane._managedPaneType = paneType ;
30
+ pane.set('anchorView',anchorView) ;
31
+ pane.set('triggerEvent',triggerEvent) ;
32
+ pane.set('isVisible', false) ;
33
+ this._visiblePanes[view._guid] = pane ;
34
+
35
+ // look through child views (which are panes). Insert before first pane
36
+ // with a layer value > this pane.
37
+ var child= this.get('firstChild') ;
38
+ var layer = pane.get('layer');
39
+ while(child && (child.get('layer') <= layer)) {
40
+ child = child.get('nextSibling');
41
+ }
42
+
43
+ this.insertBefore(pane, child);
44
+
45
+ // if this pane is not visible, make it visible too.
46
+ this.set('isVisible',true) ;
47
+
48
+ // and make target pane visible, but set visibility hidden.
49
+ // visibility hidden will be turned off when the view is fully configured.
50
+ pane.setStyle({ visibility: 'hidden' }) ;
51
+ pane.set('isVisible',true) ;
52
+
53
+
54
+ this._setApplicationKeyPane();
55
+
56
+ // set content on view.
57
+ pane.set('content',view);
58
+ },
59
+
60
+ // this method will hide a visible pane view. Pass the content view. If
61
+ // the view is not already visible, this will do nothing.
62
+ hidePaneView: function(view) {
63
+ var pane = this._visiblePanes[view._guid] ;
64
+ if (!pane) return ;
65
+
66
+ // make pane not visible then do the rest of the cleanup when that
67
+ // finishes.
68
+ pane.addObserver('displayIsVisible', this._boundPaneDidHide) ;
69
+ pane.set('isVisible', false) ;
70
+ },
71
+
72
+ // this method will return a pave view for the specified type. If no panes
73
+ // of the type exist in the pane cache, then a new pane will be created.
74
+ getPaneFor: function(paneType) {
75
+ var panes = this._paneCache[paneType] ;
76
+ var pane = (panes) ? panes.pop() : null ;
77
+ if (pane) return pane ;
78
+
79
+ // no pane found in cache. Build one instead. First look for class in
80
+ // set of registered pane types. If that doesn't work, build class name.
81
+ var paneClass = this._paneTypes[paneType] ;
82
+ if (!paneClass) paneClass = SC[paneType.classify() + 'PaneView'] ;
83
+ if (!paneClass) {
84
+ throw "no matching class found for pane type '%@'".fmt(paneType);
85
+ }
86
+
87
+ // now create an instance.
88
+ pane = paneClass.viewFor(null) ;
89
+ return pane ;
90
+ },
91
+
92
+ // this method will add the pane instance to the pane cache for later use.
93
+ returnToCache: function(pane, paneType) {
94
+ var panes = this._paneCache[paneType] || [] ;
95
+ panes.push(pane) ;
96
+ this._paneCache[paneType] = panes;
97
+ },
98
+
99
+ // this method is called by the pane when it finishes hiding itself.
100
+ _paneDidHide: function(pane) {
101
+ var visible = pane.get('displayIsVisible') ;
102
+ if (visible) return ;
103
+
104
+ // remove this observer and remove pane from parent view.
105
+ pane.removeObserver('displayIsVisible', this._boundPanelDidHide) ;
106
+ pane.removeFromParent() ;
107
+
108
+ // now remove content view from pane and return pane to cache.
109
+ pane.set('content', null) ;
110
+ this.returnToCache(pane,pane._managedPaneType) ;
111
+
112
+ // if there are no more panes left visible, hide pane manager as well.
113
+ if (this.get('firstChild') == null) {
114
+ this.set('isVisible',false) ;
115
+ }
116
+
117
+ this._setApplicationKeyPane();
118
+ },
119
+
120
+ /**
121
+ * @todo Need to move this (and all of the pane display/hide interface) into SC.Application
122
+ */
123
+ _setApplicationKeyPane: function()
124
+ {
125
+ // ensure that the frontmost pane is the key pane
126
+ // we're making a lot of assumptions here... need to create a some unit tests that:
127
+ // lastChild is always a pane view
128
+ // calling makeKeyPane indiscriminately will have no ill effect (currently it's fine)
129
+ var frontMostPane = this.get('lastChild');
130
+ if (frontMostPane && frontMostPane.get('isVisible')) {
131
+ frontMostPane.makeKeyPane();
132
+ } else {
133
+ var pane = SC.app.get('mainPane');
134
+ if (pane) pane.makeKeyPane();
135
+ }
136
+ },
137
+
138
+ // on init, add to main HTML page if not already added.
139
+ init: function() {
140
+ arguments.callee.base.apply(this,arguments) ;
141
+ var el = this.rootElement ;
142
+ if (!this.parentNode) {
143
+ $tag('body').insertBefore(el, null) ;
144
+ SC.window.insertBefore(this, null) ;
145
+ }
146
+ this.set('isVisible',false) ;
147
+ this._boundPaneDidHide = this._paneDidHide.bind(this) ;
148
+ },
149
+
150
+ // registered panes.
151
+ _paneTypes: {},
152
+ _paneCache: {}, // unused pane instances stored by paneType.
153
+ _visiblePanes: {} // panes stored by views
154
+ }) ;
155
+
156
+ SC.PaneManager.registerPaneType = function(paneType, paneClass) {
157
+ SC.PaneManager.prototype._paneTypes[paneType] = paneClass ;
158
+ } ;
159
+
160
+ // This will create the manager instance if it does not already exist.
161
+ SC.PaneManager.manager = function() {
162
+ if (!this._manager) this._manager = SC.PaneManager.viewFor('panes') ;
163
+ return this._manager ;
164
+ };
@@ -0,0 +1,45 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('panes/overlay') ;
7
+
8
+ SC.MENU_PANE = 'menu';
9
+ SC.MenuPaneView = SC.OverlayPaneView.extend({
10
+
11
+ emptyElement: '<div class="pane menu-pane"><div class="shadow pane-wrapper"><div class="pane-root"></div><div class="top-left-edge"></div><div class="top-edge"></div><div class="top-right-edge"></div><div class="right-edge"></div><div class="bottom-right-edge"></div><div class="bottom-edge"></div><div class="bottom-left-edge"></div><div class="left-edge"></div></div></div>',
12
+
13
+ layer: 400,
14
+
15
+ isModal: false,
16
+
17
+ // The ideal position for a picker pane is just below the anchor that
18
+ // triggered it. Find that ideal position, then call adjustPosition.
19
+ positionPane: function() {
20
+ var anchor = this.anchorView ;
21
+ var picker = this.containerView ;
22
+ var origin ;
23
+
24
+ // usually an anchorView will be passed. The ideal position to appear is
25
+ // just below the anchorView. If that is not possible, fitToScreen will
26
+ // take care of that.
27
+ if (anchor) {
28
+ origin = picker.convertFrameFromView(anchor.get('frame'), anchor) ;
29
+ origin.y += origin.height ;
30
+ origin = this.fitPositionToScreen(origin, picker, anchor) ;
31
+
32
+ // if no anchor view has been set for some reason, just center.
33
+ } else {
34
+ var wsize = SC.window.get('size') ;
35
+ var psize = picker.get('size') ;
36
+ origin = {} ;
37
+ origin.x = (wsize.width - psize.width) / 2 ;
38
+ origin.y = (wsize.height - psize.height) / 2 ;
39
+ }
40
+
41
+ picker.set('origin',origin) ;
42
+ }
43
+
44
+ }) ;
45
+