bivouac 0.1.4 → 0.1.5

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 (58) hide show
  1. data/README +6 -7
  2. data/bin/bivouac +1 -1
  3. data/doc/rdoc/classes/BivouacHelpers/BaseView.html +178 -0
  4. data/doc/rdoc/classes/BivouacHelpers/FormView.html +398 -0
  5. data/doc/rdoc/classes/BivouacHelpers/HtmlView.html +305 -0
  6. data/doc/rdoc/classes/BivouacHelpers/JavaScriptView.html +573 -0
  7. data/doc/rdoc/classes/BivouacHelpers/ScriptAculoUsView.html +258 -0
  8. data/doc/rdoc/classes/BivouacHelpers/TooltipView.html +158 -0
  9. data/doc/rdoc/classes/BivouacHelpers.html +117 -0
  10. data/doc/rdoc/classes/JavaScriptGenerator.html +564 -0
  11. data/doc/rdoc/created.rid +1 -0
  12. data/doc/rdoc/files/AUTHORS.html +109 -0
  13. data/doc/rdoc/files/COPYING.html +533 -0
  14. data/doc/rdoc/files/README.html +427 -0
  15. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/base_rb.html +109 -0
  16. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/form_rb.html +109 -0
  17. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/html_rb.html +109 -0
  18. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/javascript_rb.html +113 -0
  19. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/scriptaculous_rb.html +113 -0
  20. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/tooltip_rb.html +109 -0
  21. data/doc/rdoc/index.html +10 -0
  22. data/doc/rdoc/permalink.gif +0 -0
  23. data/doc/rdoc/rdoc-style.css +106 -0
  24. data/doc/rdoc/rubyfr.png +0 -0
  25. data/examples/bivouac_sample/Rakefile +48 -0
  26. data/examples/bivouac_sample/app/bivouac_sample.rb +15 -7
  27. data/examples/bivouac_sample/app/controllers/index.rb +2 -2
  28. data/examples/bivouac_sample/app/controllers/sound.rb +10 -0
  29. data/examples/bivouac_sample/app/helpers/_helpers.rb +6 -3
  30. data/examples/bivouac_sample/app/views/sound.rb +16 -0
  31. data/examples/bivouac_sample/config/environment.rb +5 -2
  32. data/examples/bivouac_sample/config/postamble.rb +89 -18
  33. data/examples/bivouac_sample/public/javascripts/builder.js +12 -7
  34. data/examples/bivouac_sample/public/javascripts/controls.js +485 -355
  35. data/examples/bivouac_sample/public/javascripts/dragdrop.js +82 -52
  36. data/examples/bivouac_sample/public/javascripts/effects.js +361 -329
  37. data/examples/bivouac_sample/public/javascripts/prototype.js +2826 -1120
  38. data/examples/bivouac_sample/public/javascripts/scriptaculous.js +15 -8
  39. data/examples/bivouac_sample/public/javascripts/slider.js +40 -43
  40. data/examples/bivouac_sample/public/javascripts/sound.js +55 -0
  41. data/examples/bivouac_sample/public/javascripts/unittest.js +16 -12
  42. data/examples/bivouac_sample/public/sound/sword.mp3 +0 -0
  43. data/examples/bivouac_sample/script/console +6 -0
  44. data/examples/bivouac_sample/script/plugin +3 -0
  45. data/examples/bivouac_sample/script/server +2 -1
  46. data/examples/bivouac_sample/test/test_sound.rb +15 -0
  47. data/lib/bivouac/helpers/view/goh/sound.rb +38 -0
  48. data/lib/bivouac/template/application/helpers_goh.rb +2 -0
  49. data/lib/bivouac/template/static/builder.js +12 -7
  50. data/lib/bivouac/template/static/controls.js +485 -355
  51. data/lib/bivouac/template/static/dragdrop.js +82 -52
  52. data/lib/bivouac/template/static/effects.js +361 -329
  53. data/lib/bivouac/template/static/prototype.js +2826 -1120
  54. data/lib/bivouac/template/static/scriptaculous.js +15 -8
  55. data/lib/bivouac/template/static/slider.js +40 -43
  56. data/lib/bivouac/template/static/sound.js +55 -0
  57. data/lib/bivouac/template/static/unittest.js +16 -12
  58. metadata +45 -2
@@ -1,6 +1,6 @@
1
- // script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
1
+ // script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
2
 
3
- // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
3
+ // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
4
  // Contributors:
5
5
  // Justin Palmer (http://encytemedia.com/)
6
6
  // Mark Pilgrim (http://diveintomark.org/)
@@ -13,17 +13,17 @@
13
13
  // returns self (or first argument) if not convertable
14
14
  String.prototype.parseColor = function() {
15
15
  var color = '#';
16
- if(this.slice(0,4) == 'rgb(') {
16
+ if (this.slice(0,4) == 'rgb(') {
17
17
  var cols = this.slice(4,this.length-1).split(',');
18
18
  var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
19
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();
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
23
  }
24
24
  }
25
- return(color.length==7 ? color : (arguments[0] || this));
26
- }
25
+ return (color.length==7 ? color : (arguments[0] || this));
26
+ };
27
27
 
28
28
  /*--------------------------------------------------------------------------*/
29
29
 
@@ -32,7 +32,7 @@ Element.collectTextNodes = function(element) {
32
32
  return (node.nodeType==3 ? node.nodeValue :
33
33
  (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
34
34
  }).flatten().join('');
35
- }
35
+ };
36
36
 
37
37
  Element.collectTextNodesIgnoreClass = function(element, className) {
38
38
  return $A($(element).childNodes).collect( function(node) {
@@ -40,26 +40,18 @@ Element.collectTextNodesIgnoreClass = function(element, className) {
40
40
  ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
41
41
  Element.collectTextNodesIgnoreClass(node, className) : ''));
42
42
  }).flatten().join('');
43
- }
43
+ };
44
44
 
