var Prototype={
	Version:'1.5.0_rc0',ScriptFragment:'(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',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 (destination,source)
{
	for(var property in source){
		destination[property]=source[property];
		
	}
	return destination;
};

Object.inspect=function (object)
{
	try{
		if(object==undefined){
			return 'undefined';
			
		}
		if(object==null){
			return 'null';
			
		}
		return object.inspect?object.inspect():object.toString ();
		
	}catch(e)
	{
		if(e instanceof RangeError){
			return '...';
			
		}
		throw e;
	}
};
Function.prototype.bind=function ()
{
	var __method=this,args=$A(arguments),object=args.shift();
	return function (){
		return __method.apply(object,args.concat($A(arguments)));
		
	};
};
Function.prototype.bindAsEventListener=function (object)
{
	var __method=this;
	return function (event){
		return __method.call(object,event||window.event);
		
	};
};

Object.extend(Number.prototype,{
	toColorPart:function (){
		var digits=this.toString (16);
		if(this<16){
			return '0'+digits;
			
		}
		return digits;
		
	},succ:function (){
		return this+1;
		
	},times:function (iterator){
		$R(0,this,true).each(iterator);
		return this;
		
	}
});


var PeriodicalExecuter=Class.create();

PeriodicalExecuter.prototype=
{
	initialize:function (callback,frequency){
		this.callback=callback;
		this.frequency=frequency;
		this.currentlyExecuting=false;
		this.registerCallback();
		
	},registerCallback:function (){
		setInterval(this.onTimerEvent.bind(this),this.frequency*1000);
		
	},onTimerEvent:function (){
		if(!this.currentlyExecuting){
			try{
				this.currentlyExecuting=true;
				this.callback();
				
			}finally{
				this.currentlyExecuting=false;
				
			}
		}
	}
};

Object.extend(String.prototype,
    {
	    gsub:function (pattern,replacement)
	    {
		    var result='',source=this,match;
		    replacement=arguments.callee.prepareReplacement(replacement);
		    while(source.length>0)
		    {
			    if(source.match(pattern)){
				    match=source.match(pattern);
				    result+=source.slice(0,match.index);
				    result+=(replacement(match)||'').toString ();
				    source=source.slice(match.index+match[0].length);
    				
			    }else 
			    {
				    result+=source;
				    source='';
			    }
		    }
		    return result;
	    },
	    sub:function (pattern,replacement,count)
	    {
		    replacement=this.gsub.prepareReplacement(replacement);
		    count=count===undefined?1:count;
		    return this.gsub(pattern,function (match){
			    if(--count<0){
				    return match[0];
    				
			    }
			    return replacement(match);
    			
		    });
		
	    },
	    scan:function (pattern,iterator)
	    {
		    this.gsub(pattern,iterator);
		    return this;
	    },
	    truncate:function (length,truncation)
	    {
		    length=length||30;
		    truncation=truncation===undefined?'...':truncation;
		    return this.length>length?this.slice(0,length-truncation.length)+truncation: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 matchAll=new RegExp(Prototype.ScriptFragment,'img');
		    var matchOne=new RegExp(Prototype.ScriptFragment,'im');
		    return (this.match(matchAll)||[]).map(function (scriptTag)
		    {
			    return (scriptTag.match(matchOne)||['',''])[1];
			});
		
	    },evalScripts:function ()
	    {
		    return this.extractScripts().map(function (script){
			    return eval(script);
    			
		    });
	    },escapeHTML:function ()
	    {
		    var div=document.createElement('div');
		    var text=document.createTextNode(this);
		    div.appendChild(text);
		    return div.innerHTML;
	    },unescapeHTML:function ()
	    {
		    var div=document.createElement('div');
		    div.innerHTML=this.stripTags();
		    return div.childNodes[0]?div.childNodes[0].nodeValue:'';
	    },convertTextToHTML:function ()
	    {
		    return(this.replace(/\&/g,"&").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\r\n|\n|\r/g,"<br \/>").replace(/  /g,"&nbsp; "));
	    },convertHTMLToText:function (){
		    return(this.replace(/(\s*(\r\n|\n|\r)\s*)/g,"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/<br\s*\/?>/ig,"\r\n").replace(/\&nbsp;/g," "));
	    },trim:function ()
	    {
		    return (this.replace(/(^\s*)|(\s*$)/g,""));
	    },toQueryParams:function ()
	    {
		    var pairs=this.match(/^\??(.*)$/)[1].split('&');
		    return pairs.inject({},function (params,pairString){
			    var pair=pairString.split('=');
			    params[pair[0]]=pair[1];
			    return params;
    			
		    });
	    },toArray:function ()
	    {
		    return this.split('');
		},camelize:function ()
		{
		    var oStringList=this.split('-');
		    if(oStringList.length==1){
			    return oStringList[0];}
		    var camelizedString=this.indexOf('-')==0?oStringList[0].charAt(0).toUpperCase()+oStringList[0].substring(1):oStringList[0];
		    for(var i=1,len=oStringList.length;i<len;i++){
			    var s=oStringList[i];
			    camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);
    			
		    }
		    return camelizedString;
	     },inspect:function ()
	    {
		    return "'"+this.replace(/\\/g,'\\\\').replace(/'/g,'\\\'')+"'";}});String.prototype.gsub.prepareReplacement=function(replacement){if(typeof replacement=='function'){return replacement;}
		    var template=new Template(replacement);
		    return function (match)
		    {
			    return template.evaluate(match);
			};
		};
	String.prototype.parseQuery=String.prototype.toQueryParams;
	var Template=Class.create();
	Template.Pattern=/(^|.|\r|\n)(#\{(.*?)\})/;
	Template.prototype={
		initialize:function (template,pattern){
			this.template=template.toString ();
			this.pattern=pattern||Template.Pattern;
			
		},evaluate:function (object){
			return this.template.gsub(this.pattern,function (match){
				var before=match[1];
				if(before=='\\'){
					return match[2];
					
				}
				return before+(object[match[3]]||'').toString ();
				
			});
			
		}
	};
	var $break=new Object();
	var $continue=new Object();
	var Enumerable={
		each:function (iterator)
		{
			var index=0;
			try{
				    this._each(function (value)
				    {
					    try
					    {
					        iterator(value,index++);
					    }
					    catch(e)
					    {
						    if(e!=$continue)
						    {
							    throw e;
						    }
					    }
				    });
				
			    }catch(e)
			    {
				    if(e!=$break)
				    {
					    throw e;
				    }
			    }
		},all:function (iterator){
			var result=true;
			this.each(function (value,index){
				result=result&&!!(iterator||Prototype.K)(value,index);
				if(!result){
					throw$break;
					
				}
			});
			return result;
			
		},any:function (iterator){
			var result=false;
			this.each(function (value,index){
				if(!!(iterator||Prototype.K)(value,index)){
					result=!!(iterator||Prototype.K)(value,index);
					throw$break;
					
				}
			});
			return result;
			
		},collect:function (iterator){
			var results=[];
			this.each(function (value,index){
				results.push(iterator(value,index));
				
			});
			return results;
			
		},detect:function (iterator){
			var result;
			this.each(function (value,index){
				if(iterator(value,index)){
					result=value;
					throw$break;
					
				}
			});
			return result;
			
		},findAll:function (iterator){
			var results=[];
			this.each(function (value,index){
				if(iterator(value,index)){
					results.push(value);
					
				}
			});
			return results;
			
		},grep:function (pattern,iterator){
			var results=[];
			this.each(function (value,index){
				var stringValue=value.toString ();
				if(stringValue.match(pattern)){
					results.push((iterator||Prototype.K)(value,index));
					
				}
			});
			return results;
			
		},include:function (object){
			var found=false;
			this.each(function (value){
				if(value==object){
					found=true;
					throw$break;
					
				}
			});
			return found;
			
		},inject:function (memo,iterator){
			this.each(function (value,index){
				memo=iterator(memo,value,index);
				
			});
			return memo;
			
		},invoke:function (method){
			var args=$A(arguments).slice(1);
			return this.collect(function (value){
				return value[method].apply(value,args);
				
			});
			
		},max:function (iterator){
			var result;
			this.each(function (value,index){
				value=(iterator||Prototype.K)(value,index);
				if(result==undefined||value>=result){
					result=value;
					
				}
			});
			return result;
			
		},min:function (iterator){
			var result;
			this.each(function (value,index){
				value=(iterator||Prototype.K)(value,index);
				if(result==undefined||value<result){
					result=value;
					
				}
			});
			return result;
			
		},partition:function (iterator){
			var trues=[],falses=[];
			this.each(function (value,index){
				((iterator||Prototype.K)(value,index)?trues:falses).push(value);
				
			});
			return [trues,falses];
			
		},pluck:function (property){
			var results=[];
			this.each(function (value,index){
				results.push(value[property]);
				
			});
			return results;
			
		},reject:function (iterator){
			var results=[];
			this.each(function (value,index){
				if(!iterator(value,index)){
					results.push(value);
					
				}
			});
			return results;
			
		},sortBy:function (iterator){
			return this.collect(function (value,index){
				return {
					value:value,criteria:iterator(value,index)
				};
				
			}).sort(function (left,right){
				var a=left.criteria,b=right.criteria;
				return a<b?-1:a>b?1:0;
				
			}).pluck('value');
			
		},toArray:function (){
			return this.collect(Prototype.K);
			
		},zip:function (){
			var iterator=Prototype.K,args=$A(arguments);
			if(typeof args.last()=='function'){
				iterator=args.pop();
				
			}
			var collections=[this].concat(args).map($A);
			return this.map(function (value,index){
				return iterator(collections.pluck(index));
				
			});
			
		},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
//	});
	Array.from=function (iterable){
		if(!iterable){
			return [];
			
		}
		if(iterable.toArray){
			return iterable.toArray();
			
		}else {
			var results=[];
			var l=iterable.length;
			for(var i=0;i<l;i++){
				results.push(iterable[i]);
				
			}
			return results;
			
		}
	};
	var $A=Array.from;
	Object.extend(Array.prototype,Enumerable);
	if(!Array.prototype._reverse){
		Array.prototype._reverse=Array.prototype.reverse;
		
	}
	
	var Hash={
		_each:function (iterator){
			for(var key in this){
				var value=this[key];
				if(typeof value=='function'){
					continue;
					
				}
				var pair=[key,value];
				pair.key=key;
				pair.value=value;
				iterator(pair);
				
			}
		},keys:function (){
			return this.pluck('key');
			
		},values:function (){
			return this.pluck('value');
			
		},merge:function (hash){
			return $H(hash).inject($H(this),function (mergedHash,pair){
				mergedHash[pair.key]=pair.value;
				return mergedHash;
				
			});
			
		},toQueryString:function (){
			return this.map(function (pair){
				return pair.map(encodeURIComponent).join('=');
				
			}).join('&');
			
		},inspect:function (){
			return '#<Hash:{'+this.map(function (pair){
				return pair.map(Object.inspect).join(': ');
				
			}).join(', ')+'}>';
			
		}
	};
	function $H(object){
		var hash=Object.extend({
			
		},object||{
			
		});
		Object.extend(hash,Enumerable);
		Object.extend(hash,Hash);
		return hash;
		
	}
	ObjectRange=Class.create();
	Object.extend(ObjectRange.prototype,Enumerable);
	Object.extend(ObjectRange.prototype,{
		initialize:function (start,end,exclusive){
			this.start=start;
			this.end=end;
			this.exclusive=exclusive;
			
		},_each:function (iterator){
			var value=this.start;
			do{
				iterator(value);
				value=value.succ();
				
			}while(this.include(value));
			
		},include:function (value){
			if(value<this.start){
				return false;
				
			}
			if(this.exclusive){
				return value<this.end;
				
			}
			return value<=this.end;
			
		}
	});
	var $R=function (start,end,exclusive){
		return new ObjectRange(start,end,exclusive);
		
	};	
	
	function $(){
		var results=[],element;
		for(var i=0;i<arguments.length;i++){
			element=arguments[i];
			if(typeof element=='string'){
				element=document.getElementById(element);
				
			}
			try{
				results.push(Element.extend(element));
				
			}catch(e){
				results.push(element);
				
			}
		}
		return results.length<2?results[0]:results;
		
	}

	if(!window.Element){
		var Element=new Object();
		
	}
	Element.extend=function (element){
		if(!element){
			return null;
			
		}
		if(_nativeExtensions){
			return element;
			
		}
		if(!element._extended&&element.tagName&&element!=window){
			var methods=Element.Methods,cache=Element.extend.cache;
			for(property in methods){
				var value=methods[property];
				if(typeof value=='function'){
					element[property]=cache.findOrStore(value);
					
				}
			}
		}
		element._extended=true;
		return element;
		
	};
	Element.extend.cache={
		findOrStore:function (value){
			this[value]=this[value]||function (){
				return value.apply(null,[this].concat($A(arguments)));
				
			};
			return this[value];
			
		}
	};
	Element.Methods={
		visible:function (element){
			return $(element).style.display!='none';
			
		},toggle:function (){
			for(var i=0;i<arguments.length;i++){
				var element=$(arguments[i]);
				Element[Element.visible(element)?'hide':'show'](element);
				
			}
		},hide:function (){
			for(var i=0;i<arguments.length;i++){
				var element=$(arguments[i]);
				element.style.display='none';
				
			}
		},show:function (){
			for(var i=0;i<arguments.length;i++){
				var element=$(arguments[i]);
				element.style.display='';
				
			}
		},remove:function (element){
			element=$(element);
			element.parentNode.removeChild(element);
			
		},update:function (element,html){
			$(element).innerHTML=html.stripScripts();
			setTimeout(function (){
				html.evalScripts();
				
			},10);
			
		},replace:function (element,html){
			element=$(element);
			if(element.outerHTML){
				element.outerHTML=html.stripScripts();
				
			}else {
				var range=element.ownerDocument.createRange();
				range.selectNodeContents(element);
				element.parentNode.replaceChild(range.createContextualFragment(html.stripScripts()),element);
				
			}
			setTimeout(function (){
				html.evalScripts();
				
			},10);
			
		},getWidth:function (element){
			element=$(element);
			return element.offsetWidth;
			
		},getHeight:function (element){
			element=$(element);
			return element.offsetHeight;
			
		},classNames:function (element){
			return new Element.ClassNames(element);
			
		},hasClassName:function (element,className){
			if(!(element=$(element))){
				return ;
				
			}
			return Element.classNames(element).include(className);
			
		},addClassName:function (element,className){
			if(!(element=$(element))){
				return ;
				
			}
			return Element.classNames(element).add(className);
			
		},removeClassName:function (element,className){
			if(!(element=$(element))){
				return ;
				
			}
			return Element.classNames(element).remove(className);
			
		},swapClassName:function (element){
			element=$(element);
			for(var i=1;i<arguments.length;i++){
				if(element.className==arguments[i]){
					element.className=(i==arguments.length-1?arguments[1]:arguments[i+1]);
					break;
					
				}
			}
		},getParentElementByTagName:function (element,tagName){
			element=$(element);
			while(element.tagName!=tagName){
				element=element.parentNode;
				
			}
			return element;
			
		},getChildElementByTagName:function (element,tagName){
			element=$(element);
			var ln=element.childNodes.length;
			var arr=[];
			for(var i=0;i<ln;i++){
				if(element.childNodes[i].nodeName.toLowerCase()==tagName){
					arr.push(element.childNodes[i]);
					
				}
			}
			return arr;
			
		},getParentElementByClassName:function (element,_className){
			element=$(element);
			while(element.className!=_className){
				element=element.parentNode;
				
			}
			return element;
			
		},getChildValueByTagName:function (element,tagName){
			element=$(element);
			var arr=$A(element.getElementsByTagName(tagName)).map(function (c){
				return (c.firstChild)?((c.firstChild.nodetype!=1)?c.firstChild.data:null):'';
				
			});
			return arr;
			
		},cleanWhitespace:function (element){
			element=$(element);
			for(var i=0;i<element.childNodes.length;i++){
				var node=element.childNodes[i];
				if(node.nodeType==3&&(!(/\S/.test(node.nodeValue)))){
					Element.remove(node);
					i--;
					
				}
				if(node.nodeType==1){
					Element.cleanWhitespace(node);
					
				}
			}
		},empty:function (element){
			return $(element).innerHTML.match(/^\s*$/);
			
		},childOf:function (element,ancestor){
			element=$(element);
			ancestor=$(ancestor);
			while(element.parentNode){
				element=element.parentNode;
				if(element==ancestor){
					return true;
					
				}
			}
			return false;
			
		},scrollTo:function (element){
			element=$(element);
			var x=element.x?element.x:element.offsetLeft,y=element.y?element.y:element.offsetTop;
			window.scrollTo(x,y);
			
		},getStyle:function (element,style){
			element=$(element);
			var value=element.style[style.camelize()];
			if(!value){
				if(document.defaultView&&document.defaultView.getComputedStyle){
					var css=document.defaultView.getComputedStyle(element,null);
					value=css?css.getPropertyValue(style):null;
					
				}else if(element.currentStyle){
					value=element.currentStyle[style.camelize()];
					
				}
			}
			if(window.opera&&['left','top','right','bottom'].include(style)){
				if(Element.getStyle(element,'position')=='static'){
					value='auto';
					
				}
			}
			return value=='auto'?null:value;
			
		},setStyle:function (element,style){
			element=$(element);
			for(var name in style){
				element.style[name.camelize()]=style[name];
				
			}
		},getDimensions:function (element){
			element=$(element);
			if(Element.getStyle(element,'display')!='none'){
				return {
					width:element.offsetWidth,height:element.offsetHeight
				};
				
			}
			var els=element.style;
			var originalVisibility=els.visibility;
			var originalPosition=els.position;
			els.visibility='hidden';
			els.position='absolute';
			els.display='';
			var originalWidth=element.clientWidth;
			var originalHeight=element.clientHeight;
			els.display='none';
			els.position=originalPosition;
			els.visibility=originalVisibility;
			return {
				width:originalWidth,height:originalHeight
			};
			
		},makePositioned:function (element){
			element=$(element);
			var pos=Element.getStyle(element,'position');
			if(pos=='static'||!pos){
				element._madePositioned=true;
				element.style.position='relative';
				if(window.opera){
					element.style.top=0;
					element.style.left=0;
					
				}
			}
		},undoPositioned:function (element){
			element=$(element);
			if(element._madePositioned){
				element._madePositioned=undefined;
				element.style.position=element.style.top=element.style.left=element.style.bottom=element.style.right='';
				
			}
		},makeClipping:function (element){
			element=$(element);
			if(element._overflow){
				return ;
				
			}
			element._overflow=element.style.overflow;
			if((Element.getStyle(element,'overflow')||'visible')!='hidden'){
				element.style.overflow='hidden';
				
			}
		},undoClipping:function (element){
			element=$(element);
			if(element._overflow){
				return ;
				
			}
			element.style.overflow=element._overflow;
			element._overflow=undefined;
			
		}
	};
	Object.extend(Element,Element.Methods);
	var _nativeExtensions=false;
	if(!HTMLElement&&(/Konqueror|Safari|KHTML/.test(navigator.userAgent))){
		var HTMLElement={
			
		};
		HTMLElement.prototype=document.createElement('div').__proto__;
		
	}
	Element.addMethods=function (methods){
		Object.extend(Element.Methods,methods||{
			
		});
		if(typeof HTMLElement != 'undefined'){
			var methods=Element.Methods,cache=Element.extend.cache;
			for(property in methods){
				var value=methods[property];
				if(typeof value=='function'){
					HTMLElement.prototype[property]=cache.findOrStore(value);
					
				}
			}
			_nativeExtensions=true;
			
		}
	};
	Element.addMethods();
	var Toggle=new Object();
	Toggle.display=Element.toggle;
	Abstract.Insertion=function (adjacency){
		this.adjacency=adjacency;
		
	};
	Abstract.Insertion.prototype={
		initialize:function (element,content){
			this.element=$(element);
			this.content=content.stripScripts();
			if(this.adjacency&&this.element.insertAdjacentHTML){
				try{
					this.element.insertAdjacentHTML(this.adjacency,this.content);
					
				}catch(e){
					var tagName=this.element.tagName.toLowerCase();
					if(tagName=='tbody'||tagName=='tr'){
						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 (){
				content.evalScripts();
				
			},10);
			
		},contentFromAnonymousTable:function (){
			var div=document.createElement('div');
			div.innerHTML='<table><tbody>'+this.content+'</tbody></table>';
			return $A(div.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 (fragments){
			fragments.each((function (fragment){
				this.element.parentNode.insertBefore(fragment,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 (fragments){
			fragments.reverse(false).each((function (fragment){
				this.element.insertBefore(fragment,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 (fragments){
			fragments.each((function (fragment){
				this.element.appendChild(fragment);
				
			}).bind(this));
			
		}
	});
	Insertion.After=Class.create();
	Insertion.After.prototype=Object.extend(new Abstract.Insertion('afterEnd'),{
		initializeRange:function (){
			this.range.setStartAfter(this.element);
			
		},insertContent:function (fragments){
			fragments.each((function (fragment){
				this.element.parentNode.insertBefore(fragment,this.element.nextSibling);
				
			}).bind(this));
			
		}
	});
	Element.ClassNames=Class.create();
	Element.ClassNames.prototype={
		initialize:function (element){
			this.element=$(element);
			
		},_each:function (iterator){
			this.element.className.split(/\s+/).select(function (name){
				return name.length>0;
				
			})._each(iterator);
			
		},set:function (className){
			this.element.className=className;
			
		},add:function (classNameToAdd){
			if(this.include(classNameToAdd)){
				return ;
				
			}
			this.set(this.toArray().concat(classNameToAdd).join(' '));
			
		},remove:function (classNameToRemove){
			if(!this.include(classNameToRemove)){
				return ;
				
			}
			this.set(this.select(function (className){
				return className!=classNameToRemove;
				
			}).join(' '));
			
		},toString :function (){
			return this.toArray().join(' ');
			
		}
	};
	Object.extend(Element.ClassNames.prototype,Enumerable);
	var Selector=Class.create();
	Selector.prototype={
		initialize:function (expression){
			this.params={
				classNames:[]
			};
			this.expression=expression.toString ().strip();
			this.parseExpression();
			this.compileMatcher();
			
		},parseExpression:function (){
			function abort(message){
				throw'Parse error in selector: '+message;
				
			}
			if(this.expression==''){
				abort('empty expression');
				
			}
			var params=this.params,expr=this.expression,match,modifier,clause,rest;
			while(expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)){match=expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i);
			params.attributes=params.attributes||[];
			params.attributes.push({
				name:match[2],operator:match[3],value:match[4]||match[5]||''
			});
			expr=match[1];
			
		}
		if(expr=='*'){
			this.params.wildcard=true;
			return this.params.wildcard;
			
		}
		while(expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)){
			match=expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i);
			modifier=match[1];
			clause=match[2];
			rest=match[3];
			switch(modifier){
				case '#':params.id=clause;
				break;
				case '.':params.classNames.push(clause);
				break;
				case '':case undefined:params.tagName=clause.toUpperCase();
				break;
				default:abort(expr.inspect());
				
			}
			expr=rest;
			
		}
		if(expr.length>0){
			abort(expr.inspect());
			
		}
	},buildMatchExpression:function (){
		var params=this.params,conditions=[],clause;
		if(params.wildcard){
			conditions.push('true');
			
		}
		if(params.id){
			clause=params.id;
			conditions.push('element.id == '+clause.inspect());
			
		}
		if(params.tagName){
			clause=params.tagName;
			conditions.push('element.tagName.toUpperCase() == '+clause.inspect());
			
		}
		if(params.classNames.length>0){
			clause=params.classNames;
			for(var i=0;i<clause.length;i++){
				conditions.push('Element.hasClassName(element, '+clause[i].inspect()+')');
				
			}
		}
		if(params.attributes){
			clause=params.attributes;
			clause.each(function (attribute){
				var value='element.getAttribute('+attribute.name.inspect()+')';
				var splitValueBy=function (delimiter){
					return value+' && '+value+'.split('+delimiter.inspect()+')';
					
				};
				switch(attribute.operator){
					case '=':conditions.push(value+' == '+attribute.value.inspect());
					break;
					case '~=':conditions.push(splitValueBy(' ')+'.include('+attribute.value.inspect()+')');
					break;
					case '|=':conditions.push(splitValueBy('-')+'.first().toUpperCase() == '+attribute.value.toUpperCase().inspect());
					break;
					case '!=':conditions.push(value+' != '+attribute.value.inspect());
					break;
					case '':case undefined:conditions.push(value+' != null');
					break;
					default:throw'Unknown operator '+attribute.operator+' in selector';
					
				}
			});
			
		}
		return conditions.join(' && ');
		
	},compileMatcher:function (){
		this.match=new Function('element','if (!element.tagName) return false; return '+this.buildMatchExpression());
		
	},findElements:function (scope){
		var element;
		if($(this.params.id)){
			element=$(this.params.id);
			if(this.match(element)){
				if(!scope||Element.childOf(element,scope)){
					return [element];
					
				}
			}
		}
		scope=(scope||document).getElementsByTagName(this.params.tagName||'*');
		var results=[];
		for(var i=0;i<scope.length;i++){
			if(this.match(element=scope[i])){
				results.push(Element.extend(element));
				
			}
		}
		return results;
		
	},toString :function (){
		return this.expression;
		
	}
};

Abstract.TimedObserver=function (){
	
};
Abstract.TimedObserver.prototype={
	initialize:function (element,frequency,callback){
		this.frequency=frequency;
		this.element=$(element);
		this.callback=callback;
		this.lastValue=this.getValue();
		this.registerCallback();
		
	},registerCallback:function (){
		setInterval(this.onTimerEvent.bind(this),this.frequency*1000);
		
	},onTimerEvent:function (){
		var value=this.getValue();
		if(this.lastValue!=value){
			this.callback(this.element,value);
			this.lastValue=value;
			
		}
	}
};


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,element:function (event){
		return event.target||event.srcElement;
		
	},isLeftClick:function (event){
		return (((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));
		
	},pointerX:function (event){
		return event.pageX||(event.clientX+
		(document.documentElement.scrollLeft||document.body.scrollLeft));
		
	},pointerY:function (event){
		return event.pageY||(event.clientY+
		(document.documentElement.scrollTop||document.body.scrollTop));
		
	},stop:function (event){
		if(event.preventDefault){
			event.preventDefault();
			event.stopPropagation();
			
		}else {
			event.returnValue=false;
			event.cancelBubble=true;
			
		}
	},findElement:function (event,tagName){
		var element=Event.element(event);
		while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase()))){
			element=element.parentNode;
			
		}
		return element;
		
	},observers:false,_observeAndCache:function (element,name,observer,useCapture){
		if(!this.observers){
			this.observers=[];
			
		}
		if(element.addEventListener){
			this.observers.push([element,name,observer,useCapture]);
			element.addEventListener(name,observer,useCapture);
			
		}else if(element.attachEvent){
			this.observers.push([element,name,observer,useCapture]);
			element.attachEvent('on'+name,observer);
			
		}
	},unloadCache:function (){
		if(!Event.observers){
			return ;
			
		}
		for(var i=0;i<Event.observers.length;i++){
			Event.stopObserving.apply(this,Event.observers[i]);
			Event.observers[i][0]=null;
			
		}
		Event.observers=false;
		
	},observe:function (element,name,observer,useCapture){
		var element=$(element);
		useCapture=useCapture||false;
		if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent)){
			name='keydown';
			
		}
		this._observeAndCache(element,name,observer,useCapture);
		
	},stopObserving:function (element,name,observer,useCapture){
		var element=$(element);
		useCapture=useCapture||false;
		if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent)){
			name='keydown';
			
		}
		try
		{
		if(element.removeEventListener)
		{
			element.removeEventListener(name,observer,useCapture);
			
		}else if(element.detachEvent)
		{
			element.detachEvent('on'+name,observer);
		}
		}
		catch(e)
		{}
	}
});
if(navigator.appVersion.match(/\bMSIE\b/)){
	Event.observe(window,'unload',Event.unloadCache,false);
	
}