sproutcore 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +269 -0
- data/README.txt +67 -0
- data/Rakefile +4 -0
- data/app_generators/sproutcore/USAGE +5 -0
- data/app_generators/sproutcore/sproutcore_generator.rb +66 -0
- data/app_generators/sproutcore/templates/README +77 -0
- data/app_generators/sproutcore/templates/environment.yml +4 -0
- data/bin/sc-build +145 -0
- data/bin/sc-gen +24 -0
- data/bin/sc-server +63 -0
- data/bin/sproutcore +21 -0
- data/clients/sc_docs/controllers/docs.js +118 -0
- data/clients/sc_docs/core.js +19 -0
- data/clients/sc_docs/english.lproj/body.css +159 -0
- data/clients/sc_docs/english.lproj/body.rhtml +33 -0
- data/clients/sc_docs/english.lproj/controls.css +0 -0
- data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
- data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
- data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
- data/clients/sc_docs/english.lproj/images/indicator.gif +0 -0
- data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
- data/clients/sc_docs/english.lproj/no_docs.rhtml +7 -0
- data/clients/sc_docs/english.lproj/strings.js +14 -0
- data/clients/sc_docs/english.lproj/warning.rhtml +6 -0
- data/clients/sc_docs/fixtures/doc.js +11 -0
- data/clients/sc_docs/main.js +21 -0
- data/clients/sc_docs/models/doc.js +9 -0
- data/clients/sc_docs/tests/controllers/docs.rhtml +21 -0
- data/clients/sc_docs/tests/models/doc.rhtml +21 -0
- data/clients/sc_docs/tests/views/doc_frame.rhtml +21 -0
- data/clients/sc_docs/tests/views/doc_label_view.rhtml +21 -0
- data/clients/sc_docs/views/doc_frame.js +33 -0
- data/clients/sc_docs/views/doc_label.js +20 -0
- data/clients/sc_test_runner/controllers/runner.js +175 -0
- data/clients/sc_test_runner/core.js +19 -0
- data/clients/sc_test_runner/english.lproj/body.css +151 -0
- data/clients/sc_test_runner/english.lproj/body.rhtml +35 -0
- data/clients/sc_test_runner/english.lproj/controls.css +0 -0
- data/clients/sc_test_runner/english.lproj/icons/small/next.png +0 -0
- data/clients/sc_test_runner/english.lproj/icons/small/reset.png +0 -0
- data/clients/sc_test_runner/english.lproj/images/gradients.png +0 -0
- data/clients/sc_test_runner/english.lproj/images/indicator.gif +0 -0
- data/clients/sc_test_runner/english.lproj/images/toolbar.png +0 -0
- data/clients/sc_test_runner/english.lproj/no_tests.rhtml +6 -0
- data/clients/sc_test_runner/english.lproj/strings.js +14 -0
- data/clients/sc_test_runner/english.lproj/warning.rhtml +6 -0
- data/clients/sc_test_runner/fixtures/test.js +12 -0
- data/clients/sc_test_runner/main.js +26 -0
- data/clients/sc_test_runner/models/test.js +11 -0
- data/clients/sc_test_runner/views/runner_frame.js +72 -0
- data/clients/sc_test_runner/views/test_label.js +20 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +17 -0
- data/environment.yml +9 -0
- data/frameworks/prototype/prototype.js +4186 -0
- data/frameworks/sproutcore/Core.js +378 -0
- data/frameworks/sproutcore/README +3 -0
- data/frameworks/sproutcore/controllers/array.js +236 -0
- data/frameworks/sproutcore/controllers/collection.js +305 -0
- data/frameworks/sproutcore/controllers/controller.js +323 -0
- data/frameworks/sproutcore/controllers/object.js +372 -0
- data/frameworks/sproutcore/drag/drag.js +549 -0
- data/frameworks/sproutcore/drag/drag_data_source.js +32 -0
- data/frameworks/sproutcore/drag/drag_source.js +64 -0
- data/frameworks/sproutcore/drag/drop_target.js +153 -0
- data/frameworks/sproutcore/english.lproj/blank.gif +0 -0
- data/frameworks/sproutcore/english.lproj/buttons.css +589 -0
- data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
- data/frameworks/sproutcore/english.lproj/inline_text_editor.css +21 -0
- data/frameworks/sproutcore/english.lproj/menu.css +121 -0
- data/frameworks/sproutcore/english.lproj/panels/background-fat.jpg +0 -0
- data/frameworks/sproutcore/english.lproj/panels/background-thin.jpg +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-left-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-right-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/left-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/overlay.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/right-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-left-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-right-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panes.css +155 -0
- data/frameworks/sproutcore/english.lproj/picker.css +22 -0
- data/frameworks/sproutcore/english.lproj/strings.js +15 -0
- data/frameworks/sproutcore/english.lproj/tab.css +23 -0
- data/frameworks/sproutcore/english.lproj/tests.css +67 -0
- data/frameworks/sproutcore/english.lproj/theme.css +77 -0
- data/frameworks/sproutcore/foundation/animator.js +670 -0
- data/frameworks/sproutcore/foundation/application.js +199 -0
- data/frameworks/sproutcore/foundation/array.js +348 -0
- data/frameworks/sproutcore/foundation/benchmark.js +211 -0
- data/frameworks/sproutcore/foundation/binding.js +384 -0
- data/frameworks/sproutcore/foundation/date.js +357 -0
- data/frameworks/sproutcore/foundation/error.js +39 -0
- data/frameworks/sproutcore/foundation/input_manager.js +153 -0
- data/frameworks/sproutcore/foundation/json.js +296 -0
- data/frameworks/sproutcore/foundation/mock.js +42 -0
- data/frameworks/sproutcore/foundation/node_descriptor.js +56 -0
- data/frameworks/sproutcore/foundation/object.js +777 -0
- data/frameworks/sproutcore/foundation/observable.js +451 -0
- data/frameworks/sproutcore/foundation/page.js +63 -0
- data/frameworks/sproutcore/foundation/path_module.js +413 -0
- data/frameworks/sproutcore/foundation/responder.js +310 -0
- data/frameworks/sproutcore/foundation/routes.js +371 -0
- data/frameworks/sproutcore/foundation/run_loop.js +21 -0
- data/frameworks/sproutcore/foundation/server.js +491 -0
- data/frameworks/sproutcore/foundation/set.js +96 -0
- data/frameworks/sproutcore/foundation/string.js +149 -0
- data/frameworks/sproutcore/foundation/undo_manager.js +186 -0
- data/frameworks/sproutcore/foundation/unittest.js +622 -0
- data/frameworks/sproutcore/foundation/utils.js +61 -0
- data/frameworks/sproutcore/globals/panels.js +182 -0
- data/frameworks/sproutcore/globals/popups.js +60 -0
- data/frameworks/sproutcore/globals/window.js +381 -0
- data/frameworks/sproutcore/lib/index.rhtml +66 -0
- data/frameworks/sproutcore/models/collection.js +395 -0
- data/frameworks/sproutcore/models/record.js +622 -0
- data/frameworks/sproutcore/models/store.js +295 -0
- data/frameworks/sproutcore/panes/dialog.js +16 -0
- data/frameworks/sproutcore/panes/manager.js +164 -0
- data/frameworks/sproutcore/panes/menu.js +45 -0
- data/frameworks/sproutcore/panes/overlay.js +231 -0
- data/frameworks/sproutcore/panes/pane.js +90 -0
- data/frameworks/sproutcore/panes/panel.js +19 -0
- data/frameworks/sproutcore/panes/picker.js +45 -0
- data/frameworks/sproutcore/tests/controllers/array.rhtml +86 -0
- data/frameworks/sproutcore/tests/controllers/controller.rhtml +273 -0
- data/frameworks/sproutcore/tests/controllers/object.rhtml +327 -0
- data/frameworks/sproutcore/tests/foundation/application.rhtml +125 -0
- data/frameworks/sproutcore/tests/foundation/array.rhtml +221 -0
- data/frameworks/sproutcore/tests/foundation/object.rhtml +69 -0
- data/frameworks/sproutcore/tests/globals/window.rhtml +45 -0
- data/frameworks/sproutcore/tests/panes/pane.rhtml +88 -0
- data/frameworks/sproutcore/tests/views/collection.rhtml +137 -0
- data/frameworks/sproutcore/tests/views/popup_button.rhtml +115 -0
- data/frameworks/sproutcore/tests/views/text_field.rhtml +37 -0
- data/frameworks/sproutcore/validators/credit_card.js +92 -0
- data/frameworks/sproutcore/validators/date.js +36 -0
- data/frameworks/sproutcore/validators/email.js +29 -0
- data/frameworks/sproutcore/validators/not_empty.js +24 -0
- data/frameworks/sproutcore/validators/number.js +55 -0
- data/frameworks/sproutcore/validators/password.js +78 -0
- data/frameworks/sproutcore/validators/validator.js +304 -0
- data/frameworks/sproutcore/views/button.js +425 -0
- data/frameworks/sproutcore/views/checkbox_field.js +30 -0
- data/frameworks/sproutcore/views/collection.js +1521 -0
- data/frameworks/sproutcore/views/container.js +62 -0
- data/frameworks/sproutcore/views/error_explanation.js +45 -0
- data/frameworks/sproutcore/views/field.js +214 -0
- data/frameworks/sproutcore/views/filter_button.js +29 -0
- data/frameworks/sproutcore/views/form.js +591 -0
- data/frameworks/sproutcore/views/image.js +141 -0
- data/frameworks/sproutcore/views/inline_text_editor.js +96 -0
- data/frameworks/sproutcore/views/label.js +176 -0
- data/frameworks/sproutcore/views/menu_item.js +90 -0
- data/frameworks/sproutcore/views/pagination.js +54 -0
- data/frameworks/sproutcore/views/popup_button.js +86 -0
- data/frameworks/sproutcore/views/popup_menu.js +137 -0
- data/frameworks/sproutcore/views/progress.js +100 -0
- data/frameworks/sproutcore/views/radio_field.js +107 -0
- data/frameworks/sproutcore/views/radio_group.js +48 -0
- data/frameworks/sproutcore/views/segmented.js +80 -0
- data/frameworks/sproutcore/views/select_field.js +272 -0
- data/frameworks/sproutcore/views/spinner.js +11 -0
- data/frameworks/sproutcore/views/tab.js +126 -0
- data/frameworks/sproutcore/views/text_field.js +179 -0
- data/frameworks/sproutcore/views/textarea_field.js +14 -0
- data/frameworks/sproutcore/views/toolbar.js +29 -0
- data/frameworks/sproutcore/views/view.js +1389 -0
- data/frameworks/sproutcore/views/workspace.js +170 -0
- data/generators/client/README +3 -0
- data/generators/client/USAGE +12 -0
- data/generators/client/client_generator.rb +53 -0
- data/generators/client/templates/core.js +19 -0
- data/generators/client/templates/english.lproj/body.css +0 -0
- data/generators/client/templates/english.lproj/body.rhtml +3 -0
- data/generators/client/templates/english.lproj/controls.css +0 -0
- data/generators/client/templates/english.lproj/strings.js +14 -0
- data/generators/client/templates/main.js +37 -0
- data/generators/controller/USAGE +16 -0
- data/generators/controller/controller_generator.rb +51 -0
- data/generators/controller/templates/controller.js +21 -0
- data/generators/controller/templates/test.rhtml +21 -0
- data/generators/framework/README +7 -0
- data/generators/framework/USAGE +12 -0
- data/generators/framework/framework_generator.rb +53 -0
- data/generators/framework/templates/core.js +20 -0
- data/generators/framework/templates/english.lproj/body.css +0 -0
- data/generators/framework/templates/english.lproj/body.rhtml +3 -0
- data/generators/framework/templates/english.lproj/controls.css +0 -0
- data/generators/framework/templates/english.lproj/strings.js +14 -0
- data/generators/language/USAGE +16 -0
- data/generators/language/language_generator.rb +47 -0
- data/generators/language/templates/strings.js +10 -0
- data/generators/model/USAGE +24 -0
- data/generators/model/model_generator.rb +55 -0
- data/generators/model/templates/fixture.js +11 -0
- data/generators/model/templates/model.js +20 -0
- data/generators/model/templates/test.rhtml +21 -0
- data/generators/test/USAGE +16 -0
- data/generators/test/templates/test.rhtml +21 -0
- data/generators/test/test_generator.rb +47 -0
- data/generators/view/USAGE +16 -0
- data/generators/view/templates/test.rhtml +21 -0
- data/generators/view/templates/view.js +20 -0
- data/generators/view/view_generator.rb +51 -0
- data/jsdoc/README.txt +119 -0
- data/jsdoc/app/DocFile.js +137 -0
- data/jsdoc/app/DocTag.js +110 -0
- data/jsdoc/app/Doclet.js +63 -0
- data/jsdoc/app/Dumper.js +143 -0
- data/jsdoc/app/JsDoc.js +103 -0
- data/jsdoc/app/JsHilite.js +45 -0
- data/jsdoc/app/JsIO.js +163 -0
- data/jsdoc/app/JsParse.js +385 -0
- data/jsdoc/app/JsPlate.js +130 -0
- data/jsdoc/app/JsTestrun.js +129 -0
- data/jsdoc/app/JsToke.js +564 -0
- data/jsdoc/app/Symbol.js +298 -0
- data/jsdoc/app/Transformer.js +14 -0
- data/jsdoc/app/Util.js +97 -0
- data/jsdoc/app/js.jar +0 -0
- data/jsdoc/app/run.js +144 -0
- data/jsdoc/plugins/min.js +316 -0
- data/jsdoc/plugins/strip.js +20 -0
- data/jsdoc/templates/sproutcore/class.tmpl +438 -0
- data/jsdoc/templates/sproutcore/default.css +241 -0
- data/jsdoc/templates/sproutcore/index.html +13 -0
- data/jsdoc/templates/sproutcore/index.tmpl +21 -0
- data/jsdoc/templates/sproutcore/prototype.js +4186 -0
- data/jsdoc/templates/sproutcore/publish.js +236 -0
- data/jsdoc/templates/sproutcore/splash.html +7 -0
- data/lib/sproutcore/build_tools/html_builder.rb +88 -0
- data/lib/sproutcore/build_tools/resource_builder.rb +194 -0
- data/lib/sproutcore/build_tools.rb +44 -0
- data/lib/sproutcore/bundle.rb +517 -0
- data/lib/sproutcore/bundle_manifest.rb +397 -0
- data/lib/sproutcore/generator_helper.rb +170 -0
- data/lib/sproutcore/helpers/capture_helper.rb +42 -0
- data/lib/sproutcore/helpers/static_helper.rb +80 -0
- data/lib/sproutcore/helpers/tag_helper.rb +110 -0
- data/lib/sproutcore/helpers/text_helper.rb +336 -0
- data/lib/sproutcore/helpers.rb +3 -0
- data/lib/sproutcore/jsdoc.rb +40 -0
- data/lib/sproutcore/jsmin.rb +247 -0
- data/lib/sproutcore/library.rb +258 -0
- data/lib/sproutcore/merb/bundle_controller.rb +179 -0
- data/lib/sproutcore/merb/router.rb +43 -0
- data/lib/sproutcore/merb.rb +27 -0
- data/lib/sproutcore/version.rb +9 -0
- data/lib/sproutcore/view_helpers/button_views.rb +302 -0
- data/lib/sproutcore/view_helpers/core_views.rb +284 -0
- data/lib/sproutcore/view_helpers/form_views.rb +258 -0
- data/lib/sproutcore/view_helpers/menu_views.rb +94 -0
- data/lib/sproutcore/view_helpers.rb +628 -0
- data/lib/sproutcore.rb +30 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/sproutcore_spec.rb +11 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- 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)
|