var Prototype={
    Version:'1.5.1',
    Browser:{
        IE:!!(window.attachEvent&&!window.opera),
        Opera:!!window.opera,
        WebKit:navigator.userAgent.indexOf('AppleWebKit/')>-1,
        Gecko:navigator.userAgent.indexOf('Gecko')>-1&&navigator.userAgent.indexOf('KHTML')==-1
        },
    BrowserFeatures:{
        XPath:!!document.evaluate,
        ElementExtensions:!!window.HTMLElement,
        SpecificElementExtensions:(document.createElement('div').__proto__!==document.createElement('form').__proto__)
        },
    ScriptFragment:'<script[^>]*>([\u0001-\uFFFF]*?)</script>',
    JSONFilter:/^\/\*-secure-\s*(.*)\s*\*\/\s*$/,
    emptyFunction:function(){},
    K:function(x){
        return x
        }
    };

var Class={
    create:function(){
        return function(){
            this.initialize.apply(this,arguments)
            }
        }
};

var Abstract=new Object();
Object.extend=function(a,b){
    for(var c in b){
        a[c]=b[c]
        }
        return a
    };

Object.extend(Object,{
    inspect:function(a){
        try{
            if(a===undefined)return'undefined';
            if(a===null)return'null';
            return a.inspect?a.inspect():a.toString()
            }catch(e){
            if(e instanceof RangeError)return'...';
            throw e;
        }
    },
toJSON:function(a){
    var b=typeof a;
    switch(b){
        case'undefined':case'function':case'unknown':
            return;
        case'boolean':
            return a.toString()
            }
            if(a===null)return'null';
    if(a.toJSON)return a.toJSON();
    if(a.ownerDocument===document)return;
    var c=[];
    for(var d in a){
        var e=Object.toJSON(a[d]);
        if(e!==undefined)c.push(d.toJSON()+': '+e)
            }
            return'{'+c.join(', ')+'}'
    },
keys:function(a){
    var b=[];
    for(var c in a)b.push(c);return b
    },
values:function(a){
    var b=[];
    for(var c in a)b.push(a[c]);return b
    },
clone:function(a){
    return Object.extend({},a)
    }
});
Function.prototype.bind=function(){
    var a=this,args=$A(arguments),object=args.shift();
    return function(){
        return a.apply(object,args.concat($A(arguments)))
        }
    };

Function.prototype.bindAsEventListener=function(b){
    var c=this,args=$A(arguments),b=args.shift();
    return function(a){
        return c.apply(b,[a||window.event].concat(args))
        }
    };

Object.extend(Number.prototype,{
    toColorPart:function(){
        return this.toPaddedString(2,16)
        },
    succ:function(){
        return this+1
        },
    times:function(a){
        $R(0,this,true).each(a);
        return this
        },
    toPaddedString:function(a,b){
        var c=this.toString(b||10);
        return'0'.times(a-c.length)+c
        },
    toJSON:function(){
        return isFinite(this)?this.toString():'null'
        }
    });
Date.prototype.toJSON=function(){
    return'"'+this.getFullYear()+'-'+(this.getMonth()+1).toPaddedString(2)+'-'+this.getDate().toPaddedString(2)+'T'+this.getHours().toPaddedString(2)+':'+this.getMinutes().toPaddedString(2)+':'+this.getSeconds().toPaddedString(2)+'"'
    };

var Try={
    these:function(){
        var a;
        for(var i=0,length=arguments.length;i<length;i++){
            var b=arguments[i];
            try{
                a=b();
                break
            }catch(e){}
        }
        return a
    }
};

var PeriodicalExecuter=Class.create();
PeriodicalExecuter.prototype={
    initialize:function(a,b){
        this.callback=a;
        this.frequency=b;
        this.currentlyExecuting=false;
        this.registerCallback()
        },
    registerCallback:function(){
        this.timer=setInterval(this.onTimerEvent.bind(this),this.frequency*1000)
        },
    stop:function(){
        if(!this.timer)return;
        clearInterval(this.timer);
        this.timer=null
        },
    onTimerEvent:function(){
        if(!this.currentlyExecuting){
            try{
                this.currentlyExecuting=true;
                this.callback(this)
                }finally{
                this.currentlyExecuting=false
                }
            }
    }
};

