actionpack 1.8.1 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (101) hide show
  1. data/CHANGELOG +309 -16
  2. data/README +1 -1
  3. data/lib/action_controller.rb +5 -0
  4. data/lib/action_controller/assertions.rb +57 -12
  5. data/lib/action_controller/auto_complete.rb +47 -0
  6. data/lib/action_controller/base.rb +288 -258
  7. data/lib/action_controller/benchmarking.rb +8 -3
  8. data/lib/action_controller/caching.rb +88 -42
  9. data/lib/action_controller/cgi_ext/cgi_ext.rb +1 -1
  10. data/lib/action_controller/cgi_ext/cgi_methods.rb +41 -11
  11. data/lib/action_controller/cgi_ext/multipart_progress.rb +169 -0
  12. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +30 -12
  13. data/lib/action_controller/cgi_process.rb +39 -11
  14. data/lib/action_controller/code_generation.rb +235 -0
  15. data/lib/action_controller/cookies.rb +14 -8
  16. data/lib/action_controller/deprecated_renders_and_redirects.rb +76 -0
  17. data/lib/action_controller/filters.rb +8 -7
  18. data/lib/action_controller/helpers.rb +41 -6
  19. data/lib/action_controller/layout.rb +45 -16
  20. data/lib/action_controller/request.rb +86 -23
  21. data/lib/action_controller/rescue.rb +1 -0
  22. data/lib/action_controller/response.rb +1 -1
  23. data/lib/action_controller/routing.rb +536 -272
  24. data/lib/action_controller/scaffolding.rb +30 -25
  25. data/lib/action_controller/session/active_record_store.rb +251 -50
  26. data/lib/action_controller/streaming.rb +133 -0
  27. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -7
  28. data/lib/action_controller/templates/scaffolds/edit.rhtml +2 -2
  29. data/lib/action_controller/templates/scaffolds/layout.rhtml +22 -18
  30. data/lib/action_controller/templates/scaffolds/list.rhtml +3 -3
  31. data/lib/action_controller/templates/scaffolds/new.rhtml +2 -2
  32. data/lib/action_controller/templates/scaffolds/show.rhtml +1 -1
  33. data/lib/action_controller/test_process.rb +68 -47
  34. data/lib/action_controller/upload_progress.rb +421 -0
  35. data/lib/action_controller/url_rewriter.rb +8 -11
  36. data/lib/action_controller/vendor/html-scanner/html/document.rb +6 -5
  37. data/lib/action_controller/vendor/html-scanner/html/node.rb +70 -14
  38. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +17 -10
  39. data/lib/action_controller/vendor/html-scanner/html/version.rb +3 -3
  40. data/lib/action_controller/vendor/xml_simple.rb +1019 -0
  41. data/lib/action_controller/verification.rb +36 -30
  42. data/lib/action_view/base.rb +21 -14
  43. data/lib/action_view/helpers/active_record_helper.rb +15 -13
  44. data/lib/action_view/helpers/asset_tag_helper.rb +26 -9
  45. data/lib/action_view/helpers/benchmark_helper.rb +24 -0
  46. data/lib/action_view/helpers/capture_helper.rb +7 -5
  47. data/lib/action_view/helpers/date_helper.rb +63 -46
  48. data/lib/action_view/helpers/form_helper.rb +7 -1
  49. data/lib/action_view/helpers/form_options_helper.rb +19 -11
  50. data/lib/action_view/helpers/form_tag_helper.rb +5 -1
  51. data/lib/action_view/helpers/javascript_helper.rb +403 -35
  52. data/lib/action_view/helpers/javascripts/controls.js +261 -0
  53. data/lib/action_view/helpers/javascripts/dragdrop.js +476 -0
  54. data/lib/action_view/helpers/javascripts/effects.js +570 -0
  55. data/lib/action_view/helpers/javascripts/prototype.js +633 -371
  56. data/lib/action_view/helpers/number_helper.rb +11 -13
  57. data/lib/action_view/helpers/tag_helper.rb +1 -2
  58. data/lib/action_view/helpers/text_helper.rb +69 -6
  59. data/lib/action_view/helpers/upload_progress_helper.rb +433 -0
  60. data/lib/action_view/helpers/url_helper.rb +98 -3
  61. data/lib/action_view/partials.rb +14 -8
  62. data/lib/action_view/vendor/builder/xmlmarkup.rb +11 -0
  63. data/rakefile +13 -5
  64. data/test/abstract_unit.rb +1 -1
  65. data/test/controller/action_pack_assertions_test.rb +52 -9
  66. data/test/controller/active_record_assertions_test.rb +119 -120
  67. data/test/controller/active_record_store_test.rb +111 -0
  68. data/test/controller/addresses_render_test.rb +45 -0
  69. data/test/controller/caching_filestore.rb +92 -0
  70. data/test/controller/capture_test.rb +39 -0
  71. data/test/controller/cgi_test.rb +40 -3
  72. data/test/controller/helper_test.rb +65 -13
  73. data/test/controller/multipart_progress_testx.rb +365 -0
  74. data/test/controller/new_render_test.rb +263 -0
  75. data/test/controller/redirect_test.rb +64 -0
  76. data/test/controller/render_test.rb +20 -21
  77. data/test/controller/request_test.rb +83 -3
  78. data/test/controller/routing_test.rb +702 -0
  79. data/test/controller/send_file_test.rb +2 -0
  80. data/test/controller/test_test.rb +44 -8
  81. data/test/controller/upload_progress_testx.rb +89 -0
  82. data/test/controller/verification_test.rb +94 -29
  83. data/test/fixtures/addresses/list.rhtml +1 -0
  84. data/test/fixtures/test/capturing.rhtml +4 -0
  85. data/test/fixtures/test/list.rhtml +1 -1
  86. data/test/fixtures/test/update_element_with_capture.rhtml +9 -0
  87. data/test/template/active_record_helper_test.rb +30 -15
  88. data/test/template/asset_tag_helper_test.rb +12 -5
  89. data/test/template/benchmark_helper_test.rb +72 -0
  90. data/test/template/date_helper_test.rb +69 -0
  91. data/test/template/form_helper_test.rb +18 -10
  92. data/test/template/form_options_helper_test.rb +40 -5
  93. data/test/template/javascript_helper.rb +149 -2
  94. data/test/template/number_helper_test.rb +2 -0
  95. data/test/template/tag_helper_test.rb +4 -0
  96. data/test/template/text_helper_test.rb +36 -0
  97. data/test/template/upload_progress_helper_testx.rb +272 -0
  98. data/test/template/url_helper_test.rb +30 -0
  99. metadata +30 -6
  100. data/test/controller/layout_test.rb +0 -49
  101. data/test/controller/routing_tests.rb +0 -543
