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,628 @@
1
+
2
+ module SproutCore
3
+
4
+ # The PageHelper is a singleton object that can render the Page javascript
5
+ # object.
6
+ module PageHelper
7
+
8
+ @@render_contexts = []
9
+ @@outlets = {}
10
+ @@outlet_names = []
11
+ @@styles = []
12
+ @@defines = {}
13
+
14
+ # This is the current helper state used when rendering the HTML. When
15
+ # a view helper is rendered, it may add itself as an outlet to the current
16
+ # helper state instead of to the page helper.
17
+ def self.current_render_context
18
+ @@render_contexts.last
19
+ end
20
+
21
+ def self.push_render_context(state)
22
+ @@render_contexts.push(state)
23
+ end
24
+
25
+ def self.pop_render_context
26
+ @@render_contexts.pop
27
+ end
28
+
29
+ # reset the page helper.
30
+ def self.reset!
31
+ @@render_contexts = []
32
+ @@outlets = {}
33
+ @@outlet_names = []
34
+ @@styles = []
35
+ @@defines = {}
36
+ end
37
+
38
+ def self.set_define(key, opts = {})
39
+ @@defines[key] = opts
40
+ end
41
+
42
+ def self.set_outlet(key,opts = {})
43
+ @@outlet_names << key
44
+ @@outlets[key] = opts
45
+ end
46
+
47
+ def self.add_styles(styles)
48
+ @@styles << styles
49
+ end
50
+
51
+ # renders the page object for the current page. If you include a prefix
52
+ # that will be used to create a separate page object. Otherwise, the
53
+ # object will live in the SC namespace.
54
+ #
55
+ # returns the text to insert into the HTML.
56
+ def self.render_js(prefix = 'SC')
57
+
58
+ outlets = []
59
+ @@outlet_names.each do | key |
60
+ opts = @@outlets[key]
61
+ outlet_path = opts[:outlet_path] || "##{opts[:id] || key}"
62
+ outlets << %{ #{key}: #{opts[:class] || 'SC.View'}.extend({\n #{ opts[:properties].gsub("\n","\n ") }\n }).outletFor("#{outlet_path}") }
63
+ end
64
+
65
+ # defines let you define classes to include in your UI.
66
+ ret = @@defines.map do | key, opts |
67
+ %{#{key} = #{opts[:class] || 'SC.View'}.extend({\n #{ opts[:properties] }\n});}
68
+ end
69
+ ret << %{#{prefix}.page = SC.Page.create({\n#{ outlets * ",\n\n" }\n}); }
70
+ return ret * "\n"
71
+
72
+ end
73
+
74
+ def self.render_css
75
+ if @@styles.size > 0
76
+ %(<style type="application/css">\n#{ @@styles * "\n" }\n</style>)
77
+ else
78
+ ''
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ module ViewHelperSupport
85
+
86
+ @@helpers = {}
87
+ def self.find_helper(helper_name)
88
+ @@helpers[helper_name.to_sym] || @@helpers[:view]
89
+ end
90
+
91
+ def self.set_helper(helper_name,obj)
92
+ @@helpers[helper_name.to_sym] = obj
93
+ end
94
+
95
+ class RenderContext
96
+
97
+ # options passed in from the view helper
98
+ attr_reader :item_id
99
+ attr_accessor :outlet
100
+ attr_accessor :define
101
+ attr_accessor :current_helper
102
+ attr_accessor :client_builder
103
+
104
+ def initialize(item_id, opts={}, client_builder = nil)
105
+ @_options = opts.dup
106
+ @bindings = (@_options[:bind] || {}).dup
107
+ @outlets = {}
108
+ @prototypes = {}
109
+ @item_id = item_id
110
+ @outlet = opts[:outlet]
111
+ @define = opts[:define]
112
+ @client_builder = client_builder
113
+ @outlet_names = []
114
+
115
+ @attributes = (@_options[:attributes] || {}).dup
116
+
117
+ @_properties = {}
118
+ if @_options[:properties]
119
+ @_options[:properties].each do | key, value |
120
+ @_properties[key.to_s.camelize(:lower)] = prepare_for_javascript(value)
121
+ end
122
+ end
123
+ end
124
+
125
+ def options
126
+ @_options
127
+ end
128
+
129
+ def set_outlet(key,opts = {})
130
+ @outlet_names << key
131
+ @outlets[key] = opts
132
+ end
133
+
134
+ def prepare_bindings
135
+ @bindings.each do | k,v |
136
+ key = k.to_s.camelize(:lower) + 'Binding'
137
+ @_properties[key] = v.include?('(') ? v : prepare_for_javascript(v)
138
+ end
139
+ end
140
+
141
+ def prepare_outlets
142
+ return if @outlets.size == 0
143
+ outlets = []
144
+ @outlet_names.each do | key |
145
+ opts = @outlets[key]
146
+ outlet_key = key.to_s.camelize(:lower)
147
+ outlets << outlet_key unless opts[:lazy]
148
+
149
+ outlet_path = opts[:outlet_path] || ".#{opts[:id] || key }?"
150
+ str = %{#{opts[:class] || 'SC.View'}.extend({\n#{ opts[:properties] }\n}).outletFor("#{outlet_path}")}
151
+ @_properties[outlet_key] = str
152
+ end
153
+
154
+ @_properties['outlets'] = outlets
155
+ end
156
+
157
+ def parent_helper(opts = {})
158
+ if @current_helper && @current_helper.parent_helper
159
+ @_options.merge! opts
160
+ @current_helper.parent_helper.prepare_context(self)
161
+ end
162
+ end
163
+
164
+ ### RENDER METHODS
165
+ def render_content
166
+ @attributes[:id] = @item_id if @item_id && !(@outlet || @define)
167
+
168
+ old_client_builder = self.client_builder
169
+ self.client_builder = @content_render_client_builder unless @content_render_client_builder.nil?
170
+ ret = _do_render(@content_render)
171
+ self.client_builder = old_client_builder
172
+ return ret
173
+ end
174
+
175
+ def render_view
176
+ prepare_bindings
177
+ prepare_outlets
178
+ _do_render(@view_render)
179
+ end
180
+
181
+ def view_class
182
+ @view_class
183
+ end
184
+
185
+ def render_styles
186
+ _do_render(@styles_render)
187
+ end
188
+
189
+ ### BASIC CONFIG METHODS
190
+ # These are called in the helper's prepare_context method.
191
+
192
+ # This method must be called to configure the view.
193
+ def view(view_class,text = nil, &block)
194
+ @view_class = view_class
195
+ @view_render = text || block if (text || block)
196
+ end
197
+
198
+ # this method must be called to configure the HTML.
199
+ # also captures the client builder in use at the time it is called.
200
+ def content(text = nil, &block)
201
+ @content_render_client_builder = self.client_builder
202
+ @content_render = text || block if (text || block)
203
+ end
204
+
205
+ # this method may be called to add CSS styles
206
+ def styles(text = nil, &block)
207
+ @styles_render = text || block if (text || block)
208
+ end
209
+
210
+ def static_url(resource_name, opts = {})
211
+ opts[:language] ||= @language
212
+ entry = @client_builder.find_resource_entry(resource_name, opts)
213
+ entry.nil? ? '' : entry.url
214
+ end
215
+
216
+ def blank_url
217
+ static_url('blank.gif')
218
+ end
219
+
220
+ ### HTML HELPER METHODS
221
+
222
+ # This will extract the specified value and put it into an ivar you can
223
+ # access later during rendering. For example:
224
+ #
225
+ # var :label, 'Default label'
226
+ #
227
+ # will now be accessible in your code via @label
228
+ #
229
+ # Parameters:
230
+ # option_key: (req) the option to map.
231
+ # default_value: (opt) if passed, this will be used as the default value
232
+ # if the option is not passed in.
233
+ #
234
+ # :key => (opt) the name of the resulting ivar. defaults to the option
235
+ # key.
236
+ #
237
+ # :optional => (opt) if true, then the attribute will not be included if
238
+ # it is not explicitly passed in the options. if no default value is
239
+ # specified, then this will default to true, otherwise defaults to
240
+ # false.
241
+ #
242
+ # :constant => (opt) if true, then any passed in options will be ignored
243
+ # for this key and the default you specify will be used instead.
244
+ # Defaults to false
245
+ #
246
+ # you may also pass a block that will be used to compute the value at
247
+ # render time. Expect a single parameter which is the initial value.
248
+ #
249
+ def var(option_key, default_value=:__UNDEFINED__, opts={}, &block)
250
+ ret = _pair(option_key, default_value, opts, &block)
251
+ return if ret[2] # ignore
252
+ instance_variable_set("@#{ret[0]}".to_sym, ret[1])
253
+ ret[1]
254
+ end
255
+
256
+ # returns the standard attributes for the HTML. This will automatically
257
+ # include the item id. You can also declare added attributes using the
258
+ # attribute param.
259
+ def attributes
260
+ final_class_names = css_class_names
261
+ final_styles = css_styles
262
+
263
+ ret = @attributes.map do |key,value|
264
+
265
+ # if the css class or css style is declared, replace the current
266
+ # set coming from the view_helper
267
+ if key.to_sym == :class && value
268
+ final_class_names = value
269
+ nil
270
+ elsif key.to_sym == :style && value
271
+ final_styles = value
272
+ nil
273
+ else
274
+ value ? %(#{key}="#{value}") : nil
275
+ end
276
+ end
277
+
278
+ # add in class names
279
+ final_class_names = [final_class_names].flatten
280
+ final_class_names << @item_id
281
+ final_class_names.compact!
282
+ unless final_class_names.empty?
283
+ ret << %(class="#{final_class_names.uniq * ' '}")
284
+ end
285
+
286
+ # add in styles
287
+ unless final_styles.nil?
288
+ final_styles = [final_styles].flatten
289
+ final_styles.compact!
290
+ ret << %(style="#{final_styles.uniq * ' '}") unless final_styles.empty?
291
+ end
292
+
293
+ ret.compact * ' '
294
+ end
295
+
296
+ # Your view helper can add text to by appended to the styles attribute
297
+ # by adding to this array.
298
+ def css_styles
299
+ @css_styles ||= []
300
+ end
301
+
302
+ def css_styles=(new_ary)
303
+ @css_styles = new_ary
304
+ end
305
+
306
+ # Your view helper can add css classes to be appended to the classes
307
+ # attribute by adding to this array.
308
+ def css_class_names
309
+ @css_class_names ||= []
310
+ end
311
+
312
+ def css_class_names=(new_ary)
313
+ @css_class_names = new_ary
314
+ end
315
+
316
+ # This does the standard open tag with the default tag and attributes. Usually
317
+ # you can use this.
318
+ def open_tag
319
+ %{<#{@tag} #{attributes}>}
320
+ end
321
+ alias_method :ot, :open_tag
322
+
323
+ def close_tag
324
+ %{</#{@tag}>}
325
+ end
326
+ alias_method :ct, :close_tag
327
+
328
+ # Call this method in your view helper definition to map an option to
329
+ # an attribute. This attribute can then be rendered with attributes.
330
+ # This method takes the same options as var
331
+ def attribute(option_key, default_value=:__UNDEFINED__, opts={}, &block)
332
+ ret = _pair(option_key, default_value, opts, &block)
333
+ return if ret[2] # ignore
334
+ @attributes[ret[0]] = ret[1]
335
+ end
336
+
337
+ # returns all the JS properties specified by the property method.
338
+ def properties
339
+ keys = @_properties.keys
340
+ ret = []
341
+
342
+ # example element, if there is one
343
+ if @define
344
+ @_properties['emptyElement'] = %($sel("#resources? .#{@item_id}:1:1"))
345
+ ret << _partial_properties(['emptyElement'])
346
+ end
347
+
348
+ # outlets first
349
+ if keys.include?('outlets')
350
+ outlets = @_properties['outlets']
351
+ @_properties['outlets'] = '["' + (outlets * '","') + '"]'
352
+ ret << _partial_properties(['outlets'])
353
+ ret << _partial_properties(outlets,",\n\n")
354
+ keys.reject! { |k| outlets.include?(k) || (k == 'outlets') }
355
+ end
356
+
357
+ bindings = keys.reject { |k| !k.match(/Binding$/) }
358
+ if bindings.size > 0
359
+ ret << _partial_properties(bindings)
360
+ keys.reject! { |k| bindings.include?(k) }
361
+ end
362
+
363
+ if keys.size > 0
364
+ ret << _partial_properties(keys)
365
+ end
366
+
367
+ ret = ret * ",\n\n"
368
+ ' ' + ret.gsub("\n","\n ")
369
+ end
370
+
371
+ def _partial_properties(keys,join = ",\n")
372
+ ret = keys.map do |key|
373
+ value = @_properties[key]
374
+ next if value.nil?
375
+ %(#{key}: #{value})
376
+ end
377
+ ret * join
378
+ end
379
+
380
+ # Call this method to make a binding available or to set a default
381
+ # binding. You can use this for properties you want to allow a
382
+ # binding for but don't want to take as a fully property.
383
+ def bind(option_key, default_value=:__UNDEFINED__, opts={})
384
+ key, v, ignore = _pair(option_key, default_value, opts, false)
385
+
386
+ # always look for the option key in the bindings passed by the user.
387
+ # if present, this should override whatever we set
388
+ if found = @bindings[option_key.to_sym] || @bindings[option_key.to_s]
389
+ v = found
390
+ ignore = false
391
+ @bindings.delete option_key.to_sym
392
+ @bindings.delete option_key.to_s
393
+ end
394
+
395
+ # finally, set the binding value.
396
+ unless ignore
397
+ v = v.include?('(') ? v : prepare_for_javascript(v)
398
+ @_properties["#{key.camelize(:lower)}Binding"] = v
399
+ end
400
+
401
+ end
402
+
403
+ # Call this method in your view helper to specify a property you want
404
+ # added to the javascript declaration. This methos take the same
405
+ # options as var. Note that normally the type of value returned here
406
+ # will be marshalled into the proper type for JavaScript. If you
407
+ # provide a block to compute the property, however, the value will be
408
+ # inserted directly.
409
+ def property(option_key, default_value=:__UNDEFINED__, opts={}, &block)
410
+ ret = _pair(option_key, default_value, opts, &block)
411
+ key = ret[0].camelize(:lower)
412
+
413
+ unless ret[2] # ignore
414
+ value = ret[1]
415
+ value = prepare_for_javascript(value) unless block_given?
416
+ @_properties[key] = value
417
+ end
418
+
419
+ # also look for a matching binding and set it needed.
420
+ if v = @bindings[option_key.to_sym] || @bindings[option_key.to_s]
421
+ v = v.include?('(') ? v : prepare_for_javascript(v)
422
+ @_properties["#{key}Binding"] = v
423
+ @bindings.delete option_key.to_sym
424
+ @bindings.delete option_key.to_s
425
+ end
426
+
427
+ end
428
+
429
+ def prepare_for_javascript(value)
430
+ return 'null' if value.nil?
431
+ case value
432
+ when String:
433
+ %("#{ value.gsub('"','\"').gsub("\n",'\n') }")
434
+ when Symbol:
435
+ %("#{ value.to_s.gsub('"','\"').gsub("\n",'\n') }")
436
+ when Array:
437
+ "[#{value.map { |v| prepare_for_javascript(v) } * ','}]"
438
+ when Hash:
439
+ items = value.map do |k,v|
440
+ [prepare_for_javascript(k),prepare_for_javascript(v)] * ': '
441
+ end
442
+ "{ #{items * ', '} }"
443
+ when FalseClass:
444
+ "false"
445
+ when TrueClass:
446
+ "true"
447
+ else
448
+ value.to_s
449
+ end
450
+ end
451
+
452
+ ### INTERNAL SUPPORT
453
+ private
454
+
455
+ def _do_render(render_item)
456
+ if render_item.nil?
457
+ ''
458
+ elsif render_item.instance_of?(Proc)
459
+ render_item.call
460
+ else
461
+ render_item
462
+ end
463
+ end
464
+
465
+ def _pair(option_key, default_value, opts, look_for_key = true)
466
+ if default_value.instance_of?(Hash)
467
+ opts = default_value
468
+ default_value = :__UNDEFINED__
469
+ end
470
+
471
+ # get the attribute value. possibly return if no value and optional.
472
+ optional = opts.has_key?(:optional) ? opts[:optional] : (default_value == :__UNDEFINED__)
473
+ if opts[:constant] == true
474
+ value = default_value
475
+ elsif look_for_key && options.has_key?(option_key.to_sym)
476
+ value = options[option_key.to_sym]
477
+ elsif look_for_key && options.has_key?(option_key.to_s)
478
+ value = options[option_key.to_s]
479
+ else
480
+ value = default_value
481
+ end
482
+
483
+
484
+ if (optional==true) && value == :__UNDEFINED__
485
+ ignore = true
486
+ value = nil
487
+ else
488
+ ignore = false
489
+ value = nil if value == :__UNDEFINED__
490
+ value = yield(value) if block_given?
491
+ end
492
+
493
+ attr_key = (opts[:key] || option_key).to_s
494
+ [attr_key, value, ignore]
495
+ end
496
+
497
+ end
498
+
499
+ class HelperState
500
+ attr_reader :name
501
+ attr_reader :parent_helper
502
+ attr_reader :prepare_block
503
+
504
+ def initialize(helper_name, opts={}, &block)
505
+ @name = helper_name
506
+ @prepare_block = block
507
+ @parent_helper = SproutCore::ViewHelperSupport.find_helper(opts[:wraps] || opts[:extends] || :view)
508
+ @extends = opts[:wraps].nil?
509
+ end
510
+
511
+ def prepare_context(render_context)
512
+ # automatically call parent helper if extends was used.
513
+ if parent_helper && @extends
514
+ parent_helper.prepare_context(render_context)
515
+ else
516
+ render_context.current_helper = self
517
+ end
518
+
519
+ render_context.instance_eval &prepare_block
520
+ render_context.current_helper = nil
521
+ end
522
+
523
+ end
524
+
525
+ @@tick = 0
526
+ def self._gen_id(type="id")
527
+ @@tick += 1
528
+ return "#{type}_#{(Time.now.to_i + @@tick)}"
529
+ end
530
+
531
+ extend SproutCore::Helpers::CaptureHelper
532
+ extend SproutCore::Helpers::TextHelper
533
+
534
+ # :outlet => define if you want this to be used as an outlet.
535
+ # :prototype => define if you want this to be used as a prototype.
536
+ def self.render_view(view_helper_id, item_id, opts={}, client_builder=nil, &block)
537
+
538
+ # item_id is optional. If it is not a symbol or string, then generate
539
+ # an item_id
540
+ if item_id.instance_of?(Hash)
541
+ opts = item_id; item_id = nil
542
+ end
543
+ item_id = _gen_id if item_id.nil?
544
+
545
+ # create the new render context and set it.
546
+ client_builder = opts[:client] if opts[:client]
547
+ rc = RenderContext.new(item_id, opts, client_builder)
548
+ hs = find_helper(view_helper_id)
549
+
550
+ # render the inner_html using the block, if one is given.
551
+ SproutCore::PageHelper.push_render_context(rc)
552
+ rc.options[:inner_html] = capture(&block) if block_given?
553
+
554
+ # now, use the helper state to prepare the render context. This will
555
+ # extract the properties from the options and setup the render procs.
556
+ hs.prepare_context(rc) unless hs.nil?
557
+
558
+ # how have the render context render the HTML content. This may also
559
+ # make changes to the other items to render.
560
+ ret = rc.render_content
561
+
562
+ SproutCore::PageHelper.pop_render_context
563
+
564
+ # get the JS. Save as an outlet or in the page.
565
+ cur_rc = SproutCore::PageHelper.current_render_context
566
+ view_class = opts[:view] || rc.view_class
567
+ unless view_class.nil?
568
+ view_settings = { :id => item_id, :class => view_class, :properties => rc.render_view, :lazy => opts[:lazy], :outlet_path => opts[:outlet_path] }
569
+
570
+ # if an outlet item is passed, then register this as an outlet.
571
+ outlet = opts[:outlet] || rc.outlet
572
+ define = opts[:define]
573
+ if outlet && cur_rc
574
+ outlet = item_id if outlet == true
575
+ cur_rc.set_outlet(outlet, view_settings)
576
+
577
+ elsif define
578
+ define = define.to_s.camelize.gsub('::','.')
579
+ SproutCore::PageHelper.set_define(define, view_settings)
580
+
581
+ # otherwise, add it to the page-wide setting.
582
+ else
583
+ prop = item_id.to_s.camelize(:lower)
584
+ SproutCore::PageHelper.set_outlet(prop, view_settings)
585
+ end
586
+ end
587
+
588
+ # get the styles, if any
589
+ styles = rc.render_styles
590
+ SproutCore::PageHelper.add_styles(styles) if styles && styles.size > 0
591
+
592
+ # done. return the generated HTML
593
+ concat(ret,block) if block_given?
594
+ return ret
595
+ end
596
+
597
+ end
598
+
599
+ module ViewHelpers
600
+
601
+ def self.view_helper(helper_name,opts={},&prepare_block)
602
+ hs = SproutCore::ViewHelperSupport::HelperState.new(helper_name,opts,&prepare_block)
603
+ SproutCore::ViewHelperSupport.set_helper(helper_name, hs)
604
+
605
+ ## install the helper method
606
+ SproutCore::ViewHelpers.class_eval %{
607
+ def #{helper_name}(item_id=nil, opts={}, &block)
608
+ SproutCore::ViewHelperSupport.render_view(:#{helper_name}, item_id, opts, bundle, &block)
609
+ end }
610
+
611
+ SproutCore::ViewHelpers.class_eval %{
612
+ def self.#{helper_name}(item_id=nil, opts={}, &block)
613
+ SproutCore::ViewHelperSupport.render_view(:#{helper_name}, item_id, opts, bundle, &block)
614
+ end }
615
+
616
+ end
617
+
618
+ def render_page_views
619
+ ret = %(<script type="text/javascript">\n#{SproutCore::PageHelper.render_js}\n</script>)
620
+ SproutCore::PageHelper.reset!
621
+ return ret
622
+ end
623
+
624
+ end
625
+
626
+ end
627
+
628
+ Dir.glob(File.join(File.dirname(__FILE__),'view_helpers','**','*.rb')).each { |x| require x }
data/lib/sproutcore.rb ADDED
@@ -0,0 +1,30 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'activesupport'
5
+
6
+ module SproutCore
7
+
8
+ # Returns a library for the current working directory. This is useful when
9
+ # working on the command line
10
+ def self.library
11
+ Library.library_for(Dir.pwd)
12
+ end
13
+
14
+ def self.library_for(path, opts={})
15
+ Library.library_for(path, opts)
16
+ end
17
+
18
+ def self.logger; @logger ||= Logger.new(STDOUT); end
19
+ def self.logger=(new_logger); @logger = new_logger; end
20
+
21
+ end
22
+
23
+ # Force load the code files. Others may be loaded only as required
24
+ %w(library bundle bundle_manifest jsdoc jsmin version).each do |fname|
25
+ require "sproutcore/#{fname}"
26
+ end
27
+
28
+ SC= SproutCore
29
+
30
+
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)