Object.extend(String,{
    interpret:function(a){
        return a==null?'':String(a)
        },
    specialChar:{
        '\b':'\\b',
        '\t':'\\t',
        '\n':'\\n',
        '\f':'\\f',
        '\r':'\\r',
        '\\':'\\\\'
    }
});
Object.extend(String.prototype,{
    gsub:function(a,b){
        var c='',source=this,match;
        b=arguments.callee.prepareReplacement(b);
        while(source.length>0){
            if(match=source.match(a)){
                c+=source.slice(0,match.index);
                c+=String.interpret(b(match));
                source=source.slice(match.index+match[0].length)
                }else{
                c+=source,source=''
                }
            }
        return c
    },
sub:function(b,c,d){
    c=this.gsub.prepareReplacement(c);
    d=d===undefined?1:d;
    return this.gsub(b,function(a){
        if(--d<0)return a[0];
        return c(a)
        })
    },
scan:function(a,b){
    this.gsub(a,b);
    return this
    },
truncate:function(a,b){
    a=a||30;
    b=b===undefined?'...':b;
    return this.length>a?this.slice(0,a-b.length)+b:this
    },
strip:function(){
    return this.replace(/^\s+/,'').replace(/\s+$/,'')
    },
stripTags:function(){
    return this.replace(/<\/?[^>]+>/gi,'')
    },
stripScripts:function(){
    return this.replace(new RegExp(Prototype.ScriptFragment,'img'),'')
    },
extractScripts:function(){
    var b=new RegExp(Prototype.ScriptFragment,'img');
    var c=new RegExp(Prototype.ScriptFragment,'im');
    return(this.match(b)||[]).map(function(a){
        return(a.match(c)||['',''])[1]
        })
    },
evalScripts:function(){
    return this.extractScripts().map(function(a){
        return eval(a)
        })
    },
escapeHTML:function(){
    var a=arguments.callee;
    a.text.data=this;
    return a.div.innerHTML
    },
unescapeHTML:function(){
    var c=document.createElement('div');
    c.innerHTML=this.stripTags();
    return c.childNodes[0]?(c.childNodes.length>1?$A(c.childNodes).inject('',function(a,b){
        return a+b.nodeValue
        }):c.childNodes[0].nodeValue):''
    },
toQueryParams:function(e){
    var f=this.strip().match(/([^?#]*)(#.*)?$/);
    if(!f)return{};

    return f[1].split(e||'&').inject({},function(a,b){
        if((b=b.split('='))[0]){
            var c=decodeURIComponent(b.shift());
            var d=b.length>1?b.join('='):b[0];
            if(d!=undefined)d=decodeURIComponent(d);
            if(c in a){
                if(a[c].constructor!=Array)a[c]=[a[c]];
                a[c].push(d)
                }else a[c]=d
                }
                return a
        })
    },
toArray:function(){
    return this.split('')
    },
succ:function(){
    return this.slice(0,this.length-1)+String.fromCharCode(this.charCodeAt(this.length-1)+1)
    },
times:function(a){
    var b='';
    for(var i=0;i<a;i++)b+=this;
    return b
    },
camelize:function(){
    var a=this.split('-'),len=a.length;
    if(len==1)return a[0];
    var b=this.charAt(0)=='-'?a[0].charAt(0).toUpperCase()+a[0].substring(1):a[0];
    for(var i=1;i<len;i++)b+=a[i].charAt(0).toUpperCase()+a[i].substring(1);
    return b
    },
capitalize:function(){
    return this.charAt(0).toUpperCase()+this.substring(1).toLowerCase()
    },
underscore:function(){
    return this.gsub(/::/,'/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase()
    },
dasherize:function(){
    return this.gsub(/_/,'-')
    },
inspect:function(c){
    var d=this.gsub(/[\x00-\x1f\\]/,function(a){
        var b=String.specialChar[a[0]];
        return b?b:'\\u00'+a[0].charCodeAt().toPaddedString(2,16)
        });
    if(c)return'"'+d.replace(/"/g,'\\"')+'"';
    return"'"+d.replace(/'/g,'\\\'')+"'"
    },
toJSON:function(){
    return this.inspect(true)
    },
unfilterJSON:function(a){
    return this.sub(a||Prototype.JSONFilter,'#{1}')
    },
evalJSON:function(a){
    var b=this.unfilterJSON();
    try{
        if(!a||(new RegExp('^("(\\\\.|[^"\\\\\\n\\r])'+'*'+'?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$').test(b))){
            return eval('('+b+')')
            }
        }catch(e){}
    throw new SyntaxError('Badly formed JSON string: '+this.inspect());
    },
    include:function(a){
        return this.indexOf(a)>-1
        },
    startsWith:function(a){
        return this.indexOf(a)===0
        },
    endsWith:function(a){
        var d=this.length-a.length;
        return d>=0&&this.lastIndexOf(a)===d
        },
    empty:function(){
        return this==''
        },
    blank:function(){
        return/^\s*$/.test(this)
        }
    });
if(Prototype.Browser.WebKit||Prototype.Browser.IE){
    Object.extend(String.prototype,{
        escapeHTML:function(){
            return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
            },
        unescapeHTML:function(){
            return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>')
            }
        })
    }
    String.prototype.gsub.prepareReplacement=function(b){
    if(typeof b=='function')return b;
    var c=new Template(b);
    return function(a){
        return c.evaluate(a)
        }
    };

String.prototype.parseQuery=String.prototype.toQueryParams;
Object.extend(String.prototype.escapeHTML,{
    div:document.createElement('div'),
    text:document.createTextNode('')
    });
with(String.prototype.escapeHTML)div.appendChild(text);
var Template=Class.create();
Template.Pattern=/(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype={
    initialize:function(a,b){
        this.template=a.toString();
        this.pattern=b||Template.Pattern
        },
    evaluate:function(c){
        return this.template.gsub(this.pattern,function(a){
            var b=a[1];
            if(b=='\\')return a[2];
            return b+String.interpret(c[a[3]])
            })
        }
    };

var $break={};

var $continue=new Error('"throw $continue" is deprecated, use "return" instead');
var Enumerable={
    each:function(b){
        var c=0;
        try{
            this._each(function(a){
                b(a,c++)
                })
            }catch(e){
            if(e!=$break)throw e;
        }
        return this
        },
    eachSlice:function(a,b){
        var c=-a,slices=[],array=this.toArray();
        while((c+=a)<array.length)slices.push(array.slice(c,c+a));
        return slices.map(b)
        },
    all:function(c){
        var d=true;
        this.each(function(a,b){
            d=d&&!!(c||Prototype.K)(a,b);
            if(!d)throw $break;
        });
        return d
        },
    any:function(c){
        var d=false;
        this.each(function(a,b){
            if(d=!!(c||Prototype.K)(a,b))throw $break;
        });
        return d
        },
    collect:function(c){
        var d=[];
        this.each(function(a,b){
            d.push((c||Prototype.K)(a,b))
            });
        return d
        },
    detect:function(c){
        var d;
        this.each(function(a,b){
            if(c(a,b)){
                d=a;
                throw $break;
            }
        });
    return d
    },
findAll:function(c){
    var d=[];
    this.each(function(a,b){
        if(c(a,b))d.push(a)
            });
    return d
    },
grep:function(d,e){
    var f=[];
    this.each(function(a,b){
        var c=a.toString();
        if(c.match(d))f.push((e||Prototype.K)(a,b))
            });
    return f
    },
include:function(b){
    var c=false;
    this.each(function(a){
        if(a==b){
            c=true;
            throw $break;
        }
    });
return c
},
inGroupsOf:function(b,c){
    c=c===undefined?null:c;
    return this.eachSlice(b,function(a){
        while(a.length<b)a.push(c);
        return a
        })
    },
inject:function(c,d){
    this.each(function(a,b){
        c=d(c,a,b)
        });
    return c
    },
invoke:function(b){
    var c=$A(arguments).slice(1);
    return this.map(function(a){
        return a[b].apply(a,c)
        })
    },
max:function(c){
    var d;
    this.each(function(a,b){
        a=(c||Prototype.K)(a,b);
        if(d==undefined||a>=d)d=a
            });
    return d
    },
min:function(c){
    var d;
    this.each(function(a,b){
        a=(c||Prototype.K)(a,b);
        if(d==undefined||a<d)d=a
            });
    return d
    },
partition:function(c){
    var d=[],falses=[];
    this.each(function(a,b){
        ((c||Prototype.K)(a,b)?d:falses).push(a)
        });
    return[d,falses]
    },
pluck:function(c){
    var d=[];
    this.each(function(a,b){
        d.push(a[c])
        });
    return d
    },
reject:function(c){
    var d=[];
    this.each(function(a,b){
        if(!c(a,b))d.push(a)
            });
    return d
    },
sortBy:function(e){
    return this.map(function(a,b){
        return{
            value:a,
            criteria:e(a,b)
            }
        }).sort(function(c,d){
    var a=c.criteria,b=d.criteria;
    return a<b?-1:a>b?1:0
    }).pluck('value')
},
toArray:function(){
    return this.map()
    },
zip:function(){
    var c=Prototype.K,args=$A(arguments);
    if(typeof args.last()=='function')c=args.pop();
    var d=[this].concat(args).map($A);
    return this.map(function(a,b){
        return c(d.pluck(b))
        })
    },
size:function(){
    return this.toArray().length
    },
inspect:function(){
    return'#<Enumerable:'+this.toArray().inspect()+'>'
    }
};

Object.extend(Enumerable,{
    map:Enumerable.collect,
    find:Enumerable.detect,
    select:Enumerable.findAll,
    member:Enumerable.include,
    entries:Enumerable.toArray
    });
var $A=Array.from=function(a){
    if(!a)return[];
    if(a.toArray){
        return a.toArray()
        }else{
        var b=[];
        for(var i=0,length=a.length;i<length;i++)b.push(a[i]);
        return b
        }
    };

if(Prototype.Browser.WebKit){
    $A=Array.from=function(a){
        if(!a)return[];
        if(!(typeof a=='function'&&a=='[object NodeList]')&&a.toArray){
            return a.toArray()
            }else{
            var b=[];
            for(var i=0,length=a.length;i<length;i++)b.push(a[i]);
            return b
            }
        }
    }
Object.extend(Array.prototype,Enumerable);
if(!Array.prototype._reverse)Array.prototype._reverse=Array.prototype.reverse;
Object.extend(Array.prototype,{
    _each:function(a){
        for(var i=0,length=this.length;i<length;i++)a(this[i])
            },
    clear:function(){
        this.length=0;
        return this
        },
    first:function(){
        return this[0]
        },
    last:function(){
        return this[this.length-1]
        },
    compact:function(){
        return this.select(function(a){
            return a!=null
            })
        },
    flatten:function(){
        return this.inject([],function(a,b){
            return a.concat(b&&b.constructor==Array?b.flatten():[b])
            })
        },
    without:function(){
        var b=$A(arguments);
        return this.select(function(a){
            return!b.include(a)
            })
        },
    indexOf:function(a){
        for(var i=0,length=this.length;i<length;i++)if(this[i]==a)return i;return-1
        },
    reverse:function(a){
        return(a!==false?this:this.toArray())._reverse()
        },
    reduce:function(){
        return this.length>1?this:this[0]
        },
    uniq:function(d){
        return this.inject([],function(a,b,c){
            if(0==c||(d?a.last()!=b:!a.include(b)))a.push(b);
            return a
            })
        },
    clone:function(){
        return[].concat(this)
        },
    size:function(){
        return this.length
        },
    inspect:function(){
        return'['+this.map(Object.inspect).join(', ')+']'
        },
    toJSON:function(){
        var c=[];
        this.each(function(a){
            var b=Object.toJSON(a);
            if(b!==undefined)c.push(b)
                });
        return'['+c.join(', ')+']'
        }
    });
Array.prototype.toArray=Array.prototype.clone;
function $w(a){
    a=a.strip();
    return a?a.split(/\s+/):[]
    }
    if(Prototype.Browser.Opera){
    Array.prototype.concat=function(){
        var a=[];
        for(var i=0,length=this.length;i<length;i++)a.push(this[i]);
        for(var i=0,length=arguments.length;i<length;i++){
            if(arguments[i].constructor==Array){
                for(var j=0,arrayLength=arguments[i].length;j<arrayLength;j++)a.push(arguments[i][j])
                    }else{
                a.push(arguments[i])
                }
            }
        return a
    }
    }
var Hash=function(a){
    if(a instanceof Hash)this.merge(a);else Object.extend(this,a||{})
        };

Object.extend(Hash,{
    toQueryString:function(d){
        var e=[];
        e.add=arguments.callee.addPair;
        this.prototype._each.call(d,function(b){
            if(!b.key)return;
            var c=b.value;
            if(c&&typeof c=='object'){
                if(c.constructor==Array)c.each(function(a){
                    e.add(b.key,a)
                    });
                return
            }
            e.add(b.key,c)
            });
        return e.join('&')
        },
    toJSON:function(c){
        var d=[];
        this.prototype._each.call(c,function(a){
            var b=Object.toJSON(a.value);
            if(b!==undefined)d.push(a.key.toJSON()+': '+b)
                });
        return'{'+d.join(', ')+'}'
        }
    });
Hash.toQueryString.addPair=function(a,b,c){
    a=encodeURIComponent(a);
    if(b===undefined)this.push(a);else this.push(a+'='+(b==null?'':encodeURIComponent(b)))
        };

Object.extend(Hash.prototype,Enumerable);
Object.extend(Hash.prototype,{
    _each:function(a){
        for(var b in this){
            var c=this[b];
            if(c&&c==Hash.prototype[b])continue;
            var d=[b,c];
            d.key=b;
            d.value=c;
            a(d)
            }
        },
keys:function(){
    return this.pluck('key')
    },
values:function(){
    return this.pluck('value')
    },
merge:function(c){
    return $H(c).inject(this,function(a,b){
        a[b.key]=b.value;
        return a
        })
    },
remove:function(){
    var a;
    for(var i=0,length=arguments.length;i<length;i++){
        var b=this[arguments[i]];
        if(b!==undefined){
            if(a===undefined)a=b;
            else{
                if(a.constructor!=Array)a=[a];
                a.push(b)
                }
            }
        delete this[arguments[i]]
    }
    return a
},
toQueryString:function(){
    return Hash.toQueryString(this)
    },
inspect:function(){
    return'#<Hash:{'+this.map(function(a){
        return a.map(Object.inspect).join(': ')
        }).join(', ')+'}>'
    },
toJSON:function(){
    return Hash.toJSON(this)
    }
});
function $H(a){
    if(a instanceof Hash)return a;
    return new Hash(a)
    };

if(function(){
    var i=0,Test=function(a){
        this.key=a
        };

    Test.prototype.key='foo';
    for(var b in new Test('bar'))i++;return i>1
    }())Hash.prototype._each=function(a){
    var b=[];
    for(var c in this){
        var d=this[c];
        if((d&&d==Hash.prototype[c])||b.include(c))continue;
        b.push(c);
        var e=[c,d];
        e.key=c;
        e.value=d;
        a(e)
        }
    };

ObjectRange=Class.create();
Object.extend(ObjectRange.prototype,Enumerable);
Object.extend(ObjectRange.prototype,{
    initialize:function(a,b,c){
        this.start=a;
        this.end=b;
        this.exclusive=c
        },
    _each:function(a){
        var b=this.start;
        while(this.include(b)){
            a(b);
            b=b.succ()
            }
        },
include:function(a){
    if(a<this.start)return false;
    if(this.exclusive)return a<this.end;
    return a<=this.end
    }
});
var $R=function(a,b,c){
    return new ObjectRange(a,b,c)
    };

var Ajax={
    getTransport:function(){
        return Try.these(function(){
            return new XMLHttpRequest()
            },function(){
            return new ActiveXObject('Msxml2.XMLHTTP')
            },function(){
            return new ActiveXObject('Microsoft.XMLHTTP')
            })||false
        },
    activeRequestCount:0
};

Ajax.Responders={
    responders:[],
    _each:function(a){
        this.responders._each(a)
        },
    register:function(a){
        if(!this.include(a))this.responders.push(a)
            },
    unregister:function(a){
        this.responders=this.responders.without(a)
        },
    dispatch:function(b,c,d,f){
        this.each(function(a){
            if(typeof a[b]=='function'){
                try{
                    a[b].apply(a,[c,d,f])
                    }catch(e){}
            }
        })
}
};

Object.extend(Ajax.Responders,Enumerable);
Ajax.Responders.register({
    onCreate:function(){
        Ajax.activeRequestCount++
    },
    onComplete:function(){
        Ajax.activeRequestCount--
    }
});
Ajax.Base=function(){};

Ajax.Base.prototype={
    setOptions:function(a){
        this.options={
            method:'post',
            asynchronous:true,
            contentType:'application/x-www-form-urlencoded',
            encoding:'UTF-8',
            parameters:''
        };

        Object.extend(this.options,a||{});
        this.options.method=this.options.method.toLowerCase();
        if(typeof this.options.parameters=='string')this.options.parameters=this.options.parameters.toQueryParams()
            }
        };

Ajax.Request=Class.create();
Ajax.Request.Events=['Uninitialized','Loading','Loaded','Interactive','Complete'];
Ajax.Request.prototype=Object.extend(new Ajax.Base(),{
    _complete:false,
    initialize:function(a,b){
        this.transport=Ajax.getTransport();
        this.setOptions(b);
        this.request(a)
        },
    request:function(a){
        this.url=a;
        this.method=this.options.method;
        var b=Object.clone(this.options.parameters);
        if(!['get','post'].include(this.method)){
            b['_method']=this.method;
            this.method='post'
            }
            this.parameters=b;
        if(b=Hash.toQueryString(b)){
            if(this.method=='get')this.url+=(this.url.include('?')?'&':'?')+b;
            else if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))b+='&_='
                }
                try{
            if(this.options.onCreate)this.options.onCreate(this.transport);
            Ajax.Responders.dispatch('onCreate',this,this.transport);
            this.transport.open(this.method.toUpperCase(),this.url,this.options.asynchronous);
            if(this.options.asynchronous)setTimeout(function(){
                this.respondToReadyState(1)
                }.bind(this),10);
            this.transport.onreadystatechange=this.onStateChange.bind(this);
            this.setRequestHeaders();
            this.body=this.method=='post'?(this.options.postBody||b):null;
            this.transport.send(this.body);
            if(!this.options.asynchronous&&this.transport.overrideMimeType)this.onStateChange()
                }catch(e){
            this.dispatchException(e)
            }
        },
onStateChange:function(){
    var a=this.transport.readyState;
    if(a>1&&!((a==4)&&this._complete))this.respondToReadyState(this.transport.readyState)
        },
setRequestHeaders:function(){
    var b={
        'X-Requested-With':'XMLHttpRequest',
        'X-Prototype-Version':Prototype.Version,
        'Accept':'text/javascript, text/html, application/xml, text/xml, */*'
    };

    if(this.method=='post'){
        b['Content-type']=this.options.contentType+(this.options.encoding?'; charset='+this.options.encoding:'');
        if(this.transport.overrideMimeType&&(navigator.userAgent.match(/Gecko\/(\d{4})/)||[0,2005])[1]<2005)b['Connection']='close'
            }
            if(typeof this.options.requestHeaders=='object'){
        var c=this.options.requestHeaders;
        if(typeof c.push=='function')for(var i=0,length=c.length;i<length;i+=2)b[c[i]]=c[i+1];else $H(c).each(function(a){
            b[a.key]=a.value
            })
        }
        for(var d in b)this.transport.setRequestHeader(d,b[d])
        },
success:function(){
    return!this.transport.status||(this.transport.status>=200&&this.transport.status<300)
    },
respondToReadyState:function(a){
    var b=Ajax.Request.Events[a];
    var c=this.transport,json=this.evalJSON();
    if(b=='Complete'){
        try{
            this._complete=true;
            (this.options['on'+this.transport.status]||this.options['on'+(this.success()?'Success':'Failure')]||Prototype.emptyFunction)(c,json)
            }catch(e){
            this.dispatchException(e)
            }
            var d=this.getHeader('Content-type');
        if(d&&d.strip().match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))this.evalResponse()
            }
            try{
        (this.options['on'+b]||Prototype.emptyFunction)(c,json);
        Ajax.Responders.dispatch('on'+b,this,c,json)
        }catch(e){
        this.dispatchException(e)
        }
        if(b=='Complete'){
        this.transport.onreadystatechange=Prototype.emptyFunction
        }
    },
getHeader:function(a){
    try{
        return this.transport.getResponseHeader(a)
        }catch(e){
        return null
        }
    },
evalJSON:function(){
    try{
        var a=this.getHeader('X-JSON');
        return a?a.evalJSON():null
        }catch(e){
        return null
        }
    },
evalResponse:function(){
    try{
        return eval((this.transport.responseText||'').unfilterJSON())
        }catch(e){
        this.dispatchException(e)
        }
    },
dispatchException:function(a){
    (this.options.onException||Prototype.emptyFunction)(this,a);
    Ajax.Responders.dispatch('onException',this,a)
    }
});
Ajax.Updater=Class.create();
Object.extend(Object.extend(Ajax.Updater.prototype,Ajax.Request.prototype),{
    initialize:function(c,d,e){
        this.container={
            success:(c.success||c),
            failure:(c.failure||(c.success?null:c))
            };

        this.transport=Ajax.getTransport();
        this.setOptions(e);
        var f=this.options.onComplete||Prototype.emptyFunction;
        this.options.onComplete=(function(a,b){
            this.updateContent();
            f(a,b)
            }).bind(this);
        this.request(d)
        },
    updateContent:function(){
        var a=this.container[this.success()?'success':'failure'];
        var b=this.transport.responseText;
        if(!this.options.evalScripts)b=b.stripScripts();
        if(a=$(a)){
            if(this.options.insertion)new this.options.insertion(a,b);else a.update(b)
                }
                if(this.success()){
            if(this.onComplete)setTimeout(this.onComplete.bind(this),10)
                }
            }
});
Ajax.PeriodicalUpdater=Class.create();
Ajax.PeriodicalUpdater.prototype=Object.extend(new Ajax.Base(),{
    initialize:function(a,b,c){
        this.setOptions(c);
        this.onComplete=this.options.onComplete;
        this.frequency=(this.options.frequency||2);
        this.decay=(this.options.decay||1);
        this.updater={};

        this.container=a;
        this.url=b;
        this.start()
        },
    start:function(){
        this.options.onComplete=this.updateComplete.bind(this);
        this.onTimerEvent()
        },
    stop:function(){
        this.updater.options.onComplete=undefined;
        clearTimeout(this.timer);
        (this.onComplete||Prototype.emptyFunction).apply(this,arguments)
        },
    updateComplete:function(a){
        if(this.options.decay){
            this.decay=(a.responseText==this.lastText?this.decay*this.options.decay:1);
            this.lastText=a.responseText
            }
            this.timer=setTimeout(this.onTimerEvent.bind(this),this.decay*this.frequency*1000)
        },
    onTimerEvent:function(){
        this.updater=new Ajax.Updater(this.container,this.url,this.options)
        }
    });
function $(a){
    if(arguments.length>1){
        for(var i=0,elements=[],length=arguments.length;i<length;i++)elements.push($(arguments[i]));
        return elements
        }
        if(typeof a=='string')a=document.getElementById(a);
    return Element.extend(a)
    }
    if(Prototype.BrowserFeatures.XPath){
    document._getElementsByXPath=function(a,b){
        var c=[];
        var d=document.evaluate(a,$(b)||document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
        for(var i=0,length=d.snapshotLength;i<length;i++)c.push(d.snapshotItem(i));
        return c
        };

    document.getElementsByClassName=function(a,b){
        var q=".//*[contains(concat(' ', @class, ' '), ' "+a+" ')]";
        return document._getElementsByXPath(q,b)
        }
    }else{
    document.getElementsByClassName=function(a,b){
        var c=($(b)||document.body).getElementsByTagName('*');
        var d=[],child;
        for(var i=0,length=c.length;i<length;i++){
            child=c[i];
            if(Element.hasClassName(child,a))d.push(Element.extend(child))
                }
                return d
        }
    }
    if(!window.Element)var Element={};

Element.extend=function(a){
    var F=Prototype.BrowserFeatures;
    if(!a||!a.tagName||a.nodeType==3||a._extended||F.SpecificElementExtensions||a==window)return a;
    var b={},tagName=a.tagName,cache=Element.extend.cache,T=Element.Methods.ByTag;
    if(!F.ElementExtensions){
        Object.extend(b,Element.Methods),Object.extend(b,Element.Methods.Simulated)
        }
        if(T[tagName])Object.extend(b,T[tagName]);
    for(var c in b){
        var d=b[c];
        if(typeof d=='function'&&!(c in a))a[c]=cache.findOrStore(d)
            }
            a._extended=Prototype.emptyFunction;
    return a
    };

Element.extend.cache={
    findOrStore:function(a){
        return this[a]=this[a]||function(){
            return a.apply(null,[this].concat($A(arguments)))
            }
        }
};

Element.Methods={
    visible:function(a){
        return $(a).style.display!='none'
        },
    toggle:function(a){
        a=$(a);
        Element[Element.visible(a)?'hide':'show'](a);
        return a
        },
    hide:function(a){
        $(a).style.display='none';
        return a
        },
    show:function(a){
        $(a).style.display='';
        return a
        },
    remove:function(a){
        a=$(a);
        a.parentNode.removeChild(a);
        return a
        },
    update:function(a,b){
        b=typeof b=='undefined'?'':b.toString();
        $(a).innerHTML=b.stripScripts();
        setTimeout(function(){
            b.evalScripts()
            },10);
        return a
        },
    replace:function(a,b){
        a=$(a);
        b=typeof b=='undefined'?'':b.toString();
        if(a.outerHTML){
            a.outerHTML=b.stripScripts()
            }else{
            var c=a.ownerDocument.createRange();
            c.selectNodeContents(a);
            a.parentNode.replaceChild(c.createContextualFragment(b.stripScripts()),a)
            }
            setTimeout(function(){
            b.evalScripts()
            },10);
        return a
        },
    inspect:function(d){
        d=$(d);
        var e='<'+d.tagName.toLowerCase();
        $H({
            'id':'id',
            'className':'class'
        }).each(function(a){
            var b=a.first(),attribute=a.last();
            var c=(d[b]||'').toString();
            if(c)e+=' '+attribute+'='+c.inspect(true)
                });
        return e+'>'
        },
    recursivelyCollect:function(a,b){
        a=$(a);
        var c=[];
        while(a=a[b])if(a.nodeType==1)c.push(Element.extend(a));
        return c
        },
    ancestors:function(a){
        return $(a).recursivelyCollect('parentNode')
        },
    descendants:function(a){
        return $A($(a).getElementsByTagName('*')).each(Element.extend)
        },
    firstDescendant:function(a){
        a=$(a).firstChild;
        while(a&&a.nodeType!=1)a=a.nextSibling;
        return $(a)
        },
    immediateDescendants:function(a){
        if(!(a=$(a).firstChild))return[];
        while(a&&a.nodeType!=1)a=a.nextSibling;
        if(a)return[a].concat($(a).nextSiblings());
        return[]
        },
    previousSiblings:function(a){
        return $(a).recursivelyCollect('previousSibling')
        },
    nextSiblings:function(a){
        return $(a).recursivelyCollect('nextSibling')
        },
    siblings:function(a){
        a=$(a);
        return a.previousSiblings().reverse().concat(a.nextSiblings())
        },
    match:function(a,b){
        if(typeof b=='string')b=new Selector(b);
        return b.match($(a))
        },
    up:function(a,b,c){
        a=$(a);
        if(arguments.length==1)return $(a.parentNode);
        var d=a.ancestors();
        return b?Selector.findElement(d,b,c):d[c||0]
        },
    down:function(a,b,c){
        a=$(a);
        if(arguments.length==1)return a.firstDescendant();
        var d=a.descendants();
        return b?Selector.findElement(d,b,c):d[c||0]
        },
    previous:function(a,b,c){
        a=$(a);
        if(arguments.length==1)return $(Selector.handlers.previousElementSibling(a));
        var d=a.previousSiblings();
        return b?Selector.findElement(d,b,c):d[c||0]
        },
    next:function(a,b,c){
        a=$(a);
        if(arguments.length==1)return $(Selector.handlers.nextElementSibling(a));
        var d=a.nextSiblings();
        return b?Selector.findElement(d,b,c):d[c||0]
        },
    getElementsBySelector:function(){
        var a=$A(arguments),element=$(a.shift());
        return Selector.findChildElements(element,a)
        },
    getElementsByClassName:function(a,b){
        return document.getElementsByClassName(b,a)
        },
    readAttribute:function(a,b){
        a=$(a);
        if(Prototype.Browser.IE){
            if(!a.attributes)return null;
            var t=Element._attributeTranslations;
            if(t.values[b])return t.values[b](a,b);
            if(t.names[b])b=t.names[b];
            var c=a.attributes[b];
            return c?c.nodeValue:null
            }
            return a.getAttribute(b)
        },
    getHeight:function(a){
        return $(a).getDimensions().height
        },
    getWidth:function(a){
        return $(a).getDimensions().width
        },
    classNames:function(a){
        return new Element.ClassNames(a)
        },
    hasClassName:function(a,b){
        if(!(a=$(a)))return;
        var c=a.className;
        if(c.length==0)return false;
        if(c==b||c.match(new RegExp("(^|\\s)"+b+"(\\s|$)")))return true;
        return false
        },
    addClassName:function(a,b){
        if(!(a=$(a)))return;
        Element.classNames(a).add(b);
        return a
        },
    removeClassName:function(a,b){
        if(!(a=$(a)))return;
        Element.classNames(a).remove(b);
        return a
        },
    toggleClassName:function(a,b){
        if(!(a=$(a)))return;
        Element.classNames(a)[a.hasClassName(b)?'remove':'add'](b);
        return a
        },
    observe:function(){
        Event.observe.apply(Event,arguments);
        return $A(arguments).first()
        },
    stopObserving:function(){
        Event.stopObserving.apply(Event,arguments);
        return $A(arguments).first()
        },
    cleanWhitespace:function(a){
        a=$(a);
        var b=a.firstChild;
        while(b){
            var c=b.nextSibling;
            if(b.nodeType==3&&!/\S/.test(b.nodeValue))a.removeChild(b);
            b=c
            }
            return a
        },
    empty:function(a){
        return $(a).innerHTML.blank()
        },
    descendantOf:function(a,b){
        a=$(a),b=$(b);
        while(a=a.parentNode)if(a==b)return true;
        return false
        },
    scrollTo:function(a){
        a=$(a);
        var b=Position.cumulativeOffset(a);
        window.scrollTo(b[0],b[1]);
        return a
        },
    getStyle:function(a,b){
        a=$(a);
        b=b=='float'?'cssFloat':b.camelize();
        var c=a.style[b];
        if(!c){
            var d=document.defaultView.getComputedStyle(a,null);
            c=d?d[b]:null
            }
            if(b=='opacity')return c?parseFloat(c):1.0;
        return c=='auto'?null:c
        },
    getOpacity:function(a){
        return $(a).getStyle('opacity')
        },
    setStyle:function(a,b,c){
        a=$(a);
        var d=a.style;
        for(var e in b)if(e=='opacity')a.setOpacity(b[e]);else d[(e=='float'||e=='cssFloat')?(d.styleFloat===undefined?'cssFloat':'styleFloat'):(c?e:e.camelize())]=b[e];return a
        },
    setOpacity:function(a,b){
        a=$(a);
        a.style.opacity=(b==1||b==='')?'':(b<0.00001)?0:b;
        return a
        },
    getDimensions:function(a){
        a=$(a);
        var b=$(a).getStyle('display');
        if(b!='none'&&b!=null)return{
            width:a.offsetWidth,
            height:a.offsetHeight
            };

        var c=a.style;
        var d=c.visibility;
        var e=c.position;
        var f=c.display;
        c.visibility='hidden';
        c.position='absolute';
        c.display='block';
        var g=a.clientWidth;
        var h=a.clientHeight;
        c.display=f;
        c.position=e;
        c.visibility=d;
        return{
            width:g,
            height:h
        }
    },
makePositioned:function(a){
    a=$(a);
    var b=Element.getStyle(a,'position');
    if(b=='static'||!b){
        a._madePositioned=true;
        a.style.position='relative';
        if(window.opera){
            a.style.top=0;
            a.style.left=0
            }
        }
    return a
},
undoPositioned:function(a){
    a=$(a);
    if(a._madePositioned){
        a._madePositioned=undefined;
        a.style.position=a.style.top=a.style.left=a.style.bottom=a.style.right=''
        }
        return a
    },
makeClipping:function(a){
    a=$(a);
    if(a._overflow)return a;
    a._overflow=a.style.overflow||'auto';
    if((Element.getStyle(a,'overflow')||'visible')!='hidden')a.style.overflow='hidden';
    return a
    },
undoClipping:function(a){
    a=$(a);
    if(!a._overflow)return a;
    a.style.overflow=a._overflow=='auto'?'':a._overflow;
    a._overflow=null;
    return a
    }
};

Object.extend(Element.Methods,{
    childOf:Element.Methods.descendantOf,
    childElements:Element.Methods.immediateDescendants
    });
if(Prototype.Browser.Opera){
    Element.Methods._getStyle=Element.Methods.getStyle;
    Element.Methods.getStyle=function(a,b){
        switch(b){
            case'left':case'top':case'right':case'bottom':
                if(Element._getStyle(a,'position')=='static')return null;default:
                return Element._getStyle(a,b)
                }
            }
    }else if(Prototype.Browser.IE){
    Element.Methods.getStyle=function(a,b){
        a=$(a);
        b=(b=='float'||b=='cssFloat')?'styleFloat':b.camelize();
        var c=a.style[b];
        if(!c&&a.currentStyle)c=a.currentStyle[b];
        if(b=='opacity'){
            if(c=(a.getStyle('filter')||'').match(/alpha\(opacity=(.*)\)/))if(c[1])return parseFloat(c[1])/100;
            return 1.0
            }
            if(c=='auto'){
            if((b=='width'||b=='height')&&(a.getStyle('display')!='none'))return a['offset'+b.capitalize()]+'px';
            return null
            }
            return c
        };

    Element.Methods.setOpacity=function(a,b){
        a=$(a);
        var c=a.getStyle('filter'),style=a.style;
        if(b==1||b===''){
            style.filter=c.replace(/alpha\([^\)]*\)/gi,'');
            return a
            }else if(b<0.00001)b=0;
        style.filter=c.replace(/alpha\([^\)]*\)/gi,'')+'alpha(opacity='+(b*100)+')';
        return a
        };

    Element.Methods.update=function(b,c){
        b=$(b);
        c=typeof c=='undefined'?'':c.toString();
        var d=b.tagName.toUpperCase();
        if(['THEAD','TBODY','TR','TD'].include(d)){
            var e=document.createElement('div');
            switch(d){
                case'THEAD':case'TBODY':
                    e.innerHTML='<table><tbody>'+c.stripScripts()+'</tbody></table>';
                    depth=2;
                    break;
                case'TR':
                    e.innerHTML='<table><tbody><tr>'+c.stripScripts()+'</tr></tbody></table>';
                    depth=3;
                    break;
                case'TD':
                    e.innerHTML='<table><tbody><tr><td>'+c.stripScripts()+'</td></tr></tbody></table>';
                    depth=4
                    }
                    $A(b.childNodes).each(function(a){
                b.removeChild(a)
                });
            depth.times(function(){
                e=e.firstChild
                });
            $A(e.childNodes).each(function(a){
                b.appendChild(a)
                })
            }else{
            b.innerHTML=c.stripScripts()
            }
            setTimeout(function(){
            c.evalScripts()
            },10);
        return b
        }
    }else if(Prototype.Browser.Gecko){
    Element.Methods.setOpacity=function(a,b){
        a=$(a);
        a.style.opacity=(b==1)?0.999999:(b==='')?'':(b<0.00001)?0:b;
        return a
        }
    }
    Element._attributeTranslations={
    names:{
        colspan:"colSpan",
        rowspan:"rowSpan",
        valign:"vAlign",
        datetime:"dateTime",
        accesskey:"accessKey",
        tabindex:"tabIndex",
        enctype:"encType",
        maxlength:"maxLength",
        readonly:"readOnly",
        longdesc:"longDesc"
    },
    values:{
        _getAttr:function(a,b){
            return a.getAttribute(b,2)
            },
        _flag:function(a,b){
            return $(a).hasAttribute(b)?b:null
            },
        style:function(a){
            return a.style.cssText.toLowerCase()
            },
        title:function(a){
            var b=a.getAttributeNode('title');
            return b.specified?b.nodeValue:null
            }
        }
};
(function(){
    Object.extend(this,{
        href:this._getAttr,
        src:this._getAttr,
        type:this._getAttr,
        disabled:this._flag,
        checked:this._flag,
        readonly:this._flag,
        multiple:this._flag
        })
    }).call(Element._attributeTranslations.values);
Element.Methods.Simulated={
    hasAttribute:function(a,b){
        var t=Element._attributeTranslations,node;
        b=t.names[b]||b;
        node=$(a).getAttributeNode(b);
        return node&&node.specified
        }
    };

Element.Methods.ByTag={};

Object.extend(Element,Element.Methods);
if(!Prototype.BrowserFeatures.ElementExtensions&&document.createElement('div').__proto__){
    window.HTMLElement={};

    window.HTMLElement.prototype=document.createElement('div').__proto__;
    Prototype.BrowserFeatures.ElementExtensions=true
        }
        Element.hasAttribute=function(a,b){
    if(a.hasAttribute)return a.hasAttribute(b);
    return Element.Methods.Simulated.hasAttribute(a,b)
    };

Element.addMethods=function(g){
    var F=Prototype.BrowserFeatures,T=Element.Methods.ByTag;
    if(!g){
        Object.extend(Form,Form.Methods);
        Object.extend(Form.Element,Form.Element.Methods);
        Object.extend(Element.Methods.ByTag,{
            "FORM":Object.clone(Form.Methods),
            "INPUT":Object.clone(Form.Element.Methods),
            "SELECT":Object.clone(Form.Element.Methods),
            "TEXTAREA":Object.clone(Form.Element.Methods)
            })
        }
        if(arguments.length==2){
        var h=g;
        g=arguments[1]
        }
        if(!h)Object.extend(Element.Methods,g||{});
    else{
        if(h.constructor==Array)h.each(extend);else extend(h)
            }
            function extend(a){
        a=a.toUpperCase();
        if(!Element.Methods.ByTag[a])Element.Methods.ByTag[a]={};

        Object.extend(Element.Methods.ByTag[a],g)
        }
        function copy(a,b,c){
        c=c||false;
        var d=Element.extend.cache;
        for(var e in a){
            var f=a[e];
            if(!c||!(e in b))b[e]=d.findOrStore(f)
                }
            }
        function findDOMClass(a){
    var b;
    var c={
        "OPTGROUP":"OptGroup",
        "TEXTAREA":"TextArea",
        "P":"Paragraph",
        "FIELDSET":"FieldSet",
        "UL":"UList",
        "OL":"OList",
        "DL":"DList",
        "DIR":"Directory",
        "H1":"Heading",
        "H2":"Heading",
        "H3":"Heading",
        "H4":"Heading",
        "H5":"Heading",
        "H6":"Heading",
        "Q":"Quote",
        "INS":"Mod",
        "DEL":"Mod",
        "A":"Anchor",
        "IMG":"Image",
        "CAPTION":"TableCaption",
        "COL":"TableCol",
        "COLGROUP":"TableCol",
        "THEAD":"TableSection",
        "TFOOT":"TableSection",
        "TBODY":"TableSection",
        "TR":"TableRow",
        "TH":"TableCell",
        "TD":"TableCell",
        "FRAMESET":"FrameSet",
        "IFRAME":"IFrame"
    };

    if(c[a])b='HTML'+c[a]+'Element';
    if(window[b])return window[b];
    b='HTML'+a+'Element';
    if(window[b])return window[b];
    b='HTML'+a.capitalize()+'Element';
    if(window[b])return window[b];
    window[b]={};

    window[b].prototype=document.createElement(a).__proto__;
    return window[b]
    }
    if(F.ElementExtensions){
    copy(Element.Methods,HTMLElement.prototype);
    copy(Element.Methods.Simulated,HTMLElement.prototype,true)
    }
    if(F.SpecificElementExtensions){
    for(var i in Element.Methods.ByTag){
        var j=findDOMClass(i);
        if(typeof j=="undefined")continue;
        copy(T[i],j.prototype)
        }
    }
    Object.extend(Element,Element.Methods);
delete Element.ByTag
};

var Toggle={
    display:Element.toggle
    };

Abstract.Insertion=function(a){
    this.adjacency=a
    };

Abstract.Insertion.prototype={
    initialize:function(a,b){
        this.element=$(a);
        this.content=b.stripScripts();
        if(this.adjacency&&this.element.insertAdjacentHTML){
            try{
                this.element.insertAdjacentHTML(this.adjacency,this.content)
                }catch(e){
                var c=this.element.tagName.toUpperCase();
                if(['TBODY','TR'].include(c)){
                    this.insertContent(this.contentFromAnonymousTable())
                    }else{
                    throw e;
                }
            }
        }else{
    this.range=this.element.ownerDocument.createRange();
    if(this.initializeRange)this.initializeRange();
    this.insertContent([this.range.createContextualFragment(this.content)])
    }
    setTimeout(function(){
    b.evalScripts()
    },10)
},
contentFromAnonymousTable:function(){
    var a=document.createElement('div');
    a.innerHTML='<table><tbody>'+this.content+'</tbody></table>';
    return $A(a.childNodes[0].childNodes[0].childNodes)
    }
};

var Insertion=new Object();
Insertion.Before=Class.create();
Insertion.Before.prototype=Object.extend(new Abstract.Insertion('beforeBegin'),{
    initializeRange:function(){
        this.range.setStartBefore(this.element)
        },
    insertContent:function(b){
        b.each((function(a){
            this.element.parentNode.insertBefore(a,this.element)
            }).bind(this))
        }
    });
Insertion.Top=Class.create();
Insertion.Top.prototype=Object.extend(new Abstract.Insertion('afterBegin'),{
    initializeRange:function(){
        this.range.selectNodeContents(this.element);
        this.range.collapse(true)
        },
    insertContent:function(b){
        b.reverse(false).each((function(a){
            this.element.insertBefore(a,this.element.firstChild)
            }).bind(this))
        }
    });
Insertion.Bottom=Class.create();
Insertion.Bottom.prototype=Object.extend(new Abstract.Insertion('beforeEnd'),{
    initializeRange:function(){
        this.range.selectNodeContents(this.element);
        this.range.collapse(this.element)
        },
    insertContent:function(b){
        b.each((function(a){
            this.element.appendChild(a)
            }).bind(this))
        }
    });
Insertion.After=Class.create();
Insertion.After.prototype=Object.extend(new Abstract.Insertion('afterEnd'),{
    initializeRange:function(){
        this.range.setStartAfter(this.element)
        },
    insertContent:function(b){
        b.each((function(a){
            this.element.parentNode.insertBefore(a,this.element.nextSibling)
            }).bind(this))
        }
    });
Element.ClassNames=Class.create();
Element.ClassNames.prototype={
    initialize:function(a){
        this.element=$(a)
        },
    _each:function(b){
        this.element.className.split(/\s+/).select(function(a){
            return a.length>0
            })._each(b)
        },
    set:function(a){
        this.element.className=a
        },
    add:function(a){
        if(this.include(a))return;
        this.set($A(this).concat(a).join(' '))
        },
    remove:function(a){
        if(!this.include(a))return;
        this.set($A(this).without(a).join(' '))
        },
    toString:function(){
        return $A(this).join(' ')
        }
    };

Object.extend(Element.ClassNames.prototype,Enumerable);
var Selector=Class.create();
Selector.prototype={
    initialize:function(a){
        this.expression=a.strip();
        this.compileMatcher()
        },
    compileMatcher:function(){
        if(Prototype.BrowserFeatures.XPath&&!(/\[[\w-]*?:/).test(this.expression))return this.compileXPathMatcher();
        var e=this.expression,ps=Selector.patterns,h=Selector.handlers,c=Selector.criteria,le,p,m;
        if(Selector._cache[e]){
            this.matcher=Selector._cache[e];
            return
        }
        this.matcher=["this.matcher = function(root) {","var r = root, h = Selector.handlers, c = false, n;"];
        while(e&&le!=e&&(/\S/).test(e)){
            le=e;
            for(var i in ps){
                p=ps[i];
                if(m=e.match(p)){
                    this.matcher.push(typeof c[i]=='function'?c[i](m):new Template(c[i]).evaluate(m));
                    e=e.replace(m[0],'');
                    break
                }
            }
            }
            this.matcher.push("return h.unique(n);\n}");
    eval(this.matcher.join('\n'));
    Selector._cache[this.expression]=this.matcher
    },
compileXPathMatcher:function(){
    var e=this.expression,ps=Selector.patterns,x=Selector.xpath,le,m;
    if(Selector._cache[e]){
        this.xpath=Selector._cache[e];
        return
    }
    this.matcher=['.//*'];
    while(e&&le!=e&&(/\S/).test(e)){
        le=e;
        for(var i in ps){
            if(m=e.match(ps[i])){
                this.matcher.push(typeof x[i]=='function'?x[i](m):new Template(x[i]).evaluate(m));
                e=e.replace(m[0],'');
                break
            }
        }
        }
        this.xpath=this.matcher.join('');
Selector._cache[this.expression]=this.xpath
},
findElements:function(a){
    a=a||document;
    if(this.xpath)return document._getElementsByXPath(this.xpath,a);
    return this.matcher(a)
    },
match:function(a){
    return this.findElements(document).include(a)
    },
toString:function(){
    return this.expression
    },
inspect:function(){
    return"#<Selector:"+this.expression.inspect()+">"
    }
};

Object.extend(Selector,{
    _cache:{},
    xpath:{
        descendant:"//*",
        child:"/*",
        adjacent:"/following-sibling::*[1]",
        laterSibling:'/following-sibling::*',
        tagName:function(m){
            if(m[1]=='*')return'';
            return"[local-name()='"+m[1].toLowerCase()+"' or local-name()='"+m[1].toUpperCase()+"']"
            },
        className:"[contains(concat(' ', @class, ' '), ' #{1} ')]",
        id:"[@id='#{1}']",
        attrPresence:"[@#{1}]",
        attr:function(m){
            m[3]=m[5]||m[6];
            return new Template(Selector.xpath.operators[m[2]]).evaluate(m)
            },
        pseudo:function(m){
            var h=Selector.xpath.pseudos[m[1]];
            if(!h)return'';
            if(typeof h==='function')return h(m);
            return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m)
            },
        operators:{
            '=':"[@#{1}='#{3}']",
            '!=':"[@#{1}!='#{3}']",
            '^=':"[starts-with(@#{1}, '#{3}')]",
            '$=':"[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
            '*=':"[contains(@#{1}, '#{3}')]",
            '~=':"[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
            '|=':"[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
        },
        pseudos:{
            'first-child':'[not(preceding-sibling::*)]',
            'last-child':'[not(following-sibling::*)]',
            'only-child':'[not(preceding-sibling::* or following-sibling::*)]',
            'empty':"[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
            'checked':"[@checked]",
            'disabled':"[@disabled]",
            'enabled':"[not(@disabled)]",
            'not':function(m){
                var e=m[6],p=Selector.patterns,x=Selector.xpath,le,m,v;
                var a=[];
                while(e&&le!=e&&(/\S/).test(e)){
                    le=e;
                    for(var i in p){
                        if(m=e.match(p[i])){
                            v=typeof x[i]=='function'?x[i](m):new Template(x[i]).evaluate(m);
                            a.push("("+v.substring(1,v.length-1)+")");
                            e=e.replace(m[0],'');
                            break
                        }
                    }
                    }
                    return"[not("+a.join(" and ")+")]"
        },
    'nth-child':function(m){
        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ",m)
        },
    'nth-last-child':function(m){
        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ",m)
        },
    'nth-of-type':function(m){
        return Selector.xpath.pseudos.nth("position() ",m)
        },
    'nth-last-of-type':function(m){
        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ",m)
        },
    'first-of-type':function(m){
        m[6]="1";
        return Selector.xpath.pseudos['nth-of-type'](m)
        },
    'last-of-type':function(m){
        m[6]="1";
        return Selector.xpath.pseudos['nth-last-of-type'](m)
        },
    'only-of-type':function(m){
        var p=Selector.xpath.pseudos;
        return p['first-of-type'](m)+p['last-of-type'](m)
        },
    nth:function(c,m){
        var d,formula=m[6],predicate;
        if(formula=='even')formula='2n+0';
        if(formula=='odd')formula='2n+1';
        if(d=formula.match(/^(\d+)$/))return'['+c+"= "+d[1]+']';
        if(d=formula.match(/^(-?\d*)?n(([+-])(\d+))?/)){
            if(d[1]=="-")d[1]=-1;
            var a=d[1]?Number(d[1]):1;
            var b=d[2]?Number(d[2]):0;
            predicate="[((#{fragment} - #{b}) mod #{a} = 0) and "+"((#{fragment} - #{b}) div #{a} >= 0)]";
            return new Template(predicate).evaluate({
                fragment:c,
                a:a,
                b:b
            })
            }
        }
}
},
criteria:{
    tagName:'n = h.tagName(n, r, "#{1}", c);   c = false;',
    className:'n = h.className(n, r, "#{1}", c); c = false;',
    id:'n = h.id(n, r, "#{1}", c);        c = false;',
    attrPresence:'n = h.attrPresence(n, r, "#{1}"); c = false;',
    attr:function(m){
        m[3]=(m[5]||m[6]);
        return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m)
        },
    pseudo:function(m){
        if(m[6])m[6]=m[6].replace(/"/g,'\\"');
        return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m)
        },
    descendant:'c = "descendant";',
    child:'c = "child";',
    adjacent:'c = "adjacent";',
    laterSibling:'c = "laterSibling";'
},
patterns:{
    laterSibling:new RegExp('^\\s'+'*'+'~\\s*'),
    child:new RegExp('^\\s'+'*'+'>\\s*'),
    adjacent:new RegExp('^\\s'+'*'+'\\+\\s*'),
    descendant:/^\s/,
    tagName:new RegExp('^\\s*'+'(\\'+'*|[\\w\\-]+)(\\b|$)?'),
    id:new RegExp('^#([\\w\\-\\'+'*]+)(\\b|$)'),
    className:new RegExp('^\\.([\\w\\-\\'+'*]+)(\\b|$)'),
    pseudo:new RegExp('^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\\((.*?)\\))?(\\b|$|\\s||(?=:))'),
    attrPresence:new RegExp('^\\[([\\w]+)\\]'),
    attr:new RegExp('\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*(([\'"])([^\\]]*?)\\4|([^\'"][^\\]]*?)))?\\]')
    },
handlers:{
    concat:function(a,b){
        for(var i=0,node;node=b[i];i++)a.push(node);
        return a
        },
    mark:function(a){
        for(var i=0,node;node=a[i];i++)node._counted=true;
        return a
        },
    unmark:function(a){
        for(var i=0,node;node=a[i];i++)node._counted=undefined;
        return a
        },
    index:function(a,b,c){
        a._counted=true;
        if(b){
            for(var d=a.childNodes,i=d.length-1,j=1;i>=0;i--){
                node=d[i];
                if(node.nodeType==1&&(!c||node._counted))node.nodeIndex=j++
            }
            }else{
        for(var i=0,j=1,d=a.childNodes;node=d[i];i++)if(node.nodeType==1&&(!c||node._counted))node.nodeIndex=j++
        }
    },
unique:function(a){
    if(a.length==0)return a;
    var b=[],n;
    for(var i=0,l=a.length;i<l;i++)if(!(n=a[i])._counted){
        n._counted=true;
        b.push(Element.extend(n))
        }
        return Selector.handlers.unmark(b)
    },
descendant:function(a){
    var h=Selector.handlers;
    for(var i=0,results=[],node;node=a[i];i++)h.concat(results,node.getElementsByTagName('*'));
    return results
    },
child:function(a){
    var h=Selector.handlers;
    for(var i=0,results=[],node;node=a[i];i++){
        for(var j=0,children=[],child;child=node.childNodes[j];j++)if(child.nodeType==1&&child.tagName!='!')results.push(child)
            }
            return results
    },
adjacent:function(a){
    for(var i=0,results=[],node;node=a[i];i++){
        var b=this.nextElementSibling(node);
        if(b)results.push(b)
            }
            return results
    },
laterSibling:function(a){
    var h=Selector.handlers;
    for(var i=0,results=[],node;node=a[i];i++)h.concat(results,Element.nextSiblings(node));
    return results
    },
nextElementSibling:function(a){
    while(a=a.nextSibling)if(a.nodeType==1)return a;
    return null
    },
previousElementSibling:function(a){
    while(a=a.previousSibling)if(a.nodeType==1)return a;
    return null
    },
tagName:function(a,b,c,d){
    c=c.toUpperCase();
    var e=[],h=Selector.handlers;
    if(a){
        if(d){
            if(d=="descendant"){
                for(var i=0,node;node=a[i];i++)h.concat(e,node.getElementsByTagName(c));
                return e
                }else a=this[d](a);
            if(c=="*")return a
                }
                for(var i=0,node;node=a[i];i++)if(node.tagName.toUpperCase()==c)e.push(node);return e
        }else return b.getElementsByTagName(c)
        },
id:function(a,b,c,d){
    var e=$(c),h=Selector.handlers;
    if(!a&&b==document)return e?[e]:[];
    if(a){
        if(d){
            if(d=='child'){
                for(var i=0,node;node=a[i];i++)if(e.parentNode==node)return[e]
                    }else if(d=='descendant'){
                for(var i=0,node;node=a[i];i++)if(Element.descendantOf(e,node))return[e]
                    }else if(d=='adjacent'){
                for(var i=0,node;node=a[i];i++)if(Selector.handlers.previousElementSibling(e)==node)return[e]
                    }else a=h[d](a)
                }
                for(var i=0,node;node=a[i];i++)if(node==e)return[e];return[]
        }
        return(e&&Element.descendantOf(e,b))?[e]:[]
    },
className:function(a,b,c,d){
    if(a&&d)a=this[d](a);
    return Selector.handlers.byClassName(a,b,c)
    },
byClassName:function(a,b,c){
    if(!a)a=Selector.handlers.descendant([b]);
    var d=' '+c+' ';
    for(var i=0,results=[],node,nodeClassName;node=a[i];i++){
        nodeClassName=node.className;
        if(nodeClassName.length==0)continue;
        if(nodeClassName==c||(' '+nodeClassName+' ').include(d))results.push(node)
            }
            return results
    },
attrPresence:function(a,b,c){
    var d=[];
    for(var i=0,node;node=a[i];i++)if(Element.hasAttribute(node,c))d.push(node);return d
    },
attr:function(a,b,c,d,e){
    if(!a)a=b.getElementsByTagName("*");
    var f=Selector.operators[e],results=[];
    for(var i=0,node;node=a[i];i++){
        var g=Element.readAttribute(node,c);
        if(g===null)continue;
        if(f(g,d))results.push(node)
            }
            return results
    },
pseudo:function(a,b,c,d,e){
    if(a&&e)a=this[e](a);
    if(!a)a=d.getElementsByTagName("*");
    return Selector.pseudos[b](a,c,d)
    }
},
pseudos:{
    'first-child':function(a,b,c){
        for(var i=0,results=[],node;node=a[i];i++){
            if(Selector.handlers.previousElementSibling(node))continue;
            results.push(node)
            }
            return results
        },
    'last-child':function(a,b,c){
        for(var i=0,results=[],node;node=a[i];i++){
            if(Selector.handlers.nextElementSibling(node))continue;
            results.push(node)
            }
            return results
        },
    'only-child':function(a,b,c){
        var h=Selector.handlers;
        for(var i=0,results=[],node;node=a[i];i++)if(!h.previousElementSibling(node)&&!h.nextElementSibling(node))results.push(node);return results
        },
    'nth-child':function(a,b,c){
        return Selector.pseudos.nth(a,b,c)
        },
    'nth-last-child':function(a,b,c){
        return Selector.pseudos.nth(a,b,c,true)
        },
    'nth-of-type':function(a,b,c){
        return Selector.pseudos.nth(a,b,c,false,true)
        },
    'nth-last-of-type':function(a,b,c){
        return Selector.pseudos.nth(a,b,c,true,true)
        },
    'first-of-type':function(a,b,c){
        return Selector.pseudos.nth(a,"1",c,false,true)
        },
    'last-of-type':function(a,b,c){
        return Selector.pseudos.nth(a,"1",c,true,true)
        },
    'only-of-type':function(a,b,c){
        var p=Selector.pseudos;
        return p['last-of-type'](p['first-of-type'](a,b,c),b,c)
        },
    getIndices:function(a,b,d){
        if(a==0)return b>0?[b]:[];
        return $R(1,d).inject([],function(c,i){
            if(0==(i-b)%a&&(i-b)/a>=0)c.push(i);
            return c
            })
        },
    nth:function(c,d,e,f,g){
        if(c.length==0)return[];
        if(d=='even')d='2n+0';
        if(d=='odd')d='2n+1';
        var h=Selector.handlers,results=[],indexed=[],m;
        h.mark(c);
        for(var i=0,node;node=c[i];i++){
            if(!node.parentNode._counted){
                h.index(node.parentNode,f,g);
                indexed.push(node.parentNode)
                }
            }
        if(d.match(/^\d+$/)){
        d=Number(d);
        for(var i=0,node;node=c[i];i++)if(node.nodeIndex==d)results.push(node)
            }else if(m=d.match(/^(-?\d*)?n(([+-])(\d+))?/)){
        if(m[1]=="-")m[1]=-1;
        var a=m[1]?Number(m[1]):1;
        var b=m[2]?Number(m[2]):0;
        var k=Selector.pseudos.getIndices(a,b,c.length);
        for(var i=0,node,l=k.length;node=c[i];i++){
            for(var j=0;j<l;j++)if(node.nodeIndex==k[j])results.push(node)
                }
            }
        h.unmark(c);
h.unmark(indexed);
return results
},
'empty':function(a,b,c){
    for(var i=0,results=[],node;node=a[i];i++){
        if(node.tagName=='!'||(node.firstChild&&!node.innerHTML.match(/^\s*$/)))continue;
        results.push(node)
        }
        return results
    },
'not':function(a,b,c){
    var h=Selector.handlers,selectorType,m;
    var d=new Selector(b).findElements(c);
    h.mark(d);
    for(var i=0,results=[],node;node=a[i];i++)if(!node._counted)results.push(node);h.unmark(d);
    return results
    },
'enabled':function(a,b,c){
    for(var i=0,results=[],node;node=a[i];i++)if(!node.disabled)results.push(node);return results
    },
'disabled':function(a,b,c){
    for(var i=0,results=[],node;node=a[i];i++)if(node.disabled)results.push(node);return results
    },
'checked':function(a,b,c){
    for(var i=0,results=[],node;node=a[i];i++)if(node.checked)results.push(node);return results
    }
},
operators:{
    '=':function(a,v){
        return a==v
        },
    '!=':function(a,v){
        return a!=v
        },
    '^=':function(a,v){
        return a.startsWith(v)
        },
    '$=':function(a,v){
        return a.endsWith(v)
        },
    '*=':function(a,v){
        return a.include(v)
        },
    '~=':function(a,v){
        return(' '+a+' ').include(' '+v+' ')
        },
    '|=':function(a,v){
        return('-'+a.toUpperCase()+'-').include('-'+v.toUpperCase()+'-')
        }
    },
matchElements:function(a,b){
    var c=new Selector(b).findElements(),h=Selector.handlers;
    h.mark(c);
    for(var i=0,results=[],element;element=a[i];i++)if(element._counted)results.push(element);h.unmark(c);
    return results
    },
findElement:function(a,b,c){
    if(typeof b=='number'){
        c=b;
        b=false
        }
        return Selector.matchElements(a,b||'*')[c||0]
    },
findChildElements:function(a,b){
    var c=b.join(','),b=[];
    c.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/,function(m){
        b.push(m[1].strip())
        });
    var d=[],h=Selector.handlers;
    for(var i=0,l=b.length,selector;i<l;i++){
        selector=new Selector(b[i].strip());
        h.concat(d,selector.findElements(a))
        }
        return(l>1)?h.unique(d):d
    }
});
function $$(){
    return Selector.findChildElements(document,$A(arguments))
    }
    var Form={
    reset:function(a){
        $(a).reset();
        return a
        },
    serializeElements:function(d,e){
        var f=d.inject({},function(a,b){
            if(!b.disabled&&b.name){
                var c=b.name,value=$(b).getValue();
                if(value!=null){
                    if(c in a){
                        if(a[c].constructor!=Array)a[c]=[a[c]];
                        a[c].push(value)
                        }else a[c]=value
                        }
                    }
            return a
        });
    return e?f:Hash.toQueryString(f)
    }
};

