function $()
{
	var elements=new Array();
	for(var i=0;i<arguments.length;i++)
	{
		var element=arguments[i];
		if(typeof element=='string')
		element=document.getElementById(element);
		if(arguments.length==1)
		return element;elements.push(element);
	}
	return elements;
}


function diffString(o,n)
{
	var bal='x';
	while((o.indexOf(bal)>0)||(o.indexOf(bal)>0))
	{
		bal+='z';
	}

	var baloins=bal+'oi';
	var balfins=bal+'fi';
	var balodel=bal+'od';
	var balfdel=bal+'fd';
	var baln=bal+'n';o=o.replace(/\n/g,' '+baln+' ');
	n=n.replace(/\n/g,' '+baln+' ');
	o=o.replace(/\s+$/,'');
	n=n.replace(/\s+$/,'');
	var out=diff(o==""?[]:o.split(/\s+/),n==""?[]:n.split(/\s+/));
	var str="";
	var oSpace=o.match(/\s+/g);
	if(oSpace==null){oSpace=["\n"];}
	else{oSpace.push("\n");}

	var nSpace=n.match(/\s+/g);
	if(nSpace==null){nSpace=["\n"];}
	else{nSpace.push("\n");}

	if(out.n.length==0)
	{
		for(var i=0;i<out.o.length;i++)
		{
			str+=balodel+out.o[i]+oSpace[i]+balfdel;
		}
	}else{
		if(out.n[0].text==null)
		{
			for(n=0;n<out.o.length&&out.o[n].text==null;n++)
			{
				str+=balodel+out.o[n]+oSpace[n]+balfdel;
			}
		}
		for(var i=0;i<out.n.length;i++)
		{
			if(out.n[i].text==null){str+=baloins+out.n[i]+nSpace[i]+balfins;}
			else{
				var pre="";
				for(n=out.n[i].row+1;n<out.o.length&&out.o[n].text==null;n++)
				{
					pre+=balodel+out.o[n]+oSpace[n]+balfdel;
				}
			str+=" "+out.n[i].text+nSpace[i]+pre;
			}
		}
	}
	
	if(str.indexOf(balodel)!=0)
	{
		pre="";
		for(var i=0;i<out.o.length-1;i++)
		{
			if(out.o[i].text!=null)break;
			else pre+=out.o[i]+" ";
		}
		
		if(pre.length>0)
			str=balodel+pre+balfdel+str;
	}

	str=str.replace(/&/g,"&amp;");
	str=str.replace(/</g,"&lt;");
	str=str.replace(/>/g,"&gt;");
	str=str.replace(/"/g,"&quot;");
	str=str.replace(eval("/"+baloins+"/g"),"<ins>");
	str=str.replace(eval("/"+balfins+"/g"),"</ins>");
	str=str.replace(eval("/"+balodel+"/g"),"<del>");
	str=str.replace(eval("/"+balfdel+"/g"),"</del>");
	str=str.replace(eval("/"+baln+"/g"),"<br />");
	return str;
}

function diff(o,n)
{
	var ns=new Object();
	var os=new Object();
	for(var i=0;i<n.length;i++)
	{
		if(ns[n[i]]==null)
			ns[n[i]]={rows:new Array(),o:null};
		ns[n[i]].rows.push(i);
	}

	for(var i=0;i<o.length;i++)
	{
		if(os[o[i]]==null)
			os[o[i]]={rows:new Array(),n:null};
		os[o[i]].rows.push(i);
	}
	
	for(var i in ns)
	{
		if(ns[i].rows.length==1&&typeof(os[i])!="undefined"&&os[i].rows.length==1)
		{
			n[ns[i].rows[0]]={text:n[ns[i].rows[0]],row:os[i].rows[0]};
			o[os[i].rows[0]]={text:o[os[i].rows[0]],row:ns[i].rows[0]};
		}
	}
	
	for(var i=0;i<n.length-1;i++)
	{
		if(n[i].text!=null&&n[i+1].text==null&&n[i].row+1<o.length&&o[n[i].row+1].text==null&&n[i+1]==o[n[i].row+1])
		{
			n[i+1]={text:n[i+1],row:n[i].row+1};
			o[n[i].row+1]={text:o[n[i].row+1],row:i+1};
		}
	}
		
	for(var i=n.length-1;i>0;i--)
	{
		if(n[i].text!=null&&n[i-1].text==null&&n[i].row>0&&o[n[i].row-1].text==null&&n[i-1]==o[n[i].row-1])
		{
			n[i-1]={text:n[i-1],row:n[i].row-1};
			o[n[i].row-1]={text:o[n[i].row-1],row:i-1};
		}
	}
	return{o:o,n:n};
}