45
45
  Element.setContentZoom = function(element, percent) {
46
46
  element = $(element);
47
47
  element.setStyle({fontSize: (percent/100) + 'em'});
48
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
48
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
49
49
  return element;
50
- }
51
-
52
- Element.getOpacity = function(element){
53
- return $(element).getStyle('opacity');
54
- }
55
-
56
- Element.setOpacity = function(element, value){
57
- return $(element).setStyle({opacity:value});
58
- }
50
+ };
59
51
 
60
52
  Element.getInlineOpacity = function(element){
61
53
  return $(element).style.opacity || '';
62
- }
54
+ };
63
55
 
64
56
  Element.forceRerendering = function(element) {
65
57
  try {
@@ -72,31 +64,63 @@ Element.forceRerendering = function(element) {
72
64
 
73
65
  /*--------------------------------------------------------------------------*/
74
66
 
75
- Array.prototype.call = function() {
76
- var args = arguments;
77
- this.each(function(f){ f.apply(this, args) });
78
- }
79
-
80
- /*--------------------------------------------------------------------------*/
81
-
82
67
  var Effect = {
83
68
  _elementDoesNotExistError: {
84
69
  name: 'ElementDoesNotExistError',
85
70
  message: 'The specified DOM element does not exist, but is required for this effect to operate'
86
71
  },
72
+ Transitions: {
73
+ linear: Prototype.K,
74
+ sinoidal: function(pos) {
75
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
76
+ },
77
+ reverse: function(pos) {
78
+ return 1-pos;
79
+ },
80
+ flicker: function(pos) {
81
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
82
+ return pos > 1 ? 1 : pos;
83
+ },
84
+ wobble: function(pos) {
85
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
86
+ },
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
+ );
94
+ },
95
+ spring: function(pos) {
96
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
97
+ },
98
+ none: function(pos) {
99
+ return 0;
100
+ },
101
+ full: function(pos) {
102
+ return 1;
103
+ }
104
+ },
105
+ DefaultOptions: {
106
+ duration: 1.0, // seconds
107
+ fps: 100, // 100= assume 66fps max.
108
+ sync: false, // true for combining
109
+ from: 0.0,
110
+ to: 1.0,
111
+ delay: 0.0,
112
+ queue: 'parallel'
113
+ },
87
114
  tagifyText: function(element) {
88
- if(typeof Builder == 'undefined')
89
- throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
90
-
91
115
  var tagifyStyle = 'position:relative';
92
- if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
116
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
93
117
 
94
118
  element = $(element);
95
119
  $A(element.childNodes).each( function(child) {
96
- if(child.nodeType==3) {
120
+ if (child.nodeType==3) {
97
121
  child.nodeValue.toArray().each( function(character) {
98
122
  element.insertBefore(
99
- Builder.node('span',{style: tagifyStyle},
123
+ new Element('span', {style: tagifyStyle}).update(
100
124
  character == ' ' ? String.fromCharCode(160) : character),
101
125
  child);
102
126
  });
@@ -106,8 +130,8 @@ var Effect = {
106
130
  },
107
131
  multiple: function(element, effect) {
108
132
  var elements;
109
- if(((typeof element == 'object') ||
110
- (typeof element == 'function')) &&
133
+ if (((typeof element == 'object') ||
134
+ Object.isFunction(element)) &&
111
135
  (element.length))
112
136
  elements = element;
113
137
  else
@@ -116,7 +140,7 @@ var Effect = {
116
140
  var options = Object.extend({
117
141
  speed: 0.1,
118
142
  delay: 0.0
119
- }, arguments[2] || {});
143
+ }, arguments[2] || { });
120
144
  var masterDelay = options.delay;
121
145
 
122
146
  $A(elements).each( function(element, index) {
@@ -133,53 +157,20 @@ var Effect = {
133
157
  effect = (effect || 'appear').toLowerCase();
134
158
  var options = Object.extend({
135
159
  queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
136
- }, arguments[2] || {});
160
+ }, arguments[2] || { });
137
161
  Effect[element.visible() ?
138
162
  Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
139
163
  }
140
164
  };
141
165
 
142
- var Effect2 = Effect; // deprecated
143
-
144
- /* ------------- transitions ------------- */
145
-
146
- Effect.Transitions = {
147
- linear: Prototype.K,
148
- sinoidal: function(pos) {
149
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
150
- },
151
- reverse: function(pos) {
152
- return 1-pos;
153
- },
154
- flicker: function(pos) {
155
- return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
156
- },
157
- wobble: function(pos) {
158
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
159
- },
160
- pulse: function(pos, pulses) {
161
- pulses = pulses || 5;
162
- return (
163
- Math.round((pos % (1/pulses)) * pulses) == 0 ?
164
- ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
165
- 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
166
- );
167
- },
168
- none: function(pos) {
169
- return 0;
170
- },
171
- full: function(pos) {
172
- return 1;
173
- }
174
- };
166
+ Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
175
167
 
176
168
  /* ------------- core effects ------------- */
177
169
 
178
- Effect.ScopedQueue = Class.create();
179
- Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
170
+ Effect.ScopedQueue = Class.create(Enumerable, {
180
171
  initialize: function() {
181
172
  this.effects = [];
182
- this.interval = null;
173
+ this.interval = null;
183
174
  },
184
175
  _each: function(iterator) {
185
176
  this.effects._each(iterator);
@@ -187,7 +178,7 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
187
178
  add: function(effect) {
188
179
  var timestamp = new Date().getTime();
189
180
 
190
- var position = (typeof effect.options.queue == 'string') ?
181
+ var position = Object.isString(effect.options.queue) ?
191
182
  effect.options.queue : effect.options.queue.position;
192
183
 
193
184
  switch(position) {
@@ -210,15 +201,15 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
210
201
  effect.startOn += timestamp;
211
202
  effect.finishOn += timestamp;
212
203
 
213
- if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
204
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
214
205
  this.effects.push(effect);
215
206
 
216
- if(!this.interval)
207
+ if (!this.interval)
217
208
  this.interval = setInterval(this.loop.bind(this), 15);
218
209
  },
219
210
  remove: function(effect) {
220
211
  this.effects = this.effects.reject(function(e) { return e==effect });
221
- if(this.effects.length == 0) {
212
+ if (this.effects.length == 0) {
222
213
  clearInterval(this.interval);
223
214
  this.interval = null;
224
215
  }
@@ -226,103 +217,95 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
226
217
  loop: function() {
227
218
  var timePos = new Date().getTime();
228
219
  for(var i=0, len=this.effects.length;i<len;i++)
229
- if(this.effects[i]) this.effects[i].loop(timePos);
220
+ this.effects[i] && this.effects[i].loop(timePos);
230
221
  }
231
222
  });
232
223
 
233
224
  Effect.Queues = {
234
225
  instances: $H(),
235
226
  get: function(queueName) {
236
- if(typeof queueName != 'string') return queueName;
227
+ if (!Object.isString(queueName)) return queueName;
237
228
 
238
- if(!this.instances[queueName])
239
- this.instances[queueName] = new Effect.ScopedQueue();
240
-
241
- return this.instances[queueName];
229
+ return this.instances.get(queueName) ||
230
+ this.instances.set(queueName, new Effect.ScopedQueue());
242
231
  }
243
- }
232
+ };
244
233
  Effect.Queue = Effect.Queues.get('global');
245
234
 
246
- Effect.DefaultOptions = {
247
- transition: Effect.Transitions.sinoidal,
248
- duration: 1.0, // seconds
249
- fps: 60.0, // max. 60fps due to Effect.Queue implementation
250
- sync: false, // true for combining
251
- from: 0.0,
252
- to: 1.0,
253
- delay: 0.0,
254
- queue: 'parallel'
255
- }
256
-
257
- Effect.Base = function() {};
258
- Effect.Base.prototype = {
235
+ Effect.Base = Class.create({
259
236
  position: null,
260
237
  start: function(options) {
261
- this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
238
+ function codeForEvent(options,eventName){
239
+ return (
240
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
241
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
242
+ );
243
+ }
244
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
245
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
262
246
  this.currentFrame = 0;
263
247
  this.state = 'idle';
264
248
  this.startOn = this.options.delay*1000;
265
- this.finishOn = this.startOn + (this.options.duration*1000);
249
+ this.finishOn = this.startOn+(this.options.duration*1000);
250
+ this.fromToDelta = this.options.to-this.options.from;
251
+ this.totalTime = this.finishOn-this.startOn;
252
+ 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
+
266
267
  this.event('beforeStart');
267
- if(!this.options.sync)
268
- Effect.Queues.get(typeof this.options.queue == 'string' ?
268
+ if (!this.options.sync)
269
+ Effect.Queues.get(Object.isString(this.options.queue) ?
269
270
  'global' : this.options.queue.scope).add(this);
270
271
  },
271
272
  loop: function(timePos) {
272
- if(timePos >= this.startOn) {
273
- if(timePos >= this.finishOn) {
273
+ if (timePos >= this.startOn) {
274
+ if (timePos >= this.finishOn) {
274
275
  this.render(1.0);
275
276
  this.cancel();
276
277
  this.event('beforeFinish');
277
- if(this.finish) this.finish();
278
+ if (this.finish) this.finish();
278
279
  this.event('afterFinish');
279
280
  return;
280
281
  }
281
- var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
282
- var frame = Math.round(pos * this.options.fps * this.options.duration);
283
- if(frame > this.currentFrame) {
282
+ var pos = (timePos - this.startOn) / this.totalTime,
283
+ frame = (pos * this.totalFrames).round();
284
+ if (frame > this.currentFrame) {
284
285
  this.render(pos);
285
286
  this.currentFrame = frame;
286
287
  }
287
288
  }
288
289
  },
289
- render: function(pos) {
290
- if(this.state == 'idle') {
291
- this.state = 'running';
292
- this.event('beforeSetup');
293
- if(this.setup) this.setup();
294
- this.event('afterSetup');
295
- }
296
- if(this.state == 'running') {
297
- if(this.options.transition) pos = this.options.transition(pos);
298
- pos *= (this.options.to-this.options.from);
299
- pos += this.options.from;
300
- this.position = pos;
301
- this.event('beforeUpdate');
302
- if(this.update) this.update(pos);
303
- this.event('afterUpdate');
304
- }
305
- },
306
290
  cancel: function() {
307
- if(!this.options.sync)
308
- Effect.Queues.get(typeof this.options.queue == 'string' ?
291
+ if (!this.options.sync)
292
+ Effect.Queues.get(Object.isString(this.options.queue) ?
309
293
  'global' : this.options.queue.scope).remove(this);
310
294
  this.state = 'finished';
311
295
  },
312
296
  event: function(eventName) {
313
- if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
314
- if(this.options[eventName]) this.options[eventName](this);
297
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
298
+ if (this.options[eventName]) this.options[eventName](this);
315
299
  },
316
300
  inspect: function() {
317
301
  var data = $H();
318
302
  for(property in this)
319
- if(typeof this[property] != 'function') data[property] = this[property];
303
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
320
304
  return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
321
305
  }
322
- }
306
+ });
323
307
 
324
- Effect.Parallel = Class.create();
325
- Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
308
+ Effect.Parallel = Class.create(Effect.Base, {
326
309
  initialize: function(effects) {
327
310
  this.effects = effects || [];
328
311
  this.start(arguments[1]);
@@ -335,35 +318,45 @@ Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
335
318
  effect.render(1.0);
336
319
  effect.cancel();
337
320
  effect.event('beforeFinish');
338
- if(effect.finish) effect.finish(position);
321
+ if (effect.finish) effect.finish(position);
339
322
  effect.event('afterFinish');
340
323
  });
341
324
  }
342
325
  });
343
326
 
344
- Effect.Event = Class.create();
345
- Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
327
+ Effect.Tween = Class.create(Effect.Base, {
328
+ initialize: function(object, from, to) {
329
+ object = Object.isString(object) ? $(object) : object;
330
+ var args = $A(arguments), method = args.last(),
331
+ options = args.length == 5 ? args[3] : null;
332
+ this.method = Object.isFunction(method) ? method.bind(object) :
333
+ Object.isFunction(object[method]) ? object[method].bind(object) :
334
+ function(value) { object[method] = value };
335
+ this.start(Object.extend({ from: from, to: to }, options || { }));
336
+ },
337
+ update: function(position) {
338
+ this.method(position);
339
+ }
340
+ });
341
+
342
+ Effect.Event = Class.create(Effect.Base, {
346
343
  initialize: function() {
347
- var options = Object.extend({
348
- duration: 0
349
- }, arguments[0] || {});
350
- this.start(options);
344
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
351
345
  },
352
346
  update: Prototype.emptyFunction
353
347
  });
354
348
 
355
- Effect.Opacity = Class.create();
356
- Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
349
+ Effect.Opacity = Class.create(Effect.Base, {
357
350
  initialize: function(element) {
358
351
  this.element = $(element);
359
- if(!this.element) throw(Effect._elementDoesNotExistError);
352
+ if (!this.element) throw(Effect._elementDoesNotExistError);
360
353
  // make this work on IE on elements without 'layout'
361
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
354
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
362
355
  this.element.setStyle({zoom: 1});
363
356
  var options = Object.extend({
364
357
  from: this.element.getOpacity() || 0.0,
365
358
  to: 1.0
366
- }, arguments[1] || {});
359
+ }, arguments[1] || { });
367
360
  this.start(options);
368
361
  },
369
362
  update: function(position) {
@@ -371,36 +364,30 @@ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
371
364
  }
372
365
  });
373
366
 
374
- Effect.Move = Class.create();
375
- Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
367
+ Effect.Move = Class.create(Effect.Base, {
376
368
  initialize: function(element) {
377
369
  this.element = $(element);
378
- if(!this.element) throw(Effect._elementDoesNotExistError);
370
+ if (!this.element) throw(Effect._elementDoesNotExistError);
379
371
  var options = Object.extend({
380
372
  x: 0,
381
373
  y: 0,
382
374
  mode: 'relative'
383
- }, arguments[1] || {});
375
+ }, arguments[1] || { });
384
376
  this.start(options);
385
377
  },
386
378
  setup: function() {
387
- // Bug in Opera: Opera returns the "real" position of a static element or
388
- // relative element that does not have top/left explicitly set.
389
- // ==> Always set top and left for position relative elements in your stylesheets
390
- // (to 0 if you do not need them)
391
379
  this.element.makePositioned();
392
380
  this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
393
381
  this.originalTop = parseFloat(this.element.getStyle('top') || '0');
394
- if(this.options.mode == 'absolute') {
395
- // absolute movement, so we need to calc deltaX and deltaY
382
+ if (this.options.mode == 'absolute') {
396
383
  this.options.x = this.options.x - this.originalLeft;
397
384
  this.options.y = this.options.y - this.originalTop;
398
385
  }
399
386
  },
400
387
  update: function(position) {
401
388
  this.element.setStyle({
402
- left: Math.round(this.options.x * position + this.originalLeft) + 'px',
403
- top: Math.round(this.options.y * position + this.originalTop) + 'px'
389
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
390
+ top: (this.options.y * position + this.originalTop).round() + 'px'
404
391
  });
405
392
  }
406
393
  });
@@ -408,30 +395,29 @@ Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
408
395
  // for backwards compatibility
409
396
  Effect.MoveBy = function(element, toTop, toLeft) {
410
397
  return new Effect.Move(element,
411
- Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
398
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
412
399
  };
413
400
 
414
- Effect.Scale = Class.create();
415
- Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
401
+ Effect.Scale = Class.create(Effect.Base, {
416
402
  initialize: function(element, percent) {
417
403
  this.element = $(element);
418
- if(!this.element) throw(Effect._elementDoesNotExistError);
404
+ if (!this.element) throw(Effect._elementDoesNotExistError);
419
405
  var options = Object.extend({
420
406
  scaleX: true,
421
407
  scaleY: true,
422
408
  scaleContent: true,
423
409
  scaleFromCenter: false,
424
- scaleMode: 'box', // 'box' or 'contents' or {} with provided values
410
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
425
411
  scaleFrom: 100.0,
426
412
  scaleTo: percent
427
- }, arguments[2] || {});
413
+ }, arguments[2] || { });
428
414
  this.start(options);
429
415
  },
430
416
  setup: function() {
431
417
  this.restoreAfterFinish = this.options.restoreAfterFinish || false;
432
418
  this.elementPositioning = this.element.getStyle('position');
433
419
 
434
- this.originalStyle = {};
420
+ this.originalStyle = { };
435
421
  ['top','left','width','height','fontSize'].each( function(k) {
436
422
  this.originalStyle[k] = this.element.style[k];
437
423
  }.bind(this));
@@ -441,7 +427,7 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
441
427
 
442
428
  var fontSize = this.element.getStyle('font-size') || '100%';
443
429
  ['em','px','%','pt'].each( function(fontSizeType) {
444
- if(fontSize.indexOf(fontSizeType)>0) {
430
+ if (fontSize.indexOf(fontSizeType)>0) {
445
431
  this.fontSize = parseFloat(fontSize);
446
432
  this.fontSizeType = fontSizeType;
447
433
  }
@@ -450,62 +436,61 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
450
436
  this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
451
437
 
452
438
  this.dims = null;
453
- if(this.options.scaleMode=='box')
439
+ if (this.options.scaleMode=='box')
454
440
  this.dims = [this.element.offsetHeight, this.element.offsetWidth];
455
- if(/^content/.test(this.options.scaleMode))
441
+ if (/^content/.test(this.options.scaleMode))
456
442
  this.dims = [this.element.scrollHeight, this.element.scrollWidth];
457
- if(!this.dims)
443
+ if (!this.dims)
458
444
  this.dims = [this.options.scaleMode.originalHeight,
459
445
  this.options.scaleMode.originalWidth];
460
446
  },
461
447
  update: function(position) {
462
448
  var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
463
- if(this.options.scaleContent && this.fontSize)
449
+ if (this.options.scaleContent && this.fontSize)
464
450
  this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
465
451
  this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
466
452
  },
467
453
  finish: function(position) {
468
- if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
454
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
469
455
  },
470
456
  setDimensions: function(height, width) {
471
- var d = {};
472
- if(this.options.scaleX) d.width = Math.round(width) + 'px';
473
- if(this.options.scaleY) d.height = Math.round(height) + 'px';
474
- if(this.options.scaleFromCenter) {
457
+ var d = { };
458
+ if (this.options.scaleX) d.width = width.round() + 'px';
459
+ if (this.options.scaleY) d.height = height.round() + 'px';
460
+ if (this.options.scaleFromCenter) {
475
461
  var topd = (height - this.dims[0])/2;
476
462
  var leftd = (width - this.dims[1])/2;
477
- if(this.elementPositioning == 'absolute') {
478
- if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
479
- if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
463
+ if (this.elementPositioning == 'absolute') {
464
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
465
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
480
466
  } else {
481
- if(this.options.scaleY) d.top = -topd + 'px';
482
- if(this.options.scaleX) d.left = -leftd + 'px';
467
+ if (this.options.scaleY) d.top = -topd + 'px';
468
+ if (this.options.scaleX) d.left = -leftd + 'px';
483
469
  }
484
470
  }
485
471
  this.element.setStyle(d);
486
472
  }
487
473
  });
488
474
 
489
- Effect.Highlight = Class.create();
490
- Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
475
+ Effect.Highlight = Class.create(Effect.Base, {
491
476
  initialize: function(element) {
492
477
  this.element = $(element);
493
- if(!this.element) throw(Effect._elementDoesNotExistError);
494
- var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
478
+ if (!this.element) throw(Effect._elementDoesNotExistError);
479
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
495
480
  this.start(options);
496
481
  },
497
482
  setup: function() {
498
483
  // Prevent executing on elements not in the layout flow
499
- if(this.element.getStyle('display')=='none') { this.cancel(); return; }
484
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
500
485
  // Disable background image during the effect
501
- this.oldStyle = {};
486
+ this.oldStyle = { };
502
487
  if (!this.options.keepBackgroundImage) {
503
488
  this.oldStyle.backgroundImage = this.element.getStyle('background-image');
504
489
  this.element.setStyle({backgroundImage: 'none'});
505
490
  }
506
- if(!this.options.endcolor)
491
+ if (!this.options.endcolor)
507
492
  this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
508
- if(!this.options.restorecolor)
493
+ if (!this.options.restorecolor)
509
494
  this.options.restorecolor = this.element.getStyle('background-color');
510
495
  // init color calculations
511
496
  this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
@@ -513,7 +498,7 @@ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype),
513
498
  },
514
499
  update: function(position) {
515
500
  this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
516
- return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
501
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
517
502
  },
518
503
  finish: function() {
519
504
  this.element.setStyle(Object.extend(this.oldStyle, {
@@ -522,30 +507,21 @@ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype),
522
507
  }
523
508
  });
524
509
 
525
- Effect.ScrollTo = Class.create();
526
- Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
527
- initialize: function(element) {
528
- this.element = $(element);
529
- this.start(arguments[1] || {});
530
- },
531
- setup: function() {
532
- Position.prepare();
533
- var offsets = Position.cumulativeOffset(this.element);
534
- if(this.options.offset) offsets[1] += this.options.offset;
535
- var max = window.innerHeight ?
536
- window.height - window.innerHeight :
537
- document.body.scrollHeight -
538
- (document.documentElement.clientHeight ?
539
- document.documentElement.clientHeight : document.body.clientHeight);
540
- this.scrollStart = Position.deltaY;
541
- this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
542
- },
543
- update: function(position) {
544
- Position.prepare();
545
- window.scrollTo(Position.deltaX,
546
- this.scrollStart + (position*this.delta));
547
- }
548
- });
510
+ Effect.ScrollTo = function(element) {
511
+ var options = arguments[1] || { },
512
+ scrollOffsets = document.viewport.getScrollOffsets(),
513
+ elementOffsets = $(element).cumulativeOffset(),
514
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
515
+
516
+ if (options.offset) elementOffsets[1] += options.offset;
517
+
518
+ return new Effect.Tween(null,
519
+ scrollOffsets.top,
520
+ elementOffsets[1] > max ? max : elementOffsets[1],
521
+ options,
522
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
523
+ );
524
+ };
549
525
 
550
526
  /* ------------- combination effects ------------- */
551
527
 
@@ -553,14 +529,15 @@ Effect.Fade = function(element) {
553
529
  element = $(element);
554
530
  var oldOpacity = element.getInlineOpacity();
555
531
  var options = Object.extend({
556
- from: element.getOpacity() || 1.0,
557
- to: 0.0,
558
- afterFinishInternal: function(effect) {
559
- if(effect.options.to!=0) return;
560
- effect.element.hide().setStyle({opacity: oldOpacity});
561
- }}, arguments[1] || {});
532
+ from: element.getOpacity() || 1.0,
533
+ to: 0.0,
534
+ afterFinishInternal: function(effect) {
535
+ if (effect.options.to!=0) return;
536
+ effect.element.hide().setStyle({opacity: oldOpacity});
537
+ }
538
+ }, arguments[1] || { });
562
539
  return new Effect.Opacity(element,options);
563
- }
540
+ };
564
541
 
565
542
  Effect.Appear = function(element) {
566
543
  element = $(element);
@@ -573,9 +550,9 @@ Effect.Appear = function(element) {
573
550
  },
574
551
  beforeSetup: function(effect) {
575
552
  effect.element.setOpacity(effect.options.from).show();
576
- }}, arguments[1] || {});
553
+ }}, arguments[1] || { });
577
554
  return new Effect.Opacity(element,options);
578
- }
555
+ };
579
556
 
580
557
  Effect.Puff = function(element) {
581
558
  element = $(element);
@@ -597,9 +574,9 @@ Effect.Puff = function(element) {
597
574
  },
598
575
  afterFinishInternal: function(effect) {
599
576
  effect.effects[0].element.hide().setStyle(oldStyle); }
600
- }, arguments[1] || {})
577
+ }, arguments[1] || { })
601
578
  );
602
- }
579
+ };
603
580
 
