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,272 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('views/field') ;
7
+
8
+ // SelectFieldView displays browser-native popup menu. To use this view,
9
+ // you should either bake into the HTML the preset list of options, or
10
+ // you can set the -objects property to an array of items to show. The
11
+ // value is current value of the select.
12
+ SC.SelectFieldView = SC.FieldView.extend({
13
+
14
+ emptyElement: '<select></select>',
15
+
16
+ // set this property to an array of items that will form the menu
17
+ // you want to show.
18
+ objects: null,
19
+
20
+ // if you set this to a non-null value, then the name shown for each
21
+ // menu item will be pulled from the object using the named property.
22
+ // if this is null, the collection objects themselves will be used.
23
+ nameKey: null,
24
+
25
+ // if you set this to a non-null value, then the value of this key will
26
+ // be used to sort the objects. If this is not set, then nameKey will
27
+ // be used.
28
+ sortKey: null,
29
+
30
+ // set this to a non-null value to use a key from the passed set of objects
31
+ // as the value for the options popup. If you don't set this, then the
32
+ // objects themselves will be used as the value.
33
+ valueKey: null,
34
+
35
+ // set this to non-null to place an empty option at the top of the menu.
36
+ emptyName: null,
37
+
38
+ // if true, the empty name will be localized.
39
+ localize: false,
40
+
41
+ // override this to change the enabled/disabled state of menu items as they
42
+ // are built. Return false if you want the menu item to be disabled.
43
+ validateMenuItem: function(itemValue, itemName) {
44
+ return true ;
45
+ },
46
+
47
+ // override this method to implement your own sorting of the menu. By
48
+ // default, menu items are sorted using the value shown.
49
+ sortObjects: function(objects) {
50
+ var nameKey = this.get('sortKey') || this.get('nameKey') ;
51
+ objects = objects.sort(function(a,b) {
52
+ if (nameKey) {
53
+ a = (a.get) ? a.get(nameKey) : a[nameKey] ;
54
+ b = (b.get) ? b.get(nameKey) : b[nameKey] ;
55
+ }
56
+ return (a<b) ? -1 : ((a>b) ? 1 : 0) ;
57
+ }) ;
58
+
59
+ return objects ;
60
+ },
61
+
62
+ // call this method to rebuild the menu manually. Normally you should not
63
+ // need to do this since the menu will be rebuilt as its data changes.
64
+ rebuildMenu: function() {
65
+ this._rebuildMenu() ;
66
+ },
67
+
68
+
69
+ mouseDown: function(e)
70
+ {
71
+ e._stopWhenHandled = false;
72
+ return false;
73
+ },
74
+
75
+
76
+ // .......................................
77
+ // PRIVATE
78
+ //
79
+
80
+ // when fetching the raw value, convert back to an object if needed...
81
+ getFieldValue: function() {
82
+ var value = this.rootElement.value ; // get raw value...
83
+ var valueKey = this.get('valueKey') ;
84
+ var objects = this.get('objects') ;
85
+
86
+ // Handle empty selection.
87
+ if (value == '***') {
88
+ value = null ;
89
+
90
+ // If no value key was set and there are objects then match back to an
91
+ // object.
92
+ } else if (value && objects) {
93
+ objects = Array.from(objects) ;
94
+ var loc = objects.length ;
95
+ var found = null ; // matching object goes here.
96
+ while(!found && (--loc >= 0)) {
97
+ var object = objects[loc] ;
98
+
99
+ // get value using valueKey if there is one or use object
100
+ // map to _guid or toString.
101
+ if (valueKey) object = (object.get) ? object.get(valueKey) : object[valueKey] ;
102
+ ov = (object) ? ((object._guid) ? object._guid : object.toString()) : null ;
103
+
104
+ // use this object value if it matches.
105
+ if (value == ov) found = object ;
106
+ }
107
+ }
108
+
109
+ return value ;
110
+ },
111
+
112
+ // when setting the raw value, convert from object...
113
+ setFieldValue: function(nv) {
114
+ if (nv) {
115
+ nv = (nv._guid) ? nv._guid : nv.toString() ;
116
+ } else {
117
+ nv = "***" ;
118
+ }
119
+ if (this.rootElement.value != nv) this.rootElement.value = nv ;
120
+ },
121
+
122
+ // this method is called anytime the objects property or any of its member
123
+ // objects change.
124
+ _rebuildMenu: function() {
125
+ // get list of objects.
126
+ var nameKey = this.get('nameKey') ;
127
+ var valueKey = this.get('valueKey') ;
128
+ var objects = this.get('objects') ;
129
+ var fieldValue = this.get('value') ;
130
+
131
+ // convert fieldValue to guid, if it is an object.
132
+ if (!valueKey && fieldValue) fieldValue = fieldValue._guid ;
133
+ if ((fieldValue == null) || (fieldValue == '')) fieldValue = '***' ;
134
+
135
+ if (objects) {
136
+ objects = Array.from(objects) ; // make array.
137
+ objects = this.sortObjects(objects) ; // sort'em.
138
+ var html = [] ;
139
+
140
+ var emptyName = this.get('emptyName') ;
141
+ if (emptyName) {
142
+ if (this.get('localize')) emptyName = emptyName.loc() ;
143
+ html.push('<option value="***">%@</option>'.fmt(emptyName)) ;
144
+ html.push('<option disabled="disabled"></option>') ;
145
+ }
146
+
147
+ // generate option elements.
148
+ objects.each(function(object) {
149
+ if (object) {
150
+
151
+ // either get the name from the object or convert object to string.
152
+ var name = (nameKey) ? ((object.get) ? object.get(nameKey) : object[nameKey]) : object.toString() ;
153
+
154
+ // get the value using the valueKey or the object if no valueKey.
155
+ // then convert to a string or use _guid if one of available.
156
+ var value = (valueKey) ? ((object.get) ? object.get(valueKey) : object[valueKey]) : object ;
157
+ if (value) value = (value._guid) ? value._guid : value.toString() ;
158
+
159
+ // render HTML
160
+ var disable = (this.validateMenuItem && this.validateMenuItem(value, name)) ? '' : 'disabled="disabled" ' ;
161
+ html.push('<option %@value="%@">%@</option>'.fmt(disable,value,name)) ;
162
+
163
+ // null value means separator.
164
+ } else {
165
+ html.push('<option disabled="disabled"></option>') ;
166
+ }
167
+ }.bind(this) );
168
+
169
+ // replace the contents of this HTML element.
170
+ this.update(html.join(""));
171
+ this.rootElement.value = fieldValue ;
172
+
173
+ } else {
174
+ this.set('value',null);
175
+ }
176
+ },
177
+
178
+ // object changes to the objects array of objects if possible.
179
+ _objectsObserver: function() {
180
+ if (!this._boundObserver) {
181
+ this._boundObserver = this._objectsItemObserver.bind(this) ;
182
+ }
183
+
184
+ if (this.didChangeFor('_objO','objects','nameKey','valueKey')) {
185
+ var loc ;
186
+ var objects = Array.from(this.get('objects')) ;
187
+ var func = this._boundObserver ;
188
+
189
+ // stop observing old objects.
190
+ if (this._objects) {
191
+ loc = this._objects.length ;
192
+ while(--loc >= 0) {
193
+ var object = this._objects[loc] ;
194
+ if (object && object.removeObserver) {
195
+ if (this._nameKey && this._valueKey) {
196
+ object.removeObserver(this._nameKey, func) ;
197
+ object.removeObserver(this._valueKey, func) ;
198
+ } else {
199
+ object.removeObserver('*', func) ;
200
+ } // if (this._nameKey)
201
+ } // if (object &&...)
202
+ } // while(--loc)
203
+ } // if (this._objects)
204
+
205
+ // start observing new objects.
206
+ this._objects = objects ;
207
+ this._nameKey = this.get('nameKey') ;
208
+ this._valueKey = this.get('valueKey') ;
209
+
210
+ if (this._objects) {
211
+ loc = this._objects.length ;
212
+ while(--loc >= 0) {
213
+ var object = this._objects[loc] ;
214
+ if (object && object.addObserver) {
215
+ if (this._nameKey && this._valueKey) {
216
+ object.addObserver(this._nameKey, func) ;
217
+ object.addObserver(this._valueKey, func) ;
218
+ } else {
219
+ object.addObserver('*', func) ;
220
+ } // if (this._nameKey)
221
+ } // if (object &&...)
222
+ } // while(--loc)
223
+ } // if (this._objects)
224
+
225
+ this._rebuildMenu() ;
226
+ } // if (this.didChangeFor...)
227
+ }.observes('objects','nameKey','valueKey'),
228
+
229
+ // this is invoked anytime an item we are interested in in the menu changes
230
+ // rebuild the menu when this happens, but only one time.
231
+ _objectsItemObserver: function(item, key, value) {
232
+ if (item.didChangeFor(this._guid, key)) {
233
+ console.log('rebuildMenu') ;
234
+ this._rebuildMenu() ;
235
+ }
236
+ },
237
+
238
+
239
+
240
+ _fieldDidFocus: function()
241
+ {
242
+ var isFocused = this.get('isFocused');
243
+ if (!isFocused) this.set('isFocused', true);
244
+ },
245
+ _fieldDidBlur: function()
246
+ {
247
+ var isFocused = this.get('isFocused');
248
+ if (isFocused) this.set('isFocused', false);
249
+ },
250
+ _isFocusedObserver: function()
251
+ {
252
+ var isFocused = this.get('isFocused');
253
+ this.setClassName('focus', isFocused);
254
+ }.observes('isFocused'),
255
+
256
+
257
+ init: function()
258
+ {
259
+ arguments.callee.base.call(this);
260
+ this._rebuildMenu();
261
+
262
+ var changeListener = this.fieldValueDidChange.bind(this,false);
263
+ Element.observe(this.rootElement, 'change', changeListener);
264
+
265
+ var focusListener = this._fieldDidFocus.bindAsEventListener(this);
266
+ Element.observe(this.rootElement, 'focus', focusListener);
267
+
268
+ var blurListener = this._fieldDidBlur.bindAsEventListener(this);
269
+ Element.observe(this.rootElement, 'blur', blurListener);
270
+ }
271
+
272
+ });
@@ -0,0 +1,11 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('views/view') ;
7
+
8
+ // A SpinnerView can be used to show state when loading.
9
+ SC.SpinnerView = SC.View.extend({
10
+ isVisibleBindingDefault: SC.Binding.Not
11
+ }) ;
@@ -0,0 +1,126 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('views/view') ;
7
+ require('views/container') ;
8
+
9
+ /** @class
10
+
11
+ To use a TabView, just declare the views and buttons you want to manage
12
+ as outlets. Then set the "nowShowing" property to the name of view.
13
+
14
+ View names comes from either the name of the view property or from the
15
+ view's 'tabId' property, if it has one. Declare tabs by adding properties
16
+ ending in 'Tab' and buttons ending in 'Button'
17
+
18
+ @extends SC.ContainerView
19
+ */
20
+ SC.TabView = SC.ContainerView.extend(
21
+ /** @scope SC.TabView.prototype */
22
+ {
23
+
24
+ /**
25
+ set the tabId here that you to display minus the "Tab".
26
+
27
+ @type String
28
+ */
29
+ nowShowing: '',
30
+
31
+ /**
32
+ instantiate tabs lazily as they are accessed.
33
+
34
+ If set to true, tabs will be instanted from the SC.page object when they
35
+ are first accessed. If your tabs have complex content, using lazy tabs
36
+ can dramatically improve page load performance.
37
+
38
+ @type Boolean
39
+ */
40
+ lazyTabs: false,
41
+
42
+
43
+ // ...................................
44
+ // INTERNAL
45
+ //
46
+
47
+ /** @private */
48
+ init: function() {
49
+ arguments.callee.base.call(this) ;
50
+
51
+ // find outlets and build list of tabs and buttons.
52
+ var tabs = {} ;
53
+ var buttons = {} ;
54
+ var view = this ;
55
+ var loc = (this.outlets) ? this.outlets.length : 0 ;
56
+ while(--loc >= 0) {
57
+ var outlet = this.outlets[loc] ;
58
+ // look for outlets ending in 'Tab'
59
+ if (outlet.slice(outlet.length-3,outlet.length) == "Tab") {
60
+ var key = outlet.slice(0,-3) ; // remove 'Tab'
61
+ var tab = view.get(outlet) ; // find tab view
62
+ var button = view.get(key + 'Button') ; // find button view (opt)
63
+ if (tab) {
64
+ // the key is either computed from the property name or from tabId.
65
+ var tabId = tab.get('tabId') || key ;
66
+ tabs[tabId] = tab ;
67
+ if (button) buttons[tabId] = button ;
68
+
69
+ // also remove the tab from its parent view.
70
+ if (tab.removeFromParent) tab.removeFromParent() ;
71
+
72
+ } // if (tab)
73
+ } // if (outlet.slice)
74
+ } // while
75
+
76
+ this._tabs = tabs; this._buttons = buttons ;
77
+ this.nowShowingObserver() ; // swap in/out the appropriate views.
78
+ },
79
+
80
+ /** @private
81
+ swaps the views in and out.
82
+ */
83
+ nowShowingObserver: function() {
84
+ var nowShowing = this.get('nowShowing') ;
85
+ if (nowShowing == this._oldNowShowing) return ; // nothing to do.
86
+ this._oldNowShowing = nowShowing ;
87
+ for(var tabId in this._tabs) {
88
+ var tab = this._tabs[tabId] ;
89
+ var button = this._buttons[tabId] ;
90
+ if (tabId == nowShowing) {
91
+ if (button) button.set('isSelected',true) ;
92
+ } else {
93
+ if (tab) tab.set('isVisible',false) ;
94
+ if (button) button.set('isSelected',false) ;
95
+ }
96
+ }
97
+
98
+ var visibleTab = this._tabs[nowShowing] ;
99
+
100
+ if (!visibleTab && this.get('lazyTabs')) {
101
+ this._tabs[nowShowing] = visibleTab = SC.page.get('%@Tab'.fmt(nowShowing)) ;
102
+ }
103
+
104
+ this.set('content',visibleTab) ;
105
+ if (visibleTab) { visibleTab.set('isVisible',true); }
106
+
107
+ }.observes('nowShowing'),
108
+
109
+ /**
110
+ Used by SC.FormView to find child fields.
111
+
112
+ The TabView removes its child views from the hierarchy on startup, which
113
+ can prevent a view such as SC.FormView, that search their children for
114
+ configuration information from working properly. To work around this
115
+ problem, SC.FormView and other views will use this method to get the child
116
+ views they should search instead of looking at childNodes directly.
117
+
118
+ Note that if you use lazy tabs, form fields will not work because the tabs
119
+ are not instantiated until they are accessed.
120
+ */
121
+ childNodesForFormField: function() {
122
+ return Object.values(this._tabs || {}) ;
123
+ }
124
+
125
+ }) ;
126
+
@@ -0,0 +1,179 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('views/field') ;
7
+
8
+ // A text field is an input element with type "text". This view adds support
9
+ // for hinted values, etc.
10
+ SC.TextFieldView = SC.FieldView.extend({
11
+
12
+ emptyElement: '<input type="text" value="" />',
13
+
14
+ // PROPERTIES
15
+ // set this property to the hinted value.
16
+ hint: null,
17
+
18
+ // automatically set by text field if the hint is current showing.
19
+ isHintShowing: false,
20
+
21
+
22
+ // PRIVATE SUPPORT METHODS
23
+ init: function() {
24
+
25
+ // compatibility...
26
+ if (this.hint == null) {
27
+ this.hint = this.rootElement.getAttribute('hint') ;
28
+ }
29
+
30
+ if (this.validator == null) {
31
+ this.validator = this.rootElement.getAttribute('validate') ;
32
+ }
33
+
34
+ arguments.callee.base.call(this) ;
35
+
36
+ // observe important events for this field.
37
+ var focusListener = this._fieldDidFocus.bindAsEventListener(this) ;
38
+ Event.observe(this.rootElement, 'focus', focusListener) ;
39
+
40
+ var blurListener = this._fieldDidBlur.bindAsEventListener(this) ;
41
+ Event.observe(this.rootElement, 'blur', blurListener) ;
42
+
43
+ this._updateFieldHint() ;
44
+ },
45
+
46
+
47
+ // FOCUS AND BLUR EVENTS -
48
+ // These should be hooked into the firstResponder system..
49
+ _fieldDidFocus: function() {
50
+ if (!this._isFocused) {
51
+ this._isFocused = true ;
52
+ this.becomeFirstResponder() ;
53
+ }
54
+ },
55
+
56
+ _fieldDidBlur: function() {
57
+ if (this._isFocused) {
58
+ this._isFocused = false ;
59
+ this.resignFirstResponder() ;
60
+ }
61
+ },
62
+
63
+ acceptsFirstResponder: function() {
64
+ return this.get('isEnabled');
65
+ }.property('isEnabled'),
66
+
67
+ // First Responder
68
+ // When we become first responder, make sure the field gets focus and
69
+ // the hint value is hidden if needed.
70
+
71
+ // when we become first responder, focus the text field if needed and
72
+ // hide the hint text.
73
+ didBecomeFirstResponder: function() {
74
+
75
+ // focus the text field.
76
+ if (!this._isFocused) {
77
+ this._isFocused = true ;
78
+ if (this.get('isVisibleInWindow')) {
79
+ this.rootElement.focus();
80
+ this.rootElement.select.bind(this.rootElement).delay(0.05);
81
+ }
82
+ }
83
+
84
+ // hide the hint text if it is showing.
85
+ this._updateFieldHint() ;
86
+ },
87
+
88
+ // when we lose first responder, blur the text field if needed and show
89
+ // the hint text if needed.
90
+ willLoseFirstResponder: function() {
91
+
92
+ if (this._isFocused) {
93
+ this._isFocused = false ;
94
+ return this.rootElement.blur() ;
95
+ }
96
+
97
+ this._value = this.rootElement.value ;
98
+ this.fieldValueDidChange() ;
99
+ this._updateFieldHint() ;
100
+ },
101
+
102
+ _isFocused: false,
103
+
104
+ _updateFieldHint: function() {
105
+
106
+ // show the hint if:
107
+ // - flag is true
108
+ // - hint != null or empty.
109
+ // - this._value = null or empty.
110
+ var hint = this.get('hint') ;
111
+ var showHint = !!(!this._isFocused && ((this._value == null) || this._value == '') && (hint)) ;
112
+
113
+ this.setClassName('show-hint', showHint);
114
+ this.rootElement.value = (showHint) ? hint : (this._value || '') ;
115
+ this.set('isHintShowing', showHint);
116
+ },
117
+
118
+ // field value updates...
119
+ getFieldValue: function() {
120
+ return this._value ;
121
+ },
122
+
123
+ setFieldValue: function(value) {
124
+ if (this._value == value) return ;
125
+ this._value = value ;
126
+ this._updateFieldHint() ;
127
+ },
128
+
129
+ mouseDown: function(e)
130
+ {
131
+ e._stopWhenHandled = false;
132
+ return false;
133
+ },
134
+
135
+ // trap key-press events and notify as needed.
136
+ keyDown: function(evt) {
137
+ if (this._value != this.rootElement.value) {
138
+ this._value = this.rootElement.value ;
139
+ this.fieldValueDidChange(true) ;
140
+ }
141
+
142
+ return this.interpretKeyEvents(evt); // start bubbling key events...
143
+ //return false;
144
+ },
145
+
146
+ keyUp: function() {
147
+ if (this._value != this.rootElement.value) {
148
+ this._value = this.rootElement.value ;
149
+ this.fieldValueDidChange(true) ;
150
+ }
151
+ },
152
+
153
+ // if make a text field first responder before the view becomes visible,
154
+ // then focus the text field when it does become visible.
155
+ _focusOnVisible: function() {
156
+ if (this.get('isVisibleInWindow') && this._isFocused) {
157
+ this.rootElement.focus() ;
158
+ this.rootElement.select.bind(this.rootElement).delay(0.05);
159
+ }
160
+ }.observes('isVisibleInWindow'),
161
+
162
+ // THESE ARE DUMMY IMPLEMENTATIONS OF THE REPONDER METHODS FOR KEYBOARD
163
+ // ACTIONS HANDLED BY THE BROWSER. This avoids having the responder
164
+ // bubble up these items.
165
+ deleteBackward: function(evt) { evt._stopWhenHandled = false; return true; },
166
+ deleteForward: function(evt) { evt._stopWhenHandled = false; return true; },
167
+ moveLeft: function(evt) { evt._stopWhenHandled = false; return true; },
168
+ moveRight: function(evt) { evt._stopWhenHandled = false; return true; },
169
+ moveUp: function(evt) { evt._stopWhenHandled = false; return true; },
170
+ moveDown: function(evt) { evt._stopWhenHandled = false; return true; },
171
+ moveLeftAndModifySelection: function(evt) { evt._stopWhenHandled = false; return true; },
172
+ moveRightAndModifySelection: function(evt) { evt._stopWhenHandled = false; return true; },
173
+ moveUpAndModifySelection: function(evt) { evt._stopWhenHandled = false; return true; },
174
+ moveDownAndModifySelection: function(evt) { evt._stopWhenHandled = false; return true; },
175
+ moveToBeginningOfDocument: function(evt) { evt._stopWhenHandled = false; return true; },
176
+ moveToEndOfDocument: function(evt) { evt._stopWhenHandled = false; return true; },
177
+ selectAll: function(evt) { evt._stopWhenHandled = false; return true; }
178
+
179
+ }) ;
@@ -0,0 +1,14 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('views/text_field') ;
7
+
8
+ SC.TextareaFieldView = SC.TextFieldView.extend({
9
+
10
+ emptyElement: '<textarea></textarea>',
11
+
12
+ insertNewline: function(evt) { evt._stopWhenHandled = false; return true; }
13
+
14
+ });
@@ -0,0 +1,29 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ // A menu is not a view exactly, but you can use it to bundle together
7
+ // buttons and then validate them as a whole.
8
+ SC.Toolbar = SC.View.extend({
9
+
10
+ // override with an array of outlet functions.
11
+ buttons: [],
12
+
13
+ // to to false an all the buttons will be disabled also.
14
+ isEnabled: true,
15
+
16
+ init: function() {
17
+ arguments.callee.base.call(this) ;
18
+ var toolbar = this ;
19
+ this.buttons = this.buttons.map(function(button) {
20
+ return button(toolbar) ; // get outlet.
21
+ }) ;
22
+ },
23
+
24
+ isEnabledObserver: function() {
25
+ var e = this.get('isEnabled') ;
26
+ this.get('buttons').each(function(button) { button.set('isEnabled',e); }) ;
27
+ }.observes('isEnabled')
28
+
29
+ }) ;