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,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
+ }) ;