/** funs from fb **/
function gen_unique(){
    return++gen_unique._counter;
}

gen_unique._counter=0;

function ge(id){
    if(typeof(id)=='undefined'){
	return null;
    }
    var obj;
    if(typeof(id)=='string'){
	obj=document.getElementById(id);
	if(!(ua.ie()>=7)){
	    return obj;
	}

	if(!obj){
	    return null;
	}else if(typeof(obj.id)=='string'&&obj.id==id){
	    return obj;
	}else{
	    var candidates=document.getElementsByName(id);
	    if(!candidates||!candidates.length){
		return null;
	    }
	    var maybe=[];
	    for(var ii=0;ii<candidates.length;ii++){
		var c=candidates[ii];
		if(!c.id&&id){
		    continue;
		}
		if(typeof(c.id)=='string'&&c.id!=id){
		    continue;
		}

		maybe.push(candidates[ii]);
	    }
	    if(maybe.length!=1){
		return null;
	    }
	    return maybe[0];
	}
    }else{
	return id;
    }
    return null;
}


function show(){
    for(var i=0;i<arguments.length;i++){
	var element=ge(arguments[i]);
	if(element&&element.style)
	    element.style.display='';
    }
    return false;
}

function hide(){
    for(var i=0;i<arguments.length;i++){
	var element=ge(arguments[i]);
	if(element&&element.style)
	    element.style.display='none';
    }
    return false;
}
function shown(el){
    el=ge(el);
    return(el.style.display!='none');
}

function toggle(){
    for(var i=0;i<arguments.length;i++){
	var element=$(arguments[i]);
	element.style.display=get_style(element,"display")=='block'?'none':'block';
    }
    return false;
}
function is_descendent(base_obj,target_id){
    var target_obj=ge(target_id);
    if(base_obj==null)
	return;
    while(base_obj!=target_obj){
	if(base_obj.parentNode){
	    base_obj=base_obj.parentNode;
	}else{
	    return false;
	}
    }
    return true;
}
function get_style(object,prop){
    function hyphenate(prop){
	return prop.replace(/[A-Z]/g,function(match){
		return'-'+match.toLowerCase();
	    }
	    );
    }
    if(window.getComputedStyle){
	return window.getComputedStyle(object,null).getPropertyValue(hyphenate(prop));
    }
    if(document.defaultView&&document.defaultView.getComputedStyle){
	var computedStyle=document.defaultView.getComputedStyle(object,null);
	if(computedStyle)
	    return computedStyle.getPropertyValue(hyphenate(prop));
	if(prop=="display")
	    return"none";
    }
    if(object.currentStyle){
	return object.currentStyle[prop];
    }
    return object.style[prop];
}



function remove_node(node){
    if(node.removeNode){
	node.removeNode(true);
    }else{
	for(var ii=node.childNodes.length-1;ii>=0;ii--){
	    remove_node(node.childNodes[ii]);
	}
	node.parentNode.removeChild(node);
    }
    return null;
}

function create_hidden_input(name,value){
    var new_input=document.createElement('input');
    new_input.name=name;
    new_input.id=name;
    new_input.value=value;
    new_input.type='hidden';
    return new_input;
}

function has_css_class_name(elem,cname){
    return(elem&&cname)?new RegExp('\\b'+trim(cname)+'\\b').test(elem.className):false;
}
function swap_css_class_name(elements,class1,class2){
    for(var i=0;i<elements.length;i++){
	var element=ge(elements[i]);
	if(element.className.indexOf(class1)!=-1){
	    element.className=element.className.replace(class1,class2);
	}else{
	    element.className=element.className.replace(class2,class1);
	}
    }
}

function add_css_class_name(elem,cname){
    if(elem&&cname){
	if(elem.className){
	    if(has_css_class_name(elem,cname)){
		return false;
	    }else{
		elem.className+=' '+trim(cname);
		return true;
	    }
	}else{
	    elem.className=cname;
	    return true;
	}
    }else{return false;}
}

function remove_css_class_name(elem,cname){
    if(elem&&cname&&elem.className){
	cname=trim(cname);
	var old=elem.className;
	elem.className=elem.className.replace(new RegExp('\\b'+cname+'\\b'),'');
	return elem.className!=old;
    }else{
	return false;
    }
}

function toggle_css_class_name(elem,cname){
    if(has_css_class_name(elem,cname)){
	remove_css_class_name(elem,cname);
    }else{
	add_css_class_name(elem,cname);
    }
}

function set_inner_html(obj,html){
    var dummy='<span style="display:none">&nbsp</span>';
    html=html.replace('<style',dummy+'<style');
    html=html.replace('<STYLE',dummy+'<STYLE');
    html=html.replace('<script',dummy+'<script');
    html=html.replace('<SCRIPT',dummy+'<SCRIPT');
    obj.innerHTML=html;
    eval_inner_js(obj);
    addSafariLabelSupport(obj);
}
function eval_inner_js(obj){
    var scripts=obj.getElementsByTagName('script');
    for(var i=0;i<scripts.length;i++){
	if(scripts[i].src){
	    var script=document.createElement('script');
	    script.type='text/javascript';
	    script.src=scripts[i].src;
	    if(document.body.firstChild)
		document.body.insertBefore(script,document.body.firstChild);
	    else
		document.body.appendChild(script);
	}else{
	    try{
		eval_global(scripts[i].innerHTML);
	    }catch(e){
		if(typeof console!='undefined'){
		    console.error(e);
		}
	    }
	}
    }
}
function eval_global(js){
    var obj=document.createElement('script');
    obj.type='text/javascript';
    try{obj.innerHTML=js;
    }catch(e){obj.text=js;
    }
    if(document.body.firstChild)
	document.body.insertBefore(obj,document.body.firstChild);
    else
	document.body.appendChild(obj);
}
var KEYS={
    BACKSPACE:8,
    TAB:9,
    RETURN:13,
    ESC:27,
    SPACE:32,
    LEFT:37,
    UP:38,
    RIGHT:39,
    DOWN:40,
    DELETE:46
};
var KeyCodes={
    Left:63234,
    Right:63235
};
function mouseX(event)
{
    return event.pageX
	||(event.clientX+
	   (document.documentElement.scrollLeft||document.body.scrollLeft)
	   );
}

function mouseY(event)
{
    return event.pageY
	||(event.clientY+
	   (document.documentElement.scrollTop||document.body.scrollTop)
	   );
}
function pageScrollX()
{
    return document.body.scrollLeft||document.documentElement.scrollLeft;
}
function pageScrollY()
{
    return document.body.scrollTop||document.documentElement.scrollTop;
}
function elementX(obj){
    if(ua.safari()<500&&obj.tagName=='TR'){
	obj=obj.firstChild;
    }
    var left=obj.offsetLeft;
    var op=obj.offsetParent;
    while(obj.parentNode&&document.body!=obj.parentNode){
	obj=obj.parentNode;
	left-=obj.scrollLeft;
	if(op==obj){
	    if(ua.safari()<500&&obj.tagName=='TR'){
		left+=obj.firstChild.offsetLeft;
	    }else{
		left+=obj.offsetLeft;
	    }
	    op=obj.offsetParent;
	}
    }
    return left;
}
function elementY(obj){
    if(ua.safari()<500&&obj.tagName=='TR'){
	obj=obj.firstChild;
    }
    var top=obj.offsetTop;
    var op=obj.offsetParent;
    while(obj.parentNode&&document.body!=obj.parentNode){
	obj=obj.parentNode;
	top-=obj.scrollTop;
	if(op==obj){
	    if(ua.safari()<500&&obj.tagName=='TR'){
		top+=obj.firstChild.offsetTop;
	    }else{
		top+=obj.offsetTop;
	    }
	    op=obj.offsetParent;
	}
    }
    return top;
}

function get_all_form_inputs(root_element){
    var FORM_INPUT_TAG_NAMES={
	'input':1,
	'select':1,
	'textarea':1,
	'button':1
    };
    root_element=root_element||document;
    var ret=[];
    for(var tag_name in FORM_INPUT_TAG_NAMES){
	var elements=root_element.getElementsByTagName(tag_name);
	for(var i=0;i<elements.length;++i){
	    ret.push(elements[i]);
	}
    }
    return ret;
}
function get_form_select_value(select){
    return select.options[select.selectedIndex].value;
}
function set_form_select_value(select,value){
    for(var i=0;i<select.options.length;++i){
	if(select.options[i].value==value){
	    select.selectedIndex=i;
	    break;
	}
    }
}
function get_form_attr(form,attr){
    var val=form[attr];
    if(typeof val=='object'&&val.tagName=='INPUT'){
	var pn=val.parentNode
	    ,ns=val.nextSibling
	    ,node=val;
	pn.removeChild(node);
	val=form[attr];
	ns?pn.insertBefore(node,ns):pn.appendChild(node);
    }
    return val;
}
function serialize_form_helper(data,name,value){
    var match=/([^\]]+)\[([^\]]*)\](.*)/.exec(name);
    if(match){
	data[match[1]]=data[match[1]]||{};
	if(match[2]==''){
	    var i=0;
	    while(data[match[1]][i]!=undefined){i++;}
	}else{i=match[2];}
	
	if(match[3]==''){
	    data[match[1]][i]=value;
	}else{
	    serialize_form_helper(
				  data[match[1]],
				  i.concat(match[3]),
				  value);
	}
    }else{data[name]=value;}
}
function serialize_form(obj){
    var data={};
    var elements=obj.tagName=='FORM'?obj.elements:get_all_form_inputs(obj);

    for(var i=elements.length-1;i>=0;i--){
	if(elements[i].name&&!elements[i].disabled){
	    if(!(elements[i].type=='radio'
		 ||elements[i].type=='checkbox')
	       ||elements[i].checked
	       ||(!elements[i].type||elements[i].type=='text'
		  ||elements[i].type=='password'
		  ||elements[i].type=='hidden'
		  ||elements[i].tagName=='TEXTAREA'
		  ||elements[i].tagName=='SELECT')
	       ){
		serialize_form_helper(data,elements[i].name,elements[i].value);
	    }
	}
    }
    return data;
}
function is_button(element){
    var tagName=element.tagName.toUpperCase();
    if(tagName=='BUTTON'){return true;}
    if(tagName=='INPUT'&&element.type){
	var type=element.type.toUpperCase();
	return type=='BUTTON'||type=='SUBMIT';
    }
    return false;
}
function autogrow_textarea(obj){
    var padding=15;
    var shadow_div_id='shadow_'+obj.id;
    var shadow_div;
    if(!(shadow_div=ge(shadow_div_id))){
	shadow_div=document.createElement('div');
	shadow_div.id=shadow_div_id;
	shadow_div.style.position="absolute";
	shadow_div.style.left="-10000px";
	shadow_div.style.top="-10000px";
	shadow_div.fontSize=get_style(obj,'fontSize')+'px';
	shadow_div.style.width=parseInt(obj.clientWidth-8)+'px';
	obj.setAttribute('startHeight',obj.clientHeight);
	obj.parentNode.appendChild(shadow_div);
    }
    var clientHeight=obj.clientHeight;
    shadow_div.innerHTML=htmlspecialchars(obj.value).replace(/[\n]/g,'<br />&nbsp;');
    var shadowHeight=shadow_div.clientHeight;
    var to_height;
    var startHeight=obj.getAttribute('startHeight');
    if(shadowHeight<startHeight){
	to_height=startHeight;
    }else{
	to_height=shadowHeight+padding;
    }
    if(to_height&&to_height!=clientHeight){
	obj.style.height=to_height+'px';
    }
}
function addEventBase(obj,type,fn,name_hash)
{
    if(obj.addEventListener)
	obj.addEventListener(type,fn,false);
    else if(obj.attachEvent){
	obj["e"+type+fn+name_hash]=fn;
	obj[type+fn+name_hash]=function(){
	    obj["e"+type+fn+name_hash](window.event);
	}
	obj.attachEvent("on"+type,obj[type+fn+name_hash]);
    }
}
function removeEventBase(obj,type,fn,name_hash)
{
    if(obj.removeEventListener)
	obj.removeEventListener(type,fn,false);
    else if(obj.detachEvent){
	obj.detachEvent("on"+type,obj[type+fn+name_hash]);
	obj[type+fn+name_hash]=null;
	obj["e"+type+fn+name_hash]=null;
    }
}
function placeholderSetup(id){
    var el=ge(id);
    if(!el)return;
    if(el.type=='search')
	return;
    var ph=el.getAttribute("placeholder");
    if(!ph||ph=="")
	return;
    if(el.value==ph)
	el.value="";
    el.is_focused=(el.value!="");
    if(!el.is_focused){
	el.value=ph;
	el.style.color='#777';
	el.is_focused=0;
    }
    addEventBase(el,'focus',placeholderFocus);
    addEventBase(el,'blur',placeholderBlur);
}
function placeholderFocus(){
    if(!this.is_focused){
	this.is_focused=1;
	this.value='';
	this.style.color='#000';
	var rs=this.getAttribute("radioselect");
	if(rs&&rs!=""){
	    var re=document.getElementById(rs);
	    if(!re){return;}
	    if(re.type!='radio')return;
	    re.checked=true;
	}
    }
}
function placeholderBlur(){
    var ph=this.getAttribute("placeholder")
	if(this.is_focused&&ph&&this.value==""){
	    this.is_focused=0;
	    this.value=ph;
	    this.style.color='#777';
	}
}
function placeholderGetValue(id){
    var el=ge(id);
    if(!el){return;}
    return el.getAttribute("placeholder");
}
function getFlashPlayer(){
    goURI('http://adobe.com/go/getflashplayer');return false;
}