604
581
  Effect.BlindUp = function(element) {
605
582
  element = $(element);
@@ -611,9 +588,9 @@ Effect.BlindUp = function(element) {
611
588
  afterFinishInternal: function(effect) {
612
589
  effect.element.hide().undoClipping();
613
590
  }
614
- }, arguments[1] || {})
591
+ }, arguments[1] || { })
615
592
  );
616
- }
593
+ };
617
594
 
618
595
  Effect.BlindDown = function(element) {
619
596
  element = $(element);
@@ -630,8 +607,8 @@ Effect.BlindDown = function(element) {
630
607
  afterFinishInternal: function(effect) {
631
608
  effect.element.undoClipping();
632
609
  }
633
- }, arguments[1] || {}));
634
- }
610
+ }, arguments[1] || { }));
611
+ };
635
612
 
636
613
  Effect.SwitchOff = function(element) {
637
614
  element = $(element);
@@ -652,8 +629,8 @@ Effect.SwitchOff = function(element) {
652
629
  }
653
630
  })
654
631
  }
655
- }, arguments[1] || {}));
656
- }
632
+ }, arguments[1] || { }));
633
+ };
657
634
 
658
635
  Effect.DropOut = function(element) {
659
636
  element = $(element);
@@ -672,29 +649,35 @@ Effect.DropOut = function(element) {
672
649
  afterFinishInternal: function(effect) {
673
650
  effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
674
651
  }
675
- }, arguments[1] || {}));
676
- }
652
+ }, arguments[1] || { }));
653
+ };
677
654
 
