// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
String.prototype.parseColor=function() { 
var color='#'; 
if(this.slice(0,4)=='rgb(') { 
var cols=this.slice(4,this.length-1).split(','); 
var i=0; do { color+=parseInt(cols[i]).toColorPart() } while (++i<3); 
} else { 
if(this.slice(0,1)=='#') { 
if(this.length==4) for(var i=1;i<4;i++) color+=(this.charAt(i)+this.charAt(i)).toLowerCase(); 
if(this.length==7) color=this.toLowerCase(); 
} 
} 
return(color.length==7 ? color : (arguments[0] || this)); 
}
Element.collectTextNodes=function(element) { 
return $A($(element).childNodes).collect( function(node) {
return (node.nodeType==3 ? node.nodeValue : 
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
}).flatten().join('');
}
Element.collectTextNodesIgnoreClass=function(element, className) { 
return $A($(element).childNodes).collect( function(node) {
return (node.nodeType==3 ? node.nodeValue : 
((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
Element.collectTextNodes(node) : ''));
}).flatten().join('');
}
Element.setStyle=function(element, style) {
element=$(element);
for(k in style) element.style[k.camelize()]=style[k];
}
Element.setContentZoom=function(element, percent) { 
Element.setStyle(element, {fontSize: (percent/100)+'em'}); 
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
}
Element.getOpacity=function(element){ 
var opacity;
if (opacity=Element.getStyle(element, 'opacity'))  
return parseFloat(opacity); 
if (opacity=(Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
if(opacity[1]) return parseFloat(opacity[1]) / 100; 
return 1.0; 
}
Element.setOpacity=function(element, value){ 
element=$(element); 
if (value==1){
Element.setStyle(element, { opacity: 
(/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
0.999999 : null });
if(/MSIE/.test(navigator.userAgent))  
Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); 
} else { 
if(value <0.00001) value=0; 
Element.setStyle(element, {opacity: value});
if(/MSIE/.test(navigator.userAgent))  
Element.setStyle(element, 
{ filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')+
'alpha(opacity='+value*100+')' }); 
} 
} 
Element.getInlineOpacity=function(element){ 
return $(element).style.opacity || '';
} 
Element.childrenWithClassName=function(element, className) { 
return $A($(element).getElementsByTagName('*')).select(
function(c) { return Element.hasClassName(c, className) });
}
Array.prototype.call=function() {
var args=arguments;
this.each(function(f){ f.apply(this, args) });
}
/*--------------------------------------------------------------------------*/
var Effect={
tagifyText: function(element) {
var tagifyStyle='position:relative';
if(/MSIE/.test(navigator.userAgent)) tagifyStyle+=';zoom:1';
element=$(element);
$A(element.childNodes).each( function(child) {
if(child.nodeType==3) {
child.nodeValue.toArray().each( function(character) {
element.insertBefore(
Builder.node('span',{style: tagifyStyle},
character==' ' ? String.fromCharCode(160) : character), 
child);
});
Element.remove(child);
}});
},
multiple: function(element, effect) {
var elements;
if(((typeof element=='object') || 
(typeof element=='function')) && 
(element.length))
elements=element;
else
elements=$(element).childNodes;
var options=Object.extend({
speed: 0.1,
delay: 0.0
}, arguments[2] || {});
var masterDelay=options.delay;
$A(elements).each( function(element, index) {
new effect(element, Object.extend(options, { delay: index * options.speed+masterDelay }));
});
},
PAIRS: {
'slide':  ['SlideDown','SlideUp'],
'blind':  ['BlindDown','BlindUp'],
'appear': ['Appear','Fade']
},
toggle: function(element, effect) {
element=$(element);
effect=(effect || 'appear').toLowerCase();
var options=Object.extend({
queue: { position:'end', scope:(element.id || 'global') }}, arguments[2] || {});
Effect[Element.visible(element) ? 
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
}};
var Effect2=Effect; 
Effect.Transitions={}
Effect.Transitions.linear=function(pos) {
return pos;
}
Effect.Transitions.sinoidal=function(pos) {
return (-Math.cos(pos*Math.PI)/2)+0.5;
}
Effect.Transitions.reverse=function(pos) {
return 1-pos;
}
Effect.Transitions.flicker=function(pos) {
return ((-Math.cos(pos*Math.PI)/4)+0.75)+Math.random()/4;
}
Effect.Transitions.wobble=function(pos) {
return (-Math.cos(pos*Math.PI*(9*pos))/2)+0.5;
}
Effect.Transitions.pulse=function(pos) {
return (Math.floor(pos*10) % 2==0 ? 
(pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
}
Effect.Transitions.none=function(pos) {
return 0;
}
Effect.Transitions.full=function(pos) {
return 1;
}
Effect.ScopedQueue=Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
initialize: function() {
this.effects=[];
this.interval=null;
},
_each: function(iterator) {
this.effects._each(iterator);
},
add: function(effect) {
var timestamp=new Date().getTime();
var position=(typeof effect.options.queue=='string') ? 
effect.options.queue : effect.options.queue.position;
switch(position) {
case 'front':
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
e.startOn+=effect.finishOn;
e.finishOn+=effect.finishOn;
});
break;
case 'end':
timestamp=this.effects.pluck('finishOn').max() || timestamp;
break;
}
effect.startOn+=timestamp;
effect.finishOn+=timestamp;
this.effects.push(effect);
if(!this.interval) 
this.interval=setInterval(this.loop.bind(this), 40);
},
remove: function(effect) {
this.effects=this.effects.reject(function(e) { return e==effect });
if(this.effects.length==0) {
clearInterval(this.interval);
this.interval=null;
}},
loop: function() {
var timePos=new Date().getTime();
this.effects.invoke('loop', timePos);
}});
Effect.Queues={
instances: $H(),
get: function(queueName) {
if(typeof queueName !='string') return queueName;
if(!this.instances[queueName])
this.instances[queueName]=new Effect.ScopedQueue();
return this.instances[queueName];
}}
Effect.Queue=Effect.Queues.get('global');
Effect.DefaultOptions={
transition: Effect.Transitions.sinoidal,
duration:   1.0,   
fps:        25.0,  
sync:       false, 
from:       0.0,
to:         1.0,
delay:      0.0,
queue:      'parallel'
}
Effect.Base=function() {};
Effect.Base.prototype={
position: null,
start: function(options) {
this.options=Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
this.currentFrame=0;
this.state='idle';
this.startOn=this.options.delay*1000;
this.finishOn=this.startOn+(this.options.duration*1000);
this.event('beforeStart');
if(!this.options.sync)
Effect.Queues.get(typeof this.options.queue=='string' ? 
'global' : this.options.queue.scope).add(this);
},
loop: function(timePos) {
if(timePos>=this.startOn) {
if(timePos>=this.finishOn) {
this.render(1.0);
this.cancel();
this.event('beforeFinish');
if(this.finish) this.finish(); 
this.event('afterFinish');
return; 
}
var pos=(timePos - this.startOn) / (this.finishOn - this.startOn);
var frame=Math.round(pos * this.options.fps * this.options.duration);
if(frame> this.currentFrame) {
this.render(pos);
this.currentFrame=frame;
}}},
render: function(pos) {
if(this.state=='idle') {
this.state='running';
this.event('beforeSetup');
if(this.setup) this.setup();
this.event('afterSetup');
}
if(this.state=='running') {
if(this.options.transition) pos=this.options.transition(pos);
pos *=(this.options.to-this.options.from);
pos+=this.options.from;
this.position=pos;
this.event('beforeUpdate');
if(this.update) this.update(pos);
this.event('afterUpdate');
}},
cancel: function() {
if(!this.options.sync)
Effect.Queues.get(typeof this.options.queue=='string' ? 
'global' : this.options.queue.scope).remove(this);
this.state='finished';
},
event: function(eventName) {
if(this.options[eventName+'Internal']) this.options[eventName+'Internal'](this);
if(this.options[eventName]) this.options[eventName](this);
},
inspect: function() {
return '#<Effect:'+$H(this).inspect()+',options:'+$H(this.options).inspect()+'>';
}}
Effect.Opacity=Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
initialize: function(element) {
this.element=$(element);
if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
Element.setStyle(this.element, {zoom: 1});
var options=Object.extend({
from: Element.getOpacity(this.element) || 0.0,
to:   1.0
}, arguments[1] || {});
this.start(options);
},
update: function(position) {
Element.setOpacity(this.element, position);
}});
Effect.Scale=Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
initialize: function(element, percent) {
this.element=$(element)
var options=Object.extend({
scaleX: true,
scaleY: true,
scaleContent: true,
scaleFromCenter: false,
scaleMode: 'box',        
scaleFrom: 100.0,
scaleTo:   percent
}, arguments[2] || {});
this.start(options);
},
setup: function() {
this.restoreAfterFinish=this.options.restoreAfterFinish || false;
this.elementPositioning=Element.getStyle(this.element,'position');
this.originalStyle={};
['top','left','width','height','fontSize'].each( function(k) {
this.originalStyle[k]=this.element.style[k];
}.bind(this));
this.originalTop=this.element.offsetTop;
this.originalLeft=this.element.offsetLeft;
var fontSize=Element.getStyle(this.element,'font-size') || '100%';
['em','px','%'].each( function(fontSizeType) {
if(fontSize.indexOf(fontSizeType)>0) {
this.fontSize=parseFloat(fontSize);
this.fontSizeType=fontSizeType;
}}.bind(this));
this.factor=(this.options.scaleTo - this.options.scaleFrom)/100;
this.dims=null;
if(this.options.scaleMode=='box')
this.dims=[this.element.offsetHeight, this.element.offsetWidth];
if(/^content/.test(this.options.scaleMode))
this.dims=[this.element.scrollHeight, this.element.scrollWidth];
if(!this.dims)
this.dims=[this.options.scaleMode.originalHeight,
this.options.scaleMode.originalWidth];
},
update: function(position) {
var currentScale=(this.options.scaleFrom/100.0)+(this.factor * position);
if(this.options.scaleContent && this.fontSize)
Element.setStyle(this.element, {fontSize: this.fontSize * currentScale+this.fontSizeType });
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
finish: function(position) {
if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
},
setDimensions: function(height, width) {
var d={};
if(this.options.scaleX) d.width=width+'px';
if(this.options.scaleY) d.height=height+'px';
if(this.options.scaleFromCenter) {
var topd=(height - this.dims[0])/2;
var leftd=(width  - this.dims[1])/2;
if(this.elementPositioning=='absolute') {
if(this.options.scaleY) d.top=this.originalTop-topd+'px';
if(this.options.scaleX) d.left=this.originalLeft-leftd+'px';
} else {
if(this.options.scaleY) d.top=-topd+'px';
if(this.options.scaleX) d.left=-leftd+'px';
}}
Element.setStyle(this.element, d);
}});
Effect.Fade=function(element) {
var oldOpacity=Element.getInlineOpacity(element);
var options=Object.extend({
from: Element.getOpacity(element) || 1.0,
to:   0.0,
afterFinishInternal: function(effect) { with(Element) { 
if(effect.options.to!=0) return;
hide(effect.element);
setStyle(effect.element, {opacity: oldOpacity}); }}}, arguments[1] || {});
return new Effect.Opacity(element,options);
}
Effect.Appear=function(element) {
var options=Object.extend({
from: (Element.getStyle(element, 'display')=='none' ? 0.0 : Element.getOpacity(element) || 0.0),
to:   1.0,
beforeSetup: function(effect) { with(Element) {
setOpacity(effect.element, effect.options.from);
show(effect.element); }}}, arguments[1] || {});
return new Effect.Opacity(element,options);
}
Effect.BlindUp=function(element) {
element=$(element);
Element.makeClipping(element);
return new Effect.Scale(element, 0, 
Object.extend({ scaleContent: false, 
scaleX: false, 
restoreAfterFinish: true,
afterFinishInternal: function(effect) { with(Element) {
[hide, undoClipping].call(effect.element); }} 
}, arguments[1] || {})
);
}
Effect.BlindDown=function(element) {
element=$(element);
var oldHeight=Element.getStyle(element, 'height');
var elementDimensions=Element.getDimensions(element);
return new Effect.Scale(element, 100, 
Object.extend({ scaleContent: false, 
scaleX: false,
scaleFrom: 0,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
afterSetup: function(effect) { with(Element) {
makeClipping(effect.element);
setStyle(effect.element, {height: '0px'});
show(effect.element); 
}},  
afterFinishInternal: function(effect) { with(Element) {
undoClipping(effect.element);
setStyle(effect.element, {height: oldHeight});
}}}, arguments[1] || {})
);
}

