The companion zip shows example use of the folowing simple functions (readText.zip)

Props is a helper function to reduce code size, it simply attaches properties or methods to an object based on the passed literal object
obj is the object that will have properties/methods attached
props is an object literal of attribute/value pairs

Code:
function Props(obj,props){
	for(var i in props)
		obj[i]=props[i];
}


readText lets you load local text file content for use in the page.
sTextPath is the local path to the text file.
sFnc is the name of the callback function that gets the text once it's read.
sArg is an optional argument that, if present, will be sent to the callback function.
(Caveat: the browser have different ways they wrap the retured iframe content. See the attached zip for one way to handle the returned content)
Code:
function readText(sTextPath,sFnc,sArg)
{
	var div = document.createElement("div");
	Props(div.style,{position:"absolute",height:"20px",top:"-200px"})	//quick set style properties
	document.body.appendChild(div);
	var s = (sArg==null)?"":",\""+sArg+"\"";
	if(window.attachEvent){
		s = "<iframe src='"+sTextPath+"' onload='"+sFnc+"(this.contentWindow.document.body.innerHTML"+s+");this.parentNode.parentNode.removeChild(this.parentNode);'></iframe>";
	}else{
		s = "<iframe src='"+sTextPath+"' onload='"+sFnc+"(this.contentDocument.body.innerHTML"+s+");this.parentNode.parentNode.removeChild(this.parentNode);'></iframe>";
	}
	div.innerHTML=s;
}


A simple custom error handler.
(WebKit based browsers will ignore this code)
Code:
var customError=[];
customError.loaded=false;
customError.cnt=1;
window.onerror=function(msg,url,line){	//simple custom error handler
	if(customError.cnt>5)	//change the limit from 5 to how ever many errors at one time that you are comfortable with
	{
		var s = "";
		for(var i =0;i<customError.length;i++)
		{
			s+=customError[i] + "<br />";
		}
		s+="Error "+customError.cnt++ +") "+msg+"<br />"+"URL: "+url+"<br />"+"See line "+line
		alert("Too many errors - Custom Error Reporting Stopped:\n"+s.replace(/\<br \/\>/g,"\n"));
		window.onerror="";
		too_many_errors.count = 0;			//intentionally generate error.
	}
	if(customError.loaded==false)
	{
		customError[customError.length] = "Error "+customError.cnt++ +") "+msg+"<br />"+"URL: "+url+"<br />"+"See line "+line
		var w = window.onload;		//the original onload event code
		window.onload=function()
		{	
			w();			// execute the original onload event code
			var s = "CUSTOM Error Report:<br />[Berfore window onload event]<br /><br />";
			for(var i=0;i<customError.length;i++)
			{
				s+=customError[i]+"<br />";
			}
			var cnt=customError.cnt;
			customError=[];	
			customError.cnt=cnt;
			customError.loaded=true;
			var d = document.createElement('div')
			Props(d.style,{background:"black",color:"yellow",border:"solid 2px red",padding:"20px"});
			d.innerHTML = s + "<br />[window onload event has now occured]";
			document.body.appendChild(d);
		}
	}
	else
	{
		var d = document.createElement('div')
		Props(d.style,{background:"black",color:"yellow",border:"solid 2px red",padding:"20px"});
		d.innerHTML = "Error "+customError.cnt++ +") "+msg+"<br />"+"URL: "+url+"<br />"+"See line "+line
		document.body.appendChild(d);
	}
	return true;
}


See the companion zip for a full simple use demonstration.
index.html shows one way to handle the different ways the browsers wrap the iframe content (readText.zip).

provided by rdspooons