Form.Methods={
    serialize:function(a,b){
        return Form.serializeElements(Form.getElements(a),b)
        },
    getElements:function(c){
        return $A($(c).getElementsByTagName('*')).inject([],function(a,b){
            if(Form.Element.Serializers[b.tagName.toLowerCase()])a.push(Element.extend(b));
            return a
            })
        },
    getInputs:function(a,b,c){
        a=$(a);
        var d=a.getElementsByTagName('input');
        if(!b&&!c)return $A(d).map(Element.extend);
        for(var i=0,matchingInputs=[],length=d.length;i<length;i++){
            var e=d[i];
            if((b&&e.type!=b)||(c&&e.name!=c))continue;
            matchingInputs.push(Element.extend(e))
            }
            return matchingInputs
        },
    disable:function(a){
        a=$(a);
        Form.getElements(a).invoke('disable');
        return a
        },
    enable:function(a){
        a=$(a);
        Form.getElements(a).invoke('enable');
        return a
        },
    findFirstElement:function(b){
        return $(b).getElements().find(function(a){
            return a.type!='hidden'&&!a.disabled&&['input','select','textarea'].include(a.tagName.toLowerCase())
            })
        },
    focusFirstElement:function(a){
        a=$(a);
        a.findFirstElement().activate();
        return a
        },
    request:function(a,b){
        a=$(a),b=Object.clone(b||{});
        var c=b.parameters;
        b.parameters=a.serialize(true);
        if(c){
            if(typeof c=='string')c=c.toQueryParams();
            Object.extend(b.parameters,c)
            }
            if(a.hasAttribute('method')&&!b.method)b.method=a.method;
        return new Ajax.Request(a.readAttribute('action'),b)
        }
    };

