backlog 0.35.5 → 0.36.2

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 (150) hide show
  1. data/Gemfile +19 -0
  2. data/Gemfile~ +4 -0
  3. data/History.txt +25 -0
  4. data/Rakefile +3 -3
  5. data/app/controllers/{application.rb → application_controller.rb} +1 -2
  6. data/app/controllers/backlogs_controller.rb +0 -16
  7. data/app/controllers/search_controller.rb +0 -2
  8. data/app/controllers/user_controller.rb +7 -7
  9. data/app/controllers/work_locks_controller.rb +2 -2
  10. data/app/controllers/works_controller.rb +23 -23
  11. data/app/helpers/application_helper.rb +9 -6
  12. data/app/helpers/backlogs_helper.rb +1 -1
  13. data/app/helpers/periods_helper.rb +1 -1
  14. data/app/models/backlog.rb +13 -10
  15. data/app/models/period.rb +0 -5
  16. data/app/models/sidebar.rb +1 -0
  17. data/app/models/task.rb +4 -10
  18. data/app/models/user.rb +5 -6
  19. data/app/models/user_notify.rb +0 -1
  20. data/app/models/work.rb +20 -25
  21. data/app/models/works_report_filter.rb +4 -4
  22. data/app/views/backlogs/_buttons.rhtml +1 -1
  23. data/app/views/backlogs/_form.rhtml +5 -9
  24. data/app/views/layouts/_left_top.rhtml +0 -1
  25. data/app/views/periods/_form.rhtml +1 -1
  26. data/app/views/search/results.rhtml +1 -12
  27. data/app/views/task_notify/{invite_en.rhtml → invite.en.html.erb} +0 -0
  28. data/app/views/task_notify/{invite_no.rhtml → invite.no.html.erb} +0 -0
  29. data/app/views/tasks/_task.rhtml +49 -50
  30. data/app/views/tasks/edit.rhtml +4 -4
  31. data/app/views/tasks/start_work.rjs +1 -1
  32. data/app/views/user/_edit.rhtml +1 -1
  33. data/app/views/user/change_password.rhtml +1 -1
  34. data/app/views/user/edit.rhtml +4 -4
  35. data/app/views/user/signup.rhtml +2 -2
  36. data/app/views/user_notify/{change_password_en.rhtml → change_password.en.html.erb} +0 -0
  37. data/app/views/user_notify/{change_password_no.rhtml → change_password.no.html.erb} +0 -0
  38. data/app/views/user_notify/{forgot_password_en.rhtml → forgot_password.en.html.erb} +0 -0
  39. data/app/views/user_notify/{forgot_password_no.rhtml → forgot_password.no.html.erb} +0 -0
  40. data/app/views/user_notify/{monitoring_en.rhtml → monitoring.en.html.erb} +0 -0
  41. data/app/views/user_notify/{monitoring_no.rhtml → monitoring.no.html.erb} +0 -0
  42. data/app/views/user_notify/{monitoring_invitation_en.rhtml → monitoring_invitation.en.html.erb} +0 -0
  43. data/app/views/user_notify/{monitoring_invitation_no.rhtml → monitoring_invitation.no.html.erb} +0 -0
  44. data/app/views/user_notify/{signup_en.rhtml → signup.en.html.erb} +0 -0
  45. data/app/views/user_notify/{signup_no.rhtml → signup.no.html.erb} +0 -0
  46. data/app/views/work_lock_notify/{lock_en.rhtml → lock.en.html.erb} +0 -0
  47. data/app/views/work_lock_notify/{lock_no.rhtml → lock.no.html.erb} +0 -0
  48. data/app/views/work_lock_notify/{nag_en.rhtml → nag.en.html.erb} +0 -0
  49. data/app/views/work_lock_notify/{nag_no.rhtml → nag.no.html.erb} +0 -0
  50. data/app/views/works/_form.rhtml +6 -6
  51. data/app/views/works/_new_row.rhtml +6 -6
  52. data/app/views/works/_row.rhtml +2 -2
  53. data/app/views/works/daily_work_sheet.rhtml +1 -1
  54. data/app/views/works/list.rhtml +6 -6
  55. data/app/views/works/list_excel.rhtml +8 -4
  56. data/app/views/works/timeliste.rhtml +14 -14
  57. data/app/views/works/update_row.rjs +1 -1
  58. data/app/views/works/weekly_work_sheet.rhtml +5 -5
  59. data/app/views/works/weekly_work_sheet_details.rhtml +5 -5
  60. data/config/boot.rb +108 -27
  61. data/config/database.yml +3 -26
  62. data/config/environment.rb +4 -12
  63. data/config/environments/development.rb +0 -1
  64. data/config/initializers/jdbc.rb +7 -0
  65. data/config/initializers/mongrel.rb +83 -0
  66. data/config/locales/en.yml +189 -0
  67. data/config/locales/no.yml +192 -0
  68. data/config/preinitializer.rb +20 -0
  69. data/cruise_build.sh +10 -0
  70. data/cruise_config.rb +1 -1
  71. data/db/migrate/20100720124707_merge_work_account_into_backlog.rb +74 -0
  72. data/db/schema.rb +93 -127
  73. data/lib/class_table_inheritance.rb +53 -11
  74. data/lib/tasks/jdbc.rake +8 -0
  75. data/lib/user_system.rb +5 -1
  76. data/public/javascripts/controls.js +76 -79
  77. data/public/javascripts/dragdrop.js +166 -167
  78. data/public/javascripts/effects.js +174 -168
  79. data/public/javascripts/prototype.js +470 -334
  80. data/public/stylesheets/mwrt002.css +6 -6
  81. data/script/dbconsole +3 -0
  82. data/test/fixtures/backlogs.yml +2 -2
  83. data/test/fixtures/work_lock_subscriptions.yml +2 -2
  84. data/test/fixtures/works.yml +6 -6
  85. data/test/functional/absences_controller_test.rb +1 -1
  86. data/test/functional/backlogs_controller_test.rb +4 -4
  87. data/test/functional/customers_controller_test.rb +1 -1
  88. data/test/functional/dashboard_controller_test.rb +1 -1
  89. data/test/functional/estimates_controller_test.rb +1 -1
  90. data/test/functional/groups_controller_test.rb +1 -1
  91. data/test/functional/parties_controller_test.rb +1 -1
  92. data/test/functional/periods_controller_test.rb +1 -1
  93. data/test/functional/public_holidays_controller_test.rb +1 -1
  94. data/test/functional/search_controller_test.rb +1 -1
  95. data/test/functional/task_files_controller_test.rb +1 -1
  96. data/test/functional/tasks_controller_test.rb +6 -6
  97. data/test/functional/user_controller_test.rb +3 -2
  98. data/test/functional/welcome_controller_test.rb +1 -1
  99. data/test/functional/work_locks_controller_test.rb +1 -1
  100. data/test/functional/works_controller_test.rb +11 -11
  101. data/test/test_helper.rb +2 -2
  102. data/test/unit/absence_test.rb +1 -1
  103. data/test/unit/configuration_test.rb +1 -1
  104. data/test/unit/customer_test.rb +1 -1
  105. data/test/unit/estimate_test.rb +1 -1
  106. data/test/unit/group_test.rb +1 -1
  107. data/test/unit/party_test.rb +1 -1
  108. data/test/unit/period_test.rb +1 -1
  109. data/test/unit/public_holiday_test.rb +1 -1
  110. data/test/unit/task_file_test.rb +1 -1
  111. data/test/unit/task_test.rb +1 -1
  112. data/test/unit/user_test.rb +1 -1
  113. data/test/unit/work_lock_subscription_test.rb +1 -1
  114. data/test/unit/work_lock_test.rb +1 -1
  115. data/test/unit/work_test.rb +8 -8
  116. data/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb +3 -3
  117. data/vendor/plugins/assert_cookie/lib/assert_cookie.rb +2 -2
  118. data/vendor/plugins/auto_complete/README +23 -0
  119. data/vendor/plugins/auto_complete/Rakefile +22 -0
  120. data/vendor/plugins/auto_complete/init.rb +2 -0
  121. data/vendor/plugins/auto_complete/lib/auto_complete.rb +47 -0
  122. data/vendor/plugins/auto_complete/lib/auto_complete_macros_helper.rb +143 -0
  123. data/vendor/plugins/auto_complete/test/auto_complete_test.rb +67 -0
  124. data/vendor/plugins/backlog_jira/init.rb +4 -0
  125. data/vendor/plugins/backlog_jira/{tasks → lib/tasks}/backlog_jira_tasks.rake +0 -0
  126. data/vendor/plugins/has_history/{tasks → lib/tasks}/has_history_tasks.rake +0 -0
  127. metadata +745 -817
  128. data/#SearchRequest.xml# +0 -3443
  129. data/app/controllers/application.rb~ +0 -207
  130. data/app/controllers/work_accounts_controller.rb +0 -58
  131. data/app/helpers/work_accounts_helper.rb +0 -2
  132. data/app/models/work_account.rb +0 -18
  133. data/app/models/work_lock_subscription.rb +0 -3
  134. data/app/views/work_accounts/_form.rhtml +0 -16
  135. data/app/views/work_accounts/_name_list.rhtml +0 -5
  136. data/app/views/work_accounts/_title.rhtml +0 -5
  137. data/app/views/work_accounts/edit.rhtml +0 -12
  138. data/app/views/work_accounts/list.rhtml +0 -31
  139. data/app/views/work_accounts/new.rhtml +0 -10
  140. data/app/views/work_accounts/show.rhtml +0 -50
  141. data/config/environments/localization_environment.rb +0 -10
  142. data/jira.log +0 -98246
  143. data/lang/en.yaml +0 -147
  144. data/lang/localizations.yaml +0 -2
  145. data/lang/no.yaml +0 -146
  146. data/lib/localization.rb +0 -88
  147. data/test/fixtures/work_accounts.yml +0 -7
  148. data/test/functional/work_accounts_controller_test.rb +0 -94
  149. data/test/unit/localization_test.rb +0 -47
  150. data/test/unit/work_account_test.rb +0 -10
