actionpack 1.9.0 → 1.9.1

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.

@@ -46,15 +46,33 @@ Effect.Transitions.wobble = function(pos) {
46
46
  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
47
47
  }
48
48
  Effect.Transitions.pulse = function(pos) {
49
- return (Math.floor(pos*10) % 2 == 0 ?
49
+ return (Math.floor(pos*10) % 2 == 0 ?
50
50
  (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
51
51
  }
52
-
53
52
  Effect.Transitions.none = function(pos) {
54
- return 0;
53
+ return 0;
55
54
  }
56
55
  Effect.Transitions.full = function(pos) {
57
- return 1;
56
+ return 1;
57
+ }
58
+
59
+ /* ------------- element ext -------------- */
60
+
61
+ Element.makePositioned = function(element) {
62
+ element = $(element);
63
+ if(element.style.position == "")
64
+ element.style.position = "relative";
65
+ }
66
+
67
+ Element.makeClipping = function(element) {
68
+ element = $(element);
69
+ element._overflow = element.style.overflow || 'visible';
70
+ if(element._overflow!='hidden') element.style.overflow = 'hidden';
71
+ }
72
+
73
+ Element.undoClipping = function(element) {
74
+ element = $(element);
75
+ if(element._overflow!='hidden') element.style.overflow = element._overflow;
58
76
  }
59
77
 
60
78
  /* ------------- core effects ------------- */
@@ -62,33 +80,33 @@ Effect.Transitions.full = function(pos) {
62
80
  Effect.Base = function() {};
63
81
  Effect.Base.prototype = {
64
82
  setOptions: function(options) {
65
- this.options = {
83
+ this.options = Object.extend({
66
84
  transition: Effect.Transitions.sinoidal,
67
85
  duration: 1.0, // seconds
68
86
  fps: 25.0, // max. 100fps
69
87
  sync: false, // true for combining
70
88
  from: 0.0,
71
89
  to: 1.0
72
- }.extend(options || {});
90
+ }, options || {});
73
91
  },
74
92
  start: function(options) {
75
93
  this.setOptions(options || {});
76
- this.currentFrame = 0;
77
- this.startOn = new Date().getTime();
78
- this.finishOn = this.startOn + (this.options.duration*1000);
94
+ this.currentFrame = 0;
95
+ this.startOn = new Date().getTime();
96
+ this.finishOn = this.startOn + (this.options.duration*1000);
79
97
  if(this.options.beforeStart) this.options.beforeStart(this);
80
98
  if(!this.options.sync) this.loop();
81
99
  },
82
100
  loop: function() {
83
- timePos = new Date().getTime();
101
+ var timePos = new Date().getTime();
84
102
  if(timePos >= this.finishOn) {
85
103
  this.render(this.options.to);
86
104
  if(this.finish) this.finish();
87
105
  if(this.options.afterFinish) this.options.afterFinish(this);
88
106
  return;
89
107
  }
90
- pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
91
- frame = Math.round(pos * this.options.fps * this.options.duration);
108
+ var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
109
+ var frame = Math.round(pos * this.options.fps * this.options.duration);
92
110
  if(frame > this.currentFrame) {
93
111
  this.render(pos);
94
112
  this.currentFrame = frame;
@@ -97,7 +115,7 @@ Effect.Base.prototype = {
97
115
  },
98
116
  render: function(pos) {
99
117
  if(this.options.transition) pos = this.options.transition(pos);
100
- pos = pos * (this.options.to-this.options.from);
118
+ pos *= (this.options.to-this.options.from);
101
119
  pos += this.options.from;
102
120
  if(this.options.beforeUpdate) this.options.beforeUpdate(this);
103
121
  if(this.update) this.update(pos);
@@ -109,32 +127,32 @@ Effect.Base.prototype = {
109
127
  }
110
128
 
111
129
  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
- });
130
+ Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
131
+ initialize: function(effects) {
132
+ this.effects = effects || [];
133
+ this.start(arguments[1]);
134
+ },
135
+ update: function(position) {
136
+ for (var i = 0; i < this.effects.length; i++)
137
+ this.effects[i].render(position);
138
+ },
139
+ finish: function(position) {
140
+ for (var i = 0; i < this.effects.length; i++)
141
+ if(this.effects[i].finish) this.effects[i].finish(position);
142
+ }
143
+ });
126
144
 
127
145
  // Internet Explorer caveat: works only on elements the have
128
146
  // a 'layout', meaning having a given width or height.
129
147
  // There is no way to safely set this automatically.
130
148
  Effect.Opacity = Class.create();
131
- Effect.Opacity.prototype = (new Effect.Base()).extend({
149
+ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
132
150
  initialize: function(element) {
133
151
  this.element = $(element);
134
- options = {
152
+ options = Object.extend({
135
153
  from: 0.0,
136
154
  to: 1.0
137
- }.extend(arguments[1] || {});
155
+ }, arguments[1] || {});
138
156
  this.start(options);
139
157
  },
140
158
  update: function(position) {
@@ -148,45 +166,44 @@ Effect.Opacity.prototype = (new Effect.Base()).extend({
148
166
  });
149
167
 
150
168
  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
- }
169
+ Object.extend(Object.extend(Effect.MoveBy.prototype, Effect.Base.prototype), {
170
+ initialize: function(element, toTop, toLeft) {
171
+ this.element = $(element);
172
+ this.originalTop = parseFloat(this.element.style.top || '0');
173
+ this.originalLeft = parseFloat(this.element.style.left || '0');
174
+ this.toTop = toTop;
175
+ this.toLeft = toLeft;
176
+ Element.makePositioned(this.element);
177
+ this.start(arguments[3]);
178
+ },
179
+ update: function(position) {
180
+ topd = this.toTop * position + this.originalTop;
181
+ leftd = this.toLeft * position + this.originalLeft;
182
+ this.setPosition(topd, leftd);
183
+ },
184
+ setPosition: function(topd, leftd) {
185
+ this.element.style.top = topd + "px";
186
+ this.element.style.left = leftd + "px";
187
+ }
171
188
  });
172
189
 
173
190
  Effect.Scale = Class.create();
174
- Effect.Scale.prototype = (new Effect.Base()).extend({
191
+ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
175
192
  initialize: function(element, percent) {
176
193
  this.element = $(element)
177
- options = {
194
+ options = Object.extend({
178
195
  scaleX: true,
179
196
  scaleY: true,
180
197
  scaleContent: true,
181
198
  scaleFromCenter: false,
182
199
  scaleMode: 'box', // 'box' or 'contents' or {} with provided values
183
200
  scaleFrom: 100.0
184
- }.extend(arguments[2] || {});
201
+ }, arguments[2] || {});
185
202
  this.originalTop = this.element.offsetTop;
186
203
  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);
204
+ if(this.element.style.fontSize=="") this.sizeEm = 1.0;
205
+ if(this.element.style.fontSize && this.element.style.fontSize.indexOf("em")>0)
206
+ this.sizeEm = parseFloat(this.element.style.fontSize);
190
207
  this.factor = (percent/100.0) - (options.scaleFrom/100.0);
191
208
  if(options.scaleMode=='box') {
192
209
  this.originalHeight = this.element.clientHeight;
@@ -207,8 +224,8 @@ Effect.Scale.prototype = (new Effect.Base()).extend({
207
224
  if(this.options.scaleContent && this.sizeEm)
208
225
  this.element.style.fontSize = this.sizeEm*currentScale + "em";
209
226
  this.setDimensions(
210
- this.originalWidth * currentScale,
211
- this.originalHeight * currentScale);
227
+ this.originalWidth * currentScale,
228
+ this.originalHeight * currentScale);
212
229
  },
213
230
 
214
231
  setDimensions: function(width, height) {
@@ -229,7 +246,7 @@ Effect.Scale.prototype = (new Effect.Base()).extend({
229
246
  });
230
247
 
231
248
  Effect.Highlight = Class.create();
232
- Effect.Highlight.prototype = (new Effect.Base()).extend({
249
+ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
233
250
  initialize: function(element) {
234
251
  this.element = $(element);
235
252
 
@@ -242,10 +259,11 @@ Effect.Highlight.prototype = (new Effect.Base()).extend({
242
259
  var cols = current.slice(4,current.length-1).split(',');
243
260
  var i=0; do { endcolor += parseInt(cols[i]).toColorPart() } while (++i<3); }
244
261
 
245
- var options = {
246
- startcolor: "#ffff99",
247
- endcolor: endcolor
248
- }.extend(arguments[1] || {});
262
+ var options = Object.extend({
263
+ startcolor: "#ffff99",
264
+ endcolor: endcolor,
265
+ restorecolor: current
266
+ }, arguments[1] || {});
249
267
 
250
268
  // init color calculations
251
269
  this.colors_base = [
@@ -266,25 +284,49 @@ Effect.Highlight.prototype = (new Effect.Base()).extend({
266
284
  Math.round(this.colors_base[2]+(this.colors_delta[2]*position)) ];
267
285
  this.element.style.backgroundColor = "#" +
268
286
  colors[0].toColorPart() + colors[1].toColorPart() + colors[2].toColorPart();
287
+ },
288
+ finish: function() {
289
+ this.element.style.backgroundColor = this.options.restorecolor;
269
290
  }
270
291
  });
271
292
 
293
+ Effect.ScrollTo = Class.create();
294
+ Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
295
+ initialize: function(element) {
296
+ this.element = $(element);
297
+ Position.prepare();
298
+ var offsets = Position.cumulativeOffset(this.element);
299
+ var max = window.innerHeight ?
300
+ window.height - window.innerHeight :
301
+ document.body.scrollHeight -
302
+ (document.documentElement.clientHeight ?
303
+ document.documentElement.clientHeight : document.body.clientHeight);
304
+ this.scrollStart = Position.deltaY;
305
+ this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
306
+ this.start(arguments[1] || {});
307
+ },
308
+ update: function(position) {
309
+ Position.prepare();
310
+ window.scrollTo(Position.deltaX,
311
+ this.scrollStart + (position*this.delta));
312
+ }
313
+ });
272
314
 
273
315
  /* ------------- prepackaged effects ------------- */
274
316
 
275
- Effect.Fade = function(element) {
276
- options = {
317
+ Effect.Fade = function(element) {
318
+ options = Object.extend({
277
319
  from: 1.0,
278
320
  to: 0.0,
279
321
  afterFinish: function(effect)
280
322
  { Element.hide(effect.element);
281
323
  effect.setOpacity(1); }
282
- }.extend(arguments[1] || {});
324
+ }, arguments[1] || {});
283
325
  new Effect.Opacity(element,options);
284
326
  }
285
327
 
286
- Effect.Appear = function(element) {
287
- options = {
328
+ Effect.Appear = function(element) {
329
+ options = Object.extend({
288
330
  from: 0.0,
289
331
  to: 1.0,
290
332
  beforeStart: function(effect)
@@ -292,7 +334,7 @@ Effect.Appear = function(element) {
292
334
  Element.show(effect.element); },
293
335
  afterUpdate: function(effect)
294
336
  { Element.show(effect.element); }
295
- }.extend(arguments[1] || {});
337
+ }, arguments[1] || {});
296
338
  new Effect.Opacity(element,options);
297
339
  }
298
340
 
@@ -310,34 +352,32 @@ Effect.Puff = function(element) {
310
352
  }
311
353
 
312
354
  Effect.BlindUp = function(element) {
313
- $(element)._overflow = $(element).style.overflow || 'visible';
314
- $(element).style.overflow = 'hidden';
355
+ Element.makeClipping(element);
315
356
  new Effect.Scale(element, 0,
316
- { scaleContent: false,
357
+ Object.extend({ scaleContent: false,
317
358
  scaleX: false,
318
359
  afterFinish: function(effect)
319
360
  {
320
361
  Element.hide(effect.element);
321
- effect.element.style.overflow = effect.element._overflow;
362
+ Element.undoClipping(effect.element);
322
363
  }
323
- }.extend(arguments[1] || {})
364
+ }, arguments[1] || {})
324
365
  );
325
366
  }
326
367
 
327
368
  Effect.BlindDown = function(element) {
328
369
  $(element).style.height = '0px';
329
- $(element)._overflow = $(element).style.overflow || 'visible';
330
- $(element).style.overflow = 'hidden';
370
+ Element.makeClipping(element);
331
371
  Element.show(element);
332
372
  new Effect.Scale(element, 100,
333
- { scaleContent: false,
373
+ Object.extend({ scaleContent: false,
334
374
  scaleX: false,
335
375
  scaleMode: 'contents',
336
376
  scaleFrom: 0,
337
377
  afterFinish: function(effect) {
338
- effect.element.style.overflow = effect.element._overflow;
378
+ Element.undoClipping(effect.element);
339
379
  }
340
- }.extend(arguments[1] || {})
380
+ }, arguments[1] || {})
341
381
  );
342
382
  }
343
383
 
@@ -346,7 +386,7 @@ Effect.SwitchOff = function(element) {
346
386
  { duration: 0.4,
347
387
  transition: Effect.Transitions.flicker,
348
388
  afterFinish: function(effect)
349
- { effect.element.style.overflow = 'hidden';
389
+ { effect.element.style.overflow = 'hidden';
350
390
  new Effect.Scale(effect.element, 1,
351
391
  { duration: 0.3, scaleFromCenter: true,
352
392
  scaleX: false, scaleContent: false,
@@ -356,7 +396,7 @@ Effect.SwitchOff = function(element) {
356
396
  afterFinish: function(effect) { Element.hide(effect.element); }
357
397
  } )
358
398
  }
359
- } )
399
+ } );
360
400
  }
361
401
 
362
402
  Effect.DropOut = function(element) {
@@ -386,13 +426,14 @@ Effect.Shake = function(element) {
386
426
  }
387
427
 
388
428
  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';
429
+ element = $(element);
430
+ element.style.height = '0px';
431
+ Element.makeClipping(element);
432
+ Element.cleanWhitespace(element);
433
+ Element.makePositioned(element.firstChild);
393
434
  Element.show(element);
394
435
  new Effect.Scale(element, 100,
395
- { scaleContent: false,
436
+ Object.extend({ scaleContent: false,
396
437
  scaleX: false,
397
438
  scaleMode: 'contents',
398
439
  scaleFrom: 0,
@@ -400,18 +441,19 @@ Effect.SlideDown = function(element) {
400
441
  { effect.element.firstChild.style.bottom =
401
442
  (effect.originalHeight - effect.element.clientHeight) + 'px'; },
402
443
  afterFinish: function(effect)
403
- { effect.element.style.overflow = effect.element._overflow; }
404
- }.extend(arguments[1] || {})
444
+ { Element.undoClipping(effect.element); }
445
+ }, arguments[1] || {})
405
446
  );
406
447
  }
407
448
 
408
449
  Effect.SlideUp = function(element) {
409
- $(element)._overflow = $(element).style.overflow || 'visible';
410
- $(element).style.overflow = 'hidden';
411
- $(element).firstChild.style.position = 'relative';
450
+ element = $(element);
451
+ Element.makeClipping(element);
452
+ Element.cleanWhitespace(element);
453
+ Element.makePositioned(element.firstChild);
412
454
  Element.show(element);
413
455
  new Effect.Scale(element, 0,
414
- { scaleContent: false,
456
+ Object.extend({ scaleContent: false,
415
457
  scaleX: false,
416
458
  afterUpdate: function(effect)
417
459
  { effect.element.firstChild.style.bottom =
@@ -419,9 +461,9 @@ Effect.SlideUp = function(element) {
419
461
  afterFinish: function(effect)
420
462
  {
421
463
  Element.hide(effect.element);
422
- effect.element.style.overflow = effect.element._overflow;
464
+ Element.undoClipping(effect.element);
423
465
  }
424
- }.extend(arguments[1] || {})
466
+ }, arguments[1] || {})
425
467
  );
426
468
  }
427
469
 
@@ -540,14 +582,14 @@ Effect.Pulsate = function(element) {
540
582
  var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
541
583
  reverser.bind(transition);
542
584
  new Effect.Opacity(element,
543
- { duration: 3.0,
585
+ Object.extend(Object.extend({ duration: 3.0,
544
586
  afterFinish: function(effect) { Element.show(effect.element); }
545
- }.extend(options).extend({transition: reverser}));
587
+ }, options), {transition: reverser}));
546
588
  }
547
589
 
548
590
  Effect.Fold = function(element) {
549
591
  $(element).style.overflow = 'hidden';
550
- new Effect.Scale(element, 5, {
592
+ new Effect.Scale(element, 5, Object.extend({
551
593
  scaleContent: false,
552
594
  scaleTo: 100,
553
595
  scaleX: false,
@@ -557,7 +599,7 @@ Effect.Fold = function(element) {
557
599
  scaleTo: 0,
558
600
  scaleY: false,
559
601
  afterFinish: function(effect) { Element.hide(effect.element) } });
560
- }}.extend(arguments[1] || {}));
602
+ }}, arguments[1] || {}));
561
603
  }
562
604
 
563
605
  // old: new Effect.ContentZoom(element, percent)
@@ -1,4 +1,4 @@
1
- /* Prototype JavaScript framework, version 1.3.0
1
+ /* Prototype JavaScript framework, version 1.3.1
2
2
  * (c) 2005 Sam Stephenson <sam@conio.net>
3
3
  *
4
4
  * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
@@ -11,7 +11,7 @@
11
11
  /*--------------------------------------------------------------------------*/
12
12
 
13
13
  var Prototype = {
14
- Version: '1.3.0',
14
+ Version: '1.3.1',
15
15
  emptyFunction: function() {}
16
16
  }
17
17
 
@@ -266,12 +266,16 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
266
266
  respondToReadyState: function(readyState) {
267
267
  var event = Ajax.Request.Events[readyState];
268
268
 
269
- if (event == 'Complete' && this.responseIsFailure())
269
+ if (event == 'Complete')
270
270
  (this.options['on' + this.transport.status]
271
- || this.options.onFailure
271
+ || this.options['on' + this.responseIsSuccess() ? 'Success' : 'Failure']
272
272
  || Prototype.emptyFunction)(this.transport);
273
273
 
274
- (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
274
+ (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
275
+
276
+ /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
277
+ if (event == 'Complete')
278
+ this.transport.onreadystatechange = Prototype.emptyFunction;
275
279
  }
276
280
  });
277
281
 
@@ -292,7 +296,7 @@ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
292
296
  var onComplete = this.options.onComplete || Prototype.emptyFunction;
293
297
  this.options.onComplete = (function() {
294
298
  this.updateContent();
295
- onComplete(this.transport);
299
+ onComplete(this.transport);
296
300
  }).bind(this);
297
301
 
298
302
  this.request(url);
@@ -889,53 +893,60 @@ Object.extend(Event, {
889
893
  return element;
890
894
  },
891
895
 
896
+ observers: false,
897
+
898
+ _observeAndCache: function(element, name, observer, useCapture) {
899
+ if (!this.observers) this.observers = [];
900
+ if (element.addEventListener) {
901
+ this.observers.push([element, name, observer, useCapture]);
902
+ element.addEventListener(name, observer, useCapture);
903
+ } else if (element.attachEvent) {
904
+ this.observers.push([element, name, observer, useCapture]);
905
+ element.attachEvent('on' + name, observer);
906
+ }
907
+ },
908
+
909
+ unloadCache: function() {
910
+ if (!Event.observers) return;
911
+ for (var i = 0; i < Event.observers.length; i++) {
912
+ Event.stopObserving.apply(this, Event.observers[i]);
913
+ Event.observers[i][0] = null;
914
+ }
915
+ Event.observers = false;
916
+ },
917
+
892
918
  observe: function(element, name, observer, useCapture) {
893
919
  var element = $(element);
894
920
  useCapture = useCapture || false;
895
921
 
896
- if (name == 'keypress') {
897
- if (navigator.appVersion.indexOf('AppleWebKit') > 0) {
898
- element.addEventListener('keydown', observer, useCapture);
899
- return;
900
- }
901
- if (element.addEventListener) {
902
- element.addEventListener('keypress', observer, useCapture);
903
- } else if (element.attachEvent) {
904
- element.attachEvent('onkeydown', observer);
905
- }
906
- } else {
907
- if (element.addEventListener) {
908
- element.addEventListener(name, observer, useCapture);
909
- } else if (element.attachEvent) {
910
- element.attachEvent('on' + name, observer);
911
- }
912
- }
922
+ if (name == 'keypress' &&
923
+ ((navigator.appVersion.indexOf('AppleWebKit') > 0)
924
+ || element.attachEvent))
925
+ name = 'keydown';
926
+
927
+ this._observeAndCache(element, name, observer, useCapture);
913
928
  },
914
929
 
915
930
  stopObserving: function(element, name, observer, useCapture) {
916
931
  var element = $(element);
917
932
  useCapture = useCapture || false;
918
933
 
919
- if (name == 'keypress') {
920
- if (navigator.appVersion.indexOf('AppleWebKit') > 0) {
921
- element.removeEventListener('keydown', observer, useCapture);
922
- return;
923
- }
924
- if (element.removeEventListener) {
925
- element.removeEventListener('keypress', observer, useCapture);
926
- } else if (element.detachEvent) {
927
- element.detachEvent('onkeydown', observer);
928
- }
929
- } else {
930
- if (element.removeEventListener) {
931
- element.removeEventListener(name, observer, useCapture);
932
- } else if (element.detachEvent) {
933
- element.detachEvent('on' + name, observer);
934
- }
934
+ if (name == 'keypress' &&
935
+ ((navigator.appVersion.indexOf('AppleWebKit') > 0)
936
+ || element.detachEvent))
937
+ name = 'keydown';
938
+
939
+ if (element.removeEventListener) {
940
+ element.removeEventListener(name, observer, useCapture);
941
+ } else if (element.detachEvent) {
942
+ element.detachEvent('on' + name, observer);
935
943
  }
936
944
  }
937
945
  });
938
946
 
947
+ /* prevent memory leaks in IE */
948
+ Event.observe(window, 'unload', Event.unloadCache, false);
949
+
939
950
  var Position = {
940
951
 
941
952
  // set to true if needed, warning: firefox performance problems