@@ -0,0 +1,570 @@
1
+ // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
+ //
3
+ // Parts (c) 2005 Justin Palmer (http://encytemedia.com/)
4
+ // Parts (c) 2005 Mark Pilgrim (http://diveintomark.org/)
5
+ //
6
+ // Permission is hereby granted, free of charge, to any person obtaining
7
+ // a copy of this software and associated documentation files (the
8
+ // "Software"), to deal in the Software without restriction, including
9
+ // without limitation the rights to use, copy, modify, merge, publish,
10
+ // distribute, sublicense, and/or sell copies of the Software, and to
11
+ // permit persons to whom the Software is furnished to do so, subject to
12
+ // the following conditions:
13
+ //
14
+ // The above copyright notice and this permission notice shall be
15
+ // included in all copies or substantial portions of the Software.
16
+ //
17
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+
26
+ Effect = {}
27
+ Effect2 = Effect; // deprecated
28
+
29
+ /* ------------- transitions ------------- */
30
+
31
+ Effect.Transitions = {}
32
+
33
+ Effect.Transitions.linear = function(pos) {
34
+ return pos;
35
+ }
36
+ Effect.Transitions.sinoidal = function(pos) {
37
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
38
+ }
39
+ Effect.Transitions.reverse = function(pos) {
40
+ return 1-pos;
41
+ }
42
+ Effect.Transitions.flicker = function(pos) {
43
+ return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random(0.25);
44
+ }
45
+ Effect.Transitions.wobble = function(pos) {
46
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
47
+ }
48
+ Effect.Transitions.pulse = function(pos) {
49
+ return (Math.floor(pos*10) % 2 == 0 ?
50
+ (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
51
+ }
52
+
53
+ Effect.Transitions.none = function(pos) {
54
+ return 0;
55
+ }
56
+ Effect.Transitions.full = function(pos) {
57
+ return 1;
58
+ }
59
+
60
+ /* ------------- core effects ------------- */
61
+
62
+ Effect.Base = function() {};
63
+ Effect.Base.prototype = {
64
+ setOptions: function(options) {
65
+ this.options = {
66
+ transition: Effect.Transitions.sinoidal,
67
+ duration: 1.0, // seconds
68
+ fps: 25.0, // max. 100fps
69
+ sync: false, // true for combining
70
+ from: 0.0,
71
+ to: 1.0
72
+ }.extend(options || {});
73
+ },
74
+ start: function(options) {
75
+ this.setOptions(options || {});
76
+ this.currentFrame = 0;
77
+ this.startOn = new Date().getTime();
78
+ this.finishOn = this.startOn + (this.options.duration*1000);
79
+ if(this.options.beforeStart) this.options.beforeStart(this);
80
+ if(!this.options.sync) this.loop();
81
+ },
82
+ loop: function() {
83
+ timePos = new Date().getTime();
84
+ if(timePos >= this.finishOn) {
85
+ this.render(this.options.to);
86
+ if(this.finish) this.finish();
87
+ if(this.options.afterFinish) this.options.afterFinish(this);
88
+ return;
89
+ }
90
+ pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
91
+ frame = Math.round(pos * this.options.fps * this.options.duration);
92
+ if(frame > this.currentFrame) {
93
+ this.render(pos);
94
+ this.currentFrame = frame;
95
+ }
96
+ this.timeout = setTimeout(this.loop.bind(this), 10);
97
+ },
98
+ render: function(pos) {
99
+ if(this.options.transition) pos = this.options.transition(pos);
100
+ pos = pos * (this.options.to-this.options.from);
101
+ pos += this.options.from;
102
+ if(this.options.beforeUpdate) this.options.beforeUpdate(this);
103
+ if(this.update) this.update(pos);
104
+ if(this.options.afterUpdate) this.options.afterUpdate(this);
105
+ },
106
+ cancel: function() {
107
+ if(this.timeout) clearTimeout(this.timeout);
108
+ }
109
+ }
110
+
111
+ Effect.Parallel = Class.create();
112
+ Effect.Parallel.prototype = (new Effect.Base()).extend({
113
+ initialize: function(effects) {
114
+ this.effects = effects || [];
115
+ this.start(arguments[1]);
116
+ },
117
+ update: function(position) {
118
+ for (var i = 0; i < this.effects.length; i++)
119
+ this.effects[i].render(position);
120
+ },
121
+ finish: function(position) {
122
+ for (var i = 0; i < this.effects.length; i++)
123
+ if(this.effects[i].finish) this.effects[i].finish(position);
124
+ }
125
+ });
126
+
127
+ // Internet Explorer caveat: works only on elements the have
128
+ // a 'layout', meaning having a given width or height.
129
+ // There is no way to safely set this automatically.
130
+ Effect.Opacity = Class.create();
131
+ Effect.Opacity.prototype = (new Effect.Base()).extend({
132
+ initialize: function(element) {
133
+ this.element = $(element);
134
+ options = {
135
+ from: 0.0,
136
+ to: 1.0
137
+ }.extend(arguments[1] || {});
138
+ this.start(options);
139
+ },
140
+ update: function(position) {
141
+ this.setOpacity(position);
142
+ },
143
+ setOpacity: function(opacity) {
144
+ opacity = (opacity == 1) ? 0.99999 : opacity;
145
+ this.element.style.opacity = opacity;
146
+ this.element.style.filter = "alpha(opacity:"+opacity*100+")";
147
+ }
148
+ });
149
+
150
+ Effect.MoveBy = Class.create();
151
+ Effect.MoveBy.prototype = (new Effect.Base()).extend({
152
+ initialize: function(element, toTop, toLeft) {
153
+ this.element = $(element);
154
+ this.originalTop = parseFloat(this.element.style.top || '0');
155
+ this.originalLeft = parseFloat(this.element.style.left || '0');
156
+ this.toTop = toTop;
157
+ this.toLeft = toLeft;
158
+ if(this.element.style.position == "")
159
+ this.element.style.position = "relative";
160
+ this.start(arguments[3]);
161
+ },
162
+ update: function(position) {
163
+ topd = this.toTop * position + this.originalTop;
164
+ leftd = this.toLeft * position + this.originalLeft;
165
+ this.setPosition(topd, leftd);
166
+ },
167
+ setPosition: function(topd, leftd) {
168
+ this.element.style.top = topd + "px";
169
+ this.element.style.left = leftd + "px";
170
+ }
171
+ });
172
+
173
+ Effect.Scale = Class.create();
174
+ Effect.Scale.prototype = (new Effect.Base()).extend({
175
+ initialize: function(element, percent) {
176
+ this.element = $(element)
177
+ options = {
178
+ scaleX: true,
179
+ scaleY: true,
180
+ scaleContent: true,
181
+ scaleFromCenter: false,
182
+ scaleMode: 'box', // 'box' or 'contents' or {} with provided values
183
+ scaleFrom: 100.0
184
+ }.extend(arguments[2] || {});
185
+ this.originalTop = this.element.offsetTop;
186
+ this.originalLeft = this.element.offsetLeft;
187
+ if (this.element.style.fontSize=="") this.sizeEm = 1.0;
188
+ if (this.element.style.fontSize && this.element.style.fontSize.indexOf("em")>0)
189
+ this.sizeEm = parseFloat(this.element.style.fontSize);
190
+ this.factor = (percent/100.0) - (options.scaleFrom/100.0);
191
+ if(options.scaleMode=='box') {
192
+ this.originalHeight = this.element.clientHeight;
193
+ this.originalWidth = this.element.clientWidth;
194
+ } else
195
+ if(options.scaleMode=='contents') {
196
+ this.originalHeight = this.element.scrollHeight;
197
+ this.originalWidth = this.element.scrollWidth;
198
+ } else {
199
+ this.originalHeight = options.scaleMode.originalHeight;
200
+ this.originalWidth = options.scaleMode.originalWidth;
201
+ }
202
+ this.start(options);
203
+ },
204
+
205
+ update: function(position) {
206
+ currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
207
+ if(this.options.scaleContent && this.sizeEm)
208
+ this.element.style.fontSize = this.sizeEm*currentScale + "em";
209
+ this.setDimensions(
210
+ this.originalWidth * currentScale,
211
+ this.originalHeight * currentScale);
212
+ },
213
+
214
+ setDimensions: function(width, height) {
215
+ if(this.options.scaleX) this.element.style.width = width + 'px';
216
+ if(this.options.scaleY) this.element.style.height = height + 'px';
217
+ if(this.options.scaleFromCenter) {
218
+ topd = (height - this.originalHeight)/2;
219
+ leftd = (width - this.originalWidth)/2;
220
+ if(this.element.style.position=='absolute') {
221
+ if(this.options.scaleY) this.element.style.top = this.originalTop-topd + "px";
222
+ if(this.options.scaleX) this.element.style.left = this.originalLeft-leftd + "px";
223
+ } else {
224
+ if(this.options.scaleY) this.element.style.top = -topd + "px";
225
+ if(this.options.scaleX) this.element.style.left = -leftd + "px";
226
+ }
227
+ }
228
+ }
229
+ });
230
+
231
+ Effect.Highlight = Class.create();
232
+ Effect.Highlight.prototype = (new Effect.Base()).extend({
233
+ initialize: function(element) {
234
+ this.element = $(element);
235
+
236
+ // try to parse current background color as default for endcolor
237
+ // browser stores this as: "rgb(255, 255, 255)", convert to "#ffffff" format
238
+ var endcolor = "#ffffff";
239
+ var current = this.element.style.backgroundColor;
240
+ if(current && current.slice(0,4) == "rgb(") {
241
+ endcolor = "#";
242
+ var cols = current.slice(4,current.length-1).split(',');
243
+ var i=0; do { endcolor += parseInt(cols[i]).toColorPart() } while (++i<3); }
244
+
245
+ var options = {
246
+ startcolor: "#ffff99",
247
+ endcolor: endcolor
248
+ }.extend(arguments[1] || {});
249
+
250
+ // init color calculations
251
+ this.colors_base = [
252
+ parseInt(options.startcolor.slice(1,3),16),
253
+ parseInt(options.startcolor.slice(3,5),16),
254
+ parseInt(options.startcolor.slice(5),16) ];
255
+ this.colors_delta = [
256
+ parseInt(options.endcolor.slice(1,3),16)-this.colors_base[0],
257
+ parseInt(options.endcolor.slice(3,5),16)-this.colors_base[1],
258
+ parseInt(options.endcolor.slice(5),16)-this.colors_base[2] ];
259
+
260
+ this.start(options);
261
+ },
262
+ update: function(position) {
263
+ var colors = [
264
+ Math.round(this.colors_base[0]+(this.colors_delta[0]*position)),
265
+ Math.round(this.colors_base[1]+(this.colors_delta[1]*position)),
266
+ Math.round(this.colors_base[2]+(this.colors_delta[2]*position)) ];
267
+ this.element.style.backgroundColor = "#" +
268
+ colors[0].toColorPart() + colors[1].toColorPart() + colors[2].toColorPart();
269
+ }
270
+ });
271
+
272
+
273
+ /* ------------- prepackaged effects ------------- */
274
+
275
+ Effect.Fade = function(element) {
276
+ options = {
277
+ from: 1.0,
278
+ to: 0.0,
279
+ afterFinish: function(effect)
280
+ { Element.hide(effect.element);
281
+ effect.setOpacity(1); }
282
+ }.extend(arguments[1] || {});
283
+ new Effect.Opacity(element,options);
284
+ }
285
+
286
+ Effect.Appear = function(element) {
287
+ options = {
288
+ from: 0.0,
289
+ to: 1.0,
290
+ beforeStart: function(effect)
291
+ { effect.setOpacity(0);
292
+ Element.show(effect.element); },
293
+ afterUpdate: function(effect)
294
+ { Element.show(effect.element); }
295
+ }.extend(arguments[1] || {});
296
+ new Effect.Opacity(element,options);
297
+ }
298
+
299
+ Effect.Puff = function(element) {
300
+ new Effect.Parallel(
301
+ [ new Effect.Scale(element, 200, { sync: true, scaleFromCenter: true }),
302
+ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0 } ) ],
303
+ { duration: 1.0,
304
+ afterUpdate: function(effect)
305
+ { effect.effects[0].element.style.position = 'absolute'; },
306
+ afterFinish: function(effect)
307
+ { Element.hide(effect.effects[0].element); }
308
+ }
309
+ );
310
+ }
311
+
312
+ Effect.BlindUp = function(element) {
313
+ $(element)._overflow = $(element).style.overflow || 'visible';
314
+ $(element).style.overflow = 'hidden';
315
+ new Effect.Scale(element, 0,
316
+ { scaleContent: false,
317
+ scaleX: false,
318
+ afterFinish: function(effect)
319
+ {
320
+ Element.hide(effect.element);
321
+ effect.element.style.overflow = effect.element._overflow;
322
+ }
323
+ }.extend(arguments[1] || {})
324
+ );
325
+ }
326
+
327
+ Effect.BlindDown = function(element) {
328
+ $(element).style.height = '0px';
329
+ $(element)._overflow = $(element).style.overflow || 'visible';
330
+ $(element).style.overflow = 'hidden';
331
+ Element.show(element);
332
+ new Effect.Scale(element, 100,
333
+ { scaleContent: false,
334
+ scaleX: false,
335
+ scaleMode: 'contents',
336
+ scaleFrom: 0,
337
+ afterFinish: function(effect) {
338
+ effect.element.style.overflow = effect.element._overflow;
339
+ }
340
+ }.extend(arguments[1] || {})
341
+ );
342
+ }
343
+
344
+ Effect.SwitchOff = function(element) {
345
+ new Effect.Appear(element,
346
+ { duration: 0.4,
347
+ transition: Effect.Transitions.flicker,
348
+ afterFinish: function(effect)
349
+ { effect.element.style.overflow = 'hidden';
350
+ new Effect.Scale(effect.element, 1,
351
+ { duration: 0.3, scaleFromCenter: true,
352
+ scaleX: false, scaleContent: false,
353
+ afterUpdate: function(effect) {
354
+ if(effect.element.style.position=="")
355
+ effect.element.style.position = 'relative'; },
356
+ afterFinish: function(effect) { Element.hide(effect.element); }
357
+ } )
358
+ }
359
+ } )
360
+ }
361
+
362
+ Effect.DropOut = function(element) {
363
+ new Effect.Parallel(
364
+ [ new Effect.MoveBy(element, 100, 0, { sync: true }),
365
+ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0 } ) ],
366
+ { duration: 0.5,
367
+ afterFinish: function(effect)
368
+ { Element.hide(effect.effects[0].element); }
369
+ });
370
+ }
371
+
372
+ Effect.Shake = function(element) {
373
+ new Effect.MoveBy(element, 0, 20,
374
+ { duration: 0.05, afterFinish: function(effect) {
375
+ new Effect.MoveBy(effect.element, 0, -40,
376
+ { duration: 0.1, afterFinish: function(effect) {
377
+ new Effect.MoveBy(effect.element, 0, 40,
378
+ { duration: 0.1, afterFinish: function(effect) {
379
+ new Effect.MoveBy(effect.element, 0, -40,
380
+ { duration: 0.1, afterFinish: function(effect) {
381
+ new Effect.MoveBy(effect.element, 0, 40,
382
+ { duration: 0.1, afterFinish: function(effect) {
383
+ new Effect.MoveBy(effect.element, 0, -20,
384
+ { duration: 0.05, afterFinish: function(effect) {
385
+ }}) }}) }}) }}) }}) }});
386
+ }
387
+
388
+ Effect.SlideDown = function(element) {
389
+ $(element)._overflow = $(element).style.overflow || 'visible';
390
+ $(element).style.height = '0px';
391
+ $(element).style.overflow = 'hidden';
392
+ $(element).firstChild.style.position = 'relative';
393
+ Element.show(element);
394
+ new Effect.Scale(element, 100,
395
+ { scaleContent: false,
396
+ scaleX: false,
397
+ scaleMode: 'contents',
398
+ scaleFrom: 0,
399
+ afterUpdate: function(effect)
400
+ { effect.element.firstChild.style.bottom =
401
+ (effect.originalHeight - effect.element.clientHeight) + 'px'; },
402
+ afterFinish: function(effect)
403
+ { effect.element.style.overflow = effect.element._overflow; }
404
+ }.extend(arguments[1] || {})
405
+ );
406
+ }
407
+
408
+ Effect.SlideUp = function(element) {
409
+ $(element)._overflow = $(element).style.overflow || 'visible';
410
+ $(element).style.overflow = 'hidden';
411
+ $(element).firstChild.style.position = 'relative';
412
+ Element.show(element);
413
+ new Effect.Scale(element, 0,
414
+ { scaleContent: false,
415
+ scaleX: false,
416
+ afterUpdate: function(effect)
417
+ { effect.element.firstChild.style.bottom =
418
+ (effect.originalHeight - effect.element.clientHeight) + 'px'; },
419
+ afterFinish: function(effect)
420
+ {
421
+ Element.hide(effect.element);
422
+ effect.element.style.overflow = effect.element._overflow;
423
+ }
424
+ }.extend(arguments[1] || {})
425
+ );
426
+ }
427
+
428
+ Effect.Squish = function(element) {
429
+ new Effect.Scale(element, 0,
430
+ { afterFinish: function(effect) { Element.hide(effect.element); } });
431
+ }
432
+
433
+ Effect.Grow = function(element) {
434
+ element = $(element);
435
+ var options = arguments[1] || {};
436
+
437
+ var originalWidth = element.clientWidth;
438
+ var originalHeight = element.clientHeight;
439
+ element.style.overflow = 'hidden';
440
+ Element.show(element);
441
+
442
+ var direction = options.direction || 'center';
443
+ var moveTransition = options.moveTransition || Effect.Transitions.sinoidal;
444
+ var scaleTransition = options.scaleTransition || Effect.Transitions.sinoidal;
445
+ var opacityTransition = options.opacityTransition || Effect.Transitions.full;
446
+
447
+ var initialMoveX, initialMoveY;
448
+ var moveX, moveY;
449
+
450
+ switch (direction) {
451
+ case 'top-left':
452
+ initialMoveX = initialMoveY = moveX = moveY = 0;
453
+ break;
454
+ case 'top-right':
455
+ initialMoveX = originalWidth;
456
+ initialMoveY = moveY = 0;
457
+ moveX = -originalWidth;
458
+ break;
459
+ case 'bottom-left':
460
+ initialMoveX = moveX = 0;
461
+ initialMoveY = originalHeight;
462
+ moveY = -originalHeight;
463
+ break;
464
+ case 'bottom-right':
465
+ initialMoveX = originalWidth;
466
+ initialMoveY = originalHeight;
467
+ moveX = -originalWidth;
468
+ moveY = -originalHeight;
469
+ break;
470
+ case 'center':
471
+ initialMoveX = originalWidth / 2;
472
+ initialMoveY = originalHeight / 2;
473
+ moveX = -originalWidth / 2;
474
+ moveY = -originalHeight / 2;
475
+ break;
476
+ }
477
+
478
+ new Effect.MoveBy(element, initialMoveY, initialMoveX, {
479
+ duration: 0.01,
480
+ beforeUpdate: function(effect) { $(element).style.height = '0px'; },
481
+ afterFinish: function(effect) {
482
+ new Effect.Parallel(
483
+ [ new Effect.Opacity(element, { sync: true, to: 1.0, from: 0.0, transition: opacityTransition }),
484
+ new Effect.MoveBy(element, moveY, moveX, { sync: true, transition: moveTransition }),
485
+ new Effect.Scale(element, 100, {
486
+ scaleMode: { originalHeight: originalHeight, originalWidth: originalWidth },
487
+ sync: true, scaleFrom: 0, scaleTo: 100, transition: scaleTransition })],
488
+ options); }
489
+ });
490
+ }
491
+
492
+ Effect.Shrink = function(element) {
493
+ element = $(element);
494
+ var options = arguments[1] || {};
495
+
496
+ var originalWidth = element.clientWidth;
497
+ var originalHeight = element.clientHeight;
498
+ element.style.overflow = 'hidden';
499
+ Element.show(element);
500
+
501
+ var direction = options.direction || 'center';
502
+ var moveTransition = options.moveTransition || Effect.Transitions.sinoidal;
503
+ var scaleTransition = options.scaleTransition || Effect.Transitions.sinoidal;
504
+ var opacityTransition = options.opacityTransition || Effect.Transitions.none;
505
+
506
+ var moveX, moveY;
507
+
508
+ switch (direction) {
509
+ case 'top-left':
510
+ moveX = moveY = 0;
511
+ break;
512
+ case 'top-right':
513
+ moveX = originalWidth;
514
+ moveY = 0;
515
+ break;
516
+ case 'bottom-left':
517
+ moveX = 0;
518
+ moveY = originalHeight;
519
+ break;
520
+ case 'bottom-right':
521
+ moveX = originalWidth;
522
+ moveY = originalHeight;
523
+ break;
524
+ case 'center':
525
+ moveX = originalWidth / 2;
526
+ moveY = originalHeight / 2;
527
+ break;
528
+ }
529
+
530
+ new Effect.Parallel(
531
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: opacityTransition }),
532
+ new Effect.Scale(element, 0, { sync: true, transition: moveTransition }),
533
+ new Effect.MoveBy(element, moveY, moveX, { sync: true, transition: scaleTransition }) ],
534
+ options);
535
+ }
536
+
537
+ Effect.Pulsate = function(element) {
538
+ var options = arguments[1] || {};
539
+ var transition = options.transition || Effect.Transitions.sinoidal;
540
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
541
+ reverser.bind(transition);
542
+ new Effect.Opacity(element,
543
+ { duration: 3.0,
544
+ afterFinish: function(effect) { Element.show(effect.element); }
545
+ }.extend(options).extend({transition: reverser}));
546
+ }
547
+
548
+ Effect.Fold = function(element) {
549
+ $(element).style.overflow = 'hidden';
550
+ new Effect.Scale(element, 5, {
551
+ scaleContent: false,
552
+ scaleTo: 100,
553
+ scaleX: false,
554
+ afterFinish: function(effect) {
555
+ new Effect.Scale(element, 1, {
556
+ scaleContent: false,
557
+ scaleTo: 0,
558
+ scaleY: false,
559
+ afterFinish: function(effect) { Element.hide(effect.element) } });
560
+ }}.extend(arguments[1] || {}));
561
+ }
562
+
563
+ // old: new Effect.ContentZoom(element, percent)
564
+ // new: Element.setContentZoom(element, percent)
565
+
566
+ Element.setContentZoom = function(element, percent) {
567
+ var element = $(element);
568
+ element.style.fontSize = (percent/100) + "em";
569
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
570
+ }