Form.Element={
    focus:function(a){
        $(a).focus();
        return a
        },
    select:function(a){
        $(a).select();
        return a
        }
    };

Form.Element.Methods={
    serialize:function(a){
        a=$(a);
        if(!a.disabled&&a.name){
            var b=a.getValue();
            if(b!=undefined){
                var c={};

                c[a.name]=b;
                return Hash.toQueryString(c)
                }
            }
        return''
    },
getValue:function(a){
    a=$(a);
    var b=a.tagName.toLowerCase();
    return Form.Element.Serializers[b](a)
    },
clear:function(a){
    $(a).value='';
    return a
    },
present:function(a){
    return $(a).value!=''
    },
activate:function(a){
    a=$(a);
    try{
        a.focus();
        if(a.select&&(a.tagName.toLowerCase()!='input'||!['button','reset','submit'].include(a.type)))a.select()
            }catch(e){}
    return a
    },
disable:function(a){
    a=$(a);
    a.blur();
    a.disabled=true;
    return a
    },
enable:function(a){
    a=$(a);
    a.disabled=false;
    return a
    }
};

var Field=Form.Element;
var $F=Form.Element.Methods.getValue;
Form.Element.Serializers={
    input:function(a){
        switch(a.type.toLowerCase()){
            case'checkbox':case'radio':
                return Form.Element.Serializers.inputSelector(a);
            default:
                return Form.Element.Serializers.textarea(a)
                }
            },
inputSelector:function(a){
    return a.checked?a.value:null
    },
textarea:function(a){
    return a.value
    },
select:function(a){
    return this[a.type=='select-one'?'selectOne':'selectMany'](a)
    },
selectOne:function(a){
    var b=a.selectedIndex;
    return b>=0?this.optionValue(a.options[b]):null
    },
selectMany:function(a){
    var b,length=a.length;
    if(!length)return null;
    for(var i=0,b=[];i<length;i++){
        var c=a.options[i];
        if(c.selected)b.push(this.optionValue(c))
            }
            return b
    },
optionValue:function(a){
    return Element.extend(a).hasAttribute('value')?a.value:a.text
    }
};