function hover_tooltip(object,hover_link,hover_class,offsetX,offsetY){
    if(object.tooltip){
	var tooltip=object.previousSibling;
	tooltip.style.display='block';
	return;
    }else{
	object.parentNode.style.position="relative";
	var tooltip=document.createElement('div');
	tooltip.className="tooltip_pro "+hover_class;
	tooltip.style.left=-9999+'px';
	tooltip.style.display='block';
	tooltip.innerHTML='<div class="tooltip_text"><span>'+hover_link+'</span></div>'
	    +'<div class="tooltip_pointer"></div>';
	object.parentNode.insertBefore(tooltip,object);
	while(tooltip.firstChild.firstChild.offsetWidth<=0){1;}
	var TOOLTIP_PADDING=16;
	var offsetWidth=tooltip.firstChild.firstChild.offsetWidth+TOOLTIP_PADDING;
	tooltip.style.width=offsetWidth+'px';
	tooltip.style.display='none';
	tooltip.style.left=offsetX+object.offsetLeft
	    -((offsetWidth-6-object.offsetWidth)/2)+'px';
	tooltip.style.top=offsetY+'px';
	tooltip.style.display='block';
	object.tooltip=true;
	object.onmouseout=function(e){
	    hover_clear_tooltip(object)
	};
    }
}
function hover_clear_tooltip(object){
    var tooltip=object.previousSibling;
    tooltip.style.display='none';
}
function addSafariLabelSupport(base){
    if(ua.safari()<500){
	var labels=(base||document.body).getElementsByTagName("label");
	for(i=0;i<labels.length;i++){
	    labels[i].addEventListener('click',addLabelAction,true);
	}
    }
}
function addLabelAction(event){
    var id=this.getAttribute('for');
    var item=null;
    if(id){
	item=document.getElementById(id);
    }else{
	item=this.getElementsByTagName('input')[0];
    }
    if(!item||event.srcElement==item){
	return;
    }
    if(item.type=='checkbox'){
	item.checked=!item.checked;
    }else if(item.type=='radio'){
	var radios=document.getElementsByTagName('input');
	for(i=0;i<radios.length;i++){
	    if(radios[i].name==item.name&&radios[i].form==item.form){
		radios.checked=false;
	    }
	}
	item.checked=true;
    }else{
	item.focus();
    }
    if(item.onclick){
	item.onclick(event);
    }
}
function escapeURI(u)
{
    if(encodeURIComponent){return encodeURIComponent(u);}
    if(escape){return escape(u);}
}
function goURI(href){window.location.href=href;}
function is_email(email){
    return/^[\w!.%+]+@[\w]+(?:\.[\w]+)+$/.test(email);
}
function getViewportWidth(){
    var width=0;
    if(document.documentElement&&document.documentElement.clientWidth){
	width=document.documentElement.clientWidth;
    }
    else if(document.body&&document.body.clientWidth){
	width=document.body.clientWidth;
    }
    else if(window.innerWidth){
	width=window.innerWidth-18;
    }
    return width;
};
function getViewportHeight(){
    var height=0;
    if(window.innerHeight){height=window.innerHeight-18;}
    else if(document.documentElement&&document.documentElement.clientHeight){
	height=document.documentElement.clientHeight;
    }
    else if(document.body&&document.body.clientHeight){height=document.body.clientHeight;
    }
    return height;
};

function getPageScrollHeight(){
    var height;
    if(typeof(window.pageYOffset)=='number'){
	height=window.pageYOffset;
    }else if(document.body&&document.body.scrollTop){
	height=document.body.scrollTop;
    }else if(document.documentElement&&document.documentElement.scrollTop){
	height=document.documentElement.scrollTop;
    }
    if(isNaN(height))
	return 0;
    return height;
};

function getRadioFormValue(obj){
    for(i=0;i<obj.length;i++){
	if(obj[i].checked){
	    return obj[i].value;
	}
    }
    return null;
}
function getTableRowShownDisplayProperty(){
    if(ua.ie()){
	return'inline';
    }else{
	return'table-row';
    }
}
function showTableRow()
{
    for(var i=0;i<arguments.length;i++){
	var element=ge(arguments[i]);
	if(element&&element.style)
	    element.style.display=getTableRowShownDisplayProperty();
    }
    return false;
}
function getParentRow(el){
    el=ge(el);
    while(el.tagName&&el.tagName!="TR"){el=el.parentNode;}
    return el;
}
function stopPropagation(e){
    if(!e)
	var e=window.event;
    e.cancelBubble=true;
    if(e.stopPropagation){e.stopPropagation();}
}

function adjustImage(obj,stop_word,max){
    var pn=obj.parentNode;
    if(stop_word==null)
	stop_word='note_content';
    if(max==null){
	while(pn.className.indexOf(stop_word)==-1)
	    pn=pn.parentNode;
	if(pn.offsetWidth)
	    max=pn.offsetWidth;
	else
	    max=400;
    }
    if(navigator.userAgent.indexOf('AppleWebKit/4')==-1){
	obj.style.position='absolute';
	obj.style.left=obj.style.top='-32000px';
    }
    obj.className=obj.className.replace('img_loading','img_ready');
    if(obj.width>max){
	if(window.ActiveXObject && !ua.firefox() && !ua.safari()){
	    try{
		var img_div=document.createElement('div');
		img_div.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'
		    +obj.src.replace('"','%22')
		    +'", sizingMethod="scale")';
		img_div.style.width=max+'px';
		img_div.style.height=((max/obj.width)*obj.height)+'px';
		if(obj.parentNode.tagName=='A')
		    img_div.style.cursor='pointer';
		obj.parentNode.insertBefore(img_div,obj);
		obj.removeNode(true);
	    }
	    catch(e){obj.style.width=max+'px';}
	}
	else
	    obj.style.width=max+'px';
    }
    obj.style.left=obj.style.top=obj.style.position='';
}
function imageConstrainSize(src,maxX,maxY,placeholderid){
    var image=new Image();
    image.onload=function(){
	if(image.width>0&&image.height>0){
	    var width=image.width;
	    var height=image.height;
	    if(width>maxX||height>maxY){
		var desired_ratio=maxY/maxX;
		var actual_ratio=height/width;
		if(actual_ratio>desired_ratio){
		    width=width*(maxY/height);
		    height=maxY;
		}else{
		    height=height*(maxX/width);
		    width=maxX;
		}
	    }
	    var placeholder=ge(placeholderid);
	    var newimage=document.createElement('img');
	    newimage.src=src;
	    newimage.width=width;
	    newimage.height=height;
	    placeholder.parentNode.insertBefore(newimage,placeholder);
	    placeholder.parentNode.removeChild(placeholder);
	}
    }
    image.src=src;
}
function set_opacity(obj,opacity){
    try{
	obj.style.opacity=(opacity==1?'':opacity);
	obj.style.filter=(opacity==1?'':'alpha(opacity='+opacity*100+')');
    }
    catch(e){}
}
function get_opacity(obj){
    var opacity=get_style(obj,'filter');
    var val=null;
    if(opacity&&(val=/(\d+(?:\.\d+)?)/.exec(opacity))){
	return parseFloat(val.pop())/100;
    }else if(opacity=get_style(obj,'opacity')){
	return parseFloat(opacity);
    }else{return 1;}
}
function get_caret_position(obj){
    obj.focus();
    if(document.selection){
	if(obj.tagName=='INPUT'){
	    var range=document.selection.createRange();
	    return{
		start:-range.moveStart('character',-obj.value.length),
		    end:-range.moveEnd('character',-obj.value.length)
		    };
	}else if(obj.tagName=='TEXTAREA'){
	    var range=document.selection.createRange();
	    var range2=range.duplicate();
	    range2.moveToElementText(obj);
	    range2.setEndPoint('StartToEnd',range);
	    var end=obj.value.length-range2.text.length;
	    range2.setEndPoint('StartToStart',range);
	    return{
		start:obj.value.length-range2.text.length,
		    end:end
		    };
	}else{
	    return{
		start:undefined,
		    end:undefined
		    };
	}
    }else{
	return{
	    start:obj.selectionStart,
		end:obj.selectionEnd
		};
    }
}
function set_caret_position(obj,start,end){
    if(document.selection){
	if(obj.tagName=='TEXTAREA'){
	    var i=obj.value.indexOf("\r",0);
	    while(i!=-1&&i<end){
		end--;
		if(i<start){start--;}
		i=obj.value.indexOf("\r",i+1);
	    }
	}
	var range=obj.createTextRange();
	range.collapse(true);
	range.moveStart('character',start);
	if(end!=undefined){
	    range.moveEnd('character',end-start);
	}
	range.select();
    }else{
	obj.selectionStart=start;
	var sel_end=end==undefined?start:end;
	obj.selectionEnd=Math.min(sel_end,obj.value.length);
	obj.focus();
    }
}

