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,310 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('Core') ;
7
+ require('foundation/object') ;
8
+ require('foundation/input_manager');
9
+
10
+ /**
11
+ @class A responder is capable of responding to events such as mouse clicks and key presses.
12
+
13
+ All views are a type of responder, but you can extend this class yourself
14
+ as well to implement your own responders if you need to.
15
+
16
+ @extends SC.Object
17
+
18
+ */
19
+ SC.Responder = SC.Object.extend(
20
+ /** @scope SC.Responder.prototype */
21
+ {
22
+
23
+ // .......................................................................
24
+ // Managing Responder States
25
+ //
26
+
27
+ /**
28
+ This method will be called just before you become first responder to see
29
+ if you want to be first responder. If you don't want to handle
30
+ keyboard events, return false. (this is the default). Note that this is
31
+ a property.
32
+ */
33
+ acceptsFirstResponder: false,
34
+
35
+ /**
36
+ This property is the next responder that should be allowed to handle
37
+ events if you don't want to handle it. For views, this is automatically
38
+ set to your parentNode.
39
+ */
40
+ nextResponder: null,
41
+
42
+ /**
43
+ This property is true whenever you are the first responder. Observable.
44
+ */
45
+ isFirstResponder: false,
46
+
47
+ pane: null,
48
+
49
+ /**
50
+ Call this method to become the first responder. You will now be the
51
+ first to receive keyboard events, etc. Return false if you could not
52
+ be made first responder for some reason.
53
+ */
54
+ becomeFirstResponder: function()
55
+ {
56
+ if (!this.get('acceptsFirstResponder')) return false; // responder doesn't want it
57
+
58
+ var pane = this.get('pane');
59
+ if (!pane) return false; // there's no pane of which to become FR.. doesn't matter if it *does* want it...
60
+
61
+ if (pane.get('firstResponder') == this) return true; // we already got it... and setting it again will trigger the willResign callback
62
+
63
+ pane.set('firstResponder',this);
64
+ return true;
65
+ },
66
+
67
+ /**
68
+ Call this method if you no longer want to be first responder. Normally
69
+ you don't need to do this since you will lose firstResponder status
70
+ when the user focuses a different view.
71
+ */
72
+ resignFirstResponder: function()
73
+ {
74
+ var pane = this.get('pane');
75
+ if (!pane) return false;
76
+
77
+ if (pane.get('firstResponder') != this) return false;
78
+
79
+ pane.set('firstResponder',null);
80
+ return true;
81
+ },
82
+
83
+ noResponderFor: function() {},
84
+
85
+ /**
86
+ This method will be called just before you become the first responder
87
+ so you can make changes.
88
+ */
89
+ didBecomeFirstResponder: function() {},
90
+
91
+ /**
92
+ This method will be called just before you lose first responder status.
93
+ */
94
+ willLoseFirstResponder: function() {},
95
+
96
+
97
+ // .......................................................................
98
+ // Keyboard Events
99
+ //
100
+
101
+ /**
102
+ Set this value to an SC.InputManager instance if you want to use a
103
+ custom input manager for this specific instance. If you want to override
104
+ the input manager used for all responders, replace SC.Responder.inputManager.
105
+ */
106
+ inputManager: function()
107
+ {
108
+ return SC.Responder.inputManager;
109
+ }.property(),
110
+
111
+ /**
112
+ this method is invoked on the firstResponder whenever the user presses
113
+ a key. You can interpret this yourself or call interpretKeyEvents()
114
+ which will use the inputManager to handle the event. The default
115
+ version just passes this onto the next responder.
116
+ */
117
+ keyDown: function(evt) {
118
+ var nr = this.get('nextResponder') ;
119
+ return (nr && nr.keyDown) ? nr.keyDown(evt) : false;
120
+ },
121
+
122
+ /**
123
+ This method is invoked on the firstResponder whenever the user releases
124
+ a key. Default version just passes onto the next responder.
125
+ */
126
+ keyUp: function(evt) {
127
+ var nr = this.get('nextResponder') ;
128
+ return (nr && nr.keyUp) ? nr.keyUp(evt) : false ;
129
+ },
130
+
131
+ /**
132
+ This method is invoked whenever the user changes the flag keys that are
133
+ pressed. pressedFlags is a hash. The default version passes on to the
134
+ nextRespoonder.
135
+ */
136
+ flagsChanged: function(pressedFlags, evt) {
137
+ //var nr = this.get('nextResponder') || SC.window.get('firstResponder') ;
138
+ var nr = this.get('nextResponder') ;
139
+ return (nr && nr.flagsChanges) ? nr.flagsChanges(pressedFlags, evt) : false;
140
+ },
141
+
142
+ /**
143
+ This will be called if a keydown event isn't handled by the responder chain.
144
+ */
145
+ performKeyEquivalent: function(keystring, evt) {
146
+ return false;
147
+ },
148
+
149
+ /*
150
+ call this method with one or more event objects to process the incoming
151
+ text. This will use the current inputManager (see above) to process
152
+ the event and then to make an appropriate call on the receiver.
153
+ */
154
+ interpretKeyEvents: function(evts) {
155
+ var inputManager = this.get('inputManager');
156
+ if (inputManager) return inputManager.interpretKeyEvents(evts, this) ;
157
+ return false ;
158
+ },
159
+
160
+ /**
161
+ * Attempt to perform a method. If either the method does not exist, or the method returns false, send the request to the nextResponder.
162
+ * @param {String} method The name of the method to perform
163
+ * @return {SC.Responder} The responder that handled the command, or false
164
+ */
165
+ doCommand: function(method)
166
+ {
167
+ var responder = this;
168
+ var args = $A(arguments);
169
+ var method = args.shift();
170
+ var aliases = this._commandAliases[method];
171
+ var handled = false;
172
+
173
+ do {
174
+ // attempt to handle the method
175
+ if (this._responderHandledCommand(responder, method, args)) return responder;
176
+ // perhaps under an alias?
177
+ if (aliases)
178
+ {
179
+ for (var i=0, n=aliases.length; i < n; i++)
180
+ {
181
+ if (this._responderHandledCommand(responder, aliases[i], args)) return responder;
182
+ }
183
+ }
184
+ // nope... next responder, please...
185
+ } while (responder = responder.get('nextResponder'));
186
+ // ran out of responders...
187
+ return false;
188
+ },
189
+
190
+ /** @private */
191
+ _responderHandledCommand: function( responder, method, args )
192
+ {
193
+ // if the method does not explicitly return a false-y value (false, "", 0), it's considered "handled"
194
+ // WARNING: returning null, or void is *not* == false
195
+ return (responder.respondsTo(method) && (responder[method].apply(responder, args) != false));
196
+ },
197
+ /** @private */
198
+ _commandAliases: {
199
+ 'mouseDown': ['didMouseDown'],
200
+ 'mouseUp': ['didMouseUp'],
201
+ 'doubleClick': ['didDoubleClick'],
202
+ 'click': ['didClick'],
203
+ 'mouseDown': ['didMouseDown']
204
+ }
205
+
206
+ // .......................................................................
207
+ // Mouse Event Handlers
208
+ //
209
+ // Implement any of these if you want them to be implemented.
210
+
211
+ // when the mouse is pressed.
212
+ // mouseDown: function(evt) {},
213
+
214
+ // when the mouse is releases
215
+ // mouseUp: function(evt) {},
216
+
217
+ // when the mouse is dragged
218
+ // mouseDragged: function(evt) {},
219
+
220
+ // when the mouse leaves the view responder
221
+ // mouseOut: function(evt) {},
222
+
223
+ // when the mouse enters the view.
224
+ // mouseOver: function(evt) {},
225
+
226
+ // when the mouse is moved.
227
+ // mouseMoved: function(evt) {},
228
+
229
+ // .......................................................................
230
+ // Event Handlers
231
+ //
232
+ // These methods are called by the input manager in response to keyboard
233
+ // events. Most of these methods are defined here for you, but not actually
234
+ // implemented in code.
235
+
236
+ // insert the text or act on the key.
237
+ // insertText: function(text) {},
238
+
239
+ // if the user presses a key-combination event, this will be called so you
240
+ // can run the command.
241
+ // performKeyEquivalent: function(charCode, evt) { return false; },
242
+
243
+ // this method is called if no other view in the current view hierarchy is
244
+ // bound to the escape or command-. key equivalent. You can use this to
245
+ // cancel whatever operation is running.
246
+ //
247
+ // cancel: function(sender, evt) {},
248
+
249
+ // delete the current selection or delete one element backward from the
250
+ // current selection.
251
+ // deleteBackward: function(sender, evt) {},
252
+
253
+ // delete the current selection or delete one element forward from the
254
+ // current selection.
255
+ // deleteForward: function(sender, evt) {},
256
+
257
+ // a field editor might respond by selecting the field before it.
258
+ // insertBacktab: function(sender, evt) {},
259
+
260
+ // insert a newline character or end editing of the receiver.
261
+ // insertNewline: function(sender, evt) {},
262
+
263
+ // insert a tab or move forward to the next field.
264
+ // insertTab: function(sender, evt) {},
265
+
266
+ // move insertion point/selection backward one. (i.e. left arrow key)
267
+ // moveLeft: function(sender, evt) {},
268
+
269
+ // move the insertion point/selection forward one (i.e. right arrow key)
270
+ // in left-to-right text, this could be the left arrow key.
271
+ // moveRight: function(sender, evt) {},
272
+
273
+ // move the insertion point/selection up one (i.e. up arrow key)
274
+ // moveUp: function(sender, evt) {},
275
+
276
+ // move the insertion point/selection down one (i.e. down arrow key)
277
+ // moveDown: function(sender, evt) {},
278
+
279
+ // move left, extending the selection. - shift || alt
280
+ // moveLeftAndModifySelection: function(sender, evt) {},
281
+
282
+ // move right, extending the seleciton - shift || alt
283
+ // moveRightAndModifySelection: function(sender, evt) {},
284
+
285
+ // move up, extending the selection - shift || alt
286
+ // moveUpAndModifySelection: function(sender, evt) {},
287
+
288
+ // move down, extending selection - shift || alt
289
+ // moveDownAndModifySelection: function(sender, evt) {},
290
+
291
+ // move insertion point/selection to beginning of document.
292
+ // moveToBeginningOfDocument: function(sender, evt) {},
293
+
294
+ // move insertion point/selection to end of document.
295
+ // moveToEndOfDocument: function(sender, evt) {},
296
+
297
+ // page down
298
+ // pageDown: function(sender, evt) {},
299
+
300
+ // page up
301
+ // pageUp: function(sender, evt) {},
302
+
303
+ // select all
304
+ // selectAll: function(sender, evt) {},
305
+
306
+ });
307
+
308
+ SC.Responder.mixin({
309
+ inputManager: SC.InputManager.create()
310
+ }) ;
@@ -0,0 +1,371 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('foundation/object') ;
7
+
8
+ // Routes makes it possible to load a location in the browser.
9
+ SC.Routes = SC.Object.create({
10
+
11
+ // set this property to your current app lication
12
+ location: function(key,value) {
13
+ if (value !== undefined) {
14
+ if (value === null) value = '' ;
15
+
16
+ // convert an object hash to a string, if it was passed.
17
+ if (typeof(value) == "object") {
18
+
19
+ // get the original route and any params
20
+ var parts = (value.route) ? value.route.split('&') : [''] ;
21
+ var route = parts.shift() ;
22
+ var params = {} ;
23
+ parts.each(function(p) {
24
+ var bits = p.split('=') ;
25
+ params[bits[0]] = bits[1] ;
26
+ }) ;
27
+
28
+ // overlay any params passed in the object.
29
+ for(var key in value) {
30
+ if (!value.hasOwnProperty(key)) continue ;
31
+ if (key != 'route') {
32
+ params[key] = encodeURIComponent(''+value[key]) ;
33
+ }
34
+ }
35
+
36
+ // now build params.
37
+ parts = [route] ;
38
+ for(var key in params) {
39
+ if (!params.hasOwnProperty(key)) continue ;
40
+ parts.push([key,params[key]].join('=')) ;
41
+ }
42
+
43
+ // and combine.
44
+ value = parts.join('&') ;
45
+ }
46
+
47
+ if (this._location != value) {
48
+ this._location = value ;
49
+ this._setWindowLocation(value) ;
50
+ //this.gotoRoute(value) ;
51
+ }
52
+ }
53
+ return this._location ;
54
+ }.property(),
55
+
56
+ // ensures we are at the current route location.
57
+ ping: function() {
58
+ if (!this._didSetupHistory) {
59
+ this._didSetupHistory = true ;
60
+ this._setupHistory() ;
61
+ }
62
+ this._checkWindowLocation();
63
+ },
64
+
65
+ // register a route here. Routes have the following format:
66
+ // static/route/path -- matches this path only.
67
+ // static/route/:path -- matches any static/route, :path passed as param.
68
+ // static/*route -- matches any static, route gets rest of URL.
69
+ //
70
+ // parameters can also be passed using &.
71
+ // static/route&param1=value&param2=value2
72
+ //
73
+ addRoute: function(route, func) {
74
+ var parts = route.split('/') ;
75
+ if (!this._routes) this._routes = SC.Routes._Route.create() ;
76
+ this._routes.addRoute(parts,func) ;
77
+ },
78
+
79
+ // eval routes.
80
+ gotoRoute: function(route) {
81
+ var params = {} ; var parts, route, func ;
82
+
83
+ // save this route for window location sensing
84
+ this._lastRoute = route ;
85
+
86
+ // step 1: split out parameters
87
+ var parts = route.split('&') ;
88
+ if (parts && parts.length > 0) {
89
+ route = parts.shift() ;
90
+ parts.each(function(part) {
91
+ var param = part.split('=') ;
92
+ if (param && param.length > 1) params[param[0]] = decodeURIComponent(param[1]) ;
93
+ }) ;
94
+ } else route = '' ;
95
+
96
+ // step 2: split our route parts
97
+ parts = route.split('/') ;
98
+
99
+ // step 3: evaluate route.
100
+ if (!this._routes) this._routes = SC.Routes._Route.create() ;
101
+ func = this._routes.functionForRoute(parts,params) ;
102
+ if (func) func(params) ;
103
+ else console.log('could not find route for: "'+route+'"') ;
104
+ },
105
+
106
+
107
+ init: function() {
108
+ arguments.callee.base.call(this) ;
109
+ if (SC.isSafari() && !SC.isSafari3()) {
110
+ Object.extend(this,this.browserFuncs.safari) ;
111
+ } else if (SC.isIE()) {
112
+ Object.extend(this,this.browserFuncs.ie) ;
113
+ }
114
+ this._didSetupHistory = false ;
115
+ },
116
+
117
+ // _checkWindowLocation and _setWindowLocation are implemented separately for
118
+ // each browser. Below are the implementations, which get copied during init.
119
+ browserFuncs: {
120
+
121
+ // for Safari2 and earlier.
122
+ safari: {
123
+
124
+ _setupHistory: function() {
125
+ // get initial cloc.
126
+ var cloc = location.hash ;
127
+ cloc = (cloc && cloc.length > 0) ? cloc.slice(1,cloc.length) : '' ;
128
+ this._cloc = cloc ;
129
+
130
+ // create back stack.
131
+ this._backStack = [] ;
132
+ this._backStack.length = history.length ;
133
+ this._backStack.push(cloc) ;
134
+
135
+ // create forward stack.
136
+ this._forwardStack = [] ;
137
+
138
+ this._boundChecker = this._checkWindowLocation.bind(this) ;
139
+ this.timer = setTimeout(this._boundChecker,1000) ;
140
+ },
141
+
142
+ _checkWindowLocation: function() {
143
+ // The way we know the user has moved forward or back in the history
144
+ // is when the length of the history array no longer matched our own
145
+ // copy of the history. However, when we first change locations, it
146
+ // takes a little while for Safari to catch up. So what we do instead
147
+ // is first check to see if Safari's length has changed from its last
148
+ // known length and only then check for a delta.
149
+ var historyDidChange = (history.length - this._lastLength) != 0;
150
+ var delta = (historyDidChange) ? (history.length - this._backStack.length) : 0 ;
151
+ this._lastLength = history.length ;
152
+
153
+ if (historyDidChange) console.log('historyDidChange') ;
154
+
155
+ // if the history length has changed, then we need to move forward or
156
+ // back in the history.
157
+ if (delta) {
158
+ if (delta < 0) { // back button has been pushed
159
+
160
+ // shift out the current loc.
161
+ this._forwardStack.push(this._cloc) ;
162
+
163
+ // shift out other items.
164
+ for(var i=0; i < Math.abs(delta+1);i++) {
165
+ this._forwardStack.push(this._backStack.pop()) ;
166
+ }
167
+
168
+ // set new cloc.
169
+ this._cloc = this._backStack.pop() ;
170
+
171
+
172
+ } else { // forward button has been pushed
173
+
174
+ // shift out the current loc.
175
+ this._backStack.push(this._cloc) ;
176
+
177
+ for(var i=0; i < (delta-1); i++) {
178
+ this._backStack.push(this._forwardStack.pop()) ;
179
+ }
180
+
181
+ this._cloc = this._forwardStack.pop() ;
182
+ }
183
+
184
+ // if the history has changed but the delta hasn't, then that means
185
+ // a new location was set via _setWindowLocation(). Normally we would
186
+ // call gotoRoute in that method, but doing so will crash Safari.
187
+ // Instead, we wait until Safari registers the change and then do the
188
+ // route change.
189
+ } else if (historyDidChange && this._locationDidChange) {
190
+ this.gotoRoute(this._cloc) ;
191
+ this._locationDidChange = false ;
192
+ }
193
+
194
+ var cloc = this._cloc ;
195
+ var loc = this.get('location') ;
196
+ if (cloc != loc) {
197
+ this.set('location',(cloc) ? cloc : '') ;
198
+ this.gotoRoute(cloc) ;
199
+ }
200
+
201
+ this.timer = setTimeout(this._boundChecker,50) ;
202
+ },
203
+
204
+ _setWindowLocation: function(loc) {
205
+ var cloc = this._cloc ;
206
+ if (cloc != loc) {
207
+ this._backStack.push(this._cloc) ;
208
+ this._forwardStack.length = 0 ;
209
+ this._cloc = loc ;
210
+ location.hash = (loc && loc.length > 0) ? loc : '' ;
211
+ this._locationDidChange = true ;
212
+ }
213
+ }
214
+
215
+ },
216
+
217
+ // for IE.
218
+ ie: {
219
+ _setupHistory: function() {
220
+ this._boundChecker = this._checkWindowLocation.bind(this) ;
221
+ // this.timer = setTimeout(this._boundChecker,1000) ;
222
+ },
223
+
224
+ _checkWindowLocation: function() {
225
+ var loc = this.get('location') ;
226
+ var cloc = location.hash ;
227
+ cloc = (cloc && cloc.length > 0) ? cloc.slice(1,cloc.length) : '' ;
228
+ if (cloc != loc) this.set('location',(cloc) ? cloc : '') ;
229
+ this.timer = setTimeout(this._boundChecker,100) ;
230
+ },
231
+
232
+ _setWindowLocation: function(loc) {
233
+ //console.log('_setWindowLocation('+loc+')') ;
234
+ var cloc = location.hash ;
235
+ cloc = (cloc && cloc.length > 0) ? cloc.slice(1,cloc.length) : '' ;
236
+ if (cloc != loc) {
237
+ location.hash = (loc && loc.length > 0) ? loc : '#' ;
238
+ }
239
+ this.gotoRoute(loc) ;
240
+ }
241
+ }
242
+ },
243
+
244
+ _setupHistory: function() {
245
+ this._boundChecker = this._checkWindowLocation.bind(this) ;
246
+ this.timer = setTimeout(this._boundChecker,1000) ;
247
+ },
248
+
249
+ _checkWindowLocation: function() {
250
+ var loc = this.get('location') ;
251
+ var cloc = location.hash ;
252
+ cloc = (cloc && cloc.length > 0) ? cloc.slice(1,cloc.length) : '' ;
253
+ if (cloc != loc) this.set('location',(cloc) ? cloc : '') ;
254
+ this.timer = setTimeout(this._boundChecker,100) ;
255
+ },
256
+
257
+ _setWindowLocation: function(loc) {
258
+ //console.log('_setWindowLocation('+loc+')') ;
259
+ var cloc = location.hash ;
260
+ cloc = (cloc && cloc.length > 0) ? cloc.slice(1,cloc.length) : '' ;
261
+ if (cloc != loc) {
262
+ location.hash = (loc && loc.length > 0) ? loc : '#' ;
263
+ }
264
+ this.gotoRoute(loc) ;
265
+ },
266
+
267
+ _routes: null,
268
+
269
+ // This object handles a single route level.
270
+ _Route: SC.Object.extend({
271
+
272
+ // a route that ends here gets this func.
273
+ _func: null,
274
+
275
+ // staticly named routes.
276
+ _static: null,
277
+
278
+ // dynamically named routes.
279
+ _dynamic: null,
280
+
281
+ // set the wildcard route name here.
282
+ _wildcard: null,
283
+
284
+ addRoute: function(parts, func) {
285
+ if (!parts || parts.length == 0) {
286
+ this._func = func ;
287
+
288
+ // add to route table.
289
+ } else {
290
+ var part = parts.shift() ; // get next route.
291
+ var nextRoute = null ;
292
+ switch(part.slice(0,1)) {
293
+
294
+ // add a dynamic route
295
+ case ':':
296
+ part = part.slice(1,part.length) ;
297
+ var routes = this._dynamic[part] || [] ;
298
+ nextRoute = SC.Routes._Route.create() ;
299
+ routes.push(nextRoute) ;
300
+ this._dynamic[part] = routes ;
301
+ break ;
302
+
303
+ // setup wildcard route
304
+ case '*':
305
+ part = part.slice(1,part.length) ;
306
+ this._wildcard = part ;
307
+ this._func = func ;
308
+ break ;
309
+
310
+ // setup a normal static route.
311
+ default:
312
+ var routes = this._static[part] || [] ;
313
+ nextRoute = SC.Routes._Route.create() ;
314
+ routes.push(nextRoute) ;
315
+ this._static[part] = routes ;
316
+ }
317
+
318
+ // if we need to go another level deeper, call nextRoute
319
+ if (nextRoute) nextRoute.addRoute(parts,func) ;
320
+ }
321
+ },
322
+
323
+ // process the next level of the route and pass on.
324
+ functionForRoute: function(parts, params) {
325
+ // if parts it empty, then we are here, so return func
326
+ if (!parts || parts.length == 0) {
327
+ return this._func ;
328
+
329
+ // process the next part
330
+ } else {
331
+ var part = parts.shift() ;
332
+ var routes, nextRoute, ret, loc ;
333
+
334
+ // try to match to static
335
+ routes = this._static[part] ;
336
+ if (routes) for(loc=0;(loc < routes.length) && (ret==null);loc++) {
337
+ var clone = parts.slice() ;
338
+ ret = routes[loc].functionForRoute(clone, params) ;
339
+ }
340
+
341
+ // try to match dynamic if no static match was found.
342
+ if (ret == null) for(var key in this._dynamic) {
343
+ routes = this._dynamic[key] ;
344
+ if (routes) for(loc=0;(loc<routes.length) && (ret == null);loc++) {
345
+ var clone = parts.slice() ;
346
+ ret = routes[loc].functionForRoute(clone,params) ;
347
+
348
+ // if a route was found, save the current part in params.
349
+ if (ret && params) params[key] = part ;
350
+ }
351
+ if (ret) break ;
352
+ }
353
+
354
+ // if nothing still found, and there is a wildcard, match that.
355
+ if ((ret == null) && this._wildcard) {
356
+ parts.unshift(part) ;
357
+ if (params) params[this._wildcard] = parts.join('/') ;
358
+ ret = this._func ;
359
+ }
360
+
361
+ return ret ;
362
+ }
363
+ },
364
+
365
+ init: function() {
366
+ arguments.callee.base.call(this) ;
367
+ this._static = {} ; this._dynamic = {} ;
368
+ }
369
+ })
370
+
371
+ }) ;
@@ -0,0 +1,21 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('Core') ;
7
+
8
+ // RunLoop is used to manage deferred runs. It's lighter weight than setting
9
+ // lots of timeouts.
10
+ SC.runLoop = SC.Object.create({
11
+
12
+ schedule: function() {
13
+ var args = $A(arguments) ;
14
+ var obj = args.shift() ;
15
+ var method = obj[args.shift()];
16
+ var delay = args.pop() ;
17
+ var func = function() { method.apply(obj, args); }
18
+ return setTimeout(func, delay) ;
19
+ }
20
+
21
+ }) ;