riojs 0.0.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/LICENSE +20 -0
  2. data/README.rdoc +24 -0
  3. data/VERSION +1 -0
  4. data/bin/rio +5 -0
  5. data/generators/rio_app/USAGE +19 -0
  6. data/generators/rio_app/rio_app_generator.rb +40 -0
  7. data/generators/rio_app/templates/app.build +10 -0
  8. data/generators/rio_app/templates/app.css +0 -0
  9. data/generators/rio_app/templates/app.js +20 -0
  10. data/generators/rio_app/templates/app_view.html.erb +19 -0
  11. data/generators/rio_app/templates/fixture.js +4 -0
  12. data/generators/rio_app/templates/rio.html.erb +18 -0
  13. data/generators/rio_app/templates/rio_controller.rb +2 -0
  14. data/generators/rio_app/templates/spec.js +7 -0
  15. data/generators/rio_component/USAGE +13 -0
  16. data/generators/rio_component/rio_component_generator.rb +16 -0
  17. data/generators/rio_component/templates/component.css +0 -0
  18. data/generators/rio_component/templates/component.js +11 -0
  19. data/generators/rio_component/templates/fixture.js +3 -0
  20. data/generators/rio_component/templates/spec.js +6 -0
  21. data/generators/rio_model/USAGE +12 -0
  22. data/generators/rio_model/rio_model_generator.rb +21 -0
  23. data/generators/rio_model/templates/fixture.js +3 -0
  24. data/generators/rio_model/templates/model.js +9 -0
  25. data/generators/rio_model/templates/spec.js +6 -0
  26. data/generators/rio_page/USAGE +14 -0
  27. data/generators/rio_page/rio_page_generator.rb +16 -0
  28. data/generators/rio_page/templates/fixture.js +3 -0
  29. data/generators/rio_page/templates/page.css +12 -0
  30. data/generators/rio_page/templates/page.js +12 -0
  31. data/generators/rio_page/templates/page.jst +64 -0
  32. data/generators/rio_page/templates/spec.js +6 -0
  33. data/generators/rio_resource/USAGE +20 -0
  34. data/generators/rio_resource/rio_resource_generator.rb +10 -0
  35. data/generators/rio_resource/templates/controller.rb +3 -0
  36. data/init.rb +4 -0
  37. data/install/config/juggernaut_hosts.yml +18 -0
  38. data/install/lib/tasks/rio.rake +1 -0
  39. data/install/script/rio_server +37 -0
  40. data/lib/rio/autospec.rb +86 -0
  41. data/lib/rio/install.rb +90 -0
  42. data/lib/rio/juggernaut.rb +212 -0
  43. data/lib/rio/path.rb +3 -0
  44. data/lib/rio/rio_compressor.rb +219 -0
  45. data/lib/rio/rio_file_controller.rb +16 -0
  46. data/lib/rio/rio_on_rails.rb +586 -0
  47. data/lib/rio/rio_proxy_controller.rb +60 -0
  48. data/lib/rio/rio_push_controller.rb +48 -0
  49. data/lib/rio/rio_routes.rb +24 -0
  50. data/lib/rio/rio_spec_controller.rb +70 -0
  51. data/lib/riojs.rb +14 -0
  52. data/lib/tasks/rio.rb +63 -0
  53. data/public/images/background-chiffon.png +0 -0
  54. data/public/images/button-gradient-overlay-down.png +0 -0
  55. data/public/images/button-gradient-overlay.png +0 -0
  56. data/public/images/icons/add.png +0 -0
  57. data/public/images/icons/error-big.png +0 -0
  58. data/public/images/icons/warning-big.png +0 -0
  59. data/public/images/rio-logo-big.png +0 -0
  60. data/public/images/rio-logo.png +0 -0
  61. data/public/images/splitter-handle-horizontal.png +0 -0
  62. data/public/images/splitter-handle-vertical.png +0 -0
  63. data/public/images/tab-bar-gradient-overlay.png +0 -0
  64. data/public/images/title-gradient-overlay.png +0 -0
  65. data/public/images/trash.gif +0 -0
  66. data/public/javascripts/components/accordion.js +144 -0
  67. data/public/javascripts/components/alert_box.js +59 -0
  68. data/public/javascripts/components/base.js +47 -0
  69. data/public/javascripts/components/box.js +63 -0
  70. data/public/javascripts/components/button.js +98 -0
  71. data/public/javascripts/components/checkbox.js +44 -0
  72. data/public/javascripts/components/container.js +265 -0
  73. data/public/javascripts/components/grid_view.js +107 -0
  74. data/public/javascripts/components/image.js +19 -0
  75. data/public/javascripts/components/input.js +171 -0
  76. data/public/javascripts/components/label.js +15 -0
  77. data/public/javascripts/components/lightbox.js +160 -0
  78. data/public/javascripts/components/link.js +43 -0
  79. data/public/javascripts/components/list_item.js +44 -0
  80. data/public/javascripts/components/list_view.js +192 -0
  81. data/public/javascripts/components/marquee.js +131 -0
  82. data/public/javascripts/components/menu.js +89 -0
  83. data/public/javascripts/components/notification.js +75 -0
  84. data/public/javascripts/components/overlay.js +134 -0
  85. data/public/javascripts/components/panel.js +146 -0
  86. data/public/javascripts/components/radio.js +46 -0
  87. data/public/javascripts/components/splitter.js +65 -0
  88. data/public/javascripts/components/tab_bar.js +64 -0
  89. data/public/javascripts/components/tab_panel.js +57 -0
  90. data/public/javascripts/components/textarea.js +223 -0
  91. data/public/javascripts/components/toggle_button.js +22 -0
  92. data/public/javascripts/components/tooltip.js +80 -0
  93. data/public/javascripts/lib/application.js +482 -0
  94. data/public/javascripts/lib/attr.js +760 -0
  95. data/public/javascripts/lib/benchmark.js +235 -0
  96. data/public/javascripts/lib/blank.html +39 -0
  97. data/public/javascripts/lib/boot.js +300 -0
  98. data/public/javascripts/lib/clipboard.js +96 -0
  99. data/public/javascripts/lib/collection_entity.js +46 -0
  100. data/public/javascripts/lib/component.js +129 -0
  101. data/public/javascripts/lib/console.js +75 -0
  102. data/public/javascripts/lib/console/apps/console.build +43 -0
  103. data/public/javascripts/lib/console/apps/console.js +28 -0
  104. data/public/javascripts/lib/console/blank.html +39 -0
  105. data/public/javascripts/lib/console/components/benchmark.js +196 -0
  106. data/public/javascripts/lib/console/components/console.js +352 -0
  107. data/public/javascripts/lib/console/components/dependencies_list.js +17 -0
  108. data/public/javascripts/lib/console/components/docs.js +66 -0
  109. data/public/javascripts/lib/console/components/playground.js +30 -0
  110. data/public/javascripts/lib/console/console.html +27 -0
  111. data/public/javascripts/lib/console/console_commands.js +287 -0
  112. data/public/javascripts/lib/console/console_commands.js.rej +21 -0
  113. data/public/javascripts/lib/console/console_mixin.js +22 -0
  114. data/public/javascripts/lib/console/docs/files.html +579 -0
  115. data/public/javascripts/lib/console/docs/index.html +323 -0
  116. data/public/javascripts/lib/console/docs/symbols/Object.html +291 -0
  117. data/public/javascripts/lib/console/docs/symbols/_global_.html +413 -0
  118. data/public/javascripts/lib/console/docs/symbols/rio.AIM.html +490 -0
  119. data/public/javascripts/lib/console/docs/symbols/rio.Application.html +841 -0
  120. data/public/javascripts/lib/console/docs/symbols/rio.Attr.html +1075 -0
  121. data/public/javascripts/lib/console/docs/symbols/rio.Binding.html +272 -0
  122. data/public/javascripts/lib/console/docs/symbols/rio.Component.html +419 -0
  123. data/public/javascripts/lib/console/docs/symbols/rio.Cookie.html +543 -0
  124. data/public/javascripts/lib/console/docs/symbols/rio.DelayedTask#initialize.html +270 -0
  125. data/public/javascripts/lib/console/docs/symbols/rio.DelayedTask.html +391 -0
  126. data/public/javascripts/lib/console/docs/symbols/rio.JsTemplate.html +271 -0
  127. data/public/javascripts/lib/console/docs/symbols/rio.Juggernaut.html +329 -0
  128. data/public/javascripts/lib/console/docs/symbols/rio.Model.html +822 -0
  129. data/public/javascripts/lib/console/docs/symbols/rio.Page.html +383 -0
  130. data/public/javascripts/lib/console/docs/symbols/rio.Template.html +328 -0
  131. data/public/javascripts/lib/console/docs/symbols/rio.Utils.html +617 -0
  132. data/public/javascripts/lib/console/docs/symbols/rio.html +506 -0
  133. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_components_base.js.html +54 -0
  134. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_application.js.html +490 -0
  135. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_attr.js.html +768 -0
  136. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_boot.js.html +308 -0
  137. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_clipboard.js.html +103 -0
  138. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_collection_entity.js.html +53 -0
  139. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_component.js.html +137 -0
  140. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_cookie.js.html +81 -0
  141. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_delayed_task.js.html +68 -0
  142. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_file.js.html +80 -0
  143. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_flash_detect.js.html +129 -0
  144. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_form.js.html +95 -0
  145. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_id.js.html +50 -0
  146. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_inflector.js.html +167 -0
  147. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_js_template.js.html +283 -0
  148. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_juggernaut.js.html +303 -0
  149. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_key_map.js.html +68 -0
  150. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_layout_manager.js.html +175 -0
  151. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_log.js.html +17 -0
  152. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_model.js.html +1074 -0
  153. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_page.js.html +246 -0
  154. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_parameters.js.html +66 -0
  155. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_protohack.js.html +305 -0
  156. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_push.js.html +12 -0
  157. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_rsh.js.html +659 -0
  158. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_swfobject.js.html +12 -0
  159. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_tag.js.html +60 -0
  160. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_template.js.html +64 -0
  161. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_theme.js.html +105 -0
  162. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_undo.js.html +142 -0
  163. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_utils.js.html +87 -0
  164. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_yaml.js.html +88 -0
  165. data/public/javascripts/lib/console/file-small.png +0 -0
  166. data/public/javascripts/lib/console/green-circle.png +0 -0
  167. data/public/javascripts/lib/console/loading.gif +0 -0
  168. data/public/javascripts/lib/console/pages/console_page.js +149 -0
  169. data/public/javascripts/lib/console/pages/console_page.jst +27 -0
  170. data/public/javascripts/lib/console/red-circle.png +0 -0
  171. data/public/javascripts/lib/cookie.js +74 -0
  172. data/public/javascripts/lib/delayed_task.js +61 -0
  173. data/public/javascripts/lib/dependencies.js +76 -0
  174. data/public/javascripts/lib/environment.js +30 -0
  175. data/public/javascripts/lib/event.simulate.js +137 -0
  176. data/public/javascripts/lib/expressinstall.swf +0 -0
  177. data/public/javascripts/lib/file.js +72 -0
  178. data/public/javascripts/lib/flash_detect.js +122 -0
  179. data/public/javascripts/lib/flashembed.min.js +16 -0
  180. data/public/javascripts/lib/form.js +88 -0
  181. data/public/javascripts/lib/id.js +43 -0
  182. data/public/javascripts/lib/inflector.js +160 -0
  183. data/public/javascripts/lib/instrumenter.js +106 -0
  184. data/public/javascripts/lib/js_template.js +275 -0
  185. data/public/javascripts/lib/jslint.js +4950 -0
  186. data/public/javascripts/lib/juggernaut.js +295 -0
  187. data/public/javascripts/lib/juggernaut.swf +0 -0
  188. data/public/javascripts/lib/key_map.js +60 -0
  189. data/public/javascripts/lib/layout_manager.js +167 -0
  190. data/public/javascripts/lib/model.js +1067 -0
  191. data/public/javascripts/lib/page.js +238 -0
  192. data/public/javascripts/lib/parameters.js +59 -0
  193. data/public/javascripts/lib/png_fix.js +75 -0
  194. data/public/javascripts/lib/protohack.js +297 -0
  195. data/public/javascripts/lib/push.js +5 -0
  196. data/public/javascripts/lib/rio.build +28 -0
  197. data/public/javascripts/lib/rio_development.build +5 -0
  198. data/public/javascripts/lib/rio_lint.js +66 -0
  199. data/public/javascripts/lib/rsh.js +651 -0
  200. data/public/javascripts/lib/spec.js +545 -0
  201. data/public/javascripts/lib/spec_runner.js +242 -0
  202. data/public/javascripts/lib/swfobject.js +5 -0
  203. data/public/javascripts/lib/tag.js +52 -0
  204. data/public/javascripts/lib/undo.js +134 -0
  205. data/public/javascripts/lib/utils.js +80 -0
  206. data/public/javascripts/lib/yaml.js +80 -0
  207. data/public/javascripts/pages/playground_page.js +15 -0
  208. data/public/javascripts/prototype/builder.js +146 -0
  209. data/public/javascripts/prototype/controls.js +1004 -0
  210. data/public/javascripts/prototype/dragdrop.js +1030 -0
  211. data/public/javascripts/prototype/effects.js +1137 -0
  212. data/public/javascripts/prototype/prototype.js +4320 -0
  213. data/public/javascripts/prototype/slider.js +283 -0
  214. data/public/javascripts/prototype/sound.js +67 -0
  215. data/public/javascripts/specs/components/box_spec.js +6 -0
  216. data/public/javascripts/specs/components/checkbox_spec.js +26 -0
  217. data/public/javascripts/specs/components/container_spec.js +6 -0
  218. data/public/javascripts/specs/components/input_spec.js +71 -0
  219. data/public/javascripts/specs/components/panel_spec.js +6 -0
  220. data/public/javascripts/specs/components/radio_spec.js +40 -0
  221. data/public/javascripts/specs/fixtures/components/box.js +3 -0
  222. data/public/javascripts/specs/fixtures/components/checkbox.js +9 -0
  223. data/public/javascripts/specs/fixtures/components/container.js +3 -0
  224. data/public/javascripts/specs/fixtures/components/input.js +12 -0
  225. data/public/javascripts/specs/fixtures/components/menu.js +19 -0
  226. data/public/javascripts/specs/fixtures/components/menu_item.js +18 -0
  227. data/public/javascripts/specs/fixtures/components/radio.js +11 -0
  228. data/public/javascripts/specs/lib/application_spec.js +281 -0
  229. data/public/javascripts/specs/lib/attr_spec.js +1514 -0
  230. data/public/javascripts/specs/lib/benchmark_spec.js +361 -0
  231. data/public/javascripts/specs/lib/collection_entity_spec.js +131 -0
  232. data/public/javascripts/specs/lib/component_spec.js +86 -0
  233. data/public/javascripts/specs/lib/form_spec.js +171 -0
  234. data/public/javascripts/specs/lib/id_spec.js +21 -0
  235. data/public/javascripts/specs/lib/instrumenter_spec.js +5 -0
  236. data/public/javascripts/specs/lib/js_template_spec.js +131 -0
  237. data/public/javascripts/specs/lib/key_map_spec.js +227 -0
  238. data/public/javascripts/specs/lib/model_spec.js +2268 -0
  239. data/public/javascripts/specs/lib/parameters_spec.js +94 -0
  240. data/public/javascripts/specs/lib/spec_spec.js +943 -0
  241. data/public/javascripts/specs/lib/undo_spec.js +105 -0
  242. data/public/javascripts/specs/lib/yaml_spec.js +127 -0
  243. data/public/sounds/basso.wav +0 -0
  244. data/public/sounds/purr.wav +0 -0
  245. data/public/stylesheets/components/accordion.css +24 -0
  246. data/public/stylesheets/components/alert_box.css +35 -0
  247. data/public/stylesheets/components/box.css +0 -0
  248. data/public/stylesheets/components/button.css +39 -0
  249. data/public/stylesheets/components/checkbox.css +9 -0
  250. data/public/stylesheets/components/container.css +3 -0
  251. data/public/stylesheets/components/grid_view.css +52 -0
  252. data/public/stylesheets/components/input.css +10 -0
  253. data/public/stylesheets/components/label.css +3 -0
  254. data/public/stylesheets/components/lightbox.css +31 -0
  255. data/public/stylesheets/components/link.css +4 -0
  256. data/public/stylesheets/components/list_view.css +23 -0
  257. data/public/stylesheets/components/marquee.css +29 -0
  258. data/public/stylesheets/components/menu.css +34 -0
  259. data/public/stylesheets/components/notification.css +52 -0
  260. data/public/stylesheets/components/overlay.css +8 -0
  261. data/public/stylesheets/components/panel.css +36 -0
  262. data/public/stylesheets/components/radio.css +9 -0
  263. data/public/stylesheets/components/splitter.css +35 -0
  264. data/public/stylesheets/components/tab_bar.css +59 -0
  265. data/public/stylesheets/components/tab_panel.css +15 -0
  266. data/public/stylesheets/components/textarea.css +11 -0
  267. data/public/stylesheets/components/tooltip.css +10 -0
  268. data/public/stylesheets/console.css +151 -0
  269. data/public/stylesheets/css_reset.css +55 -0
  270. metadata +343 -0