function array_indexOf(arr,val,index){
    if(!index){index=0;}
    for(var i=index;i<arr.length;i++){
	if(arr[i]==val){return i;}
    }
    return-1;
}
var ua={
    ie:function(){return this._ie;},
    firefox:function(){return this._firefox;},
    opera:function(){return this._opera;},
    safari:function(){return this._safari;},
    windows:function(){return this._windows;},
    osx:function(){return this._osx;},
    populate:function(){
	var agent=/(?:MSIE.(\d+\.\d+))|(?:(?:Firefox|GranParadiso).(\d+\.\d+))|(?:Opera.(\d+\.\d+))|(?:AppleWebKit.(\d+(?:\.\d+)?))/.exec(navigator.userAgent);
	var os=/(Mac OS X;)|(Windows;)/.exec(navigator.userAgent);
	if(agent){
	    ua._ie=agent[1]?parseFloat(agent[1]):NaN;
	    ua._firefox=agent[2]?parseFloat(agent[2]):NaN;
	    ua._opera=agent[3]?parseFloat(agent[3]):NaN;
	    ua._safari=agent[4]?parseFloat(agent[4]):NaN;
	}else{
	    ua._ie=ua._firefox=ua._opera=ua._safari=NaN;
	}
	if(os){
	    ua._osx=!!os[1];
	    ua._windows=!!os[2];
	}else{
	    ua._osx=ua._windows=false;
	}
    },
    adjustBehaviors:function(){
	onloadRegister(addSafariLabelSupport);
	if(ua.ie()<7){
	    try{
		document.execCommand('BackgroundImageCache',false,true);
	    }catch(ignored){}
	}
    }
};
function is_scalar(v){
    switch(typeof(v)){
    case'string':
    case'number':
    case'null':
    case'boolean':
	return true;
    }
    return false;
}
function is_node(o){
    if(typeof(Node)=='undefined'){
	Node=null;
    }
    try{
	return o&&((Node!=undefined&&o instanceof Node)||o.nodeName);
    }catch(ignored){return false;}
}
var DOM={
    setText:function(el,text){
	if(ua.firefox()){
	    el.textContent=text;
	}else{
	    el.innerText=text;
	}
    },
    getText:function(el){
	if(ua.firefox()){
	    return el.textContent;
	}else{
	    return el.innerText;
	}
    },
    setContent:function(el,content){
	if(ua.ie()){
	    for(var ii=el.childNodes.length-1;ii>=0;--ii){
		DOM.remove(el.childNodes[ii]);
	    }
	}else{
	    el.innerHTML='';
	}
	if(is_scalar(content)){
	    content=document.createTextNode(content);
	    el.appendChild(content);
	}else if(is_node(content)){
	    el.appendChild(content);
	}else if(content instanceof Array){
	    for(var ii=0;ii<content.length;ii++){
		var node=content[ii];
		if(!is_node(node)){
		    node=document.createTextNode(node);
		}
		el.appendChild(node);
	    }
	}else{
	}
    },
    remove:function(el){
	return remove_node(el);
    }
};
var CSS={
    removeClass:function(element,className){
	return remove_css_class_name(element,className);
    },
    addClass:function(element,className){
	return add_css_class_name(element,className);
    },
    setClass:function(element,className){
	element.className=className;
	return CSS;
    },
    Cursor:{
	kGrabbable:'grabbable',
	kGrabbing:'grabbing',
	kEditable:'editable',
	set:function(element,name){
	    element=element||document.body;
	    switch(name){
	    case CSS.Cursor.kEditable:
		name='text';
		break;
	    case CSS.Cursor.kGrabbable:
		if(ua.firefox()){
		    name='-moz-grab';
		}else{name='move';}
		break;
	    case CSS.Cursor.kGrabbing:
		if(ua.firefox()){
		    name='-moz-grabbing';
		}else{name='move';}
		break;
	    }
	    element.style.cursor=name;
	}
    }
};

if(Object.prototype.eval){
    window.eval=Object.prototype.eval;
}
delete Object.prototype.eval;
delete Object.prototype.valueOf;
Array.prototype.forEach=null;
Array.prototype.every=null;
/*Array.prototype.map=null;*/
Array.prototype.some=null;
/*Array.prototype.reduce=null;*/
/*Array.prototype.reduceRight=null;*/
/*Array.prototype.filter=null;*/
Array.prototype.sort=(function(sort){
	return function(callback){
	    return(this==window)
	    ?null
	    :(callback
	      ?sort.call(this,function(a,b){
		      return callback(a,b)})
	      :sort.call(this)
	      );
	}
    }
    )(Array.prototype.sort);
Array.prototype.reverse=(function(reverse){
	return function(){
	    return(this==window)
	    ?null
	    :reverse.call(this);
	}
    }
    )(Array.prototype.reverse);
Array.prototype.concat=(function(concat){
	return function(){
	    return(this==window)
	    ?null
	    :concat.apply(this,arguments);
	}
    })(Array.prototype.concat);
Array.prototype.slice=(function(slice){
	return function(){
	    return(this==window)
	    ?null
	    :slice.apply(this,arguments);
	}
    })(Array.prototype.slice);
Function.prototype.class_extend=function(superclass){
    var superprototype=__metaprototype(superclass,0);
    var subprototype=__metaprototype(this,superprototype.prototype.__level+1);
    subprototype.parent=superprototype;
}
function __metaprototype(obj,level){
    if(obj.__metaprototype){return obj.__metaprototype;}
    var metaprototype=new Function();
    metaprototype.construct=__metaprototype_construct;
    metaprototype.prototype.construct=__metaprototype_wrap(obj,level,true);
    metaprototype.prototype.__level=level;
    metaprototype.base=obj;
    obj.prototype.parent=metaprototype;
    obj.__metaprototype=metaprototype;
    return metaprototype;
}
function __metaprototype_construct(instance){
    __metaprototype_init(instance.parent);
    var parents=[];
    var obj=instance;
    while(obj.parent){
	parents.push(new_obj=new obj.parent());
	new_obj.__instance=instance;
	obj=obj.parent;
    }
    instance.parent=parents[1];
    parents.reverse();
    parents.pop();
    instance.__parents=parents;
    instance.__instance=instance;
    return instance.parent.construct.apply(instance.parent,arguments);
}
var aiert;
if(!aiert){
    aiert=alert;
}
function __metaprototype_init(metaprototype){
    if(metaprototype.initialized)
	return;
    var base=metaprototype.base.prototype;
    if(metaprototype.parent){
	__metaprototype_init(metaprototype.parent);
	var parent_prototype=metaprototype.parent.prototype;
	for(i in parent_prototype){
	    if(i!='__level'&&i!='construct'&&base[i]===undefined){
		base[i]=metaprototype.prototype[i]=parent_prototype[i];
	    }
	}
    }
    metaprototype.initialized=true;
    var level=metaprototype.prototype.__level;
    for(i in base){
	if(i!='parent'){
	    base[i]=metaprototype.prototype[i]=__metaprototype_wrap(base[i],level);
	}
    }
}
function __metaprototype_wrap(method,level,shift){
    if(typeof method!='function'||method.__prototyped){return method;}
    var func=function(){
	var instance=this.__instance;
	if(instance){
	    var old_parent=instance.parent;
	    instance.parent=level?instance.__parents[level-1]:null;
	    if(shift){
		var args=[];
		for(var i=1;i<arguments.length;i++){args.push(arguments[i]);}
		var ret=method.apply(instance,args);
	    }else{
		var ret=method.apply(instance,arguments);
	    }
	    instance.parent=old_parent;
	    return ret;
	}else{
	    return method.apply(this,arguments);
	}
    }
    func.__prototyped=true;
    return func;
}
function clearCookie(cookieName){
    document.cookie=cookieName+"=; expires=Mon, 26 Jul 1997 05:00:00 GMT; path=/; domain=.mipang.com";
}
function do_post(url){
    var pieces=/(^([^?])+)\??(.*)$/.exec(url);
    var form=document.createElement('form');
    form.action=pieces[1];
    form.method='post';
    form.style.display='none';
    var sparam=/([\w]+)(?:=([^&]+)|&|$)/g;
    var param=null;
    if(ge('post_form_id'))
	pieces[3]+='&post_form_id='+$('post_form_id').value;
    while(param=sparam.exec(pieces[3])){
	var input=document.createElement('input');
	input.type='hidden';
	input.name=param[1];
	input.value=param[2];
	form.appendChild(input);
    }
    document.body.appendChild(form);
    form.submit();
    return false;
}
function dynamic_post(url,params){
    var form=document.createElement('form');
    form.action=url;
    form.method='POST';
    form.style.display='none';
    if(ge('post_form_id')){
	params['post_form_id']=$('post_form_id').value;
    }
    for(var param in params){
	var input=document.createElement('input');
	input.type='hidden';
	input.name=param;
	input.value=params[param];
	form.appendChild(input);
    }
    document.body.appendChild(form);
    form.submit();
    return false;
}
function query_param_get(param_name){
    var params=window.location.search.split('&')||[];
    for(var i=0;i<params.length;i++){
	if(params[i]==param_name){return'';}
	else if(params[i].indexOf(param_name+'=')){return params[i].split('=')[1];}
    }
    return null;
}
function anchor_set(anchor){
    window.location=window.location.href.split('#')[0]+'#'+anchor;
}
function anchor_get(){
    return window.location.href.split('#')[1]||null;
}
function event_get(e){return e||window.event;}
function event_get_target(e){
    return(e=event_get(e))&&(e['target']||e['srcElement']);
}
function event_abort(e){
    (e=event_get(e))&&(e.cancelBubble=true)&&e.stopPropagation&&e.stopPropagation();
    return false;
}
function event_prevent(e){
    (e=event_get(e))&&!(e.returnValue=false)&&e.preventDefault&&e.preventDefault();
    return false;
}
function event_get_keypress_keycode(event){
    switch(event.keyCode){
    case 63232:return 38;
    case 63233:return 40;
    case 63234:return 37;
    case 63235:return 39;
    case 63272:
    case 63273:
    case 63275:return null;
    case 63276:return 33;
    case 63277:return 34;
    }
    if(event.shiftKey){
	switch(event.keyCode){
	case 33:
	case 34:
	case 37:
	case 38:
	case 39:
	case 40:return null;
	}
    }else{return event.keyCode;}
}
function env_get(k){
    return typeof(window['Env'])!='undefined'&&Env[k];
}
function chain(u,v){
    var calls=[];
    for(var ii=0;ii<arguments.length;ii++){
	calls.push(arguments[ii]);
    }
    return function(){
	for(var ii=0;ii<calls.length;ii++){
	    if(calls[ii]&&calls[ii].apply(null,arguments)===false){
		return false;
	    }
	}
	return true;
    }
}
function onloadRegister(handler){
    window.loaded?_runHook(handler):_addHook('onloadhooks',handler);
}
function onafterloadRegister(handler){
    window.loaded?_runHook(handler):_addHook('onafterloadhooks',handler);
}
function onbeforeunloadRegister(handler){_addHook('onbeforeunloadhooks',handler);}
function onunloadRegister(handler){_addHook('onunloadhooks',handler);}
function _onloadHook(){_runHooks('onloadhooks');window.loaded=true;}
function _runHook(handler){try{handler();}catch(ex){
    }
}
function _runHooks(hooks){
    var isbeforeunload=(hooks=='onbeforeunloadhooks');
    var warn=null;
    do{
	var h=window[hooks];
	if(!isbeforeunload){
	    window[hooks]=null;
	}
	if(!h){break;}
	for(var ii=0;ii<h.length;ii++){
	    try{
		if(isbeforeunload){
		    warn=warn||h[ii]();
		}else{
		    h[ii]();
		}
	    }catch(ex){
	    }
	}
	if(isbeforeunload){break;}
    }while(window[hooks]);
    if(isbeforeunload){
	if(warn){return warn;}else{window.loaded=false;}
    }
}
function _addHook(hooks,handler){(window[hooks]?window[hooks]:(window[hooks]=[])).push(handler);}
function _bootstrapEventHandlers(){
    if(document.addEventListener){
	if(ua.safari()){
	    var timeout=setInterval(function(){
		    if(/loaded|complete/.test(document.readyState)){
			_onloadHook();
			clearTimeout(timeout);
		    }
		},10);
	}else{
	    document.addEventListener("DOMContentLoaded",_onloadHook,true);
	}
    }else{
	var src='javascript:void(0)';
	if(window.location.protocol=='https:'){
	    src='//:';
	}
	document.write('<script onreadystatechange="if (this.readyState==\'complete\') {'
		       +'this.parentNode.removeChild(this);_onloadHook();}" defer="defer" '
		       +'src="'+src+'"><\/script\>');
    }
    window.onload=chain(window.onload
			,function(){
			    _onloadHook();
			    _runHooks('afterloadhooks');
			}
			);
    window.onbeforeunload=function(){
	return _runHooks('onbeforeunloadhooks');
    };
    window.onunload=chain(window.onunload,function(){_runHooks('onunloadhooks');});
}
function iterTraverseDom(root,visitCb){
    var c=root,n=null;
    var it=0;
    do{
	n=c.firstChild;
	if(!n){
	    if(visitCb(c)==false)
		return;
	    n=c.nextSibling;
	}
	if(!n){
	    var tmp=c;
	    do{
		n=tmp.parentNode;
		if(n==root)
		    break;
		if(visitCb(n)==false)
		    return;
		tmp=n;
		n=n.nextSibling;
	    }while(!n);
	}
	c=n;
    }while(c!=root);
}
function prependChild(parent,elem){
    if(parent.firstChild){
	parent.insertBefore(elem,parent.firstChild);
    }else{
	parent.appendChild(elem);
    }
}
ua.populate();
_bootstrapEventHandlers();
ua.adjustBehaviors();
/**
if(navigator
   &&navigator.userAgent
   &&navigator.userAgent.indexOf('Firefox/1.0')==-1
   &&!/Netscape\/[1-8]\./.test(navigator.userAgent)){
    document.domain='mipang.com';
}
**/
////////////////////////


