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,777 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2007 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('Core') ;
7
+ require('foundation/benchmark') ;
8
+ require('foundation/observable') ;
9
+
10
+ SC.BENCHMARK_OBJECTS = NO;
11
+
12
+ /**
13
+ @class Root Object for SproutCore framework.
14
+
15
+ This is the root object of the SproutCore framework. All other objects
16
+ inherit from you. SC.Object among other things implements support for
17
+ class inheritance, observers, and bindings. You should use SC.Object to
18
+ create your own subclasses as well.
19
+
20
+ Please see online documentation for more information about this.
21
+
22
+ I should be able to put a long list of things here I suppose.
23
+
24
+ Do bullet
25
+ points
26
+ work?
27
+
28
+ @extends SC.Observable
29
+ */
30
+ SC.Object = function(noinit) {
31
+ if (noinit == SC.Object._noinit_) return ;
32
+ var ret = SC.Object._init.apply(this,$A(arguments)) ;
33
+ return ret ;
34
+ };
35
+
36
+ Object.extend(SC.Object, {
37
+
38
+ _noinit_: '__noinit__',
39
+
40
+ // Use this to add class methods to an object.
41
+ mixin: function() {
42
+ var ext = $A(arguments) ;
43
+ for(var loc=0;loc<ext.length;loc++) {
44
+ Object.extend(this,ext[loc]);
45
+ }
46
+ return this ;
47
+ },
48
+
49
+ // this will created a new version of the passed object, updating the
50
+ // prototype to use the new code.
51
+ extend: function() {
52
+
53
+ if (SC.BENCHMARK_OBJECTS) SC.Benchmark.start('SC.Object.extend') ;
54
+
55
+ // build function. copy class methods on to it.
56
+ var ret = function(noinit) {
57
+ if (noinit && (typeof(noinit) == 'string') && (noinit == SC.Object._noinit_)) return ;
58
+ var ret = SC.Object._init.apply(this,$A(arguments));
59
+ return ret ;
60
+ };
61
+ for(var prop in this) { ret[prop] = this[prop]; }
62
+
63
+ // extend the prototype with passed arguments.
64
+ var base = new this(SC.Object._noinit_) ;
65
+
66
+ // var base = SC.Object._extend({},this.prototype) ;
67
+ var extensions = $A(arguments) ;
68
+ for(var loc=0;loc<extensions.length;loc++) {
69
+ base = SC.Object._extend(base, extensions[loc]);
70
+ }
71
+ ret.prototype = base ;
72
+
73
+ // return new extension
74
+ ret._guid = SC._nextGUID++ ; // each time we extend, get a new guid.
75
+ ret._type = this ;
76
+
77
+ if (SC.BENCHMARK_OBJECTS) SC.Benchmark.end('SC.Object.extend') ;
78
+
79
+ return ret ;
80
+ },
81
+
82
+ // create a new instance of the object.
83
+ create: function() {
84
+ var ret = new this($A(arguments),this) ;
85
+ return ret ;
86
+ },
87
+
88
+ // takes an array of configs and returns instances of each object.
89
+ createArray: function(array) {
90
+ var obj = this ;
91
+ return array.map(function(props) { return obj.create(props); }) ;
92
+ },
93
+
94
+ // configure this object as an outlet
95
+ outlet: function() {
96
+ var obj = this ;
97
+ return function() {
98
+ var ret = obj.create() ; ret.owner = this ; return ret ;
99
+ } ;
100
+ },
101
+
102
+ isClass: true,
103
+
104
+ // ..........................................
105
+ // PROPERTY SUPPORT METHODS
106
+ //
107
+ // get the tuple for a property path (the object and key).
108
+ tupleForPropertyPath: function(path,root) {
109
+ if (path.constructor == Array) return path ;
110
+
111
+ // * = the rest is a chained property.
112
+ var parts = path.split('*') ; var key = null ;
113
+ if (parts && parts.length > 1) {
114
+ key = parts.pop(); path = parts.join('*') ;
115
+ }
116
+
117
+ // get object path. property is last part if * was nt found.
118
+ parts = path.split('.') ;
119
+ if (!key) key = parts.pop() ;
120
+
121
+ // convert path to object.
122
+ var obj = this.objectForPropertyPath(parts,root) ;
123
+ return (obj && key) ? [obj,key] : null ;
124
+ },
125
+
126
+ objectForPropertyPath: function(path,root) {
127
+ var parts = (typeof(path) == "string") ? path.split('.') : path ;
128
+ if (!root) root = window ;
129
+ var key = parts.shift() ;
130
+ while(key && root) {
131
+ root = (root.get) ? root.get(key) : root[key];
132
+ key = parts.shift();
133
+ }
134
+ return (parts.length > 0) ? undefined : root ;
135
+ },
136
+
137
+
138
+ // ..........................................
139
+ // INTERNAL SUPPORT METHODS
140
+ //
141
+ _init: function(extensions,type) {
142
+
143
+ var ret = this ;
144
+ for(var loc=0;loc<extensions.length;loc++) {
145
+ ret = SC.Object._extend(ret,extensions[loc]) ;
146
+ }
147
+ ret._guid = SC._nextGUID++ ;
148
+ ret._type = type ;
149
+ ret.init() ;
150
+
151
+ return ret ;
152
+ },
153
+
154
+ // This will extend the base object with the properties passed in the second
155
+ // var, maintaining super's for the functions and concatinating cprops.
156
+ _extend: function(base,ext) { return this._extendAllProps(false, base, ext); },
157
+
158
+ _extendAllProps: function(allProperties, base,ext) {
159
+ var cprops = base._cprops ; var f = Prototype.emptyFunction ;
160
+
161
+ // first, save any concat props.
162
+ var concats = {} ;
163
+ if (cprops) for(var cloc=0;cloc<cprops.length;cloc++) {
164
+ var p = cprops[cloc]; var p1 = base[p]; var p2 = ext[p] ;
165
+ p1 = (p1 && p2) ? p1.concat(p2) : (p1 || p2) ;
166
+ concats[p] = p1 ;
167
+ }
168
+
169
+ // deal with observers, bindings, and properties only if they are not
170
+ // defined already in the ext. If they are defined in ext, they will be
171
+ // concated using the above code.
172
+ var bindings = (ext._bindings) ? null : (base._bindings || []).slice() ;
173
+ var observers = (ext._observers) ? null : (base._observers || []).slice();
174
+ var properties = (ext._properties) ? null : (base._properties || []).slice() ;
175
+
176
+ // now copy properties, add superclass to func.
177
+ for(var key in ext) {
178
+ // avoid copying builtin methods
179
+ if (!allProperties && !ext.hasOwnProperty(key)) continue ;
180
+
181
+ // add super to funcs. Be sure not to set the base of a func to itself
182
+ // to avoid infinite loops.
183
+ var value = (concats.hasOwnProperty(key) ? concats[key] : null) || ext[key] ;
184
+ if (value && (value instanceof Function) && (!value.base)) {
185
+ if (value != base[key]) value.base = base[key] || f;
186
+ }
187
+
188
+ // Possibly add to a bindings.
189
+ var keyLen = key.length ;
190
+ if (bindings && (key.slice(keyLen-7,keyLen) == "Binding")) {
191
+ bindings.push(key) ;
192
+
193
+ // Also add observers and properties for functions...
194
+ } else if (value && (value instanceof Function)) {
195
+ if (observers && value.propertyPaths) {
196
+ observers.push(key) ;
197
+ } else if (properties && value.dependentKeys) {
198
+ properties.push(key) ;
199
+ }
200
+ }
201
+
202
+ // copy property
203
+ base[key] = value ;
204
+ }
205
+
206
+ // copy bindings, observers, and properties if defined.
207
+ if (bindings) base._bindings = bindings;
208
+ if (observers) base._observers = observers ;
209
+ if (properties) base._properties = properties ;
210
+
211
+ //console.log('bindings: %@ -- observers: %@ -- properties: %@'.format(base._bindings,base._observers,base._properties)) ;
212
+
213
+ return base ;
214
+ },
215
+
216
+ toString: function() { return 'Object('+ SC.getGUID(this) +')'; },
217
+
218
+ // Returns true if the receiver is a subclass of the named class. If the
219
+ // receiver is the class passed, this will return false. See kindOf().
220
+ subclassOf: function(scClass) {
221
+ if (this == scClass) return false ;
222
+ var t = this._type ;
223
+ while(t) {
224
+ if (t == scClass) return true ;
225
+ t = t._type ;
226
+ }
227
+ return false ;
228
+ },
229
+
230
+ // Returns true if the receiver is the passed class or is any subclass.
231
+ kindOf: function(scClass) {
232
+ if (this == scClass) return true ;
233
+ return this.subclassOf(scClass);
234
+ }
235
+
236
+ }) ;
237
+
238
+ SC.idt = { count: 0, t: 0.0, keys: 0, observers: 0, bindings: 0, pv: 0, observers_t: 0, bindings_t: 0, pv_t: 0, conf_t: 0, b1_t: 0, b2_t: 0, b3_t: 0, e_count: 0, e_t: 0, v_count: 0, v_t: 0, vc_t: 0 ,active: false } ;
239
+
240
+ SC.report = function() {
241
+ var c = SC.idt.count ;
242
+ var e = SC.idt.e_count ;
243
+ var v = SC.idt.v_count ;
244
+ var ret = [] ;
245
+ ret.push('CREATED: ' + c + ' (avg time: '+(Math.floor(SC.idt.t * 100 / c) / 100)+' msec)') ;
246
+ ret.push('EXTENDED: ' + e + ' (avg time: '+(Math.floor(SC.idt.e_t * 100 / e) / 100)+' msec)') ;
247
+ ret.push('AVG KEYS: ' + (Math.floor(SC.idt.keys * 100 / c) / 100)) ;
248
+ ret.push('AVG OBSERVERS: ' + (Math.floor(SC.idt.observers * 100 / c) / 100) + ' ('+ (Math.floor(SC.idt.observers_t * 100 / c) / 100) + ' msec)') ;
249
+ ret.push('AVG BINDINGS: ' + (Math.floor(SC.idt.bindings * 100 / c) / 100) + ' ('+ (Math.floor(SC.idt.bindings_t * 100 / c) / 100) + ' msec)') ;
250
+ ret.push('AVG PV: ' + (Math.floor(SC.idt.pv * 100 / c) / 100) + ' ('+ (Math.floor(SC.idt.pv_t * 100 / c) / 100) + ' msec)') ;
251
+ ret.push('AVG CONFIGURE OUTLETS: ' + (Math.floor(SC.idt.conf_t * 100 / c) / 100) + ' msec') ;
252
+ ret.push('AVG B1: ' + (Math.floor(SC.idt.b1_t * 100 / c) / 100) + ' msec') ;
253
+ ret.push('EXT: ' + SC.idt.ext_c + ' (avg time: ' + (Math.floor(SC.idt.ext_t * 100 / SC.idt.ext_c) / 100) + ' msec)') ;
254
+ ret.push('VIEWS: ' + v + ' (avg time: ' + (Math.floor(SC.idt.v_t * 100 / v) / 100) + ' msec)') ;
255
+ ret.push('VIEW CREATE: ' + (Math.floor(SC.idt.vc_t * 100 / v) / 100) + ' msec)') ;
256
+ console.log(ret.join("\n")) ;
257
+ return ret.join("\n") ;
258
+ } ;
259
+
260
+ // ..........................................
261
+ // DEFAULT OBJECT INSTANCE
262
+ //
263
+ SC.Object.prototype = {
264
+
265
+ isObject: true,
266
+
267
+ respondsTo: function( name )
268
+ {
269
+ return !!(name && this[name] && ($type(this[name]) == T_FUNCTION));
270
+ },
271
+
272
+ tryToPerform: function( name, args )
273
+ {
274
+ if ( !name ) return false;
275
+
276
+ var args = $A(arguments);
277
+ var name = args.shift();
278
+ if (this.respondsTo(name))
279
+ {
280
+ return this[name].apply(this,args);
281
+ }
282
+ return false;
283
+ },
284
+
285
+ /**
286
+ this function is called automatically when a new object instance is
287
+ created. You can use this to configure your child elements if you want.
288
+ Be sure to invoke the base method.
289
+ */
290
+ init: function() {
291
+
292
+ // This keySource is used to fix a bug in FF that will not iterate through
293
+ // keys you add to an HTMLElement. The key values are still accessible,
294
+ // they just aren't visible to the for...in loop. viewType is the hash
295
+ // of values that was applied to the HTMLElement, so its a 1:1 substitute.
296
+ var keySource = this.viewType || this ;
297
+ var loc ; var keys ; var key ; var value ;
298
+
299
+ var r = SC.idt.active ; var idtStart ; var idtSt ;
300
+ if (r) {
301
+ SC.idt.count++;
302
+ idtStart = new Date().getTime() ;
303
+ } ;
304
+
305
+ // Add Observers
306
+ if (keys = keySource._observers) for(loc=0;loc<keys.length;loc++) {
307
+ key = keys[loc] ; value = this[key] ;
308
+
309
+ if (r) {
310
+ SC.idt.keys++ ;
311
+ SC.idt.observers++ ;
312
+ idtSt = new Date().getTime() ;
313
+ }
314
+
315
+ var propertyPaths = null ;
316
+ if ((value instanceof Function) && value.propertyPaths) {
317
+ propertyPaths = value.propertyPaths ;
318
+ value = value.bind(this) ;
319
+ } else if (typeof(value) == "string") {
320
+ propertyPaths = [value] ;
321
+ value = this.propertyObserver.bind(this,key.slice(0,-8)) ;
322
+ }
323
+
324
+ // a property path string was found. Convert this to an object/path
325
+ // and observe.
326
+ if (propertyPaths) for(var ploc=0;ploc<propertyPaths.length;ploc++) {
327
+ var propertyPath = propertyPaths[ploc] ;
328
+ var object = null;
329
+
330
+ // most common case. refers to local property.
331
+ if (propertyPath.indexOf('.') == -1) {
332
+ this.addObserver(propertyPath, value) ;
333
+
334
+ // deal with more exotic cases
335
+ } else switch(propertyPath.slice(0,1)) {
336
+ // start with a . or * means this is a chained local path.
337
+ case '*':
338
+ case '.':
339
+ propertyPath = propertyPath.slice(1,propertyPath.length) ;
340
+ this.addObserver(propertyPath, value) ;
341
+ break ;
342
+
343
+ // this is an absolute path. so hook 'er up.
344
+ default:
345
+ SC.Observers.addObserver(propertyPath, value) ;
346
+ }
347
+ }
348
+
349
+ if (r) SC.idt.observers_t += (new Date().getTime()) - idtSt ;
350
+ }
351
+
352
+ // Add Bindings
353
+ this.bindings = [] ;
354
+ if (keys = keySource._bindings) for(loc=0;loc<keys.length;loc++) {
355
+ key = keys[loc] ; value = this[key] ;
356
+
357
+ if (r) {
358
+ SC.idt.keys++ ;
359
+ SC.idt.bindings++ ;
360
+ idtSt = new Date().getTime() ;
361
+ }
362
+
363
+ // get propertyKey
364
+ var propertyKey = key.slice(0,-7) ; // contentBinding => content
365
+ this[key] = this.bind(propertyKey, value) ;
366
+ if (r) SC.idt.bindings_t += (new Date().getTime()) - idtSt ;
367
+ }
368
+
369
+ // Add Properties
370
+ if (keys = keySource._properties) for(loc=0;loc<keys.length;loc++) {
371
+ key = keys[loc] ; value = this[key] ;
372
+ if (value && value.dependentKeys && (value.dependentKeys.length > 0)) {
373
+ args = value.dependentKeys.slice() ;
374
+ args.unshift(key) ;
375
+ this.registerDependentKey.apply(this,args) ;
376
+ }
377
+ }
378
+
379
+ if (r) { SC.idt.t += ((new Date().getTime()) - idtStart); }
380
+ },
381
+
382
+ /**
383
+ EXPERIMENTAL: You can use this to call super in any method. This
384
+ currently does not work in some versions of Safari.
385
+ */
386
+ $super: function(args) {
387
+ var caller = SC.Object.prototype.$super.caller;
388
+ if (!caller) throw "$super cannot determine the caller method" ;
389
+ if (caller.base) caller.base.apply(this, arguments) ;
390
+ },
391
+
392
+ /**
393
+ Use this to add class methods to an object.
394
+ */
395
+ mixin: function() { return SC.Object.mixin.apply(this,arguments) ; },
396
+
397
+ /**
398
+ Returns all the keys defined on this object, excluding any defined in
399
+ parent classes unless you pass all.
400
+
401
+ @param {Boolean} all OPTIONAL: if YES return all keys, NO return only keys belonging to object itself. Defaults to NO.
402
+ */
403
+ keys: function(all) {
404
+ var ret = []; for(var key in this) {
405
+ if (all || ret.hasOwnProperty(key)) ret.push(key);
406
+ }; return ret ;
407
+ },
408
+
409
+ /**
410
+ returns true if the receiver is an instance of the named class. See also
411
+ kindOf().
412
+ */
413
+ instanceOf: function(scClass) {
414
+ return this._type == scClass ;
415
+ },
416
+
417
+ /**
418
+ Returns true if the receiver is an instance of the named class or any
419
+ subclass of the named class. See also instanceOf().
420
+ */
421
+ kindOf: function(scClass) {
422
+ var t = this._type ;
423
+ while(t) {
424
+ if (t == scClass) return true ;
425
+ t = t._type ;
426
+ }
427
+ return false ;
428
+ },
429
+
430
+ /** @private */
431
+ _enumerator: function() {
432
+
433
+ // build in enumerator.
434
+ if (this.objectAtIndex) {
435
+ ret = {
436
+ nextObject: function() {
437
+ var loc = this.loc ;
438
+ return (loc>=0) ? this.obj.objectAtIndex(--loc) : null ;
439
+ },
440
+ loc: this.get('length') || 0,
441
+ obj: this
442
+ } ;
443
+
444
+ // or just return one that does nothing.
445
+ } else {
446
+ ret = { nextObject: function() { return null; } } ;
447
+ }
448
+
449
+ return ret ;
450
+ },
451
+
452
+ // ..........................................
453
+ // OUTLETS
454
+ //
455
+
456
+ /**
457
+ A view may contain outlets. Outlets are a way to find and connect to
458
+ elements within the view.
459
+ */
460
+ awake: function(key) {
461
+ // if a key is passed, convert that from an outlet and awake it. otherwise
462
+ // awake self.
463
+ if (key !== undefined) {
464
+ var obj = this.outlet(key) ;
465
+ if (obj) obj.awake() ;
466
+ return ;
467
+ }
468
+
469
+ if (this._awake) return ;
470
+ this._awake = true ;
471
+
472
+ // it would be cool to do this in a recursive way, but sadly we cannot
473
+ // without a stack overflow problem. Just loop through outlets and collect
474
+ // items to awake.
475
+ this.bindings.invoke('relay') ;
476
+
477
+ if (this.outlets && this.outlets.length) {
478
+ var stack = [] ;
479
+ var working = [this, this.outlets.slice()] ;
480
+ while(working) {
481
+ // find the next item to work on.
482
+ var next = working[1].pop() ;
483
+ var obj = working[0] ;
484
+
485
+ // an item was found in the array. Process it.
486
+ if (next) {
487
+ next = obj[next] ;
488
+ if (next) {
489
+ // awake these bindings.
490
+ if (next.bindings) next.bindings.invoke('relay') ;
491
+
492
+ // next has outlets itself. Start a new context and process them.
493
+ if (next.outlets && next.outlets.length > 0) {
494
+ stack.push(working) ;
495
+ working = [next,next.outlets.slice()] ;
496
+ }
497
+ }
498
+
499
+ // no more items found in the current array. pop the stack.
500
+ } else working = stack.pop() ;
501
+ }
502
+ }
503
+
504
+ },
505
+
506
+ /**
507
+ name your outlets here or name the outlets "somethingOutlet". See
508
+ also outletFor in views.
509
+ */
510
+ outlets: [],
511
+
512
+ /**
513
+ This method works just like get() except if the value of the property
514
+ is an outlet-packaged View, the view will be created first. You can use
515
+ this to create lazy outlets. (DOC-INCOMPLETE)
516
+
517
+ @param {String} key The key to read as an outlet.
518
+ */
519
+ outlet: function(key) {
520
+ var value = this[key] ; // get the current value.
521
+
522
+ // if its an outlet, then configure it first.
523
+ if (value && (value instanceof Function) && value.isOutlet == true) {
524
+ if (!this._originalOutlets) this._originalOutlets = {} ;
525
+ this._originalOutlets[key] = value ;
526
+
527
+ value = value.call(this) ;
528
+ this.set(key, value) ;
529
+ } else if (typeof(value) == "string") {
530
+ if (!this._originalOutlets) this._originalOutlets = {} ;
531
+ this._originalOutlets[key] = value ;
532
+
533
+ value = (this.$$sel) ? this.$$sel(value) : $$sel(value) ;
534
+ if (value) value = (value.length > 0) ? ((value.length == 1) ? value[0] : value) : null ;
535
+ this.set(key, value) ;
536
+ }
537
+
538
+ return value ;
539
+ },
540
+
541
+ /**
542
+ DEPRECATED: Will be removed in SproutCore 1.0.
543
+ */
544
+ invokeLater: function(period) {
545
+ var args = $A(arguments) ; args.unshift(this) ;
546
+ return SC.runLoop.schedule.apply(SC.runLoop,args) ;
547
+ },
548
+
549
+ _cprops: ['_cprops','outlets','_bindings','_observers','_properties']
550
+
551
+ } ;
552
+
553
+ Object.extend(SC.Object.prototype, SC.Observable) ;
554
+
555
+
556
+ function logChange(target,key,value) {
557
+ console.log("CHANGE: " + target + "["+key+"]=" + value) ;
558
+ }
559
+
560
+ // ........................................................................
561
+ // FUNCTION ENHANCEMENTS
562
+ //
563
+ // Enhance function.
564
+ Object.extend(Function.prototype,{
565
+
566
+ // Declare a function as a property. This makes it something that can be
567
+ // accessed via get/set.
568
+ property: function() {
569
+ this.dependentKeys = $A(arguments) ;
570
+ this.isProperty = true; return this;
571
+ },
572
+
573
+ // Declare that a function should observe an object at the named path. Note
574
+ // that the path is used only to construct the observation one time.
575
+ observes: function(propertyPaths) {
576
+ this.propertyPaths = $A(arguments);
577
+ return this;
578
+ },
579
+
580
+ typeConverter: function() {
581
+ this.isTypeConverter = true; return this ;
582
+ }
583
+
584
+ }) ;
585
+
586
+ // ........................................................................
587
+ // OBSERVER QUEUE
588
+ //
589
+ // This queue is used to hold observers when the object you tried to observe
590
+ // does not exist yet. This queue is flushed just before any property
591
+ // notification is sent.
592
+ SC.Observers = {
593
+ queue: {},
594
+
595
+ addObserver: function(propertyPath, func) {
596
+ // try to get the tuple for this.
597
+ if (typeof(propertyPath) == "string") {
598
+ var tuple = SC.Object.tupleForPropertyPath(propertyPath) ;
599
+ } else {
600
+ var tuple = propertyPath;
601
+ }
602
+
603
+ if (tuple) {
604
+ tuple[0].addObserver(tuple[1],func) ;
605
+ } else {
606
+ var ary = this.queue[propertyPath] || [] ;
607
+ ary.push(func) ;
608
+ this.queue[propertyPath] = ary ;
609
+ }
610
+ },
611
+
612
+ removeObserver: function(propertyPath, func) {
613
+ var tuple = SC.Object.tupleForPropertyPath(propertyPath) ;
614
+ if (tuple) {
615
+ tuple[0].removeObserver(tuple[1],func) ;
616
+ }
617
+
618
+ var ary = this.queue[propertyPath] ;
619
+ if (ary) {
620
+ ary = ary.without(func) ;
621
+ this.queue[propertyPath] = ary ;
622
+ }
623
+ },
624
+
625
+ flush: function() {
626
+ var newQueue = {} ;
627
+ for(var path in this.queue) {
628
+ var funcs = this.queue[path] ;
629
+ var tuple = SC.Object.tupleForPropertyPath(path) ;
630
+ if (tuple) {
631
+ var loc = funcs.length ;
632
+ while(--loc >= 0) {
633
+ var func = funcs[loc] ;
634
+ tuple[0].addObserver(tuple[1],func) ;
635
+ }
636
+ } else newQueue[path] = funcs ;
637
+ }
638
+
639
+ // set queue to remaining items
640
+ this.queue = newQueue ;
641
+ }
642
+ } ;
643
+
644
+ // ........................................................................
645
+ // NOTIFCATION QUEUE
646
+ //
647
+ // Property notifications are placed into this queue first and then processed
648
+ // to keep the stack size down.
649
+ SC.NotificationQueue = {
650
+ queue: [],
651
+ maxFlush: 5000, // max time you can spend flushing before we reschedule.
652
+ _flushing: false,
653
+ add: function(target, func, args) { this.queue.push([target, func, args]);},
654
+ flush: function() {
655
+ if (this._flushing) return ;
656
+ this._flushing = true ;
657
+
658
+ var start = new Date().getTime() ;
659
+ var now = start ;
660
+ var n = null ;
661
+ while(((now - start) < this.maxFlush) && (n = this.queue.pop())) {
662
+ try {
663
+ var t = n[0] || n[1] ;
664
+ n[1].apply(t,n[2]) ;
665
+ }
666
+ catch(e) {
667
+ console.log("Exception while notify("+n[1]+"): " + e) ;
668
+ } // catch
669
+ now = Date.now() ;
670
+ }
671
+ this._flushing = false ;
672
+
673
+ if (this.queue.length > 0) {
674
+ setTimeout(this._reflush,1);
675
+ }
676
+ },
677
+
678
+ _reflush: function() { SC.NotificationQueue.flush(); }
679
+ } ;
680
+
681
+ // ........................................................................
682
+ // CHAIN OBSERVER
683
+ //
684
+
685
+ // ChainObservers are used to automatically monitor a property several
686
+ // layers deep.
687
+ // org.plan.name = SC._ChainObserver.create({
688
+ // target: this, property: 'org',
689
+ // next: SC._ChainObserver.create({
690
+ // property: 'plan',
691
+ // next: SC._ChainObserver.create({
692
+ // property: 'name', func: myFunc
693
+ // })
694
+ // })
695
+ // })
696
+ //
697
+ SC._ChainObserver = SC.Object.extend({
698
+
699
+ isChainObserver: true,
700
+
701
+ // the object this link in the chain is observing.
702
+ target: null,
703
+
704
+ // the property on the object this link is observing
705
+ property: null,
706
+
707
+ // if not null, the next link in the chain. The target property
708
+ // of this next link will be set to the value of this link.
709
+ next: null,
710
+
711
+ // if not null, the function to be called when the property value changes.
712
+ func: null,
713
+
714
+ propertyObserver: function(observing,target,key,value) {
715
+ if ((key == 'target') && (value != this._target)) {
716
+ var func = this.boundObserver() ;
717
+ if (this._target && this._target.removeObserver) {
718
+ this._target.removeObserver(this.property,func);
719
+ }
720
+ this._target = value ;
721
+ if (this._target && this._target.addObserver) {
722
+ this._target.addObserver(this.property,func) ;
723
+ }
724
+
725
+ // the target property has probably changed since the target has
726
+ // changed. notify myself of this.
727
+ if (!(observing == 'init')) this.targetPropertyObserver() ;
728
+ }
729
+ },
730
+
731
+ boundObserver: function() {
732
+ if (!this._boundObserver) {
733
+ this._boundObserver = this.targetPropertyObserver.bind(this) ;
734
+ }
735
+ return this._boundObserver ;
736
+ },
737
+
738
+ // invoked when the target property changes. act based
739
+ targetPropertyObserver: function() {
740
+
741
+ // get the new target property value. if the target or property is
742
+ // not valid, just use null.
743
+ var value = (this.target && this.target.get && this.property) ? this.target.get(this.property) : null ;
744
+
745
+ if (value !== this._lastTargetProperty) {
746
+ this._lastTargetProperty = value ;
747
+ // if we have another item in the chain, just forward the change.
748
+ if (this.next) {
749
+ this.next.set('target',value) ;
750
+
751
+ // otherwise, invoke the function.
752
+ } else if (this.func) this.func(this.target,this.property,value) ;
753
+ }
754
+
755
+ },
756
+
757
+ // hookup observer.
758
+ init: function() {
759
+ arguments.callee.base.call(this) ;
760
+ this.propertyObserver('init',this,'target',this.get('target')) ;
761
+ }
762
+
763
+ }) ;
764
+
765
+ // Class Methods.
766
+ SC._ChainObserver.mixin({
767
+ createChain: function(target,keys,func) {
768
+ var property = keys.shift() ;
769
+ var nextTarget = (target && property && target.get) ? target.get(property) : null ;
770
+ var next = (keys && keys.length>0) ? this.createChain(nextTarget,keys,func) : null ;
771
+
772
+ return this.create({
773
+ target: target, property: property,
774
+ next: next, func: ((next) ? null : func)
775
+ }) ;
776
+ }
777
+ }) ;