@@ -0,0 +1,760 @@
1
+ /**
2
+ @class
3
+
4
+ Attr is the basis for most of rio. It is the class from which all apps, pages, models, and components
5
+ are derived, though you will rarely have to use Attr directly. Attr provides all of the functionality
6
+ related to attributes, bindings, dependency management, and events.
7
+
8
+ @author Jason Tillery
9
+ @copyright 2008-2009 Thinklink LLC
10
+ */
11
+ rio.Attr = {
12
+ /**
13
+ Creates an instance of rio.Attr.
14
+
15
+ @param {String} name (optional) The name of this Attr. Used primarily for testing reports.
16
+ @param {Object} extends (optional) An Attr class to use as a superclass.
17
+ @param {Object} args (optional) The definition of the class.
18
+ @returns a new instance of type Attr
19
+ @type rio.Attr
20
+ @example
21
+ var attr = rio.Attr.create("AttrName", {
22
+ attrAccessors: [], // list of accessors
23
+ attrReaders: [], // list of readers
24
+ methods: {
25
+ initialize: function() {
26
+
27
+ }
28
+ },
29
+ classMethods: {
30
+
31
+ }
32
+ });
33
+ */
34
+ create: function() {
35
+ var args = $A(arguments);
36
+ var attr = (args.length > 0 && args[0] != undefined && args[0].ATTR) ? Class.create(args[0]) : Class.create();
37
+
38
+ if (args.length > 0 && args.first() != undefined && Object.isString(args.first())) {
39
+ attr.NAME = args.first();
40
+ } else if (attr.superclass && args.length > 1 && args[1] != undefined && Object.isString(args[1])) {
41
+ attr.NAME = args[1];
42
+ } else {
43
+ attr.NAME = "[attr rio.Attr]";
44
+ }
45
+
46
+ attr.addMethods(
47
+ /**
48
+ @scope rio.Attr.prototype
49
+ */
50
+ {
51
+ /** @private */
52
+ ATTR: true,
53
+
54
+ /** @private */
55
+ __bindings: function() {
56
+ if (!this.___bindings) { this.___bindings = {}; }
57
+ return this.___bindings;
58
+ },
59
+
60
+ /** @private */
61
+ __bindingsFor: function(fieldName) {
62
+ return this.__bindings()[fieldName] || [];
63
+ },
64
+
65
+ /** @private */
66
+ __subBindings: function() {
67
+ if (!this.___subBindings) { this.___subBindings = {}; }
68
+ return this.___subBindings;
69
+ },
70
+
71
+ /** @private */
72
+ __subBindingsFor: function(fieldName) {
73
+ return this.__subBindings()[fieldName] || [];
74
+ },
75
+
76
+ /** @private */
77
+ __executeSubBinding: function(attribute, subAttribute, binding, skipInitialExecution, oldValue) {
78
+ var subObj = this[("get-" + attribute).camelize()]();
79
+ if (subObj instanceof Object && subObj.ATTR) {
80
+ if (oldValue instanceof Object && oldValue.ATTR) {
81
+ oldValue.unbind(subAttribute, binding);
82
+ }
83
+ var subOldValue = oldValue && oldValue[("get-" + subAttribute).camelize()] && oldValue[("get-" + subAttribute).camelize()]();
84
+ subObj.bind(subAttribute, binding, skipInitialExecution, subOldValue);
85
+ }
86
+ },
87
+
88
+ /** @private */
89
+ __executeAllBindings: function(fieldName, newValue, oldValue) {
90
+ var i;
91
+ var bindingsFor = this.__bindingsFor(fieldName);
92
+ var bindingsForLength = bindingsFor.length;
93
+ for (i=0; i<bindingsForLength; i++) {
94
+ this.fireBinding(bindingsFor[i], newValue, oldValue);
95
+ }
96
+
97
+ var subBindingsFor = this.__subBindingsFor(fieldName);
98
+ var subBindingsForLength = subBindingsFor.length;
99
+ for (i=0; i<subBindingsForLength; i++) {
100
+ var subBinding = subBindingsFor[i];
101
+ this.__executeSubBinding(fieldName, subBinding[0], subBinding[1], false, oldValue);
102
+ }
103
+ },
104
+
105
+ /** @private */
106
+ fireBinding: function(binding, value, oldValue) {
107
+ rio.Attr.fireWhenReady(this.doFireBinding.bind(this, binding, value, oldValue));
108
+ },
109
+
110
+ /** @private */
111
+ doFireBinding: function(binding, value, oldValue) {
112
+ if (Object.isFunction(binding)) {
113
+ // try {
114
+ binding(value, oldValue);
115
+ // } catch(e) {
116
+ // TODO: This check is in here because refreshing the console can leave null binding references in the app
117
+ // This needs to be resolved immediately. We should be "un-binding" instead of ignoring this error.
118
+ // rio.log(e);
119
+ //}
120
+ } else {
121
+ if (Object.isArray(value)) {
122
+ var i;
123
+
124
+ if (!binding.__unbindings) {
125
+ binding.__unbindings = [];
126
+ } else {
127
+ var unbindings = binding.__unbindings;
128
+ for (i=unbindings.length; i--;) {
129
+ var unbinding = unbindings[i];
130
+ if (unbinding.forAttr == this) {
131
+ unbinding();
132
+ }
133
+ }
134
+ }
135
+
136
+
137
+ if (rio.environment.giveWarnings) {
138
+ var unsupportedListBindingOperations = ["reverse", "shift", "sort", "unshift"];
139
+ var oldUnsupportedFunctions = {};
140
+
141
+ var buildWrapper = function(operation) {
142
+ return function() {
143
+ rio.log("warning: " + operation + " does not fire rio bindings", "warningLogItem", "- ");
144
+ var args = $A(arguments);
145
+ var proceed = args.shift();
146
+ return proceed.apply(this, args);
147
+ };
148
+ };
149
+ for (i=unsupportedListBindingOperations.length; i--;) {
150
+ var operation = unsupportedListBindingOperations[i];
151
+ oldUnsupportedFunctions[operation] = value[operation];
152
+ value[operation] = value[operation].wrap(buildWrapper(operation));
153
+ }
154
+ }
155
+
156
+ var oldPush = value.push;
157
+ value.push = value.push.wrap(function(proceed, val) {
158
+ var ret = proceed(val);
159
+ if (binding.insert) {
160
+ rio.Attr.fireWhenReady(binding.insert.curry(val, value.length - 1));
161
+ }
162
+ if (binding.empty && value.length == 1) {
163
+ rio.Attr.fireWhenReady(binding.empty.curry(false));
164
+ }
165
+ return ret;
166
+ });
167
+
168
+ var oldPop = value.pop;
169
+ value.pop = value.pop.wrap(function(proceed, val) {
170
+ if (value.length == 0) { return; }
171
+ var startsEmpty = value.length == 0;
172
+ var ret = proceed(val);
173
+ if (binding.remove) {
174
+ rio.Attr.fireWhenReady(binding.remove.curry(ret));
175
+ }
176
+ if (binding.empty) {
177
+ var endsEmpty = value.length == 0;
178
+ if (startsEmpty != endsEmpty) {
179
+ rio.Attr.fireWhenReady(binding.empty.curry(endsEmpty));
180
+ }
181
+ }
182
+ return ret;
183
+ });
184
+
185
+ var oldSplice = value.splice;
186
+ value.splice = value.splice.wrap(function(proceed, index, count, toInsert) {
187
+ var startsEmpty = value.length == 0;
188
+
189
+ var removing = count > 0 && binding.remove;
190
+ var inserting = (toInsert !== undefined) && binding.insert;
191
+ if (removing) { var toRemove = value[index]; }
192
+
193
+ var ret = (toInsert !== undefined) ? proceed(index, count, toInsert) : proceed(index, count);
194
+
195
+ if (removing) {
196
+ rio.Attr.fireWhenReady(binding.remove.curry(toRemove));
197
+ }
198
+ if (inserting) {
199
+ rio.Attr.fireWhenReady(binding.insert.curry(toInsert, index));
200
+ }
201
+
202
+ var endsEmpty = value.length == 0;
203
+ if (binding.empty && (startsEmpty != endsEmpty)) {
204
+ rio.Attr.fireWhenReady(binding.empty.curry(endsEmpty));
205
+ }
206
+ return ret;
207
+ });
208
+
209
+ var oldClear = value.clear;
210
+ value.clear = value.clear.wrap(function(proceed) {
211
+ if (value.length == 0) { return; }
212
+ proceed();
213
+ if (binding.set) {
214
+ rio.Attr.fireWhenReady(binding.set.curry(value));
215
+ }
216
+ if (binding.empty) {
217
+ rio.Attr.fireWhenReady(binding.empty.curry(true));
218
+ }
219
+ });
220
+
221
+ var unbindingFunction = function() {
222
+ value.push = oldPush;
223
+ value.pop = oldPop;
224
+ value.splice = oldSplice;
225
+ value.clear = oldClear;
226
+ if (rio.environment.giveWarnings) {
227
+ unsupportedListBindingOperations.each(function(operation) {
228
+ value[operation] = oldUnsupportedFunctions[operation];
229
+ });
230
+ }
231
+ };
232
+ unbindingFunction.forAttr = this;
233
+ binding.__unbindings.push(unbindingFunction);
234
+
235
+ if (binding.empty) { binding.empty(value.length == 0); }
236
+ }
237
+ if (binding.set) {
238
+ binding.set(value);
239
+ }
240
+ }
241
+ },
242
+
243
+ /**
244
+ Binds a function to an attribute.
245
+ <br /><br />
246
+ <i>NOTE: The function will be called immediately with the current value of the attribute.</i>
247
+
248
+ @param {String} attribute The name of the attribute to bind
249
+ @param {Function} binding The function to execute when the value of the attribute changes
250
+ @param {Boolean} skipInitialExecution (optional) Do <b>not</b> immediately call the function with the attributes current value
251
+
252
+ @example
253
+ attr.bind("attribute", function(newValue) {
254
+ alert(newValue);
255
+ });
256
+ */
257
+ bind: function(attribute, binding, skipInitialExecution, overrideInitialOldValue) {
258
+ var unbind;
259
+ if (attribute.include(".")) {
260
+ var thisAttribute = attribute.match(/^([^\.]*)\.(.*)/)[1];
261
+ var subAttributes = attribute.match(/^([^\.]*)\.(.*)/)[2];
262
+ if (!this.__subBindings()[thisAttribute]) { this.__subBindings()[thisAttribute] = []; }
263
+ this.__subBindings()[thisAttribute].push([subAttributes, binding]);
264
+ this.__executeSubBinding(thisAttribute, subAttributes, binding, skipInitialExecution);
265
+ } else {
266
+ if (!this.__bindings()[attribute]) { this.__bindings()[attribute] = []; }
267
+ this.__bindings()[attribute].push(binding);
268
+ unbind = this.unbind.curry(attribute, binding).bind(this);
269
+ if (!skipInitialExecution) {
270
+ var value = this[("get-" + attribute).camelize()]();
271
+ this.fireBinding(binding, value, overrideInitialOldValue || value);
272
+ }
273
+ }
274
+ return unbind;
275
+ },
276
+
277
+ /**
278
+ Returns a binding to the specified attribute or attribute path
279
+ <br /><br />
280
+ <i>NOTE: The most common reason for using binding is to specify the initial value of another attrAccessor with an attribute path.</i>
281
+
282
+ @param {String} attribute The name of the attribute to bind
283
+
284
+ @example
285
+ attr.binding("attribute");
286
+ */
287
+ binding: function(attribute) {
288
+ return new rio.Binding(this, attribute);
289
+ },
290
+
291
+ /** @private */
292
+ unbind: function(fieldName, binding) {
293
+ if (fieldName.include(".")) {
294
+ var thisField = fieldName.match(/^([^\.]*)\.(.*)/)[1];
295
+ var subFields = fieldName.match(/^([^\.]*)\.(.*)/)[2];
296
+
297
+ var subBindings = this.__subBindings()[thisField] || [];
298
+ var subIndex = subBindings.indexOf(binding);
299
+ if (subIndex >= 0) {
300
+ subBindings.splice(subIndex, 1);
301
+ }
302
+ var subObj = this[("get-" + thisField).camelize()]();
303
+ if (subObj) {
304
+ subObj.unbind(subFields, binding);
305
+ }
306
+ } else {
307
+ var bindings = this.__bindingsFor(fieldName);
308
+ if (bindings) {
309
+ var index = bindings.indexOf(binding);
310
+ if (index >= 0) {
311
+ bindings.splice(index, 1);
312
+ (binding.__unbindings || []).each(function(unbinding) {
313
+ if (unbinding.forAttr == this) {
314
+ unbinding();
315
+ }
316
+ }.bind(this));
317
+ }
318
+ }
319
+ }
320
+ },
321
+
322
+ freeze: function() {
323
+ this._frozen = true;
324
+ },
325
+
326
+ unfreeze: function() {
327
+ this._frozen = false;
328
+ },
329
+
330
+ frozen: function() {
331
+ return this._frozen;
332
+ },
333
+
334
+ updateAttributes: function(attributes, options) {
335
+ Object.keys(attributes).map(function(attribute) {
336
+ return this.setAndReturnAfterSet(attribute, attributes[attribute], options);
337
+ }.bind(this)).each(function(f) {
338
+ f();
339
+ });
340
+ },
341
+
342
+ /** @private */
343
+ __eventHandlers: function() {
344
+ if (!this.___eventHandlers) { this.___eventHandlers = {}; }
345
+ return this.___eventHandlers;
346
+ },
347
+
348
+ /** @private */
349
+ __eventHandlersFor: function(eventName) {
350
+ return this.__eventHandlers()[eventName] || [];
351
+ },
352
+
353
+ /**
354
+ Fires an event.
355
+
356
+ @param {String} eventName The name of the event to fire
357
+ */
358
+ fire: function() {
359
+ var args = $A(arguments);
360
+ var eventName = args.shift();
361
+ var handlers = this.__eventHandlersFor(eventName);
362
+ for (var i=0, len=handlers.length; i<len; i++) {
363
+ handlers[i].apply(this, args);
364
+ }
365
+ },
366
+
367
+ /**
368
+ Observes an event.
369
+
370
+ @param {String} eventName The name of the event to observe
371
+ @param {Function} handler A function to call when the even is fired
372
+ */
373
+ observe: function(eventName, handler) {
374
+ if (!this.__eventHandlers()[eventName]) { this.__eventHandlers()[eventName] = []; }
375
+ this.__eventHandlers()[eventName].push(handler);
376
+ return this.stopObserving.bind(this, eventName, handler);
377
+ },
378
+
379
+ stopObserving: function(eventName, handler) {
380
+ var handlers = this.__eventHandlers()[eventName];
381
+ if (handlers && handlers.include(handler)) {
382
+ handlers.splice(handlers.indexOf(handler), 1);
383
+ }
384
+ },
385
+
386
+ /* @private */
387
+ setAndReturnAfterSet: function(fieldName, newValue, options) {
388
+ var oldValue = this["_" + fieldName];
389
+ this["_" + fieldName] = newValue;
390
+ return function() {
391
+ if (oldValue != newValue) {
392
+ this.__executeAllBindings(fieldName, newValue, oldValue);
393
+
394
+ // TODO: move this crap into model.js
395
+ if (this.afterUpdateField && !(options && options.skipSave)) {
396
+ this.afterUpdateField(fieldName, oldValue, newValue);
397
+ }
398
+ if (this.save && !(options && options.skipSave) && !(attr._clientOnlyAttrs && attr._clientOnlyAttrs.include(fieldName))) {
399
+ this.save.bind(this)();
400
+ }
401
+ }
402
+ }.bind(this);
403
+ }
404
+ });
405
+
406
+ var defaultFields = {};
407
+ var defaultHtmls = [];
408
+ var defaultEvents = [];
409
+
410
+ if (attr.superclass) {
411
+ defaultFields = Object.clone(attr.superclass._fields);
412
+ defaultHtmls = attr.superclass._htmls.clone();
413
+ defaultEvents = attr.superclass._events.clone();
414
+ }
415
+
416
+ Object.extend(attr, {
417
+ ATTR: true,
418
+ _fields: defaultFields,
419
+ _htmls: defaultHtmls,
420
+ _events: defaultEvents,
421
+
422
+ attrAccessor: function(fieldName, defaultValue) {
423
+ this.attrReader(fieldName, defaultValue);
424
+ var methods = {};
425
+ methods[("set-" + fieldName).camelize()] = function(newValue, options) {
426
+ if (this.frozen()) { return; }
427
+ this.setAndReturnAfterSet(fieldName, newValue, options)();
428
+ };
429
+ this.addMethods(methods);
430
+ },
431
+
432
+ attrReader: function(fieldName, defaultValue) {
433
+ if (Object.keys(this._fields).include(fieldName)) {
434
+ this._fields[fieldName] = defaultValue;
435
+ return;
436
+ }
437
+ var methods = {};
438
+ var getFunction = function() {
439
+ return this["_" + fieldName];
440
+ };
441
+ methods[("get-" + fieldName).camelize()] = getFunction;
442
+ methods[("is-" + fieldName).camelize()] = getFunction;
443
+
444
+ this.addMethods(methods);
445
+ this._fields[fieldName] = defaultValue;
446
+ },
447
+
448
+ attrHtml: function() {
449
+ var methods = {};
450
+ $A(arguments).each(function(name) {
451
+ var fieldName = "_" + name + "Html";
452
+ var methodName = name + "Html";
453
+ var buildMethodName = ("build-" + name + "Html").camelize();
454
+
455
+ methods[methodName] = function() {
456
+ if (!this[fieldName]) { this[fieldName] = this[buildMethodName](); }
457
+ return this[fieldName];
458
+ };
459
+ this._htmls.push(fieldName);
460
+ }.bind(this));
461
+ this.addMethods(methods);
462
+ },
463
+
464
+ attrEvent: function(eventName) {
465
+ this._events.push(eventName);
466
+ },
467
+
468
+ require: function() {
469
+ $A(arguments).each(function(fileName) {
470
+ rio.Application.include(fileName);
471
+ });
472
+ },
473
+
474
+ _examples: {},
475
+
476
+ setExamples: function(exampleJson) {
477
+ Object.keys(exampleJson).each(function(name) {
478
+ this._examples[name] = exampleJson[name];
479
+ }.bind(this));
480
+ },
481
+
482
+ examples: function() {
483
+ var exampleGroup = {};
484
+
485
+ Object.keys(this._examples).each(function(name) {
486
+ exampleGroup[name] = this.example(name);
487
+ }.bind(this));
488
+
489
+ return exampleGroup;
490
+ },
491
+
492
+ exampleParams: function(name) {
493
+ var exampleJson = this._examples[name];
494
+
495
+ var evalExamples = function(json) {
496
+ if (json == undefined) {
497
+ return;
498
+ } else if (json._EXAMPLE) {
499
+ return json.attr.example(json.name);
500
+ } else if (Object.isArray(json) || json.size) {
501
+ return json.map(function(value) {
502
+ return evalExamples(value);
503
+ });
504
+ } else if (typeof json == "object") {
505
+ var newObj = {};
506
+ Object.keys(json).each(function(key) {
507
+ newObj[key] = evalExamples(json[key]);
508
+ });
509
+ return newObj;
510
+ } else {
511
+ return json;
512
+ }
513
+ };
514
+
515
+ var params = evalExamples(exampleJson) || {};
516
+ params.__example = true;
517
+ return params;
518
+ },
519
+
520
+ example: function(name) {
521
+ rio.loadingFixtures = true;
522
+ try {
523
+ var params = this.exampleParams(name);
524
+ var exampleAttr = new attr(params);
525
+ exampleAttr.__example = true;
526
+ return exampleAttr;
527
+ } finally {
528
+ rio.loadingFixtures = false;
529
+ }
530
+ }
531
+ });
532
+ attr.toString = function() {
533
+ return this.NAME;
534
+ };
535
+
536
+
537
+ if (args.length > 0 && args.last() != undefined && !args.last().ATTR) {
538
+ var initializers = args.last();
539
+
540
+ (initializers.attrReaders || []).each(function(attribute) {
541
+ if (Object.isString(attribute)) {
542
+ attr.attrReader(attribute);
543
+ } else {
544
+ attr.attrReader(attribute[0], attribute[1]);
545
+ }
546
+ });
547
+
548
+ (initializers.attrAccessors || []).each(function(attribute) {
549
+ if (Object.isString(attribute)) {
550
+ attr.attrAccessor(attribute);
551
+ } else {
552
+ attr.attrAccessor(attribute[0], attribute[1]);
553
+ }
554
+ });
555
+
556
+ (initializers.attrHtmls || []).each(function(attribute) {
557
+ attr.attrHtml(attribute);
558
+ });
559
+
560
+ (initializers.attrEvents || []).each(function(eventName) {
561
+ attr.attrEvent(eventName);
562
+ });
563
+
564
+ if (initializers.require) {
565
+ attr.require.apply(attr, initializers.require);
566
+ }
567
+
568
+ if (!initializers.noExtend) {
569
+ rio.Attr.extend(attr, initializers.methods || {});
570
+ }
571
+ Object.extend(attr, initializers.classMethods || {});
572
+ }
573
+
574
+ return attr;
575
+ },
576
+
577
+ _transactionCount: 0,
578
+ _toFire: [],
579
+ transaction: function(t) {
580
+ this._transactionCount++;
581
+ try {
582
+ t();
583
+ } finally {
584
+ this._transactionCount--;
585
+ }
586
+ if (this._transactionCount == 0) {
587
+ this._toFire.each(function(tf) { tf(); });
588
+ this._toFire.clear();
589
+ }
590
+ },
591
+
592
+ fireWhenReady: function(f) {
593
+ if (this._transactionCount != 0) {
594
+ this._toFire.push(f);
595
+ } else {
596
+ f();
597
+ }
598
+ },
599
+
600
+ updateAttributes: function(updates) {
601
+ updates.map(function(update) {
602
+ var attributes = update.attributes;
603
+ var object = update.object;
604
+ return Object.keys(attributes).map(function(attribute) {
605
+ return object.setAndReturnAfterSet(attribute, attributes[attribute]);
606
+ // return instance.setAndReturnAfterSet(attribute, attributes[attribute], options);
607
+ });
608
+ }).flatten().each(function(f) {
609
+ f();
610
+ });
611
+ },
612
+
613
+ extend: function(attr, extension) {
614
+ /*
615
+ This code is called a lot.
616
+
617
+ Consider (and benchmark) the performance implication of any changes here.
618
+ */
619
+ if (!attr.prototype._initialize) {
620
+ extension._initialize = extension.initialize || Prototype.emptyFunction;
621
+ extension.initialize = function(options) {
622
+ var attr = this.constructor;
623
+ options = options || {};
624
+
625
+ for (var fieldName in attr._fields) {
626
+ this[fieldName] = new rio.Binding(this, fieldName);
627
+
628
+ var val = attr._fields[fieldName];
629
+
630
+ if (val != undefined) {
631
+ if (Object.isArray(val)) { val = val.clone(); }
632
+ if (typeof val == "object" && val != null && !Object.isArray(val) && !Object.isFunction(val)) {
633
+ val = Object.clone(val);
634
+ }
635
+ }
636
+
637
+ var optVal = options[fieldName] != undefined ? options[fieldName] : options[fieldName.underscore()];
638
+ if (optVal && optVal.BINDING) {
639
+ optVal.bindTo(this[fieldName]);
640
+ val = optVal.value();
641
+ } else if (optVal != undefined) {
642
+ val = optVal;
643
+ }
644
+ this["_" + fieldName] = val;
645
+ }
646
+
647
+ var events = attr._events;
648
+ var len = attr._events.length;
649
+ for (var i=0; i<len; i++) {
650
+ var eventName = events[i];
651
+ var handler = options[("on_" + eventName).camelize()];
652
+ if (handler && Object.isFunction(handler)) {
653
+ this.observe(eventName, handler);
654
+ }
655
+ }
656
+
657
+ this._initialize(options);
658
+ };
659
+ } else if(extension.initialize) {
660
+ extension._initialize = extension.initialize;
661
+ delete extension.initialize;
662
+ }
663
+ attr.addMethods(extension);
664
+ },
665
+
666
+ toString: function() {
667
+ return "Attr";
668
+ }
669
+ };
670
+
671
+ /**
672
+ @class
673
+
674
+ Represents a bindable attribute. Bindings can be bound to each other to create a bi-directional binding.<br /><br />
675
+
676
+ <i>You should rarely need to instantiate this class directly</i>
677
+ */
678
+ rio.Binding = Class.create({
679
+ BINDING: true,
680
+
681
+ // This attribute might be unused
682
+ __bindings: [],
683
+
684
+ initialize: function(obj, fieldName) {
685
+ this._obj = obj;
686
+ this._fieldName = fieldName;
687
+ },
688
+
689
+ bind: function(observer, skipInitialExecution) {
690
+ return this._obj.bind(this._fieldName, observer, skipInitialExecution);
691
+ },
692
+
693
+ bindTo: function(binding) {
694
+ var unbinding1 = this.bind(binding.update.bind(binding));
695
+ var unbinding2 = binding.bind(this.update.bind(this));
696
+ return function() {
697
+ unbinding1();
698
+ unbinding2();
699
+ };
700
+ },
701
+
702
+ value: function() {
703
+ if (this._fieldName.include(".")) {
704
+ var parts = this._fieldName.split(".");
705
+ return parts.inject(this._obj, function(acc, field) {
706
+ return acc ? acc[("get-" + field).camelize()]() : null;
707
+ }.bind(this));
708
+ } else {
709
+ return this._obj[("get-" + this._fieldName).camelize()]();
710
+ }
711
+ },
712
+
713
+ update: function(newVal) {
714
+ var fieldToSet = this._fieldName;
715
+ var setOn = this._obj;
716
+ if (this._fieldName.include(".")) {
717
+ var parts = this._fieldName.split(".");
718
+ fieldToSet = parts.last();
719
+ setOn = parts.slice(0, parts.size() - 1).inject(this._obj, function(acc, field) {
720
+ return acc ? acc["_" + field] : null;
721
+ }.bind(this));
722
+ }
723
+ if (setOn) {
724
+ setOn[("set-" + fieldToSet).camelize()](newVal);
725
+ }
726
+ },
727
+
728
+ invert: function() {
729
+ var invert = {
730
+ BINDING: true,
731
+
732
+ bind: function(observer, skipInitialExecution) {
733
+ return this.bind(observer.wrap(function() {
734
+ var args = $A(arguments);
735
+ var proceed = args.shift();
736
+ args[0] = !args[0];
737
+ return proceed.apply(this, args);
738
+ }), skipInitialExecution);
739
+ }.bind(this),
740
+
741
+ bindTo: function(binding) {
742
+ var unbinding1 = invert.bind(binding.update.bind(binding));
743
+ var unbinding2 = binding.bind(invert.update.bind(invert));
744
+ return function() {
745
+ unbinding1();
746
+ unbinding2();
747
+ };
748
+ }.bind(this),
749
+
750
+ value: function() {
751
+ return !this.value();
752
+ }.bind(this),
753
+
754
+ update: function(val) {
755
+ this.update(!val);
756
+ }.bind(this)
757
+ };
758
+ return invert;
759
+ }
760
+ });