// extend

function bind(obj,method){
    var args=[];
    for(var ii=2;ii<arguments.length;ii++){
	args.push(arguments[ii]);
    }
    return function(){
	var _obj=obj||this;
	var _args=args.slice();
	for(var jj=0;jj<arguments.length;jj++){
	    _args.push(arguments[jj]);
	}
	if(typeof(method)=="string"){
	    if(_obj[method]){
		return _obj[method].apply(_obj,_args);
	    }
	}else{
	    return method.apply(_obj,_args);
	}
    }
}
function copy_properties(u,v){

    return Object.extend(u,v);
}

var Util={
    isDevelopmentEnvironment:function(){
	return env_get('dev');
    },
    warn:function(){
	Util.log(sprintf.apply(null,arguments),'warn');
    },
    error:function(){
	Util.log(sprintf.apply(null,arguments),'error');
    },
    log:function(msg,type){
	if(Util.isDevelopmentEnvironment()){
	    var written=false;
	    if(typeof(window['TabConsole'])!='undefined'){
		var con=TabConsole.getInstance();
		if(con){
		    con.log(msg,type);
		    written=true;
		}
	    }
	    if(typeof(console)!="undefined"&&console.error){
		console.error(msg);
		written=true;
	    }
	    if(!written&&type!='deprecated'){
		aiert(msg);
	    }
	}else{
	    if(type=='error'){
		msg+='\n\n'+Util.stack();
		(typeof(window['debug_rlog'])=='function')&&debug_rlog(msg);
	    }
	}
    },
    deprecated:function(what){
	if(!Util._deprecatedThings[what]){
	    Util._deprecatedThings[what]=true;
	    var msg=sprintf('Deprecated: %q is deprecated.\n\n%s',what,Util.whyIsThisDeprecated(what));
	    Util.log(msg,'deprecated');
	}
    },
    stack:function(){
	try{
	    try{
		({}).llama();
	    }catch(e){
		if(e.stack){
		    var stack=[];
		    var trace=[];
		    var regex=/^([^@]+)@(.+)$/mg;
		    var line=regex.exec(e.stack);
		    do{
			stack.push([line[1],line[2]]);
		    }while(line=regex.exec());
		    for(var i=0;i<stack.length;i++){
			trace.push('#'+i+' '+stack[i][0]+' @ '+(stack[i+1]?stack[i+1][1]:'?'));
		    }
		    return trace.join('\n');
		}else{
		    var trace=[];
		    var pos=arguments.callee;
		    var stale=[];
		    while(pos){
			for(var i=0;i<stale.length;i++){
			    if(stale[i]==pos){
				trace.push('#'+trace.length+' ** recursion ** @ ?');
				return trace.join('\n');
			    }
			}
			stale.push(pos);
			var args=[];
			for(var i=0;i<pos.arguments.length;i++){
			    if(pos.arguments[i]instanceof Function){
				var func=/function ?([^(]*)/.exec(pos.arguments[i].toString()).pop(); //)
						     args.push(func?func:'anonymous');
			    }else if(pos.arguments[i]instanceof Array){
				    args.push('Array');
			    }else if(pos.arguments[i]instanceof Object){
				    args.push('Object');
			    }else if(typeof pos.arguments[i]=='string'){
				    args.push('"'+pos.arguments[i].replace(/("|\\)/g,'\\$1')+'"'); //'
			    }else{args.push(pos.arguments[i]);
			    }
		       }
		       trace.push('#'+trace.length+' '+/function?([^(]*)/.exec(pos).pop()+'('+args.join(', ')+') @ ?');
		       if(trace.length>100)
			   break;
		       pos=pos.caller;
		  }
		  return trace.join('\n');
					      }
	}
 }catch(e){return'No stack trace available';}
		},
			    whyIsThisDeprecated:function(what){
			    return Util._deprecatedBecause[what.toLowerCase()]||'No additional information is available about this deprecation.';},
			    _deprecatedBecause:{},
			    _deprecatedThings:{}
		    };

Util._deprecatedBecause={};

var Configurable={
    getOption:function(opt){
	if(typeof(this.option[opt])=='undefined'){
	    Util.warn('Failed to get option %q; it does not exist.',opt);
	    return null;
	}
	return this.option[opt];
    },
    setOption:function(opt,v){
	if(typeof(this.option[opt])=='undefined'){
	    Util.warn('Failed to set option %q; it does not exist.',opt);
	}else{this.option[opt]=v;}
	return this;
    },
    getOptions:function(){return this.option;}
};


function URI(uri){
    if(this===window){
	return new URI(uri||window.location.href);
    }
    this.parse(uri||'');
}
copy_properties(URI,{
	expression:/(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/,
	explodeQuery:function(q){
	    if(!q){return{};}
	    var ii,t,r={};
	    q=q.split('&');
	    for(ii=0,l=q.length;ii<l;ii++){
		t=q[ii].split('=');
		r[decodeURIComponent(t[0])]=(typeof(t[1])=='undefined')?'':decodeURIComponent(t[1]);
	    }
	    return r;
	},
	implodeQuery:function(obj,name){
	    name=name||'';
	    var r=[];
	    if(obj instanceof Array){
		for(var ii=0;ii<obj.length;ii++){
		    try{
			r.push(URI.implodeQuery(obj[ii],name?name+'['+ii+']':ii));
		    }catch(ignored){}
		}
	    }else if(typeof(obj)=='object'){
		if(is_node(obj)){
		    r.push('{node}');
		}else{
		    for(var k in obj){
			try{
			    r.push(URI.implodeQuery(obj[k],name?name+'['+k+']':k));
			}catch(ignored){}
		    }
		}
	    }else if(name&&name.length){
		r.push(encodeURIComponent(name)+'='+encodeURIComponent(obj));
	    }else{r.push(encodeURIComponent(obj));}
	    return r.join('&');
	}
    });
copy_properties(URI.prototype,{
	parse:function(uri){
	    var m=uri.toString().match(URI.expression);
	    copy_properties(this,{
		    protocol:m[3]||'',
			domain:m[4]||'',
			port:m[6]||'',
			path:m[7]||'',
			query:URI.explodeQuery(m[9]||''),
			fragment:m[11]||''
			});
	    return this;
	},
	    setProtocol:function(p){
	    this.protocol=p;
	    return this;
	},
	    getProtocol:function(){
	    return this.protocol;
	},
	    setQueryData:function(o){
	    this.query=o;
	    return this;
	},
	    addQueryData:function(o){
	    return this.setQueryData(copy_properties(this.query,o));
	},
	    getQueryData:function(){
	    return this.query;
	},
	    setFragment:function(f){
	    this.fragment=f;
	    return this;
	},

	    getFragment:function(){
	    return this.fragment;
	},
	    setDomain:function(d){
	    this.domain=d;
	    return this;
	},
	    getDomain:function(){
	    return this.domain;
	},
	    setPort:function(p){
	    this.port=p;
	    return this;
	},
	    getPort:function(){
	    return this.port;
	},
	    setPath:function(p){
	    this.path=p;
	    return this;
	},
	    getPath:function(){
	    return this.path;
	},
    toString:function(){ /* Bug in IE */
	    var r='';
	    var q=URI.implodeQuery(this.query);
	    this.protocol&&(r+=this.protocol+'://');
	    this.domain&&(r+=this.domain);
	    this.port&&(r+=':'+this.port);
	    if(this.domain&&!this.path){r+='/';}
	    this.path&&(r+=this.path);
	    q&&(r+='?'+q);
	    this.fragment&&(r+='#'+this.fragment);
	    return r;
	},
    _toString:function(){
	    var r='';
	    var q=URI.implodeQuery(this.query);
	    this.protocol&&(r+=this.protocol+'://');
	    this.domain&&(r+=this.domain);
	    this.port&&(r+=':'+this.port);
	    if(this.domain&&!this.path){r+='/';}
	    this.path&&(r+=this.path);
	    q&&(r+='?'+q);
	    this.fragment&&(r+='#'+this.fragment);
	    return r;
	},
	    isSameOrigin:function(asThisURI){
	    var uri=asThisURI||window.location.href;
	    if(!(uri instanceof URI)){uri=new URI(uri.toString());}
	    if(this.getProtocol()&&this.getProtocol()!=uri.getProtocol()){return false;}
	    if(this.getDomain()&&this.getDomain()!=uri.getDomain()){return false;}
	    return true;
	},
	    coerceToSameOrigin:function(targetURI){
	    var uri=targetURI||window.location.href;
	    if(!(uri instanceof URI)){uri=new URI(uri.toString());}
	    if(this.isSameOrigin(uri)){return true;}
	    if(this.getProtocol()!=uri.getProtocol()){return false;}
	    var dst=uri.getDomain().split('.');
	    var src=this.getDomain().split('.');
	    if(dst.pop()=='com'&&src.pop()=='com'){
		if(dst.pop()=='facebook'&&src.pop()=='facebook'){
		    this.setDomain(uri.getDomain());
		    return true;
		}
	    }
	    return false;
	}
    });

function EventController(eventResponderObject){
    copy_properties(this,{
	    queue:[],
		ready:false,
		responder:eventResponderObject
		});
};

copy_properties(EventController.prototype,{
	startQueue:function(){
	    this.ready=true;
	    this.dispatchEvents();
	    return this;
	},
	    pauseQueue:function(){
	    this.ready=false;
	    return this;
	},
	    addEvent:function(event){
	    if(event.toLowerCase()!==event){
	    }
	    var args=[];
	    for(var ii=1;ii<arguments.length;ii++){args.push(arguments[ii]);}
	    this.queue.push({type:event,args:args});if(this.ready){this.dispatchEvents();}
	    return event_abort(event_get(arguments[1]));
	},
	    dispatchEvents:function(){
	    if(!this.responder){
	    }
	    for(var ii=0;ii<this.queue.length;ii++){
		var evtName='on'+this.queue[ii].type;
		if(typeof(this.responder[evtName])!='function'&&typeof(this.responder[evtName])!='null'){
		}else{
		    if(this.responder[evtName]){
			this.responder[evtName].apply(this.responder,this.queue[ii].args);
		    }
		}
	    }
	    this.queue=[];
	}
    });


/// deprecated


function extend(u,v){
    return copy_properties(u,v);
}
var ajaxLoadIndicatorRefCount=0;
function ajaxShowLoadIndicator()
{
    indicatorDiv=ge('ajaxLoadIndicator');
    if(!indicatorDiv){
	indicatorDiv=document.createElement("div");
	indicatorDiv.id='ajaxLoadIndicator';
	indicatorDiv.innerHTML='Loading';
	indicatorDiv.className='ajaxLoadIndicator';
	document.body.appendChild(indicatorDiv);
    }
    indicatorDiv.style.top=(5+pageScrollY())+'px';
    indicatorDiv.style.left=(5+pageScrollX())+'px';
    indicatorDiv.style.display='block';
    ajaxLoadIndicatorRefCount++;
}
function ajaxHideLoadIndicator()
{
    ajaxLoadIndicatorRefCount--;
    if(ajaxLoadIndicatorRefCount==0)
	$('ajaxLoadIndicator').style.display='';
}
function fbAjax(doneHandler,failHandler)
{
    newAjax=this;
    this.onDone=doneHandler;
    this.onFail=failHandler;
    this.transport=this.getTransport();
    this.transport.onreadystatechange=ajaxTrampoline(this);
}
fbAjax.prototype.get=function(uri,query,force_sync)
{

    /* fix url, proxy to main host */
    
    if( typeof MIPANG != 'undefined' && typeof MIPANG.location != 'undefined' && MIPANG.location.main_host != MIPANG.location.current_host){
	
	if(uri.indexOf('http') != 0){
	    uri = MIPANG.location.scheme+'://'+MIPANG.location.main_host + uri;
	}

	uri = '/service/proxy/*/'+uri;
	
    }

    force_sync=force_sync||false;
    if(query&&(typeof query!='string')){
	query=URI.implodeQuery(query);
    }
    fullURI=uri+(query?('?'+query):'');
    this.transport.open('GET',fullURI,!force_sync);
    this.transport.send('');
};

fbAjax.prototype.post=function(uri,data,force_sync,no_post_form_id)
{
    
    /* fix url, proxy to main host */
    
    if( typeof MIPANG != 'undefined' && typeof MIPANG.location != 'undefined' && MIPANG.location.main_host != MIPANG.location.current_host){
	
	if(uri.indexOf('http') != 0){
	    uri = MIPANG.location.scheme+'://'+MIPANG.location.main_host + uri;
	}

	uri = '/service/proxy/*/'+uri;
	
    }


    force_sync=force_sync||false;
    no_post_form_id=no_post_form_id||false;
    if(data&&(typeof data!='string')){
	data=URI.implodeQuery(data);
    }
    if(!no_post_form_id){
	var post_form_id=ge('post_form_id');
	if(post_form_id){
	    data+='&post_form_id='+post_form_id.value;
	}
    }
    this.transport.open('POST',uri,!force_sync);
    this.transport.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    this.transport.send(data);
};
fbAjax.prototype.stateDispatch=function()
{
    try{
	if(this.transport.readyState==1&&this.showLoad)
	    ajaxShowLoadIndicator();
	if(this.transport.readyState==4){
	    if(this.showLoad)
		ajaxHideLoadIndicator();
	    if(this.transport.status>=200&&this.transport.status<300&&this.transport.responseText.length>0){
		try{
		    if(this.onDone)
			this.onDone(this,this.transport.responseText);
		}catch(tempError){
		    console?console.error(tempError):false;
		}
	    }else{
		try{
		    if(this.onFail)
			this.onFail(this);
		}catch(tempError){
		    console?console.error(tempError):false;
		}
	    }
	}
    }catch(error){
	if(this.onFail)
	    this.onFail(this);
    }
};
fbAjax.prototype.getTransport=function()
{
    var ajax=null;
    try{
	ajax=new XMLHttpRequest();
    }
    catch(e){ajax=null;}
    try{if(!ajax)ajax=new ActiveXObject("Msxml2.XMLHTTP");}
    catch(e){ajax=null;}
    try{if(!ajax)ajax=new ActiveXObject("Microsoft.XMLHTTP");}
    catch(e){ajax=null;}
    return ajax;
};
function ajaxTrampoline(ajaxObject)
{
    return function(){
	ajaxObject.stateDispatch();
    };
}
function same_place(rootEl,dynamic_dialog){
    //Util.deprecated('dynamicdialog');
    if(rootEl=ge(rootEl)){
	if(elementY(rootEl)+20==elementY(dynamic_dialog))
	    return true;
    }
    return false;
}
function move_here(rootEl,el){
    //Util.deprecated('dynamicdialog');
    var x=getViewportWidth()/2-120;
    var y=elementY(rootEl)+20;
    el.style.left=x+"px";
    el.style.top=y+"px";
}


// async


function AsyncRequest(){
    var dispatchResponse=bind(this,function(asyncResponse){
	    try{
		this.handler(asyncResponse);
	    }catch(exception){
		Util.error('The user supplied handler function for an AsyncRequest to URI %q '
		   +'threw an exception: %x. (This is not a problem with AsyncRequest, it '
		   +'is a problem with the callback, which failed to catch the exception.)',this.uri,exception);
	    }
	});

    var dispatchErrorResponse=bind(this,function(asyncResponse,isTransport){
	    try{
		if(isTransport){
		    this.transportErrorHandler(asyncResponse);
		}else{
		    this.errorHandler(asyncResponse);
		}
	    }catch(exception){
		Util.error('Async error handler threw an exception for URI %q, when processing a '
		   +'%d error: %s.',this.uri,asyncResponse.getError(),exception);
	    }
	});

    var invokeResponseHandler=bind(this,function(){
	    var r=new AsyncResponse();
	    if(this.handler){
		try{
		    var shield="for (;;);";
		    var shieldlen=shield.length;
		    if(this.transport.responseText.length<=shieldlen){
			if(!this.getOption('suppressErrorAlerts')){
			    Util.error('AsyncResponse returned with shorter length than required.');
			}
			throw"AsyncResponse too short.";
		    }
		    var text=this.transport.responseText;
		    var offset=0;
		    while(text.charAt(offset)==" "||text.charAt(offset)=="\n"){offset++;}
		    if(offset&&text.substring(offset,offset+shieldlen)==shield){
			Util.error('Response for request to endpoint %q seems to be valid, but was '
			   +'preceeded by whitespace. (This probably means that someone '
			   +'committed whitespace in a header file.)',this.uri);
		    }
		    var safeResponse=text.substring(offset+shieldlen);
		    if(!this.getOption('suppressEvaluation')){
			var response;
			eval('response = ('+safeResponse+')');
			if(typeof(response.payload)=='undefined'
			   ||typeof(response.error)=='undefined'
			   ||typeof(response.errorDescription)=='undefined'
			   ||typeof(response.errorSummary)=='undefined'){
			    Util.warn('AsyncRequest to endpoint %q returned a JSON response, but it '
			          +'is not properly formatted. The endpoint needs to provide a '
			          +'response including both error and payload information; use '
			          +'the AsyncResponse PHP class to do this easily.',this.uri);
			    r.payload=response;
			}else{
			    copy_properties(r,response);
			}
		    }else{r.payload=this.transport;}
		    if(r.getError()){
			dispatchErrorResponse(r);
		    }else{
			dispatchResponse(r);
		    }
		}catch(exception){
		    var desc='An error occurred during a request to a remote server. '
			+'This failure may be temporary, try repeating the request.';

		    if(Util.isDevelopmentEnvironment()){
		    if(this.transport.responseText==''){
		        desc=sprintf('An error occurred when making an AsyncRequest to %q. '
		    		 +'The server returned an empty response.',this.uri);
		    }else{
		        desc=sprintf('An error occurred when decoding the JSON payload of the '
		    		 +'AsyncResponse associated with an AsyncRequest to %q. The '
		    		 +'server returned <a href="javascript:aiert(%e);">a garbled '
		    		 +'response</a>, then Javascript threw an exception: %x.',
		    		 this.uri,this.transport.responseText,exception);
		    }
		    }
		    copy_properties(r,
				    {
					error:1000,
					    errorSummary:'Data Error',
					    errorDescription:desc
					    });
		    if(this.transportErrorHandler){
			dispatchErrorResponse(r,true);
		    }else{
			Util.error('Something bad happened; provide a transport error handler for '
			   +'complete details.');
		    }
		}
	    }
	});
    
    var invokeErrorHandler=bind(this,function(explicitError){
	    if(!window.loaded){return;}
	    var r=new AsyncResponse();
	    var err;
	    try{
		err=explicitError||this.transport.status||1001;
	    }catch(ex){err=1001;}
	    try{
		if(this.responseText==''){err=1002;}
	    }catch(ignore){}
	    if(this.transportErrorHandler){
		var desc=sprintf('Transport error (#%d) while retrieving data from endpoint %q: %s',
				 err,this.uri,AsyncRequest.getHTTPErrorDescription(err));
		if(!this.getOption('suppressErrorAlerts')){
		    Util.error(desc);
		}
		copy_properties(r,
    {error:err,errorSummary:AsyncRequest.getHTTPErrorSummary(err),errorDescription:desc});
		
		dispatchErrorResponse(r,true);
	    }else{
		Util.error('Async request to %q failed with a %d error, but there was no error '
		   +'handler available to deal with it.',this.uri,err);
	    }
	});

    var onStateChange=function(){
	try{
	    if(this.transport.readyState==4){
		if(this.transport.status>=200&&this.transport.status<300){
		    invokeResponseHandler();
		}else{
		    if(ua.safari()&&(typeof(this.transport.status)=='undefined')){
			invokeErrorHandler(1002);
		    }else{invokeErrorHandler();}
		}
		delete this.transport;
	    }
	}catch(exception){
	    if(!window.loaded){return;}
	    delete this.transport;
	    if(this.remainingRetries){
		--this.remainingRetries;
		this.send(true);
	    }else{
		if(!this.getOption('suppressErrorAlerts')){
		    Util.error('AsyncRequest exception when attempting to handle a state change: %x.',exception);
		}
		invokeErrorHandler(1001);
	    }
	}
    };
    
    copy_properties(this,
		    {
			onstatechange:onStateChange,
			    transport:null,
			    method:'POST',
			    uri:'',
			    handler:null,
			    errorHandler:ErrorDialog.showAsyncError,
			    transportErrorHandler:ErrorDialog.showAsyncError,
			    data:{},
			    readOnly:false,
			    writeRequiredParams:[],/*'post_form_id'],*/
			    remainingRetries:0,
			    option:{
			    asynchronous:true,
				suppressErrorHandlerWarning:false,
				suppressEvaluation:false,
				suppressErrorAlerts:false,
				retries:1}
		    });
    return this;
}
copy_properties(AsyncRequest,
		{
		    getHTTPErrorSummary:function(errCode){
			return AsyncRequest._getHTTPError(errCode).summary;
		    },
			getHTTPErrorDescription:function(errCode){
			return AsyncRequest._getHTTPError(errCode).description;
		    },
			pingURI:function(uri,data,synchronous){
			return new AsyncRequest().setURI(uri)
			    .setData(data).setOption('asynchronous',!synchronous)
			    .setOption('suppressErrorHandlerWarning',true).send();
		    },
			_getHTTPError:function(errCode){
			var e=AsyncRequest._HTTPErrors[errCode]
			    ||AsyncRequest._HTTPErrors[errCode-(errCode%100)]
			    ||{
			    summary:'HTTP Error',
			    description:'Unknown HTTP error #'+errCode
			};
			return e;
		    },
			_HTTPErrors:{
			400:{summary:'Bad Request',description:'Bad HTTP request.'},
			    401:{summary:'Unauthorized',description:'Not authorized.'},
			    403:{summary:'Forbidden',description:'Access forbidden.'},
			    404:{summary:'Not Found',description:'Web address does not exist.'},
			    1000:{summary:'Bad Response',description:'Invalid response.'},
			    1001:{summary:'No Network',description:'A network error occurred. Check that you are connected to the '+'internet.'},
			    1002:{summary:'No Data',description:'The server did not return a response.'}
		    }
		});
copy_properties(AsyncRequest.prototype,
		{
		    setMethod:function(m){
			this.method=m.toString().toUpperCase();
			return this;
		    },
			getMethod:function(){return this.method;},
			setData:function(obj){
			this.data=obj;
			return this;
		    },
			getData:function(){return this.data;},
			setURI:function(uri){
			if(!(new URI(uri)).isSameOrigin()){
			    Util.error('Asynchronous requests must specify relative URIs (like %q); this '
			           +'ensures they conform to the Same Origin Policy (see %q). The '
			           +'provided absolute URI (%q) is invalid, use a relative URI instead.'
			           ,'/path/to/endpoint.php'
			           ,'http://www.mozilla.org/projects/security/components/same-origin.html',uri);
			    return;
			}
			this.uri=uri;return this;
		    },
			getURI:function(){return this.uri;},
			setHandler:function(fn){
			if(typeof(fn)!='function'){
			    Util.error('AsyncRequest response handlers must be functions. Pass a function, '+'or use bind() to build one.');
			}else{this.handler=fn;}
			return this;
		    },
			getHandler:function(){return this.handler;},
			setErrorHandler:function(fn){
			if(typeof(fn)!='function'){
			    Util.error('AsyncRequest error handlers must be functions. Pass a function, or '+'use bind() to build one.');
			}else{this.errorHandler=fn;}
			return this;
		    },
			setTransportErrorHandler:function(fn){
			this.transportErrorHandler=fn;
			return this;
		    },
			getErrorHandler:function(){return this.handler;},
			setReadOnly:function(readOnly){
			if(typeof(readOnly)!='boolean'){
			    Util.error('AsyncRequest readOnly value must be a boolean.');
			}else{this.readOnly=readOnly;}
			return this;
		    },
			getReadOnly:function(){
			return this.readOnly;
		    },
			specifiesWriteRequiredParams:function(){
			var specifiesWriteRequiredParams=true;
			for(var i=0;i<this.writeRequiredParams.length;i++){
			    var param=this.writeRequiredParams[i];
			    if(typeof(this.data[param])=='undefined'){
				var e=ge(param);
				if(e&&typeof(e.value)!='undefined'){
				    this.data[param]=e.value;
				}else{
				    specifiesWriteRequiredParams=false;
				    break;
				}
			    }
			}
			return specifiesWriteRequiredParams;
		    },

			setOption:function(opt,v){
			if(typeof(this.option[opt])!='undefined'){
			    this.option[opt]=v;
			}else{
			    Util.warn('AsyncRequest option %q does not exist; request to set it was ignored.',opt);
			}
			return this;
		    },

			getOption:function(opt){
			if(typeof(this.option[opt])=='undefined'){
			    Util.warn('AsyncRequest option %q does not exist, get request failed.',opt);
			}
			return this.option[opt];
		    },

			send:function(isRetry){
			isRetry=isRetry||false;
			if(!this.uri){
			    Util.error('Attempt to dispatch an AsyncRequest without an endpoint URI! This is '+'all sorts of silly and impossible, so the request failed.');return false;
			}
			if(!this.errorHandler&&!this.getOption('suppressErrorHandlerWarning')){
			    Util.warn('Dispatching an AsyncRequest that does not have an error handler. '
			          +'You SHOULD supply one, or use AsyncRequest.pingURI(). If this '
			          +'omission is intentional and well-considered, set the %q option to '
			          +'suppress this warning.','suppressErrorHandlerWarning');
			}
			if(!this.getReadOnly()){
			    if(!this.specifiesWriteRequiredParams()){
				Util.error('You are making a POST request without one or more of the required '
				   +'parameters: %s. Requests which modify data and do not verify the '
				   +'request origin through parameter validation are vulnerable to CSRF '
				   +'attacks. You should either specify values for these parameters '
				   +'explicitly by using setData(), put them in the page as inputs, or '
				   +'mark this request as safe and idempotent by using setReadOnly(). '
				   +'Consult the setReadOnly() documentation for more information.',
				   this.writeRequiredParams.join(','));
				return false;
			    }
			    if(this.method!='POST'){
				Util.error('You are making a GET request which modifies data; this violates '
				   +'the HTTP spec and is generally a bad idea. Either change this '
				   +'request to use POST or use setReadOnly() to mark the request as '
				   +'idempotent and appropriate for HTTP GET. Consult the setReadOnly() '
				   +'documentation for more information.');
				return false;
			    }
			}
			if(this.transport){
			    Util.error('You must wait for an AsyncRequest to complete before sending another '
			           +'request with the same object. To send two simultaneous requests, '
			           +'create a second AsyncRequest object.');
			    return false;
			}
			var uri;
			var query=URI.implodeQuery(this.data);
			if(this.method=='GET'){
			    uri=this.uri+(query?'?'+query:'');
			    query='';
			    uri+=(uri.indexOf('?')!=-1?'&':'?')+'_uts'+((new Date()).getTime());
			}else{
			    uri=this.uri;
			}
			    
			    /* fix url, proxy to main host */
    
			    if( typeof MIPANG != 'undefined' && typeof MIPANG.location != 'undefined' && MIPANG.location.main_host != MIPANG.location.current_host){
	
				if(uri.indexOf('http') != 0){
				    uri = MIPANG.location.scheme+'://'+MIPANG.location.main_host + uri;
				}
				
				uri = '/service/proxy/*/'+uri;
				
			    }

			var transport=Try.these(
						function(){
						    return new XMLHttpRequest();
						},
						function(){
						    return new ActiveXObject("Msxml2.XMLHTTP");
						},
						function(){
						    return new ActiveXObject("Microsoft.XMLHTTP");
						})
			    ||null;
			if(!transport){
			    Util.error('Unable to build XMLHTTPRequest transport.');
			    return;
			}
			transport.onreadystatechange=bind(this,'onstatechange');
			if(!isRetry){
			    this.remainingRetries=0;
			    if(this.getReadOnly()){
				this.remainingRetries=this.getOption('retries');
			    }
			}
			this.transport=transport;
			this.transport.open(this.method,uri,this.getOption('asynchronous'));
			if(this.method=='POST'&&!this.setHeader){
			    this.setHeader=true;
			    this.transport.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
			    /**this.transport.setRequestHeader('Content-Length',query.length);**/
			}
			this.transport.send(query);
			return true;
		    }
		});
function AsyncResponse(){
    copy_properties(this,{
	    error:0,
		errorSummary:null,
		errorDescription:null,
		payload:null
		}
	);
    return this;
}
copy_properties(AsyncResponse.prototype,{
	getPayload:function(){return this.payload;},
	    getError:function(){return this.error;},
	    getErrorSummary:function(){return this.errorSummary;},
	    getErrorDescription:function(){return this.errorDescription;}
    });


//string

function htmlspecialchars(text){
    if(typeof(text)=='undefined'||!text.toString){return'';}
    if(text===false){return'0';}else if(text===true){return'1';}
    return text.toString().replace(/&/g,'&amp;').replace(/"/g,'&quot;').replace(/'/g,'&#039;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); // '"
}
var htmlize=htmlspecialchars;
function escape_js_quotes(text){
    if(typeof(text)=='undefined'||!text.toString){return'';}
    return text.toString().replace(/\\/g,'\\\\').replace(/\n/g,'\\n').replace(/\r/g,'\\r').replace(/"/g,'\\x22').replace(/'/g,'\\\'').replace(/</g,'\\x3c').replace(/>/g,'\\x3e').replace(/&/g,'\\x26');
//"
}
function nl2br(text){
    if(typeof(text)=='undefined'||!text.toString){return'';}
    return text.toString().replace(/\n/g,'<br />');
}


function sprintf(){
    if(arguments.length==0){
	//Util.warn('sprintf() was called with no arguments; it should be called with at '+'least one argument.');
	return'';
    }
    var args=['This is an argument vector.'];
    for(var ii=arguments.length-1;ii>0;ii--){
	if(typeof(arguments[ii])=="undefined"){
	    Util.log('You passed an undefined argument (argument '+ii+' to sprintf(). '
		     +'Pattern was: `'+(arguments[0])+'\'.','error');
	    args.push('');
	}else if(arguments[ii]===null){
	    args.push('');
	}else if(arguments[ii]===true){
	    args.push('true');
	}else if(arguments[ii]===false){
	    args.push('false');
	}else{if(!arguments[ii].toString){
		//Util.log('Argument '+(ii+1)+' to sprintf() does not have a toString() '
		// +'method. The pattern was: `'+(arguments[0])+'\'.','error');
		return'';
	    }
	    args.push(arguments[ii]);
	}
    }
    var pattern=arguments[0];
    pattern=pattern.toString().split('%');
    var patlen=pattern.length;
    var result=pattern[0];
    for(var ii=1;ii<patlen;ii++){
	if(args.length==0){
	    //Util.log('Not enough arguments were provide to sprintf(). The pattern was: '+'`'
	    //+(arguments[0])+'\'.','error');
	    return'';
	}
	if(!pattern[ii].length){result+="%";continue;}
	var p=0;
	var m=0;
	var r='';
	var padChar=' ';
	var padSize=null;
	var maxSize=null;
	var rawPad='';
	var pos=0;

	if(m=pattern[ii].match(/^('.)?(?:(-?\d+\.)?(-?\d+)?)/)){ //'
	    if(m[2]!==undefined&&m[2].length){
		padSize=parseInt(rawPad=m[2]);
	    }
				  if(m[3]!==undefined&&m[3].length){
				      if(padSize!==null){
					  maxSize=parseInt(m[3]);
				      }else{
					  padSize=parseInt(rawPad=m[3]);
				      }
				  }
				  pos=m[0].length;
				  if(m[1]!==undefined&&m[1].length){
				      padChar=m[1].charAt(1);
				  }else{
				      if(rawPad.charAt(0)==0){padChar='0';}
				  }
				  }
	    switch(pattern[ii].charAt(pos)){
	    case's':
	    raw=htmlspecialchars(args.pop().toString());
	    break;
	    case'h':raw=args.pop().toString();
	    break;
	    case'd':raw=parseInt(args.pop()).toString();
	    break;
	    case'f':raw=parseFloat(args.pop()).toString();
	    break;
	    case'q':raw="`"+htmlspecialchars(args.pop().toString())+"'";
	    break;
	    case'e':raw="'"+escape_js_quotes(args.pop().toString())+"'";
	    break;
	    case'L':var list=args.pop();
	    for(var ii=0;ii<list.length;ii++){
		list[ii]="`"+htmlspecialchars(args.pop().toString())+"'";
	    }
	    if(list.length>1){
		list[list.length-1]='and '+list[list.length-1];
	    }
	    raw=list.join(', ');
	    break;
	    case'x':x=args.pop();
	    var line='?';
	    var src='?';
	    
	    try{
		if(typeof(x['line'])!='undefined'){
		    line=x.line;
		}else if(typeof(x['lineNumber'])!='undefined'){
		    line=x.lineNumber;
		}
		if(typeof(x['sourceURL'])!='undefined'){
		    src=x['sourceURL'];
		}else if(typeof(x['fileName'])!='undefined'){
		    src=s['fileName'];
		}
	    }catch(exception){}
	    var s='[An Exception]';
	    try{s=x.message||x.toString();}catch(exception){}
	    raw=s+' [at line '+line+' in '+src+']';
	    break;
	    
	    default:raw="%"+pattern[ii].charAt(pos+1);
	    break;
	    }
			       if(padSize!==null){
				   if(raw.length<Math.abs(padSize)){
				       var padding='';
				       var padlen=(Math.abs(padSize)-raw.length);
				       for(var ll=0;ll<padlen;ll++){padding+=padChar;}
				       if(padSize<0){raw+=padding;}else{raw=padding+raw;}
				   }
			       }
			       if(maxSize!==null){
				   if(raw.length>maxSize){raw=raw.substr(0,maxSize);}
			       }
			       result+=raw+pattern[ii].substring(pos+1);
			       }
	   if(args.length>1){
	       //Util.log('Too many arguments ('+(args.length-1)+' extras) were passed to '+'sprintf(). Pattern was: `'+(arguments[0])+'\'.','error');
	   }
	   return result;
	   }

String.prototype.split=(function(split){
	return function(separator,limit){
	    var flags="";
	    if(separator===null||limit===null){
		return[];
	    }else if(typeof separator=='string'){
		return split.call(this,separator,limit);
	    }else if(separator===undefined){
		return[this.toString()];
	    }else if(separator instanceof RegExp){
		if(!separator._2||!separator._1){
		    flags=separator.toString().replace(/^[\S\s]+\//,"");
		    if(!separator._1){
			if(!separator.global){
			    separator._1=new RegExp(separator.source,"g"+flags);
			}else{separator._1=1;}
		    }
		}
		separator1=separator._1==1?separator:separator._1;
		var separator2=(separator._2?separator._2:separator._2=new RegExp("^"+separator1.source+"$",flags));
		if(limit===undefined||limit<0){
		    limit=false;
		}else{
		    limit=Math.floor(limit);
		    if(!limit)return[];
		}
		var match,output=[],lastLastIndex=0,i=0;
		while((limit?i++<=limit:true)&&(match=separator1.exec(this))){
		    if((match[0].length===0)&&(separator1.lastIndex>match.index)){separator1.lastIndex--;}
		    if(separator1.lastIndex>lastLastIndex){
			if(match.length>1){
			    match[0].replace(separator2,function(){
				    for(var j=1;j<arguments.length-2;j++){
					if(arguments[j]===undefined)match[j]=undefined;
				    }
				});
			}
			output=output.concat(this.substring(lastLastIndex,match.index),
					     (match.index===this.length?[]:match.slice(1)));

			lastLastIndex=separator1.lastIndex;
		    }
		    if(match[0].length===0){separator1.lastIndex++;}
		}
		
		return(lastLastIndex===this.length)
		?(separator1.test("")?output:output.concat(""))
		:(limit?output:output.concat(this.substring(lastLastIndex)));
	    }else{
		return split.call(this,separator,limit);
	    }
	}
    })(String.prototype.split);

	//animation


function animation(obj){
    if(this==window){
	return new animation(obj);
    }else{
	this.obj=obj;
	this._reset_state();
	this.queue=[];
    }
}
animation.resolution=20;
animation.offset=0;
animation.prototype._reset_state=function(){
    this.state={attrs:{},duration:500}
};
animation.prototype.stop=function(){
    this._reset_state();
    this.queue=[];
    return this;
};
animation.prototype._build_container=function(){
    if(this.container_div){
	this._refresh_container();
	return;
    }
    var container=document.createElement('div');
    container.style.padding='0px';
    container.style.margin='0px';
    container.style.border='0px';
    var children=this.obj.childNodes;
    while(children.length){container.appendChild(children[0]);}
    this.obj.appendChild(container);
    this.obj.style.overflow='hidden';
    this.container_div=container;
    this._refresh_container();
};
animation.prototype._refresh_container=function(){
    this.container_div.style.height='auto';
    this.container_div.style.width='auto';
    this.container_div.style.height=this.container_div.offsetHeight+'px';
    this.container_div.style.width=this.container_div.offsetWidth+'px';
};
animation.prototype._destroy_container=function(){
    if(!this.container_div){return;}
    var children=this.container_div.childNodes;
    while(children.length){this.obj.appendChild(children[0]);}
    this.obj.removeChild(this.container_div);
    this.container_div=null;
};
animation.ATTR_TO=1;
animation.ATTR_BY=2;
animation.ATTR_FROM=3;
animation.prototype._attr=function(attr,value,mode){
    var auto=false;
    switch(attr){
    case'background':
	this._attr('backgroundColor',value,mode);
	return this;
    case'margin':
	value=animation.parse_group(value);
	this.attr('marginBottom',value[0],mode);
	this.attr('marginLeft',value[1],mode);
	this.attr('marginRight',value[2],mode);
	this.attr('marginTop',value[3],mode);
	return this;
    case'padding':
	value=animation.parse_group(value);
	this.attr('paddingBottom',value[0],mode);
	this.attr('paddingLeft',value[1],mode);
	this.attr('paddingRight',value[2],mode);
	this.attr('paddingTop',value[3],mode);
	return this;
    case'backgroundColor':
    case'borderColor':
    case'color':
	value=animation.parse_color(value);
	break;
    case'opacity':
	value=parseFloat(value,10);
	break;
    case'height':
    case'width':
	if(value=='auto'){
	    auto=true;
	}else{
	    value=parseInt(value);
	}
	break;
    case'borderWidth':
    case'lineHeight':
    case'fontSize':
    case'marginBottom':
    case'marginLeft':
    case'marginRight':
    case'marginTop':
    case'paddingBottom':
    case'paddingLeft':
    case'paddingRight':
    case'paddingTop':
    case'bottom':
    case'left':
    case'right':
    case'top':
    case'scrollTop':
    case'scrollLeft':
	value=parseInt(value,10);
	break;
    default:
	throw a+' is not a supported attribute!';
	break;
    }
    if(this.state.attrs[attr]===undefined){
	this.state.attrs[attr]={};
    }
    if(auto){this.state.attrs[attr].auto=true;}
    switch(mode){
    case animation.ATTR_FROM:
    this.state.attrs[attr].start=value;
    break;
    case animation.ATTR_BY:
    this.state.attrs[attr].by=true;
    case animation.ATTR_TO:
    this.state.attrs[attr].value=value;
    break;
    }
};
animation.prototype.to=function(attr,value){this._attr(attr,value,animation.ATTR_TO);return this;};
animation.prototype.by=function(attr,value){this._attr(attr,value,animation.ATTR_BY);return this;};
animation.prototype.from=function(attr,value){this._attr(attr,value,animation.ATTR_FROM);return this;};
animation.prototype.duration=function(duration){this.state.duration=duration?duration:0;return this;};
animation.prototype.checkpoint=function(distance,callback){
    if(distance===undefined){distance=1;}
    this.state.checkpoint=distance;
    this.state.checkpointcb=callback;
    this.queue.push(this.state);
    this._reset_state();
    return this;
};
animation.prototype.blind=function(){this.state.blind=true;return this;};
animation.prototype.hide=function(){this.state.hide=true;return this;};
animation.prototype.show=function(){this.state.show=true;return this;};
animation.prototype.ease=function(ease){this.state.ease=ease;return this;};
animation.prototype.go=function(){
    var time=(new Date()).getTime();
    this.queue.push(this.state);
    for(var i=0;i<this.queue.length;i++){
	this.queue[i].start=time-animation.offset;
	if(this.queue[i].checkpoint){
	    time+=this.queue[i].checkpoint*this.queue[i].duration;
	}
    }
    animation.push(this);
    return this;
};
animation.prototype._frame=function(time){
    var done=true;
    var still_needs_container=false;
    var blake_ross=false;
    for(var i=0;i<this.queue.length;i++){
	var cur=this.queue[i];
	if(cur.start>time){
	    done=false;
	    continue;
	}else if(cur.checkpointcb&&(cur.checkpoint*cur.duration+cur.start>time)){
	    this._callback(cur.checkpointcb,time-cur.start-cur.checkpoint*cur.duration);
	    cur.checkpointcb=null;
	}
	if(cur.started===undefined){
	    if(cur.show){
		this.obj.style.display='block';
	    }
	    for(var a in cur.attrs){
		if(cur.attrs[a].start!==undefined){continue;}
		switch(a){
		case'backgroundColor':
		case'borderColor':
		case'color':
		    var val=animation.parse_color(get_style(this.obj,a=='borderColor'?'borderLeftColor':a));
		    if(cur.attrs[a].by){
			cur.attrs[a].value[0]=Math.min(255,Math.max(0,cur.attrs[a].value[0]+val[0]));
			cur.attrs[a].value[1]=Math.min(255,Math.max(0,cur.attrs[a].value[1]+val[1]));
			cur.attrs[a].value[2]=Math.min(255,Math.max(0,cur.attrs[a].value[2]+val[2]));
		    }
		    break;
		case'opacity':
		    var val=get_opacity(this.obj);
		    if(cur.attrs[a].by){
			cur.attrs[a].value=Math.min(1,Math.max(0,cur.attrs[a].value+val));
		    }
		    break;
		case'height':
		case'width':
		    var val=animation['get_'+a](this.obj);
		    if(cur.attrs[a].by){cur.attrs[a].value+=val;}
		    break;
		case'scrollLeft':
		case'scrollTop':
		    var val=(this.obj==document.body?(document.documentElement||document.body):this.obj)[a];
		    if(cur.attrs[a].by){cur.attrs[a].value+=val;}
		    cur['last'+a]=val;
		    break;
		default:
		    var val=parseInt(get_style(this.obj,a),10);
		    if(cur.attrs[a].by){cur.attrs[a].value+=val;}
		    break;
		}
		cur.attrs[a].start=val;
	    }
	    if((cur.attrs.height&&cur.attrs.height.auto)
	       ||(cur.attrs.width&&cur.attrs.width.auto)
	       ){
		if(ua.firefox()<3){blake_ross=true;}
		this._destroy_container();
		for(var a in{
			height:1,width:1,
			    fontSize:1,
			    borderLeftWidth:1,borderRightWidth:1,borderTopWidth:1,borderBottomWidth:1,
			    paddingLeft:1,paddingRight:1,paddingTop:1,paddingBottom:1}
		    ){
		    if(cur.attrs[a]){
			this.obj.style[a]=cur.attrs[a].value+(typeof cur.attrs[a].value=='number'?'px':'');
		    }
		}
		if(cur.attrs.height&&cur.attrs.height.auto){cur.attrs.height.value=animation.get_height(this.obj);}
		if(cur.attrs.width&&cur.attrs.width.auto){cur.attrs.width.value=animation.get_width(this.obj);}
	    }
	    
	    cur.started=true;
	    if(cur.blind){this._build_container();}
	}
	var p=(time-cur.start)/cur.duration;
	if(p>=1){
	    p=1;
	    if(cur.hide){
		this.obj.style.display='none';
	    }
	}else{done=false;}
	if(cur.ease){p=cur.ease(p);}
	if(!still_needs_container&&p!=1&&cur.blind){still_needs_container=true;}
	if(blake_ross&&this.obj.parentNode){
	    var parentNode=this.obj.parentNode;
	    var nextChild=this.obj.nextSibling;
	    parentNode.removeChild(this.obj);
	}
	for(var a in cur.attrs){
	    switch(a){
	    case'backgroundColor':case'borderColor':case'color':
		this.obj.style[a]='rgb('+
		    animation.calc_tween(p,cur.attrs[a].start[0],cur.attrs[a].value[0],true)+','+
		    animation.calc_tween(p,cur.attrs[a].start[1],cur.attrs[a].value[1],true)+','+
		    animation.calc_tween(p,cur.attrs[a].start[2],cur.attrs[a].value[2],true)+')';
		break;
	    case'opacity':
		set_opacity(this.obj,animation.calc_tween(p,cur.attrs[a].start,cur.attrs[a].value));
		break;
	    case'height':case'width':
		this.obj.style[a]=p==1&&cur.attrs[a].auto?'auto'
		    :animation.calc_tween(p,cur.attrs[a].start,cur.attrs[a].value,true)+'px';
		break;
	    case'scrollLeft':case'scrollTop':
		var val=this.obj==document.body?document.documentElement[a]||document.body[a]:this.obj[a];
	    if(cur['last'+a]!=val){
		delete cur.attrs[a];
	    }else{
		var diff=animation.calc_tween(p,cur.attrs[a].start,cur.attrs[a].value,true)-val;
		if(a=='scrollLeft'){
		    window.scrollBy(diff,0);
		}else{window.scrollBy(0,diff);}
		cur['last'+a]=diff+val;
	    }
	    break;
	    default:
		this.obj.style[a]=animation.calc_tween(p,cur.attrs[a].start,cur.attrs[a].value,true)+'px';
		break;
	    }
	}
	if(p==1){
	    this.queue.splice(i--,1);
	    this._callback(cur.ondone,time-cur.start-cur.duration);
	}
    }
    if(blake_ross){
	parentNode[nextChild?'insertBefore':'appendChild'](this.obj,nextChild);
    }
    if(!still_needs_container&&this.container_div){this._destroy_container();}
    return!done;
};
animation.prototype.ondone=function(fn){this.state.ondone=fn;return this;};
animation.prototype._callback=function(callback,offset){
    if(callback){
	animation.offset=offset;
	callback.call(this);
	animation.offset=0;
    }
};
animation.calc_tween=function(p,v1,v2,whole){return(whole?parseInt:parseFloat)((v2-v1)*p+v1,10);};
animation.parse_color=function(color){
    var hex=/^#([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{1,2})$/i.exec(color);
    if(hex){
	return[parseInt(hex[1].length==1?hex[1]+hex[1]:hex[1],16),
	       parseInt(hex[2].length==1?hex[2]+hex[2]:hex[2],16),
	       parseInt(hex[3].length==1?hex[3]+hex[3]:hex[3],16)];
    }else{
	var rgb=/^rgba? *\(([0-9]+), *([0-9]+), *([0-9]+)(?:, *([0-9]+))?\)$/.exec(color);
	if(rgb){
	    if(rgb[4]==='0'){
		return[255,255,255];
	    }else{
		return[parseInt(rgb[1],10),
		       parseInt(rgb[2],10),
		       parseInt(rgb[3],10)];
	    }
	}else if(color=='transparent'){
	    return[255,255,255];
	}else{throw'Named color attributes are not supported.';}
    }
};
animation.parse_group=function(value){
    var value=trim(value).split(/ +/);
    if(value.length==4){
	return value;
    }else if(value.length==3){
	return[value[0],value[1],value[2],value[1]];
    }else if(value.length==2){
	return[value[0],value[1],value[0],value[1]];
    }else{return[value[0],value[0],value[0],value[0]];}
};
animation.get_height=function(obj){
    var pT=parseInt(get_style(obj,'paddingTop'),10),
    pB=parseInt(get_style(obj,'paddingBottom'),10),
    bT=parseInt(get_style(obj,'borderTopWidth'),10),
    bW=parseInt(get_style(obj,'borderBottomWidth'),10);
    return obj.offsetHeight-(pT?pT:0)-(pB?pB:0)-(bT?bT:0)-(bW?bW:0);
};
animation.get_width=function(obj){
    var pL=parseInt(get_style(obj,'paddingLeft'),10),
    pR=parseInt(get_style(obj,'paddingRight'),10),
    bL=parseInt(get_style(obj,'borderLeftWidth'),10),
    bR=parseInt(get_style(obj,'borderRightWidth'),10);
    return obj.offsetWidth-(pL?pL:0)-(pR?pR:0)-(bL?bL:0)-(bR?bR:0);
};
animation.push=function(instance){
    if(!animation.active){animation.active=[];}
    animation.active.push(instance);
    if(!animation.timeout){
	animation.timeout=setInterval(animation.animate.bind(animation),animation.resolution);
    }
};
animation.animate=function(){
    var done=true;
    var time=(new Date()).getTime();
    for(var i=0;i<animation.active.length;i++){
	if(animation.active[i]._frame(time)){
	    done=false;
	}else{
	    animation.active.splice(i--,1);
	}
    }
    if(done){
	clearInterval(animation.timeout);
	animation.timeout=null;
    }
};
animation.ease={};
animation.ease.begin=function(p){return p*p;};
animation.ease.end=function(p){p-=1;return-(p*p)+1;};
animation.ease.both=function(p){
    if(p<=0.5){
	return(p*p)*2;
    }else{
	p-=1;
	return(p*p)*-2+1;
    }
};