678
655
  Effect.Shake = function(element) {
679
656
  element = $(element);
657
+ var options = Object.extend({
658
+ distance: 20,
659
+ duration: 0.5
660
+ }, arguments[1] || {});
661
+ var distance = parseFloat(options.distance);
662
+ var split = parseFloat(options.duration) / 10.0;
680
663
  var oldStyle = {
681
664
  top: element.getStyle('top'),
682
665
  left: element.getStyle('left') };
683
- return new Effect.Move(element,
684
- { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
666
+ return new Effect.Move(element,
667
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
685
668
  new Effect.Move(effect.element,
686
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
669
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
687
670
  new Effect.Move(effect.element,
688
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
671
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
689
672
  new Effect.Move(effect.element,
690
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
673
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
691
674
  new Effect.Move(effect.element,
692
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
675
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
693
676
  new Effect.Move(effect.element,
694
- { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
677
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
695
678
  effect.element.undoPositioned().setStyle(oldStyle);
696
679
  }}) }}) }}) }}) }}) }});
697
- }
680
+ };
698
681
 
699
682
  Effect.SlideDown = function(element) {
700
683
  element = $(element).cleanWhitespace();
@@ -710,7 +693,7 @@ Effect.SlideDown = function(element) {
710
693
  afterSetup: function(effect) {
711
694
  effect.element.makePositioned();
712
695
  effect.element.down().makePositioned();
713
- if(window.opera) effect.element.setStyle({top: ''});
696
+ if (window.opera) effect.element.setStyle({top: ''});
714
697
  effect.element.makeClipping().setStyle({height: '0px'}).show();
715
698
  },
716
699
  afterUpdateInternal: function(effect) {
@@ -720,23 +703,25 @@ Effect.SlideDown = function(element) {
720
703
  afterFinishInternal: function(effect) {
721
704
  effect.element.undoClipping().undoPositioned();
722
705
  effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
723
- }, arguments[1] || {})
706
+ }, arguments[1] || { })
724
707
  );
