parlement 0.14 → 0.17

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