@@ -1,50 +1,48 @@
1
- // script.aculo.us effects.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
2
-
3
- // Copyright (c) 2005-2007 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)
4
2
  // Contributors:
5
3
  // Justin Palmer (http://encytemedia.com/)
6
4
  // Mark Pilgrim (http://diveintomark.org/)
7
5
  // Martin Bialasinki
8
- //
6
+ //
9
7
  // script.aculo.us is freely distributable under the terms of an MIT-style license.
10
- // 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/
11
9
 
12
- // converts rgb() and #xxx to #xxxxxx format,
13
- // returns self (or first argument) if not convertable
14
- 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() {
15
13
  var color = '#';
16
- if (this.slice(0,4) == 'rgb(') {
17
- var cols = this.slice(4,this.length-1).split(',');
18
- var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
19
- } else {
20
- if (this.slice(0,1) == '#') {
21
- if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
22
- if (this.length==7) color = this.toLowerCase();
23
- }
24
- }
25
- return (color.length==7 ? color : (arguments[0] || this));
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));
26
24
  };
27
25
 
28
26
  /*--------------------------------------------------------------------------*/
29
27
 
30
- Element.collectTextNodes = function(element) {
28
+ Element.collectTextNodes = function(element) {
31
29
  return $A($(element).childNodes).collect( function(node) {
32
- return (node.nodeType==3 ? node.nodeValue :
30
+ return (node.nodeType==3 ? node.nodeValue :
33
31
  (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
34
32
  }).flatten().join('');
35
33
  };
36
34
 
37
- Element.collectTextNodesIgnoreClass = function(element, className) {
35
+ Element.collectTextNodesIgnoreClass = function(element, className) {
38
36
  return $A($(element).childNodes).collect( function(node) {
39
- return (node.nodeType==3 ? node.nodeValue :
40
- ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
37
+ return (node.nodeType==3 ? node.nodeValue :
38
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
41
39
  Element.collectTextNodesIgnoreClass(node, className) : ''));
42
40
  }).flatten().join('');
43
41
  };
44
42
 
45
43
  Element.setContentZoom = function(element, percent) {
46
- element = $(element);
47
- element.setStyle({fontSize: (percent/100) + 'em'});
44
+ element = $(element);
45
+ element.setStyle({fontSize: (percent/100) + 'em'});
48
46
  if (Prototype.Browser.WebKit) window.scrollBy(0,0);
49
47
  return element;
50
48
  };
@@ -72,28 +70,23 @@ var Effect = {
72
70
  Transitions: {
73
71
  linear: Prototype.K,
74
72
  sinoidal: function(pos) {
75
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
73
+ return (-Math.cos(pos*Math.PI)/2) + .5;
76
74
  },
77
75
  reverse: function(pos) {
78
76
  return 1-pos;
79
77
  },
80
78
  flicker: function(pos) {
81
- var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
79
+ var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
82
80
  return pos > 1 ? 1 : pos;
83
81
  },
84
82
  wobble: function(pos) {
85
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
83
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
86
84
  },
87
- pulse: function(pos, pulses) {
88
- pulses = pulses || 5;
89
- return (
90
- ((pos % (1/pulses)) * pulses).round() == 0 ?
91
- ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
92
- 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
93
- );
85
+ pulse: function(pos, pulses) {
86
+ return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
94
87
  },
95
- spring: function(pos) {
96
- return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
88
+ spring: function(pos) {
89
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
97
90
  },
98
91
  none: function(pos) {
99
92
  return 0;
@@ -114,14 +107,14 @@ var Effect = {
114
107
  tagifyText: function(element) {
115
108
  var tagifyStyle = 'position:relative';
116
109
  if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
117
-
110
+
118
111
  element = $(element);
119
112
  $A(element.childNodes).each( function(child) {
120
113
  if (child.nodeType==3) {
121
114
  child.nodeValue.toArray().each( function(character) {
122
115
  element.insertBefore(
123
116
  new Element('span', {style: tagifyStyle}).update(
124
- character == ' ' ? String.fromCharCode(160) : character),
117
+ character == ' ' ? String.fromCharCode(160) : character),
125
118
  child);
126
119
  });
127
120
  Element.remove(child);
@@ -130,13 +123,13 @@ var Effect = {
130
123
  },
131
124
  multiple: function(element, effect) {
132
125
  var elements;
133
- if (((typeof element == 'object') ||
134
- Object.isFunction(element)) &&
126
+ if (((typeof element == 'object') ||
127
+ Object.isFunction(element)) &&
135
128
  (element.length))
136
129
  elements = element;
137
130
  else
138
131
  elements = $(element).childNodes;
139
-
132
+
140
133
  var options = Object.extend({
141
134
  speed: 0.1,
142
135
  delay: 0.0
@@ -158,7 +151,7 @@ var Effect = {
158
151
  var options = Object.extend({
159
152
  queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
160
153
  }, arguments[2] || { });
161
- Effect[element.visible() ?
154
+ Effect[element.visible() ?
162
155
  Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
163
156
  }
164
157
  };
@@ -170,20 +163,20 @@ Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
170
163
  Effect.ScopedQueue = Class.create(Enumerable, {
171
164
  initialize: function() {
172
165
  this.effects = [];
173
- this.interval = null;
166
+ this.interval = null;
174
167
  },
175
168
  _each: function(iterator) {
176
169
  this.effects._each(iterator);
177
170
  },
178
171
  add: function(effect) {
179
172
  var timestamp = new Date().getTime();
180
-
181
- var position = Object.isString(effect.options.queue) ?
173
+
174
+ var position = Object.isString(effect.options.queue) ?
182
175
  effect.options.queue : effect.options.queue.position;
183
-
176
+
184
177
  switch(position) {
185
178
  case 'front':
186
- // move unstarted effects after this effect
179
+ // move unstarted effects after this effect
187
180
  this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
188
181
  e.startOn += effect.finishOn;
189
182
  e.finishOn += effect.finishOn;
@@ -197,13 +190,13 @@ Effect.ScopedQueue = Class.create(Enumerable, {
197
190
  timestamp = this.effects.pluck('finishOn').max() || timestamp;
198
191
  break;
199
192
  }
200
-
193
+
201
194
  effect.startOn += timestamp;
202
195
  effect.finishOn += timestamp;
203
196
 
204
197
  if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
205
198
  this.effects.push(effect);
206
-
199
+
207
200
  if (!this.interval)
208
201
  this.interval = setInterval(this.loop.bind(this), 15);
209
202
  },
@@ -216,7 +209,7 @@ Effect.ScopedQueue = Class.create(Enumerable, {
216
209
  },
217
210
  loop: function() {
218
211
  var timePos = new Date().getTime();
219
- for(var i=0, len=this.effects.length;i<len;i++)
212
+ for(var i=0, len=this.effects.length;i<len;i++)
220
213
  this.effects[i] && this.effects[i].loop(timePos);
221
214
  }
222
215
  });
@@ -225,7 +218,7 @@ Effect.Queues = {
225
218
  instances: $H(),
226
219
  get: function(queueName) {
227
220
  if (!Object.isString(queueName)) return queueName;
228
-
221
+
229
222
  return this.instances.get(queueName) ||
230
223
  this.instances.set(queueName, new Effect.ScopedQueue());
231
224
  }
@@ -250,23 +243,35 @@ Effect.Base = Class.create({
250
243
  this.fromToDelta = this.options.to-this.options.from;
251
244
  this.totalTime = this.finishOn-this.startOn;
252
245
  this.totalFrames = this.options.fps*this.options.duration;
253
-
254
- eval('this.render = function(pos){ '+
255
- 'if (this.state=="idle"){this.state="running";'+
256
- codeForEvent(this.options,'beforeSetup')+
257
- (this.setup ? 'this.setup();':'')+
258
- codeForEvent(this.options,'afterSetup')+
259
- '};if (this.state=="running"){'+
260
- 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
261
- 'this.position=pos;'+
262
- codeForEvent(this.options,'beforeUpdate')+
263
- (this.update ? 'this.update(pos);':'')+
264
- codeForEvent(this.options,'afterUpdate')+
265
- '}}');
266
-
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
+
267
272
  this.event('beforeStart');
268
273
  if (!this.options.sync)
269
- Effect.Queues.get(Object.isString(this.options.queue) ?
274
+ Effect.Queues.get(Object.isString(this.options.queue) ?
270
275
  'global' : this.options.queue.scope).add(this);
271
276
  },
272
277
  loop: function(timePos) {
@@ -275,9 +280,9 @@ Effect.Base = Class.create({
275
280
  this.render(1.0);
276
281
  this.cancel();
277
282
  this.event('beforeFinish');
278
- if (this.finish) this.finish();
283
+ if (this.finish) this.finish();
279
284
  this.event('afterFinish');
280
- return;
285
+ return;
281
286
  }
282
287
  var pos = (timePos - this.startOn) / this.totalTime,
283
288
  frame = (pos * this.totalFrames).round();
@@ -289,7 +294,7 @@ Effect.Base = Class.create({
289
294
  },
290
295
  cancel: function() {
291
296
  if (!this.options.sync)
292
- Effect.Queues.get(Object.isString(this.options.queue) ?
297
+ Effect.Queues.get(Object.isString(this.options.queue) ?
293
298
  'global' : this.options.queue.scope).remove(this);
294
299
  this.state = 'finished';
295
300
  },
@@ -327,10 +332,10 @@ Effect.Parallel = Class.create(Effect.Base, {
327
332
  Effect.Tween = Class.create(Effect.Base, {
328
333
  initialize: function(object, from, to) {
329
334
  object = Object.isString(object) ? $(object) : object;
330
- var args = $A(arguments), method = args.last(),
335
+ var args = $A(arguments), method = args.last(),
331
336
  options = args.length == 5 ? args[3] : null;
332
337
  this.method = Object.isFunction(method) ? method.bind(object) :
333
- Object.isFunction(object[method]) ? object[method].bind(object) :
338
+ Object.isFunction(object[method]) ? object[method].bind(object) :
334
339
  function(value) { object[method] = value };
335
340
  this.start(Object.extend({ from: from, to: to }, options || { }));
336
341
  },
@@ -394,7 +399,7 @@ Effect.Move = Class.create(Effect.Base, {
394
399
 
395
400
  // for backwards compatibility
396
401
  Effect.MoveBy = function(element, toTop, toLeft) {
397
- return new Effect.Move(element,
402
+ return new Effect.Move(element,
398
403
  Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
399
404
  };
400
405
 
@@ -416,15 +421,15 @@ Effect.Scale = Class.create(Effect.Base, {
416
421
  setup: function() {
417
422
  this.restoreAfterFinish = this.options.restoreAfterFinish || false;
418
423
  this.elementPositioning = this.element.getStyle('position');
419
-
424
+
420
425
  this.originalStyle = { };
421
426
  ['top','left','width','height','fontSize'].each( function(k) {
422
427
  this.originalStyle[k] = this.element.style[k];
423
428
  }.bind(this));
424
-
429
+
425
430
  this.originalTop = this.element.offsetTop;
426
431
  this.originalLeft = this.element.offsetLeft;
427
-
432
+
428
433
  var fontSize = this.element.getStyle('font-size') || '100%';
429
434
  ['em','px','%','pt'].each( function(fontSizeType) {
430
435
  if (fontSize.indexOf(fontSizeType)>0) {
@@ -432,9 +437,9 @@ Effect.Scale = Class.create(Effect.Base, {
432
437
  this.fontSizeType = fontSizeType;
433
438
  }
434
439
  }.bind(this));
435
-
440
+
436
441
  this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
437
-
442
+
438
443
  this.dims = null;
439
444
  if (this.options.scaleMode=='box')
440
445
  this.dims = [this.element.offsetHeight, this.element.offsetWidth];
@@ -509,17 +514,16 @@ Effect.Highlight = Class.create(Effect.Base, {
509
514
 
510
515
  Effect.ScrollTo = function(element) {
511
516
  var options = arguments[1] || { },
512
- scrollOffsets = document.viewport.getScrollOffsets(),
513
- elementOffsets = $(element).cumulativeOffset(),
514
- max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
517
+ scrollOffsets = document.viewport.getScrollOffsets(),
518
+ elementOffsets = $(element).cumulativeOffset();
515
519
 
516
520
  if (options.offset) elementOffsets[1] += options.offset;
517
521
 
518
522
  return new Effect.Tween(null,
519
523
  scrollOffsets.top,
520
- elementOffsets[1] > max ? max : elementOffsets[1],
524
+ elementOffsets[1],
521
525
  options,
522
- function(p){ scrollTo(scrollOffsets.left, p.round()) }
526
+ function(p){ scrollTo(scrollOffsets.left, p.round()); }
523
527
  );
524
528
  };
525
529
 
@@ -531,9 +535,9 @@ Effect.Fade = function(element) {
531
535
  var options = Object.extend({
532
536
  from: element.getOpacity() || 1.0,
533
537
  to: 0.0,
534
- afterFinishInternal: function(effect) {
538
+ afterFinishInternal: function(effect) {
535
539
  if (effect.options.to!=0) return;
536
- effect.element.hide().setStyle({opacity: oldOpacity});
540
+ effect.element.hide().setStyle({opacity: oldOpacity});
537
541
  }
538
542
  }, arguments[1] || { });
539
543
  return new Effect.Opacity(element,options);
@@ -549,15 +553,15 @@ Effect.Appear = function(element) {
549
553
  effect.element.forceRerendering();
550
554
  },
551
555
  beforeSetup: function(effect) {
552
- effect.element.setOpacity(effect.options.from).show();
556
+ effect.element.setOpacity(effect.options.from).show();
553
557
  }}, arguments[1] || { });
554
558
  return new Effect.Opacity(element,options);
555
559
  };
556
560
 
557
561
  Effect.Puff = function(element) {
558
562
  element = $(element);
559
- var oldStyle = {
560
- opacity: element.getInlineOpacity(),
563
+ var oldStyle = {
564
+ opacity: element.getInlineOpacity(),
561
565
  position: element.getStyle('position'),
562
566
  top: element.style.top,
563
567
  left: element.style.left,
@@ -565,12 +569,12 @@ Effect.Puff = function(element) {
565
569
  height: element.style.height
566
570
  };
567
571
  return new Effect.Parallel(
568
- [ new Effect.Scale(element, 200,
569
- { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
570
- new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
571
- 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,
572
576
  beforeSetupInternal: function(effect) {
573
- Position.absolutize(effect.effects[0].element)
577
+ Position.absolutize(effect.effects[0].element);
574
578
  },
575
579
  afterFinishInternal: function(effect) {
576
580
  effect.effects[0].element.hide().setStyle(oldStyle); }
@@ -582,12 +586,12 @@ Effect.BlindUp = function(element) {
582
586
  element = $(element);
583
587
  element.makeClipping();
584
588
  return new Effect.Scale(element, 0,
585
- Object.extend({ scaleContent: false,
586
- scaleX: false,
589
+ Object.extend({ scaleContent: false,
590
+ scaleX: false,
587
591
  restoreAfterFinish: true,
588
592
  afterFinishInternal: function(effect) {
589
593
  effect.element.hide().undoClipping();
590
- }
594
+ }
591
595
  }, arguments[1] || { })
592
596
  );
593
597
  };
@@ -595,15 +599,15 @@ Effect.BlindUp = function(element) {
595
599
  Effect.BlindDown = function(element) {
596
600
  element = $(element);
597
601
  var elementDimensions = element.getDimensions();
598
- return new Effect.Scale(element, 100, Object.extend({
599
- scaleContent: false,
602
+ return new Effect.Scale(element, 100, Object.extend({
603
+ scaleContent: false,
600
604
  scaleX: false,
601
605
  scaleFrom: 0,
602
606
  scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
603
607
  restoreAfterFinish: true,
604
608
  afterSetup: function(effect) {
605
- effect.element.makeClipping().setStyle({height: '0px'}).show();
606
- },
609
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
610
+ },
607
611
  afterFinishInternal: function(effect) {
608
612
  effect.element.undoClipping();
609
613
  }
@@ -618,16 +622,16 @@ Effect.SwitchOff = function(element) {
618
622
  from: 0,
619
623
  transition: Effect.Transitions.flicker,
620
624
  afterFinishInternal: function(effect) {
621
- new Effect.Scale(effect.element, 1, {
625
+ new Effect.Scale(effect.element, 1, {
622
626
  duration: 0.3, scaleFromCenter: true,
623
627
  scaleX: false, scaleContent: false, restoreAfterFinish: true,
624
- beforeSetup: function(effect) {
628
+ beforeSetup: function(effect) {
625
629
  effect.element.makePositioned().makeClipping();
626
630
  },
627
631
  afterFinishInternal: function(effect) {
628
632
  effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
629
633
  }
630
- })
634
+ });
631
635
  }
632
636
  }, arguments[1] || { }));
633
637
  };
@@ -639,16 +643,16 @@ Effect.DropOut = function(element) {
639
643
  left: element.getStyle('left'),
640
644
  opacity: element.getInlineOpacity() };
641
645
  return new Effect.Parallel(
642
- [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
646
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
643
647
  new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
644
648
  Object.extend(
645
649
  { duration: 0.5,
646
650
  beforeSetup: function(effect) {
647
- effect.effects[0].element.makePositioned();
651
+ effect.effects[0].element.makePositioned();
648
652
  },
649
653
  afterFinishInternal: function(effect) {
650
654
  effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
651
- }
655
+ }
652
656
  }, arguments[1] || { }));
653
657
  };
654
658
 
@@ -676,7 +680,7 @@ Effect.Shake = function(element) {
676
680
  new Effect.Move(effect.element,
677
681
  { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
678
682
  effect.element.undoPositioned().setStyle(oldStyle);
679
- }}) }}) }}) }}) }}) }});
683
+ }}); }}); }}); }}); }}); }});
680
684
  };
681
685
 
682
686
  Effect.SlideDown = function(element) {
@@ -684,9 +688,9 @@ Effect.SlideDown = function(element) {
684
688
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
685
689
  var oldInnerBottom = element.down().getStyle('bottom');
686
690
  var elementDimensions = element.getDimensions();
687
- return new Effect.Scale(element, 100, Object.extend({
688
- scaleContent: false,
689
- scaleX: false,
691
+ return new Effect.Scale(element, 100, Object.extend({
692
+ scaleContent: false,
693
+ scaleX: false,
690
694
  scaleFrom: window.opera ? 0 : 1,
691
695
  scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
692
696
  restoreAfterFinish: true,
@@ -694,11 +698,11 @@ Effect.SlideDown = function(element) {
694
698
  effect.element.makePositioned();
695
699
  effect.element.down().makePositioned();
696
700
  if (window.opera) effect.element.setStyle({top: ''});
697
- effect.element.makeClipping().setStyle({height: '0px'}).show();
701
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
698
702
  },
699
703
  afterUpdateInternal: function(effect) {
700
704
  effect.element.down().setStyle({bottom:
701
- (effect.dims[0] - effect.element.clientHeight) + 'px' });
705
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
702
706
  },
703
707
  afterFinishInternal: function(effect) {
704
708
  effect.element.undoClipping().undoPositioned();
@@ -712,8 +716,8 @@ Effect.SlideUp = function(element) {
712
716
  var oldInnerBottom = element.down().getStyle('bottom');
713
717
  var elementDimensions = element.getDimensions();
714
718
  return new Effect.Scale(element, window.opera ? 0 : 1,
715
- Object.extend({ scaleContent: false,
716
- scaleX: false,
719
+ Object.extend({ scaleContent: false,
720
+ scaleX: false,
717
721
  scaleMode: 'box',
718
722
  scaleFrom: 100,
719
723
  scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
@@ -723,7 +727,7 @@ Effect.SlideUp = function(element) {
723
727
  effect.element.down().makePositioned();
724
728
  if (window.opera) effect.element.setStyle({top: ''});
725
729
  effect.element.makeClipping().show();
726
- },
730
+ },
727
731
  afterUpdateInternal: function(effect) {
728
732
  effect.element.down().setStyle({bottom:
729
733
  (effect.dims[0] - effect.element.clientHeight) + 'px' });
@@ -736,15 +740,15 @@ Effect.SlideUp = function(element) {
736
740
  );
737
741
  };
738
742
 
739
- // 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
740
744
  Effect.Squish = function(element) {
741
- return new Effect.Scale(element, window.opera ? 1 : 0, {
745
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
742
746
  restoreAfterFinish: true,
743
747
  beforeSetup: function(effect) {
744
- effect.element.makeClipping();
745
- },
748
+ effect.element.makeClipping();
749
+ },
746
750
  afterFinishInternal: function(effect) {
747
- effect.element.hide().undoClipping();
751
+ effect.element.hide().undoClipping();
748
752
  }
749
753
  });
750
754
  };
@@ -764,13 +768,13 @@ Effect.Grow = function(element) {
764
768
  width: element.style.width,
765
769
  opacity: element.getInlineOpacity() };
766
770
 
767
- var dims = element.getDimensions();
771
+ var dims = element.getDimensions();
768
772
  var initialMoveX, initialMoveY;
769
773
  var moveX, moveY;
770
-
774
+
771
775
  switch (options.direction) {
772
776
  case 'top-left':
773
- initialMoveX = initialMoveY = moveX = moveY = 0;
777
+ initialMoveX = initialMoveY = moveX = moveY = 0;
774
778
  break;
775
779
  case 'top-right':
776
780
  initialMoveX = dims.width;
@@ -795,11 +799,11 @@ Effect.Grow = function(element) {
795
799
  moveY = -dims.height / 2;
796
800
  break;
797
801
  }
798
-
802
+
799
803
  return new Effect.Move(element, {
800
804
  x: initialMoveX,
801
805
  y: initialMoveY,
802
- duration: 0.01,
806
+ duration: 0.01,
803
807
  beforeSetup: function(effect) {
804
808
  effect.element.hide().makeClipping().makePositioned();
805
809
  },
@@ -808,17 +812,17 @@ Effect.Grow = function(element) {
808
812
  [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
809
813
  new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
810
814
  new Effect.Scale(effect.element, 100, {
811
- scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
815
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
812
816
  sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
813
817
  ], Object.extend({
814
818
  beforeSetup: function(effect) {
815
- effect.effects[0].element.setStyle({height: '0px'}).show();
819
+ effect.effects[0].element.setStyle({height: '0px'}).show();
816
820
  },
817
821
  afterFinishInternal: function(effect) {
818
- effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
822
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
819
823
  }
820
824
  }, options)
821
- )
825
+ );
822
826
  }
823
827
  });
824
828
  };
@@ -840,7 +844,7 @@ Effect.Shrink = function(element) {
840
844
 
841
845
  var dims = element.getDimensions();
842
846
  var moveX, moveY;
843
-
847
+
844
848
  switch (options.direction) {
845
849
  case 'top-left':
846
850
  moveX = moveY = 0;
@@ -857,19 +861,19 @@ Effect.Shrink = function(element) {
857
861
  moveX = dims.width;
858
862
  moveY = dims.height;
859
863
  break;
860
- case 'center':
864
+ case 'center':
861
865
  moveX = dims.width / 2;
862
866
  moveY = dims.height / 2;
863
867
  break;
864
868
  }
865
-
869
+
866
870
  return new Effect.Parallel(
867
871
  [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
868
872
  new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
869
873
  new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
870
- ], Object.extend({
874
+ ], Object.extend({
871
875
  beforeStartInternal: function(effect) {
872
- effect.effects[0].element.makePositioned().makeClipping();
876
+ effect.effects[0].element.makePositioned().makeClipping();
873
877
  },
874
878
  afterFinishInternal: function(effect) {
875
879
  effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
@@ -879,12 +883,14 @@ Effect.Shrink = function(element) {
879
883
 
880
884
  Effect.Pulsate = function(element) {
881
885
  element = $(element);
882
- var options = arguments[1] || { };
883
- var oldOpacity = element.getInlineOpacity();
884
- var transition = options.transition || Effect.Transitions.sinoidal;
885
- var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
886
- reverser.bind(transition);
887
- 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,
888
894
  Object.extend(Object.extend({ duration: 2.0, from: 0,
889
895
  afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
890
896
  }, options), {transition: reverser}));
@@ -898,12 +904,12 @@ Effect.Fold = function(element) {
898
904
  width: element.style.width,
899
905
  height: element.style.height };
900
906
  element.makeClipping();
901
- return new Effect.Scale(element, 5, Object.extend({
907
+ return new Effect.Scale(element, 5, Object.extend({
902
908
  scaleContent: false,
903
909
  scaleX: false,
904
910
  afterFinishInternal: function(effect) {
905
- new Effect.Scale(element, 1, {
906
- scaleContent: false,
911
+ new Effect.Scale(element, 1, {
912
+ scaleContent: false,
907
913
  scaleY: false,
908
914
  afterFinishInternal: function(effect) {
909
915
  effect.element.hide().undoClipping().setStyle(oldStyle);
@@ -918,7 +924,7 @@ Effect.Morph = Class.create(Effect.Base, {
918
924
  var options = Object.extend({
919
925
  style: { }
920
926
  }, arguments[1] || { });
921
-
927
+
922
928
  if (!Object.isString(options.style)) this.style = $H(options.style);
923
929
  else {
924
930
  if (options.style.include(':'))
@@ -936,18 +942,18 @@ Effect.Morph = Class.create(Effect.Base, {
936
942
  effect.transforms.each(function(transform) {
937
943
  effect.element.style[transform.style] = '';
938
944
  });
939
- }
945
+ };
940
946
  }
941
947
  }
942
948
  this.start(options);
943
949
  },
944
-
950
+
945
951
  setup: function(){
946
952
  function parseColor(color){
947
953
  if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
948
954
  color = color.parseColor();
949
955
  return $R(0,2).map(function(i){
950
- return parseInt( color.slice(i*2+1,i*2+3), 16 )
956
+ return parseInt( color.slice(i*2+1,i*2+3), 16 );
951
957
  });
952
958
  }
953
959
  this.transforms = this.style.map(function(pair){
@@ -967,9 +973,9 @@ Effect.Morph = Class.create(Effect.Base, {
967
973
  }
968
974
 
969
975
  var originalValue = this.element.getStyle(property);
970
- return {
971
- style: property.camelize(),
972
- originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
976
+ return {
977
+ style: property.camelize(),
978
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
973
979
  targetValue: unit=='color' ? parseColor(value) : value,
974
980
  unit: unit
975
981
  };
@@ -980,13 +986,13 @@ Effect.Morph = Class.create(Effect.Base, {
980
986
  transform.unit != 'color' &&
981
987
  (isNaN(transform.originalValue) || isNaN(transform.targetValue))
982
988
  )
983
- )
989
+ );
984
990
  });
985
991
  },
986
992
  update: function(position) {
987
993
  var style = { }, transform, i = this.transforms.length;
988
994
  while(i--)
989
- style[(transform = this.transforms[i]).style] =
995
+ style[(transform = this.transforms[i]).style] =
990
996
  transform.unit=='color' ? '#'+
991
997
  (Math.round(transform.originalValue[0]+
992
998
  (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
@@ -995,7 +1001,7 @@ Effect.Morph = Class.create(Effect.Base, {
995
1001
  (Math.round(transform.originalValue[2]+
996
1002
  (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
997
1003
  (transform.originalValue +
998
- (transform.targetValue - transform.originalValue) * position).toFixed(3) +
1004
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
999
1005
  (transform.unit === null ? '' : transform.unit);
1000
1006
  this.element.setStyle(style, true);
1001
1007
  }
@@ -1032,7 +1038,7 @@ Effect.Transform = Class.create({
1032
1038
  });
1033
1039
 
1034
1040
  Element.CSS_PROPERTIES = $w(
1035
- 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1041
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1036
1042
  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1037
1043
  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1038
1044
  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
@@ -1041,7 +1047,7 @@ Element.CSS_PROPERTIES = $w(
1041
1047
  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1042
1048
  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1043
1049
  'right textIndent top width wordSpacing zIndex');
1044
-
1050
+
1045
1051
  Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1046
1052
 
1047
1053
  String.__parseStyleElement = document.createElement('div');
@@ -1053,11 +1059,11 @@ String.prototype.parseStyle = function(){
1053
1059
  String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1054
1060
  style = String.__parseStyleElement.childNodes[0].style;
1055
1061
  }
1056
-
1062
+
1057
1063
  Element.CSS_PROPERTIES.each(function(property){
1058
- if (style[property]) styleRules.set(property, style[property]);
1064
+ if (style[property]) styleRules.set(property, style[property]);
1059
1065
  });
1060
-
1066
+
1061
1067
  if (Prototype.Browser.IE && this.include('opacity'))
1062
1068
  styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1063
1069
 
@@ -1076,14 +1082,14 @@ if (document.defaultView && document.defaultView.getComputedStyle) {
1076
1082
  Element.getStyles = function(element) {
1077
1083
  element = $(element);
1078
1084
  var css = element.currentStyle, styles;
1079
- styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) {
1080
- hash.set(property, css[property]);
1081
- return hash;
1085
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
1086
+ results[property] = css[property];
1087
+ return results;
1082
1088
  });
1083
- if (!styles.opacity) styles.set('opacity', element.getOpacity());
1089
+ if (!styles.opacity) styles.opacity = element.getOpacity();
1084
1090
  return styles;
1085
1091
  };
1086
- };
1092
+ }
1087
1093
 
1088
1094
  Effect.Methods = {
1089
1095
  morph: function(element, style) {
@@ -1092,7 +1098,7 @@ Effect.Methods = {
1092
1098
  return element;
1093
1099
  },
1094
1100
  visualEffect: function(element, effect, options) {
1095
- element = $(element)
1101
+ element = $(element);
1096
1102
  var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1097
1103
  new Effect[klass](element, options);
1098
1104
  return element;
@@ -1106,17 +1112,17 @@ Effect.Methods = {
1106
1112
 
1107
1113
  $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1108
1114
  'pulsate shake puff squish switchOff dropOut').each(
1109
- function(effect) {
1115
+ function(effect) {
1110
1116
  Effect.Methods[effect] = function(element, options){
1111
1117
  element = $(element);
1112
1118
  Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1113
1119
  return element;
1114
- }
1120
+ };
1115
1121
  }
1116
1122
  );
1117
1123
 
1118
- $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1124
+ $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1119
1125
  function(f) { Effect.Methods[f] = Element[f]; }
1120
1126
  );
1121
1127
 
1122
- Element.addMethods(Effect.Methods);
1128
+ Element.addMethods(Effect.Methods);