parlement 0.14 → 0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);