Abstract.TimedObserver=function(){};

Abstract.TimedObserver.prototype={
    initialize:function(a,b,c){
        this.frequency=b;
        this.element=$(a);
        this.callback=c;
        this.lastValue=this.getValue();
        this.registerCallback()
        },
    registerCallback:function(){
        setInterval(this.onTimerEvent.bind(this),this.frequency*1000)
        },
    onTimerEvent:function(){
        var a=this.getValue();
        var b=('string'==typeof this.lastValue&&'string'==typeof a?this.lastValue!=a:String(this.lastValue)!=String(a));
        if(b){
            this.callback(this.element,a);
            this.lastValue=a
            }
        }
};

Form.Element.Observer=Class.create();
Form.Element.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{
    getValue:function(){
        return Form.Element.getValue(this.element)
        }
    });
Form.Observer=Class.create();
Form.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{
    getValue:function(){
        return Form.serialize(this.element)
        }
    });
Abstract.EventObserver=function(){};

Abstract.EventObserver.prototype={
    initialize:function(a,b){
        this.element=$(a);
        this.callback=b;
        this.lastValue=this.getValue();
        if(this.element.tagName.toLowerCase()=='form')this.registerFormCallbacks();else this.registerCallback(this.element)
            },
    onElementEvent:function(){
        var a=this.getValue();
        if(this.lastValue!=a){
            this.callback(this.element,a);
            this.lastValue=a
            }
        },
registerFormCallbacks:function(){
    Form.getElements(this.element).each(this.registerCallback.bind(this))
    },
registerCallback:function(a){
    if(a.type){
        switch(a.type.toLowerCase()){
            case'checkbox':case'radio':
                Event.observe(a,'click',this.onElementEvent.bind(this));
                break;
            default:
                Event.observe(a,'change',this.onElementEvent.bind(this));
                break
                }
            }
}
};