725
- }
708
+ };
726
709
 
727
710
  Effect.SlideUp = function(element) {
728
711
  element = $(element).cleanWhitespace();
729
712
  var oldInnerBottom = element.down().getStyle('bottom');
713
+ var elementDimensions = element.getDimensions();
730
714
  return new Effect.Scale(element, window.opera ? 0 : 1,
731
715
  Object.extend({ scaleContent: false,
732
716
  scaleX: false,
733
717
  scaleMode: 'box',
734
718
  scaleFrom: 100,
719
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
735
720
  restoreAfterFinish: true,
736
- beforeStartInternal: function(effect) {
721
+ afterSetup: function(effect) {
737
722
  effect.element.makePositioned();
738
723
  effect.element.down().makePositioned();
739
- if(window.opera) effect.element.setStyle({top: ''});
724
+ if (window.opera) effect.element.setStyle({top: ''});
740
725
  effect.element.makeClipping().show();
741
726
  },
742
727
  afterUpdateInternal: function(effect) {
@@ -744,12 +729,12 @@ Effect.SlideUp = function(element) {
744
729
  (effect.dims[0] - effect.element.clientHeight) + 'px' });
745
730
  },
746
731
  afterFinishInternal: function(effect) {
747
- effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
748
- effect.element.down().undoPositioned();
732
+ effect.element.hide().undoClipping().undoPositioned();
733
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
749
734
  }
750
- }, arguments[1] || {})
735
+ }, arguments[1] || { })
751
736
  );
