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,1137 @@
1
+ // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
+ // Contributors:
3
+ // Justin Palmer (http://encytemedia.com/)
4
+ // Mark Pilgrim (http://diveintomark.org/)
5
+ // Martin Bialasinki
6
+ //
7
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
8
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
9
+
10
+ // converts rgb() and #xxx to #xxxxxx format,
11
+ // returns self (or first argument) if not convertable
12
+ String.prototype.parseColor = function() {
13
+ var color = '#';
14
+ var i;
15
+ if (this.slice(0,4) == 'rgb(') {
16
+ var cols = this.slice(4,this.length-1).split(',');
17
+ i=0; do { color += parseInt(cols[i], 10).toColorPart(); } while (++i<3);
18
+ } else {
19
+ if (this.slice(0,1) == '#') {
20
+ if (this.length==4) { for(i=1;i<4;i++) { color += (this.charAt(i) + this.charAt(i)).toLowerCase(); } }
21
+ if (this.length==7) { color = this.toLowerCase(); }
22
+ }
23
+ }
24
+ return (color.length==7 ? color : (arguments[0] || this));
25
+ };
26
+
27
+ /*--------------------------------------------------------------------------*/
28
+
29
+ Element.collectTextNodes = function(element) {
30
+ return $A($(element).childNodes).collect( function(node) {
31
+ return (node.nodeType==3 ? node.nodeValue :
32
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
33
+ }).flatten().join('');
34
+ };
35
+
36
+ Element.collectTextNodesIgnoreClass = function(element, className) {
37
+ return $A($(element).childNodes).collect( function(node) {
38
+ return (node.nodeType==3 ? node.nodeValue :
39
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
40
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
41
+ }).flatten().join('');
42
+ };
43
+
44
+ Element.setContentZoom = function(element, percent) {
45
+ element = $(element);
46
+ element.setStyle({fontSize: (percent/100) + 'em'});
47
+ if (Prototype.Browser.WebKit) { window.scrollBy(0,0); }
48
+ return element;
49
+ };
50
+
51
+ Element.getInlineOpacity = function(element){
52
+ return $(element).style.opacity || '';
53
+ };
54
+
55
+ Element.forceRerendering = function(element) {
56
+ try {
57
+ element = $(element);
58
+ var n = document.createTextNode(' ');
59
+ element.appendChild(n);
60
+ element.removeChild(n);
61
+ } catch(e) { }
62
+ };
63
+
64
+ /*--------------------------------------------------------------------------*/
65
+ Effect = {
66
+ _elementDoesNotExistError: {
67
+ name: 'ElementDoesNotExistError',
68
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
69
+ },
70
+ Transitions: {
71
+ linear: Prototype.K,
72
+ sinoidal: function(pos) {
73
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
74
+ },
75
+ reverse: function(pos) {
76
+ return 1-pos;
77
+ },
78
+ flicker: function(pos) {
79
+ pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
80
+ return pos > 1 ? 1 : pos;
81
+ },
82
+ wobble: function(pos) {
83
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
84
+ },
85
+ pulse: function(pos, pulses) {
86
+ pulses = pulses || 5;
87
+ return (
88
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
89
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
90
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
91
+ );
92
+ },
93
+ spring: function(pos) {
94
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
95
+ },
96
+ none: function(pos) {
97
+ return 0;
98
+ },
99
+ full: function(pos) {
100
+ return 1;
101
+ }
102
+ },
103
+ DefaultOptions: {
104
+ duration: 1.0, // seconds
105
+ fps: 100, // 100= assume 66fps max.
106
+ sync: false, // true for combining
107
+ from: 0.0,
108
+ to: 1.0,
109
+ delay: 0.0,
110
+ queue: 'parallel'
111
+ },
112
+ tagifyText: function(element) {
113
+ var tagifyStyle = 'position:relative';
114
+ if (Prototype.Browser.IE) { tagifyStyle += ';zoom:1'; }
115
+
116
+ element = $(element);
117
+ $A(element.childNodes).each( function(child) {
118
+ if (child.nodeType==3) {
119
+ child.nodeValue.toArray().each( function(character) {
120
+ element.insertBefore(
121
+ new Element('span', {style: tagifyStyle}).update(
122
+ character == ' ' ? String.fromCharCode(160) : character),
123
+ child);
124
+ });
125
+ Element.remove(child);
126
+ }
127
+ });
128
+ },
129
+ multiple: function(element, effect) {
130
+ var elements;
131
+ if (((typeof element == 'object') ||
132
+ Object.isFunction(element)) &&
133
+ (element.length)) {
134
+ elements = element;
135
+ } else {
136
+ elements = $(element).childNodes;
137
+ }
138
+
139
+ var options = Object.extend({
140
+ speed: 0.1,
141
+ delay: 0.0
142
+ }, arguments[2] || { });
143
+ var masterDelay = options.delay;
144
+
145
+ $A(elements).each( function(element, index) {
146
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
147
+ });
148
+ },
149
+ PAIRS: {
150
+ 'slide': ['SlideDown','SlideUp'],
151
+ 'blind': ['BlindDown','BlindUp'],
152
+ 'appear': ['Appear','Fade']
153
+ },
154
+ toggle: function(element, effect) {
155
+ element = $(element);
156
+ effect = (effect || 'appear').toLowerCase();
157
+ var options = Object.extend({
158
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
159
+ }, arguments[2] || { });
160
+ Effect[element.visible() ?
161
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
162
+ }
163
+ };
164
+
165
+ Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
166
+
167
+ /* ------------- core effects ------------- */
168
+
169
+ Effect.ScopedQueue = Class.create(Enumerable, {
170
+ initialize: function() {
171
+ this.effects = [];
172
+ this.interval = null;
173
+ },
174
+ _each: function(iterator) {
175
+ this.effects._each(iterator);
176
+ },
177
+ add: function(effect) {
178
+ var timestamp = new Date().getTime();
179
+
180
+ var position = Object.isString(effect.options.queue) ?
181
+ effect.options.queue : effect.options.queue.position;
182
+
183
+ switch(position) {
184
+ case 'front':
185
+ // move unstarted effects after this effect
186
+ this.effects.findAll(function(e){ return e.state=='idle'; }).each( function(e) {
187
+ e.startOn += effect.finishOn;
188
+ e.finishOn += effect.finishOn;
189
+ });
190
+ break;
191
+ case 'with-last':
192
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
193
+ break;
194
+ case 'end':
195
+ // start effect after last queued effect has finished
196
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
197
+ break;
198
+ }
199
+
200
+ effect.startOn += timestamp;
201
+ effect.finishOn += timestamp;
202
+
203
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) {
204
+ this.effects.push(effect);
205
+ }
206
+
207
+ if (!this.interval) {
208
+ this.interval = setInterval(this.loop.bind(this), 15);
209
+ }
210
+ },
211
+ remove: function(effect) {
212
+ this.effects = this.effects.reject(function(e) { return e==effect; });
213
+ if (this.effects.length == 0) {
214
+ clearInterval(this.interval);
215
+ this.interval = null;
216
+ }
217
+ },
218
+ loop: function() {
219
+ var timePos = new Date().getTime();
220
+ for(var i=0, len=this.effects.length;i<len;i++) {
221
+ this.effects[i] && this.effects[i].loop(timePos);
222
+ }
223
+ }
224
+ });
225
+
226
+ Effect.Queues = {
227
+ instances: $H(),
228
+ get: function(queueName) {
229
+ if (!Object.isString(queueName)) { return queueName; }
230
+
231
+ return this.instances.get(queueName) ||
232
+ this.instances.set(queueName, new Effect.ScopedQueue());
233
+ }
234
+ };
235
+ Effect.Queue = Effect.Queues.get('global');
236
+
237
+ Effect.Base = Class.create({
238
+ position: null,
239
+ start: function(options) {
240
+ function codeForEvent(options,eventName){
241
+ return (
242
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
243
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
244
+ );
245
+ }
246
+ if (options && options.transition === false) { options.transition = Effect.Transitions.linear; }
247
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
248
+ this.currentFrame = 0;
249
+ this.state = 'idle';
250
+ this.startOn = this.options.delay*1000;
251
+ this.finishOn = this.startOn+(this.options.duration*1000);
252
+ this.fromToDelta = this.options.to-this.options.from;
253
+ this.totalTime = this.finishOn-this.startOn;
254
+ this.totalFrames = this.options.fps*this.options.duration;
255
+
256
+ eval('this.render = function(pos){ '+
257
+ 'if (this.state=="idle"){this.state="running";'+
258
+ codeForEvent(this.options,'beforeSetup')+
259
+ (this.setup ? 'this.setup();':'')+
260
+ codeForEvent(this.options,'afterSetup')+
261
+ '};if (this.state=="running"){'+
262
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
263
+ 'this.position=pos;'+
264
+ codeForEvent(this.options,'beforeUpdate')+
265
+ (this.update ? 'this.update(pos);':'')+
266
+ codeForEvent(this.options,'afterUpdate')+
267
+ '}}');
268
+
269
+ this.event('beforeStart');
270
+ if (!this.options.sync) {
271
+ Effect.Queues.get(Object.isString(this.options.queue) ?
272
+ 'global' : this.options.queue.scope).add(this);
273
+ }
274
+ },
275
+ loop: function(timePos) {
276
+ if (timePos >= this.startOn) {
277
+ if (timePos >= this.finishOn) {
278
+ this.render(1.0);
279
+ this.cancel();
280
+ this.event('beforeFinish');
281
+ if (this.finish) { this.finish(); }
282
+ this.event('afterFinish');
283
+ return;
284
+ }
285
+ var pos = (timePos - this.startOn) / this.totalTime,
286
+ frame = (pos * this.totalFrames).round();
287
+ if (frame > this.currentFrame) {
288
+ this.render(pos);
289
+ this.currentFrame = frame;
290
+ }
291
+ }
292
+ },
293
+ cancel: function() {
294
+ if (!this.options.sync) {
295
+ Effect.Queues.get(Object.isString(this.options.queue) ?
296
+ 'global' : this.options.queue.scope).remove(this);
297
+ }
298
+ this.state = 'finished';
299
+ },
300
+ event: function(eventName) {
301
+ if (this.options[eventName + 'Internal']) { this.options[eventName + 'Internal'](this); }
302
+ if (this.options[eventName]) { this.options[eventName](this); }
303
+ },
304
+ inspect: function() {
305
+ var data = $H();
306
+ for(property in this) {
307
+ if (!Object.isFunction(this[property])) { data.set(property, this[property]); }
308
+ }
309
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
310
+ }
311
+ });
312
+
313
+ Effect.Parallel = Class.create(Effect.Base, {
314
+ initialize: function(effects) {
315
+ this.effects = effects || [];
316
+ this.start(arguments[1]);
317
+ },
318
+ update: function(position) {
319
+ this.effects.invoke('render', position);
320
+ },
321
+ finish: function(position) {
322
+ this.effects.each( function(effect) {
323
+ effect.render(1.0);
324
+ effect.cancel();
325
+ effect.event('beforeFinish');
326
+ if (effect.finish) { effect.finish(position); }
327
+ effect.event('afterFinish');
328
+ });
329
+ }
330
+ });
331
+
332
+ Effect.Tween = Class.create(Effect.Base, {
333
+ initialize: function(object, from, to) {
334
+ object = Object.isString(object) ? $(object) : object;
335
+ var args = $A(arguments), method = args.last(),
336
+ options = args.length == 5 ? args[3] : null;
337
+ this.method = Object.isFunction(method) ? method.bind(object) :
338
+ Object.isFunction(object[method]) ? object[method].bind(object) :
339
+ function(value) { object[method] = value; };
340
+ this.start(Object.extend({ from: from, to: to }, options || { }));
341
+ },
342
+ update: function(position) {
343
+ this.method(position);
344
+ }
345
+ });
346
+
347
+ Effect.Event = Class.create(Effect.Base, {
348
+ initialize: function() {
349
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
350
+ },
351
+ update: Prototype.emptyFunction
352
+ });
353
+
354
+ Effect.Opacity = Class.create(Effect.Base, {
355
+ initialize: function(element) {
356
+ this.element = $(element);
357
+ if (!this.element) { throw(Effect._elementDoesNotExistError); }
358
+ // make this work on IE on elements without 'layout'
359
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) {
360
+ this.element.setStyle({zoom: 1});
361
+ }
362
+ var options = Object.extend({
363
+ from: this.element.getOpacity() || 0.0,
364
+ to: 1.0
365
+ }, arguments[1] || { });
366
+ this.start(options);
367
+ },
368
+ update: function(position) {
369
+ this.element.setOpacity(position);
370
+ }
371
+ });
372
+
373
+ Effect.Move = Class.create(Effect.Base, {
374
+ initialize: function(element) {
375
+ this.element = $(element);
376
+ if (!this.element) { throw(Effect._elementDoesNotExistError); }
377
+ var options = Object.extend({
378
+ x: 0,
379
+ y: 0,
380
+ mode: 'relative'
381
+ }, arguments[1] || { });
382
+ this.start(options);
383
+ },
384
+ setup: function() {
385
+ this.element.makePositioned();
386
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
387
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
388
+ if (this.options.mode == 'absolute') {
389
+ this.options.x = this.options.x - this.originalLeft;
390
+ this.options.y = this.options.y - this.originalTop;
391
+ }
392
+ },
393
+ update: function(position) {
394
+ this.element.setStyle({
395
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
396
+ top: (this.options.y * position + this.originalTop).round() + 'px'
397
+ });
398
+ }
399
+ });
400
+
401
+ // for backwards compatibility
402
+ Effect.MoveBy = function(element, toTop, toLeft) {
403
+ return new Effect.Move(element,
404
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
405
+ };
406
+
407
+ Effect.Scale = Class.create(Effect.Base, {
408
+ initialize: function(element, percent) {
409
+ this.element = $(element);
410
+ if (!this.element) { throw(Effect._elementDoesNotExistError); }
411
+ var options = Object.extend({
412
+ scaleX: true,
413
+ scaleY: true,
414
+ scaleContent: true,
415
+ scaleFromCenter: false,
416
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
417
+ scaleFrom: 100.0,
418
+ scaleTo: percent
419
+ }, arguments[2] || { });
420
+ this.start(options);
421
+ },
422
+ setup: function() {
423
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
424
+ this.elementPositioning = this.element.getStyle('position');
425
+
426
+ this.originalStyle = { };
427
+ ['top','left','width','height','fontSize'].each( function(k) {
428
+ this.originalStyle[k] = this.element.style[k];
429
+ }.bind(this));
430
+
431
+ this.originalTop = this.element.offsetTop;
432
+ this.originalLeft = this.element.offsetLeft;
433
+
434
+ var fontSize = this.element.getStyle('font-size') || '100%';
435
+ ['em','px','%','pt'].each( function(fontSizeType) {
436
+ if (fontSize.indexOf(fontSizeType)>0) {
437
+ this.fontSize = parseFloat(fontSize);
438
+ this.fontSizeType = fontSizeType;
439
+ }
440
+ }.bind(this));
441
+
442
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
443
+
444
+ this.dims = null;
445
+ if (this.options.scaleMode=='box') {
446
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
447
+ }
448
+ if (/^content/.test(this.options.scaleMode)) {
449
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
450
+ }
451
+ if (!this.dims) {
452
+ this.dims = [this.options.scaleMode.originalHeight,
453
+ this.options.scaleMode.originalWidth];
454
+ }
455
+ },
456
+ update: function(position) {
457
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
458
+ if (this.options.scaleContent && this.fontSize) {
459
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
460
+ }
461
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
462
+ },
463
+ finish: function(position) {
464
+ if (this.restoreAfterFinish) { this.element.setStyle(this.originalStyle); }
465
+ },
466
+ setDimensions: function(height, width) {
467
+ var d = { };
468
+ if (this.options.scaleX) { d.width = width.round() + 'px'; }
469
+ if (this.options.scaleY) { d.height = height.round() + 'px'; }
470
+ if (this.options.scaleFromCenter) {
471
+ var topd = (height - this.dims[0])/2;
472
+ var leftd = (width - this.dims[1])/2;
473
+ if (this.elementPositioning == 'absolute') {
474
+ if (this.options.scaleY) { d.top = this.originalTop-topd + 'px'; }
475
+ if (this.options.scaleX) { d.left = this.originalLeft-leftd + 'px'; }
476
+ } else {
477
+ if (this.options.scaleY) { d.top = -topd + 'px'; }
478
+ if (this.options.scaleX) { d.left = -leftd + 'px'; }
479
+ }
480
+ }
481
+ this.element.setStyle(d);
482
+ }
483
+ });
484
+
485
+ Effect.Highlight = Class.create(Effect.Base, {
486
+ initialize: function(element) {
487
+ this.element = $(element);
488
+ if (!this.element) { throw(Effect._elementDoesNotExistError); }
489
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
490
+ this.start(options);
491
+ },
492
+ setup: function() {
493
+ // Prevent executing on elements not in the layout flow
494
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
495
+ // Disable background image during the effect
496
+ this.oldStyle = { };
497
+ if (!this.options.keepBackgroundImage) {
498
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
499
+ this.element.setStyle({backgroundImage: 'none'});
500
+ }
501
+ if (!this.options.endcolor) {
502
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
503
+ }
504
+ if (!this.options.restorecolor) {
505
+ this.options.restorecolor = this.element.getStyle('background-color');
506
+ }
507
+ // init color calculations
508
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16); }.bind(this));
509
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i]; }.bind(this));
510
+ },
511
+ update: function(position) {
512
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
513
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
514
+ },
515
+ finish: function() {
516
+ this.element.setStyle(Object.extend(this.oldStyle, {
517
+ backgroundColor: this.options.restorecolor
518
+ }));
519
+ }
520
+ });
521
+
522
+ Effect.ScrollTo = function(element) {
523
+ var options = arguments[1] || { },
524
+ scrollOffsets = document.viewport.getScrollOffsets(),
525
+ elementOffsets = $(element).cumulativeOffset(),
526
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
527
+
528
+ if (options.offset) { elementOffsets[1] += options.offset; }
529
+
530
+ return new Effect.Tween(null,
531
+ scrollOffsets.top,
532
+ elementOffsets[1] > max ? max : elementOffsets[1],
533
+ options,
534
+ function(p){ scrollTo(scrollOffsets.left, p.round()); }
535
+ );
536
+ };
537
+
538
+ /* ------------- combination effects ------------- */
539
+
540
+ Effect.Fade = function(element) {
541
+ element = $(element);
542
+ var oldOpacity = element.getInlineOpacity();
543
+ var options = Object.extend({
544
+ from: element.getOpacity() || 1.0,
545
+ to: 0.0,
546
+ afterFinishInternal: function(effect) {
547
+ if (effect.options.to!=0) { return; }
548
+ effect.element.hide().setStyle({opacity: oldOpacity});
549
+ }
550
+ }, arguments[1] || { });
551
+ return new Effect.Opacity(element,options);
552
+ };
553
+
554
+ Effect.Appear = function(element) {
555
+ element = $(element);
556
+ var options = Object.extend({
557
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
558
+ to: 1.0,
559
+ // force Safari to render floated elements properly
560
+ afterFinishInternal: function(effect) {
561
+ effect.element.forceRerendering();
562
+ },
563
+ beforeSetup: function(effect) {
564
+ effect.element.setOpacity(effect.options.from).show();
565
+ }}, arguments[1] || { });
566
+ return new Effect.Opacity(element,options);
567
+ };
568
+
569
+ Effect.Puff = function(element) {
570
+ element = $(element);
571
+ var oldStyle = {
572
+ opacity: element.getInlineOpacity(),
573
+ position: element.getStyle('position'),
574
+ top: element.style.top,
575
+ left: element.style.left,
576
+ width: element.style.width,
577
+ height: element.style.height
578
+ };
579
+ return new Effect.Parallel(
580
+ [ new Effect.Scale(element, 200,
581
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
582
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
583
+ Object.extend({ duration: 1.0,
584
+ beforeSetupInternal: function(effect) {
585
+ Position.absolutize(effect.effects[0].element);
586
+ },
587
+ afterFinishInternal: function(effect) {
588
+ effect.effects[0].element.hide().setStyle(oldStyle); }
589
+ }, arguments[1] || { })
590
+ );
591
+ };
592
+
593
+ Effect.BlindUp = function(element) {
594
+ element = $(element);
595
+ element.makeClipping();
596
+ return new Effect.Scale(element, 0,
597
+ Object.extend({ scaleContent: false,
598
+ scaleX: false,
599
+ restoreAfterFinish: true,
600
+ afterFinishInternal: function(effect) {
601
+ effect.element.hide().undoClipping();
602
+ }
603
+ }, arguments[1] || { })
604
+ );
605
+ };
606
+
607
+ Effect.BlindDown = function(element) {
608
+ element = $(element);
609
+ var elementDimensions = element.getDimensions();
610
+ return new Effect.Scale(element, 100, Object.extend({
611
+ scaleContent: false,
612
+ scaleX: false,
613
+ scaleFrom: 0,
614
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
615
+ restoreAfterFinish: true,
616
+ afterSetup: function(effect) {
617
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
618
+ },
619
+ afterFinishInternal: function(effect) {
620
+ effect.element.undoClipping();
621
+ }
622
+ }, arguments[1] || { }));
623
+ };
624
+
625
+ Effect.SwitchOff = function(element) {
626
+ element = $(element);
627
+ var oldOpacity = element.getInlineOpacity();
628
+ return new Effect.Appear(element, Object.extend({
629
+ duration: 0.4,
630
+ from: 0,
631
+ transition: Effect.Transitions.flicker,
632
+ afterFinishInternal: function(effect) {
633
+ new Effect.Scale(effect.element, 1, {
634
+ duration: 0.3, scaleFromCenter: true,
635
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
636
+ beforeSetup: function(effect) {
637
+ effect.element.makePositioned().makeClipping();
638
+ },
639
+ afterFinishInternal: function(effect) {
640
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
641
+ }
642
+ });
643
+ }
644
+ }, arguments[1] || { }));
645
+ };
646
+
647
+ Effect.DropOut = function(element) {
648
+ element = $(element);
649
+ var oldStyle = {
650
+ top: element.getStyle('top'),
651
+ left: element.getStyle('left'),
652
+ opacity: element.getInlineOpacity() };
653
+ return new Effect.Parallel(
654
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
655
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
656
+ Object.extend(
657
+ { duration: 0.5,
658
+ beforeSetup: function(effect) {
659
+ effect.effects[0].element.makePositioned();
660
+ },
661
+ afterFinishInternal: function(effect) {
662
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
663
+ }
664
+ }, arguments[1] || { }));
665
+ };
666
+
667
+ Effect.Shake = function(element) {
668
+ element = $(element);
669
+ var options = Object.extend({
670
+ distance: 20,
671
+ duration: 0.5
672
+ }, arguments[1] || {});
673
+ var distance = parseFloat(options.distance);
674
+ var split = parseFloat(options.duration) / 10.0;
675
+ var oldStyle = {
676
+ top: element.getStyle('top'),
677
+ left: element.getStyle('left') };
678
+ return new Effect.Move(element,
679
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
680
+ new Effect.Move(effect.element,
681
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
682
+ new Effect.Move(effect.element,
683
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
684
+ new Effect.Move(effect.element,
685
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
686
+ new Effect.Move(effect.element,
687
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
688
+ new Effect.Move(effect.element,
689
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
690
+ effect.element.undoPositioned().setStyle(oldStyle);
691
+ }}); }}); }}); }}); }}); }});
692
+ };
693
+
694
+ Effect.SlideDown = function(element) {
695
+ element = $(element).cleanWhitespace();
696
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
697
+ var oldInnerBottom = element.down().getStyle('bottom');
698
+ var elementDimensions = element.getDimensions();
699
+ return new Effect.Scale(element, 100, Object.extend({
700
+ scaleContent: false,
701
+ scaleX: false,
702
+ scaleFrom: window.opera ? 0 : 1,
703
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
704
+ restoreAfterFinish: true,
705
+ afterSetup: function(effect) {
706
+ effect.element.makePositioned();
707
+ effect.element.down().makePositioned();
708
+ if (window.opera) { effect.element.setStyle({top: ''}); }
709
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
710
+ },
711
+ afterUpdateInternal: function(effect) {
712
+ effect.element.down().setStyle({bottom:
713
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
714
+ },
715
+ afterFinishInternal: function(effect) {
716
+ effect.element.undoClipping().undoPositioned();
717
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
718
+ }, arguments[1] || { })
719
+ );
720
+ };
721
+
722
+ Effect.SlideUp = function(element) {
723
+ element = $(element).cleanWhitespace();
724
+ var oldInnerBottom = element.down().getStyle('bottom');
725
+ var elementDimensions = element.getDimensions();
726
+ return new Effect.Scale(element, window.opera ? 0 : 1,
727
+ Object.extend({ scaleContent: false,
728
+ scaleX: false,
729
+ scaleMode: 'box',
730
+ scaleFrom: 100,
731
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
732
+ restoreAfterFinish: true,
733
+ afterSetup: function(effect) {
734
+ effect.element.makePositioned();
735
+ effect.element.down().makePositioned();
736
+ if (window.opera) { effect.element.setStyle({top: ''}); }
737
+ effect.element.makeClipping().show();
738
+ },
739
+ afterUpdateInternal: function(effect) {
740
+ effect.element.down().setStyle({bottom:
741
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
742
+ },
743
+ afterFinishInternal: function(effect) {
744
+ effect.element.hide().undoClipping().undoPositioned();
745
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
746
+ }
747
+ }, arguments[1] || { })
748
+ );
749
+ };
750
+
751
+ // Bug in opera makes the TD containing this element expand for a instance after finish
752
+ Effect.Squish = function(element) {
753
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
754
+ restoreAfterFinish: true,
755
+ beforeSetup: function(effect) {
756
+ effect.element.makeClipping();
757
+ },
758
+ afterFinishInternal: function(effect) {
759
+ effect.element.hide().undoClipping();
760
+ }
761
+ });
762
+ };
763
+
764
+ Effect.Grow = function(element) {
765
+ element = $(element);
766
+ var options = Object.extend({
767
+ direction: 'center',
768
+ moveTransition: Effect.Transitions.sinoidal,
769
+ scaleTransition: Effect.Transitions.sinoidal,
770
+ opacityTransition: Effect.Transitions.full
771
+ }, arguments[1] || { });
772
+ var oldStyle = {
773
+ top: element.style.top,
774
+ left: element.style.left,
775
+ height: element.style.height,
776
+ width: element.style.width,
777
+ opacity: element.getInlineOpacity() };
778
+
779
+ var dims = element.getDimensions();
780
+ var initialMoveX, initialMoveY;
781
+ var moveX, moveY;
782
+
783
+ switch (options.direction) {
784
+ case 'top-left':
785
+ initialMoveX = initialMoveY = moveX = moveY = 0;
786
+ break;
787
+ case 'top-right':
788
+ initialMoveX = dims.width;
789
+ initialMoveY = moveY = 0;
790
+ moveX = -dims.width;
791
+ break;
792
+ case 'bottom-left':
793
+ initialMoveX = moveX = 0;
794
+ initialMoveY = dims.height;
795
+ moveY = -dims.height;
796
+ break;
797
+ case 'bottom-right':
798
+ initialMoveX = dims.width;
799
+ initialMoveY = dims.height;
800
+ moveX = -dims.width;
801
+ moveY = -dims.height;
802
+ break;
803
+ case 'center':
804
+ initialMoveX = dims.width / 2;
805
+ initialMoveY = dims.height / 2;
806
+ moveX = -dims.width / 2;
807
+ moveY = -dims.height / 2;
808
+ break;
809
+ }
810
+
811
+ return new Effect.Move(element, {
812
+ x: initialMoveX,
813
+ y: initialMoveY,
814
+ duration: 0.01,
815
+ beforeSetup: function(effect) {
816
+ effect.element.hide().makeClipping().makePositioned();
817
+ },
818
+ afterFinishInternal: function(effect) {
819
+ new Effect.Parallel(
820
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
821
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
822
+ new Effect.Scale(effect.element, 100, {
823
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
824
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
825
+ ], Object.extend({
826
+ beforeSetup: function(effect) {
827
+ effect.effects[0].element.setStyle({height: '0px'}).show();
828
+ },
829
+ afterFinishInternal: function(effect) {
830
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
831
+ }
832
+ }, options)
833
+ );
834
+ }
835
+ });
836
+ };
837
+
838
+ Effect.Shrink = function(element) {
839
+ element = $(element);
840
+ var options = Object.extend({
841
+ direction: 'center',
842
+ moveTransition: Effect.Transitions.sinoidal,
843
+ scaleTransition: Effect.Transitions.sinoidal,
844
+ opacityTransition: Effect.Transitions.none
845
+ }, arguments[1] || { });
846
+ var oldStyle = {
847
+ top: element.style.top,
848
+ left: element.style.left,
849
+ height: element.style.height,
850
+ width: element.style.width,
851
+ opacity: element.getInlineOpacity() };
852
+
853
+ var dims = element.getDimensions();
854
+ var moveX, moveY;
855
+
856
+ switch (options.direction) {
857
+ case 'top-left':
858
+ moveX = moveY = 0;
859
+ break;
860
+ case 'top-right':
861
+ moveX = dims.width;
862
+ moveY = 0;
863
+ break;
864
+ case 'bottom-left':
865
+ moveX = 0;
866
+ moveY = dims.height;
867
+ break;
868
+ case 'bottom-right':
869
+ moveX = dims.width;
870
+ moveY = dims.height;
871
+ break;
872
+ case 'center':
873
+ moveX = dims.width / 2;
874
+ moveY = dims.height / 2;
875
+ break;
876
+ }
877
+
878
+ return new Effect.Parallel(
879
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
880
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
881
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
882
+ ], Object.extend({
883
+ beforeStartInternal: function(effect) {
884
+ effect.effects[0].element.makePositioned().makeClipping();
885
+ },
886
+ afterFinishInternal: function(effect) {
887
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
888
+ }, options)
889
+ );
890
+ };
891
+
892
+ Effect.Pulsate = function(element) {
893
+ element = $(element);
894
+ var options = arguments[1] || { };
895
+ var oldOpacity = element.getInlineOpacity();
896
+ var transition = options.transition || Effect.Transitions.sinoidal;
897
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)); };
898
+ reverser.bind(transition);
899
+ return new Effect.Opacity(element,
900
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
901
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
902
+ }, options), {transition: reverser}));
903
+ };
904
+
905
+ Effect.Fold = function(element) {
906
+ element = $(element);
907
+ var oldStyle = {
908
+ top: element.style.top,
909
+ left: element.style.left,
910
+ width: element.style.width,
911
+ height: element.style.height };
912
+ element.makeClipping();
913
+ return new Effect.Scale(element, 5, Object.extend({
914
+ scaleContent: false,
915
+ scaleX: false,
916
+ afterFinishInternal: function(effect) {
917
+ new Effect.Scale(element, 1, {
918
+ scaleContent: false,
919
+ scaleY: false,
920
+ afterFinishInternal: function(effect) {
921
+ effect.element.hide().undoClipping().setStyle(oldStyle);
922
+ } });
923
+ }}, arguments[1] || { }));
924
+ };
925
+
926
+ Effect.Morph = Class.create(Effect.Base, {
927
+ initialize: function(element) {
928
+ this.element = $(element);
929
+ if (!this.element) { throw(Effect._elementDoesNotExistError); }
930
+ var options = Object.extend({
931
+ style: { }
932
+ }, arguments[1] || { });
933
+
934
+ if (!Object.isString(options.style)) { this.style = $H(options.style); }
935
+ else {
936
+ if (options.style.include(':')) {
937
+ this.style = options.style.parseStyle();
938
+ } else {
939
+ this.element.addClassName(options.style);
940
+ this.style = $H(this.element.getStyles());
941
+ this.element.removeClassName(options.style);
942
+ var css = this.element.getStyles();
943
+ this.style = this.style.reject(function(style) {
944
+ return style.value == css[style.key];
945
+ });
946
+ options.afterFinishInternal = function(effect) {
947
+ effect.element.addClassName(effect.options.style);
948
+ effect.transforms.each(function(transform) {
949
+ effect.element.style[transform.style] = '';
950
+ });
951
+ };
952
+ }
953
+ }
954
+ this.start(options);
955
+ },
956
+
957
+ setup: function(){
958
+ function parseColor(color){
959
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) { color = '#ffffff'; }
960
+ color = color.parseColor();
961
+ return $R(0,2).map(function(i){
962
+ return parseInt( color.slice(i*2+1,i*2+3), 16 );
963
+ });
964
+ }
965
+ this.transforms = this.style.map(function(pair){
966
+ var property = pair[0], value = pair[1], unit = null;
967
+
968
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
969
+ value = value.parseColor();
970
+ unit = 'color';
971
+ } else if (property == 'opacity') {
972
+ value = parseFloat(value);
973
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) {
974
+ this.element.setStyle({zoom: 1});
975
+ }
976
+ } else if (Element.CSS_LENGTH.test(value)) {
977
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
978
+ value = parseFloat(components[1]);
979
+ unit = (components.length == 3) ? components[2] : null;
980
+ }
981
+
982
+ var originalValue = this.element.getStyle(property);
983
+ return {
984
+ style: property.camelize(),
985
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
986
+ targetValue: unit=='color' ? parseColor(value) : value,
987
+ unit: unit
988
+ };
989
+ }.bind(this)).reject(function(transform){
990
+ return (
991
+ (transform.originalValue == transform.targetValue) ||
992
+ (
993
+ transform.unit != 'color' &&
994
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
995
+ )
996
+ );
997
+ });
998
+ },
999
+ update: function(position) {
1000
+ var style = { }, transform, i = this.transforms.length;
1001
+ while(i--) {
1002
+ style[(transform = this.transforms[i]).style] =
1003
+ transform.unit=='color' ? '#'+
1004
+ (Math.round(transform.originalValue[0]+
1005
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
1006
+ (Math.round(transform.originalValue[1]+
1007
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
1008
+ (Math.round(transform.originalValue[2]+
1009
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
1010
+ (transform.originalValue +
1011
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
1012
+ (transform.unit === null ? '' : transform.unit);
1013
+ }
1014
+ this.element.setStyle(style, true);
1015
+ }
1016
+ });
1017
+
1018
+ Effect.Transform = Class.create({
1019
+ initialize: function(tracks){
1020
+ this.tracks = [];
1021
+ this.options = arguments[1] || { };
1022
+ this.addTracks(tracks);
1023
+ },
1024
+ addTracks: function(tracks){
1025
+ tracks.each(function(track){
1026
+ track = $H(track);
1027
+ var data = track.values().first();
1028
+ this.tracks.push($H({
1029
+ ids: track.keys().first(),
1030
+ effect: Effect.Morph,
1031
+ options: { style: data }
1032
+ }));
1033
+ }.bind(this));
1034
+ return this;
1035
+ },
1036
+ play: function(){
1037
+ return new Effect.Parallel(
1038
+ this.tracks.map(function(track){
1039
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
1040
+ var elements = [$(ids) || $$(ids)].flatten();
1041
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)); });
1042
+ }).flatten(),
1043
+ this.options
1044
+ );
1045
+ }
1046
+ });
1047
+
1048
+ Element.CSS_PROPERTIES = $w(
1049
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1050
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1051
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1052
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1053
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
1054
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1055
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1056
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1057
+ 'right textIndent top width wordSpacing zIndex');
1058
+
1059
+ Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1060
+
1061
+ String.__parseStyleElement = document.createElement('div');
1062
+ String.prototype.parseStyle = function(){
1063
+ var style, styleRules = $H();
1064
+ if (Prototype.Browser.WebKit) {
1065
+ style = new Element('div',{style:this}).style;
1066
+ } else {
1067
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1068
+ style = String.__parseStyleElement.childNodes[0].style;
1069
+ }
1070
+
1071
+ Element.CSS_PROPERTIES.each(function(property){
1072
+ if (style[property]) { styleRules.set(property, style[property]); }
1073
+ });
1074
+
1075
+ if (Prototype.Browser.IE && this.include('opacity')) {
1076
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1077
+ }
1078
+
1079
+ return styleRules;
1080
+ };
1081
+
1082
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1083
+ Element.getStyles = function(element) {
1084
+ var css = document.defaultView.getComputedStyle($(element), null);
1085
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
1086
+ styles[property] = css[property];
1087
+ return styles;
1088
+ });
1089
+ };
1090
+ } else {
1091
+ Element.getStyles = function(element) {
1092
+ element = $(element);
1093
+ var css = element.currentStyle, styles;
1094
+ styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) {
1095
+ hash.set(property, css[property]);
1096
+ return hash;
1097
+ });
1098
+ if (!styles.opacity) { styles.set('opacity', element.getOpacity()); }
1099
+ return styles;
1100
+ };
1101
+ }
1102
+
1103
+ Effect.Methods = {
1104
+ morph: function(element, style) {
1105
+ element = $(element);
1106
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
1107
+ return element;
1108
+ },
1109
+ visualEffect: function(element, effect, options) {
1110
+ element = $(element);
1111
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1112
+ new Effect[klass](element, options);
1113
+ return element;
1114
+ },
1115
+ highlight: function(element, options) {
1116
+ element = $(element);
1117
+ new Effect.Highlight(element, options);
1118
+ return element;
1119
+ }
1120
+ };
1121
+
1122
+ $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1123
+ 'pulsate shake puff squish switchOff dropOut').each(
1124
+ function(effect) {
1125
+ Effect.Methods[effect] = function(element, options){
1126
+ element = $(element);
1127
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1128
+ return element;
1129
+ };
1130
+ }
1131
+ );
1132
+
1133
+ $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1134
+ function(f) { Effect.Methods[f] = Element[f]; }
1135
+ );
1136
+
1137
+ Element.addMethods(Effect.Methods);