Form.Element.EventObserver=Class.create();
Form.Element.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{
    getValue:function(){
        return Form.Element.getValue(this.element)
        }
    });
Form.EventObserver=Class.create();
Form.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{
    getValue:function(){
        return Form.serialize(this.element)
        }
    });
if(!window.Event){
    var Event=new Object()
    }
    Object.extend(Event,{
    KEY_BACKSPACE:8,
    KEY_TAB:9,
    KEY_RETURN:13,
    KEY_ESC:27,
    KEY_LEFT:37,
    KEY_UP:38,
    KEY_RIGHT:39,
    KEY_DOWN:40,
    KEY_DELETE:46,
    KEY_HOME:36,
    KEY_END:35,
    KEY_PAGEUP:33,
    KEY_PAGEDOWN:34,
    element:function(a){
        return $(a.target||a.srcElement)
        },
    isLeftClick:function(a){
        return(((a.which)&&(a.which==1))||((a.button)&&(a.button==1)))
        },
    pointerX:function(a){
        return a.pageX||(a.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft))
        },
    pointerY:function(a){
        return a.pageY||(a.clientY+(document.documentElement.scrollTop||document.body.scrollTop))
        },
    stop:function(a){
        if(a.preventDefault){
            a.preventDefault();
            a.stopPropagation()
            }else{
            a.returnValue=false;
            a.cancelBubble=true
            }
        },
findElement:function(a,b){
    var c=Event.element(a);
    while(c.parentNode&&(!c.tagName||(c.tagName.toUpperCase()!=b.toUpperCase())))c=c.parentNode;
    return c
    },
observers:false,
_observeAndCache:function(a,b,c,d){
    if(!this.observers)this.observers=[];
    if(a.addEventListener){
        this.observers.push([a,b,c,d]);
        a.addEventListener(b,c,d)
        }else if(a.attachEvent){
        this.observers.push([a,b,c,d]);
        a.attachEvent('on'+b,c)
        }
    },
unloadCache:function(){
    if(!Event.observers)return;
    for(var i=0,length=Event.observers.length;i<length;i++){
        Event.stopObserving.apply(this,Event.observers[i]);
        Event.observers[i][0]=null
        }
        Event.observers=false
    },
observe:function(a,b,c,d){
    a=$(a);
    d=d||false;
    if(b=='keypress'&&(Prototype.Browser.WebKit||a.attachEvent))b='keydown';
    Event._observeAndCache(a,b,c,d)
    },
stopObserving:function(a,b,c,d){
    a=$(a);
    d=d||false;
    if(b=='keypress'&&(Prototype.Browser.WebKit||a.attachEvent))b='keydown';
    if(a.removeEventListener){
        a.removeEventListener(b,c,d)
        }else if(a.detachEvent){
        try{
            a.detachEvent('on'+b,c)
            }catch(e){}
    }
}
});
if(Prototype.Browser.IE)Event.observe(window,'unload',Event.unloadCache,false);
var Position={
    includeScrollOffsets:false,
    prepare:function(){
        this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
        this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0
        },
    realOffset:function(a){
        var b=0,valueL=0;
        do{
            b+=a.scrollTop||0;
            valueL+=a.scrollLeft||0;
            a=a.parentNode
            }while(a);
        return[valueL,b]
        },
    cumulativeOffset:function(a){
        var b=0,valueL=0;
        do{
            b+=a.offsetTop||0;
            valueL+=a.offsetLeft||0;
            a=a.offsetParent
            }while(a);
        return[valueL,b]
        },
    positionedOffset:function(a){
        var b=0,valueL=0;
        do{
            b+=a.offsetTop||0;
            valueL+=a.offsetLeft||0;
            a=a.offsetParent;
            if(a){
                if(a.tagName=='BODY')break;
                var p=Element.getStyle(a,'position');
                if(p=='relative'||p=='absolute')break
            }
        }while(a);
    return[valueL,b]
    },
offsetParent:function(a){
    if(a.offsetParent)return a.offsetParent;
    if(a==document.body)return a;
    while((a=a.parentNode)&&a!=document.body)if(Element.getStyle(a,'position')!='static')return a;
    return document.body
    },
within:function(a,x,y){
    if(this.includeScrollOffsets)return this.withinIncludingScrolloffsets(a,x,y);
    this.xcomp=x;
    this.ycomp=y;
    this.offset=this.cumulativeOffset(a);
    return(y>=this.offset[1]&&y<this.offset[1]+a.offsetHeight&&x>=this.offset[0]&&x<this.offset[0]+a.offsetWidth)
    },
withinIncludingScrolloffsets:function(a,x,y){
    var b=this.realOffset(a);
    this.xcomp=x+b[0]-this.deltaX;
    this.ycomp=y+b[1]-this.deltaY;
    this.offset=this.cumulativeOffset(a);
    return(this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+a.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+a.offsetWidth)
    },
overlap:function(a,b){
    if(!a)return 0;
    if(a=='vertical')return((this.offset[1]+b.offsetHeight)-this.ycomp)/b.offsetHeight;
    if(a=='horizontal')return((this.offset[0]+b.offsetWidth)-this.xcomp)/b.offsetWidth
        },
page:function(a){
    var b=0,valueL=0;
    var c=a;
    do{
        b+=c.offsetTop||0;
        valueL+=c.offsetLeft||0;
        if(c.offsetParent==document.body)if(Element.getStyle(c,'position')=='absolute')break
    }while(c=c.offsetParent);
    c=a;
    do{
        if(!window.opera||c.tagName=='BODY'){
            b-=c.scrollTop||0;
            valueL-=c.scrollLeft||0
            }
        }while(c=c.parentNode);
return[valueL,b]
},
clone:function(a,b){
    var c=Object.extend({
        setLeft:true,
        setTop:true,
        setWidth:true,
        setHeight:true,
        offsetTop:0,
        offsetLeft:0
    },arguments[2]||{});
    a=$(a);
    var p=Position.page(a);
    b=$(b);
    var d=[0,0];
    var e=null;
    if(Element.getStyle(b,'position')=='absolute'){
        e=Position.offsetParent(b);
        d=Position.page(e)
        }
        if(e==document.body){
        d[0]-=document.body.offsetLeft;
        d[1]-=document.body.offsetTop
        }
        if(c.setLeft)b.style.left=(p[0]-d[0]+c.offsetLeft)+'px';
    if(c.setTop)b.style.top=(p[1]-d[1]+c.offsetTop)+'px';
    if(c.setWidth)b.style.width=a.offsetWidth+'px';
    if(c.setHeight)b.style.height=a.offsetHeight+'px'
        },
absolutize:function(a){
    a=$(a);
    if(a.style.position=='absolute')return;
    Position.prepare();
    var b=Position.positionedOffset(a);
    var c=b[1];
    var d=b[0];
    var e=a.clientWidth;
    var f=a.clientHeight;
    a._originalLeft=d-parseFloat(a.style.left||0);
    a._originalTop=c-parseFloat(a.style.top||0);
    a._originalWidth=a.style.width;
    a._originalHeight=a.style.height;
    a.style.position='absolute';
    a.style.top=c+'px';
    a.style.left=d+'px';
    a.style.width=e+'px';
    a.style.height=f+'px'
    },
relativize:function(a){
    a=$(a);
    if(a.style.position=='relative')return;
    Position.prepare();
    a.style.position='relative';
    var b=parseFloat(a.style.top||0)-(a._originalTop||0);
    var c=parseFloat(a.style.left||0)-(a._originalLeft||0);
    a.style.top=b+'px';
    a.style.left=c+'px';
    a.style.height=a._originalHeight;
    a.style.width=a._originalWidth
    }
};

if(Prototype.Browser.WebKit){
    Position.cumulativeOffset=function(a){
        var b=0,valueL=0;
        do{
            b+=a.offsetTop||0;
            valueL+=a.offsetLeft||0;
            if(a.offsetParent==document.body)if(Element.getStyle(a,'position')=='absolute')break;
            a=a.offsetParent
            }while(a);
        return[valueL,b]
        }
    }
    Element.addMethods();