752
- }
737
+ };
753
738
 
754
739
  // Bug in opera makes the TD containing this element expand for a instance after finish
755
740
  Effect.Squish = function(element) {
@@ -762,7 +747,7 @@ Effect.Squish = function(element) {
762
747
  effect.element.hide().undoClipping();
763
748
  }
764
749
  });
765
- }
750
+ };
766
751
 
767
752
  Effect.Grow = function(element) {
768
753
  element = $(element);
@@ -771,7 +756,7 @@ Effect.Grow = function(element) {
771
756
  moveTransition: Effect.Transitions.sinoidal,
772
757
  scaleTransition: Effect.Transitions.sinoidal,
773
758
  opacityTransition: Effect.Transitions.full
774
- }, arguments[1] || {});
759
+ }, arguments[1] || { });
775
760
  var oldStyle = {
776
761
  top: element.style.top,
777
762
  left: element.style.left,
@@ -836,7 +821,7 @@ Effect.Grow = function(element) {
836
821
  )
837
822
  }
838
823
  });
839
- }
824
+ };
840
825
 
841
826
  Effect.Shrink = function(element) {
842
827
  element = $(element);
@@ -845,7 +830,7 @@ Effect.Shrink = function(element) {
845
830
  moveTransition: Effect.Transitions.sinoidal,
846
831
  scaleTransition: Effect.Transitions.sinoidal,
847
832
  opacityTransition: Effect.Transitions.none
848
- }, arguments[1] || {});
833
+ }, arguments[1] || { });
849
834
  var oldStyle = {
850
835
  top: element.style.top,
851
836
  left: element.style.left,
@@ -890,11 +875,11 @@ Effect.Shrink = function(element) {
890
875
  effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
891
876
  }, options)
892
877
  );
893
- }
878
+ };
894
879
 
895
880
  Effect.Pulsate = function(element) {
896
881
  element = $(element);
897
- var options = arguments[1] || {};
882
+ var options = arguments[1] || { };
898
883
  var oldOpacity = element.getInlineOpacity();
899
884
  var transition = options.transition || Effect.Transitions.sinoidal;
900
885
  var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
@@ -903,7 +888,7 @@ Effect.Pulsate = function(element) {
903
888
  Object.extend(Object.extend({ duration: 2.0, from: 0,
904
889
  afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
905
890
  }, options), {transition: reverser}));
906
- }
891
+ };
907
892
 
908
893
  Effect.Fold = function(element) {
909
894
  element = $(element);
@@ -923,72 +908,71 @@ Effect.Fold = function(element) {
923
908
  afterFinishInternal: function(effect) {
924
909
  effect.element.hide().undoClipping().setStyle(oldStyle);
925
910
  } });
926
- }}, arguments[1] || {}));
911
+ }}, arguments[1] || { }));
927
912
  };
928
913
 
929
- Effect.Morph = Class.create();
930
- Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
914
+ Effect.Morph = Class.create(Effect.Base, {
931
915
  initialize: function(element) {
932
916
  this.element = $(element);
933
- if(!this.element) throw(Effect._elementDoesNotExistError);
917
+ if (!this.element) throw(Effect._elementDoesNotExistError);
934
918
  var options = Object.extend({
935
- style: {}
936
- }, arguments[1] || {});
937
- if (typeof options.style == 'string') {
938
- if(options.style.indexOf(':') == -1) {
939
- var cssText = '', selector = '.' + options.style;
940
- $A(document.styleSheets).reverse().each(function(styleSheet) {
941
- if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
942
- else if (styleSheet.rules) cssRules = styleSheet.rules;
943
- $A(cssRules).reverse().each(function(rule) {
944
- if (selector == rule.selectorText) {
945
- cssText = rule.style.cssText;
946
- throw $break;
947
- }
948
- });
949
- if (cssText) throw $break;
919
+ style: { }
920
+ }, arguments[1] || { });
921
+
922
+ if (!Object.isString(options.style)) this.style = $H(options.style);
923
+ else {
924
+ if (options.style.include(':'))
925
+ this.style = options.style.parseStyle();
926
+ else {
927
+ this.element.addClassName(options.style);
928
+ this.style = $H(this.element.getStyles());
929
+ this.element.removeClassName(options.style);
930
+ var css = this.element.getStyles();
931
+ this.style = this.style.reject(function(style) {
932
+ return style.value == css[style.key];
950
933
  });
951
- this.style = cssText.parseStyle();
952
- options.afterFinishInternal = function(effect){
934
+ options.afterFinishInternal = function(effect) {
953
935
  effect.element.addClassName(effect.options.style);
954
936
  effect.transforms.each(function(transform) {
955
- if(transform.style != 'opacity')
956
- effect.element.style[transform.style.camelize()] = '';
937
+ effect.element.style[transform.style] = '';
957
938
  });
958
939
  }
959
- } else this.style = options.style.parseStyle();
960
- } else this.style = $H(options.style)
940
+ }
941
+ }
961
942
  this.start(options);
962
943
  },
944
+
963
945
  setup: function(){
964
946
  function parseColor(color){
965
- if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
947
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
966
948
  color = color.parseColor();
967
949
  return $R(0,2).map(function(i){
968
950
  return parseInt( color.slice(i*2+1,i*2+3), 16 )
969
951
  });
970
952
  }
971
953
  this.transforms = this.style.map(function(pair){
972
- var property = pair[0].underscore().dasherize(), value = pair[1], unit = null;
954
+ var property = pair[0], value = pair[1], unit = null;
973
955
 
974
- if(value.parseColor('#zzzzzz') != '#zzzzzz') {
956
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
975
957
  value = value.parseColor();
976
958
  unit = 'color';
977
- } else if(property == 'opacity') {
959
+ } else if (property == 'opacity') {
978
960
  value = parseFloat(value);
979
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
961
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
980
962
  this.element.setStyle({zoom: 1});
981
- } else if(Element.CSS_LENGTH.test(value))
982
- var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/),
983
- value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null;
963
+ } else if (Element.CSS_LENGTH.test(value)) {
964
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
965
+ value = parseFloat(components[1]);
966
+ unit = (components.length == 3) ? components[2] : null;
967
+ }
984
968
 
985
969
  var originalValue = this.element.getStyle(property);
986
- return $H({
987
- style: property,
970
+ return {
971
+ style: property.camelize(),
988
972
  originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
989
973
  targetValue: unit=='color' ? parseColor(value) : value,
990
974
  unit: unit
991
- });
975
+ };
992
976
  }.bind(this)).reject(function(transform){
993
977
  return (
994
978
  (transform.originalValue == transform.targetValue) ||
@@ -1000,32 +984,35 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
1000
984
  });
1001
985
  },
1002
986
  update: function(position) {
1003
- var style = $H(), value = null;
1004
- this.transforms.each(function(transform){
1005
- value = transform.unit=='color' ?
1006
- $R(0,2).inject('#',function(m,v,i){
1007
- return m+(Math.round(transform.originalValue[i]+
1008
- (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) :
1009
- transform.originalValue + Math.round(
1010
- ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
1011
- style[transform.style] = value;
1012
- });
1013
- this.element.setStyle(style);
987
+ var style = { }, transform, i = this.transforms.length;
988
+ while(i--)
989
+ style[(transform = this.transforms[i]).style] =
990
+ transform.unit=='color' ? '#'+
991
+ (Math.round(transform.originalValue[0]+
992
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
993
+ (Math.round(transform.originalValue[1]+
994
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
995
+ (Math.round(transform.originalValue[2]+
996
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
997
+ (transform.originalValue +
998
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
999
+ (transform.unit === null ? '' : transform.unit);
1000
+ this.element.setStyle(style, true);
1014
1001
  }
1015
1002
  });
1016
1003
 
1017
- Effect.Transform = Class.create();
1018
- Object.extend(Effect.Transform.prototype, {
1004
+ Effect.Transform = Class.create({
1019
1005
  initialize: function(tracks){
1020
1006
  this.tracks = [];
1021
- this.options = arguments[1] || {};
1007
+ this.options = arguments[1] || { };
1022
1008
  this.addTracks(tracks);
1023
1009
  },
1024
1010
  addTracks: function(tracks){
1025
1011
  tracks.each(function(track){
1026
- var data = $H(track).values().first();
1012
+ track = $H(track);
1013
+ var data = track.values().first();
1027
1014
  this.tracks.push($H({
1028
- ids: $H(track).keys().first(),
1015
+ ids: track.keys().first(),
1029
1016
  effect: Effect.Morph,
1030
1017
  options: { style: data }
1031
1018
  }));
@@ -1035,8 +1022,9 @@ Object.extend(Effect.Transform.prototype, {
1035
1022
  play: function(){
1036
1023
  return new Effect.Parallel(
1037
1024
  this.tracks.map(function(track){
1038
- var elements = [$(track.ids) || $$(track.ids)].flatten();
1039
- return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
1025
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
1026
+ var elements = [$(ids) || $$(ids)].flatten();
1027
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
1040
1028
  }).flatten(),
1041
1029
  this.options
1042
1030
  );
@@ -1056,35 +1044,79 @@ Element.CSS_PROPERTIES = $w(
1056
1044
 
1057
1045
  Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1058
1046
 
1047
+ String.__parseStyleElement = document.createElement('div');
1059
1048
  String.prototype.parseStyle = function(){
1060
- var element = Element.extend(document.createElement('div'));
1061
- element.innerHTML = '<div style="' + this + '"></div>';
1062
- var style = element.down().style, styleRules = $H();
1049
+ var style, styleRules = $H();
1050
+ if (Prototype.Browser.WebKit)
1051
+ style = new Element('div',{style:this}).style;
1052
+ else {
1053
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1054
+ style = String.__parseStyleElement.childNodes[0].style;
1055
+ }
1063
1056
 
1064
1057
  Element.CSS_PROPERTIES.each(function(property){
1065
- if(style[property]) styleRules[property] = style[property];
1058
+ if (style[property]) styleRules.set(property, style[property]);
1066
1059
  });
1067
- if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) {
1068
- styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
1069
- }
1060
+
1061
+ if (Prototype.Browser.IE && this.include('opacity'))
1062
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1063
+
1070
1064
  return styleRules;
1071
1065
  };
1072
1066
 
1073
- Element.morph = function(element, style) {
1074
- new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
1075
- return element;
1067
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1068
+ Element.getStyles = function(element) {
1069
+ var css = document.defaultView.getComputedStyle($(element), null);
1070
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
1071
+ styles[property] = css[property];
1072
+ return styles;
1073
+ });
1074
+ };
1075
+ } else {
1076
+ Element.getStyles = function(element) {
1077
+ element = $(element);
1078
+ var css = element.currentStyle, styles;
1079
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
1080
+ results[property] = css[property];
1081
+ return results;
1082
+ });
1083
+ if (!styles.opacity) styles.opacity = element.getOpacity();
1084
+ return styles;
1085
+ };
1086
+ };
1087
+
1088
+ Effect.Methods = {
1089
+ morph: function(element, style) {
1090
+ element = $(element);
1091
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
1092
+ return element;
1093
+ },
1094
+ visualEffect: function(element, effect, options) {
1095
+ element = $(element)
1096
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1097
+ new Effect[klass](element, options);
1098
+ return element;
1099
+ },
1100
+ highlight: function(element, options) {
1101
+ element = $(element);
1102
+ new Effect.Highlight(element, options);
1103
+ return element;
1104
+ }
1076
1105
  };
1077
1106
 
1078
- ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
1079
- 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
1080
- function(f) { Element.Methods[f] = Element[f]; }
1107
+ $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1108
+ 'pulsate shake puff squish switchOff dropOut').each(
1109
+ function(effect) {
1110
+ Effect.Methods[effect] = function(element, options){
1111
+ element = $(element);
1112
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1113
+ return element;
1114
+ }
1115
+ }
1081
1116
  );
1082
1117
 
1083
- Element.Methods.visualEffect = function(element, effect, options) {
1084
- s = effect.gsub(/_/, '-').camelize();
1085
- effect_class = s.charAt(0).toUpperCase() + s.substring(1);
1086
- new Effect[effect_class](element, options);
1087
- return $(element);
1088
- };
1118
+ $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1119
+ function(f) { Effect.Methods[f] = Element[f]; }
1120
+ );
1089
1121
 
1090
- Element.addMethods();
1122
+ Element.addMethods(Effect.Methods);